@oyasmi/pipiclaw 0.2.1 → 0.3.0

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.
Files changed (49) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/README.md +48 -16
  3. package/dist/agent.d.ts +2 -2
  4. package/dist/agent.d.ts.map +1 -1
  5. package/dist/agent.js +119 -106
  6. package/dist/agent.js.map +1 -1
  7. package/dist/command-extension.d.ts +14 -0
  8. package/dist/command-extension.d.ts.map +1 -0
  9. package/dist/command-extension.js +112 -0
  10. package/dist/command-extension.js.map +1 -0
  11. package/dist/commands.d.ts +1 -1
  12. package/dist/commands.d.ts.map +1 -1
  13. package/dist/commands.js +22 -25
  14. package/dist/commands.js.map +1 -1
  15. package/dist/config-loader.d.ts +2 -6
  16. package/dist/config-loader.d.ts.map +1 -1
  17. package/dist/config-loader.js +4 -60
  18. package/dist/config-loader.js.map +1 -1
  19. package/dist/context.d.ts +4 -23
  20. package/dist/context.d.ts.map +1 -1
  21. package/dist/context.js +7 -122
  22. package/dist/context.js.map +1 -1
  23. package/dist/dingtalk.d.ts.map +1 -1
  24. package/dist/dingtalk.js +5 -0
  25. package/dist/dingtalk.js.map +1 -1
  26. package/dist/main.d.ts.map +1 -1
  27. package/dist/main.js +27 -15
  28. package/dist/main.js.map +1 -1
  29. package/dist/memory-consolidation.d.ts +22 -0
  30. package/dist/memory-consolidation.d.ts.map +1 -0
  31. package/dist/memory-consolidation.js +258 -0
  32. package/dist/memory-consolidation.js.map +1 -0
  33. package/dist/memory-files.d.ts +24 -0
  34. package/dist/memory-files.d.ts.map +1 -0
  35. package/dist/memory-files.js +131 -0
  36. package/dist/memory-files.js.map +1 -0
  37. package/dist/memory-lifecycle.d.ts +27 -0
  38. package/dist/memory-lifecycle.d.ts.map +1 -0
  39. package/dist/memory-lifecycle.js +85 -0
  40. package/dist/memory-lifecycle.js.map +1 -0
  41. package/dist/prompt-builder.d.ts +1 -2
  42. package/dist/prompt-builder.d.ts.map +1 -1
  43. package/dist/prompt-builder.js +35 -88
  44. package/dist/prompt-builder.js.map +1 -1
  45. package/dist/store.d.ts +2 -1
  46. package/dist/store.d.ts.map +1 -1
  47. package/dist/store.js +2 -1
  48. package/dist/store.js.map +1 -1
  49. package/package.json +2 -2
package/dist/agent.js CHANGED
@@ -1,14 +1,16 @@
1
1
  import { Agent } from "@mariozechner/pi-agent-core";
2
2
  import { AgentSession, AuthStorage, convertToLlm, DefaultResourceLoader, ModelRegistry, SessionManager, } from "@mariozechner/pi-coding-agent";
3
3
  import { mkdir, writeFile } from "fs/promises";
4
- import { basename, join } from "path";
4
+ import { join } from "path";
5
+ import { COMMAND_RESULT_CUSTOM_TYPE, createCommandExtension } from "./command-extension.js";
5
6
  import { renderBuiltInHelp } from "./commands.js";
6
- import { getAgentConfig, getApiKeyForModel, getMemory, getSoul, loadPipiclawSkills } from "./config-loader.js";
7
- import { PipiclawSettingsManager, syncLogToSessionManager } from "./context.js";
7
+ import { getAgentConfig, getApiKeyForModel, getSoul, loadPipiclawSkills } from "./config-loader.js";
8
+ import { PipiclawSettingsManager } from "./context.js";
8
9
  import * as log from "./log.js";
9
- import { findExactModelReferenceMatch, formatModelList, formatModelReference, resolveInitialModel, } from "./model-utils.js";
10
+ import { MemoryLifecycle } from "./memory-lifecycle.js";
11
+ import { resolveInitialModel } from "./model-utils.js";
10
12
  import { APP_HOME_DIR, AUTH_CONFIG_PATH, MODELS_CONFIG_PATH } from "./paths.js";
11
- import { buildSystemPrompt } from "./prompt-builder.js";
13
+ import { buildAppendSystemPrompt } from "./prompt-builder.js";
12
14
  import { createExecutor } from "./sandbox.js";
13
15
  import { createPipiclawTools } from "./tools/index.js";
14
16
  function isSilentOutcome(outcome) {
@@ -71,6 +73,18 @@ function extractToolResultText(result) {
71
73
  }
72
74
  return JSON.stringify(result);
73
75
  }
76
+ function extractCustomCommandResultText(message) {
77
+ if (!message ||
78
+ typeof message !== "object" ||
79
+ !("role" in message) ||
80
+ !("customType" in message) ||
81
+ message.role !== "custom" ||
82
+ message.customType !== COMMAND_RESULT_CUSTOM_TYPE) {
83
+ return null;
84
+ }
85
+ const content = message.content;
86
+ return typeof content === "string" && content.trim() ? content : null;
87
+ }
74
88
  function createEmptyRunState() {
75
89
  return {
76
90
  ctx: null,
@@ -105,6 +119,8 @@ class ChannelRunner {
105
119
  sessionManager;
106
120
  settingsManager;
107
121
  modelRegistry;
122
+ memoryLifecycle;
123
+ sessionReady;
108
124
  // --- Mutable across runs ---
109
125
  activeModel;
110
126
  currentSkills;
@@ -119,13 +135,9 @@ class ChannelRunner {
119
135
  this.workspaceDir = join(channelDir, "..");
120
136
  // Create tools
121
137
  const tools = createPipiclawTools(executor);
122
- // Initial system prompt
123
- const soul = getSoul(this.workspaceDir);
124
- const agentConfig = getAgentConfig(channelDir);
125
- const memory = getMemory(channelDir);
138
+ // Initial skill summaries
126
139
  const initialSkills = loadPipiclawSkills(channelDir, this.workspacePath);
127
140
  this.currentSkills = initialSkills;
128
- const systemPrompt = buildSystemPrompt(this.workspacePath, channelId, soul, agentConfig, memory, sandboxConfig, initialSkills);
129
141
  // Create session manager
130
142
  const contextFile = join(channelDir, "context.jsonl");
131
143
  this.sessionManager = SessionManager.open(contextFile, channelDir);
@@ -139,7 +151,7 @@ class ChannelRunner {
139
151
  // Create agent
140
152
  this.agent = new Agent({
141
153
  initialState: {
142
- systemPrompt,
154
+ systemPrompt: "",
143
155
  model: this.activeModel,
144
156
  thinkingLevel: "off",
145
157
  tools,
@@ -147,16 +159,52 @@ class ChannelRunner {
147
159
  convertToLlm,
148
160
  getApiKey: async () => getApiKeyForModel(this.modelRegistry, this.activeModel),
149
161
  });
150
- // Load existing messages
151
- const loadedSession = this.sessionManager.buildSessionContext();
152
- if (loadedSession.messages.length > 0) {
153
- this.agent.replaceMessages(loadedSession.messages);
154
- log.logInfo(`[${channelId}] Loaded ${loadedSession.messages.length} messages from context.jsonl`);
155
- }
162
+ this.memoryLifecycle = new MemoryLifecycle({
163
+ channelId: this.channelId,
164
+ channelDir: this.channelDir,
165
+ getMessages: () => this.session.messages,
166
+ getSessionEntries: () => this.sessionManager.getBranch(),
167
+ getModel: () => this.session.model ?? this.activeModel,
168
+ resolveApiKey: async (model) => getApiKeyForModel(this.modelRegistry, model),
169
+ });
156
170
  const resourceLoader = new DefaultResourceLoader({
157
171
  cwd: process.cwd(),
158
172
  agentDir: APP_HOME_DIR,
159
173
  settingsManager: this.settingsManager,
174
+ extensionFactories: [
175
+ this.memoryLifecycle.createExtensionFactory(),
176
+ createCommandExtension({
177
+ getCurrentModel: () => this.session.model ?? this.activeModel,
178
+ getAvailableModels: async () => {
179
+ this.modelRegistry.refresh();
180
+ return await this.modelRegistry.getAvailable();
181
+ },
182
+ getSessionStats: () => this.session.getSessionStats(),
183
+ getThinkingLevel: () => this.session.thinkingLevel,
184
+ switchModel: async (model) => {
185
+ await this.session.setModel(model);
186
+ this.activeModel = model;
187
+ },
188
+ refreshSessionResources: async () => {
189
+ await this.refreshSessionResources();
190
+ },
191
+ }),
192
+ ],
193
+ appendSystemPromptOverride: (base) => {
194
+ const soul = getSoul(this.workspaceDir);
195
+ const sections = [...base];
196
+ if (soul) {
197
+ sections.unshift(soul);
198
+ }
199
+ sections.push(buildAppendSystemPrompt(this.workspacePath, this.channelId, this.sandboxConfig));
200
+ return sections;
201
+ },
202
+ agentsFilesOverride: () => {
203
+ const agentConfig = getAgentConfig(this.channelDir);
204
+ return {
205
+ agentsFiles: agentConfig ? [{ path: `${this.workspacePath}/AGENTS.md`, content: agentConfig }] : [],
206
+ };
207
+ },
160
208
  skillsOverride: (base) => ({
161
209
  skills: [...base.skills, ...this.currentSkills],
162
210
  diagnostics: base.diagnostics,
@@ -175,6 +223,7 @@ class ChannelRunner {
175
223
  });
176
224
  // Subscribe to session events
177
225
  this.subscribeToSessionEvents();
226
+ this.sessionReady = this.initializeSession();
178
227
  }
179
228
  // === Public API ===
180
229
  async run(ctx, _store) {
@@ -198,49 +247,21 @@ class ChannelRunner {
198
247
  },
199
248
  };
200
249
  try {
250
+ await this.ensureSessionReady();
201
251
  // Ensure channel directory exists
202
252
  await mkdir(this.channelDir, { recursive: true });
203
- // Update system prompt and runtime resources with fresh config
204
- const soul = getSoul(this.workspaceDir);
205
- const agentConfig = getAgentConfig(this.channelDir);
206
- const memory = getMemory(this.channelDir);
207
- const skills = loadPipiclawSkills(this.channelDir, this.workspacePath);
208
- this.currentSkills = skills;
209
- const systemPrompt = buildSystemPrompt(this.workspacePath, this.channelId, soul, agentConfig, memory, this.sandboxConfig, skills);
210
- this.session.agent.setSystemPrompt(systemPrompt);
211
- await this.session.reload();
212
- // Sync messages from log.jsonl
213
- const syncedCount = syncLogToSessionManager(this.sessionManager, this.channelDir, ctx.message.ts);
214
- if (syncedCount > 0) {
215
- log.logInfo(`[${this.channelId}] Synced ${syncedCount} messages from log.jsonl`);
216
- }
217
- // Reload messages from context.jsonl
218
- const reloadedSession = this.sessionManager.buildSessionContext();
219
- if (reloadedSession.messages.length > 0) {
220
- this.agent.replaceMessages(reloadedSession.messages);
221
- log.logInfo(`[${this.channelId}] Reloaded ${reloadedSession.messages.length} messages from context`);
222
- }
223
- // Log context info
224
- log.logInfo(`Context sizes - system: ${systemPrompt.length} chars, memory: ${memory.length} chars`);
225
- // Build user message with timestamp and username prefix
226
- const now = new Date();
227
- const pad = (n) => n.toString().padStart(2, "0");
228
- const offset = -now.getTimezoneOffset();
229
- const offsetSign = offset >= 0 ? "+" : "-";
230
- const offsetHours = pad(Math.floor(Math.abs(offset) / 60));
231
- const offsetMins = pad(Math.abs(offset) % 60);
232
- const timestamp = `${now.getFullYear()}-${pad(now.getMonth() + 1)}-${pad(now.getDate())} ${pad(now.getHours())}:${pad(now.getMinutes())}:${pad(now.getSeconds())}${offsetSign}${offsetHours}:${offsetMins}`;
233
- const userMessage = `[${timestamp}] [${ctx.message.userName || "unknown"}]: ${ctx.message.text}`;
253
+ const userMessage = this.formatUserMessage(ctx.message.text, ctx.message.userName);
254
+ const promptText = this.shouldPreserveRawInput(ctx.message.text) ? ctx.message.text.trim() : userMessage;
234
255
  // Debug: write context to last_prompt.json (only with PIPICLAW_DEBUG=1)
235
256
  if (process.env.PIPICLAW_DEBUG) {
236
257
  const debugContext = {
237
- systemPrompt,
258
+ systemPrompt: this.agent.state.systemPrompt,
238
259
  messages: this.session.messages,
239
- newUserMessage: userMessage,
260
+ newUserMessage: promptText,
240
261
  };
241
262
  await writeFile(join(this.channelDir, "last_prompt.json"), JSON.stringify(debugContext, null, 2));
242
263
  }
243
- await this.session.prompt(userMessage);
264
+ await this.session.prompt(promptText);
244
265
  }
245
266
  catch (err) {
246
267
  this.runState.stopReason = "error";
@@ -317,26 +338,6 @@ class ChannelRunner {
317
338
  case "help":
318
339
  await this.sendCommandReply(ctx, renderBuiltInHelp());
319
340
  return;
320
- case "new": {
321
- const completed = await this.session.newSession();
322
- await this.sendCommandReply(ctx, completed ? `已开启新会话。\n\nSession ID: \`${this.session.sessionId}\`` : "新会话已取消。");
323
- return;
324
- }
325
- case "compact": {
326
- const result = await this.session.compact(command.args || undefined);
327
- await this.sendCommandReply(ctx, `已压缩当前会话上下文。\n\n- Tokens before compaction: \`${result.tokensBefore}\`\n- Summary:\n\n\`\`\`text\n${result.summary}\n\`\`\``);
328
- return;
329
- }
330
- case "session": {
331
- const stats = this.session.getSessionStats();
332
- const currentModel = this.session.model ? `\`${formatModelReference(this.session.model)}\`` : "(none)";
333
- const sessionFile = stats.sessionFile ? `\`${basename(stats.sessionFile)}\`` : "(none)";
334
- await this.sendCommandReply(ctx, `# Session\n\n- Session ID: \`${stats.sessionId}\`\n- Session file: ${sessionFile}\n- Model: ${currentModel}\n- Thinking level: \`${this.session.thinkingLevel}\`\n- User messages: \`${stats.userMessages}\`\n- Assistant messages: \`${stats.assistantMessages}\`\n- Tool calls: \`${stats.toolCalls}\`\n- Tool results: \`${stats.toolResults}\`\n- Total messages: \`${stats.totalMessages}\`\n- Tokens: \`${stats.tokens.total}\` (input \`${stats.tokens.input}\`, output \`${stats.tokens.output}\`, cache read \`${stats.tokens.cacheRead}\`, cache write \`${stats.tokens.cacheWrite}\`)\n- Cost: \`$${stats.cost.toFixed(4)}\``);
335
- return;
336
- }
337
- case "model":
338
- await this.handleModelCommand(ctx, command.args);
339
- return;
340
341
  case "stop":
341
342
  await this.sendCommandReply(ctx, "No task is running. Use `/stop` only while a task is running.");
342
343
  return;
@@ -356,11 +357,11 @@ class ChannelRunner {
356
357
  await this.sendCommandReply(ctx, `命令执行失败:${errMsg}`);
357
358
  }
358
359
  }
359
- async queueSteer(text) {
360
- await this.queueBusyMessage("steer", this.requireQueuedMessage(text, "steer"));
360
+ async queueSteer(text, userName) {
361
+ await this.queueBusyMessage("steer", this.requireQueuedMessage(text, "steer"), userName);
361
362
  }
362
- async queueFollowUp(text) {
363
- await this.queueBusyMessage("followUp", this.requireQueuedMessage(text, "followup"));
363
+ async queueFollowUp(text, userName) {
364
+ await this.queueBusyMessage("followUp", this.requireQueuedMessage(text, "followup"), userName);
364
365
  }
365
366
  abort() {
366
367
  this.session.abort();
@@ -380,40 +381,25 @@ class ChannelRunner {
380
381
  }
381
382
  return trimmedText;
382
383
  }
383
- async queueBusyMessage(delivery, text) {
384
+ shouldPreserveRawInput(text) {
385
+ return text.trim().startsWith("/");
386
+ }
387
+ formatUserMessage(text, userName, now = new Date()) {
388
+ const pad = (n) => n.toString().padStart(2, "0");
389
+ const offset = -now.getTimezoneOffset();
390
+ const offsetSign = offset >= 0 ? "+" : "-";
391
+ const offsetHours = pad(Math.floor(Math.abs(offset) / 60));
392
+ const offsetMins = pad(Math.abs(offset) % 60);
393
+ const timestamp = `${now.getFullYear()}-${pad(now.getMonth() + 1)}-${pad(now.getDate())} ${pad(now.getHours())}:${pad(now.getMinutes())}:${pad(now.getSeconds())}${offsetSign}${offsetHours}:${offsetMins}`;
394
+ return `[${timestamp}] [${userName || "unknown"}]: ${text}`;
395
+ }
396
+ async queueBusyMessage(delivery, text, userName) {
384
397
  if (!this.session.isStreaming) {
385
398
  throw new Error("No task is currently running.");
386
399
  }
387
- if (delivery === "followUp") {
388
- await this.session.followUp(text);
389
- }
390
- else {
391
- await this.session.steer(text);
392
- }
393
- }
394
- async handleModelCommand(ctx, args) {
395
- this.modelRegistry.refresh();
396
- const availableModels = await this.modelRegistry.getAvailable();
397
- const currentModel = this.session.model;
398
- if (!args.trim()) {
399
- const current = currentModel ? `\`${formatModelReference(currentModel)}\`` : "(none)";
400
- const available = availableModels.length > 0 ? formatModelList(availableModels, currentModel) : "- (none)";
401
- await this.sendCommandReply(ctx, `# Model\n\nCurrent model: ${current}\n\nUse \`/model <provider/modelId>\` or \`/model <modelId>\` to switch. Bare model IDs must resolve uniquely.\n\nAvailable models:\n${available}`);
402
- return;
403
- }
404
- const match = findExactModelReferenceMatch(args, availableModels);
405
- if (match.match) {
406
- await this.session.setModel(match.match);
407
- this.activeModel = match.match;
408
- await this.sendCommandReply(ctx, `已切换模型到 \`${formatModelReference(match.match)}\`。`);
409
- return;
410
- }
411
- const available = availableModels.length > 0 ? formatModelList(availableModels, currentModel, 10) : "- (none)";
412
- if (match.ambiguous) {
413
- await this.sendCommandReply(ctx, `未切换模型:\`${args.trim()}\` 匹配到多个模型。请改用精确的 \`provider/modelId\` 形式。\n\nAvailable models:\n${available}`);
414
- return;
415
- }
416
- await this.sendCommandReply(ctx, `未找到模型 \`${args.trim()}\`。请使用精确的 \`provider/modelId\` 或唯一的 \`modelId\`。\n\nAvailable models:\n${available}`);
400
+ await this.session.prompt(this.formatUserMessage(text, userName), {
401
+ streamingBehavior: delivery,
402
+ });
417
403
  }
418
404
  resetRunState(ctx) {
419
405
  this.runState = createEmptyRunState();
@@ -424,6 +410,20 @@ class ChannelRunner {
424
410
  channelName: ctx.channelName,
425
411
  };
426
412
  }
413
+ async refreshSessionResources() {
414
+ await this.ensureSessionReady();
415
+ const skills = loadPipiclawSkills(this.channelDir, this.workspacePath);
416
+ this.currentSkills = skills;
417
+ await this.session.reload();
418
+ }
419
+ async initializeSession() {
420
+ const skills = loadPipiclawSkills(this.channelDir, this.workspacePath);
421
+ this.currentSkills = skills;
422
+ await this.session.reload();
423
+ }
424
+ async ensureSessionReady() {
425
+ await this.sessionReady;
426
+ }
427
427
  // === Session event subscription ===
428
428
  subscribeToSessionEvents() {
429
429
  this.session.subscribe(async (event) => {
@@ -466,6 +466,19 @@ class ChannelRunner {
466
466
  }
467
467
  else if (event.type === "message_end") {
468
468
  const agentEvent = event;
469
+ const commandResultText = extractCustomCommandResultText(agentEvent.message);
470
+ if (commandResultText) {
471
+ this.runState.finalOutcome = { kind: "final", text: commandResultText };
472
+ log.logResponse(logCtx, commandResultText);
473
+ queue.enqueue(async () => {
474
+ const delivered = await ctx.respondPlain(commandResultText);
475
+ if (!delivered) {
476
+ await ctx.replaceMessage(commandResultText);
477
+ }
478
+ this.runState.finalResponseDelivered = true;
479
+ }, "command result");
480
+ return;
481
+ }
469
482
  if (agentEvent.message.role === "assistant") {
470
483
  const assistantMsg = agentEvent.message;
471
484
  if (assistantMsg.stopReason) {
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 { basename, join } from \"path\";\nimport { type BuiltInCommand, renderBuiltInHelp } from \"./commands.js\";\nimport { getAgentConfig, getApiKeyForModel, getMemory, getSoul, loadPipiclawSkills } from \"./config-loader.js\";\nimport { PipiclawSettingsManager, syncLogToSessionManager } from \"./context.js\";\nimport type { DingTalkContext } from \"./dingtalk.js\";\nimport * as log from \"./log.js\";\nimport {\n\tfindExactModelReferenceMatch,\n\tformatModelList,\n\tformatModelReference,\n\tresolveInitialModel,\n} from \"./model-utils.js\";\nimport { APP_HOME_DIR, AUTH_CONFIG_PATH, MODELS_CONFIG_PATH } from \"./paths.js\";\nimport { buildSystemPrompt } from \"./prompt-builder.js\";\nimport { createExecutor, type SandboxConfig } from \"./sandbox.js\";\nimport type { ChannelStore } from \"./store.js\";\nimport { createPipiclawTools } from \"./tools/index.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): Promise<void>;\n\tqueueFollowUp(text: string): Promise<void>;\n\tabort(): void;\n}\n\ntype FinalOutcome = { kind: \"none\" } | { kind: \"silent\" } | { kind: \"final\"; text: string };\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\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\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\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.workspacePath = executor.getWorkspacePath(channelDir.replace(`/${channelId}`, \"\"));\n\t\tthis.workspaceDir = join(channelDir, \"..\");\n\n\t\t// Create tools\n\t\tconst tools = createPipiclawTools(executor);\n\n\t\t// Initial system prompt\n\t\tconst soul = getSoul(this.workspaceDir);\n\t\tconst agentConfig = getAgentConfig(channelDir);\n\t\tconst memory = getMemory(channelDir);\n\t\tconst initialSkills = loadPipiclawSkills(channelDir, this.workspacePath);\n\t\tthis.currentSkills = initialSkills;\n\t\tconst systemPrompt = buildSystemPrompt(\n\t\t\tthis.workspacePath,\n\t\t\tchannelId,\n\t\t\tsoul,\n\t\t\tagentConfig,\n\t\t\tmemory,\n\t\t\tsandboxConfig,\n\t\t\tinitialSkills,\n\t\t);\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 = new ModelRegistry(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 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\t// Load existing messages\n\t\tconst loadedSession = this.sessionManager.buildSessionContext();\n\t\tif (loadedSession.messages.length > 0) {\n\t\t\tthis.agent.replaceMessages(loadedSession.messages);\n\t\t\tlog.logInfo(`[${channelId}] Loaded ${loadedSession.messages.length} messages from context.jsonl`);\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\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}\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\t// Ensure channel directory exists\n\t\t\tawait mkdir(this.channelDir, { recursive: true });\n\n\t\t\t// Update system prompt and runtime resources with fresh config\n\t\t\tconst soul = getSoul(this.workspaceDir);\n\t\t\tconst agentConfig = getAgentConfig(this.channelDir);\n\t\t\tconst memory = getMemory(this.channelDir);\n\t\t\tconst skills = loadPipiclawSkills(this.channelDir, this.workspacePath);\n\t\t\tthis.currentSkills = skills;\n\t\t\tconst systemPrompt = buildSystemPrompt(\n\t\t\t\tthis.workspacePath,\n\t\t\t\tthis.channelId,\n\t\t\t\tsoul,\n\t\t\t\tagentConfig,\n\t\t\t\tmemory,\n\t\t\t\tthis.sandboxConfig,\n\t\t\t\tskills,\n\t\t\t);\n\t\t\tthis.session.agent.setSystemPrompt(systemPrompt);\n\t\t\tawait this.session.reload();\n\n\t\t\t// Sync messages from log.jsonl\n\t\t\tconst syncedCount = syncLogToSessionManager(this.sessionManager, this.channelDir, ctx.message.ts);\n\t\t\tif (syncedCount > 0) {\n\t\t\t\tlog.logInfo(`[${this.channelId}] Synced ${syncedCount} messages from log.jsonl`);\n\t\t\t}\n\n\t\t\t// Reload messages from context.jsonl\n\t\t\tconst reloadedSession = this.sessionManager.buildSessionContext();\n\t\t\tif (reloadedSession.messages.length > 0) {\n\t\t\t\tthis.agent.replaceMessages(reloadedSession.messages);\n\t\t\t\tlog.logInfo(`[${this.channelId}] Reloaded ${reloadedSession.messages.length} messages from context`);\n\t\t\t}\n\n\t\t\t// Log context info\n\t\t\tlog.logInfo(`Context sizes - system: ${systemPrompt.length} chars, memory: ${memory.length} chars`);\n\n\t\t\t// Build user message with timestamp and username prefix\n\t\t\tconst now = new Date();\n\t\t\tconst pad = (n: number) => n.toString().padStart(2, \"0\");\n\t\t\tconst offset = -now.getTimezoneOffset();\n\t\t\tconst offsetSign = offset >= 0 ? \"+\" : \"-\";\n\t\t\tconst offsetHours = pad(Math.floor(Math.abs(offset) / 60));\n\t\t\tconst offsetMins = pad(Math.abs(offset) % 60);\n\t\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\t\tconst userMessage = `[${timestamp}] [${ctx.message.userName || \"unknown\"}]: ${ctx.message.text}`;\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,\n\t\t\t\t\tmessages: this.session.messages,\n\t\t\t\t\tnewUserMessage: userMessage,\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(userMessage);\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 \"new\": {\n\t\t\t\t\tconst completed = await this.session.newSession();\n\t\t\t\t\tawait this.sendCommandReply(\n\t\t\t\t\t\tctx,\n\t\t\t\t\t\tcompleted ? `已开启新会话。\\n\\nSession ID: \\`${this.session.sessionId}\\`` : \"新会话已取消。\",\n\t\t\t\t\t);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tcase \"compact\": {\n\t\t\t\t\tconst result = await this.session.compact(command.args || undefined);\n\t\t\t\t\tawait this.sendCommandReply(\n\t\t\t\t\t\tctx,\n\t\t\t\t\t\t`已压缩当前会话上下文。\\n\\n- Tokens before compaction: \\`${result.tokensBefore}\\`\\n- Summary:\\n\\n\\`\\`\\`text\\n${result.summary}\\n\\`\\`\\``,\n\t\t\t\t\t);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tcase \"session\": {\n\t\t\t\t\tconst stats = this.session.getSessionStats();\n\t\t\t\t\tconst currentModel = this.session.model ? `\\`${formatModelReference(this.session.model)}\\`` : \"(none)\";\n\t\t\t\t\tconst sessionFile = stats.sessionFile ? `\\`${basename(stats.sessionFile)}\\`` : \"(none)\";\n\t\t\t\t\tawait this.sendCommandReply(\n\t\t\t\t\t\tctx,\n\t\t\t\t\t\t`# Session\\n\\n- Session ID: \\`${stats.sessionId}\\`\\n- Session file: ${sessionFile}\\n- Model: ${currentModel}\\n- Thinking level: \\`${this.session.thinkingLevel}\\`\\n- User messages: \\`${stats.userMessages}\\`\\n- Assistant messages: \\`${stats.assistantMessages}\\`\\n- Tool calls: \\`${stats.toolCalls}\\`\\n- Tool results: \\`${stats.toolResults}\\`\\n- Total messages: \\`${stats.totalMessages}\\`\\n- Tokens: \\`${stats.tokens.total}\\` (input \\`${stats.tokens.input}\\`, output \\`${stats.tokens.output}\\`, cache read \\`${stats.tokens.cacheRead}\\`, cache write \\`${stats.tokens.cacheWrite}\\`)\\n- Cost: \\`$${stats.cost.toFixed(4)}\\``,\n\t\t\t\t\t);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tcase \"model\":\n\t\t\t\t\tawait this.handleModelCommand(ctx, command.args);\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): Promise<void> {\n\t\tawait this.queueBusyMessage(\"steer\", this.requireQueuedMessage(text, \"steer\"));\n\t}\n\n\tasync queueFollowUp(text: string): Promise<void> {\n\t\tawait this.queueBusyMessage(\"followUp\", this.requireQueuedMessage(text, \"followup\"));\n\t}\n\n\tabort(): void {\n\t\tthis.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 async queueBusyMessage(delivery: \"steer\" | \"followUp\", text: 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\tif (delivery === \"followUp\") {\n\t\t\tawait this.session.followUp(text);\n\t\t} else {\n\t\t\tawait this.session.steer(text);\n\t\t}\n\t}\n\n\tprivate async handleModelCommand(ctx: DingTalkContext, args: string): Promise<void> {\n\t\tthis.modelRegistry.refresh();\n\t\tconst availableModels = await this.modelRegistry.getAvailable();\n\t\tconst currentModel = this.session.model;\n\n\t\tif (!args.trim()) {\n\t\t\tconst current = currentModel ? `\\`${formatModelReference(currentModel)}\\`` : \"(none)\";\n\t\t\tconst available = availableModels.length > 0 ? formatModelList(availableModels, currentModel) : \"- (none)\";\n\t\t\tawait this.sendCommandReply(\n\t\t\t\tctx,\n\t\t\t\t`# Model\\n\\nCurrent model: ${current}\\n\\nUse \\`/model <provider/modelId>\\` or \\`/model <modelId>\\` to switch. Bare model IDs must resolve uniquely.\\n\\nAvailable models:\\n${available}`,\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\tconst match = findExactModelReferenceMatch(args, availableModels);\n\t\tif (match.match) {\n\t\t\tawait this.session.setModel(match.match);\n\t\t\tthis.activeModel = match.match;\n\t\t\tawait this.sendCommandReply(ctx, `已切换模型到 \\`${formatModelReference(match.match)}\\`。`);\n\t\t\treturn;\n\t\t}\n\n\t\tconst available = availableModels.length > 0 ? formatModelList(availableModels, currentModel, 10) : \"- (none)\";\n\t\tif (match.ambiguous) {\n\t\t\tawait this.sendCommandReply(\n\t\t\t\tctx,\n\t\t\t\t`未切换模型:\\`${args.trim()}\\` 匹配到多个模型。请改用精确的 \\`provider/modelId\\` 形式。\\n\\nAvailable models:\\n${available}`,\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\tawait this.sendCommandReply(\n\t\t\tctx,\n\t\t\t`未找到模型 \\`${args.trim()}\\`。请使用精确的 \\`provider/modelId\\` 或唯一的 \\`modelId\\`。\\n\\nAvailable models:\\n${available}`,\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\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_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 (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\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 { join } 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 { createPipiclawTools } from \"./tools/index.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(): void;\n}\n\ntype FinalOutcome = { kind: \"none\" } | { kind: \"silent\" } | { kind: \"final\"; text: string };\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\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 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.workspacePath = executor.getWorkspacePath(channelDir.replace(`/${channelId}`, \"\"));\n\t\tthis.workspaceDir = join(channelDir, \"..\");\n\n\t\t// Create tools\n\t\tconst tools = createPipiclawTools(executor);\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 = new ModelRegistry(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 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(buildAppendSystemPrompt(this.workspacePath, this.channelId, this.sandboxConfig));\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\tabort(): void {\n\t\tthis.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_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 (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"]}
@@ -0,0 +1,14 @@
1
+ import type { ThinkingLevel } from "@mariozechner/pi-agent-core";
2
+ import type { Api, Model } from "@mariozechner/pi-ai";
3
+ import type { ExtensionFactory, SessionStats } from "@mariozechner/pi-coding-agent";
4
+ export declare const COMMAND_RESULT_CUSTOM_TYPE = "pipiclaw.command_result";
5
+ export interface PipiclawCommandExtensionOptions {
6
+ getCurrentModel: () => Model<Api> | undefined;
7
+ getAvailableModels: () => Promise<Model<Api>[]>;
8
+ getSessionStats: () => SessionStats;
9
+ getThinkingLevel: () => ThinkingLevel;
10
+ switchModel: (model: Model<Api>) => Promise<void>;
11
+ refreshSessionResources: () => Promise<void>;
12
+ }
13
+ export declare function createCommandExtension(options: PipiclawCommandExtensionOptions): ExtensionFactory;
14
+ //# sourceMappingURL=command-extension.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"command-extension.d.ts","sourceRoot":"","sources":["../src/command-extension.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AACjE,OAAO,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,KAAK,EAIX,gBAAgB,EAChB,YAAY,EACZ,MAAM,+BAA+B,CAAC;AAIvC,eAAO,MAAM,0BAA0B,4BAA4B,CAAC;AAEpE,MAAM,WAAW,+BAA+B;IAC/C,eAAe,EAAE,MAAM,KAAK,CAAC,GAAG,CAAC,GAAG,SAAS,CAAC;IAC9C,kBAAkB,EAAE,MAAM,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAChD,eAAe,EAAE,MAAM,YAAY,CAAC;IACpC,gBAAgB,EAAE,MAAM,aAAa,CAAC;IACtC,WAAW,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAClD,uBAAuB,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC7C;AA6CD,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,+BAA+B,GAAG,gBAAgB,CAsGjG","sourcesContent":["import type { ThinkingLevel } from \"@mariozechner/pi-agent-core\";\nimport type { Api, Model } from \"@mariozechner/pi-ai\";\nimport type {\n\tCompactionResult,\n\tExtensionAPI,\n\tExtensionCommandContext,\n\tExtensionFactory,\n\tSessionStats,\n} from \"@mariozechner/pi-coding-agent\";\nimport { basename } from \"path\";\nimport { findExactModelReferenceMatch, formatModelList, formatModelReference } from \"./model-utils.js\";\n\nexport const COMMAND_RESULT_CUSTOM_TYPE = \"pipiclaw.command_result\";\n\nexport interface PipiclawCommandExtensionOptions {\n\tgetCurrentModel: () => Model<Api> | undefined;\n\tgetAvailableModels: () => Promise<Model<Api>[]>;\n\tgetSessionStats: () => SessionStats;\n\tgetThinkingLevel: () => ThinkingLevel;\n\tswitchModel: (model: Model<Api>) => Promise<void>;\n\trefreshSessionResources: () => Promise<void>;\n}\n\nfunction buildSessionText(\n\tstats: SessionStats,\n\tcurrentModel: Model<Api> | undefined,\n\tthinkingLevel: ThinkingLevel,\n): string {\n\tconst modelText = currentModel ? `\\`${formatModelReference(currentModel)}\\`` : \"(none)\";\n\tconst sessionFile = stats.sessionFile ? `\\`${basename(stats.sessionFile)}\\`` : \"(none)\";\n\treturn `# Session\n\n- Session ID: \\`${stats.sessionId}\\`\n- Session file: ${sessionFile}\n- Model: ${modelText}\n- Thinking level: \\`${thinkingLevel}\\`\n- User messages: \\`${stats.userMessages}\\`\n- Assistant messages: \\`${stats.assistantMessages}\\`\n- Tool calls: \\`${stats.toolCalls}\\`\n- Tool results: \\`${stats.toolResults}\\`\n- Total messages: \\`${stats.totalMessages}\\`\n- Tokens: \\`${stats.tokens.total}\\` (input \\`${stats.tokens.input}\\`, output \\`${stats.tokens.output}\\`, cache read \\`${stats.tokens.cacheRead}\\`, cache write \\`${stats.tokens.cacheWrite}\\`)\n- Cost: \\`$${stats.cost.toFixed(4)}\\``;\n}\n\nasync function runCompact(\n\tctx: ExtensionCommandContext,\n\tcustomInstructions: string | undefined,\n): Promise<CompactionResult> {\n\treturn await new Promise<CompactionResult>((resolve, reject) => {\n\t\tctx.compact({\n\t\t\tcustomInstructions,\n\t\t\tonComplete: resolve,\n\t\t\tonError: reject,\n\t\t});\n\t});\n}\n\nfunction sendCommandResult(pi: Pick<ExtensionAPI, \"sendMessage\">, text: string): void {\n\tpi.sendMessage({\n\t\tcustomType: COMMAND_RESULT_CUSTOM_TYPE,\n\t\tcontent: text,\n\t\tdisplay: true,\n\t});\n}\n\nexport function createCommandExtension(options: PipiclawCommandExtensionOptions): ExtensionFactory {\n\treturn (pi) => {\n\t\tpi.registerCommand(\"session\", {\n\t\t\tdescription: \"Show current session state, usage, and model info\",\n\t\t\thandler: async () => {\n\t\t\t\tsendCommandResult(\n\t\t\t\t\tpi,\n\t\t\t\t\tbuildSessionText(options.getSessionStats(), options.getCurrentModel(), options.getThinkingLevel()),\n\t\t\t\t);\n\t\t\t},\n\t\t});\n\n\t\tpi.registerCommand(\"model\", {\n\t\t\tdescription: \"Show the current model or switch models using an exact match\",\n\t\t\thandler: async (args) => {\n\t\t\t\tconst availableModels = await options.getAvailableModels();\n\t\t\t\tconst currentModel = options.getCurrentModel();\n\n\t\t\t\tif (!args.trim()) {\n\t\t\t\t\tconst current = currentModel ? `\\`${formatModelReference(currentModel)}\\`` : \"(none)\";\n\t\t\t\t\tconst available =\n\t\t\t\t\t\tavailableModels.length > 0 ? formatModelList(availableModels, currentModel) : \"- (none)\";\n\t\t\t\t\tsendCommandResult(\n\t\t\t\t\t\tpi,\n\t\t\t\t\t\t`# Model\n\nCurrent model: ${current}\n\nUse \\`/model <provider/modelId>\\` or \\`/model <modelId>\\` to switch. Bare model IDs must resolve uniquely.\n\nAvailable models:\n${available}`,\n\t\t\t\t\t);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst match = findExactModelReferenceMatch(args, availableModels);\n\t\t\t\tconst available =\n\t\t\t\t\tavailableModels.length > 0 ? formatModelList(availableModels, currentModel, 10) : \"- (none)\";\n\n\t\t\t\tif (match.match) {\n\t\t\t\t\tawait options.switchModel(match.match);\n\t\t\t\t\tsendCommandResult(pi, `已切换模型到 \\`${formatModelReference(match.match)}\\`.`);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tif (match.ambiguous) {\n\t\t\t\t\tsendCommandResult(\n\t\t\t\t\t\tpi,\n\t\t\t\t\t\t`未切换模型:\\`${args.trim()}\\` 匹配到多个模型。请改用精确的 \\`provider/modelId\\` 形式。\n\nAvailable models:\n${available}`,\n\t\t\t\t\t);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tsendCommandResult(\n\t\t\t\t\tpi,\n\t\t\t\t\t`未找到模型 \\`${args.trim()}\\`。请使用精确的 \\`provider/modelId\\` 或唯一的 \\`modelId\\`。\n\nAvailable models:\n${available}`,\n\t\t\t\t);\n\t\t\t},\n\t\t});\n\n\t\tpi.registerCommand(\"new\", {\n\t\t\tdescription: \"Start a new session\",\n\t\t\thandler: async (_args, ctx) => {\n\t\t\t\tconst result = await ctx.newSession();\n\t\t\t\tif (!result.cancelled) {\n\t\t\t\t\tawait options.refreshSessionResources();\n\t\t\t\t}\n\t\t\t\tsendCommandResult(\n\t\t\t\t\tpi,\n\t\t\t\t\tresult.cancelled\n\t\t\t\t\t\t? \"新会话已取消。\"\n\t\t\t\t\t\t: `已开启新会话。\\n\\nSession ID: \\`${ctx.sessionManager.getSessionId()}\\``,\n\t\t\t\t);\n\t\t\t},\n\t\t});\n\n\t\tpi.registerCommand(\"compact\", {\n\t\t\tdescription: \"Manually compact the current session context\",\n\t\t\thandler: async (args, ctx) => {\n\t\t\t\tconst customInstructions = args.trim() || undefined;\n\t\t\t\tconst result = await runCompact(ctx, customInstructions);\n\t\t\t\tsendCommandResult(\n\t\t\t\t\tpi,\n\t\t\t\t\t`已压缩当前会话上下文。\n\n- Tokens before compaction: \\`${result.tokensBefore}\\`\n- Summary:\n\n\\`\\`\\`text\n${result.summary}\n\\`\\`\\``,\n\t\t\t\t);\n\t\t\t},\n\t\t});\n\t};\n}\n"]}