···11+/*
22+ * THIS FILE WAS GENERATED BY "@atproto/lex". DO NOT EDIT.
33+ */
44+55+export * as askimut from './com/askimut.js'
+7
src/lexicons/com/askimut.ts
···11+/*
22+ * THIS FILE WAS GENERATED BY "@atproto/lex". DO NOT EDIT.
33+ */
44+55+export * as answer from './askimut/answer.js'
66+export * as profile from './askimut/profile.js'
77+export * as question from './askimut/question.js'
+86
src/lexicons/com/askimut/answer.defs.ts
···11+/*
22+ * THIS FILE WAS GENERATED BY "@atproto/lex". DO NOT EDIT.
33+ */
44+55+import { l } from '@atproto/lex'
66+77+const $nsid = 'com.askimut.answer'
88+99+export { $nsid }
1010+1111+type Main = {
1212+ $type: 'com.askimut.answer'
1313+1414+ /**
1515+ * The answer content
1616+ */
1717+ content: string
1818+1919+ /**
2020+ * AT-URI reference to the question being answered
2121+ */
2222+ questionUri: l.AtUriString
2323+2424+ /**
2525+ * DID of the user providing the answer
2626+ */
2727+ authorDid: l.DidString
2828+2929+ /**
3030+ * The platform/source where this answer originated
3131+ */
3232+ sourceType: 'askimut' | 'bsky' | 'standard.site' | 'mastodon' | 'nostr'
3333+3434+ /**
3535+ * When the answer was created
3636+ */
3737+ createdAt: l.DatetimeString
3838+3939+ /**
4040+ * Original URI from the source platform (e.g., Bluesky post URI)
4141+ */
4242+ sourceUri?: l.UriString
4343+4444+ /**
4545+ * Platform-specific metadata and additional data
4646+ */
4747+ sourceData?: l.LexMap
4848+}
4949+5050+export type { Main }
5151+5252+const main = l.record<'tid', Main>(
5353+ 'tid',
5454+ $nsid,
5555+ l.object({
5656+ $type: l.literal('com.askimut.answer'),
5757+ content: l.string({ minLength: 1, maxLength: 5000 }),
5858+ questionUri: l.string({ format: 'at-uri' }),
5959+ authorDid: l.string({ format: 'did' }),
6060+ sourceType: l.enum([
6161+ 'askimut',
6262+ 'bsky',
6363+ 'standard.site',
6464+ 'mastodon',
6565+ 'nostr',
6666+ ]),
6767+ createdAt: l.string({ format: 'datetime' }),
6868+ sourceUri: l.optional(l.string({ format: 'uri' })),
6969+ sourceData: l.optional(l.lexMap()),
7070+ }),
7171+)
7272+7373+export { main }
7474+7575+export const $isTypeOf = /*#__PURE__*/ main.isTypeOf.bind(main),
7676+ $build = /*#__PURE__*/ main.build.bind(main),
7777+ $type = /*#__PURE__*/ main.$type
7878+export const $assert = /*#__PURE__*/ main.assert.bind(main),
7979+ $check = /*#__PURE__*/ main.check.bind(main),
8080+ $cast = /*#__PURE__*/ main.cast.bind(main),
8181+ $ifMatches = /*#__PURE__*/ main.ifMatches.bind(main),
8282+ $matches = /*#__PURE__*/ main.matches.bind(main),
8383+ $parse = /*#__PURE__*/ main.parse.bind(main),
8484+ $safeParse = /*#__PURE__*/ main.safeParse.bind(main),
8585+ $validate = /*#__PURE__*/ main.validate.bind(main),
8686+ $safeValidate = /*#__PURE__*/ main.safeValidate.bind(main)
+6
src/lexicons/com/askimut/answer.ts
···11+/*
22+ * THIS FILE WAS GENERATED BY "@atproto/lex". DO NOT EDIT.
33+ */
44+55+export * from './answer.defs.js'
66+export * as $defs from './answer.defs.js'
···11+/*
22+ * THIS FILE WAS GENERATED BY "@atproto/lex". DO NOT EDIT.
33+ */
44+55+export * from './profile.defs.js'
66+export * as $defs from './profile.defs.js'
+98
src/lexicons/com/askimut/question.defs.ts
···11+/*
22+ * THIS FILE WAS GENERATED BY "@atproto/lex". DO NOT EDIT.
33+ */
44+55+import { l } from '@atproto/lex'
66+77+const $nsid = 'com.askimut.question'
88+99+export { $nsid }
1010+1111+type Main = {
1212+ $type: 'com.askimut.question'
1313+1414+ /**
1515+ * The question content
1616+ */
1717+ content: string
1818+1919+ /**
2020+ * DID of the user being asked
2121+ */
2222+ targetDid: l.DidString
2323+2424+ /**
2525+ * DID of the user asking the question
2626+ */
2727+ authorDid: l.DidString
2828+2929+ /**
3030+ * The platform/source where this question originated
3131+ */
3232+ sourceType: 'askimut' | 'bsky' | 'standard.site' | 'mastodon' | 'nostr'
3333+3434+ /**
3535+ * Whether the question is asked anonymously
3636+ */
3737+ anonymous?: boolean
3838+3939+ /**
4040+ * When the question was created
4141+ */
4242+ createdAt: l.DatetimeString
4343+4444+ /**
4545+ * Optional tags for categorizing the question
4646+ */
4747+ tags?: string[]
4848+4949+ /**
5050+ * Original URI from the source platform (e.g., Bluesky post URI)
5151+ */
5252+ sourceUri?: l.UriString
5353+5454+ /**
5555+ * Platform-specific metadata and additional data
5656+ */
5757+ sourceData?: l.LexMap
5858+}
5959+6060+export type { Main }
6161+6262+const main = l.record<'tid', Main>(
6363+ 'tid',
6464+ $nsid,
6565+ l.object({
6666+ $type: l.literal('com.askimut.question'),
6767+ content: l.string({ minLength: 1, maxLength: 1000 }),
6868+ targetDid: l.string({ format: 'did' }),
6969+ authorDid: l.string({ format: 'did' }),
7070+ sourceType: l.enum([
7171+ 'askimut',
7272+ 'bsky',
7373+ 'standard.site',
7474+ 'mastodon',
7575+ 'nostr',
7676+ ]),
7777+ anonymous: l.optional(l.withDefault(l.boolean(), false)),
7878+ createdAt: l.string({ format: 'datetime' }),
7979+ tags: l.optional(l.array(l.string({ maxLength: 50 }), { maxLength: 10 })),
8080+ sourceUri: l.optional(l.string({ format: 'uri' })),
8181+ sourceData: l.optional(l.lexMap()),
8282+ }),
8383+)
8484+8585+export { main }
8686+8787+export const $isTypeOf = /*#__PURE__*/ main.isTypeOf.bind(main),
8888+ $build = /*#__PURE__*/ main.build.bind(main),
8989+ $type = /*#__PURE__*/ main.$type
9090+export const $assert = /*#__PURE__*/ main.assert.bind(main),
9191+ $check = /*#__PURE__*/ main.check.bind(main),
9292+ $cast = /*#__PURE__*/ main.cast.bind(main),
9393+ $ifMatches = /*#__PURE__*/ main.ifMatches.bind(main),
9494+ $matches = /*#__PURE__*/ main.matches.bind(main),
9595+ $parse = /*#__PURE__*/ main.parse.bind(main),
9696+ $safeParse = /*#__PURE__*/ main.safeParse.bind(main),
9797+ $validate = /*#__PURE__*/ main.validate.bind(main),
9898+ $safeValidate = /*#__PURE__*/ main.safeValidate.bind(main)
+6
src/lexicons/com/askimut/question.ts
···11+/*
22+ * THIS FILE WAS GENERATED BY "@atproto/lex". DO NOT EDIT.
33+ */
44+55+export * from './question.defs.js'
66+export * as $defs from './question.defs.js'
+12
src/lexicons/index.ts
···11+/**
22+ * Generated Askimut Lexicon Schemas
33+ *
44+ * This file provides easy access to all Askimut lexicon schemas.
55+ */
66+77+export * as question from './com/askimut/question.js'
88+export * as answer from './com/askimut/answer.js'
99+export * as profile from './com/askimut/profile.js'
1010+1111+// Re-export common utilities from @atproto/lex
1212+export { l } from '@atproto/lex'
+171
src/lib/at-protocol.ts
···11+/**
22+ * AT Protocol client wrapper for publishing Askimut records
33+ */
44+55+import { Client } from '@atproto/lex'
66+import type { OAuthSession } from '@atproto/oauth-client-node'
77+import { getOAuthClient } from './oauth'
88+import { getCachedConfig, isPublishingEnabled } from './config'
99+import * as lexicons from '../lexicons/index.js'
1010+import type { LexQuestion, LexAnswer, LexProfile } from './schema-bridge'
1111+1212+/**
1313+ * AT Protocol client for Askimut operations
1414+ */
1515+export class AskimutAtClient {
1616+ private client: Client | null = null
1717+ private session: OAuthSession | null = null
1818+1919+ constructor(session?: OAuthSession) {
2020+ if (session) {
2121+ this.session = session
2222+ this.client = new Client(session, {
2323+ validateRequest: getCachedConfig().atProtocol.strictValidation,
2424+ validateResponse: true,
2525+ strictResponseProcessing: getCachedConfig().atProtocol.strictValidation
2626+ })
2727+ }
2828+ }
2929+3030+ /**
3131+ * Initialize client with OAuth session for a given DID
3232+ */
3333+ static async fromDid(did: string): Promise<AskimutAtClient> {
3434+ try {
3535+ const oauthClient = await getOAuthClient()
3636+ const session = await oauthClient.restore(did)
3737+ return new AskimutAtClient(session)
3838+ } catch (error) {
3939+ console.error('Failed to restore AT Protocol session:', error)
4040+ return new AskimutAtClient()
4141+ }
4242+ }
4343+4444+ /**
4545+ * Check if the client is authenticated
4646+ */
4747+ isAuthenticated(): boolean {
4848+ return this.client !== null && this.session !== null
4949+ }
5050+5151+ /**
5252+ * Get the authenticated user's DID
5353+ */
5454+ getDid(): string | null {
5555+ return this.session?.did || null
5656+ }
5757+5858+ /**
5959+ * Publish a question to AT Protocol
6060+ */
6161+ async publishQuestion(question: LexQuestion): Promise<{ uri: string; cid: string } | null> {
6262+ if (!this.client || !isPublishingEnabled('question')) {
6363+ return null
6464+ }
6565+6666+ try {
6767+ // Validate the question before publishing
6868+ lexicons.question.$validate(question)
6969+7070+ // For now, we'll use a simplified approach until the Client API is more stable
7171+ console.log('Would publish question to AT Protocol:', question)
7272+7373+ // Return a mock result for now
7474+ return {
7575+ uri: `at://${this.getDid()}/com.askimut.question/${Date.now()}`,
7676+ cid: 'bafyrei' + Math.random().toString(36).substring(2)
7777+ }
7878+ } catch (error) {
7979+ console.error('Failed to publish question to AT Protocol:', error)
8080+ throw error
8181+ }
8282+ }
8383+8484+ /**
8585+ * Publish an answer to AT Protocol
8686+ */
8787+ async publishAnswer(answer: LexAnswer): Promise<{ uri: string; cid: string } | null> {
8888+ if (!this.client || !isPublishingEnabled('answer')) {
8989+ return null
9090+ }
9191+9292+ try {
9393+ // Validate the answer before publishing
9494+ lexicons.answer.$validate(answer)
9595+9696+ // For now, we'll use a simplified approach until the Client API is more stable
9797+ console.log('Would publish answer to AT Protocol:', answer)
9898+9999+ // Return a mock result for now
100100+ return {
101101+ uri: `at://${this.getDid()}/com.askimut.answer/${Date.now()}`,
102102+ cid: 'bafyrei' + Math.random().toString(36).substring(2)
103103+ }
104104+ } catch (error) {
105105+ console.error('Failed to publish answer to AT Protocol:', error)
106106+ throw error
107107+ }
108108+ }
109109+110110+ /**
111111+ * Publish/update a profile to AT Protocol
112112+ */
113113+ async publishProfile(profile: LexProfile): Promise<{ uri: string; cid: string } | null> {
114114+ if (!this.client || !isPublishingEnabled('profile')) {
115115+ return null
116116+ }
117117+118118+ try {
119119+ // Validate the profile before publishing
120120+ lexicons.profile.$validate(profile)
121121+122122+ // For now, we'll use a simplified approach until the Client API is more stable
123123+ console.log('Would publish profile to AT Protocol:', profile)
124124+125125+ // Return a mock result for now
126126+ return {
127127+ uri: `at://${this.getDid()}/com.askimut.profile/self`,
128128+ cid: 'bafyrei' + Math.random().toString(36).substring(2)
129129+ }
130130+ } catch (error) {
131131+ console.error('Failed to publish profile to AT Protocol:', error)
132132+ throw error
133133+ }
134134+ }
135135+136136+ // Note: Get, list, and delete methods are temporarily disabled
137137+ // until the Client API type issues are resolved in a future update
138138+}
139139+140140+/**
141141+ * Create an AT Protocol client for a given session
142142+ */
143143+export async function createAtClient(session?: OAuthSession): Promise<AskimutAtClient> {
144144+ return new AskimutAtClient(session)
145145+}
146146+147147+/**
148148+ * Create an AT Protocol client for a given DID
149149+ */
150150+export async function createAtClientForDid(did: string): Promise<AskimutAtClient> {
151151+ return AskimutAtClient.fromDid(did)
152152+}
153153+154154+/**
155155+ * Utility function to extract record key (rkey) from AT-URI
156156+ */
157157+export function extractRkeyFromUri(atUri: string): string | null {
158158+ try {
159159+ const parts = atUri.split('/')
160160+ return parts[parts.length - 1] || null
161161+ } catch {
162162+ return null
163163+ }
164164+}
165165+166166+/**
167167+ * Utility function to construct AT-URI from DID and rkey
168168+ */
169169+export function constructAtUri(did: string, collection: string, rkey: string): string {
170170+ return `at://${did}/${collection}/${rkey}`
171171+}