@geminixiang/mikan 1.0.0-beta.95 → 1.0.0-beta.96
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +427 -388
- package/README.md +31 -40
- package/dist/adapters/github/bot.js +1 -1
- package/dist/adapters/github/bot.js.map +1 -1
- package/dist/adapters/github/policy.d.ts +2 -9
- package/dist/adapters/github/policy.d.ts.map +1 -1
- package/dist/adapters/github/policy.js +18 -26
- package/dist/adapters/github/policy.js.map +1 -1
- package/dist/adapters/slack/bot.d.ts +2 -4
- package/dist/adapters/slack/bot.d.ts.map +1 -1
- package/dist/adapters/slack/bot.js +28 -56
- package/dist/adapters/slack/bot.js.map +1 -1
- package/dist/adapters/slack/socket-agent.d.ts +9 -0
- package/dist/adapters/slack/socket-agent.d.ts.map +1 -0
- package/dist/adapters/slack/socket-agent.js +17 -0
- package/dist/adapters/slack/socket-agent.js.map +1 -0
- package/dist/adapters/telegram/bot.d.ts +1 -0
- package/dist/adapters/telegram/bot.d.ts.map +1 -1
- package/dist/adapters/telegram/bot.js +6 -1
- package/dist/adapters/telegram/bot.js.map +1 -1
- package/dist/adapters/telegram/types.d.ts +1 -0
- package/dist/adapters/telegram/types.d.ts.map +1 -1
- package/dist/adapters/telegram/types.js.map +1 -1
- package/dist/cli/arg-grammar.d.ts +1 -2
- package/dist/cli/arg-grammar.d.ts.map +1 -1
- package/dist/cli/arg-grammar.js +2 -17
- package/dist/cli/arg-grammar.js.map +1 -1
- package/dist/cli/boot.d.ts.map +1 -1
- package/dist/cli/boot.js +5 -11
- package/dist/cli/boot.js.map +1 -1
- package/dist/cli/migrate.d.ts.map +1 -1
- package/dist/cli/migrate.js +22 -7
- package/dist/cli/migrate.js.map +1 -1
- package/dist/cli/office.d.ts.map +1 -1
- package/dist/cli/office.js +3 -5
- package/dist/cli/office.js.map +1 -1
- package/dist/cli/onboard.js +18 -20
- package/dist/cli/onboard.js.map +1 -1
- package/dist/cli/types.d.ts +1 -2
- package/dist/cli/types.d.ts.map +1 -1
- package/dist/cli/types.js.map +1 -1
- package/dist/env-manifest.d.ts +2 -0
- package/dist/env-manifest.d.ts.map +1 -1
- package/dist/env-manifest.js +76 -43
- package/dist/env-manifest.js.map +1 -1
- package/dist/events/index.d.ts +5 -5
- package/dist/events/index.d.ts.map +1 -1
- package/dist/events/index.js +1 -7
- package/dist/events/index.js.map +1 -1
- package/dist/file-guards.d.ts +1 -0
- package/dist/file-guards.d.ts.map +1 -1
- package/dist/file-guards.js +4 -1
- package/dist/file-guards.js.map +1 -1
- package/dist/harness/execution-resolver.d.ts.map +1 -1
- package/dist/harness/execution-resolver.js +1 -7
- package/dist/harness/execution-resolver.js.map +1 -1
- package/dist/harness/http.d.ts +1 -2
- package/dist/harness/http.d.ts.map +1 -1
- package/dist/harness/http.js +3 -16
- package/dist/harness/http.js.map +1 -1
- package/dist/harness/jev.d.ts +2 -1
- package/dist/harness/jev.d.ts.map +1 -1
- package/dist/harness/jev.js.map +1 -1
- package/dist/harness/prompt.d.ts.map +1 -1
- package/dist/harness/prompt.js +0 -6
- package/dist/harness/prompt.js.map +1 -1
- package/dist/harness/session.d.ts +2 -9
- package/dist/harness/session.d.ts.map +1 -1
- package/dist/harness/session.js +3 -3
- package/dist/harness/session.js.map +1 -1
- package/dist/harness/tools/event.d.ts +0 -1
- package/dist/harness/tools/event.d.ts.map +1 -1
- package/dist/harness/tools/event.js +1 -7
- package/dist/harness/tools/event.js.map +1 -1
- package/dist/harness/types.d.ts +3 -3
- package/dist/harness/types.d.ts.map +1 -1
- package/dist/harness/types.js.map +1 -1
- package/dist/index.d.ts +8 -31
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -15
- package/dist/index.js.map +1 -1
- package/dist/main.js +26 -36
- package/dist/main.js.map +1 -1
- package/dist/migrations/index.d.ts +0 -1
- package/dist/migrations/index.d.ts.map +1 -1
- package/dist/migrations/index.js +4 -4
- package/dist/migrations/index.js.map +1 -1
- package/dist/migrations/legacy-office-files.d.ts +3 -0
- package/dist/migrations/legacy-office-files.d.ts.map +1 -0
- package/dist/migrations/legacy-office-files.js +29 -0
- package/dist/migrations/legacy-office-files.js.map +1 -0
- package/dist/observability/instrument.js +2 -3
- package/dist/observability/instrument.js.map +1 -1
- package/dist/observability/sentry.js +1 -1
- package/dist/observability/sentry.js.map +1 -1
- package/dist/office/projection.js +2 -2
- package/dist/office/projection.js.map +1 -1
- package/dist/sandbox/identity.d.ts +0 -1
- package/dist/sandbox/identity.d.ts.map +1 -1
- package/dist/sandbox/identity.js +0 -3
- package/dist/sandbox/identity.js.map +1 -1
- package/dist/sandbox/registry.d.ts +1 -5
- package/dist/sandbox/registry.d.ts.map +1 -1
- package/dist/sandbox/registry.js +4 -13
- package/dist/sandbox/registry.js.map +1 -1
- package/dist/sandbox/types.d.ts +1 -5
- package/dist/sandbox/types.d.ts.map +1 -1
- package/dist/sandbox/types.js.map +1 -1
- package/dist/sessions/types.d.ts +1 -1
- package/dist/sessions/types.d.ts.map +1 -1
- package/dist/sessions/types.js.map +1 -1
- package/dist/settings/index.d.ts +56 -2
- package/dist/settings/index.d.ts.map +1 -1
- package/dist/settings/index.js +57 -37
- package/dist/settings/index.js.map +1 -1
- package/dist/types.d.ts +1 -25
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/vault/index.js +1 -1
- package/dist/vault/index.js.map +1 -1
- package/package.json +4 -17
- package/dist/cli/download.d.ts +0 -2
- package/dist/cli/download.d.ts.map +0 -1
- package/dist/cli/download.js +0 -84
- package/dist/cli/download.js.map +0 -1
- package/dist/harness/index.d.ts +0 -20
- package/dist/harness/index.d.ts.map +0 -1
- package/dist/harness/index.js +0 -14
- package/dist/harness/index.js.map +0 -1
- package/dist/sandbox/cloudflare.d.ts +0 -17
- package/dist/sandbox/cloudflare.d.ts.map +0 -1
- package/dist/sandbox/cloudflare.js +0 -142
- package/dist/sandbox/cloudflare.js.map +0 -1
- package/dist/sandbox/index.d.ts +0 -7
- package/dist/sandbox/index.d.ts.map +0 -1
- package/dist/sandbox/index.js +0 -6
- package/dist/sandbox/index.js.map +0 -1
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { ClientRequestArgs } from "node:http";
|
|
2
|
+
import { Agent } from "node:https";
|
|
3
|
+
import type { Duplex } from "node:stream";
|
|
4
|
+
export declare class SlackSocketAgent extends Agent {
|
|
5
|
+
private readonly stallMs;
|
|
6
|
+
constructor(stallMs?: number);
|
|
7
|
+
createConnection(options: ClientRequestArgs, callback?: (error: Error | null, stream: Duplex) => void): Duplex | null | undefined;
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=socket-agent.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"socket-agent.d.ts","sourceRoot":"","sources":["../../../src/adapters/slack/socket-agent.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AACnD,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAEnC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAI1C,qBAAa,gBAAiB,SAAQ,KAAK;IACzC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IAEjC,YAAY,OAAO,SAA4B,EAG9C;IAEQ,gBAAgB,CACvB,OAAO,EAAE,iBAAiB,EAC1B,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,GACvD,MAAM,GAAG,IAAI,GAAG,SAAS,CAQ3B;CACF"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Agent } from "node:https";
|
|
2
|
+
import { Socket } from "node:net";
|
|
3
|
+
const SLACK_CONNECTION_STALL_MS = 30_000;
|
|
4
|
+
export class SlackSocketAgent extends Agent {
|
|
5
|
+
constructor(stallMs = SLACK_CONNECTION_STALL_MS) {
|
|
6
|
+
super();
|
|
7
|
+
this.stallMs = stallMs;
|
|
8
|
+
}
|
|
9
|
+
createConnection(options, callback) {
|
|
10
|
+
const stream = super.createConnection(options, callback);
|
|
11
|
+
if (stream instanceof Socket) {
|
|
12
|
+
stream.setTimeout(this.stallMs, () => stream.destroy(new Error(`Slack connection got no response within ${this.stallMs}ms`)));
|
|
13
|
+
}
|
|
14
|
+
return stream;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=socket-agent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"socket-agent.js","sourceRoot":"","sources":["../../../src/adapters/slack/socket-agent.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAGlC,MAAM,yBAAyB,GAAG,MAAM,CAAC;AAEzC,MAAM,OAAO,gBAAiB,SAAQ,KAAK;IAGzC,YAAY,OAAO,GAAG,yBAAyB;QAC7C,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACzB,CAAC;IAEQ,gBAAgB,CACvB,OAA0B,EAC1B,QAAwD;QAExD,MAAM,MAAM,GAAG,KAAK,CAAC,gBAAgB,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;QACzD,IAAI,MAAM,YAAY,MAAM,EAAE,CAAC;YAC7B,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,EAAE,CACnC,MAAM,CAAC,OAAO,CAAC,IAAI,KAAK,CAAC,2CAA2C,IAAI,CAAC,OAAO,IAAI,CAAC,CAAC,CACvF,CAAC;QACJ,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;CACF","sourcesContent":["import type { ClientRequestArgs } from \"node:http\";\nimport { Agent } from \"node:https\";\nimport { Socket } from \"node:net\";\nimport type { Duplex } from \"node:stream\";\n\nconst SLACK_CONNECTION_STALL_MS = 30_000;\n\nexport class SlackSocketAgent extends Agent {\n private readonly stallMs: number;\n\n constructor(stallMs = SLACK_CONNECTION_STALL_MS) {\n super();\n this.stallMs = stallMs;\n }\n\n override createConnection(\n options: ClientRequestArgs,\n callback?: (error: Error | null, stream: Duplex) => void,\n ): Duplex | null | undefined {\n const stream = super.createConnection(options, callback);\n if (stream instanceof Socket) {\n stream.setTimeout(this.stallMs, () =>\n stream.destroy(new Error(`Slack connection got no response within ${this.stallMs}ms`)),\n );\n }\n return stream;\n }\n}\n"]}
|
|
@@ -13,6 +13,7 @@ export declare class TelegramMessagingBot implements MessagingBot {
|
|
|
13
13
|
private queues;
|
|
14
14
|
private intake;
|
|
15
15
|
private startupTime;
|
|
16
|
+
private readonly onPollingFailure;
|
|
16
17
|
constructor(handler: MessagingEventHandler, options: TelegramMessagingBotOptions);
|
|
17
18
|
start(): Promise<void>;
|
|
18
19
|
stop(): Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bot.d.ts","sourceRoot":"","sources":["../../../src/adapters/telegram/bot.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sBAAsB,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAKxE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,KAAK,EACV,iBAAiB,EACjB,qBAAqB,EAErB,aAAa,EACb,YAAY,EACb,MAAM,gBAAgB,CAAC;AACxB,OAAO,KAAK,EAAiC,2BAA2B,EAAE,MAAM,YAAY,CAAC;AA2C7F,qBAAa,oBAAqB,YAAW,YAAY;IACvD,OAAO,CAAC,MAAM,CAAiB;IAC/B,OAAO,CAAC,OAAO,CAAwB;IACvC,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,SAAS,CAAY;IAC7B,OAAO,CAAC,SAAS,CAAuB;IACxC,OAAO,CAAC,WAAW,CAAuB;IAC1C,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,MAAM,CAA0C;IACxD,OAAO,CAAC,MAAM,CAA0C;IACxD,OAAO,CAAC,WAAW,CAAa;
|
|
1
|
+
{"version":3,"file":"bot.d.ts","sourceRoot":"","sources":["../../../src/adapters/telegram/bot.ts"],"names":[],"mappings":"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"}
|
|
@@ -29,6 +29,9 @@ export class TelegramMessagingBot {
|
|
|
29
29
|
this.botToken = options.token;
|
|
30
30
|
this.workspace = options.workspace;
|
|
31
31
|
this.client = options.client ?? new GrammyMessagingBot(options.token);
|
|
32
|
+
this.onPollingFailure =
|
|
33
|
+
options.onPollingFailure ??
|
|
34
|
+
((error) => log.logWarning("Telegram polling error", error.message));
|
|
32
35
|
this.client.catch((err) => {
|
|
33
36
|
log.logWarning("Telegram error", errorMessage(err));
|
|
34
37
|
});
|
|
@@ -44,7 +47,9 @@ export class TelegramMessagingBot {
|
|
|
44
47
|
return;
|
|
45
48
|
this.setupEventHandlers();
|
|
46
49
|
this.client.start().catch((err) => {
|
|
47
|
-
|
|
50
|
+
if (this.stopped)
|
|
51
|
+
return;
|
|
52
|
+
this.onPollingFailure(err instanceof Error ? err : new Error(String(err)));
|
|
48
53
|
});
|
|
49
54
|
log.logConnected("Telegram");
|
|
50
55
|
log.logInfo(`Telegram bot started as @${this.botUsername ?? this.botUserId}`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bot.js","sourceRoot":"","sources":["../../../src/adapters/telegram/bot.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ConversationLogMessage, RunAnswer } from \"../../types.js\";\nimport { appendBotResponseLog, appendOfficeLog } from \"../../office/log.js\";\nimport { readFileSync } from \"node:fs\";\nimport { basename } from \"node:path\";\nimport { Bot as GrammyMessagingBot, InputFile } from \"grammy\";\nimport type { Message } from \"grammy/types\";\nimport type {\n ConversationEvent,\n MessagingEventHandler,\n ConversationKind,\n MessagingInfo,\n MessagingBot,\n} from \"../../types.js\";\nimport type { TelegramClient, TelegramEvent, TelegramMessagingBotOptions } from \"./types.js\";\nimport * as log from \"../../log.js\";\nimport { resolveChatSessionKey } from \"../../sessions/session-key.js\";\nimport {\n MessagingEventQueue,\n MessagingIntakeTracker,\n downloadUrlToFile,\n withRetry,\n saveIncomingAttachments,\n shortNameToUnicodeEmoji,\n} from \"../shared.js\";\nimport type { IncomingAttachment } from \"../types.js\";\nimport { COMMAND_MANIFEST, telegramCommandMenu } from \"../commands/manifest.js\";\nimport { processMessageIntake } from \"../intake.js\";\nimport { createTelegramAdapters } from \"./context.js\";\nimport { createConversationEvent, createOfficeAddress } from \"../../office/index.js\";\nimport type { Workspace } from \"../../office/types.js\";\nimport { errorMessage } from \"../../unknown-values.js\";\n\nfunction telegramIsRateLimited(err: Error): boolean {\n return (err as { error_code?: number }).error_code === 429;\n}\n\nconst telegramRetry = <T>(fn: () => Promise<T>): Promise<T> =>\n withRetry(fn, { isRateLimited: telegramIsRateLimited });\n\ninterface MessageContext {\n msg: Message;\n text: string;\n chatId: string;\n chatType: string;\n conversationKind: ConversationKind;\n userId: string;\n userName: string;\n msgId: string;\n threadTs: string | undefined;\n sessionKey: string;\n}\n\nfunction richMessage(markdown: string): { markdown: string } {\n return { markdown };\n}\n\nexport class TelegramMessagingBot implements MessagingBot {\n private client: TelegramClient;\n private handler: MessagingEventHandler;\n private botToken: string;\n private workspace: Workspace;\n private botUserId: string | null = null;\n private botUsername: string | null = null;\n private stopped = false;\n private queues = new Map<string, MessagingEventQueue>();\n private intake = new MessagingIntakeTracker(\"Telegram\");\n private startupTime: number = 0;\n\n constructor(handler: MessagingEventHandler, options: TelegramMessagingBotOptions) {\n this.handler = handler;\n this.botToken = options.token;\n this.workspace = options.workspace;\n this.client = options.client ?? new GrammyMessagingBot(options.token);\n this.client.catch((err) => {\n log.logWarning(\"Telegram error\", errorMessage(err));\n });\n }\n\n async start(): Promise<void> {\n this.stopped = false;\n const me = await this.client.api.getMe();\n this.botUserId = String(me.id);\n this.botUsername = me.username ?? null;\n this.startupTime = Date.now();\n\n await this.client.api.setMyCommands(telegramCommandMenu());\n if (this.stopped) return;\n\n this.setupEventHandlers();\n\n this.client.start().catch((err) => {\n log.logWarning(\"Telegram polling error\", errorMessage(err));\n });\n\n log.logConnected(\"Telegram\");\n log.logInfo(`Telegram bot started as @${this.botUsername ?? this.botUserId}`);\n }\n\n async stop(): Promise<void> {\n this.stopped = true;\n try {\n await this.client.stop();\n } finally {\n await this.intake.close();\n await Promise.all([...this.queues.values()].map((queue) => queue.close()));\n }\n }\n\n async postMessage(channel: string, text: string): Promise<string> {\n const result = await this.postMessageRaw(parseInt(channel), text);\n return String(result);\n }\n\n async addReaction(channel: string, messageTs: string, emoji: string): Promise<void> {\n await telegramRetry(async () => {\n await this.client.api.setMessageReaction(parseInt(channel), parseInt(messageTs), [\n { type: \"emoji\", emoji: shortNameToUnicodeEmoji(emoji) as never },\n ]);\n });\n }\n\n async updateMessage(channel: string, ts: string, text: string): Promise<void> {\n return telegramRetry(async () => {\n try {\n await this.client.api.editMessageText(parseInt(channel), parseInt(ts), richMessage(text));\n } catch (err) {\n const msg = errorMessage(err);\n if (msg.includes(\"message is not modified\")) return;\n throw err;\n }\n });\n }\n\n enqueueEvent(event: ConversationEvent): boolean {\n if (this.stopped) return false;\n return this.getQueue(event.address.conversationId).offerEvent(event, () => {\n const context = createTelegramAdapters(event as TelegramEvent, this);\n return this.handler.handleEvent(event, this, context);\n });\n }\n\n getMessagingInfo(): MessagingInfo {\n return {\n name: \"telegram\",\n trustModel: \"membership\",\n formattingGuide:\n \"## Telegram Formatting (Markdown)\\nWrite ordinary Markdown — headings, lists, tables, code fences, quotes and links all render natively. Nothing needs converting by hand.\",\n channels: [],\n users: [],\n };\n }\n\n async postMessageRaw(chatId: number, text: string): Promise<number> {\n return telegramRetry(async () => {\n const result = await this.client.api.sendRichMessage(chatId, richMessage(text));\n return result.message_id;\n });\n }\n\n async postPlainMessage(chatId: number, text: string): Promise<void> {\n return telegramRetry(async () => {\n await this.client.api.sendMessage(chatId, text);\n });\n }\n\n async postReply(chatId: number, replyToMessageId: number, text: string): Promise<number> {\n return telegramRetry(async () => {\n const result = await this.client.api.sendRichMessage(chatId, richMessage(text), {\n reply_parameters: { message_id: replyToMessageId },\n });\n return result.message_id;\n });\n }\n\n async deleteMessageRaw(chatId: number, messageId: number): Promise<void> {\n await this.client.api.deleteMessage(chatId, messageId);\n }\n\n async sendTyping(chatId: number): Promise<void> {\n await this.client.api.sendChatAction(chatId, \"typing\");\n }\n\n async uploadFile(channel: string, filePath: string, title?: string): Promise<void> {\n return telegramRetry(async () => {\n const fileName = title ?? basename(filePath);\n const fileContent = readFileSync(filePath);\n await this.client.api.sendDocument(parseInt(channel), new InputFile(fileContent, fileName));\n });\n }\n\n logToFile(channel: string, entry: ConversationLogMessage): void {\n appendOfficeLog(this.workspace.office(createOfficeAddress(\"telegram\", channel)), entry);\n }\n\n logBotResponse(\n channel: string,\n text: string,\n ts: string,\n threadTs?: string,\n { answer }: { answer?: RunAnswer } = {},\n ): void {\n appendBotResponseLog(this.workspace.office(createOfficeAddress(\"telegram\", channel)), {\n text,\n ts,\n threadTs,\n answer,\n });\n }\n\n async processAttachments(\n chatId: string,\n message: Message,\n ): Promise<{ name: string; localPath: string }[]> {\n const items: IncomingAttachment[] = [];\n\n const photo = message.photo?.[message.photo.length - 1];\n if (photo) {\n items.push(this.telegramFileItem(photo.file_id, `photo_${message.message_id}.jpg`));\n }\n if (message.document) {\n const doc = message.document;\n items.push(\n this.telegramFileItem(doc.file_id, doc.file_name ?? `document_${message.message_id}`),\n );\n }\n\n const office = this.workspace.office(createOfficeAddress(\"telegram\", chatId));\n const { saved, failed } = await saveIncomingAttachments(office, items);\n for (const failure of failed) {\n log.logWarning(`Failed to process Telegram file`, `${failure.name}: ${failure.error}`);\n }\n return saved.map((item) => ({ name: item.original, localPath: item.localPath }));\n }\n\n private telegramFileItem(fileId: string, name: string): IncomingAttachment {\n return {\n name,\n download: async (destPath) => {\n const file = await this.client.api.getFile(fileId);\n if (!file.file_path) throw new Error(`Telegram file has no path: ${fileId}`);\n await downloadUrlToFile(\n `https://api.telegram.org/file/bot${this.botToken}/${file.file_path}`,\n destPath,\n );\n },\n };\n }\n\n private getQueue(channelId: string): MessagingEventQueue {\n let queue = this.queues.get(channelId);\n if (!queue) {\n queue = new MessagingEventQueue(\"Telegram\");\n this.queues.set(channelId, queue);\n }\n return queue;\n }\n\n private extractMessageContext(msg: Message): MessageContext | null {\n if (!msg) return null;\n if (msg.date * 1000 < this.startupTime) return null;\n if (msg.from?.is_bot) return null;\n\n const text = msg.text ?? msg.caption ?? \"\";\n if (!text && !msg.document && !msg.photo) return null;\n\n const chatId = String(msg.chat.id);\n const chatType = msg.chat.type;\n const userId = String(msg.from?.id ?? \"unknown\");\n const userName = msg.from?.username ?? msg.from?.first_name ?? userId;\n const msgId = String(msg.message_id);\n const replyToId = msg.reply_to_message?.message_id;\n const threadTs = replyToId ? String(replyToId) : undefined;\n const conversationKind = chatType === \"private\" ? \"direct\" : \"shared\";\n\n const sessionKey = resolveChatSessionKey({\n conversationId: chatId,\n conversationKind,\n messageId: msgId,\n threadTs,\n });\n\n return {\n msg,\n text,\n chatId,\n chatType,\n conversationKind,\n userId,\n userName,\n msgId,\n threadTs,\n sessionKey,\n };\n }\n\n private isAddressedToMessagingBot(text: string, chatType: string): boolean {\n if (chatType === \"private\") return true;\n if (!this.botUsername) return false;\n return text.toLowerCase().includes(`@${this.botUsername.toLowerCase()}`);\n }\n\n private cleanText(text: string): string {\n if (!this.botUsername) return text.trim();\n return text.replace(new RegExp(`@${this.botUsername}`, \"gi\"), \"\").trim();\n }\n\n private setupEventHandlers(): void {\n for (const entry of COMMAND_MANIFEST) {\n if (!entry.telegramCommand || entry.magicWord) continue;\n this.client.command(entry.name, (ctx) =>\n this.intake.run(async () => {\n const mc = ctx.message ? this.extractMessageContext(ctx.message) : null;\n if (!mc) return;\n const commandText = this.cleanText(mc.text);\n const event = createConversationEvent({\n platform: \"telegram\",\n type: \"command\",\n conversationId: mc.chatId,\n conversationKind: mc.conversationKind,\n ts: mc.msgId,\n thread_ts: mc.threadTs,\n sessionKey: mc.sessionKey,\n user: mc.userId,\n userName: mc.userName,\n text: commandText,\n attachments: [],\n }) as TelegramEvent;\n this.logToFile(mc.chatId, {\n date: new Date(mc.msg.date * 1000).toISOString(),\n ts: mc.msgId,\n threadTs: mc.conversationKind === \"shared\" && mc.threadTs ? mc.threadTs : undefined,\n user: mc.userId,\n userName: mc.userName,\n text: commandText,\n attachments: [],\n isMessagingBot: false,\n });\n await this.handler.handleEvent(event, this, createTelegramAdapters(event, this));\n }),\n );\n }\n\n this.client.on(\"message\", (ctx) =>\n this.intake.run(async () => {\n const mc = ctx.message ? this.extractMessageContext(ctx.message) : null;\n if (!mc) return;\n\n const cleanedText = this.cleanText(mc.text);\n const addressedToMessagingBot = this.isAddressedToMessagingBot(mc.text, mc.chatType);\n const addressed = mc.chatType === \"private\" || addressedToMessagingBot;\n\n const eventBase = createConversationEvent({\n platform: \"telegram\",\n type: \"message\",\n conversationId: mc.chatId,\n conversationKind: mc.conversationKind,\n ts: mc.msgId,\n thread_ts: mc.threadTs,\n sessionKey: mc.sessionKey,\n user: mc.userId,\n userName: mc.userName,\n text: cleanedText,\n }) as TelegramEvent;\n\n await processMessageIntake({\n eventBase,\n addressed,\n magicWord: {\n addressed: addressedToMessagingBot || mc.chatType === \"private\",\n scopeFallback: \"always\",\n },\n busyPolicy: \"reject\",\n logEntryBase: {\n date: new Date(mc.msg.date * 1000).toISOString(),\n ts: mc.msgId,\n threadTs: mc.conversationKind === \"shared\" && mc.threadTs ? mc.threadTs : undefined,\n user: mc.userId,\n userName: mc.userName,\n text: cleanedText,\n isMessagingBot: false,\n },\n log: (entry) => this.logToFile(mc.chatId, entry),\n processAttachments: () => this.processAttachments(mc.chatId, mc.msg),\n queueKey: mc.sessionKey,\n enqueue: (queueKey, work) => this.getQueue(queueKey).admit(work),\n handler: this.handler,\n bot: this,\n createContext: (event) => createTelegramAdapters(event, this),\n });\n }),\n );\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"bot.js","sourceRoot":"","sources":["../../../src/adapters/telegram/bot.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ConversationLogMessage, RunAnswer } from \"../../types.js\";\nimport { appendBotResponseLog, appendOfficeLog } from \"../../office/log.js\";\nimport { readFileSync } from \"node:fs\";\nimport { basename } from \"node:path\";\nimport { Bot as GrammyMessagingBot, InputFile } from \"grammy\";\nimport type { Message } from \"grammy/types\";\nimport type {\n ConversationEvent,\n MessagingEventHandler,\n ConversationKind,\n MessagingInfo,\n MessagingBot,\n} from \"../../types.js\";\nimport type { TelegramClient, TelegramEvent, TelegramMessagingBotOptions } from \"./types.js\";\nimport * as log from \"../../log.js\";\nimport { resolveChatSessionKey } from \"../../sessions/session-key.js\";\nimport {\n MessagingEventQueue,\n MessagingIntakeTracker,\n downloadUrlToFile,\n withRetry,\n saveIncomingAttachments,\n shortNameToUnicodeEmoji,\n} from \"../shared.js\";\nimport type { IncomingAttachment } from \"../types.js\";\nimport { COMMAND_MANIFEST, telegramCommandMenu } from \"../commands/manifest.js\";\nimport { processMessageIntake } from \"../intake.js\";\nimport { createTelegramAdapters } from \"./context.js\";\nimport { createConversationEvent, createOfficeAddress } from \"../../office/index.js\";\nimport type { Workspace } from \"../../office/types.js\";\nimport { errorMessage } from \"../../unknown-values.js\";\n\nfunction telegramIsRateLimited(err: Error): boolean {\n return (err as { error_code?: number }).error_code === 429;\n}\n\nconst telegramRetry = <T>(fn: () => Promise<T>): Promise<T> =>\n withRetry(fn, { isRateLimited: telegramIsRateLimited });\n\ninterface MessageContext {\n msg: Message;\n text: string;\n chatId: string;\n chatType: string;\n conversationKind: ConversationKind;\n userId: string;\n userName: string;\n msgId: string;\n threadTs: string | undefined;\n sessionKey: string;\n}\n\nfunction richMessage(markdown: string): { markdown: string } {\n return { markdown };\n}\n\nexport class TelegramMessagingBot implements MessagingBot {\n private client: TelegramClient;\n private handler: MessagingEventHandler;\n private botToken: string;\n private workspace: Workspace;\n private botUserId: string | null = null;\n private botUsername: string | null = null;\n private stopped = false;\n private queues = new Map<string, MessagingEventQueue>();\n private intake = new MessagingIntakeTracker(\"Telegram\");\n private startupTime: number = 0;\n private readonly onPollingFailure: (error: Error) => void;\n\n constructor(handler: MessagingEventHandler, options: TelegramMessagingBotOptions) {\n this.handler = handler;\n this.botToken = options.token;\n this.workspace = options.workspace;\n this.client = options.client ?? new GrammyMessagingBot(options.token);\n this.onPollingFailure =\n options.onPollingFailure ??\n ((error) => log.logWarning(\"Telegram polling error\", error.message));\n this.client.catch((err) => {\n log.logWarning(\"Telegram error\", errorMessage(err));\n });\n }\n\n async start(): Promise<void> {\n this.stopped = false;\n const me = await this.client.api.getMe();\n this.botUserId = String(me.id);\n this.botUsername = me.username ?? null;\n this.startupTime = Date.now();\n\n await this.client.api.setMyCommands(telegramCommandMenu());\n if (this.stopped) return;\n\n this.setupEventHandlers();\n\n this.client.start().catch((err: unknown) => {\n if (this.stopped) return;\n this.onPollingFailure(err instanceof Error ? err : new Error(String(err)));\n });\n\n log.logConnected(\"Telegram\");\n log.logInfo(`Telegram bot started as @${this.botUsername ?? this.botUserId}`);\n }\n\n async stop(): Promise<void> {\n this.stopped = true;\n try {\n await this.client.stop();\n } finally {\n await this.intake.close();\n await Promise.all([...this.queues.values()].map((queue) => queue.close()));\n }\n }\n\n async postMessage(channel: string, text: string): Promise<string> {\n const result = await this.postMessageRaw(parseInt(channel), text);\n return String(result);\n }\n\n async addReaction(channel: string, messageTs: string, emoji: string): Promise<void> {\n await telegramRetry(async () => {\n await this.client.api.setMessageReaction(parseInt(channel), parseInt(messageTs), [\n { type: \"emoji\", emoji: shortNameToUnicodeEmoji(emoji) as never },\n ]);\n });\n }\n\n async updateMessage(channel: string, ts: string, text: string): Promise<void> {\n return telegramRetry(async () => {\n try {\n await this.client.api.editMessageText(parseInt(channel), parseInt(ts), richMessage(text));\n } catch (err) {\n const msg = errorMessage(err);\n if (msg.includes(\"message is not modified\")) return;\n throw err;\n }\n });\n }\n\n enqueueEvent(event: ConversationEvent): boolean {\n if (this.stopped) return false;\n return this.getQueue(event.address.conversationId).offerEvent(event, () => {\n const context = createTelegramAdapters(event as TelegramEvent, this);\n return this.handler.handleEvent(event, this, context);\n });\n }\n\n getMessagingInfo(): MessagingInfo {\n return {\n name: \"telegram\",\n trustModel: \"membership\",\n formattingGuide:\n \"## Telegram Formatting (Markdown)\\nWrite ordinary Markdown — headings, lists, tables, code fences, quotes and links all render natively. Nothing needs converting by hand.\",\n channels: [],\n users: [],\n };\n }\n\n async postMessageRaw(chatId: number, text: string): Promise<number> {\n return telegramRetry(async () => {\n const result = await this.client.api.sendRichMessage(chatId, richMessage(text));\n return result.message_id;\n });\n }\n\n async postPlainMessage(chatId: number, text: string): Promise<void> {\n return telegramRetry(async () => {\n await this.client.api.sendMessage(chatId, text);\n });\n }\n\n async postReply(chatId: number, replyToMessageId: number, text: string): Promise<number> {\n return telegramRetry(async () => {\n const result = await this.client.api.sendRichMessage(chatId, richMessage(text), {\n reply_parameters: { message_id: replyToMessageId },\n });\n return result.message_id;\n });\n }\n\n async deleteMessageRaw(chatId: number, messageId: number): Promise<void> {\n await this.client.api.deleteMessage(chatId, messageId);\n }\n\n async sendTyping(chatId: number): Promise<void> {\n await this.client.api.sendChatAction(chatId, \"typing\");\n }\n\n async uploadFile(channel: string, filePath: string, title?: string): Promise<void> {\n return telegramRetry(async () => {\n const fileName = title ?? basename(filePath);\n const fileContent = readFileSync(filePath);\n await this.client.api.sendDocument(parseInt(channel), new InputFile(fileContent, fileName));\n });\n }\n\n logToFile(channel: string, entry: ConversationLogMessage): void {\n appendOfficeLog(this.workspace.office(createOfficeAddress(\"telegram\", channel)), entry);\n }\n\n logBotResponse(\n channel: string,\n text: string,\n ts: string,\n threadTs?: string,\n { answer }: { answer?: RunAnswer } = {},\n ): void {\n appendBotResponseLog(this.workspace.office(createOfficeAddress(\"telegram\", channel)), {\n text,\n ts,\n threadTs,\n answer,\n });\n }\n\n async processAttachments(\n chatId: string,\n message: Message,\n ): Promise<{ name: string; localPath: string }[]> {\n const items: IncomingAttachment[] = [];\n\n const photo = message.photo?.[message.photo.length - 1];\n if (photo) {\n items.push(this.telegramFileItem(photo.file_id, `photo_${message.message_id}.jpg`));\n }\n if (message.document) {\n const doc = message.document;\n items.push(\n this.telegramFileItem(doc.file_id, doc.file_name ?? `document_${message.message_id}`),\n );\n }\n\n const office = this.workspace.office(createOfficeAddress(\"telegram\", chatId));\n const { saved, failed } = await saveIncomingAttachments(office, items);\n for (const failure of failed) {\n log.logWarning(`Failed to process Telegram file`, `${failure.name}: ${failure.error}`);\n }\n return saved.map((item) => ({ name: item.original, localPath: item.localPath }));\n }\n\n private telegramFileItem(fileId: string, name: string): IncomingAttachment {\n return {\n name,\n download: async (destPath) => {\n const file = await this.client.api.getFile(fileId);\n if (!file.file_path) throw new Error(`Telegram file has no path: ${fileId}`);\n await downloadUrlToFile(\n `https://api.telegram.org/file/bot${this.botToken}/${file.file_path}`,\n destPath,\n );\n },\n };\n }\n\n private getQueue(channelId: string): MessagingEventQueue {\n let queue = this.queues.get(channelId);\n if (!queue) {\n queue = new MessagingEventQueue(\"Telegram\");\n this.queues.set(channelId, queue);\n }\n return queue;\n }\n\n private extractMessageContext(msg: Message): MessageContext | null {\n if (!msg) return null;\n if (msg.date * 1000 < this.startupTime) return null;\n if (msg.from?.is_bot) return null;\n\n const text = msg.text ?? msg.caption ?? \"\";\n if (!text && !msg.document && !msg.photo) return null;\n\n const chatId = String(msg.chat.id);\n const chatType = msg.chat.type;\n const userId = String(msg.from?.id ?? \"unknown\");\n const userName = msg.from?.username ?? msg.from?.first_name ?? userId;\n const msgId = String(msg.message_id);\n const replyToId = msg.reply_to_message?.message_id;\n const threadTs = replyToId ? String(replyToId) : undefined;\n const conversationKind = chatType === \"private\" ? \"direct\" : \"shared\";\n\n const sessionKey = resolveChatSessionKey({\n conversationId: chatId,\n conversationKind,\n messageId: msgId,\n threadTs,\n });\n\n return {\n msg,\n text,\n chatId,\n chatType,\n conversationKind,\n userId,\n userName,\n msgId,\n threadTs,\n sessionKey,\n };\n }\n\n private isAddressedToMessagingBot(text: string, chatType: string): boolean {\n if (chatType === \"private\") return true;\n if (!this.botUsername) return false;\n return text.toLowerCase().includes(`@${this.botUsername.toLowerCase()}`);\n }\n\n private cleanText(text: string): string {\n if (!this.botUsername) return text.trim();\n return text.replace(new RegExp(`@${this.botUsername}`, \"gi\"), \"\").trim();\n }\n\n private setupEventHandlers(): void {\n for (const entry of COMMAND_MANIFEST) {\n if (!entry.telegramCommand || entry.magicWord) continue;\n this.client.command(entry.name, (ctx) =>\n this.intake.run(async () => {\n const mc = ctx.message ? this.extractMessageContext(ctx.message) : null;\n if (!mc) return;\n const commandText = this.cleanText(mc.text);\n const event = createConversationEvent({\n platform: \"telegram\",\n type: \"command\",\n conversationId: mc.chatId,\n conversationKind: mc.conversationKind,\n ts: mc.msgId,\n thread_ts: mc.threadTs,\n sessionKey: mc.sessionKey,\n user: mc.userId,\n userName: mc.userName,\n text: commandText,\n attachments: [],\n }) as TelegramEvent;\n this.logToFile(mc.chatId, {\n date: new Date(mc.msg.date * 1000).toISOString(),\n ts: mc.msgId,\n threadTs: mc.conversationKind === \"shared\" && mc.threadTs ? mc.threadTs : undefined,\n user: mc.userId,\n userName: mc.userName,\n text: commandText,\n attachments: [],\n isMessagingBot: false,\n });\n await this.handler.handleEvent(event, this, createTelegramAdapters(event, this));\n }),\n );\n }\n\n this.client.on(\"message\", (ctx) =>\n this.intake.run(async () => {\n const mc = ctx.message ? this.extractMessageContext(ctx.message) : null;\n if (!mc) return;\n\n const cleanedText = this.cleanText(mc.text);\n const addressedToMessagingBot = this.isAddressedToMessagingBot(mc.text, mc.chatType);\n const addressed = mc.chatType === \"private\" || addressedToMessagingBot;\n\n const eventBase = createConversationEvent({\n platform: \"telegram\",\n type: \"message\",\n conversationId: mc.chatId,\n conversationKind: mc.conversationKind,\n ts: mc.msgId,\n thread_ts: mc.threadTs,\n sessionKey: mc.sessionKey,\n user: mc.userId,\n userName: mc.userName,\n text: cleanedText,\n }) as TelegramEvent;\n\n await processMessageIntake({\n eventBase,\n addressed,\n magicWord: {\n addressed: addressedToMessagingBot || mc.chatType === \"private\",\n scopeFallback: \"always\",\n },\n busyPolicy: \"reject\",\n logEntryBase: {\n date: new Date(mc.msg.date * 1000).toISOString(),\n ts: mc.msgId,\n threadTs: mc.conversationKind === \"shared\" && mc.threadTs ? mc.threadTs : undefined,\n user: mc.userId,\n userName: mc.userName,\n text: cleanedText,\n isMessagingBot: false,\n },\n log: (entry) => this.logToFile(mc.chatId, entry),\n processAttachments: () => this.processAttachments(mc.chatId, mc.msg),\n queueKey: mc.sessionKey,\n enqueue: (queueKey, work) => this.getQueue(queueKey).admit(work),\n handler: this.handler,\n bot: this,\n createContext: (event) => createTelegramAdapters(event, this),\n });\n }),\n );\n }\n}\n"]}
|
|
@@ -23,6 +23,7 @@ export interface TelegramMessagingBotOptions {
|
|
|
23
23
|
token: string;
|
|
24
24
|
workspace: Workspace;
|
|
25
25
|
client?: TelegramClient;
|
|
26
|
+
onPollingFailure?: (error: Error) => void;
|
|
26
27
|
}
|
|
27
28
|
export type TelegramResponseBot = Pick<TelegramMessagingBot, "getMessagingInfo" | "sendTyping" | "postPlainMessage" | "postReply" | "postMessageRaw" | "updateMessage" | "deleteMessageRaw" | "logBotResponse" | "uploadFile" | "addReaction">;
|
|
28
29
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/adapters/telegram/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAC5C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACxD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAC;AAErD,MAAM,WAAW,aAAc,SAAQ,iBAAiB;IACtD,IAAI,EAAE,SAAS,GAAG,SAAS,CAAC;IAC5B,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,UAAU,qBAAqB;IAC7B,OAAO,EAAE,OAAO,GAAG,SAAS,CAAC;CAC9B;AAED,MAAM,MAAM,qBAAqB,GAAG,CAAC,GAAG,EAAE,qBAAqB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;AAElF,MAAM,WAAW,cAAc;IAC7B,GAAG,EAAE,IAAI,CACP,GAAG,EACD,OAAO,GACP,eAAe,GACf,oBAAoB,GACpB,iBAAiB,GACjB,iBAAiB,GACjB,aAAa,GACb,eAAe,GACf,gBAAgB,GAChB,cAAc,GACd,SAAS,CACZ,CAAC;IACF,KAAK,CAAC,YAAY,EAAE,CAAC,KAAK,EAAE,QAAQ,KAAK,IAAI,GAAG,IAAI,CAAC;IACrD,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACtB,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAAC;IAClE,EAAE,CAAC,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAAC;CAChE;AAED,MAAM,WAAW,2BAA2B;IAC1C,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,SAAS,CAAC;IACrB,MAAM,CAAC,EAAE,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/adapters/telegram/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAC5C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACxD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAC;AAErD,MAAM,WAAW,aAAc,SAAQ,iBAAiB;IACtD,IAAI,EAAE,SAAS,GAAG,SAAS,CAAC;IAC5B,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,UAAU,qBAAqB;IAC7B,OAAO,EAAE,OAAO,GAAG,SAAS,CAAC;CAC9B;AAED,MAAM,MAAM,qBAAqB,GAAG,CAAC,GAAG,EAAE,qBAAqB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;AAElF,MAAM,WAAW,cAAc;IAC7B,GAAG,EAAE,IAAI,CACP,GAAG,EACD,OAAO,GACP,eAAe,GACf,oBAAoB,GACpB,iBAAiB,GACjB,iBAAiB,GACjB,aAAa,GACb,eAAe,GACf,gBAAgB,GAChB,cAAc,GACd,SAAS,CACZ,CAAC;IACF,KAAK,CAAC,YAAY,EAAE,CAAC,KAAK,EAAE,QAAQ,KAAK,IAAI,GAAG,IAAI,CAAC;IACrD,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACtB,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAAC;IAClE,EAAE,CAAC,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAAC;CAChE;AAED,MAAM,WAAW,2BAA2B;IAC1C,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,SAAS,CAAC;IACrB,MAAM,CAAC,EAAE,cAAc,CAAC;IACxB,gBAAgB,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CAC3C;AAED,MAAM,MAAM,mBAAmB,GAAG,IAAI,CACpC,oBAAoB,EAClB,kBAAkB,GAClB,YAAY,GACZ,kBAAkB,GAClB,WAAW,GACX,gBAAgB,GAChB,eAAe,GACf,kBAAkB,GAClB,gBAAgB,GAChB,YAAY,GACZ,aAAa,CAChB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/adapters/telegram/types.ts"],"names":[],"mappings":"","sourcesContent":["import type { Api, BotError } from \"grammy\";\nimport type { Message } from \"grammy/types\";\nimport type { ConversationEvent } from \"../../types.js\";\nimport type { Workspace } from \"../../office/types.js\";\nimport type { TelegramMessagingBot } from \"./bot.js\";\n\nexport interface TelegramEvent extends ConversationEvent {\n type: \"message\" | \"command\";\n userName?: string;\n}\n\ninterface TelegramMessageUpdate {\n message: Message | undefined;\n}\n\nexport type TelegramUpdateHandler = (ctx: TelegramMessageUpdate) => Promise<void>;\n\nexport interface TelegramClient {\n api: Pick<\n Api,\n | \"getMe\"\n | \"setMyCommands\"\n | \"setMessageReaction\"\n | \"editMessageText\"\n | \"sendRichMessage\"\n | \"sendMessage\"\n | \"deleteMessage\"\n | \"sendChatAction\"\n | \"sendDocument\"\n | \"getFile\"\n >;\n catch(errorHandler: (error: BotError) => void): void;\n start(): Promise<void>;\n stop(): Promise<void>;\n command(command: string, handler: TelegramUpdateHandler): unknown;\n on(filter: \"message\", handler: TelegramUpdateHandler): unknown;\n}\n\nexport interface TelegramMessagingBotOptions {\n token: string;\n workspace: Workspace;\n client?: TelegramClient;\n}\n\nexport type TelegramResponseBot = Pick<\n TelegramMessagingBot,\n | \"getMessagingInfo\"\n | \"sendTyping\"\n | \"postPlainMessage\"\n | \"postReply\"\n | \"postMessageRaw\"\n | \"updateMessage\"\n | \"deleteMessageRaw\"\n | \"logBotResponse\"\n | \"uploadFile\"\n | \"addReaction\"\n>;\n"]}
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/adapters/telegram/types.ts"],"names":[],"mappings":"","sourcesContent":["import type { Api, BotError } from \"grammy\";\nimport type { Message } from \"grammy/types\";\nimport type { ConversationEvent } from \"../../types.js\";\nimport type { Workspace } from \"../../office/types.js\";\nimport type { TelegramMessagingBot } from \"./bot.js\";\n\nexport interface TelegramEvent extends ConversationEvent {\n type: \"message\" | \"command\";\n userName?: string;\n}\n\ninterface TelegramMessageUpdate {\n message: Message | undefined;\n}\n\nexport type TelegramUpdateHandler = (ctx: TelegramMessageUpdate) => Promise<void>;\n\nexport interface TelegramClient {\n api: Pick<\n Api,\n | \"getMe\"\n | \"setMyCommands\"\n | \"setMessageReaction\"\n | \"editMessageText\"\n | \"sendRichMessage\"\n | \"sendMessage\"\n | \"deleteMessage\"\n | \"sendChatAction\"\n | \"sendDocument\"\n | \"getFile\"\n >;\n catch(errorHandler: (error: BotError) => void): void;\n start(): Promise<void>;\n stop(): Promise<void>;\n command(command: string, handler: TelegramUpdateHandler): unknown;\n on(filter: \"message\", handler: TelegramUpdateHandler): unknown;\n}\n\nexport interface TelegramMessagingBotOptions {\n token: string;\n workspace: Workspace;\n client?: TelegramClient;\n onPollingFailure?: (error: Error) => void;\n}\n\nexport type TelegramResponseBot = Pick<\n TelegramMessagingBot,\n | \"getMessagingInfo\"\n | \"sendTyping\"\n | \"postPlainMessage\"\n | \"postReply\"\n | \"postMessageRaw\"\n | \"updateMessage\"\n | \"deleteMessageRaw\"\n | \"logBotResponse\"\n | \"uploadFile\"\n | \"addReaction\"\n>;\n"]}
|
|
@@ -2,6 +2,5 @@ import { Command } from "commander";
|
|
|
2
2
|
export declare function cliCommand(name: string): Command;
|
|
3
3
|
export declare function nonEmptyValue(value: string): string;
|
|
4
4
|
export declare function commandExitCode(error: unknown, command: Command): number;
|
|
5
|
-
export declare function
|
|
6
|
-
export declare function resolveStateDir(args?: string[], envValue?: string | undefined): string;
|
|
5
|
+
export declare function stateDirPath(): string;
|
|
7
6
|
//# sourceMappingURL=arg-grammar.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"arg-grammar.d.ts","sourceRoot":"","sources":["../../src/cli/arg-grammar.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAwC,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"arg-grammar.d.ts","sourceRoot":"","sources":["../../src/cli/arg-grammar.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAwC,MAAM,WAAW,CAAC;AAI1E,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAQhD;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAKnD;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,GAAG,MAAM,CAIxE;AAED,wBAAgB,YAAY,IAAI,MAAM,CAErC"}
|
package/dist/cli/arg-grammar.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { Command, CommanderError, InvalidArgumentError } from "commander";
|
|
2
2
|
import { homedir } from "node:os";
|
|
3
|
-
import { join
|
|
4
|
-
import { readEnv } from "../env-manifest.js";
|
|
3
|
+
import { join } from "node:path";
|
|
5
4
|
export function cliCommand(name) {
|
|
6
5
|
return new Command(name)
|
|
7
6
|
.configureHelp({ showGlobalOptions: true })
|
|
@@ -24,21 +23,7 @@ export function commandExitCode(error, command) {
|
|
|
24
23
|
console.error(`${error.message}\n${command.helpInformation()}`);
|
|
25
24
|
return error.exitCode;
|
|
26
25
|
}
|
|
27
|
-
export function
|
|
26
|
+
export function stateDirPath() {
|
|
28
27
|
return join(homedir(), ".mikan");
|
|
29
28
|
}
|
|
30
|
-
export function resolveStateDir(args = process.argv.slice(2), envValue = readEnv("STATE_DIR")) {
|
|
31
|
-
const command = cliCommand("mikan")
|
|
32
|
-
.helpOption(false)
|
|
33
|
-
.allowUnknownOption()
|
|
34
|
-
.allowExcessArguments()
|
|
35
|
-
.option("--state-dir <dir>", "State directory", nonEmptyValue);
|
|
36
|
-
command.parse(args, { from: "user" });
|
|
37
|
-
const { stateDir } = command.opts();
|
|
38
|
-
return stateDir !== undefined
|
|
39
|
-
? resolve(stateDir)
|
|
40
|
-
: envValue
|
|
41
|
-
? resolve(envValue)
|
|
42
|
-
: defaultStateDir();
|
|
43
|
-
}
|
|
44
29
|
//# sourceMappingURL=arg-grammar.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"arg-grammar.js","sourceRoot":"","sources":["../../src/cli/arg-grammar.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAC;AAC1E,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,
|
|
1
|
+
{"version":3,"file":"arg-grammar.js","sourceRoot":"","sources":["../../src/cli/arg-grammar.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAC;AAC1E,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,MAAM,UAAU,UAAU,CAAC,IAAY;IACrC,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;SACrB,aAAa,CAAC,EAAE,iBAAiB,EAAE,IAAI,EAAE,CAAC;SAC1C,YAAY,EAAE;SACd,eAAe,CAAC;QACf,QAAQ,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;QAC/C,QAAQ,EAAE,GAAG,EAAE,GAAE,CAAC;KACnB,CAAC,CAAC;AACP,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,KAAa;IACzC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QAC3C,MAAM,IAAI,oBAAoB,CAAC,2CAA2C,CAAC,CAAC;IAC9E,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,KAAc,EAAE,OAAgB;IAC9D,IAAI,CAAC,CAAC,KAAK,YAAY,cAAc,CAAC;QAAE,MAAM,KAAK,CAAC;IACpD,IAAI,KAAK,CAAC,QAAQ,KAAK,CAAC;QAAE,OAAO,CAAC,KAAK,CAAC,GAAG,KAAK,CAAC,OAAO,KAAK,OAAO,CAAC,eAAe,EAAE,EAAE,CAAC,CAAC;IAC1F,OAAO,KAAK,CAAC,QAAQ,CAAC;AACxB,CAAC;AAED,MAAM,UAAU,YAAY;IAC1B,OAAO,IAAI,CAAC,OAAO,EAAE,EAAE,QAAQ,CAAC,CAAC;AACnC,CAAC","sourcesContent":["import { Command, CommanderError, InvalidArgumentError } from \"commander\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\n\nexport function cliCommand(name: string): Command {\n return new Command(name)\n .configureHelp({ showGlobalOptions: true })\n .exitOverride()\n .configureOutput({\n writeOut: (text) => console.log(text.trimEnd()),\n writeErr: () => {},\n });\n}\n\nexport function nonEmptyValue(value: string): string {\n if (!value.trim() || value.startsWith(\"-\")) {\n throw new InvalidArgumentError(\"expected a non-empty value, not an option\");\n }\n return value;\n}\n\nexport function commandExitCode(error: unknown, command: Command): number {\n if (!(error instanceof CommanderError)) throw error;\n if (error.exitCode !== 0) console.error(`${error.message}\\n${command.helpInformation()}`);\n return error.exitCode;\n}\n\nexport function stateDirPath(): string {\n return join(homedir(), \".mikan\");\n}\n"]}
|
package/dist/cli/boot.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"boot.d.ts","sourceRoot":"","sources":["../../src/cli/boot.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"boot.d.ts","sourceRoot":"","sources":["../../src/cli/boot.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAwB3C,wBAAgB,WAAW,CAAC,IAAI,GAAE,MAAM,EAA0B,GAAG,QAAQ,CAkB5E;AAwBD,wBAAgB,QAAQ,IAAI,MAAM,CAcjC"}
|
package/dist/cli/boot.js
CHANGED
|
@@ -1,16 +1,14 @@
|
|
|
1
1
|
import { join, resolve } from "node:path";
|
|
2
2
|
import { envSummaryLines } from "../env-manifest.js";
|
|
3
3
|
import { parseSandboxArg } from "../sandbox/registry.js";
|
|
4
|
-
import { cliCommand,
|
|
4
|
+
import { cliCommand, nonEmptyValue, stateDirPath } from "./arg-grammar.js";
|
|
5
5
|
const SUBCOMMANDS = ["migrate", "office", "env"];
|
|
6
6
|
function bootCommand() {
|
|
7
7
|
return cliCommand("mikan")
|
|
8
8
|
.description("Multi-platform chat agent daemon")
|
|
9
9
|
.helpOption(false)
|
|
10
|
-
.argument("[working-directory...]", "Workspace directory (default:
|
|
11
|
-
.option("--
|
|
12
|
-
.option("--sandbox <spec>", "host | container:<name> | image:<image[:tag]> | cloudflare:<id>", nonEmptyValue)
|
|
13
|
-
.option("--download <channel>", "Dump a Slack channel's history, then exit", nonEmptyValue)
|
|
10
|
+
.argument("[working-directory...]", "Workspace directory (default: ~/.mikan/workspace)")
|
|
11
|
+
.option("--sandbox <spec>", "host | container:<name> | image:<image[:tag]>", nonEmptyValue)
|
|
14
12
|
.option("--onboard", "Interactive first-run setup (also: mikan onboard)")
|
|
15
13
|
.option("-v, --version", "Print version")
|
|
16
14
|
.option("-V", "Print version")
|
|
@@ -25,23 +23,21 @@ export function resolveBoot(args = process.argv.slice(2)) {
|
|
|
25
23
|
const options = command.opts();
|
|
26
24
|
const onboardFirst = args[0] === "onboard";
|
|
27
25
|
const workingDirArg = (onboardFirst ? command.args.slice(1) : command.args).at(-1);
|
|
28
|
-
const downloadChannel = options.download;
|
|
29
26
|
const sandboxArg = options.sandbox;
|
|
30
|
-
const stateDir =
|
|
27
|
+
const stateDir = stateDirPath();
|
|
31
28
|
return {
|
|
32
29
|
mode: bootMode({ ...options, version: options.version || options.V }, onboardFirst),
|
|
33
30
|
stateDir,
|
|
34
31
|
workingDir: workingDirArg ? resolve(workingDirArg) : join(stateDir, "workspace"),
|
|
35
32
|
workingDirExplicit: workingDirArg !== undefined,
|
|
36
33
|
sandbox: sandboxArg === undefined ? { type: "host" } : parseSandboxArg(sandboxArg),
|
|
37
|
-
downloadChannel,
|
|
38
34
|
};
|
|
39
35
|
}
|
|
40
36
|
function subcommandPlan(args) {
|
|
41
37
|
const mode = SUBCOMMANDS.find((name) => name === args[0]);
|
|
42
38
|
if (!mode)
|
|
43
39
|
return undefined;
|
|
44
|
-
const stateDir =
|
|
40
|
+
const stateDir = stateDirPath();
|
|
45
41
|
return {
|
|
46
42
|
mode,
|
|
47
43
|
migrateArgs: mode === "migrate" ? args.slice(1) : undefined,
|
|
@@ -59,8 +55,6 @@ function bootMode(options, onboardFirst) {
|
|
|
59
55
|
return "version";
|
|
60
56
|
if (onboardFirst || options.onboard)
|
|
61
57
|
return "onboard";
|
|
62
|
-
if (options.download)
|
|
63
|
-
return "download";
|
|
64
58
|
return "run";
|
|
65
59
|
}
|
|
66
60
|
export function helpText() {
|
package/dist/cli/boot.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"boot.js","sourceRoot":"","sources":["../../src/cli/boot.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAEzD,OAAO,EAAE,UAAU,EAAE,
|
|
1
|
+
{"version":3,"file":"boot.js","sourceRoot":"","sources":["../../src/cli/boot.ts"],"names":[],"mappings":"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","sourcesContent":["import { join, resolve } from \"node:path\";\nimport { envSummaryLines } from \"../env-manifest.js\";\nimport { parseSandboxArg } from \"../sandbox/registry.js\";\nimport type { BootPlan } from \"./types.js\";\nimport { cliCommand, nonEmptyValue, stateDirPath } from \"./arg-grammar.js\";\n\nconst SUBCOMMANDS = [\"migrate\", \"office\", \"env\"] as const;\n\ninterface BootOptions {\n sandbox?: string;\n help?: boolean;\n version?: boolean;\n onboard?: boolean;\n}\n\nfunction bootCommand() {\n return cliCommand(\"mikan\")\n .description(\"Multi-platform chat agent daemon\")\n .helpOption(false)\n .argument(\"[working-directory...]\", \"Workspace directory (default: ~/.mikan/workspace)\")\n .option(\"--sandbox <spec>\", \"host | container:<name> | image:<image[:tag]>\", nonEmptyValue)\n .option(\"--onboard\", \"Interactive first-run setup (also: mikan onboard)\")\n .option(\"-v, --version\", \"Print version\")\n .option(\"-V\", \"Print version\")\n .option(\"-h, --help\", \"Show help\");\n}\n\nexport function resolveBoot(args: string[] = process.argv.slice(2)): BootPlan {\n const routed = subcommandPlan(args);\n if (routed) return routed;\n\n const command = bootCommand();\n command.parse(args, { from: \"user\" });\n const options = command.opts<BootOptions & { V?: boolean }>();\n const onboardFirst = args[0] === \"onboard\";\n const workingDirArg = (onboardFirst ? command.args.slice(1) : command.args).at(-1);\n const sandboxArg = options.sandbox;\n const stateDir = stateDirPath();\n return {\n mode: bootMode({ ...options, version: options.version || options.V }, onboardFirst),\n stateDir,\n workingDir: workingDirArg ? resolve(workingDirArg) : join(stateDir, \"workspace\"),\n workingDirExplicit: workingDirArg !== undefined,\n sandbox: sandboxArg === undefined ? { type: \"host\" } : parseSandboxArg(sandboxArg),\n };\n}\n\nfunction subcommandPlan(args: string[]): BootPlan | undefined {\n const mode = SUBCOMMANDS.find((name) => name === args[0]);\n if (!mode) return undefined;\n const stateDir = stateDirPath();\n return {\n mode,\n migrateArgs: mode === \"migrate\" ? args.slice(1) : undefined,\n officeArgs: mode === \"office\" ? args.slice(1) : undefined,\n stateDir,\n workingDir: join(stateDir, \"workspace\"),\n workingDirExplicit: false,\n sandbox: { type: \"host\" },\n };\n}\n\nfunction bootMode(options: BootOptions, onboardFirst: boolean): BootPlan[\"mode\"] {\n if (options.help) return \"help\";\n if (options.version) return \"version\";\n if (onboardFirst || options.onboard) return \"onboard\";\n return \"run\";\n}\n\nexport function helpText(): string {\n return (\n bootCommand().helpInformation() +\n `\nCommands:\n mikan migrate --sandbox <spec> [--dry-run] Apply pending state migrations (stop the daemon first).\n mikan office list List office keys with their platform and conversation id.\n mikan env Show environment-variable inventory.\n mikan onboard Interactive first-run setup.\n\nEnvironment (platform tokens select which chat adapters start):\n${envSummaryLines().join(\"\\n\")}\nRun mikan env for the full inventory.`\n );\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"migrate.d.ts","sourceRoot":"","sources":["../../src/cli/migrate.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"migrate.d.ts","sourceRoot":"","sources":["../../src/cli/migrate.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AA4CxD,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,MAAM,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC,CAsD3F"}
|
package/dist/cli/migrate.js
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
import { execFile } from "node:child_process";
|
|
2
|
+
import { existsSync } from "node:fs";
|
|
2
3
|
import { homedir } from "node:os";
|
|
3
4
|
import { join, resolve } from "node:path";
|
|
4
5
|
import { promisify } from "node:util";
|
|
5
6
|
import { InvalidArgumentError } from "commander";
|
|
6
7
|
import { platformIsActive, readEnv } from "../env-manifest.js";
|
|
7
|
-
import { runMigrations } from "../migrations/index.js";
|
|
8
|
+
import { pendingMigrations, runMigrations } from "../migrations/index.js";
|
|
8
9
|
import { parseSandboxArg } from "../sandbox/registry.js";
|
|
10
|
+
import { globalSettingsPath } from "../settings/index.js";
|
|
9
11
|
import { assertPlatformName } from "../office/index.js";
|
|
10
12
|
import { errorMessage } from "../unknown-values.js";
|
|
11
|
-
import { cliCommand, commandExitCode, nonEmptyValue,
|
|
13
|
+
import { cliCommand, commandExitCode, nonEmptyValue, stateDirPath } from "./arg-grammar.js";
|
|
12
14
|
const PLATFORMS = ["slack", "telegram", "discord", "github"];
|
|
13
15
|
const execFileAsync = promisify(execFile);
|
|
14
16
|
const dockerCli = async (args) => (await execFileAsync("docker", [...args])).stdout;
|
|
@@ -24,12 +26,20 @@ function collectOwner(value, owners) {
|
|
|
24
26
|
}
|
|
25
27
|
return owners;
|
|
26
28
|
}
|
|
29
|
+
function assertInstallPaths(stateDir, workspaceRoot) {
|
|
30
|
+
const settingsPath = globalSettingsPath(stateDir);
|
|
31
|
+
if (!existsSync(settingsPath)) {
|
|
32
|
+
throw new Error(`No settings at ${settingsPath}; move the state directory the daemon ran with to ${stateDir}`);
|
|
33
|
+
}
|
|
34
|
+
if (!existsSync(workspaceRoot)) {
|
|
35
|
+
throw new Error(`Workspace ${workspaceRoot} does not exist; pass the working directory the daemon ran with as --workspace`);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
27
38
|
export async function runMigrateCommand(argv, docker = dockerCli) {
|
|
28
39
|
const command = cliCommand("mikan migrate")
|
|
29
40
|
.description("Apply pending state migrations (stop the daemon first)")
|
|
30
|
-
.option("--
|
|
31
|
-
.
|
|
32
|
-
.requiredOption("--sandbox <spec>", "The daemon's --sandbox value: host | container:<name> | image:<image> | cloudflare:<id>", nonEmptyValue)
|
|
41
|
+
.option("--workspace <dir>", "Workspace directory (default: ~/.mikan/workspace)")
|
|
42
|
+
.requiredOption("--sandbox <spec>", "The daemon's --sandbox value: host | container:<name> | image:<image>", nonEmptyValue)
|
|
33
43
|
.option("--dry-run", "List what each pending migration would change, without writing")
|
|
34
44
|
.option("--owner <conversationId=platform>", "Owning platform for a legacy conversation directory (repeatable)", collectOwner, new Map());
|
|
35
45
|
try {
|
|
@@ -39,12 +49,17 @@ export async function runMigrateCommand(argv, docker = dockerCli) {
|
|
|
39
49
|
return commandExitCode(error, command);
|
|
40
50
|
}
|
|
41
51
|
const options = command.opts();
|
|
42
|
-
const stateDir =
|
|
52
|
+
const stateDir = stateDirPath();
|
|
43
53
|
const dryRun = options.dryRun ?? false;
|
|
54
|
+
const workspaceRoot = options.workspace
|
|
55
|
+
? resolve(options.workspace)
|
|
56
|
+
: join(stateDir, "workspace");
|
|
44
57
|
try {
|
|
45
58
|
const sandbox = parseSandboxArg(options.sandbox);
|
|
59
|
+
if (pendingMigrations(stateDir).length > 0)
|
|
60
|
+
assertInstallPaths(stateDir, workspaceRoot);
|
|
46
61
|
const ran = await runMigrations({
|
|
47
|
-
workspaceRoot
|
|
62
|
+
workspaceRoot,
|
|
48
63
|
stateDir,
|
|
49
64
|
dryRun,
|
|
50
65
|
owners: options.owner,
|
package/dist/cli/migrate.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"migrate.js","sourceRoot":"","sources":["../../src/cli/migrate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAC/D,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"migrate.js","sourceRoot":"","sources":["../../src/cli/migrate.ts"],"names":[],"mappings":"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","sourcesContent":["import { execFile } from \"node:child_process\";\nimport { existsSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join, resolve } from \"node:path\";\nimport { promisify } from \"node:util\";\nimport { InvalidArgumentError } from \"commander\";\nimport { platformIsActive, readEnv } from \"../env-manifest.js\";\nimport { pendingMigrations, runMigrations } from \"../migrations/index.js\";\nimport { parseSandboxArg } from \"../sandbox/registry.js\";\nimport { globalSettingsPath } from \"../settings/index.js\";\nimport type { DockerCli } from \"../migrations/types.js\";\nimport { assertPlatformName } from \"../office/index.js\";\nimport type { PlatformName } from \"../types.js\";\nimport { errorMessage } from \"../unknown-values.js\";\nimport { cliCommand, commandExitCode, nonEmptyValue, stateDirPath } from \"./arg-grammar.js\";\n\nconst PLATFORMS: readonly PlatformName[] = [\"slack\", \"telegram\", \"discord\", \"github\"];\n\nconst execFileAsync = promisify(execFile);\n\nconst dockerCli: DockerCli = async (args) => (await execFileAsync(\"docker\", [...args])).stdout;\n\nfunction collectOwner(value: string, owners: Map<string, PlatformName>): Map<string, PlatformName> {\n const separator = value.lastIndexOf(\"=\");\n if (separator <= 0) throw new InvalidArgumentError(\"expected <conversationId>=<platform>\");\n try {\n owners.set(value.slice(0, separator), assertPlatformName(value.slice(separator + 1)));\n } catch (error) {\n throw new InvalidArgumentError(errorMessage(error));\n }\n return owners;\n}\n\nfunction assertInstallPaths(stateDir: string, workspaceRoot: string): void {\n const settingsPath = globalSettingsPath(stateDir);\n if (!existsSync(settingsPath)) {\n throw new Error(\n `No settings at ${settingsPath}; move the state directory the daemon ran with to ${stateDir}`,\n );\n }\n if (!existsSync(workspaceRoot)) {\n throw new Error(\n `Workspace ${workspaceRoot} does not exist; pass the working directory the daemon ran with as --workspace`,\n );\n }\n}\n\ninterface MigrateOptions {\n workspace?: string;\n dryRun?: boolean;\n sandbox: string;\n owner: Map<string, PlatformName>;\n}\n\nexport async function runMigrateCommand(argv: string[], docker = dockerCli): Promise<number> {\n const command = cliCommand(\"mikan migrate\")\n .description(\"Apply pending state migrations (stop the daemon first)\")\n .option(\"--workspace <dir>\", \"Workspace directory (default: ~/.mikan/workspace)\")\n .requiredOption(\n \"--sandbox <spec>\",\n \"The daemon's --sandbox value: host | container:<name> | image:<image>\",\n nonEmptyValue,\n )\n .option(\"--dry-run\", \"List what each pending migration would change, without writing\")\n .option(\n \"--owner <conversationId=platform>\",\n \"Owning platform for a legacy conversation directory (repeatable)\",\n collectOwner,\n new Map<string, PlatformName>(),\n );\n try {\n command.parse(argv, { from: \"user\" });\n } catch (error) {\n return commandExitCode(error, command);\n }\n const options = command.opts<MigrateOptions>();\n const stateDir = stateDirPath();\n const dryRun = options.dryRun ?? false;\n const workspaceRoot = options.workspace\n ? resolve(options.workspace)\n : join(stateDir, \"workspace\");\n try {\n const sandbox = parseSandboxArg(options.sandbox);\n if (pendingMigrations(stateDir).length > 0) assertInstallPaths(stateDir, workspaceRoot);\n const ran = await runMigrations({\n workspaceRoot,\n stateDir,\n dryRun,\n owners: options.owner,\n sandbox,\n enabledPlatforms: PLATFORMS.filter((platform) => platformIsActive(platform)),\n piAgentDir: readEnv(\"PI_CODING_AGENT_DIR\") ?? join(homedir(), \".pi\", \"agent\"),\n modelsPath: join(stateDir, \"models.json\"),\n docker,\n report: (line) => console.log(line),\n });\n if (ran.length === 0) console.log(\"No pending migrations.\");\n else if (!dryRun) console.log(`Applied ${ran.length}.`);\n else {\n console.log(`Dry run: ${ran.length} pending.`);\n console.log(\"Each step was previewed against the files as they are now, so a step may find\");\n console.log(\"more to do once the steps before it have run.\");\n }\n return 0;\n } catch (error) {\n console.error(`Migration failed: ${errorMessage(error)}`);\n return 1;\n }\n}\n"]}
|
package/dist/cli/office.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"office.d.ts","sourceRoot":"","sources":["../../src/cli/office.ts"],"names":[],"mappings":"AAGA,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"office.d.ts","sourceRoot":"","sources":["../../src/cli/office.ts"],"names":[],"mappings":"AAGA,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,CAevD"}
|
package/dist/cli/office.js
CHANGED
|
@@ -1,15 +1,13 @@
|
|
|
1
1
|
import { officeKey, OfficeRegistry } from "../office/index.js";
|
|
2
|
-
import { cliCommand, commandExitCode,
|
|
2
|
+
import { cliCommand, commandExitCode, stateDirPath } from "./arg-grammar.js";
|
|
3
3
|
export function runOfficeCommand(argv) {
|
|
4
|
-
const command = cliCommand("mikan office")
|
|
5
|
-
.description("Inspect conversation offices")
|
|
6
|
-
.option("--state-dir <dir>", "State directory", nonEmptyValue);
|
|
4
|
+
const command = cliCommand("mikan office").description("Inspect conversation offices");
|
|
7
5
|
let result = 1;
|
|
8
6
|
command
|
|
9
7
|
.command("list")
|
|
10
8
|
.description("List each registered office key with its platform and conversation id")
|
|
11
9
|
.action(() => {
|
|
12
|
-
result = listOffices(
|
|
10
|
+
result = listOffices(stateDirPath());
|
|
13
11
|
});
|
|
14
12
|
try {
|
|
15
13
|
command.parse(argv, { from: "user" });
|
package/dist/cli/office.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"office.js","sourceRoot":"","sources":["../../src/cli/office.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAC/D,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,
|
|
1
|
+
{"version":3,"file":"office.js","sourceRoot":"","sources":["../../src/cli/office.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAC/D,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAE7E,MAAM,UAAU,gBAAgB,CAAC,IAAc;IAC7C,MAAM,OAAO,GAAG,UAAU,CAAC,cAAc,CAAC,CAAC,WAAW,CAAC,8BAA8B,CAAC,CAAC;IACvF,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,OAAO;SACJ,OAAO,CAAC,MAAM,CAAC;SACf,WAAW,CAAC,uEAAuE,CAAC;SACpF,MAAM,CAAC,GAAG,EAAE;QACX,MAAM,GAAG,WAAW,CAAC,YAAY,EAAE,CAAC,CAAC;IACvC,CAAC,CAAC,CAAC;IACL,IAAI,CAAC;QACH,OAAO,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;QACtC,OAAO,MAAM,CAAC;IAChB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,eAAe,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IACzC,CAAC;AACH,CAAC;AAED,SAAS,WAAW,CAAC,QAAgB;IACnC,MAAM,OAAO,GAAG,IAAI,cAAc,CAAC,QAAQ,CAAC,CAAC,UAAU,EAAE,CAAC;IAC1D,OAAO,CAAC,GAAG,CAAC,YAAY,OAAO,CAAC,MAAM,IAAI,CAAC,CAAC;IAC5C,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,OAAO,CAAC,GAAG,CAAC,KAAK,SAAS,CAAC,MAAM,CAAC,KAAK,MAAM,CAAC,QAAQ,KAAK,MAAM,CAAC,cAAc,EAAE,CAAC,CAAC;IACtF,CAAC;IACD,OAAO,CAAC,CAAC;AACX,CAAC","sourcesContent":["import { officeKey, OfficeRegistry } from \"../office/index.js\";\nimport { cliCommand, commandExitCode, stateDirPath } from \"./arg-grammar.js\";\n\nexport function runOfficeCommand(argv: string[]): number {\n const command = cliCommand(\"mikan office\").description(\"Inspect conversation offices\");\n let result = 1;\n command\n .command(\"list\")\n .description(\"List each registered office key with its platform and conversation id\")\n .action(() => {\n result = listOffices(stateDirPath());\n });\n try {\n command.parse(argv, { from: \"user\" });\n return result;\n } catch (error) {\n return commandExitCode(error, command);\n }\n}\n\nfunction listOffices(stateDir: string): number {\n const offices = new OfficeRegistry(stateDir).getOffices();\n console.log(`Offices (${offices.length}):`);\n for (const office of offices) {\n console.log(` ${officeKey(office)} ${office.platform} ${office.conversationId}`);\n }\n return 0;\n}\n"]}
|