@caupulican/pi-adaptative 0.85.8 → 0.86.2
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 +42 -0
- package/dist/core/agent-paths.d.ts +6 -3
- package/dist/core/agent-paths.d.ts.map +1 -1
- package/dist/core/agent-paths.js +10 -3
- package/dist/core/agent-paths.js.map +1 -1
- package/dist/core/agent-session.d.ts +5 -2
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +7 -1
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/autonomy/bounded-completion.d.ts.map +1 -1
- package/dist/core/autonomy/bounded-completion.js +19 -8
- package/dist/core/autonomy/bounded-completion.js.map +1 -1
- package/dist/core/autonomy/lane-tool-surface.d.ts +11 -5
- package/dist/core/autonomy/lane-tool-surface.d.ts.map +1 -1
- package/dist/core/autonomy/lane-tool-surface.js +34 -8
- package/dist/core/autonomy/lane-tool-surface.js.map +1 -1
- package/dist/core/autonomy/subagent-prompt.d.ts +3 -3
- package/dist/core/autonomy/subagent-prompt.js +9 -9
- package/dist/core/autonomy/subagent-prompt.js.map +1 -1
- package/dist/core/background-lane-controller.d.ts +10 -8
- package/dist/core/background-lane-controller.d.ts.map +1 -1
- package/dist/core/background-lane-controller.js +23 -13
- package/dist/core/background-lane-controller.js.map +1 -1
- package/dist/core/bash-execution-controller.d.ts +4 -0
- package/dist/core/bash-execution-controller.d.ts.map +1 -1
- package/dist/core/bash-execution-controller.js +11 -4
- package/dist/core/bash-execution-controller.js.map +1 -1
- package/dist/core/bash-executor.d.ts +2 -0
- package/dist/core/bash-executor.d.ts.map +1 -1
- package/dist/core/bash-executor.js +2 -1
- package/dist/core/bash-executor.js.map +1 -1
- package/dist/core/capability-contract.d.ts +1 -1
- package/dist/core/capability-contract.d.ts.map +1 -1
- package/dist/core/capability-contract.js +0 -1
- package/dist/core/capability-contract.js.map +1 -1
- package/dist/core/default-tool-surface.d.ts +1 -0
- package/dist/core/default-tool-surface.d.ts.map +1 -1
- package/dist/core/default-tool-surface.js +3 -2
- package/dist/core/default-tool-surface.js.map +1 -1
- package/dist/core/delegation/worker-agent-control-coordinator.d.ts +27 -8
- package/dist/core/delegation/worker-agent-control-coordinator.d.ts.map +1 -1
- package/dist/core/delegation/worker-agent-control-coordinator.js +191 -33
- package/dist/core/delegation/worker-agent-control-coordinator.js.map +1 -1
- package/dist/core/delegation/worker-agent-control.d.ts +45 -6
- package/dist/core/delegation/worker-agent-control.d.ts.map +1 -1
- package/dist/core/delegation/worker-agent-control.js +110 -13
- package/dist/core/delegation/worker-agent-control.js.map +1 -1
- package/dist/core/delegation/worker-attempt-executor.d.ts.map +1 -1
- package/dist/core/delegation/worker-attempt-executor.js +177 -158
- package/dist/core/delegation/worker-attempt-executor.js.map +1 -1
- package/dist/core/delegation/worker-authority-resolver.d.ts +23 -0
- package/dist/core/delegation/worker-authority-resolver.d.ts.map +1 -0
- package/dist/core/delegation/worker-authority-resolver.js +128 -0
- package/dist/core/delegation/worker-authority-resolver.js.map +1 -0
- package/dist/core/delegation/worker-conversation-store.d.ts.map +1 -1
- package/dist/core/delegation/worker-conversation-store.js +1 -1
- package/dist/core/delegation/worker-conversation-store.js.map +1 -1
- package/dist/core/delegation/worker-delegation-controller.d.ts +7 -1
- package/dist/core/delegation/worker-delegation-controller.d.ts.map +1 -1
- package/dist/core/delegation/worker-delegation-controller.js +260 -87
- package/dist/core/delegation/worker-delegation-controller.js.map +1 -1
- package/dist/core/delegation/worker-delegation-request.d.ts +25 -4
- package/dist/core/delegation/worker-delegation-request.d.ts.map +1 -1
- package/dist/core/delegation/worker-delegation-request.js +90 -1
- package/dist/core/delegation/worker-delegation-request.js.map +1 -1
- package/dist/core/delegation/worker-execution-policy.d.ts +2 -0
- package/dist/core/delegation/worker-execution-policy.d.ts.map +1 -1
- package/dist/core/delegation/worker-execution-policy.js +22 -12
- package/dist/core/delegation/worker-execution-policy.js.map +1 -1
- package/dist/core/delegation/worker-lifecycle.d.ts +1 -0
- package/dist/core/delegation/worker-lifecycle.d.ts.map +1 -1
- package/dist/core/delegation/worker-lifecycle.js +4 -2
- package/dist/core/delegation/worker-lifecycle.js.map +1 -1
- package/dist/core/delegation/worker-profile-resolver.d.ts +0 -2
- package/dist/core/delegation/worker-profile-resolver.d.ts.map +1 -1
- package/dist/core/delegation/worker-profile-resolver.js +8 -35
- package/dist/core/delegation/worker-profile-resolver.js.map +1 -1
- package/dist/core/delegation/worker-recovery-coordinator.d.ts.map +1 -1
- package/dist/core/delegation/worker-recovery-coordinator.js +1 -0
- package/dist/core/delegation/worker-recovery-coordinator.js.map +1 -1
- package/dist/core/delegation/worker-runner.d.ts +6 -1
- package/dist/core/delegation/worker-runner.d.ts.map +1 -1
- package/dist/core/delegation/worker-runner.js +20 -6
- package/dist/core/delegation/worker-runner.js.map +1 -1
- package/dist/core/delegation/worker-tree-budget-coordinator.d.ts +47 -0
- package/dist/core/delegation/worker-tree-budget-coordinator.d.ts.map +1 -0
- package/dist/core/delegation/worker-tree-budget-coordinator.js +210 -0
- package/dist/core/delegation/worker-tree-budget-coordinator.js.map +1 -0
- package/dist/core/memory/providers/file-store.d.ts +2 -0
- package/dist/core/memory/providers/file-store.d.ts.map +1 -1
- package/dist/core/memory/providers/file-store.js +22 -20
- package/dist/core/memory/providers/file-store.js.map +1 -1
- package/dist/core/models/runtime-process.d.ts.map +1 -1
- package/dist/core/models/runtime-process.js +5 -18
- package/dist/core/models/runtime-process.js.map +1 -1
- package/dist/core/orchestration/bounded-string-array.d.ts +11 -0
- package/dist/core/orchestration/bounded-string-array.d.ts.map +1 -0
- package/dist/core/orchestration/bounded-string-array.js +17 -0
- package/dist/core/orchestration/bounded-string-array.js.map +1 -0
- package/dist/core/orchestration/capability-gateway.d.ts +16 -0
- package/dist/core/orchestration/capability-gateway.d.ts.map +1 -1
- package/dist/core/orchestration/capability-gateway.js +38 -0
- package/dist/core/orchestration/capability-gateway.js.map +1 -1
- package/dist/core/orchestration/contracts.d.ts +11 -3
- package/dist/core/orchestration/contracts.d.ts.map +1 -1
- package/dist/core/orchestration/contracts.js +0 -1
- package/dist/core/orchestration/contracts.js.map +1 -1
- package/dist/core/orchestration/delegation-ledger.d.ts +1 -0
- package/dist/core/orchestration/delegation-ledger.d.ts.map +1 -1
- package/dist/core/orchestration/delegation-ledger.js +3 -0
- package/dist/core/orchestration/delegation-ledger.js.map +1 -1
- package/dist/core/orchestration/event-store.d.ts +12 -10
- package/dist/core/orchestration/event-store.d.ts.map +1 -1
- package/dist/core/orchestration/event-store.js +94 -104
- package/dist/core/orchestration/event-store.js.map +1 -1
- package/dist/core/orchestration/lane-tool-manifests.d.ts +2 -2
- package/dist/core/orchestration/lane-tool-manifests.d.ts.map +1 -1
- package/dist/core/orchestration/lane-tool-manifests.js +4 -1
- package/dist/core/orchestration/lane-tool-manifests.js.map +1 -1
- package/dist/core/orchestration/policy-compiler.d.ts.map +1 -1
- package/dist/core/orchestration/policy-compiler.js +8 -9
- package/dist/core/orchestration/policy-compiler.js.map +1 -1
- package/dist/core/orchestration/profile-registry.d.ts.map +1 -1
- package/dist/core/orchestration/profile-registry.js +4 -10
- package/dist/core/orchestration/profile-registry.js.map +1 -1
- package/dist/core/orchestration/task-runtime.d.ts +1 -0
- package/dist/core/orchestration/task-runtime.d.ts.map +1 -1
- package/dist/core/orchestration/task-runtime.js +58 -3
- package/dist/core/orchestration/task-runtime.js.map +1 -1
- package/dist/core/orchestration/worker-execution-contract.d.ts.map +1 -1
- package/dist/core/orchestration/worker-execution-contract.js +10 -17
- package/dist/core/orchestration/worker-execution-contract.js.map +1 -1
- package/dist/core/risk-classifier.js +3 -3
- package/dist/core/risk-classifier.js.map +1 -1
- package/dist/core/runtime-builder.d.ts +4 -1
- package/dist/core/runtime-builder.d.ts.map +1 -1
- package/dist/core/runtime-builder.js +34 -15
- package/dist/core/runtime-builder.js.map +1 -1
- package/dist/core/secrets/bitwarden-credential-storage.d.ts +51 -0
- package/dist/core/secrets/bitwarden-credential-storage.d.ts.map +1 -0
- package/dist/core/secrets/bitwarden-credential-storage.js +345 -0
- package/dist/core/secrets/bitwarden-credential-storage.js.map +1 -0
- package/dist/core/secrets/credential-exposure-guard.d.ts +8 -4
- package/dist/core/secrets/credential-exposure-guard.d.ts.map +1 -1
- package/dist/core/secrets/credential-exposure-guard.js +30 -31
- package/dist/core/secrets/credential-exposure-guard.js.map +1 -1
- package/dist/core/secrets/credential-manager.d.ts +109 -0
- package/dist/core/secrets/credential-manager.d.ts.map +1 -0
- package/dist/core/secrets/credential-manager.js +384 -0
- package/dist/core/secrets/credential-manager.js.map +1 -0
- package/dist/core/secrets/credential-project.d.ts +4 -0
- package/dist/core/secrets/credential-project.d.ts.map +1 -0
- package/dist/core/secrets/credential-project.js +145 -0
- package/dist/core/secrets/credential-project.js.map +1 -0
- package/dist/core/secrets/secret-dotenv.d.ts +1 -1
- package/dist/core/secrets/secret-dotenv.js +1 -1
- package/dist/core/secrets/secret-dotenv.js.map +1 -1
- package/dist/core/settings-manager.d.ts +4 -2
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +9 -5
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/slash-commands.d.ts.map +1 -1
- package/dist/core/slash-commands.js +1 -0
- package/dist/core/slash-commands.js.map +1 -1
- package/dist/core/system-prompt.js +1 -1
- package/dist/core/system-prompt.js.map +1 -1
- package/dist/core/tool-capability-policy.js +2 -2
- package/dist/core/tool-capability-policy.js.map +1 -1
- package/dist/core/tools/delegate.d.ts +29 -1
- package/dist/core/tools/delegate.d.ts.map +1 -1
- package/dist/core/tools/delegate.js +179 -28
- package/dist/core/tools/delegate.js.map +1 -1
- package/dist/core/tools/git-filter.d.ts +1 -0
- package/dist/core/tools/git-filter.d.ts.map +1 -1
- package/dist/core/tools/git-filter.js +1 -1
- package/dist/core/tools/git-filter.js.map +1 -1
- package/dist/core/tools/profile-writer.js +3 -3
- package/dist/core/tools/profile-writer.js.map +1 -1
- package/dist/core/tools/python.d.ts +2 -0
- package/dist/core/tools/python.d.ts.map +1 -1
- package/dist/core/tools/python.js +17 -12
- package/dist/core/tools/python.js.map +1 -1
- package/dist/core/tools/run-process.d.ts +2 -0
- package/dist/core/tools/run-process.d.ts.map +1 -1
- package/dist/core/tools/run-process.js +7 -3
- package/dist/core/tools/run-process.js.map +1 -1
- package/dist/core/tools/secret-store.d.ts +8 -18
- package/dist/core/tools/secret-store.d.ts.map +1 -1
- package/dist/core/tools/secret-store.js +83 -348
- package/dist/core/tools/secret-store.js.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/migrations.d.ts.map +1 -1
- package/dist/migrations.js +38 -1
- package/dist/migrations.js.map +1 -1
- package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/settings-selector.js +35 -14
- package/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +1 -0
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +26 -3
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/secret-menu-controller.d.ts +21 -0
- package/dist/modes/interactive/secret-menu-controller.d.ts.map +1 -0
- package/dist/modes/interactive/secret-menu-controller.js +276 -0
- package/dist/modes/interactive/secret-menu-controller.js.map +1 -0
- package/dist/utils/tools-manager.d.ts +2 -1
- package/dist/utils/tools-manager.d.ts.map +1 -1
- package/dist/utils/tools-manager.js +43 -48
- package/dist/utils/tools-manager.js.map +1 -1
- package/dist/utils/zip-extractor.d.ts +8 -0
- package/dist/utils/zip-extractor.d.ts.map +1 -0
- package/dist/utils/zip-extractor.js +275 -0
- package/dist/utils/zip-extractor.js.map +1 -0
- package/docs/harness-architecture.md +34 -22
- package/docs/index.md +1 -1
- package/docs/resources.md +1 -1
- package/docs/settings.md +39 -103
- package/docs/usage.md +7 -5
- package/docs/worker-profiles.md +9 -7
- 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
- package/dist/core/secrets/secret-vault-format.d.ts +0 -112
- package/dist/core/secrets/secret-vault-format.d.ts.map +0 -1
- package/dist/core/secrets/secret-vault-format.js +0 -396
- package/dist/core/secrets/secret-vault-format.js.map +0 -1
- package/dist/core/secrets/secret-vault.d.ts +0 -72
- package/dist/core/secrets/secret-vault.d.ts.map +0 -1
- package/dist/core/secrets/secret-vault.js +0 -663
- package/dist/core/secrets/secret-vault.js.map +0 -1
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { SharedCapabilityBudget } from "../orchestration/capability-gateway.ts";
|
|
2
|
+
import type { AttemptUsageSnapshot, RiskBudget } from "../orchestration/contracts.ts";
|
|
3
|
+
export declare class WorkerTreeBudgetExceededError extends Error {
|
|
4
|
+
readonly field: "maxTokens" | "maxCostUsd" | "maxToolCalls" | "maxWallClockMs" | "maxAttempts";
|
|
5
|
+
constructor(field: WorkerTreeBudgetExceededError["field"], subject: string);
|
|
6
|
+
}
|
|
7
|
+
export interface WorkerTreeBudgetSeed {
|
|
8
|
+
attemptId: string;
|
|
9
|
+
usage: AttemptUsageSnapshot;
|
|
10
|
+
}
|
|
11
|
+
export interface WorkerTreeBudgetProjection {
|
|
12
|
+
agents: Readonly<Record<string, {
|
|
13
|
+
rootAgentId: string;
|
|
14
|
+
}>>;
|
|
15
|
+
attempts: Readonly<Record<string, {
|
|
16
|
+
attemptId: string;
|
|
17
|
+
agentId?: string;
|
|
18
|
+
dispatch: {
|
|
19
|
+
logicalLaneId?: string;
|
|
20
|
+
};
|
|
21
|
+
checkpointIds: readonly string[];
|
|
22
|
+
}>>;
|
|
23
|
+
checkpoints: Readonly<Record<string, {
|
|
24
|
+
usage?: AttemptUsageSnapshot;
|
|
25
|
+
}>>;
|
|
26
|
+
}
|
|
27
|
+
/** Rebuild every durable tree attempt, including attempts with no usage checkpoint yet. */
|
|
28
|
+
export declare function collectWorkerTreeBudgetSeeds(snapshot: WorkerTreeBudgetProjection, rootAgentId: string): WorkerTreeBudgetSeed[];
|
|
29
|
+
/** One in-memory aggregate reconstructed from durable checkpoints whenever a root is first used. */
|
|
30
|
+
export declare class WorkerTreeBudgetCoordinator {
|
|
31
|
+
private readonly trees;
|
|
32
|
+
createPort(args: {
|
|
33
|
+
rootAgentId: string;
|
|
34
|
+
attemptId: string;
|
|
35
|
+
budget: RiskBudget;
|
|
36
|
+
seeds: readonly WorkerTreeBudgetSeed[];
|
|
37
|
+
initialUsage: AttemptUsageSnapshot;
|
|
38
|
+
}): SharedCapabilityBudget;
|
|
39
|
+
private recordAttemptUsage;
|
|
40
|
+
private reserveProviderBudget;
|
|
41
|
+
private drainWaiters;
|
|
42
|
+
private detachAbort;
|
|
43
|
+
private totalTokens;
|
|
44
|
+
private reservedTokens;
|
|
45
|
+
private assertAvailable;
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=worker-tree-budget-coordinator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"worker-tree-budget-coordinator.d.ts","sourceRoot":"","sources":["../../../src/core/delegation/worker-tree-budget-coordinator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAGX,sBAAsB,EACtB,MAAM,wCAAwC,CAAC;AAChD,OAAO,KAAK,EAAE,oBAAoB,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAGtF,qBAAa,6BAA8B,SAAQ,KAAK;IACvD,QAAQ,CAAC,KAAK,EAAE,WAAW,GAAG,YAAY,GAAG,cAAc,GAAG,gBAAgB,GAAG,aAAa,CAAC;IAE/F,YAAY,KAAK,EAAE,6BAA6B,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,MAAM,EAIzE;CACD;AAmBD,MAAM,WAAW,oBAAoB;IACpC,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,oBAAoB,CAAC;CAC5B;AAED,MAAM,WAAW,0BAA0B;IAC1C,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE;QAAE,WAAW,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC,CAAC;IAC1D,QAAQ,EAAE,QAAQ,CACjB,MAAM,CACL,MAAM,EACN;QACC,SAAS,EAAE,MAAM,CAAC;QAClB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,QAAQ,EAAE;YAAE,aAAa,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC;QACrC,aAAa,EAAE,SAAS,MAAM,EAAE,CAAC;KACjC,CACD,CACD,CAAC;IACF,WAAW,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE;QAAE,KAAK,CAAC,EAAE,oBAAoB,CAAA;KAAE,CAAC,CAAC,CAAC;CACxE;AAaD,2FAA2F;AAC3F,wBAAgB,4BAA4B,CAC3C,QAAQ,EAAE,0BAA0B,EACpC,WAAW,EAAE,MAAM,GACjB,oBAAoB,EAAE,CAYxB;AAiCD,oGAAoG;AACpG,qBAAa,2BAA2B;IACvC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAsC;IAE5D,UAAU,CAAC,IAAI,EAAE;QAChB,WAAW,EAAE,MAAM,CAAC;QACpB,SAAS,EAAE,MAAM,CAAC;QAClB,MAAM,EAAE,UAAU,CAAC;QACnB,KAAK,EAAE,SAAS,oBAAoB,EAAE,CAAC;QACvC,YAAY,EAAE,oBAAoB,CAAC;KACnC,GAAG,sBAAsB,CA4BzB;IAED,OAAO,CAAC,kBAAkB;IAa1B,OAAO,CAAC,qBAAqB;IAmC7B,OAAO,CAAC,YAAY;IA4CpB,OAAO,CAAC,WAAW;IAInB,OAAO,CAAC,WAAW;IAInB,OAAO,CAAC,cAAc;IAItB,OAAO,CAAC,eAAe;CA2BvB"}
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
import { intersectRiskBudgets } from "../orchestration/risk-budget.js";
|
|
2
|
+
export class WorkerTreeBudgetExceededError extends Error {
|
|
3
|
+
constructor(field, subject) {
|
|
4
|
+
super(`Worker orchestration tree budget '${field}' is exhausted before ${subject}.`);
|
|
5
|
+
this.name = "WorkerTreeBudgetExceededError";
|
|
6
|
+
this.field = field;
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
const EMPTY_ATTEMPT_USAGE = {
|
|
10
|
+
toolCalls: 0,
|
|
11
|
+
inputTokens: 0,
|
|
12
|
+
outputTokens: 0,
|
|
13
|
+
cacheReadTokens: 0,
|
|
14
|
+
cacheWriteTokens: 0,
|
|
15
|
+
totalTokens: 0,
|
|
16
|
+
costUsd: 0,
|
|
17
|
+
activeWallClockMs: 0,
|
|
18
|
+
};
|
|
19
|
+
/** Rebuild every durable tree attempt, including attempts with no usage checkpoint yet. */
|
|
20
|
+
export function collectWorkerTreeBudgetSeeds(snapshot, rootAgentId) {
|
|
21
|
+
const seeds = [];
|
|
22
|
+
for (const attempt of Object.values(snapshot.attempts)) {
|
|
23
|
+
const attemptAgentId = attempt.agentId ?? attempt.dispatch.logicalLaneId;
|
|
24
|
+
if (!attemptAgentId || snapshot.agents[attemptAgentId]?.rootAgentId !== rootAgentId)
|
|
25
|
+
continue;
|
|
26
|
+
const usage = [...attempt.checkpointIds]
|
|
27
|
+
.reverse()
|
|
28
|
+
.map((checkpointId) => snapshot.checkpoints[checkpointId]?.usage)
|
|
29
|
+
.find((candidate) => candidate !== undefined);
|
|
30
|
+
seeds.push({ attemptId: attempt.attemptId, usage: usage ?? EMPTY_ATTEMPT_USAGE });
|
|
31
|
+
}
|
|
32
|
+
return seeds;
|
|
33
|
+
}
|
|
34
|
+
function gatewayUsage(usage) {
|
|
35
|
+
return {
|
|
36
|
+
toolCalls: usage.toolCalls,
|
|
37
|
+
inputTokens: usage.inputTokens,
|
|
38
|
+
outputTokens: usage.outputTokens,
|
|
39
|
+
cacheReadTokens: usage.cacheReadTokens,
|
|
40
|
+
cacheWriteTokens: usage.cacheWriteTokens,
|
|
41
|
+
totalTokens: usage.totalTokens,
|
|
42
|
+
costUsd: usage.costUsd,
|
|
43
|
+
wallClockMs: usage.activeWallClockMs,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
function mergeUsage(current, incoming) {
|
|
47
|
+
if (!current)
|
|
48
|
+
return structuredClone(incoming);
|
|
49
|
+
return {
|
|
50
|
+
toolCalls: Math.max(current.toolCalls, incoming.toolCalls),
|
|
51
|
+
inputTokens: Math.max(current.inputTokens, incoming.inputTokens),
|
|
52
|
+
outputTokens: Math.max(current.outputTokens, incoming.outputTokens),
|
|
53
|
+
cacheReadTokens: Math.max(current.cacheReadTokens, incoming.cacheReadTokens),
|
|
54
|
+
cacheWriteTokens: Math.max(current.cacheWriteTokens, incoming.cacheWriteTokens),
|
|
55
|
+
totalTokens: Math.max(current.totalTokens, incoming.totalTokens),
|
|
56
|
+
costUsd: Math.max(current.costUsd, incoming.costUsd),
|
|
57
|
+
wallClockMs: Math.max(current.wallClockMs, incoming.wallClockMs),
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
function abortReason(signal) {
|
|
61
|
+
return signal.reason ?? new Error("Worker provider budget reservation was aborted.");
|
|
62
|
+
}
|
|
63
|
+
/** One in-memory aggregate reconstructed from durable checkpoints whenever a root is first used. */
|
|
64
|
+
export class WorkerTreeBudgetCoordinator {
|
|
65
|
+
constructor() {
|
|
66
|
+
this.trees = new Map();
|
|
67
|
+
}
|
|
68
|
+
createPort(args) {
|
|
69
|
+
let state = this.trees.get(args.rootAgentId);
|
|
70
|
+
if (!state) {
|
|
71
|
+
state = { budget: structuredClone(args.budget), attempts: new Map(), reservations: new Map(), waiters: [] };
|
|
72
|
+
this.trees.set(args.rootAgentId, state);
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
state.budget = intersectRiskBudgets(state.budget, args.budget);
|
|
76
|
+
}
|
|
77
|
+
for (const seed of args.seeds) {
|
|
78
|
+
state.attempts.set(seed.attemptId, mergeUsage(state.attempts.get(seed.attemptId), gatewayUsage(seed.usage)));
|
|
79
|
+
}
|
|
80
|
+
state.attempts.set(args.attemptId, mergeUsage(state.attempts.get(args.attemptId), gatewayUsage(args.initialUsage)));
|
|
81
|
+
const tree = state;
|
|
82
|
+
return {
|
|
83
|
+
assertBudgetAvailable: (subject) => this.assertAvailable(tree, subject),
|
|
84
|
+
recordAttemptUsage: (usage) => this.recordAttemptUsage(tree, args.attemptId, usage),
|
|
85
|
+
remainingTokens: () => {
|
|
86
|
+
const maximum = tree.budget.maxTokens;
|
|
87
|
+
return maximum === undefined
|
|
88
|
+
? undefined
|
|
89
|
+
: Math.max(0, maximum - this.totalTokens(tree) - this.reservedTokens(tree));
|
|
90
|
+
},
|
|
91
|
+
reserveProviderBudget: (requestedMaxTokens, subject, signal) => this.reserveProviderBudget(tree, args.attemptId, requestedMaxTokens, subject, signal),
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
recordAttemptUsage(state, attemptId, usage) {
|
|
95
|
+
const previous = state.attempts.get(attemptId);
|
|
96
|
+
const merged = mergeUsage(previous, usage);
|
|
97
|
+
state.attempts.set(attemptId, merged);
|
|
98
|
+
const reservation = state.reservations.get(attemptId);
|
|
99
|
+
if (reservation && previous) {
|
|
100
|
+
reservation.maxTokens = Math.max(0, reservation.maxTokens - Math.max(0, merged.totalTokens - previous.totalTokens));
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
reserveProviderBudget(state, attemptId, requestedMaxTokens, subject, signal) {
|
|
104
|
+
if (!Number.isSafeInteger(requestedMaxTokens) || requestedMaxTokens <= 0) {
|
|
105
|
+
return Promise.reject(new Error("Worker provider token reservation must be a positive safe integer."));
|
|
106
|
+
}
|
|
107
|
+
if (signal?.aborted)
|
|
108
|
+
return Promise.reject(abortReason(signal));
|
|
109
|
+
return new Promise((resolve, reject) => {
|
|
110
|
+
const waiter = {
|
|
111
|
+
attemptId,
|
|
112
|
+
requestedMaxTokens,
|
|
113
|
+
subject,
|
|
114
|
+
...(signal ? { signal } : {}),
|
|
115
|
+
resolve,
|
|
116
|
+
reject,
|
|
117
|
+
};
|
|
118
|
+
if (signal) {
|
|
119
|
+
waiter.onAbort = () => {
|
|
120
|
+
const index = state.waiters.indexOf(waiter);
|
|
121
|
+
if (index < 0)
|
|
122
|
+
return;
|
|
123
|
+
state.waiters.splice(index, 1);
|
|
124
|
+
reject(abortReason(signal));
|
|
125
|
+
this.drainWaiters(state);
|
|
126
|
+
};
|
|
127
|
+
signal.addEventListener("abort", waiter.onAbort, { once: true });
|
|
128
|
+
}
|
|
129
|
+
state.waiters.push(waiter);
|
|
130
|
+
this.drainWaiters(state);
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
drainWaiters(state) {
|
|
134
|
+
while (state.waiters.length > 0) {
|
|
135
|
+
const waiter = state.waiters[0];
|
|
136
|
+
if (!waiter)
|
|
137
|
+
return;
|
|
138
|
+
try {
|
|
139
|
+
this.assertAvailable(state, waiter.subject);
|
|
140
|
+
}
|
|
141
|
+
catch (error) {
|
|
142
|
+
state.waiters.shift();
|
|
143
|
+
this.detachAbort(waiter);
|
|
144
|
+
waiter.reject(error);
|
|
145
|
+
continue;
|
|
146
|
+
}
|
|
147
|
+
if (state.reservations.has(waiter.attemptId))
|
|
148
|
+
return;
|
|
149
|
+
if ((state.budget.maxCostUsd !== undefined || state.budget.maxWallClockMs !== undefined) &&
|
|
150
|
+
state.reservations.size > 0) {
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
const availableTokens = state.budget.maxTokens === undefined
|
|
154
|
+
? waiter.requestedMaxTokens
|
|
155
|
+
: Math.max(0, state.budget.maxTokens - this.totalTokens(state) - this.reservedTokens(state));
|
|
156
|
+
if (availableTokens <= 0)
|
|
157
|
+
return;
|
|
158
|
+
const maxTokens = Math.min(waiter.requestedMaxTokens, availableTokens);
|
|
159
|
+
state.waiters.shift();
|
|
160
|
+
this.detachAbort(waiter);
|
|
161
|
+
const reservationState = { maxTokens };
|
|
162
|
+
state.reservations.set(waiter.attemptId, reservationState);
|
|
163
|
+
let released = false;
|
|
164
|
+
waiter.resolve({
|
|
165
|
+
maxTokens,
|
|
166
|
+
release: () => {
|
|
167
|
+
if (released)
|
|
168
|
+
return;
|
|
169
|
+
released = true;
|
|
170
|
+
if (state.reservations.get(waiter.attemptId) === reservationState) {
|
|
171
|
+
state.reservations.delete(waiter.attemptId);
|
|
172
|
+
}
|
|
173
|
+
this.drainWaiters(state);
|
|
174
|
+
},
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
detachAbort(waiter) {
|
|
179
|
+
if (waiter.signal && waiter.onAbort)
|
|
180
|
+
waiter.signal.removeEventListener("abort", waiter.onAbort);
|
|
181
|
+
}
|
|
182
|
+
totalTokens(state) {
|
|
183
|
+
return [...state.attempts.values()].reduce((total, usage) => total + usage.totalTokens, 0);
|
|
184
|
+
}
|
|
185
|
+
reservedTokens(state) {
|
|
186
|
+
return [...state.reservations.values()].reduce((total, reservation) => total + reservation.maxTokens, 0);
|
|
187
|
+
}
|
|
188
|
+
assertAvailable(state, subject) {
|
|
189
|
+
const usages = [...state.attempts.values()];
|
|
190
|
+
if (state.budget.maxAttempts !== undefined && usages.length > state.budget.maxAttempts) {
|
|
191
|
+
throw new WorkerTreeBudgetExceededError("maxAttempts", subject);
|
|
192
|
+
}
|
|
193
|
+
if (state.budget.maxTokens !== undefined && this.totalTokens(state) >= state.budget.maxTokens) {
|
|
194
|
+
throw new WorkerTreeBudgetExceededError("maxTokens", subject);
|
|
195
|
+
}
|
|
196
|
+
if (state.budget.maxCostUsd !== undefined &&
|
|
197
|
+
usages.reduce((total, usage) => total + usage.costUsd, 0) >= state.budget.maxCostUsd) {
|
|
198
|
+
throw new WorkerTreeBudgetExceededError("maxCostUsd", subject);
|
|
199
|
+
}
|
|
200
|
+
if (state.budget.maxToolCalls !== undefined &&
|
|
201
|
+
usages.reduce((total, usage) => total + usage.toolCalls, 0) >= state.budget.maxToolCalls) {
|
|
202
|
+
throw new WorkerTreeBudgetExceededError("maxToolCalls", subject);
|
|
203
|
+
}
|
|
204
|
+
if (state.budget.maxWallClockMs !== undefined &&
|
|
205
|
+
usages.reduce((total, usage) => total + usage.wallClockMs, 0) >= state.budget.maxWallClockMs) {
|
|
206
|
+
throw new WorkerTreeBudgetExceededError("maxWallClockMs", subject);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
//# sourceMappingURL=worker-tree-budget-coordinator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"worker-tree-budget-coordinator.js","sourceRoot":"","sources":["../../../src/core/delegation/worker-tree-budget-coordinator.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n\tGatewayUsageSnapshot,\n\tProviderBudgetReservation,\n\tSharedCapabilityBudget,\n} from \"../orchestration/capability-gateway.ts\";\nimport type { AttemptUsageSnapshot, RiskBudget } from \"../orchestration/contracts.ts\";\nimport { intersectRiskBudgets } from \"../orchestration/risk-budget.ts\";\n\nexport class WorkerTreeBudgetExceededError extends Error {\n\treadonly field: \"maxTokens\" | \"maxCostUsd\" | \"maxToolCalls\" | \"maxWallClockMs\" | \"maxAttempts\";\n\n\tconstructor(field: WorkerTreeBudgetExceededError[\"field\"], subject: string) {\n\t\tsuper(`Worker orchestration tree budget '${field}' is exhausted before ${subject}.`);\n\t\tthis.name = \"WorkerTreeBudgetExceededError\";\n\t\tthis.field = field;\n\t}\n}\n\ninterface TreeBudgetState {\n\tbudget: RiskBudget;\n\tattempts: Map<string, GatewayUsageSnapshot>;\n\treservations: Map<string, { maxTokens: number }>;\n\twaiters: ProviderBudgetWaiter[];\n}\n\ninterface ProviderBudgetWaiter {\n\tattemptId: string;\n\trequestedMaxTokens: number;\n\tsubject: string;\n\tsignal?: AbortSignal;\n\tresolve(reservation: ProviderBudgetReservation): void;\n\treject(error: unknown): void;\n\tonAbort?: () => void;\n}\n\nexport interface WorkerTreeBudgetSeed {\n\tattemptId: string;\n\tusage: AttemptUsageSnapshot;\n}\n\nexport interface WorkerTreeBudgetProjection {\n\tagents: Readonly<Record<string, { rootAgentId: string }>>;\n\tattempts: Readonly<\n\t\tRecord<\n\t\t\tstring,\n\t\t\t{\n\t\t\t\tattemptId: string;\n\t\t\t\tagentId?: string;\n\t\t\t\tdispatch: { logicalLaneId?: string };\n\t\t\t\tcheckpointIds: readonly string[];\n\t\t\t}\n\t\t>\n\t>;\n\tcheckpoints: Readonly<Record<string, { usage?: AttemptUsageSnapshot }>>;\n}\n\nconst EMPTY_ATTEMPT_USAGE: AttemptUsageSnapshot = {\n\ttoolCalls: 0,\n\tinputTokens: 0,\n\toutputTokens: 0,\n\tcacheReadTokens: 0,\n\tcacheWriteTokens: 0,\n\ttotalTokens: 0,\n\tcostUsd: 0,\n\tactiveWallClockMs: 0,\n};\n\n/** Rebuild every durable tree attempt, including attempts with no usage checkpoint yet. */\nexport function collectWorkerTreeBudgetSeeds(\n\tsnapshot: WorkerTreeBudgetProjection,\n\trootAgentId: string,\n): WorkerTreeBudgetSeed[] {\n\tconst seeds: WorkerTreeBudgetSeed[] = [];\n\tfor (const attempt of Object.values(snapshot.attempts)) {\n\t\tconst attemptAgentId = attempt.agentId ?? attempt.dispatch.logicalLaneId;\n\t\tif (!attemptAgentId || snapshot.agents[attemptAgentId]?.rootAgentId !== rootAgentId) continue;\n\t\tconst usage = [...attempt.checkpointIds]\n\t\t\t.reverse()\n\t\t\t.map((checkpointId) => snapshot.checkpoints[checkpointId]?.usage)\n\t\t\t.find((candidate): candidate is AttemptUsageSnapshot => candidate !== undefined);\n\t\tseeds.push({ attemptId: attempt.attemptId, usage: usage ?? EMPTY_ATTEMPT_USAGE });\n\t}\n\treturn seeds;\n}\n\nfunction gatewayUsage(usage: AttemptUsageSnapshot): GatewayUsageSnapshot {\n\treturn {\n\t\ttoolCalls: usage.toolCalls,\n\t\tinputTokens: usage.inputTokens,\n\t\toutputTokens: usage.outputTokens,\n\t\tcacheReadTokens: usage.cacheReadTokens,\n\t\tcacheWriteTokens: usage.cacheWriteTokens,\n\t\ttotalTokens: usage.totalTokens,\n\t\tcostUsd: usage.costUsd,\n\t\twallClockMs: usage.activeWallClockMs,\n\t};\n}\n\nfunction mergeUsage(current: GatewayUsageSnapshot | undefined, incoming: GatewayUsageSnapshot): GatewayUsageSnapshot {\n\tif (!current) return structuredClone(incoming);\n\treturn {\n\t\ttoolCalls: Math.max(current.toolCalls, incoming.toolCalls),\n\t\tinputTokens: Math.max(current.inputTokens, incoming.inputTokens),\n\t\toutputTokens: Math.max(current.outputTokens, incoming.outputTokens),\n\t\tcacheReadTokens: Math.max(current.cacheReadTokens, incoming.cacheReadTokens),\n\t\tcacheWriteTokens: Math.max(current.cacheWriteTokens, incoming.cacheWriteTokens),\n\t\ttotalTokens: Math.max(current.totalTokens, incoming.totalTokens),\n\t\tcostUsd: Math.max(current.costUsd, incoming.costUsd),\n\t\twallClockMs: Math.max(current.wallClockMs, incoming.wallClockMs),\n\t};\n}\n\nfunction abortReason(signal: AbortSignal): unknown {\n\treturn signal.reason ?? new Error(\"Worker provider budget reservation was aborted.\");\n}\n\n/** One in-memory aggregate reconstructed from durable checkpoints whenever a root is first used. */\nexport class WorkerTreeBudgetCoordinator {\n\tprivate readonly trees = new Map<string, TreeBudgetState>();\n\n\tcreatePort(args: {\n\t\trootAgentId: string;\n\t\tattemptId: string;\n\t\tbudget: RiskBudget;\n\t\tseeds: readonly WorkerTreeBudgetSeed[];\n\t\tinitialUsage: AttemptUsageSnapshot;\n\t}): SharedCapabilityBudget {\n\t\tlet state = this.trees.get(args.rootAgentId);\n\t\tif (!state) {\n\t\t\tstate = { budget: structuredClone(args.budget), attempts: new Map(), reservations: new Map(), waiters: [] };\n\t\t\tthis.trees.set(args.rootAgentId, state);\n\t\t} else {\n\t\t\tstate.budget = intersectRiskBudgets(state.budget, args.budget);\n\t\t}\n\t\tfor (const seed of args.seeds) {\n\t\t\tstate.attempts.set(seed.attemptId, mergeUsage(state.attempts.get(seed.attemptId), gatewayUsage(seed.usage)));\n\t\t}\n\t\tstate.attempts.set(\n\t\t\targs.attemptId,\n\t\t\tmergeUsage(state.attempts.get(args.attemptId), gatewayUsage(args.initialUsage)),\n\t\t);\n\t\tconst tree = state;\n\t\treturn {\n\t\t\tassertBudgetAvailable: (subject) => this.assertAvailable(tree, subject),\n\t\t\trecordAttemptUsage: (usage) => this.recordAttemptUsage(tree, args.attemptId, usage),\n\t\t\tremainingTokens: () => {\n\t\t\t\tconst maximum = tree.budget.maxTokens;\n\t\t\t\treturn maximum === undefined\n\t\t\t\t\t? undefined\n\t\t\t\t\t: Math.max(0, maximum - this.totalTokens(tree) - this.reservedTokens(tree));\n\t\t\t},\n\t\t\treserveProviderBudget: (requestedMaxTokens, subject, signal) =>\n\t\t\t\tthis.reserveProviderBudget(tree, args.attemptId, requestedMaxTokens, subject, signal),\n\t\t};\n\t}\n\n\tprivate recordAttemptUsage(state: TreeBudgetState, attemptId: string, usage: GatewayUsageSnapshot): void {\n\t\tconst previous = state.attempts.get(attemptId);\n\t\tconst merged = mergeUsage(previous, usage);\n\t\tstate.attempts.set(attemptId, merged);\n\t\tconst reservation = state.reservations.get(attemptId);\n\t\tif (reservation && previous) {\n\t\t\treservation.maxTokens = Math.max(\n\t\t\t\t0,\n\t\t\t\treservation.maxTokens - Math.max(0, merged.totalTokens - previous.totalTokens),\n\t\t\t);\n\t\t}\n\t}\n\n\tprivate reserveProviderBudget(\n\t\tstate: TreeBudgetState,\n\t\tattemptId: string,\n\t\trequestedMaxTokens: number,\n\t\tsubject: string,\n\t\tsignal?: AbortSignal,\n\t): Promise<ProviderBudgetReservation> {\n\t\tif (!Number.isSafeInteger(requestedMaxTokens) || requestedMaxTokens <= 0) {\n\t\t\treturn Promise.reject(new Error(\"Worker provider token reservation must be a positive safe integer.\"));\n\t\t}\n\t\tif (signal?.aborted) return Promise.reject(abortReason(signal));\n\t\treturn new Promise<ProviderBudgetReservation>((resolve, reject) => {\n\t\t\tconst waiter: ProviderBudgetWaiter = {\n\t\t\t\tattemptId,\n\t\t\t\trequestedMaxTokens,\n\t\t\t\tsubject,\n\t\t\t\t...(signal ? { signal } : {}),\n\t\t\t\tresolve,\n\t\t\t\treject,\n\t\t\t};\n\t\t\tif (signal) {\n\t\t\t\twaiter.onAbort = () => {\n\t\t\t\t\tconst index = state.waiters.indexOf(waiter);\n\t\t\t\t\tif (index < 0) return;\n\t\t\t\t\tstate.waiters.splice(index, 1);\n\t\t\t\t\treject(abortReason(signal));\n\t\t\t\t\tthis.drainWaiters(state);\n\t\t\t\t};\n\t\t\t\tsignal.addEventListener(\"abort\", waiter.onAbort, { once: true });\n\t\t\t}\n\t\t\tstate.waiters.push(waiter);\n\t\t\tthis.drainWaiters(state);\n\t\t});\n\t}\n\n\tprivate drainWaiters(state: TreeBudgetState): void {\n\t\twhile (state.waiters.length > 0) {\n\t\t\tconst waiter = state.waiters[0];\n\t\t\tif (!waiter) return;\n\t\t\ttry {\n\t\t\t\tthis.assertAvailable(state, waiter.subject);\n\t\t\t} catch (error) {\n\t\t\t\tstate.waiters.shift();\n\t\t\t\tthis.detachAbort(waiter);\n\t\t\t\twaiter.reject(error);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (state.reservations.has(waiter.attemptId)) return;\n\t\t\tif (\n\t\t\t\t(state.budget.maxCostUsd !== undefined || state.budget.maxWallClockMs !== undefined) &&\n\t\t\t\tstate.reservations.size > 0\n\t\t\t) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst availableTokens =\n\t\t\t\tstate.budget.maxTokens === undefined\n\t\t\t\t\t? waiter.requestedMaxTokens\n\t\t\t\t\t: Math.max(0, state.budget.maxTokens - this.totalTokens(state) - this.reservedTokens(state));\n\t\t\tif (availableTokens <= 0) return;\n\t\t\tconst maxTokens = Math.min(waiter.requestedMaxTokens, availableTokens);\n\t\t\tstate.waiters.shift();\n\t\t\tthis.detachAbort(waiter);\n\t\t\tconst reservationState = { maxTokens };\n\t\t\tstate.reservations.set(waiter.attemptId, reservationState);\n\t\t\tlet released = false;\n\t\t\twaiter.resolve({\n\t\t\t\tmaxTokens,\n\t\t\t\trelease: () => {\n\t\t\t\t\tif (released) return;\n\t\t\t\t\treleased = true;\n\t\t\t\t\tif (state.reservations.get(waiter.attemptId) === reservationState) {\n\t\t\t\t\t\tstate.reservations.delete(waiter.attemptId);\n\t\t\t\t\t}\n\t\t\t\t\tthis.drainWaiters(state);\n\t\t\t\t},\n\t\t\t});\n\t\t}\n\t}\n\n\tprivate detachAbort(waiter: ProviderBudgetWaiter): void {\n\t\tif (waiter.signal && waiter.onAbort) waiter.signal.removeEventListener(\"abort\", waiter.onAbort);\n\t}\n\n\tprivate totalTokens(state: TreeBudgetState): number {\n\t\treturn [...state.attempts.values()].reduce((total, usage) => total + usage.totalTokens, 0);\n\t}\n\n\tprivate reservedTokens(state: TreeBudgetState): number {\n\t\treturn [...state.reservations.values()].reduce((total, reservation) => total + reservation.maxTokens, 0);\n\t}\n\n\tprivate assertAvailable(state: TreeBudgetState, subject: string): void {\n\t\tconst usages = [...state.attempts.values()];\n\t\tif (state.budget.maxAttempts !== undefined && usages.length > state.budget.maxAttempts) {\n\t\t\tthrow new WorkerTreeBudgetExceededError(\"maxAttempts\", subject);\n\t\t}\n\t\tif (state.budget.maxTokens !== undefined && this.totalTokens(state) >= state.budget.maxTokens) {\n\t\t\tthrow new WorkerTreeBudgetExceededError(\"maxTokens\", subject);\n\t\t}\n\t\tif (\n\t\t\tstate.budget.maxCostUsd !== undefined &&\n\t\t\tusages.reduce((total, usage) => total + usage.costUsd, 0) >= state.budget.maxCostUsd\n\t\t) {\n\t\t\tthrow new WorkerTreeBudgetExceededError(\"maxCostUsd\", subject);\n\t\t}\n\t\tif (\n\t\t\tstate.budget.maxToolCalls !== undefined &&\n\t\t\tusages.reduce((total, usage) => total + usage.toolCalls, 0) >= state.budget.maxToolCalls\n\t\t) {\n\t\t\tthrow new WorkerTreeBudgetExceededError(\"maxToolCalls\", subject);\n\t\t}\n\t\tif (\n\t\t\tstate.budget.maxWallClockMs !== undefined &&\n\t\t\tusages.reduce((total, usage) => total + usage.wallClockMs, 0) >= state.budget.maxWallClockMs\n\t\t) {\n\t\t\tthrow new WorkerTreeBudgetExceededError(\"maxWallClockMs\", subject);\n\t\t}\n\t}\n}\n"]}
|
|
@@ -17,6 +17,8 @@ export declare class FileStoreProvider implements MemoryProvider {
|
|
|
17
17
|
private ctx?;
|
|
18
18
|
private memoryFilePath;
|
|
19
19
|
private userFilePath;
|
|
20
|
+
private memoryStatePath;
|
|
21
|
+
private userStatePath;
|
|
20
22
|
private lastWrittenMemory;
|
|
21
23
|
private lastWrittenUser;
|
|
22
24
|
private userArchive?;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"file-store.d.ts","sourceRoot":"","sources":["../../../../src/core/memory/providers/file-store.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uCAAuC,CAAC;AAChF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAQhE,OAAO,KAAK,EAAE,sBAAsB,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAGpF;;;;GAIG;AACH,wBAAgB,0BAA0B,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAsB3F;AAiBD,MAAM,WAAW,wBAAwB;IACxC,sBAAsB,CAAC,EAAE,MAAM,IAAI,CAAC;CACpC;AAED,eAAO,MAAM,6BAA6B,0LAC8I,CAAC;
|
|
1
|
+
{"version":3,"file":"file-store.d.ts","sourceRoot":"","sources":["../../../../src/core/memory/providers/file-store.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uCAAuC,CAAC;AAChF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAQhE,OAAO,KAAK,EAAE,sBAAsB,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAGpF;;;;GAIG;AACH,wBAAgB,0BAA0B,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAsB3F;AAiBD,MAAM,WAAW,wBAAwB;IACxC,sBAAsB,CAAC,EAAE,MAAM,IAAI,CAAC;CACpC;AAED,eAAO,MAAM,6BAA6B,0LAC8I,CAAC;AA4GzL,qBAAa,iBAAkB,YAAW,cAAc;IACvD,SAAgB,IAAI,gBAAgB;IACpC,SAAgB,MAAM,WAAW;IAEjC,OAAO,CAAC,GAAG,CAAC,CAAyB;IACrC,OAAO,CAAC,cAAc,CAAM;IAC5B,OAAO,CAAC,YAAY,CAAM;IAC1B,OAAO,CAAC,eAAe,CAAM;IAC7B,OAAO,CAAC,aAAa,CAAM;IAE3B,OAAO,CAAC,iBAAiB,CAAM;IAC/B,OAAO,CAAC,eAAe,CAAM;IAC7B,OAAO,CAAC,WAAW,CAAC,CAAoB;IACxC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA2B;IAGnD,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAQ;IAC7C,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,WAAW,CAAQ;IAE3C,YAAY,OAAO,GAAE,wBAA6B,EAEjD;IAEM,WAAW,IAAI,OAAO,CAE5B;IAEM,eAAe;QACZ,QAAQ;MACjB;IAEY,UAAU,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,EAAE,sBAAsB,GAAG,OAAO,CAAC,IAAI,CAAC,CAatF;YAEa,qBAAqB;IA8B5B,iBAAiB,CAAC,MAAM,CAAC,EAAE,kBAAkB,GAAG,MAAM,CAyC5D;IAEY,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAGrD;IAEY,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CAErC;IAEM,iBAAiB,IAAI,MAAM,EAAE,CAEnC;IAEM,kBAAkB,IAAI,cAAc,EAAE,CAoN5C;CACD"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createHash, randomUUID } from "node:crypto";
|
|
2
2
|
import { promises as fs } from "node:fs";
|
|
3
3
|
import { Type } from "typebox";
|
|
4
|
-
import { configFile } from "../../agent-paths.js";
|
|
4
|
+
import { configFile, managedMemoryStateFile } from "../../agent-paths.js";
|
|
5
5
|
import { hasInvisibleUnicode, scanContextFileThreats, stripInvisibleUnicode, } from "../../security/context-threat-scanner.js";
|
|
6
6
|
import { jaccard, tokenize } from "../../tools/skill-audit.js";
|
|
7
7
|
import { withFileLock, writeFileAtomic } from "../../util/atomic-file.js";
|
|
@@ -49,9 +49,6 @@ const memorySchema = Type.Object({
|
|
|
49
49
|
oldContent: Type.Optional(Type.String({ description: "Exact substring to replace or remove (required for 'replace' or 'remove')" })),
|
|
50
50
|
});
|
|
51
51
|
export const FILE_STORE_MEMORY_SYSTEM_NOTE = "[System Note: Below is a snapshot of persistent memory. Proactively record verified reusable project facts and user preferences with the 'memory' tool; never store transient noise.]";
|
|
52
|
-
function managedMemoryStatePath(filePath) {
|
|
53
|
-
return `${filePath}.pi-managed.json`;
|
|
54
|
-
}
|
|
55
52
|
function contentDigest(content) {
|
|
56
53
|
return createHash("sha256").update(content, "utf8").digest("hex");
|
|
57
54
|
}
|
|
@@ -79,9 +76,9 @@ function parseManagedMemoryState(raw) {
|
|
|
79
76
|
...(typeof record.pendingDigest === "string" ? { pendingDigest: record.pendingDigest } : {}),
|
|
80
77
|
};
|
|
81
78
|
}
|
|
82
|
-
async function readManagedMemoryState(
|
|
79
|
+
async function readManagedMemoryState(statePath) {
|
|
83
80
|
try {
|
|
84
|
-
const raw = await fs.readFile(
|
|
81
|
+
const raw = await fs.readFile(statePath, "utf8");
|
|
85
82
|
const state = parseManagedMemoryState(raw);
|
|
86
83
|
return state ? { status: "valid", state } : { status: "invalid", raw };
|
|
87
84
|
}
|
|
@@ -94,8 +91,8 @@ async function readManagedMemoryState(filePath) {
|
|
|
94
91
|
function serializeManagedMemoryState(state) {
|
|
95
92
|
return `${JSON.stringify(state)}\n`;
|
|
96
93
|
}
|
|
97
|
-
async function writeManagedMemoryState(
|
|
98
|
-
await writeFileAtomic(
|
|
94
|
+
async function writeManagedMemoryState(statePath, state) {
|
|
95
|
+
await writeFileAtomic(statePath, serializeManagedMemoryState(state), { mode: 0o600 });
|
|
99
96
|
}
|
|
100
97
|
function reconcileManagedMemoryState(currentDigest, state) {
|
|
101
98
|
if (currentDigest === state.committedDigest) {
|
|
@@ -160,6 +157,8 @@ export class FileStoreProvider {
|
|
|
160
157
|
this.egress = "local";
|
|
161
158
|
this.memoryFilePath = "";
|
|
162
159
|
this.userFilePath = "";
|
|
160
|
+
this.memoryStatePath = "";
|
|
161
|
+
this.userStatePath = "";
|
|
163
162
|
this.lastWrittenMemory = "";
|
|
164
163
|
this.lastWrittenUser = "";
|
|
165
164
|
this.options = options;
|
|
@@ -174,14 +173,16 @@ export class FileStoreProvider {
|
|
|
174
173
|
this.ctx = ctx;
|
|
175
174
|
this.memoryFilePath = configFile(ctx.agentDir, "MEMORY.md");
|
|
176
175
|
this.userFilePath = configFile(ctx.agentDir, "USER.md");
|
|
176
|
+
this.memoryStatePath = managedMemoryStateFile(ctx.agentDir, "MEMORY.md");
|
|
177
|
+
this.userStatePath = managedMemoryStateFile(ctx.agentDir, "USER.md");
|
|
177
178
|
this.userArchive = new UserMemoryArchive(ctx.agentDir);
|
|
178
179
|
await fs.mkdir(ctx.agentDir, { recursive: true });
|
|
179
180
|
[this.lastWrittenMemory, this.lastWrittenUser] = await Promise.all([
|
|
180
|
-
this.initializeManagedFile(this.memoryFilePath),
|
|
181
|
-
this.initializeManagedFile(this.userFilePath),
|
|
181
|
+
this.initializeManagedFile(this.memoryFilePath, this.memoryStatePath),
|
|
182
|
+
this.initializeManagedFile(this.userFilePath, this.userStatePath),
|
|
182
183
|
]);
|
|
183
184
|
}
|
|
184
|
-
async initializeManagedFile(filePath) {
|
|
185
|
+
async initializeManagedFile(filePath, statePath) {
|
|
185
186
|
return withFileLock(filePath, async () => {
|
|
186
187
|
let current = "";
|
|
187
188
|
try {
|
|
@@ -193,19 +194,19 @@ export class FileStoreProvider {
|
|
|
193
194
|
await writeFileAtomic(filePath, "", { mode: 0o600 });
|
|
194
195
|
}
|
|
195
196
|
const currentDigest = contentDigest(current);
|
|
196
|
-
const stateRead = await readManagedMemoryState(
|
|
197
|
+
const stateRead = await readManagedMemoryState(statePath);
|
|
197
198
|
if (stateRead.status === "missing") {
|
|
198
|
-
await writeManagedMemoryState(
|
|
199
|
+
await writeManagedMemoryState(statePath, { version: 1, committedDigest: currentDigest });
|
|
199
200
|
return current;
|
|
200
201
|
}
|
|
201
202
|
if (stateRead.status === "invalid") {
|
|
202
|
-
await writeFileAtomic(`${
|
|
203
|
-
await writeManagedMemoryState(
|
|
203
|
+
await writeFileAtomic(`${statePath}.bak.${Date.now()}.${randomUUID()}`, stateRead.raw, { mode: 0o600 });
|
|
204
|
+
await writeManagedMemoryState(statePath, { version: 1, committedDigest: currentDigest });
|
|
204
205
|
return current;
|
|
205
206
|
}
|
|
206
207
|
const reconciled = reconcileManagedMemoryState(currentDigest, stateRead.state);
|
|
207
208
|
if (reconciled.recognized && reconciled.changed) {
|
|
208
|
-
await writeManagedMemoryState(
|
|
209
|
+
await writeManagedMemoryState(statePath, reconciled.state);
|
|
209
210
|
}
|
|
210
211
|
return current;
|
|
211
212
|
});
|
|
@@ -308,19 +309,20 @@ export class FileStoreProvider {
|
|
|
308
309
|
}
|
|
309
310
|
}
|
|
310
311
|
const filePath = target === "memory" ? this.memoryFilePath : this.userFilePath;
|
|
312
|
+
const statePath = target === "memory" ? this.memoryStatePath : this.userStatePath;
|
|
311
313
|
const budget = target === "memory" ? FileStoreProvider.BUDGET_MEMORY : FileStoreProvider.BUDGET_USER;
|
|
312
314
|
try {
|
|
313
315
|
return await withFileLock(filePath, async () => {
|
|
314
316
|
const currentOnDisk = await fs.readFile(filePath, "utf8");
|
|
315
317
|
const currentDigest = contentDigest(currentOnDisk);
|
|
316
|
-
const stateRead = await readManagedMemoryState(
|
|
318
|
+
const stateRead = await readManagedMemoryState(statePath);
|
|
317
319
|
let managedState;
|
|
318
320
|
if (stateRead.status === "valid") {
|
|
319
321
|
const reconciled = reconcileManagedMemoryState(currentDigest, stateRead.state);
|
|
320
322
|
if (reconciled.recognized) {
|
|
321
323
|
managedState = reconciled.state;
|
|
322
324
|
if (reconciled.changed)
|
|
323
|
-
await writeManagedMemoryState(
|
|
325
|
+
await writeManagedMemoryState(statePath, reconciled.state);
|
|
324
326
|
}
|
|
325
327
|
}
|
|
326
328
|
if (!managedState) {
|
|
@@ -416,13 +418,13 @@ export class FileStoreProvider {
|
|
|
416
418
|
}
|
|
417
419
|
if (newContent !== currentOnDisk) {
|
|
418
420
|
const newDigest = contentDigest(newContent);
|
|
419
|
-
await writeManagedMemoryState(
|
|
421
|
+
await writeManagedMemoryState(statePath, {
|
|
420
422
|
version: 1,
|
|
421
423
|
committedDigest: managedState.committedDigest,
|
|
422
424
|
pendingDigest: newDigest,
|
|
423
425
|
});
|
|
424
426
|
await writeFileAtomic(filePath, newContent, { mode: 0o600 });
|
|
425
|
-
await writeManagedMemoryState(
|
|
427
|
+
await writeManagedMemoryState(statePath, { version: 1, committedDigest: newDigest });
|
|
426
428
|
}
|
|
427
429
|
if (target === "memory")
|
|
428
430
|
this.lastWrittenMemory = newContent;
|