@caupulican/pi-adaptative 0.81.26 → 0.81.29
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 +45 -0
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +3 -2
- package/dist/cli/args.js.map +1 -1
- package/dist/core/agent-session-services.d.ts +4 -0
- package/dist/core/agent-session-services.d.ts.map +1 -1
- package/dist/core/agent-session-services.js +19 -2
- package/dist/core/agent-session-services.js.map +1 -1
- package/dist/core/agent-session.d.ts +30 -12
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +128 -36
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/auth-storage.d.ts +6 -0
- package/dist/core/auth-storage.d.ts.map +1 -1
- package/dist/core/auth-storage.js +35 -0
- package/dist/core/auth-storage.js.map +1 -1
- package/dist/core/autonomy/bounded-completion.d.ts.map +1 -1
- package/dist/core/autonomy/bounded-completion.js +59 -19
- package/dist/core/autonomy/bounded-completion.js.map +1 -1
- package/dist/core/autonomy/contracts.d.ts +2 -0
- package/dist/core/autonomy/contracts.d.ts.map +1 -1
- package/dist/core/autonomy/contracts.js.map +1 -1
- package/dist/core/autonomy/lane-tool-surface.d.ts +31 -0
- package/dist/core/autonomy/lane-tool-surface.d.ts.map +1 -0
- package/dist/core/autonomy/lane-tool-surface.js +96 -0
- package/dist/core/autonomy/lane-tool-surface.js.map +1 -0
- package/dist/core/autonomy/lane-tracker.d.ts +5 -0
- package/dist/core/autonomy/lane-tracker.d.ts.map +1 -1
- package/dist/core/autonomy/lane-tracker.js +14 -3
- package/dist/core/autonomy/lane-tracker.js.map +1 -1
- package/dist/core/background-lane-controller.d.ts +28 -4
- package/dist/core/background-lane-controller.d.ts.map +1 -1
- package/dist/core/background-lane-controller.js +237 -28
- package/dist/core/background-lane-controller.js.map +1 -1
- package/dist/core/billing-failover-controller.d.ts.map +1 -1
- package/dist/core/billing-failover-controller.js +1 -1
- package/dist/core/billing-failover-controller.js.map +1 -1
- package/dist/core/context/current-work-memory.d.ts +9 -0
- package/dist/core/context/current-work-memory.d.ts.map +1 -0
- package/dist/core/context/current-work-memory.js +61 -0
- package/dist/core/context/current-work-memory.js.map +1 -0
- package/dist/core/context/file-store-memory-provider.d.ts +9 -0
- package/dist/core/context/file-store-memory-provider.d.ts.map +1 -0
- package/dist/core/context/file-store-memory-provider.js +106 -0
- package/dist/core/context/file-store-memory-provider.js.map +1 -0
- package/dist/core/context/long-term-memory-trigger.d.ts +15 -0
- package/dist/core/context/long-term-memory-trigger.d.ts.map +1 -0
- package/dist/core/context/long-term-memory-trigger.js +39 -0
- package/dist/core/context/long-term-memory-trigger.js.map +1 -0
- package/dist/core/context/memory-prompt-block.d.ts +3 -1
- package/dist/core/context/memory-prompt-block.d.ts.map +1 -1
- package/dist/core/context/memory-prompt-block.js +20 -3
- package/dist/core/context/memory-prompt-block.js.map +1 -1
- package/dist/core/context/memory-prompt-budget.d.ts +17 -0
- package/dist/core/context/memory-prompt-budget.d.ts.map +1 -0
- package/dist/core/context/memory-prompt-budget.js +64 -0
- package/dist/core/context/memory-prompt-budget.js.map +1 -0
- package/dist/core/context/memory-provider-contract.d.ts.map +1 -1
- package/dist/core/context/memory-provider-contract.js +2 -5
- package/dist/core/context/memory-provider-contract.js.map +1 -1
- package/dist/core/context/memory-tier-composer.d.ts +27 -0
- package/dist/core/context/memory-tier-composer.d.ts.map +1 -0
- package/dist/core/context/memory-tier-composer.js +79 -0
- package/dist/core/context/memory-tier-composer.js.map +1 -0
- package/dist/core/context-gc.d.ts.map +1 -1
- package/dist/core/context-gc.js +2 -0
- package/dist/core/context-gc.js.map +1 -1
- package/dist/core/context-pipeline.d.ts +5 -3
- package/dist/core/context-pipeline.d.ts.map +1 -1
- package/dist/core/context-pipeline.js +15 -5
- package/dist/core/context-pipeline.js.map +1 -1
- package/dist/core/cost/cost-summary.d.ts +3 -1
- package/dist/core/cost/cost-summary.d.ts.map +1 -1
- package/dist/core/cost/cost-summary.js +3 -3
- package/dist/core/cost/cost-summary.js.map +1 -1
- package/dist/core/cost-guard.d.ts +17 -7
- package/dist/core/cost-guard.d.ts.map +1 -1
- package/dist/core/cost-guard.js +33 -10
- package/dist/core/cost-guard.js.map +1 -1
- package/dist/core/default-tool-surface.d.ts +9 -0
- package/dist/core/default-tool-surface.d.ts.map +1 -0
- package/dist/core/default-tool-surface.js +18 -0
- package/dist/core/default-tool-surface.js.map +1 -0
- package/dist/core/delegation/worker-result.d.ts.map +1 -1
- package/dist/core/delegation/worker-result.js +3 -0
- package/dist/core/delegation/worker-result.js.map +1 -1
- package/dist/core/delegation/worker-runner.d.ts +11 -5
- package/dist/core/delegation/worker-runner.d.ts.map +1 -1
- package/dist/core/delegation/worker-runner.js +77 -16
- package/dist/core/delegation/worker-runner.js.map +1 -1
- package/dist/core/extensions/loader.d.ts.map +1 -1
- package/dist/core/extensions/loader.js +15 -0
- package/dist/core/extensions/loader.js.map +1 -1
- package/dist/core/extensions/runner.d.ts +2 -0
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +7 -0
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/extensions/types.d.ts +9 -0
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/failure-corpus.d.ts.map +1 -1
- package/dist/core/failure-corpus.js +2 -4
- package/dist/core/failure-corpus.js.map +1 -1
- package/dist/core/footer-data-provider.d.ts.map +1 -1
- package/dist/core/footer-data-provider.js +9 -1
- package/dist/core/footer-data-provider.js.map +1 -1
- package/dist/core/goals/goal-continuation-prompt.d.ts.map +1 -1
- package/dist/core/goals/goal-continuation-prompt.js +4 -3
- package/dist/core/goals/goal-continuation-prompt.js.map +1 -1
- package/dist/core/http-dispatcher.d.ts +12 -0
- package/dist/core/http-dispatcher.d.ts.map +1 -1
- package/dist/core/http-dispatcher.js +42 -4
- package/dist/core/http-dispatcher.js.map +1 -1
- package/dist/core/local-runtime-controller.d.ts +16 -0
- package/dist/core/local-runtime-controller.d.ts.map +1 -1
- package/dist/core/local-runtime-controller.js +107 -28
- package/dist/core/local-runtime-controller.js.map +1 -1
- package/dist/core/memory/memory-manager.d.ts +8 -3
- package/dist/core/memory/memory-manager.d.ts.map +1 -1
- package/dist/core/memory/memory-manager.js +27 -11
- package/dist/core/memory/memory-manager.js.map +1 -1
- package/dist/core/memory/memory-provider.d.ts +5 -1
- package/dist/core/memory/memory-provider.d.ts.map +1 -1
- package/dist/core/memory/memory-provider.js.map +1 -1
- package/dist/core/memory/providers/file-store.d.ts +3 -1
- package/dist/core/memory/providers/file-store.d.ts.map +1 -1
- package/dist/core/memory/providers/file-store.js +7 -2
- package/dist/core/memory/providers/file-store.js.map +1 -1
- package/dist/core/memory/providers/transcript-recall.d.ts +1 -0
- package/dist/core/memory/providers/transcript-recall.d.ts.map +1 -1
- package/dist/core/memory/providers/transcript-recall.js +4 -7
- package/dist/core/memory/providers/transcript-recall.js.map +1 -1
- package/dist/core/memory-controller.d.ts +36 -10
- package/dist/core/memory-controller.d.ts.map +1 -1
- package/dist/core/memory-controller.js +137 -21
- package/dist/core/memory-controller.js.map +1 -1
- package/dist/core/model-registry.d.ts +25 -0
- package/dist/core/model-registry.d.ts.map +1 -1
- package/dist/core/model-registry.js +91 -8
- package/dist/core/model-registry.js.map +1 -1
- package/dist/core/model-resolver.d.ts.map +1 -1
- package/dist/core/model-resolver.js +30 -11
- package/dist/core/model-resolver.js.map +1 -1
- package/dist/core/model-router-controller.d.ts.map +1 -1
- package/dist/core/model-router-controller.js +33 -29
- package/dist/core/model-router-controller.js.map +1 -1
- package/dist/core/model-selection-controller.d.ts +3 -0
- package/dist/core/model-selection-controller.d.ts.map +1 -1
- package/dist/core/model-selection-controller.js +8 -1
- package/dist/core/model-selection-controller.js.map +1 -1
- package/dist/core/models/local-runtime.d.ts +2 -0
- package/dist/core/models/local-runtime.d.ts.map +1 -1
- package/dist/core/models/local-runtime.js +10 -4
- package/dist/core/models/local-runtime.js.map +1 -1
- package/dist/core/models/perf-profile.d.ts.map +1 -1
- package/dist/core/models/perf-profile.js +95 -33
- package/dist/core/models/perf-profile.js.map +1 -1
- package/dist/core/models/runtime-arbiter.d.ts +11 -0
- package/dist/core/models/runtime-arbiter.d.ts.map +1 -1
- package/dist/core/models/runtime-arbiter.js +35 -13
- package/dist/core/models/runtime-arbiter.js.map +1 -1
- package/dist/core/profile-filter-controller.d.ts +11 -0
- package/dist/core/profile-filter-controller.d.ts.map +1 -1
- package/dist/core/profile-filter-controller.js +56 -11
- package/dist/core/profile-filter-controller.js.map +1 -1
- package/dist/core/profile-registry.d.ts +2 -2
- package/dist/core/profile-registry.d.ts.map +1 -1
- package/dist/core/profile-registry.js +58 -7
- package/dist/core/profile-registry.js.map +1 -1
- package/dist/core/reflection-controller.d.ts +9 -7
- package/dist/core/reflection-controller.d.ts.map +1 -1
- package/dist/core/reflection-controller.js +81 -12
- package/dist/core/reflection-controller.js.map +1 -1
- package/dist/core/research/research-runner.d.ts +2 -2
- package/dist/core/research/research-runner.d.ts.map +1 -1
- package/dist/core/research/research-runner.js +8 -6
- package/dist/core/research/research-runner.js.map +1 -1
- package/dist/core/resource-loader.d.ts +4 -2
- package/dist/core/resource-loader.d.ts.map +1 -1
- package/dist/core/resource-loader.js +11 -1
- package/dist/core/resource-loader.js.map +1 -1
- package/dist/core/runtime-builder.d.ts +30 -3
- package/dist/core/runtime-builder.d.ts.map +1 -1
- package/dist/core/runtime-builder.js +140 -40
- package/dist/core/runtime-builder.js.map +1 -1
- package/dist/core/sdk.d.ts +8 -7
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +38 -5
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/security/secret-text.d.ts +3 -0
- package/dist/core/security/secret-text.d.ts.map +1 -0
- package/dist/core/security/secret-text.js +26 -0
- package/dist/core/security/secret-text.js.map +1 -0
- package/dist/core/settings-manager.d.ts +59 -17
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +300 -51
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/skills.d.ts.map +1 -1
- package/dist/core/skills.js +1 -1
- package/dist/core/skills.js.map +1 -1
- package/dist/core/system-prompt-builder.d.ts +7 -0
- package/dist/core/system-prompt-builder.d.ts.map +1 -1
- package/dist/core/system-prompt-builder.js +23 -1
- package/dist/core/system-prompt-builder.js.map +1 -1
- package/dist/core/tool-gate-controller.d.ts +3 -0
- package/dist/core/tool-gate-controller.d.ts.map +1 -1
- package/dist/core/tool-gate-controller.js +20 -15
- package/dist/core/tool-gate-controller.js.map +1 -1
- package/dist/core/tool-selection/expected-utility.d.ts +51 -0
- package/dist/core/tool-selection/expected-utility.d.ts.map +1 -0
- package/dist/core/tool-selection/expected-utility.js +85 -0
- package/dist/core/tool-selection/expected-utility.js.map +1 -0
- package/dist/core/tool-selection/tool-performance-store.d.ts +82 -0
- package/dist/core/tool-selection/tool-performance-store.d.ts.map +1 -0
- package/dist/core/tool-selection/tool-performance-store.js +249 -0
- package/dist/core/tool-selection/tool-performance-store.js.map +1 -0
- package/dist/core/tool-selection/tool-selection-controller.d.ts +41 -0
- package/dist/core/tool-selection/tool-selection-controller.d.ts.map +1 -0
- package/dist/core/tool-selection/tool-selection-controller.js +199 -0
- package/dist/core/tool-selection/tool-selection-controller.js.map +1 -0
- package/dist/core/tools/delegate-status.d.ts +9 -0
- package/dist/core/tools/delegate-status.d.ts.map +1 -0
- package/dist/core/tools/delegate-status.js +52 -0
- package/dist/core/tools/delegate-status.js.map +1 -0
- package/dist/core/tools/delegate.d.ts +10 -0
- package/dist/core/tools/delegate.d.ts.map +1 -1
- package/dist/core/tools/delegate.js +36 -13
- package/dist/core/tools/delegate.js.map +1 -1
- package/dist/core/tools/run-toolkit-script.d.ts +3 -0
- package/dist/core/tools/run-toolkit-script.d.ts.map +1 -1
- package/dist/core/tools/run-toolkit-script.js +17 -7
- package/dist/core/tools/run-toolkit-script.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/footer.d.ts.map +1 -1
- package/dist/modes/interactive/components/footer.js +8 -1
- package/dist/modes/interactive/components/footer.js.map +1 -1
- package/dist/modes/interactive/components/settings-selector.d.ts +2 -0
- package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/settings-selector.js +69 -29
- package/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/dist/modes/interactive/components/thinking-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/thinking-selector.js +2 -0
- package/dist/modes/interactive/components/thinking-selector.js.map +1 -1
- package/dist/modes/interactive/config-backup.d.ts +7 -1
- package/dist/modes/interactive/config-backup.d.ts.map +1 -1
- package/dist/modes/interactive/config-backup.js +196 -32
- package/dist/modes/interactive/config-backup.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +22 -28
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/local-model-commands.d.ts.map +1 -1
- package/dist/modes/interactive/local-model-commands.js +2 -0
- package/dist/modes/interactive/local-model-commands.js.map +1 -1
- package/dist/modes/interactive/profile-menu-controller.d.ts +6 -4
- package/dist/modes/interactive/profile-menu-controller.d.ts.map +1 -1
- package/dist/modes/interactive/profile-menu-controller.js +248 -65
- package/dist/modes/interactive/profile-menu-controller.js.map +1 -1
- package/dist/modes/interactive/report-commands.d.ts.map +1 -1
- package/dist/modes/interactive/report-commands.js +8 -2
- package/dist/modes/interactive/report-commands.js.map +1 -1
- package/dist/modes/interactive/settings-selector-flow.d.ts.map +1 -1
- package/dist/modes/interactive/settings-selector-flow.js +8 -0
- package/dist/modes/interactive/settings-selector-flow.js.map +1 -1
- package/dist/modes/interactive/theme/theme-schema.json +1 -1
- package/dist/modes/interactive/theme/theme.d.ts +1 -1
- package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
- package/dist/modes/interactive/theme/theme.js +3 -1
- package/dist/modes/interactive/theme/theme.js.map +1 -1
- package/docs/extensions.md +32 -0
- package/docs/integration-sweep-builder-blueprint-2026-07-09.md +365 -0
- package/docs/integration-sweep-resume-2026-07-09.md +407 -0
- package/docs/resources.md +15 -7
- package/docs/settings.md +56 -5
- 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/preset.ts +2 -2
- 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 +44 -35
- package/package.json +4 -4
|
@@ -14,7 +14,10 @@
|
|
|
14
14
|
* delegations; goal auto-continue itself only ever asks the session to `continueGoalLoop`, so this
|
|
15
15
|
* controller never touches `prompt()`, the last-assistant-message, retry, or streaming state.
|
|
16
16
|
*/
|
|
17
|
+
import path from "node:path";
|
|
18
|
+
import { createLaneToolSurface } from "./autonomy/lane-tool-surface.js";
|
|
17
19
|
import { LaneTracker } from "./autonomy/lane-tracker.js";
|
|
20
|
+
import { safeRealpathSync } from "./autonomy/path-scope.js";
|
|
18
21
|
import { appendLaneRecordSnapshot, getLaneRecordSnapshots } from "./autonomy/session-lane-record.js";
|
|
19
22
|
import { composeSubagentSystemPrompt } from "./autonomy/subagent-prompt.js";
|
|
20
23
|
import { AUTONOMY_TELEMETRY_EVENT_TYPES } from "./autonomy/telemetry-events.js";
|
|
@@ -45,7 +48,37 @@ export class BackgroundLaneController {
|
|
|
45
48
|
_researchLaneAbort = new AbortController();
|
|
46
49
|
/** Session-lifetime abort for in-flight delegated workers. */
|
|
47
50
|
_workerDelegationAbort = new AbortController();
|
|
51
|
+
/** Session-local de-duplication for fail-closed profile grants that cannot bind to lane tools. */
|
|
52
|
+
_warnedUnboundLaneToolGrants = new Set();
|
|
53
|
+
/** Every background execution is retained until its terminal result is observed. */
|
|
54
|
+
_workerPromises = new Map();
|
|
55
|
+
_queuedWorkers = new Map();
|
|
56
|
+
_workerNotificationTimer;
|
|
57
|
+
_workersCompletedSinceFlush = 0;
|
|
58
|
+
_workersFailedSinceFlush = 0;
|
|
48
59
|
deps;
|
|
60
|
+
_scheduleWorkerNotification() {
|
|
61
|
+
if (this._workerNotificationTimer !== undefined)
|
|
62
|
+
return;
|
|
63
|
+
this._workerNotificationTimer = setTimeout(() => {
|
|
64
|
+
this._workerNotificationTimer = undefined;
|
|
65
|
+
this.deps.emit({
|
|
66
|
+
type: "delegate_workers",
|
|
67
|
+
active: this._laneTracker.getActiveCount("worker"),
|
|
68
|
+
completedSinceFlush: this._workersCompletedSinceFlush,
|
|
69
|
+
failedSinceFlush: this._workersFailedSinceFlush,
|
|
70
|
+
});
|
|
71
|
+
this._workersCompletedSinceFlush = 0;
|
|
72
|
+
this._workersFailedSinceFlush = 0;
|
|
73
|
+
}, 75);
|
|
74
|
+
}
|
|
75
|
+
_recordWorkerTerminal(status) {
|
|
76
|
+
if (status === "succeeded")
|
|
77
|
+
this._workersCompletedSinceFlush++;
|
|
78
|
+
else
|
|
79
|
+
this._workersFailedSinceFlush++;
|
|
80
|
+
this._scheduleWorkerNotification();
|
|
81
|
+
}
|
|
49
82
|
constructor(deps) {
|
|
50
83
|
this.deps = deps;
|
|
51
84
|
}
|
|
@@ -174,10 +207,6 @@ export class BackgroundLaneController {
|
|
|
174
207
|
scheduleResearchLaneFromIdle() {
|
|
175
208
|
if (this._isResearchLaneRunning || this.deps.isDisposed() || this.deps.isChildSession())
|
|
176
209
|
return;
|
|
177
|
-
if (!this.deps.getModelCapabilityProfile().backgroundLanesEnabled) {
|
|
178
|
-
this._lastResearchLaneSkipReason = "model_context_too_small";
|
|
179
|
-
return;
|
|
180
|
-
}
|
|
181
210
|
const research = this.deps.getSettingsManager().getResearchLaneSettings();
|
|
182
211
|
if (!research.enabled) {
|
|
183
212
|
this._lastResearchLaneSkipReason = "research_lane_disabled";
|
|
@@ -195,6 +224,15 @@ export class BackgroundLaneController {
|
|
|
195
224
|
}
|
|
196
225
|
if (!this._buildResearchLaneDemand())
|
|
197
226
|
return;
|
|
227
|
+
const shipment = this._resolveLaneShipment(research, "no_research_model");
|
|
228
|
+
if (!shipment.ok) {
|
|
229
|
+
this._lastResearchLaneSkipReason = shipment.skipReason;
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
232
|
+
if (!this._laneCapabilityProfile(shipment.model).backgroundLanesEnabled) {
|
|
233
|
+
this._lastResearchLaneSkipReason = "model_research_unsupported";
|
|
234
|
+
return;
|
|
235
|
+
}
|
|
198
236
|
this.clearResearchLaneTimer();
|
|
199
237
|
this._researchLaneTimer = setTimeout(() => {
|
|
200
238
|
this._researchLaneTimer = undefined;
|
|
@@ -252,7 +290,12 @@ export class BackgroundLaneController {
|
|
|
252
290
|
_resolveLaneShipment(laneSettings, missingModelReason) {
|
|
253
291
|
let laneProfile;
|
|
254
292
|
if (laneSettings.profile) {
|
|
255
|
-
|
|
293
|
+
const profileRef = laneSettings.profile.trim();
|
|
294
|
+
const registry = this.deps.getSettingsManager().getProfileRegistry();
|
|
295
|
+
laneProfile =
|
|
296
|
+
profileRef.startsWith("./") || profileRef.startsWith("../")
|
|
297
|
+
? registry.resolveProfileRef(profileRef, this.deps.getCwd())
|
|
298
|
+
: registry.getProfile(profileRef);
|
|
256
299
|
if (!laneProfile) {
|
|
257
300
|
return { ok: false, skipReason: "lane_profile_not_found" };
|
|
258
301
|
}
|
|
@@ -278,21 +321,27 @@ export class BackgroundLaneController {
|
|
|
278
321
|
}
|
|
279
322
|
return { ok: true, model, laneProfile };
|
|
280
323
|
}
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
324
|
+
_warnUnboundLaneToolGrants(laneProfile, surface) {
|
|
325
|
+
if (!laneProfile || surface.unboundAllowPatterns.length === 0)
|
|
326
|
+
return;
|
|
327
|
+
const warningKey = `${laneProfile.name}\0${[...surface.unboundAllowPatterns].sort().join("\0")}`;
|
|
328
|
+
if (this._warnedUnboundLaneToolGrants.has(warningKey))
|
|
329
|
+
return;
|
|
330
|
+
this._warnedUnboundLaneToolGrants.add(warningKey);
|
|
331
|
+
this.deps.emit({
|
|
332
|
+
type: "warning",
|
|
333
|
+
message: `Lane profile '${laneProfile.name}' grants unavailable isolated-lane tools: ${surface.unboundAllowPatterns.join(", ")}. Only classified lane tools can execute.`,
|
|
334
|
+
});
|
|
288
335
|
}
|
|
289
336
|
/** Stripped research envelope — never the foreground/architect envelope. */
|
|
290
|
-
_buildResearchLaneEnvelope(maxUsd, laneProfile) {
|
|
337
|
+
_buildResearchLaneEnvelope(maxUsd, laneProfile, surface) {
|
|
291
338
|
return {
|
|
292
339
|
id: `research-${this.deps.getSessionId()}-${Date.now()}`,
|
|
293
340
|
profileId: laneProfile?.name,
|
|
294
341
|
capabilities: ["research", "read_files", "memory_read"],
|
|
295
|
-
...
|
|
342
|
+
allowedTools: [...surface.allowedTools],
|
|
343
|
+
deniedTools: [...surface.deniedTools],
|
|
344
|
+
allowedPaths: [this.deps.getCwd()],
|
|
296
345
|
maxEstimatedUsd: clampLaneMaxUsd(maxUsd, this.deps.getCapabilityEnvelope()?.maxEstimatedUsd),
|
|
297
346
|
createdAt: new Date().toISOString(),
|
|
298
347
|
};
|
|
@@ -323,6 +372,11 @@ export class BackgroundLaneController {
|
|
|
323
372
|
return { started: false, skipReason: shipment.skipReason };
|
|
324
373
|
}
|
|
325
374
|
const { model, laneProfile } = shipment;
|
|
375
|
+
const laneCapability = this._laneCapabilityProfile(model);
|
|
376
|
+
if (!laneCapability.backgroundLanesEnabled) {
|
|
377
|
+
this._lastResearchLaneSkipReason = "model_research_unsupported";
|
|
378
|
+
return { started: false, skipReason: "model_research_unsupported" };
|
|
379
|
+
}
|
|
326
380
|
this._isResearchLaneRunning = true;
|
|
327
381
|
this._laneTracker.ensureCounterAtLeast(getLaneRecordSnapshots(this.deps.getSessionManager().getEntries()).length + 1);
|
|
328
382
|
const startedRecord = this._laneTracker.start({ type: "research", goalId: demand.goalId });
|
|
@@ -336,11 +390,13 @@ export class BackgroundLaneController {
|
|
|
336
390
|
maxSources: settings.maxSources,
|
|
337
391
|
});
|
|
338
392
|
const maxUsd = clampLaneMaxUsd(settings.maxUsd, this.deps.getCapabilityEnvelope()?.maxEstimatedUsd);
|
|
393
|
+
const toolSurface = createLaneToolSurface({ cwd: this.deps.getCwd(), profile: laneProfile });
|
|
394
|
+
this._warnUnboundLaneToolGrants(laneProfile, toolSurface);
|
|
339
395
|
const result = await runResearch({
|
|
340
396
|
query: demand.query,
|
|
341
397
|
context: demand.context,
|
|
342
398
|
sources: workspaceSources,
|
|
343
|
-
envelope: this._buildResearchLaneEnvelope(maxUsd, laneProfile),
|
|
399
|
+
envelope: this._buildResearchLaneEnvelope(maxUsd, laneProfile, toolSurface),
|
|
344
400
|
maxUsd,
|
|
345
401
|
maxSources: settings.maxSources,
|
|
346
402
|
maxFindings: settings.maxFindings,
|
|
@@ -358,7 +414,10 @@ export class BackgroundLaneController {
|
|
|
358
414
|
messages: [{ role: "user", content: [{ type: "text", text: userPrompt }], timestamp: Date.now() }],
|
|
359
415
|
model,
|
|
360
416
|
thinkingLevel: laneProfile?.thinking ?? "off",
|
|
361
|
-
maxTokens:
|
|
417
|
+
maxTokens: laneCapability.laneMaxOutputTokens,
|
|
418
|
+
tools: toolSurface.tools,
|
|
419
|
+
maxTurns: 6,
|
|
420
|
+
beforeToolCall: toolSurface.beforeToolCall,
|
|
362
421
|
signal,
|
|
363
422
|
// Core/soul/role are all static per configuration — the provider can cache the prefix.
|
|
364
423
|
cacheRetention: "short",
|
|
@@ -449,9 +508,38 @@ export class BackgroundLaneController {
|
|
|
449
508
|
* {@link validateWorkerResult} before acceptance, and persist result + lane record + spawned
|
|
450
509
|
* usage (idempotent per-lane reportId). Consumed by the `delegate` tool.
|
|
451
510
|
*/
|
|
452
|
-
|
|
511
|
+
startWorkerDelegation(request) {
|
|
512
|
+
const settings = this.deps.getSettingsManager().getWorkerDelegationSettings();
|
|
513
|
+
const foreground = this.deps.getModel();
|
|
514
|
+
const managedLocal = foreground?.provider === "ollama" || foreground?.provider === "transformers";
|
|
515
|
+
if (managedLocal) {
|
|
516
|
+
if (this._queuedWorkers.size >= 8 ||
|
|
517
|
+
this._laneTracker.getActiveCount("worker") >= settings.maxConcurrent + 8) {
|
|
518
|
+
return { started: false, skipReason: "worker_delegation_queue_full" };
|
|
519
|
+
}
|
|
520
|
+
const record = this._laneTracker.enqueue({ type: "worker" });
|
|
521
|
+
this._queuedWorkers.set(record.laneId, request);
|
|
522
|
+
this._scheduleWorkerNotification();
|
|
523
|
+
return { started: true, record };
|
|
524
|
+
}
|
|
525
|
+
let startedRecord;
|
|
526
|
+
const promise = this.runWorkerDelegationOnce(request, (record) => {
|
|
527
|
+
startedRecord = record;
|
|
528
|
+
});
|
|
529
|
+
if (!startedRecord) {
|
|
530
|
+
// Preparation is synchronous up to the first isolated completion await. A promise that
|
|
531
|
+
// rejected before producing a lane is still observed below, so it cannot become unhandled.
|
|
532
|
+
void promise.catch(() => undefined);
|
|
533
|
+
return { started: false, skipReason: "worker_not_started" };
|
|
534
|
+
}
|
|
535
|
+
this._workerPromises.set(startedRecord.laneId, promise);
|
|
536
|
+
void promise.then(() => this._workerPromises.delete(startedRecord?.laneId ?? ""), () => this._workerPromises.delete(startedRecord?.laneId ?? ""));
|
|
537
|
+
return { started: true, record: startedRecord };
|
|
538
|
+
}
|
|
539
|
+
async runWorkerDelegationOnce(request, onStarted, existingRecord) {
|
|
453
540
|
const delegationSettings = this.deps.getSettingsManager().getWorkerDelegationSettings();
|
|
454
|
-
|
|
541
|
+
const activeWorkers = this._laneTracker.getActiveCount("worker") - (existingRecord ? 1 : 0);
|
|
542
|
+
if (activeWorkers >= delegationSettings.maxConcurrent) {
|
|
455
543
|
return { started: false, skipReason: "worker_delegation_already_running" };
|
|
456
544
|
}
|
|
457
545
|
if (this.deps.isDisposed()) {
|
|
@@ -462,6 +550,9 @@ export class BackgroundLaneController {
|
|
|
462
550
|
return { started: false, skipReason: "missing_instructions" };
|
|
463
551
|
}
|
|
464
552
|
const settings = delegationSettings;
|
|
553
|
+
if (!this.deps.isDelegateToolActive()) {
|
|
554
|
+
return { started: false, skipReason: "delegate_tool_inactive" };
|
|
555
|
+
}
|
|
465
556
|
if (!settings.enabled) {
|
|
466
557
|
return { started: false, skipReason: "worker_delegation_disabled" };
|
|
467
558
|
}
|
|
@@ -470,29 +561,45 @@ export class BackgroundLaneController {
|
|
|
470
561
|
return { started: false, skipReason: shipment.skipReason };
|
|
471
562
|
}
|
|
472
563
|
const { model, laneProfile } = shipment;
|
|
564
|
+
const laneCapability = this._laneCapabilityProfile(model);
|
|
565
|
+
if (!laneCapability.backgroundLanesEnabled) {
|
|
566
|
+
return { started: false, skipReason: "model_delegation_unsupported" };
|
|
567
|
+
}
|
|
473
568
|
this._laneTracker.ensureCounterAtLeast(getLaneRecordSnapshots(this.deps.getSessionManager().getEntries()).length + 1);
|
|
474
|
-
const startedRecord = this._laneTracker.start({ type: "worker" });
|
|
569
|
+
const startedRecord = existingRecord ?? this._laneTracker.start({ type: "worker" });
|
|
570
|
+
if (existingRecord)
|
|
571
|
+
this._laneTracker.markRunning(existingRecord.laneId);
|
|
572
|
+
onStarted?.(startedRecord);
|
|
475
573
|
const maxUsd = Math.min(settings.maxUsd, this.deps.getCapabilityEnvelope()?.maxEstimatedUsd ?? Number.POSITIVE_INFINITY);
|
|
574
|
+
const writeEnabled = settings.writeEnabled && settings.writePaths.length > 0;
|
|
575
|
+
const toolSurface = createLaneToolSurface({
|
|
576
|
+
cwd: this.deps.getCwd(),
|
|
577
|
+
profile: laneProfile,
|
|
578
|
+
writeEnabled,
|
|
579
|
+
writePaths: settings.writePaths,
|
|
580
|
+
});
|
|
581
|
+
this._warnUnboundLaneToolGrants(laneProfile, toolSurface);
|
|
582
|
+
const allowedActionOps = new Set(toolSurface.allowedTools.filter((name) => name === "write" || name === "edit"));
|
|
583
|
+
const writeGranted = writeEnabled && allowedActionOps.size > 0;
|
|
476
584
|
const workerRequest = {
|
|
477
585
|
id: startedRecord.laneId,
|
|
478
586
|
instructions,
|
|
479
587
|
route: {
|
|
480
588
|
tier: "cheap",
|
|
481
|
-
risk: "read-only",
|
|
589
|
+
risk: writeGranted ? "scoped-write" : "read-only",
|
|
482
590
|
confidence: 1,
|
|
483
591
|
reasonCode: "scout_worker",
|
|
484
|
-
reasons: ["Read-only scout delegation"],
|
|
592
|
+
reasons: [writeGranted ? "Path-scoped worker delegation" : "Read-only scout delegation"],
|
|
485
593
|
},
|
|
486
594
|
envelope: {
|
|
487
595
|
id: `worker-${this.deps.getSessionId()}-${startedRecord.laneId}`,
|
|
488
596
|
profileId: laneProfile?.name,
|
|
489
597
|
// write_files requires BOTH the opt-in AND an explicit non-empty path scope —
|
|
490
598
|
// an unscoped write grant is refused here, not discovered at validation time.
|
|
491
|
-
capabilities:
|
|
492
|
-
...(
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
...this._laneProfileToolGrants(laneProfile),
|
|
599
|
+
capabilities: writeGranted ? ["read_files", "write_files"] : ["read_files"],
|
|
600
|
+
...(writeGranted ? { allowedPaths: [...settings.writePaths] } : {}),
|
|
601
|
+
allowedTools: [...toolSurface.allowedTools],
|
|
602
|
+
deniedTools: [...toolSurface.deniedTools],
|
|
496
603
|
maxEstimatedUsd: maxUsd,
|
|
497
604
|
createdAt: new Date().toISOString(),
|
|
498
605
|
},
|
|
@@ -513,17 +620,39 @@ export class BackgroundLaneController {
|
|
|
513
620
|
const usageReportId = `worker:${this.deps.getSessionId()}:${startedRecord.laneId}`;
|
|
514
621
|
try {
|
|
515
622
|
let spentUsage;
|
|
623
|
+
const toolChangedFiles = new Set();
|
|
624
|
+
const toolIssues = new Set();
|
|
516
625
|
const outcome = await runWorker({
|
|
517
626
|
request: workerRequest,
|
|
518
627
|
maxUsd,
|
|
519
628
|
maxWallClockMs: settings.maxWallClockMs,
|
|
520
629
|
usageReportId,
|
|
630
|
+
getChangedFiles: () => [...toolChangedFiles],
|
|
521
631
|
signal: this._workerDelegationAbort.signal,
|
|
522
632
|
// Parent validation must use the same relative-path baseline the runner reports in.
|
|
523
633
|
cwd: this.deps.getCwd(),
|
|
524
634
|
// Write lane (G2): runner-side action application through the envelope path scope.
|
|
525
635
|
applyActions: workerRequest.envelope.capabilities.includes("write_files")
|
|
526
|
-
? (actions) =>
|
|
636
|
+
? (actions) => {
|
|
637
|
+
const permitted = actions.filter((action) => allowedActionOps.has(action.op));
|
|
638
|
+
const applied = applyWorkerActions({
|
|
639
|
+
actions: permitted,
|
|
640
|
+
envelope: workerRequest.envelope,
|
|
641
|
+
cwd: this.deps.getCwd(),
|
|
642
|
+
});
|
|
643
|
+
return {
|
|
644
|
+
...applied,
|
|
645
|
+
refused: [
|
|
646
|
+
...actions
|
|
647
|
+
.filter((action) => !allowedActionOps.has(action.op))
|
|
648
|
+
.map((action) => ({
|
|
649
|
+
path: action.path,
|
|
650
|
+
reason: `${action.op} is not granted by the lane profile`,
|
|
651
|
+
})),
|
|
652
|
+
...applied.refused,
|
|
653
|
+
],
|
|
654
|
+
};
|
|
655
|
+
}
|
|
527
656
|
: undefined,
|
|
528
657
|
complete: async ({ systemPrompt, userPrompt, signal }) => {
|
|
529
658
|
const completion = await this.deps.runIsolatedCompletion({
|
|
@@ -537,7 +666,45 @@ export class BackgroundLaneController {
|
|
|
537
666
|
messages: [{ role: "user", content: [{ type: "text", text: userPrompt }], timestamp: Date.now() }],
|
|
538
667
|
model,
|
|
539
668
|
thinkingLevel: laneProfile?.thinking ?? "off",
|
|
540
|
-
maxTokens:
|
|
669
|
+
maxTokens: laneCapability.laneMaxOutputTokens,
|
|
670
|
+
tools: toolSurface.tools,
|
|
671
|
+
maxTurns: 6,
|
|
672
|
+
beforeToolCall: async (context, toolSignal) => {
|
|
673
|
+
const decision = await toolSurface.beforeToolCall(context, toolSignal);
|
|
674
|
+
if (decision?.block) {
|
|
675
|
+
toolIssues.add(`${context.toolCall.name} blocked: ${decision.reason ?? "capability denied"}`);
|
|
676
|
+
}
|
|
677
|
+
return decision;
|
|
678
|
+
},
|
|
679
|
+
afterToolCall: async ({ toolCall, args, isError }) => {
|
|
680
|
+
// This hook runs only for a validated, gate-approved tool that actually entered
|
|
681
|
+
// execution. Record a direct mutation target before inspecting `isError`: write/edit
|
|
682
|
+
// may have changed disk and then observed cancellation, timeout, or a late I/O error.
|
|
683
|
+
// Pre-gate/profile/path refusals never reach afterToolCall, so they remain unreported.
|
|
684
|
+
if (toolCall.name === "write" || toolCall.name === "edit") {
|
|
685
|
+
if (args && typeof args === "object" && !Array.isArray(args)) {
|
|
686
|
+
const rawPath = args.path;
|
|
687
|
+
if (typeof rawPath === "string" && rawPath.length > 0) {
|
|
688
|
+
const absolutePath = path.isAbsolute(rawPath)
|
|
689
|
+
? path.resolve(rawPath)
|
|
690
|
+
: path.resolve(this.deps.getCwd(), rawPath);
|
|
691
|
+
let canonicalPath = absolutePath;
|
|
692
|
+
try {
|
|
693
|
+
canonicalPath = safeRealpathSync(absolutePath);
|
|
694
|
+
}
|
|
695
|
+
catch {
|
|
696
|
+
// Execution was attempted; preserve conservative accounting with the lexical path.
|
|
697
|
+
}
|
|
698
|
+
toolChangedFiles.add(path.relative(this.deps.getCwd(), canonicalPath));
|
|
699
|
+
}
|
|
700
|
+
}
|
|
701
|
+
}
|
|
702
|
+
if (isError) {
|
|
703
|
+
toolIssues.add(`${toolCall.name} failed during isolated execution`);
|
|
704
|
+
return undefined;
|
|
705
|
+
}
|
|
706
|
+
return undefined;
|
|
707
|
+
},
|
|
541
708
|
signal,
|
|
542
709
|
// Core/soul/role are all static per configuration — the provider can cache the prefix.
|
|
543
710
|
cacheRetention: "short",
|
|
@@ -547,6 +714,8 @@ export class BackgroundLaneController {
|
|
|
547
714
|
text: completion.text,
|
|
548
715
|
costUsd: completion.usage.cost.total,
|
|
549
716
|
stopReason: String(completion.stopReason),
|
|
717
|
+
changedFiles: [...toolChangedFiles],
|
|
718
|
+
blockers: [...toolIssues],
|
|
550
719
|
};
|
|
551
720
|
},
|
|
552
721
|
});
|
|
@@ -556,6 +725,8 @@ export class BackgroundLaneController {
|
|
|
556
725
|
status: "canceled",
|
|
557
726
|
reasonCode: "session_disposed",
|
|
558
727
|
});
|
|
728
|
+
if (record)
|
|
729
|
+
this._recordWorkerTerminal(record.status);
|
|
559
730
|
return { started: true, record, outcome };
|
|
560
731
|
}
|
|
561
732
|
this.deps.saveWorkerResultSnapshot(outcome.result, workerRequest);
|
|
@@ -568,6 +739,7 @@ export class BackgroundLaneController {
|
|
|
568
739
|
costUsd: outcome.costUsd,
|
|
569
740
|
});
|
|
570
741
|
if (record) {
|
|
742
|
+
this._recordWorkerTerminal(record.status);
|
|
571
743
|
appendLaneRecordSnapshot(this.deps.getSessionManager(), record);
|
|
572
744
|
// G3: worker lane terminal record -> worker_result event. Lane outcome only
|
|
573
745
|
// (status/reasonCode/cost) — never the worker's summary/changed-file text.
|
|
@@ -590,6 +762,8 @@ export class BackgroundLaneController {
|
|
|
590
762
|
status: "failed",
|
|
591
763
|
reasonCode: "worker_delegation_error",
|
|
592
764
|
});
|
|
765
|
+
if (record)
|
|
766
|
+
this._recordWorkerTerminal(record.status);
|
|
593
767
|
if (record && !this.deps.isDisposed()) {
|
|
594
768
|
appendLaneRecordSnapshot(this.deps.getSessionManager(), record);
|
|
595
769
|
this.deps.emitAutonomyTelemetry({
|
|
@@ -688,6 +862,41 @@ export class BackgroundLaneController {
|
|
|
688
862
|
}
|
|
689
863
|
return { started: true, model: modelRef, report };
|
|
690
864
|
}
|
|
865
|
+
/** Start queued local workers at the owner session's foreground-idle boundary. */
|
|
866
|
+
drainQueuedWorkerDelegations() {
|
|
867
|
+
for (const [laneId, request] of [...this._queuedWorkers]) {
|
|
868
|
+
if (this._laneTracker.getActiveCount("worker") >
|
|
869
|
+
this.deps.getSettingsManager().getWorkerDelegationSettings().maxConcurrent)
|
|
870
|
+
break;
|
|
871
|
+
const record = this._laneTracker.getRecords().find((candidate) => candidate.laneId === laneId);
|
|
872
|
+
if (!record) {
|
|
873
|
+
this._queuedWorkers.delete(laneId);
|
|
874
|
+
continue;
|
|
875
|
+
}
|
|
876
|
+
this._queuedWorkers.delete(laneId);
|
|
877
|
+
const promise = this.runWorkerDelegationOnce(request, undefined, record);
|
|
878
|
+
this._workerPromises.set(laneId, promise);
|
|
879
|
+
void promise.then((outcome) => {
|
|
880
|
+
if (!outcome.started) {
|
|
881
|
+
const terminal = this._laneTracker.complete(laneId, {
|
|
882
|
+
status: "canceled",
|
|
883
|
+
reasonCode: outcome.skipReason,
|
|
884
|
+
});
|
|
885
|
+
if (terminal)
|
|
886
|
+
this._recordWorkerTerminal(terminal.status);
|
|
887
|
+
}
|
|
888
|
+
this._workerPromises.delete(laneId);
|
|
889
|
+
}, () => {
|
|
890
|
+
const terminal = this._laneTracker.complete(laneId, {
|
|
891
|
+
status: "failed",
|
|
892
|
+
reasonCode: "worker_background_error",
|
|
893
|
+
});
|
|
894
|
+
if (terminal)
|
|
895
|
+
this._recordWorkerTerminal(terminal.status);
|
|
896
|
+
this._workerPromises.delete(laneId);
|
|
897
|
+
});
|
|
898
|
+
}
|
|
899
|
+
}
|
|
691
900
|
/** Fitness reports persisted for THIS host (measured evidence for architect/profile decisions). */
|
|
692
901
|
getStoredFitnessReports() {
|
|
693
902
|
try {
|