@caupulican/pi-adaptative 0.91.4 → 0.93.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +43 -0
- package/dist/cli/args.d.ts +2 -0
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +24 -0
- package/dist/cli/args.js.map +1 -1
- package/dist/cli.js +6 -1
- package/dist/cli.js.map +1 -1
- package/dist/core/agent-session-contracts.d.ts +1 -0
- package/dist/core/agent-session-contracts.d.ts.map +1 -1
- package/dist/core/agent-session-contracts.js.map +1 -1
- package/dist/core/agent-session-services.d.ts +1 -0
- package/dist/core/agent-session-services.d.ts.map +1 -1
- package/dist/core/agent-session-services.js +1 -0
- package/dist/core/agent-session-services.js.map +1 -1
- package/dist/core/agent-session.d.ts +1 -6
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +15 -13
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/autonomy/lane-tool-surface.d.ts.map +1 -1
- package/dist/core/autonomy/lane-tool-surface.js +7 -1
- package/dist/core/autonomy/lane-tool-surface.js.map +1 -1
- package/dist/core/background-lane-controller.d.ts +2 -4
- package/dist/core/background-lane-controller.d.ts.map +1 -1
- package/dist/core/background-lane-controller.js +0 -1
- package/dist/core/background-lane-controller.js.map +1 -1
- package/dist/core/bash-execution-controller.d.ts.map +1 -1
- package/dist/core/bash-execution-controller.js +1 -0
- package/dist/core/bash-execution-controller.js.map +1 -1
- package/dist/core/bash-executor.d.ts +2 -0
- package/dist/core/bash-executor.d.ts.map +1 -1
- package/dist/core/bash-executor.js +13 -4
- package/dist/core/bash-executor.js.map +1 -1
- package/dist/core/compaction-controller.d.ts.map +1 -1
- package/dist/core/compaction-controller.js +2 -1
- package/dist/core/compaction-controller.js.map +1 -1
- package/dist/core/context/context-composition.d.ts +1 -1
- package/dist/core/context/context-composition.d.ts.map +1 -1
- package/dist/core/context/context-composition.js +1 -1
- package/dist/core/context/context-composition.js.map +1 -1
- package/dist/core/default-tool-surface.d.ts +0 -10
- package/dist/core/default-tool-surface.d.ts.map +1 -1
- package/dist/core/default-tool-surface.js +3 -1
- package/dist/core/default-tool-surface.js.map +1 -1
- package/dist/core/extensions/bundled-virtual-modules.js +8 -0
- package/dist/core/extensions/bundled-virtual-modules.js.map +1 -1
- package/dist/core/extensions/runner.d.ts +1 -1
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +1 -1
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/extensions/virtual-modules.d.ts +4 -0
- package/dist/core/extensions/virtual-modules.d.ts.map +1 -1
- package/dist/core/extensions/virtual-modules.js +4 -0
- package/dist/core/extensions/virtual-modules.js.map +1 -1
- package/dist/core/goal-loop-controller.d.ts +6 -2
- package/dist/core/goal-loop-controller.d.ts.map +1 -1
- package/dist/core/goal-loop-controller.js +15 -4
- package/dist/core/goal-loop-controller.js.map +1 -1
- package/dist/core/goals/compact-goal-context.d.ts.map +1 -1
- package/dist/core/goals/compact-goal-context.js +10 -14
- package/dist/core/goals/compact-goal-context.js.map +1 -1
- package/dist/core/goals/goal-auto-continue-controller.d.ts +0 -2
- package/dist/core/goals/goal-auto-continue-controller.d.ts.map +1 -1
- package/dist/core/goals/goal-auto-continue-controller.js +0 -2
- package/dist/core/goals/goal-auto-continue-controller.js.map +1 -1
- package/dist/core/goals/goal-session-controller.d.ts +7 -7
- package/dist/core/goals/goal-session-controller.d.ts.map +1 -1
- package/dist/core/goals/goal-session-controller.js +27 -5
- package/dist/core/goals/goal-session-controller.js.map +1 -1
- package/dist/core/goals/goal-tool-core.d.ts.map +1 -1
- package/dist/core/goals/goal-tool-core.js +7 -0
- package/dist/core/goals/goal-tool-core.js.map +1 -1
- package/dist/core/goals/goal-tool-names.d.ts +7 -0
- package/dist/core/goals/goal-tool-names.d.ts.map +1 -0
- package/dist/core/goals/goal-tool-names.js +8 -0
- package/dist/core/goals/goal-tool-names.js.map +1 -0
- package/dist/core/model-capability.d.ts +1 -1
- package/dist/core/model-capability.d.ts.map +1 -1
- package/dist/core/model-capability.js +3 -1
- package/dist/core/model-capability.js.map +1 -1
- package/dist/core/models/perf-profile.d.ts +2 -1
- package/dist/core/models/perf-profile.d.ts.map +1 -1
- package/dist/core/models/perf-profile.js +1 -1
- package/dist/core/models/perf-profile.js.map +1 -1
- package/dist/core/provider-request-context-controller.d.ts.map +1 -1
- package/dist/core/provider-request-context-controller.js +6 -5
- package/dist/core/provider-request-context-controller.js.map +1 -1
- package/dist/core/provider-request-runtime-controller.d.ts.map +1 -1
- package/dist/core/provider-request-runtime-controller.js +3 -2
- package/dist/core/provider-request-runtime-controller.js.map +1 -1
- package/dist/core/runtime-builder.d.ts.map +1 -1
- package/dist/core/runtime-builder.js +13 -4
- package/dist/core/runtime-builder.js.map +1 -1
- package/dist/core/sdk.d.ts +3 -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/session-analytics.d.ts +2 -2
- package/dist/core/session-analytics.d.ts.map +1 -1
- package/dist/core/session-analytics.js +3 -2
- package/dist/core/session-analytics.js.map +1 -1
- package/dist/core/session-manager-factory.d.ts +1 -1
- package/dist/core/session-manager-factory.d.ts.map +1 -1
- package/dist/core/session-manager-factory.js +1 -1
- package/dist/core/session-manager-factory.js.map +1 -1
- package/dist/core/session-role.d.ts.map +1 -1
- package/dist/core/session-role.js +2 -0
- package/dist/core/session-role.js.map +1 -1
- package/dist/core/session-tree-navigator.d.ts +2 -2
- package/dist/core/session-tree-navigator.d.ts.map +1 -1
- package/dist/core/session-tree-navigator.js +1 -1
- package/dist/core/session-tree-navigator.js.map +1 -1
- package/dist/core/skill-vault.d.ts +6 -7
- package/dist/core/skill-vault.d.ts.map +1 -1
- package/dist/core/skill-vault.js +12 -12
- package/dist/core/skill-vault.js.map +1 -1
- package/dist/core/tool-capability-policy.d.ts.map +1 -1
- package/dist/core/tool-capability-policy.js +2 -1
- package/dist/core/tool-capability-policy.js.map +1 -1
- package/dist/core/tools/bash.d.ts +2 -0
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +27 -12
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/core/tools/early-powershell-session.d.ts +21 -0
- package/dist/core/tools/early-powershell-session.d.ts.map +1 -0
- package/dist/core/tools/early-powershell-session.js +137 -0
- package/dist/core/tools/early-powershell-session.js.map +1 -0
- package/dist/core/tools/edit.d.ts +1 -1
- package/dist/core/tools/edit.d.ts.map +1 -1
- package/dist/core/tools/edit.js +1 -1
- package/dist/core/tools/edit.js.map +1 -1
- package/dist/core/tools/file-failure-recovery.d.ts +1 -1
- package/dist/core/tools/file-failure-recovery.d.ts.map +1 -1
- package/dist/core/tools/file-failure-recovery.js +1 -1
- package/dist/core/tools/file-failure-recovery.js.map +1 -1
- package/dist/core/tools/goal.d.ts +9 -2
- package/dist/core/tools/goal.d.ts.map +1 -1
- package/dist/core/tools/goal.js +64 -1
- package/dist/core/tools/goal.js.map +1 -1
- package/dist/core/tools/grep.d.ts +2 -2
- package/dist/core/tools/grep.d.ts.map +1 -1
- package/dist/core/tools/grep.js +1 -1
- package/dist/core/tools/grep.js.map +1 -1
- package/dist/core/tools/output-accumulator.d.ts +2 -0
- package/dist/core/tools/output-accumulator.d.ts.map +1 -1
- package/dist/core/tools/output-accumulator.js +2 -1
- package/dist/core/tools/output-accumulator.js.map +1 -1
- package/dist/core/tools/persistent-process-coordinator.d.ts.map +1 -1
- package/dist/core/tools/persistent-process-coordinator.js +2 -11
- package/dist/core/tools/persistent-process-coordinator.js.map +1 -1
- package/dist/core/tools/read.d.ts +2 -2
- package/dist/core/tools/read.d.ts.map +1 -1
- package/dist/core/tools/read.js +1 -1
- package/dist/core/tools/read.js.map +1 -1
- package/dist/core/tools/render-utils.d.ts +1 -0
- package/dist/core/tools/render-utils.d.ts.map +1 -1
- package/dist/core/tools/render-utils.js +11 -9
- package/dist/core/tools/render-utils.js.map +1 -1
- package/dist/core/tools/shell-output-decoder.d.ts +7 -0
- package/dist/core/tools/shell-output-decoder.d.ts.map +1 -0
- package/dist/core/tools/shell-output-decoder.js +135 -0
- package/dist/core/tools/shell-output-decoder.js.map +1 -0
- package/dist/core/tools/shell-session.d.ts +23 -6
- package/dist/core/tools/shell-session.d.ts.map +1 -1
- package/dist/core/tools/shell-session.js +275 -88
- package/dist/core/tools/shell-session.js.map +1 -1
- package/dist/core/tools/skill.js +2 -2
- package/dist/core/tools/skill.js.map +1 -1
- package/dist/core/tools/write.d.ts +1 -1
- package/dist/core/tools/write.d.ts.map +1 -1
- package/dist/core/tools/write.js +1 -1
- package/dist/core/tools/write.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +2 -0
- package/dist/main.js.map +1 -1
- package/dist/modes/interactive/components/bash-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/bash-execution.js +4 -33
- package/dist/modes/interactive/components/bash-execution.js.map +1 -1
- package/dist/modes/interactive/components/tool-execution.d.ts +3 -0
- package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/tool-execution.js +63 -27
- package/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/dist/utils/child-process-ref.d.ts +4 -0
- package/dist/utils/child-process-ref.d.ts.map +1 -0
- package/dist/utils/child-process-ref.js +15 -0
- package/dist/utils/child-process-ref.js.map +1 -0
- package/dist/utils/powershell-session-protocol.d.ts +16 -0
- package/dist/utils/powershell-session-protocol.d.ts.map +1 -0
- package/dist/utils/powershell-session-protocol.js +63 -0
- package/dist/utils/powershell-session-protocol.js.map +1 -0
- package/dist/utils/shell.d.ts +7 -4
- package/dist/utils/shell.d.ts.map +1 -1
- package/dist/utils/shell.js +38 -23
- package/dist/utils/shell.js.map +1 -1
- package/docs/settings.md +2 -2
- package/docs/windows.md +9 -8
- package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
- package/examples/extensions/custom-provider-anthropic/package.json +2 -2
- 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 +2 -2
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/npm-shrinkwrap.json +318 -332
- package/package.json +4 -4
|
@@ -8,8 +8,9 @@
|
|
|
8
8
|
* gated only by real terminal conditions and limits the owner explicitly supplied: an optional
|
|
9
9
|
* per-invocation turn cap, an optional per-invocation wall-clock cap, and an optional durable token
|
|
10
10
|
* budget on the goal. Each submitted pass still reports turn/wall-clock telemetry; provider usage
|
|
11
|
-
* and spend are attributed at the response boundary.
|
|
12
|
-
*
|
|
11
|
+
* and spend are attributed at the response boundary. The host compares each pass's authoritative
|
|
12
|
+
* progress revision and records unchanged passes as stalls, so a model cannot bypass the stall
|
|
13
|
+
* limit by omitting a voluntary `no_progress` call.
|
|
13
14
|
*/
|
|
14
15
|
import type { GoalContinuationLoopOptions, GoalContinuationLoopResult, GoalContinuationOnceOptions, GoalContinuationOnceResult, PromptOptions } from "./agent-session-contracts.ts";
|
|
15
16
|
import type { GoalRuntimeSnapshot, GoalRuntimeSnapshotSettings } from "./goals/goal-runtime-snapshot.ts";
|
|
@@ -26,6 +27,9 @@ export interface GoalLoopControllerDeps {
|
|
|
26
27
|
recordGoalContinuationPass(pass: {
|
|
27
28
|
turns: number;
|
|
28
29
|
wallClockMs: number;
|
|
30
|
+
goalId: string;
|
|
31
|
+
progressRevision: number;
|
|
32
|
+
stallTurns: number;
|
|
29
33
|
}): void;
|
|
30
34
|
/** Persist an exhausted/non-retryable continuation failure as a stopped goal state. */
|
|
31
35
|
recordGoalContinuationFailure(error: unknown): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"goal-loop-controller.d.ts","sourceRoot":"","sources":["../../src/core/goal-loop-controller.ts"],"names":[],"mappings":"AAAA
|
|
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,IAAI,CAAC,CAAC;IAC7D;;;;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"}
|
|
@@ -8,8 +8,9 @@
|
|
|
8
8
|
* gated only by real terminal conditions and limits the owner explicitly supplied: an optional
|
|
9
9
|
* per-invocation turn cap, an optional per-invocation wall-clock cap, and an optional durable token
|
|
10
10
|
* budget on the goal. Each submitted pass still reports turn/wall-clock telemetry; provider usage
|
|
11
|
-
* and spend are attributed at the response boundary.
|
|
12
|
-
*
|
|
11
|
+
* and spend are attributed at the response boundary. The host compares each pass's authoritative
|
|
12
|
+
* progress revision and records unchanged passes as stalls, so a model cannot bypass the stall
|
|
13
|
+
* limit by omitting a voluntary `no_progress` call.
|
|
13
14
|
*/
|
|
14
15
|
import { AgentBusyError } from "@caupulican/pi-agent-core/agent";
|
|
15
16
|
import { buildGoalContinuationPrompt, GOAL_CONTINUATION_TRIGGER_CUSTOM_TYPE, } from "./goals/goal-continuation-prompt.js";
|
|
@@ -87,6 +88,16 @@ export class GoalLoopController {
|
|
|
87
88
|
return { turnsSubmitted, stopReason: "goal_budget_exhausted", finalSnapshot: snapshot() };
|
|
88
89
|
}
|
|
89
90
|
const passStartedAt = now();
|
|
91
|
+
const beforeGoal = beforeSnapshot.goalState;
|
|
92
|
+
if (!beforeGoal) {
|
|
93
|
+
return { turnsSubmitted, stopReason: "continuation_not_allowed", finalSnapshot: beforeSnapshot };
|
|
94
|
+
}
|
|
95
|
+
const passAccounting = {
|
|
96
|
+
turns: 1,
|
|
97
|
+
goalId: beforeGoal.goalId,
|
|
98
|
+
progressRevision: beforeGoal.progressRevision ?? 0,
|
|
99
|
+
stallTurns: beforeGoal.stallTurns,
|
|
100
|
+
};
|
|
90
101
|
let result;
|
|
91
102
|
try {
|
|
92
103
|
result = await this.continueGoalOnce(options);
|
|
@@ -97,7 +108,7 @@ export class GoalLoopController {
|
|
|
97
108
|
if (error instanceof AgentBusyError)
|
|
98
109
|
throw error;
|
|
99
110
|
turnsSubmitted++;
|
|
100
|
-
this.deps.recordGoalContinuationPass({
|
|
111
|
+
this.deps.recordGoalContinuationPass({ ...passAccounting, wallClockMs: now() - passStartedAt });
|
|
101
112
|
if (error instanceof GoalBudgetExhaustedError) {
|
|
102
113
|
// The goal already stopped itself durably (markBudgetLimited ran synchronously before
|
|
103
114
|
// this signal was thrown) — surface the existing clean stop instead of reclassifying an
|
|
@@ -110,7 +121,7 @@ export class GoalLoopController {
|
|
|
110
121
|
}
|
|
111
122
|
if (result.submitted) {
|
|
112
123
|
turnsSubmitted++;
|
|
113
|
-
this.deps.recordGoalContinuationPass({
|
|
124
|
+
this.deps.recordGoalContinuationPass({ ...passAccounting, wallClockMs: now() - passStartedAt });
|
|
114
125
|
}
|
|
115
126
|
if (hasReachedWallClockBudget()) {
|
|
116
127
|
return { turnsSubmitted, stopReason: "wall_clock_budget_reached", finalSnapshot: snapshot() };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"goal-loop-controller.js","sourceRoot":"","sources":["../../src/core/goal-loop-controller.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AASjE,OAAO,EACN,2BAA2B,EAC3B,qCAAqC,GACrC,MAAM,qCAAqC,CAAC;AAC7C,OAAO,EAAE,wBAAwB,EAAE,MAAM,kCAAkC,CAAC;AAE5E,OAAO,EAAkB,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAE9E;;;;GAIG;AACH,SAAS,+BAA+B,CAAC,KAA4B;IACpE,IAAI,CAAC,KAAK,IAAI,CAAC,qBAAqB,CAAC,KAAK,CAAC,MAAM,CAAC;QAAE,OAAO,SAAS,CAAC;IACrE,IAAI,KAAK,CAAC,WAAW,KAAK,SAAS,IAAI,CAAC,KAAK,CAAC,UAAU,IAAI,CAAC,CAAC,IAAI,KAAK,CAAC,WAAW,EAAE,CAAC;QACrF,OAAO,2BAA2B,KAAK,CAAC,UAAU,IAAI,CAAC,IAAI,KAAK,CAAC,WAAW,GAAG,CAAC;IACjF,CAAC;IACD,OAAO,SAAS,CAAC;AAClB,CAAC;AAED;;;;;;;GAOG;AACH,SAAS,qBAAqB,CAAC,QAA6B;IAC3D,OAAO,QAAQ,CAAC,YAAY,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,0BAA0B,CAAC;AACrG,CAAC;AAmBD,MAAM,OAAO,kBAAkB;IAG9B,YAAY,IAA4B;QACvC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IAClB,CAAC;IAED,KAAK,CAAC,gBAAgB,CAAC,OAAoC;QAC1D,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,sBAAsB,CAAC,EAAE,aAAa,EAAE,OAAO,CAAC,aAAa,EAAE,CAAC,CAAC;QAE5F,IAAI,QAAQ,CAAC,YAAY,CAAC,MAAM,KAAK,UAAU,EAAE,CAAC;YACjD,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC;QACvC,CAAC;QAED,MAAM,MAAM,GAAG,2BAA2B,EAAE,CAAC;QAC7C,MAAM,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE;YACnC,qBAAqB,EAAE,KAAK;YAC5B,oBAAoB,EAAE,KAAK;YAC3B,gBAAgB,EAAE,KAAK;YACvB,mBAAmB,EAAE,qCAAqC;YAC1D,eAAe,EAAE,QAAQ,CAAC,SAAS,EAAE,MAAM;SAC3C,CAAC,CAAC;QAEH,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC;IAC9C,CAAC;IAED,KAAK,CAAC,gBAAgB,CAAC,OAAoC;QAC1D,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,OAAO,CAAC,QAAQ,GAAG,CAAC,EAAE,CAAC;YACrE,MAAM,IAAI,KAAK,CAAC,oFAAoF,CAAC,CAAC;QACvG,CAAC;QACD,IAAI,cAAc,GAAG,CAAC,CAAC;QACvB,MAAM,oBAAoB,GAAG,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;QAClD,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC;QACpC,MAAM,cAAc,GACnB,OAAO,OAAO,CAAC,mBAAmB,KAAK,QAAQ,IAAI,OAAO,CAAC,mBAAmB,GAAG,CAAC;YACjF,CAAC,CAAC,OAAO,CAAC,mBAAmB,GAAG,MAAM;YACtC,CAAC,CAAC,SAAS,CAAC;QACd,MAAM,SAAS,GAAG,GAAG,EAAE,CAAC;QACxB,MAAM,yBAAyB,GAAG,GAAG,EAAE,CAAC,cAAc,KAAK,SAAS,IAAI,GAAG,EAAE,GAAG,SAAS,IAAI,cAAc,CAAC;QAC5G,MAAM,QAAQ,GAAG,GAAG,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,sBAAsB,CAAC,EAAE,aAAa,EAAE,OAAO,CAAC,aAAa,EAAE,CAAC,CAAC;QAElG,IAAI,yBAAyB,EAAE,EAAE,CAAC;YACjC,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,2BAA2B,EAAE,aAAa,EAAE,QAAQ,EAAE,EAAE,CAAC;QAC/F,CAAC;QAED,OAAO,CAAC,oBAAoB,IAAI,cAAc,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC;YACnE,MAAM,cAAc,GAAG,QAAQ,EAAE,CAAC;YAClC,IAAI,cAAc,CAAC,YAAY,CAAC,MAAM,KAAK,UAAU,EAAE,CAAC;gBACvD,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,qBAAqB,CAAC,cAAc,CAAC,EAAE,aAAa,EAAE,cAAc,EAAE,CAAC;YAC7G,CAAC;YAED,wFAAwF;YACxF,uEAAuE;YACvE,MAAM,sBAAsB,GAAG,+BAA+B,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC;YACzF,IAAI,sBAAsB,EAAE,CAAC;gBAC5B,IAAI,CAAC,IAAI,CAAC,qBAAqB,CAAC,sBAAsB,CAAC,CAAC;gBACxD,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,uBAAuB,EAAE,aAAa,EAAE,QAAQ,EAAE,EAAE,CAAC;YAC3F,CAAC;YAED,MAAM,aAAa,GAAG,GAAG,EAAE,CAAC;YAC5B,IAAI,MAAkC,CAAC;YACvC,IAAI,CAAC;gBACJ,MAAM,GAAG,MAAM,IAAI,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC;YAC/C,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBAChB,sFAAsF;gBACtF,oFAAoF;gBACpF,IAAI,KAAK,YAAY,cAAc;oBAAE,MAAM,KAAK,CAAC;gBACjD,cAAc,EAAE,CAAC;gBACjB,IAAI,CAAC,IAAI,CAAC,0BAA0B,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,WAAW,EAAE,GAAG,EAAE,GAAG,aAAa,EAAE,CAAC,CAAC;gBACvF,IAAI,KAAK,YAAY,wBAAwB,EAAE,CAAC;oBAC/C,sFAAsF;oBACtF,wFAAwF;oBACxF,qFAAqF;oBACrF,0BAA0B;oBAC1B,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,uBAAuB,EAAE,aAAa,EAAE,QAAQ,EAAE,EAAE,CAAC;gBAC3F,CAAC;gBACD,IAAI,CAAC,IAAI,CAAC,6BAA6B,CAAC,KAAK,CAAC,CAAC;gBAC/C,MAAM,KAAK,CAAC;YACb,CAAC;YACD,IAAI,MAAM,CAAC,SAAS,EAAE,CAAC;gBACtB,cAAc,EAAE,CAAC;gBACjB,IAAI,CAAC,IAAI,CAAC,0BAA0B,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,WAAW,EAAE,GAAG,EAAE,GAAG,aAAa,EAAE,CAAC,CAAC;YACxF,CAAC;YAED,IAAI,yBAAyB,EAAE,EAAE,CAAC;gBACjC,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,2BAA2B,EAAE,aAAa,EAAE,QAAQ,EAAE,EAAE,CAAC;YAC/F,CAAC;YAED,IAAI,aAAa,GAAG,QAAQ,EAAE,CAAC;YAC/B,IAAI,aAAa,CAAC,SAAS,EAAE,MAAM,KAAK,gBAAgB,EAAE,CAAC;gBAC1D,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,uBAAuB,EAAE,aAAa,EAAE,aAAa,EAAE,CAAC;YAC9F,CAAC;YACD,MAAM,qBAAqB,GAAG,+BAA+B,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC;YACvF,IAAI,qBAAqB,EAAE,CAAC;gBAC3B,IAAI,CAAC,IAAI,CAAC,qBAAqB,CAAC,qBAAqB,CAAC,CAAC;gBACvD,aAAa,GAAG,QAAQ,EAAE,CAAC;gBAC3B,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,uBAAuB,EAAE,aAAa,EAAE,aAAa,EAAE,CAAC;YAC9F,CAAC;YACD,IAAI,aAAa,CAAC,YAAY,CAAC,MAAM,KAAK,UAAU,EAAE,CAAC;gBACtD,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,qBAAqB,CAAC,aAAa,CAAC,EAAE,aAAa,EAAE,aAAa,EAAE,CAAC;YAC3G,CAAC;QACF,CAAC;QAED,OAAO;YACN,cAAc;YACd,UAAU,EAAE,mBAAmB;YAC/B,aAAa,EAAE,QAAQ,EAAE;SACzB,CAAC;IACH,CAAC;CACD","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. Progress is inferred from real work and\n * terminal goal updates; telemetry never becomes an implicit execution limit.\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: { turns: number; wallClockMs: number }): 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\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\tturnsSubmitted++;\n\t\t\t\tthis.deps.recordGoalContinuationPass({ turns: 1, wallClockMs: now() - passStartedAt });\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 reclassifying an\n\t\t\t\t\t// intentional, already-recorded stop as a generic continuation failure and rejecting\n\t\t\t\t\t// the whole loop promise.\n\t\t\t\t\treturn { turnsSubmitted, stopReason: \"goal_budget_exhausted\", finalSnapshot: snapshot() };\n\t\t\t\t}\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({ turns: 1, 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<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\tturnsSubmitted++;\n\t\t\t\tthis.deps.recordGoalContinuationPass({ ...passAccounting, wallClockMs: now() - passStartedAt });\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 reclassifying an\n\t\t\t\t\t// intentional, already-recorded stop as a generic continuation failure and rejecting\n\t\t\t\t\t// the whole loop promise.\n\t\t\t\t\treturn { turnsSubmitted, stopReason: \"goal_budget_exhausted\", finalSnapshot: snapshot() };\n\t\t\t\t}\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 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compact-goal-context.d.ts","sourceRoot":"","sources":["../../../src/core/goals/compact-goal-context.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iCAAiC,CAAC;AAIpE,OAAO,EAAE,KAAK,SAAS,EAAyB,MAAM,iBAAiB,CAAC;AAExE,eAAO,MAAM,+BAA+B,wBAAwB,CAAC;AAsBrE,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,SAAS,EAAE,gBAAgB,EAAE,OAAO,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"compact-goal-context.d.ts","sourceRoot":"","sources":["../../../src/core/goals/compact-goal-context.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iCAAiC,CAAC;AAIpE,OAAO,EAAE,KAAK,SAAS,EAAyB,MAAM,iBAAiB,CAAC;AAExE,eAAO,MAAM,+BAA+B,wBAAwB,CAAC;AAsBrE,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,SAAS,EAAE,gBAAgB,EAAE,OAAO,GAAG,MAAM,CAkB5F;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,YAAY,EAAE,EAAE,KAAK,EAAE,SAAS,GAAG,SAAS,GAAG,YAAY,EAAE,CAkB/G"}
|
|
@@ -23,24 +23,20 @@ function isGoalContextMessage(message) {
|
|
|
23
23
|
}
|
|
24
24
|
export function formatCompactGoalContext(state, continuationTurn) {
|
|
25
25
|
const record = projectGoalRecord(state);
|
|
26
|
-
const budgetText = record.tokenBudget === undefined ? "unbounded" : String(record.tokenBudget);
|
|
27
|
-
const remainingText = record.tokensRemaining === undefined ? "unbounded" : String(record.tokensRemaining);
|
|
28
26
|
const instruction = continuationTurn
|
|
29
|
-
? "Continue now:
|
|
30
|
-
: "
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
tokensRemaining: remainingText,
|
|
36
|
-
})
|
|
37
|
-
.replaceAll("<", "\\u003c")
|
|
38
|
-
.replaceAll(">", "\\u003e");
|
|
27
|
+
? "Continue now: pursue full objective."
|
|
28
|
+
: "current user message steers this turn.";
|
|
29
|
+
const compactRecord = record.tokenBudget === undefined
|
|
30
|
+
? { untrustedObjective: record.objective }
|
|
31
|
+
: { untrustedObjective: record.objective, tokenBudget: String(record.tokenBudget) };
|
|
32
|
+
const encodedRecord = JSON.stringify(compactRecord).replaceAll("<", "\\u003c").replaceAll(">", "\\u003e");
|
|
39
33
|
return [
|
|
40
|
-
"ACTIVE GOAL",
|
|
34
|
+
"ACTIVE GOAL — HOST-OWNED CONTINUATION",
|
|
41
35
|
encodedRecord,
|
|
42
36
|
instruction,
|
|
43
|
-
"
|
|
37
|
+
"get_goal; task_steps for decomposition.",
|
|
38
|
+
'Progress: update_goal status "active".',
|
|
39
|
+
'update_goal with status "complete" after requirement-by-requirement audit; "blocked" only after same blocking condition lasts 3 consecutive goal turns; else continue.',
|
|
44
40
|
].join("\n");
|
|
45
41
|
}
|
|
46
42
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compact-goal-context.js","sourceRoot":"","sources":["../../../src/core/goals/compact-goal-context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,oCAAoC,CAAC;AAGzE,OAAO,EAAE,qCAAqC,EAAE,MAAM,+BAA+B,CAAC;AACtF,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAkB,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AAExE,MAAM,CAAC,MAAM,+BAA+B,GAAG,qBAAqB,CAAC;AACrE,MAAM,+BAA+B,GAAG,sDAAsD,CAAC;AAE/F,SAAS,WAAW,CAAC,OAAqB;IACzC,IAAI,OAAO,CAAC,IAAI,KAAK,MAAM;QAAE,OAAO,EAAE,CAAC;IACvC,IAAI,OAAO,OAAO,CAAC,OAAO,KAAK,QAAQ;QAAE,OAAO,OAAO,CAAC,OAAO,CAAC;IAChE,OAAO,OAAO,CAAC,OAAO;SACpB,MAAM,CAAC,CAAC,IAAI,EAAuB,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,MAAM,CAAC;SAC3D,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC;SACxB,IAAI,CAAC,IAAI,CAAC,CAAC;AACd,CAAC;AAED,SAAS,oBAAoB,CAAC,OAAqB;IAClD,IAAI,OAAO,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;QAC/B,OAAO,CACN,OAAO,CAAC,UAAU,KAAK,qCAAqC;YAC5D,OAAO,CAAC,UAAU,KAAK,+BAA+B,CACtD,CAAC;IACH,CAAC;IACD,OAAO,WAAW,CAAC,OAAO,CAAC,CAAC,UAAU,CAAC,+BAA+B,CAAC,CAAC;AACzE,CAAC;AAED,MAAM,UAAU,wBAAwB,CAAC,KAAgB,EAAE,gBAAyB;IACnF,MAAM,MAAM,GAAG,iBAAiB,CAAC,KAAK,CAAC,CAAC;IACxC,MAAM,
|
|
1
|
+
{"version":3,"file":"compact-goal-context.js","sourceRoot":"","sources":["../../../src/core/goals/compact-goal-context.ts"],"names":[],"mappings":"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","sourcesContent":["import { createCustomMessage } from \"@caupulican/pi-agent-core/messages\";\nimport type { AgentMessage } from \"@caupulican/pi-agent-core/types\";\nimport type { TextContent } from \"@caupulican/pi-ai\";\nimport { GOAL_CONTINUATION_TRIGGER_CUSTOM_TYPE } from \"./goal-continuation-prompt.ts\";\nimport { projectGoalRecord } from \"./goal-record.ts\";\nimport { type GoalState, isGoalExecutionActive } from \"./goal-state.ts\";\n\nexport const ACTIVE_GOAL_CONTEXT_CUSTOM_TYPE = \"active_goal_context\";\nconst LEGACY_GOAL_CONTINUATION_PREFIX = \"Goal continuation context\\n=========================\";\n\nfunction messageText(message: AgentMessage): string {\n\tif (message.role !== \"user\") return \"\";\n\tif (typeof message.content === \"string\") return message.content;\n\treturn message.content\n\t\t.filter((part): part is TextContent => part.type === \"text\")\n\t\t.map((part) => part.text)\n\t\t.join(\"\\n\");\n}\n\nfunction isGoalContextMessage(message: AgentMessage): boolean {\n\tif (message.role === \"custom\") {\n\t\treturn (\n\t\t\tmessage.customType === GOAL_CONTINUATION_TRIGGER_CUSTOM_TYPE ||\n\t\t\tmessage.customType === ACTIVE_GOAL_CONTEXT_CUSTOM_TYPE\n\t\t);\n\t}\n\treturn messageText(message).startsWith(LEGACY_GOAL_CONTINUATION_PREFIX);\n}\n\nexport function formatCompactGoalContext(state: GoalState, continuationTurn: boolean): string {\n\tconst record = projectGoalRecord(state);\n\tconst instruction = continuationTurn\n\t\t? \"Continue now: pursue full objective.\"\n\t\t: \"current user message steers this turn.\";\n\tconst compactRecord =\n\t\trecord.tokenBudget === undefined\n\t\t\t? { untrustedObjective: record.objective }\n\t\t\t: { untrustedObjective: record.objective, tokenBudget: String(record.tokenBudget) };\n\tconst encodedRecord = JSON.stringify(compactRecord).replaceAll(\"<\", \"\\\\u003c\").replaceAll(\">\", \"\\\\u003e\");\n\treturn [\n\t\t\"ACTIVE GOAL — HOST-OWNED CONTINUATION\",\n\t\tencodedRecord,\n\t\tinstruction,\n\t\t\"get_goal; task_steps for decomposition.\",\n\t\t'Progress: update_goal status \"active\".',\n\t\t'update_goal with status \"complete\" after requirement-by-requirement audit; \"blocked\" only after same blocking condition lasts 3 consecutive goal turns; else continue.',\n\t].join(\"\\n\");\n}\n\n/**\n * Replace every historical goal continuation payload with one current compact projection. The\n * projection exists only in the provider request returned from context assembly; it is never\n * appended to the transcript or session log.\n */\nexport function injectCompactGoalContext(messages: AgentMessage[], state: GoalState | undefined): AgentMessage[] {\n\tconst continuationTurn = messages.some(\n\t\t(message) =>\n\t\t\t(message.role === \"custom\" && message.customType === GOAL_CONTINUATION_TRIGGER_CUSTOM_TYPE) ||\n\t\t\tmessageText(message).startsWith(LEGACY_GOAL_CONTINUATION_PREFIX),\n\t);\n\tconst filtered = messages.filter((message) => !isGoalContextMessage(message));\n\tif (!state || !isGoalExecutionActive(state.status)) return filtered;\n\treturn [\n\t\t...filtered,\n\t\tcreateCustomMessage(\n\t\t\tACTIVE_GOAL_CONTEXT_CUSTOM_TYPE,\n\t\t\tformatCompactGoalContext(state, continuationTurn),\n\t\t\tfalse,\n\t\t\t{ goalId: state.goalId, revision: state.revision ?? 0 },\n\t\t\tnew Date().toISOString(),\n\t\t),\n\t];\n}\n"]}
|
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
import type { AgentSessionEvent, GoalContinuationLoopOptions, GoalContinuationLoopResult, PromptOptions } from "../agent-session.ts";
|
|
2
|
-
import type { ModelCapabilityProfile } from "../model-capability.ts";
|
|
3
2
|
import type { SettingsManager } from "../settings-manager.ts";
|
|
4
3
|
import type { GoalRuntimeSnapshot, GoalRuntimeSnapshotSettings } from "./goal-runtime-snapshot.ts";
|
|
5
4
|
export interface GoalAutoContinueControllerDeps {
|
|
6
5
|
isDisposed(): boolean;
|
|
7
6
|
isGoalToolActive(): boolean;
|
|
8
7
|
getSettingsManager(): SettingsManager;
|
|
9
|
-
getModelCapabilityProfile(): ModelCapabilityProfile;
|
|
10
8
|
getGoalRuntimeSnapshot(settings: GoalRuntimeSnapshotSettings): GoalRuntimeSnapshot;
|
|
11
9
|
hasInFlightLaneForGoal(goalId: string): boolean;
|
|
12
10
|
continueGoalLoop(options: GoalContinuationLoopOptions): Promise<GoalContinuationLoopResult>;
|
|
@@ -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,
|
|
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;IAoB1B,OAAO,CAAC,aAAa;CAUrB"}
|
|
@@ -14,8 +14,6 @@ export class GoalAutoContinueController {
|
|
|
14
14
|
scheduleFromIdle(options) {
|
|
15
15
|
if (options?.autoContinueGoal === false || this._isContinuing || this.deps.isDisposed())
|
|
16
16
|
return;
|
|
17
|
-
if (!this.deps.getModelCapabilityProfile().backgroundLanesEnabled)
|
|
18
|
-
return;
|
|
19
17
|
const { maxStallTurns, goalAutoContinue, goalAutoContinueDelayMs } = this.deps
|
|
20
18
|
.getSettingsManager()
|
|
21
19
|
.getAutonomySettings();
|
|
@@ -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;
|
|
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\tawait 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} 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,5 +1,5 @@
|
|
|
1
1
|
import type { SessionManager } from "@caupulican/pi-agent-core/session";
|
|
2
|
-
import type { AgentMessage } from "@caupulican/pi-agent-core/types";
|
|
2
|
+
import type { AgentMessage, AgentRunawayStopInfo } from "@caupulican/pi-agent-core/types";
|
|
3
3
|
import type { AssistantMessage } from "@caupulican/pi-ai";
|
|
4
4
|
import type { GoalContinuationLoopOptions, GoalContinuationLoopResult, GoalContinuationOnceOptions, GoalContinuationOnceResult, PromptOptions } from "../agent-session-contracts.ts";
|
|
5
5
|
import type { LaneRecord } from "../autonomy/lane-tracker.ts";
|
|
@@ -70,11 +70,14 @@ export declare class GoalSessionController {
|
|
|
70
70
|
}[]): void;
|
|
71
71
|
endQueuedOwnerChatGoalExecution(): void;
|
|
72
72
|
admitExplicitChatGoal(text: string, now?: string, priorUserText?: string): ChatGoalAdmission;
|
|
73
|
-
/** Attribute turn/wall-clock telemetry
|
|
74
|
-
|
|
73
|
+
/** Attribute turn/wall-clock telemetry without inferring progress (public/manual accounting seam). */
|
|
74
|
+
recordContinuationTelemetry(pass: {
|
|
75
75
|
turns: number;
|
|
76
76
|
wallClockMs: number;
|
|
77
77
|
}): void;
|
|
78
|
+
/** Attribute one host-driven pass and derive stall state from the authoritative revision. */
|
|
79
|
+
private recordContinuationPass;
|
|
80
|
+
private persistContinuationPass;
|
|
78
81
|
/** Begin one foreground execution whose provider usage belongs to the specified active goal. */
|
|
79
82
|
beginExecution(goalId: string | undefined, options?: {
|
|
80
83
|
adoptNewGoal?: boolean;
|
|
@@ -105,10 +108,7 @@ export declare class GoalSessionController {
|
|
|
105
108
|
private resolveExecutionState;
|
|
106
109
|
private flushPendingExecutionUsage;
|
|
107
110
|
markToolUnavailable(): void;
|
|
108
|
-
|
|
109
|
-
signature: string;
|
|
110
|
-
repeats: number;
|
|
111
|
-
}): boolean;
|
|
111
|
+
markHarnessGuardBlocked(info: AgentRunawayStopInfo): boolean;
|
|
112
112
|
markTerminalToolFailureBlocked(toolName: string): boolean;
|
|
113
113
|
getRuntimeSnapshot(settings: GoalRuntimeSnapshotSettings): GoalRuntimeSnapshot;
|
|
114
114
|
continueOnce(options: GoalContinuationOnceOptions): Promise<GoalContinuationOnceResult>;
|
|
@@ -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,EAAE,cAAc,EAAE,MAAM,mCAAmC,CAAC;AACxE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iCAAiC,CAAC;
|
|
1
|
+
{"version":3,"file":"goal-session-controller.d.ts","sourceRoot":"","sources":["../../../src/core/goals/goal-session-controller.ts"],"names":[],"mappings":"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"}
|
|
@@ -135,19 +135,38 @@ export class GoalSessionController {
|
|
|
135
135
|
this.saveState(result.state, current ? getGoalStateRevision(current) : undefined);
|
|
136
136
|
return { status: "started", state: result.state };
|
|
137
137
|
}
|
|
138
|
-
/** Attribute turn/wall-clock telemetry
|
|
138
|
+
/** Attribute turn/wall-clock telemetry without inferring progress (public/manual accounting seam). */
|
|
139
|
+
recordContinuationTelemetry(pass) {
|
|
140
|
+
this.persistContinuationPass(pass);
|
|
141
|
+
}
|
|
142
|
+
/** Attribute one host-driven pass and derive stall state from the authoritative revision. */
|
|
139
143
|
recordContinuationPass(pass) {
|
|
144
|
+
this.persistContinuationPass(pass);
|
|
145
|
+
}
|
|
146
|
+
persistContinuationPass(pass) {
|
|
140
147
|
const state = this.getState();
|
|
141
148
|
if (!state)
|
|
142
149
|
return;
|
|
143
|
-
|
|
150
|
+
if (pass.goalId !== undefined && state.goalId !== pass.goalId) {
|
|
151
|
+
this.deps.emitWarning(`Goal continuation accounting skipped because goal '${pass.goalId}' was replaced by '${state.goalId}' during the pass.`);
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
const now = new Date().toISOString();
|
|
155
|
+
let updated = applyGoalEvent(state, {
|
|
144
156
|
type: "record_continuation_budget",
|
|
145
157
|
turns: pass.turns,
|
|
146
158
|
wallClockMs: pass.wallClockMs,
|
|
147
159
|
tokens: 0,
|
|
148
160
|
spendUsd: 0,
|
|
149
|
-
now
|
|
161
|
+
now,
|
|
150
162
|
});
|
|
163
|
+
if (pass.progressRevision !== undefined &&
|
|
164
|
+
pass.stallTurns !== undefined &&
|
|
165
|
+
isGoalExecutionActive(state.status) &&
|
|
166
|
+
(state.progressRevision ?? 0) <= pass.progressRevision &&
|
|
167
|
+
state.stallTurns <= pass.stallTurns) {
|
|
168
|
+
updated = applyGoalEvent(updated, { type: "no_progress", now });
|
|
169
|
+
}
|
|
151
170
|
this.saveState(updated, getGoalStateRevision(state));
|
|
152
171
|
}
|
|
153
172
|
/** Begin one foreground execution whose provider usage belongs to the specified active goal. */
|
|
@@ -346,8 +365,11 @@ export class GoalSessionController {
|
|
|
346
365
|
markToolUnavailable() {
|
|
347
366
|
this.stopActiveGoal("blocked", "goal_tool_unavailable: the active capability surface cannot update durable goal state");
|
|
348
367
|
}
|
|
349
|
-
|
|
350
|
-
|
|
368
|
+
markHarnessGuardBlocked(info) {
|
|
369
|
+
const reason = info.reason === "provider_turn_limit"
|
|
370
|
+
? `provider_turn_limit: reached the ${info.repeats}-request provider-turn cost fuse`
|
|
371
|
+
: `runaway_tool_loop: repeated tool-call signature ${info.signature} ${info.repeats} times without progress`;
|
|
372
|
+
return this.stopActiveGoal("blocked", reason);
|
|
351
373
|
}
|
|
352
374
|
markTerminalToolFailureBlocked(toolName) {
|
|
353
375
|
return this.stopActiveGoal("blocked", `terminal_tool_failure: ${toolName} reported an unrecoverable error and terminated the run`);
|