@code-yeongyu/senpi 2026.9.16-2 → 2026.9.16-3

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 (87) hide show
  1. package/CHANGELOG.md +18 -2
  2. package/dist/cli/help-extension-flags.d.ts +22 -0
  3. package/dist/cli/help-extension-flags.d.ts.map +1 -0
  4. package/dist/cli/help-extension-flags.js +30 -0
  5. package/dist/cli/help-extension-flags.js.map +1 -0
  6. package/dist/cli/help-fast-path.d.ts +19 -0
  7. package/dist/cli/help-fast-path.d.ts.map +1 -0
  8. package/dist/cli/help-fast-path.js +64 -0
  9. package/dist/cli/help-fast-path.js.map +1 -0
  10. package/dist/cli/help-flags-cache.d.ts +23 -0
  11. package/dist/cli/help-flags-cache.d.ts.map +1 -0
  12. package/dist/cli/help-flags-cache.js +118 -0
  13. package/dist/cli/help-flags-cache.js.map +1 -0
  14. package/dist/cli/startup-loading-indicator.d.ts.map +1 -1
  15. package/dist/cli/startup-loading-indicator.js +10 -4
  16. package/dist/cli/startup-loading-indicator.js.map +1 -1
  17. package/dist/cli.js +9 -0
  18. package/dist/cli.js.map +1 -1
  19. package/dist/core/agent-session.d.ts +0 -11
  20. package/dist/core/agent-session.d.ts.map +1 -1
  21. package/dist/core/agent-session.js +6 -50
  22. package/dist/core/agent-session.js.map +1 -1
  23. package/dist/core/extensions/builtin/ttsr/detectors/collapse-near-duplicates.d.ts +38 -0
  24. package/dist/core/extensions/builtin/ttsr/detectors/collapse-near-duplicates.d.ts.map +1 -0
  25. package/dist/core/extensions/builtin/ttsr/detectors/collapse-near-duplicates.js +155 -0
  26. package/dist/core/extensions/builtin/ttsr/detectors/collapse-near-duplicates.js.map +1 -0
  27. package/dist/core/extensions/builtin/ttsr/detectors/collapse.d.ts +2 -0
  28. package/dist/core/extensions/builtin/ttsr/detectors/collapse.d.ts.map +1 -1
  29. package/dist/core/extensions/builtin/ttsr/detectors/collapse.js +4 -1
  30. package/dist/core/extensions/builtin/ttsr/detectors/collapse.js.map +1 -1
  31. package/dist/core/retry-fallback/settings.d.ts +0 -3
  32. package/dist/core/retry-fallback/settings.d.ts.map +1 -1
  33. package/dist/core/retry-fallback/settings.js.map +1 -1
  34. package/dist/core/sdk.d.ts.map +1 -1
  35. package/dist/core/sdk.js +0 -1
  36. package/dist/core/sdk.js.map +1 -1
  37. package/dist/core/settings-manager.d.ts +1 -12
  38. package/dist/core/settings-manager.d.ts.map +1 -1
  39. package/dist/core/settings-manager.js +0 -21
  40. package/dist/core/settings-manager.js.map +1 -1
  41. package/dist/main.d.ts.map +1 -1
  42. package/dist/main.js +31 -3
  43. package/dist/main.js.map +1 -1
  44. package/dist/modes/interactive/interactive-mode.d.ts +1 -12
  45. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  46. package/dist/modes/interactive/interactive-mode.js +1 -34
  47. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  48. package/dist/modes/interactive/working-status.d.ts +2 -3
  49. package/dist/modes/interactive/working-status.d.ts.map +1 -1
  50. package/dist/modes/interactive/working-status.js +4 -17
  51. package/dist/modes/interactive/working-status.js.map +1 -1
  52. package/dist/senpi +9 -0
  53. package/docs/settings.md +1 -19
  54. package/node_modules/@code-yeongyu/senpi-codemode/CHANGELOG.md +12 -0
  55. package/node_modules/@code-yeongyu/senpi-codemode/package.json +4 -4
  56. package/node_modules/@earendil-works/pi-agent-core/dist/agent-loop.d.ts.map +1 -1
  57. package/node_modules/@earendil-works/pi-agent-core/dist/agent-loop.js +3 -30
  58. package/node_modules/@earendil-works/pi-agent-core/dist/agent-loop.js.map +1 -1
  59. package/node_modules/@earendil-works/pi-agent-core/dist/agent.d.ts +0 -5
  60. package/node_modules/@earendil-works/pi-agent-core/dist/agent.d.ts.map +1 -1
  61. package/node_modules/@earendil-works/pi-agent-core/dist/agent.js +0 -2
  62. package/node_modules/@earendil-works/pi-agent-core/dist/agent.js.map +1 -1
  63. package/node_modules/@earendil-works/pi-agent-core/dist/index.d.ts +0 -2
  64. package/node_modules/@earendil-works/pi-agent-core/dist/index.d.ts.map +1 -1
  65. package/node_modules/@earendil-works/pi-agent-core/dist/index.js +0 -1
  66. package/node_modules/@earendil-works/pi-agent-core/dist/index.js.map +1 -1
  67. package/node_modules/@earendil-works/pi-agent-core/dist/types.d.ts +0 -9
  68. package/node_modules/@earendil-works/pi-agent-core/dist/types.d.ts.map +1 -1
  69. package/node_modules/@earendil-works/pi-agent-core/dist/types.js.map +1 -1
  70. package/node_modules/@earendil-works/pi-agent-core/package.json +3 -3
  71. package/node_modules/@earendil-works/pi-ai/dist/providers/data/.manifest.json +1 -1
  72. package/node_modules/@earendil-works/pi-ai/dist/providers/data/fireworks.json +1 -1
  73. package/node_modules/@earendil-works/pi-ai/dist/providers/data/openrouter.json +1 -1
  74. package/node_modules/@earendil-works/pi-ai/dist/providers/data/venice.json +1 -1
  75. package/node_modules/@earendil-works/pi-ai/dist/utils/retry.d.ts +0 -1
  76. package/node_modules/@earendil-works/pi-ai/dist/utils/retry.d.ts.map +1 -1
  77. package/node_modules/@earendil-works/pi-ai/dist/utils/retry.js +0 -18
  78. package/node_modules/@earendil-works/pi-ai/dist/utils/retry.js.map +1 -1
  79. package/node_modules/@earendil-works/pi-ai/package.json +2 -2
  80. package/node_modules/@earendil-works/pi-pty/package.json +1 -1
  81. package/node_modules/@earendil-works/pi-telemetry/package.json +1 -1
  82. package/node_modules/@earendil-works/pi-tui/package.json +1 -1
  83. package/package.json +7 -7
  84. package/node_modules/@earendil-works/pi-agent-core/dist/stream-throughput-watchdog.d.ts +0 -101
  85. package/node_modules/@earendil-works/pi-agent-core/dist/stream-throughput-watchdog.d.ts.map +0 -1
  86. package/node_modules/@earendil-works/pi-agent-core/dist/stream-throughput-watchdog.js +0 -178
  87. package/node_modules/@earendil-works/pi-agent-core/dist/stream-throughput-watchdog.js.map +0 -1
@@ -14,15 +14,14 @@ type WorkingStatusMessageFrameStyle = WorkingStatusTextFrameStyle & {
14
14
  suffix: (text: string) => string;
15
15
  };
16
16
  export declare function formatWorkingElapsedSeconds(elapsedSeconds: number): string;
17
- export declare function formatWorkingStatusSuffix(elapsedSeconds: number, interruptKey: string, tokensPerSecond?: number): string;
18
- export declare function formatWorkingStatusMessage(message: string, elapsedSeconds: number, interruptKey: string, tokensPerSecond?: number): string;
17
+ export declare function formatWorkingStatusMessage(message: string, elapsedSeconds: number, interruptKey: string): string;
19
18
  export type ToolHookStatusHookName = "PreToolUse" | "PostToolUse";
20
19
  export declare function formatToolHookStatusMessage(hookName: ToolHookStatusHookName, statusMessage: string, elapsedSeconds: number): string;
21
20
  export declare function sanitizeWorkingStatusPlainText(value: string): string;
22
21
  export declare function formatActiveToolWorkingLabel(toolName: string, input: unknown): string;
23
22
  export declare function blendWorkingStatusShimmerRgbColor(highlight: WorkingStatusRgbColor, base: WorkingStatusRgbColor, amount: number): WorkingStatusRgbColor;
24
23
  export declare function formatWorkingStatusTextFrame(statusMessage: string, animationElapsedMs: number, style: WorkingStatusTextFrameStyle): string;
25
- export declare function formatWorkingStatusMessageFrame(message: string, elapsedSeconds: number, interruptKey: string, animationElapsedMs: number, style: WorkingStatusMessageFrameStyle, tokensPerSecond?: number): string;
24
+ export declare function formatWorkingStatusMessageFrame(message: string, elapsedSeconds: number, interruptKey: string, animationElapsedMs: number, style: WorkingStatusMessageFrameStyle): string;
26
25
  export declare function formatToolHookStatusMessageFrame(hookName: ToolHookStatusHookName, statusMessage: string, elapsedSeconds: number, animationElapsedMs: number, style: WorkingStatusMessageFrameStyle): string;
27
26
  export {};
28
27
  //# sourceMappingURL=working-status.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"working-status.d.ts","sourceRoot":"","sources":["../../../src/modes/interactive/working-status.ts"],"names":[],"mappings":"AAMA,wBAAgB,iCAAiC,CAChD,iBAAiB,EAAE,MAAM,EACzB,iBAAiB,EAAE,MAAM,EACzB,sBAAsB,EAAE,MAAM,GAC5B,MAAM,CAER;AAED,MAAM,MAAM,qBAAqB,GAAG;IACnC,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACV,CAAC;AAEF,KAAK,2BAA2B,GAAG;IAClC,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IAC/B,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IAC/B,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IACpC,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,KAAK,MAAM,CAAC;CACtD,CAAC;AAEF,KAAK,8BAA8B,GAAG,2BAA2B,GAAG;IACnE,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;CACjC,CAAC;AAEF,wBAAgB,2BAA2B,CAAC,cAAc,EAAE,MAAM,GAAG,MAAM,CAa1E;AAYD,wBAAgB,yBAAyB,CACxC,cAAc,EAAE,MAAM,EACtB,YAAY,EAAE,MAAM,EACpB,eAAe,CAAC,EAAE,MAAM,GACtB,MAAM,CAER;AAED,wBAAgB,0BAA0B,CACzC,OAAO,EAAE,MAAM,EACf,cAAc,EAAE,MAAM,EACtB,YAAY,EAAE,MAAM,EACpB,eAAe,CAAC,EAAE,MAAM,GACtB,MAAM,CAER;AAED,MAAM,MAAM,sBAAsB,GAAG,YAAY,GAAG,aAAa,CAAC;AAElE,wBAAgB,2BAA2B,CAC1C,QAAQ,EAAE,sBAAsB,EAChC,aAAa,EAAE,MAAM,EACrB,cAAc,EAAE,MAAM,GACpB,MAAM,CAGR;AAED,wBAAgB,8BAA8B,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAQpE;AAqBD,wBAAgB,4BAA4B,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,MAAM,CAMrF;AAMD,wBAAgB,iCAAiC,CAChD,SAAS,EAAE,qBAAqB,EAChC,IAAI,EAAE,qBAAqB,EAC3B,MAAM,EAAE,MAAM,GACZ,qBAAqB,CAOvB;AAED,wBAAgB,4BAA4B,CAC3C,aAAa,EAAE,MAAM,EACrB,kBAAkB,EAAE,MAAM,EAC1B,KAAK,EAAE,2BAA2B,GAChC,MAAM,CAsCR;AAED,wBAAgB,+BAA+B,CAC9C,OAAO,EAAE,MAAM,EACf,cAAc,EAAE,MAAM,EACtB,YAAY,EAAE,MAAM,EACpB,kBAAkB,EAAE,MAAM,EAC1B,KAAK,EAAE,8BAA8B,EACrC,eAAe,CAAC,EAAE,MAAM,GACtB,MAAM,CAGR;AAED,wBAAgB,gCAAgC,CAC/C,QAAQ,EAAE,sBAAsB,EAChC,aAAa,EAAE,MAAM,EACrB,cAAc,EAAE,MAAM,EACtB,kBAAkB,EAAE,MAAM,EAC1B,KAAK,EAAE,8BAA8B,GACnC,MAAM,CAKR"}
1
+ {"version":3,"file":"working-status.d.ts","sourceRoot":"","sources":["../../../src/modes/interactive/working-status.ts"],"names":[],"mappings":"AAMA,wBAAgB,iCAAiC,CAChD,iBAAiB,EAAE,MAAM,EACzB,iBAAiB,EAAE,MAAM,EACzB,sBAAsB,EAAE,MAAM,GAC5B,MAAM,CAER;AAED,MAAM,MAAM,qBAAqB,GAAG;IACnC,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACV,CAAC;AAEF,KAAK,2BAA2B,GAAG;IAClC,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IAC/B,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IAC/B,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IACpC,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,KAAK,MAAM,CAAC;CACtD,CAAC;AAEF,KAAK,8BAA8B,GAAG,2BAA2B,GAAG;IACnE,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;CACjC,CAAC;AAEF,wBAAgB,2BAA2B,CAAC,cAAc,EAAE,MAAM,GAAG,MAAM,CAa1E;AAED,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,MAAM,CAEhH;AAED,MAAM,MAAM,sBAAsB,GAAG,YAAY,GAAG,aAAa,CAAC;AAElE,wBAAgB,2BAA2B,CAC1C,QAAQ,EAAE,sBAAsB,EAChC,aAAa,EAAE,MAAM,EACrB,cAAc,EAAE,MAAM,GACpB,MAAM,CAGR;AAED,wBAAgB,8BAA8B,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAQpE;AAqBD,wBAAgB,4BAA4B,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,MAAM,CAMrF;AAMD,wBAAgB,iCAAiC,CAChD,SAAS,EAAE,qBAAqB,EAChC,IAAI,EAAE,qBAAqB,EAC3B,MAAM,EAAE,MAAM,GACZ,qBAAqB,CAOvB;AAED,wBAAgB,4BAA4B,CAC3C,aAAa,EAAE,MAAM,EACrB,kBAAkB,EAAE,MAAM,EAC1B,KAAK,EAAE,2BAA2B,GAChC,MAAM,CAsCR;AAED,wBAAgB,+BAA+B,CAC9C,OAAO,EAAE,MAAM,EACf,cAAc,EAAE,MAAM,EACtB,YAAY,EAAE,MAAM,EACpB,kBAAkB,EAAE,MAAM,EAC1B,KAAK,EAAE,8BAA8B,GACnC,MAAM,CAGR;AAED,wBAAgB,gCAAgC,CAC/C,QAAQ,EAAE,sBAAsB,EAChC,aAAa,EAAE,MAAM,EACrB,cAAc,EAAE,MAAM,EACtB,kBAAkB,EAAE,MAAM,EAC1B,KAAK,EAAE,8BAA8B,GACnC,MAAM,CAKR"}
@@ -20,21 +20,8 @@ export function formatWorkingElapsedSeconds(elapsedSeconds) {
20
20
  const minutes = totalMinutes % 60;
21
21
  return `${hours}h ${minutes.toString().padStart(2, "0")}m ${seconds.toString().padStart(2, "0")}s`;
22
22
  }
23
- /**
24
- * Live streaming rate for the working line. A crawling turn used to look
25
- * exactly like a healthy one (elapsed time only), so a 2 tok/s session stayed
26
- * "Working (10m 00s • Esc to interrupt)" for ten minutes (#1739).
27
- */
28
- function formatWorkingRateSegment(tokensPerSecond) {
29
- if (tokensPerSecond === undefined || !Number.isFinite(tokensPerSecond) || tokensPerSecond < 0)
30
- return "";
31
- return ` • ${tokensPerSecond.toFixed(1)} tok/s`;
32
- }
33
- export function formatWorkingStatusSuffix(elapsedSeconds, interruptKey, tokensPerSecond) {
34
- return ` (${formatWorkingElapsedSeconds(elapsedSeconds)}${formatWorkingRateSegment(tokensPerSecond)} • ${interruptKey} to interrupt)`;
35
- }
36
- export function formatWorkingStatusMessage(message, elapsedSeconds, interruptKey, tokensPerSecond) {
37
- return `${message}${formatWorkingStatusSuffix(elapsedSeconds, interruptKey, tokensPerSecond)}`;
23
+ export function formatWorkingStatusMessage(message, elapsedSeconds, interruptKey) {
24
+ return `${message} (${formatWorkingElapsedSeconds(elapsedSeconds)} • ${interruptKey} to interrupt)`;
38
25
  }
39
26
  export function formatToolHookStatusMessage(hookName, statusMessage, elapsedSeconds) {
40
27
  const suffix = statusMessage ? `: ${statusMessage}` : "";
@@ -119,8 +106,8 @@ export function formatWorkingStatusTextFrame(statusMessage, animationElapsedMs,
119
106
  })
120
107
  .join("");
121
108
  }
122
- export function formatWorkingStatusMessageFrame(message, elapsedSeconds, interruptKey, animationElapsedMs, style, tokensPerSecond) {
123
- const suffix = formatWorkingStatusSuffix(elapsedSeconds, interruptKey, tokensPerSecond);
109
+ export function formatWorkingStatusMessageFrame(message, elapsedSeconds, interruptKey, animationElapsedMs, style) {
110
+ const suffix = ` (${formatWorkingElapsedSeconds(elapsedSeconds)} • ${interruptKey} to interrupt)`;
124
111
  return `${formatWorkingStatusTextFrame(message, animationElapsedMs, style)}${style.suffix(suffix)}`;
125
112
  }
126
113
  export function formatToolHookStatusMessageFrame(hookName, statusMessage, elapsedSeconds, animationElapsedMs, style) {
@@ -1 +1 @@
1
- {"version":3,"file":"working-status.js","sourceRoot":"","sources":["../../../src/modes/interactive/working-status.ts"],"names":[],"mappings":"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","sourcesContent":["const WORKING_STATUS_MESSAGE_SHIMMER_PADDING = 10;\nconst WORKING_STATUS_MESSAGE_SHIMMER_BAND_HALF_WIDTH = 5;\nconst WORKING_STATUS_MESSAGE_SHIMMER_SWEEP_MS = 2_000;\nconst ACTIVE_TOOL_WORKING_LABEL_MAX_LENGTH = 80;\nconst LARGE_SESSION_ENTRY_THRESHOLD = 1000;\n\nexport function largeSessionWorkingStatusInterval(\n\tsessionEntryCount: number,\n\tdefaultIntervalMs: number,\n\tlargeSessionIntervalMs: number,\n): number {\n\treturn sessionEntryCount >= LARGE_SESSION_ENTRY_THRESHOLD ? largeSessionIntervalMs : defaultIntervalMs;\n}\n\nexport type WorkingStatusRgbColor = {\n\tr: number;\n\tg: number;\n\tb: number;\n};\n\ntype WorkingStatusTextFrameStyle = {\n\tbase: (text: string) => string;\n\tglow: (text: string) => string;\n\thighlight: (text: string) => string;\n\tshimmer?: (text: string, intensity: number) => string;\n};\n\ntype WorkingStatusMessageFrameStyle = WorkingStatusTextFrameStyle & {\n\tsuffix: (text: string) => string;\n};\n\nexport function formatWorkingElapsedSeconds(elapsedSeconds: number): string {\n\tconst totalSeconds = Math.max(0, Math.floor(elapsedSeconds));\n\tconst seconds = totalSeconds % 60;\n\tconst totalMinutes = Math.floor(totalSeconds / 60);\n\tif (totalSeconds < 60) {\n\t\treturn `${totalSeconds}s`;\n\t}\n\tif (totalSeconds < 3600) {\n\t\treturn `${totalMinutes}m ${seconds.toString().padStart(2, \"0\")}s`;\n\t}\n\tconst hours = Math.floor(totalMinutes / 60);\n\tconst minutes = totalMinutes % 60;\n\treturn `${hours}h ${minutes.toString().padStart(2, \"0\")}m ${seconds.toString().padStart(2, \"0\")}s`;\n}\n\n/**\n * Live streaming rate for the working line. A crawling turn used to look\n * exactly like a healthy one (elapsed time only), so a 2 tok/s session stayed\n * \"Working (10m 00s • Esc to interrupt)\" for ten minutes (#1739).\n */\nfunction formatWorkingRateSegment(tokensPerSecond: number | undefined): string {\n\tif (tokensPerSecond === undefined || !Number.isFinite(tokensPerSecond) || tokensPerSecond < 0) return \"\";\n\treturn ` • ${tokensPerSecond.toFixed(1)} tok/s`;\n}\n\nexport function formatWorkingStatusSuffix(\n\telapsedSeconds: number,\n\tinterruptKey: string,\n\ttokensPerSecond?: number,\n): string {\n\treturn ` (${formatWorkingElapsedSeconds(elapsedSeconds)}${formatWorkingRateSegment(tokensPerSecond)} • ${interruptKey} to interrupt)`;\n}\n\nexport function formatWorkingStatusMessage(\n\tmessage: string,\n\telapsedSeconds: number,\n\tinterruptKey: string,\n\ttokensPerSecond?: number,\n): string {\n\treturn `${message}${formatWorkingStatusSuffix(elapsedSeconds, interruptKey, tokensPerSecond)}`;\n}\n\nexport type ToolHookStatusHookName = \"PreToolUse\" | \"PostToolUse\";\n\nexport function formatToolHookStatusMessage(\n\thookName: ToolHookStatusHookName,\n\tstatusMessage: string,\n\telapsedSeconds: number,\n): string {\n\tconst suffix = statusMessage ? `: ${statusMessage}` : \"\";\n\treturn `Running ${hookName} hook${suffix} (${formatWorkingElapsedSeconds(elapsedSeconds)})`;\n}\n\nexport function sanitizeWorkingStatusPlainText(value: string): string {\n\treturn value\n\t\t.replace(/\\u001b\\][^\\u0007]*(?:\\u0007|\\u001b\\\\)/g, \"\")\n\t\t.replace(/\\u001b\\[[0-?]*[ -/]*[@-~]/g, \"\")\n\t\t.replace(/[\\r\\n\\t]+/g, \" \")\n\t\t.replace(/[\\u0000-\\u001f\\u007f]+/g, \"\")\n\t\t.replace(/\\s+/g, \" \")\n\t\t.trim();\n}\n\nfunction truncateActiveToolWorkingLabel(value: string): string {\n\tconst chars = Array.from(value);\n\tif (chars.length <= ACTIVE_TOOL_WORKING_LABEL_MAX_LENGTH) {\n\t\treturn value;\n\t}\n\treturn `${chars.slice(0, ACTIVE_TOOL_WORKING_LABEL_MAX_LENGTH - 3).join(\"\")}...`;\n}\n\nfunction getActiveToolWorkingDetail(input: unknown): string {\n\tif (typeof input !== \"object\" || input === null || !(\"command\" in input)) {\n\t\treturn \"\";\n\t}\n\tconst command = input.command;\n\tif (typeof command !== \"string\") {\n\t\treturn \"\";\n\t}\n\treturn sanitizeWorkingStatusPlainText(command);\n}\n\nexport function formatActiveToolWorkingLabel(toolName: string, input: unknown): string {\n\tconst sanitizedToolName = sanitizeWorkingStatusPlainText(toolName);\n\tconst labelToolName = sanitizedToolName || \"tool\";\n\tconst detail = getActiveToolWorkingDetail(input);\n\tconst label = detail ? `Running ${labelToolName}: ${detail}` : `Running ${labelToolName}`;\n\treturn truncateActiveToolWorkingLabel(label);\n}\n\nfunction clampColorChannel(value: number): number {\n\treturn Math.max(0, Math.min(255, Math.round(value)));\n}\n\nexport function blendWorkingStatusShimmerRgbColor(\n\thighlight: WorkingStatusRgbColor,\n\tbase: WorkingStatusRgbColor,\n\tamount: number,\n): WorkingStatusRgbColor {\n\tconst clampedAmount = Math.max(0, Math.min(1, amount));\n\treturn {\n\t\tr: clampColorChannel(highlight.r * clampedAmount + base.r * (1 - clampedAmount)),\n\t\tg: clampColorChannel(highlight.g * clampedAmount + base.g * (1 - clampedAmount)),\n\t\tb: clampColorChannel(highlight.b * clampedAmount + base.b * (1 - clampedAmount)),\n\t};\n}\n\nexport function formatWorkingStatusTextFrame(\n\tstatusMessage: string,\n\tanimationElapsedMs: number,\n\tstyle: WorkingStatusTextFrameStyle,\n): string {\n\tconst chars = Array.from(statusMessage);\n\tif (chars.length === 0) {\n\t\treturn \"\";\n\t}\n\n\tconst period = chars.length + WORKING_STATUS_MESSAGE_SHIMMER_PADDING * 2;\n\tconst sweepProgress =\n\t\t((Math.max(0, animationElapsedMs) % WORKING_STATUS_MESSAGE_SHIMMER_SWEEP_MS) /\n\t\t\tWORKING_STATUS_MESSAGE_SHIMMER_SWEEP_MS) *\n\t\tperiod;\n\n\treturn chars\n\t\t.map((char, index) => {\n\t\t\tif (char === \" \") {\n\t\t\t\treturn char;\n\t\t\t}\n\t\t\tconst distance = Math.abs(index + WORKING_STATUS_MESSAGE_SHIMMER_PADDING - sweepProgress);\n\t\t\tif (distance > WORKING_STATUS_MESSAGE_SHIMMER_BAND_HALF_WIDTH) {\n\t\t\t\tif (style.shimmer) {\n\t\t\t\t\treturn style.shimmer(char, 0);\n\t\t\t\t}\n\t\t\t\treturn style.base(char);\n\t\t\t}\n\n\t\t\tconst intensity = 0.5 * (1 + Math.cos(Math.PI * (distance / WORKING_STATUS_MESSAGE_SHIMMER_BAND_HALF_WIDTH)));\n\t\t\tif (style.shimmer) {\n\t\t\t\treturn style.shimmer(char, intensity);\n\t\t\t}\n\t\t\tif (intensity < 0.2) {\n\t\t\t\treturn style.base(char);\n\t\t\t}\n\t\t\tif (intensity < 0.6) {\n\t\t\t\treturn style.glow(char);\n\t\t\t}\n\t\t\treturn style.highlight(char);\n\t\t})\n\t\t.join(\"\");\n}\n\nexport function formatWorkingStatusMessageFrame(\n\tmessage: string,\n\telapsedSeconds: number,\n\tinterruptKey: string,\n\tanimationElapsedMs: number,\n\tstyle: WorkingStatusMessageFrameStyle,\n\ttokensPerSecond?: number,\n): string {\n\tconst suffix = formatWorkingStatusSuffix(elapsedSeconds, interruptKey, tokensPerSecond);\n\treturn `${formatWorkingStatusTextFrame(message, animationElapsedMs, style)}${style.suffix(suffix)}`;\n}\n\nexport function formatToolHookStatusMessageFrame(\n\thookName: ToolHookStatusHookName,\n\tstatusMessage: string,\n\telapsedSeconds: number,\n\tanimationElapsedMs: number,\n\tstyle: WorkingStatusMessageFrameStyle,\n): string {\n\tconst label = `Running ${hookName} hook`;\n\tconst statusSuffix = statusMessage ? `: ${statusMessage}` : \"\";\n\tconst suffix = `${statusSuffix} (${formatWorkingElapsedSeconds(elapsedSeconds)})`;\n\treturn `${formatWorkingStatusTextFrame(label, animationElapsedMs, style)}${style.suffix(suffix)}`;\n}\n"]}
1
+ {"version":3,"file":"working-status.js","sourceRoot":"","sources":["../../../src/modes/interactive/working-status.ts"],"names":[],"mappings":"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","sourcesContent":["const WORKING_STATUS_MESSAGE_SHIMMER_PADDING = 10;\nconst WORKING_STATUS_MESSAGE_SHIMMER_BAND_HALF_WIDTH = 5;\nconst WORKING_STATUS_MESSAGE_SHIMMER_SWEEP_MS = 2_000;\nconst ACTIVE_TOOL_WORKING_LABEL_MAX_LENGTH = 80;\nconst LARGE_SESSION_ENTRY_THRESHOLD = 1000;\n\nexport function largeSessionWorkingStatusInterval(\n\tsessionEntryCount: number,\n\tdefaultIntervalMs: number,\n\tlargeSessionIntervalMs: number,\n): number {\n\treturn sessionEntryCount >= LARGE_SESSION_ENTRY_THRESHOLD ? largeSessionIntervalMs : defaultIntervalMs;\n}\n\nexport type WorkingStatusRgbColor = {\n\tr: number;\n\tg: number;\n\tb: number;\n};\n\ntype WorkingStatusTextFrameStyle = {\n\tbase: (text: string) => string;\n\tglow: (text: string) => string;\n\thighlight: (text: string) => string;\n\tshimmer?: (text: string, intensity: number) => string;\n};\n\ntype WorkingStatusMessageFrameStyle = WorkingStatusTextFrameStyle & {\n\tsuffix: (text: string) => string;\n};\n\nexport function formatWorkingElapsedSeconds(elapsedSeconds: number): string {\n\tconst totalSeconds = Math.max(0, Math.floor(elapsedSeconds));\n\tconst seconds = totalSeconds % 60;\n\tconst totalMinutes = Math.floor(totalSeconds / 60);\n\tif (totalSeconds < 60) {\n\t\treturn `${totalSeconds}s`;\n\t}\n\tif (totalSeconds < 3600) {\n\t\treturn `${totalMinutes}m ${seconds.toString().padStart(2, \"0\")}s`;\n\t}\n\tconst hours = Math.floor(totalMinutes / 60);\n\tconst minutes = totalMinutes % 60;\n\treturn `${hours}h ${minutes.toString().padStart(2, \"0\")}m ${seconds.toString().padStart(2, \"0\")}s`;\n}\n\nexport function formatWorkingStatusMessage(message: string, elapsedSeconds: number, interruptKey: string): string {\n\treturn `${message} (${formatWorkingElapsedSeconds(elapsedSeconds)} • ${interruptKey} to interrupt)`;\n}\n\nexport type ToolHookStatusHookName = \"PreToolUse\" | \"PostToolUse\";\n\nexport function formatToolHookStatusMessage(\n\thookName: ToolHookStatusHookName,\n\tstatusMessage: string,\n\telapsedSeconds: number,\n): string {\n\tconst suffix = statusMessage ? `: ${statusMessage}` : \"\";\n\treturn `Running ${hookName} hook${suffix} (${formatWorkingElapsedSeconds(elapsedSeconds)})`;\n}\n\nexport function sanitizeWorkingStatusPlainText(value: string): string {\n\treturn value\n\t\t.replace(/\\u001b\\][^\\u0007]*(?:\\u0007|\\u001b\\\\)/g, \"\")\n\t\t.replace(/\\u001b\\[[0-?]*[ -/]*[@-~]/g, \"\")\n\t\t.replace(/[\\r\\n\\t]+/g, \" \")\n\t\t.replace(/[\\u0000-\\u001f\\u007f]+/g, \"\")\n\t\t.replace(/\\s+/g, \" \")\n\t\t.trim();\n}\n\nfunction truncateActiveToolWorkingLabel(value: string): string {\n\tconst chars = Array.from(value);\n\tif (chars.length <= ACTIVE_TOOL_WORKING_LABEL_MAX_LENGTH) {\n\t\treturn value;\n\t}\n\treturn `${chars.slice(0, ACTIVE_TOOL_WORKING_LABEL_MAX_LENGTH - 3).join(\"\")}...`;\n}\n\nfunction getActiveToolWorkingDetail(input: unknown): string {\n\tif (typeof input !== \"object\" || input === null || !(\"command\" in input)) {\n\t\treturn \"\";\n\t}\n\tconst command = input.command;\n\tif (typeof command !== \"string\") {\n\t\treturn \"\";\n\t}\n\treturn sanitizeWorkingStatusPlainText(command);\n}\n\nexport function formatActiveToolWorkingLabel(toolName: string, input: unknown): string {\n\tconst sanitizedToolName = sanitizeWorkingStatusPlainText(toolName);\n\tconst labelToolName = sanitizedToolName || \"tool\";\n\tconst detail = getActiveToolWorkingDetail(input);\n\tconst label = detail ? `Running ${labelToolName}: ${detail}` : `Running ${labelToolName}`;\n\treturn truncateActiveToolWorkingLabel(label);\n}\n\nfunction clampColorChannel(value: number): number {\n\treturn Math.max(0, Math.min(255, Math.round(value)));\n}\n\nexport function blendWorkingStatusShimmerRgbColor(\n\thighlight: WorkingStatusRgbColor,\n\tbase: WorkingStatusRgbColor,\n\tamount: number,\n): WorkingStatusRgbColor {\n\tconst clampedAmount = Math.max(0, Math.min(1, amount));\n\treturn {\n\t\tr: clampColorChannel(highlight.r * clampedAmount + base.r * (1 - clampedAmount)),\n\t\tg: clampColorChannel(highlight.g * clampedAmount + base.g * (1 - clampedAmount)),\n\t\tb: clampColorChannel(highlight.b * clampedAmount + base.b * (1 - clampedAmount)),\n\t};\n}\n\nexport function formatWorkingStatusTextFrame(\n\tstatusMessage: string,\n\tanimationElapsedMs: number,\n\tstyle: WorkingStatusTextFrameStyle,\n): string {\n\tconst chars = Array.from(statusMessage);\n\tif (chars.length === 0) {\n\t\treturn \"\";\n\t}\n\n\tconst period = chars.length + WORKING_STATUS_MESSAGE_SHIMMER_PADDING * 2;\n\tconst sweepProgress =\n\t\t((Math.max(0, animationElapsedMs) % WORKING_STATUS_MESSAGE_SHIMMER_SWEEP_MS) /\n\t\t\tWORKING_STATUS_MESSAGE_SHIMMER_SWEEP_MS) *\n\t\tperiod;\n\n\treturn chars\n\t\t.map((char, index) => {\n\t\t\tif (char === \" \") {\n\t\t\t\treturn char;\n\t\t\t}\n\t\t\tconst distance = Math.abs(index + WORKING_STATUS_MESSAGE_SHIMMER_PADDING - sweepProgress);\n\t\t\tif (distance > WORKING_STATUS_MESSAGE_SHIMMER_BAND_HALF_WIDTH) {\n\t\t\t\tif (style.shimmer) {\n\t\t\t\t\treturn style.shimmer(char, 0);\n\t\t\t\t}\n\t\t\t\treturn style.base(char);\n\t\t\t}\n\n\t\t\tconst intensity = 0.5 * (1 + Math.cos(Math.PI * (distance / WORKING_STATUS_MESSAGE_SHIMMER_BAND_HALF_WIDTH)));\n\t\t\tif (style.shimmer) {\n\t\t\t\treturn style.shimmer(char, intensity);\n\t\t\t}\n\t\t\tif (intensity < 0.2) {\n\t\t\t\treturn style.base(char);\n\t\t\t}\n\t\t\tif (intensity < 0.6) {\n\t\t\t\treturn style.glow(char);\n\t\t\t}\n\t\t\treturn style.highlight(char);\n\t\t})\n\t\t.join(\"\");\n}\n\nexport function formatWorkingStatusMessageFrame(\n\tmessage: string,\n\telapsedSeconds: number,\n\tinterruptKey: string,\n\tanimationElapsedMs: number,\n\tstyle: WorkingStatusMessageFrameStyle,\n): string {\n\tconst suffix = ` (${formatWorkingElapsedSeconds(elapsedSeconds)} • ${interruptKey} to interrupt)`;\n\treturn `${formatWorkingStatusTextFrame(message, animationElapsedMs, style)}${style.suffix(suffix)}`;\n}\n\nexport function formatToolHookStatusMessageFrame(\n\thookName: ToolHookStatusHookName,\n\tstatusMessage: string,\n\telapsedSeconds: number,\n\tanimationElapsedMs: number,\n\tstyle: WorkingStatusMessageFrameStyle,\n): string {\n\tconst label = `Running ${hookName} hook`;\n\tconst statusSuffix = statusMessage ? `: ${statusMessage}` : \"\";\n\tconst suffix = `${statusSuffix} (${formatWorkingElapsedSeconds(elapsedSeconds)})`;\n\treturn `${formatWorkingStatusTextFrame(label, animationElapsedMs, style)}${style.suffix(suffix)}`;\n}\n"]}
package/dist/senpi CHANGED
@@ -120,6 +120,15 @@ if (isRootCommand(args) && (args.includes("--version") || args.includes("-v")))
120
120
  console.log(DISPLAY_VERSION);
121
121
  process.exit();
122
122
  }
123
+ // Help is static text plus the flags extensions registered, so a launch that already knows those
124
+ // flags must not import the engine graph to print them. The import stays dynamic for the same
125
+ // reason `cli-main` is: a static one would evaluate that graph before this answer.
126
+ if (isRootCommand(args) && args.some((arg) => arg === "--help" || arg === "-h")) {
127
+ const { tryPrintHelpWithoutEngine } = await import("./cli/help-fast-path.js");
128
+ if (tryPrintHelpWithoutEngine(args)) {
129
+ process.exit();
130
+ }
131
+ }
123
132
  if (isMissingBundledWorkspaceDependencies(getPackageDir())) {
124
133
  if (await handleBootstrapSelfUpdate(args)) {
125
134
  process.exit();
package/docs/settings.md CHANGED
@@ -258,9 +258,6 @@ See [compaction.md](compaction.md) for trigger and summarization behavior.
258
258
  | `retry.provider.timeoutMs` | number | `300000` | Provider/SDK request timeout and stream idle timeout in milliseconds |
259
259
  | `retry.provider.streamStartTimeoutMs` | number | `300000` | Maximum wait for the first provider stream event; `0` disables |
260
260
  | `retry.provider.streamRetryTimeoutMs` | number | `30000` | First-request liveness cap after a known provider stream/transport timeout; `0` disables the cap |
261
- | `retry.provider.minThroughputTokensPerSecond` | number | `8` | Sustained streamed-units floor for an in-progress stream; `0` disables the watchdog |
262
- | `retry.provider.throughputWindowMs` | number | `20000` | Observation window for that floor; `0` disables the watchdog |
263
- | `retry.provider.throughputGraceMs` | number | `5000` | Streaming after the first event that is never measured; `0` measures immediately |
264
261
  | `retry.provider.maxRetries` | number | `0` | Provider/SDK retry attempts |
265
262
  | `retry.provider.maxRetryDelayMs` | number | `60000` | Max server-requested delay honored on the same model before the fallback chain engages (60s) |
266
263
 
@@ -272,18 +269,6 @@ After an exact provider stream/transport timeout, `retry.provider.streamRetryTim
272
269
  provider request and defers queued user input from that request. The cap applies only to stream guards that are
273
270
  already enabled, never turns a disabled guard back on, and restores configured timeouts for later requests.
274
271
 
275
- `streamStartTimeoutMs` bounds the wait for the FIRST event and stops applying once it arrives; `timeoutMs` then
276
- bounds silence between events. Both are silence detectors, so a provider that keeps answering at a uselessly low
277
- rate trips neither. The throughput watchdog is the rate half: after the first stream event it ignores
278
- `retry.provider.throughputGraceMs` of streaming, then measures streamed text and thinking units (about one unit
279
- per token) over a trailing `retry.provider.throughputWindowMs`. A full window carrying at least 16 units whose
280
- sustained rate is below `retry.provider.minThroughputTokensPerSecond` aborts the in-flight request with
281
- `Provider stream throughput degraded: <n> tok/s over <n>s (floor <n> tok/s)`. Time the provider spends executing
282
- local tools does not count against the window, and the interactive working line shows the live rate
283
- (`Working (1m 12s • 2.1 tok/s • esc to interrupt)`) while the turn runs. That failure is retryable but never
284
- spends same-model attempts — replaying the payload cannot make the upstream faster — so it goes straight to the
285
- fallback chain; with no chain candidate the turn ends with that error instead of continuing to crawl.
286
-
287
272
  Keep `retry.provider.maxRetries` at `0` unless provider-level retries are explicitly needed. Setting it above `0` can make SDK/provider retries handle out-of-usage-limit errors before senpi sees them, which may block the agent until the provider quota resets in some circumstances.
288
273
 
289
274
  ```json
@@ -297,9 +282,6 @@ Keep `retry.provider.maxRetries` at `0` unless provider-level retries are explic
297
282
  "timeoutMs": 3600000,
298
283
  "streamStartTimeoutMs": 300000,
299
284
  "streamRetryTimeoutMs": 30000,
300
- "minThroughputTokensPerSecond": 8,
301
- "throughputWindowMs": 20000,
302
- "throughputGraceMs": 5000,
303
285
  "maxRetries": 0,
304
286
  "maxRetryDelayMs": 60000
305
287
  }
@@ -309,7 +291,7 @@ Keep `retry.provider.maxRetries` at `0` unless provider-level retries are explic
309
291
 
310
292
  #### Model fallback chains
311
293
 
312
- `retry.fallbackChains` maps a primary-model selector to an ordered list of fallback selectors. A selector is `provider/model` with an optional `:thinking-level` suffix, or a bare `model` id that applies to every provider serving that model family. Bare selectors expand against the models you actually have: providers holding an OAuth credential are preferred, then a fixed precedence order, and OpenRouter is never chosen by expansion. Fallback chains are explicit user configuration only: Senpi ships no default and no wildcard lane, so a model without a configured chain never enters an implicit fallback lane and a failure that would fall back ends the turn instead. Set a key to `[]` to opt out of a chain you configured at a broader granularity, or set one `provider/claude-fable-5-1` key to override just that provider. For example, this switches Fable 5.1 to Kimi K3 at `max` thinking when an eligible failure occurs:
294
+ `retry.fallbackChains` maps a primary-model selector to an ordered list of fallback selectors. A selector is `provider/model` with an optional `:thinking-level` suffix, or a bare `model` id that applies to every provider serving that model family. Bare selectors expand against the models you actually have: providers holding an OAuth credential are preferred, then a fixed precedence order, and OpenRouter is never chosen by expansion. Senpi ships bare default chains for `claude-fable-5-1` and `claude-fable-5`, so Fable 5.1 and Fable 5 keep a fallback chain whichever provider serves them; set a key to `[]` to opt out entirely, or set one `provider/claude-fable-5-1` key to override just that provider. For example, this switches Fable 5.1 to Kimi K3 at `max` thinking when an eligible failure occurs:
313
295
 
314
296
  ```json
315
297
  {
@@ -12,6 +12,18 @@
12
12
 
13
13
  ### Removed
14
14
 
15
+ ## [2026.9.16-3] - 2026-09-16
16
+
17
+ ### Breaking Changes
18
+
19
+ ### Added
20
+
21
+ ### Changed
22
+
23
+ ### Fixed
24
+
25
+ ### Removed
26
+
15
27
  ## [2026.9.16-2] - 2026-09-16
16
28
 
17
29
  ### Breaking Changes
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@code-yeongyu/senpi-codemode",
3
- "version": "2026.9.16-2",
3
+ "version": "2026.9.16-3",
4
4
  "private": true,
5
5
  "description": "Source-only senpi extension package for codemode evaluation tools",
6
6
  "type": "module",
@@ -31,14 +31,14 @@
31
31
  },
32
32
  "dependencies": {
33
33
  "@babel/parser": "8.0.4",
34
- "@earendil-works/pi-ai": "npm:@code-yeongyu/senpi-ai@2026.9.16-2",
34
+ "@earendil-works/pi-ai": "npm:@code-yeongyu/senpi-ai@2026.9.16-3",
35
35
  "typebox": "1.3.27"
36
36
  },
37
37
  "peerDependencies": {
38
- "@code-yeongyu/senpi": "2026.9.16-2"
38
+ "@code-yeongyu/senpi": "2026.9.16-3"
39
39
  },
40
40
  "devDependencies": {
41
- "@code-yeongyu/senpi": "2026.9.16-2"
41
+ "@code-yeongyu/senpi": "2026.9.16-3"
42
42
  },
43
43
  "keywords": [
44
44
  "senpi",
@@ -1 +1 @@
1
- {"version":3,"file":"agent-loop.d.ts","sourceRoot":"","sources":["../src/agent-loop.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAIN,KAAK,OAAO,EAEZ,WAAW,EAIX,MAAM,uBAAuB,CAAC;AAgB/B,OAAO,KAAK,EACX,YAAY,EACZ,UAAU,EACV,eAAe,EAEf,YAAY,EACZ,SAAS,EACT,aAAa,EAEb,QAAQ,EACR,MAAM,YAAY,CAAC;AAEpB,MAAM,MAAM,cAAc,GAAG,CAAC,KAAK,EAAE,UAAU,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;AAEzE;;;GAGG;AACH,wBAAgB,SAAS,CACxB,OAAO,EAAE,YAAY,EAAE,EACvB,OAAO,EAAE,YAAY,EACrB,MAAM,EAAE,eAAe,EACvB,MAAM,EAAE,WAAW,GAAG,SAAS,EAC/B,QAAQ,EAAE,QAAQ,GAChB,WAAW,CAAC,UAAU,EAAE,YAAY,EAAE,CAAC,CAiBzC;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAChC,OAAO,EAAE,YAAY,EACrB,MAAM,EAAE,eAAe,EACvB,MAAM,EAAE,WAAW,GAAG,SAAS,EAC/B,QAAQ,EAAE,QAAQ,GAChB,WAAW,CAAC,UAAU,EAAE,YAAY,EAAE,CAAC,CAwBzC;AAED,wBAAsB,YAAY,CACjC,OAAO,EAAE,YAAY,EAAE,EACvB,OAAO,EAAE,YAAY,EACrB,MAAM,EAAE,eAAe,EACvB,IAAI,EAAE,cAAc,EACpB,MAAM,EAAE,WAAW,GAAG,SAAS,EAC/B,QAAQ,EAAE,QAAQ,GAChB,OAAO,CAAC,YAAY,EAAE,CAAC,CAgBzB;AAED,wBAAsB,oBAAoB,CACzC,OAAO,EAAE,YAAY,EACrB,MAAM,EAAE,eAAe,EACvB,IAAI,EAAE,cAAc,EACpB,MAAM,EAAE,WAAW,GAAG,SAAS,EAC/B,QAAQ,EAAE,QAAQ,GAChB,OAAO,CAAC,YAAY,EAAE,CAAC,CAiBzB;AAmBD,qBAAa,uBAAwB,SAAQ,KAAK;IACjD,YAAY,SAAS,EAAE,MAAM,EAK5B;CACD;AA2ND,uGAAuG;AACvG,wBAAsB,oBAAoB,CACzC,OAAO,EAAE,YAAY,EACrB,MAAM,EAAE,IAAI,CAAC,eAAe,EAAE,cAAc,GAAG,kBAAkB,CAAC,EAClE,MAAM,CAAC,EAAE,WAAW,GAClB,OAAO,CAAC,OAAO,CAAC,CAIlB;AA2oBD,MAAM,WAAW,qBAAqB;IACrC,QAAQ,EAAE,aAAa,CAAC;IACxB,IAAI,EAAE,SAAS,CAAC;IAChB,IAAI,EAAE,OAAO,CAAC;CACd;AAED,wBAAgB,6BAA6B,CAAC,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,aAAa,GAAG,aAAa,CAYrG;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,aAAa,GAAG,qBAAqB,CAOpG"}
1
+ {"version":3,"file":"agent-loop.d.ts","sourceRoot":"","sources":["../src/agent-loop.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAIN,KAAK,OAAO,EAEZ,WAAW,EAIX,MAAM,uBAAuB,CAAC;AAW/B,OAAO,KAAK,EACX,YAAY,EACZ,UAAU,EACV,eAAe,EAEf,YAAY,EACZ,SAAS,EACT,aAAa,EAEb,QAAQ,EACR,MAAM,YAAY,CAAC;AAEpB,MAAM,MAAM,cAAc,GAAG,CAAC,KAAK,EAAE,UAAU,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;AAEzE;;;GAGG;AACH,wBAAgB,SAAS,CACxB,OAAO,EAAE,YAAY,EAAE,EACvB,OAAO,EAAE,YAAY,EACrB,MAAM,EAAE,eAAe,EACvB,MAAM,EAAE,WAAW,GAAG,SAAS,EAC/B,QAAQ,EAAE,QAAQ,GAChB,WAAW,CAAC,UAAU,EAAE,YAAY,EAAE,CAAC,CAiBzC;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAChC,OAAO,EAAE,YAAY,EACrB,MAAM,EAAE,eAAe,EACvB,MAAM,EAAE,WAAW,GAAG,SAAS,EAC/B,QAAQ,EAAE,QAAQ,GAChB,WAAW,CAAC,UAAU,EAAE,YAAY,EAAE,CAAC,CAwBzC;AAED,wBAAsB,YAAY,CACjC,OAAO,EAAE,YAAY,EAAE,EACvB,OAAO,EAAE,YAAY,EACrB,MAAM,EAAE,eAAe,EACvB,IAAI,EAAE,cAAc,EACpB,MAAM,EAAE,WAAW,GAAG,SAAS,EAC/B,QAAQ,EAAE,QAAQ,GAChB,OAAO,CAAC,YAAY,EAAE,CAAC,CAgBzB;AAED,wBAAsB,oBAAoB,CACzC,OAAO,EAAE,YAAY,EACrB,MAAM,EAAE,eAAe,EACvB,IAAI,EAAE,cAAc,EACpB,MAAM,EAAE,WAAW,GAAG,SAAS,EAC/B,QAAQ,EAAE,QAAQ,GAChB,OAAO,CAAC,YAAY,EAAE,CAAC,CAiBzB;AAmBD,qBAAa,uBAAwB,SAAQ,KAAK;IACjD,YAAY,SAAS,EAAE,MAAM,EAK5B;CACD;AA2ND,uGAAuG;AACvG,wBAAsB,oBAAoB,CACzC,OAAO,EAAE,YAAY,EACrB,MAAM,EAAE,IAAI,CAAC,eAAe,EAAE,cAAc,GAAG,kBAAkB,CAAC,EAClE,MAAM,CAAC,EAAE,WAAW,GAClB,OAAO,CAAC,OAAO,CAAC,CAIlB;AA+mBD,MAAM,WAAW,qBAAqB;IACrC,QAAQ,EAAE,aAAa,CAAC;IACxB,IAAI,EAAE,SAAS,CAAC;IAChB,IAAI,EAAE,OAAO,CAAC;CACd;AAED,wBAAgB,6BAA6B,CAAC,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,aAAa,GAAG,aAAa,CAYrG;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,aAAa,GAAG,qBAAqB,CAOpG"}
@@ -5,7 +5,6 @@
5
5
  import { EventStream, isCursorExecResolved, validateToolArguments, } from "@earendil-works/pi-ai";
6
6
  import { createTerminalFailureAssistantMessage, demoteToolUseWithoutToolCalls, isStreamIdleTimeoutError, normalizeTerminalAssistantMessage, promoteStopWithPendingToolCalls, shouldFinalizeIdleAsStop, shouldTerminateAssistantTurn, } from "./assistant-terminal-state.js";
7
7
  import { getDefaultStreamFn, withEmptyAssistantRecovery } from "./stream-fn.js";
8
- import { createStreamThroughputWatchdog, estimateStreamedUnits, } from "./stream-throughput-watchdog.js";
9
8
  /**
10
9
  * Start an agent loop with a new prompt message.
11
10
  * The prompt is added to the context and events are emitted for it.
@@ -347,7 +346,7 @@ async function streamAssistantResponse(context, config, signal, emit, streamFunc
347
346
  : {}),
348
347
  });
349
348
  const iterator = response[Symbol.asyncIterator]();
350
- const eventReader = createAssistantEventReader(iterator, streamIdleTimeoutMs, requestAbortController.signal, (error) => requestAbortController.abort(error), config.streamStartTimeoutMs, response, createStreamThroughputWatchdog(config.streamThroughput));
349
+ const eventReader = createAssistantEventReader(iterator, streamIdleTimeoutMs, requestAbortController.signal, (error) => requestAbortController.abort(error), config.streamStartTimeoutMs, response);
351
350
  try {
352
351
  while (true) {
353
352
  const next = await eventReader.next();
@@ -497,13 +496,7 @@ function closeAssistantIterator(iterator) {
497
496
  function normalizeTimeoutMs(timeoutMs) {
498
497
  return typeof timeoutMs === "number" && Number.isFinite(timeoutMs) && timeoutMs > 0 ? timeoutMs : undefined;
499
498
  }
500
- /** Streamed units carried by one assistant event; only text and thinking count. */
501
- function streamedUnitsOf(event) {
502
- if (event.type === "text_delta" || event.type === "thinking_delta")
503
- return estimateStreamedUnits(event.delta);
504
- return 0;
505
- }
506
- function createAssistantEventReader(iterator, timeoutMs, signal, onIdleTimeout, streamStartTimeoutMs, stream, throughput) {
499
+ function createAssistantEventReader(iterator, timeoutMs, signal, onIdleTimeout, streamStartTimeoutMs, stream) {
507
500
  const idleTimeoutMs = normalizeTimeoutMs(timeoutMs);
508
501
  const startTimeoutMs = normalizeTimeoutMs(streamStartTimeoutMs);
509
502
  let sawFirstEvent = false;
@@ -534,29 +527,9 @@ function createAssistantEventReader(iterator, timeoutMs, signal, onIdleTimeout,
534
527
  const makeTimeoutError = useStartBound
535
528
  ? (ms) => new StreamStartTimeoutError(ms)
536
529
  : (ms) => new StreamIdleTimeoutError(ms);
537
- // A provider executing a server-requested tool locally (Cursor's exec
538
- // channel) is not streaming; that span must not count against the rate.
539
- const localWorkPending = throughput !== undefined && stream?.hasPendingLocalWork?.() === true;
540
- const waitStartedAt = localWorkPending ? Date.now() : 0;
541
530
  const result = await readNextAssistantEvent(iterator, readTimeoutMs, makeTimeoutError, abortPromise, onIdleTimeout, stream, signal);
542
- if (localWorkPending)
543
- throughput?.exclude(Date.now() - waitStartedAt);
544
- if (!result.done) {
531
+ if (!result.done)
545
532
  sawFirstEvent = true;
546
- if (throughput !== undefined) {
547
- // The rate clock starts at the first event, exactly where the
548
- // stream-start bound stops applying.
549
- throughput.start();
550
- const degraded = throughput.record(streamedUnitsOf(result.value));
551
- if (degraded !== undefined) {
552
- closeAssistantIterator(iterator);
553
- // Abort before rejecting: the caller inspects the request signal's
554
- // reason, and the crawling upstream must be torn down either way.
555
- onIdleTimeout?.(degraded);
556
- throw degraded;
557
- }
558
- }
559
- }
560
533
  return result;
561
534
  },
562
535
  dispose: () => removeAbortListener?.(),