pi-background-tasks 2.5.0 → 2.6.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/BACKGROUND-TASKS-INSTRUCTIONS.md +1 -1
- package/README.md +70 -25
- package/TESTING.md +42 -2
- package/TEST_PLAN.md +7 -4
- package/dist/extensions/anthropic-attribution-child.js +4 -0
- package/dist/extensions/anthropic-attribution-child.js.map +1 -0
- package/dist/extensions/anthropic-attribution.js +107 -0
- package/dist/extensions/anthropic-attribution.js.map +1 -0
- package/dist/extensions/background-tasks.js +2 -0
- package/dist/extensions/background-tasks.js.map +1 -0
- package/dist/extensions/delegate-child.js +2 -0
- package/dist/extensions/delegate-child.js.map +1 -0
- package/dist/extensions/fusion-child.js +2 -0
- package/dist/extensions/fusion-child.js.map +1 -0
- package/dist/package.json +5 -0
- package/dist/src/core/anthropic-attribution-path.js +24 -0
- package/dist/src/core/anthropic-attribution-path.js.map +1 -0
- package/dist/src/core/anthropic-attribution.js +2247 -0
- package/dist/src/core/anthropic-attribution.js.map +1 -0
- package/dist/src/core/attested-pi-contract.js +5 -0
- package/dist/src/core/attested-pi-contract.js.map +1 -0
- package/dist/src/core/attested-pi-run.js +749 -0
- package/dist/src/core/attested-pi-run.js.map +1 -0
- package/dist/src/core/canonical-json.js +19 -0
- package/dist/src/core/canonical-json.js.map +1 -0
- package/dist/src/core/common.js +787 -0
- package/dist/src/core/common.js.map +1 -0
- package/dist/src/core/config.js +78 -0
- package/dist/src/core/config.js.map +1 -0
- package/dist/src/core/context/parent-snapshot.js +75 -0
- package/dist/src/core/context/parent-snapshot.js.map +1 -0
- package/dist/src/core/context/token-budget.js +631 -0
- package/dist/src/core/context/token-budget.js.map +1 -0
- package/dist/src/core/context/visible-conversation-v2.js +390 -0
- package/dist/src/core/context/visible-conversation-v2.js.map +1 -0
- package/dist/src/core/delegate/artifacts.js +357 -0
- package/dist/src/core/delegate/artifacts.js.map +1 -0
- package/dist/src/core/delegate/budget.js +266 -0
- package/dist/src/core/delegate/budget.js.map +1 -0
- package/dist/src/core/delegate/facade-contract.js +7 -0
- package/dist/src/core/delegate/facade-contract.js.map +1 -0
- package/dist/src/core/delegate/hook-contract-evidence.json +18 -0
- package/dist/src/core/delegate/hook-contract.js +124 -0
- package/dist/src/core/delegate/hook-contract.js.map +1 -0
- package/dist/src/core/delegate/launch.js +366 -0
- package/dist/src/core/delegate/launch.js.map +1 -0
- package/dist/src/core/delegate/result-package.js +293 -0
- package/dist/src/core/delegate/result-package.js.map +1 -0
- package/dist/src/core/delegate/runner.js +398 -0
- package/dist/src/core/delegate/runner.js.map +1 -0
- package/dist/src/core/delegate/seed.js +334 -0
- package/dist/src/core/delegate/seed.js.map +1 -0
- package/dist/src/core/delegate/types.js +103 -0
- package/dist/src/core/delegate/types.js.map +1 -0
- package/dist/src/core/durable-fs.js +372 -0
- package/dist/src/core/durable-fs.js.map +1 -0
- package/dist/src/core/extension-api.js +382 -0
- package/dist/src/core/extension-api.js.map +1 -0
- package/dist/src/core/fusion/artifacts.js +654 -0
- package/dist/src/core/fusion/artifacts.js.map +1 -0
- package/dist/src/core/fusion/budget.js +949 -0
- package/dist/src/core/fusion/budget.js.map +1 -0
- package/dist/src/core/fusion/child-protocol.js +176 -0
- package/dist/src/core/fusion/child-protocol.js.map +1 -0
- package/dist/src/core/fusion/claude-cache.js +156 -0
- package/dist/src/core/fusion/claude-cache.js.map +1 -0
- package/dist/src/core/fusion/clean-context.js +64 -0
- package/dist/src/core/fusion/clean-context.js.map +1 -0
- package/dist/src/core/fusion/config.js +349 -0
- package/dist/src/core/fusion/config.js.map +1 -0
- package/dist/src/core/fusion/context.js +184 -0
- package/dist/src/core/fusion/context.js.map +1 -0
- package/dist/src/core/fusion/evaluation.js +696 -0
- package/dist/src/core/fusion/evaluation.js.map +1 -0
- package/dist/src/core/fusion/facade-contract.js +3 -0
- package/dist/src/core/fusion/facade-contract.js.map +1 -0
- package/dist/src/core/fusion/orchestrator.js +867 -0
- package/dist/src/core/fusion/orchestrator.js.map +1 -0
- package/dist/src/core/fusion/output-contract.js +27 -0
- package/dist/src/core/fusion/output-contract.js.map +1 -0
- package/dist/src/core/fusion/pi-child.js +1741 -0
- package/dist/src/core/fusion/pi-child.js.map +1 -0
- package/dist/src/core/fusion/prompts.js +260 -0
- package/dist/src/core/fusion/prompts.js.map +1 -0
- package/dist/src/core/fusion/result-package.js +857 -0
- package/dist/src/core/fusion/result-package.js.map +1 -0
- package/dist/src/core/fusion/source-policy.js +259 -0
- package/dist/src/core/fusion/source-policy.js.map +1 -0
- package/dist/src/core/fusion/types.js +207 -0
- package/dist/src/core/fusion/types.js.map +1 -0
- package/dist/src/core/fusion/web-fetch.js +777 -0
- package/dist/src/core/fusion/web-fetch.js.map +1 -0
- package/dist/src/core/fusion/workflows.js +126 -0
- package/dist/src/core/fusion/workflows.js.map +1 -0
- package/dist/src/core/lazy-module.js +181 -0
- package/dist/src/core/lazy-module.js.map +1 -0
- package/dist/src/core/pi-launch.js +431 -0
- package/dist/src/core/pi-launch.js.map +1 -0
- package/dist/src/core/registry.js +3331 -0
- package/dist/src/core/registry.js.map +1 -0
- package/dist/src/core/reload-shell-owner.js +1396 -0
- package/dist/src/core/reload-shell-owner.js.map +1 -0
- package/dist/src/core/shell-policy.js +80 -0
- package/dist/src/core/shell-policy.js.map +1 -0
- package/dist/src/core/task-durable.js +51 -0
- package/dist/src/core/task-durable.js.map +1 -0
- package/dist/src/core/update-check.js +92 -0
- package/dist/src/core/update-check.js.map +1 -0
- package/dist/src/core/windows-taskkill.js +185 -0
- package/dist/src/core/windows-taskkill.js.map +1 -0
- package/dist/src/delegate-child-extension.js +776 -0
- package/dist/src/delegate-child-extension.js.map +1 -0
- package/dist/src/delegate-extension.js +746 -0
- package/dist/src/delegate-extension.js.map +1 -0
- package/dist/src/extension.js +953 -0
- package/dist/src/extension.js.map +1 -0
- package/dist/src/fusion-child-extension.js +760 -0
- package/dist/src/fusion-child-extension.js.map +1 -0
- package/dist/src/fusion-extension.js +1030 -0
- package/dist/src/fusion-extension.js.map +1 -0
- package/dist/src/ui/background-tasks-manager.js +689 -0
- package/dist/src/ui/background-tasks-manager.js.map +1 -0
- package/dist/src/ui/fusion-model-selector.js +277 -0
- package/dist/src/ui/fusion-model-selector.js.map +1 -0
- package/docs/INDEX.md +35 -33
- package/docs/api/eventbus-v1.md +21 -5
- package/docs/choose-a-workflow.md +2 -0
- package/docs/commands/bg-clear.md +3 -3
- package/docs/commands/bg-update.md +3 -3
- package/docs/commands/bg.md +18 -6
- package/docs/commands/claude-cache.md +4 -4
- package/docs/commands/fusion-models.md +49 -4
- package/docs/commands/fusion.md +3 -3
- package/docs/commands/jobs.md +3 -3
- package/docs/commands/kill.md +3 -3
- package/docs/commands/logs.md +3 -3
- package/docs/commands/task-manager.md +5 -5
- package/docs/concepts/completion-delivery.md +6 -2
- package/docs/getting-started.md +7 -1
- package/docs/manifest.json +228 -42
- package/docs/operations/configuration.md +58 -5
- package/docs/operations/releasing.md +4 -2
- package/docs/operations/testing.md +22 -0
- package/docs/operations/troubleshooting.md +6 -2
- package/docs/read-before-edit.md +44 -31
- package/docs/reference/runtime-contracts.md +87 -51
- package/docs/reference/shortcuts-and-dock.md +28 -14
- package/docs/subsystems/anthropic-attribution.md +23 -11
- package/docs/subsystems/attested-pi-runs.md +12 -7
- package/docs/subsystems/background-task-runtime.md +53 -11
- package/docs/subsystems/child-launch-durability-and-safety.md +28 -9
- package/docs/subsystems/delegation.md +16 -3
- package/docs/subsystems/docs-freshness-gate.md +14 -7
- package/docs/subsystems/fusion.md +36 -11
- package/docs/subsystems/host-ui-and-telemetry.md +22 -9
- package/docs/tools/bg_delegate.md +3 -1
- package/docs/tools/bg_kill.md +3 -1
- package/docs/tools/bg_logs.md +3 -1
- package/docs/tools/bg_result.md +5 -3
- package/docs/tools/bg_run.md +31 -5
- package/docs/tools/bg_run_pi_attested.md +3 -1
- package/docs/tools/bg_status.md +3 -1
- package/docs/tools/fusion_investigate.md +3 -1
- package/docs/tools/fusion_reason.md +3 -1
- package/docs/tools/fusion_research.md +3 -1
- package/docs/tools/fusion_validate.md +3 -1
- package/extensions/anthropic-attribution-child.ts +3 -0
- package/extensions/anthropic-attribution.ts +166 -1
- package/package.json +12 -10
- package/src/core/anthropic-attribution-path.ts +5 -4
- package/src/core/anthropic-attribution.ts +293 -113
- package/src/core/attested-pi-contract.ts +4 -0
- package/src/core/attested-pi-run.ts +468 -81
- package/src/core/canonical-json.ts +21 -0
- package/src/core/common.ts +450 -40
- package/src/core/config.ts +121 -0
- package/src/core/context/visible-conversation-v2.ts +3 -6
- package/src/core/delegate/artifacts.ts +13 -9
- package/src/core/delegate/budget.ts +13 -6
- package/src/core/delegate/facade-contract.ts +6 -0
- package/src/core/delegate/result-package.ts +32 -14
- package/src/core/delegate/runner.ts +129 -58
- package/src/core/delegate/seed.ts +5 -7
- package/src/core/durable-fs.ts +178 -30
- package/src/core/extension-api.ts +36 -8
- package/src/core/fusion/artifacts.ts +17 -16
- package/src/core/fusion/clean-context.ts +8 -5
- package/src/core/fusion/config.ts +2 -1
- package/src/core/fusion/context.ts +2 -6
- package/src/core/fusion/facade-contract.ts +2 -0
- package/src/core/fusion/orchestrator.ts +3 -3
- package/src/core/fusion/prompts.ts +1 -1
- package/src/core/fusion/result-package.ts +259 -72
- package/src/core/fusion/source-policy.ts +43 -17
- package/src/core/lazy-module.ts +215 -0
- package/src/core/pi-launch.ts +390 -65
- package/src/core/registry.ts +2010 -381
- package/src/core/reload-shell-owner.ts +1662 -0
- package/src/core/shell-policy.ts +134 -0
- package/src/core/task-durable.ts +67 -0
- package/src/delegate-extension.ts +404 -144
- package/src/extension.ts +387 -114
- package/src/fusion-extension.ts +202 -96
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
1
2
|
import { readFile } from 'node:fs/promises';
|
|
2
3
|
import { fileURLToPath } from 'node:url';
|
|
3
4
|
import type {
|
|
@@ -8,15 +9,17 @@ import type {
|
|
|
8
9
|
} from '@earendil-works/pi-coding-agent';
|
|
9
10
|
import { Text } from '@earendil-works/pi-tui';
|
|
10
11
|
import { Type, type Static } from 'typebox';
|
|
11
|
-
import type {
|
|
12
|
+
import type {
|
|
13
|
+
BgTask,
|
|
14
|
+
BgTaskSnapshot,
|
|
15
|
+
DelegateTaskFacts,
|
|
16
|
+
StartDelegateTaskOptions,
|
|
17
|
+
} from './core/common.js';
|
|
12
18
|
import { truncateChars } from './core/common.js';
|
|
13
|
-
import {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
type FusionFailureResultView,
|
|
18
|
-
type FusionUsage,
|
|
19
|
-
type FusionWorkflowId,
|
|
19
|
+
import type {
|
|
20
|
+
FusionFailureResultView,
|
|
21
|
+
FusionUsage,
|
|
22
|
+
FusionWorkflowId,
|
|
20
23
|
} from './core/fusion/types.js';
|
|
21
24
|
import {
|
|
22
25
|
DELEGATE_AUTO_DELIVER_MODES,
|
|
@@ -32,21 +35,17 @@ import {
|
|
|
32
35
|
type DelegateExtensionMode,
|
|
33
36
|
type DelegateRoute,
|
|
34
37
|
} from './core/delegate/types.js';
|
|
38
|
+
import type { DelegateHookContractEvidence } from './core/delegate/hook-contract.js';
|
|
35
39
|
import {
|
|
36
|
-
DELEGATE_INLINE_ANSWER_BYTES,
|
|
37
40
|
DELEGATE_DEFAULT_MAX_TOOL_CALLS,
|
|
38
41
|
DELEGATE_DEFAULT_MAX_TURNS,
|
|
39
42
|
DELEGATE_DEFAULT_TIMEOUT_SECONDS,
|
|
40
|
-
|
|
41
|
-
|
|
43
|
+
DELEGATE_INLINE_ANSWER_BYTES,
|
|
44
|
+
} from './core/delegate/facade-contract.js';
|
|
42
45
|
import {
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
prepareDelegateLaunch,
|
|
47
|
-
} from './core/delegate/runner.js';
|
|
48
|
-
import { loadDelegateHookContractEvidence } from './core/delegate/launch.js';
|
|
49
|
-
import type { DelegateHookContractEvidence } from './core/delegate/hook-contract.js';
|
|
46
|
+
LazyModule,
|
|
47
|
+
SynchronousActivationCloseFence,
|
|
48
|
+
} from './core/lazy-module.js';
|
|
50
49
|
|
|
51
50
|
/**
|
|
52
51
|
* `bg_delegate` and `bg_result` registration.
|
|
@@ -224,6 +223,29 @@ function textContent(text: string) {
|
|
|
224
223
|
return [{ type: 'text' as const, text }];
|
|
225
224
|
}
|
|
226
225
|
|
|
226
|
+
function sha256Buffer(buffer: Buffer): string {
|
|
227
|
+
return `sha256:${createHash('sha256').update(buffer).digest('hex')}`;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
function cloneFusionUsage(usage: FusionUsage): FusionUsage {
|
|
231
|
+
return {
|
|
232
|
+
input: usage.input,
|
|
233
|
+
output: usage.output,
|
|
234
|
+
cacheRead: usage.cacheRead,
|
|
235
|
+
cacheWrite: usage.cacheWrite,
|
|
236
|
+
...(usage.cacheWrite1h === undefined ? {} : { cacheWrite1h: usage.cacheWrite1h }),
|
|
237
|
+
...(usage.reasoning === undefined ? {} : { reasoning: usage.reasoning }),
|
|
238
|
+
totalTokens: usage.totalTokens,
|
|
239
|
+
cost: {
|
|
240
|
+
input: usage.cost.input,
|
|
241
|
+
output: usage.cost.output,
|
|
242
|
+
cacheRead: usage.cost.cacheRead,
|
|
243
|
+
cacheWrite: usage.cost.cacheWrite,
|
|
244
|
+
total: usage.cost.total,
|
|
245
|
+
},
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
|
|
227
249
|
function isRecord(value: unknown): value is Record<PropertyKey, unknown> {
|
|
228
250
|
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
229
251
|
}
|
|
@@ -302,16 +324,102 @@ function optionalPositiveInteger(value: unknown, label: string): number | undefi
|
|
|
302
324
|
return value;
|
|
303
325
|
}
|
|
304
326
|
|
|
327
|
+
export interface DelegatePreparedLaunch {
|
|
328
|
+
preflight: {
|
|
329
|
+
childSessionId: string;
|
|
330
|
+
seed: { serialized: string };
|
|
331
|
+
limits: { max_turns: number; max_tool_calls: number; timeout_seconds: number };
|
|
332
|
+
plan: {
|
|
333
|
+
child_prompt_utf8_bytes: number;
|
|
334
|
+
launch_input_tokens_upper_bound: number;
|
|
335
|
+
route: { allowed_input_tokens: number };
|
|
336
|
+
retained_growth_budget_tokens: number;
|
|
337
|
+
};
|
|
338
|
+
};
|
|
339
|
+
argv: readonly string[];
|
|
340
|
+
stdinBytes: Buffer;
|
|
341
|
+
env: NodeJS.ProcessEnv;
|
|
342
|
+
facts: DelegateTaskFacts;
|
|
343
|
+
/** Producer-owned rollback, valid only before registry ownership transfers. */
|
|
344
|
+
rollback: () => Promise<void>;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
export interface DelegateExtensionRuntime {
|
|
348
|
+
loadDelegateHookContractEvidence: (
|
|
349
|
+
raw: string,
|
|
350
|
+
) => DelegateHookContractEvidence;
|
|
351
|
+
resolveDelegateRoute: typeof import('./core/delegate/launch.js').resolveDelegateRoute;
|
|
352
|
+
prepareDelegateLaunch: (
|
|
353
|
+
input: Parameters<typeof import('./core/delegate/runner.js').prepareDelegateLaunch>[0],
|
|
354
|
+
) => Promise<DelegatePreparedLaunch>;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
interface DelegateResultRuntime {
|
|
358
|
+
decideDelegateDelivery: typeof import('./core/delegate/runner.js').decideDelegateDelivery;
|
|
359
|
+
evaluateDelegateTerminal: typeof import('./core/delegate/runner.js').evaluateDelegateTerminal;
|
|
360
|
+
inlineTooLarge: typeof import('./core/delegate/runner.js').inlineTooLarge;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
interface FusionResultRuntime {
|
|
364
|
+
readFusionCommittedResult: typeof import('./core/fusion/result-package.js').readFusionCommittedResult;
|
|
365
|
+
readFusionFailureResult: typeof import('./core/fusion/result-package.js').readFusionFailureResult;
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
async function importDelegateExtensionRuntime(): Promise<DelegateExtensionRuntime> {
|
|
369
|
+
const [launch, runner] = await Promise.all([
|
|
370
|
+
import('./core/delegate/launch.js'),
|
|
371
|
+
import('./core/delegate/runner.js'),
|
|
372
|
+
]);
|
|
373
|
+
return {
|
|
374
|
+
loadDelegateHookContractEvidence: launch.loadDelegateHookContractEvidence,
|
|
375
|
+
resolveDelegateRoute: launch.resolveDelegateRoute,
|
|
376
|
+
prepareDelegateLaunch: runner.prepareDelegateLaunch,
|
|
377
|
+
};
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
async function importDelegateResultRuntime(): Promise<DelegateResultRuntime> {
|
|
381
|
+
const runner = await import('./core/delegate/runner.js');
|
|
382
|
+
return {
|
|
383
|
+
decideDelegateDelivery: runner.decideDelegateDelivery,
|
|
384
|
+
evaluateDelegateTerminal: runner.evaluateDelegateTerminal,
|
|
385
|
+
inlineTooLarge: runner.inlineTooLarge,
|
|
386
|
+
};
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
async function importFusionResultRuntime(): Promise<FusionResultRuntime> {
|
|
390
|
+
const resultPackage = await import('./core/fusion/result-package.js');
|
|
391
|
+
return {
|
|
392
|
+
readFusionCommittedResult: resultPackage.readFusionCommittedResult,
|
|
393
|
+
readFusionFailureResult: resultPackage.readFusionFailureResult,
|
|
394
|
+
};
|
|
395
|
+
}
|
|
396
|
+
|
|
305
397
|
export interface DelegateExtensionDependencies {
|
|
306
398
|
startDelegateTask: (ctx: ExtensionContext, options: StartDelegateTaskOptions) => Promise<BgTask>;
|
|
307
399
|
snapshot: (task: BgTask) => BgTaskSnapshot;
|
|
308
|
-
|
|
309
|
-
|
|
400
|
+
/** Exact ownership check used only after a rejected starter. */
|
|
401
|
+
isDelegateTaskRegistered: (taskId: string) => boolean;
|
|
402
|
+
/** Activation-local fence installed synchronously before asynchronous cleanup. */
|
|
403
|
+
activationCloseFence: SynchronousActivationCloseFence;
|
|
310
404
|
/** Overridable so tests can supply observed evidence without touching disk. */
|
|
311
405
|
loadHookEvidence?: (() => Promise<DelegateHookContractEvidence>) | undefined;
|
|
406
|
+
/** Internal deterministic deferred-import seam. */
|
|
407
|
+
loadRuntime?: (() => Promise<DelegateExtensionRuntime>) | undefined;
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
export interface BackgroundResultExtensionDependencies {
|
|
411
|
+
resolveTask: (idOrPrefix: string) => BgTask;
|
|
412
|
+
claimFusionUsage: (task: BgTask) => Promise<boolean>;
|
|
413
|
+
/** Activation-local fence installed synchronously before asynchronous cleanup. */
|
|
414
|
+
activationCloseFence: SynchronousActivationCloseFence;
|
|
415
|
+
/** Internal deterministic deferred-import seams. */
|
|
416
|
+
loadDelegateResultRuntime?: (() => Promise<DelegateResultRuntime>) | undefined;
|
|
417
|
+
loadFusionResultRuntime?: (() => Promise<FusionResultRuntime>) | undefined;
|
|
312
418
|
}
|
|
313
419
|
|
|
314
|
-
async function defaultHookEvidence(
|
|
420
|
+
async function defaultHookEvidence(
|
|
421
|
+
runtime: LazyModule<DelegateExtensionRuntime>,
|
|
422
|
+
): Promise<DelegateHookContractEvidence> {
|
|
315
423
|
let raw: string;
|
|
316
424
|
try {
|
|
317
425
|
raw = await readFile(HOOK_EVIDENCE_PATH, 'utf8');
|
|
@@ -328,14 +436,66 @@ async function defaultHookEvidence(): Promise<DelegateHookContractEvidence> {
|
|
|
328
436
|
},
|
|
329
437
|
);
|
|
330
438
|
}
|
|
331
|
-
return loadDelegateHookContractEvidence(raw);
|
|
439
|
+
return runtime.run((loaded) => loaded.loadDelegateHookContractEvidence(raw));
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
const DELEGATE_ROLLBACK_ERROR_MAX_CHARS = 320;
|
|
443
|
+
|
|
444
|
+
function boundedDelegateRollbackError(error: unknown): string {
|
|
445
|
+
const text = (error instanceof Error ? error.message : String(error)).replace(/\s+/gu, ' ').trim();
|
|
446
|
+
if (text.length <= DELEGATE_ROLLBACK_ERROR_MAX_CHARS) return text;
|
|
447
|
+
return `${text.slice(0, DELEGATE_ROLLBACK_ERROR_MAX_CHARS)}…`;
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
async function rollbackUnregisteredDelegatePreparation(
|
|
451
|
+
prepared: DelegatePreparedLaunch,
|
|
452
|
+
originalError: unknown,
|
|
453
|
+
): Promise<void> {
|
|
454
|
+
try {
|
|
455
|
+
await prepared.rollback();
|
|
456
|
+
} catch (cleanupError) {
|
|
457
|
+
const failure = new AggregateError(
|
|
458
|
+
[originalError, cleanupError],
|
|
459
|
+
`bg_delegate could not remove an unregistered preparation: ${boundedDelegateRollbackError(cleanupError)}`,
|
|
460
|
+
);
|
|
461
|
+
console.error(`[delegate] ${failure.message}`);
|
|
462
|
+
throw failure;
|
|
463
|
+
}
|
|
332
464
|
}
|
|
333
465
|
|
|
334
466
|
export function registerDelegateExtension(
|
|
335
467
|
pi: ExtensionAPI,
|
|
336
468
|
deps: DelegateExtensionDependencies,
|
|
337
469
|
): void {
|
|
338
|
-
const
|
|
470
|
+
const runtime = new LazyModule(
|
|
471
|
+
'delegate-producer',
|
|
472
|
+
deps.loadRuntime ?? importDelegateExtensionRuntime,
|
|
473
|
+
);
|
|
474
|
+
const loadEvidence = deps.loadHookEvidence ?? (() => defaultHookEvidence(runtime));
|
|
475
|
+
const preparationAbort = new AbortController();
|
|
476
|
+
const pendingPreparations = new Set<Promise<void>>();
|
|
477
|
+
|
|
478
|
+
const trackPreparation = <T>(operation: Promise<T>): Promise<T> => {
|
|
479
|
+
const drained = operation.then(
|
|
480
|
+
() => undefined,
|
|
481
|
+
() => undefined,
|
|
482
|
+
);
|
|
483
|
+
pendingPreparations.add(drained);
|
|
484
|
+
void drained.then(() => {
|
|
485
|
+
pendingPreparations.delete(drained);
|
|
486
|
+
});
|
|
487
|
+
return operation;
|
|
488
|
+
};
|
|
489
|
+
|
|
490
|
+
const closeDelegateActivation = (): void => {
|
|
491
|
+
runtime.close('Pi session shutdown');
|
|
492
|
+
preparationAbort.abort(new Error('Pi session shutdown cancelled delegate preparation'));
|
|
493
|
+
};
|
|
494
|
+
deps.activationCloseFence.add(closeDelegateActivation);
|
|
495
|
+
|
|
496
|
+
pi.on('session_shutdown', async () => {
|
|
497
|
+
await Promise.all([...pendingPreparations]);
|
|
498
|
+
});
|
|
339
499
|
|
|
340
500
|
pi.registerTool<typeof DelegateParams, DelegateLaunchDetails>({
|
|
341
501
|
name: DELEGATE_TOOL_NAME,
|
|
@@ -401,100 +561,148 @@ export function registerDelegateExtension(
|
|
|
401
561
|
const capability = requireCapability(params.capability);
|
|
402
562
|
const extensionMode = requireExtensionMode(params.extensionMode);
|
|
403
563
|
const autoDeliver = requireAutoDeliver(params.autoDeliver);
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
564
|
+
return runtime.run(async (loaded) => {
|
|
565
|
+
const hookEvidence = await loadEvidence();
|
|
566
|
+
runtime.assertOpen();
|
|
567
|
+
const route = loaded.resolveDelegateRoute({
|
|
568
|
+
requested: params.route,
|
|
569
|
+
currentModel:
|
|
570
|
+
ctx.model === undefined
|
|
571
|
+
? undefined
|
|
572
|
+
: {
|
|
573
|
+
provider: ctx.model.provider,
|
|
574
|
+
id: ctx.model.id,
|
|
575
|
+
contextWindow: ctx.model.contextWindow,
|
|
576
|
+
},
|
|
577
|
+
availableModels: ctx.modelRegistry.getAll().map((model) => ({
|
|
578
|
+
provider: model.provider,
|
|
579
|
+
id: model.id,
|
|
580
|
+
contextWindow: model.contextWindow,
|
|
581
|
+
})),
|
|
582
|
+
thinkingLevel: pi.getThinkingLevel(),
|
|
583
|
+
});
|
|
584
|
+
|
|
585
|
+
runtime.assertOpen();
|
|
586
|
+
const transaction = (async () => {
|
|
587
|
+
let prepared: DelegatePreparedLaunch | undefined;
|
|
588
|
+
try {
|
|
589
|
+
prepared = await loaded.prepareDelegateLaunch({
|
|
590
|
+
ctx: {
|
|
591
|
+
cwd: ctx.cwd,
|
|
592
|
+
sessionManager: ctx.sessionManager,
|
|
593
|
+
getSystemPrompt: () => ctx.getSystemPrompt(),
|
|
414
594
|
},
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
595
|
+
toolCallId,
|
|
596
|
+
prompt: params.prompt,
|
|
597
|
+
capability,
|
|
598
|
+
extensionMode,
|
|
599
|
+
route,
|
|
600
|
+
limitOverrides: {
|
|
601
|
+
maxTurns: params.maxTurns,
|
|
602
|
+
maxToolCalls: params.maxToolCalls,
|
|
603
|
+
timeoutSeconds: params.timeoutSeconds,
|
|
604
|
+
},
|
|
605
|
+
hookEvidence,
|
|
606
|
+
cwd: ctx.cwd,
|
|
607
|
+
sessionId: ctx.sessionManager.getSessionId(),
|
|
608
|
+
autoDeliver,
|
|
609
|
+
signal: preparationAbort.signal,
|
|
610
|
+
});
|
|
611
|
+
runtime.assertOpen();
|
|
612
|
+
} catch (error) {
|
|
613
|
+
if (prepared !== undefined) {
|
|
614
|
+
await rollbackUnregisteredDelegatePreparation(prepared, error);
|
|
615
|
+
}
|
|
616
|
+
if (preparationAbort.signal.aborted) {
|
|
617
|
+
if (error instanceof AggregateError) {
|
|
618
|
+
console.error(
|
|
619
|
+
`[delegate] cancelled preparation cleanup failed: ${boundedDelegateRollbackError(error)}`,
|
|
620
|
+
);
|
|
621
|
+
} else {
|
|
622
|
+
runtime.assertOpen();
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
throw error;
|
|
626
|
+
}
|
|
422
627
|
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
628
|
+
const launchOptions: StartDelegateTaskOptions = {
|
|
629
|
+
name: params.name,
|
|
630
|
+
argv: prepared.argv,
|
|
631
|
+
stdinBytes: prepared.stdinBytes,
|
|
632
|
+
env: prepared.env,
|
|
633
|
+
facts: prepared.facts,
|
|
634
|
+
notifyOnCompletion: params.notifyOnCompletion ?? true,
|
|
635
|
+
triggerOnCompletion: params.triggerOnCompletion ?? true,
|
|
636
|
+
timeoutSeconds: prepared.preflight.limits.timeout_seconds,
|
|
637
|
+
};
|
|
638
|
+
let task: BgTask;
|
|
639
|
+
try {
|
|
640
|
+
task = await deps.startDelegateTask(ctx, launchOptions);
|
|
641
|
+
} catch (error) {
|
|
642
|
+
let registered: boolean;
|
|
643
|
+
try {
|
|
644
|
+
registered = deps.isDelegateTaskRegistered(prepared.facts.taskId);
|
|
645
|
+
} catch (ownershipError) {
|
|
646
|
+
const failure = new AggregateError(
|
|
647
|
+
[error, ownershipError],
|
|
648
|
+
`bg_delegate could not determine artifact ownership after starter failure: ${boundedDelegateRollbackError(ownershipError)}`,
|
|
649
|
+
);
|
|
650
|
+
console.error(`[delegate] ${failure.message}`);
|
|
651
|
+
throw failure;
|
|
652
|
+
}
|
|
653
|
+
if (!registered) {
|
|
654
|
+
await rollbackUnregisteredDelegatePreparation(prepared, error);
|
|
655
|
+
}
|
|
656
|
+
if (preparationAbort.signal.aborted) runtime.assertOpen();
|
|
657
|
+
throw error;
|
|
658
|
+
}
|
|
659
|
+
return { prepared, launchOptions, task };
|
|
660
|
+
})();
|
|
661
|
+
const { prepared, launchOptions, task } = await trackPreparation(transaction);
|
|
662
|
+
runtime.assertOpen();
|
|
444
663
|
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
`Extension mode: ${extensionMode}${extensionMode === 'ambient' ? ' — WARNING: arbitrary discovered extension code executes in the child; the tool allowlist does not sandbox it, so inspect-only process isolation is weakened.' : ' (ambient extension discovery disabled)'}`,
|
|
488
|
-
`Limits: ${String(prepared.preflight.limits.max_turns)} turns, ${String(prepared.preflight.limits.max_tool_calls)} tool calls, ${String(prepared.preflight.limits.timeout_seconds)}s`,
|
|
489
|
-
`Auto-deliver: ${autoDeliver}`,
|
|
490
|
-
launchOptions.notifyOnCompletion
|
|
491
|
-
? `Terminal notification: enabled.${launchOptions.triggerOnCompletion ? ' It will start a follow-up turn.' : ' It will not start a turn.'}`
|
|
492
|
-
: 'Terminal notification: disabled.',
|
|
493
|
-
`Retrieve the verified answer with ${DELEGATE_RESULT_TOOL_NAME}({taskId:"${task.id}"}). Do not poll.`,
|
|
494
|
-
].join('\n'),
|
|
495
|
-
),
|
|
496
|
-
details,
|
|
497
|
-
};
|
|
664
|
+
const details: DelegateLaunchDetails = {
|
|
665
|
+
schema_version: 'pi-background-tasks.delegate-launch.v1',
|
|
666
|
+
task: deps.snapshot(task),
|
|
667
|
+
route: {
|
|
668
|
+
provider: route.provider,
|
|
669
|
+
model: route.model,
|
|
670
|
+
qualified_id: route.qualified_id,
|
|
671
|
+
origin: route.origin,
|
|
672
|
+
},
|
|
673
|
+
child_session_id: prepared.preflight.childSessionId,
|
|
674
|
+
artifact_dir: prepared.facts.artifactDir,
|
|
675
|
+
seed_sha256: prepared.facts.seedSha256,
|
|
676
|
+
seed_utf8_bytes: Buffer.byteLength(prepared.preflight.seed.serialized, 'utf8'),
|
|
677
|
+
budget: prepared.facts.budget,
|
|
678
|
+
extension_mode: extensionMode,
|
|
679
|
+
auto_deliver: autoDeliver,
|
|
680
|
+
notify_on_completion: launchOptions.notifyOnCompletion,
|
|
681
|
+
trigger_on_completion: launchOptions.triggerOnCompletion,
|
|
682
|
+
};
|
|
683
|
+
return {
|
|
684
|
+
content: textContent(
|
|
685
|
+
[
|
|
686
|
+
`Started delegate ${params.name} (${task.id})`,
|
|
687
|
+
`Route pinned: ${route.qualified_id} (${route.origin}); it is never substituted.`,
|
|
688
|
+
`Child session: ${prepared.preflight.childSessionId} (separate from this session)`,
|
|
689
|
+
`Artifacts: ${prepared.facts.artifactDir}`,
|
|
690
|
+
`Seed: ${String(Buffer.byteLength(prepared.preflight.seed.serialized, 'utf8'))} bytes, sha256 ${prepared.facts.seedSha256}`,
|
|
691
|
+
`Child prompt: ${String(prepared.preflight.plan.child_prompt_utf8_bytes)} bytes; launch estimate ${String(prepared.preflight.plan.launch_input_tokens_upper_bound)} / ${String(prepared.preflight.plan.route.allowed_input_tokens)} allowed input tokens; protected retained-growth runway ${String(prepared.preflight.plan.retained_growth_budget_tokens)} tokens.`,
|
|
692
|
+
`Estimator: family ${prepared.facts.budget.family}, source ${prepared.facts.budget.rate_source.source}, rate ${String(prepared.facts.budget.rate_source.effective_rate_bytes_per_token_x100)}/100 B/tok + ${String(prepared.facts.budget.rate_source.affine_f_tokens)} tokens${prepared.facts.budget.rate_source.warning === null ? '' : `; warning: ${prepared.facts.budget.rate_source.warning}`}`,
|
|
693
|
+
`Capability: ${capability} (read/search/list only)`,
|
|
694
|
+
`Extension mode: ${extensionMode}${extensionMode === 'ambient' ? ' — WARNING: arbitrary discovered extension code executes in the child; the tool allowlist does not sandbox it, so inspect-only process isolation is weakened.' : ' (ambient extension discovery disabled)'}`,
|
|
695
|
+
`Limits: ${String(prepared.preflight.limits.max_turns)} turns, ${String(prepared.preflight.limits.max_tool_calls)} tool calls, ${String(prepared.preflight.limits.timeout_seconds)}s`,
|
|
696
|
+
`Auto-deliver: ${autoDeliver}`,
|
|
697
|
+
launchOptions.notifyOnCompletion
|
|
698
|
+
? `Terminal notification: enabled.${launchOptions.triggerOnCompletion ? ' It will start a follow-up turn.' : ' It will not start a turn.'}`
|
|
699
|
+
: 'Terminal notification: disabled.',
|
|
700
|
+
`Retrieve the verified answer with ${DELEGATE_RESULT_TOOL_NAME}({taskId:"${task.id}"}). Do not poll.`,
|
|
701
|
+
].join('\n'),
|
|
702
|
+
),
|
|
703
|
+
details,
|
|
704
|
+
};
|
|
705
|
+
});
|
|
498
706
|
},
|
|
499
707
|
renderCall(args, theme) {
|
|
500
708
|
return new Text(
|
|
@@ -513,6 +721,39 @@ export function registerDelegateExtension(
|
|
|
513
721
|
},
|
|
514
722
|
});
|
|
515
723
|
|
|
724
|
+
pi.on('session_start', () => {
|
|
725
|
+
const active = pi.getActiveTools();
|
|
726
|
+
const missing = [DELEGATE_TOOL_NAME].filter((name) => !active.includes(name));
|
|
727
|
+
if (missing.length > 0) pi.setActiveTools([...active, ...missing]);
|
|
728
|
+
});
|
|
729
|
+
}
|
|
730
|
+
|
|
731
|
+
export function registerBackgroundResultExtension(
|
|
732
|
+
pi: ExtensionAPI,
|
|
733
|
+
deps: BackgroundResultExtensionDependencies,
|
|
734
|
+
): void {
|
|
735
|
+
const delegateResultRuntime = new LazyModule(
|
|
736
|
+
'delegate-result-verifier',
|
|
737
|
+
deps.loadDelegateResultRuntime ?? importDelegateResultRuntime,
|
|
738
|
+
);
|
|
739
|
+
const fusionResultRuntime = new LazyModule(
|
|
740
|
+
'fusion-result-verifier',
|
|
741
|
+
deps.loadFusionResultRuntime ?? importFusionResultRuntime,
|
|
742
|
+
);
|
|
743
|
+
let resultClosedError: Error | undefined;
|
|
744
|
+
const assertResultActive = (): void => {
|
|
745
|
+
if (resultClosedError !== undefined) throw resultClosedError;
|
|
746
|
+
};
|
|
747
|
+
|
|
748
|
+
const closeResultActivation = (): void => {
|
|
749
|
+
resultClosedError ??= new Error(
|
|
750
|
+
'lazy_module_closed: background-result facade belongs to a closed activation (Pi session shutdown)',
|
|
751
|
+
);
|
|
752
|
+
delegateResultRuntime.close('Pi session shutdown');
|
|
753
|
+
fusionResultRuntime.close('Pi session shutdown');
|
|
754
|
+
};
|
|
755
|
+
deps.activationCloseFence.add(closeResultActivation);
|
|
756
|
+
|
|
516
757
|
pi.registerTool<typeof ResultParams, BackgroundResultDetails>({
|
|
517
758
|
name: DELEGATE_RESULT_TOOL_NAME,
|
|
518
759
|
label: 'Background Result',
|
|
@@ -542,6 +783,8 @@ export function registerDelegateExtension(
|
|
|
542
783
|
return prepared;
|
|
543
784
|
},
|
|
544
785
|
async execute(_toolCallId, params) {
|
|
786
|
+
// Reject stale tools before touching the activation-local registry API.
|
|
787
|
+
assertResultActive();
|
|
545
788
|
let task: BgTask;
|
|
546
789
|
try {
|
|
547
790
|
task = deps.resolveTask(params.taskId);
|
|
@@ -571,12 +814,15 @@ export function registerDelegateExtension(
|
|
|
571
814
|
};
|
|
572
815
|
}
|
|
573
816
|
if (task.status !== 'completed' || fusion.outcome?.status !== 'committed') {
|
|
574
|
-
const terminal = await
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
817
|
+
const terminal = await fusionResultRuntime.run((loaded) =>
|
|
818
|
+
loaded.readFusionFailureResult({
|
|
819
|
+
artifactDirAbs: fusion.artifactDirAbs,
|
|
820
|
+
artifactDir: fusion.artifactDir,
|
|
821
|
+
runId: fusion.runId,
|
|
822
|
+
workflow: fusion.workflow,
|
|
823
|
+
}),
|
|
824
|
+
);
|
|
825
|
+
fusionResultRuntime.assertOpen();
|
|
580
826
|
const state =
|
|
581
827
|
fusion.outcome?.status === 'cancelled' || task.status === 'killed'
|
|
582
828
|
? 'cancelled'
|
|
@@ -614,12 +860,15 @@ export function registerDelegateExtension(
|
|
|
614
860
|
details,
|
|
615
861
|
};
|
|
616
862
|
}
|
|
617
|
-
const verified = await
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
863
|
+
const verified = await fusionResultRuntime.run((loaded) =>
|
|
864
|
+
loaded.readFusionCommittedResult({
|
|
865
|
+
artifactDirAbs: fusion.artifactDirAbs,
|
|
866
|
+
artifactDir: fusion.artifactDir,
|
|
867
|
+
runId: fusion.runId,
|
|
868
|
+
workflow: fusion.workflow,
|
|
869
|
+
}),
|
|
870
|
+
);
|
|
871
|
+
fusionResultRuntime.assertOpen();
|
|
623
872
|
const answerBytes = Buffer.byteLength(verified.mergedText, 'utf8');
|
|
624
873
|
const answerSha256 = sha256Buffer(Buffer.from(verified.mergedText, 'utf8'));
|
|
625
874
|
const useArtifact =
|
|
@@ -630,6 +879,12 @@ export function registerDelegateExtension(
|
|
|
630
879
|
`Fusion result ${task.id} is ${String(answerBytes)} bytes, above the ${String(DELEGATE_INLINE_ANSWER_BYTES)}-byte inline limit. Use delivery:"artifact"; nothing was truncated.`,
|
|
631
880
|
);
|
|
632
881
|
}
|
|
882
|
+
fusionResultRuntime.assertOpen();
|
|
883
|
+
// The durable claim is the settlement point. Once started, this verified
|
|
884
|
+
// retrieval must return its usage even if shutdown closes the facade
|
|
885
|
+
// while registry metadata is being written. Everything after the await
|
|
886
|
+
// is activation-local result construction with no host side effects.
|
|
887
|
+
const usage = cloneFusionUsage(verified.details.usage);
|
|
633
888
|
const usageDelivered = await deps.claimFusionUsage(task);
|
|
634
889
|
const details: FusionBackgroundResultDetails = {
|
|
635
890
|
schema_version: 'pi-background-tasks.fusion-result-view.v1',
|
|
@@ -661,7 +916,7 @@ export function registerDelegateExtension(
|
|
|
661
916
|
if (!usageDelivered) return result;
|
|
662
917
|
const resultWithUsage: typeof result & { usage: FusionUsage } = {
|
|
663
918
|
...result,
|
|
664
|
-
usage
|
|
919
|
+
usage,
|
|
665
920
|
};
|
|
666
921
|
return resultWithUsage;
|
|
667
922
|
}
|
|
@@ -673,7 +928,8 @@ export function registerDelegateExtension(
|
|
|
673
928
|
{ code: 'task_unknown', childCreated: false },
|
|
674
929
|
);
|
|
675
930
|
}
|
|
676
|
-
|
|
931
|
+
const delegateTaskStatus = task.status;
|
|
932
|
+
if (delegateTaskStatus === 'running') {
|
|
677
933
|
const details: DelegateResultDetails = {
|
|
678
934
|
schema_version: 'pi-background-tasks.delegate-result-view.v1',
|
|
679
935
|
task_id: task.id,
|
|
@@ -691,17 +947,23 @@ export function registerDelegateExtension(
|
|
|
691
947
|
};
|
|
692
948
|
}
|
|
693
949
|
|
|
694
|
-
const
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
950
|
+
const evaluation = await delegateResultRuntime.run(async (loaded) => ({
|
|
951
|
+
loaded,
|
|
952
|
+
terminal: await loaded.evaluateDelegateTerminal({
|
|
953
|
+
artifactDirAbs: facts.artifactDirAbs,
|
|
954
|
+
taskId: facts.taskId,
|
|
955
|
+
launchNonce: facts.launchNonce,
|
|
956
|
+
seedSha256: facts.seedSha256,
|
|
957
|
+
route: { provider: facts.route.provider, model: facts.route.model },
|
|
958
|
+
taskStatus:
|
|
959
|
+
delegateTaskStatus === 'completed' ? 'completed' : delegateTaskStatus,
|
|
960
|
+
taskError: task.error,
|
|
961
|
+
taskOutputPath: task.outputPath,
|
|
962
|
+
taskOutputAbsPath: task.outputAbsPath,
|
|
963
|
+
}),
|
|
964
|
+
}));
|
|
965
|
+
delegateResultRuntime.assertOpen();
|
|
966
|
+
const { loaded: verifier, terminal } = evaluation;
|
|
705
967
|
|
|
706
968
|
if (terminal.error !== undefined || terminal.result === undefined) {
|
|
707
969
|
const failure =
|
|
@@ -717,12 +979,12 @@ export function registerDelegateExtension(
|
|
|
717
979
|
|
|
718
980
|
const verified = terminal.result;
|
|
719
981
|
const requestedDelivery = requireDelivery(params.delivery);
|
|
720
|
-
const decision = decideDelegateDelivery(
|
|
982
|
+
const decision = verifier.decideDelegateDelivery(
|
|
721
983
|
verified.package.answer.byte_length,
|
|
722
984
|
requestedDelivery,
|
|
723
985
|
);
|
|
724
986
|
if (requestedDelivery === 'inline' && decision.mode === 'artifact') {
|
|
725
|
-
const failure = inlineTooLarge(
|
|
987
|
+
const failure = verifier.inlineTooLarge(
|
|
726
988
|
task.id,
|
|
727
989
|
facts.artifactDir,
|
|
728
990
|
verified.package.answer.byte_length,
|
|
@@ -796,9 +1058,7 @@ export function registerDelegateExtension(
|
|
|
796
1058
|
|
|
797
1059
|
pi.on('session_start', () => {
|
|
798
1060
|
const active = pi.getActiveTools();
|
|
799
|
-
const missing = [
|
|
800
|
-
(name) => !active.includes(name),
|
|
801
|
-
);
|
|
1061
|
+
const missing = [DELEGATE_RESULT_TOOL_NAME].filter((name) => !active.includes(name));
|
|
802
1062
|
if (missing.length > 0) pi.setActiveTools([...active, ...missing]);
|
|
803
1063
|
});
|
|
804
1064
|
}
|