engine7 7.1.64 → 7.1.66

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/cli.mjs CHANGED
@@ -105,7 +105,7 @@ async function pollRegistration(domain, deviceCode, interval, deadline, onLog, s
105
105
  if (res.client_id && res.client_secret) {
106
106
  return {
107
107
  appId: res.client_id,
108
- appSecret: res.client_secret,
108
+ appSecret: result.appSecret,
109
109
  openId: res.user_info?.open_id,
110
110
  domain: currentDomain
111
111
  };
@@ -138,13 +138,13 @@ async function registerFeishuApp(options = {}) {
138
138
  options.onQrCode?.(qrUrl);
139
139
  log(`\u8BF7\u7528\u98DE\u4E66 App \u626B\u63CF\u4E8C\u7EF4\u7801\uFF08${expireIn}\u79D2\u540E\u8FC7\u671F\uFF09...`);
140
140
  const deadline = Date.now() + Math.min(expireIn, timeoutSec) * 1e3;
141
- const result = await pollRegistration(domain, deviceCode, interval, deadline, log, options.signal);
142
- if (result) {
143
- log(`\u2705 \u6CE8\u518C\u6210\u529F\uFF01App ID: ${result.appId}`);
141
+ const result2 = await pollRegistration(domain, deviceCode, interval, deadline, log, options.signal);
142
+ if (result2) {
143
+ log(`\u2705 \u6CE8\u518C\u6210\u529F\uFF01App ID: ${result2.appId}`);
144
144
  } else {
145
145
  log("\u23F0 \u4E8C\u7EF4\u7801\u5DF2\u8FC7\u671F");
146
146
  }
147
- return result;
147
+ return result2;
148
148
  }
149
149
  function sleep(ms) {
150
150
  return new Promise((resolve11) => setTimeout(resolve11, ms));
@@ -407,20 +407,20 @@ function formatForWechat(content) {
407
407
  const m = l.match(/^#{1,4}\s+(.*)/);
408
408
  return m ? `\u3010${m[1].trim()}\u3011` : l;
409
409
  });
410
- const result = [];
410
+ const result2 = [];
411
411
  for (const line of lines) {
412
412
  if (line.trim().startsWith("|") && line.trim().endsWith("|")) {
413
413
  if (/^\|[\s:-]+\|$/.test(line.trim())) continue;
414
414
  const cells = line.trim().slice(1, -1).split("|").map((c) => c.trim());
415
415
  if (cells.every((c) => /^[-:]+$/.test(c))) continue;
416
- result.push(`\u2022 ${cells.join(" | ")}`);
416
+ result2.push(`\u2022 ${cells.join(" | ")}`);
417
417
  } else {
418
- result.push(line);
418
+ result2.push(line);
419
419
  }
420
420
  }
421
421
  const out = [];
422
422
  let prevBlank = false;
423
- for (const l of result) {
423
+ for (const l of result2) {
424
424
  if (!l.trim() && prevBlank) continue;
425
425
  out.push(l);
426
426
  prevBlank = !l.trim();
@@ -1324,7 +1324,8 @@ var init_features = __esm({
1324
1324
  var loader_exports = {};
1325
1325
  __export(loader_exports, {
1326
1326
  configSummary: () => configSummary,
1327
- loadConfig: () => loadConfig
1327
+ loadConfig: () => loadConfig,
1328
+ parseModelRef: () => parseModelRef
1328
1329
  });
1329
1330
  import * as fs2 from "node:fs";
1330
1331
  import * as path2 from "node:path";
@@ -2784,12 +2785,12 @@ var init_openai_provider = __esm({
2784
2785
  }, "openai", this.config.proxy);
2785
2786
  let response;
2786
2787
  while (true) {
2787
- const result = await retryGen.next();
2788
- if (result.done) {
2789
- response = result.value;
2788
+ const result2 = await retryGen.next();
2789
+ if (result2.done) {
2790
+ response = result2.value;
2790
2791
  break;
2791
2792
  }
2792
- const { type: _retryType, ...retryFields } = result.value;
2793
+ const { type: _retryType, ...retryFields } = result2.value;
2793
2794
  yield { type: "api_retry", ...retryFields };
2794
2795
  }
2795
2796
  if (!response.ok) {
@@ -3025,7 +3026,7 @@ var init_anthropic_provider = __esm({
3025
3026
  const toolResults = msg2.content.filter((b) => b.type === "tool_result");
3026
3027
  if (toolResults.length > 0) {
3027
3028
  const prev = repaired[repaired.length - 1];
3028
- const hasPrecedingToolUse = prev?.role === "assistant";
3029
+ const hasPrecedingToolUse = prev?.role === "assistant" && Array.isArray(prev.content) && prev.content.some((b) => b.type === "tool_use");
3029
3030
  if (!hasPrecedingToolUse) {
3030
3031
  const stripped = msg2.content.filter((b) => b.type !== "tool_result");
3031
3032
  if (stripped.length > 0) {
@@ -3152,12 +3153,12 @@ var init_anthropic_provider = __esm({
3152
3153
  }, "anthropic", this.config.proxy);
3153
3154
  let response;
3154
3155
  while (true) {
3155
- const result = await retryGen.next();
3156
- if (result.done) {
3157
- response = result.value;
3156
+ const result2 = await retryGen.next();
3157
+ if (result2.done) {
3158
+ response = result2.value;
3158
3159
  break;
3159
3160
  }
3160
- const { type: _retryType, ...retryFields } = result.value;
3161
+ const { type: _retryType, ...retryFields } = result2.value;
3161
3162
  yield { type: "api_retry", ...retryFields };
3162
3163
  }
3163
3164
  if (!response.ok) {
@@ -3521,12 +3522,12 @@ var init_gemini_provider = __esm({
3521
3522
  }, "gemini", this.config.proxy);
3522
3523
  let response;
3523
3524
  while (true) {
3524
- const result = await retryGen.next();
3525
- if (result.done) {
3526
- response = result.value;
3525
+ const result2 = await retryGen.next();
3526
+ if (result2.done) {
3527
+ response = result2.value;
3527
3528
  break;
3528
3529
  }
3529
- const { type: _retryType, ...retryFields } = result.value;
3530
+ const { type: _retryType, ...retryFields } = result2.value;
3530
3531
  yield { type: "api_retry", ...retryFields };
3531
3532
  }
3532
3533
  if (!response.ok) {
@@ -3860,21 +3861,21 @@ function parseHookOutput(stdout) {
3860
3861
  }
3861
3862
  function processHookJSONOutput(params) {
3862
3863
  const { json, command, hookEvent, stdout, stderr, exitCode, durationMs } = params;
3863
- const result = {};
3864
+ const result2 = {};
3864
3865
  if (json.continue === false) {
3865
- result.preventContinuation = true;
3866
+ result2.preventContinuation = true;
3866
3867
  if (json.stopReason) {
3867
- result.stopReason = json.stopReason;
3868
+ result2.stopReason = json.stopReason;
3868
3869
  }
3869
3870
  }
3870
3871
  if (json.decision) {
3871
3872
  switch (json.decision) {
3872
3873
  case "approve":
3873
- result.permissionBehavior = "allow";
3874
+ result2.permissionBehavior = "allow";
3874
3875
  break;
3875
3876
  case "block":
3876
- result.permissionBehavior = "deny";
3877
- result.blockingError = {
3877
+ result2.permissionBehavior = "deny";
3878
+ result2.blockingError = {
3878
3879
  blockingError: json.reason || "Blocked by hook",
3879
3880
  command
3880
3881
  };
@@ -3882,41 +3883,41 @@ function processHookJSONOutput(params) {
3882
3883
  }
3883
3884
  }
3884
3885
  if (json.systemMessage) {
3885
- result.message = `[hook] ${json.systemMessage}`;
3886
+ result2.message = `[hook] ${json.systemMessage}`;
3886
3887
  }
3887
3888
  if (json.hookSpecificOutput) {
3888
3889
  const hso = json.hookSpecificOutput;
3889
3890
  if ("permissionDecision" in hso && hso.permissionDecision) {
3890
3891
  switch (hso.permissionDecision) {
3891
3892
  case "allow":
3892
- result.permissionBehavior = "allow";
3893
+ result2.permissionBehavior = "allow";
3893
3894
  break;
3894
3895
  case "deny":
3895
- result.permissionBehavior = "deny";
3896
+ result2.permissionBehavior = "deny";
3896
3897
  break;
3897
3898
  case "ask":
3898
- result.permissionBehavior = "ask";
3899
+ result2.permissionBehavior = "ask";
3899
3900
  break;
3900
3901
  }
3901
3902
  if ("permissionDecisionReason" in hso) {
3902
- result.hookPermissionDecisionReason = hso.permissionDecisionReason;
3903
+ result2.hookPermissionDecisionReason = hso.permissionDecisionReason;
3903
3904
  }
3904
3905
  if ("updatedInput" in hso && hso.updatedInput) {
3905
- result.updatedInput = hso.updatedInput;
3906
+ result2.updatedInput = hso.updatedInput;
3906
3907
  }
3907
3908
  }
3908
3909
  if ("additionalContext" in hso && hso.additionalContext) {
3909
- result.additionalContext = hso.additionalContext;
3910
+ result2.additionalContext = hso.additionalContext;
3910
3911
  }
3911
3912
  if ("initialUserMessage" in hso && hso.initialUserMessage) {
3912
- result.initialUserMessage = hso.initialUserMessage;
3913
+ result2.initialUserMessage = hso.initialUserMessage;
3913
3914
  }
3914
3915
  }
3915
- if (!result.blockingError) {
3916
+ if (!result2.blockingError) {
3916
3917
  const elapsed = durationMs ? ` (${durationMs}ms)` : "";
3917
- result.message = result.message || `[hook:${hookEvent}] success${elapsed}`;
3918
+ result2.message = result2.message || `[hook:${hookEvent}] success${elapsed}`;
3918
3919
  }
3919
- return result;
3920
+ return result2;
3920
3921
  }
3921
3922
  async function execCommandHook(hook, hookEvent, hookName, jsonInput, signal, hookId, ctx) {
3922
3923
  const hookTimeoutMs = hook.timeout ? hook.timeout * 1e3 : TOOL_HOOK_EXECUTION_TIMEOUT_MS;
@@ -4022,17 +4023,17 @@ async function executeOneHook(hook, hookEvent, hookName, hookInput, toolUseID, s
4022
4023
  };
4023
4024
  }
4024
4025
  const jsonInput = JSON.stringify(hookInput);
4025
- const result = await execCommandHook(hook, hookEvent, hookName, jsonInput, signal, hookId, ctx);
4026
+ const result2 = await execCommandHook(hook, hookEvent, hookName, jsonInput, signal, hookId, ctx);
4026
4027
  const durationMs = Date.now() - startMs;
4027
- if (result.aborted) {
4028
+ if (result2.aborted) {
4028
4029
  return {
4029
4030
  outcome: "cancelled",
4030
4031
  message: `[hook:${hookEvent}] cancelled`,
4031
4032
  hook
4032
4033
  };
4033
4034
  }
4034
- if (result.status === 2) {
4035
- const blockingError = result.stderr || result.stdout || "Blocked by hook";
4035
+ if (result2.status === 2) {
4036
+ const blockingError = result2.stderr || result2.stdout || "Blocked by hook";
4036
4037
  return {
4037
4038
  outcome: "blocking",
4038
4039
  blockingError: { blockingError, command: hook.command },
@@ -4040,22 +4041,22 @@ async function executeOneHook(hook, hookEvent, hookName, hookInput, toolUseID, s
4040
4041
  hook
4041
4042
  };
4042
4043
  }
4043
- if (result.status !== 0) {
4044
+ if (result2.status !== 0) {
4044
4045
  return {
4045
4046
  outcome: "non_blocking_error",
4046
- message: `[hook:${hookEvent}] error (exit ${result.status}): ${result.stderr || result.stdout}`,
4047
+ message: `[hook:${hookEvent}] error (exit ${result2.status}): ${result2.stderr || result2.stdout}`,
4047
4048
  hook
4048
4049
  };
4049
4050
  }
4050
- const parsed = parseHookOutput(result.stdout);
4051
+ const parsed = parseHookOutput(result2.stdout);
4051
4052
  if (parsed.json && isSyncHookJSONOutput(parsed.json)) {
4052
4053
  const processed = processHookJSONOutput({
4053
4054
  json: parsed.json,
4054
4055
  command: hook.command,
4055
4056
  hookEvent,
4056
- stdout: result.stdout,
4057
- stderr: result.stderr,
4058
- exitCode: result.status,
4057
+ stdout: result2.stdout,
4058
+ stderr: result2.stderr,
4059
+ exitCode: result2.status,
4059
4060
  durationMs
4060
4061
  });
4061
4062
  return {
@@ -4064,7 +4065,7 @@ async function executeOneHook(hook, hookEvent, hookName, hookInput, toolUseID, s
4064
4065
  hook
4065
4066
  };
4066
4067
  }
4067
- const textOutput = parsed.plainText || result.stdout || "";
4068
+ const textOutput = parsed.plainText || result2.stdout || "";
4068
4069
  if (textOutput && (hookEvent === "UserPromptSubmit" || hookEvent === "SessionStart")) {
4069
4070
  return {
4070
4071
  outcome: "success",
@@ -4091,31 +4092,31 @@ function aggregateResults(results) {
4091
4092
  additionalContexts: []
4092
4093
  };
4093
4094
  let hasBlocking = false;
4094
- for (const result of results) {
4095
- if (result.blockingError) {
4096
- aggregated.blockingError = result.blockingError;
4095
+ for (const result2 of results) {
4096
+ if (result2.blockingError) {
4097
+ aggregated.blockingError = result2.blockingError;
4097
4098
  hasBlocking = true;
4098
4099
  }
4099
- if (result.preventContinuation) {
4100
+ if (result2.preventContinuation) {
4100
4101
  aggregated.preventContinuation = true;
4101
4102
  }
4102
- if (result.stopReason) {
4103
- aggregated.stopReason = result.stopReason;
4103
+ if (result2.stopReason) {
4104
+ aggregated.stopReason = result2.stopReason;
4104
4105
  }
4105
- if (result.permissionBehavior) {
4106
- aggregated.permissionBehavior = result.permissionBehavior;
4106
+ if (result2.permissionBehavior) {
4107
+ aggregated.permissionBehavior = result2.permissionBehavior;
4107
4108
  }
4108
- if (result.additionalContext) {
4109
- aggregated.additionalContexts.push(result.additionalContext);
4109
+ if (result2.additionalContext) {
4110
+ aggregated.additionalContexts.push(result2.additionalContext);
4110
4111
  }
4111
- if (result.initialUserMessage) {
4112
- aggregated.initialUserMessage = result.initialUserMessage;
4112
+ if (result2.initialUserMessage) {
4113
+ aggregated.initialUserMessage = result2.initialUserMessage;
4113
4114
  }
4114
- if (result.updatedInput) {
4115
- aggregated.updatedInput = result.updatedInput;
4115
+ if (result2.updatedInput) {
4116
+ aggregated.updatedInput = result2.updatedInput;
4116
4117
  }
4117
- if (result.message && !result.blockingError) {
4118
- aggregated.message = result.message;
4118
+ if (result2.message && !result2.blockingError) {
4119
+ aggregated.message = result2.message;
4119
4120
  }
4120
4121
  }
4121
4122
  if (aggregated.additionalContexts.length === 0) {
@@ -4365,9 +4366,9 @@ async function executeOne(tc, ctx, signal) {
4365
4366
  if (preResult.updatedInput) {
4366
4367
  args = { ...args, ...preResult.updatedInput };
4367
4368
  }
4368
- const result = await tool.handler(args, ctx, signal);
4369
- await executePostToolUseHooks(tc.function.name, args, result.content, hookCtx, signal);
4370
- return { call: tc, result, summary: null };
4369
+ const result2 = await tool.handler(args, ctx, signal);
4370
+ await executePostToolUseHooks(tc.function.name, args, result2.content, hookCtx, signal);
4371
+ return { call: tc, result: result2, summary: null };
4371
4372
  } catch (err) {
4372
4373
  await executePostToolUseFailureHooks(tc.function.name, args, err.message, hookCtx, signal);
4373
4374
  return { call: tc, result: { content: `Tool error: ${err.message}`, isError: true }, summary: null };
@@ -5138,7 +5139,7 @@ function maybeTimeBasedMicrocompact(messages, gapThresholdMinutes = TIME_BASED_M
5138
5139
  const clearSet = new Set(compactableToolCallIds.filter((id) => !keepSet.has(id)));
5139
5140
  if (clearSet.size === 0) return null;
5140
5141
  let tokensSaved = 0;
5141
- const result = messages.map((msg2) => {
5142
+ const result2 = messages.map((msg2) => {
5142
5143
  if (msg2.role !== "tool") return msg2;
5143
5144
  if (!msg2.tool_call_id || !clearSet.has(msg2.tool_call_id)) return msg2;
5144
5145
  if (msg2.content === TIME_BASED_MC_CLEARED_MESSAGE) return msg2;
@@ -5151,7 +5152,7 @@ function maybeTimeBasedMicrocompact(messages, gapThresholdMinutes = TIME_BASED_M
5151
5152
  if (tokensSaved === 0) return null;
5152
5153
  const clearedIds = [...clearSet].map((id) => id.slice(0, 8)).join(",");
5153
5154
  compactLog(TAG2, `Cleared ${clearSet.size} old tool results (~${tokensSaved} tokens), kept last ${keepSet.size} (cleared IDs: ${clearedIds})`);
5154
- return { messages: result, tokensSaved };
5155
+ return { messages: result2, tokensSaved };
5155
5156
  }
5156
5157
  function microcompactMessages(messages) {
5157
5158
  const toolMsgCount = messages.filter((m) => m.role === "tool").length;
@@ -5234,10 +5235,10 @@ function smartCompressToolResult(content, essentialFields, sizeLimit) {
5234
5235
  }
5235
5236
  }
5236
5237
  if (mini.length > 0) {
5237
- const result = JSON.stringify(mini, null, 0);
5238
- if (result.length < content.length * 0.3) {
5238
+ const result2 = JSON.stringify(mini, null, 0);
5239
+ if (result2.length < content.length * 0.3) {
5239
5240
  return `[Extracted ${mini.length}/${data.length} items]
5240
- ${result}`;
5241
+ ${result2}`;
5241
5242
  }
5242
5243
  }
5243
5244
  }
@@ -5301,7 +5302,7 @@ function splitByUserTurns(messages) {
5301
5302
  function step1_smartExtract(messages, essentialFields) {
5302
5303
  let compressed = 0;
5303
5304
  const largeToolResults = [];
5304
- const result = messages.map((m) => {
5305
+ const result2 = messages.map((m) => {
5305
5306
  if (m.role === "tool" && typeof m.content === "string" && m.content.length > TOOL_SIZE_LIMIT) {
5306
5307
  const originalLen = m.content.length;
5307
5308
  largeToolResults.push(`tool_call_id=${m.tool_call_id?.slice(0, 8)}... ${originalLen}chars`);
@@ -5317,7 +5318,7 @@ function step1_smartExtract(messages, essentialFields) {
5317
5318
  if (largeToolResults.length > 0 && compressed === 0) {
5318
5319
  compactLog(TAG3, `Step 1 smartExtract: found ${largeToolResults.length} large tool results but none could be compressed`);
5319
5320
  }
5320
- return { messages: result, compressed };
5321
+ return { messages: result2, compressed };
5321
5322
  }
5322
5323
  function step2_compressOldTurns(messages, maxTokens, toolResultMode = "minimal") {
5323
5324
  const { system, turns } = splitByUserTurns(messages);
@@ -5366,7 +5367,7 @@ function step2_compressOldTurns(messages, maxTokens, toolResultMode = "minimal")
5366
5367
  function step3_truncateLarge(messages) {
5367
5368
  let truncated = 0;
5368
5369
  const details = [];
5369
- const result = messages.map((m) => {
5370
+ const result2 = messages.map((m) => {
5370
5371
  if (m.role === "tool" && typeof m.content === "string" && m.content.length > TOOL_SIZE_LIMIT) {
5371
5372
  const originalLen = m.content.length;
5372
5373
  truncated++;
@@ -5381,7 +5382,7 @@ function step3_truncateLarge(messages) {
5381
5382
  if (truncated > 0) {
5382
5383
  compactLog(TAG3, `Step 3 truncateLarge: ${truncated} tool results truncated (${details.join("; ")})`);
5383
5384
  }
5384
- return { messages: result, truncated };
5385
+ return { messages: result2, truncated };
5385
5386
  }
5386
5387
  function step4_fifoDelete(messages, maxTokens) {
5387
5388
  if (estimateMessageTokens(messages) <= maxTokens) {
@@ -5475,7 +5476,7 @@ var init_ruleCompact = __esm({
5475
5476
  // src/compact/autoCompact.ts
5476
5477
  function stripImageBlocks(messages) {
5477
5478
  let stripped = 0;
5478
- const result = messages.map((m) => {
5479
+ const result2 = messages.map((m) => {
5479
5480
  if (isAttachmentMessage(m) || typeof m.content === "string" || !m.content) return m;
5480
5481
  const filtered = m.content.filter((b) => {
5481
5482
  if (b.type === "image") {
@@ -5488,7 +5489,7 @@ function stripImageBlocks(messages) {
5488
5489
  if (filtered.length === 1 && filtered[0].type === "text") return { ...m, content: filtered[0].text };
5489
5490
  return { ...m, content: filtered };
5490
5491
  });
5491
- return { messages: result, stripped };
5492
+ return { messages: result2, stripped };
5492
5493
  }
5493
5494
  function getEffectiveContextWindowSize(config) {
5494
5495
  const contextWindow = config.contextWindow || DEFAULT_COMPACT_CONFIG.contextWindow;
@@ -5507,9 +5508,9 @@ function shouldAutoCompact(messages, config) {
5507
5508
  }
5508
5509
  const tokenCount = estimateMessageTokens(messages);
5509
5510
  const threshold = getAutoCompactThreshold(config);
5510
- const result = tokenCount >= threshold;
5511
- compactLog(TAG4, `tokens=${tokenCount} threshold=${threshold} triggered=${result}`);
5512
- return result;
5511
+ const result2 = tokenCount >= threshold;
5512
+ compactLog(TAG4, `tokens=${tokenCount} threshold=${threshold} triggered=${result2}`);
5513
+ return result2;
5513
5514
  }
5514
5515
  async function autoCompactIfNeeded(messages, config, tracking, provider, model, signal, hookCtx) {
5515
5516
  if (config.enabled === false) {
@@ -6237,7 +6238,7 @@ var init_query = __esm({
6237
6238
  type: "status",
6238
6239
  text: `\u{1F9F9} Compacting context (${currentMessages.length} messages) so I can continue without losing history...`
6239
6240
  };
6240
- const result = await autoCompactIfNeeded(
6241
+ const result2 = await autoCompactIfNeeded(
6241
6242
  currentMessages,
6242
6243
  this.compactConfig,
6243
6244
  this.autoCompactTracking,
@@ -6251,25 +6252,25 @@ var init_query = __esm({
6251
6252
  cwd: context.workspace || process.env.ENGINE_WORKSPACE || ""
6252
6253
  } : void 0
6253
6254
  );
6254
- if (result.wasCompacted) {
6255
- currentMessages = result.messages;
6255
+ if (result2.wasCompacted) {
6256
+ currentMessages = result2.messages;
6256
6257
  this.autoCompactTracking.compacted = true;
6257
- this.autoCompactTracking.consecutiveFailures = result.consecutiveFailures;
6258
- console.log(`${this.logPrefix} Post-compact: ${currentMessages.length} messages, failures=${result.consecutiveFailures}`);
6259
- if (result.compactionResult) {
6258
+ this.autoCompactTracking.consecutiveFailures = result2.consecutiveFailures;
6259
+ console.log(`${this.logPrefix} Post-compact: ${currentMessages.length} messages, failures=${result2.consecutiveFailures}`);
6260
+ if (result2.compactionResult) {
6260
6261
  yield {
6261
6262
  type: "compact",
6262
- preTokens: result.compactionResult.preCompactTokenCount,
6263
- postTokens: result.compactionResult.postCompactTokenCount,
6263
+ preTokens: result2.compactionResult.preCompactTokenCount,
6264
+ postTokens: result2.compactionResult.postCompactTokenCount,
6264
6265
  messages: currentMessages
6265
6266
  };
6266
6267
  yield {
6267
6268
  type: "status",
6268
- text: `\u2705 Context compacted (${result.compactionResult.preCompactTokenCount.toLocaleString()} \u2192 ${result.compactionResult.postCompactTokenCount.toLocaleString()} tokens). Continuing from where I left off.`
6269
+ text: `\u2705 Context compacted (${result2.compactionResult.preCompactTokenCount.toLocaleString()} \u2192 ${result2.compactionResult.postCompactTokenCount.toLocaleString()} tokens). Continuing from where I left off.`
6269
6270
  };
6270
6271
  }
6271
6272
  } else {
6272
- this.autoCompactTracking.consecutiveFailures = result.consecutiveFailures;
6273
+ this.autoCompactTracking.consecutiveFailures = result2.consecutiveFailures;
6273
6274
  }
6274
6275
  this.pendingFlushTurns = 0;
6275
6276
  }
@@ -7281,13 +7282,13 @@ function recoverOrphanedParallelToolResults(allEntries, chain, byUuid, seen) {
7281
7282
  }
7282
7283
  if (recoveredCount === 0) return chain;
7283
7284
  console.log(`[reader] Recovered ${recoveredCount} orphaned parallel tool results`);
7284
- const result = [];
7285
+ const result2 = [];
7285
7286
  for (const m of chain) {
7286
- result.push(m);
7287
+ result2.push(m);
7287
7288
  const toInsert = inserts.get(m.uuid);
7288
- if (toInsert) result.push(...toInsert);
7289
+ if (toInsert) result2.push(...toInsert);
7289
7290
  }
7290
- return result;
7291
+ return result2;
7291
7292
  }
7292
7293
  async function readSessionHistory(filePath) {
7293
7294
  const stat4 = fs7.statSync(filePath);
@@ -7405,18 +7406,18 @@ function entryToSessionMessage(entry) {
7405
7406
  if (block.thinkingSignature) thinkingSig = block.thinkingSignature;
7406
7407
  }
7407
7408
  }
7408
- const result = {
7409
+ const result2 = {
7409
7410
  role: "assistant",
7410
7411
  content: textContent,
7411
7412
  timestamp: entry.timestamp,
7412
7413
  _raw: entry.raw
7413
7414
  };
7414
- if (thinkingContent) result.reasoning_content = thinkingContent;
7415
- if (thinkingSig) result.thinking_signature = thinkingSig;
7415
+ if (thinkingContent) result2.reasoning_content = thinkingContent;
7416
+ if (thinkingSig) result2.thinking_signature = thinkingSig;
7416
7417
  if (toolCalls.length > 0) {
7417
- result.tool_calls = toolCalls;
7418
+ result2.tool_calls = toolCalls;
7418
7419
  }
7419
- return result;
7420
+ return result2;
7420
7421
  } else if (role === "toolResult") {
7421
7422
  const text = extractText2(m.content);
7422
7423
  return {
@@ -8244,9 +8245,9 @@ ${items.join("\n")}` };
8244
8245
  let content;
8245
8246
  let encoding;
8246
8247
  try {
8247
- const result2 = readFileContent(filePath);
8248
- content = result2.content;
8249
- encoding = result2.encoding;
8248
+ const result3 = readFileContent(filePath);
8249
+ content = result3.content;
8250
+ encoding = result3.encoding;
8250
8251
  } catch (e) {
8251
8252
  return { content: e.message, isError: true };
8252
8253
  }
@@ -8263,7 +8264,7 @@ ${items.join("\n")}` };
8263
8264
  const mtime = new Date(stat4.mtimeMs).toLocaleString();
8264
8265
  const info = encoding !== "utf8" ? `[${encoding}] ` : "";
8265
8266
  const header = `${info}${filePath} (${totalLines} \u884C, ${stat4.size} bytes, \u4FEE\u6539: ${mtime})`;
8266
- const result = [
8267
+ const result2 = [
8267
8268
  header,
8268
8269
  "\u2500".repeat(60),
8269
8270
  numbered.join("\n"),
@@ -8272,7 +8273,7 @@ ${items.join("\n")}` };
8272
8273
  ].join("\n");
8273
8274
  return { content: loopWarning ? `${loopWarning}
8274
8275
 
8275
- ${result}` : result };
8276
+ ${result2}` : result2 };
8276
8277
  },
8277
8278
  isConcurrencySafe: () => true,
8278
8279
  isReadOnly: () => true
@@ -8484,19 +8485,19 @@ function isOpeningContext(chars, index) {
8484
8485
  }
8485
8486
  function applyCurlyDoubleQuotes(str) {
8486
8487
  const chars = [...str];
8487
- const result = [];
8488
+ const result2 = [];
8488
8489
  for (let i = 0; i < chars.length; i++) {
8489
8490
  if (chars[i] === '"') {
8490
- result.push(isOpeningContext(chars, i) ? LEFT_DOUBLE_CURLY : RIGHT_DOUBLE_CURLY);
8491
+ result2.push(isOpeningContext(chars, i) ? LEFT_DOUBLE_CURLY : RIGHT_DOUBLE_CURLY);
8491
8492
  } else {
8492
- result.push(chars[i]);
8493
+ result2.push(chars[i]);
8493
8494
  }
8494
8495
  }
8495
- return result.join("");
8496
+ return result2.join("");
8496
8497
  }
8497
8498
  function applyCurlySingleQuotes(str) {
8498
8499
  const chars = [...str];
8499
- const result = [];
8500
+ const result2 = [];
8500
8501
  for (let i = 0; i < chars.length; i++) {
8501
8502
  if (chars[i] === "'") {
8502
8503
  const prev = i > 0 ? chars[i - 1] : void 0;
@@ -8504,25 +8505,25 @@ function applyCurlySingleQuotes(str) {
8504
8505
  const prevIsLetter = prev !== void 0 && /\p{L}/u.test(prev);
8505
8506
  const nextIsLetter = next !== void 0 && /\p{L}/u.test(next);
8506
8507
  if (prevIsLetter && nextIsLetter) {
8507
- result.push(RIGHT_SINGLE_CURLY);
8508
+ result2.push(RIGHT_SINGLE_CURLY);
8508
8509
  } else {
8509
- result.push(isOpeningContext(chars, i) ? LEFT_SINGLE_CURLY : RIGHT_SINGLE_CURLY);
8510
+ result2.push(isOpeningContext(chars, i) ? LEFT_SINGLE_CURLY : RIGHT_SINGLE_CURLY);
8510
8511
  }
8511
8512
  } else {
8512
- result.push(chars[i]);
8513
+ result2.push(chars[i]);
8513
8514
  }
8514
8515
  }
8515
- return result.join("");
8516
+ return result2.join("");
8516
8517
  }
8517
8518
  function preserveQuoteStyle(oldString, actualOldString, newString) {
8518
8519
  if (oldString === actualOldString) return newString;
8519
8520
  const hasDouble = actualOldString.includes(LEFT_DOUBLE_CURLY) || actualOldString.includes(RIGHT_DOUBLE_CURLY);
8520
8521
  const hasSingle = actualOldString.includes(LEFT_SINGLE_CURLY) || actualOldString.includes(RIGHT_SINGLE_CURLY);
8521
8522
  if (!hasDouble && !hasSingle) return newString;
8522
- let result = newString;
8523
- if (hasDouble) result = applyCurlyDoubleQuotes(result);
8524
- if (hasSingle) result = applyCurlySingleQuotes(result);
8525
- return result;
8523
+ let result2 = newString;
8524
+ if (hasDouble) result2 = applyCurlyDoubleQuotes(result2);
8525
+ if (hasSingle) result2 = applyCurlySingleQuotes(result2);
8526
+ return result2;
8526
8527
  }
8527
8528
  function applyEditToFile(originalContent, oldString, newString, replaceAll = false) {
8528
8529
  const f = replaceAll ? (content, search2, replace) => content.replaceAll(search2, () => replace) : (content, search2, replace) => content.replace(search2, () => replace);
@@ -8545,23 +8546,23 @@ function generateEditDiff(fileContent, actualOldString, actualNewString, context
8545
8546
  const oldLines = actualOldString.split(/\r?\n/);
8546
8547
  const newLines = actualNewString.split(/\r?\n/);
8547
8548
  const fileLines = fileContent.split(/\r?\n/);
8548
- const result = [];
8549
+ const result2 = [];
8549
8550
  const ctxStart = Math.max(0, startLine - contextLines);
8550
8551
  for (let i = ctxStart; i < startLine; i++) {
8551
- result.push(` ${fileLines[i] ?? ""}`);
8552
+ result2.push(` ${fileLines[i] ?? ""}`);
8552
8553
  }
8553
8554
  for (let i = 0; i < oldLines.length; i++) {
8554
- result.push(`-${oldLines[i]}`);
8555
+ result2.push(`-${oldLines[i]}`);
8555
8556
  }
8556
8557
  for (let i = 0; i < newLines.length; i++) {
8557
- result.push(`+${newLines[i]}`);
8558
+ result2.push(`+${newLines[i]}`);
8558
8559
  }
8559
8560
  const afterStart = startLine + oldLines.length;
8560
8561
  const afterEnd = Math.min(fileLines.length, afterStart + contextLines);
8561
8562
  for (let i = afterStart; i < afterEnd; i++) {
8562
- result.push(` ${fileLines[i] ?? ""}`);
8563
+ result2.push(` ${fileLines[i] ?? ""}`);
8563
8564
  }
8564
- return result.join("\n");
8565
+ return result2.join("\n");
8565
8566
  }
8566
8567
  var LEFT_SINGLE_CURLY, RIGHT_SINGLE_CURLY, LEFT_DOUBLE_CURLY, RIGHT_DOUBLE_CURLY, MAX_EDIT_FILE_SIZE;
8567
8568
  var init_edit = __esm({
@@ -8948,19 +8949,19 @@ var init_grep = __esm({
8948
8949
  rgArgs.push("--glob", p);
8949
8950
  }
8950
8951
  }
8951
- const result = await ripGrep(rgArgs, searchPath);
8952
- if (result.timedOut) {
8952
+ const result2 = await ripGrep(rgArgs, searchPath);
8953
+ if (result2.timedOut) {
8953
8954
  return {
8954
8955
  content: `\u641C\u7D22\u8D85\u65F6\uFF08${RG_TIMEOUT_MS / 1e3}\u79D2\uFF09\u3002\u5C1D\u8BD5\u7F29\u5C0F\u641C\u7D22\u8303\u56F4\u6216\u4F7F\u7528\u66F4\u5177\u4F53\u7684 pattern\u3002`,
8955
8956
  isError: true
8956
8957
  };
8957
8958
  }
8958
- if (result.lines.length === 0) {
8959
+ if (result2.lines.length === 0) {
8959
8960
  return { content: "No files found" };
8960
8961
  }
8961
8962
  const cwd = ctx.workspace;
8962
8963
  if (outputMode === "content") {
8963
- const { items: limited2, appliedLimit: appliedLimit2 } = applyHeadLimit(result.lines, headLimit, offset);
8964
+ const { items: limited2, appliedLimit: appliedLimit2 } = applyHeadLimit(result2.lines, headLimit, offset);
8964
8965
  const finalLines = limited2.map((line) => {
8965
8966
  const colonIdx = line.indexOf(":");
8966
8967
  if (colonIdx > 0) {
@@ -8978,7 +8979,7 @@ var init_grep = __esm({
8978
8979
  return { content: content + suffix2 };
8979
8980
  }
8980
8981
  if (outputMode === "count") {
8981
- const { items: limited2, appliedLimit: appliedLimit2 } = applyHeadLimit(result.lines, headLimit, offset);
8982
+ const { items: limited2, appliedLimit: appliedLimit2 } = applyHeadLimit(result2.lines, headLimit, offset);
8982
8983
  const finalLines = limited2.map((line) => {
8983
8984
  const colonIdx = line.lastIndexOf(":");
8984
8985
  if (colonIdx > 0) {
@@ -9000,7 +9001,7 @@ var init_grep = __esm({
9000
9001
  Found ${totalMatches} total occurrences across ${limited2.length} files.${limitInfo2 ? ` with pagination = ${limitInfo2}` : ""}`;
9001
9002
  return { content: content + summary };
9002
9003
  }
9003
- const { items: limited, appliedLimit } = applyHeadLimit(result.lines, headLimit, offset);
9004
+ const { items: limited, appliedLimit } = applyHeadLimit(result2.lines, headLimit, offset);
9004
9005
  const filenames = limited.map((line) => {
9005
9006
  const colonIdx = line.indexOf(":");
9006
9007
  const fpath = colonIdx > 0 ? line.substring(0, colonIdx) : line;
@@ -9330,17 +9331,17 @@ function getBackgroundUsageNote() {
9330
9331
  return "You can use the `run_in_background` parameter to run the command in the background. Only use this if you don't need the result immediately and are OK being notified when the command completes later. You do not need to check the output right away - you'll be notified when it finishes. You do not need to use '&' at the end of the command when using this parameter.";
9331
9332
  }
9332
9333
  function prependBullets2(items) {
9333
- const result = [];
9334
+ const result2 = [];
9334
9335
  for (const item of items) {
9335
9336
  if (Array.isArray(item)) {
9336
9337
  for (const sub of item) {
9337
- result.push(` - ${sub}`);
9338
+ result2.push(` - ${sub}`);
9338
9339
  }
9339
9340
  } else {
9340
- result.push(`- ${item}`);
9341
+ result2.push(`- ${item}`);
9341
9342
  }
9342
9343
  }
9343
- return result;
9344
+ return result2;
9344
9345
  }
9345
9346
  function getExecPrompt() {
9346
9347
  const toolPreferenceItems = [
@@ -9428,17 +9429,17 @@ function isDestructiveCommand(command) {
9428
9429
  return DESTRUCTIVE_PATTERNS.some((p) => p.test(trimmed));
9429
9430
  }
9430
9431
  function sanitizeEnv(env) {
9431
- const result = {};
9432
+ const result2 = {};
9432
9433
  for (const [k, v] of Object.entries(env)) {
9433
9434
  if (ENV_ALLOW_KEYS.includes(k)) {
9434
- result[k] = v;
9435
+ result2[k] = v;
9435
9436
  continue;
9436
9437
  }
9437
9438
  if (!BLOCKED_ENV_KEYS.some((b) => k.toUpperCase().includes(b))) {
9438
- result[k] = v;
9439
+ result2[k] = v;
9439
9440
  }
9440
9441
  }
9441
- return result;
9442
+ return result2;
9442
9443
  }
9443
9444
  var DANGEROUS_COMMANDS, DESTRUCTIVE_PATTERNS, BLOCKED_ENV_KEYS, ENV_ALLOW_KEYS;
9444
9445
  var init_bashSecurity = __esm({
@@ -9559,12 +9560,12 @@ function findShell() {
9559
9560
  return cachedShell;
9560
9561
  }
9561
9562
  try {
9562
- const result = execSync("where.exe bash", {
9563
+ const result2 = execSync("where.exe bash", {
9563
9564
  encoding: "utf-8",
9564
9565
  timeout: 5e3,
9565
9566
  stdio: ["ignore", "pipe", "ignore"]
9566
9567
  });
9567
- const candidates = result.trim().split(/\r?\n/).map((s) => s.trim()).filter(Boolean);
9568
+ const candidates = result2.trim().split(/\r?\n/).map((s) => s.trim()).filter(Boolean);
9568
9569
  const nonWsl = candidates.find((p) => !isWslBash(p));
9569
9570
  if (nonWsl && fs14.existsSync(nonWsl)) {
9570
9571
  cachedShell = { shell: nonWsl, args: ["-c"] };
@@ -10298,7 +10299,7 @@ async function runAgent(opts) {
10298
10299
  console.warn(`[agent:${agentId}] No visualRegistry in context, cannot bind Discord channel for "${visualName}"`);
10299
10300
  }
10300
10301
  }
10301
- let result = "";
10302
+ let result2 = "";
10302
10303
  let toolUseCount = 0;
10303
10304
  try {
10304
10305
  for await (const chunk of subEngine.query(messages, runAbort.signal, opts.context)) {
@@ -10329,12 +10330,12 @@ async function runAgent(opts) {
10329
10330
  }
10330
10331
  }
10331
10332
  if (chunk.type === "text" && chunk.text) {
10332
- result += chunk.text;
10333
+ result2 += chunk.text;
10333
10334
  }
10334
10335
  if (chunk.type === "result") {
10335
10336
  const resultContent = chunk.content;
10336
10337
  if (resultContent) {
10337
- result = resultContent;
10338
+ result2 = resultContent;
10338
10339
  }
10339
10340
  }
10340
10341
  }
@@ -10342,11 +10343,11 @@ async function runAgent(opts) {
10342
10343
  agentRegistry.unregister(agentId);
10343
10344
  }
10344
10345
  const durationMs = Date.now() - startTime;
10345
- console.log(`[agent:${agentId}] ${agentDef.agentType} completed in ${durationMs}ms, ${toolUseCount} tools, ${result.length} chars`);
10346
+ console.log(`[agent:${agentId}] ${agentDef.agentType} completed in ${durationMs}ms, ${toolUseCount} tools, ${result2.length} chars`);
10346
10347
  return {
10347
10348
  agentId,
10348
10349
  agentType: agentDef.agentType,
10349
- content: result || "(no output from agent)",
10350
+ content: result2 || "(no output from agent)",
10350
10351
  totalToolUseCount: toolUseCount,
10351
10352
  totalDurationMs: durationMs
10352
10353
  };
@@ -11492,7 +11493,7 @@ var init_AgentTool = __esm({
11492
11493
  console.log(`[AgentTool] Background requested but running synchronously (headless limitation)`);
11493
11494
  }
11494
11495
  try {
11495
- const result = await runAgent({
11496
+ const result2 = await runAgent({
11496
11497
  prompt,
11497
11498
  description,
11498
11499
  subagentType,
@@ -11509,9 +11510,9 @@ var init_AgentTool = __esm({
11509
11510
  // visual 系统用这个 name 创建频道
11510
11511
  });
11511
11512
  const parts = [
11512
- result.content,
11513
+ result2.content,
11513
11514
  "",
11514
- `[Agent: ${result.agentType}, ${result.totalDurationMs}ms, ${result.totalToolUseCount} tool uses]`
11515
+ `[Agent: ${result2.agentType}, ${result2.totalDurationMs}ms, ${result2.totalToolUseCount} tool uses]`
11515
11516
  ];
11516
11517
  visualEmitter?.emitAgentDone(agentLabel);
11517
11518
  return {
@@ -12308,7 +12309,7 @@ var init_my_eyes = __esm({
12308
12309
  ]
12309
12310
  };
12310
12311
  try {
12311
- let result = "";
12312
+ let result2 = "";
12312
12313
  const stream = provider.streamChat({
12313
12314
  model: modelId,
12314
12315
  messages: [userMsg],
@@ -12318,13 +12319,13 @@ var init_my_eyes = __esm({
12318
12319
  });
12319
12320
  for await (const chunk of stream) {
12320
12321
  if (chunk.type === "text" && chunk.text) {
12321
- result += chunk.text;
12322
+ result2 += chunk.text;
12322
12323
  }
12323
12324
  }
12324
- if (!result.trim()) {
12325
+ if (!result2.trim()) {
12325
12326
  return { content: "Image analysis returned empty.", isError: true };
12326
12327
  }
12327
- return { content: result };
12328
+ return { content: result2 };
12328
12329
  } catch (e) {
12329
12330
  return { content: `Image analysis failed: ${e.message}`, isError: true };
12330
12331
  }
@@ -12497,10 +12498,10 @@ var init_opus_encoder = __esm({
12497
12498
  }
12498
12499
  });
12499
12500
 
12500
- // src/voice-chat/tts-daemon.ts
12501
+ // src/optional/voice-chat-tts-daemon.ts
12501
12502
  var SOCK_PATH;
12502
- var init_tts_daemon = __esm({
12503
- "src/voice-chat/tts-daemon.ts"() {
12503
+ var init_voice_chat_tts_daemon = __esm({
12504
+ "src/optional/voice-chat-tts-daemon.ts"() {
12504
12505
  "use strict";
12505
12506
  SOCK_PATH = process.platform === "win32" ? "\\\\.\\pipe\\tts_daemon" : "/tmp/tts_daemon.sock";
12506
12507
  }
@@ -12513,14 +12514,22 @@ import { promisify } from "node:util";
12513
12514
  import * as fs18 from "node:fs";
12514
12515
  import * as path19 from "node:path";
12515
12516
  import * as os3 from "node:os";
12516
- function resolvePython() {
12517
+ function resolvePython(configuredPath) {
12518
+ if (configuredPath) {
12519
+ if (_pyCache === configuredPath) return configuredPath;
12520
+ try {
12521
+ __require("child_process").execFileSync(configuredPath, ["-c", "1"], { timeout: 5e3, stdio: "ignore" });
12522
+ _pyCache = configuredPath;
12523
+ return configuredPath;
12524
+ } catch {
12525
+ }
12526
+ }
12517
12527
  if (_pyCache) return _pyCache;
12518
12528
  const candidates = [
12519
12529
  "python3",
12520
12530
  "python",
12521
12531
  process.env.LOCALAPPDATA + "MicrosoftWindowsAppspython3.exe",
12522
- process.env.LOCALAPPDATA + "MicrosoftWindowsAppspython.exe",
12523
- "C:Python314python.exe"
12532
+ process.env.LOCALAPPDATA + "MicrosoftWindowsAppspython.exe"
12524
12533
  ];
12525
12534
  for (const c of candidates) {
12526
12535
  try {
@@ -12582,7 +12591,7 @@ done.wait(timeout=30)
12582
12591
  print('EOS')
12583
12592
  `;
12584
12593
  const configJson = JSON.stringify({ apiKey, model, voice, workspaceId, instruction });
12585
- const child = execFile2(resolvePython(), ["-c", script, configJson, text, output]);
12594
+ const child = execFile2(resolvePython((liveConfig.get("tools.my_voice") || {}).pythonPath), ["-c", script, configJson, text, output]);
12586
12595
  let pyErr = "";
12587
12596
  child.stderr?.on("data", (d) => {
12588
12597
  pyErr += d.toString();
@@ -12708,7 +12717,7 @@ async def main():
12708
12717
  await communicate.save(sys.argv[3])
12709
12718
  asyncio.run(main())
12710
12719
  `;
12711
- await execFileAsync(resolvePython(), ["-c", script, text, EDGE_VOICE, output], { timeout: 3e4 });
12720
+ await execFileAsync(resolvePython((liveConfig.get("tools.my_voice") || {}).pythonPath), ["-c", script, text, EDGE_VOICE, output], { timeout: 3e4 });
12712
12721
  return output;
12713
12722
  }
12714
12723
  async function toWav24kWithDuration(audioPath) {
@@ -12740,7 +12749,7 @@ import sys, wave
12740
12749
  with wave.open(sys.argv[1], 'rb') as wf:
12741
12750
  print(round(wf.getnframes() / wf.getframerate(), 3))
12742
12751
  `;
12743
- const { stdout } = await execFileAsync(resolvePython(), ["-c", script, wavPath], { timeout: 15e3 });
12752
+ const { stdout } = await execFileAsync(resolvePython((liveConfig.get("tools.my_voice") || {}).pythonPath), ["-c", script, wavPath], { timeout: 15e3 });
12744
12753
  const durationSec = parseFloat(stdout.trim());
12745
12754
  if (!Number.isFinite(durationSec) || durationSec <= 0) {
12746
12755
  throw new Error(`invalid duration: ${stdout.trim()}`);
@@ -12911,7 +12920,7 @@ var init_my_voice = __esm({
12911
12920
  init_live();
12912
12921
  init_registry();
12913
12922
  init_opus_encoder();
12914
- init_tts_daemon();
12923
+ init_voice_chat_tts_daemon();
12915
12924
  execFileAsync = promisify(execFile2);
12916
12925
  VOICE_DIR = path19.join(os3.tmpdir(), "engine-voice");
12917
12926
  _pyCache = null;
@@ -13776,18 +13785,18 @@ function parseDuration(s) {
13776
13785
  }
13777
13786
  function expandDates(input) {
13778
13787
  const parts = input.split(",").map((s) => s.trim()).filter(Boolean);
13779
- const result = [];
13788
+ const result2 = [];
13780
13789
  for (const part of parts) {
13781
13790
  const range = parseDateRange(part);
13782
13791
  if (range && range.dEnd > range.dStart) {
13783
13792
  for (let d = range.dStart; d <= range.dEnd; d++) {
13784
- result.push(`${range.month}/${d}`);
13793
+ result2.push(`${range.month}/${d}`);
13785
13794
  }
13786
13795
  } else {
13787
- result.push(part);
13796
+ result2.push(part);
13788
13797
  }
13789
13798
  }
13790
- return result;
13799
+ return result2;
13791
13800
  }
13792
13801
  function timeToMin(t) {
13793
13802
  const [hh, mm] = t.split(":").map(Number);
@@ -13990,16 +13999,16 @@ function addBatch(db, args) {
13990
13999
  ).run(args.event, dateStr, args.time, args.time, durationMin, remindMin, remindAt, 0, nowIso(), args.channel || null, args.channelTarget || null);
13991
14000
  ok.push(`#${r.lastInsertRowid} ${dateStr}`);
13992
14001
  }
13993
- let result = `\u2705 \u6210\u529F ${ok.length} \u6761`;
13994
- if (skipped.length > 0) result += `\uFF0C\u26A0\uFE0F \u51B2\u7A81\u8DF3\u8FC7 ${skipped.length} \u6761`;
13995
- result += `
14002
+ let result2 = `\u2705 \u6210\u529F ${ok.length} \u6761`;
14003
+ if (skipped.length > 0) result2 += `\uFF0C\u26A0\uFE0F \u51B2\u7A81\u8DF3\u8FC7 ${skipped.length} \u6761`;
14004
+ result2 += `
13996
14005
  ${ok.map((s) => ` ${s}`).join("\n")}`;
13997
14006
  if (skipped.length > 0) {
13998
- result += `
14007
+ result2 += `
13999
14008
  \u51B2\u7A81\u8BE6\u60C5\uFF1A
14000
14009
  ${skipped.map((s) => ` ${s}`).join("\n")}`;
14001
14010
  }
14002
- return result;
14011
+ return result2;
14003
14012
  }
14004
14013
  function addTask(db, args) {
14005
14014
  const { dateStr, timeExact, event, docPath } = args;
@@ -14240,7 +14249,7 @@ var init_calendar = __esm({
14240
14249
  if (!action) return { content: "Error: action is required", isError: true };
14241
14250
  try {
14242
14251
  const db = openDb(ctx.workspace);
14243
- let result;
14252
+ let result2;
14244
14253
  let isAddTask = false;
14245
14254
  if (action === "add") {
14246
14255
  const event = args.event?.trim();
@@ -14249,22 +14258,22 @@ var init_calendar = __esm({
14249
14258
  const repeat = args.repeat || (args.weekly ? "weekly" : "once");
14250
14259
  if (repeat === "daily" || repeat === "weekdays") {
14251
14260
  if (!args.time) return { content: "Error: add daily/weekdays needs time (e.g. 23:00)", isError: true };
14252
- result = addDaily(db, { time: args.time, event, repeatType: repeat, remind, channel: ctx.channel, channelTarget: ctx.channelTarget });
14261
+ result2 = addDaily(db, { time: args.time, event, repeatType: repeat, remind, channel: ctx.channel, channelTarget: ctx.channelTarget });
14253
14262
  } else if (repeat === "weekly") {
14254
14263
  const day = args.day;
14255
14264
  if (!day) return { content: "Error: add weekly needs day", isError: true };
14256
- result = addWeekly(db, { day, event, time: args.time, duration: args.duration, remind, channel: ctx.channel, channelTarget: ctx.channelTarget });
14265
+ result2 = addWeekly(db, { day, event, time: args.time, duration: args.duration, remind, channel: ctx.channel, channelTarget: ctx.channelTarget });
14257
14266
  } else {
14258
14267
  const date = args.date?.trim();
14259
14268
  if (!date) return { content: "Error: add once needs date (e.g. 5/26)", isError: true };
14260
- result = addDate(db, { dateStr: date, event, time: args.time, duration: args.duration, remind, channel: ctx.channel, channelTarget: ctx.channelTarget });
14269
+ result2 = addDate(db, { dateStr: date, event, time: args.time, duration: args.duration, remind, channel: ctx.channel, channelTarget: ctx.channelTarget });
14261
14270
  }
14262
14271
  } else if (action === "add-batch") {
14263
14272
  const event = args.event?.trim();
14264
14273
  const datesInput = args.dates?.trim();
14265
14274
  if (!event) return { content: "Error: add-batch needs event", isError: true };
14266
14275
  if (!datesInput) return { content: 'Error: add-batch needs dates (e.g. "7/2,7/4,7/6-7/10")', isError: true };
14267
- result = addBatch(db, { datesInput, event, time: args.time, duration: args.duration, remind: args.remind, channel: ctx.channel, channelTarget: ctx.channelTarget });
14276
+ result2 = addBatch(db, { datesInput, event, time: args.time, duration: args.duration, remind: args.remind, channel: ctx.channel, channelTarget: ctx.channelTarget });
14268
14277
  } else if (action === "add-task") {
14269
14278
  isAddTask = true;
14270
14279
  const event = args.event?.trim();
@@ -14275,60 +14284,60 @@ var init_calendar = __esm({
14275
14284
  if (!date) return { content: "Error: add-task needs date (e.g. 7/5)", isError: true };
14276
14285
  if (!timeExact || !timeExact.includes(":")) return { content: "Error: add-task needs time_exact (HH:MM, e.g. 14:00)", isError: true };
14277
14286
  if (!docPath) return { content: "\u274C \u521B\u5EFA\u5931\u8D25\uFF1Aadd-task \u5FC5\u987B\u4F20 doc_path\u3002\n\u6CA1\u6709\u6587\u6863\u652F\u6491\u7684 task \u4E0D\u662F\u5408\u683C\u7684 task\u3002\n\u8BF7\u5148\u5728 docs/todo/ \u4E0B\u521B\u5EFA\u6587\u6863\uFF08\u547D\u540D\uFF1AYYYY-MM-DD_\u4E3B\u9898.md \u6216 \u4EFB\u52A1\u540D.md\uFF09\uFF0C\u7136\u540E\u4F20 doc_path \u53C2\u6570\u3002", isError: true };
14278
- result = addTask(db, { dateStr: date, timeExact, event, remind: args.remind, channel: ctx.channel, channelTarget: ctx.channelTarget, docPath });
14287
+ result2 = addTask(db, { dateStr: date, timeExact, event, remind: args.remind, channel: ctx.channel, channelTarget: ctx.channelTarget, docPath });
14279
14288
  } else if (action === "reschedule") {
14280
14289
  if (args.id == null) return { content: "Error: reschedule needs id", isError: true };
14281
14290
  const date = args.date?.trim();
14282
14291
  const timeExact = args.time_exact?.trim();
14283
14292
  if (!date) return { content: "Error: reschedule needs date (e.g. 7/10)", isError: true };
14284
14293
  if (!timeExact || !timeExact.includes(":")) return { content: "Error: reschedule needs time_exact (HH:MM)", isError: true };
14285
- result = reschedule(db, { id: args.id, dateStr: date, timeExact, remind: args.remind });
14294
+ result2 = reschedule(db, { id: args.id, dateStr: date, timeExact, remind: args.remind });
14286
14295
  } else if (action === "link-doc") {
14287
14296
  if (args.id == null) return { content: "Error: link-doc needs id", isError: true };
14288
14297
  const docPath = args.doc_path?.trim();
14289
14298
  if (!docPath) return { content: "Error: link-doc needs doc_path", isError: true };
14290
- result = linkDoc(db, args.id, docPath);
14299
+ result2 = linkDoc(db, args.id, docPath);
14291
14300
  } else if (action === "find-doc") {
14292
14301
  if (args.id == null) return { content: "Error: find-doc needs id", isError: true };
14293
- result = findDoc(db, args.id);
14302
+ result2 = findDoc(db, args.id);
14294
14303
  } else if (action === "list") {
14295
- result = list(db, { all: !!args.all });
14304
+ result2 = list(db, { all: !!args.all });
14296
14305
  } else if (action === "done") {
14297
14306
  if (args.id == null) return { content: "Error: done needs id", isError: true };
14298
- result = done(db, args.id);
14307
+ result2 = done(db, args.id);
14299
14308
  } else if (action === "pending") {
14300
- result = pending(db);
14309
+ result2 = pending(db);
14301
14310
  } else if (action === "search") {
14302
14311
  const kw = args.event?.trim();
14303
14312
  if (!kw) return { content: "Error: search needs keyword (event field)", isError: true };
14304
- result = search(db, kw);
14313
+ result2 = search(db, kw);
14305
14314
  } else if (action === "archive") {
14306
14315
  if (args.id == null) return { content: "Error: archive needs id", isError: true };
14307
- result = archive(db, args.id);
14316
+ result2 = archive(db, args.id);
14308
14317
  } else if (action === "delete") {
14309
14318
  if (args.id == null) return { content: "Error: delete needs id", isError: true };
14310
- result = archive(db, args.id);
14319
+ result2 = archive(db, args.id);
14311
14320
  } else if (action === "cleanup") {
14312
- result = cleanup(db);
14321
+ result2 = cleanup(db);
14313
14322
  } else if (action === "stats") {
14314
- result = stats(db);
14323
+ result2 = stats(db);
14315
14324
  } else {
14316
14325
  return { content: `Error: unknown action '${action}'`, isError: true };
14317
14326
  }
14318
14327
  db.close();
14319
- const isFailed = result.startsWith("\u274C") || result.includes("Error") || result.includes("\u7528\u6CD5");
14328
+ const isFailed = result2.startsWith("\u274C") || result2.includes("Error") || result2.includes("\u7528\u6CD5");
14320
14329
  if (isAddTask && !isFailed) {
14321
14330
  const { enqueueNotification: enqueueNotification2, buildCalendarNotification: buildCalendarNotification2 } = await Promise.resolve().then(() => (init_task_manager(), task_manager_exports));
14322
14331
  const sessionId = ctx.sessionId || "main";
14323
14332
  const channel = ctx.channel;
14324
14333
  const channelTarget = ctx.channelTarget;
14325
14334
  if (!channel || !channelTarget) {
14326
- return { content: result };
14335
+ return { content: result2 };
14327
14336
  }
14328
- const notif = buildCalendarNotification2("task-created", [result + "\n\n\u8BF7\u6309\u4EE5\u4E0B\u6B65\u9AA4\u540C\u6B65\uFF1A\n1. \u5148\u62C6 Phase\uFF08\u5217\u51FA\u5B50\u4EFB\u52A1\uFF0C\u6807 - [ ] / - [~] / - [!] \u72B6\u6001\uFF09\u2014 \u4E0D\u62C6 Phase \u76F4\u63A5\u5E72\u6D3B = 3-Strike \u7B2C1\u6B21\n2. \u540C\u6B65\u5230 SESSION-STATE.md\uFF08- [~] \u4EFB\u52A1\u540D \u2014 started M/D HH:MM\uFF09\n3. \u7528\u4EFB\u52A1\u7BA1\u7406\u5DE5\u5177\u8DDF\u8E2A\uFF08\u5982 TodoWrite\uFF09\n4. \u5927\u4EFB\u52A1\u5199 docs/todo/YYYY-MM-DD_\u4E3B\u9898.md\uFF08\u80CC\u666F+\u65B9\u6848+\u9A8C\u8BC1\u6807\u51C6\uFF09\n5. \u5B8C\u6210\u540E\uFF1ASESSION-STATE \u6807 - [x] + calendar done <id>"]);
14337
+ const notif = buildCalendarNotification2("task-created", [result2 + "\n\n\u8BF7\u6309\u4EE5\u4E0B\u6B65\u9AA4\u540C\u6B65\uFF1A\n1. \u5148\u62C6 Phase\uFF08\u5217\u51FA\u5B50\u4EFB\u52A1\uFF0C\u6807 - [ ] / - [~] / - [!] \u72B6\u6001\uFF09\u2014 \u4E0D\u62C6 Phase \u76F4\u63A5\u5E72\u6D3B = 3-Strike \u7B2C1\u6B21\n2. \u540C\u6B65\u5230 SESSION-STATE.md\uFF08- [~] \u4EFB\u52A1\u540D \u2014 started M/D HH:MM\uFF09\n3. \u7528\u4EFB\u52A1\u7BA1\u7406\u5DE5\u5177\u8DDF\u8E2A\uFF08\u5982 TodoWrite\uFF09\n4. \u5927\u4EFB\u52A1\u5199 docs/todo/YYYY-MM-DD_\u4E3B\u9898.md\uFF08\u80CC\u666F+\u65B9\u6848+\u9A8C\u8BC1\u6807\u51C6\uFF09\n5. \u5B8C\u6210\u540E\uFF1ASESSION-STATE \u6807 - [x] + calendar done <id>"]);
14329
14338
  enqueueNotification2(notif, { sessionId, channel, channelTarget });
14330
14339
  }
14331
- return { content: result };
14340
+ return { content: result2 };
14332
14341
  } catch (e) {
14333
14342
  return { content: `Calendar ${action} failed: ${e.message}`, isError: true };
14334
14343
  }
@@ -14628,10 +14637,10 @@ var init_TodoWriteTool = __esm({
14628
14637
  const allDone = todos.length > 0 && todos.every((t) => t.status === "completed");
14629
14638
  const newTodos = allDone ? [] : todos;
14630
14639
  saveTodos(sessionId, newTodos);
14631
- let result = "Todos have been successfully. Ensure that you use the todo list to track your progress. Please proceed with the current task as applicable";
14640
+ let result2 = "Todos have been successfully. Ensure that you use the todo list to track your progress. Please proceed with the current task as applicable";
14632
14641
  if (allDone && todos.length >= 3) {
14633
14642
  }
14634
- return { content: result };
14643
+ return { content: result2 };
14635
14644
  },
14636
14645
  isReadOnly: () => false,
14637
14646
  isConcurrencySafe: () => false
@@ -16459,16 +16468,16 @@ var init_task_output = __esm({
16459
16468
  }
16460
16469
  let task = initialTask;
16461
16470
  if (block && (task.status === "running" || task.status === "pending")) {
16462
- const result2 = await waitForTaskCompletion(taskId, timeout, signal);
16463
- if (!result2) {
16471
+ const result3 = await waitForTaskCompletion(taskId, timeout, signal);
16472
+ if (!result3) {
16464
16473
  return { content: `Task ${taskId} was aborted or not found`, isError: true };
16465
16474
  }
16466
- task = result2;
16475
+ task = result3;
16467
16476
  }
16468
16477
  const output = getTaskOutput(taskId);
16469
16478
  const truncated = output.length > 5e4 ? output.slice(0, 5e4) + "\n...[output truncated]" : output;
16470
16479
  const retrievalStatus = !block && (task.status === "running" || task.status === "pending") ? "not_ready" : block && (task.status === "running" || task.status === "pending") ? "timeout" : "success";
16471
- const result = {
16480
+ const result2 = {
16472
16481
  retrieval_status: retrievalStatus,
16473
16482
  task: {
16474
16483
  task_id: task.id,
@@ -16480,7 +16489,7 @@ var init_task_output = __esm({
16480
16489
  }
16481
16490
  };
16482
16491
  return {
16483
- content: JSON.stringify(result, null, 2)
16492
+ content: JSON.stringify(result2, null, 2)
16484
16493
  };
16485
16494
  },
16486
16495
  isConcurrencySafe: () => true,
@@ -16628,7 +16637,7 @@ var init_reply_blocklist = __esm({
16628
16637
  const workspace = ctx.workspace || process.env.ENGINE_WORKSPACE || ".";
16629
16638
  const stripIds = ctx?.channelConfig?.discord?.stripMentionIds || [];
16630
16639
  ensureLoaded(workspace, stripIds);
16631
- let result;
16640
+ let result2;
16632
16641
  switch (action) {
16633
16642
  case "list": {
16634
16643
  const lines = ["**\u81EA\u52A8\u56DE\u590D\u5C4F\u853D\u5217\u8868\uFF1A**"];
@@ -16642,14 +16651,14 @@ var init_reply_blocklist = __esm({
16642
16651
  lines.push(` - \`${id}\``);
16643
16652
  }
16644
16653
  }
16645
- result = { content: lines.join("\n") };
16654
+ result2 = { content: lines.join("\n") };
16646
16655
  break;
16647
16656
  }
16648
16657
  case "block_all": {
16649
16658
  state.blockAll = true;
16650
16659
  save(workspace);
16651
16660
  console.log(`[reply-blocklist] Block ALL enabled`);
16652
- result = { content: '\u{1F6AB} \u5DF2\u5C4F\u853D\u6240\u6709\u4EBA\u7684\u81EA\u52A8\u56DE\u590D\u3002\u7528 action="unblock_all" \u89E3\u9664\u3002' };
16661
+ result2 = { content: '\u{1F6AB} \u5DF2\u5C4F\u853D\u6240\u6709\u4EBA\u7684\u81EA\u52A8\u56DE\u590D\u3002\u7528 action="unblock_all" \u89E3\u9664\u3002' };
16653
16662
  break;
16654
16663
  }
16655
16664
  case "unblock_all": {
@@ -16657,7 +16666,7 @@ var init_reply_blocklist = __esm({
16657
16666
  state.blockedUserIds = [];
16658
16667
  save(workspace);
16659
16668
  console.log(`[reply-blocklist] Block ALL disabled, list cleared`);
16660
- result = { content: "\u2705 \u5DF2\u89E3\u9664\u6240\u6709\u4EBA\u5C4F\u853D\uFF0C\u6E05\u7A7A\u5C4F\u853D\u5217\u8868\u3002" };
16669
+ result2 = { content: "\u2705 \u5DF2\u89E3\u9664\u6240\u6709\u4EBA\u5C4F\u853D\uFF0C\u6E05\u7A7A\u5C4F\u853D\u5217\u8868\u3002" };
16661
16670
  break;
16662
16671
  }
16663
16672
  case "add": {
@@ -16674,7 +16683,7 @@ var init_reply_blocklist = __esm({
16674
16683
  }
16675
16684
  save(workspace);
16676
16685
  console.log(`[reply-blocklist] Added ${added} user(s): ${ids.join(", ")}`);
16677
- result = { content: `\u2705 \u5DF2\u5C4F\u853D ${added} \u4EBA\uFF08\u5171 ${state.blockedUserIds.length} \u4EBA\uFF09\u3002\u5C4F\u853D\u5217\u8868\uFF1A${state.blockedUserIds.join(", ")}` };
16686
+ result2 = { content: `\u2705 \u5DF2\u5C4F\u853D ${added} \u4EBA\uFF08\u5171 ${state.blockedUserIds.length} \u4EBA\uFF09\u3002\u5C4F\u853D\u5217\u8868\uFF1A${state.blockedUserIds.join(", ")}` };
16678
16687
  break;
16679
16688
  }
16680
16689
  case "remove": {
@@ -16687,11 +16696,11 @@ var init_reply_blocklist = __esm({
16687
16696
  const removed = before - state.blockedUserIds.length;
16688
16697
  save(workspace);
16689
16698
  console.log(`[reply-blocklist] Removed ${removed} user(s)`);
16690
- result = { content: `\u2705 \u5DF2\u79FB\u9664 ${removed} \u4EBA\uFF08\u5269 ${state.blockedUserIds.length} \u4EBA\uFF09\u3002` };
16699
+ result2 = { content: `\u2705 \u5DF2\u79FB\u9664 ${removed} \u4EBA\uFF08\u5269 ${state.blockedUserIds.length} \u4EBA\uFF09\u3002` };
16691
16700
  break;
16692
16701
  }
16693
16702
  default:
16694
- result = { content: `Error: \u672A\u77E5\u64CD\u4F5C "${action}"`, isError: true };
16703
+ result2 = { content: `Error: \u672A\u77E5\u64CD\u4F5C "${action}"`, isError: true };
16695
16704
  }
16696
16705
  const adapters = globalThis.__channelAdapters;
16697
16706
  if (adapters) {
@@ -16700,7 +16709,7 @@ var init_reply_blocklist = __esm({
16700
16709
  discordAdapter.addStripMentionIds(state.blockedUserIds);
16701
16710
  }
16702
16711
  }
16703
- return result;
16712
+ return result2;
16704
16713
  },
16705
16714
  isConcurrencySafe: () => true,
16706
16715
  isReadOnly: () => false
@@ -16744,7 +16753,7 @@ var init_wx_query = __esm({
16744
16753
  "use strict";
16745
16754
  init_registry();
16746
16755
  init_live();
16747
- STATE_DIR = process.env.ENGINE7_STATE_DIR || process.env.OPENCLAW_STATE_DIR || join24(process.env.HOME || process.env.USERPROFILE || ".", ".engine7");
16756
+ STATE_DIR = process.env.ENGINE7_STATE_DIR || join24(process.env.HOME || process.env.USERPROFILE || ".", ".engine7");
16748
16757
  SCRIPT = join24("/Users/chongzhang/work/twinsun-hearth/engine", "src", "tools", "wechat", "wx_query.py");
16749
16758
  PYTHON = "python3";
16750
16759
  registry.register({
@@ -17165,9 +17174,9 @@ Select up to ${topK} most relevant (return their 1-indexed numbers as JSON {"sel
17165
17174
  const parsed = JSON.parse(jsonMatch[0]);
17166
17175
  if (parsed.selected && Array.isArray(parsed.selected)) {
17167
17176
  const indices = parsed.selected.filter((n) => n >= 1 && n <= candidates.length).map((n) => n - 1);
17168
- const result = indices.map((i) => candidates[i]);
17169
- console.log(`[memdir] rerank: ${model} selected ${result.length}/${candidates.length} candidates (indices: ${indices.map((i) => i + 1).join(",")})`);
17170
- return result.slice(0, topK);
17177
+ const result2 = indices.map((i) => candidates[i]);
17178
+ console.log(`[memdir] rerank: ${model} selected ${result2.length}/${candidates.length} candidates (indices: ${indices.map((i) => i + 1).join(",")})`);
17179
+ return result2.slice(0, topK);
17171
17180
  }
17172
17181
  } catch {
17173
17182
  }
@@ -17393,7 +17402,7 @@ async function findRelevantMemoriesEveros(query, _memoryDir, alreadySurfaced = /
17393
17402
  } else {
17394
17403
  }
17395
17404
  }
17396
- const result = [];
17405
+ const result2 = [];
17397
17406
  const seenSubjects = /* @__PURE__ */ new Set();
17398
17407
  for (const ep of episodes) {
17399
17408
  if (ep.score < minScore) continue;
@@ -17403,7 +17412,7 @@ async function findRelevantMemoriesEveros(query, _memoryDir, alreadySurfaced = /
17403
17412
  if (surfacedSubjects.has(subject)) continue;
17404
17413
  if (seenSubjects.has(subject)) continue;
17405
17414
  seenSubjects.add(subject);
17406
- result.push({
17415
+ result2.push({
17407
17416
  path: virtualPath,
17408
17417
  mtimeMs: ep.timestamp ? new Date(ep.timestamp).getTime() : Date.now(),
17409
17418
  content: `### ${ep.subject}
@@ -17411,10 +17420,10 @@ async function findRelevantMemoriesEveros(query, _memoryDir, alreadySurfaced = /
17411
17420
  ${ep.episode || ep.summary}`,
17412
17421
  header: formatEverosHeader(ep)
17413
17422
  });
17414
- if (result.length >= topK) break;
17423
+ if (result2.length >= topK) break;
17415
17424
  }
17416
- console.log(`[memdir] everos recall: returning ${result.length} memories (after dedup)`);
17417
- return result;
17425
+ console.log(`[memdir] everos recall: returning ${result2.length} memories (after dedup)`);
17426
+ return result2;
17418
17427
  } catch (e) {
17419
17428
  const ms = Date.now() - t0;
17420
17429
  console.warn(`[memdir] everos recall: error after ${ms}ms: ${e?.message ?? e}`);
@@ -17812,10 +17821,10 @@ ${conversationText}`
17812
17821
  channelManager: null
17813
17822
  };
17814
17823
  let toolCount = 0;
17815
- let result = "";
17824
+ let result2 = "";
17816
17825
  for await (const chunk of extractEngine.query(extractMessages, void 0, toolContext)) {
17817
17826
  if (chunk.type === "text" && chunk.text) {
17818
- result += chunk.text;
17827
+ result2 += chunk.text;
17819
17828
  }
17820
17829
  if (chunk.type === "tool_call") {
17821
17830
  toolCount++;
@@ -17826,7 +17835,7 @@ ${conversationText}`
17826
17835
  persistState(workspace);
17827
17836
  const duration = Date.now() - startTime;
17828
17837
  console.log(
17829
- `[memory] extractMemories finished in ${duration}ms \u2014 ${toolCount} tools used, ${result.length} chars`
17838
+ `[memory] extractMemories finished in ${duration}ms \u2014 ${toolCount} tools used, ${result2.length} chars`
17830
17839
  );
17831
17840
  } catch (error) {
17832
17841
  console.warn(
@@ -18241,18 +18250,18 @@ function truncateSessionMemoryForCompact(content) {
18241
18250
  let wasTruncated = false;
18242
18251
  for (const line of lines) {
18243
18252
  if (line.startsWith("# ")) {
18244
- const result2 = flushSessionSection(currentSectionHeader, currentSectionLines, maxCharsPerSection);
18245
- outputLines.push(...result2.lines);
18246
- wasTruncated = wasTruncated || result2.wasTruncated;
18253
+ const result3 = flushSessionSection(currentSectionHeader, currentSectionLines, maxCharsPerSection);
18254
+ outputLines.push(...result3.lines);
18255
+ wasTruncated = wasTruncated || result3.wasTruncated;
18247
18256
  currentSectionHeader = line;
18248
18257
  currentSectionLines = [];
18249
18258
  } else {
18250
18259
  currentSectionLines.push(line);
18251
18260
  }
18252
18261
  }
18253
- const result = flushSessionSection(currentSectionHeader, currentSectionLines, maxCharsPerSection);
18254
- outputLines.push(...result.lines);
18255
- wasTruncated = wasTruncated || result.wasTruncated;
18262
+ const result2 = flushSessionSection(currentSectionHeader, currentSectionLines, maxCharsPerSection);
18263
+ outputLines.push(...result2.lines);
18264
+ wasTruncated = wasTruncated || result2.wasTruncated;
18256
18265
  return { truncatedContent: outputLines.join("\n"), wasTruncated };
18257
18266
  }
18258
18267
  function flushSessionSection(sectionHeader, sectionLines, maxCharsPerSection) {
@@ -18439,10 +18448,10 @@ ${messages.filter((m) => m.role === "user" || m.role === "assistant").slice(-20)
18439
18448
  channelManager: null
18440
18449
  };
18441
18450
  let toolCount = 0;
18442
- let result = "";
18451
+ let result2 = "";
18443
18452
  for await (const chunk of extractEngine.query(extractMessages, void 0, toolContext)) {
18444
18453
  if (chunk.type === "text" && chunk.text) {
18445
- result += chunk.text;
18454
+ result2 += chunk.text;
18446
18455
  }
18447
18456
  if (chunk.type === "tool_call") {
18448
18457
  toolCount++;
@@ -18451,7 +18460,7 @@ ${messages.filter((m) => m.role === "user" || m.role === "assistant").slice(-20)
18451
18460
  recordExtractionTokenCount(roughTokenCountEstimation5(
18452
18461
  messages.map((m) => typeof m.content === "string" ? m.content : "").join("")
18453
18462
  ));
18454
- console.log(`[sessionMemory] extraction complete: ${toolCount} edits applied, ${result.length} chars`);
18463
+ console.log(`[sessionMemory] extraction complete: ${toolCount} edits applied, ${result2.length} chars`);
18455
18464
  return {
18456
18465
  fired: true,
18457
18466
  summary: `Applied ${toolCount} edits to session notes`
@@ -18834,23 +18843,23 @@ ${sessionIds.map((id) => `- ${id}`).join("\n")}`;
18834
18843
  workspace,
18835
18844
  channelManager: null
18836
18845
  };
18837
- let result = "";
18846
+ let result2 = "";
18838
18847
  let turnCount = 0;
18839
18848
  dlog("dream query START");
18840
18849
  for await (const chunk of dreamEngine.query(messages, void 0, toolContext)) {
18841
18850
  if (chunk.type === "text") {
18842
- result += chunk.text || "";
18851
+ result2 += chunk.text || "";
18843
18852
  }
18844
18853
  if (chunk.type === "tool_call") {
18845
18854
  turnCount++;
18846
18855
  dlog(`dream turn ${turnCount}: tool_call`);
18847
18856
  }
18848
18857
  }
18849
- dlog(`dream query DONE \u2014 ${turnCount} tool_calls, result=${result.length} chars`);
18858
+ dlog(`dream query DONE \u2014 ${turnCount} tool_calls, result=${result2.length} chars`);
18850
18859
  await recordConsolidation(memoryDir);
18851
18860
  dlog(`recordConsolidation OK \u2014 wrote .consolidate-lock`);
18852
18861
  console.log(`[autoDream] completed \u2014 reviewed ${sessionIds.length} sessions`);
18853
- return { fired: true, summary: result.slice(0, 500) };
18862
+ return { fired: true, summary: result2.slice(0, 500) };
18854
18863
  } catch (e) {
18855
18864
  const err = e;
18856
18865
  dlog(`CATCH failed: ${err.message}
@@ -18879,6 +18888,7 @@ var handle_query_exports = {};
18879
18888
  __export(handle_query_exports, {
18880
18889
  handleQuery: () => handleQuery,
18881
18890
  resetSessionStartInjection: () => resetSessionStartInjection,
18891
+ resetWorkModeInjection: () => resetWorkModeInjection,
18882
18892
  resolveSystemPrompt: () => resolveSystemPrompt
18883
18893
  });
18884
18894
  import { readFileSync as readFileSync25, existsSync as existsSync22 } from "node:fs";
@@ -18890,6 +18900,9 @@ function resolveSystemPrompt(v) {
18890
18900
  function resetSessionStartInjection(sessionId) {
18891
18901
  sessionStartDone.delete(sessionId);
18892
18902
  }
18903
+ function resetWorkModeInjection(sessionId) {
18904
+ workModeInjected.delete(sessionId);
18905
+ }
18893
18906
  function loadExternalChanRules(workspace) {
18894
18907
  const path30 = join33(workspace, "prompts", "external-chan-rules.md");
18895
18908
  if (externalChanRulesCache && externalChanRulesCache.path === path30) return externalChanRulesCache;
@@ -19164,6 +19177,30 @@ ${text}` : text });
19164
19177
  }
19165
19178
  }
19166
19179
  }
19180
+ if (chatMode === "emotion") {
19181
+ if (workModeInjected.has(sessionId)) workModeInjected.delete(sessionId);
19182
+ } else if (!workModeInjected.has(sessionId)) {
19183
+ workModeInjected.add(sessionId);
19184
+ try {
19185
+ const sr = await executeSessionStartHooks(channelName === "cli" ? "cli" : "channel", {
19186
+ sessionId,
19187
+ workspace,
19188
+ cwd: workspace,
19189
+ channel: channelName === "cli" ? "console" : channelName,
19190
+ senderId: inboundMeta?.from || "",
19191
+ channelType: inboundMeta?.channelType || "",
19192
+ source
19193
+ });
19194
+ if (sr.additionalContexts && sr.additionalContexts.length > 0) {
19195
+ const att = createAttachmentMessage({ type: "session_start", text: sr.additionalContexts.join("\n\n") });
19196
+ history.push(att);
19197
+ messages.push(att);
19198
+ console.log(`[hooks] work-mode injection: ${sr.additionalContexts.length} additionalContext(s) at END of messages (session ${sessionId}, cache-safe, persisted)`);
19199
+ }
19200
+ } catch (err) {
19201
+ console.warn(`[hooks] work-mode injection error: ${err.message}`);
19202
+ }
19203
+ }
19167
19204
  const pendingNotifications2 = drainPendingNotifications();
19168
19205
  if (pendingNotifications2.length > 0) {
19169
19206
  messages.push(createAttachmentMessage({
@@ -19614,11 +19651,11 @@ ${text}` : text });
19614
19651
  toolOverride: void 0,
19615
19652
  disableThinking: extractP?.disableThinking ?? true
19616
19653
  });
19617
- executeAutoDream2().then((result) => {
19618
- if (result.fired) {
19619
- console.log(`[autoDream] completed: ${result.summary?.slice(0, 200)}`);
19654
+ executeAutoDream2().then((result2) => {
19655
+ if (result2.fired) {
19656
+ console.log(`[autoDream] completed: ${result2.summary?.slice(0, 200)}`);
19620
19657
  } else {
19621
- console.log(`[autoDream] not fired: ${result.reason}`);
19658
+ console.log(`[autoDream] not fired: ${result2.reason}`);
19622
19659
  }
19623
19660
  }).catch((err) => {
19624
19661
  console.warn(`[handle-query] AutoDream error: ${err.message}`);
@@ -19628,7 +19665,7 @@ stack: ${err.stack ?? "(none)"}`);
19628
19665
  }
19629
19666
  } catch (err) {
19630
19667
  try {
19631
- (await import("node:fs")).appendFileSync(join33(process.env.ENGINE7_STATE_DIR || process.env.OPENCLAW_STATE_DIR || path27.join(process.env.HOME || process.env.USERPROFILE || ".", ".engine7"), "logs", "autoDream-debug.log"), `[${(/* @__PURE__ */ new Date()).toISOString()}] [handle-query] autoDream trigger TRY-CATCH: ${err.message}
19668
+ (await import("node:fs")).appendFileSync(join33(process.env.ENGINE7_STATE_DIR || path27.join(process.env.HOME || process.env.USERPROFILE || ".", ".engine7"), "logs", "autoDream-debug.log"), `[${(/* @__PURE__ */ new Date()).toISOString()}] [handle-query] autoDream trigger TRY-CATCH: ${err.message}
19632
19669
  stack: ${err.stack ?? "(none)"}
19633
19670
  `);
19634
19671
  } catch {
@@ -19646,7 +19683,7 @@ function roughTokenCount(messages) {
19646
19683
  }
19647
19684
  return total;
19648
19685
  }
19649
- var sessionStartDone, externalChanRulesCache;
19686
+ var sessionStartDone, workModeInjected, externalChanRulesCache;
19650
19687
  var init_handle_query = __esm({
19651
19688
  "src/handle-query.ts"() {
19652
19689
  "use strict";
@@ -19668,6 +19705,7 @@ var init_handle_query = __esm({
19668
19705
  init_light_mode();
19669
19706
  init_sender_context();
19670
19707
  sessionStartDone = /* @__PURE__ */ new Set();
19708
+ workModeInjected = /* @__PURE__ */ new Set();
19671
19709
  externalChanRulesCache = null;
19672
19710
  }
19673
19711
  });
@@ -19762,6 +19800,8 @@ function parseCcRunArgs(argv) {
19762
19800
  args.agentName = takeValue().trim();
19763
19801
  } else if (a === "--resume") {
19764
19802
  takeValue();
19803
+ } else if (a === "--model") {
19804
+ args.model = takeValue().trim();
19765
19805
  }
19766
19806
  }
19767
19807
  if (!hasPrompt) {
@@ -19864,6 +19904,25 @@ async function runQuery(args) {
19864
19904
  loadSecretsEnv(stateDir, configName);
19865
19905
  const { loadConfig: loadConfig2 } = await Promise.resolve().then(() => (init_loader(), loader_exports));
19866
19906
  const config = loadConfig2(configPath);
19907
+ let effectiveModel = config.model;
19908
+ if (args.model && args.model !== config.model) {
19909
+ const slash = args.model.indexOf("/");
19910
+ const pid = slash > 0 ? args.model.slice(0, slash) : "";
19911
+ const mid = slash > 0 ? args.model.slice(slash + 1) : args.model;
19912
+ const provExists = pid && config.providers?.[pid];
19913
+ const modelExists = provExists?.models?.some((m) => (typeof m === "string" ? m : m?.id) === mid);
19914
+ if (provExists && modelExists) {
19915
+ effectiveModel = args.model;
19916
+ config.provider = {
19917
+ ...config.providers?.[pid],
19918
+ id: pid,
19919
+ models: config.providers?.[pid]?.models
19920
+ };
19921
+ console.log(`[cc-run] --model override: ${args.model} (found in providers)`);
19922
+ } else {
19923
+ console.log(`[cc-run] --model "${args.model}" not in config providers, using default ${config.model}`);
19924
+ }
19925
+ }
19867
19926
  const { buildStablePrompt: buildStablePrompt2, buildDynamicPrompt: buildDynamicPrompt2 } = await Promise.resolve().then(() => (init_prompt(), prompt_exports));
19868
19927
  const systemStable = buildStablePrompt2(config.workspace, config.prompt);
19869
19928
  const systemDynamic = buildDynamicPrompt2({ workspace: config.workspace });
@@ -19872,7 +19931,7 @@ async function runQuery(args) {
19872
19931
  const provider = createProvider2(config.provider);
19873
19932
  const { QueryEngine: QueryEngine2 } = await Promise.resolve().then(() => (init_query(), query_exports));
19874
19933
  const engine = new QueryEngine2(provider, {
19875
- model: config.model,
19934
+ model: effectiveModel,
19876
19935
  systemPrompt,
19877
19936
  maxTokens: 4096,
19878
19937
  temperature: 0.7,
@@ -19885,7 +19944,7 @@ async function runQuery(args) {
19885
19944
  workspace: config.workspace,
19886
19945
  providerId: config.provider.id,
19887
19946
  providerApi: config.provider.api,
19888
- model: config.model,
19947
+ model: effectiveModel,
19889
19948
  scopeConfig: config.session,
19890
19949
  restoreRecall: config.topics?.restoreRecall
19891
19950
  });
@@ -19907,8 +19966,8 @@ async function runQuery(args) {
19907
19966
  stateDir: config.stateDir,
19908
19967
  providerId: config.provider.id,
19909
19968
  providerApi: config.provider.api,
19910
- model: config.model,
19911
- modelInputs: config.provider.models?.find((m) => m.id === config.model)?.input || ["text"],
19969
+ model: effectiveModel,
19970
+ modelInputs: config.provider.models?.find((m) => m.id === effectiveModel)?.input || ["text"],
19912
19971
  systemPrompt,
19913
19972
  channels: config.channels,
19914
19973
  config,
@@ -19977,10 +20036,10 @@ function emitInit(sessionId, model) {
19977
20036
  session_id: sessionId
19978
20037
  });
19979
20038
  }
19980
- function emitTurn(result, model) {
20039
+ function emitTurn(result2, model) {
19981
20040
  const content = [];
19982
- if (result.thinking) content.push({ type: "thinking", text: result.thinking });
19983
- content.push({ type: "text", text: result.text });
20041
+ if (result2.thinking) content.push({ type: "thinking", text: result2.thinking });
20042
+ content.push({ type: "text", text: result2.text });
19984
20043
  writeLine({
19985
20044
  type: "assistant",
19986
20045
  message: {
@@ -19993,25 +20052,25 @@ function emitTurn(result, model) {
19993
20052
  usage: { input_tokens: 0, output_tokens: 0 }
19994
20053
  },
19995
20054
  uuid: randomUUID9(),
19996
- session_id: result.sessionId
20055
+ session_id: result2.sessionId
19997
20056
  });
19998
20057
  writeLine({
19999
20058
  type: "result",
20000
- subtype: result.ok ? "success" : "error_during_execution",
20001
- is_error: !result.ok,
20002
- ...result.terminalReason ? { terminal_reason: result.terminalReason } : {},
20003
- duration_ms: result.durationMs,
20004
- duration_api_ms: result.durationMs,
20005
- num_turns: result.numTurns,
20006
- result: result.text,
20059
+ subtype: result2.ok ? "success" : "error_during_execution",
20060
+ is_error: !result2.ok,
20061
+ ...result2.terminalReason ? { terminal_reason: result2.terminalReason } : {},
20062
+ duration_ms: result2.durationMs,
20063
+ duration_api_ms: result2.durationMs,
20064
+ num_turns: result2.numTurns,
20065
+ result: result2.text,
20007
20066
  stop_reason: "end_turn",
20008
20067
  total_cost_usd: 0,
20009
20068
  usage: { input_tokens: 0, output_tokens: 0 },
20010
20069
  modelUsage: {},
20011
20070
  permission_denials: [],
20012
- errors: result.errors,
20071
+ errors: result2.errors,
20013
20072
  uuid: randomUUID9(),
20014
- session_id: result.sessionId
20073
+ session_id: result2.sessionId
20015
20074
  });
20016
20075
  }
20017
20076
  async function doCcRun(argv) {
@@ -20099,9 +20158,9 @@ async function doCcRun(argv) {
20099
20158
  process.stderr.write("cc-run: \u6CA1\u6536\u5230 prompt\uFF08-p \u6216 stdin user message \u5747\u4E3A\u7A7A\uFF09\n");
20100
20159
  return 1;
20101
20160
  }
20102
- let result;
20161
+ let result2;
20103
20162
  try {
20104
- result = await runQuery(args);
20163
+ result2 = await runQuery(args);
20105
20164
  } catch (e) {
20106
20165
  const errMsg = String(e?.message || e);
20107
20166
  process.stderr.write(`cc-run: ${errMsg}
@@ -20124,10 +20183,10 @@ async function doCcRun(argv) {
20124
20183
  return 1;
20125
20184
  }
20126
20185
  if (args.outputFormat === "stream-json") {
20127
- emitTurn(result, model);
20186
+ emitTurn(result2, model);
20128
20187
  await flushStdout();
20129
20188
  } else {
20130
- process.stdout.write(result.text.endsWith("\n") ? result.text : result.text + "\n");
20189
+ process.stdout.write(result2.text.endsWith("\n") ? result2.text : result2.text + "\n");
20131
20190
  await flushStdout();
20132
20191
  }
20133
20192
  return 0;
@@ -20168,26 +20227,26 @@ function saveTravelConfig(cfg) {
20168
20227
  fs26.writeFileSync(CONFIG_PATH, JSON.stringify(cfg, null, 2));
20169
20228
  }
20170
20229
  function sanitizeContent(content, dirs) {
20171
- let result = content;
20230
+ let result2 = content;
20172
20231
  for (const { placeholder, getOriginal } of PATH_PLACEHOLDERS) {
20173
20232
  const original = getOriginal(dirs);
20174
20233
  if (original) {
20175
- result = result.split(original).join(placeholder);
20176
- result = result.split(original.replace(/\//g, "\\")).join(placeholder);
20177
- result = result.split(original.replace(/\//g, "\\\\")).join(placeholder);
20234
+ result2 = result2.split(original).join(placeholder);
20235
+ result2 = result2.split(original.replace(/\//g, "\\")).join(placeholder);
20236
+ result2 = result2.split(original.replace(/\//g, "\\\\")).join(placeholder);
20178
20237
  }
20179
20238
  }
20180
- return result;
20239
+ return result2;
20181
20240
  }
20182
20241
  function restoreContent(content, dirs) {
20183
- let result = content;
20242
+ let result2 = content;
20184
20243
  for (const { placeholder, getOriginal } of PATH_PLACEHOLDERS) {
20185
20244
  const target = getOriginal(dirs);
20186
20245
  if (target) {
20187
- result = result.split(placeholder).join(target);
20246
+ result2 = result2.split(placeholder).join(target);
20188
20247
  }
20189
20248
  }
20190
- return result;
20249
+ return result2;
20191
20250
  }
20192
20251
  function isTextFile(filePath) {
20193
20252
  const ext = path28.extname(filePath).toLowerCase();
@@ -21119,7 +21178,7 @@ async function configureFeishu(rl, v) {
21119
21178
  const feishuMode = await ask(rl, "\u9009\u62E9 (1/2)", "1");
21120
21179
  if (feishuMode === "1") {
21121
21180
  console.log("\n\u{1F4DD} \u6B63\u5728\u751F\u6210\u98DE\u4E66\u4E8C\u7EF4\u7801...\n");
21122
- const result = await registerFeishuApp({
21181
+ const result2 = await registerFeishuApp({
21123
21182
  onLog: (msg2) => console.log(` ${msg2}`),
21124
21183
  onQrCode: async (url) => {
21125
21184
  try {
@@ -21133,14 +21192,14 @@ async function configureFeishu(rl, v) {
21133
21192
  }
21134
21193
  }
21135
21194
  });
21136
- if (result) {
21137
- v.feishuAppId = result.appId;
21138
- v.feishuAppSecret = result.appSecret;
21139
- v.feishuOpenId = result.openId || "";
21195
+ if (result2) {
21196
+ v.feishuAppId = result2.appId;
21197
+ v.feishuAppSecret = result2.appSecret;
21198
+ v.feishuOpenId = result2.openId || "";
21140
21199
  console.log(`
21141
- \u2705 App ID: ${result.appId}`);
21142
- console.log(` \u2705 App Secret: ${result.appSecret.slice(0, 6)}...`);
21143
- if (result.openId) console.log(` \u2705 Open ID: ${result.openId}`);
21200
+ \u2705 App ID: ${result2.appId}`);
21201
+ console.log(` \u2705 App Secret: ${result2.appSecret.slice(0, 6)}...`);
21202
+ if (result2.openId) console.log(` \u2705 Open ID: ${result2.openId}`);
21144
21203
  } else {
21145
21204
  console.log("\n \u26A0\uFE0F \u626B\u7801\u8D85\u65F6\u6216\u5931\u8D25\uFF0C\u8BF7\u624B\u52A8\u8F93\u5165");
21146
21205
  v.feishuAppId = await ask(rl, "\u98DE\u4E66 App ID");
@@ -21598,7 +21657,7 @@ async function main() {
21598
21657
  console.log("\u{1F527} \u98DE\u4E66\u626B\u7801\u63A5\u5165...");
21599
21658
  const { registerFeishuApp: registerFeishuApp2 } = await Promise.resolve().then(() => (init_feishu_quick_register(), feishu_quick_register_exports));
21600
21659
  const { renderQrTerminal: renderQrTerminal2 } = await Promise.resolve().then(() => (init_qr_render(), qr_render_exports));
21601
- const result = await registerFeishuApp2({
21660
+ const result2 = await registerFeishuApp2({
21602
21661
  onLog: (msg2) => console.log(` ${msg2}`),
21603
21662
  onQrCode: async (url) => {
21604
21663
  try {
@@ -21610,7 +21669,7 @@ async function main() {
21610
21669
  }
21611
21670
  }
21612
21671
  });
21613
- if (!result) {
21672
+ if (!result2) {
21614
21673
  console.error("\u274C \u626B\u7801\u8D85\u65F6\u6216\u5931\u8D25");
21615
21674
  process.exit(1);
21616
21675
  }
@@ -21633,13 +21692,13 @@ async function main() {
21633
21692
  if (configFile2 && fs27.existsSync(configFile2)) {
21634
21693
  const j = JSON.parse(fs27.readFileSync(configFile2, "utf8"));
21635
21694
  j.channels = j.channels || {};
21636
- j.channels.feishu = { enabled: true, appId: result.appId, appSecret: result.appSecret, connectionMode: "websocket", dmPolicy: "pairing", groupPolicy: "open" };
21695
+ j.channels.feishu = { enabled: true, appId: result2.appId, appSecret: result2.appSecret, connectionMode: "websocket", dmPolicy: "pairing", groupPolicy: "open" };
21637
21696
  fs27.writeFileSync(configFile2, JSON.stringify(j, null, 2), "utf8");
21638
21697
  console.log("\u2705 \u98DE\u4E66\u901A\u9053\u5DF2\u5199\u5165: " + configFile2);
21639
21698
  console.log("\u91CD\u542F\u751F\u6548: engine7 restart");
21640
21699
  } else {
21641
21700
  console.log("\u26A0\uFE0F \u6CA1\u627E\u5230 config\uFF0C\u624B\u52A8\u52A0\uFF1A");
21642
- console.log(JSON.stringify({ feishu: { enabled: true, appId: result.appId, appSecret: result.appSecret, connectionMode: "websocket", dmPolicy: "pairing", groupPolicy: "open" } }, null, 2));
21701
+ console.log(JSON.stringify({ feishu: { enabled: true, appId: result2.appId, appSecret: result2.appSecret, connectionMode: "websocket", dmPolicy: "pairing", groupPolicy: "open" } }, null, 2));
21643
21702
  }
21644
21703
  process.exit(0);
21645
21704
  }