reasonix 0.52.0 → 0.53.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (143) hide show
  1. package/README.md +1 -0
  2. package/README.zh-CN.md +1 -0
  3. package/dashboard/dist/app.css +1 -1
  4. package/dashboard/dist/app.js +13 -13
  5. package/dashboard/dist/app.js.map +1 -1
  6. package/dist/cli/{acp-NEUYWGUU.js → acp-ABNDGEYC.js} +63 -30
  7. package/dist/cli/acp-ABNDGEYC.js.map +1 -0
  8. package/dist/cli/chat-377YZV56.js +49 -0
  9. package/dist/cli/{chunk-FY5UERSG.js → chunk-2WZT27GR.js} +9 -9
  10. package/dist/cli/{chunk-B4MOGWHW.js → chunk-4EHRIP5U.js} +7 -7
  11. package/dist/cli/chunk-4EHRIP5U.js.map +1 -0
  12. package/dist/cli/{chunk-RCC73DWQ.js → chunk-4SBXAHR6.js} +4 -4
  13. package/dist/cli/{chunk-5YLEKX2V.js → chunk-4V4TKQMB.js} +4 -4
  14. package/dist/cli/{chunk-5YLEKX2V.js.map → chunk-4V4TKQMB.js.map} +1 -1
  15. package/dist/cli/chunk-7ZO6H6ZK.js +54 -0
  16. package/dist/cli/chunk-7ZO6H6ZK.js.map +1 -0
  17. package/dist/cli/{chunk-3OXD5CBM.js → chunk-A6GSOADP.js} +17870 -16070
  18. package/dist/cli/chunk-A6GSOADP.js.map +1 -0
  19. package/dist/cli/{chunk-Z663GVUB.js → chunk-APOSDBAU.js} +3 -3
  20. package/dist/cli/{chunk-CTRM32BP.js → chunk-B5JISV5I.js} +2 -2
  21. package/dist/cli/{chunk-HNZ4727T.js → chunk-DFHI2MRB.js} +412 -152
  22. package/dist/cli/chunk-DFHI2MRB.js.map +1 -0
  23. package/dist/cli/{chunk-CGVW5W7N.js → chunk-EPIHGOM3.js} +14 -14
  24. package/dist/cli/{chunk-CGVW5W7N.js.map → chunk-EPIHGOM3.js.map} +1 -1
  25. package/dist/cli/{chunk-77JIQ7SL.js → chunk-EQFZIHKJ.js} +8 -8
  26. package/dist/cli/chunk-EQFZIHKJ.js.map +1 -0
  27. package/dist/cli/{chunk-XNMXVL6C.js → chunk-FB27YXPX.js} +2 -2
  28. package/dist/cli/{chunk-ARBGTNHM.js → chunk-FK7NXDRP.js} +2 -2
  29. package/dist/cli/{chunk-AOYUW3HR.js → chunk-GCNBIWK7.js} +22 -2
  30. package/dist/cli/chunk-GCNBIWK7.js.map +1 -0
  31. package/dist/cli/{chunk-XBYHNZ5Z.js → chunk-GMQVINZK.js} +13 -5
  32. package/dist/cli/chunk-GMQVINZK.js.map +1 -0
  33. package/dist/cli/{chunk-MVLPXZAA.js → chunk-GOASYYZ4.js} +43 -11
  34. package/dist/cli/{chunk-MVLPXZAA.js.map → chunk-GOASYYZ4.js.map} +1 -1
  35. package/dist/cli/{chunk-WPY7AFS6.js → chunk-I4SH5Z7S.js} +2 -2
  36. package/dist/cli/{chunk-MW64SQUE.js → chunk-J26XOB2T.js} +2 -2
  37. package/dist/cli/{chunk-DLTE4GBY.js → chunk-J4MYMBJ7.js} +3 -3
  38. package/dist/cli/{chunk-CFJY64UA.js → chunk-LRO63VNK.js} +2 -2
  39. package/dist/cli/{chunk-XUZHBQSM.js → chunk-MQJR7YQ2.js} +2 -2
  40. package/dist/cli/{chunk-CPCUMMSR.js → chunk-NVI4XPOQ.js} +3 -3
  41. package/dist/cli/{chunk-RHQOGG43.js → chunk-OHSVEXFF.js} +3 -3
  42. package/dist/cli/chunk-OHSVEXFF.js.map +1 -0
  43. package/dist/cli/{chunk-AMSK3ZLB.js → chunk-P5SUHDUQ.js} +2 -2
  44. package/dist/cli/{chunk-GFJJEW3Z.js → chunk-QSKDP3OS.js} +55 -5
  45. package/dist/cli/chunk-QSKDP3OS.js.map +1 -0
  46. package/dist/cli/{chunk-D6WRFR6V.js → chunk-R7JMQMLD.js} +6 -5
  47. package/dist/cli/chunk-R7JMQMLD.js.map +1 -0
  48. package/dist/cli/{chunk-VVPV5HU6.js → chunk-RRZIIMAF.js} +2 -2
  49. package/dist/cli/{chunk-GNRKXRRE.js → chunk-S3QII236.js} +369 -359
  50. package/dist/cli/{chunk-GNRKXRRE.js.map → chunk-S3QII236.js.map} +1 -1
  51. package/dist/cli/{chunk-HI6THNAZ.js → chunk-TGP7JGHN.js} +32 -14
  52. package/dist/cli/chunk-TGP7JGHN.js.map +1 -0
  53. package/dist/cli/{chunk-CLHMV6OL.js → chunk-U7G72DHQ.js} +83 -42
  54. package/dist/cli/chunk-U7G72DHQ.js.map +1 -0
  55. package/dist/cli/{chunk-OMNRXZNA.js → chunk-URAI4YRL.js} +2 -2
  56. package/dist/cli/{chunk-6QBUXA73.js → chunk-V4AXMN4X.js} +2 -2
  57. package/dist/cli/{chunk-2W4F3RIZ.js → chunk-XHP6NYOT.js} +3 -2
  58. package/dist/cli/{chunk-2W4F3RIZ.js.map → chunk-XHP6NYOT.js.map} +1 -1
  59. package/dist/cli/{code-WN6D4VZO.js → code-JPFZJYVW.js} +34 -34
  60. package/dist/cli/{commands-DHETOY7O.js → commands-IUL2CLKH.js} +4 -4
  61. package/dist/cli/{commit-BBUYAKZV.js → commit-JT7LYBTL.js} +3 -3
  62. package/dist/cli/{config-KV7VV5LG.js → config-T4RWI5NG.js} +6 -2
  63. package/dist/cli/{desktop-LJVXWXNF.js → desktop-AUBW2SLL.js} +122 -38
  64. package/dist/cli/desktop-AUBW2SLL.js.map +1 -0
  65. package/dist/cli/devtools-O5HOMAGZ.js +3 -0
  66. package/dist/cli/diff-NINZHUJR.js +165 -0
  67. package/dist/cli/diff-NINZHUJR.js.map +1 -0
  68. package/dist/cli/{doctor-GI5LOEZL.js → doctor-OMAYGY4F.js} +10 -10
  69. package/dist/cli/{events-LBKMLFM4.js → events-5IVFJ4H3.js} +5 -5
  70. package/dist/cli/index.js +38 -38
  71. package/dist/cli/{mcp-DKEJK5ND.js → mcp-ECGJACAP.js} +3 -3
  72. package/dist/cli/{mcp-browse-V7KWDY32.js → mcp-browse-NGEOHVJB.js} +15 -15
  73. package/dist/cli/mcp-browse-NGEOHVJB.js.map +1 -0
  74. package/dist/cli/{mcp-inspect-MTABNHVM.js → mcp-inspect-ZIMNRG7G.js} +5 -5
  75. package/dist/cli/{prompt-ATI7DKHF.js → prompt-JCC3A7AA.js} +5 -5
  76. package/dist/cli/{prune-sessions-YQQSZTZS.js → prune-sessions-TE4BJYO2.js} +4 -4
  77. package/dist/cli/{replay-ZJQ4I4CJ.js → replay-2UUTCRTG.js} +29 -29
  78. package/dist/cli/replay-2UUTCRTG.js.map +1 -0
  79. package/dist/cli/{run-HFPRNWJY.js → run-ABQYOPVM.js} +22 -22
  80. package/dist/cli/{server-UHKO2VVM.js → server-MPCXIW2O.js} +27 -25
  81. package/dist/cli/{server-UHKO2VVM.js.map → server-MPCXIW2O.js.map} +1 -1
  82. package/dist/cli/{sessions-IQEWWUH3.js → sessions-YBPRGIAF.js} +16 -16
  83. package/dist/cli/{setup-5BYKCL62.js → setup-A34LF2QE.js} +42 -42
  84. package/dist/cli/setup-A34LF2QE.js.map +1 -0
  85. package/dist/cli/{stats-OFCGOQMZ.js → stats-GKG5JZQX.js} +6 -6
  86. package/dist/cli/stats-GKG5JZQX.js.map +1 -0
  87. package/dist/cli/{version-EODUFAAI.js → version-JD6QSM4X.js} +16 -16
  88. package/dist/index.d.ts +36 -5
  89. package/dist/index.js +443 -73
  90. package/dist/index.js.map +1 -1
  91. package/package.json +7 -2
  92. package/dist/cli/acp-NEUYWGUU.js.map +0 -1
  93. package/dist/cli/chat-QA6IVFJD.js +0 -49
  94. package/dist/cli/chunk-3OXD5CBM.js.map +0 -1
  95. package/dist/cli/chunk-77JIQ7SL.js.map +0 -1
  96. package/dist/cli/chunk-AOYUW3HR.js.map +0 -1
  97. package/dist/cli/chunk-B4MOGWHW.js.map +0 -1
  98. package/dist/cli/chunk-CLHMV6OL.js.map +0 -1
  99. package/dist/cli/chunk-D6WRFR6V.js.map +0 -1
  100. package/dist/cli/chunk-GFJJEW3Z.js.map +0 -1
  101. package/dist/cli/chunk-HI6THNAZ.js.map +0 -1
  102. package/dist/cli/chunk-HNZ4727T.js.map +0 -1
  103. package/dist/cli/chunk-I3NE5S63.js +0 -54
  104. package/dist/cli/chunk-I3NE5S63.js.map +0 -1
  105. package/dist/cli/chunk-RHQOGG43.js.map +0 -1
  106. package/dist/cli/chunk-XBYHNZ5Z.js.map +0 -1
  107. package/dist/cli/desktop-LJVXWXNF.js.map +0 -1
  108. package/dist/cli/diff-2JHMQAHI.js +0 -165
  109. package/dist/cli/diff-2JHMQAHI.js.map +0 -1
  110. package/dist/cli/mcp-browse-V7KWDY32.js.map +0 -1
  111. package/dist/cli/replay-ZJQ4I4CJ.js.map +0 -1
  112. package/dist/cli/setup-5BYKCL62.js.map +0 -1
  113. /package/dist/cli/{chat-QA6IVFJD.js.map → chat-377YZV56.js.map} +0 -0
  114. /package/dist/cli/{chunk-FY5UERSG.js.map → chunk-2WZT27GR.js.map} +0 -0
  115. /package/dist/cli/{chunk-RCC73DWQ.js.map → chunk-4SBXAHR6.js.map} +0 -0
  116. /package/dist/cli/{chunk-Z663GVUB.js.map → chunk-APOSDBAU.js.map} +0 -0
  117. /package/dist/cli/{chunk-CTRM32BP.js.map → chunk-B5JISV5I.js.map} +0 -0
  118. /package/dist/cli/{chunk-XNMXVL6C.js.map → chunk-FB27YXPX.js.map} +0 -0
  119. /package/dist/cli/{chunk-ARBGTNHM.js.map → chunk-FK7NXDRP.js.map} +0 -0
  120. /package/dist/cli/{chunk-WPY7AFS6.js.map → chunk-I4SH5Z7S.js.map} +0 -0
  121. /package/dist/cli/{chunk-MW64SQUE.js.map → chunk-J26XOB2T.js.map} +0 -0
  122. /package/dist/cli/{chunk-DLTE4GBY.js.map → chunk-J4MYMBJ7.js.map} +0 -0
  123. /package/dist/cli/{chunk-CFJY64UA.js.map → chunk-LRO63VNK.js.map} +0 -0
  124. /package/dist/cli/{chunk-XUZHBQSM.js.map → chunk-MQJR7YQ2.js.map} +0 -0
  125. /package/dist/cli/{chunk-CPCUMMSR.js.map → chunk-NVI4XPOQ.js.map} +0 -0
  126. /package/dist/cli/{chunk-AMSK3ZLB.js.map → chunk-P5SUHDUQ.js.map} +0 -0
  127. /package/dist/cli/{chunk-VVPV5HU6.js.map → chunk-RRZIIMAF.js.map} +0 -0
  128. /package/dist/cli/{chunk-OMNRXZNA.js.map → chunk-URAI4YRL.js.map} +0 -0
  129. /package/dist/cli/{chunk-6QBUXA73.js.map → chunk-V4AXMN4X.js.map} +0 -0
  130. /package/dist/cli/{code-WN6D4VZO.js.map → code-JPFZJYVW.js.map} +0 -0
  131. /package/dist/cli/{commands-DHETOY7O.js.map → commands-IUL2CLKH.js.map} +0 -0
  132. /package/dist/cli/{commit-BBUYAKZV.js.map → commit-JT7LYBTL.js.map} +0 -0
  133. /package/dist/cli/{config-KV7VV5LG.js.map → config-T4RWI5NG.js.map} +0 -0
  134. /package/dist/cli/{doctor-GI5LOEZL.js.map → devtools-O5HOMAGZ.js.map} +0 -0
  135. /package/dist/cli/{prompt-ATI7DKHF.js.map → doctor-OMAYGY4F.js.map} +0 -0
  136. /package/dist/cli/{events-LBKMLFM4.js.map → events-5IVFJ4H3.js.map} +0 -0
  137. /package/dist/cli/{mcp-DKEJK5ND.js.map → mcp-ECGJACAP.js.map} +0 -0
  138. /package/dist/cli/{mcp-inspect-MTABNHVM.js.map → mcp-inspect-ZIMNRG7G.js.map} +0 -0
  139. /package/dist/cli/{stats-OFCGOQMZ.js.map → prompt-JCC3A7AA.js.map} +0 -0
  140. /package/dist/cli/{prune-sessions-YQQSZTZS.js.map → prune-sessions-TE4BJYO2.js.map} +0 -0
  141. /package/dist/cli/{run-HFPRNWJY.js.map → run-ABQYOPVM.js.map} +0 -0
  142. /package/dist/cli/{sessions-IQEWWUH3.js.map → sessions-YBPRGIAF.js.map} +0 -0
  143. /package/dist/cli/{version-EODUFAAI.js.map → version-JD6QSM4X.js.map} +0 -0
@@ -2,7 +2,7 @@
2
2
  import { createRequire as __cr } from 'node:module'; if (typeof globalThis.require === 'undefined') { globalThis.require = __cr(import.meta.url); }
3
3
  import {
4
4
  SkillStore
5
- } from "./chunk-DLTE4GBY.js";
5
+ } from "./chunk-J4MYMBJ7.js";
6
6
 
7
7
  // src/core/event-redaction.ts
8
8
  var SECRET_KEY_RE = /(secret|token|password|passphrase|api[-_]?key|authorization|cookie|credential|passwd|pwd)/i;
@@ -81,7 +81,14 @@ var Eventizer = class {
81
81
  break;
82
82
  }
83
83
  case "error":
84
- out.push(this.errorEvent(ev.turn, ev.error ?? ev.content, false));
84
+ out.push(
85
+ this.errorEvent(ev.turn, ev.error ?? ev.content, ev.errorDetail?.recoverable ?? false, {
86
+ name: ev.errorDetail?.name,
87
+ code: ev.errorDetail?.code,
88
+ phase: ev.errorDetail?.phase,
89
+ retryable: ev.errorDetail?.retryable
90
+ })
91
+ );
85
92
  break;
86
93
  case "status":
87
94
  out.push(this.statusEvent(ev.turn, ev.content));
@@ -270,14 +277,15 @@ var Eventizer = class {
270
277
  text
271
278
  };
272
279
  }
273
- errorEvent(turn, message, recoverable) {
280
+ errorEvent(turn, message, recoverable, detail) {
274
281
  return {
275
282
  id: ++this.nextId,
276
283
  ts: (/* @__PURE__ */ new Date()).toISOString(),
277
284
  turn,
278
285
  type: "error",
279
286
  message,
280
- recoverable
287
+ recoverable,
288
+ ...detail
281
289
  };
282
290
  }
283
291
  /** Pattern-match warning text since LoopEvent doesn't carry a typed kind. Returns null
@@ -600,4 +608,4 @@ export {
600
608
  shouldAutoResolveCheckpoint,
601
609
  autoResolveVerdict
602
610
  };
603
- //# sourceMappingURL=chunk-XBYHNZ5Z.js.map
611
+ //# sourceMappingURL=chunk-GMQVINZK.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/core/event-redaction.ts","../../src/core/eventize.ts","../../src/core/pause-policy.ts","../../src/tools/skills.ts"],"sourcesContent":["const SECRET_KEY_RE =\n /(secret|token|password|passphrase|api[-_]?key|authorization|cookie|credential|passwd|pwd)/i;\n\nexport function redactEventValue<T>(value: T): T {\n return redactUnknown(value, null) as T;\n}\n\nfunction redactUnknown(value: unknown, key: string | null): unknown {\n if (Array.isArray(value)) return value.map((item) => redactUnknown(item, null));\n if (value && typeof value === \"object\") {\n const out: Record<string, unknown> = {};\n for (const [childKey, childValue] of Object.entries(value)) {\n out[childKey] = redactUnknown(childValue, childKey);\n }\n return out;\n }\n if (typeof value === \"string\") {\n if ((key && SECRET_KEY_RE.test(key)) || /^Bearer\\s+/i.test(value)) return \"[redacted]\";\n }\n return value;\n}\n","import type { LoopEvent } from \"../loop.js\";\nimport type { ChatMessage, RawUsage, ToolCall } from \"../types.js\";\nimport { redactEventValue } from \"./event-redaction.js\";\nimport type {\n Event,\n ErrorEvent as KernelErrorEvent,\n ModelDeltaEvent,\n ModelFinalEvent,\n ModelTurnStartedEvent,\n SessionCompactedEvent,\n SessionOpenedEvent,\n SlashInvokedEvent,\n StatusEvent,\n ToolCallEvent,\n ToolConfirmAllowEvent,\n ToolConfirmAlwaysAllowEvent,\n ToolConfirmDenyEvent,\n ToolDispatchedEvent,\n ToolIntentEvent,\n ToolPreparingEvent,\n ToolResultEvent,\n UserMessageEvent,\n} from \"./events.js\";\n\nexport interface EventizeContext {\n model: string;\n prefixHash: string;\n reasoningEffort: import(\"../config.js\").ReasoningEffort;\n}\n\nexport class Eventizer {\n private nextId = 0;\n private lastTurn = -1;\n private nextToolSeq = 0;\n /** Tool calls announced via tool_call_delta but not yet dispatched. FIFO upgraded by tool_start. */\n private preparingCallIds: string[] = [];\n /** Tool calls dispatched but not yet finished. FIFO popped by tool result. */\n private inflightCallIds: string[] = [];\n /** Per-turn dedupe so each toolCallIndex emits exactly one tool.preparing. */\n private announcedToolIdx = new Set<string>();\n\n consume(ev: LoopEvent, ctx: EventizeContext): Event[] {\n const out: Event[] = [];\n if (ev.turn !== this.lastTurn) {\n this.lastTurn = ev.turn;\n this.announcedToolIdx.clear();\n out.push(this.turnStartedEvent(ev.turn, ctx));\n }\n switch (ev.role) {\n case \"assistant_delta\":\n if (ev.content) out.push(this.deltaEvent(ev.turn, \"content\", ev.content));\n if (ev.reasoningDelta) out.push(this.deltaEvent(ev.turn, \"reasoning\", ev.reasoningDelta));\n break;\n case \"tool_call_delta\": {\n const idx = ev.toolCallIndex;\n const name = ev.toolName;\n if (idx === undefined || !name) break;\n const key = `${ev.turn}:${idx}`;\n if (this.announcedToolIdx.has(key)) break;\n this.announcedToolIdx.add(key);\n const callId = `tc-${++this.nextToolSeq}`;\n this.preparingCallIds.push(callId);\n out.push(this.toolPreparingEvent(ev.turn, callId, name));\n break;\n }\n case \"assistant_final\":\n out.push(this.finalEvent(ev));\n break;\n case \"tool_start\": {\n const callId = this.preparingCallIds.shift() ?? `tc-${++this.nextToolSeq}`;\n this.inflightCallIds.push(callId);\n out.push(this.toolIntentEvent(ev.turn, callId, ev.toolName ?? \"\", ev.toolArgs ?? \"\"));\n out.push(this.toolDispatchedEvent(ev.turn, callId));\n break;\n }\n case \"tool\": {\n const callId = this.inflightCallIds.shift() ?? `tc-orphan-${++this.nextToolSeq}`;\n const ok = !looksLikeToolError(ev.content, ev.toolName);\n out.push(this.toolResultEvent(ev.turn, callId, ok, ev.content, 0));\n break;\n }\n case \"warning\": {\n const classified = this.classifyWarning(ev);\n if (classified) out.push(classified);\n break;\n }\n case \"error\":\n out.push(\n this.errorEvent(ev.turn, ev.error ?? ev.content, ev.errorDetail?.recoverable ?? false, {\n name: ev.errorDetail?.name,\n code: ev.errorDetail?.code,\n phase: ev.errorDetail?.phase,\n retryable: ev.errorDetail?.retryable,\n }),\n );\n break;\n case \"status\":\n out.push(this.statusEvent(ev.turn, ev.content));\n break;\n // `done` / `branch_*` intentionally drop — no kernel-level event.\n default:\n break;\n }\n return out;\n }\n\n emitUserMessage(turn: number, text: string): UserMessageEvent {\n return {\n id: ++this.nextId,\n ts: new Date().toISOString(),\n turn,\n type: \"user.message\",\n text,\n };\n }\n\n emitSlashInvoked(turn: number, name: string, args: string): SlashInvokedEvent {\n return {\n id: ++this.nextId,\n ts: new Date().toISOString(),\n turn,\n type: \"slash.invoked\",\n name,\n args,\n };\n }\n\n emitSessionOpened(turn: number, name: string, resumedFromTurn: number): SessionOpenedEvent {\n return {\n id: ++this.nextId,\n ts: new Date().toISOString(),\n turn,\n type: \"session.opened\",\n name,\n resumedFromTurn,\n };\n }\n\n emitSessionCompacted(\n turn: number,\n before: number,\n after: number,\n reason: \"user\" | \"auto-context-pressure\",\n replacementMessages: ReadonlyArray<ChatMessage>,\n ): SessionCompactedEvent {\n return {\n id: ++this.nextId,\n ts: new Date().toISOString(),\n turn,\n type: \"session.compacted\",\n beforeMessages: before,\n afterMessages: after,\n reason,\n replacementMessages,\n };\n }\n\n emitToolCall(turn: number, name: string, args: Record<string, unknown>): ToolCallEvent {\n return {\n id: ++this.nextId,\n ts: new Date().toISOString(),\n turn,\n type: \"tool.call\",\n name,\n args: redactEventValue(args),\n };\n }\n\n emitToolConfirmAllow(\n turn: number,\n kind: \"run_command\" | \"run_background\",\n payload: { command: string },\n ): ToolConfirmAllowEvent {\n return {\n id: ++this.nextId,\n ts: new Date().toISOString(),\n turn,\n type: \"tool.confirm.allow\",\n kind,\n payload: redactEventValue(payload),\n };\n }\n\n emitToolConfirmDeny(\n turn: number,\n kind: \"run_command\" | \"run_background\",\n payload: { command: string },\n denyContext?: string,\n ): ToolConfirmDenyEvent {\n return {\n id: ++this.nextId,\n ts: new Date().toISOString(),\n turn,\n type: \"tool.confirm.deny\",\n kind,\n payload: redactEventValue(payload),\n denyContext,\n };\n }\n\n emitToolConfirmAlwaysAllow(\n turn: number,\n kind: \"run_command\" | \"run_background\",\n payload: { command: string },\n prefix: string,\n ): ToolConfirmAlwaysAllowEvent {\n return {\n id: ++this.nextId,\n ts: new Date().toISOString(),\n turn,\n type: \"tool.confirm.always_allow\",\n kind,\n payload: redactEventValue(payload),\n prefix,\n };\n }\n\n private turnStartedEvent(turn: number, ctx: EventizeContext): ModelTurnStartedEvent {\n return {\n id: ++this.nextId,\n ts: new Date().toISOString(),\n turn,\n type: \"model.turn.started\",\n model: ctx.model,\n reasoningEffort: ctx.reasoningEffort,\n prefixHash: ctx.prefixHash,\n };\n }\n\n private deltaEvent(\n turn: number,\n channel: \"content\" | \"reasoning\" | \"tool_args\",\n text: string,\n ): ModelDeltaEvent {\n return {\n id: ++this.nextId,\n ts: new Date().toISOString(),\n turn,\n type: \"model.delta\",\n channel,\n text,\n };\n }\n\n private finalEvent(ev: LoopEvent): ModelFinalEvent {\n const usage: RawUsage = ev.stats\n ? {\n prompt_tokens: ev.stats.usage.promptTokens,\n completion_tokens: ev.stats.usage.completionTokens,\n total_tokens: ev.stats.usage.totalTokens,\n prompt_cache_hit_tokens: ev.stats.usage.promptCacheHitTokens,\n prompt_cache_miss_tokens: ev.stats.usage.promptCacheMissTokens,\n }\n : {};\n const costUsd = ev.stats?.cost ?? 0;\n const out: ModelFinalEvent = {\n id: ++this.nextId,\n ts: new Date().toISOString(),\n turn: ev.turn,\n type: \"model.final\",\n content: ev.content,\n // toolCalls land later via tool_start → tool.intent — not in this event.\n toolCalls: [] as ReadonlyArray<ToolCall>,\n usage,\n costUsd,\n };\n if (ev.forcedSummary) out.forcedSummary = true;\n return out;\n }\n\n private toolPreparingEvent(turn: number, callId: string, name: string): ToolPreparingEvent {\n return {\n id: ++this.nextId,\n ts: new Date().toISOString(),\n turn,\n type: \"tool.preparing\",\n callId,\n name,\n };\n }\n\n private toolIntentEvent(\n turn: number,\n callId: string,\n name: string,\n args: string,\n ): ToolIntentEvent {\n return {\n id: ++this.nextId,\n ts: new Date().toISOString(),\n turn,\n type: \"tool.intent\",\n callId,\n name,\n args,\n };\n }\n\n private toolDispatchedEvent(turn: number, callId: string): ToolDispatchedEvent {\n return {\n id: ++this.nextId,\n ts: new Date().toISOString(),\n turn,\n type: \"tool.dispatched\",\n callId,\n };\n }\n\n private toolResultEvent(\n turn: number,\n callId: string,\n ok: boolean,\n output: string,\n durationMs: number,\n ): ToolResultEvent {\n return {\n id: ++this.nextId,\n ts: new Date().toISOString(),\n turn,\n type: \"tool.result\",\n callId,\n ok,\n output,\n durationMs,\n };\n }\n\n private statusEvent(turn: number, text: string): StatusEvent {\n return {\n id: ++this.nextId,\n ts: new Date().toISOString(),\n turn,\n type: \"status\",\n text,\n };\n }\n\n private errorEvent(\n turn: number,\n message: string,\n recoverable: boolean,\n detail?: { name?: string; code?: string; phase?: string; retryable?: boolean },\n ): KernelErrorEvent {\n return {\n id: ++this.nextId,\n ts: new Date().toISOString(),\n turn,\n type: \"error\",\n message,\n recoverable,\n ...detail,\n };\n }\n\n /** Pattern-match warning text since LoopEvent doesn't carry a typed kind. Returns null\n * for low-severity warnings (self-correcting / counter messages); the UI surface drops\n * them entirely instead of rendering noise. */\n private classifyWarning(ev: LoopEvent): Event | null {\n const c = ev.content;\n if (/\\bauto-escalating to\\b|\\barmed\\b.*pro|NEEDS_PRO/.test(c)) {\n return {\n id: ++this.nextId,\n ts: new Date().toISOString(),\n turn: ev.turn,\n type: \"policy.escalated\",\n fromModel: \"\",\n toModel: \"\",\n reason: c.includes(\"armed\") ? \"user-request\" : \"self-report\",\n };\n }\n if (/budget\\b.*\\$|\\$\\d.*\\/\\s*\\$\\d/.test(c)) {\n const blocked = /blocked|exceeded|refus/i.test(c);\n return {\n id: ++this.nextId,\n ts: new Date().toISOString(),\n turn: ev.turn,\n type: blocked ? \"policy.budget.blocked\" : \"policy.budget.warning\",\n spentUsd: 0,\n capUsd: 0,\n };\n }\n if (ev.severity === \"low\") return null;\n return {\n id: ++this.nextId,\n ts: new Date().toISOString(),\n turn: ev.turn,\n type: \"warning\",\n text: c,\n severity: ev.severity ?? \"high\",\n };\n }\n}\n\nfunction looksLikeToolError(content: string, _toolName: string | undefined): boolean {\n if (!content) return false;\n if (content.startsWith(\"ERROR:\")) return true;\n if (content.startsWith(\"[hook block]\")) return true;\n if (/^\\{\"error\"\\s*:/.test(content)) return true;\n if (/\\bConfirmationError:|\\bNeedsConfirmationError\\b/.test(content)) return true;\n return false;\n}\n","/** Shared editMode → auto-resolve rules so CLI TUI + Tauri desktop don't drift. */\n\nimport type { EditMode } from \"../config.js\";\nimport type { PauseRequest } from \"./pause-gate.js\";\n\n/** Mirrors shell.ts's allowAll bypass: only review still pauses on checkpoints. */\nexport function shouldAutoResolveCheckpoint(editMode: EditMode): boolean {\n return editMode === \"auto\" || editMode === \"yolo\";\n}\n\n/** null = surface to user; non-null = resolve gate immediately with this verdict. */\nexport function autoResolveVerdict(req: PauseRequest, editMode: EditMode): unknown | null {\n if (req.kind === \"plan_checkpoint\" && shouldAutoResolveCheckpoint(editMode)) {\n return { type: \"continue\" };\n }\n // yolo mirrors shell.ts's allowAll bypass — outside-sandbox reads/writes pass\n // through too. Stays \"run_once\" rather than \"always_allow\" so the YOLO session\n // doesn't pollute the on-disk allowlist with every transient path it touched.\n if (req.kind === \"path_access\" && editMode === \"yolo\") {\n return { type: \"run_once\" };\n }\n // Shell commands in YOLO: shell.ts's `allowAll` callback should already have\n // skipped gate.ask for these, but the closure reads on-disk config via\n // `loadEditMode()` while ACP's `--yolo` flag and any future runtime-only\n // YOLO source don't write to config. Without this second layer those paths\n // surface a confirmation prompt even though the user is in YOLO (#1448).\n // `run_once` matches shell.ts's behavior — don't pollute the persistent\n // allowlist with every transient command.\n if ((req.kind === \"run_command\" || req.kind === \"run_background\") && editMode === \"yolo\") {\n return { type: \"run_once\" };\n }\n return null;\n}\n","/** runAs: inline appends the body to the parent log; subagent spawns an isolated child loop and only returns the final answer. */\n\nimport { type Skill, SkillStore } from \"../skills.js\";\nimport type { ToolRegistry } from \"../tools.js\";\n\n/** Returns serialized tool-result string — dispatch path is pure pass-through. */\nexport type SubagentRunner = (skill: Skill, task: string, signal?: AbortSignal) => Promise<string>;\n\n/** Fired after a successful `install_skill` write — host wires this to push a fresh `$skills` event so the desktop sidebar updates without a tab reload. */\nexport type SkillInstalledHook = (info: {\n name: string;\n path: string;\n scope: \"project\" | \"global\";\n}) => void;\n\nexport interface SkillToolsOptions {\n /** Override `$HOME` — tests set this to a tmpdir. */\n homeDir?: string;\n projectRoot?: string;\n customSkillPaths?: readonly string[];\n /** When omitted, subagent skills error rather than silently falling back to inline (loses isolation). */\n subagentRunner?: SubagentRunner;\n /** Hide built-in skills (test-only knob; production callers leave off). */\n disableBuiltins?: boolean;\n /** Called synchronously after `install_skill` successfully writes a new skill file. */\n onSkillInstalled?: SkillInstalledHook;\n /** Per-skill model override for `runAs: subagent` skills — sourced from config.json's `subagentModels`. */\n subagentModels?: Record<string, \"flash\" | \"pro\">;\n}\n\ninterface BuiltinSubagentToolSpec {\n toolName: string;\n skillName: string;\n description: string;\n taskDescription: string;\n}\n\nfunction registerBuiltinSubagentTool(\n registry: ToolRegistry,\n store: SkillStore,\n subagentRunner: SubagentRunner | undefined,\n spec: BuiltinSubagentToolSpec,\n): void {\n // Eager presence check — keeps disableBuiltins test mode clean (no\n // phantom tool spec when its skill body is absent).\n if (!store.read(spec.skillName)) return;\n registry.register({\n name: spec.toolName,\n description: spec.description,\n readOnly: true,\n parallelSafe: true,\n parameters: {\n type: \"object\",\n properties: {\n task: { type: \"string\", description: spec.taskDescription },\n },\n required: [\"task\"],\n },\n fn: async (args: { task?: unknown }, ctx) => {\n if (!subagentRunner) {\n return JSON.stringify({\n error: `${spec.toolName}: no subagent runner is configured for this session — run inside \\`reasonix code\\`, or pass \\`subagentRunner\\` to \\`registerSkillTools\\`.`,\n });\n }\n const task = typeof args.task === \"string\" ? args.task.trim() : \"\";\n if (!task) {\n return JSON.stringify({\n error: `${spec.toolName} requires a non-empty 'task' argument — describe the concrete question.`,\n });\n }\n const skill = store.read(spec.skillName);\n if (!skill) {\n return JSON.stringify({\n error: `${spec.toolName}: built-in skill ${JSON.stringify(spec.skillName)} is no longer registered`,\n });\n }\n // A user-supplied skill with the same name but `runAs: inline`\n // would silently lose isolation if we dispatched it here — bounce\n // back to run_skill where inline is well-defined.\n if (skill.runAs !== \"subagent\") {\n return JSON.stringify({\n error: `${spec.toolName}: skill ${JSON.stringify(spec.skillName)} is overridden as inline; invoke it via run_skill instead.`,\n });\n }\n return subagentRunner(skill, task, ctx?.signal);\n },\n });\n}\n\nexport function registerSkillTools(\n registry: ToolRegistry,\n opts: SkillToolsOptions = {},\n): ToolRegistry {\n const store = new SkillStore({\n homeDir: opts.homeDir,\n projectRoot: opts.projectRoot,\n customSkillPaths: opts.customSkillPaths,\n disableBuiltins: opts.disableBuiltins,\n subagentModels: opts.subagentModels,\n });\n const subagentRunner = opts.subagentRunner;\n const onSkillInstalled = opts.onSkillInstalled;\n const hasProjectScope = store.hasProjectScope();\n\n registry.register({\n name: \"run_skill\",\n description:\n \"Invoke a user-defined playbook from the Skills index pinned in the system prompt. **For the built-in subagent skills (explore / research / review / security_review), prefer the dedicated top-level tools by the same name — they're cheaper to pick and produce the same result.** Pass `name` as the BARE skill identifier (e.g. 'my-custom-skill'), NOT the `[🧬 subagent]` tag that appears after it in the index. Entries tagged `[🧬 subagent]` spawn an isolated subagent — only the final distilled answer comes back. Plain skills are inlined: the body becomes a tool result you read and follow. For subagent skills, supply 'arguments' describing the concrete task — they'll be the only context the subagent has.\",\n readOnly: true,\n parallelSafe: true,\n parameters: {\n type: \"object\",\n properties: {\n name: {\n type: \"string\",\n description:\n \"Skill identifier as it appears in the pinned Skills index (e.g. 'explore', 'review', 'security-review'). Case-sensitive.\",\n },\n arguments: {\n type: \"string\",\n description:\n \"Free-form arguments the skill should act on. For inline skills: appended to the body as an 'Arguments:' line; the skill's own instructions decide how to consume them. For `[🧬 subagent]` skills: REQUIRED — becomes the entire task description the subagent receives, since it has no other context.\",\n },\n },\n required: [\"name\"],\n },\n fn: async (args: { name?: unknown; arguments?: unknown }, ctx) => {\n const raw = typeof args.name === \"string\" ? args.name.trim() : \"\";\n if (!raw) {\n return JSON.stringify({ error: \"run_skill requires a 'name' argument\" });\n }\n // Defensive: The Skills index writes entries like\n // `explore [🧬 subagent]`, and models sometimes copy the\n // decoration verbatim into the `name` argument instead of just\n // the identifier. Rather than reject those calls:\n // 1. Drop any `[...]` bracketed tag (possibly containing\n // emoji + \"subagent\" label).\n // 2. Find the first whitespace-delimited token whose first\n // char is alphanumeric — that's the skill identifier,\n // whether the tag came before or after the name.\n const stripped = raw.replace(/\\[[^\\]]*\\]/g, \" \").trim();\n const tokens = stripped.split(/\\s+/).filter(Boolean);\n const name = tokens.find((t) => /^[a-zA-Z0-9]/.test(t)) ?? \"\";\n if (!name) {\n return JSON.stringify({\n error: \"run_skill requires a 'name' argument\",\n hint: `'${raw}' is just a marker/tag, not a skill name`,\n });\n }\n const skill = store.read(name);\n if (!skill) {\n const available = store\n .list()\n .map((s) => s.name)\n .join(\", \");\n return JSON.stringify({\n error: `unknown skill: ${JSON.stringify(name)}`,\n available: available || \"(none — user has not defined any skills)\",\n });\n }\n const rawArgs = typeof args.arguments === \"string\" ? args.arguments.trim() : \"\";\n\n if (skill.runAs === \"subagent\") {\n if (!subagentRunner) {\n return JSON.stringify({\n error: `run_skill: skill ${JSON.stringify(name)} is marked runAs=subagent but no subagent runner is configured for this session. Skill authors who need isolation should run inside reasonix code (or a library setup that passes subagentRunner to registerSkillTools).`,\n });\n }\n if (!rawArgs) {\n return JSON.stringify({\n error: `run_skill: skill ${JSON.stringify(name)} is a subagent and requires 'arguments' — the subagent has no other context, so describe the concrete task in the arguments field.`,\n });\n }\n return subagentRunner(skill, rawArgs, ctx?.signal);\n }\n\n const header = [\n `# Skill: ${skill.name}`,\n skill.description ? `> ${skill.description}` : \"\",\n `(scope: ${skill.scope} · ${skill.path})`,\n ]\n .filter(Boolean)\n .join(\"\\n\");\n const argsBlock = rawArgs ? `\\n\\nArguments: ${rawArgs}` : \"\";\n const inner = `${header}\\n\\n${skill.body}${argsBlock}`;\n // Sentinel-wrapped so ContextManager.fold preserves the body verbatim instead of paraphrasing it.\n return `<skill-pin name=${JSON.stringify(skill.name)}>\\n${inner}\\n</skill-pin>`;\n },\n });\n\n // Top-level wrappers for built-in subagent skills. Same underlying\n // subagentRunner path as `run_skill(name=\"explore\", ...)`, but the\n // tool name matches the verb in the question — models pick it\n // because affordance design > prompt rules.\n registerBuiltinSubagentTool(registry, store, subagentRunner, {\n toolName: \"explore\",\n skillName: \"explore\",\n description:\n \"Run a focused read-only codebase investigation in an isolated subagent. **Use for broad survey questions across multiple files** — 'find all places that X', 'how does Y work across the project', 'audit Z'. Returns one distilled answer with file:line citations. Chained `read_file` is the wrong tool for these — it bloats your context with raw file contents; `explore`'s reads + reasoning never enter your log.\",\n taskDescription:\n \"Concrete investigation question. The subagent has none of your context — write a self-contained prompt naming the symbol / pattern / behavior you want surveyed.\",\n });\n registerBuiltinSubagentTool(registry, store, subagentRunner, {\n toolName: \"research\",\n skillName: \"research\",\n description:\n \"Combine web search + code reading in an isolated subagent. **Use when the answer needs both external reference and local verification** — 'is X supported by lib Y in version Z', 'compare our impl against the spec', 'what's the canonical way to do Q'. Returns one synthesis citing code (file:line) and web (URL). Reads + searches stay in the subagent.\",\n taskDescription:\n \"Concrete research question. The subagent has none of your context — name the external thing to look up and the local code to compare against.\",\n });\n registerBuiltinSubagentTool(registry, store, subagentRunner, {\n toolName: \"review\",\n skillName: \"review\",\n description:\n \"Review the pending changes (current branch diff) in an isolated subagent — flags correctness / security / missing-tests / hidden behavior per file:line. Read-only; you decide what to act on. Use before suggesting a PR-shaped change, or when you've finished a multi-step edit and want a second pass.\",\n taskDescription:\n \"What to focus the review on (e.g. 'focus on the auth changes' or 'general'). The subagent reads the diff itself.\",\n });\n registerBuiltinSubagentTool(registry, store, subagentRunner, {\n toolName: \"security_review\",\n skillName: \"security-review\",\n description:\n \"Security-focused review of current branch diff in an isolated subagent — injection / authz / secrets / deserialization / path-traversal / crypto issues, severity-tagged. Use when shipping changes that touch auth, input parsing, file IO, or external requests. Read-only.\",\n taskDescription:\n \"Optional scope hint (e.g. 'focus on token handling in src/auth/') or 'full' for everything in the diff.\",\n });\n\n const installScopeDesc = hasProjectScope\n ? \"'project' (default) writes to <repo>/.reasonix/skills/, scoped to this workspace only; 'global' writes to ~/.reasonix/skills/, available in every project.\"\n : \"'global' (only option here — no project workspace) writes to ~/.reasonix/skills/.\";\n\n registry.register({\n name: \"install_skill\",\n description:\n \"Author and save a new skill — a reusable playbook future turns invoke via `run_skill`. Runnable immediately (same turn); appears in the pinned Skills index on next `/new` or launch. Skill bodies become prompts for future turns, so write what you'd want your future self to follow.\",\n parameters: {\n type: \"object\",\n properties: {\n name: {\n type: \"string\",\n description:\n \"Identifier — letters/digits/_/-/., 1-64 chars, starts alnum. Becomes the filename.\",\n },\n description: {\n type: \"string\",\n description:\n \"≤120 char one-liner shown in the pinned Skills index — future agents read this to decide whether to invoke.\",\n },\n body: {\n type: \"string\",\n description:\n \"Markdown playbook. For subagent skills, write the subagent's persona/rules — it gets no context besides `arguments` at runtime.\",\n },\n scope: {\n type: \"string\",\n enum: [\"project\", \"global\"],\n description: installScopeDesc,\n },\n runAs: {\n type: \"string\",\n enum: [\"inline\", \"subagent\"],\n description:\n \"inline (default) appends body to parent log. subagent spawns isolated child loop; only final answer returns (use for context-heavy work).\",\n },\n model: {\n type: \"string\",\n description:\n \"Optional `deepseek-*` model override for runAs=subagent. Ignored otherwise.\",\n },\n allowedTools: {\n type: \"array\",\n items: { type: \"string\" },\n description:\n \"Optional tool allowlist for runAs=subagent (e.g. ['read_file','search_content']).\",\n },\n },\n required: [\"name\", \"description\", \"body\"],\n },\n fn: async (args: {\n name?: unknown;\n description?: unknown;\n body?: unknown;\n scope?: unknown;\n runAs?: unknown;\n model?: unknown;\n allowedTools?: unknown;\n }) => {\n const name = typeof args.name === \"string\" ? args.name.trim() : \"\";\n const description =\n typeof args.description === \"string\"\n ? args.description.replace(/[\\r\\n]+/g, \" \").trim()\n : \"\";\n const body = typeof args.body === \"string\" ? args.body : \"\";\n if (!name) return JSON.stringify({ error: \"install_skill requires a non-empty 'name'\" });\n if (!description) {\n return JSON.stringify({\n error:\n \"install_skill requires a non-empty 'description' — it is what appears in the Skills index and how future agents decide whether to invoke the skill\",\n });\n }\n if (!body.trim()) {\n return JSON.stringify({\n error:\n \"install_skill requires a non-empty 'body' — the playbook the skill executes when invoked\",\n });\n }\n\n const scopeRaw = typeof args.scope === \"string\" ? args.scope.trim() : \"\";\n let scope: \"project\" | \"global\";\n if (scopeRaw === \"global\") scope = \"global\";\n else if (scopeRaw === \"project\") scope = \"project\";\n else scope = hasProjectScope ? \"project\" : \"global\";\n if (scope === \"project\" && !hasProjectScope) {\n return JSON.stringify({\n error:\n \"install_skill: scope='project' requires a workspace — run from `reasonix code`, or use scope='global'\",\n });\n }\n\n const runAsRaw = typeof args.runAs === \"string\" ? args.runAs.trim() : \"\";\n const runAs: \"inline\" | \"subagent\" = runAsRaw === \"subagent\" ? \"subagent\" : \"inline\";\n\n const fmLines = [\"---\", `name: ${name}`, `description: ${description}`];\n if (runAs === \"subagent\") {\n fmLines.push(\"runAs: subagent\");\n const model = typeof args.model === \"string\" ? args.model.trim() : \"\";\n if (model) fmLines.push(`model: ${model}`);\n if (Array.isArray(args.allowedTools)) {\n const tools = args.allowedTools\n .filter((t): t is string => typeof t === \"string\")\n .map((t) => t.trim())\n .filter(Boolean);\n if (tools.length > 0) fmLines.push(`allowed-tools: ${tools.join(\", \")}`);\n }\n }\n fmLines.push(\"---\", \"\");\n const content = `${fmLines.join(\"\\n\")}${body.replace(/\\s+$/, \"\")}\\n`;\n\n const result = store.createWithContent(name, scope, content);\n if (\"error\" in result) {\n return JSON.stringify({ error: result.error });\n }\n\n try {\n onSkillInstalled?.({ name, path: result.path, scope });\n } catch {\n // host hook failure must not undo a successful write\n }\n\n return JSON.stringify({\n ok: true,\n name,\n scope,\n path: result.path,\n runAs,\n note: \"Skill is callable right now via run_skill({ name }). It will appear in the pinned Skills index after the next /new or launch.\",\n });\n },\n });\n\n return registry;\n}\n"],"mappings":"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","names":[]}
@@ -3,24 +3,24 @@ import { createRequire as __cr } from 'node:module'; if (typeof globalThis.requi
3
3
  import {
4
4
  formatMcpLifecycleEvent,
5
5
  formatMcpSlowToast
6
- } from "./chunk-CFJY64UA.js";
6
+ } from "./chunk-LRO63VNK.js";
7
7
  import {
8
8
  buildTransportFromSpec,
9
9
  preflightStdioSpec
10
- } from "./chunk-XUZHBQSM.js";
10
+ } from "./chunk-MQJR7YQ2.js";
11
11
  import {
12
12
  bridgeMcpTools
13
- } from "./chunk-HNZ4727T.js";
13
+ } from "./chunk-DFHI2MRB.js";
14
14
  import {
15
15
  McpClient,
16
16
  inspectMcpServer
17
- } from "./chunk-RCC73DWQ.js";
17
+ } from "./chunk-4SBXAHR6.js";
18
18
  import {
19
19
  loadDotenv
20
20
  } from "./chunk-2UQP6H6T.js";
21
21
  import {
22
22
  t
23
- } from "./chunk-CLHMV6OL.js";
23
+ } from "./chunk-U7G72DHQ.js";
24
24
  import {
25
25
  decideQQAccess,
26
26
  describeQQAccess,
@@ -33,7 +33,7 @@ import {
33
33
  readConfig,
34
34
  redactQQOpenId,
35
35
  specToRaw
36
- } from "./chunk-AOYUW3HR.js";
36
+ } from "./chunk-GCNBIWK7.js";
37
37
  import {
38
38
  __commonJS,
39
39
  __require,
@@ -3879,9 +3879,12 @@ var QQBot = class extends EventEmitter {
3879
3879
  this.closed = true;
3880
3880
  this.cleanup();
3881
3881
  }
3882
- async sendPrivateMessage(openid, content, msgId, msgSeq) {
3882
+ async sendPrivateMessage(openid, content, msgId, msgSeq, markdown = false) {
3883
3883
  const token = await this.ensureToken();
3884
- const body = {
3884
+ const body = markdown ? {
3885
+ markdown: { content },
3886
+ msg_type: 2
3887
+ } : {
3885
3888
  content,
3886
3889
  msg_type: 0
3887
3890
  };
@@ -3946,6 +3949,7 @@ function formatQQSetupWaiting(step) {
3946
3949
  var QQ_LOCK_FILE = join(homedir(), ".reasonix", "qq-channel.pid");
3947
3950
  var QQ_MAX_CHUNK_BYTES = 1500;
3948
3951
  var NATURAL_SPLIT_MIN_FRACTION = 0.6;
3952
+ var QQ_MARKDOWN_WRAPPER_RE = /^```(?:markdown|md)\s*\r?\n([\s\S]*?)\r?\n```$/i;
3949
3953
  function fitUtf8Slice(text, maxBytes) {
3950
3954
  let end = 0;
3951
3955
  let bytes = 0;
@@ -3981,6 +3985,14 @@ function splitQQMessage(text, maxBytes = QQ_MAX_CHUNK_BYTES) {
3981
3985
  }
3982
3986
  return chunks;
3983
3987
  }
3988
+ function normalizeQQMarkdownReply(text) {
3989
+ const trimmed = text.trim();
3990
+ const match = trimmed.match(QQ_MARKDOWN_WRAPPER_RE);
3991
+ if (!match) {
3992
+ return text;
3993
+ }
3994
+ return match[1] ?? text;
3995
+ }
3984
3996
  var QQChannel = class {
3985
3997
  constructor(callbacks) {
3986
3998
  this.callbacks = callbacks;
@@ -3996,6 +4008,7 @@ var QQChannel = class {
3996
4008
  processedMsgIdQueue = [];
3997
4009
  lockAcquired = false;
3998
4010
  nextOutboundMsgSeq = 1;
4011
+ markdownDisabled = false;
3999
4012
  rememberMessage(id) {
4000
4013
  if (this.processedMsgIds.has(id)) return false;
4001
4014
  this.processedMsgIds.add(id);
@@ -4141,16 +4154,35 @@ var QQChannel = class {
4141
4154
  }
4142
4155
  async sendResponse(text) {
4143
4156
  if (!this.bot || !this.qqUserId) return;
4144
- const chunks = splitQQMessage(text);
4157
+ const chunks = splitQQMessage(normalizeQQMarkdownReply(text));
4145
4158
  for (let index = 0; index < chunks.length; index++) {
4146
4159
  const chunk = chunks[index];
4147
4160
  if (!chunk) continue;
4148
4161
  try {
4162
+ const msgSeq = this.nextOutboundMsgSeq++;
4163
+ if (!this.markdownDisabled) {
4164
+ try {
4165
+ await this.bot.sendPrivateMessage(
4166
+ this.qqUserId,
4167
+ chunk,
4168
+ this.qqMessageId ?? void 0,
4169
+ msgSeq,
4170
+ true
4171
+ );
4172
+ continue;
4173
+ } catch (err) {
4174
+ this.markdownDisabled = true;
4175
+ this.callbacks.onError?.(
4176
+ `QQ markdown delivery disabled after first failure: ${err.message}`
4177
+ );
4178
+ }
4179
+ }
4149
4180
  await this.bot.sendPrivateMessage(
4150
4181
  this.qqUserId,
4151
4182
  chunk,
4152
4183
  this.qqMessageId ?? void 0,
4153
- this.nextOutboundMsgSeq++
4184
+ this.nextOutboundMsgSeq++,
4185
+ false
4154
4186
  );
4155
4187
  } catch (err) {
4156
4188
  const msg = `QQ sendResponse chunk ${index + 1}/${chunks.length} failed: ${err.message}`;
@@ -4465,4 +4497,4 @@ export {
4465
4497
  QQChannel,
4466
4498
  createMcpRuntime
4467
4499
  };
4468
- //# sourceMappingURL=chunk-MVLPXZAA.js.map
4500
+ //# sourceMappingURL=chunk-GOASYYZ4.js.map