engine7 7.1.65 → 7.1.67

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);
@@ -7317,8 +7318,15 @@ async function readSessionHistory(filePath) {
7317
7318
  let filtered = filterUnresolvedToolUses(sessionMsgs);
7318
7319
  filtered = filterOrphanedThinkingOnly(filtered);
7319
7320
  filtered = filterWhitespaceOnlyAssistant(filtered);
7320
- const sessionStarts = attachmentMsgs.filter((m) => m.attachment.type === "session_start");
7321
- const restAttachments = attachmentMsgs.filter((m) => m.attachment.type !== "session_start");
7321
+ const seenStartTexts = /* @__PURE__ */ new Set();
7322
+ const sessionStarts = attachmentMsgs.filter((m) => {
7323
+ if (m.attachment.type !== "session_start") return false;
7324
+ const key = JSON.stringify(m.attachment);
7325
+ if (seenStartTexts.has(key)) return false;
7326
+ seenStartTexts.add(key);
7327
+ return true;
7328
+ });
7329
+ const restAttachments = attachmentMsgs.filter((m) => m.type === "attachment" && m.attachment.type !== "session_start");
7322
7330
  return [...sessionStarts, ...filtered, ...restAttachments];
7323
7331
  }
7324
7332
  async function readAllLines(filePath) {
@@ -7405,18 +7413,18 @@ function entryToSessionMessage(entry) {
7405
7413
  if (block.thinkingSignature) thinkingSig = block.thinkingSignature;
7406
7414
  }
7407
7415
  }
7408
- const result = {
7416
+ const result2 = {
7409
7417
  role: "assistant",
7410
7418
  content: textContent,
7411
7419
  timestamp: entry.timestamp,
7412
7420
  _raw: entry.raw
7413
7421
  };
7414
- if (thinkingContent) result.reasoning_content = thinkingContent;
7415
- if (thinkingSig) result.thinking_signature = thinkingSig;
7422
+ if (thinkingContent) result2.reasoning_content = thinkingContent;
7423
+ if (thinkingSig) result2.thinking_signature = thinkingSig;
7416
7424
  if (toolCalls.length > 0) {
7417
- result.tool_calls = toolCalls;
7425
+ result2.tool_calls = toolCalls;
7418
7426
  }
7419
- return result;
7427
+ return result2;
7420
7428
  } else if (role === "toolResult") {
7421
7429
  const text = extractText2(m.content);
7422
7430
  return {
@@ -8244,9 +8252,9 @@ ${items.join("\n")}` };
8244
8252
  let content;
8245
8253
  let encoding;
8246
8254
  try {
8247
- const result2 = readFileContent(filePath);
8248
- content = result2.content;
8249
- encoding = result2.encoding;
8255
+ const result3 = readFileContent(filePath);
8256
+ content = result3.content;
8257
+ encoding = result3.encoding;
8250
8258
  } catch (e) {
8251
8259
  return { content: e.message, isError: true };
8252
8260
  }
@@ -8263,7 +8271,7 @@ ${items.join("\n")}` };
8263
8271
  const mtime = new Date(stat4.mtimeMs).toLocaleString();
8264
8272
  const info = encoding !== "utf8" ? `[${encoding}] ` : "";
8265
8273
  const header = `${info}${filePath} (${totalLines} \u884C, ${stat4.size} bytes, \u4FEE\u6539: ${mtime})`;
8266
- const result = [
8274
+ const result2 = [
8267
8275
  header,
8268
8276
  "\u2500".repeat(60),
8269
8277
  numbered.join("\n"),
@@ -8272,7 +8280,7 @@ ${items.join("\n")}` };
8272
8280
  ].join("\n");
8273
8281
  return { content: loopWarning ? `${loopWarning}
8274
8282
 
8275
- ${result}` : result };
8283
+ ${result2}` : result2 };
8276
8284
  },
8277
8285
  isConcurrencySafe: () => true,
8278
8286
  isReadOnly: () => true
@@ -8484,19 +8492,19 @@ function isOpeningContext(chars, index) {
8484
8492
  }
8485
8493
  function applyCurlyDoubleQuotes(str) {
8486
8494
  const chars = [...str];
8487
- const result = [];
8495
+ const result2 = [];
8488
8496
  for (let i = 0; i < chars.length; i++) {
8489
8497
  if (chars[i] === '"') {
8490
- result.push(isOpeningContext(chars, i) ? LEFT_DOUBLE_CURLY : RIGHT_DOUBLE_CURLY);
8498
+ result2.push(isOpeningContext(chars, i) ? LEFT_DOUBLE_CURLY : RIGHT_DOUBLE_CURLY);
8491
8499
  } else {
8492
- result.push(chars[i]);
8500
+ result2.push(chars[i]);
8493
8501
  }
8494
8502
  }
8495
- return result.join("");
8503
+ return result2.join("");
8496
8504
  }
8497
8505
  function applyCurlySingleQuotes(str) {
8498
8506
  const chars = [...str];
8499
- const result = [];
8507
+ const result2 = [];
8500
8508
  for (let i = 0; i < chars.length; i++) {
8501
8509
  if (chars[i] === "'") {
8502
8510
  const prev = i > 0 ? chars[i - 1] : void 0;
@@ -8504,25 +8512,25 @@ function applyCurlySingleQuotes(str) {
8504
8512
  const prevIsLetter = prev !== void 0 && /\p{L}/u.test(prev);
8505
8513
  const nextIsLetter = next !== void 0 && /\p{L}/u.test(next);
8506
8514
  if (prevIsLetter && nextIsLetter) {
8507
- result.push(RIGHT_SINGLE_CURLY);
8515
+ result2.push(RIGHT_SINGLE_CURLY);
8508
8516
  } else {
8509
- result.push(isOpeningContext(chars, i) ? LEFT_SINGLE_CURLY : RIGHT_SINGLE_CURLY);
8517
+ result2.push(isOpeningContext(chars, i) ? LEFT_SINGLE_CURLY : RIGHT_SINGLE_CURLY);
8510
8518
  }
8511
8519
  } else {
8512
- result.push(chars[i]);
8520
+ result2.push(chars[i]);
8513
8521
  }
8514
8522
  }
8515
- return result.join("");
8523
+ return result2.join("");
8516
8524
  }
8517
8525
  function preserveQuoteStyle(oldString, actualOldString, newString) {
8518
8526
  if (oldString === actualOldString) return newString;
8519
8527
  const hasDouble = actualOldString.includes(LEFT_DOUBLE_CURLY) || actualOldString.includes(RIGHT_DOUBLE_CURLY);
8520
8528
  const hasSingle = actualOldString.includes(LEFT_SINGLE_CURLY) || actualOldString.includes(RIGHT_SINGLE_CURLY);
8521
8529
  if (!hasDouble && !hasSingle) return newString;
8522
- let result = newString;
8523
- if (hasDouble) result = applyCurlyDoubleQuotes(result);
8524
- if (hasSingle) result = applyCurlySingleQuotes(result);
8525
- return result;
8530
+ let result2 = newString;
8531
+ if (hasDouble) result2 = applyCurlyDoubleQuotes(result2);
8532
+ if (hasSingle) result2 = applyCurlySingleQuotes(result2);
8533
+ return result2;
8526
8534
  }
8527
8535
  function applyEditToFile(originalContent, oldString, newString, replaceAll = false) {
8528
8536
  const f = replaceAll ? (content, search2, replace) => content.replaceAll(search2, () => replace) : (content, search2, replace) => content.replace(search2, () => replace);
@@ -8545,23 +8553,23 @@ function generateEditDiff(fileContent, actualOldString, actualNewString, context
8545
8553
  const oldLines = actualOldString.split(/\r?\n/);
8546
8554
  const newLines = actualNewString.split(/\r?\n/);
8547
8555
  const fileLines = fileContent.split(/\r?\n/);
8548
- const result = [];
8556
+ const result2 = [];
8549
8557
  const ctxStart = Math.max(0, startLine - contextLines);
8550
8558
  for (let i = ctxStart; i < startLine; i++) {
8551
- result.push(` ${fileLines[i] ?? ""}`);
8559
+ result2.push(` ${fileLines[i] ?? ""}`);
8552
8560
  }
8553
8561
  for (let i = 0; i < oldLines.length; i++) {
8554
- result.push(`-${oldLines[i]}`);
8562
+ result2.push(`-${oldLines[i]}`);
8555
8563
  }
8556
8564
  for (let i = 0; i < newLines.length; i++) {
8557
- result.push(`+${newLines[i]}`);
8565
+ result2.push(`+${newLines[i]}`);
8558
8566
  }
8559
8567
  const afterStart = startLine + oldLines.length;
8560
8568
  const afterEnd = Math.min(fileLines.length, afterStart + contextLines);
8561
8569
  for (let i = afterStart; i < afterEnd; i++) {
8562
- result.push(` ${fileLines[i] ?? ""}`);
8570
+ result2.push(` ${fileLines[i] ?? ""}`);
8563
8571
  }
8564
- return result.join("\n");
8572
+ return result2.join("\n");
8565
8573
  }
8566
8574
  var LEFT_SINGLE_CURLY, RIGHT_SINGLE_CURLY, LEFT_DOUBLE_CURLY, RIGHT_DOUBLE_CURLY, MAX_EDIT_FILE_SIZE;
8567
8575
  var init_edit = __esm({
@@ -8948,19 +8956,19 @@ var init_grep = __esm({
8948
8956
  rgArgs.push("--glob", p);
8949
8957
  }
8950
8958
  }
8951
- const result = await ripGrep(rgArgs, searchPath);
8952
- if (result.timedOut) {
8959
+ const result2 = await ripGrep(rgArgs, searchPath);
8960
+ if (result2.timedOut) {
8953
8961
  return {
8954
8962
  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
8963
  isError: true
8956
8964
  };
8957
8965
  }
8958
- if (result.lines.length === 0) {
8966
+ if (result2.lines.length === 0) {
8959
8967
  return { content: "No files found" };
8960
8968
  }
8961
8969
  const cwd = ctx.workspace;
8962
8970
  if (outputMode === "content") {
8963
- const { items: limited2, appliedLimit: appliedLimit2 } = applyHeadLimit(result.lines, headLimit, offset);
8971
+ const { items: limited2, appliedLimit: appliedLimit2 } = applyHeadLimit(result2.lines, headLimit, offset);
8964
8972
  const finalLines = limited2.map((line) => {
8965
8973
  const colonIdx = line.indexOf(":");
8966
8974
  if (colonIdx > 0) {
@@ -8978,7 +8986,7 @@ var init_grep = __esm({
8978
8986
  return { content: content + suffix2 };
8979
8987
  }
8980
8988
  if (outputMode === "count") {
8981
- const { items: limited2, appliedLimit: appliedLimit2 } = applyHeadLimit(result.lines, headLimit, offset);
8989
+ const { items: limited2, appliedLimit: appliedLimit2 } = applyHeadLimit(result2.lines, headLimit, offset);
8982
8990
  const finalLines = limited2.map((line) => {
8983
8991
  const colonIdx = line.lastIndexOf(":");
8984
8992
  if (colonIdx > 0) {
@@ -9000,7 +9008,7 @@ var init_grep = __esm({
9000
9008
  Found ${totalMatches} total occurrences across ${limited2.length} files.${limitInfo2 ? ` with pagination = ${limitInfo2}` : ""}`;
9001
9009
  return { content: content + summary };
9002
9010
  }
9003
- const { items: limited, appliedLimit } = applyHeadLimit(result.lines, headLimit, offset);
9011
+ const { items: limited, appliedLimit } = applyHeadLimit(result2.lines, headLimit, offset);
9004
9012
  const filenames = limited.map((line) => {
9005
9013
  const colonIdx = line.indexOf(":");
9006
9014
  const fpath = colonIdx > 0 ? line.substring(0, colonIdx) : line;
@@ -9330,17 +9338,17 @@ function getBackgroundUsageNote() {
9330
9338
  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
9339
  }
9332
9340
  function prependBullets2(items) {
9333
- const result = [];
9341
+ const result2 = [];
9334
9342
  for (const item of items) {
9335
9343
  if (Array.isArray(item)) {
9336
9344
  for (const sub of item) {
9337
- result.push(` - ${sub}`);
9345
+ result2.push(` - ${sub}`);
9338
9346
  }
9339
9347
  } else {
9340
- result.push(`- ${item}`);
9348
+ result2.push(`- ${item}`);
9341
9349
  }
9342
9350
  }
9343
- return result;
9351
+ return result2;
9344
9352
  }
9345
9353
  function getExecPrompt() {
9346
9354
  const toolPreferenceItems = [
@@ -9428,17 +9436,17 @@ function isDestructiveCommand(command) {
9428
9436
  return DESTRUCTIVE_PATTERNS.some((p) => p.test(trimmed));
9429
9437
  }
9430
9438
  function sanitizeEnv(env) {
9431
- const result = {};
9439
+ const result2 = {};
9432
9440
  for (const [k, v] of Object.entries(env)) {
9433
9441
  if (ENV_ALLOW_KEYS.includes(k)) {
9434
- result[k] = v;
9442
+ result2[k] = v;
9435
9443
  continue;
9436
9444
  }
9437
9445
  if (!BLOCKED_ENV_KEYS.some((b) => k.toUpperCase().includes(b))) {
9438
- result[k] = v;
9446
+ result2[k] = v;
9439
9447
  }
9440
9448
  }
9441
- return result;
9449
+ return result2;
9442
9450
  }
9443
9451
  var DANGEROUS_COMMANDS, DESTRUCTIVE_PATTERNS, BLOCKED_ENV_KEYS, ENV_ALLOW_KEYS;
9444
9452
  var init_bashSecurity = __esm({
@@ -9559,12 +9567,12 @@ function findShell() {
9559
9567
  return cachedShell;
9560
9568
  }
9561
9569
  try {
9562
- const result = execSync("where.exe bash", {
9570
+ const result2 = execSync("where.exe bash", {
9563
9571
  encoding: "utf-8",
9564
9572
  timeout: 5e3,
9565
9573
  stdio: ["ignore", "pipe", "ignore"]
9566
9574
  });
9567
- const candidates = result.trim().split(/\r?\n/).map((s) => s.trim()).filter(Boolean);
9575
+ const candidates = result2.trim().split(/\r?\n/).map((s) => s.trim()).filter(Boolean);
9568
9576
  const nonWsl = candidates.find((p) => !isWslBash(p));
9569
9577
  if (nonWsl && fs14.existsSync(nonWsl)) {
9570
9578
  cachedShell = { shell: nonWsl, args: ["-c"] };
@@ -10298,7 +10306,7 @@ async function runAgent(opts) {
10298
10306
  console.warn(`[agent:${agentId}] No visualRegistry in context, cannot bind Discord channel for "${visualName}"`);
10299
10307
  }
10300
10308
  }
10301
- let result = "";
10309
+ let result2 = "";
10302
10310
  let toolUseCount = 0;
10303
10311
  try {
10304
10312
  for await (const chunk of subEngine.query(messages, runAbort.signal, opts.context)) {
@@ -10329,12 +10337,12 @@ async function runAgent(opts) {
10329
10337
  }
10330
10338
  }
10331
10339
  if (chunk.type === "text" && chunk.text) {
10332
- result += chunk.text;
10340
+ result2 += chunk.text;
10333
10341
  }
10334
10342
  if (chunk.type === "result") {
10335
10343
  const resultContent = chunk.content;
10336
10344
  if (resultContent) {
10337
- result = resultContent;
10345
+ result2 = resultContent;
10338
10346
  }
10339
10347
  }
10340
10348
  }
@@ -10342,11 +10350,11 @@ async function runAgent(opts) {
10342
10350
  agentRegistry.unregister(agentId);
10343
10351
  }
10344
10352
  const durationMs = Date.now() - startTime;
10345
- console.log(`[agent:${agentId}] ${agentDef.agentType} completed in ${durationMs}ms, ${toolUseCount} tools, ${result.length} chars`);
10353
+ console.log(`[agent:${agentId}] ${agentDef.agentType} completed in ${durationMs}ms, ${toolUseCount} tools, ${result2.length} chars`);
10346
10354
  return {
10347
10355
  agentId,
10348
10356
  agentType: agentDef.agentType,
10349
- content: result || "(no output from agent)",
10357
+ content: result2 || "(no output from agent)",
10350
10358
  totalToolUseCount: toolUseCount,
10351
10359
  totalDurationMs: durationMs
10352
10360
  };
@@ -11492,7 +11500,7 @@ var init_AgentTool = __esm({
11492
11500
  console.log(`[AgentTool] Background requested but running synchronously (headless limitation)`);
11493
11501
  }
11494
11502
  try {
11495
- const result = await runAgent({
11503
+ const result2 = await runAgent({
11496
11504
  prompt,
11497
11505
  description,
11498
11506
  subagentType,
@@ -11509,9 +11517,9 @@ var init_AgentTool = __esm({
11509
11517
  // visual 系统用这个 name 创建频道
11510
11518
  });
11511
11519
  const parts = [
11512
- result.content,
11520
+ result2.content,
11513
11521
  "",
11514
- `[Agent: ${result.agentType}, ${result.totalDurationMs}ms, ${result.totalToolUseCount} tool uses]`
11522
+ `[Agent: ${result2.agentType}, ${result2.totalDurationMs}ms, ${result2.totalToolUseCount} tool uses]`
11515
11523
  ];
11516
11524
  visualEmitter?.emitAgentDone(agentLabel);
11517
11525
  return {
@@ -12308,7 +12316,7 @@ var init_my_eyes = __esm({
12308
12316
  ]
12309
12317
  };
12310
12318
  try {
12311
- let result = "";
12319
+ let result2 = "";
12312
12320
  const stream = provider.streamChat({
12313
12321
  model: modelId,
12314
12322
  messages: [userMsg],
@@ -12318,13 +12326,13 @@ var init_my_eyes = __esm({
12318
12326
  });
12319
12327
  for await (const chunk of stream) {
12320
12328
  if (chunk.type === "text" && chunk.text) {
12321
- result += chunk.text;
12329
+ result2 += chunk.text;
12322
12330
  }
12323
12331
  }
12324
- if (!result.trim()) {
12332
+ if (!result2.trim()) {
12325
12333
  return { content: "Image analysis returned empty.", isError: true };
12326
12334
  }
12327
- return { content: result };
12335
+ return { content: result2 };
12328
12336
  } catch (e) {
12329
12337
  return { content: `Image analysis failed: ${e.message}`, isError: true };
12330
12338
  }
@@ -12497,10 +12505,10 @@ var init_opus_encoder = __esm({
12497
12505
  }
12498
12506
  });
12499
12507
 
12500
- // src/voice-chat/tts-daemon.ts
12508
+ // src/optional/voice-chat-tts-daemon.ts
12501
12509
  var SOCK_PATH;
12502
- var init_tts_daemon = __esm({
12503
- "src/voice-chat/tts-daemon.ts"() {
12510
+ var init_voice_chat_tts_daemon = __esm({
12511
+ "src/optional/voice-chat-tts-daemon.ts"() {
12504
12512
  "use strict";
12505
12513
  SOCK_PATH = process.platform === "win32" ? "\\\\.\\pipe\\tts_daemon" : "/tmp/tts_daemon.sock";
12506
12514
  }
@@ -12513,14 +12521,22 @@ import { promisify } from "node:util";
12513
12521
  import * as fs18 from "node:fs";
12514
12522
  import * as path19 from "node:path";
12515
12523
  import * as os3 from "node:os";
12516
- function resolvePython() {
12524
+ function resolvePython(configuredPath) {
12525
+ if (configuredPath) {
12526
+ if (_pyCache === configuredPath) return configuredPath;
12527
+ try {
12528
+ __require("child_process").execFileSync(configuredPath, ["-c", "1"], { timeout: 5e3, stdio: "ignore" });
12529
+ _pyCache = configuredPath;
12530
+ return configuredPath;
12531
+ } catch {
12532
+ }
12533
+ }
12517
12534
  if (_pyCache) return _pyCache;
12518
12535
  const candidates = [
12519
12536
  "python3",
12520
12537
  "python",
12521
12538
  process.env.LOCALAPPDATA + "MicrosoftWindowsAppspython3.exe",
12522
- process.env.LOCALAPPDATA + "MicrosoftWindowsAppspython.exe",
12523
- "C:Python314python.exe"
12539
+ process.env.LOCALAPPDATA + "MicrosoftWindowsAppspython.exe"
12524
12540
  ];
12525
12541
  for (const c of candidates) {
12526
12542
  try {
@@ -12582,7 +12598,7 @@ done.wait(timeout=30)
12582
12598
  print('EOS')
12583
12599
  `;
12584
12600
  const configJson = JSON.stringify({ apiKey, model, voice, workspaceId, instruction });
12585
- const child = execFile2(resolvePython(), ["-c", script, configJson, text, output]);
12601
+ const child = execFile2(resolvePython((liveConfig.get("tools.my_voice") || {}).pythonPath), ["-c", script, configJson, text, output]);
12586
12602
  let pyErr = "";
12587
12603
  child.stderr?.on("data", (d) => {
12588
12604
  pyErr += d.toString();
@@ -12708,7 +12724,7 @@ async def main():
12708
12724
  await communicate.save(sys.argv[3])
12709
12725
  asyncio.run(main())
12710
12726
  `;
12711
- await execFileAsync(resolvePython(), ["-c", script, text, EDGE_VOICE, output], { timeout: 3e4 });
12727
+ await execFileAsync(resolvePython((liveConfig.get("tools.my_voice") || {}).pythonPath), ["-c", script, text, EDGE_VOICE, output], { timeout: 3e4 });
12712
12728
  return output;
12713
12729
  }
12714
12730
  async function toWav24kWithDuration(audioPath) {
@@ -12740,7 +12756,7 @@ import sys, wave
12740
12756
  with wave.open(sys.argv[1], 'rb') as wf:
12741
12757
  print(round(wf.getnframes() / wf.getframerate(), 3))
12742
12758
  `;
12743
- const { stdout } = await execFileAsync(resolvePython(), ["-c", script, wavPath], { timeout: 15e3 });
12759
+ const { stdout } = await execFileAsync(resolvePython((liveConfig.get("tools.my_voice") || {}).pythonPath), ["-c", script, wavPath], { timeout: 15e3 });
12744
12760
  const durationSec = parseFloat(stdout.trim());
12745
12761
  if (!Number.isFinite(durationSec) || durationSec <= 0) {
12746
12762
  throw new Error(`invalid duration: ${stdout.trim()}`);
@@ -12911,7 +12927,7 @@ var init_my_voice = __esm({
12911
12927
  init_live();
12912
12928
  init_registry();
12913
12929
  init_opus_encoder();
12914
- init_tts_daemon();
12930
+ init_voice_chat_tts_daemon();
12915
12931
  execFileAsync = promisify(execFile2);
12916
12932
  VOICE_DIR = path19.join(os3.tmpdir(), "engine-voice");
12917
12933
  _pyCache = null;
@@ -13776,18 +13792,18 @@ function parseDuration(s) {
13776
13792
  }
13777
13793
  function expandDates(input) {
13778
13794
  const parts = input.split(",").map((s) => s.trim()).filter(Boolean);
13779
- const result = [];
13795
+ const result2 = [];
13780
13796
  for (const part of parts) {
13781
13797
  const range = parseDateRange(part);
13782
13798
  if (range && range.dEnd > range.dStart) {
13783
13799
  for (let d = range.dStart; d <= range.dEnd; d++) {
13784
- result.push(`${range.month}/${d}`);
13800
+ result2.push(`${range.month}/${d}`);
13785
13801
  }
13786
13802
  } else {
13787
- result.push(part);
13803
+ result2.push(part);
13788
13804
  }
13789
13805
  }
13790
- return result;
13806
+ return result2;
13791
13807
  }
13792
13808
  function timeToMin(t) {
13793
13809
  const [hh, mm] = t.split(":").map(Number);
@@ -13990,16 +14006,16 @@ function addBatch(db, args) {
13990
14006
  ).run(args.event, dateStr, args.time, args.time, durationMin, remindMin, remindAt, 0, nowIso(), args.channel || null, args.channelTarget || null);
13991
14007
  ok.push(`#${r.lastInsertRowid} ${dateStr}`);
13992
14008
  }
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 += `
14009
+ let result2 = `\u2705 \u6210\u529F ${ok.length} \u6761`;
14010
+ if (skipped.length > 0) result2 += `\uFF0C\u26A0\uFE0F \u51B2\u7A81\u8DF3\u8FC7 ${skipped.length} \u6761`;
14011
+ result2 += `
13996
14012
  ${ok.map((s) => ` ${s}`).join("\n")}`;
13997
14013
  if (skipped.length > 0) {
13998
- result += `
14014
+ result2 += `
13999
14015
  \u51B2\u7A81\u8BE6\u60C5\uFF1A
14000
14016
  ${skipped.map((s) => ` ${s}`).join("\n")}`;
14001
14017
  }
14002
- return result;
14018
+ return result2;
14003
14019
  }
14004
14020
  function addTask(db, args) {
14005
14021
  const { dateStr, timeExact, event, docPath } = args;
@@ -14240,7 +14256,7 @@ var init_calendar = __esm({
14240
14256
  if (!action) return { content: "Error: action is required", isError: true };
14241
14257
  try {
14242
14258
  const db = openDb(ctx.workspace);
14243
- let result;
14259
+ let result2;
14244
14260
  let isAddTask = false;
14245
14261
  if (action === "add") {
14246
14262
  const event = args.event?.trim();
@@ -14249,22 +14265,22 @@ var init_calendar = __esm({
14249
14265
  const repeat = args.repeat || (args.weekly ? "weekly" : "once");
14250
14266
  if (repeat === "daily" || repeat === "weekdays") {
14251
14267
  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 });
14268
+ result2 = addDaily(db, { time: args.time, event, repeatType: repeat, remind, channel: ctx.channel, channelTarget: ctx.channelTarget });
14253
14269
  } else if (repeat === "weekly") {
14254
14270
  const day = args.day;
14255
14271
  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 });
14272
+ result2 = addWeekly(db, { day, event, time: args.time, duration: args.duration, remind, channel: ctx.channel, channelTarget: ctx.channelTarget });
14257
14273
  } else {
14258
14274
  const date = args.date?.trim();
14259
14275
  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 });
14276
+ result2 = addDate(db, { dateStr: date, event, time: args.time, duration: args.duration, remind, channel: ctx.channel, channelTarget: ctx.channelTarget });
14261
14277
  }
14262
14278
  } else if (action === "add-batch") {
14263
14279
  const event = args.event?.trim();
14264
14280
  const datesInput = args.dates?.trim();
14265
14281
  if (!event) return { content: "Error: add-batch needs event", isError: true };
14266
14282
  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 });
14283
+ result2 = addBatch(db, { datesInput, event, time: args.time, duration: args.duration, remind: args.remind, channel: ctx.channel, channelTarget: ctx.channelTarget });
14268
14284
  } else if (action === "add-task") {
14269
14285
  isAddTask = true;
14270
14286
  const event = args.event?.trim();
@@ -14275,60 +14291,60 @@ var init_calendar = __esm({
14275
14291
  if (!date) return { content: "Error: add-task needs date (e.g. 7/5)", isError: true };
14276
14292
  if (!timeExact || !timeExact.includes(":")) return { content: "Error: add-task needs time_exact (HH:MM, e.g. 14:00)", isError: true };
14277
14293
  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 });
14294
+ result2 = addTask(db, { dateStr: date, timeExact, event, remind: args.remind, channel: ctx.channel, channelTarget: ctx.channelTarget, docPath });
14279
14295
  } else if (action === "reschedule") {
14280
14296
  if (args.id == null) return { content: "Error: reschedule needs id", isError: true };
14281
14297
  const date = args.date?.trim();
14282
14298
  const timeExact = args.time_exact?.trim();
14283
14299
  if (!date) return { content: "Error: reschedule needs date (e.g. 7/10)", isError: true };
14284
14300
  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 });
14301
+ result2 = reschedule(db, { id: args.id, dateStr: date, timeExact, remind: args.remind });
14286
14302
  } else if (action === "link-doc") {
14287
14303
  if (args.id == null) return { content: "Error: link-doc needs id", isError: true };
14288
14304
  const docPath = args.doc_path?.trim();
14289
14305
  if (!docPath) return { content: "Error: link-doc needs doc_path", isError: true };
14290
- result = linkDoc(db, args.id, docPath);
14306
+ result2 = linkDoc(db, args.id, docPath);
14291
14307
  } else if (action === "find-doc") {
14292
14308
  if (args.id == null) return { content: "Error: find-doc needs id", isError: true };
14293
- result = findDoc(db, args.id);
14309
+ result2 = findDoc(db, args.id);
14294
14310
  } else if (action === "list") {
14295
- result = list(db, { all: !!args.all });
14311
+ result2 = list(db, { all: !!args.all });
14296
14312
  } else if (action === "done") {
14297
14313
  if (args.id == null) return { content: "Error: done needs id", isError: true };
14298
- result = done(db, args.id);
14314
+ result2 = done(db, args.id);
14299
14315
  } else if (action === "pending") {
14300
- result = pending(db);
14316
+ result2 = pending(db);
14301
14317
  } else if (action === "search") {
14302
14318
  const kw = args.event?.trim();
14303
14319
  if (!kw) return { content: "Error: search needs keyword (event field)", isError: true };
14304
- result = search(db, kw);
14320
+ result2 = search(db, kw);
14305
14321
  } else if (action === "archive") {
14306
14322
  if (args.id == null) return { content: "Error: archive needs id", isError: true };
14307
- result = archive(db, args.id);
14323
+ result2 = archive(db, args.id);
14308
14324
  } else if (action === "delete") {
14309
14325
  if (args.id == null) return { content: "Error: delete needs id", isError: true };
14310
- result = archive(db, args.id);
14326
+ result2 = archive(db, args.id);
14311
14327
  } else if (action === "cleanup") {
14312
- result = cleanup(db);
14328
+ result2 = cleanup(db);
14313
14329
  } else if (action === "stats") {
14314
- result = stats(db);
14330
+ result2 = stats(db);
14315
14331
  } else {
14316
14332
  return { content: `Error: unknown action '${action}'`, isError: true };
14317
14333
  }
14318
14334
  db.close();
14319
- const isFailed = result.startsWith("\u274C") || result.includes("Error") || result.includes("\u7528\u6CD5");
14335
+ const isFailed = result2.startsWith("\u274C") || result2.includes("Error") || result2.includes("\u7528\u6CD5");
14320
14336
  if (isAddTask && !isFailed) {
14321
14337
  const { enqueueNotification: enqueueNotification2, buildCalendarNotification: buildCalendarNotification2 } = await Promise.resolve().then(() => (init_task_manager(), task_manager_exports));
14322
14338
  const sessionId = ctx.sessionId || "main";
14323
14339
  const channel = ctx.channel;
14324
14340
  const channelTarget = ctx.channelTarget;
14325
14341
  if (!channel || !channelTarget) {
14326
- return { content: result };
14342
+ return { content: result2 };
14327
14343
  }
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>"]);
14344
+ 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
14345
  enqueueNotification2(notif, { sessionId, channel, channelTarget });
14330
14346
  }
14331
- return { content: result };
14347
+ return { content: result2 };
14332
14348
  } catch (e) {
14333
14349
  return { content: `Calendar ${action} failed: ${e.message}`, isError: true };
14334
14350
  }
@@ -14628,10 +14644,10 @@ var init_TodoWriteTool = __esm({
14628
14644
  const allDone = todos.length > 0 && todos.every((t) => t.status === "completed");
14629
14645
  const newTodos = allDone ? [] : todos;
14630
14646
  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";
14647
+ 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
14648
  if (allDone && todos.length >= 3) {
14633
14649
  }
14634
- return { content: result };
14650
+ return { content: result2 };
14635
14651
  },
14636
14652
  isReadOnly: () => false,
14637
14653
  isConcurrencySafe: () => false
@@ -16459,16 +16475,16 @@ var init_task_output = __esm({
16459
16475
  }
16460
16476
  let task = initialTask;
16461
16477
  if (block && (task.status === "running" || task.status === "pending")) {
16462
- const result2 = await waitForTaskCompletion(taskId, timeout, signal);
16463
- if (!result2) {
16478
+ const result3 = await waitForTaskCompletion(taskId, timeout, signal);
16479
+ if (!result3) {
16464
16480
  return { content: `Task ${taskId} was aborted or not found`, isError: true };
16465
16481
  }
16466
- task = result2;
16482
+ task = result3;
16467
16483
  }
16468
16484
  const output = getTaskOutput(taskId);
16469
16485
  const truncated = output.length > 5e4 ? output.slice(0, 5e4) + "\n...[output truncated]" : output;
16470
16486
  const retrievalStatus = !block && (task.status === "running" || task.status === "pending") ? "not_ready" : block && (task.status === "running" || task.status === "pending") ? "timeout" : "success";
16471
- const result = {
16487
+ const result2 = {
16472
16488
  retrieval_status: retrievalStatus,
16473
16489
  task: {
16474
16490
  task_id: task.id,
@@ -16480,7 +16496,7 @@ var init_task_output = __esm({
16480
16496
  }
16481
16497
  };
16482
16498
  return {
16483
- content: JSON.stringify(result, null, 2)
16499
+ content: JSON.stringify(result2, null, 2)
16484
16500
  };
16485
16501
  },
16486
16502
  isConcurrencySafe: () => true,
@@ -16628,7 +16644,7 @@ var init_reply_blocklist = __esm({
16628
16644
  const workspace = ctx.workspace || process.env.ENGINE_WORKSPACE || ".";
16629
16645
  const stripIds = ctx?.channelConfig?.discord?.stripMentionIds || [];
16630
16646
  ensureLoaded(workspace, stripIds);
16631
- let result;
16647
+ let result2;
16632
16648
  switch (action) {
16633
16649
  case "list": {
16634
16650
  const lines = ["**\u81EA\u52A8\u56DE\u590D\u5C4F\u853D\u5217\u8868\uFF1A**"];
@@ -16642,14 +16658,14 @@ var init_reply_blocklist = __esm({
16642
16658
  lines.push(` - \`${id}\``);
16643
16659
  }
16644
16660
  }
16645
- result = { content: lines.join("\n") };
16661
+ result2 = { content: lines.join("\n") };
16646
16662
  break;
16647
16663
  }
16648
16664
  case "block_all": {
16649
16665
  state.blockAll = true;
16650
16666
  save(workspace);
16651
16667
  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' };
16668
+ result2 = { content: '\u{1F6AB} \u5DF2\u5C4F\u853D\u6240\u6709\u4EBA\u7684\u81EA\u52A8\u56DE\u590D\u3002\u7528 action="unblock_all" \u89E3\u9664\u3002' };
16653
16669
  break;
16654
16670
  }
16655
16671
  case "unblock_all": {
@@ -16657,7 +16673,7 @@ var init_reply_blocklist = __esm({
16657
16673
  state.blockedUserIds = [];
16658
16674
  save(workspace);
16659
16675
  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" };
16676
+ result2 = { content: "\u2705 \u5DF2\u89E3\u9664\u6240\u6709\u4EBA\u5C4F\u853D\uFF0C\u6E05\u7A7A\u5C4F\u853D\u5217\u8868\u3002" };
16661
16677
  break;
16662
16678
  }
16663
16679
  case "add": {
@@ -16674,7 +16690,7 @@ var init_reply_blocklist = __esm({
16674
16690
  }
16675
16691
  save(workspace);
16676
16692
  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(", ")}` };
16693
+ 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
16694
  break;
16679
16695
  }
16680
16696
  case "remove": {
@@ -16687,11 +16703,11 @@ var init_reply_blocklist = __esm({
16687
16703
  const removed = before - state.blockedUserIds.length;
16688
16704
  save(workspace);
16689
16705
  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` };
16706
+ result2 = { content: `\u2705 \u5DF2\u79FB\u9664 ${removed} \u4EBA\uFF08\u5269 ${state.blockedUserIds.length} \u4EBA\uFF09\u3002` };
16691
16707
  break;
16692
16708
  }
16693
16709
  default:
16694
- result = { content: `Error: \u672A\u77E5\u64CD\u4F5C "${action}"`, isError: true };
16710
+ result2 = { content: `Error: \u672A\u77E5\u64CD\u4F5C "${action}"`, isError: true };
16695
16711
  }
16696
16712
  const adapters = globalThis.__channelAdapters;
16697
16713
  if (adapters) {
@@ -16700,7 +16716,7 @@ var init_reply_blocklist = __esm({
16700
16716
  discordAdapter.addStripMentionIds(state.blockedUserIds);
16701
16717
  }
16702
16718
  }
16703
- return result;
16719
+ return result2;
16704
16720
  },
16705
16721
  isConcurrencySafe: () => true,
16706
16722
  isReadOnly: () => false
@@ -16744,7 +16760,7 @@ var init_wx_query = __esm({
16744
16760
  "use strict";
16745
16761
  init_registry();
16746
16762
  init_live();
16747
- STATE_DIR = process.env.ENGINE7_STATE_DIR || process.env.OPENCLAW_STATE_DIR || join24(process.env.HOME || process.env.USERPROFILE || ".", ".engine7");
16763
+ STATE_DIR = process.env.ENGINE7_STATE_DIR || join24(process.env.HOME || process.env.USERPROFILE || ".", ".engine7");
16748
16764
  SCRIPT = join24("/Users/chongzhang/work/twinsun-hearth/engine", "src", "tools", "wechat", "wx_query.py");
16749
16765
  PYTHON = "python3";
16750
16766
  registry.register({
@@ -17165,9 +17181,9 @@ Select up to ${topK} most relevant (return their 1-indexed numbers as JSON {"sel
17165
17181
  const parsed = JSON.parse(jsonMatch[0]);
17166
17182
  if (parsed.selected && Array.isArray(parsed.selected)) {
17167
17183
  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);
17184
+ const result2 = indices.map((i) => candidates[i]);
17185
+ console.log(`[memdir] rerank: ${model} selected ${result2.length}/${candidates.length} candidates (indices: ${indices.map((i) => i + 1).join(",")})`);
17186
+ return result2.slice(0, topK);
17171
17187
  }
17172
17188
  } catch {
17173
17189
  }
@@ -17393,7 +17409,7 @@ async function findRelevantMemoriesEveros(query, _memoryDir, alreadySurfaced = /
17393
17409
  } else {
17394
17410
  }
17395
17411
  }
17396
- const result = [];
17412
+ const result2 = [];
17397
17413
  const seenSubjects = /* @__PURE__ */ new Set();
17398
17414
  for (const ep of episodes) {
17399
17415
  if (ep.score < minScore) continue;
@@ -17403,7 +17419,7 @@ async function findRelevantMemoriesEveros(query, _memoryDir, alreadySurfaced = /
17403
17419
  if (surfacedSubjects.has(subject)) continue;
17404
17420
  if (seenSubjects.has(subject)) continue;
17405
17421
  seenSubjects.add(subject);
17406
- result.push({
17422
+ result2.push({
17407
17423
  path: virtualPath,
17408
17424
  mtimeMs: ep.timestamp ? new Date(ep.timestamp).getTime() : Date.now(),
17409
17425
  content: `### ${ep.subject}
@@ -17411,10 +17427,10 @@ async function findRelevantMemoriesEveros(query, _memoryDir, alreadySurfaced = /
17411
17427
  ${ep.episode || ep.summary}`,
17412
17428
  header: formatEverosHeader(ep)
17413
17429
  });
17414
- if (result.length >= topK) break;
17430
+ if (result2.length >= topK) break;
17415
17431
  }
17416
- console.log(`[memdir] everos recall: returning ${result.length} memories (after dedup)`);
17417
- return result;
17432
+ console.log(`[memdir] everos recall: returning ${result2.length} memories (after dedup)`);
17433
+ return result2;
17418
17434
  } catch (e) {
17419
17435
  const ms = Date.now() - t0;
17420
17436
  console.warn(`[memdir] everos recall: error after ${ms}ms: ${e?.message ?? e}`);
@@ -17812,10 +17828,10 @@ ${conversationText}`
17812
17828
  channelManager: null
17813
17829
  };
17814
17830
  let toolCount = 0;
17815
- let result = "";
17831
+ let result2 = "";
17816
17832
  for await (const chunk of extractEngine.query(extractMessages, void 0, toolContext)) {
17817
17833
  if (chunk.type === "text" && chunk.text) {
17818
- result += chunk.text;
17834
+ result2 += chunk.text;
17819
17835
  }
17820
17836
  if (chunk.type === "tool_call") {
17821
17837
  toolCount++;
@@ -17826,7 +17842,7 @@ ${conversationText}`
17826
17842
  persistState(workspace);
17827
17843
  const duration = Date.now() - startTime;
17828
17844
  console.log(
17829
- `[memory] extractMemories finished in ${duration}ms \u2014 ${toolCount} tools used, ${result.length} chars`
17845
+ `[memory] extractMemories finished in ${duration}ms \u2014 ${toolCount} tools used, ${result2.length} chars`
17830
17846
  );
17831
17847
  } catch (error) {
17832
17848
  console.warn(
@@ -18241,18 +18257,18 @@ function truncateSessionMemoryForCompact(content) {
18241
18257
  let wasTruncated = false;
18242
18258
  for (const line of lines) {
18243
18259
  if (line.startsWith("# ")) {
18244
- const result2 = flushSessionSection(currentSectionHeader, currentSectionLines, maxCharsPerSection);
18245
- outputLines.push(...result2.lines);
18246
- wasTruncated = wasTruncated || result2.wasTruncated;
18260
+ const result3 = flushSessionSection(currentSectionHeader, currentSectionLines, maxCharsPerSection);
18261
+ outputLines.push(...result3.lines);
18262
+ wasTruncated = wasTruncated || result3.wasTruncated;
18247
18263
  currentSectionHeader = line;
18248
18264
  currentSectionLines = [];
18249
18265
  } else {
18250
18266
  currentSectionLines.push(line);
18251
18267
  }
18252
18268
  }
18253
- const result = flushSessionSection(currentSectionHeader, currentSectionLines, maxCharsPerSection);
18254
- outputLines.push(...result.lines);
18255
- wasTruncated = wasTruncated || result.wasTruncated;
18269
+ const result2 = flushSessionSection(currentSectionHeader, currentSectionLines, maxCharsPerSection);
18270
+ outputLines.push(...result2.lines);
18271
+ wasTruncated = wasTruncated || result2.wasTruncated;
18256
18272
  return { truncatedContent: outputLines.join("\n"), wasTruncated };
18257
18273
  }
18258
18274
  function flushSessionSection(sectionHeader, sectionLines, maxCharsPerSection) {
@@ -18439,10 +18455,10 @@ ${messages.filter((m) => m.role === "user" || m.role === "assistant").slice(-20)
18439
18455
  channelManager: null
18440
18456
  };
18441
18457
  let toolCount = 0;
18442
- let result = "";
18458
+ let result2 = "";
18443
18459
  for await (const chunk of extractEngine.query(extractMessages, void 0, toolContext)) {
18444
18460
  if (chunk.type === "text" && chunk.text) {
18445
- result += chunk.text;
18461
+ result2 += chunk.text;
18446
18462
  }
18447
18463
  if (chunk.type === "tool_call") {
18448
18464
  toolCount++;
@@ -18451,7 +18467,7 @@ ${messages.filter((m) => m.role === "user" || m.role === "assistant").slice(-20)
18451
18467
  recordExtractionTokenCount(roughTokenCountEstimation5(
18452
18468
  messages.map((m) => typeof m.content === "string" ? m.content : "").join("")
18453
18469
  ));
18454
- console.log(`[sessionMemory] extraction complete: ${toolCount} edits applied, ${result.length} chars`);
18470
+ console.log(`[sessionMemory] extraction complete: ${toolCount} edits applied, ${result2.length} chars`);
18455
18471
  return {
18456
18472
  fired: true,
18457
18473
  summary: `Applied ${toolCount} edits to session notes`
@@ -18834,23 +18850,23 @@ ${sessionIds.map((id) => `- ${id}`).join("\n")}`;
18834
18850
  workspace,
18835
18851
  channelManager: null
18836
18852
  };
18837
- let result = "";
18853
+ let result2 = "";
18838
18854
  let turnCount = 0;
18839
18855
  dlog("dream query START");
18840
18856
  for await (const chunk of dreamEngine.query(messages, void 0, toolContext)) {
18841
18857
  if (chunk.type === "text") {
18842
- result += chunk.text || "";
18858
+ result2 += chunk.text || "";
18843
18859
  }
18844
18860
  if (chunk.type === "tool_call") {
18845
18861
  turnCount++;
18846
18862
  dlog(`dream turn ${turnCount}: tool_call`);
18847
18863
  }
18848
18864
  }
18849
- dlog(`dream query DONE \u2014 ${turnCount} tool_calls, result=${result.length} chars`);
18865
+ dlog(`dream query DONE \u2014 ${turnCount} tool_calls, result=${result2.length} chars`);
18850
18866
  await recordConsolidation(memoryDir);
18851
18867
  dlog(`recordConsolidation OK \u2014 wrote .consolidate-lock`);
18852
18868
  console.log(`[autoDream] completed \u2014 reviewed ${sessionIds.length} sessions`);
18853
- return { fired: true, summary: result.slice(0, 500) };
18869
+ return { fired: true, summary: result2.slice(0, 500) };
18854
18870
  } catch (e) {
18855
18871
  const err = e;
18856
18872
  dlog(`CATCH failed: ${err.message}
@@ -18879,6 +18895,7 @@ var handle_query_exports = {};
18879
18895
  __export(handle_query_exports, {
18880
18896
  handleQuery: () => handleQuery,
18881
18897
  resetSessionStartInjection: () => resetSessionStartInjection,
18898
+ resetWorkModeInjection: () => resetWorkModeInjection,
18882
18899
  resolveSystemPrompt: () => resolveSystemPrompt
18883
18900
  });
18884
18901
  import { readFileSync as readFileSync25, existsSync as existsSync22 } from "node:fs";
@@ -18890,6 +18907,9 @@ function resolveSystemPrompt(v) {
18890
18907
  function resetSessionStartInjection(sessionId) {
18891
18908
  sessionStartDone.delete(sessionId);
18892
18909
  }
18910
+ function resetWorkModeInjection(sessionId) {
18911
+ workModeInjected.delete(sessionId);
18912
+ }
18893
18913
  function loadExternalChanRules(workspace) {
18894
18914
  const path30 = join33(workspace, "prompts", "external-chan-rules.md");
18895
18915
  if (externalChanRulesCache && externalChanRulesCache.path === path30) return externalChanRulesCache;
@@ -19164,6 +19184,30 @@ ${text}` : text });
19164
19184
  }
19165
19185
  }
19166
19186
  }
19187
+ if (chatMode === "emotion") {
19188
+ if (workModeInjected.has(sessionId)) workModeInjected.delete(sessionId);
19189
+ } else if (!workModeInjected.has(sessionId)) {
19190
+ workModeInjected.add(sessionId);
19191
+ try {
19192
+ const sr = await executeSessionStartHooks(channelName === "cli" ? "cli" : "channel", {
19193
+ sessionId,
19194
+ workspace,
19195
+ cwd: workspace,
19196
+ channel: channelName === "cli" ? "console" : channelName,
19197
+ senderId: inboundMeta?.from || "",
19198
+ channelType: inboundMeta?.channelType || "",
19199
+ source
19200
+ });
19201
+ if (sr.additionalContexts && sr.additionalContexts.length > 0) {
19202
+ const att = createAttachmentMessage({ type: "session_start", text: sr.additionalContexts.join("\n\n") });
19203
+ history.push(att);
19204
+ messages.push(att);
19205
+ console.log(`[hooks] work-mode injection: ${sr.additionalContexts.length} additionalContext(s) at END of messages (session ${sessionId}, cache-safe, persisted)`);
19206
+ }
19207
+ } catch (err) {
19208
+ console.warn(`[hooks] work-mode injection error: ${err.message}`);
19209
+ }
19210
+ }
19167
19211
  const pendingNotifications2 = drainPendingNotifications();
19168
19212
  if (pendingNotifications2.length > 0) {
19169
19213
  messages.push(createAttachmentMessage({
@@ -19614,11 +19658,11 @@ ${text}` : text });
19614
19658
  toolOverride: void 0,
19615
19659
  disableThinking: extractP?.disableThinking ?? true
19616
19660
  });
19617
- executeAutoDream2().then((result) => {
19618
- if (result.fired) {
19619
- console.log(`[autoDream] completed: ${result.summary?.slice(0, 200)}`);
19661
+ executeAutoDream2().then((result2) => {
19662
+ if (result2.fired) {
19663
+ console.log(`[autoDream] completed: ${result2.summary?.slice(0, 200)}`);
19620
19664
  } else {
19621
- console.log(`[autoDream] not fired: ${result.reason}`);
19665
+ console.log(`[autoDream] not fired: ${result2.reason}`);
19622
19666
  }
19623
19667
  }).catch((err) => {
19624
19668
  console.warn(`[handle-query] AutoDream error: ${err.message}`);
@@ -19628,7 +19672,7 @@ stack: ${err.stack ?? "(none)"}`);
19628
19672
  }
19629
19673
  } catch (err) {
19630
19674
  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}
19675
+ (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
19676
  stack: ${err.stack ?? "(none)"}
19633
19677
  `);
19634
19678
  } catch {
@@ -19646,7 +19690,7 @@ function roughTokenCount(messages) {
19646
19690
  }
19647
19691
  return total;
19648
19692
  }
19649
- var sessionStartDone, externalChanRulesCache;
19693
+ var sessionStartDone, workModeInjected, externalChanRulesCache;
19650
19694
  var init_handle_query = __esm({
19651
19695
  "src/handle-query.ts"() {
19652
19696
  "use strict";
@@ -19668,6 +19712,7 @@ var init_handle_query = __esm({
19668
19712
  init_light_mode();
19669
19713
  init_sender_context();
19670
19714
  sessionStartDone = /* @__PURE__ */ new Set();
19715
+ workModeInjected = /* @__PURE__ */ new Set();
19671
19716
  externalChanRulesCache = null;
19672
19717
  }
19673
19718
  });
@@ -19998,10 +20043,10 @@ function emitInit(sessionId, model) {
19998
20043
  session_id: sessionId
19999
20044
  });
20000
20045
  }
20001
- function emitTurn(result, model) {
20046
+ function emitTurn(result2, model) {
20002
20047
  const content = [];
20003
- if (result.thinking) content.push({ type: "thinking", text: result.thinking });
20004
- content.push({ type: "text", text: result.text });
20048
+ if (result2.thinking) content.push({ type: "thinking", text: result2.thinking });
20049
+ content.push({ type: "text", text: result2.text });
20005
20050
  writeLine({
20006
20051
  type: "assistant",
20007
20052
  message: {
@@ -20014,25 +20059,25 @@ function emitTurn(result, model) {
20014
20059
  usage: { input_tokens: 0, output_tokens: 0 }
20015
20060
  },
20016
20061
  uuid: randomUUID9(),
20017
- session_id: result.sessionId
20062
+ session_id: result2.sessionId
20018
20063
  });
20019
20064
  writeLine({
20020
20065
  type: "result",
20021
- subtype: result.ok ? "success" : "error_during_execution",
20022
- is_error: !result.ok,
20023
- ...result.terminalReason ? { terminal_reason: result.terminalReason } : {},
20024
- duration_ms: result.durationMs,
20025
- duration_api_ms: result.durationMs,
20026
- num_turns: result.numTurns,
20027
- result: result.text,
20066
+ subtype: result2.ok ? "success" : "error_during_execution",
20067
+ is_error: !result2.ok,
20068
+ ...result2.terminalReason ? { terminal_reason: result2.terminalReason } : {},
20069
+ duration_ms: result2.durationMs,
20070
+ duration_api_ms: result2.durationMs,
20071
+ num_turns: result2.numTurns,
20072
+ result: result2.text,
20028
20073
  stop_reason: "end_turn",
20029
20074
  total_cost_usd: 0,
20030
20075
  usage: { input_tokens: 0, output_tokens: 0 },
20031
20076
  modelUsage: {},
20032
20077
  permission_denials: [],
20033
- errors: result.errors,
20078
+ errors: result2.errors,
20034
20079
  uuid: randomUUID9(),
20035
- session_id: result.sessionId
20080
+ session_id: result2.sessionId
20036
20081
  });
20037
20082
  }
20038
20083
  async function doCcRun(argv) {
@@ -20120,9 +20165,9 @@ async function doCcRun(argv) {
20120
20165
  process.stderr.write("cc-run: \u6CA1\u6536\u5230 prompt\uFF08-p \u6216 stdin user message \u5747\u4E3A\u7A7A\uFF09\n");
20121
20166
  return 1;
20122
20167
  }
20123
- let result;
20168
+ let result2;
20124
20169
  try {
20125
- result = await runQuery(args);
20170
+ result2 = await runQuery(args);
20126
20171
  } catch (e) {
20127
20172
  const errMsg = String(e?.message || e);
20128
20173
  process.stderr.write(`cc-run: ${errMsg}
@@ -20145,10 +20190,10 @@ async function doCcRun(argv) {
20145
20190
  return 1;
20146
20191
  }
20147
20192
  if (args.outputFormat === "stream-json") {
20148
- emitTurn(result, model);
20193
+ emitTurn(result2, model);
20149
20194
  await flushStdout();
20150
20195
  } else {
20151
- process.stdout.write(result.text.endsWith("\n") ? result.text : result.text + "\n");
20196
+ process.stdout.write(result2.text.endsWith("\n") ? result2.text : result2.text + "\n");
20152
20197
  await flushStdout();
20153
20198
  }
20154
20199
  return 0;
@@ -20189,26 +20234,26 @@ function saveTravelConfig(cfg) {
20189
20234
  fs26.writeFileSync(CONFIG_PATH, JSON.stringify(cfg, null, 2));
20190
20235
  }
20191
20236
  function sanitizeContent(content, dirs) {
20192
- let result = content;
20237
+ let result2 = content;
20193
20238
  for (const { placeholder, getOriginal } of PATH_PLACEHOLDERS) {
20194
20239
  const original = getOriginal(dirs);
20195
20240
  if (original) {
20196
- result = result.split(original).join(placeholder);
20197
- result = result.split(original.replace(/\//g, "\\")).join(placeholder);
20198
- result = result.split(original.replace(/\//g, "\\\\")).join(placeholder);
20241
+ result2 = result2.split(original).join(placeholder);
20242
+ result2 = result2.split(original.replace(/\//g, "\\")).join(placeholder);
20243
+ result2 = result2.split(original.replace(/\//g, "\\\\")).join(placeholder);
20199
20244
  }
20200
20245
  }
20201
- return result;
20246
+ return result2;
20202
20247
  }
20203
20248
  function restoreContent(content, dirs) {
20204
- let result = content;
20249
+ let result2 = content;
20205
20250
  for (const { placeholder, getOriginal } of PATH_PLACEHOLDERS) {
20206
20251
  const target = getOriginal(dirs);
20207
20252
  if (target) {
20208
- result = result.split(placeholder).join(target);
20253
+ result2 = result2.split(placeholder).join(target);
20209
20254
  }
20210
20255
  }
20211
- return result;
20256
+ return result2;
20212
20257
  }
20213
20258
  function isTextFile(filePath) {
20214
20259
  const ext = path28.extname(filePath).toLowerCase();
@@ -21140,7 +21185,7 @@ async function configureFeishu(rl, v) {
21140
21185
  const feishuMode = await ask(rl, "\u9009\u62E9 (1/2)", "1");
21141
21186
  if (feishuMode === "1") {
21142
21187
  console.log("\n\u{1F4DD} \u6B63\u5728\u751F\u6210\u98DE\u4E66\u4E8C\u7EF4\u7801...\n");
21143
- const result = await registerFeishuApp({
21188
+ const result2 = await registerFeishuApp({
21144
21189
  onLog: (msg2) => console.log(` ${msg2}`),
21145
21190
  onQrCode: async (url) => {
21146
21191
  try {
@@ -21154,14 +21199,14 @@ async function configureFeishu(rl, v) {
21154
21199
  }
21155
21200
  }
21156
21201
  });
21157
- if (result) {
21158
- v.feishuAppId = result.appId;
21159
- v.feishuAppSecret = result.appSecret;
21160
- v.feishuOpenId = result.openId || "";
21202
+ if (result2) {
21203
+ v.feishuAppId = result2.appId;
21204
+ v.feishuAppSecret = result2.appSecret;
21205
+ v.feishuOpenId = result2.openId || "";
21161
21206
  console.log(`
21162
- \u2705 App ID: ${result.appId}`);
21163
- console.log(` \u2705 App Secret: ${result.appSecret.slice(0, 6)}...`);
21164
- if (result.openId) console.log(` \u2705 Open ID: ${result.openId}`);
21207
+ \u2705 App ID: ${result2.appId}`);
21208
+ console.log(` \u2705 App Secret: ${result2.appSecret.slice(0, 6)}...`);
21209
+ if (result2.openId) console.log(` \u2705 Open ID: ${result2.openId}`);
21165
21210
  } else {
21166
21211
  console.log("\n \u26A0\uFE0F \u626B\u7801\u8D85\u65F6\u6216\u5931\u8D25\uFF0C\u8BF7\u624B\u52A8\u8F93\u5165");
21167
21212
  v.feishuAppId = await ask(rl, "\u98DE\u4E66 App ID");
@@ -21619,7 +21664,7 @@ async function main() {
21619
21664
  console.log("\u{1F527} \u98DE\u4E66\u626B\u7801\u63A5\u5165...");
21620
21665
  const { registerFeishuApp: registerFeishuApp2 } = await Promise.resolve().then(() => (init_feishu_quick_register(), feishu_quick_register_exports));
21621
21666
  const { renderQrTerminal: renderQrTerminal2 } = await Promise.resolve().then(() => (init_qr_render(), qr_render_exports));
21622
- const result = await registerFeishuApp2({
21667
+ const result2 = await registerFeishuApp2({
21623
21668
  onLog: (msg2) => console.log(` ${msg2}`),
21624
21669
  onQrCode: async (url) => {
21625
21670
  try {
@@ -21631,7 +21676,7 @@ async function main() {
21631
21676
  }
21632
21677
  }
21633
21678
  });
21634
- if (!result) {
21679
+ if (!result2) {
21635
21680
  console.error("\u274C \u626B\u7801\u8D85\u65F6\u6216\u5931\u8D25");
21636
21681
  process.exit(1);
21637
21682
  }
@@ -21654,13 +21699,13 @@ async function main() {
21654
21699
  if (configFile2 && fs27.existsSync(configFile2)) {
21655
21700
  const j = JSON.parse(fs27.readFileSync(configFile2, "utf8"));
21656
21701
  j.channels = j.channels || {};
21657
- j.channels.feishu = { enabled: true, appId: result.appId, appSecret: result.appSecret, connectionMode: "websocket", dmPolicy: "pairing", groupPolicy: "open" };
21702
+ j.channels.feishu = { enabled: true, appId: result2.appId, appSecret: result2.appSecret, connectionMode: "websocket", dmPolicy: "pairing", groupPolicy: "open" };
21658
21703
  fs27.writeFileSync(configFile2, JSON.stringify(j, null, 2), "utf8");
21659
21704
  console.log("\u2705 \u98DE\u4E66\u901A\u9053\u5DF2\u5199\u5165: " + configFile2);
21660
21705
  console.log("\u91CD\u542F\u751F\u6548: engine7 restart");
21661
21706
  } else {
21662
21707
  console.log("\u26A0\uFE0F \u6CA1\u627E\u5230 config\uFF0C\u624B\u52A8\u52A0\uFF1A");
21663
- console.log(JSON.stringify({ feishu: { enabled: true, appId: result.appId, appSecret: result.appSecret, connectionMode: "websocket", dmPolicy: "pairing", groupPolicy: "open" } }, null, 2));
21708
+ console.log(JSON.stringify({ feishu: { enabled: true, appId: result2.appId, appSecret: result2.appSecret, connectionMode: "websocket", dmPolicy: "pairing", groupPolicy: "open" } }, null, 2));
21664
21709
  }
21665
21710
  process.exit(0);
21666
21711
  }