@oyasmi/pipiclaw 0.3.3 → 0.3.5

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/dist/agent.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"agent.js","sourceRoot":"","sources":["../src/agent.ts"],"names":[],"mappings":"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","sourcesContent":["import { Agent } from \"@mariozechner/pi-agent-core\";\nimport type { Api, Model } from \"@mariozechner/pi-ai\";\nimport {\n\tAgentSession,\n\tAuthStorage,\n\tconvertToLlm,\n\tDefaultResourceLoader,\n\tModelRegistry,\n\tSessionManager,\n\ttype Skill,\n} from \"@mariozechner/pi-coding-agent\";\nimport { mkdir, writeFile } from \"fs/promises\";\nimport { dirname, join, resolve } from \"path\";\nimport { COMMAND_RESULT_CUSTOM_TYPE, createCommandExtension } from \"./command-extension.js\";\nimport { type BuiltInCommand, renderBuiltInHelp } from \"./commands.js\";\nimport { getAgentConfig, getApiKeyForModel, getSoul, loadPipiclawSkills } from \"./config-loader.js\";\nimport { PipiclawSettingsManager } from \"./context.js\";\nimport type { DingTalkContext } from \"./dingtalk.js\";\nimport * as log from \"./log.js\";\nimport { MemoryLifecycle } from \"./memory-lifecycle.js\";\nimport { resolveInitialModel } from \"./model-utils.js\";\nimport { APP_HOME_DIR, AUTH_CONFIG_PATH, MODELS_CONFIG_PATH } from \"./paths.js\";\nimport { buildAppendSystemPrompt } from \"./prompt-builder.js\";\nimport { createExecutor, type SandboxConfig } from \"./sandbox.js\";\nimport type { ChannelStore } from \"./store.js\";\nimport { discoverSubAgents, formatSubAgentList } from \"./sub-agents.js\";\nimport { createPipiclawTools } from \"./tools/index.js\";\nimport type { SubAgentToolDetails } from \"./tools/subagent.js\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface AgentRunner {\n\trun(ctx: DingTalkContext, store: ChannelStore): Promise<{ stopReason: string; errorMessage?: string }>;\n\thandleBuiltinCommand(ctx: DingTalkContext, command: BuiltInCommand): Promise<void>;\n\tqueueSteer(text: string, userName?: string): Promise<void>;\n\tqueueFollowUp(text: string, userName?: string): Promise<void>;\n\tabort(): Promise<void>;\n}\n\ntype FinalOutcome = { kind: \"none\" } | { kind: \"silent\" } | { kind: \"final\"; text: string };\ntype ModelRegistryClass = {\n\tcreate?: (authStorage: AuthStorage, modelsJsonPath?: string) => ModelRegistry;\n\tnew (authStorage: AuthStorage, modelsJsonPath?: string): ModelRegistry;\n};\n\nfunction isSilentOutcome(outcome: FinalOutcome): outcome is { kind: \"silent\" } {\n\treturn outcome.kind === \"silent\";\n}\n\nfunction isFinalOutcome(outcome: FinalOutcome): outcome is { kind: \"final\"; text: string } {\n\treturn outcome.kind === \"final\";\n}\n\nfunction getFinalOutcomeText(outcome: FinalOutcome): string | null {\n\treturn isFinalOutcome(outcome) ? outcome.text : null;\n}\n\nfunction createModelRegistry(authStorage: AuthStorage, modelsJsonPath: string): ModelRegistry {\n\tconst registryClass = ModelRegistry as unknown as ModelRegistryClass;\n\treturn typeof registryClass.create === \"function\"\n\t\t? registryClass.create(authStorage, modelsJsonPath)\n\t\t: new registryClass(authStorage, modelsJsonPath);\n}\n\n// ============================================================================\n// Text helpers\n// ============================================================================\n\nfunction truncate(text: string, maxLen: number): string {\n\tif (text.length <= maxLen) return text;\n\treturn `${text.substring(0, maxLen - 3)}...`;\n}\n\nfunction sanitizeProgressText(text: string): string {\n\treturn text\n\t\t.replace(/\\uFFFC/g, \"\")\n\t\t.replace(/\\r/g, \"\")\n\t\t.trim();\n}\n\nfunction formatProgressEntry(kind: \"tool\" | \"thinking\" | \"error\" | \"assistant\", text: string): string {\n\tconst cleaned = sanitizeProgressText(text);\n\tif (!cleaned) return \"\";\n\n\tconst normalized = cleaned.replace(/\\n+/g, \" \").trim();\n\tswitch (kind) {\n\t\tcase \"tool\":\n\t\t\treturn `Running: ${normalized}`;\n\t\tcase \"thinking\":\n\t\t\treturn `Thinking: ${normalized}`;\n\t\tcase \"error\":\n\t\t\treturn `Error: ${normalized}`;\n\t\tcase \"assistant\":\n\t\t\treturn normalized;\n\t}\n}\n\nfunction extractToolResultText(result: unknown): string {\n\tif (typeof result === \"string\") {\n\t\treturn result;\n\t}\n\n\tif (\n\t\tresult &&\n\t\ttypeof result === \"object\" &&\n\t\t\"content\" in result &&\n\t\tArray.isArray((result as { content: unknown }).content)\n\t) {\n\t\tconst content = (result as { content: Array<{ type: string; text?: string }> }).content;\n\t\tconst textParts: string[] = [];\n\t\tfor (const part of content) {\n\t\t\tif (part.type === \"text\" && part.text) {\n\t\t\t\ttextParts.push(part.text);\n\t\t\t}\n\t\t}\n\t\tif (textParts.length > 0) {\n\t\t\treturn textParts.join(\"\\n\");\n\t\t}\n\t}\n\n\treturn JSON.stringify(result);\n}\n\nfunction isSubAgentToolDetails(value: unknown): value is SubAgentToolDetails {\n\tif (!value || typeof value !== \"object\" || !(\"usage\" in value)) {\n\t\treturn false;\n\t}\n\n\tconst usage = (value as { usage?: unknown }).usage;\n\treturn (\n\t\t!!usage &&\n\t\ttypeof usage === \"object\" &&\n\t\t\"input\" in usage &&\n\t\t\"output\" in usage &&\n\t\t\"cacheRead\" in usage &&\n\t\t\"cacheWrite\" in usage &&\n\t\t\"cost\" in usage\n\t);\n}\n\nfunction mergeSubAgentUsage(totalUsage: UsageTotals, details: SubAgentToolDetails): void {\n\ttotalUsage.input += details.usage.input;\n\ttotalUsage.output += details.usage.output;\n\ttotalUsage.cacheRead += details.usage.cacheRead;\n\ttotalUsage.cacheWrite += details.usage.cacheWrite;\n\ttotalUsage.cost.input += details.usage.cost.input;\n\ttotalUsage.cost.output += details.usage.cost.output;\n\ttotalUsage.cost.cacheRead += details.usage.cost.cacheRead;\n\ttotalUsage.cost.cacheWrite += details.usage.cost.cacheWrite;\n\ttotalUsage.cost.total += details.usage.cost.total;\n}\n\nfunction extractCustomCommandResultText(message: unknown): string | null {\n\tif (\n\t\t!message ||\n\t\ttypeof message !== \"object\" ||\n\t\t!(\"role\" in message) ||\n\t\t!(\"customType\" in message) ||\n\t\t(message as { role?: unknown }).role !== \"custom\" ||\n\t\t(message as { customType?: unknown }).customType !== COMMAND_RESULT_CUSTOM_TYPE\n\t) {\n\t\treturn null;\n\t}\n\n\tconst content = (message as { content?: unknown }).content;\n\treturn typeof content === \"string\" && content.trim() ? content : null;\n}\n\n// ============================================================================\n// Run State\n// ============================================================================\n\ninterface PendingTool {\n\ttoolName: string;\n\targs: unknown;\n\tstartTime: number;\n}\n\ninterface UsageTotals {\n\tinput: number;\n\toutput: number;\n\tcacheRead: number;\n\tcacheWrite: number;\n\tcost: { input: number; output: number; cacheRead: number; cacheWrite: number; total: number };\n}\n\ninterface RunQueue {\n\tenqueue(fn: () => Promise<void>, errorContext: string): void;\n\tenqueueMessage(text: string, target: \"main\" | \"thread\", errorContext: string, doLog?: boolean): void;\n}\n\ninterface RunState {\n\tctx: DingTalkContext | null;\n\tlogCtx: { channelId: string; userName?: string; channelName?: string } | null;\n\tqueue: RunQueue | null;\n\tpendingTools: Map<string, PendingTool>;\n\ttotalUsage: UsageTotals;\n\tstopReason: string;\n\terrorMessage: string | undefined;\n\tfinalOutcome: FinalOutcome;\n\tfinalResponseDelivered: boolean;\n}\n\nfunction createEmptyRunState(): RunState {\n\treturn {\n\t\tctx: null,\n\t\tlogCtx: null,\n\t\tqueue: null,\n\t\tpendingTools: new Map(),\n\t\ttotalUsage: {\n\t\t\tinput: 0,\n\t\t\toutput: 0,\n\t\t\tcacheRead: 0,\n\t\t\tcacheWrite: 0,\n\t\t\tcost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },\n\t\t},\n\t\tstopReason: \"stop\",\n\t\terrorMessage: undefined,\n\t\tfinalOutcome: { kind: \"none\" },\n\t\tfinalResponseDelivered: false,\n\t};\n}\n\n// ============================================================================\n// ChannelRunner\n// ============================================================================\n\nclass ChannelRunner implements AgentRunner {\n\t// --- Constructed once ---\n\tprivate readonly sandboxConfig: SandboxConfig;\n\tprivate readonly channelId: string;\n\tprivate readonly channelDir: string;\n\tprivate readonly workspacePath: string;\n\tprivate readonly workspaceDir: string;\n\tprivate readonly session: AgentSession;\n\tprivate readonly agent: Agent;\n\tprivate readonly sessionManager: SessionManager;\n\tprivate readonly settingsManager: PipiclawSettingsManager;\n\tprivate readonly modelRegistry: ModelRegistry;\n\tprivate readonly memoryLifecycle: MemoryLifecycle;\n\tprivate readonly sessionReady: Promise<void>;\n\n\t// --- Mutable across runs ---\n\tprivate activeModel: Model<Api>;\n\tprivate currentSkills: Skill[];\n\n\t// --- Per run ---\n\tprivate runState: RunState = createEmptyRunState();\n\n\tconstructor(sandboxConfig: SandboxConfig, channelId: string, channelDir: string) {\n\t\tthis.sandboxConfig = sandboxConfig;\n\t\tthis.channelId = channelId;\n\t\tthis.channelDir = channelDir;\n\n\t\tconst executor = createExecutor(sandboxConfig);\n\t\tthis.workspaceDir = resolve(dirname(channelDir));\n\t\tthis.workspacePath = executor.getWorkspacePath(this.workspaceDir);\n\n\t\t// Initial skill summaries\n\t\tconst initialSkills = loadPipiclawSkills(channelDir, this.workspacePath);\n\t\tthis.currentSkills = initialSkills;\n\n\t\t// Create session manager\n\t\tconst contextFile = join(channelDir, \"context.jsonl\");\n\t\tthis.sessionManager = SessionManager.open(contextFile, channelDir);\n\t\tthis.settingsManager = new PipiclawSettingsManager(APP_HOME_DIR);\n\n\t\t// Create AuthStorage and ModelRegistry\n\t\tconst authStorage = AuthStorage.create(AUTH_CONFIG_PATH);\n\t\tthis.modelRegistry = createModelRegistry(authStorage, MODELS_CONFIG_PATH);\n\n\t\t// Resolve model: prefer saved global default, fall back to first available model\n\t\tthis.activeModel = resolveInitialModel(this.modelRegistry, this.settingsManager);\n\t\tlog.logInfo(`Using model: ${this.activeModel.provider}/${this.activeModel.id} (${this.activeModel.name})`);\n\n\t\t// Create tools\n\t\tconst tools = createPipiclawTools({\n\t\t\texecutor,\n\t\t\tgetCurrentModel: () => this.activeModel,\n\t\t\tgetAvailableModels: () => this.modelRegistry.getAvailable(),\n\t\t\tresolveApiKey: async (model) => getApiKeyForModel(this.modelRegistry, model),\n\t\t\tworkspaceDir: this.workspaceDir,\n\t\t});\n\n\t\t// Create agent\n\t\tthis.agent = new Agent({\n\t\t\tinitialState: {\n\t\t\t\tsystemPrompt: \"\",\n\t\t\t\tmodel: this.activeModel,\n\t\t\t\tthinkingLevel: \"off\",\n\t\t\t\ttools,\n\t\t\t},\n\t\t\tconvertToLlm,\n\t\t\tgetApiKey: async () => getApiKeyForModel(this.modelRegistry, this.activeModel),\n\t\t});\n\n\t\tthis.memoryLifecycle = new MemoryLifecycle({\n\t\t\tchannelId: this.channelId,\n\t\t\tchannelDir: this.channelDir,\n\t\t\tgetMessages: () => this.session.messages,\n\t\t\tgetSessionEntries: () => this.sessionManager.getBranch(),\n\t\t\tgetModel: () => this.session.model ?? this.activeModel,\n\t\t\tresolveApiKey: async (model) => getApiKeyForModel(this.modelRegistry, model),\n\t\t});\n\n\t\tconst resourceLoader = new DefaultResourceLoader({\n\t\t\tcwd: process.cwd(),\n\t\t\tagentDir: APP_HOME_DIR,\n\t\t\tsettingsManager: this.settingsManager as any,\n\t\t\textensionFactories: [\n\t\t\t\tthis.memoryLifecycle.createExtensionFactory(),\n\t\t\t\tcreateCommandExtension({\n\t\t\t\t\tgetCurrentModel: () => this.session.model ?? this.activeModel,\n\t\t\t\t\tgetAvailableModels: async () => {\n\t\t\t\t\t\tthis.modelRegistry.refresh();\n\t\t\t\t\t\treturn await this.modelRegistry.getAvailable();\n\t\t\t\t\t},\n\t\t\t\t\tgetSessionStats: () => this.session.getSessionStats(),\n\t\t\t\t\tgetThinkingLevel: () => this.session.thinkingLevel,\n\t\t\t\t\tswitchModel: async (model) => {\n\t\t\t\t\t\tawait this.session.setModel(model);\n\t\t\t\t\t\tthis.activeModel = model;\n\t\t\t\t\t},\n\t\t\t\t\trefreshSessionResources: async () => {\n\t\t\t\t\t\tawait this.refreshSessionResources();\n\t\t\t\t\t},\n\t\t\t\t}),\n\t\t\t],\n\t\t\tappendSystemPromptOverride: (base) => {\n\t\t\t\tconst soul = getSoul(this.workspaceDir);\n\t\t\t\tconst sections = [...base];\n\t\t\t\tif (soul) {\n\t\t\t\t\tsections.unshift(soul);\n\t\t\t\t}\n\t\t\t\tconst subAgents = discoverSubAgents(this.workspaceDir, this.modelRegistry.getAvailable());\n\t\t\t\tsections.push(\n\t\t\t\t\tbuildAppendSystemPrompt(this.workspacePath, this.channelId, this.sandboxConfig, {\n\t\t\t\t\t\tsubAgentList: formatSubAgentList(subAgents.agents),\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t\treturn sections;\n\t\t\t},\n\t\t\tagentsFilesOverride: () => {\n\t\t\t\tconst agentConfig = getAgentConfig(this.channelDir);\n\t\t\t\treturn {\n\t\t\t\t\tagentsFiles: agentConfig ? [{ path: `${this.workspacePath}/AGENTS.md`, content: agentConfig }] : [],\n\t\t\t\t};\n\t\t\t},\n\t\t\tskillsOverride: (base) => ({\n\t\t\t\tskills: [...base.skills, ...this.currentSkills],\n\t\t\t\tdiagnostics: base.diagnostics,\n\t\t\t}),\n\t\t});\n\n\t\tconst baseToolsOverride = Object.fromEntries(tools.map((tool) => [tool.name, tool]));\n\n\t\t// Create AgentSession\n\t\tthis.session = new AgentSession({\n\t\t\tagent: this.agent,\n\t\t\tsessionManager: this.sessionManager,\n\t\t\tsettingsManager: this.settingsManager as any,\n\t\t\tcwd: process.cwd(),\n\t\t\tmodelRegistry: this.modelRegistry,\n\t\t\tresourceLoader,\n\t\t\tbaseToolsOverride,\n\t\t});\n\n\t\t// Subscribe to session events\n\t\tthis.subscribeToSessionEvents();\n\t\tthis.sessionReady = this.initializeSession();\n\t}\n\n\t// === Public API ===\n\n\tasync run(ctx: DingTalkContext, _store: ChannelStore): Promise<{ stopReason: string; errorMessage?: string }> {\n\t\tthis.resetRunState(ctx);\n\n\t\t// Create queue for this run\n\t\tlet queueChain = Promise.resolve();\n\t\tthis.runState.queue = {\n\t\t\tenqueue: (fn: () => Promise<void>, errorContext: string): void => {\n\t\t\t\tqueueChain = queueChain.then(async () => {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tawait fn();\n\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\tconst errMsg = err instanceof Error ? err.message : String(err);\n\t\t\t\t\t\tlog.logWarning(`DingTalk API error (${errorContext})`, errMsg);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t},\n\t\t\tenqueueMessage: function (text: string, target: \"main\" | \"thread\", errorContext: string, doLog = true): void {\n\t\t\t\tthis.enqueue(\n\t\t\t\t\t() => (target === \"main\" ? ctx.respond(text, doLog) : ctx.respondInThread(text)),\n\t\t\t\t\terrorContext,\n\t\t\t\t);\n\t\t\t},\n\t\t};\n\n\t\ttry {\n\t\t\tawait this.ensureSessionReady();\n\n\t\t\t// Ensure channel directory exists\n\t\t\tawait mkdir(this.channelDir, { recursive: true });\n\n\t\t\tconst userMessage = this.formatUserMessage(ctx.message.text, ctx.message.userName);\n\t\t\tconst promptText = this.shouldPreserveRawInput(ctx.message.text) ? ctx.message.text.trim() : userMessage;\n\n\t\t\t// Debug: write context to last_prompt.json (only with PIPICLAW_DEBUG=1)\n\t\t\tif (process.env.PIPICLAW_DEBUG) {\n\t\t\t\tconst debugContext = {\n\t\t\t\t\tsystemPrompt: this.agent.state.systemPrompt,\n\t\t\t\t\tmessages: this.session.messages,\n\t\t\t\t\tnewUserMessage: promptText,\n\t\t\t\t};\n\t\t\t\tawait writeFile(join(this.channelDir, \"last_prompt.json\"), JSON.stringify(debugContext, null, 2));\n\t\t\t}\n\n\t\t\tawait this.session.prompt(promptText);\n\t\t} catch (err) {\n\t\t\tthis.runState.stopReason = \"error\";\n\t\t\tthis.runState.errorMessage = err instanceof Error ? err.message : String(err);\n\t\t\tlog.logWarning(`[${this.channelId}] Runner failed`, this.runState.errorMessage);\n\t\t} finally {\n\t\t\tawait queueChain;\n\t\t\tconst finalOutcome = this.runState.finalOutcome;\n\t\t\tconst finalOutcomeText = getFinalOutcomeText(finalOutcome);\n\n\t\t\ttry {\n\t\t\t\tif (\n\t\t\t\t\tthis.runState.stopReason === \"error\" &&\n\t\t\t\t\tthis.runState.errorMessage &&\n\t\t\t\t\t!this.runState.finalResponseDelivered\n\t\t\t\t) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tawait ctx.replaceMessage(\"_Sorry, something went wrong_\");\n\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\tconst errMsg = err instanceof Error ? err.message : String(err);\n\t\t\t\t\t\tlog.logWarning(\"Failed to post error message\", errMsg);\n\t\t\t\t\t}\n\t\t\t\t} else if (isSilentOutcome(finalOutcome)) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tawait ctx.deleteMessage();\n\t\t\t\t\t\tlog.logInfo(\"Silent response - deleted message\");\n\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\tconst errMsg = err instanceof Error ? err.message : String(err);\n\t\t\t\t\t\tlog.logWarning(\"Failed to delete message for silent response\", errMsg);\n\t\t\t\t\t}\n\t\t\t\t} else if (finalOutcomeText && !this.runState.finalResponseDelivered) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tawait ctx.replaceMessage(finalOutcomeText);\n\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\tconst errMsg = err instanceof Error ? err.message : String(err);\n\t\t\t\t\t\tlog.logWarning(\"Failed to replace message with final text\", errMsg);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tawait ctx.flush();\n\t\t\t} finally {\n\t\t\t\tawait ctx.close();\n\t\t\t}\n\n\t\t\t// Log usage summary\n\t\t\tif (this.runState.totalUsage.cost.total > 0) {\n\t\t\t\tconst messages = this.session.messages;\n\t\t\t\tconst lastAssistantMessage = messages\n\t\t\t\t\t.slice()\n\t\t\t\t\t.reverse()\n\t\t\t\t\t.find((m: any) => m.role === \"assistant\" && m.stopReason !== \"aborted\") as any;\n\n\t\t\t\tconst contextTokens = lastAssistantMessage\n\t\t\t\t\t? lastAssistantMessage.usage.input +\n\t\t\t\t\t\tlastAssistantMessage.usage.output +\n\t\t\t\t\t\tlastAssistantMessage.usage.cacheRead +\n\t\t\t\t\t\tlastAssistantMessage.usage.cacheWrite\n\t\t\t\t\t: 0;\n\t\t\t\tconst currentRunModel = this.session.model ?? this.activeModel;\n\t\t\t\tconst contextWindow = currentRunModel.contextWindow || 200000;\n\n\t\t\t\tlog.logUsageSummary(this.runState.logCtx!, this.runState.totalUsage, contextTokens, contextWindow);\n\t\t\t}\n\n\t\t\t// Clear run state\n\t\t\tthis.runState.ctx = null;\n\t\t\tthis.runState.logCtx = null;\n\t\t\tthis.runState.queue = null;\n\t\t}\n\n\t\treturn { stopReason: this.runState.stopReason, errorMessage: this.runState.errorMessage };\n\t}\n\n\tasync handleBuiltinCommand(ctx: DingTalkContext, command: BuiltInCommand): Promise<void> {\n\t\ttry {\n\t\t\tswitch (command.name) {\n\t\t\t\tcase \"help\":\n\t\t\t\t\tawait this.sendCommandReply(ctx, renderBuiltInHelp());\n\t\t\t\t\treturn;\n\t\t\t\tcase \"stop\":\n\t\t\t\t\tawait this.sendCommandReply(ctx, \"No task is running. Use `/stop` only while a task is running.\");\n\t\t\t\t\treturn;\n\t\t\t\tcase \"steer\":\n\t\t\t\t\tthis.requireQueuedMessage(command.args, \"steer\");\n\t\t\t\t\tawait this.sendCommandReply(\n\t\t\t\t\t\tctx,\n\t\t\t\t\t\t\"No task is running. Send the message directly instead of using `/steer`.\",\n\t\t\t\t\t);\n\t\t\t\t\treturn;\n\t\t\t\tcase \"followup\":\n\t\t\t\t\tthis.requireQueuedMessage(command.args, \"followup\");\n\t\t\t\t\tawait this.sendCommandReply(\n\t\t\t\t\t\tctx,\n\t\t\t\t\t\t\"No task is running. Send the message directly now, or use `/followup` while a task is running.\",\n\t\t\t\t\t);\n\t\t\t\t\treturn;\n\t\t\t}\n\t\t} catch (err) {\n\t\t\tconst errMsg = err instanceof Error ? err.message : String(err);\n\t\t\tlog.logWarning(`[${this.channelId}] Built-in command failed`, errMsg);\n\t\t\tawait this.sendCommandReply(ctx, `命令执行失败:${errMsg}`);\n\t\t}\n\t}\n\n\tasync queueSteer(text: string, userName?: string): Promise<void> {\n\t\tawait this.queueBusyMessage(\"steer\", this.requireQueuedMessage(text, \"steer\"), userName);\n\t}\n\n\tasync queueFollowUp(text: string, userName?: string): Promise<void> {\n\t\tawait this.queueBusyMessage(\"followUp\", this.requireQueuedMessage(text, \"followup\"), userName);\n\t}\n\n\tasync abort(): Promise<void> {\n\t\tawait this.session.abort();\n\t}\n\n\t// === Private helpers ===\n\n\tprivate async sendCommandReply(ctx: DingTalkContext, text: string): Promise<void> {\n\t\tconst delivered = await ctx.respondPlain(text);\n\t\tif (!delivered) {\n\t\t\tawait ctx.replaceMessage(text);\n\t\t\tawait ctx.flush();\n\t\t}\n\t}\n\n\tprivate requireQueuedMessage(text: string, commandName: \"steer\" | \"followup\"): string {\n\t\tconst trimmedText = text.trim();\n\t\tif (!trimmedText) {\n\t\t\tthrow new Error(`/${commandName} requires a message.`);\n\t\t}\n\t\treturn trimmedText;\n\t}\n\n\tprivate shouldPreserveRawInput(text: string): boolean {\n\t\treturn text.trim().startsWith(\"/\");\n\t}\n\n\tprivate formatUserMessage(text: string, userName?: string, now: Date = new Date()): string {\n\t\tconst pad = (n: number) => n.toString().padStart(2, \"0\");\n\t\tconst offset = -now.getTimezoneOffset();\n\t\tconst offsetSign = offset >= 0 ? \"+\" : \"-\";\n\t\tconst offsetHours = pad(Math.floor(Math.abs(offset) / 60));\n\t\tconst offsetMins = pad(Math.abs(offset) % 60);\n\t\tconst timestamp = `${now.getFullYear()}-${pad(now.getMonth() + 1)}-${pad(now.getDate())} ${pad(now.getHours())}:${pad(now.getMinutes())}:${pad(now.getSeconds())}${offsetSign}${offsetHours}:${offsetMins}`;\n\t\treturn `[${timestamp}] [${userName || \"unknown\"}]: ${text}`;\n\t}\n\n\tprivate async queueBusyMessage(delivery: \"steer\" | \"followUp\", text: string, userName?: string): Promise<void> {\n\t\tif (!this.session.isStreaming) {\n\t\t\tthrow new Error(\"No task is currently running.\");\n\t\t}\n\n\t\tawait this.session.prompt(this.formatUserMessage(text, userName), {\n\t\t\tstreamingBehavior: delivery,\n\t\t});\n\t}\n\n\tprivate resetRunState(ctx: DingTalkContext): void {\n\t\tthis.runState = createEmptyRunState();\n\t\tthis.runState.ctx = ctx;\n\t\tthis.runState.logCtx = {\n\t\t\tchannelId: ctx.message.channel,\n\t\t\tuserName: ctx.message.userName,\n\t\t\tchannelName: ctx.channelName,\n\t\t};\n\t}\n\n\tprivate async refreshSessionResources(): Promise<void> {\n\t\tawait this.ensureSessionReady();\n\t\tconst skills = loadPipiclawSkills(this.channelDir, this.workspacePath);\n\t\tthis.currentSkills = skills;\n\t\tawait this.session.reload();\n\t}\n\n\tprivate async initializeSession(): Promise<void> {\n\t\tconst skills = loadPipiclawSkills(this.channelDir, this.workspacePath);\n\t\tthis.currentSkills = skills;\n\t\tawait this.session.reload();\n\t}\n\n\tprivate async ensureSessionReady(): Promise<void> {\n\t\tawait this.sessionReady;\n\t}\n\n\t// === Session event subscription ===\n\n\tprivate subscribeToSessionEvents(): void {\n\t\tthis.session.subscribe(async (event: any) => {\n\t\t\tif (!this.runState.ctx || !this.runState.logCtx || !this.runState.queue) return;\n\n\t\t\tconst { ctx, logCtx, queue, pendingTools } = this.runState;\n\n\t\t\tif (event.type === \"tool_execution_start\") {\n\t\t\t\tconst agentEvent = event as any & { type: \"tool_execution_start\" };\n\t\t\t\tconst args = agentEvent.args as { label?: string };\n\t\t\t\tconst label = args.label || agentEvent.toolName;\n\n\t\t\t\tpendingTools.set(agentEvent.toolCallId, {\n\t\t\t\t\ttoolName: agentEvent.toolName,\n\t\t\t\t\targs: agentEvent.args,\n\t\t\t\t\tstartTime: Date.now(),\n\t\t\t\t});\n\n\t\t\t\tlog.logToolStart(logCtx, agentEvent.toolName, label, agentEvent.args as Record<string, unknown>);\n\t\t\t\tqueue.enqueue(() => ctx.respond(formatProgressEntry(\"tool\", label), false), \"tool label\");\n\t\t\t} else if (event.type === \"tool_execution_update\") {\n\t\t\t\tconst agentEvent = event as { type: \"tool_execution_update\"; toolName: string; partialResult: unknown };\n\t\t\t\tif (agentEvent.toolName !== \"subagent\") {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tconst partialText = truncate(extractToolResultText(agentEvent.partialResult), 200);\n\t\t\t\tif (!partialText.trim()) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tqueue.enqueue(() => ctx.respond(formatProgressEntry(\"tool\", partialText), false), \"tool update\");\n\t\t\t} else if (event.type === \"tool_execution_end\") {\n\t\t\t\tconst agentEvent = event as any & { type: \"tool_execution_end\" };\n\t\t\t\tconst resultStr = extractToolResultText(agentEvent.result);\n\t\t\t\tconst pending = pendingTools.get(agentEvent.toolCallId);\n\t\t\t\tpendingTools.delete(agentEvent.toolCallId);\n\n\t\t\t\tconst durationMs = pending ? Date.now() - pending.startTime : 0;\n\n\t\t\t\tif (agentEvent.isError) {\n\t\t\t\t\tlog.logToolError(logCtx, agentEvent.toolName, durationMs, resultStr);\n\t\t\t\t} else {\n\t\t\t\t\tlog.logToolSuccess(logCtx, agentEvent.toolName, durationMs, resultStr);\n\t\t\t\t}\n\n\t\t\t\tif (\n\t\t\t\t\tagentEvent.toolName === \"subagent\" &&\n\t\t\t\t\tagentEvent.result &&\n\t\t\t\t\ttypeof agentEvent.result === \"object\" &&\n\t\t\t\t\t\"details\" in agentEvent.result &&\n\t\t\t\t\tisSubAgentToolDetails((agentEvent.result as { details?: unknown }).details)\n\t\t\t\t) {\n\t\t\t\t\tmergeSubAgentUsage(\n\t\t\t\t\t\tthis.runState.totalUsage,\n\t\t\t\t\t\t(agentEvent.result as { details: SubAgentToolDetails }).details,\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\tif (agentEvent.isError) {\n\t\t\t\t\tqueue.enqueue(\n\t\t\t\t\t\t() => ctx.respond(formatProgressEntry(\"error\", truncate(resultStr, 200)), false),\n\t\t\t\t\t\t\"tool error\",\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t} else if (event.type === \"message_start\") {\n\t\t\t\tconst agentEvent = event as any & { type: \"message_start\" };\n\t\t\t\tif (agentEvent.message.role === \"assistant\") {\n\t\t\t\t\tlog.logResponseStart(logCtx);\n\t\t\t\t}\n\t\t\t} else if (event.type === \"message_end\") {\n\t\t\t\tconst agentEvent = event as any & { type: \"message_end\" };\n\t\t\t\tconst commandResultText = extractCustomCommandResultText(agentEvent.message);\n\t\t\t\tif (commandResultText) {\n\t\t\t\t\tthis.runState.finalOutcome = { kind: \"final\", text: commandResultText };\n\t\t\t\t\tlog.logResponse(logCtx, commandResultText);\n\t\t\t\t\tqueue.enqueue(async () => {\n\t\t\t\t\t\tconst delivered = await ctx.respondPlain(commandResultText);\n\t\t\t\t\t\tif (!delivered) {\n\t\t\t\t\t\t\tawait ctx.replaceMessage(commandResultText);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tthis.runState.finalResponseDelivered = true;\n\t\t\t\t\t}, \"command result\");\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tif (agentEvent.message.role === \"assistant\") {\n\t\t\t\t\tconst assistantMsg = agentEvent.message as any;\n\n\t\t\t\t\tif (assistantMsg.stopReason) {\n\t\t\t\t\t\tthis.runState.stopReason = assistantMsg.stopReason;\n\t\t\t\t\t}\n\t\t\t\t\tif (assistantMsg.errorMessage) {\n\t\t\t\t\t\tthis.runState.errorMessage = assistantMsg.errorMessage;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (assistantMsg.usage) {\n\t\t\t\t\t\tthis.runState.totalUsage.input += assistantMsg.usage.input;\n\t\t\t\t\t\tthis.runState.totalUsage.output += assistantMsg.usage.output;\n\t\t\t\t\t\tthis.runState.totalUsage.cacheRead += assistantMsg.usage.cacheRead;\n\t\t\t\t\t\tthis.runState.totalUsage.cacheWrite += assistantMsg.usage.cacheWrite;\n\t\t\t\t\t\tthis.runState.totalUsage.cost.input += assistantMsg.usage.cost.input;\n\t\t\t\t\t\tthis.runState.totalUsage.cost.output += assistantMsg.usage.cost.output;\n\t\t\t\t\t\tthis.runState.totalUsage.cost.cacheRead += assistantMsg.usage.cost.cacheRead;\n\t\t\t\t\t\tthis.runState.totalUsage.cost.cacheWrite += assistantMsg.usage.cost.cacheWrite;\n\t\t\t\t\t\tthis.runState.totalUsage.cost.total += assistantMsg.usage.cost.total;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst content = agentEvent.message.content;\n\t\t\t\t\tconst thinkingParts: string[] = [];\n\t\t\t\t\tconst textParts: string[] = [];\n\t\t\t\t\tlet hasToolCalls = false;\n\t\t\t\t\tfor (const part of content) {\n\t\t\t\t\t\tif (part.type === \"thinking\") {\n\t\t\t\t\t\t\tthinkingParts.push((part as any).thinking);\n\t\t\t\t\t\t} else if (part.type === \"text\") {\n\t\t\t\t\t\t\ttextParts.push((part as any).text);\n\t\t\t\t\t\t} else if (part.type === \"toolCall\") {\n\t\t\t\t\t\t\thasToolCalls = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tconst text = textParts.join(\"\\n\");\n\n\t\t\t\t\tfor (const thinking of thinkingParts) {\n\t\t\t\t\t\tlog.logThinking(logCtx, thinking);\n\t\t\t\t\t\tqueue.enqueue(() => ctx.respond(formatProgressEntry(\"thinking\", thinking), false), \"thinking\");\n\t\t\t\t\t}\n\n\t\t\t\t\tif (hasToolCalls && text.trim()) {\n\t\t\t\t\t\tqueue.enqueue(() => ctx.respond(formatProgressEntry(\"assistant\", text), false), \"assistant progress\");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else if (event.type === \"turn_end\") {\n\t\t\t\tconst turnEvent = event as any & {\n\t\t\t\t\ttype: \"turn_end\";\n\t\t\t\t\tmessage: { role: string; stopReason?: string; content: Array<{ type: string; text?: string }> };\n\t\t\t\t\ttoolResults: unknown[];\n\t\t\t\t};\n\t\t\t\tif (turnEvent.message.role === \"assistant\" && turnEvent.toolResults.length === 0) {\n\t\t\t\t\tif (turnEvent.message.stopReason === \"error\" || turnEvent.message.stopReason === \"aborted\") {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst finalContent = turnEvent.message.content as Array<{ type: string; text?: string }>;\n\t\t\t\t\tconst finalText = finalContent\n\t\t\t\t\t\t.filter((part): part is { type: \"text\"; text: string } => part.type === \"text\" && !!part.text)\n\t\t\t\t\t\t.map((part) => part.text)\n\t\t\t\t\t\t.join(\"\\n\");\n\n\t\t\t\t\tconst trimmedFinalText = finalText.trim();\n\t\t\t\t\tif (!trimmedFinalText) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (trimmedFinalText === \"[SILENT]\" || trimmedFinalText.startsWith(\"[SILENT]\")) {\n\t\t\t\t\t\tthis.runState.finalOutcome = { kind: \"silent\" };\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (\n\t\t\t\t\t\tthis.runState.finalOutcome.kind === \"final\" &&\n\t\t\t\t\t\tthis.runState.finalOutcome.text.trim() === trimmedFinalText\n\t\t\t\t\t) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tthis.runState.finalOutcome = { kind: \"final\", text: finalText };\n\t\t\t\t\tlog.logResponse(logCtx, finalText);\n\t\t\t\t\tqueue.enqueue(async () => {\n\t\t\t\t\t\tconst delivered = await ctx.respondPlain(finalText);\n\t\t\t\t\t\tif (delivered) {\n\t\t\t\t\t\t\tthis.runState.finalResponseDelivered = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}, \"final response\");\n\t\t\t\t}\n\t\t\t} else if (event.type === \"auto_compaction_start\") {\n\t\t\t\tlog.logInfo(`Auto-compaction started (reason: ${(event as any).reason})`);\n\t\t\t\tqueue.enqueue(\n\t\t\t\t\t() => ctx.respond(formatProgressEntry(\"assistant\", \"Compacting context...\"), false),\n\t\t\t\t\t\"compaction start\",\n\t\t\t\t);\n\t\t\t} else if (event.type === \"auto_compaction_end\") {\n\t\t\t\tconst compEvent = event as any;\n\t\t\t\tif (compEvent.result) {\n\t\t\t\t\tlog.logInfo(`Auto-compaction complete: ${compEvent.result.tokensBefore} tokens compacted`);\n\t\t\t\t} else if (compEvent.aborted) {\n\t\t\t\t\tlog.logInfo(\"Auto-compaction aborted\");\n\t\t\t\t}\n\t\t\t} else if (event.type === \"auto_retry_start\") {\n\t\t\t\tconst retryEvent = event as any;\n\t\t\t\tlog.logWarning(`Retrying (${retryEvent.attempt}/${retryEvent.maxAttempts})`, retryEvent.errorMessage);\n\t\t\t\tqueue.enqueue(\n\t\t\t\t\t() =>\n\t\t\t\t\t\tctx.respond(\n\t\t\t\t\t\t\tformatProgressEntry(\"assistant\", `Retrying (${retryEvent.attempt}/${retryEvent.maxAttempts})...`),\n\t\t\t\t\t\t\tfalse,\n\t\t\t\t\t\t),\n\t\t\t\t\t\"retry\",\n\t\t\t\t);\n\t\t\t}\n\t\t});\n\t}\n}\n\n// ============================================================================\n// Factory\n// ============================================================================\n\nconst channelRunners = new Map<string, AgentRunner>();\n\nexport function getOrCreateRunner(sandboxConfig: SandboxConfig, channelId: string, channelDir: string): AgentRunner {\n\tconst existing = channelRunners.get(channelId);\n\tif (existing) return existing;\n\n\tconst runner = new ChannelRunner(sandboxConfig, channelId, channelDir);\n\tchannelRunners.set(channelId, runner);\n\treturn runner;\n}\n"]}
1
+ {"version":3,"file":"agent.js","sourceRoot":"","sources":["../src/agent.ts"],"names":[],"mappings":"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","sourcesContent":["import { Agent } from \"@mariozechner/pi-agent-core\";\nimport type { Api, Model } from \"@mariozechner/pi-ai\";\nimport {\n\tAgentSession,\n\tAuthStorage,\n\tconvertToLlm,\n\tDefaultResourceLoader,\n\tModelRegistry,\n\tSessionManager,\n\ttype Skill,\n} from \"@mariozechner/pi-coding-agent\";\nimport { mkdir, writeFile } from \"fs/promises\";\nimport { dirname, join, resolve } from \"path\";\nimport { COMMAND_RESULT_CUSTOM_TYPE, createCommandExtension } from \"./command-extension.js\";\nimport { type BuiltInCommand, renderBuiltInHelp } from \"./commands.js\";\nimport { getAgentConfig, getApiKeyForModel, getSoul, loadPipiclawSkills } from \"./config-loader.js\";\nimport { PipiclawSettingsManager } from \"./context.js\";\nimport type { DingTalkContext } from \"./dingtalk.js\";\nimport * as log from \"./log.js\";\nimport { MemoryLifecycle } from \"./memory-lifecycle.js\";\nimport { resolveInitialModel } from \"./model-utils.js\";\nimport { APP_HOME_DIR, AUTH_CONFIG_PATH, MODELS_CONFIG_PATH } from \"./paths.js\";\nimport { buildAppendSystemPrompt } from \"./prompt-builder.js\";\nimport { createExecutor, type SandboxConfig } from \"./sandbox.js\";\nimport type { ChannelStore } from \"./store.js\";\nimport { discoverSubAgents, formatSubAgentList, type SubAgentDiscoveryResult } from \"./sub-agents.js\";\nimport { createPipiclawTools } from \"./tools/index.js\";\nimport type { SubAgentToolDetails } from \"./tools/subagent.js\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface AgentRunner {\n\trun(ctx: DingTalkContext, store: ChannelStore): Promise<{ stopReason: string; errorMessage?: string }>;\n\thandleBuiltinCommand(ctx: DingTalkContext, command: BuiltInCommand): Promise<void>;\n\tqueueSteer(text: string, userName?: string): Promise<void>;\n\tqueueFollowUp(text: string, userName?: string): Promise<void>;\n\tabort(): Promise<void>;\n}\n\ntype FinalOutcome = { kind: \"none\" } | { kind: \"silent\" } | { kind: \"final\"; text: string };\ntype ModelRegistryClass = {\n\tcreate?: (authStorage: AuthStorage, modelsJsonPath?: string) => ModelRegistry;\n\tnew (authStorage: AuthStorage, modelsJsonPath?: string): ModelRegistry;\n};\n\nfunction isSilentOutcome(outcome: FinalOutcome): outcome is { kind: \"silent\" } {\n\treturn outcome.kind === \"silent\";\n}\n\nfunction isFinalOutcome(outcome: FinalOutcome): outcome is { kind: \"final\"; text: string } {\n\treturn outcome.kind === \"final\";\n}\n\nfunction getFinalOutcomeText(outcome: FinalOutcome): string | null {\n\treturn isFinalOutcome(outcome) ? outcome.text : null;\n}\n\nfunction createModelRegistry(authStorage: AuthStorage, modelsJsonPath: string): ModelRegistry {\n\tconst registryClass = ModelRegistry as unknown as ModelRegistryClass;\n\treturn typeof registryClass.create === \"function\"\n\t\t? registryClass.create(authStorage, modelsJsonPath)\n\t\t: new registryClass(authStorage, modelsJsonPath);\n}\n\n// ============================================================================\n// Text helpers\n// ============================================================================\n\nfunction truncate(text: string, maxLen: number): string {\n\tif (text.length <= maxLen) return text;\n\treturn `${text.substring(0, maxLen - 3)}...`;\n}\n\nfunction sanitizeProgressText(text: string): string {\n\treturn text\n\t\t.replace(/\\uFFFC/g, \"\")\n\t\t.replace(/\\r/g, \"\")\n\t\t.trim();\n}\n\nfunction formatProgressEntry(kind: \"tool\" | \"thinking\" | \"error\" | \"assistant\", text: string): string {\n\tconst cleaned = sanitizeProgressText(text);\n\tif (!cleaned) return \"\";\n\n\tconst normalized = cleaned.replace(/\\n+/g, \" \").trim();\n\tswitch (kind) {\n\t\tcase \"tool\":\n\t\t\treturn `Running: ${normalized}`;\n\t\tcase \"thinking\":\n\t\t\treturn `Thinking: ${normalized}`;\n\t\tcase \"error\":\n\t\t\treturn `Error: ${normalized}`;\n\t\tcase \"assistant\":\n\t\t\treturn normalized;\n\t}\n}\n\nfunction extractToolResultText(result: unknown): string {\n\tif (typeof result === \"string\") {\n\t\treturn result;\n\t}\n\n\tif (\n\t\tresult &&\n\t\ttypeof result === \"object\" &&\n\t\t\"content\" in result &&\n\t\tArray.isArray((result as { content: unknown }).content)\n\t) {\n\t\tconst content = (result as { content: Array<{ type: string; text?: string }> }).content;\n\t\tconst textParts: string[] = [];\n\t\tfor (const part of content) {\n\t\t\tif (part.type === \"text\" && part.text) {\n\t\t\t\ttextParts.push(part.text);\n\t\t\t}\n\t\t}\n\t\tif (textParts.length > 0) {\n\t\t\treturn textParts.join(\"\\n\");\n\t\t}\n\t}\n\n\treturn JSON.stringify(result);\n}\n\nfunction isSubAgentToolDetails(value: unknown): value is SubAgentToolDetails {\n\tif (!value || typeof value !== \"object\" || !(\"kind\" in value) || (value as { kind?: unknown }).kind !== \"subagent\") {\n\t\treturn false;\n\t}\n\n\tif (!(\"usage\" in value)) {\n\t\treturn false;\n\t}\n\n\tconst usage = (value as { usage?: unknown }).usage;\n\treturn (\n\t\t!!usage &&\n\t\ttypeof usage === \"object\" &&\n\t\t\"input\" in usage &&\n\t\t\"output\" in usage &&\n\t\t\"cacheRead\" in usage &&\n\t\t\"cacheWrite\" in usage &&\n\t\t\"cost\" in usage\n\t);\n}\n\nfunction mergeSubAgentUsage(totalUsage: UsageTotals, details: SubAgentToolDetails): void {\n\ttotalUsage.input += details.usage.input;\n\ttotalUsage.output += details.usage.output;\n\ttotalUsage.cacheRead += details.usage.cacheRead;\n\ttotalUsage.cacheWrite += details.usage.cacheWrite;\n\ttotalUsage.cost.input += details.usage.cost.input;\n\ttotalUsage.cost.output += details.usage.cost.output;\n\ttotalUsage.cost.cacheRead += details.usage.cost.cacheRead;\n\ttotalUsage.cost.cacheWrite += details.usage.cost.cacheWrite;\n\ttotalUsage.cost.total += details.usage.cost.total;\n}\n\nfunction extractCustomCommandResultText(message: unknown): string | null {\n\tif (\n\t\t!message ||\n\t\ttypeof message !== \"object\" ||\n\t\t!(\"role\" in message) ||\n\t\t!(\"customType\" in message) ||\n\t\t(message as { role?: unknown }).role !== \"custom\" ||\n\t\t(message as { customType?: unknown }).customType !== COMMAND_RESULT_CUSTOM_TYPE\n\t) {\n\t\treturn null;\n\t}\n\n\tconst content = (message as { content?: unknown }).content;\n\treturn typeof content === \"string\" && content.trim() ? content : null;\n}\n\n// ============================================================================\n// Run State\n// ============================================================================\n\ninterface PendingTool {\n\ttoolName: string;\n\targs: unknown;\n\tstartTime: number;\n}\n\ninterface UsageTotals {\n\tinput: number;\n\toutput: number;\n\tcacheRead: number;\n\tcacheWrite: number;\n\tcost: { input: number; output: number; cacheRead: number; cacheWrite: number; total: number };\n}\n\ninterface RunQueue {\n\tenqueue(fn: () => Promise<void>, errorContext: string): void;\n\tenqueueMessage(text: string, target: \"main\" | \"thread\", errorContext: string, doLog?: boolean): void;\n}\n\ninterface RunState {\n\tctx: DingTalkContext | null;\n\tlogCtx: { channelId: string; userName?: string; channelName?: string } | null;\n\tstore: ChannelStore | null;\n\tqueue: RunQueue | null;\n\tpendingTools: Map<string, PendingTool>;\n\ttotalUsage: UsageTotals;\n\tstopReason: string;\n\terrorMessage: string | undefined;\n\tfinalOutcome: FinalOutcome;\n\tfinalResponseDelivered: boolean;\n}\n\nfunction createEmptyRunState(): RunState {\n\treturn {\n\t\tctx: null,\n\t\tlogCtx: null,\n\t\tstore: null,\n\t\tqueue: null,\n\t\tpendingTools: new Map(),\n\t\ttotalUsage: {\n\t\t\tinput: 0,\n\t\t\toutput: 0,\n\t\t\tcacheRead: 0,\n\t\t\tcacheWrite: 0,\n\t\t\tcost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },\n\t\t},\n\t\tstopReason: \"stop\",\n\t\terrorMessage: undefined,\n\t\tfinalOutcome: { kind: \"none\" },\n\t\tfinalResponseDelivered: false,\n\t};\n}\n\n// ============================================================================\n// ChannelRunner\n// ============================================================================\n\nclass ChannelRunner implements AgentRunner {\n\t// --- Constructed once ---\n\tprivate readonly sandboxConfig: SandboxConfig;\n\tprivate readonly channelId: string;\n\tprivate readonly channelDir: string;\n\tprivate readonly workspacePath: string;\n\tprivate readonly workspaceDir: string;\n\tprivate readonly session: AgentSession;\n\tprivate readonly agent: Agent;\n\tprivate readonly sessionManager: SessionManager;\n\tprivate readonly settingsManager: PipiclawSettingsManager;\n\tprivate readonly modelRegistry: ModelRegistry;\n\tprivate readonly memoryLifecycle: MemoryLifecycle;\n\tprivate readonly sessionReady: Promise<void>;\n\tprivate subAgentDiscovery: SubAgentDiscoveryResult;\n\n\t// --- Mutable across runs ---\n\tprivate activeModel: Model<Api>;\n\tprivate currentSkills: Skill[];\n\n\t// --- Per run ---\n\tprivate runState: RunState = createEmptyRunState();\n\n\tconstructor(sandboxConfig: SandboxConfig, channelId: string, channelDir: string) {\n\t\tthis.sandboxConfig = sandboxConfig;\n\t\tthis.channelId = channelId;\n\t\tthis.channelDir = channelDir;\n\n\t\tconst executor = createExecutor(sandboxConfig);\n\t\tthis.workspaceDir = resolve(dirname(channelDir));\n\t\tthis.workspacePath = executor.getWorkspacePath(this.workspaceDir);\n\n\t\t// Initial skill summaries\n\t\tconst initialSkills = loadPipiclawSkills(channelDir, this.workspacePath);\n\t\tthis.currentSkills = initialSkills;\n\n\t\t// Create session manager\n\t\tconst contextFile = join(channelDir, \"context.jsonl\");\n\t\tthis.sessionManager = SessionManager.open(contextFile, channelDir);\n\t\tthis.settingsManager = new PipiclawSettingsManager(APP_HOME_DIR);\n\n\t\t// Create AuthStorage and ModelRegistry\n\t\tconst authStorage = AuthStorage.create(AUTH_CONFIG_PATH);\n\t\tthis.modelRegistry = createModelRegistry(authStorage, MODELS_CONFIG_PATH);\n\n\t\t// Resolve model: prefer saved global default, fall back to first available model\n\t\tthis.activeModel = resolveInitialModel(this.modelRegistry, this.settingsManager);\n\t\tlog.logInfo(`Using model: ${this.activeModel.provider}/${this.activeModel.id} (${this.activeModel.name})`);\n\t\tthis.subAgentDiscovery = this.refreshSubAgentDiscovery();\n\n\t\t// Create tools\n\t\tconst tools = createPipiclawTools({\n\t\t\texecutor,\n\t\t\tgetCurrentModel: () => this.activeModel,\n\t\t\tgetAvailableModels: () => this.modelRegistry.getAvailable(),\n\t\t\tresolveApiKey: async (model) => getApiKeyForModel(this.modelRegistry, model),\n\t\t\tworkspaceDir: this.workspaceDir,\n\t\t\tworkspacePath: this.workspacePath,\n\t\t\tchannelId: this.channelId,\n\t\t\tsandboxConfig: this.sandboxConfig,\n\t\t\tgetSubAgentDiscovery: () => this.subAgentDiscovery,\n\t\t});\n\n\t\t// Create agent\n\t\tthis.agent = new Agent({\n\t\t\tinitialState: {\n\t\t\t\tsystemPrompt: \"\",\n\t\t\t\tmodel: this.activeModel,\n\t\t\t\tthinkingLevel: \"off\",\n\t\t\t\ttools,\n\t\t\t},\n\t\t\tconvertToLlm,\n\t\t\tgetApiKey: async () => getApiKeyForModel(this.modelRegistry, this.activeModel),\n\t\t});\n\n\t\tthis.memoryLifecycle = new MemoryLifecycle({\n\t\t\tchannelId: this.channelId,\n\t\t\tchannelDir: this.channelDir,\n\t\t\tgetMessages: () => this.session.messages,\n\t\t\tgetSessionEntries: () => this.sessionManager.getBranch(),\n\t\t\tgetModel: () => this.session.model ?? this.activeModel,\n\t\t\tresolveApiKey: async (model) => getApiKeyForModel(this.modelRegistry, model),\n\t\t});\n\n\t\tconst resourceLoader = new DefaultResourceLoader({\n\t\t\tcwd: process.cwd(),\n\t\t\tagentDir: APP_HOME_DIR,\n\t\t\tsettingsManager: this.settingsManager as any,\n\t\t\textensionFactories: [\n\t\t\t\tthis.memoryLifecycle.createExtensionFactory(),\n\t\t\t\tcreateCommandExtension({\n\t\t\t\t\tgetCurrentModel: () => this.session.model ?? this.activeModel,\n\t\t\t\t\tgetAvailableModels: async () => {\n\t\t\t\t\t\tthis.modelRegistry.refresh();\n\t\t\t\t\t\treturn await this.modelRegistry.getAvailable();\n\t\t\t\t\t},\n\t\t\t\t\tgetSessionStats: () => this.session.getSessionStats(),\n\t\t\t\t\tgetThinkingLevel: () => this.session.thinkingLevel,\n\t\t\t\t\tswitchModel: async (model) => {\n\t\t\t\t\t\tawait this.session.setModel(model);\n\t\t\t\t\t\tthis.activeModel = model;\n\t\t\t\t\t},\n\t\t\t\t\trefreshSessionResources: async () => {\n\t\t\t\t\t\tawait this.refreshSessionResources();\n\t\t\t\t\t},\n\t\t\t\t}),\n\t\t\t],\n\t\t\tappendSystemPromptOverride: (base) => {\n\t\t\t\tconst soul = getSoul(this.workspaceDir);\n\t\t\t\tconst sections = [...base];\n\t\t\t\tif (soul) {\n\t\t\t\t\tsections.unshift(soul);\n\t\t\t\t}\n\t\t\t\tsections.push(\n\t\t\t\t\tbuildAppendSystemPrompt(this.workspacePath, this.channelId, this.sandboxConfig, {\n\t\t\t\t\t\tsubAgentList: formatSubAgentList(this.subAgentDiscovery.agents),\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t\treturn sections;\n\t\t\t},\n\t\t\tagentsFilesOverride: () => {\n\t\t\t\tconst agentConfig = getAgentConfig(this.channelDir);\n\t\t\t\treturn {\n\t\t\t\t\tagentsFiles: agentConfig ? [{ path: `${this.workspacePath}/AGENTS.md`, content: agentConfig }] : [],\n\t\t\t\t};\n\t\t\t},\n\t\t\tskillsOverride: (base) => ({\n\t\t\t\tskills: [...base.skills, ...this.currentSkills],\n\t\t\t\tdiagnostics: base.diagnostics,\n\t\t\t}),\n\t\t});\n\n\t\tconst baseToolsOverride = Object.fromEntries(tools.map((tool) => [tool.name, tool]));\n\n\t\t// Create AgentSession\n\t\tthis.session = new AgentSession({\n\t\t\tagent: this.agent,\n\t\t\tsessionManager: this.sessionManager,\n\t\t\tsettingsManager: this.settingsManager as any,\n\t\t\tcwd: process.cwd(),\n\t\t\tmodelRegistry: this.modelRegistry,\n\t\t\tresourceLoader,\n\t\t\tbaseToolsOverride,\n\t\t});\n\n\t\t// Subscribe to session events\n\t\tthis.subscribeToSessionEvents();\n\t\tthis.sessionReady = this.initializeSession();\n\t}\n\n\t// === Public API ===\n\n\tasync run(ctx: DingTalkContext, store: ChannelStore): Promise<{ stopReason: string; errorMessage?: string }> {\n\t\tthis.resetRunState(ctx, store);\n\n\t\t// Create queue for this run\n\t\tlet queueChain = Promise.resolve();\n\t\tthis.runState.queue = {\n\t\t\tenqueue: (fn: () => Promise<void>, errorContext: string): void => {\n\t\t\t\tqueueChain = queueChain.then(async () => {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tawait fn();\n\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\tconst errMsg = err instanceof Error ? err.message : String(err);\n\t\t\t\t\t\tlog.logWarning(`DingTalk API error (${errorContext})`, errMsg);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t},\n\t\t\tenqueueMessage: function (text: string, target: \"main\" | \"thread\", errorContext: string, doLog = true): void {\n\t\t\t\tthis.enqueue(\n\t\t\t\t\t() => (target === \"main\" ? ctx.respond(text, doLog) : ctx.respondInThread(text)),\n\t\t\t\t\terrorContext,\n\t\t\t\t);\n\t\t\t},\n\t\t};\n\n\t\ttry {\n\t\t\tawait this.ensureSessionReady();\n\n\t\t\t// Ensure channel directory exists\n\t\t\tawait mkdir(this.channelDir, { recursive: true });\n\n\t\t\tconst userMessage = this.formatUserMessage(ctx.message.text, ctx.message.userName);\n\t\t\tconst promptText = this.shouldPreserveRawInput(ctx.message.text) ? ctx.message.text.trim() : userMessage;\n\n\t\t\t// Debug: write context to last_prompt.json (only with PIPICLAW_DEBUG=1)\n\t\t\tif (process.env.PIPICLAW_DEBUG) {\n\t\t\t\tconst debugContext = {\n\t\t\t\t\tsystemPrompt: this.agent.state.systemPrompt,\n\t\t\t\t\tmessages: this.session.messages,\n\t\t\t\t\tnewUserMessage: promptText,\n\t\t\t\t};\n\t\t\t\tawait writeFile(join(this.channelDir, \"last_prompt.json\"), JSON.stringify(debugContext, null, 2));\n\t\t\t}\n\n\t\t\tawait this.session.prompt(promptText);\n\t\t} catch (err) {\n\t\t\tthis.runState.stopReason = \"error\";\n\t\t\tthis.runState.errorMessage = err instanceof Error ? err.message : String(err);\n\t\t\tlog.logWarning(`[${this.channelId}] Runner failed`, this.runState.errorMessage);\n\t\t} finally {\n\t\t\tawait queueChain;\n\t\t\tconst finalOutcome = this.runState.finalOutcome;\n\t\t\tconst finalOutcomeText = getFinalOutcomeText(finalOutcome);\n\n\t\t\ttry {\n\t\t\t\tif (\n\t\t\t\t\tthis.runState.stopReason === \"error\" &&\n\t\t\t\t\tthis.runState.errorMessage &&\n\t\t\t\t\t!this.runState.finalResponseDelivered\n\t\t\t\t) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tawait ctx.replaceMessage(\"_Sorry, something went wrong_\");\n\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\tconst errMsg = err instanceof Error ? err.message : String(err);\n\t\t\t\t\t\tlog.logWarning(\"Failed to post error message\", errMsg);\n\t\t\t\t\t}\n\t\t\t\t} else if (isSilentOutcome(finalOutcome)) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tawait ctx.deleteMessage();\n\t\t\t\t\t\tlog.logInfo(\"Silent response - deleted message\");\n\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\tconst errMsg = err instanceof Error ? err.message : String(err);\n\t\t\t\t\t\tlog.logWarning(\"Failed to delete message for silent response\", errMsg);\n\t\t\t\t\t}\n\t\t\t\t} else if (finalOutcomeText && !this.runState.finalResponseDelivered) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tawait ctx.replaceMessage(finalOutcomeText);\n\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\tconst errMsg = err instanceof Error ? err.message : String(err);\n\t\t\t\t\t\tlog.logWarning(\"Failed to replace message with final text\", errMsg);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tawait ctx.flush();\n\t\t\t} finally {\n\t\t\t\tawait ctx.close();\n\t\t\t}\n\n\t\t\t// Log usage summary\n\t\t\tif (this.runState.totalUsage.cost.total > 0) {\n\t\t\t\tconst messages = this.session.messages;\n\t\t\t\tconst lastAssistantMessage = messages\n\t\t\t\t\t.slice()\n\t\t\t\t\t.reverse()\n\t\t\t\t\t.find((m: any) => m.role === \"assistant\" && m.stopReason !== \"aborted\") as any;\n\n\t\t\t\tconst contextTokens = lastAssistantMessage\n\t\t\t\t\t? lastAssistantMessage.usage.input +\n\t\t\t\t\t\tlastAssistantMessage.usage.output +\n\t\t\t\t\t\tlastAssistantMessage.usage.cacheRead +\n\t\t\t\t\t\tlastAssistantMessage.usage.cacheWrite\n\t\t\t\t\t: 0;\n\t\t\t\tconst currentRunModel = this.session.model ?? this.activeModel;\n\t\t\t\tconst contextWindow = currentRunModel.contextWindow || 200000;\n\n\t\t\t\tlog.logUsageSummary(this.runState.logCtx!, this.runState.totalUsage, contextTokens, contextWindow);\n\t\t\t}\n\n\t\t\t// Clear run state\n\t\t\tthis.runState.ctx = null;\n\t\t\tthis.runState.logCtx = null;\n\t\t\tthis.runState.queue = null;\n\t\t}\n\n\t\treturn { stopReason: this.runState.stopReason, errorMessage: this.runState.errorMessage };\n\t}\n\n\tasync handleBuiltinCommand(ctx: DingTalkContext, command: BuiltInCommand): Promise<void> {\n\t\ttry {\n\t\t\tswitch (command.name) {\n\t\t\t\tcase \"help\":\n\t\t\t\t\tawait this.sendCommandReply(ctx, renderBuiltInHelp());\n\t\t\t\t\treturn;\n\t\t\t\tcase \"stop\":\n\t\t\t\t\tawait this.sendCommandReply(ctx, \"No task is running. Use `/stop` only while a task is running.\");\n\t\t\t\t\treturn;\n\t\t\t\tcase \"steer\":\n\t\t\t\t\tthis.requireQueuedMessage(command.args, \"steer\");\n\t\t\t\t\tawait this.sendCommandReply(\n\t\t\t\t\t\tctx,\n\t\t\t\t\t\t\"No task is running. Send the message directly instead of using `/steer`.\",\n\t\t\t\t\t);\n\t\t\t\t\treturn;\n\t\t\t\tcase \"followup\":\n\t\t\t\t\tthis.requireQueuedMessage(command.args, \"followup\");\n\t\t\t\t\tawait this.sendCommandReply(\n\t\t\t\t\t\tctx,\n\t\t\t\t\t\t\"No task is running. Send the message directly now, or use `/followup` while a task is running.\",\n\t\t\t\t\t);\n\t\t\t\t\treturn;\n\t\t\t}\n\t\t} catch (err) {\n\t\t\tconst errMsg = err instanceof Error ? err.message : String(err);\n\t\t\tlog.logWarning(`[${this.channelId}] Built-in command failed`, errMsg);\n\t\t\tawait this.sendCommandReply(ctx, `命令执行失败:${errMsg}`);\n\t\t}\n\t}\n\n\tasync queueSteer(text: string, userName?: string): Promise<void> {\n\t\tawait this.queueBusyMessage(\"steer\", this.requireQueuedMessage(text, \"steer\"), userName);\n\t}\n\n\tasync queueFollowUp(text: string, userName?: string): Promise<void> {\n\t\tawait this.queueBusyMessage(\"followUp\", this.requireQueuedMessage(text, \"followup\"), userName);\n\t}\n\n\tasync abort(): Promise<void> {\n\t\tawait this.session.abort();\n\t}\n\n\t// === Private helpers ===\n\n\tprivate async sendCommandReply(ctx: DingTalkContext, text: string): Promise<void> {\n\t\tconst delivered = await ctx.respondPlain(text);\n\t\tif (!delivered) {\n\t\t\tawait ctx.replaceMessage(text);\n\t\t\tawait ctx.flush();\n\t\t}\n\t}\n\n\tprivate requireQueuedMessage(text: string, commandName: \"steer\" | \"followup\"): string {\n\t\tconst trimmedText = text.trim();\n\t\tif (!trimmedText) {\n\t\t\tthrow new Error(`/${commandName} requires a message.`);\n\t\t}\n\t\treturn trimmedText;\n\t}\n\n\tprivate shouldPreserveRawInput(text: string): boolean {\n\t\treturn text.trim().startsWith(\"/\");\n\t}\n\n\tprivate formatUserMessage(text: string, userName?: string, now: Date = new Date()): string {\n\t\tconst pad = (n: number) => n.toString().padStart(2, \"0\");\n\t\tconst offset = -now.getTimezoneOffset();\n\t\tconst offsetSign = offset >= 0 ? \"+\" : \"-\";\n\t\tconst offsetHours = pad(Math.floor(Math.abs(offset) / 60));\n\t\tconst offsetMins = pad(Math.abs(offset) % 60);\n\t\tconst timestamp = `${now.getFullYear()}-${pad(now.getMonth() + 1)}-${pad(now.getDate())} ${pad(now.getHours())}:${pad(now.getMinutes())}:${pad(now.getSeconds())}${offsetSign}${offsetHours}:${offsetMins}`;\n\t\treturn `[${timestamp}] [${userName || \"unknown\"}]: ${text}`;\n\t}\n\n\tprivate async queueBusyMessage(delivery: \"steer\" | \"followUp\", text: string, userName?: string): Promise<void> {\n\t\tif (!this.session.isStreaming) {\n\t\t\tthrow new Error(\"No task is currently running.\");\n\t\t}\n\n\t\tawait this.session.prompt(this.formatUserMessage(text, userName), {\n\t\t\tstreamingBehavior: delivery,\n\t\t});\n\t}\n\n\tprivate resetRunState(ctx: DingTalkContext, store: ChannelStore): void {\n\t\tthis.runState = createEmptyRunState();\n\t\tthis.runState.ctx = ctx;\n\t\tthis.runState.logCtx = {\n\t\t\tchannelId: ctx.message.channel,\n\t\t\tuserName: ctx.message.userName,\n\t\t\tchannelName: ctx.channelName,\n\t\t};\n\t\tthis.runState.store = store;\n\t}\n\n\tprivate async refreshSessionResources(): Promise<void> {\n\t\tawait this.ensureSessionReady();\n\t\tconst skills = loadPipiclawSkills(this.channelDir, this.workspacePath);\n\t\tthis.currentSkills = skills;\n\t\tthis.subAgentDiscovery = this.refreshSubAgentDiscovery();\n\t\tawait this.session.reload();\n\t}\n\n\tprivate async initializeSession(): Promise<void> {\n\t\tconst skills = loadPipiclawSkills(this.channelDir, this.workspacePath);\n\t\tthis.currentSkills = skills;\n\t\tthis.subAgentDiscovery = this.refreshSubAgentDiscovery();\n\t\tawait this.session.reload();\n\t}\n\n\tprivate async ensureSessionReady(): Promise<void> {\n\t\tawait this.sessionReady;\n\t}\n\n\tprivate refreshSubAgentDiscovery(): SubAgentDiscoveryResult {\n\t\tthis.modelRegistry.refresh();\n\t\tconst discovery = discoverSubAgents(this.workspaceDir, this.modelRegistry.getAvailable());\n\t\tfor (const warning of discovery.warnings) {\n\t\t\tlog.logWarning(`Sub-agent config warning (${this.channelId})`, warning);\n\t\t}\n\t\treturn discovery;\n\t}\n\n\t// === Session event subscription ===\n\n\tprivate subscribeToSessionEvents(): void {\n\t\tthis.session.subscribe(async (event: any) => {\n\t\t\tif (!this.runState.ctx || !this.runState.logCtx || !this.runState.queue) return;\n\n\t\t\tconst { ctx, logCtx, queue, pendingTools, store } = this.runState;\n\n\t\t\tif (event.type === \"tool_execution_start\") {\n\t\t\t\tconst agentEvent = event as any & { type: \"tool_execution_start\" };\n\t\t\t\tconst args = agentEvent.args as { label?: string };\n\t\t\t\tconst label = args.label || agentEvent.toolName;\n\n\t\t\t\tpendingTools.set(agentEvent.toolCallId, {\n\t\t\t\t\ttoolName: agentEvent.toolName,\n\t\t\t\t\targs: agentEvent.args,\n\t\t\t\t\tstartTime: Date.now(),\n\t\t\t\t});\n\n\t\t\t\tlog.logToolStart(logCtx, agentEvent.toolName, label, agentEvent.args as Record<string, unknown>);\n\t\t\t\tqueue.enqueue(() => ctx.respond(formatProgressEntry(\"tool\", label), false), \"tool label\");\n\t\t\t} else if (event.type === \"tool_execution_update\") {\n\t\t\t\tconst agentEvent = event as { type: \"tool_execution_update\"; toolName: string; partialResult: unknown };\n\t\t\t\tif (agentEvent.toolName !== \"subagent\") {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tconst partialText = truncate(extractToolResultText(agentEvent.partialResult), 200);\n\t\t\t\tif (!partialText.trim()) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tqueue.enqueue(() => ctx.respond(formatProgressEntry(\"tool\", partialText), false), \"tool update\");\n\t\t\t} else if (event.type === \"tool_execution_end\") {\n\t\t\t\tconst agentEvent = event as any & { type: \"tool_execution_end\" };\n\t\t\t\tconst resultStr = extractToolResultText(agentEvent.result);\n\t\t\t\tconst pending = pendingTools.get(agentEvent.toolCallId);\n\t\t\t\tpendingTools.delete(agentEvent.toolCallId);\n\n\t\t\t\tconst durationMs = pending ? Date.now() - pending.startTime : 0;\n\t\t\t\tconst subAgentDetails =\n\t\t\t\t\tagentEvent.toolName === \"subagent\" &&\n\t\t\t\t\tagentEvent.result &&\n\t\t\t\t\ttypeof agentEvent.result === \"object\" &&\n\t\t\t\t\t\"details\" in agentEvent.result &&\n\t\t\t\t\tisSubAgentToolDetails((agentEvent.result as { details?: unknown }).details)\n\t\t\t\t\t\t? (agentEvent.result as { details: SubAgentToolDetails }).details\n\t\t\t\t\t\t: null;\n\n\t\t\t\tif (subAgentDetails) {\n\t\t\t\t\tmergeSubAgentUsage(this.runState.totalUsage, subAgentDetails);\n\t\t\t\t\tconst label =\n\t\t\t\t\t\tpending?.args &&\n\t\t\t\t\t\ttypeof pending.args === \"object\" &&\n\t\t\t\t\t\t\"label\" in pending.args &&\n\t\t\t\t\t\ttypeof (pending.args as { label?: unknown }).label === \"string\"\n\t\t\t\t\t\t\t? ((pending.args as { label: string }).label ?? \"subagent\").trim()\n\t\t\t\t\t\t\t: \"subagent\";\n\t\t\t\t\tqueue.enqueue(\n\t\t\t\t\t\t() =>\n\t\t\t\t\t\t\tstore?.logSubAgentRun(logCtx.channelId, {\n\t\t\t\t\t\t\t\tdate: new Date().toISOString(),\n\t\t\t\t\t\t\t\ttoolCallId: agentEvent.toolCallId,\n\t\t\t\t\t\t\t\tlabel,\n\t\t\t\t\t\t\t\tagent: subAgentDetails.agent,\n\t\t\t\t\t\t\t\tsource: subAgentDetails.source,\n\t\t\t\t\t\t\t\tmodel: subAgentDetails.model,\n\t\t\t\t\t\t\t\ttools: [...subAgentDetails.tools],\n\t\t\t\t\t\t\t\tturns: subAgentDetails.turns,\n\t\t\t\t\t\t\t\ttoolCalls: subAgentDetails.toolCalls,\n\t\t\t\t\t\t\t\tdurationMs: subAgentDetails.durationMs,\n\t\t\t\t\t\t\t\tfailed: subAgentDetails.failed,\n\t\t\t\t\t\t\t\tfailureReason: subAgentDetails.failureReason,\n\t\t\t\t\t\t\t\toutput: resultStr.length > 16000 ? resultStr.slice(0, 16000) : resultStr,\n\t\t\t\t\t\t\t\toutputTruncated: resultStr.length > 16000,\n\t\t\t\t\t\t\t\tusage: {\n\t\t\t\t\t\t\t\t\t...subAgentDetails.usage,\n\t\t\t\t\t\t\t\t\tcost: { ...subAgentDetails.usage.cost },\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t}) ?? Promise.resolve(),\n\t\t\t\t\t\t\"sub-agent run log\",\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\tconst treatAsError = agentEvent.isError || Boolean(subAgentDetails?.failed);\n\t\t\t\tif (treatAsError) {\n\t\t\t\t\tlog.logToolError(logCtx, agentEvent.toolName, durationMs, resultStr);\n\t\t\t\t} else {\n\t\t\t\t\tlog.logToolSuccess(logCtx, agentEvent.toolName, durationMs, resultStr);\n\t\t\t\t}\n\n\t\t\t\tif (treatAsError) {\n\t\t\t\t\tqueue.enqueue(\n\t\t\t\t\t\t() => ctx.respond(formatProgressEntry(\"error\", truncate(resultStr, 200)), false),\n\t\t\t\t\t\t\"tool error\",\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t} else if (event.type === \"message_start\") {\n\t\t\t\tconst agentEvent = event as any & { type: \"message_start\" };\n\t\t\t\tif (agentEvent.message.role === \"assistant\") {\n\t\t\t\t\tlog.logResponseStart(logCtx);\n\t\t\t\t}\n\t\t\t} else if (event.type === \"message_end\") {\n\t\t\t\tconst agentEvent = event as any & { type: \"message_end\" };\n\t\t\t\tconst commandResultText = extractCustomCommandResultText(agentEvent.message);\n\t\t\t\tif (commandResultText) {\n\t\t\t\t\tthis.runState.finalOutcome = { kind: \"final\", text: commandResultText };\n\t\t\t\t\tlog.logResponse(logCtx, commandResultText);\n\t\t\t\t\tqueue.enqueue(async () => {\n\t\t\t\t\t\tconst delivered = await ctx.respondPlain(commandResultText);\n\t\t\t\t\t\tif (!delivered) {\n\t\t\t\t\t\t\tawait ctx.replaceMessage(commandResultText);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tthis.runState.finalResponseDelivered = true;\n\t\t\t\t\t}, \"command result\");\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tif (agentEvent.message.role === \"assistant\") {\n\t\t\t\t\tconst assistantMsg = agentEvent.message as any;\n\n\t\t\t\t\tif (assistantMsg.stopReason) {\n\t\t\t\t\t\tthis.runState.stopReason = assistantMsg.stopReason;\n\t\t\t\t\t}\n\t\t\t\t\tif (assistantMsg.errorMessage) {\n\t\t\t\t\t\tthis.runState.errorMessage = assistantMsg.errorMessage;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (assistantMsg.usage) {\n\t\t\t\t\t\tthis.runState.totalUsage.input += assistantMsg.usage.input;\n\t\t\t\t\t\tthis.runState.totalUsage.output += assistantMsg.usage.output;\n\t\t\t\t\t\tthis.runState.totalUsage.cacheRead += assistantMsg.usage.cacheRead;\n\t\t\t\t\t\tthis.runState.totalUsage.cacheWrite += assistantMsg.usage.cacheWrite;\n\t\t\t\t\t\tthis.runState.totalUsage.cost.input += assistantMsg.usage.cost.input;\n\t\t\t\t\t\tthis.runState.totalUsage.cost.output += assistantMsg.usage.cost.output;\n\t\t\t\t\t\tthis.runState.totalUsage.cost.cacheRead += assistantMsg.usage.cost.cacheRead;\n\t\t\t\t\t\tthis.runState.totalUsage.cost.cacheWrite += assistantMsg.usage.cost.cacheWrite;\n\t\t\t\t\t\tthis.runState.totalUsage.cost.total += assistantMsg.usage.cost.total;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst content = agentEvent.message.content;\n\t\t\t\t\tconst thinkingParts: string[] = [];\n\t\t\t\t\tconst textParts: string[] = [];\n\t\t\t\t\tlet hasToolCalls = false;\n\t\t\t\t\tfor (const part of content) {\n\t\t\t\t\t\tif (part.type === \"thinking\") {\n\t\t\t\t\t\t\tthinkingParts.push((part as any).thinking);\n\t\t\t\t\t\t} else if (part.type === \"text\") {\n\t\t\t\t\t\t\ttextParts.push((part as any).text);\n\t\t\t\t\t\t} else if (part.type === \"toolCall\") {\n\t\t\t\t\t\t\thasToolCalls = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tconst text = textParts.join(\"\\n\");\n\n\t\t\t\t\tfor (const thinking of thinkingParts) {\n\t\t\t\t\t\tlog.logThinking(logCtx, thinking);\n\t\t\t\t\t\tqueue.enqueue(() => ctx.respond(formatProgressEntry(\"thinking\", thinking), false), \"thinking\");\n\t\t\t\t\t}\n\n\t\t\t\t\tif (hasToolCalls && text.trim()) {\n\t\t\t\t\t\tqueue.enqueue(() => ctx.respond(formatProgressEntry(\"assistant\", text), false), \"assistant progress\");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else if (event.type === \"turn_end\") {\n\t\t\t\tconst turnEvent = event as any & {\n\t\t\t\t\ttype: \"turn_end\";\n\t\t\t\t\tmessage: { role: string; stopReason?: string; content: Array<{ type: string; text?: string }> };\n\t\t\t\t\ttoolResults: unknown[];\n\t\t\t\t};\n\t\t\t\tif (turnEvent.message.role === \"assistant\" && turnEvent.toolResults.length === 0) {\n\t\t\t\t\tif (turnEvent.message.stopReason === \"error\" || turnEvent.message.stopReason === \"aborted\") {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst finalContent = turnEvent.message.content as Array<{ type: string; text?: string }>;\n\t\t\t\t\tconst finalText = finalContent\n\t\t\t\t\t\t.filter((part): part is { type: \"text\"; text: string } => part.type === \"text\" && !!part.text)\n\t\t\t\t\t\t.map((part) => part.text)\n\t\t\t\t\t\t.join(\"\\n\");\n\n\t\t\t\t\tconst trimmedFinalText = finalText.trim();\n\t\t\t\t\tif (!trimmedFinalText) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (trimmedFinalText === \"[SILENT]\" || trimmedFinalText.startsWith(\"[SILENT]\")) {\n\t\t\t\t\t\tthis.runState.finalOutcome = { kind: \"silent\" };\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (\n\t\t\t\t\t\tthis.runState.finalOutcome.kind === \"final\" &&\n\t\t\t\t\t\tthis.runState.finalOutcome.text.trim() === trimmedFinalText\n\t\t\t\t\t) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tthis.runState.finalOutcome = { kind: \"final\", text: finalText };\n\t\t\t\t\tlog.logResponse(logCtx, finalText);\n\t\t\t\t\tqueue.enqueue(async () => {\n\t\t\t\t\t\tconst delivered = await ctx.respondPlain(finalText);\n\t\t\t\t\t\tif (delivered) {\n\t\t\t\t\t\t\tthis.runState.finalResponseDelivered = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}, \"final response\");\n\t\t\t\t}\n\t\t\t} else if (event.type === \"auto_compaction_start\") {\n\t\t\t\tlog.logInfo(`Auto-compaction started (reason: ${(event as any).reason})`);\n\t\t\t\tqueue.enqueue(\n\t\t\t\t\t() => ctx.respond(formatProgressEntry(\"assistant\", \"Compacting context...\"), false),\n\t\t\t\t\t\"compaction start\",\n\t\t\t\t);\n\t\t\t} else if (event.type === \"auto_compaction_end\") {\n\t\t\t\tconst compEvent = event as any;\n\t\t\t\tif (compEvent.result) {\n\t\t\t\t\tlog.logInfo(`Auto-compaction complete: ${compEvent.result.tokensBefore} tokens compacted`);\n\t\t\t\t} else if (compEvent.aborted) {\n\t\t\t\t\tlog.logInfo(\"Auto-compaction aborted\");\n\t\t\t\t}\n\t\t\t} else if (event.type === \"auto_retry_start\") {\n\t\t\t\tconst retryEvent = event as any;\n\t\t\t\tlog.logWarning(`Retrying (${retryEvent.attempt}/${retryEvent.maxAttempts})`, retryEvent.errorMessage);\n\t\t\t\tqueue.enqueue(\n\t\t\t\t\t() =>\n\t\t\t\t\t\tctx.respond(\n\t\t\t\t\t\t\tformatProgressEntry(\"assistant\", `Retrying (${retryEvent.attempt}/${retryEvent.maxAttempts})...`),\n\t\t\t\t\t\t\tfalse,\n\t\t\t\t\t\t),\n\t\t\t\t\t\"retry\",\n\t\t\t\t);\n\t\t\t}\n\t\t});\n\t}\n}\n\n// ============================================================================\n// Factory\n// ============================================================================\n\nconst channelRunners = new Map<string, AgentRunner>();\n\nexport function getOrCreateRunner(sandboxConfig: SandboxConfig, channelId: string, channelDir: string): AgentRunner {\n\tconst existing = channelRunners.get(channelId);\n\tif (existing) return existing;\n\n\tconst runner = new ChannelRunner(sandboxConfig, channelId, channelDir);\n\tchannelRunners.set(channelId, runner);\n\treturn runner;\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"prompt-builder.d.ts","sourceRoot":"","sources":["../src/prompt-builder.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAElD,MAAM,WAAW,yBAAyB;IACzC,YAAY,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,wBAAgB,uBAAuB,CACtC,aAAa,EAAE,MAAM,EACrB,SAAS,EAAE,MAAM,EACjB,aAAa,EAAE,aAAa,EAC5B,OAAO,GAAE,yBAA8B,GACrC,MAAM,CAmJR","sourcesContent":["import type { SandboxConfig } from \"./sandbox.js\";\n\nexport interface AppendSystemPromptOptions {\n\tsubAgentList?: string;\n}\n\nexport function buildAppendSystemPrompt(\n\tworkspacePath: string,\n\tchannelId: string,\n\tsandboxConfig: SandboxConfig,\n\toptions: AppendSystemPromptOptions = {},\n): string {\n\tconst channelPath = `${workspacePath}/${channelId}`;\n\tconst subAgentsPath = `${workspacePath}/sub-agents`;\n\tconst isDocker = sandboxConfig.type === \"docker\";\n\n\tconst envDescription = isDocker\n\t\t? `You are running inside a Docker container (Alpine Linux).\n- Bash working directory: / (use cd or absolute paths)\n- Install tools with: apk add <package>\n- Your changes persist across sessions`\n\t\t: `You are running directly on the host machine.\n- Bash working directory: ${process.cwd()}\n- Be careful with system modifications`;\n\n\tconst sections: string[] = [];\n\n\tsections.push(`## Pipiclaw Runtime\nYou are running inside Pipiclaw, a DingTalk-oriented runtime built on top of pi.\n\n## Context\n- For current date/time, use: date\n- You have access to the active session context for this session.\n- Raw transcript files are cold storage. Do not assume they are preloaded.\n\n## Formatting\nUse Markdown for formatting. DingTalk AI Card supports basic Markdown:\nBold: **text**, Italic: *text*, Code: \\`code\\`, Block: \\`\\`\\`code\\`\\`\\`, Links: [text](url)\n\n## Environment\n${envDescription}\n\n## Workspace Layout\n${workspacePath}/\n├── SOUL.md # Your identity/personality (read-only)\n├── AGENTS.md # Custom behavior instructions (read-only)\n├── MEMORY.md # Stable workspace memory (admin-managed, read on demand)\n├── sub-agents/ # Predefined sub-agent definitions\n├── skills/ # Global CLI tools you create\n├── events/ # Scheduled events\n└── ${channelId}/ # This channel\n ├── MEMORY.md # Channel durable memory (read on demand, runtime-managed)\n ├── HISTORY.md # Channel summarized history (read on demand, runtime-managed)\n ├── log.jsonl # Raw message archive (cold storage)\n ├── context.jsonl # Raw session archive (cold storage)\n ├── scratch/ # Your working directory\n └── skills/ # Channel-specific tools`);\n\n\tsections.push(`## Events\nYou can schedule events that wake you up at specific times or when external things happen. Events are JSON files in \\`${workspacePath}/events/\\`.\n\n### Event Types\n\n**Immediate** - Triggers as soon as harness sees the file.\n\\`\\`\\`json\n{\"type\": \"immediate\", \"channelId\": \"${channelId}\", \"text\": \"New event occurred\"}\n\\`\\`\\`\n\n**One-shot** - Triggers once at a specific time.\n\\`\\`\\`json\n{\"type\": \"one-shot\", \"channelId\": \"${channelId}\", \"text\": \"Reminder\", \"at\": \"2025-12-15T09:00:00+08:00\"}\n\\`\\`\\`\n\n**Periodic** - Triggers on a cron schedule.\n\\`\\`\\`json\n{\"type\": \"periodic\", \"channelId\": \"${channelId}\", \"text\": \"Check inbox\", \"schedule\": \"0 9 * * 1-5\", \"timezone\": \"${Intl.DateTimeFormat().resolvedOptions().timeZone}\"}\n\\`\\`\\`\n\n### Cron Format\n\\`minute hour day-of-month month day-of-week\\`\n\n### Creating Events\nCreate a JSON file under \\`${workspacePath}/events/\\` with the appropriate event payload.\nPrefer the file tools for creating or editing the event file. Use shell commands only when they are the clearest option.\n\n### Silent Completion\nFor periodic events where there's nothing to report, respond with just \\`[SILENT]\\`. This deletes the status message. Use this to avoid spam when periodic checks find nothing.\n\n### Limits\nMaximum 5 events can be queued.`);\n\n\tsections.push(`## Memory\nMemory files are not preloaded into session context. Read them explicitly when memory or history matters.\n\n### Files\n- Workspace memory: ${workspacePath}/MEMORY.md\n Stable shared background memory. Admin-managed. Read on demand.\n- Channel memory: ${channelPath}/MEMORY.md\n Durable channel memory. Runtime-managed via consolidation. You may update this file manually when necessary.\n- Channel history: ${channelPath}/HISTORY.md\n Summarized older channel history. Runtime-managed. Read on demand. Do not maintain this file manually during normal work.\n\n### Runtime Behavior\n- The runtime automatically consolidates channel MEMORY.md and HISTORY.md before compaction or session trimming.\n- Workspace MEMORY.md is not updated by normal runtime consolidation.\n\n### Cold Storage\n- ${channelPath}/log.jsonl is a raw archive. It is not normal memory and is not proactively loaded.\n- ${channelPath}/context.jsonl is a raw session archive. It is not normal memory and is not proactively loaded.\n\nWhen a task depends on prior decisions, preferences, or long-running work, read channel MEMORY.md and HISTORY.md first.`);\n\n\tsections.push(`## System Configuration Log\nMaintain ${workspacePath}/SYSTEM.md to log all environment modifications:\n- Installed packages (apk add, npm install, pip install)\n- Environment variables set\n- Config files modified\n- Skill dependencies installed\n\nUpdate this file whenever you modify the environment.`);\n\n\tsections.push(`## Tools\n- read: Read files\n- edit: Surgical file edits\n- write: Create or overwrite files when needed\n- bash: Run shell commands and external programs\n- subagent: Delegate a focused task to a sub-agent with its own isolated context\n\nEach tool requires a \"label\" parameter (shown to user).`);\n\n\tsections.push(`## Sub-Agents\nYou have a \\`subagent\\` tool for delegating focused work to a separate agent with an isolated context window.\n\n### Predefined Sub-Agents\nPredefined sub-agent definitions live in \\`${subAgentsPath}/\\`.\n${options.subAgentList ? `Available predefined sub-agents:\\n${options.subAgentList}` : \"Available predefined sub-agents: none\"}\n\n### Temporary Inline Sub-Agents\nIf no predefined sub-agent fits, you may define a temporary inline sub-agent directly in the \\`subagent\\` tool call by providing a focused \\`systemPrompt\\` plus optional tools, model, and budget settings.\n\nUse sub-agents when:\n- The task can be decomposed into a focused sub-problem\n- You need a fresh context for heavy file reading, shell work, or review\n- A specialized role would produce better results\n- The main conversation has grown long and you want to offload a bounded task\n\nDo not use sub-agents when:\n- The task is simple and direct\n- The task depends heavily on the full current conversation state\n- The task requires frequent user confirmation\n\nImportant rules:\n- Sub-agents cannot see your conversation history unless you include the needed context in \\`task\\`\n- Sub-agents do not receive the \\`subagent\\` tool, so they cannot create nested agents\n- Prefer predefined sub-agents when one clearly fits\n- Use temporary inline sub-agents only when that extra flexibility is genuinely useful`);\n\n\treturn sections.join(\"\\n\\n\");\n}\n"]}
1
+ {"version":3,"file":"prompt-builder.d.ts","sourceRoot":"","sources":["../src/prompt-builder.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAElD,MAAM,WAAW,yBAAyB;IACzC,YAAY,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,wBAAgB,uBAAuB,CACtC,aAAa,EAAE,MAAM,EACrB,SAAS,EAAE,MAAM,EACjB,aAAa,EAAE,aAAa,EAC5B,OAAO,GAAE,yBAA8B,GACrC,MAAM,CAoJR","sourcesContent":["import type { SandboxConfig } from \"./sandbox.js\";\n\nexport interface AppendSystemPromptOptions {\n\tsubAgentList?: string;\n}\n\nexport function buildAppendSystemPrompt(\n\tworkspacePath: string,\n\tchannelId: string,\n\tsandboxConfig: SandboxConfig,\n\toptions: AppendSystemPromptOptions = {},\n): string {\n\tconst channelPath = `${workspacePath}/${channelId}`;\n\tconst subAgentsPath = `${workspacePath}/sub-agents`;\n\tconst isDocker = sandboxConfig.type === \"docker\";\n\n\tconst envDescription = isDocker\n\t\t? `You are running inside a Docker container (Alpine Linux).\n- Bash working directory: / (use cd or absolute paths)\n- Install tools with: apk add <package>\n- Your changes persist across sessions`\n\t\t: `You are running directly on the host machine.\n- Bash working directory: ${process.cwd()}\n- Be careful with system modifications`;\n\n\tconst sections: string[] = [];\n\n\tsections.push(`## Pipiclaw Runtime\nYou are running inside Pipiclaw, a DingTalk-oriented runtime built on top of pi.\n\n## Context\n- For current date/time, use: date\n- You have access to the active session context for this session.\n- Raw transcript files are cold storage. Do not assume they are preloaded.\n\n## Formatting\nUse Markdown for formatting. DingTalk AI Card supports basic Markdown:\nBold: **text**, Italic: *text*, Code: \\`code\\`, Block: \\`\\`\\`code\\`\\`\\`, Links: [text](url)\n\n## Environment\n${envDescription}\n\n## Workspace Layout\n${workspacePath}/\n├── SOUL.md # Your identity/personality (read-only)\n├── AGENTS.md # Custom behavior instructions (read-only)\n├── MEMORY.md # Stable workspace memory (admin-managed, read on demand)\n├── sub-agents/ # Predefined sub-agent definitions\n├── skills/ # Global CLI tools you create\n├── events/ # Scheduled events\n└── ${channelId}/ # This channel\n ├── MEMORY.md # Channel durable memory (read on demand, runtime-managed)\n ├── HISTORY.md # Channel summarized history (read on demand, runtime-managed)\n ├── log.jsonl # Raw message archive (cold storage)\n ├── context.jsonl # Raw session archive (cold storage)\n ├── scratch/ # Your working directory\n └── skills/ # Channel-specific tools`);\n\n\tsections.push(`## Events\nYou can schedule events that wake you up at specific times or when external things happen. Events are JSON files in \\`${workspacePath}/events/\\`.\n\n### Event Types\n\n**Immediate** - Triggers as soon as harness sees the file.\n\\`\\`\\`json\n{\"type\": \"immediate\", \"channelId\": \"${channelId}\", \"text\": \"New event occurred\"}\n\\`\\`\\`\n\n**One-shot** - Triggers once at a specific time.\n\\`\\`\\`json\n{\"type\": \"one-shot\", \"channelId\": \"${channelId}\", \"text\": \"Reminder\", \"at\": \"2025-12-15T09:00:00+08:00\"}\n\\`\\`\\`\n\n**Periodic** - Triggers on a cron schedule.\n\\`\\`\\`json\n{\"type\": \"periodic\", \"channelId\": \"${channelId}\", \"text\": \"Check inbox\", \"schedule\": \"0 9 * * 1-5\", \"timezone\": \"${Intl.DateTimeFormat().resolvedOptions().timeZone}\"}\n\\`\\`\\`\n\n### Cron Format\n\\`minute hour day-of-month month day-of-week\\`\n\n### Creating Events\nCreate a JSON file under \\`${workspacePath}/events/\\` with the appropriate event payload.\nPrefer the file tools for creating or editing the event file. Use shell commands only when they are the clearest option.\n\n### Silent Completion\nFor periodic events where there's nothing to report, respond with just \\`[SILENT]\\`. This deletes the status message. Use this to avoid spam when periodic checks find nothing.\n\n### Limits\nMaximum 5 events can be queued.`);\n\n\tsections.push(`## Memory\nMemory files are not preloaded into session context. Read them explicitly when memory or history matters.\n\n### Files\n- Workspace memory: ${workspacePath}/MEMORY.md\n Stable shared background memory. Admin-managed. Read on demand.\n- Channel memory: ${channelPath}/MEMORY.md\n Durable channel memory. Runtime-managed via consolidation. You may update this file manually when necessary.\n- Channel history: ${channelPath}/HISTORY.md\n Summarized older channel history. Runtime-managed. Read on demand. Do not maintain this file manually during normal work.\n\n### Runtime Behavior\n- The runtime automatically consolidates channel MEMORY.md and HISTORY.md before compaction or session trimming.\n- Workspace MEMORY.md is not updated by normal runtime consolidation.\n\n### Cold Storage\n- ${channelPath}/log.jsonl is a raw archive. It is not normal memory and is not proactively loaded.\n- ${channelPath}/context.jsonl is a raw session archive. It is not normal memory and is not proactively loaded.\n\nWhen a task depends on prior decisions, preferences, or long-running work, read channel MEMORY.md and HISTORY.md first.`);\n\n\tsections.push(`## System Configuration Log\nMaintain ${workspacePath}/SYSTEM.md to log all environment modifications:\n- Installed packages (apk add, npm install, pip install)\n- Environment variables set\n- Config files modified\n- Skill dependencies installed\n\nUpdate this file whenever you modify the environment.`);\n\n\tsections.push(`## Tools\n- read: Read files\n- edit: Surgical file edits\n- write: Create or overwrite files when needed\n- bash: Run shell commands and external programs\n- subagent: Delegate a focused task to a sub-agent with its own isolated context\n\nEach tool requires a \"label\" parameter (shown to user).`);\n\n\tsections.push(`## Sub-Agents\nYou have a \\`subagent\\` tool for delegating focused work to a separate agent with an isolated context window.\n\n### Predefined Sub-Agents\nPredefined sub-agent definitions live in \\`${subAgentsPath}/\\`.\n${options.subAgentList ? `Available predefined sub-agents:\\n${options.subAgentList}` : \"Available predefined sub-agents: none\"}\n\n### Temporary Inline Sub-Agents\nIf no predefined sub-agent fits, you may define a temporary inline sub-agent directly in the \\`subagent\\` tool call by providing a focused \\`systemPrompt\\` plus optional tools, model, and budget settings.\n\nUse sub-agents when:\n- The task can be decomposed into a focused sub-problem\n- You need a fresh context for heavy file reading, shell work, or review\n- A specialized role would produce better results\n- The main conversation has grown long and you want to offload a bounded task\n\nDo not use sub-agents when:\n- The task is simple and direct\n- The task depends heavily on the full current conversation state\n- The task requires frequent user confirmation\n\nImportant rules:\n- Sub-agents cannot see your conversation history unless you include the needed context in \\`task\\`\n- The runtime injects a small fixed execution context (workspace path, channel id, sandbox), but you must still include task-specific context yourself\n- Sub-agents do not receive the \\`subagent\\` tool, so they cannot create nested agents\n- Prefer predefined sub-agents when one clearly fits\n- Use temporary inline sub-agents only when that extra flexibility is genuinely useful`);\n\n\treturn sections.join(\"\\n\\n\");\n}\n"]}
@@ -132,6 +132,7 @@ Do not use sub-agents when:
132
132
 
133
133
  Important rules:
134
134
  - Sub-agents cannot see your conversation history unless you include the needed context in \`task\`
135
+ - The runtime injects a small fixed execution context (workspace path, channel id, sandbox), but you must still include task-specific context yourself
135
136
  - Sub-agents do not receive the \`subagent\` tool, so they cannot create nested agents
136
137
  - Prefer predefined sub-agents when one clearly fits
137
138
  - Use temporary inline sub-agents only when that extra flexibility is genuinely useful`);
@@ -1 +1 @@
1
- {"version":3,"file":"prompt-builder.js","sourceRoot":"","sources":["../src/prompt-builder.ts"],"names":[],"mappings":"AAMA,MAAM,UAAU,uBAAuB,CACtC,aAAqB,EACrB,SAAiB,EACjB,aAA4B,EAC5B,OAAO,GAA8B,EAAE,EAC9B;IACT,MAAM,WAAW,GAAG,GAAG,aAAa,IAAI,SAAS,EAAE,CAAC;IACpD,MAAM,aAAa,GAAG,GAAG,aAAa,aAAa,CAAC;IACpD,MAAM,QAAQ,GAAG,aAAa,CAAC,IAAI,KAAK,QAAQ,CAAC;IAEjD,MAAM,cAAc,GAAG,QAAQ;QAC9B,CAAC,CAAC;;;uCAGmC;QACrC,CAAC,CAAC;4BACwB,OAAO,CAAC,GAAG,EAAE;uCACF,CAAC;IAEvC,MAAM,QAAQ,GAAa,EAAE,CAAC;IAE9B,QAAQ,CAAC,IAAI,CAAC;;;;;;;;;;;;;EAab,cAAc;;;EAGd,aAAa;;;;;;;YAOT,SAAS;;;;;;gEAM2C,CAAC,CAAC;IAE3D,QAAQ,CAAC,IAAI,CAAC;wHACyG,aAAa;;;;;;sCAM/F,SAAS;;;;;qCAKV,SAAS;;;;;qCAKT,SAAS,qEAAqE,IAAI,CAAC,cAAc,EAAE,CAAC,eAAe,EAAE,CAAC,QAAQ;;;;;;;6BAOtI,aAAa;;;;;;;gCAOV,CAAC,CAAC;IAEjC,QAAQ,CAAC,IAAI,CAAC;;;;sBAIO,aAAa;;oBAEf,WAAW;;qBAEV,WAAW;;;;;;;;IAQ5B,WAAW;IACX,WAAW;;wHAEyG,CAAC,CAAC;IAEzH,QAAQ,CAAC,IAAI,CAAC;WACJ,aAAa;;;;;;sDAM8B,CAAC,CAAC;IAEvD,QAAQ,CAAC,IAAI,CAAC;;;;;;;wDAOyC,CAAC,CAAC;IAEzD,QAAQ,CAAC,IAAI,CAAC;;;;6CAI8B,aAAa;EACxD,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,qCAAqC,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC,uCAAuC;;;;;;;;;;;;;;;;;;;;uFAoBvC,CAAC,CAAC;IAExF,OAAO,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AAAA,CAC7B","sourcesContent":["import type { SandboxConfig } from \"./sandbox.js\";\n\nexport interface AppendSystemPromptOptions {\n\tsubAgentList?: string;\n}\n\nexport function buildAppendSystemPrompt(\n\tworkspacePath: string,\n\tchannelId: string,\n\tsandboxConfig: SandboxConfig,\n\toptions: AppendSystemPromptOptions = {},\n): string {\n\tconst channelPath = `${workspacePath}/${channelId}`;\n\tconst subAgentsPath = `${workspacePath}/sub-agents`;\n\tconst isDocker = sandboxConfig.type === \"docker\";\n\n\tconst envDescription = isDocker\n\t\t? `You are running inside a Docker container (Alpine Linux).\n- Bash working directory: / (use cd or absolute paths)\n- Install tools with: apk add <package>\n- Your changes persist across sessions`\n\t\t: `You are running directly on the host machine.\n- Bash working directory: ${process.cwd()}\n- Be careful with system modifications`;\n\n\tconst sections: string[] = [];\n\n\tsections.push(`## Pipiclaw Runtime\nYou are running inside Pipiclaw, a DingTalk-oriented runtime built on top of pi.\n\n## Context\n- For current date/time, use: date\n- You have access to the active session context for this session.\n- Raw transcript files are cold storage. Do not assume they are preloaded.\n\n## Formatting\nUse Markdown for formatting. DingTalk AI Card supports basic Markdown:\nBold: **text**, Italic: *text*, Code: \\`code\\`, Block: \\`\\`\\`code\\`\\`\\`, Links: [text](url)\n\n## Environment\n${envDescription}\n\n## Workspace Layout\n${workspacePath}/\n├── SOUL.md # Your identity/personality (read-only)\n├── AGENTS.md # Custom behavior instructions (read-only)\n├── MEMORY.md # Stable workspace memory (admin-managed, read on demand)\n├── sub-agents/ # Predefined sub-agent definitions\n├── skills/ # Global CLI tools you create\n├── events/ # Scheduled events\n└── ${channelId}/ # This channel\n ├── MEMORY.md # Channel durable memory (read on demand, runtime-managed)\n ├── HISTORY.md # Channel summarized history (read on demand, runtime-managed)\n ├── log.jsonl # Raw message archive (cold storage)\n ├── context.jsonl # Raw session archive (cold storage)\n ├── scratch/ # Your working directory\n └── skills/ # Channel-specific tools`);\n\n\tsections.push(`## Events\nYou can schedule events that wake you up at specific times or when external things happen. Events are JSON files in \\`${workspacePath}/events/\\`.\n\n### Event Types\n\n**Immediate** - Triggers as soon as harness sees the file.\n\\`\\`\\`json\n{\"type\": \"immediate\", \"channelId\": \"${channelId}\", \"text\": \"New event occurred\"}\n\\`\\`\\`\n\n**One-shot** - Triggers once at a specific time.\n\\`\\`\\`json\n{\"type\": \"one-shot\", \"channelId\": \"${channelId}\", \"text\": \"Reminder\", \"at\": \"2025-12-15T09:00:00+08:00\"}\n\\`\\`\\`\n\n**Periodic** - Triggers on a cron schedule.\n\\`\\`\\`json\n{\"type\": \"periodic\", \"channelId\": \"${channelId}\", \"text\": \"Check inbox\", \"schedule\": \"0 9 * * 1-5\", \"timezone\": \"${Intl.DateTimeFormat().resolvedOptions().timeZone}\"}\n\\`\\`\\`\n\n### Cron Format\n\\`minute hour day-of-month month day-of-week\\`\n\n### Creating Events\nCreate a JSON file under \\`${workspacePath}/events/\\` with the appropriate event payload.\nPrefer the file tools for creating or editing the event file. Use shell commands only when they are the clearest option.\n\n### Silent Completion\nFor periodic events where there's nothing to report, respond with just \\`[SILENT]\\`. This deletes the status message. Use this to avoid spam when periodic checks find nothing.\n\n### Limits\nMaximum 5 events can be queued.`);\n\n\tsections.push(`## Memory\nMemory files are not preloaded into session context. Read them explicitly when memory or history matters.\n\n### Files\n- Workspace memory: ${workspacePath}/MEMORY.md\n Stable shared background memory. Admin-managed. Read on demand.\n- Channel memory: ${channelPath}/MEMORY.md\n Durable channel memory. Runtime-managed via consolidation. You may update this file manually when necessary.\n- Channel history: ${channelPath}/HISTORY.md\n Summarized older channel history. Runtime-managed. Read on demand. Do not maintain this file manually during normal work.\n\n### Runtime Behavior\n- The runtime automatically consolidates channel MEMORY.md and HISTORY.md before compaction or session trimming.\n- Workspace MEMORY.md is not updated by normal runtime consolidation.\n\n### Cold Storage\n- ${channelPath}/log.jsonl is a raw archive. It is not normal memory and is not proactively loaded.\n- ${channelPath}/context.jsonl is a raw session archive. It is not normal memory and is not proactively loaded.\n\nWhen a task depends on prior decisions, preferences, or long-running work, read channel MEMORY.md and HISTORY.md first.`);\n\n\tsections.push(`## System Configuration Log\nMaintain ${workspacePath}/SYSTEM.md to log all environment modifications:\n- Installed packages (apk add, npm install, pip install)\n- Environment variables set\n- Config files modified\n- Skill dependencies installed\n\nUpdate this file whenever you modify the environment.`);\n\n\tsections.push(`## Tools\n- read: Read files\n- edit: Surgical file edits\n- write: Create or overwrite files when needed\n- bash: Run shell commands and external programs\n- subagent: Delegate a focused task to a sub-agent with its own isolated context\n\nEach tool requires a \"label\" parameter (shown to user).`);\n\n\tsections.push(`## Sub-Agents\nYou have a \\`subagent\\` tool for delegating focused work to a separate agent with an isolated context window.\n\n### Predefined Sub-Agents\nPredefined sub-agent definitions live in \\`${subAgentsPath}/\\`.\n${options.subAgentList ? `Available predefined sub-agents:\\n${options.subAgentList}` : \"Available predefined sub-agents: none\"}\n\n### Temporary Inline Sub-Agents\nIf no predefined sub-agent fits, you may define a temporary inline sub-agent directly in the \\`subagent\\` tool call by providing a focused \\`systemPrompt\\` plus optional tools, model, and budget settings.\n\nUse sub-agents when:\n- The task can be decomposed into a focused sub-problem\n- You need a fresh context for heavy file reading, shell work, or review\n- A specialized role would produce better results\n- The main conversation has grown long and you want to offload a bounded task\n\nDo not use sub-agents when:\n- The task is simple and direct\n- The task depends heavily on the full current conversation state\n- The task requires frequent user confirmation\n\nImportant rules:\n- Sub-agents cannot see your conversation history unless you include the needed context in \\`task\\`\n- Sub-agents do not receive the \\`subagent\\` tool, so they cannot create nested agents\n- Prefer predefined sub-agents when one clearly fits\n- Use temporary inline sub-agents only when that extra flexibility is genuinely useful`);\n\n\treturn sections.join(\"\\n\\n\");\n}\n"]}
1
+ {"version":3,"file":"prompt-builder.js","sourceRoot":"","sources":["../src/prompt-builder.ts"],"names":[],"mappings":"AAMA,MAAM,UAAU,uBAAuB,CACtC,aAAqB,EACrB,SAAiB,EACjB,aAA4B,EAC5B,OAAO,GAA8B,EAAE,EAC9B;IACT,MAAM,WAAW,GAAG,GAAG,aAAa,IAAI,SAAS,EAAE,CAAC;IACpD,MAAM,aAAa,GAAG,GAAG,aAAa,aAAa,CAAC;IACpD,MAAM,QAAQ,GAAG,aAAa,CAAC,IAAI,KAAK,QAAQ,CAAC;IAEjD,MAAM,cAAc,GAAG,QAAQ;QAC9B,CAAC,CAAC;;;uCAGmC;QACrC,CAAC,CAAC;4BACwB,OAAO,CAAC,GAAG,EAAE;uCACF,CAAC;IAEvC,MAAM,QAAQ,GAAa,EAAE,CAAC;IAE9B,QAAQ,CAAC,IAAI,CAAC;;;;;;;;;;;;;EAab,cAAc;;;EAGd,aAAa;;;;;;;YAOT,SAAS;;;;;;gEAM2C,CAAC,CAAC;IAE3D,QAAQ,CAAC,IAAI,CAAC;wHACyG,aAAa;;;;;;sCAM/F,SAAS;;;;;qCAKV,SAAS;;;;;qCAKT,SAAS,qEAAqE,IAAI,CAAC,cAAc,EAAE,CAAC,eAAe,EAAE,CAAC,QAAQ;;;;;;;6BAOtI,aAAa;;;;;;;gCAOV,CAAC,CAAC;IAEjC,QAAQ,CAAC,IAAI,CAAC;;;;sBAIO,aAAa;;oBAEf,WAAW;;qBAEV,WAAW;;;;;;;;IAQ5B,WAAW;IACX,WAAW;;wHAEyG,CAAC,CAAC;IAEzH,QAAQ,CAAC,IAAI,CAAC;WACJ,aAAa;;;;;;sDAM8B,CAAC,CAAC;IAEvD,QAAQ,CAAC,IAAI,CAAC;;;;;;;wDAOyC,CAAC,CAAC;IAEzD,QAAQ,CAAC,IAAI,CAAC;;;;6CAI8B,aAAa;EACxD,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,qCAAqC,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC,uCAAuC;;;;;;;;;;;;;;;;;;;;;uFAqBvC,CAAC,CAAC;IAExF,OAAO,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AAAA,CAC7B","sourcesContent":["import type { SandboxConfig } from \"./sandbox.js\";\n\nexport interface AppendSystemPromptOptions {\n\tsubAgentList?: string;\n}\n\nexport function buildAppendSystemPrompt(\n\tworkspacePath: string,\n\tchannelId: string,\n\tsandboxConfig: SandboxConfig,\n\toptions: AppendSystemPromptOptions = {},\n): string {\n\tconst channelPath = `${workspacePath}/${channelId}`;\n\tconst subAgentsPath = `${workspacePath}/sub-agents`;\n\tconst isDocker = sandboxConfig.type === \"docker\";\n\n\tconst envDescription = isDocker\n\t\t? `You are running inside a Docker container (Alpine Linux).\n- Bash working directory: / (use cd or absolute paths)\n- Install tools with: apk add <package>\n- Your changes persist across sessions`\n\t\t: `You are running directly on the host machine.\n- Bash working directory: ${process.cwd()}\n- Be careful with system modifications`;\n\n\tconst sections: string[] = [];\n\n\tsections.push(`## Pipiclaw Runtime\nYou are running inside Pipiclaw, a DingTalk-oriented runtime built on top of pi.\n\n## Context\n- For current date/time, use: date\n- You have access to the active session context for this session.\n- Raw transcript files are cold storage. Do not assume they are preloaded.\n\n## Formatting\nUse Markdown for formatting. DingTalk AI Card supports basic Markdown:\nBold: **text**, Italic: *text*, Code: \\`code\\`, Block: \\`\\`\\`code\\`\\`\\`, Links: [text](url)\n\n## Environment\n${envDescription}\n\n## Workspace Layout\n${workspacePath}/\n├── SOUL.md # Your identity/personality (read-only)\n├── AGENTS.md # Custom behavior instructions (read-only)\n├── MEMORY.md # Stable workspace memory (admin-managed, read on demand)\n├── sub-agents/ # Predefined sub-agent definitions\n├── skills/ # Global CLI tools you create\n├── events/ # Scheduled events\n└── ${channelId}/ # This channel\n ├── MEMORY.md # Channel durable memory (read on demand, runtime-managed)\n ├── HISTORY.md # Channel summarized history (read on demand, runtime-managed)\n ├── log.jsonl # Raw message archive (cold storage)\n ├── context.jsonl # Raw session archive (cold storage)\n ├── scratch/ # Your working directory\n └── skills/ # Channel-specific tools`);\n\n\tsections.push(`## Events\nYou can schedule events that wake you up at specific times or when external things happen. Events are JSON files in \\`${workspacePath}/events/\\`.\n\n### Event Types\n\n**Immediate** - Triggers as soon as harness sees the file.\n\\`\\`\\`json\n{\"type\": \"immediate\", \"channelId\": \"${channelId}\", \"text\": \"New event occurred\"}\n\\`\\`\\`\n\n**One-shot** - Triggers once at a specific time.\n\\`\\`\\`json\n{\"type\": \"one-shot\", \"channelId\": \"${channelId}\", \"text\": \"Reminder\", \"at\": \"2025-12-15T09:00:00+08:00\"}\n\\`\\`\\`\n\n**Periodic** - Triggers on a cron schedule.\n\\`\\`\\`json\n{\"type\": \"periodic\", \"channelId\": \"${channelId}\", \"text\": \"Check inbox\", \"schedule\": \"0 9 * * 1-5\", \"timezone\": \"${Intl.DateTimeFormat().resolvedOptions().timeZone}\"}\n\\`\\`\\`\n\n### Cron Format\n\\`minute hour day-of-month month day-of-week\\`\n\n### Creating Events\nCreate a JSON file under \\`${workspacePath}/events/\\` with the appropriate event payload.\nPrefer the file tools for creating or editing the event file. Use shell commands only when they are the clearest option.\n\n### Silent Completion\nFor periodic events where there's nothing to report, respond with just \\`[SILENT]\\`. This deletes the status message. Use this to avoid spam when periodic checks find nothing.\n\n### Limits\nMaximum 5 events can be queued.`);\n\n\tsections.push(`## Memory\nMemory files are not preloaded into session context. Read them explicitly when memory or history matters.\n\n### Files\n- Workspace memory: ${workspacePath}/MEMORY.md\n Stable shared background memory. Admin-managed. Read on demand.\n- Channel memory: ${channelPath}/MEMORY.md\n Durable channel memory. Runtime-managed via consolidation. You may update this file manually when necessary.\n- Channel history: ${channelPath}/HISTORY.md\n Summarized older channel history. Runtime-managed. Read on demand. Do not maintain this file manually during normal work.\n\n### Runtime Behavior\n- The runtime automatically consolidates channel MEMORY.md and HISTORY.md before compaction or session trimming.\n- Workspace MEMORY.md is not updated by normal runtime consolidation.\n\n### Cold Storage\n- ${channelPath}/log.jsonl is a raw archive. It is not normal memory and is not proactively loaded.\n- ${channelPath}/context.jsonl is a raw session archive. It is not normal memory and is not proactively loaded.\n\nWhen a task depends on prior decisions, preferences, or long-running work, read channel MEMORY.md and HISTORY.md first.`);\n\n\tsections.push(`## System Configuration Log\nMaintain ${workspacePath}/SYSTEM.md to log all environment modifications:\n- Installed packages (apk add, npm install, pip install)\n- Environment variables set\n- Config files modified\n- Skill dependencies installed\n\nUpdate this file whenever you modify the environment.`);\n\n\tsections.push(`## Tools\n- read: Read files\n- edit: Surgical file edits\n- write: Create or overwrite files when needed\n- bash: Run shell commands and external programs\n- subagent: Delegate a focused task to a sub-agent with its own isolated context\n\nEach tool requires a \"label\" parameter (shown to user).`);\n\n\tsections.push(`## Sub-Agents\nYou have a \\`subagent\\` tool for delegating focused work to a separate agent with an isolated context window.\n\n### Predefined Sub-Agents\nPredefined sub-agent definitions live in \\`${subAgentsPath}/\\`.\n${options.subAgentList ? `Available predefined sub-agents:\\n${options.subAgentList}` : \"Available predefined sub-agents: none\"}\n\n### Temporary Inline Sub-Agents\nIf no predefined sub-agent fits, you may define a temporary inline sub-agent directly in the \\`subagent\\` tool call by providing a focused \\`systemPrompt\\` plus optional tools, model, and budget settings.\n\nUse sub-agents when:\n- The task can be decomposed into a focused sub-problem\n- You need a fresh context for heavy file reading, shell work, or review\n- A specialized role would produce better results\n- The main conversation has grown long and you want to offload a bounded task\n\nDo not use sub-agents when:\n- The task is simple and direct\n- The task depends heavily on the full current conversation state\n- The task requires frequent user confirmation\n\nImportant rules:\n- Sub-agents cannot see your conversation history unless you include the needed context in \\`task\\`\n- The runtime injects a small fixed execution context (workspace path, channel id, sandbox), but you must still include task-specific context yourself\n- Sub-agents do not receive the \\`subagent\\` tool, so they cannot create nested agents\n- Prefer predefined sub-agents when one clearly fits\n- Use temporary inline sub-agents only when that extra flexibility is genuinely useful`);\n\n\treturn sections.join(\"\\n\\n\");\n}\n"]}
package/dist/store.d.ts CHANGED
@@ -12,6 +12,36 @@ export interface LoggedMessage {
12
12
  export interface ChannelStoreConfig {
13
13
  workingDir: string;
14
14
  }
15
+ export interface LoggedSubAgentRun {
16
+ date: string;
17
+ toolCallId: string;
18
+ label: string;
19
+ agent: string;
20
+ source: "predefined" | "inline";
21
+ model: string;
22
+ tools: string[];
23
+ turns: number;
24
+ toolCalls: number;
25
+ durationMs: number;
26
+ failed: boolean;
27
+ failureReason?: string;
28
+ output: string;
29
+ outputTruncated: boolean;
30
+ usage: {
31
+ input: number;
32
+ output: number;
33
+ cacheRead: number;
34
+ cacheWrite: number;
35
+ total: number;
36
+ cost: {
37
+ input: number;
38
+ output: number;
39
+ cacheRead: number;
40
+ cacheWrite: number;
41
+ total: number;
42
+ };
43
+ };
44
+ }
15
45
  export declare class ChannelStore {
16
46
  private workingDir;
17
47
  private recentlyLogged;
@@ -26,6 +56,7 @@ export declare class ChannelStore {
26
56
  * Returns false if message was already logged (duplicate)
27
57
  */
28
58
  logMessage(channelId: string, message: LoggedMessage): Promise<boolean>;
59
+ logSubAgentRun(channelId: string, run: LoggedSubAgentRun): Promise<void>;
29
60
  /**
30
61
  * Rotate log file if it exceeds 1MB.
31
62
  * Keeps one backup (log.jsonl.1) and resets the sync offset.
@@ -1 +1 @@
1
- {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,aAAa;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,OAAO,CAAC;IACf,YAAY,CAAC,EAAE,OAAO,GAAG,UAAU,CAAC;IACpC,eAAe,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,MAAM,WAAW,kBAAkB;IAClC,UAAU,EAAE,MAAM,CAAC;CACnB;AAED,qBAAa,YAAY;IACxB,OAAO,CAAC,UAAU,CAAS;IAE3B,OAAO,CAAC,cAAc,CAA6B;IAEnD,YAAY,MAAM,EAAE,kBAAkB,EAOrC;IAED;;OAEG;IACH,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAMvC;IAED;;;;OAIG;IACG,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,OAAO,CAAC,CAwB5E;IAED;;;OAGG;IACH,OAAO,CAAC,cAAc;IAmBtB;;OAEG;IACG,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAQ/E;IAED;;;OAGG;IACH,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAiEjD;CACD","sourcesContent":["import { closeSync, existsSync, mkdirSync, openSync, readSync, renameSync, statSync } from \"fs\";\nimport { appendFile, writeFile } from \"fs/promises\";\nimport { dirname, join } from \"path\";\n\nexport interface LoggedMessage {\n\tdate: string;\n\tts: string;\n\tuser: string;\n\tuserName?: string;\n\tdisplayName?: string;\n\ttext: string;\n\tisBot: boolean;\n\tdeliveryMode?: \"steer\" | \"followUp\";\n\tskipContextSync?: boolean;\n}\n\nexport interface ChannelStoreConfig {\n\tworkingDir: string;\n}\n\nexport class ChannelStore {\n\tprivate workingDir: string;\n\t// Track recently logged message timestamps to prevent duplicates\n\tprivate recentlyLogged = new Map<string, number>();\n\n\tconstructor(config: ChannelStoreConfig) {\n\t\tthis.workingDir = config.workingDir;\n\n\t\t// Ensure working directory exists\n\t\tif (!existsSync(this.workingDir)) {\n\t\t\tmkdirSync(this.workingDir, { recursive: true });\n\t\t}\n\t}\n\n\t/**\n\t * Get or create the directory for a channel/DM\n\t */\n\tgetChannelDir(channelId: string): string {\n\t\tconst dir = join(this.workingDir, channelId);\n\t\tif (!existsSync(dir)) {\n\t\t\tmkdirSync(dir, { recursive: true });\n\t\t}\n\t\treturn dir;\n\t}\n\n\t/**\n\t * Log a message to the channel's log.jsonl raw archive.\n\t * This file is cold storage and is not proactively loaded into memory context.\n\t * Returns false if message was already logged (duplicate)\n\t */\n\tasync logMessage(channelId: string, message: LoggedMessage): Promise<boolean> {\n\t\t// Check for duplicate (same channel + timestamp)\n\t\tconst dedupeKey = `${channelId}:${message.ts}`;\n\t\tif (this.recentlyLogged.has(dedupeKey)) {\n\t\t\treturn false; // Already logged\n\t\t}\n\n\t\t// Mark as logged and schedule cleanup after 60 seconds\n\t\tthis.recentlyLogged.set(dedupeKey, Date.now());\n\t\tsetTimeout(() => this.recentlyLogged.delete(dedupeKey), 60000);\n\n\t\tconst logPath = join(this.getChannelDir(channelId), \"log.jsonl\");\n\n\t\t// Rotate if file exceeds size limit\n\t\tthis.rotateIfNeeded(logPath);\n\n\t\t// Ensure message has a date field\n\t\tif (!message.date) {\n\t\t\tmessage.date = new Date().toISOString();\n\t\t}\n\n\t\tconst line = `${JSON.stringify(message)}\\n`;\n\t\tawait appendFile(logPath, line, \"utf-8\");\n\t\treturn true;\n\t}\n\n\t/**\n\t * Rotate log file if it exceeds 1MB.\n\t * Keeps one backup (log.jsonl.1) and resets the sync offset.\n\t */\n\tprivate rotateIfNeeded(logPath: string): void {\n\t\ttry {\n\t\t\tif (!existsSync(logPath)) return;\n\t\t\tconst stats = statSync(logPath);\n\t\t\tif (stats.size > 1_000_000) {\n\t\t\t\trenameSync(logPath, `${logPath}.1`);\n\t\t\t\t// Reset sync offset since log.jsonl was replaced\n\t\t\t\tconst syncOffsetPath = join(dirname(logPath), \".sync-offset\");\n\t\t\t\ttry {\n\t\t\t\t\twriteFile(syncOffsetPath, \"0\", \"utf-8\").catch(() => {});\n\t\t\t\t} catch {\n\t\t\t\t\t/* ignore */\n\t\t\t\t}\n\t\t\t}\n\t\t} catch {\n\t\t\t// Ignore rotation errors\n\t\t}\n\t}\n\n\t/**\n\t * Log a bot response\n\t */\n\tasync logBotResponse(channelId: string, text: string, ts: string): Promise<void> {\n\t\tawait this.logMessage(channelId, {\n\t\t\tdate: new Date().toISOString(),\n\t\t\tts,\n\t\t\tuser: \"bot\",\n\t\t\ttext,\n\t\t\tisBot: true,\n\t\t});\n\t}\n\n\t/**\n\t * Get the timestamp of the last logged message for a channel\n\t * Returns null if no log exists\n\t */\n\tgetLastTimestamp(channelId: string): string | null {\n\t\tconst logPath = join(this.workingDir, channelId, \"log.jsonl\");\n\t\tif (!existsSync(logPath)) {\n\t\t\treturn null;\n\t\t}\n\n\t\ttry {\n\t\t\tconst stats = statSync(logPath);\n\t\t\tif (stats.size === 0) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tconst fd = openSync(logPath, \"r\");\n\t\t\ttry {\n\t\t\t\tlet end = stats.size;\n\t\t\t\tconst trailing = Buffer.alloc(1);\n\t\t\t\twhile (end > 0) {\n\t\t\t\t\treadSync(fd, trailing, 0, 1, end - 1);\n\t\t\t\t\tif (trailing[0] !== 0x0a && trailing[0] !== 0x0d) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tend--;\n\t\t\t\t}\n\n\t\t\t\tif (end === 0) {\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\n\t\t\t\tconst chunkSize = 4096;\n\t\t\t\tconst buffer = Buffer.alloc(chunkSize);\n\t\t\t\tlet lineStart = 0;\n\t\t\t\tlet position = end;\n\n\t\t\t\twhile (position > 0) {\n\t\t\t\t\tconst bytesToRead = Math.min(chunkSize, position);\n\t\t\t\t\tposition -= bytesToRead;\n\t\t\t\t\treadSync(fd, buffer, 0, bytesToRead, position);\n\n\t\t\t\t\tconst newlineIndex = buffer.subarray(0, bytesToRead).lastIndexOf(0x0a);\n\t\t\t\t\tif (newlineIndex !== -1) {\n\t\t\t\t\t\tlineStart = position + newlineIndex + 1;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconst lineLength = end - lineStart;\n\t\t\t\tif (lineLength <= 0) {\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\n\t\t\t\tconst lineBuffer = Buffer.alloc(lineLength);\n\t\t\t\treadSync(fd, lineBuffer, 0, lineLength, lineStart);\n\t\t\t\tconst lastLine = lineBuffer.toString(\"utf-8\").replace(/\\r+$/, \"\");\n\t\t\t\tif (!lastLine) {\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\n\t\t\t\tconst message = JSON.parse(lastLine) as LoggedMessage;\n\t\t\t\treturn message.ts;\n\t\t\t} finally {\n\t\t\t\tcloseSync(fd);\n\t\t\t}\n\t\t} catch {\n\t\t\treturn null;\n\t\t}\n\t}\n}\n"]}
1
+ {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,aAAa;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,OAAO,CAAC;IACf,YAAY,CAAC,EAAE,OAAO,GAAG,UAAU,CAAC;IACpC,eAAe,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,MAAM,WAAW,kBAAkB;IAClC,UAAU,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,iBAAiB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,YAAY,GAAG,QAAQ,CAAC;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,OAAO,CAAC;IAChB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,eAAe,EAAE,OAAO,CAAC;IACzB,KAAK,EAAE;QACN,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,MAAM,CAAC;QACf,SAAS,EAAE,MAAM,CAAC;QAClB,UAAU,EAAE,MAAM,CAAC;QACnB,KAAK,EAAE,MAAM,CAAC;QACd,IAAI,EAAE;YACL,KAAK,EAAE,MAAM,CAAC;YACd,MAAM,EAAE,MAAM,CAAC;YACf,SAAS,EAAE,MAAM,CAAC;YAClB,UAAU,EAAE,MAAM,CAAC;YACnB,KAAK,EAAE,MAAM,CAAC;SACd,CAAC;KACF,CAAC;CACF;AAED,qBAAa,YAAY;IACxB,OAAO,CAAC,UAAU,CAAS;IAE3B,OAAO,CAAC,cAAc,CAA6B;IAEnD,YAAY,MAAM,EAAE,kBAAkB,EAOrC;IAED;;OAEG;IACH,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAMvC;IAED;;;;OAIG;IACG,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,OAAO,CAAC,CAwB5E;IAEK,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAK7E;IAED;;;OAGG;IACH,OAAO,CAAC,cAAc;IAmBtB;;OAEG;IACG,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAQ/E;IAED;;;OAGG;IACH,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAiEjD;CACD","sourcesContent":["import { closeSync, existsSync, mkdirSync, openSync, readSync, renameSync, statSync } from \"fs\";\nimport { appendFile, writeFile } from \"fs/promises\";\nimport { dirname, join } from \"path\";\n\nexport interface LoggedMessage {\n\tdate: string;\n\tts: string;\n\tuser: string;\n\tuserName?: string;\n\tdisplayName?: string;\n\ttext: string;\n\tisBot: boolean;\n\tdeliveryMode?: \"steer\" | \"followUp\";\n\tskipContextSync?: boolean;\n}\n\nexport interface ChannelStoreConfig {\n\tworkingDir: string;\n}\n\nexport interface LoggedSubAgentRun {\n\tdate: string;\n\ttoolCallId: string;\n\tlabel: string;\n\tagent: string;\n\tsource: \"predefined\" | \"inline\";\n\tmodel: string;\n\ttools: string[];\n\tturns: number;\n\ttoolCalls: number;\n\tdurationMs: number;\n\tfailed: boolean;\n\tfailureReason?: string;\n\toutput: string;\n\toutputTruncated: boolean;\n\tusage: {\n\t\tinput: number;\n\t\toutput: number;\n\t\tcacheRead: number;\n\t\tcacheWrite: number;\n\t\ttotal: number;\n\t\tcost: {\n\t\t\tinput: number;\n\t\t\toutput: number;\n\t\t\tcacheRead: number;\n\t\t\tcacheWrite: number;\n\t\t\ttotal: number;\n\t\t};\n\t};\n}\n\nexport class ChannelStore {\n\tprivate workingDir: string;\n\t// Track recently logged message timestamps to prevent duplicates\n\tprivate recentlyLogged = new Map<string, number>();\n\n\tconstructor(config: ChannelStoreConfig) {\n\t\tthis.workingDir = config.workingDir;\n\n\t\t// Ensure working directory exists\n\t\tif (!existsSync(this.workingDir)) {\n\t\t\tmkdirSync(this.workingDir, { recursive: true });\n\t\t}\n\t}\n\n\t/**\n\t * Get or create the directory for a channel/DM\n\t */\n\tgetChannelDir(channelId: string): string {\n\t\tconst dir = join(this.workingDir, channelId);\n\t\tif (!existsSync(dir)) {\n\t\t\tmkdirSync(dir, { recursive: true });\n\t\t}\n\t\treturn dir;\n\t}\n\n\t/**\n\t * Log a message to the channel's log.jsonl raw archive.\n\t * This file is cold storage and is not proactively loaded into memory context.\n\t * Returns false if message was already logged (duplicate)\n\t */\n\tasync logMessage(channelId: string, message: LoggedMessage): Promise<boolean> {\n\t\t// Check for duplicate (same channel + timestamp)\n\t\tconst dedupeKey = `${channelId}:${message.ts}`;\n\t\tif (this.recentlyLogged.has(dedupeKey)) {\n\t\t\treturn false; // Already logged\n\t\t}\n\n\t\t// Mark as logged and schedule cleanup after 60 seconds\n\t\tthis.recentlyLogged.set(dedupeKey, Date.now());\n\t\tsetTimeout(() => this.recentlyLogged.delete(dedupeKey), 60000);\n\n\t\tconst logPath = join(this.getChannelDir(channelId), \"log.jsonl\");\n\n\t\t// Rotate if file exceeds size limit\n\t\tthis.rotateIfNeeded(logPath);\n\n\t\t// Ensure message has a date field\n\t\tif (!message.date) {\n\t\t\tmessage.date = new Date().toISOString();\n\t\t}\n\n\t\tconst line = `${JSON.stringify(message)}\\n`;\n\t\tawait appendFile(logPath, line, \"utf-8\");\n\t\treturn true;\n\t}\n\n\tasync logSubAgentRun(channelId: string, run: LoggedSubAgentRun): Promise<void> {\n\t\tconst logPath = join(this.getChannelDir(channelId), \"subagent-runs.jsonl\");\n\t\tthis.rotateIfNeeded(logPath);\n\t\tconst line = `${JSON.stringify(run)}\\n`;\n\t\tawait appendFile(logPath, line, \"utf-8\");\n\t}\n\n\t/**\n\t * Rotate log file if it exceeds 1MB.\n\t * Keeps one backup (log.jsonl.1) and resets the sync offset.\n\t */\n\tprivate rotateIfNeeded(logPath: string): void {\n\t\ttry {\n\t\t\tif (!existsSync(logPath)) return;\n\t\t\tconst stats = statSync(logPath);\n\t\t\tif (stats.size > 1_000_000) {\n\t\t\t\trenameSync(logPath, `${logPath}.1`);\n\t\t\t\t// Reset sync offset since log.jsonl was replaced\n\t\t\t\tconst syncOffsetPath = join(dirname(logPath), \".sync-offset\");\n\t\t\t\ttry {\n\t\t\t\t\twriteFile(syncOffsetPath, \"0\", \"utf-8\").catch(() => {});\n\t\t\t\t} catch {\n\t\t\t\t\t/* ignore */\n\t\t\t\t}\n\t\t\t}\n\t\t} catch {\n\t\t\t// Ignore rotation errors\n\t\t}\n\t}\n\n\t/**\n\t * Log a bot response\n\t */\n\tasync logBotResponse(channelId: string, text: string, ts: string): Promise<void> {\n\t\tawait this.logMessage(channelId, {\n\t\t\tdate: new Date().toISOString(),\n\t\t\tts,\n\t\t\tuser: \"bot\",\n\t\t\ttext,\n\t\t\tisBot: true,\n\t\t});\n\t}\n\n\t/**\n\t * Get the timestamp of the last logged message for a channel\n\t * Returns null if no log exists\n\t */\n\tgetLastTimestamp(channelId: string): string | null {\n\t\tconst logPath = join(this.workingDir, channelId, \"log.jsonl\");\n\t\tif (!existsSync(logPath)) {\n\t\t\treturn null;\n\t\t}\n\n\t\ttry {\n\t\t\tconst stats = statSync(logPath);\n\t\t\tif (stats.size === 0) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tconst fd = openSync(logPath, \"r\");\n\t\t\ttry {\n\t\t\t\tlet end = stats.size;\n\t\t\t\tconst trailing = Buffer.alloc(1);\n\t\t\t\twhile (end > 0) {\n\t\t\t\t\treadSync(fd, trailing, 0, 1, end - 1);\n\t\t\t\t\tif (trailing[0] !== 0x0a && trailing[0] !== 0x0d) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tend--;\n\t\t\t\t}\n\n\t\t\t\tif (end === 0) {\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\n\t\t\t\tconst chunkSize = 4096;\n\t\t\t\tconst buffer = Buffer.alloc(chunkSize);\n\t\t\t\tlet lineStart = 0;\n\t\t\t\tlet position = end;\n\n\t\t\t\twhile (position > 0) {\n\t\t\t\t\tconst bytesToRead = Math.min(chunkSize, position);\n\t\t\t\t\tposition -= bytesToRead;\n\t\t\t\t\treadSync(fd, buffer, 0, bytesToRead, position);\n\n\t\t\t\t\tconst newlineIndex = buffer.subarray(0, bytesToRead).lastIndexOf(0x0a);\n\t\t\t\t\tif (newlineIndex !== -1) {\n\t\t\t\t\t\tlineStart = position + newlineIndex + 1;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconst lineLength = end - lineStart;\n\t\t\t\tif (lineLength <= 0) {\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\n\t\t\t\tconst lineBuffer = Buffer.alloc(lineLength);\n\t\t\t\treadSync(fd, lineBuffer, 0, lineLength, lineStart);\n\t\t\t\tconst lastLine = lineBuffer.toString(\"utf-8\").replace(/\\r+$/, \"\");\n\t\t\t\tif (!lastLine) {\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\n\t\t\t\tconst message = JSON.parse(lastLine) as LoggedMessage;\n\t\t\t\treturn message.ts;\n\t\t\t} finally {\n\t\t\t\tcloseSync(fd);\n\t\t\t}\n\t\t} catch {\n\t\t\treturn null;\n\t\t}\n\t}\n}\n"]}
package/dist/store.js CHANGED
@@ -47,6 +47,12 @@ export class ChannelStore {
47
47
  await appendFile(logPath, line, "utf-8");
48
48
  return true;
49
49
  }
50
+ async logSubAgentRun(channelId, run) {
51
+ const logPath = join(this.getChannelDir(channelId), "subagent-runs.jsonl");
52
+ this.rotateIfNeeded(logPath);
53
+ const line = `${JSON.stringify(run)}\n`;
54
+ await appendFile(logPath, line, "utf-8");
55
+ }
50
56
  /**
51
57
  * Rotate log file if it exceeds 1MB.
52
58
  * Keeps one backup (log.jsonl.1) and resets the sync offset.
package/dist/store.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"store.js","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"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","sourcesContent":["import { closeSync, existsSync, mkdirSync, openSync, readSync, renameSync, statSync } from \"fs\";\nimport { appendFile, writeFile } from \"fs/promises\";\nimport { dirname, join } from \"path\";\n\nexport interface LoggedMessage {\n\tdate: string;\n\tts: string;\n\tuser: string;\n\tuserName?: string;\n\tdisplayName?: string;\n\ttext: string;\n\tisBot: boolean;\n\tdeliveryMode?: \"steer\" | \"followUp\";\n\tskipContextSync?: boolean;\n}\n\nexport interface ChannelStoreConfig {\n\tworkingDir: string;\n}\n\nexport class ChannelStore {\n\tprivate workingDir: string;\n\t// Track recently logged message timestamps to prevent duplicates\n\tprivate recentlyLogged = new Map<string, number>();\n\n\tconstructor(config: ChannelStoreConfig) {\n\t\tthis.workingDir = config.workingDir;\n\n\t\t// Ensure working directory exists\n\t\tif (!existsSync(this.workingDir)) {\n\t\t\tmkdirSync(this.workingDir, { recursive: true });\n\t\t}\n\t}\n\n\t/**\n\t * Get or create the directory for a channel/DM\n\t */\n\tgetChannelDir(channelId: string): string {\n\t\tconst dir = join(this.workingDir, channelId);\n\t\tif (!existsSync(dir)) {\n\t\t\tmkdirSync(dir, { recursive: true });\n\t\t}\n\t\treturn dir;\n\t}\n\n\t/**\n\t * Log a message to the channel's log.jsonl raw archive.\n\t * This file is cold storage and is not proactively loaded into memory context.\n\t * Returns false if message was already logged (duplicate)\n\t */\n\tasync logMessage(channelId: string, message: LoggedMessage): Promise<boolean> {\n\t\t// Check for duplicate (same channel + timestamp)\n\t\tconst dedupeKey = `${channelId}:${message.ts}`;\n\t\tif (this.recentlyLogged.has(dedupeKey)) {\n\t\t\treturn false; // Already logged\n\t\t}\n\n\t\t// Mark as logged and schedule cleanup after 60 seconds\n\t\tthis.recentlyLogged.set(dedupeKey, Date.now());\n\t\tsetTimeout(() => this.recentlyLogged.delete(dedupeKey), 60000);\n\n\t\tconst logPath = join(this.getChannelDir(channelId), \"log.jsonl\");\n\n\t\t// Rotate if file exceeds size limit\n\t\tthis.rotateIfNeeded(logPath);\n\n\t\t// Ensure message has a date field\n\t\tif (!message.date) {\n\t\t\tmessage.date = new Date().toISOString();\n\t\t}\n\n\t\tconst line = `${JSON.stringify(message)}\\n`;\n\t\tawait appendFile(logPath, line, \"utf-8\");\n\t\treturn true;\n\t}\n\n\t/**\n\t * Rotate log file if it exceeds 1MB.\n\t * Keeps one backup (log.jsonl.1) and resets the sync offset.\n\t */\n\tprivate rotateIfNeeded(logPath: string): void {\n\t\ttry {\n\t\t\tif (!existsSync(logPath)) return;\n\t\t\tconst stats = statSync(logPath);\n\t\t\tif (stats.size > 1_000_000) {\n\t\t\t\trenameSync(logPath, `${logPath}.1`);\n\t\t\t\t// Reset sync offset since log.jsonl was replaced\n\t\t\t\tconst syncOffsetPath = join(dirname(logPath), \".sync-offset\");\n\t\t\t\ttry {\n\t\t\t\t\twriteFile(syncOffsetPath, \"0\", \"utf-8\").catch(() => {});\n\t\t\t\t} catch {\n\t\t\t\t\t/* ignore */\n\t\t\t\t}\n\t\t\t}\n\t\t} catch {\n\t\t\t// Ignore rotation errors\n\t\t}\n\t}\n\n\t/**\n\t * Log a bot response\n\t */\n\tasync logBotResponse(channelId: string, text: string, ts: string): Promise<void> {\n\t\tawait this.logMessage(channelId, {\n\t\t\tdate: new Date().toISOString(),\n\t\t\tts,\n\t\t\tuser: \"bot\",\n\t\t\ttext,\n\t\t\tisBot: true,\n\t\t});\n\t}\n\n\t/**\n\t * Get the timestamp of the last logged message for a channel\n\t * Returns null if no log exists\n\t */\n\tgetLastTimestamp(channelId: string): string | null {\n\t\tconst logPath = join(this.workingDir, channelId, \"log.jsonl\");\n\t\tif (!existsSync(logPath)) {\n\t\t\treturn null;\n\t\t}\n\n\t\ttry {\n\t\t\tconst stats = statSync(logPath);\n\t\t\tif (stats.size === 0) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tconst fd = openSync(logPath, \"r\");\n\t\t\ttry {\n\t\t\t\tlet end = stats.size;\n\t\t\t\tconst trailing = Buffer.alloc(1);\n\t\t\t\twhile (end > 0) {\n\t\t\t\t\treadSync(fd, trailing, 0, 1, end - 1);\n\t\t\t\t\tif (trailing[0] !== 0x0a && trailing[0] !== 0x0d) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tend--;\n\t\t\t\t}\n\n\t\t\t\tif (end === 0) {\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\n\t\t\t\tconst chunkSize = 4096;\n\t\t\t\tconst buffer = Buffer.alloc(chunkSize);\n\t\t\t\tlet lineStart = 0;\n\t\t\t\tlet position = end;\n\n\t\t\t\twhile (position > 0) {\n\t\t\t\t\tconst bytesToRead = Math.min(chunkSize, position);\n\t\t\t\t\tposition -= bytesToRead;\n\t\t\t\t\treadSync(fd, buffer, 0, bytesToRead, position);\n\n\t\t\t\t\tconst newlineIndex = buffer.subarray(0, bytesToRead).lastIndexOf(0x0a);\n\t\t\t\t\tif (newlineIndex !== -1) {\n\t\t\t\t\t\tlineStart = position + newlineIndex + 1;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconst lineLength = end - lineStart;\n\t\t\t\tif (lineLength <= 0) {\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\n\t\t\t\tconst lineBuffer = Buffer.alloc(lineLength);\n\t\t\t\treadSync(fd, lineBuffer, 0, lineLength, lineStart);\n\t\t\t\tconst lastLine = lineBuffer.toString(\"utf-8\").replace(/\\r+$/, \"\");\n\t\t\t\tif (!lastLine) {\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\n\t\t\t\tconst message = JSON.parse(lastLine) as LoggedMessage;\n\t\t\t\treturn message.ts;\n\t\t\t} finally {\n\t\t\t\tcloseSync(fd);\n\t\t\t}\n\t\t} catch {\n\t\t\treturn null;\n\t\t}\n\t}\n}\n"]}
1
+ {"version":3,"file":"store.js","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"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","sourcesContent":["import { closeSync, existsSync, mkdirSync, openSync, readSync, renameSync, statSync } from \"fs\";\nimport { appendFile, writeFile } from \"fs/promises\";\nimport { dirname, join } from \"path\";\n\nexport interface LoggedMessage {\n\tdate: string;\n\tts: string;\n\tuser: string;\n\tuserName?: string;\n\tdisplayName?: string;\n\ttext: string;\n\tisBot: boolean;\n\tdeliveryMode?: \"steer\" | \"followUp\";\n\tskipContextSync?: boolean;\n}\n\nexport interface ChannelStoreConfig {\n\tworkingDir: string;\n}\n\nexport interface LoggedSubAgentRun {\n\tdate: string;\n\ttoolCallId: string;\n\tlabel: string;\n\tagent: string;\n\tsource: \"predefined\" | \"inline\";\n\tmodel: string;\n\ttools: string[];\n\tturns: number;\n\ttoolCalls: number;\n\tdurationMs: number;\n\tfailed: boolean;\n\tfailureReason?: string;\n\toutput: string;\n\toutputTruncated: boolean;\n\tusage: {\n\t\tinput: number;\n\t\toutput: number;\n\t\tcacheRead: number;\n\t\tcacheWrite: number;\n\t\ttotal: number;\n\t\tcost: {\n\t\t\tinput: number;\n\t\t\toutput: number;\n\t\t\tcacheRead: number;\n\t\t\tcacheWrite: number;\n\t\t\ttotal: number;\n\t\t};\n\t};\n}\n\nexport class ChannelStore {\n\tprivate workingDir: string;\n\t// Track recently logged message timestamps to prevent duplicates\n\tprivate recentlyLogged = new Map<string, number>();\n\n\tconstructor(config: ChannelStoreConfig) {\n\t\tthis.workingDir = config.workingDir;\n\n\t\t// Ensure working directory exists\n\t\tif (!existsSync(this.workingDir)) {\n\t\t\tmkdirSync(this.workingDir, { recursive: true });\n\t\t}\n\t}\n\n\t/**\n\t * Get or create the directory for a channel/DM\n\t */\n\tgetChannelDir(channelId: string): string {\n\t\tconst dir = join(this.workingDir, channelId);\n\t\tif (!existsSync(dir)) {\n\t\t\tmkdirSync(dir, { recursive: true });\n\t\t}\n\t\treturn dir;\n\t}\n\n\t/**\n\t * Log a message to the channel's log.jsonl raw archive.\n\t * This file is cold storage and is not proactively loaded into memory context.\n\t * Returns false if message was already logged (duplicate)\n\t */\n\tasync logMessage(channelId: string, message: LoggedMessage): Promise<boolean> {\n\t\t// Check for duplicate (same channel + timestamp)\n\t\tconst dedupeKey = `${channelId}:${message.ts}`;\n\t\tif (this.recentlyLogged.has(dedupeKey)) {\n\t\t\treturn false; // Already logged\n\t\t}\n\n\t\t// Mark as logged and schedule cleanup after 60 seconds\n\t\tthis.recentlyLogged.set(dedupeKey, Date.now());\n\t\tsetTimeout(() => this.recentlyLogged.delete(dedupeKey), 60000);\n\n\t\tconst logPath = join(this.getChannelDir(channelId), \"log.jsonl\");\n\n\t\t// Rotate if file exceeds size limit\n\t\tthis.rotateIfNeeded(logPath);\n\n\t\t// Ensure message has a date field\n\t\tif (!message.date) {\n\t\t\tmessage.date = new Date().toISOString();\n\t\t}\n\n\t\tconst line = `${JSON.stringify(message)}\\n`;\n\t\tawait appendFile(logPath, line, \"utf-8\");\n\t\treturn true;\n\t}\n\n\tasync logSubAgentRun(channelId: string, run: LoggedSubAgentRun): Promise<void> {\n\t\tconst logPath = join(this.getChannelDir(channelId), \"subagent-runs.jsonl\");\n\t\tthis.rotateIfNeeded(logPath);\n\t\tconst line = `${JSON.stringify(run)}\\n`;\n\t\tawait appendFile(logPath, line, \"utf-8\");\n\t}\n\n\t/**\n\t * Rotate log file if it exceeds 1MB.\n\t * Keeps one backup (log.jsonl.1) and resets the sync offset.\n\t */\n\tprivate rotateIfNeeded(logPath: string): void {\n\t\ttry {\n\t\t\tif (!existsSync(logPath)) return;\n\t\t\tconst stats = statSync(logPath);\n\t\t\tif (stats.size > 1_000_000) {\n\t\t\t\trenameSync(logPath, `${logPath}.1`);\n\t\t\t\t// Reset sync offset since log.jsonl was replaced\n\t\t\t\tconst syncOffsetPath = join(dirname(logPath), \".sync-offset\");\n\t\t\t\ttry {\n\t\t\t\t\twriteFile(syncOffsetPath, \"0\", \"utf-8\").catch(() => {});\n\t\t\t\t} catch {\n\t\t\t\t\t/* ignore */\n\t\t\t\t}\n\t\t\t}\n\t\t} catch {\n\t\t\t// Ignore rotation errors\n\t\t}\n\t}\n\n\t/**\n\t * Log a bot response\n\t */\n\tasync logBotResponse(channelId: string, text: string, ts: string): Promise<void> {\n\t\tawait this.logMessage(channelId, {\n\t\t\tdate: new Date().toISOString(),\n\t\t\tts,\n\t\t\tuser: \"bot\",\n\t\t\ttext,\n\t\t\tisBot: true,\n\t\t});\n\t}\n\n\t/**\n\t * Get the timestamp of the last logged message for a channel\n\t * Returns null if no log exists\n\t */\n\tgetLastTimestamp(channelId: string): string | null {\n\t\tconst logPath = join(this.workingDir, channelId, \"log.jsonl\");\n\t\tif (!existsSync(logPath)) {\n\t\t\treturn null;\n\t\t}\n\n\t\ttry {\n\t\t\tconst stats = statSync(logPath);\n\t\t\tif (stats.size === 0) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tconst fd = openSync(logPath, \"r\");\n\t\t\ttry {\n\t\t\t\tlet end = stats.size;\n\t\t\t\tconst trailing = Buffer.alloc(1);\n\t\t\t\twhile (end > 0) {\n\t\t\t\t\treadSync(fd, trailing, 0, 1, end - 1);\n\t\t\t\t\tif (trailing[0] !== 0x0a && trailing[0] !== 0x0d) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tend--;\n\t\t\t\t}\n\n\t\t\t\tif (end === 0) {\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\n\t\t\t\tconst chunkSize = 4096;\n\t\t\t\tconst buffer = Buffer.alloc(chunkSize);\n\t\t\t\tlet lineStart = 0;\n\t\t\t\tlet position = end;\n\n\t\t\t\twhile (position > 0) {\n\t\t\t\t\tconst bytesToRead = Math.min(chunkSize, position);\n\t\t\t\t\tposition -= bytesToRead;\n\t\t\t\t\treadSync(fd, buffer, 0, bytesToRead, position);\n\n\t\t\t\t\tconst newlineIndex = buffer.subarray(0, bytesToRead).lastIndexOf(0x0a);\n\t\t\t\t\tif (newlineIndex !== -1) {\n\t\t\t\t\t\tlineStart = position + newlineIndex + 1;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconst lineLength = end - lineStart;\n\t\t\t\tif (lineLength <= 0) {\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\n\t\t\t\tconst lineBuffer = Buffer.alloc(lineLength);\n\t\t\t\treadSync(fd, lineBuffer, 0, lineLength, lineStart);\n\t\t\t\tconst lastLine = lineBuffer.toString(\"utf-8\").replace(/\\r+$/, \"\");\n\t\t\t\tif (!lastLine) {\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\n\t\t\t\tconst message = JSON.parse(lastLine) as LoggedMessage;\n\t\t\t\treturn message.ts;\n\t\t\t} finally {\n\t\t\t\tcloseSync(fd);\n\t\t\t}\n\t\t} catch {\n\t\t\treturn null;\n\t\t}\n\t}\n}\n"]}
@@ -15,6 +15,10 @@ export interface SubAgentConfig {
15
15
  filePath?: string;
16
16
  source: "predefined" | "inline";
17
17
  }
18
+ export interface ResolvedSubAgentConfig extends Omit<SubAgentConfig, "model" | "modelRef"> {
19
+ model: Model<Api>;
20
+ modelRef: string;
21
+ }
18
22
  export interface SubAgentDiscoveryResult {
19
23
  directory: string;
20
24
  agents: SubAgentConfig[];
@@ -39,7 +43,7 @@ export declare function validateToolNames(values: string[] | undefined): {
39
43
  };
40
44
  export declare function discoverSubAgents(workspaceDir: string, availableModels: Model<Api>[]): SubAgentDiscoveryResult;
41
45
  export declare function resolveSubAgentConfig(availableModels: Model<Api>[], currentModel: Model<Api>, predefinedAgents: SubAgentConfig[], overrides: SubAgentInvocationOverrides): {
42
- config?: SubAgentConfig;
46
+ config?: ResolvedSubAgentConfig;
43
47
  error?: string;
44
48
  };
45
49
  export declare function formatSubAgentList(agents: SubAgentConfig[], maxItems?: number): string;