@caupulican/pi-adaptative 0.80.98 → 0.80.99
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 +23 -0
- package/dist/core/agent-session.d.ts +27 -3
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +200 -11
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/autonomy/foreground-envelope.d.ts +22 -0
- package/dist/core/autonomy/foreground-envelope.d.ts.map +1 -0
- package/dist/core/autonomy/foreground-envelope.js +65 -0
- package/dist/core/autonomy/foreground-envelope.js.map +1 -0
- package/dist/core/autonomy/status.d.ts +11 -0
- package/dist/core/autonomy/status.d.ts.map +1 -1
- package/dist/core/autonomy/status.js.map +1 -1
- package/dist/core/delegation/worker-actions.d.ts +50 -0
- package/dist/core/delegation/worker-actions.d.ts.map +1 -0
- package/dist/core/delegation/worker-actions.js +70 -0
- package/dist/core/delegation/worker-actions.js.map +1 -0
- package/dist/core/delegation/worker-runner.d.ts +9 -0
- package/dist/core/delegation/worker-runner.d.ts.map +1 -1
- package/dist/core/delegation/worker-runner.js +38 -4
- package/dist/core/delegation/worker-runner.js.map +1 -1
- package/dist/core/model-capability.d.ts +19 -0
- package/dist/core/model-capability.d.ts.map +1 -1
- package/dist/core/model-capability.js +19 -0
- package/dist/core/model-capability.js.map +1 -1
- package/dist/core/settings-manager.d.ts +3 -0
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +5 -0
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/settings-selector.js +20 -0
- package/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
- package/examples/extensions/custom-provider-anthropic/package.json +1 -1
- package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
- package/examples/extensions/sandbox/package-lock.json +2 -2
- package/examples/extensions/sandbox/package.json +1 -1
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/npm-shrinkwrap.json +12 -12
- package/package.json +4 -4
|
@@ -21,6 +21,7 @@ import { stripFrontmatter } from "../utils/frontmatter.js";
|
|
|
21
21
|
import { resolvePath } from "../utils/paths.js";
|
|
22
22
|
import { sleep } from "../utils/sleep.js";
|
|
23
23
|
import { formatNoApiKeyFoundMessage, formatNoModelSelectedMessage } from "./auth-guidance.js";
|
|
24
|
+
import { buildForegroundEnvelope, formatForegroundEnvelopeObservation } from "./autonomy/foreground-envelope.js";
|
|
24
25
|
import { evaluateToolGate } from "./autonomy/gates.js";
|
|
25
26
|
import { LaneTracker } from "./autonomy/lane-tracker.js";
|
|
26
27
|
import { appendLaneRecordSnapshot, getLaneRecordSnapshots } from "./autonomy/session-lane-record.js";
|
|
@@ -45,6 +46,7 @@ import { aggregateDailyUsageFromSessionFiles, aggregateDailyUsageFromSessionRoot
|
|
|
45
46
|
import { downgradeReasoning, estimateTurnCostUsd, evaluateCostGuard } from "./cost-guard.js";
|
|
46
47
|
import { DEFAULT_THINKING_LEVEL } from "./defaults.js";
|
|
47
48
|
import { appendWorkerResultSnapshot, getWorkerResultSnapshots } from "./delegation/session-worker-result.js";
|
|
49
|
+
import { applyWorkerActions } from "./delegation/worker-actions.js";
|
|
48
50
|
import { runWorker } from "./delegation/worker-runner.js";
|
|
49
51
|
import { exportSessionToHtml } from "./export-html/index.js";
|
|
50
52
|
import { createToolHtmlRenderer } from "./export-html/tool-renderer.js";
|
|
@@ -68,7 +70,7 @@ import { FileStoreProvider } from "./memory/providers/file-store.js";
|
|
|
68
70
|
import { TranscriptRecallProvider } from "./memory/providers/transcript-recall.js";
|
|
69
71
|
import { compactToolResultDetailsForRetention } from "./message-retention.js";
|
|
70
72
|
import { createCustomMessage } from "./messages.js";
|
|
71
|
-
import { deriveModelCapabilityProfile, filterToolNamesForCapability, } from "./model-capability.js";
|
|
73
|
+
import { deriveModelCapabilityProfile, filterToolNamesForCapability, scaleContinuationBudgetsForCapability, } from "./model-capability.js";
|
|
72
74
|
import { resolveCliModel, resolveProfileModelSettings } from "./model-resolver.js";
|
|
73
75
|
import { collectModelRouterConfigDiagnostics } from "./model-router/config-diagnostics.js";
|
|
74
76
|
import { classifyExecutorTurn } from "./model-router/executor-route.js";
|
|
@@ -149,6 +151,8 @@ function persistModelRouterDecision(sessionManager, decision) {
|
|
|
149
151
|
/** Custom-entry type for G3 autonomy telemetry. Distinct from the router/lane record types so a
|
|
150
152
|
* telemetry consumer can filter on it without decoding operational snapshots. */
|
|
151
153
|
const AUTONOMY_TELEMETRY_CUSTOM_TYPE = "autonomy-telemetry";
|
|
154
|
+
/** G8: bound on the in-memory gate-outcome history. Oldest entries evict once the cap is reached. */
|
|
155
|
+
const GATE_OUTCOME_HISTORY_LIMIT = 50;
|
|
152
156
|
/** Read a packed grep/find tool result's `details.artifactId`, if present, without `any`. */
|
|
153
157
|
function extractArtifactId(message) {
|
|
154
158
|
if (!message || message.role !== "toolResult")
|
|
@@ -218,8 +222,6 @@ export class AgentSession {
|
|
|
218
222
|
_laneTracker = new LaneTracker();
|
|
219
223
|
/** Session-lifetime abort for in-flight research passes (same pattern as _reflectionAbort). */
|
|
220
224
|
_researchLaneAbort = new AbortController();
|
|
221
|
-
/** Single-flight guard: at most one delegated worker runs at a time per session. */
|
|
222
|
-
_isWorkerDelegationRunning = false;
|
|
223
225
|
/** Session-lifetime abort for in-flight delegated workers. */
|
|
224
226
|
_workerDelegationAbort = new AbortController();
|
|
225
227
|
/**
|
|
@@ -258,6 +260,8 @@ export class AgentSession {
|
|
|
258
260
|
// Extension system
|
|
259
261
|
_extensionRunner;
|
|
260
262
|
_turnIndex = 0;
|
|
263
|
+
/** G7: per-turn foreground CapabilityEnvelope auto-built for visibility (observe-only; not enforced). */
|
|
264
|
+
_currentForegroundEnvelope;
|
|
261
265
|
_resourceLoader;
|
|
262
266
|
_customTools;
|
|
263
267
|
_baseToolDefinitions = new Map();
|
|
@@ -292,6 +296,8 @@ export class AgentSession {
|
|
|
292
296
|
_isModelRouterRetry = false;
|
|
293
297
|
_lastModelRouterDecision;
|
|
294
298
|
_lastAutonomyGateOutcome;
|
|
299
|
+
/** G8: bounded (cap {@link GATE_OUTCOME_HISTORY_LIMIT}) history of gate outcomes; tail is latest. */
|
|
300
|
+
_gateOutcomeHistory = [];
|
|
295
301
|
_lastModelRouterSkipReason;
|
|
296
302
|
_lastModelRouterIntent;
|
|
297
303
|
/** Lazily-built skill curator (#32) over `<agentDir>/skills`. */
|
|
@@ -1014,6 +1020,9 @@ export class AgentSession {
|
|
|
1014
1020
|
...this._resourceLoader.getAgentsDiagnostics().map((diagnostic) => diagnostic.message),
|
|
1015
1021
|
...this._inertExtensionWarnings,
|
|
1016
1022
|
...this._unboundToolGrantWarnings,
|
|
1023
|
+
// G7: auto-built per-turn foreground envelope (observe-only; not enforced). Falls back to a
|
|
1024
|
+
// live preview when no turn has run yet so /context always shows the current scope.
|
|
1025
|
+
formatForegroundEnvelopeObservation(this._currentForegroundEnvelope ?? this._buildForegroundEnvelopeFromState()),
|
|
1017
1026
|
// G14 (ratified): a user disable always beats a profile grant — surface the conflict.
|
|
1018
1027
|
...["tools", "skills", "prompts", "extensions"].flatMap((kind) => this.settingsManager
|
|
1019
1028
|
.getProfileGrantsOverriddenByUserDisable(kind)
|
|
@@ -1351,7 +1360,7 @@ export class AgentSession {
|
|
|
1351
1360
|
envelope: this.capabilityEnvelope,
|
|
1352
1361
|
});
|
|
1353
1362
|
if (this.capabilityEnvelope) {
|
|
1354
|
-
this.
|
|
1363
|
+
this._recordGateOutcome(gateResult);
|
|
1355
1364
|
}
|
|
1356
1365
|
if (gateResult.outcome === "block" || gateResult.outcome === "ask-user") {
|
|
1357
1366
|
return {
|
|
@@ -1568,6 +1577,7 @@ export class AgentSession {
|
|
|
1568
1577
|
await this._extensionRunner.emit({ type: "agent_end", messages: event.messages });
|
|
1569
1578
|
}
|
|
1570
1579
|
else if (event.type === "turn_start") {
|
|
1580
|
+
this._refreshForegroundEnvelope();
|
|
1571
1581
|
const extensionEvent = {
|
|
1572
1582
|
type: "turn_start",
|
|
1573
1583
|
turnIndex: this._turnIndex,
|
|
@@ -1789,6 +1799,31 @@ export class AgentSession {
|
|
|
1789
1799
|
getActiveToolNames() {
|
|
1790
1800
|
return this.agent.state.tools.map((t) => t.name);
|
|
1791
1801
|
}
|
|
1802
|
+
/** G7: build a foreground {@link CapabilityEnvelope} from the live session state (active tools, cwd, cost ceiling). */
|
|
1803
|
+
_buildForegroundEnvelopeFromState() {
|
|
1804
|
+
return buildForegroundEnvelope({
|
|
1805
|
+
turnIndex: this._turnIndex,
|
|
1806
|
+
activeToolNames: this.getActiveToolNames(),
|
|
1807
|
+
cwd: this._cwd,
|
|
1808
|
+
maxTurnUsd: this.settingsManager.getCostGuardSettings().maxTurnUsd,
|
|
1809
|
+
});
|
|
1810
|
+
}
|
|
1811
|
+
/**
|
|
1812
|
+
* G7: (re)build the foreground envelope for the current turn. Visibility only -- the foreground
|
|
1813
|
+
* envelope is NOT enforced this round. Best-effort: never throws into the turn.
|
|
1814
|
+
*/
|
|
1815
|
+
_refreshForegroundEnvelope() {
|
|
1816
|
+
try {
|
|
1817
|
+
this._currentForegroundEnvelope = this._buildForegroundEnvelopeFromState();
|
|
1818
|
+
}
|
|
1819
|
+
catch {
|
|
1820
|
+
// Visibility only: a failure to build the envelope must never disturb the turn.
|
|
1821
|
+
}
|
|
1822
|
+
}
|
|
1823
|
+
/** G7: the auto-constructed foreground envelope for the current/most-recent turn (visibility only). */
|
|
1824
|
+
getForegroundEnvelope() {
|
|
1825
|
+
return this._currentForegroundEnvelope;
|
|
1826
|
+
}
|
|
1792
1827
|
/**
|
|
1793
1828
|
* Get all configured tools with name, description, parameter schema, prompt guidelines, and source metadata.
|
|
1794
1829
|
*/
|
|
@@ -2092,6 +2127,59 @@ export class AgentSession {
|
|
|
2092
2127
|
return undefined;
|
|
2093
2128
|
}
|
|
2094
2129
|
}
|
|
2130
|
+
/** True if a run_toolkit_script tool result since `fromIndex` actually EXECUTED (not error/ambiguous). */
|
|
2131
|
+
_executorTurnExecutedScript(fromIndex) {
|
|
2132
|
+
for (const message of this.agent.state.messages.slice(fromIndex)) {
|
|
2133
|
+
if (message.role !== "toolResult")
|
|
2134
|
+
continue;
|
|
2135
|
+
if (message.toolName !== "run_toolkit_script")
|
|
2136
|
+
continue;
|
|
2137
|
+
if (message.isError === true)
|
|
2138
|
+
continue;
|
|
2139
|
+
const outcome = message.details?.outcome;
|
|
2140
|
+
if (outcome === "executed")
|
|
2141
|
+
return true;
|
|
2142
|
+
}
|
|
2143
|
+
return false;
|
|
2144
|
+
}
|
|
2145
|
+
/** Ask the reflex brain to refine the last user request into an explicit toolkit instruction. */
|
|
2146
|
+
async _buildExecutorRefinedPrompt(messages) {
|
|
2147
|
+
try {
|
|
2148
|
+
const model = this._resolveCurationModelIfFit();
|
|
2149
|
+
if (!model)
|
|
2150
|
+
return undefined;
|
|
2151
|
+
const list = Array.isArray(messages) ? messages : [messages];
|
|
2152
|
+
const request = latestUserPromptText(list.filter((m) => true));
|
|
2153
|
+
if (!request)
|
|
2154
|
+
return undefined;
|
|
2155
|
+
const scripts = this.settingsManager.getToolkitScripts();
|
|
2156
|
+
const completion = await this.runIsolatedCompletion({
|
|
2157
|
+
systemPrompt: REFLEX_INTERPRETER_SYSTEM_PROMPT,
|
|
2158
|
+
messages: [
|
|
2159
|
+
{
|
|
2160
|
+
role: "user",
|
|
2161
|
+
content: [{ type: "text", text: buildReflexUserPrompt(request, scripts) }],
|
|
2162
|
+
timestamp: Date.now(),
|
|
2163
|
+
},
|
|
2164
|
+
],
|
|
2165
|
+
model,
|
|
2166
|
+
thinkingLevel: "off",
|
|
2167
|
+
maxTokens: 256,
|
|
2168
|
+
cacheRetention: "short",
|
|
2169
|
+
});
|
|
2170
|
+
if (completion.usage.cost.total > 0 || completion.usage.totalTokens > 0) {
|
|
2171
|
+
this.addSpawnedUsage(completion.usage, { label: "executor-brain-warmup" });
|
|
2172
|
+
}
|
|
2173
|
+
const plan = parseReflexPlan(completion.text);
|
|
2174
|
+
if (!plan || plan.script === "none")
|
|
2175
|
+
return undefined;
|
|
2176
|
+
const argHint = plan.args.length > 0 ? ` with args ${JSON.stringify(plan.args)}` : "";
|
|
2177
|
+
return `Run the toolkit script "${plan.script}"${argHint} using run_toolkit_script, then report its result exactly.`;
|
|
2178
|
+
}
|
|
2179
|
+
catch {
|
|
2180
|
+
return undefined;
|
|
2181
|
+
}
|
|
2182
|
+
}
|
|
2095
2183
|
_resolveModelRouterTurnRoute(prompt) {
|
|
2096
2184
|
const settings = this.settingsManager.getModelRouterSettings();
|
|
2097
2185
|
if (!settings.enabled) {
|
|
@@ -2328,6 +2416,36 @@ export class AgentSession {
|
|
|
2328
2416
|
}
|
|
2329
2417
|
try {
|
|
2330
2418
|
await this._runAgentPrompt(messages);
|
|
2419
|
+
// Speculative muscle-retry (G16 refinement): an executor-routed turn is a bet that the
|
|
2420
|
+
// small model can run the toolkit command directly. If it ends WITHOUT a successful
|
|
2421
|
+
// run_toolkit_script execution, retry ONCE on the same executor with the brain's
|
|
2422
|
+
// refined instruction injected — the brain warms while the muscle tries, so the retry
|
|
2423
|
+
// pays only when the muscle actually missed.
|
|
2424
|
+
if (routeDecision?.reasonCode === "executor_direct" &&
|
|
2425
|
+
!this._isModelRouterRetry &&
|
|
2426
|
+
!this._executorTurnExecutedScript(originalHistoryLength)) {
|
|
2427
|
+
const refined = await this._buildExecutorRefinedPrompt(messages);
|
|
2428
|
+
if (refined) {
|
|
2429
|
+
this.agent.state.messages.splice(originalHistoryLength);
|
|
2430
|
+
await this._runAgentPrompt([
|
|
2431
|
+
{ role: "user", content: [{ type: "text", text: refined }], timestamp: Date.now() },
|
|
2432
|
+
]);
|
|
2433
|
+
completedDecision = {
|
|
2434
|
+
route: {
|
|
2435
|
+
...routeDecision,
|
|
2436
|
+
reasonCode: "executor_speculative_retry",
|
|
2437
|
+
reasons: [
|
|
2438
|
+
...routeDecision.reasons,
|
|
2439
|
+
"Executor missed on first try; retried with brain-refined instruction",
|
|
2440
|
+
],
|
|
2441
|
+
},
|
|
2442
|
+
routedModel: formatModelRouterModel(routedModel),
|
|
2443
|
+
outcome: "routed",
|
|
2444
|
+
intent: "research",
|
|
2445
|
+
};
|
|
2446
|
+
this._lastModelRouterDecision = completedDecision;
|
|
2447
|
+
}
|
|
2448
|
+
}
|
|
2331
2449
|
if (bufferRoutedTurn && this._modelRouterEscalationRequested) {
|
|
2332
2450
|
this.agent.state.messages.splice(originalHistoryLength);
|
|
2333
2451
|
retryModel = this._resolveModelRouterModelForIntent("modify") ?? previousModel;
|
|
@@ -5101,6 +5219,40 @@ export class AgentSession {
|
|
|
5101
5219
|
// Telemetry is best-effort: swallow so a sink failure cannot break the observed turn.
|
|
5102
5220
|
}
|
|
5103
5221
|
}
|
|
5222
|
+
/**
|
|
5223
|
+
* G8: single sink for a gate outcome. Keeps the latest-outcome getter behavior identical (the
|
|
5224
|
+
* full {@link GateOutcome} still lands in `_lastAutonomyGateOutcome`), and additionally appends a
|
|
5225
|
+
* bounded codes-only entry to {@link _gateOutcomeHistory} (oldest evicted at
|
|
5226
|
+
* {@link GATE_OUTCOME_HISTORY_LIMIT}) and emits the `gate_outcome` telemetry event. The history
|
|
5227
|
+
* tail therefore always mirrors the latest outcome. Only called with an active envelope.
|
|
5228
|
+
*/
|
|
5229
|
+
_recordGateOutcome(outcome) {
|
|
5230
|
+
this._lastAutonomyGateOutcome = outcome;
|
|
5231
|
+
const at = new Date().toISOString();
|
|
5232
|
+
this._gateOutcomeHistory.push({
|
|
5233
|
+
outcome: outcome.outcome,
|
|
5234
|
+
gate: outcome.gate,
|
|
5235
|
+
reasonCode: outcome.reasonCode,
|
|
5236
|
+
at,
|
|
5237
|
+
});
|
|
5238
|
+
while (this._gateOutcomeHistory.length > GATE_OUTCOME_HISTORY_LIMIT) {
|
|
5239
|
+
this._gateOutcomeHistory.shift();
|
|
5240
|
+
}
|
|
5241
|
+
// G8: gate outcome event. Codes/ids only — never the gate's human-facing message.
|
|
5242
|
+
this._emitAutonomyTelemetry({
|
|
5243
|
+
type: AUTONOMY_TELEMETRY_EVENT_TYPES.gateOutcome,
|
|
5244
|
+
timestamp: at,
|
|
5245
|
+
payload: {
|
|
5246
|
+
outcome: outcome.outcome,
|
|
5247
|
+
gate: outcome.gate,
|
|
5248
|
+
reasonCode: outcome.reasonCode,
|
|
5249
|
+
},
|
|
5250
|
+
});
|
|
5251
|
+
}
|
|
5252
|
+
/** G8: copies of the bounded gate-outcome history, oldest first, latest last. */
|
|
5253
|
+
getGateOutcomeHistory() {
|
|
5254
|
+
return this._gateOutcomeHistory.map((entry) => ({ ...entry }));
|
|
5255
|
+
}
|
|
5104
5256
|
saveWorkerResultSnapshot(result, request) {
|
|
5105
5257
|
return appendWorkerResultSnapshot(this.sessionManager, result, request);
|
|
5106
5258
|
}
|
|
@@ -5157,12 +5309,17 @@ export class AgentSession {
|
|
|
5157
5309
|
const snapshot = this.getGoalRuntimeSnapshot({ maxStallTurns });
|
|
5158
5310
|
if (snapshot.continuation.action !== "continue")
|
|
5159
5311
|
return;
|
|
5312
|
+
// Lean-window models (16-32k) keep autosteer but at a reduced budget; full passes through.
|
|
5313
|
+
const scaled = scaleContinuationBudgetsForCapability(this.getModelCapabilityProfile(), {
|
|
5314
|
+
maxTurns: goalContinueTurns,
|
|
5315
|
+
maxWallClockMinutes: goalContinueMaxWallClockMinutes,
|
|
5316
|
+
});
|
|
5160
5317
|
this._isGoalAutoContinuing = true;
|
|
5161
5318
|
try {
|
|
5162
5319
|
await this.continueGoalLoop({
|
|
5163
|
-
maxTurns:
|
|
5320
|
+
maxTurns: scaled.maxTurns,
|
|
5164
5321
|
maxStallTurns,
|
|
5165
|
-
maxWallClockMinutes:
|
|
5322
|
+
maxWallClockMinutes: scaled.maxWallClockMinutes,
|
|
5166
5323
|
});
|
|
5167
5324
|
}
|
|
5168
5325
|
catch (error) {
|
|
@@ -5500,7 +5657,8 @@ export class AgentSession {
|
|
|
5500
5657
|
* usage (idempotent per-lane reportId). Consumed by the `delegate` tool.
|
|
5501
5658
|
*/
|
|
5502
5659
|
async runWorkerDelegationOnce(request) {
|
|
5503
|
-
|
|
5660
|
+
const delegationSettings = this.settingsManager.getWorkerDelegationSettings();
|
|
5661
|
+
if (this._laneTracker.getActiveCount("worker") >= delegationSettings.maxConcurrent) {
|
|
5504
5662
|
return { started: false, skipReason: "worker_delegation_already_running" };
|
|
5505
5663
|
}
|
|
5506
5664
|
if (this._disposed) {
|
|
@@ -5510,7 +5668,7 @@ export class AgentSession {
|
|
|
5510
5668
|
if (instructions.length === 0) {
|
|
5511
5669
|
return { started: false, skipReason: "missing_instructions" };
|
|
5512
5670
|
}
|
|
5513
|
-
const settings =
|
|
5671
|
+
const settings = delegationSettings;
|
|
5514
5672
|
if (!settings.enabled) {
|
|
5515
5673
|
return { started: false, skipReason: "worker_delegation_disabled" };
|
|
5516
5674
|
}
|
|
@@ -5519,7 +5677,6 @@ export class AgentSession {
|
|
|
5519
5677
|
return { started: false, skipReason: shipment.skipReason };
|
|
5520
5678
|
}
|
|
5521
5679
|
const { model, laneProfile } = shipment;
|
|
5522
|
-
this._isWorkerDelegationRunning = true;
|
|
5523
5680
|
this._laneTracker.ensureCounterAtLeast(getLaneRecordSnapshots(this.sessionManager.getEntries()).length + 1);
|
|
5524
5681
|
const startedRecord = this._laneTracker.start({ type: "worker" });
|
|
5525
5682
|
const maxUsd = Math.min(settings.maxUsd, this.capabilityEnvelope?.maxEstimatedUsd ?? Number.POSITIVE_INFINITY);
|
|
@@ -5536,7 +5693,12 @@ export class AgentSession {
|
|
|
5536
5693
|
envelope: {
|
|
5537
5694
|
id: `worker-${this.sessionId}-${startedRecord.laneId}`,
|
|
5538
5695
|
profileId: laneProfile?.name,
|
|
5539
|
-
|
|
5696
|
+
// write_files requires BOTH the opt-in AND an explicit non-empty path scope —
|
|
5697
|
+
// an unscoped write grant is refused here, not discovered at validation time.
|
|
5698
|
+
capabilities: settings.writeEnabled && settings.writePaths.length > 0 ? ["read_files", "write_files"] : ["read_files"],
|
|
5699
|
+
...(settings.writeEnabled && settings.writePaths.length > 0
|
|
5700
|
+
? { allowedPaths: [...settings.writePaths] }
|
|
5701
|
+
: {}),
|
|
5540
5702
|
...this._laneProfileToolGrants(laneProfile),
|
|
5541
5703
|
maxEstimatedUsd: maxUsd,
|
|
5542
5704
|
createdAt: new Date().toISOString(),
|
|
@@ -5544,6 +5706,17 @@ export class AgentSession {
|
|
|
5544
5706
|
maxEstimatedUsd: maxUsd,
|
|
5545
5707
|
createdAt: new Date().toISOString(),
|
|
5546
5708
|
};
|
|
5709
|
+
// G8: worker delegation START. Routing/scope codes + budget only — never the instructions text.
|
|
5710
|
+
this._emitAutonomyTelemetry({
|
|
5711
|
+
type: AUTONOMY_TELEMETRY_EVENT_TYPES.workerRequest,
|
|
5712
|
+
timestamp: new Date().toISOString(),
|
|
5713
|
+
payload: {
|
|
5714
|
+
id: workerRequest.id,
|
|
5715
|
+
tier: workerRequest.route.tier,
|
|
5716
|
+
capabilities: [...workerRequest.envelope.capabilities],
|
|
5717
|
+
maxEstimatedUsd: workerRequest.maxEstimatedUsd ?? null,
|
|
5718
|
+
},
|
|
5719
|
+
});
|
|
5547
5720
|
const usageReportId = `worker:${this.sessionId}:${startedRecord.laneId}`;
|
|
5548
5721
|
try {
|
|
5549
5722
|
let spentUsage;
|
|
@@ -5553,6 +5726,10 @@ export class AgentSession {
|
|
|
5553
5726
|
maxWallClockMs: settings.maxWallClockMs,
|
|
5554
5727
|
usageReportId,
|
|
5555
5728
|
signal: this._workerDelegationAbort.signal,
|
|
5729
|
+
// Write lane (G2): runner-side action application through the envelope path scope.
|
|
5730
|
+
applyActions: workerRequest.envelope.capabilities.includes("write_files")
|
|
5731
|
+
? (actions) => applyWorkerActions({ actions, envelope: workerRequest.envelope, cwd: this._cwd })
|
|
5732
|
+
: undefined,
|
|
5556
5733
|
complete: async ({ systemPrompt, userPrompt, signal }) => {
|
|
5557
5734
|
const completion = await this.runIsolatedCompletion({
|
|
5558
5735
|
// Level-0 core always survives. A model-provided prompt (delegate tool) is the most
|
|
@@ -5637,7 +5814,6 @@ export class AgentSession {
|
|
|
5637
5814
|
return { started: true, record };
|
|
5638
5815
|
}
|
|
5639
5816
|
finally {
|
|
5640
|
-
this._isWorkerDelegationRunning = false;
|
|
5641
5817
|
}
|
|
5642
5818
|
}
|
|
5643
5819
|
/**
|
|
@@ -5958,6 +6134,19 @@ export class AgentSession {
|
|
|
5958
6134
|
requiresApproval: decision.requiresApproval,
|
|
5959
6135
|
},
|
|
5960
6136
|
});
|
|
6137
|
+
// G8: a proposal that needs human sign-off is an approval REQUEST. Codes/layer only —
|
|
6138
|
+
// never the proposal summary/memory text (those live only in the audit snapshot).
|
|
6139
|
+
if (decision.requiresApproval) {
|
|
6140
|
+
this._emitAutonomyTelemetry({
|
|
6141
|
+
type: AUTONOMY_TELEMETRY_EVENT_TYPES.approvalRequest,
|
|
6142
|
+
timestamp: new Date().toISOString(),
|
|
6143
|
+
payload: {
|
|
6144
|
+
kind: decision.kind,
|
|
6145
|
+
reasonCode: decision.reasonCode,
|
|
6146
|
+
layer: proposal.layer,
|
|
6147
|
+
},
|
|
6148
|
+
});
|
|
6149
|
+
}
|
|
5961
6150
|
if (decision.kind === "apply") {
|
|
5962
6151
|
await this._applyReflectionWrite(write, signal);
|
|
5963
6152
|
}
|