@caupulican/pi-adaptative 0.93.9 → 0.93.11
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 +18 -0
- package/dist/core/agent-session-contracts.d.ts +5 -1
- package/dist/core/agent-session-contracts.d.ts.map +1 -1
- package/dist/core/agent-session-contracts.js +4 -0
- package/dist/core/agent-session-contracts.js.map +1 -1
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +4 -2
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/autonomy/envelope-enforcement.d.ts.map +1 -1
- package/dist/core/autonomy/envelope-enforcement.js +2 -0
- package/dist/core/autonomy/envelope-enforcement.js.map +1 -1
- package/dist/core/fast-mode.d.ts +22 -0
- package/dist/core/fast-mode.d.ts.map +1 -0
- package/dist/core/fast-mode.js +37 -0
- package/dist/core/fast-mode.js.map +1 -0
- package/dist/core/goal-loop-controller.d.ts +1 -1
- package/dist/core/goal-loop-controller.d.ts.map +1 -1
- package/dist/core/goal-loop-controller.js +8 -5
- package/dist/core/goal-loop-controller.js.map +1 -1
- package/dist/core/goals/goal-auto-continue-controller.d.ts.map +1 -1
- package/dist/core/goals/goal-auto-continue-controller.js +3 -1
- package/dist/core/goals/goal-auto-continue-controller.js.map +1 -1
- package/dist/core/goals/goal-session-controller.d.ts +3 -2
- package/dist/core/goals/goal-session-controller.d.ts.map +1 -1
- package/dist/core/goals/goal-session-controller.js +22 -1
- package/dist/core/goals/goal-session-controller.js.map +1 -1
- package/dist/core/goals/natural-language-goal.d.ts +1 -1
- package/dist/core/goals/natural-language-goal.d.ts.map +1 -1
- package/dist/core/goals/natural-language-goal.js +1 -1
- package/dist/core/goals/natural-language-goal.js.map +1 -1
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +3 -1
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/secrets/credential-exposure-guard.d.ts +1 -1
- package/dist/core/secrets/credential-exposure-guard.d.ts.map +1 -1
- package/dist/core/secrets/credential-exposure-guard.js +11 -4
- package/dist/core/secrets/credential-exposure-guard.js.map +1 -1
- package/dist/core/secrets/credential-source-discovery.d.ts +23 -0
- package/dist/core/secrets/credential-source-discovery.d.ts.map +1 -0
- package/dist/core/secrets/credential-source-discovery.js +187 -0
- package/dist/core/secrets/credential-source-discovery.js.map +1 -0
- package/dist/core/settings-manager.d.ts +4 -0
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +12 -0
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/slash-commands.d.ts.map +1 -1
- package/dist/core/slash-commands.js +1 -0
- package/dist/core/slash-commands.js.map +1 -1
- package/dist/core/tool-capability-policy.js +1 -1
- package/dist/core/tool-capability-policy.js.map +1 -1
- package/dist/core/tools/goal.js +7 -7
- package/dist/core/tools/goal.js.map +1 -1
- package/dist/core/tools/secret-store.d.ts +8 -3
- package/dist/core/tools/secret-store.d.ts.map +1 -1
- package/dist/core/tools/secret-store.js +37 -6
- package/dist/core/tools/secret-store.js.map +1 -1
- package/dist/modes/interactive/components/footer.d.ts.map +1 -1
- package/dist/modes/interactive/components/footer.js +12 -3
- package/dist/modes/interactive/components/footer.js.map +1 -1
- package/dist/modes/interactive/fast-mode-command.d.ts +7 -0
- package/dist/modes/interactive/fast-mode-command.d.ts.map +1 -0
- package/dist/modes/interactive/fast-mode-command.js +32 -0
- package/dist/modes/interactive/fast-mode-command.js.map +1 -0
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +7 -0
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
- package/examples/extensions/custom-provider-anthropic/package.json +1 -1
- package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
- package/examples/extensions/sandbox/package-lock.json +2 -2
- package/examples/extensions/sandbox/package.json +1 -1
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/npm-shrinkwrap.json +12 -12
- package/package.json +4 -4
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"envelope-enforcement.d.ts","sourceRoot":"","sources":["../../../src/core/autonomy/envelope-enforcement.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAezD,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,EAAE,CAiB9D;AAED,wFAAwF;AACxF,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG,MAAM,EAAE,
|
|
1
|
+
{"version":3,"file":"envelope-enforcement.d.ts","sourceRoot":"","sources":["../../../src/core/autonomy/envelope-enforcement.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAezD,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,EAAE,CAiB9D;AAED,wFAAwF;AACxF,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG,MAAM,EAAE,CAwBpF;AAED;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,kBAAkB,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAoCxG;AAED,MAAM,WAAW,kBAAkB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC;CACzC;AAED;;;;;GAKG;AACH,wBAAgB,yBAAyB,CAAC,CAAC,SAAS,kBAAkB,EACrE,IAAI,EAAE,CAAC,EACP,QAAQ,EAAE,kBAAkB,EAC5B,GAAG,EAAE,MAAM,GACT,CAAC,CA8BH"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"envelope-enforcement.js","sourceRoot":"","sources":["../../../src/core/autonomy/envelope-enforcement.ts"],"names":[],"mappings":"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","sourcesContent":["import { resolve } from \"node:path\";\nimport { resolveToolCallPathAccess } from \"../tool-capability-policy.ts\";\nimport type { CapabilityEnvelope } from \"./contracts.ts\";\nimport { isPathWithinScope, safeRealpathSync } from \"./path-scope.ts\";\n\n/**\n * Tool-level envelope enforcement (G2 prerequisite for code-writing workers): the capability\n * envelope's `allowedPaths`/`deniedPaths` were previously VALIDATION-ONLY — recorded on the\n * envelope but never checked when a tool actually ran. This module wraps tools so path-bearing\n * arguments are checked AT EXECUTION TIME, structurally refusing out-of-scope paths the same way\n * a failed script can never look like success: the refusal is an isError result with a stable\n * outcome code, never a silent no-op.\n */\n\nconst PATH_ARGUMENT_KEYS = [\"path\", \"file_path\", \"filePath\", \"cwd\", \"directory\", \"dir\", \"target\"] as const;\nconst PATH_LIST_ARGUMENT_KEYS = [\"paths\", \"files\"] as const;\n\nexport function extractPathArguments(params: unknown): string[] {\n\tif (!params || typeof params !== \"object\") return [];\n\tconst record = params as Record<string, unknown>;\n\tconst found: string[] = [];\n\tfor (const key of PATH_ARGUMENT_KEYS) {\n\t\tconst value = record[key];\n\t\tif (typeof value === \"string\" && value.trim()) found.push(value.trim());\n\t}\n\tfor (const key of PATH_LIST_ARGUMENT_KEYS) {\n\t\tconst value = record[key];\n\t\tif (Array.isArray(value)) {\n\t\t\tfor (const entry of value) {\n\t\t\t\tif (typeof entry === \"string\" && entry.trim()) found.push(entry.trim());\n\t\t\t}\n\t\t}\n\t}\n\treturn found;\n}\n\n/** Tool-aware path projection shared by every envelope/gateway enforcement boundary. */\nexport function extractToolPathArguments(toolName: string, params: unknown): string[] {\n\tconst normalizedToolName = toolName.toLowerCase();\n\tconst paths = extractPathArguments(params);\n\tif (normalizedToolName === \"secret_store\" && params && typeof params === \"object\") {\n\t\tconst record = params as Record<string, unknown>;\n\t\tif (record.action === \"migrate\" && Array.isArray(record.sources)) {\n\t\t\tfor (const source of record.sources) {\n\t\t\t\tif (!source || typeof source !== \"object\" || !(\"path\" in source)) continue;\n\t\t\t\tconst sourcePath = source.path;\n\t\t\t\tif (typeof sourcePath === \"string\" && sourcePath.trim()) paths.push(sourcePath.trim());\n\t\t\t}\n\t\t}\n\t}\n\tif (\n\t\tpaths.length === 0 &&\n\t\t(normalizedToolName === \"find\" ||\n\t\t\tnormalizedToolName === \"grep\" ||\n\t\t\tnormalizedToolName === \"ls\" ||\n\t\t\tnormalizedToolName === \"pipeline\")\n\t) {\n\t\tpaths.push(\".\");\n\t}\n\treturn paths;\n}\n\n/**\n * Deny wins over allow; an empty/absent allow list means \"no positive scope restriction\"\n * (only denies apply) — mirroring the resource-profile filter semantics.\n *\n * Both the target and every scope root are resolved through the real filesystem\n * (symlinks expanded in the existing prefix) before comparison: a pre-existing symlink\n * under an allowed root cannot smuggle a write outside the scope, and a shortcut into a\n * denied subtree is still denied. An unresolvable target fails closed.\n */\nexport function isPathWithinEnvelope(envelope: CapabilityEnvelope, rawPath: string, cwd: string): boolean {\n\tconst lexicalTarget = resolve(cwd, rawPath);\n\tconst allowed = envelope.allowedPaths ?? [];\n\tif (allowed.length > 0) {\n\t\tconst couldBeAllowed = allowed.some((root) => {\n\t\t\tconst lexicalRoot = resolve(cwd, root);\n\t\t\tif (isPathWithinScope(lexicalTarget, lexicalRoot)) return true;\n\t\t\ttry {\n\t\t\t\treturn isPathWithinScope(lexicalTarget, safeRealpathSync(lexicalRoot));\n\t\t\t} catch {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t});\n\t\tif (!couldBeAllowed) return false;\n\t}\n\tlet target: string;\n\ttry {\n\t\ttarget = safeRealpathSync(lexicalTarget);\n\t} catch {\n\t\treturn false;\n\t}\n\tfor (const denied of envelope.deniedPaths ?? []) {\n\t\ttry {\n\t\t\tif (isPathWithinScope(target, safeRealpathSync(resolve(cwd, denied)))) return false;\n\t\t} catch {\n\t\t\t// Mirror checkPathScope: an unresolvable deny root cannot match anything.\n\t\t}\n\t}\n\tif (allowed.length === 0) return true;\n\treturn allowed.some((root) => {\n\t\ttry {\n\t\t\treturn isPathWithinScope(target, safeRealpathSync(resolve(cwd, root)));\n\t\t} catch {\n\t\t\treturn false;\n\t\t}\n\t});\n}\n\nexport interface EnvelopeScopedTool {\n\tname: string;\n\texecute: (...args: unknown[]) => unknown;\n}\n\n/**\n * Wrap a tool so path-bearing arguments are scope-checked when it RUNS, consulting canonical\n * tool capability policy so only tools whose policy declares path-scope access\n * (resolveToolCallPathAccess !== \"none\") are checked against envelope boundaries. The wrapped tool is\n * shape-identical; params are conventionally the second execute argument (toolCallId, params, …).\n */\nexport function wrapToolWithEnvelopeScope<T extends EnvelopeScopedTool>(\n\ttool: T,\n\tenvelope: CapabilityEnvelope,\n\tcwd: string,\n): T {\n\treturn {\n\t\t...tool,\n\t\texecute: (...args: unknown[]) => {\n\t\t\tconst params = args[1];\n\t\t\tconst pathAccess = resolveToolCallPathAccess(envelope.capabilities, tool.name, params);\n\t\t\tif (pathAccess !== \"none\") {\n\t\t\t\tfor (const rawPath of extractToolPathArguments(tool.name, params)) {\n\t\t\t\t\tif (!isPathWithinEnvelope(envelope, rawPath, cwd)) {\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tcontent: [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\ttype: \"text\",\n\t\t\t\t\t\t\t\t\ttext: `envelope_path_denied: \"${rawPath}\" is outside envelope ${envelope.id}'s path scope. The tool was NOT run.`,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\tdetails: {\n\t\t\t\t\t\t\t\toutcome: \"envelope_path_denied\",\n\t\t\t\t\t\t\t\ttool: tool.name,\n\t\t\t\t\t\t\t\tpath: rawPath,\n\t\t\t\t\t\t\t\tenvelopeId: envelope.id,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tisError: true,\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn tool.execute(...args);\n\t\t},\n\t};\n}\n"]}
|
|
1
|
+
{"version":3,"file":"envelope-enforcement.js","sourceRoot":"","sources":["../../../src/core/autonomy/envelope-enforcement.ts"],"names":[],"mappings":"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","sourcesContent":["import { resolve } from \"node:path\";\nimport { resolveToolCallPathAccess } from \"../tool-capability-policy.ts\";\nimport type { CapabilityEnvelope } from \"./contracts.ts\";\nimport { isPathWithinScope, safeRealpathSync } from \"./path-scope.ts\";\n\n/**\n * Tool-level envelope enforcement (G2 prerequisite for code-writing workers): the capability\n * envelope's `allowedPaths`/`deniedPaths` were previously VALIDATION-ONLY — recorded on the\n * envelope but never checked when a tool actually ran. This module wraps tools so path-bearing\n * arguments are checked AT EXECUTION TIME, structurally refusing out-of-scope paths the same way\n * a failed script can never look like success: the refusal is an isError result with a stable\n * outcome code, never a silent no-op.\n */\n\nconst PATH_ARGUMENT_KEYS = [\"path\", \"file_path\", \"filePath\", \"cwd\", \"directory\", \"dir\", \"target\"] as const;\nconst PATH_LIST_ARGUMENT_KEYS = [\"paths\", \"files\"] as const;\n\nexport function extractPathArguments(params: unknown): string[] {\n\tif (!params || typeof params !== \"object\") return [];\n\tconst record = params as Record<string, unknown>;\n\tconst found: string[] = [];\n\tfor (const key of PATH_ARGUMENT_KEYS) {\n\t\tconst value = record[key];\n\t\tif (typeof value === \"string\" && value.trim()) found.push(value.trim());\n\t}\n\tfor (const key of PATH_LIST_ARGUMENT_KEYS) {\n\t\tconst value = record[key];\n\t\tif (Array.isArray(value)) {\n\t\t\tfor (const entry of value) {\n\t\t\t\tif (typeof entry === \"string\" && entry.trim()) found.push(entry.trim());\n\t\t\t}\n\t\t}\n\t}\n\treturn found;\n}\n\n/** Tool-aware path projection shared by every envelope/gateway enforcement boundary. */\nexport function extractToolPathArguments(toolName: string, params: unknown): string[] {\n\tconst normalizedToolName = toolName.toLowerCase();\n\tconst paths = extractPathArguments(params);\n\tif (normalizedToolName === \"secret_store\" && params && typeof params === \"object\") {\n\t\tconst record = params as Record<string, unknown>;\n\t\tif (record.action === \"migrate\" && Array.isArray(record.sources)) {\n\t\t\tfor (const source of record.sources) {\n\t\t\t\tif (!source || typeof source !== \"object\" || !(\"path\" in source)) continue;\n\t\t\t\tconst sourcePath = source.path;\n\t\t\t\tif (typeof sourcePath === \"string\" && sourcePath.trim()) paths.push(sourcePath.trim());\n\t\t\t}\n\t\t}\n\t\tif (record.action === \"discover\" && paths.length === 0) paths.push(\".\");\n\t}\n\tif (\n\t\tpaths.length === 0 &&\n\t\t(normalizedToolName === \"find\" ||\n\t\t\tnormalizedToolName === \"grep\" ||\n\t\t\tnormalizedToolName === \"ls\" ||\n\t\t\tnormalizedToolName === \"pipeline\")\n\t) {\n\t\tpaths.push(\".\");\n\t}\n\treturn paths;\n}\n\n/**\n * Deny wins over allow; an empty/absent allow list means \"no positive scope restriction\"\n * (only denies apply) — mirroring the resource-profile filter semantics.\n *\n * Both the target and every scope root are resolved through the real filesystem\n * (symlinks expanded in the existing prefix) before comparison: a pre-existing symlink\n * under an allowed root cannot smuggle a write outside the scope, and a shortcut into a\n * denied subtree is still denied. An unresolvable target fails closed.\n */\nexport function isPathWithinEnvelope(envelope: CapabilityEnvelope, rawPath: string, cwd: string): boolean {\n\tconst lexicalTarget = resolve(cwd, rawPath);\n\tconst allowed = envelope.allowedPaths ?? [];\n\tif (allowed.length > 0) {\n\t\tconst couldBeAllowed = allowed.some((root) => {\n\t\t\tconst lexicalRoot = resolve(cwd, root);\n\t\t\tif (isPathWithinScope(lexicalTarget, lexicalRoot)) return true;\n\t\t\ttry {\n\t\t\t\treturn isPathWithinScope(lexicalTarget, safeRealpathSync(lexicalRoot));\n\t\t\t} catch {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t});\n\t\tif (!couldBeAllowed) return false;\n\t}\n\tlet target: string;\n\ttry {\n\t\ttarget = safeRealpathSync(lexicalTarget);\n\t} catch {\n\t\treturn false;\n\t}\n\tfor (const denied of envelope.deniedPaths ?? []) {\n\t\ttry {\n\t\t\tif (isPathWithinScope(target, safeRealpathSync(resolve(cwd, denied)))) return false;\n\t\t} catch {\n\t\t\t// Mirror checkPathScope: an unresolvable deny root cannot match anything.\n\t\t}\n\t}\n\tif (allowed.length === 0) return true;\n\treturn allowed.some((root) => {\n\t\ttry {\n\t\t\treturn isPathWithinScope(target, safeRealpathSync(resolve(cwd, root)));\n\t\t} catch {\n\t\t\treturn false;\n\t\t}\n\t});\n}\n\nexport interface EnvelopeScopedTool {\n\tname: string;\n\texecute: (...args: unknown[]) => unknown;\n}\n\n/**\n * Wrap a tool so path-bearing arguments are scope-checked when it RUNS, consulting canonical\n * tool capability policy so only tools whose policy declares path-scope access\n * (resolveToolCallPathAccess !== \"none\") are checked against envelope boundaries. The wrapped tool is\n * shape-identical; params are conventionally the second execute argument (toolCallId, params, …).\n */\nexport function wrapToolWithEnvelopeScope<T extends EnvelopeScopedTool>(\n\ttool: T,\n\tenvelope: CapabilityEnvelope,\n\tcwd: string,\n): T {\n\treturn {\n\t\t...tool,\n\t\texecute: (...args: unknown[]) => {\n\t\t\tconst params = args[1];\n\t\t\tconst pathAccess = resolveToolCallPathAccess(envelope.capabilities, tool.name, params);\n\t\t\tif (pathAccess !== \"none\") {\n\t\t\t\tfor (const rawPath of extractToolPathArguments(tool.name, params)) {\n\t\t\t\t\tif (!isPathWithinEnvelope(envelope, rawPath, cwd)) {\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tcontent: [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\ttype: \"text\",\n\t\t\t\t\t\t\t\t\ttext: `envelope_path_denied: \"${rawPath}\" is outside envelope ${envelope.id}'s path scope. The tool was NOT run.`,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\tdetails: {\n\t\t\t\t\t\t\t\toutcome: \"envelope_path_denied\",\n\t\t\t\t\t\t\t\ttool: tool.name,\n\t\t\t\t\t\t\t\tpath: rawPath,\n\t\t\t\t\t\t\t\tenvelopeId: envelope.id,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tisError: true,\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn tool.execute(...args);\n\t\t},\n\t};\n}\n"]}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { Api, Model, ServiceTier } from "@caupulican/pi-ai";
|
|
2
|
+
export type FastModeKind = "service-tier";
|
|
3
|
+
interface FastModeSettings {
|
|
4
|
+
getFastModeEnabled(provider: string): boolean | undefined;
|
|
5
|
+
setFastModeEnabled(provider: string, enabled: boolean): void;
|
|
6
|
+
}
|
|
7
|
+
export interface FastModeSession {
|
|
8
|
+
readonly model: Model<Api> | undefined;
|
|
9
|
+
readonly settingsManager: FastModeSettings;
|
|
10
|
+
}
|
|
11
|
+
export interface FastModeStatus {
|
|
12
|
+
available: boolean;
|
|
13
|
+
changed: boolean;
|
|
14
|
+
enabled: boolean;
|
|
15
|
+
kind?: FastModeKind;
|
|
16
|
+
}
|
|
17
|
+
export declare function getFastModeStatus(session: FastModeSession): FastModeStatus;
|
|
18
|
+
export declare function setFastMode(session: FastModeSession, enabled: boolean): FastModeStatus;
|
|
19
|
+
export declare function toggleFastMode(session: FastModeSession): FastModeStatus;
|
|
20
|
+
export declare function resolveFastModeServiceTier(model: Model<Api>, preference: boolean | undefined): ServiceTier | undefined;
|
|
21
|
+
export {};
|
|
22
|
+
//# sourceMappingURL=fast-mode.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fast-mode.d.ts","sourceRoot":"","sources":["../../src/core/fast-mode.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEjE,MAAM,MAAM,YAAY,GAAG,cAAc,CAAC;AAE1C,UAAU,gBAAgB;IACzB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC;IAC1D,kBAAkB,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;CAC7D;AAED,MAAM,WAAW,eAAe;IAC/B,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,GAAG,SAAS,CAAC;IACvC,QAAQ,CAAC,eAAe,EAAE,gBAAgB,CAAC;CAC3C;AAED,MAAM,WAAW,cAAc;IAC9B,SAAS,EAAE,OAAO,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,YAAY,CAAC;CACpB;AAMD,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,eAAe,GAAG,cAAc,CAU1E;AAED,wBAAgB,WAAW,CAAC,OAAO,EAAE,eAAe,EAAE,OAAO,EAAE,OAAO,GAAG,cAAc,CAatF;AAED,wBAAgB,cAAc,CAAC,OAAO,EAAE,eAAe,GAAG,cAAc,CAGvE;AAED,wBAAgB,0BAA0B,CACzC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,EACjB,UAAU,EAAE,OAAO,GAAG,SAAS,GAC7B,WAAW,GAAG,SAAS,CAGzB"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
function supportsFastMode(model) {
|
|
2
|
+
return model?.provider === "openai-codex" || (model?.provider === "xai" && model.api === "openai-responses");
|
|
3
|
+
}
|
|
4
|
+
export function getFastModeStatus(session) {
|
|
5
|
+
if (!supportsFastMode(session.model) || !session.model) {
|
|
6
|
+
return { available: false, changed: false, enabled: false };
|
|
7
|
+
}
|
|
8
|
+
return {
|
|
9
|
+
available: true,
|
|
10
|
+
changed: false,
|
|
11
|
+
enabled: session.settingsManager.getFastModeEnabled(session.model.provider) ?? false,
|
|
12
|
+
kind: "service-tier",
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
export function setFastMode(session, enabled) {
|
|
16
|
+
if (!supportsFastMode(session.model) || !session.model) {
|
|
17
|
+
return { available: false, changed: false, enabled: false };
|
|
18
|
+
}
|
|
19
|
+
const previousPreference = session.settingsManager.getFastModeEnabled(session.model.provider);
|
|
20
|
+
session.settingsManager.setFastModeEnabled(session.model.provider, enabled);
|
|
21
|
+
return {
|
|
22
|
+
available: true,
|
|
23
|
+
changed: previousPreference !== enabled,
|
|
24
|
+
enabled,
|
|
25
|
+
kind: "service-tier",
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
export function toggleFastMode(session) {
|
|
29
|
+
const status = getFastModeStatus(session);
|
|
30
|
+
return status.available ? setFastMode(session, !status.enabled) : status;
|
|
31
|
+
}
|
|
32
|
+
export function resolveFastModeServiceTier(model, preference) {
|
|
33
|
+
if (!supportsFastMode(model) || preference === undefined)
|
|
34
|
+
return undefined;
|
|
35
|
+
return preference ? "priority" : "default";
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=fast-mode.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fast-mode.js","sourceRoot":"","sources":["../../src/core/fast-mode.ts"],"names":[],"mappings":"AAqBA,SAAS,gBAAgB,CAAC,KAA6B;IACtD,OAAO,KAAK,EAAE,QAAQ,KAAK,cAAc,IAAI,CAAC,KAAK,EAAE,QAAQ,KAAK,KAAK,IAAI,KAAK,CAAC,GAAG,KAAK,kBAAkB,CAAC,CAAC;AAC9G,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,OAAwB;IACzD,IAAI,CAAC,gBAAgB,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;QACxD,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;IAC7D,CAAC;IACD,OAAO;QACN,SAAS,EAAE,IAAI;QACf,OAAO,EAAE,KAAK;QACd,OAAO,EAAE,OAAO,CAAC,eAAe,CAAC,kBAAkB,CAAC,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,KAAK;QACpF,IAAI,EAAE,cAAc;KACpB,CAAC;AACH,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,OAAwB,EAAE,OAAgB;IACrE,IAAI,CAAC,gBAAgB,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;QACxD,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;IAC7D,CAAC;IAED,MAAM,kBAAkB,GAAG,OAAO,CAAC,eAAe,CAAC,kBAAkB,CAAC,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IAC9F,OAAO,CAAC,eAAe,CAAC,kBAAkB,CAAC,OAAO,CAAC,KAAK,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAC5E,OAAO;QACN,SAAS,EAAE,IAAI;QACf,OAAO,EAAE,kBAAkB,KAAK,OAAO;QACvC,OAAO;QACP,IAAI,EAAE,cAAc;KACpB,CAAC;AACH,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,OAAwB;IACtD,MAAM,MAAM,GAAG,iBAAiB,CAAC,OAAO,CAAC,CAAC;IAC1C,OAAO,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,OAAO,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;AAC1E,CAAC;AAED,MAAM,UAAU,0BAA0B,CACzC,KAAiB,EACjB,UAA+B;IAE/B,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC,IAAI,UAAU,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IAC3E,OAAO,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS,CAAC;AAC5C,CAAC","sourcesContent":["import type { Api, Model, ServiceTier } from \"@caupulican/pi-ai\";\n\nexport type FastModeKind = \"service-tier\";\n\ninterface FastModeSettings {\n\tgetFastModeEnabled(provider: string): boolean | undefined;\n\tsetFastModeEnabled(provider: string, enabled: boolean): void;\n}\n\nexport interface FastModeSession {\n\treadonly model: Model<Api> | undefined;\n\treadonly settingsManager: FastModeSettings;\n}\n\nexport interface FastModeStatus {\n\tavailable: boolean;\n\tchanged: boolean;\n\tenabled: boolean;\n\tkind?: FastModeKind;\n}\n\nfunction supportsFastMode(model: Model<Api> | undefined): boolean {\n\treturn model?.provider === \"openai-codex\" || (model?.provider === \"xai\" && model.api === \"openai-responses\");\n}\n\nexport function getFastModeStatus(session: FastModeSession): FastModeStatus {\n\tif (!supportsFastMode(session.model) || !session.model) {\n\t\treturn { available: false, changed: false, enabled: false };\n\t}\n\treturn {\n\t\tavailable: true,\n\t\tchanged: false,\n\t\tenabled: session.settingsManager.getFastModeEnabled(session.model.provider) ?? false,\n\t\tkind: \"service-tier\",\n\t};\n}\n\nexport function setFastMode(session: FastModeSession, enabled: boolean): FastModeStatus {\n\tif (!supportsFastMode(session.model) || !session.model) {\n\t\treturn { available: false, changed: false, enabled: false };\n\t}\n\n\tconst previousPreference = session.settingsManager.getFastModeEnabled(session.model.provider);\n\tsession.settingsManager.setFastModeEnabled(session.model.provider, enabled);\n\treturn {\n\t\tavailable: true,\n\t\tchanged: previousPreference !== enabled,\n\t\tenabled,\n\t\tkind: \"service-tier\",\n\t};\n}\n\nexport function toggleFastMode(session: FastModeSession): FastModeStatus {\n\tconst status = getFastModeStatus(session);\n\treturn status.available ? setFastMode(session, !status.enabled) : status;\n}\n\nexport function resolveFastModeServiceTier(\n\tmodel: Model<Api>,\n\tpreference: boolean | undefined,\n): ServiceTier | undefined {\n\tif (!supportsFastMode(model) || preference === undefined) return undefined;\n\treturn preference ? \"priority\" : \"default\";\n}\n"]}
|
|
@@ -18,7 +18,7 @@ export interface GoalLoopControllerDeps {
|
|
|
18
18
|
/** Read the current goal runtime snapshot (continuation decision + goal state) fresh each pass. */
|
|
19
19
|
getGoalRuntimeSnapshot(settings: GoalRuntimeSnapshotSettings): GoalRuntimeSnapshot;
|
|
20
20
|
/** Submit a continuation prompt through the session's own prompt path. */
|
|
21
|
-
prompt(text: string, options?: PromptOptions): Promise<
|
|
21
|
+
prompt(text: string, options?: PromptOptions): Promise<"completed" | "interrupted">;
|
|
22
22
|
/**
|
|
23
23
|
* Persist one submitted pass's turn and active-wall-clock contribution. Provider usage is charged
|
|
24
24
|
* at each assistant response before another request can be admitted. Called once per
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"goal-loop-controller.d.ts","sourceRoot":"","sources":["../../src/core/goal-loop-controller.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAGH,OAAO,KAAK,EACX,2BAA2B,EAC3B,0BAA0B,EAE1B,2BAA2B,EAC3B,0BAA0B,EAC1B,aAAa,EACb,MAAM,8BAA8B,CAAC;AAMtC,OAAO,KAAK,EAAE,mBAAmB,EAAE,2BAA2B,EAAE,MAAM,kCAAkC,CAAC;AA4BzG,MAAM,WAAW,sBAAsB;IACtC,mGAAmG;IACnG,sBAAsB,CAAC,QAAQ,EAAE,2BAA2B,GAAG,mBAAmB,CAAC;IACnF,0EAA0E;IAC1E,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,
|
|
1
|
+
{"version":3,"file":"goal-loop-controller.d.ts","sourceRoot":"","sources":["../../src/core/goal-loop-controller.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAGH,OAAO,KAAK,EACX,2BAA2B,EAC3B,0BAA0B,EAE1B,2BAA2B,EAC3B,0BAA0B,EAC1B,aAAa,EACb,MAAM,8BAA8B,CAAC;AAMtC,OAAO,KAAK,EAAE,mBAAmB,EAAE,2BAA2B,EAAE,MAAM,kCAAkC,CAAC;AA4BzG,MAAM,WAAW,sBAAsB;IACtC,mGAAmG;IACnG,sBAAsB,CAAC,QAAQ,EAAE,2BAA2B,GAAG,mBAAmB,CAAC;IACnF,0EAA0E;IAC1E,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,WAAW,GAAG,aAAa,CAAC,CAAC;IACpF;;;;OAIG;IACH,0BAA0B,CAAC,IAAI,EAAE;QAChC,KAAK,EAAE,MAAM,CAAC;QACd,WAAW,EAAE,MAAM,CAAC;QACpB,MAAM,EAAE,MAAM,CAAC;QACf,gBAAgB,EAAE,MAAM,CAAC;QACzB,UAAU,EAAE,MAAM,CAAC;KACnB,GAAG,IAAI,CAAC;IACT,uFAAuF;IACvF,6BAA6B,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAAC;IACpD,gFAAgF;IAChF,qBAAqB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5C;AAED,qBAAa,kBAAkB;IAC9B,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAyB;IAE9C,YAAY,IAAI,EAAE,sBAAsB,EAEvC;IAEK,gBAAgB,CAAC,OAAO,EAAE,2BAA2B,GAAG,OAAO,CAAC,0BAA0B,CAAC,CAiBhG;IAEK,gBAAgB,CAAC,OAAO,EAAE,2BAA2B,GAAG,OAAO,CAAC,0BAA0B,CAAC,CA4FhG;CACD"}
|
|
@@ -50,14 +50,14 @@ export class GoalLoopController {
|
|
|
50
50
|
return { submitted: false, snapshot };
|
|
51
51
|
}
|
|
52
52
|
const prompt = buildGoalContinuationPrompt();
|
|
53
|
-
await this.deps.prompt(prompt.text, {
|
|
53
|
+
const turnOutcome = await this.deps.prompt(prompt.text, {
|
|
54
54
|
expandPromptTemplates: false,
|
|
55
55
|
processSlashCommands: false,
|
|
56
56
|
autoContinueGoal: false,
|
|
57
57
|
internalContextType: GOAL_CONTINUATION_TRIGGER_CUSTOM_TYPE,
|
|
58
58
|
goalExecutionId: snapshot.goalState?.goalId,
|
|
59
59
|
});
|
|
60
|
-
return { submitted: true, snapshot, prompt };
|
|
60
|
+
return { submitted: true, snapshot, prompt, turnOutcome };
|
|
61
61
|
}
|
|
62
62
|
async continueGoalLoop(options) {
|
|
63
63
|
if (!Number.isSafeInteger(options.maxTurns) || options.maxTurns < 0) {
|
|
@@ -121,9 +121,6 @@ export class GoalLoopController {
|
|
|
121
121
|
turnsSubmitted++;
|
|
122
122
|
this.deps.recordGoalContinuationPass({ ...passAccounting, wallClockMs: now() - passStartedAt });
|
|
123
123
|
}
|
|
124
|
-
if (hasReachedWallClockBudget()) {
|
|
125
|
-
return { turnsSubmitted, stopReason: "wall_clock_budget_reached", finalSnapshot: snapshot() };
|
|
126
|
-
}
|
|
127
124
|
let afterSnapshot = snapshot();
|
|
128
125
|
if (afterSnapshot.goalState?.status === "budget_limited") {
|
|
129
126
|
return { turnsSubmitted, stopReason: "goal_budget_exhausted", finalSnapshot: afterSnapshot };
|
|
@@ -137,6 +134,12 @@ export class GoalLoopController {
|
|
|
137
134
|
if (afterSnapshot.continuation.action !== "continue") {
|
|
138
135
|
return { turnsSubmitted, stopReason: nonContinueStopReason(afterSnapshot), finalSnapshot: afterSnapshot };
|
|
139
136
|
}
|
|
137
|
+
if (result.turnOutcome === "interrupted") {
|
|
138
|
+
return { turnsSubmitted, stopReason: "turn_interrupted", finalSnapshot: afterSnapshot };
|
|
139
|
+
}
|
|
140
|
+
if (hasReachedWallClockBudget()) {
|
|
141
|
+
return { turnsSubmitted, stopReason: "wall_clock_budget_reached", finalSnapshot: afterSnapshot };
|
|
142
|
+
}
|
|
140
143
|
}
|
|
141
144
|
return {
|
|
142
145
|
turnsSubmitted,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"goal-loop-controller.js","sourceRoot":"","sources":["../../src/core/goal-loop-controller.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Goal auto-continuation loop.\n *\n * Extracted verbatim from agent-session.ts (god-file decomposition). Drives the bounded \"keep the\n * active goal moving\" loop: each pass reads the goal runtime snapshot, and — only while the snapshot\n * says `continue` — submits one continuation prompt back through the session's own prompt path. It\n * owns no state; the goal state lives in the session log and is read fresh every pass. Termination is\n * gated only by real terminal conditions and limits the owner explicitly supplied: an optional\n * per-invocation turn cap, an optional per-invocation wall-clock cap, and an optional durable token\n * budget on the goal. Each submitted pass still reports turn/wall-clock telemetry; provider usage\n * and spend are attributed at the response boundary. The host compares each pass's authoritative\n * progress revision and records unchanged passes as stalls, so a model cannot bypass the stall\n * limit by omitting a voluntary `no_progress` call.\n */\n\nimport { AgentBusyError } from \"@caupulican/pi-agent-core/agent\";\nimport type {\n\tGoalContinuationLoopOptions,\n\tGoalContinuationLoopResult,\n\tGoalContinuationLoopStopReason,\n\tGoalContinuationOnceOptions,\n\tGoalContinuationOnceResult,\n\tPromptOptions,\n} from \"./agent-session-contracts.ts\";\nimport {\n\tbuildGoalContinuationPrompt,\n\tGOAL_CONTINUATION_TRIGGER_CUSTOM_TYPE,\n} from \"./goals/goal-continuation-prompt.ts\";\nimport { GoalBudgetExhaustedError } from \"./goals/goal-execution-errors.ts\";\nimport type { GoalRuntimeSnapshot, GoalRuntimeSnapshotSettings } from \"./goals/goal-runtime-snapshot.ts\";\nimport { type GoalState, isGoalExecutionActive } from \"./goals/goal-state.ts\";\n\n/**\n * Resolve an owner-supplied durable goal budget. Wall-clock and spend counters are deliberately\n * absent here: they are telemetry unless the public goal contract grows matching explicit limits.\n * Execution limits are policy inputs, not hidden runtime defaults.\n */\nfunction getExplicitGoalBudgetExhaustion(state: GoalState | undefined): string | undefined {\n\tif (!state || !isGoalExecutionActive(state.status)) return undefined;\n\tif (state.tokenBudget !== undefined && (state.tokensUsed ?? 0) >= state.tokenBudget) {\n\t\treturn `token budget exhausted (${state.tokensUsed ?? 0}/${state.tokenBudget})`;\n\t}\n\treturn undefined;\n}\n\n/**\n * Maps a non-\"continue\" continuation action onto the loop's own stopReason vocabulary.\n * `\"waiting\"` (a worker is dispatched against an open requirement) gets its OWN benign stopReason so\n * a wait is never misreported as `continuation_not_allowed` (which reads as a terminal refusal) —\n * callers/telemetry can tell \"paused, will resume on its own\" apart from \"stopped, needs a human or a\n * new decision.\" Every other non-continue action (ask-user/finalize/stop) keeps the existing\n * `continuation_not_allowed` stopReason unchanged.\n */\nfunction nonContinueStopReason(snapshot: GoalRuntimeSnapshot): GoalContinuationLoopStopReason {\n\treturn snapshot.continuation.action === \"waiting\" ? \"worker_in_flight\" : \"continuation_not_allowed\";\n}\n\nexport interface GoalLoopControllerDeps {\n\t/** Read the current goal runtime snapshot (continuation decision + goal state) fresh each pass. */\n\tgetGoalRuntimeSnapshot(settings: GoalRuntimeSnapshotSettings): GoalRuntimeSnapshot;\n\t/** Submit a continuation prompt through the session's own prompt path. */\n\tprompt(text: string, options?: PromptOptions): Promise<void>;\n\t/**\n\t * Persist one submitted pass's turn and active-wall-clock contribution. Provider usage is charged\n\t * at each assistant response before another request can be admitted. Called once per\n\t * pass actually SUBMITTED (never for a no-op `continueGoalOnce` call).\n\t */\n\trecordGoalContinuationPass(pass: {\n\t\tturns: number;\n\t\twallClockMs: number;\n\t\tgoalId: string;\n\t\tprogressRevision: number;\n\t\tstallTurns: number;\n\t}): void;\n\t/** Persist an exhausted/non-retryable continuation failure as a stopped goal state. */\n\trecordGoalContinuationFailure(error: unknown): void;\n\t/** Persist a reason-specific budget terminal state before returning control. */\n\tmarkGoalBudgetLimited(reason: string): void;\n}\n\nexport class GoalLoopController {\n\tprivate readonly deps: GoalLoopControllerDeps;\n\n\tconstructor(deps: GoalLoopControllerDeps) {\n\t\tthis.deps = deps;\n\t}\n\n\tasync continueGoalOnce(options: GoalContinuationOnceOptions): Promise<GoalContinuationOnceResult> {\n\t\tconst snapshot = this.deps.getGoalRuntimeSnapshot({ maxStallTurns: options.maxStallTurns });\n\n\t\tif (snapshot.continuation.action !== \"continue\") {\n\t\t\treturn { submitted: false, snapshot };\n\t\t}\n\n\t\tconst prompt = buildGoalContinuationPrompt();\n\t\tawait this.deps.prompt(prompt.text, {\n\t\t\texpandPromptTemplates: false,\n\t\t\tprocessSlashCommands: false,\n\t\t\tautoContinueGoal: false,\n\t\t\tinternalContextType: GOAL_CONTINUATION_TRIGGER_CUSTOM_TYPE,\n\t\t\tgoalExecutionId: snapshot.goalState?.goalId,\n\t\t});\n\n\t\treturn { submitted: true, snapshot, prompt };\n\t}\n\n\tasync continueGoalLoop(options: GoalContinuationLoopOptions): Promise<GoalContinuationLoopResult> {\n\t\tif (!Number.isSafeInteger(options.maxTurns) || options.maxTurns < 0) {\n\t\t\tthrow new Error(\"Goal continuation maxTurns must be a non-negative safe integer; 0 means unbounded.\");\n\t\t}\n\t\tlet turnsSubmitted = 0;\n\t\tconst hasExplicitTurnLimit = options.maxTurns > 0;\n\t\tconst now = options.now ?? Date.now;\n\t\tconst maxWallClockMs =\n\t\t\ttypeof options.maxWallClockMinutes === \"number\" && options.maxWallClockMinutes > 0\n\t\t\t\t? options.maxWallClockMinutes * 60_000\n\t\t\t\t: undefined;\n\t\tconst startedAt = now();\n\t\tconst hasReachedWallClockBudget = () => maxWallClockMs !== undefined && now() - startedAt >= maxWallClockMs;\n\t\tconst snapshot = () => this.deps.getGoalRuntimeSnapshot({ maxStallTurns: options.maxStallTurns });\n\n\t\tif (hasReachedWallClockBudget()) {\n\t\t\treturn { turnsSubmitted, stopReason: \"wall_clock_budget_reached\", finalSnapshot: snapshot() };\n\t\t}\n\n\t\twhile (!hasExplicitTurnLimit || turnsSubmitted < options.maxTurns) {\n\t\t\tconst beforeSnapshot = snapshot();\n\t\t\tif (beforeSnapshot.continuation.action !== \"continue\") {\n\t\t\t\treturn { turnsSubmitted, stopReason: nonContinueStopReason(beforeSnapshot), finalSnapshot: beforeSnapshot };\n\t\t\t}\n\n\t\t\t// Owner-supplied durable token budget — read fresh every pass so an invocation stops as\n\t\t\t// soon as its own latest persisted usage crosses the explicit ceiling.\n\t\t\tconst beforeBudgetExhaustion = getExplicitGoalBudgetExhaustion(beforeSnapshot.goalState);\n\t\t\tif (beforeBudgetExhaustion) {\n\t\t\t\tthis.deps.markGoalBudgetLimited(beforeBudgetExhaustion);\n\t\t\t\treturn { turnsSubmitted, stopReason: \"goal_budget_exhausted\", finalSnapshot: snapshot() };\n\t\t\t}\n\n\t\t\tconst passStartedAt = now();\n\t\t\tconst beforeGoal = beforeSnapshot.goalState;\n\t\t\tif (!beforeGoal) {\n\t\t\t\treturn { turnsSubmitted, stopReason: \"continuation_not_allowed\", finalSnapshot: beforeSnapshot };\n\t\t\t}\n\t\t\tconst passAccounting = {\n\t\t\t\tturns: 1,\n\t\t\t\tgoalId: beforeGoal.goalId,\n\t\t\t\tprogressRevision: beforeGoal.progressRevision ?? 0,\n\t\t\t\tstallTurns: beforeGoal.stallTurns,\n\t\t\t};\n\t\t\tlet result: GoalContinuationOnceResult;\n\t\t\ttry {\n\t\t\t\tresult = await this.continueGoalOnce(options);\n\t\t\t} catch (error) {\n\t\t\t\t// Prompt admission did not happen. A concurrent foreground owner is transient session\n\t\t\t\t// coordination, not a consumed goal turn and not evidence that the goal is blocked.\n\t\t\t\tif (error instanceof AgentBusyError) throw error;\n\t\t\t\tif (error instanceof GoalBudgetExhaustedError) {\n\t\t\t\t\t// The goal already stopped itself durably (markBudgetLimited ran synchronously before\n\t\t\t\t\t// this signal was thrown) — surface the existing clean stop instead of charging a turn.\n\t\t\t\t\treturn { turnsSubmitted, stopReason: \"goal_budget_exhausted\", finalSnapshot: snapshot() };\n\t\t\t\t}\n\t\t\t\tturnsSubmitted++;\n\t\t\t\tthis.deps.recordGoalContinuationPass({ ...passAccounting, wallClockMs: now() - passStartedAt });\n\t\t\t\tthis.deps.recordGoalContinuationFailure(error);\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t\tif (result.submitted) {\n\t\t\t\tturnsSubmitted++;\n\t\t\t\tthis.deps.recordGoalContinuationPass({ ...passAccounting, wallClockMs: now() - passStartedAt });\n\t\t\t}\n\n\t\t\tif (hasReachedWallClockBudget()) {\n\t\t\t\treturn { turnsSubmitted, stopReason: \"wall_clock_budget_reached\", finalSnapshot: snapshot() };\n\t\t\t}\n\n\t\t\tlet afterSnapshot = snapshot();\n\t\t\tif (afterSnapshot.goalState?.status === \"budget_limited\") {\n\t\t\t\treturn { turnsSubmitted, stopReason: \"goal_budget_exhausted\", finalSnapshot: afterSnapshot };\n\t\t\t}\n\t\t\tconst afterBudgetExhaustion = getExplicitGoalBudgetExhaustion(afterSnapshot.goalState);\n\t\t\tif (afterBudgetExhaustion) {\n\t\t\t\tthis.deps.markGoalBudgetLimited(afterBudgetExhaustion);\n\t\t\t\tafterSnapshot = snapshot();\n\t\t\t\treturn { turnsSubmitted, stopReason: \"goal_budget_exhausted\", finalSnapshot: afterSnapshot };\n\t\t\t}\n\t\t\tif (afterSnapshot.continuation.action !== \"continue\") {\n\t\t\t\treturn { turnsSubmitted, stopReason: nonContinueStopReason(afterSnapshot), finalSnapshot: afterSnapshot };\n\t\t\t}\n\t\t}\n\n\t\treturn {\n\t\t\tturnsSubmitted,\n\t\t\tstopReason: \"max_turns_reached\",\n\t\t\tfinalSnapshot: snapshot(),\n\t\t};\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"goal-loop-controller.js","sourceRoot":"","sources":["../../src/core/goal-loop-controller.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Goal auto-continuation loop.\n *\n * Extracted verbatim from agent-session.ts (god-file decomposition). Drives the bounded \"keep the\n * active goal moving\" loop: each pass reads the goal runtime snapshot, and — only while the snapshot\n * says `continue` — submits one continuation prompt back through the session's own prompt path. It\n * owns no state; the goal state lives in the session log and is read fresh every pass. Termination is\n * gated only by real terminal conditions and limits the owner explicitly supplied: an optional\n * per-invocation turn cap, an optional per-invocation wall-clock cap, and an optional durable token\n * budget on the goal. Each submitted pass still reports turn/wall-clock telemetry; provider usage\n * and spend are attributed at the response boundary. The host compares each pass's authoritative\n * progress revision and records unchanged passes as stalls, so a model cannot bypass the stall\n * limit by omitting a voluntary `no_progress` call.\n */\n\nimport { AgentBusyError } from \"@caupulican/pi-agent-core/agent\";\nimport type {\n\tGoalContinuationLoopOptions,\n\tGoalContinuationLoopResult,\n\tGoalContinuationLoopStopReason,\n\tGoalContinuationOnceOptions,\n\tGoalContinuationOnceResult,\n\tPromptOptions,\n} from \"./agent-session-contracts.ts\";\nimport {\n\tbuildGoalContinuationPrompt,\n\tGOAL_CONTINUATION_TRIGGER_CUSTOM_TYPE,\n} from \"./goals/goal-continuation-prompt.ts\";\nimport { GoalBudgetExhaustedError } from \"./goals/goal-execution-errors.ts\";\nimport type { GoalRuntimeSnapshot, GoalRuntimeSnapshotSettings } from \"./goals/goal-runtime-snapshot.ts\";\nimport { type GoalState, isGoalExecutionActive } from \"./goals/goal-state.ts\";\n\n/**\n * Resolve an owner-supplied durable goal budget. Wall-clock and spend counters are deliberately\n * absent here: they are telemetry unless the public goal contract grows matching explicit limits.\n * Execution limits are policy inputs, not hidden runtime defaults.\n */\nfunction getExplicitGoalBudgetExhaustion(state: GoalState | undefined): string | undefined {\n\tif (!state || !isGoalExecutionActive(state.status)) return undefined;\n\tif (state.tokenBudget !== undefined && (state.tokensUsed ?? 0) >= state.tokenBudget) {\n\t\treturn `token budget exhausted (${state.tokensUsed ?? 0}/${state.tokenBudget})`;\n\t}\n\treturn undefined;\n}\n\n/**\n * Maps a non-\"continue\" continuation action onto the loop's own stopReason vocabulary.\n * `\"waiting\"` (a worker is dispatched against an open requirement) gets its OWN benign stopReason so\n * a wait is never misreported as `continuation_not_allowed` (which reads as a terminal refusal) —\n * callers/telemetry can tell \"paused, will resume on its own\" apart from \"stopped, needs a human or a\n * new decision.\" Every other non-continue action (ask-user/finalize/stop) keeps the existing\n * `continuation_not_allowed` stopReason unchanged.\n */\nfunction nonContinueStopReason(snapshot: GoalRuntimeSnapshot): GoalContinuationLoopStopReason {\n\treturn snapshot.continuation.action === \"waiting\" ? \"worker_in_flight\" : \"continuation_not_allowed\";\n}\n\nexport interface GoalLoopControllerDeps {\n\t/** Read the current goal runtime snapshot (continuation decision + goal state) fresh each pass. */\n\tgetGoalRuntimeSnapshot(settings: GoalRuntimeSnapshotSettings): GoalRuntimeSnapshot;\n\t/** Submit a continuation prompt through the session's own prompt path. */\n\tprompt(text: string, options?: PromptOptions): Promise<\"completed\" | \"interrupted\">;\n\t/**\n\t * Persist one submitted pass's turn and active-wall-clock contribution. Provider usage is charged\n\t * at each assistant response before another request can be admitted. Called once per\n\t * pass actually SUBMITTED (never for a no-op `continueGoalOnce` call).\n\t */\n\trecordGoalContinuationPass(pass: {\n\t\tturns: number;\n\t\twallClockMs: number;\n\t\tgoalId: string;\n\t\tprogressRevision: number;\n\t\tstallTurns: number;\n\t}): void;\n\t/** Persist an exhausted/non-retryable continuation failure as a stopped goal state. */\n\trecordGoalContinuationFailure(error: unknown): void;\n\t/** Persist a reason-specific budget terminal state before returning control. */\n\tmarkGoalBudgetLimited(reason: string): void;\n}\n\nexport class GoalLoopController {\n\tprivate readonly deps: GoalLoopControllerDeps;\n\n\tconstructor(deps: GoalLoopControllerDeps) {\n\t\tthis.deps = deps;\n\t}\n\n\tasync continueGoalOnce(options: GoalContinuationOnceOptions): Promise<GoalContinuationOnceResult> {\n\t\tconst snapshot = this.deps.getGoalRuntimeSnapshot({ maxStallTurns: options.maxStallTurns });\n\n\t\tif (snapshot.continuation.action !== \"continue\") {\n\t\t\treturn { submitted: false, snapshot };\n\t\t}\n\n\t\tconst prompt = buildGoalContinuationPrompt();\n\t\tconst turnOutcome = await this.deps.prompt(prompt.text, {\n\t\t\texpandPromptTemplates: false,\n\t\t\tprocessSlashCommands: false,\n\t\t\tautoContinueGoal: false,\n\t\t\tinternalContextType: GOAL_CONTINUATION_TRIGGER_CUSTOM_TYPE,\n\t\t\tgoalExecutionId: snapshot.goalState?.goalId,\n\t\t});\n\n\t\treturn { submitted: true, snapshot, prompt, turnOutcome };\n\t}\n\n\tasync continueGoalLoop(options: GoalContinuationLoopOptions): Promise<GoalContinuationLoopResult> {\n\t\tif (!Number.isSafeInteger(options.maxTurns) || options.maxTurns < 0) {\n\t\t\tthrow new Error(\"Goal continuation maxTurns must be a non-negative safe integer; 0 means unbounded.\");\n\t\t}\n\t\tlet turnsSubmitted = 0;\n\t\tconst hasExplicitTurnLimit = options.maxTurns > 0;\n\t\tconst now = options.now ?? Date.now;\n\t\tconst maxWallClockMs =\n\t\t\ttypeof options.maxWallClockMinutes === \"number\" && options.maxWallClockMinutes > 0\n\t\t\t\t? options.maxWallClockMinutes * 60_000\n\t\t\t\t: undefined;\n\t\tconst startedAt = now();\n\t\tconst hasReachedWallClockBudget = () => maxWallClockMs !== undefined && now() - startedAt >= maxWallClockMs;\n\t\tconst snapshot = () => this.deps.getGoalRuntimeSnapshot({ maxStallTurns: options.maxStallTurns });\n\n\t\tif (hasReachedWallClockBudget()) {\n\t\t\treturn { turnsSubmitted, stopReason: \"wall_clock_budget_reached\", finalSnapshot: snapshot() };\n\t\t}\n\n\t\twhile (!hasExplicitTurnLimit || turnsSubmitted < options.maxTurns) {\n\t\t\tconst beforeSnapshot = snapshot();\n\t\t\tif (beforeSnapshot.continuation.action !== \"continue\") {\n\t\t\t\treturn { turnsSubmitted, stopReason: nonContinueStopReason(beforeSnapshot), finalSnapshot: beforeSnapshot };\n\t\t\t}\n\n\t\t\t// Owner-supplied durable token budget — read fresh every pass so an invocation stops as\n\t\t\t// soon as its own latest persisted usage crosses the explicit ceiling.\n\t\t\tconst beforeBudgetExhaustion = getExplicitGoalBudgetExhaustion(beforeSnapshot.goalState);\n\t\t\tif (beforeBudgetExhaustion) {\n\t\t\t\tthis.deps.markGoalBudgetLimited(beforeBudgetExhaustion);\n\t\t\t\treturn { turnsSubmitted, stopReason: \"goal_budget_exhausted\", finalSnapshot: snapshot() };\n\t\t\t}\n\n\t\t\tconst passStartedAt = now();\n\t\t\tconst beforeGoal = beforeSnapshot.goalState;\n\t\t\tif (!beforeGoal) {\n\t\t\t\treturn { turnsSubmitted, stopReason: \"continuation_not_allowed\", finalSnapshot: beforeSnapshot };\n\t\t\t}\n\t\t\tconst passAccounting = {\n\t\t\t\tturns: 1,\n\t\t\t\tgoalId: beforeGoal.goalId,\n\t\t\t\tprogressRevision: beforeGoal.progressRevision ?? 0,\n\t\t\t\tstallTurns: beforeGoal.stallTurns,\n\t\t\t};\n\t\t\tlet result: GoalContinuationOnceResult;\n\t\t\ttry {\n\t\t\t\tresult = await this.continueGoalOnce(options);\n\t\t\t} catch (error) {\n\t\t\t\t// Prompt admission did not happen. A concurrent foreground owner is transient session\n\t\t\t\t// coordination, not a consumed goal turn and not evidence that the goal is blocked.\n\t\t\t\tif (error instanceof AgentBusyError) throw error;\n\t\t\t\tif (error instanceof GoalBudgetExhaustedError) {\n\t\t\t\t\t// The goal already stopped itself durably (markBudgetLimited ran synchronously before\n\t\t\t\t\t// this signal was thrown) — surface the existing clean stop instead of charging a turn.\n\t\t\t\t\treturn { turnsSubmitted, stopReason: \"goal_budget_exhausted\", finalSnapshot: snapshot() };\n\t\t\t\t}\n\t\t\t\tturnsSubmitted++;\n\t\t\t\tthis.deps.recordGoalContinuationPass({ ...passAccounting, wallClockMs: now() - passStartedAt });\n\t\t\t\tthis.deps.recordGoalContinuationFailure(error);\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t\tif (result.submitted) {\n\t\t\t\tturnsSubmitted++;\n\t\t\t\tthis.deps.recordGoalContinuationPass({ ...passAccounting, wallClockMs: now() - passStartedAt });\n\t\t\t}\n\n\t\t\tlet afterSnapshot = snapshot();\n\t\t\tif (afterSnapshot.goalState?.status === \"budget_limited\") {\n\t\t\t\treturn { turnsSubmitted, stopReason: \"goal_budget_exhausted\", finalSnapshot: afterSnapshot };\n\t\t\t}\n\t\t\tconst afterBudgetExhaustion = getExplicitGoalBudgetExhaustion(afterSnapshot.goalState);\n\t\t\tif (afterBudgetExhaustion) {\n\t\t\t\tthis.deps.markGoalBudgetLimited(afterBudgetExhaustion);\n\t\t\t\tafterSnapshot = snapshot();\n\t\t\t\treturn { turnsSubmitted, stopReason: \"goal_budget_exhausted\", finalSnapshot: afterSnapshot };\n\t\t\t}\n\t\t\tif (afterSnapshot.continuation.action !== \"continue\") {\n\t\t\t\treturn { turnsSubmitted, stopReason: nonContinueStopReason(afterSnapshot), finalSnapshot: afterSnapshot };\n\t\t\t}\n\t\t\tif (result.turnOutcome === \"interrupted\") {\n\t\t\t\treturn { turnsSubmitted, stopReason: \"turn_interrupted\", finalSnapshot: afterSnapshot };\n\t\t\t}\n\t\t\tif (hasReachedWallClockBudget()) {\n\t\t\t\treturn { turnsSubmitted, stopReason: \"wall_clock_budget_reached\", finalSnapshot: afterSnapshot };\n\t\t\t}\n\t\t}\n\n\t\treturn {\n\t\t\tturnsSubmitted,\n\t\t\tstopReason: \"max_turns_reached\",\n\t\t\tfinalSnapshot: snapshot(),\n\t\t};\n\t}\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"goal-auto-continue-controller.d.ts","sourceRoot":"","sources":["../../../src/core/goals/goal-auto-continue-controller.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACX,iBAAiB,EACjB,2BAA2B,EAC3B,0BAA0B,EAC1B,aAAa,EACb,MAAM,qBAAqB,CAAC;AAC7B,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,KAAK,EAAE,mBAAmB,EAAE,2BAA2B,EAAE,MAAM,4BAA4B,CAAC;AAEnG,MAAM,WAAW,8BAA8B;IAC9C,UAAU,IAAI,OAAO,CAAC;IACtB,gBAAgB,IAAI,OAAO,CAAC;IAC5B,kBAAkB,IAAI,eAAe,CAAC;IACtC,sBAAsB,CAAC,QAAQ,EAAE,2BAA2B,GAAG,mBAAmB,CAAC;IACnF,sBAAsB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC;IAChD,gBAAgB,CAAC,OAAO,EAAE,2BAA2B,GAAG,OAAO,CAAC,0BAA0B,CAAC,CAAC;IAC5F,gBAAgB,IAAI,OAAO,CAAC;IAC5B,qBAAqB,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvC,uBAAuB,IAAI,IAAI,CAAC;IAChC,IAAI,CAAC,KAAK,EAAE,iBAAiB,GAAG,IAAI,CAAC;CACrC;AAED,mFAAmF;AACnF,qBAAa,0BAA0B;IACtC,OAAO,CAAC,MAAM,CAA4C;IAC1D,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAiC;IAEtD,YAAY,IAAI,EAAE,8BAA8B,EAE/C;IAED,UAAU,IAAI,IAAI,CAKjB;IAED,gBAAgB,CAAC,OAAO,CAAC,EAAE,aAAa,GAAG,IAAI,CAsB9C;IAEK,iBAAiB,CAAC,OAAO,EAAE,2BAA2B,GAAG,OAAO,CAAC,0BAA0B,CAAC,CAqBjG;IAED,OAAO,CAAC,iBAAiB;YAOX,YAAY;
|
|
1
|
+
{"version":3,"file":"goal-auto-continue-controller.d.ts","sourceRoot":"","sources":["../../../src/core/goals/goal-auto-continue-controller.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACX,iBAAiB,EACjB,2BAA2B,EAC3B,0BAA0B,EAC1B,aAAa,EACb,MAAM,qBAAqB,CAAC;AAC7B,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,KAAK,EAAE,mBAAmB,EAAE,2BAA2B,EAAE,MAAM,4BAA4B,CAAC;AAEnG,MAAM,WAAW,8BAA8B;IAC9C,UAAU,IAAI,OAAO,CAAC;IACtB,gBAAgB,IAAI,OAAO,CAAC;IAC5B,kBAAkB,IAAI,eAAe,CAAC;IACtC,sBAAsB,CAAC,QAAQ,EAAE,2BAA2B,GAAG,mBAAmB,CAAC;IACnF,sBAAsB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC;IAChD,gBAAgB,CAAC,OAAO,EAAE,2BAA2B,GAAG,OAAO,CAAC,0BAA0B,CAAC,CAAC;IAC5F,gBAAgB,IAAI,OAAO,CAAC;IAC5B,qBAAqB,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvC,uBAAuB,IAAI,IAAI,CAAC;IAChC,IAAI,CAAC,KAAK,EAAE,iBAAiB,GAAG,IAAI,CAAC;CACrC;AAED,mFAAmF;AACnF,qBAAa,0BAA0B;IACtC,OAAO,CAAC,MAAM,CAA4C;IAC1D,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAiC;IAEtD,YAAY,IAAI,EAAE,8BAA8B,EAE/C;IAED,UAAU,IAAI,IAAI,CAKjB;IAED,gBAAgB,CAAC,OAAO,CAAC,EAAE,aAAa,GAAG,IAAI,CAsB9C;IAEK,iBAAiB,CAAC,OAAO,EAAE,2BAA2B,GAAG,OAAO,CAAC,0BAA0B,CAAC,CAqBjG;IAED,OAAO,CAAC,iBAAiB;YAOX,YAAY;IA2B1B,OAAO,CAAC,aAAa;CAUrB"}
|
|
@@ -85,11 +85,13 @@ export class GoalAutoContinueController {
|
|
|
85
85
|
if (snapshot.continuation.action !== "continue")
|
|
86
86
|
return;
|
|
87
87
|
try {
|
|
88
|
-
await this.continueExclusive({
|
|
88
|
+
const result = await this.continueExclusive({
|
|
89
89
|
maxTurns: goalContinueTurns,
|
|
90
90
|
maxStallTurns,
|
|
91
91
|
maxWallClockMinutes: goalContinueMaxWallClockMinutes,
|
|
92
92
|
});
|
|
93
|
+
if (result.stopReason === "turn_interrupted")
|
|
94
|
+
return;
|
|
93
95
|
if (!this.deps.isDisposed()) {
|
|
94
96
|
const nextSnapshot = this.deps.getGoalRuntimeSnapshot({ maxStallTurns });
|
|
95
97
|
if (nextSnapshot.continuation.action === "continue") {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"goal-auto-continue-controller.js","sourceRoot":"","sources":["../../../src/core/goals/goal-auto-continue-controller.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AAuBjE,mFAAmF;AACnF,MAAM,OAAO,0BAA0B;IAKtC,YAAY,IAAoC;QAHxC,kBAAa,GAAG,KAAK,CAAC;QAI7B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IAClB,CAAC;IAED,UAAU;QACT,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YAC/B,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YAC1B,IAAI,CAAC,MAAM,GAAG,SAAS,CAAC;QACzB,CAAC;IACF,CAAC;IAED,gBAAgB,CAAC,OAAuB;QACvC,IAAI,OAAO,EAAE,gBAAgB,KAAK,KAAK,IAAI,IAAI,CAAC,aAAa,IAAI,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE;YAAE,OAAO;QAEhG,MAAM,EAAE,aAAa,EAAE,gBAAgB,EAAE,uBAAuB,EAAE,GAAG,IAAI,CAAC,IAAI;aAC5E,kBAAkB,EAAE;aACpB,mBAAmB,EAAE,CAAC;QACxB,IAAI,CAAC,gBAAgB;YAAE,OAAO;QAC9B,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,sBAAsB,CAAC,EAAE,aAAa,EAAE,CAAC,CAAC;QACrE,IAAI,QAAQ,CAAC,YAAY,CAAC,MAAM,KAAK,UAAU;YAAE,OAAO;QACxD,MAAM,YAAY,GAAG,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;QAChD,IAAI,YAAY,KAAK,SAAS,IAAI,IAAI,CAAC,IAAI,CAAC,sBAAsB,CAAC,YAAY,CAAC;YAAE,OAAO;QAEzF,IAAI,CAAC,UAAU,EAAE,CAAC;QAClB,IAAI,CAAC,MAAM,GAAG,UAAU,CAAC,GAAG,EAAE;YAC7B,IAAI,CAAC,MAAM,GAAG,SAAS,CAAC;YACxB,KAAK,IAAI,CAAC,YAAY,EAAE,CAAC;QAC1B,CAAC,EAAE,uBAAuB,CAAC,CAAC;QAC5B,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC;QAC1B,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,IAAI,OAAO,IAAI,KAAK,EAAE,CAAC;YAC5D,MAAM,EAAE,KAAK,EAAE,GAAG,KAA+B,CAAC;YAClD,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;QACpB,CAAC;IACF,CAAC;IAED,KAAK,CAAC,iBAAiB,CAAC,OAAoC;QAC3D,IAAI,IAAI,CAAC,aAAa;YAAE,OAAO,IAAI,CAAC,aAAa,CAAC,OAAO,EAAE,oBAAoB,CAAC,CAAC;QACjF,MAAM,YAAY,GAAG,IAAI,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC;QACrD,IAAI,YAAY;YAAE,OAAO,YAAY,CAAC;QACtC,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC;QAC1B,IAAI,CAAC;YACJ,OAAO,IAAI,EAAE,CAAC;gBACb,IAAI,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE;oBAAE,MAAM,IAAI,CAAC,IAAI,CAAC,qBAAqB,EAAE,CAAC;gBAC1E,MAAM,aAAa,GAAG,IAAI,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC;gBACtD,IAAI,aAAa;oBAAE,OAAO,aAAa,CAAC;gBACxC,IAAI,CAAC;oBACJ,OAAO,MAAM,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC;gBAClD,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBAChB,qFAAqF;oBACrF,sFAAsF;oBACtF,IAAI,CAAC,CAAC,KAAK,YAAY,cAAc,CAAC;wBAAE,MAAM,KAAK,CAAC;gBACrD,CAAC;YACF,CAAC;QACF,CAAC;gBAAS,CAAC;YACV,IAAI,CAAC,aAAa,GAAG,KAAK,CAAC;QAC5B,CAAC;IACF,CAAC;IAEO,iBAAiB,CAAC,OAAoC;QAC7D,IAAI,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE;YAAE,OAAO,IAAI,CAAC,aAAa,CAAC,OAAO,EAAE,kBAAkB,CAAC,CAAC;QACnF,IAAI,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE;YAAE,OAAO,SAAS,CAAC;QACnD,IAAI,CAAC,IAAI,CAAC,uBAAuB,EAAE,CAAC;QACpC,OAAO,IAAI,CAAC,aAAa,CAAC,OAAO,EAAE,uBAAuB,CAAC,CAAC;IAC7D,CAAC;IAEO,KAAK,CAAC,YAAY;QACzB,IAAI,IAAI,CAAC,aAAa,IAAI,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE;YAAE,OAAO;QACzD,MAAM,EAAE,aAAa,EAAE,iBAAiB,EAAE,+BAA+B,EAAE,gBAAgB,EAAE,GAAG,IAAI,CAAC,IAAI;aACvG,kBAAkB,EAAE;aACpB,mBAAmB,EAAE,CAAC;QACxB,IAAI,CAAC,gBAAgB;YAAE,OAAO;QAC9B,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,sBAAsB,CAAC,EAAE,aAAa,EAAE,CAAC,CAAC;QACrE,IAAI,QAAQ,CAAC,YAAY,CAAC,MAAM,KAAK,UAAU;YAAE,OAAO;QACxD,IAAI,CAAC;YACJ,MAAM,IAAI,CAAC,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"goal-auto-continue-controller.js","sourceRoot":"","sources":["../../../src/core/goals/goal-auto-continue-controller.ts"],"names":[],"mappings":"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","sourcesContent":["import { AgentBusyError } from \"@caupulican/pi-agent-core/agent\";\nimport type {\n\tAgentSessionEvent,\n\tGoalContinuationLoopOptions,\n\tGoalContinuationLoopResult,\n\tPromptOptions,\n} from \"../agent-session.ts\";\nimport type { SettingsManager } from \"../settings-manager.ts\";\nimport type { GoalRuntimeSnapshot, GoalRuntimeSnapshotSettings } from \"./goal-runtime-snapshot.ts\";\n\nexport interface GoalAutoContinueControllerDeps {\n\tisDisposed(): boolean;\n\tisGoalToolActive(): boolean;\n\tgetSettingsManager(): SettingsManager;\n\tgetGoalRuntimeSnapshot(settings: GoalRuntimeSnapshotSettings): GoalRuntimeSnapshot;\n\thasInFlightLaneForGoal(goalId: string): boolean;\n\tcontinueGoalLoop(options: GoalContinuationLoopOptions): Promise<GoalContinuationLoopResult>;\n\tisForegroundBusy(): boolean;\n\twaitForForegroundIdle(): Promise<void>;\n\tmarkGoalToolUnavailable(): void;\n\temit(event: AgentSessionEvent): void;\n}\n\n/** Owns the single-flight goal continuation loop and its foreground-idle timer. */\nexport class GoalAutoContinueController {\n\tprivate _timer: ReturnType<typeof setTimeout> | undefined;\n\tprivate _isContinuing = false;\n\tprivate readonly deps: GoalAutoContinueControllerDeps;\n\n\tconstructor(deps: GoalAutoContinueControllerDeps) {\n\t\tthis.deps = deps;\n\t}\n\n\tclearTimer(): void {\n\t\tif (this._timer !== undefined) {\n\t\t\tclearTimeout(this._timer);\n\t\t\tthis._timer = undefined;\n\t\t}\n\t}\n\n\tscheduleFromIdle(options?: PromptOptions): void {\n\t\tif (options?.autoContinueGoal === false || this._isContinuing || this.deps.isDisposed()) return;\n\n\t\tconst { maxStallTurns, goalAutoContinue, goalAutoContinueDelayMs } = this.deps\n\t\t\t.getSettingsManager()\n\t\t\t.getAutonomySettings();\n\t\tif (!goalAutoContinue) return;\n\t\tconst snapshot = this.deps.getGoalRuntimeSnapshot({ maxStallTurns });\n\t\tif (snapshot.continuation.action !== \"continue\") return;\n\t\tconst activeGoalId = snapshot.goalState?.goalId;\n\t\tif (activeGoalId !== undefined && this.deps.hasInFlightLaneForGoal(activeGoalId)) return;\n\n\t\tthis.clearTimer();\n\t\tthis._timer = setTimeout(() => {\n\t\t\tthis._timer = undefined;\n\t\t\tvoid this.runScheduled();\n\t\t}, goalAutoContinueDelayMs);\n\t\tconst timer = this._timer;\n\t\tif (typeof timer === \"object\" && timer && \"unref\" in timer) {\n\t\t\tconst { unref } = timer as { unref?: () => void };\n\t\t\tunref?.call(timer);\n\t\t}\n\t}\n\n\tasync continueExclusive(options: GoalContinuationLoopOptions): Promise<GoalContinuationLoopResult> {\n\t\tif (this._isContinuing) return this.skippedResult(options, \"already_continuing\");\n\t\tconst initialGuard = this.unavailableResult(options);\n\t\tif (initialGuard) return initialGuard;\n\t\tthis._isContinuing = true;\n\t\ttry {\n\t\t\twhile (true) {\n\t\t\t\tif (this.deps.isForegroundBusy()) await this.deps.waitForForegroundIdle();\n\t\t\t\tconst postWaitGuard = this.unavailableResult(options);\n\t\t\t\tif (postWaitGuard) return postWaitGuard;\n\t\t\t\ttry {\n\t\t\t\t\treturn await this.deps.continueGoalLoop(options);\n\t\t\t\t} catch (error) {\n\t\t\t\t\t// A different foreground owner can acquire the Agent after the idle event but before\n\t\t\t\t\t// prompt admission. Wait for that exact run and retry without terminalizing the goal.\n\t\t\t\t\tif (!(error instanceof AgentBusyError)) throw error;\n\t\t\t\t}\n\t\t\t}\n\t\t} finally {\n\t\t\tthis._isContinuing = false;\n\t\t}\n\t}\n\n\tprivate unavailableResult(options: GoalContinuationLoopOptions): GoalContinuationLoopResult | undefined {\n\t\tif (this.deps.isDisposed()) return this.skippedResult(options, \"session_disposed\");\n\t\tif (this.deps.isGoalToolActive()) return undefined;\n\t\tthis.deps.markGoalToolUnavailable();\n\t\treturn this.skippedResult(options, \"goal_tool_unavailable\");\n\t}\n\n\tprivate async runScheduled(): Promise<void> {\n\t\tif (this._isContinuing || this.deps.isDisposed()) return;\n\t\tconst { maxStallTurns, goalContinueTurns, goalContinueMaxWallClockMinutes, goalAutoContinue } = this.deps\n\t\t\t.getSettingsManager()\n\t\t\t.getAutonomySettings();\n\t\tif (!goalAutoContinue) return;\n\t\tconst snapshot = this.deps.getGoalRuntimeSnapshot({ maxStallTurns });\n\t\tif (snapshot.continuation.action !== \"continue\") return;\n\t\ttry {\n\t\t\tconst result = await this.continueExclusive({\n\t\t\t\tmaxTurns: goalContinueTurns,\n\t\t\t\tmaxStallTurns,\n\t\t\t\tmaxWallClockMinutes: goalContinueMaxWallClockMinutes,\n\t\t\t});\n\t\t\tif (result.stopReason === \"turn_interrupted\") return;\n\t\t\tif (!this.deps.isDisposed()) {\n\t\t\t\tconst nextSnapshot = this.deps.getGoalRuntimeSnapshot({ maxStallTurns });\n\t\t\t\tif (nextSnapshot.continuation.action === \"continue\") {\n\t\t\t\t\tthis.scheduleFromIdle();\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\t\tthis.deps.emit({ type: \"warning\", message: `Goal auto-continuation failed: ${message}` });\n\t\t}\n\t}\n\n\tprivate skippedResult(\n\t\toptions: GoalContinuationLoopOptions,\n\t\tstopReason: \"already_continuing\" | \"session_disposed\" | \"goal_tool_unavailable\",\n\t): GoalContinuationLoopResult {\n\t\treturn {\n\t\t\tturnsSubmitted: 0,\n\t\t\tstopReason,\n\t\t\tfinalSnapshot: this.deps.getGoalRuntimeSnapshot({ maxStallTurns: options.maxStallTurns }),\n\t\t};\n\t}\n}\n"]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type SessionManager } from "@caupulican/pi-agent-core/session";
|
|
2
2
|
import type { AgentMessage, AgentRunawayStopInfo } from "@caupulican/pi-agent-core/types";
|
|
3
3
|
import type { AssistantMessage } from "@caupulican/pi-ai";
|
|
4
|
-
import type
|
|
4
|
+
import { type GoalContinuationLoopOptions, type GoalContinuationLoopResult, type GoalContinuationOnceOptions, type GoalContinuationOnceResult, type PromptOptions } from "../agent-session-contracts.ts";
|
|
5
5
|
import type { LaneRecord } from "../autonomy/lane-tracker.ts";
|
|
6
6
|
import type { BackgroundToolTaskRef } from "../background-tool-task-controller.ts";
|
|
7
7
|
import type { TaskRuntimeProjection } from "../orchestration/task-runtime.ts";
|
|
@@ -47,6 +47,7 @@ export declare class GoalSessionController {
|
|
|
47
47
|
private readonly queuedOwnerChatGoals;
|
|
48
48
|
private queuedOwnerChatExecutionLease;
|
|
49
49
|
constructor(deps: GoalSessionControllerDeps);
|
|
50
|
+
private getContinuationTurnOutcome;
|
|
50
51
|
saveState(state: GoalState, expected?: GoalStateRevision): string;
|
|
51
52
|
clearState(state: GoalState, now: string): string;
|
|
52
53
|
getState(): GoalState | undefined;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"goal-session-controller.d.ts","sourceRoot":"","sources":["../../../src/core/goals/goal-session-controller.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"goal-session-controller.d.ts","sourceRoot":"","sources":["../../../src/core/goals/goal-session-controller.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
2
|
import { classifyFailure } from "@caupulican/pi-agent-core/reliability";
|
|
3
|
+
import { MAX_SESSION_ENTRY_VISIT_COUNT } from "@caupulican/pi-agent-core/session";
|
|
4
|
+
import { isInterruptedAssistantStopReason, } from "../agent-session-contracts.js";
|
|
3
5
|
import { GoalLoopController } from "../goal-loop-controller.js";
|
|
4
6
|
import { budgetedTokens } from "../orchestration/capability-gateway.js";
|
|
5
7
|
import { GoalBudgetExhaustedError } from "./goal-execution-errors.js";
|
|
@@ -32,12 +34,31 @@ export class GoalSessionController {
|
|
|
32
34
|
this.deps = deps;
|
|
33
35
|
this.loop = new GoalLoopController({
|
|
34
36
|
getGoalRuntimeSnapshot: (settings) => this.getRuntimeSnapshot(settings),
|
|
35
|
-
prompt: (text, options) =>
|
|
37
|
+
prompt: async (text, options) => {
|
|
38
|
+
const firstTurnEntryIndex = this.deps.getSessionManager().getEntryCount();
|
|
39
|
+
await this.deps.prompt(text, options);
|
|
40
|
+
return this.getContinuationTurnOutcome(firstTurnEntryIndex);
|
|
41
|
+
},
|
|
36
42
|
recordGoalContinuationPass: (pass) => this.recordContinuationPass(pass),
|
|
37
43
|
recordGoalContinuationFailure: (error) => this.recordContinuationFailure(error),
|
|
38
44
|
markGoalBudgetLimited: (reason) => this.markBudgetLimited(reason),
|
|
39
45
|
});
|
|
40
46
|
}
|
|
47
|
+
getContinuationTurnOutcome(firstTurnEntryIndex) {
|
|
48
|
+
const sessionManager = this.deps.getSessionManager();
|
|
49
|
+
const endIndex = sessionManager.getEntryCount();
|
|
50
|
+
let nextIndex = firstTurnEntryIndex;
|
|
51
|
+
let lastAssistantStopReason;
|
|
52
|
+
while (nextIndex < endIndex) {
|
|
53
|
+
const visitCount = Math.min(MAX_SESSION_ENTRY_VISIT_COUNT, endIndex - nextIndex);
|
|
54
|
+
nextIndex = sessionManager.visitEntries(nextIndex, visitCount, (entry) => {
|
|
55
|
+
if (entry.type === "message" && entry.message.role === "assistant") {
|
|
56
|
+
lastAssistantStopReason = entry.message.stopReason;
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
return isInterruptedAssistantStopReason(lastAssistantStopReason) ? "interrupted" : "completed";
|
|
61
|
+
}
|
|
41
62
|
saveState(state, expected) {
|
|
42
63
|
const current = this.getState();
|
|
43
64
|
if (expected &&
|