@code-yeongyu/senpi 2026.8.6 → 2026.8.9
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/CHANGELOG.md +104 -0
- package/dist/core/agent-session.d.ts +10 -0
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +71 -50
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/extensions/builtin/bash-timeout/index.d.ts +2 -2
- package/dist/core/extensions/builtin/bash-timeout/index.d.ts.map +1 -1
- package/dist/core/extensions/builtin/bash-timeout/index.js +17 -20
- package/dist/core/extensions/builtin/bash-timeout/index.js.map +1 -1
- package/dist/core/extensions/builtin/bash-timeout/timeout.d.ts +7 -12
- package/dist/core/extensions/builtin/bash-timeout/timeout.d.ts.map +1 -1
- package/dist/core/extensions/builtin/bash-timeout/timeout.js +11 -19
- package/dist/core/extensions/builtin/bash-timeout/timeout.js.map +1 -1
- package/dist/core/extensions/builtin/goal/cache-warm.d.ts +2 -0
- package/dist/core/extensions/builtin/goal/cache-warm.d.ts.map +1 -1
- package/dist/core/extensions/builtin/goal/cache-warm.js.map +1 -1
- package/dist/core/extensions/builtin/goal/monitor-continuation-types.d.ts +1 -0
- package/dist/core/extensions/builtin/goal/monitor-continuation-types.d.ts.map +1 -1
- package/dist/core/extensions/builtin/goal/monitor-continuation-types.js.map +1 -1
- package/dist/core/extensions/builtin/goal/monitor-continuation.d.ts.map +1 -1
- package/dist/core/extensions/builtin/goal/monitor-continuation.js +76 -35
- package/dist/core/extensions/builtin/goal/monitor-continuation.js.map +1 -1
- package/dist/core/extensions/builtin/goal/prompt.d.ts +1 -1
- package/dist/core/extensions/builtin/goal/prompt.d.ts.map +1 -1
- package/dist/core/extensions/builtin/goal/prompt.js +21 -7
- package/dist/core/extensions/builtin/goal/prompt.js.map +1 -1
- package/dist/core/extensions/builtin/goal/wait-progress.d.ts +3 -1
- package/dist/core/extensions/builtin/goal/wait-progress.d.ts.map +1 -1
- package/dist/core/extensions/builtin/goal/wait-progress.js +27 -3
- package/dist/core/extensions/builtin/goal/wait-progress.js.map +1 -1
- package/dist/core/extensions/builtin/goal/wait-ticker.d.ts +4 -3
- package/dist/core/extensions/builtin/goal/wait-ticker.d.ts.map +1 -1
- package/dist/core/extensions/builtin/goal/wait-ticker.js +6 -6
- package/dist/core/extensions/builtin/goal/wait-ticker.js.map +1 -1
- package/dist/core/extensions/builtin/import-repro.d.ts.map +1 -1
- package/dist/core/extensions/builtin/import-repro.js +9 -0
- package/dist/core/extensions/builtin/import-repro.js.map +1 -1
- package/dist/core/extensions/builtin/model-fallback/settings.d.ts.map +1 -1
- package/dist/core/extensions/builtin/model-fallback/settings.js +21 -1
- package/dist/core/extensions/builtin/model-fallback/settings.js.map +1 -1
- package/dist/core/extensions/builtin/resumption-channel-event.d.ts +13 -0
- package/dist/core/extensions/builtin/resumption-channel-event.d.ts.map +1 -0
- package/dist/core/extensions/builtin/resumption-channel-event.js +13 -0
- package/dist/core/extensions/builtin/resumption-channel-event.js.map +1 -0
- package/dist/core/extensions/builtin/terminal/extension.d.ts.map +1 -1
- package/dist/core/extensions/builtin/terminal/extension.js +20 -0
- package/dist/core/extensions/builtin/terminal/extension.js.map +1 -1
- package/dist/core/extensions/builtin/terminal/session-bundle.d.ts +5 -1
- package/dist/core/extensions/builtin/terminal/session-bundle.d.ts.map +1 -1
- package/dist/core/extensions/builtin/terminal/session-bundle.js +19 -2
- package/dist/core/extensions/builtin/terminal/session-bundle.js.map +1 -1
- package/dist/core/extensions/builtin/terminal/tools/bash.d.ts.map +1 -1
- package/dist/core/extensions/builtin/terminal/tools/bash.js +24 -10
- package/dist/core/extensions/builtin/terminal/tools/bash.js.map +1 -1
- package/dist/core/extensions/builtin/terminal/tools/context.d.ts +2 -0
- package/dist/core/extensions/builtin/terminal/tools/context.d.ts.map +1 -1
- package/dist/core/extensions/builtin/terminal/tools/context.js.map +1 -1
- package/dist/core/extensions/builtin/terminal/tools/foreground-window.d.ts +11 -0
- package/dist/core/extensions/builtin/terminal/tools/foreground-window.d.ts.map +1 -0
- package/dist/core/extensions/builtin/terminal/tools/foreground-window.js +16 -0
- package/dist/core/extensions/builtin/terminal/tools/foreground-window.js.map +1 -0
- package/dist/core/extensions/builtin/terminal/tools/sleep-wait.d.ts +28 -0
- package/dist/core/extensions/builtin/terminal/tools/sleep-wait.d.ts.map +1 -0
- package/dist/core/extensions/builtin/terminal/tools/sleep-wait.js +75 -0
- package/dist/core/extensions/builtin/terminal/tools/sleep-wait.js.map +1 -0
- package/dist/core/extensions/builtin/tps.d.ts.map +1 -1
- package/dist/core/extensions/builtin/tps.js +3 -3
- package/dist/core/extensions/builtin/tps.js.map +1 -1
- package/dist/core/retry-fallback/chains.d.ts +13 -1
- package/dist/core/retry-fallback/chains.d.ts.map +1 -1
- package/dist/core/retry-fallback/chains.js +80 -8
- package/dist/core/retry-fallback/chains.js.map +1 -1
- package/dist/core/retry-fallback/controller.d.ts +2 -0
- package/dist/core/retry-fallback/controller.d.ts.map +1 -1
- package/dist/core/retry-fallback/controller.js.map +1 -1
- package/dist/core/retry-fallback/expansion.d.ts +46 -0
- package/dist/core/retry-fallback/expansion.d.ts.map +1 -0
- package/dist/core/retry-fallback/expansion.js +113 -0
- package/dist/core/retry-fallback/expansion.js.map +1 -0
- package/dist/core/retry-fallback/hint-policy.d.ts +14 -0
- package/dist/core/retry-fallback/hint-policy.d.ts.map +1 -1
- package/dist/core/retry-fallback/hint-policy.js +14 -0
- package/dist/core/retry-fallback/hint-policy.js.map +1 -1
- package/dist/core/retry-fallback/settings.d.ts +6 -0
- package/dist/core/retry-fallback/settings.d.ts.map +1 -1
- package/dist/core/retry-fallback/settings.js +12 -10
- package/dist/core/retry-fallback/settings.js.map +1 -1
- package/dist/core/retry-fallback/validate.d.ts.map +1 -1
- package/dist/core/retry-fallback/validate.js +14 -1
- package/dist/core/retry-fallback/validate.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +18 -3
- package/dist/main.js.map +1 -1
- package/dist/modes/interactive/components/favorite-models-selector.d.ts +4 -0
- package/dist/modes/interactive/components/favorite-models-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/favorite-models-selector.js +23 -7
- package/dist/modes/interactive/components/favorite-models-selector.js.map +1 -1
- package/dist/modes/interactive/components/model-selector.d.ts +1 -0
- package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/model-selector.js +11 -7
- package/dist/modes/interactive/components/model-selector.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +25 -6
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/model-search-rank.d.ts +13 -0
- package/dist/modes/interactive/model-search-rank.d.ts.map +1 -0
- package/dist/modes/interactive/model-search-rank.js +200 -0
- package/dist/modes/interactive/model-search-rank.js.map +1 -0
- package/dist/modes/interactive/model-search.d.ts +0 -5
- package/dist/modes/interactive/model-search.d.ts.map +1 -1
- package/dist/modes/interactive/model-search.js +0 -9
- package/dist/modes/interactive/model-search.js.map +1 -1
- package/dist/modes/rpc/session-command-router.d.ts.map +1 -1
- package/dist/modes/rpc/session-command-router.js +3 -2
- package/dist/modes/rpc/session-command-router.js.map +1 -1
- package/dist/modes/rpc/session-registry.d.ts +1 -1
- package/dist/modes/rpc/session-registry.d.ts.map +1 -1
- package/dist/modes/rpc/session-registry.js +3 -3
- package/dist/modes/rpc/session-registry.js.map +1 -1
- package/docs/settings.md +1 -1
- package/node_modules/@code-yeongyu/senpi-codemode/CHANGELOG.md +36 -0
- package/node_modules/@code-yeongyu/senpi-codemode/package.json +4 -4
- package/node_modules/@code-yeongyu/senpi-codemode/src/extension/resumption-channel.ts +29 -0
- package/node_modules/@code-yeongyu/senpi-codemode/src/index.ts +10 -0
- package/node_modules/@code-yeongyu/senpi-codemode/src/tool/detached-cell-manager.ts +26 -1
- package/node_modules/@code-yeongyu/senpi-codemode/src/tool/render.ts +2 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/empty-assistant-recovery.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/empty-assistant-recovery.js +4 -7
- package/node_modules/@earendil-works/pi-agent-core/dist/empty-assistant-recovery.js.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/package.json +2 -2
- package/node_modules/@earendil-works/pi-ai/dist/index.d.ts +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/index.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/index.js +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/index.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/.manifest.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/github-copilot.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/huggingface.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/nvidia.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/opencode-go.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/opencode.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/openrouter.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/vercel-ai-gateway.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/utils/visible-text.d.ts +4 -0
- package/node_modules/@earendil-works/pi-ai/dist/utils/visible-text.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/utils/visible-text.js +8 -0
- package/node_modules/@earendil-works/pi-ai/dist/utils/visible-text.js.map +1 -0
- package/node_modules/@earendil-works/pi-ai/package.json +1 -1
- package/node_modules/@earendil-works/pi-pty/dist/pipe-fallback.d.ts +12 -0
- package/node_modules/@earendil-works/pi-pty/dist/pipe-fallback.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-pty/dist/pipe-fallback.js +34 -2
- package/node_modules/@earendil-works/pi-pty/dist/pipe-fallback.js.map +1 -1
- package/node_modules/@earendil-works/pi-pty/package.json +1 -1
- package/node_modules/@earendil-works/pi-tui/package.json +1 -1
- package/package.json +6 -6
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ExtensionAPI } from "../../types.ts";
|
|
2
|
-
export type { BashTimeoutDefaults, BashToolInputLike
|
|
3
|
-
export { applyBashTimeout, BASH_DEFAULT_TIMEOUT_SECONDS, BASH_MAX_TIMEOUT_SECONDS, buildBashTimeoutPrompt, resolveBashTimeoutDefaults,
|
|
2
|
+
export type { BashTimeoutDefaults, BashToolInputLike } from "./timeout.ts";
|
|
3
|
+
export { applyBashTimeout, BASH_DEFAULT_TIMEOUT_SECONDS, BASH_MAX_TIMEOUT_SECONDS, buildBashTimeoutPrompt, resolveBashTimeoutDefaults, } from "./timeout.ts";
|
|
4
4
|
export default function bashTimeoutExtension(pi: ExtensionAPI): void;
|
|
5
5
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/bash-timeout/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAoB,MAAM,gBAAgB,CAAC;AAWrE,YAAY,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/bash-timeout/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAoB,MAAM,gBAAgB,CAAC;AAWrE,YAAY,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAC3E,OAAO,EACN,gBAAgB,EAChB,4BAA4B,EAC5B,wBAAwB,EACxB,sBAAsB,EACtB,0BAA0B,GAC1B,MAAM,cAAc,CAAC;AAEtB,MAAM,CAAC,OAAO,UAAU,oBAAoB,CAAC,EAAE,EAAE,YAAY,GAAG,IAAI,CA2BnE"}
|
|
@@ -1,36 +1,33 @@
|
|
|
1
1
|
import { isAnthropicBashEnabled } from "../anthropic-bash/index.js";
|
|
2
|
-
import {
|
|
3
|
-
|
|
2
|
+
import { resolveForegroundWindowSeconds } from "../terminal/tools/foreground-window.js";
|
|
3
|
+
import { applyBashTimeout, buildBashTimeoutPrompt, resolveBashTimeoutDefaults, } from "./timeout.js";
|
|
4
|
+
export { applyBashTimeout, BASH_DEFAULT_TIMEOUT_SECONDS, BASH_MAX_TIMEOUT_SECONDS, buildBashTimeoutPrompt, resolveBashTimeoutDefaults, } from "./timeout.js";
|
|
4
5
|
export default function bashTimeoutExtension(pi) {
|
|
5
6
|
const env = typeof process !== "undefined" ? process.env : {};
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Native Anthropic bash replaces the PTY `bash` tool, and the terminal
|
|
10
|
-
* extension steps aside with it — so nothing implements the cache-deadline
|
|
11
|
-
* detach. Advertising a cache ceiling there would promise behavior that
|
|
12
|
-
* cannot happen, so the budget only applies while the PTY tool is live.
|
|
13
|
-
*/
|
|
14
|
-
const resolveBudget = (ctx) => {
|
|
15
|
-
if (isAnthropicBashEnabled() && ctx?.model?.api === "anthropic-messages")
|
|
16
|
-
return undefined;
|
|
17
|
-
return ctx?.getPromptCacheSafeWaitSeconds?.();
|
|
18
|
-
};
|
|
19
|
-
pi.on("tool_call", async (event, ctx) => {
|
|
7
|
+
const defaults = resolveBashTimeoutDefaults(env);
|
|
8
|
+
pi.on("tool_call", async (event) => {
|
|
20
9
|
if (event.toolName !== "bash")
|
|
21
10
|
return;
|
|
22
|
-
effective = resolveEffectiveBashTimeouts(baseDefaults, resolveBudget(ctx));
|
|
23
11
|
const input = event.input;
|
|
24
|
-
const updated = applyBashTimeout(input,
|
|
12
|
+
const updated = applyBashTimeout(input, defaults);
|
|
25
13
|
if (updated !== input) {
|
|
26
14
|
const timeout = updated.timeout;
|
|
27
15
|
if (timeout !== undefined)
|
|
28
16
|
input.timeout = timeout;
|
|
29
17
|
}
|
|
30
18
|
});
|
|
19
|
+
/**
|
|
20
|
+
* Native Anthropic bash replaces the PTY `bash` tool and the terminal
|
|
21
|
+
* extension steps aside with it, so nothing implements the auto-detach the
|
|
22
|
+
* policy would otherwise advertise.
|
|
23
|
+
*/
|
|
24
|
+
const resolveWindow = (ctx) => {
|
|
25
|
+
if (isAnthropicBashEnabled() && ctx?.model?.api === "anthropic-messages")
|
|
26
|
+
return undefined;
|
|
27
|
+
return resolveForegroundWindowSeconds(env);
|
|
28
|
+
};
|
|
31
29
|
pi.on("before_agent_start", async (event, ctx) => {
|
|
32
|
-
|
|
33
|
-
return { systemPrompt: `${event.systemPrompt}${buildBashTimeoutPrompt(effective)}` };
|
|
30
|
+
return { systemPrompt: `${event.systemPrompt}${buildBashTimeoutPrompt(defaults, resolveWindow(ctx))}` };
|
|
34
31
|
});
|
|
35
32
|
}
|
|
36
33
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/bash-timeout/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/bash-timeout/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AACpE,OAAO,EAAE,8BAA8B,EAAE,MAAM,wCAAwC,CAAC;AAExF,OAAO,EACN,gBAAgB,EAEhB,sBAAsB,EACtB,0BAA0B,GAC1B,MAAM,cAAc,CAAC;AAGtB,OAAO,EACN,gBAAgB,EAChB,4BAA4B,EAC5B,wBAAwB,EACxB,sBAAsB,EACtB,0BAA0B,GAC1B,MAAM,cAAc,CAAC;AAEtB,MAAM,CAAC,OAAO,UAAU,oBAAoB,CAAC,EAAgB;IAC5D,MAAM,GAAG,GAAG,OAAO,OAAO,KAAK,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;IAC9D,MAAM,QAAQ,GAAG,0BAA0B,CAAC,GAAG,CAAC,CAAC;IAEjD,EAAE,CAAC,EAAE,CAAC,WAAW,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE;QAClC,IAAI,KAAK,CAAC,QAAQ,KAAK,MAAM;YAAE,OAAO;QACtC,MAAM,KAAK,GAAG,KAAK,CAAC,KAA0B,CAAC;QAC/C,MAAM,OAAO,GAAG,gBAAgB,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;QAClD,IAAI,OAAO,KAAK,KAAK,EAAE,CAAC;YACvB,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;YAChC,IAAI,OAAO,KAAK,SAAS;gBAAE,KAAK,CAAC,OAAO,GAAG,OAAO,CAAC;QACpD,CAAC;IACF,CAAC,CAAC,CAAC;IAEH;;;;OAIG;IACH,MAAM,aAAa,GAAG,CAAC,GAAiC,EAAsB,EAAE;QAC/E,IAAI,sBAAsB,EAAE,IAAI,GAAG,EAAE,KAAK,EAAE,GAAG,KAAK,oBAAoB;YAAE,OAAO,SAAS,CAAC;QAC3F,OAAO,8BAA8B,CAAC,GAAG,CAAC,CAAC;IAC5C,CAAC,CAAC;IAEF,EAAE,CAAC,EAAE,CAAC,oBAAoB,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;QAChD,OAAO,EAAE,YAAY,EAAE,GAAG,KAAK,CAAC,YAAY,GAAG,sBAAsB,CAAC,QAAQ,EAAE,aAAa,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC;IACzG,CAAC,CAAC,CAAC;AACJ,CAAC","sourcesContent":["import type { ExtensionAPI, ExtensionContext } from \"../../types.ts\";\nimport { isAnthropicBashEnabled } from \"../anthropic-bash/index.ts\";\nimport { resolveForegroundWindowSeconds } from \"../terminal/tools/foreground-window.ts\";\n\nimport {\n\tapplyBashTimeout,\n\ttype BashToolInputLike,\n\tbuildBashTimeoutPrompt,\n\tresolveBashTimeoutDefaults,\n} from \"./timeout.ts\";\n\nexport type { BashTimeoutDefaults, BashToolInputLike } from \"./timeout.ts\";\nexport {\n\tapplyBashTimeout,\n\tBASH_DEFAULT_TIMEOUT_SECONDS,\n\tBASH_MAX_TIMEOUT_SECONDS,\n\tbuildBashTimeoutPrompt,\n\tresolveBashTimeoutDefaults,\n} from \"./timeout.ts\";\n\nexport default function bashTimeoutExtension(pi: ExtensionAPI): void {\n\tconst env = typeof process !== \"undefined\" ? process.env : {};\n\tconst defaults = resolveBashTimeoutDefaults(env);\n\n\tpi.on(\"tool_call\", async (event) => {\n\t\tif (event.toolName !== \"bash\") return;\n\t\tconst input = event.input as BashToolInputLike;\n\t\tconst updated = applyBashTimeout(input, defaults);\n\t\tif (updated !== input) {\n\t\t\tconst timeout = updated.timeout;\n\t\t\tif (timeout !== undefined) input.timeout = timeout;\n\t\t}\n\t});\n\n\t/**\n\t * Native Anthropic bash replaces the PTY `bash` tool and the terminal\n\t * extension steps aside with it, so nothing implements the auto-detach the\n\t * policy would otherwise advertise.\n\t */\n\tconst resolveWindow = (ctx: ExtensionContext | undefined): number | undefined => {\n\t\tif (isAnthropicBashEnabled() && ctx?.model?.api === \"anthropic-messages\") return undefined;\n\t\treturn resolveForegroundWindowSeconds(env);\n\t};\n\n\tpi.on(\"before_agent_start\", async (event, ctx) => {\n\t\treturn { systemPrompt: `${event.systemPrompt}${buildBashTimeoutPrompt(defaults, resolveWindow(ctx))}` };\n\t});\n}\n"]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export declare const BASH_DEFAULT_TIMEOUT_SECONDS =
|
|
2
|
-
export declare const BASH_MAX_TIMEOUT_SECONDS =
|
|
1
|
+
export declare const BASH_DEFAULT_TIMEOUT_SECONDS = 1800;
|
|
2
|
+
export declare const BASH_MAX_TIMEOUT_SECONDS = 1800;
|
|
3
3
|
export interface BashTimeoutDefaults {
|
|
4
4
|
defaultSeconds: number;
|
|
5
5
|
maxSeconds: number;
|
|
@@ -12,17 +12,12 @@ export interface BashToolInputLike {
|
|
|
12
12
|
[key: string]: unknown;
|
|
13
13
|
}
|
|
14
14
|
export declare function applyBashTimeout<TInput extends BashToolInputLike>(input: TInput, defaults: BashTimeoutDefaults): TInput;
|
|
15
|
-
export interface EffectiveBashTimeouts extends BashTimeoutDefaults {
|
|
16
|
-
cacheCapped?: boolean;
|
|
17
|
-
}
|
|
18
15
|
/**
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
* value, and the terminal detach deadline consistent.
|
|
16
|
+
* `foregroundWindowSeconds` is `undefined` when no PTY bash tool is live (native
|
|
17
|
+
* Anthropic bash replaces it). Nothing implements auto-detach then, so the
|
|
18
|
+
* policy must not promise it — a prompt that describes impossible behavior is
|
|
19
|
+
* worse than a silent one.
|
|
24
20
|
*/
|
|
25
|
-
export declare function
|
|
26
|
-
export declare function buildBashTimeoutPrompt(defaults: EffectiveBashTimeouts): string;
|
|
21
|
+
export declare function buildBashTimeoutPrompt(defaults: BashTimeoutDefaults, foregroundWindowSeconds?: number): string;
|
|
27
22
|
export {};
|
|
28
23
|
//# sourceMappingURL=timeout.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"timeout.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/bash-timeout/timeout.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,4BAA4B,
|
|
1
|
+
{"version":3,"file":"timeout.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/bash-timeout/timeout.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,4BAA4B,OAAO,CAAC;AACjD,eAAO,MAAM,wBAAwB,OAAO,CAAC;AAE7C,MAAM,WAAW,mBAAmB;IACnC,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;CACnB;AAED,KAAK,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;AASlD,wBAAgB,0BAA0B,CAAC,GAAG,EAAE,OAAO,GAAG,mBAAmB,CAM5E;AAED,MAAM,WAAW,iBAAiB;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACvB;AAED,wBAAgB,gBAAgB,CAAC,MAAM,SAAS,iBAAiB,EAChE,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,mBAAmB,GAC3B,MAAM,CAMR;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,mBAAmB,EAAE,uBAAuB,CAAC,EAAE,MAAM,GAAG,MAAM,CAO9G"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export const BASH_DEFAULT_TIMEOUT_SECONDS =
|
|
2
|
-
export const BASH_MAX_TIMEOUT_SECONDS =
|
|
1
|
+
export const BASH_DEFAULT_TIMEOUT_SECONDS = 1800;
|
|
2
|
+
export const BASH_MAX_TIMEOUT_SECONDS = 1800;
|
|
3
3
|
function parsePositiveInt(value) {
|
|
4
4
|
if (!value)
|
|
5
5
|
return undefined;
|
|
@@ -23,24 +23,16 @@ export function applyBashTimeout(input, defaults) {
|
|
|
23
23
|
return input;
|
|
24
24
|
}
|
|
25
25
|
/**
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
* value, and the terminal detach deadline consistent.
|
|
26
|
+
* `foregroundWindowSeconds` is `undefined` when no PTY bash tool is live (native
|
|
27
|
+
* Anthropic bash replaces it). Nothing implements auto-detach then, so the
|
|
28
|
+
* policy must not promise it — a prompt that describes impossible behavior is
|
|
29
|
+
* worse than a silent one.
|
|
31
30
|
*/
|
|
32
|
-
export function
|
|
33
|
-
if (safeWaitSeconds === undefined || safeWaitSeconds >= defaults.maxSeconds) {
|
|
34
|
-
return { ...defaults, cacheCapped: false };
|
|
35
|
-
}
|
|
36
|
-
const maxSeconds = Math.min(defaults.maxSeconds, safeWaitSeconds);
|
|
37
|
-
return { defaultSeconds: Math.min(defaults.defaultSeconds, maxSeconds), maxSeconds, cacheCapped: true };
|
|
38
|
-
}
|
|
39
|
-
export function buildBashTimeoutPrompt(defaults) {
|
|
31
|
+
export function buildBashTimeoutPrompt(defaults, foregroundWindowSeconds) {
|
|
40
32
|
const minutes = (seconds) => (seconds % 60 === 0 ? `${seconds / 60} min` : `${seconds}s`);
|
|
41
|
-
const
|
|
42
|
-
?
|
|
43
|
-
:
|
|
44
|
-
return `\n## Bash Tool Timeout Policy\n\nThe \`bash\` tool
|
|
33
|
+
const detachRules = foregroundWindowSeconds === undefined
|
|
34
|
+
? ""
|
|
35
|
+
: `\n- Foreground blocking stops at the ~${foregroundWindowSeconds}s window. A command still running then auto-detaches alive to a background session with a \`bash_id\` and keeps running until it exits, hits the kill deadline, or is stopped with \`kill_bash\`.\n- Completion arrives automatically as a notification carrying the exit status and output tail, so end your turn rather than poll. Use \`bash_output\` only for a midpoint peek.`;
|
|
36
|
+
return `\n## Bash Tool Timeout Policy\n\nThe \`bash\` tool's \`timeout\` parameter is the process kill deadline, not how long you wait for output: the command is killed when it reaches the deadline.\n\n- Default timeout: ${defaults.defaultSeconds}s (${minutes(defaults.defaultSeconds)}). Applied automatically when you do not set \`timeout\`.\n- Recommended maximum timeout: ${defaults.maxSeconds}s (${minutes(defaults.maxSeconds)}). Explicit \`timeout\` values are preserved because different hosts may use different timeout units.${detachRules}\n- Waiting on an observable condition (a log line, a CI check, a server coming up) belongs to \`monitor({command, filter})\`, never a foreground \`sleep\` or poll loop.\n- Sessions started with \`run_in_background: true\` ignore \`timeout\` and live until exit or \`kill_bash\`.\n`;
|
|
45
37
|
}
|
|
46
38
|
//# sourceMappingURL=timeout.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"timeout.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/bash-timeout/timeout.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,4BAA4B,GAAG,
|
|
1
|
+
{"version":3,"file":"timeout.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/bash-timeout/timeout.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,4BAA4B,GAAG,IAAI,CAAC;AACjD,MAAM,CAAC,MAAM,wBAAwB,GAAG,IAAI,CAAC;AAS7C,SAAS,gBAAgB,CAAC,KAAyB;IAClD,IAAI,CAAC,KAAK;QAAE,OAAO,SAAS,CAAC;IAC7B,MAAM,MAAM,GAAG,MAAM,CAAC,QAAQ,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IAC1C,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,MAAM,IAAI,CAAC;QAAE,OAAO,SAAS,CAAC;IAC9D,OAAO,MAAM,CAAC;AACf,CAAC;AAED,MAAM,UAAU,0BAA0B,CAAC,GAAY;IACtD,MAAM,EAAE,+BAA+B,EAAE,cAAc,EAAE,2BAA2B,EAAE,UAAU,EAAE,GAAG,GAAG,CAAC;IACzG,MAAM,cAAc,GAAG,gBAAgB,CAAC,cAAc,CAAC,IAAI,4BAA4B,CAAC;IACxF,MAAM,MAAM,GAAG,gBAAgB,CAAC,UAAU,CAAC,IAAI,wBAAwB,CAAC;IACxE,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IACpD,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,CAAC;AACvC,CAAC;AAQD,MAAM,UAAU,gBAAgB,CAC/B,KAAa,EACb,QAA6B;IAE7B,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC;IAC9B,IAAI,OAAO,KAAK,SAAS,IAAI,OAAO,IAAI,CAAC,EAAE,CAAC;QAC3C,OAAO,EAAE,GAAG,KAAK,EAAE,OAAO,EAAE,QAAQ,CAAC,cAAc,EAAE,CAAC;IACvD,CAAC;IACD,OAAO,KAAK,CAAC;AACd,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,sBAAsB,CAAC,QAA6B,EAAE,uBAAgC;IACrG,MAAM,OAAO,GAAG,CAAC,OAAe,EAAU,EAAE,CAAC,CAAC,OAAO,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,OAAO,GAAG,EAAE,MAAM,CAAC,CAAC,CAAC,GAAG,OAAO,GAAG,CAAC,CAAC;IAC1G,MAAM,WAAW,GAChB,uBAAuB,KAAK,SAAS;QACpC,CAAC,CAAC,EAAE;QACJ,CAAC,CAAC,yCAAyC,uBAAuB,oXAAoX,CAAC;IACzb,OAAO,wNAAwN,QAAQ,CAAC,cAAc,MAAM,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAC,6FAA6F,QAAQ,CAAC,UAAU,MAAM,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC,wGAAwG,WAAW,2RAA2R,CAAC;AAC9zB,CAAC","sourcesContent":["export const BASH_DEFAULT_TIMEOUT_SECONDS = 1800;\nexport const BASH_MAX_TIMEOUT_SECONDS = 1800;\n\nexport interface BashTimeoutDefaults {\n\tdefaultSeconds: number;\n\tmaxSeconds: number;\n}\n\ntype EnvLike = Record<string, string | undefined>;\n\nfunction parsePositiveInt(value: string | undefined): number | undefined {\n\tif (!value) return undefined;\n\tconst parsed = Number.parseInt(value, 10);\n\tif (!Number.isFinite(parsed) || parsed <= 0) return undefined;\n\treturn parsed;\n}\n\nexport function resolveBashTimeoutDefaults(env: EnvLike): BashTimeoutDefaults {\n\tconst { PI_BASH_DEFAULT_TIMEOUT_SECONDS: defaultTimeout, PI_BASH_MAX_TIMEOUT_SECONDS: maxTimeout } = env;\n\tconst defaultSeconds = parsePositiveInt(defaultTimeout) ?? BASH_DEFAULT_TIMEOUT_SECONDS;\n\tconst rawMax = parsePositiveInt(maxTimeout) ?? BASH_MAX_TIMEOUT_SECONDS;\n\tconst maxSeconds = Math.max(rawMax, defaultSeconds);\n\treturn { defaultSeconds, maxSeconds };\n}\n\nexport interface BashToolInputLike {\n\tcommand: string;\n\ttimeout?: number;\n\t[key: string]: unknown;\n}\n\nexport function applyBashTimeout<TInput extends BashToolInputLike>(\n\tinput: TInput,\n\tdefaults: BashTimeoutDefaults,\n): TInput {\n\tconst current = input.timeout;\n\tif (current === undefined || current <= 0) {\n\t\treturn { ...input, timeout: defaults.defaultSeconds };\n\t}\n\treturn input;\n}\n\n/**\n * `foregroundWindowSeconds` is `undefined` when no PTY bash tool is live (native\n * Anthropic bash replaces it). Nothing implements auto-detach then, so the\n * policy must not promise it — a prompt that describes impossible behavior is\n * worse than a silent one.\n */\nexport function buildBashTimeoutPrompt(defaults: BashTimeoutDefaults, foregroundWindowSeconds?: number): string {\n\tconst minutes = (seconds: number): string => (seconds % 60 === 0 ? `${seconds / 60} min` : `${seconds}s`);\n\tconst detachRules =\n\t\tforegroundWindowSeconds === undefined\n\t\t\t? \"\"\n\t\t\t: `\\n- Foreground blocking stops at the ~${foregroundWindowSeconds}s window. A command still running then auto-detaches alive to a background session with a \\`bash_id\\` and keeps running until it exits, hits the kill deadline, or is stopped with \\`kill_bash\\`.\\n- Completion arrives automatically as a notification carrying the exit status and output tail, so end your turn rather than poll. Use \\`bash_output\\` only for a midpoint peek.`;\n\treturn `\\n## Bash Tool Timeout Policy\\n\\nThe \\`bash\\` tool's \\`timeout\\` parameter is the process kill deadline, not how long you wait for output: the command is killed when it reaches the deadline.\\n\\n- Default timeout: ${defaults.defaultSeconds}s (${minutes(defaults.defaultSeconds)}). Applied automatically when you do not set \\`timeout\\`.\\n- Recommended maximum timeout: ${defaults.maxSeconds}s (${minutes(defaults.maxSeconds)}). Explicit \\`timeout\\` values are preserved because different hosts may use different timeout units.${detachRules}\\n- Waiting on an observable condition (a log line, a CI check, a server coming up) belongs to \\`monitor({command, filter})\\`, never a foreground \\`sleep\\` or poll loop.\\n- Sessions started with \\`run_in_background: true\\` ignore \\`timeout\\` and live until exit or \\`kill_bash\\`.\\n`;\n}\n"]}
|
|
@@ -25,6 +25,8 @@ export interface GoalCacheWarmupEntryData {
|
|
|
25
25
|
/** Actual wait in milliseconds; present on the `resumed` phase only. */
|
|
26
26
|
readonly waitedMs?: number;
|
|
27
27
|
readonly activeMonitorCount: number;
|
|
28
|
+
/** Full source-keyed snapshot; absent on entries written before resumption channels were generalized. */
|
|
29
|
+
readonly channelCounts?: Readonly<Record<string, number>>;
|
|
28
30
|
readonly cache?: GoalCacheWarmMetrics;
|
|
29
31
|
}
|
|
30
32
|
export declare function estimateCacheWarmMetrics(model: Model<Api> | undefined, env: NodeJS.ProcessEnv, lastTurnUsage: Pick<TokenUsageSnapshot, "cacheRead" | "cacheWrite"> | undefined): GoalCacheWarmMetrics | undefined;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cache-warm.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/goal/cache-warm.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,KAAK,EAAe,MAAM,uBAAuB,CAAC;AAErE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAErD,4EAA4E;AAC5E,eAAO,MAAM,4BAA4B,sBAAsB,CAAC;AAEhE,4EAA4E;AAC5E,MAAM,WAAW,oBAAoB;IACpC,mEAAmE;IACnE,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,4EAA4E;IAC5E,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,qGAAqG;IACrG,QAAQ,CAAC,iBAAiB,CAAC,EAAE,MAAM,CAAC;CACpC;AAED,MAAM,MAAM,oBAAoB,GAAG,WAAW,GAAG,SAAS,CAAC;AAE3D;;;;GAIG;AACH,MAAM,WAAW,wBAAwB;IACxC,QAAQ,CAAC,KAAK,EAAE,oBAAoB,CAAC;IACrC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,kDAAkD;IAClD,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,wEAAwE;IACxE,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC;IACpC,QAAQ,CAAC,KAAK,CAAC,EAAE,oBAAoB,CAAC;CACtC;AAID,wBAAgB,wBAAwB,CACvC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,GAAG,SAAS,EAC7B,GAAG,EAAE,MAAM,CAAC,UAAU,EACtB,aAAa,EAAE,IAAI,CAAC,kBAAkB,EAAE,WAAW,GAAG,YAAY,CAAC,GAAG,SAAS,GAC7E,oBAAoB,GAAG,SAAS,CAalC;AAED,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAI3D;AAED,wBAAgB,kBAAkB,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CASrD;AAED,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAItD;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAIpD"}
|
|
1
|
+
{"version":3,"file":"cache-warm.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/goal/cache-warm.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,KAAK,EAAe,MAAM,uBAAuB,CAAC;AAErE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAErD,4EAA4E;AAC5E,eAAO,MAAM,4BAA4B,sBAAsB,CAAC;AAEhE,4EAA4E;AAC5E,MAAM,WAAW,oBAAoB;IACpC,mEAAmE;IACnE,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,4EAA4E;IAC5E,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,qGAAqG;IACrG,QAAQ,CAAC,iBAAiB,CAAC,EAAE,MAAM,CAAC;CACpC;AAED,MAAM,MAAM,oBAAoB,GAAG,WAAW,GAAG,SAAS,CAAC;AAE3D;;;;GAIG;AACH,MAAM,WAAW,wBAAwB;IACxC,QAAQ,CAAC,KAAK,EAAE,oBAAoB,CAAC;IACrC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,kDAAkD;IAClD,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,wEAAwE;IACxE,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC;IACpC,yGAAyG;IACzG,QAAQ,CAAC,aAAa,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAC1D,QAAQ,CAAC,KAAK,CAAC,EAAE,oBAAoB,CAAC;CACtC;AAID,wBAAgB,wBAAwB,CACvC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,GAAG,SAAS,EAC7B,GAAG,EAAE,MAAM,CAAC,UAAU,EACtB,aAAa,EAAE,IAAI,CAAC,kBAAkB,EAAE,WAAW,GAAG,YAAY,CAAC,GAAG,SAAS,GAC7E,oBAAoB,GAAG,SAAS,CAalC;AAED,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAI3D;AAED,wBAAgB,kBAAkB,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CASrD;AAED,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAItD;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAIpD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cache-warm.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/goal/cache-warm.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,4BAA4B,EAAE,MAAM,uBAAuB,CAAC;AAGrE,4EAA4E;AAC5E,MAAM,CAAC,MAAM,4BAA4B,GAAG,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"cache-warm.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/goal/cache-warm.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Api, Model, ProviderEnv } from \"@earendil-works/pi-ai\";\nimport { resolvePromptCacheTtlSeconds } from \"@earendil-works/pi-ai\";\nimport type { TokenUsageSnapshot } from \"./types.ts\";\n\n/** Custom session-entry type carrying the cache-warm continuation story. */\nexport const GOAL_CACHE_WARMUP_ENTRY_TYPE = \"goal-cache-warmup\";\n\n/** Cache context captured when a monitor-wait continuation is scheduled. */\nexport interface GoalCacheWarmMetrics {\n\t/** Prompt-cache TTL of the active model in seconds, when known. */\n\treadonly ttlSeconds?: number;\n\t/** Tokens sitting warm in the provider prompt cache after the last turn. */\n\treadonly cachedTokens: number;\n\t/** Estimated USD saved by re-reading those tokens from cache instead of paying a cold input read. */\n\treadonly estimatedSavedUsd?: number;\n}\n\nexport type GoalCacheWarmupPhase = \"scheduled\" | \"resumed\";\n\n/**\n * Durable payload appended as a `goal-cache-warmup` custom entry and carried by\n * the `goal_continuation_scheduled` / `goal_continuation_resumed` pi-events, so\n * external consumers (for example omo-desktop-app) can render the story later.\n */\nexport interface GoalCacheWarmupEntryData {\n\treadonly phase: GoalCacheWarmupPhase;\n\treadonly goalId: string;\n\t/** Planned continuation delay in milliseconds. */\n\treadonly delayMs: number;\n\t/** Actual wait in milliseconds; present on the `resumed` phase only. */\n\treadonly waitedMs?: number;\n\treadonly activeMonitorCount: number;\n\t/** Full source-keyed snapshot; absent on entries written before resumption channels were generalized. */\n\treadonly channelCounts?: Readonly<Record<string, number>>;\n\treadonly cache?: GoalCacheWarmMetrics;\n}\n\nconst TOKENS_PER_PRICE_UNIT = 1_000_000;\n\nexport function estimateCacheWarmMetrics(\n\tmodel: Model<Api> | undefined,\n\tenv: NodeJS.ProcessEnv,\n\tlastTurnUsage: Pick<TokenUsageSnapshot, \"cacheRead\" | \"cacheWrite\"> | undefined,\n): GoalCacheWarmMetrics | undefined {\n\tconst cachedTokens = clampTokens(lastTurnUsage?.cacheRead) + clampTokens(lastTurnUsage?.cacheWrite);\n\tconst ttlSeconds = model === undefined ? undefined : resolvePromptCacheTtlSeconds(model, toProviderEnv(env));\n\tif (ttlSeconds === undefined && cachedTokens === 0) return undefined;\n\tconst estimatedSavedUsd =\n\t\tmodel !== undefined && cachedTokens > 0\n\t\t\t? (Math.max(0, model.cost.input - model.cost.cacheRead) * cachedTokens) / TOKENS_PER_PRICE_UNIT\n\t\t\t: undefined;\n\treturn {\n\t\tcachedTokens,\n\t\t...(ttlSeconds !== undefined ? { ttlSeconds } : {}),\n\t\t...(estimatedSavedUsd !== undefined ? { estimatedSavedUsd } : {}),\n\t};\n}\n\nexport function formatWarmTokenCount(tokens: number): string {\n\tif (tokens >= 1_000_000) return `${trimTrailingZero((tokens / 1_000_000).toFixed(1))}M`;\n\tif (tokens >= 1000) return `${trimTrailingZero((tokens / 1000).toFixed(1))}K`;\n\treturn String(Math.max(0, Math.trunc(tokens)));\n}\n\nexport function formatWakeDuration(ms: number): string {\n\tconst seconds = Math.round(ms / 1000);\n\tif (seconds < 60) return `${seconds}s`;\n\tconst minutes = Math.floor(seconds / 60);\n\tconst restSeconds = seconds % 60;\n\tif (minutes < 60) return restSeconds === 0 ? `${minutes}m` : `${minutes}m ${restSeconds}s`;\n\tconst hours = Math.floor(minutes / 60);\n\tconst restMinutes = minutes % 60;\n\treturn restMinutes === 0 ? `${hours}h` : `${hours}h ${restMinutes}m`;\n}\n\nexport function formatCacheTtl(seconds: number): string {\n\tif (seconds % 3600 === 0) return `${seconds / 3600}h`;\n\tif (seconds % 60 === 0) return `${seconds / 60}m`;\n\treturn `${seconds}s`;\n}\n\nexport function formatSavedUsd(value: number): string {\n\tif (value < 0.0005) return \"<$0.001\";\n\tif (value < 1) return `$${value.toFixed(3)}`;\n\treturn `$${value.toFixed(2)}`;\n}\n\nfunction trimTrailingZero(value: string): string {\n\treturn value.endsWith(\".0\") ? value.slice(0, -2) : value;\n}\n\nfunction clampTokens(value: number | undefined): number {\n\treturn typeof value === \"number\" && Number.isFinite(value) && value > 0 ? Math.trunc(value) : 0;\n}\n\nfunction toProviderEnv(env: NodeJS.ProcessEnv): ProviderEnv {\n\tconst resolved: Record<string, string> = {};\n\tfor (const [key, value] of Object.entries(env)) {\n\t\tif (value !== undefined) resolved[key] = value;\n\t}\n\treturn resolved;\n}\n"]}
|
|
@@ -16,6 +16,7 @@ export type ContinuingGoalContinuationVerdict = Extract<GoalContinuationVerdict,
|
|
|
16
16
|
kind: "continue";
|
|
17
17
|
}>;
|
|
18
18
|
export type DelayedContinuationKind = GoalWaitKind;
|
|
19
|
+
export type ResumptionChannelCounts = Readonly<Record<string, number>>;
|
|
19
20
|
export type GoalContinuationAdmission = {
|
|
20
21
|
readonly goal: Goal;
|
|
21
22
|
readonly admitted: boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"monitor-continuation-types.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/goal/monitor-continuation-types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAClE,OAAO,KAAK,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AACtE,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,mBAAmB,CAAC;AACjE,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEvD,MAAM,WAAW,eAAe;IAC/B,QAAQ,CAAC,GAAG,EAAE,gBAAgB,CAAC;IAC/B,QAAQ,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,CAAC;IAC3B,QAAQ,CAAC,QAAQ,EAAE,SAAS,YAAY,EAAE,CAAC;CAC3C;AAED,MAAM,WAAW,kBAAmB,SAAQ,eAAe;IAC1D,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC;IAC9B,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;CAC5B;AAED,MAAM,MAAM,iCAAiC,GAAG,OAAO,CAAC,uBAAuB,EAAE;IAAE,IAAI,EAAE,UAAU,CAAA;CAAE,CAAC,CAAC;AACvG,MAAM,MAAM,uBAAuB,GAAG,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"monitor-continuation-types.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/goal/monitor-continuation-types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAClE,OAAO,KAAK,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AACtE,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,mBAAmB,CAAC;AACjE,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEvD,MAAM,WAAW,eAAe;IAC/B,QAAQ,CAAC,GAAG,EAAE,gBAAgB,CAAC;IAC/B,QAAQ,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,CAAC;IAC3B,QAAQ,CAAC,QAAQ,EAAE,SAAS,YAAY,EAAE,CAAC;CAC3C;AAED,MAAM,WAAW,kBAAmB,SAAQ,eAAe;IAC1D,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC;IAC9B,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;CAC5B;AAED,MAAM,MAAM,iCAAiC,GAAG,OAAO,CAAC,uBAAuB,EAAE;IAAE,IAAI,EAAE,UAAU,CAAA;CAAE,CAAC,CAAC;AACvG,MAAM,MAAM,uBAAuB,GAAG,YAAY,CAAC;AACnD,MAAM,MAAM,uBAAuB,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;AAEvE,MAAM,MAAM,yBAAyB,GAAG;IACvC,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC;IACpB,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;CAC3B,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"monitor-continuation-types.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/goal/monitor-continuation-types.ts"],"names":[],"mappings":"","sourcesContent":["import type { AgentMessage } from \"@earendil-works/pi-agent-core\";\nimport type { AgentEndEvent, ExtensionContext } from \"../../types.ts\";\nimport type { GoalContinuationVerdict } from \"./continuation.ts\";\nimport type { Goal } from \"./types.ts\";\nimport type { GoalWaitKind } from \"./wait-progress.ts\";\n\nexport interface AgentEndOptions {\n\treadonly ctx: ExtensionContext;\n\treadonly goal: Goal | null;\n\treadonly messages: readonly AgentMessage[];\n}\n\nexport interface SystemAbortOptions extends AgentEndOptions {\n\treadonly event: AgentEndEvent;\n\treadonly willRetry: boolean;\n}\n\nexport type ContinuingGoalContinuationVerdict = Extract<GoalContinuationVerdict, { kind: \"continue\" }>;\nexport type DelayedContinuationKind = GoalWaitKind;\n\nexport type GoalContinuationAdmission = {\n\treadonly goal: Goal;\n\treadonly admitted: boolean;\n};\n"]}
|
|
1
|
+
{"version":3,"file":"monitor-continuation-types.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/goal/monitor-continuation-types.ts"],"names":[],"mappings":"","sourcesContent":["import type { AgentMessage } from \"@earendil-works/pi-agent-core\";\nimport type { AgentEndEvent, ExtensionContext } from \"../../types.ts\";\nimport type { GoalContinuationVerdict } from \"./continuation.ts\";\nimport type { Goal } from \"./types.ts\";\nimport type { GoalWaitKind } from \"./wait-progress.ts\";\n\nexport interface AgentEndOptions {\n\treadonly ctx: ExtensionContext;\n\treadonly goal: Goal | null;\n\treadonly messages: readonly AgentMessage[];\n}\n\nexport interface SystemAbortOptions extends AgentEndOptions {\n\treadonly event: AgentEndEvent;\n\treadonly willRetry: boolean;\n}\n\nexport type ContinuingGoalContinuationVerdict = Extract<GoalContinuationVerdict, { kind: \"continue\" }>;\nexport type DelayedContinuationKind = GoalWaitKind;\nexport type ResumptionChannelCounts = Readonly<Record<string, number>>;\n\nexport type GoalContinuationAdmission = {\n\treadonly goal: Goal;\n\treadonly admitted: boolean;\n};\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"monitor-continuation.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/goal/monitor-continuation.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"monitor-continuation.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/goal/monitor-continuation.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAyBrE,OAAO,KAAK,EACX,eAAe,EAKf,kBAAkB,EAClB,MAAM,iCAAiC,CAAC;AAKzC,OAAO,KAAK,EAAE,IAAI,EAAsB,MAAM,YAAY,CAAC;AAC3D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAEvD,eAAO,MAAM,kCAAkC,SAAU,CAAC;AAC1D,eAAO,MAAM,iCAAiC,gCAAgC,CAAC;AAC/E,eAAO,MAAM,+BAA+B,8BAA8B,CAAC;AAC3E,eAAO,MAAM,wBAAwB,oCAAoC,CAAC;AAE1E,qBAAa,4BAA4B;;IA0BxC,YACC,EAAE,EAAE,YAAY,EAChB,qBAAqB,GAAE,MAAM,OAAqB,EAClD,uBAAuB,GAAE,MAAM,IAAe,EAC9C,UAAU,CAAC,EAAE,cAAc,EAO3B;IAED,KAAK,CAAC,GAAG,EAAE,gBAAgB,GAAG,IAAI,CASjC;IAEK,aAAa,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC,CAsDlE;IAEK,gBAAgB,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC,CAaxE;IAEK,iBAAiB,IAAI,OAAO,CAAC,IAAI,GAAG,IAAI,GAAG,SAAS,CAAC,CAK1D;IAED,QAAQ,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAOhC;IAED,mGAAmG;IACnG,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAkBrC;IAED,6FAA6F;IAC7F,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,GAAG,IAAI,CAW3D;IAED,sEAAsE;IACtE,cAAc,IAAI,IAAI,CAIrB;IAED,mGAAmG;IACnG,uBAAuB,IAAI,IAAI,CAE9B;IAED,OAAO,IAAI,IAAI,CAUd;CAkRD"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { isTerminalMonitorStateEvent, TERMINAL_MONITOR_STATE_EVENT } from "../monitor-state-event.js";
|
|
2
|
+
import { isResumptionChannelStateEvent, RESUMPTION_CHANNEL_STATE_EVENT } from "../resumption-channel-event.js";
|
|
2
3
|
import { estimateCacheWarmMetrics, GOAL_CACHE_WARMUP_ENTRY_TYPE, } from "./cache-warm.js";
|
|
3
4
|
import { continuationTurnUsedTools, evaluateGoalContinuation, GOAL_USER_GRACE_DELAY_MS, hasGoalContinuationProgress, hashAssistantText, normalizeAssistantText, } from "./continuation.js";
|
|
4
5
|
import { lastAssistantMessage } from "./last-assistant-message.js";
|
|
@@ -16,12 +17,13 @@ export class MonitorAwareGoalContinuation {
|
|
|
16
17
|
#isContinuationPending;
|
|
17
18
|
#markContinuationPending;
|
|
18
19
|
#waitTicker;
|
|
19
|
-
#
|
|
20
|
+
#channelCounts = new Map();
|
|
21
|
+
#hasStarted = false;
|
|
20
22
|
#ctx;
|
|
21
23
|
#goal = null;
|
|
22
24
|
#timer;
|
|
23
25
|
#scheduledContinuationKind;
|
|
24
|
-
#
|
|
26
|
+
#channelStateUnsubscribers = [];
|
|
25
27
|
#lastAgentEndMessages = [];
|
|
26
28
|
#consecutiveLengthRecoveries = new Map();
|
|
27
29
|
#recentNormalizedOutputHashes = [];
|
|
@@ -40,33 +42,19 @@ export class MonitorAwareGoalContinuation {
|
|
|
40
42
|
this.#isContinuationPending = isContinuationPending;
|
|
41
43
|
this.#markContinuationPending = markContinuationPending;
|
|
42
44
|
this.#waitTicker = waitTicker;
|
|
45
|
+
this.#subscribeToChannelState();
|
|
43
46
|
}
|
|
44
47
|
start(ctx) {
|
|
45
48
|
this.#cancelTimer();
|
|
46
|
-
this.#unsubscribeMonitorState?.();
|
|
47
49
|
this.#ctx = ctx;
|
|
48
|
-
this.#
|
|
50
|
+
if (this.#hasStarted)
|
|
51
|
+
this.#channelCounts.clear();
|
|
52
|
+
else
|
|
53
|
+
this.#hasStarted = true;
|
|
49
54
|
this.#goal = null;
|
|
50
55
|
this.#lastAgentEndMessages = [];
|
|
51
56
|
this.#directInputHolds.clear();
|
|
52
57
|
this.#resetContinuationState();
|
|
53
|
-
const events = this.#pi.events;
|
|
54
|
-
if (events === undefined)
|
|
55
|
-
return;
|
|
56
|
-
this.#unsubscribeMonitorState = events.on(TERMINAL_MONITOR_STATE_EVENT, (data) => {
|
|
57
|
-
if (!isTerminalMonitorStateEvent(data))
|
|
58
|
-
return;
|
|
59
|
-
this.#activeMonitorCount = data.activeCount;
|
|
60
|
-
if (data.activeCount === 0) {
|
|
61
|
-
if (this.#scheduledContinuationKind === "monitor")
|
|
62
|
-
this.#cancelTimer();
|
|
63
|
-
this.#resetToollessContinuationStreak();
|
|
64
|
-
return;
|
|
65
|
-
}
|
|
66
|
-
if (this.#scheduledContinuationKind === "monitor") {
|
|
67
|
-
this.#waitTicker?.setActiveMonitorCount(data.activeCount);
|
|
68
|
-
}
|
|
69
|
-
});
|
|
70
58
|
}
|
|
71
59
|
async afterAgentEnd(options) {
|
|
72
60
|
if (options.goal?.id !== this.#goal?.id)
|
|
@@ -115,7 +103,7 @@ export class MonitorAwareGoalContinuation {
|
|
|
115
103
|
}
|
|
116
104
|
if (immediateVerdict.kind === "deny" && immediateVerdict.reason === "not-eligible")
|
|
117
105
|
return goal;
|
|
118
|
-
if (this.#
|
|
106
|
+
if (this.#activeChannelCount() === 0) {
|
|
119
107
|
this.#cancelTimer();
|
|
120
108
|
const admission = await this.#admitAndQueue(options.ctx, goal, "immediate", options.messages);
|
|
121
109
|
return admission.goal;
|
|
@@ -132,7 +120,7 @@ export class MonitorAwareGoalContinuation {
|
|
|
132
120
|
this.#lastTurnUsage = collectAssistantUsage([...options.messages]);
|
|
133
121
|
if (options.willRetry || options.goal?.status !== "active")
|
|
134
122
|
return options.goal;
|
|
135
|
-
if (this.#
|
|
123
|
+
if (this.#activeChannelCount() > 0)
|
|
136
124
|
this.#schedule(options.goal, "monitor");
|
|
137
125
|
else if (lastAssistantMessage(options.messages)?.stopReason === "error") {
|
|
138
126
|
this.#pendingSystemRecovery = options;
|
|
@@ -201,11 +189,12 @@ export class MonitorAwareGoalContinuation {
|
|
|
201
189
|
}
|
|
202
190
|
dispose() {
|
|
203
191
|
this.#cancelTimer();
|
|
204
|
-
this.#
|
|
205
|
-
|
|
192
|
+
for (const unsubscribe of this.#channelStateUnsubscribers)
|
|
193
|
+
unsubscribe();
|
|
194
|
+
this.#channelStateUnsubscribers = [];
|
|
206
195
|
this.#ctx = undefined;
|
|
207
196
|
this.#goal = null;
|
|
208
|
-
this.#
|
|
197
|
+
this.#channelCounts.clear();
|
|
209
198
|
this.#lastAgentEndMessages = [];
|
|
210
199
|
this.#directInputHolds.clear();
|
|
211
200
|
this.#resetContinuationState();
|
|
@@ -216,19 +205,22 @@ export class MonitorAwareGoalContinuation {
|
|
|
216
205
|
const delayMs = kind === "monitor" ? GOAL_MONITOR_CONTINUATION_DELAY_MS : GOAL_USER_GRACE_DELAY_MS;
|
|
217
206
|
if (kind === "monitor") {
|
|
218
207
|
const cache = estimateCacheWarmMetrics(this.#ctx?.model, process.env, this.#lastTurnUsage);
|
|
208
|
+
const channelCounts = this.#channelCountSnapshot();
|
|
219
209
|
this.#scheduledCache = cache;
|
|
220
210
|
this.#scheduledAtMs = Date.now();
|
|
221
211
|
this.#pi.events?.emit(GOAL_CONTINUATION_SCHEDULED_EVENT, {
|
|
222
212
|
goalId: goal.id,
|
|
223
213
|
delayMs,
|
|
224
|
-
activeMonitorCount: this.#
|
|
214
|
+
activeMonitorCount: this.#activeTerminalMonitorCount(),
|
|
215
|
+
channelCounts,
|
|
225
216
|
cache,
|
|
226
217
|
});
|
|
227
218
|
this.#appendWarmupEntry({
|
|
228
219
|
phase: "scheduled",
|
|
229
220
|
goalId: goal.id,
|
|
230
221
|
delayMs,
|
|
231
|
-
activeMonitorCount: this.#
|
|
222
|
+
activeMonitorCount: this.#activeTerminalMonitorCount(),
|
|
223
|
+
channelCounts,
|
|
232
224
|
...(cache !== undefined ? { cache } : {}),
|
|
233
225
|
});
|
|
234
226
|
}
|
|
@@ -251,7 +243,7 @@ export class MonitorAwareGoalContinuation {
|
|
|
251
243
|
kind,
|
|
252
244
|
remainingMs: delayMs,
|
|
253
245
|
totalMs: kind === "monitor" ? GOAL_MONITOR_CONTINUATION_DELAY_MS : GOAL_USER_GRACE_DELAY_MS,
|
|
254
|
-
|
|
246
|
+
channelCounts: this.#channelCountSnapshot(),
|
|
255
247
|
});
|
|
256
248
|
}
|
|
257
249
|
this.#timer = setTimeout(() => {
|
|
@@ -277,16 +269,18 @@ export class MonitorAwareGoalContinuation {
|
|
|
277
269
|
const goal = this.#goal;
|
|
278
270
|
if (ctx === undefined || goal?.status !== "active" || !ctx.isIdle() || ctx.hasPendingMessages())
|
|
279
271
|
return;
|
|
280
|
-
if (kind === "monitor" && this.#
|
|
272
|
+
if (kind === "monitor" && this.#activeChannelCount() === 0)
|
|
281
273
|
return;
|
|
282
274
|
const admission = await this.#admitAndQueue(ctx, goal, kind === "monitor" ? "monitorDelayed" : "userGrace", this.#lastAgentEndMessages);
|
|
283
275
|
if (kind !== "monitor" || !admission.admitted)
|
|
284
276
|
return;
|
|
277
|
+
const channelCounts = this.#channelCountSnapshot();
|
|
285
278
|
this.#pi.events?.emit(GOAL_CONTINUATION_RESUMED_EVENT, {
|
|
286
279
|
goalId: goal.id,
|
|
287
280
|
delayMs,
|
|
288
281
|
waitedMs,
|
|
289
|
-
activeMonitorCount: this.#
|
|
282
|
+
activeMonitorCount: this.#activeTerminalMonitorCount(),
|
|
283
|
+
channelCounts,
|
|
290
284
|
cache,
|
|
291
285
|
});
|
|
292
286
|
this.#appendWarmupEntry({
|
|
@@ -294,7 +288,8 @@ export class MonitorAwareGoalContinuation {
|
|
|
294
288
|
goalId: goal.id,
|
|
295
289
|
delayMs,
|
|
296
290
|
waitedMs,
|
|
297
|
-
activeMonitorCount: this.#
|
|
291
|
+
activeMonitorCount: this.#activeTerminalMonitorCount(),
|
|
292
|
+
channelCounts,
|
|
298
293
|
...(cache !== undefined ? { cache } : {}),
|
|
299
294
|
});
|
|
300
295
|
}
|
|
@@ -339,17 +334,17 @@ export class MonitorAwareGoalContinuation {
|
|
|
339
334
|
let content = verdict.prompt === "minimal" ? buildTruncationRecoveryPrompt() : buildContinuationPrompt(goal);
|
|
340
335
|
if (!verdict.stallNotice)
|
|
341
336
|
return content;
|
|
342
|
-
const
|
|
337
|
+
const liveSources = this.#liveChannelSources();
|
|
343
338
|
this.#pi.events?.emit(GOAL_MONITOR_STALL_EVENT, {
|
|
344
339
|
goalId: goal.id,
|
|
345
340
|
consecutiveContinuations: this.#toollessContinuationStreak,
|
|
346
341
|
toolless: true,
|
|
347
342
|
});
|
|
348
343
|
if (ctx.hasUI) {
|
|
349
|
-
const context =
|
|
344
|
+
const context = liveSources.length > 0 ? `while ${liveSources.join(", ")} channels stayed active` : "without tool use";
|
|
350
345
|
ctx.ui.notify(`Goal continuation repeated ${this.#toollessContinuationStreak} toolless turns ${context} - injected a stall check.`, "info");
|
|
351
346
|
}
|
|
352
|
-
content = `${buildGoalStallNotice(this.#toollessContinuationStreak, {
|
|
347
|
+
content = `${buildGoalStallNotice(this.#toollessContinuationStreak, { liveSources })}\n\n${content}`;
|
|
353
348
|
return content;
|
|
354
349
|
}
|
|
355
350
|
/** A tool-using turn is forward progress, so it clears the repetition window instead of extending it. */
|
|
@@ -381,6 +376,52 @@ export class MonitorAwareGoalContinuation {
|
|
|
381
376
|
return;
|
|
382
377
|
this.#consecutiveLengthRecoveries.delete(goal.id);
|
|
383
378
|
}
|
|
379
|
+
#subscribeToChannelState() {
|
|
380
|
+
const events = this.#pi.events;
|
|
381
|
+
if (events === undefined)
|
|
382
|
+
return;
|
|
383
|
+
this.#channelStateUnsubscribers.push(events.on(TERMINAL_MONITOR_STATE_EVENT, (data) => {
|
|
384
|
+
if (!isTerminalMonitorStateEvent(data))
|
|
385
|
+
return;
|
|
386
|
+
this.#setChannelCount("terminal-monitor", data.activeCount);
|
|
387
|
+
}), events.on(RESUMPTION_CHANNEL_STATE_EVENT, (data) => {
|
|
388
|
+
if (!isResumptionChannelStateEvent(data))
|
|
389
|
+
return;
|
|
390
|
+
this.#setChannelCount(data.source, data.activeCount);
|
|
391
|
+
}));
|
|
392
|
+
}
|
|
393
|
+
#setChannelCount(source, activeCount) {
|
|
394
|
+
const previousTotal = this.#activeChannelCount();
|
|
395
|
+
this.#channelCounts.set(source, activeCount);
|
|
396
|
+
const nextTotal = this.#activeChannelCount();
|
|
397
|
+
if (previousTotal > 0 && nextTotal === 0) {
|
|
398
|
+
if (this.#scheduledContinuationKind === "monitor")
|
|
399
|
+
this.#cancelTimer();
|
|
400
|
+
this.#resetToollessContinuationStreak();
|
|
401
|
+
return;
|
|
402
|
+
}
|
|
403
|
+
if (this.#scheduledContinuationKind === "monitor") {
|
|
404
|
+
this.#waitTicker?.setChannelCounts(this.#channelCountSnapshot());
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
#activeChannelCount() {
|
|
408
|
+
let total = 0;
|
|
409
|
+
for (const count of this.#channelCounts.values())
|
|
410
|
+
total += count;
|
|
411
|
+
return total;
|
|
412
|
+
}
|
|
413
|
+
#activeTerminalMonitorCount() {
|
|
414
|
+
return this.#channelCounts.get("terminal-monitor") ?? 0;
|
|
415
|
+
}
|
|
416
|
+
#channelCountSnapshot() {
|
|
417
|
+
return Object.fromEntries([...this.#channelCounts.entries()].sort(([left], [right]) => left.localeCompare(right)));
|
|
418
|
+
}
|
|
419
|
+
#liveChannelSources() {
|
|
420
|
+
return [...this.#channelCounts.entries()]
|
|
421
|
+
.filter(([, count]) => count > 0)
|
|
422
|
+
.map(([source]) => source)
|
|
423
|
+
.sort();
|
|
424
|
+
}
|
|
384
425
|
#resetContinuationState() {
|
|
385
426
|
this.#pendingSystemRecovery = undefined;
|
|
386
427
|
this.#consecutiveLengthRecoveries.clear();
|