@caupulican/pi-adaptative 0.81.41 → 0.81.42
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 +16 -0
- package/dist/bundled-resources/runtimes/pi-shell-engine/commands/text.py +5 -1
- package/dist/bundled-resources/runtimes/pi-shell-engine/context.py +3 -3
- package/dist/bundled-resources/runtimes/pi-shell-engine/errors.py +8 -0
- package/dist/bundled-resources/runtimes/pi-shell-engine/exec.py +26 -3
- package/dist/bundled-resources/runtimes/pi-shell-engine/expand.py +3 -0
- package/dist/bundled-resources/runtimes/pi-shell-engine/main.py +4 -1
- package/dist/bundled-resources/runtimes/pi-shell-engine/state.py +2 -1
- package/dist/bundled-resources/runtimes/pi-shell-engine/tokens.py +2 -0
- package/dist/core/agent-paths.d.ts +32 -0
- package/dist/core/agent-paths.d.ts.map +1 -1
- package/dist/core/agent-paths.js +65 -0
- package/dist/core/agent-paths.js.map +1 -1
- package/dist/core/agent-session-contracts.d.ts +19 -1
- package/dist/core/agent-session-contracts.d.ts.map +1 -1
- package/dist/core/agent-session-contracts.js.map +1 -1
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +4 -9
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/autonomy/contracts.d.ts +2 -0
- package/dist/core/autonomy/contracts.d.ts.map +1 -1
- package/dist/core/autonomy/contracts.js.map +1 -1
- package/dist/core/autonomy/envelope-enforcement.d.ts.map +1 -1
- package/dist/core/autonomy/envelope-enforcement.js +4 -9
- package/dist/core/autonomy/envelope-enforcement.js.map +1 -1
- package/dist/core/autonomy/lane-tool-surface.d.ts +3 -1
- package/dist/core/autonomy/lane-tool-surface.d.ts.map +1 -1
- package/dist/core/autonomy/lane-tool-surface.js +17 -4
- package/dist/core/autonomy/lane-tool-surface.js.map +1 -1
- package/dist/core/autonomy/path-scope.d.ts +14 -0
- package/dist/core/autonomy/path-scope.d.ts.map +1 -1
- package/dist/core/autonomy/path-scope.js +37 -6
- package/dist/core/autonomy/path-scope.js.map +1 -1
- package/dist/core/background-lane-controller.d.ts +27 -1
- package/dist/core/background-lane-controller.d.ts.map +1 -1
- package/dist/core/background-lane-controller.js +32 -1
- package/dist/core/background-lane-controller.js.map +1 -1
- package/dist/core/delegation/managed-lane-controller.d.ts +11 -1
- package/dist/core/delegation/managed-lane-controller.d.ts.map +1 -1
- package/dist/core/delegation/managed-lane-controller.js +84 -41
- package/dist/core/delegation/managed-lane-controller.js.map +1 -1
- package/dist/core/delegation/session-worker-claim.d.ts.map +1 -1
- package/dist/core/delegation/session-worker-claim.js +4 -3
- package/dist/core/delegation/session-worker-claim.js.map +1 -1
- package/dist/core/delegation/worker-action-journal.d.ts +73 -0
- package/dist/core/delegation/worker-action-journal.d.ts.map +1 -0
- package/dist/core/delegation/worker-action-journal.js +297 -0
- package/dist/core/delegation/worker-action-journal.js.map +1 -0
- package/dist/core/delegation/worker-actions.d.ts +36 -1
- package/dist/core/delegation/worker-actions.d.ts.map +1 -1
- package/dist/core/delegation/worker-actions.js +171 -46
- package/dist/core/delegation/worker-actions.js.map +1 -1
- package/dist/core/delegation/worker-agent-control-coordinator.d.ts +75 -0
- package/dist/core/delegation/worker-agent-control-coordinator.d.ts.map +1 -0
- package/dist/core/delegation/worker-agent-control-coordinator.js +218 -0
- package/dist/core/delegation/worker-agent-control-coordinator.js.map +1 -0
- package/dist/core/delegation/worker-agent-control.d.ts +66 -0
- package/dist/core/delegation/worker-agent-control.d.ts.map +1 -0
- package/dist/core/delegation/worker-agent-control.js +163 -0
- package/dist/core/delegation/worker-agent-control.js.map +1 -0
- package/dist/core/delegation/worker-attempt-executor.d.ts +80 -0
- package/dist/core/delegation/worker-attempt-executor.d.ts.map +1 -0
- package/dist/core/delegation/worker-attempt-executor.js +343 -0
- package/dist/core/delegation/worker-attempt-executor.js.map +1 -0
- package/dist/core/delegation/worker-claim.d.ts +30 -0
- package/dist/core/delegation/worker-claim.d.ts.map +1 -1
- package/dist/core/delegation/worker-claim.js +205 -53
- package/dist/core/delegation/worker-claim.js.map +1 -1
- package/dist/core/delegation/worker-conversation-store.d.ts +116 -0
- package/dist/core/delegation/worker-conversation-store.d.ts.map +1 -0
- package/dist/core/delegation/worker-conversation-store.js +442 -0
- package/dist/core/delegation/worker-conversation-store.js.map +1 -0
- package/dist/core/delegation/worker-delegation-controller.d.ts +21 -5
- package/dist/core/delegation/worker-delegation-controller.d.ts.map +1 -1
- package/dist/core/delegation/worker-delegation-controller.js +386 -251
- package/dist/core/delegation/worker-delegation-controller.js.map +1 -1
- package/dist/core/delegation/worker-delegation-request.d.ts +14 -0
- package/dist/core/delegation/worker-delegation-request.d.ts.map +1 -1
- package/dist/core/delegation/worker-delegation-request.js.map +1 -1
- package/dist/core/delegation/worker-dispatch-scheduler.d.ts +4 -2
- package/dist/core/delegation/worker-dispatch-scheduler.d.ts.map +1 -1
- package/dist/core/delegation/worker-dispatch-scheduler.js +16 -6
- package/dist/core/delegation/worker-dispatch-scheduler.js.map +1 -1
- package/dist/core/delegation/worker-execution-policy.d.ts +2 -1
- package/dist/core/delegation/worker-execution-policy.d.ts.map +1 -1
- package/dist/core/delegation/worker-execution-policy.js +5 -7
- package/dist/core/delegation/worker-execution-policy.js.map +1 -1
- package/dist/core/delegation/worker-lifecycle.d.ts +44 -1
- package/dist/core/delegation/worker-lifecycle.d.ts.map +1 -1
- package/dist/core/delegation/worker-lifecycle.js +120 -0
- package/dist/core/delegation/worker-lifecycle.js.map +1 -1
- package/dist/core/delegation/worker-process-owner.d.ts +18 -0
- package/dist/core/delegation/worker-process-owner.d.ts.map +1 -0
- package/dist/core/delegation/worker-process-owner.js +54 -0
- package/dist/core/delegation/worker-process-owner.js.map +1 -0
- package/dist/core/delegation/worker-profile-resolver.d.ts +5 -1
- package/dist/core/delegation/worker-profile-resolver.d.ts.map +1 -1
- package/dist/core/delegation/worker-profile-resolver.js +8 -0
- package/dist/core/delegation/worker-profile-resolver.js.map +1 -1
- package/dist/core/delegation/worker-recovery-coordinator.d.ts +54 -0
- package/dist/core/delegation/worker-recovery-coordinator.d.ts.map +1 -0
- package/dist/core/delegation/worker-recovery-coordinator.js +181 -0
- package/dist/core/delegation/worker-recovery-coordinator.js.map +1 -0
- package/dist/core/delegation/worker-resource-catalog.d.ts +32 -0
- package/dist/core/delegation/worker-resource-catalog.d.ts.map +1 -0
- package/dist/core/delegation/worker-resource-catalog.js +116 -0
- package/dist/core/delegation/worker-resource-catalog.js.map +1 -0
- package/dist/core/delegation/worker-resource-materializer.d.ts +47 -0
- package/dist/core/delegation/worker-resource-materializer.d.ts.map +1 -0
- package/dist/core/delegation/worker-resource-materializer.js +137 -0
- package/dist/core/delegation/worker-resource-materializer.js.map +1 -0
- package/dist/core/delegation/worker-runner.d.ts +3 -1
- package/dist/core/delegation/worker-runner.d.ts.map +1 -1
- package/dist/core/delegation/worker-runner.js +189 -54
- package/dist/core/delegation/worker-runner.js.map +1 -1
- package/dist/core/delegation/worker-terminal-finalizer.d.ts +23 -0
- package/dist/core/delegation/worker-terminal-finalizer.d.ts.map +1 -0
- package/dist/core/delegation/worker-terminal-finalizer.js +12 -0
- package/dist/core/delegation/worker-terminal-finalizer.js.map +1 -0
- package/dist/core/delegation/worker-write-reservation-coordinator.d.ts +38 -0
- package/dist/core/delegation/worker-write-reservation-coordinator.d.ts.map +1 -0
- package/dist/core/delegation/worker-write-reservation-coordinator.js +107 -0
- package/dist/core/delegation/worker-write-reservation-coordinator.js.map +1 -0
- package/dist/core/delegation/worker-write-reservation.d.ts +90 -0
- package/dist/core/delegation/worker-write-reservation.d.ts.map +1 -0
- package/dist/core/delegation/worker-write-reservation.js +348 -0
- package/dist/core/delegation/worker-write-reservation.js.map +1 -0
- package/dist/core/models/model-endpoint.d.ts +3 -0
- package/dist/core/models/model-endpoint.d.ts.map +1 -0
- package/dist/core/models/model-endpoint.js +11 -0
- package/dist/core/models/model-endpoint.js.map +1 -0
- package/dist/core/orchestration/agent-resume.d.ts +2 -0
- package/dist/core/orchestration/agent-resume.d.ts.map +1 -1
- package/dist/core/orchestration/agent-resume.js +7 -0
- package/dist/core/orchestration/agent-resume.js.map +1 -1
- package/dist/core/orchestration/attempt-usage.d.ts +28 -0
- package/dist/core/orchestration/attempt-usage.d.ts.map +1 -0
- package/dist/core/orchestration/attempt-usage.js +168 -0
- package/dist/core/orchestration/attempt-usage.js.map +1 -0
- package/dist/core/orchestration/capability-gateway.d.ts +19 -1
- package/dist/core/orchestration/capability-gateway.d.ts.map +1 -1
- package/dist/core/orchestration/capability-gateway.js +128 -28
- package/dist/core/orchestration/capability-gateway.js.map +1 -1
- package/dist/core/orchestration/contracts.d.ts +35 -0
- package/dist/core/orchestration/contracts.d.ts.map +1 -1
- package/dist/core/orchestration/contracts.js +17 -0
- package/dist/core/orchestration/contracts.js.map +1 -1
- package/dist/core/orchestration/delegation-ledger.d.ts +17 -2
- package/dist/core/orchestration/delegation-ledger.d.ts.map +1 -1
- package/dist/core/orchestration/delegation-ledger.js +78 -3
- package/dist/core/orchestration/delegation-ledger.js.map +1 -1
- package/dist/core/orchestration/event-store.d.ts +1 -0
- package/dist/core/orchestration/event-store.d.ts.map +1 -1
- package/dist/core/orchestration/event-store.js +78 -38
- package/dist/core/orchestration/event-store.js.map +1 -1
- package/dist/core/orchestration/profile-registry.d.ts.map +1 -1
- package/dist/core/orchestration/profile-registry.js +81 -41
- package/dist/core/orchestration/profile-registry.js.map +1 -1
- package/dist/core/orchestration/profile-store.d.ts.map +1 -1
- package/dist/core/orchestration/profile-store.js +18 -4
- package/dist/core/orchestration/profile-store.js.map +1 -1
- package/dist/core/orchestration/risk-budget.d.ts +2 -0
- package/dist/core/orchestration/risk-budget.d.ts.map +1 -1
- package/dist/core/orchestration/risk-budget.js +26 -0
- package/dist/core/orchestration/risk-budget.js.map +1 -1
- package/dist/core/orchestration/task-runtime.d.ts +13 -1
- package/dist/core/orchestration/task-runtime.d.ts.map +1 -1
- package/dist/core/orchestration/task-runtime.js +127 -16
- package/dist/core/orchestration/task-runtime.js.map +1 -1
- package/dist/core/orchestration/worker-execution-contract.d.ts +3 -1
- package/dist/core/orchestration/worker-execution-contract.d.ts.map +1 -1
- package/dist/core/orchestration/worker-execution-contract.js +75 -23
- package/dist/core/orchestration/worker-execution-contract.js.map +1 -1
- package/dist/core/orchestration/worker-result-adapter.d.ts +9 -3
- package/dist/core/orchestration/worker-result-adapter.d.ts.map +1 -1
- package/dist/core/orchestration/worker-result-adapter.js +167 -14
- package/dist/core/orchestration/worker-result-adapter.js.map +1 -1
- package/dist/core/reflection-controller.d.ts +1 -1
- package/dist/core/reflection-controller.d.ts.map +1 -1
- package/dist/core/reflection-controller.js +90 -54
- package/dist/core/reflection-controller.js.map +1 -1
- package/dist/core/research/evidence-bundle.d.ts +20 -0
- package/dist/core/research/evidence-bundle.d.ts.map +1 -1
- package/dist/core/research/evidence-bundle.js +173 -69
- package/dist/core/research/evidence-bundle.js.map +1 -1
- package/dist/core/runtime-builder.d.ts +7 -0
- package/dist/core/runtime-builder.d.ts.map +1 -1
- package/dist/core/runtime-builder.js +15 -1
- package/dist/core/runtime-builder.js.map +1 -1
- package/dist/core/session-artifact-bundle.d.ts +35 -0
- package/dist/core/session-artifact-bundle.d.ts.map +1 -0
- package/dist/core/session-artifact-bundle.js +61 -0
- package/dist/core/session-artifact-bundle.js.map +1 -0
- package/dist/core/tools/delegate-status.d.ts +6 -1
- package/dist/core/tools/delegate-status.d.ts.map +1 -1
- package/dist/core/tools/delegate-status.js +100 -18
- package/dist/core/tools/delegate-status.js.map +1 -1
- package/dist/core/tools/delegate.d.ts +9 -1
- package/dist/core/tools/delegate.d.ts.map +1 -1
- package/dist/core/tools/delegate.js +323 -61
- package/dist/core/tools/delegate.js.map +1 -1
- package/dist/core/tools/run-process.d.ts +1 -1
- package/dist/core/tools/run-process.d.ts.map +1 -1
- package/dist/core/tools/run-process.js +69 -9
- package/dist/core/tools/run-process.js.map +1 -1
- package/dist/core/tools/shell-contract-router.d.ts.map +1 -1
- package/dist/core/tools/shell-contract-router.js +12 -5
- package/dist/core/tools/shell-contract-router.js.map +1 -1
- package/dist/core/util/bounded-file.d.ts +15 -0
- package/dist/core/util/bounded-file.d.ts.map +1 -0
- package/dist/core/util/bounded-file.js +120 -0
- package/dist/core/util/bounded-file.js.map +1 -0
- package/dist/core/util/bounded-jsonl.d.ts.map +1 -1
- package/dist/core/util/bounded-jsonl.js +119 -9
- package/dist/core/util/bounded-jsonl.js.map +1 -1
- package/dist/core/util/bounded-value.d.ts +3 -0
- package/dist/core/util/bounded-value.d.ts.map +1 -0
- package/dist/core/util/bounded-value.js +12 -0
- package/dist/core/util/bounded-value.js.map +1 -0
- package/dist/core/util/value-guards.d.ts +2 -0
- package/dist/core/util/value-guards.d.ts.map +1 -1
- package/dist/core/util/value-guards.js +5 -0
- package/dist/core/util/value-guards.js.map +1 -1
- package/dist/modes/interactive/components/session-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/session-selector.js +27 -44
- package/dist/modes/interactive/components/session-selector.js.map +1 -1
- package/docs/tool-repair.md +3 -0
- package/docs/windows.md +4 -2
- 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
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"worker-action-journal.js","sourceRoot":"","sources":["../../../src/core/delegation/worker-action-journal.ts"],"names":[],"mappings":"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","sourcesContent":["import { createHash } from \"node:crypto\";\nimport { existsSync } from \"node:fs\";\nimport path from \"node:path\";\nimport { workerActionJournalFile } from \"../agent-paths.ts\";\nimport { withFileLockSync, writeFileAtomicSync } from \"../util/atomic-file.ts\";\nimport { readBoundedTextFileSync } from \"../util/bounded-file.ts\";\nimport { requireBoundedTrimmedText } from \"../util/bounded-value.ts\";\n\nconst JOURNAL_SCHEMA_VERSION = 1;\nconst MAX_IDENTIFIER_CHARS = 256;\nconst MAX_TARGET_CHARS = 2048;\nconst MAX_REASON_CHARS = 512;\nconst MAX_EVIDENCE_POINTER_CHARS = 512;\nconst MAX_ENTRIES = 64;\nconst MAX_JOURNAL_BYTES = 256 * 1024;\n\nexport type WorkerActionJournalState = \"not_started\" | \"unknown\" | \"succeeded\" | \"failed\";\n\nexport interface WorkerActionJournalScope {\n\tagentDir: string;\n\tparentSessionId: string;\n\ttaskId: string;\n\tattemptId: string;\n\tfencingToken: number;\n}\n\nexport interface WorkerActionJournalAction {\n\top: \"write\" | \"edit\";\n\tpath: string;\n\tcontent?: string;\n\told?: string;\n\tnew?: string;\n}\n\nexport interface BeginWorkerActionInput {\n\tindex: number;\n\taction: WorkerActionJournalAction;\n\t/** Realpath-resolved target used by the executor, never model-provided text alone. */\n\ttargetPath: string;\n}\n\nexport interface WorkerActionExecutionPermit {\n\tkind: \"execute\";\n\tstate: \"not_started\";\n\tactionId: string;\n\tactionDigest: string;\n\tnormalizedTarget: string;\n}\n\nexport interface WorkerActionInspectionRequired {\n\tkind: \"inspection_required\";\n\tstate: Exclude<WorkerActionJournalState, \"not_started\">;\n\tactionId: string;\n\tactionDigest: string;\n\tnormalizedTarget: string;\n\treasonCode: string;\n\tevidencePointer?: string;\n}\n\nexport type BeginWorkerActionResult = WorkerActionExecutionPermit | WorkerActionInspectionRequired;\n\nexport interface WorkerActionJournalInspection {\n\tstate: WorkerActionJournalState;\n\tactionId: string;\n\tactionDigest?: string;\n\tnormalizedTarget?: string;\n\treasonCode?: string;\n\tevidencePointer?: string;\n}\n\ninterface PersistedJournalEntry {\n\tactionId: string;\n\tactionDigest: string;\n\tindex: number;\n\tattemptId: string;\n\tfencingToken: number;\n\toperation: \"write\" | \"edit\";\n\tnormalizedTarget: string;\n\tstatus: \"intent\" | \"succeeded\" | \"failed\";\n\tcreatedAt: string;\n\tupdatedAt: string;\n\treasonCode?: string;\n\tevidencePointer?: string;\n}\n\ninterface PersistedJournal {\n\tschemaVersion: number;\n\tscope: WorkerActionJournalIdentity;\n\tentries: PersistedJournalEntry[];\n}\n\ninterface WorkerActionJournalIdentity {\n\tparentSessionId: string;\n\ttaskId: string;\n}\n\nfunction safeFencingToken(value: unknown): number {\n\tif (typeof value !== \"number\" || !Number.isSafeInteger(value) || value < 1)\n\t\tthrow new TypeError(\"Worker action journal fencing token must be a positive safe integer.\");\n\treturn value;\n}\n\nfunction validateScope(scope: WorkerActionJournalScope): Omit<WorkerActionJournalScope, \"agentDir\"> {\n\treturn {\n\t\tparentSessionId: requireBoundedTrimmedText(scope.parentSessionId, MAX_IDENTIFIER_CHARS, \"Parent session id\"),\n\t\ttaskId: requireBoundedTrimmedText(scope.taskId, MAX_IDENTIFIER_CHARS, \"Task id\"),\n\t\tattemptId: requireBoundedTrimmedText(scope.attemptId, MAX_IDENTIFIER_CHARS, \"Attempt id\"),\n\t\tfencingToken: safeFencingToken(scope.fencingToken),\n\t};\n}\n\nfunction journalIdentity(scope: Omit<WorkerActionJournalScope, \"agentDir\">): WorkerActionJournalIdentity {\n\treturn { parentSessionId: scope.parentSessionId, taskId: scope.taskId };\n}\n\nfunction scopeDigest(scope: WorkerActionJournalIdentity): string {\n\treturn createHash(\"sha256\")\n\t\t.update(\"pi-worker-action-journal-scope-v1\")\n\t\t.update(\"\\0\")\n\t\t.update(scope.parentSessionId)\n\t\t.update(\"\\0\")\n\t\t.update(scope.taskId)\n\t\t.update(\"\\0\")\n\t\t.digest(\"hex\");\n}\n\nfunction usesWindowsPath(value: string): boolean {\n\treturn /^[a-zA-Z]:([\\\\/]|$)/.test(value) || value.startsWith(\"\\\\\\\\\") || value.startsWith(\"//\");\n}\n\n/** Canonical lexical identity for an already-authorized real target, including native Windows paths. */\nexport function normalizeWorkerActionTarget(cwd: string, targetPath: string): string {\n\tconst pathApi = usesWindowsPath(cwd) || usesWindowsPath(targetPath) ? path.win32 : path.posix;\n\tconst normalized = pathApi.resolve(cwd, targetPath);\n\treturn pathApi === path.win32 ? normalized.toLowerCase() : normalized;\n}\n\nfunction actionDigest(input: BeginWorkerActionInput, normalizedTarget: string): string {\n\tconst hash = createHash(\"sha256\");\n\thash.update(\"pi-worker-action-v1\");\n\thash.update(\"\\0\");\n\thash.update(input.action.op);\n\thash.update(\"\\0\");\n\thash.update(normalizedTarget);\n\thash.update(\"\\0\");\n\tif (input.action.op === \"write\") {\n\t\thash.update(input.action.content ?? \"\");\n\t} else {\n\t\thash.update(input.action.old ?? \"\");\n\t\thash.update(\"\\0\");\n\t\thash.update(input.action.new ?? \"\");\n\t}\n\treturn hash.digest(\"hex\");\n}\n\nfunction actionId(scope: Omit<WorkerActionJournalScope, \"agentDir\">, index: number, digest: string): string {\n\treturn createHash(\"sha256\")\n\t\t.update(\"pi-worker-action-id-v1\")\n\t\t.update(\"\\0\")\n\t\t.update(scope.attemptId)\n\t\t.update(\"\\0\")\n\t\t.update(String(scope.fencingToken))\n\t\t.update(\"\\0\")\n\t\t.update(String(index))\n\t\t.update(\"\\0\")\n\t\t.update(digest)\n\t\t.digest(\"hex\")\n\t\t.slice(0, 40);\n}\n\nfunction stringValue(value: unknown, label: string, maximum: number): string {\n\tif (typeof value !== \"string\" || value.length === 0 || value.length > maximum) {\n\t\tthrow new Error(`Worker action journal ${label} is invalid.`);\n\t}\n\treturn value;\n}\n\nfunction objectValue(value: unknown, label: string): Record<string, unknown> {\n\tif (!value || typeof value !== \"object\" || Array.isArray(value))\n\t\tthrow new Error(`Worker action journal ${label} is invalid.`);\n\treturn value as Record<string, unknown>;\n}\n\nfunction parseEntry(value: unknown): PersistedJournalEntry {\n\tconst entry = objectValue(value, \"entry\");\n\tconst index = entry.index;\n\tif (typeof index !== \"number\" || !Number.isSafeInteger(index) || index < 0)\n\t\tthrow new Error(\"Worker action journal entry index is invalid.\");\n\tconst parsedIndex = index;\n\tconst operation = entry.operation;\n\tconst status = entry.status;\n\tif (\n\t\t(operation !== \"write\" && operation !== \"edit\") ||\n\t\t(status !== \"intent\" && status !== \"succeeded\" && status !== \"failed\")\n\t) {\n\t\tthrow new Error(\"Worker action journal entry shape is invalid.\");\n\t}\n\tconst reasonCode = entry.reasonCode;\n\tconst evidencePointer = entry.evidencePointer;\n\tif (reasonCode !== undefined && (typeof reasonCode !== \"string\" || reasonCode.length > MAX_REASON_CHARS)) {\n\t\tthrow new Error(\"Worker action journal entry reason is invalid.\");\n\t}\n\tif (\n\t\tevidencePointer !== undefined &&\n\t\t(typeof evidencePointer !== \"string\" || evidencePointer.length > MAX_EVIDENCE_POINTER_CHARS)\n\t) {\n\t\tthrow new Error(\"Worker action journal entry evidence pointer is invalid.\");\n\t}\n\treturn {\n\t\tactionId: stringValue(entry.actionId, \"entry action id\", 128),\n\t\tactionDigest: stringValue(entry.actionDigest, \"entry action digest\", 128),\n\t\tindex: parsedIndex,\n\t\tattemptId: stringValue(entry.attemptId, \"entry attempt id\", MAX_IDENTIFIER_CHARS),\n\t\tfencingToken: safeFencingToken(entry.fencingToken),\n\t\toperation,\n\t\tnormalizedTarget: stringValue(entry.normalizedTarget, \"entry target\", MAX_TARGET_CHARS),\n\t\tstatus,\n\t\tcreatedAt: stringValue(entry.createdAt, \"entry created time\", 128),\n\t\tupdatedAt: stringValue(entry.updatedAt, \"entry updated time\", 128),\n\t\t...(reasonCode ? { reasonCode } : {}),\n\t\t...(evidencePointer ? { evidencePointer } : {}),\n\t};\n}\n\nfunction parseJournal(value: unknown, expectedScope: WorkerActionJournalIdentity): PersistedJournal {\n\tconst journal = objectValue(value, \"document\");\n\tif (journal.schemaVersion !== JOURNAL_SCHEMA_VERSION)\n\t\tthrow new Error(\"Worker action journal schema is unsupported.\");\n\tconst scope = objectValue(journal.scope, \"scope\");\n\tconst parsedScope = {\n\t\tparentSessionId: stringValue(scope.parentSessionId, \"scope parent session\", MAX_IDENTIFIER_CHARS),\n\t\ttaskId: stringValue(scope.taskId, \"scope task\", MAX_IDENTIFIER_CHARS),\n\t};\n\tif (parsedScope.parentSessionId !== expectedScope.parentSessionId || parsedScope.taskId !== expectedScope.taskId) {\n\t\tthrow new Error(\"Worker action journal scope conflicts with the current fenced attempt.\");\n\t}\n\tif (!Array.isArray(journal.entries) || journal.entries.length > MAX_ENTRIES) {\n\t\tthrow new Error(\"Worker action journal entries are invalid.\");\n\t}\n\tconst entries = journal.entries.map(parseEntry);\n\tif (new Set(entries.map((entry) => entry.actionId)).size !== entries.length) {\n\t\tthrow new Error(\"Worker action journal contains duplicate action identities.\");\n\t}\n\treturn { schemaVersion: JOURNAL_SCHEMA_VERSION, scope: parsedScope, entries };\n}\n\nfunction now(): string {\n\treturn new Date().toISOString();\n}\n\n/**\n * Durable intent/receipt journal for model-emitted structured mutations. It deliberately records\n * only action digests and normalized targets; operation payloads can contain source text or secrets\n * and must never leave the model result in persisted orchestration state.\n */\nexport class WorkerActionJournal {\n\treadonly agentDir: string;\n\treadonly filePath: string;\n\tprivate readonly scope: Omit<WorkerActionJournalScope, \"agentDir\">;\n\tprivate readonly identity: WorkerActionJournalIdentity;\n\n\tconstructor(scope: WorkerActionJournalScope) {\n\t\tthis.agentDir = requireBoundedTrimmedText(scope.agentDir, MAX_TARGET_CHARS, \"Agent directory\");\n\t\tthis.scope = validateScope(scope);\n\t\tthis.identity = journalIdentity(this.scope);\n\t\tthis.filePath = workerActionJournalFile(this.agentDir, this.scope.parentSessionId, scopeDigest(this.identity));\n\t}\n\n\tinspect(actionIdentity: string): WorkerActionJournalInspection {\n\t\tconst actionId = requireBoundedTrimmedText(actionIdentity, 128, \"Worker action id\");\n\t\treturn withFileLockSync(this.filePath, () => {\n\t\t\tconst entry = this.readLocked().entries.find((candidate) => candidate.actionId === actionId);\n\t\t\tif (!entry) return { state: \"not_started\", actionId };\n\t\t\treturn this.inspectionFor(entry);\n\t\t});\n\t}\n\n\tbegin(input: BeginWorkerActionInput): BeginWorkerActionResult {\n\t\tif (!Number.isSafeInteger(input.index) || input.index < 0 || input.index >= MAX_ENTRIES) {\n\t\t\tthrow new TypeError(`Worker action index must be a safe integer from 0 through ${MAX_ENTRIES - 1}.`);\n\t\t}\n\t\tconst normalizedTarget = normalizeWorkerActionTarget(this.agentDir, input.targetPath);\n\t\tif (normalizedTarget.length > MAX_TARGET_CHARS) throw new TypeError(\"Worker action target is too long.\");\n\t\tconst digest = actionDigest(input, normalizedTarget);\n\t\tconst id = actionId(this.scope, input.index, digest);\n\t\treturn withFileLockSync(this.filePath, () => {\n\t\t\tconst journal = this.readLocked();\n\t\t\tconst existing = journal.entries.find((entry) => entry.actionId === id);\n\t\t\tif (existing) {\n\t\t\t\tif (existing.actionDigest !== digest) throw new Error(\"Worker action journal action identity collision.\");\n\t\t\t\treturn this.inspectionFor(existing);\n\t\t\t}\n\t\t\tconst previousFence = journal.entries.find(\n\t\t\t\t(entry) =>\n\t\t\t\t\tentry.actionDigest === digest &&\n\t\t\t\t\tentry.operation === input.action.op &&\n\t\t\t\t\tentry.normalizedTarget === normalizedTarget,\n\t\t\t);\n\t\t\tif (previousFence) return this.inspectionFor(previousFence, true);\n\t\t\tconst timestamp = now();\n\t\t\tjournal.entries.push({\n\t\t\t\tactionId: id,\n\t\t\t\tactionDigest: digest,\n\t\t\t\tindex: input.index,\n\t\t\t\tattemptId: this.scope.attemptId,\n\t\t\t\tfencingToken: this.scope.fencingToken,\n\t\t\t\toperation: input.action.op,\n\t\t\t\tnormalizedTarget,\n\t\t\t\tstatus: \"intent\",\n\t\t\t\tcreatedAt: timestamp,\n\t\t\t\tupdatedAt: timestamp,\n\t\t\t});\n\t\t\tthis.writeLocked(journal);\n\t\t\treturn { kind: \"execute\", state: \"not_started\", actionId: id, actionDigest: digest, normalizedTarget };\n\t\t});\n\t}\n\n\trecordSucceeded(permit: WorkerActionExecutionPermit, options: { evidencePointer?: string } = {}): void {\n\t\tthis.recordTerminal(permit, \"succeeded\", \"worker_action_applied\", options.evidencePointer);\n\t}\n\n\trecordFailed(\n\t\tpermit: WorkerActionExecutionPermit,\n\t\treasonCode: string,\n\t\toptions: { evidencePointer?: string } = {},\n\t): void {\n\t\tthis.recordTerminal(\n\t\t\tpermit,\n\t\t\t\"failed\",\n\t\t\trequireBoundedTrimmedText(reasonCode, MAX_REASON_CHARS, \"Worker action failure reason\"),\n\t\t\toptions.evidencePointer,\n\t\t);\n\t}\n\n\tprivate recordTerminal(\n\t\tpermit: WorkerActionExecutionPermit,\n\t\tstatus: \"succeeded\" | \"failed\",\n\t\treasonCode: string,\n\t\tevidencePointer: string | undefined,\n\t): void {\n\t\tconst boundedEvidence = evidencePointer\n\t\t\t? requireBoundedTrimmedText(evidencePointer, MAX_EVIDENCE_POINTER_CHARS, \"Worker action evidence pointer\")\n\t\t\t: undefined;\n\t\twithFileLockSync(this.filePath, () => {\n\t\t\tconst journal = this.readLocked();\n\t\t\tconst entry = journal.entries.find((candidate) => candidate.actionId === permit.actionId);\n\t\t\tif (\n\t\t\t\t!entry ||\n\t\t\t\tentry.actionDigest !== permit.actionDigest ||\n\t\t\t\tentry.normalizedTarget !== permit.normalizedTarget ||\n\t\t\t\tentry.attemptId !== this.scope.attemptId ||\n\t\t\t\tentry.fencingToken !== this.scope.fencingToken\n\t\t\t) {\n\t\t\t\tthrow new Error(\"Worker action journal receipt does not match a persisted intent.\");\n\t\t\t}\n\t\t\tif (entry.status !== \"intent\") throw new Error(\"Worker action journal intent already has a terminal receipt.\");\n\t\t\tentry.status = status;\n\t\t\tentry.reasonCode = reasonCode;\n\t\t\tentry.updatedAt = now();\n\t\t\tif (boundedEvidence) entry.evidencePointer = boundedEvidence;\n\t\t\tthis.writeLocked(journal);\n\t\t});\n\t}\n\n\tprivate readLocked(): PersistedJournal {\n\t\tif (!existsSync(this.filePath)) {\n\t\t\treturn { schemaVersion: JOURNAL_SCHEMA_VERSION, scope: structuredClone(this.identity), entries: [] };\n\t\t}\n\t\tconst content = readBoundedTextFileSync(this.filePath, MAX_JOURNAL_BYTES, \"Worker action journal\");\n\t\tlet raw: unknown;\n\t\ttry {\n\t\t\traw = JSON.parse(content);\n\t\t} catch {\n\t\t\tthrow new Error(\"Worker action journal is unreadable; refusing mutation replay.\");\n\t\t}\n\t\treturn parseJournal(raw, this.identity);\n\t}\n\n\tprivate writeLocked(journal: PersistedJournal): void {\n\t\tconst serialized = `${JSON.stringify(journal)}\\n`;\n\t\tif (Buffer.byteLength(serialized, \"utf-8\") > MAX_JOURNAL_BYTES) {\n\t\t\tthrow new Error(\"Worker action journal would exceed its byte limit.\");\n\t\t}\n\t\twriteFileAtomicSync(this.filePath, serialized, { mode: 0o600 });\n\t}\n\n\tprivate inspectionFor(entry: PersistedJournalEntry, fromPreviousFence = false): WorkerActionInspectionRequired {\n\t\tif (entry.status === \"intent\") {\n\t\t\treturn {\n\t\t\t\tkind: \"inspection_required\",\n\t\t\t\tstate: \"unknown\",\n\t\t\t\tactionId: entry.actionId,\n\t\t\t\tactionDigest: entry.actionDigest,\n\t\t\t\tnormalizedTarget: entry.normalizedTarget,\n\t\t\t\treasonCode: fromPreviousFence\n\t\t\t\t\t? \"worker_action_prior_fence_requires_inspection\"\n\t\t\t\t\t: \"worker_action_outcome_unknown\",\n\t\t\t\t...(entry.evidencePointer ? { evidencePointer: entry.evidencePointer } : {}),\n\t\t\t};\n\t\t}\n\t\treturn {\n\t\t\tkind: \"inspection_required\",\n\t\t\tstate: entry.status,\n\t\t\tactionId: entry.actionId,\n\t\t\tactionDigest: entry.actionDigest,\n\t\t\tnormalizedTarget: entry.normalizedTarget,\n\t\t\treasonCode: fromPreviousFence\n\t\t\t\t? \"worker_action_prior_fence_requires_inspection\"\n\t\t\t\t: entry.status === \"succeeded\"\n\t\t\t\t\t? \"worker_action_already_succeeded\"\n\t\t\t\t\t: \"worker_action_previously_failed\",\n\t\t\t...(entry.evidencePointer ? { evidencePointer: entry.evidencePointer } : {}),\n\t\t};\n\t}\n}\n"]}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { ToolArgumentValidationOptions } from "@caupulican/pi-ai";
|
|
2
2
|
import { type CapabilityGateway } from "../orchestration/capability-gateway.ts";
|
|
3
3
|
import type { ToolCapabilityManifest } from "../orchestration/contracts.ts";
|
|
4
|
+
import type { WorkerActionInspectionRequired, WorkerActionJournal } from "./worker-action-journal.ts";
|
|
4
5
|
/**
|
|
5
6
|
* Code-writing workers (G2): the worker MODEL never touches the filesystem — it emits strict-JSON
|
|
6
7
|
* actions, and this RUNNER-side module applies them deterministically through the compiled
|
|
@@ -19,7 +20,31 @@ export interface WorkerAction {
|
|
|
19
20
|
/** edit: replacement text. */
|
|
20
21
|
new?: string;
|
|
21
22
|
}
|
|
22
|
-
export
|
|
23
|
+
export type WorkerActionRejectionCode = "worker_actions_invalid_shape" | "worker_actions_too_many" | "worker_actions_path_too_long" | "worker_actions_field_too_large" | "worker_actions_payload_too_large";
|
|
24
|
+
export interface AcceptedWorkerActions {
|
|
25
|
+
kind: "accepted";
|
|
26
|
+
actions: WorkerAction[];
|
|
27
|
+
}
|
|
28
|
+
export interface RejectedWorkerActions {
|
|
29
|
+
kind: "rejected";
|
|
30
|
+
reasonCode: WorkerActionRejectionCode;
|
|
31
|
+
message: string;
|
|
32
|
+
}
|
|
33
|
+
/** The sole structured-action admission result used before execution or worker-result projection. */
|
|
34
|
+
export type WorkerActionParseOutcome = AcceptedWorkerActions | RejectedWorkerActions;
|
|
35
|
+
/** Bounded model-to-filesystem mutation contract. All execution callers pass through this owner. */
|
|
36
|
+
export declare const MAX_WORKER_ACTIONS = 20;
|
|
37
|
+
export declare const MAX_WORKER_ACTION_PATH_CHARS = 2048;
|
|
38
|
+
export declare const MAX_WORKER_ACTION_TEXT_CHARS: number;
|
|
39
|
+
/** Limits all source/replacement payloads for one atomic worker action batch. */
|
|
40
|
+
export declare const MAX_WORKER_ACTION_PAYLOAD_CHARS: number;
|
|
41
|
+
/**
|
|
42
|
+
* A structured edit only needs bounded source/replacement text. Limit the target read to 2 MiB:
|
|
43
|
+
* this admits the largest UTF-8 text payload (512 Ki code units at four bytes each)
|
|
44
|
+
* without letting a small edit cause an unbounded repository-file allocation.
|
|
45
|
+
*/
|
|
46
|
+
export declare const MAX_WORKER_ACTION_EDIT_TARGET_BYTES: number;
|
|
47
|
+
export declare function parseWorkerActions(raw: unknown, validation?: ToolArgumentValidationOptions): WorkerActionParseOutcome;
|
|
23
48
|
export interface AppliedActionsReport {
|
|
24
49
|
/** Repo-relative paths actually changed. */
|
|
25
50
|
changedFiles: string[];
|
|
@@ -33,11 +58,21 @@ export interface AppliedActionsReport {
|
|
|
33
58
|
path: string;
|
|
34
59
|
reason: string;
|
|
35
60
|
}>;
|
|
61
|
+
/** Durable replay blocks. The parent must inspect workspace/evidence instead of re-executing. */
|
|
62
|
+
inspectionRequired: Array<{
|
|
63
|
+
path: string;
|
|
64
|
+
actionId: string;
|
|
65
|
+
state: WorkerActionInspectionRequired["state"];
|
|
66
|
+
reasonCode: string;
|
|
67
|
+
evidencePointer?: string;
|
|
68
|
+
}>;
|
|
36
69
|
}
|
|
37
70
|
export declare function applyWorkerActions(args: {
|
|
38
71
|
actions: readonly WorkerAction[];
|
|
39
72
|
gateway: CapabilityGateway;
|
|
40
73
|
toolManifests: readonly ToolCapabilityManifest[];
|
|
41
74
|
cwd: string;
|
|
75
|
+
/** Optional durable mutation journal for one fenced worker attempt. */
|
|
76
|
+
actionJournal?: WorkerActionJournal;
|
|
42
77
|
}): AppliedActionsReport;
|
|
43
78
|
//# sourceMappingURL=worker-actions.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"worker-actions.d.ts","sourceRoot":"","sources":["../../../src/core/delegation/worker-actions.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAQ,6BAA6B,EAAE,MAAM,mBAAmB,CAAC;AAI7E,OAAO,EAAE,KAAK,iBAAiB,EAAgC,MAAM,wCAAwC,CAAC;AAC9G,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAC;AAE5E;;;;;;;GAOG;AAEH,MAAM,WAAW,YAAY;IAC5B,EAAE,EAAE,OAAO,GAAG,MAAM,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,gCAAgC;IAChC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,8DAA8D;IAC9D,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,8BAA8B;IAC9B,GAAG,CAAC,EAAE,MAAM,CAAC;CACb;AAyDD,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,OAAO,EAAE,UAAU,CAAC,EAAE,6BAA6B,GAAG,YAAY,EAAE,CAG3G;AAED,MAAM,WAAW,oBAAoB;IACpC,4CAA4C;IAC5C,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,8EAA4E;IAC5E,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACjD,8FAA8F;IAC9F,MAAM,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAChD;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE;IACxC,OAAO,EAAE,SAAS,YAAY,EAAE,CAAC;IACjC,OAAO,EAAE,iBAAiB,CAAC;IAC3B,aAAa,EAAE,SAAS,sBAAsB,EAAE,CAAC;IACjD,GAAG,EAAE,MAAM,CAAC;CACZ,GAAG,oBAAoB,CAiDvB","sourcesContent":["import { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { dirname, relative, resolve } from \"node:path\";\nimport type { Tool, ToolArgumentValidationOptions } from \"@caupulican/pi-ai\";\nimport { validateToolArguments } from \"@caupulican/pi-ai\";\nimport { Type } from \"typebox\";\nimport { safeRealpathSync } from \"../autonomy/path-scope.ts\";\nimport { type CapabilityGateway, CapabilityGatewayDeniedError } from \"../orchestration/capability-gateway.ts\";\nimport type { ToolCapabilityManifest } from \"../orchestration/contracts.ts\";\n\n/**\n * Code-writing workers (G2): the worker MODEL never touches the filesystem — it emits strict-JSON\n * actions, and this RUNNER-side module applies them deterministically through the compiled\n * execution grant. That keeps the structural-contract philosophy (a local model without\n * tool-calling templates can still write code) and makes enforcement execution-time, not\n * validation-only: an out-of-scope action is REFUSED with a reason, never silently dropped, and\n * refusals surface as blockers on the result.\n */\n\nexport interface WorkerAction {\n\top: \"write\" | \"edit\";\n\tpath: string;\n\t/** write: full file content. */\n\tcontent?: string;\n\t/** edit: exact string to replace (must occur in the file). */\n\told?: string;\n\t/** edit: replacement text. */\n\tnew?: string;\n}\n\nconst MAX_ACTIONS = 20;\nconst MAX_CONTENT_CHARS = 512 * 1024;\n\nconst workerActionSchema = Type.Union([\n\tType.Object({\n\t\top: Type.Literal(\"write\"),\n\t\tpath: Type.String({ minLength: 1 }),\n\t\tcontent: Type.String({ maxLength: MAX_CONTENT_CHARS }),\n\t}),\n\tType.Object({\n\t\top: Type.Literal(\"edit\"),\n\t\tpath: Type.String({ minLength: 1 }),\n\t\told: Type.String({ minLength: 1 }),\n\t\tnew: Type.String({ maxLength: MAX_CONTENT_CHARS }),\n\t}),\n]);\n\nconst workerActionsTool: Tool = {\n\tname: \"worker_actions\",\n\tdescription: \"Worker filesystem action list\",\n\tparameters: Type.Object({ actions: Type.Array(workerActionSchema) }),\n};\n\nfunction validateWorkerActions(raw: unknown, validation?: ToolArgumentValidationOptions): unknown[] {\n\ttry {\n\t\tconst validated = validateToolArguments(\n\t\t\tworkerActionsTool,\n\t\t\t{ type: \"toolCall\", id: \"worker-actions\", name: \"worker_actions\", arguments: { actions: raw } },\n\t\t\tvalidation,\n\t\t).actions;\n\t\treturn Array.isArray(validated) ? validated : [];\n\t} catch {\n\t\treturn [];\n\t}\n}\n\nfunction sanitizeWorkerActions(raw: readonly unknown[]): WorkerAction[] {\n\tconst actions: WorkerAction[] = [];\n\tfor (const entry of raw.slice(0, MAX_ACTIONS)) {\n\t\tif (!entry || typeof entry !== \"object\") continue;\n\t\tconst record = entry as Record<string, unknown>;\n\t\tif (record.op !== \"write\" && record.op !== \"edit\") continue;\n\t\tif (typeof record.path !== \"string\" || record.path.length === 0) continue;\n\t\tif (record.op === \"write\") {\n\t\t\tif (typeof record.content !== \"string\" || record.content.length > MAX_CONTENT_CHARS) continue;\n\t\t\tactions.push({ op: \"write\", path: record.path, content: record.content });\n\t\t} else {\n\t\t\tif (typeof record.old !== \"string\" || record.old.length === 0) continue;\n\t\t\tif (typeof record.new !== \"string\" || record.new.length > MAX_CONTENT_CHARS) continue;\n\t\t\tactions.push({ op: \"edit\", path: record.path, old: record.old, new: record.new });\n\t\t}\n\t}\n\treturn actions;\n}\n\nexport function parseWorkerActions(raw: unknown, validation?: ToolArgumentValidationOptions): WorkerAction[] {\n\tif (Array.isArray(raw)) return sanitizeWorkerActions(validateWorkerActions(sanitizeWorkerActions(raw), validation));\n\treturn sanitizeWorkerActions(validateWorkerActions(raw, validation));\n}\n\nexport interface AppliedActionsReport {\n\t/** Repo-relative paths actually changed. */\n\tchangedFiles: string[];\n\t/** Grant refusals (execution-time enforcement) — surfaced, never silent. */\n\trefused: Array<{ path: string; reason: string }>;\n\t/** Actions that were in scope but could not be applied (missing file, old-text not found). */\n\tfailed: Array<{ path: string; reason: string }>;\n}\n\nexport function applyWorkerActions(args: {\n\tactions: readonly WorkerAction[];\n\tgateway: CapabilityGateway;\n\ttoolManifests: readonly ToolCapabilityManifest[];\n\tcwd: string;\n}): AppliedActionsReport {\n\tconst report: AppliedActionsReport = { changedFiles: [], refused: [], failed: [] };\n\tconst manifests = new Map(args.toolManifests.map((manifest) => [manifest.toolName, manifest]));\n\tfor (const action of args.actions) {\n\t\tconst manifest = manifests.get(action.op);\n\t\tif (!manifest) {\n\t\t\treport.refused.push({\n\t\t\t\tpath: action.path,\n\t\t\t\treason: `${action.op} is not present in the compiled tool manifest`,\n\t\t\t});\n\t\t\tcontinue;\n\t\t}\n\t\ttry {\n\t\t\targs.gateway.authorizeToolCall(manifest, action.op, { path: action.path });\n\t\t} catch (error) {\n\t\t\tif (error instanceof CapabilityGatewayDeniedError) {\n\t\t\t\treport.refused.push({ path: action.path, reason: `${error.reasonCode}: ${error.message}` });\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t\tconst target = safeRealpathSync(resolve(args.cwd, action.path));\n\t\tconst relativePath = relative(args.cwd, target).replaceAll(\"\\\\\", \"/\");\n\t\ttry {\n\t\t\tif (action.op === \"write\") {\n\t\t\t\tmkdirSync(dirname(target), { recursive: true });\n\t\t\t\twriteFileSync(target, action.content ?? \"\", \"utf-8\");\n\t\t\t} else {\n\t\t\t\tif (!existsSync(target)) {\n\t\t\t\t\treport.failed.push({ path: action.path, reason: \"file does not exist\" });\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tconst current = readFileSync(target, \"utf-8\");\n\t\t\t\tif (!action.old || !current.includes(action.old)) {\n\t\t\t\t\treport.failed.push({ path: action.path, reason: \"edit old-text not found in file\" });\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\twriteFileSync(\n\t\t\t\t\ttarget,\n\t\t\t\t\tcurrent.replace(action.old, () => action.new ?? \"\"),\n\t\t\t\t\t\"utf-8\",\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (!report.changedFiles.includes(relativePath)) report.changedFiles.push(relativePath);\n\t\t} catch (error) {\n\t\t\treport.failed.push({ path: action.path, reason: error instanceof Error ? error.message : String(error) });\n\t\t}\n\t}\n\treturn report;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"worker-actions.d.ts","sourceRoot":"","sources":["../../../src/core/delegation/worker-actions.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAQ,6BAA6B,EAAE,MAAM,mBAAmB,CAAC;AAI7E,OAAO,EAAE,KAAK,iBAAiB,EAAgC,MAAM,wCAAwC,CAAC;AAC9G,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAC;AAG5E,OAAO,KAAK,EAAE,8BAA8B,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAEtG;;;;;;;GAOG;AAEH,MAAM,WAAW,YAAY;IAC5B,EAAE,EAAE,OAAO,GAAG,MAAM,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,gCAAgC;IAChC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,8DAA8D;IAC9D,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,8BAA8B;IAC9B,GAAG,CAAC,EAAE,MAAM,CAAC;CACb;AAED,MAAM,MAAM,yBAAyB,GAClC,8BAA8B,GAC9B,yBAAyB,GACzB,8BAA8B,GAC9B,gCAAgC,GAChC,kCAAkC,CAAC;AAEtC,MAAM,WAAW,qBAAqB;IACrC,IAAI,EAAE,UAAU,CAAC;IACjB,OAAO,EAAE,YAAY,EAAE,CAAC;CACxB;AAED,MAAM,WAAW,qBAAqB;IACrC,IAAI,EAAE,UAAU,CAAC;IACjB,UAAU,EAAE,yBAAyB,CAAC;IACtC,OAAO,EAAE,MAAM,CAAC;CAChB;AAED,qGAAqG;AACrG,MAAM,MAAM,wBAAwB,GAAG,qBAAqB,GAAG,qBAAqB,CAAC;AAErF,oGAAoG;AACpG,eAAO,MAAM,kBAAkB,KAAK,CAAC;AACrC,eAAO,MAAM,4BAA4B,OAAQ,CAAC;AAClD,eAAO,MAAM,4BAA4B,QAAa,CAAC;AACvD,iFAAiF;AACjF,eAAO,MAAM,+BAA+B,QAAa,CAAC;AAC1D;;;;GAIG;AACH,eAAO,MAAM,mCAAmC,QAAkB,CAAC;AA8GnE,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,OAAO,EAAE,UAAU,CAAC,EAAE,6BAA6B,GAAG,wBAAwB,CAOrH;AAED,MAAM,WAAW,oBAAoB;IACpC,4CAA4C;IAC5C,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,8EAA4E;IAC5E,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACjD,8FAA8F;IAC9F,MAAM,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAChD,iGAAiG;IACjG,kBAAkB,EAAE,KAAK,CAAC;QACzB,IAAI,EAAE,MAAM,CAAC;QACb,QAAQ,EAAE,MAAM,CAAC;QACjB,KAAK,EAAE,8BAA8B,CAAC,OAAO,CAAC,CAAC;QAC/C,UAAU,EAAE,MAAM,CAAC;QACnB,eAAe,CAAC,EAAE,MAAM,CAAC;KACzB,CAAC,CAAC;CACH;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE;IACxC,OAAO,EAAE,SAAS,YAAY,EAAE,CAAC;IACjC,OAAO,EAAE,iBAAiB,CAAC;IAC3B,aAAa,EAAE,SAAS,sBAAsB,EAAE,CAAC;IACjD,GAAG,EAAE,MAAM,CAAC;IACZ,uEAAuE;IACvE,aAAa,CAAC,EAAE,mBAAmB,CAAC;CACpC,GAAG,oBAAoB,CAoHvB","sourcesContent":["import { existsSync, mkdirSync, writeFileSync } from \"node:fs\";\nimport { dirname, relative, resolve } from \"node:path\";\nimport type { Tool, ToolArgumentValidationOptions } from \"@caupulican/pi-ai\";\nimport { validateToolArguments } from \"@caupulican/pi-ai\";\nimport { Type } from \"typebox\";\nimport { safeRealpathSync } from \"../autonomy/path-scope.ts\";\nimport { type CapabilityGateway, CapabilityGatewayDeniedError } from \"../orchestration/capability-gateway.ts\";\nimport type { ToolCapabilityManifest } from \"../orchestration/contracts.ts\";\nimport { readBoundedTextFileSync } from \"../util/bounded-file.ts\";\nimport { isPlainRecord } from \"../util/value-guards.ts\";\nimport type { WorkerActionInspectionRequired, WorkerActionJournal } from \"./worker-action-journal.ts\";\n\n/**\n * Code-writing workers (G2): the worker MODEL never touches the filesystem — it emits strict-JSON\n * actions, and this RUNNER-side module applies them deterministically through the compiled\n * execution grant. That keeps the structural-contract philosophy (a local model without\n * tool-calling templates can still write code) and makes enforcement execution-time, not\n * validation-only: an out-of-scope action is REFUSED with a reason, never silently dropped, and\n * refusals surface as blockers on the result.\n */\n\nexport interface WorkerAction {\n\top: \"write\" | \"edit\";\n\tpath: string;\n\t/** write: full file content. */\n\tcontent?: string;\n\t/** edit: exact string to replace (must occur in the file). */\n\told?: string;\n\t/** edit: replacement text. */\n\tnew?: string;\n}\n\nexport type WorkerActionRejectionCode =\n\t| \"worker_actions_invalid_shape\"\n\t| \"worker_actions_too_many\"\n\t| \"worker_actions_path_too_long\"\n\t| \"worker_actions_field_too_large\"\n\t| \"worker_actions_payload_too_large\";\n\nexport interface AcceptedWorkerActions {\n\tkind: \"accepted\";\n\tactions: WorkerAction[];\n}\n\nexport interface RejectedWorkerActions {\n\tkind: \"rejected\";\n\treasonCode: WorkerActionRejectionCode;\n\tmessage: string;\n}\n\n/** The sole structured-action admission result used before execution or worker-result projection. */\nexport type WorkerActionParseOutcome = AcceptedWorkerActions | RejectedWorkerActions;\n\n/** Bounded model-to-filesystem mutation contract. All execution callers pass through this owner. */\nexport const MAX_WORKER_ACTIONS = 20;\nexport const MAX_WORKER_ACTION_PATH_CHARS = 2_048;\nexport const MAX_WORKER_ACTION_TEXT_CHARS = 512 * 1024;\n/** Limits all source/replacement payloads for one atomic worker action batch. */\nexport const MAX_WORKER_ACTION_PAYLOAD_CHARS = 512 * 1024;\n/**\n * A structured edit only needs bounded source/replacement text. Limit the target read to 2 MiB:\n * this admits the largest UTF-8 text payload (512 Ki code units at four bytes each)\n * without letting a small edit cause an unbounded repository-file allocation.\n */\nexport const MAX_WORKER_ACTION_EDIT_TARGET_BYTES = 2 * 1024 * 1024;\n\nconst workerActionSchema = Type.Union([\n\tType.Object(\n\t\t{\n\t\t\top: Type.Literal(\"write\"),\n\t\t\tpath: Type.String({ minLength: 1, maxLength: MAX_WORKER_ACTION_PATH_CHARS }),\n\t\t\tcontent: Type.String({ maxLength: MAX_WORKER_ACTION_TEXT_CHARS }),\n\t\t},\n\t\t{ additionalProperties: false },\n\t),\n\tType.Object(\n\t\t{\n\t\t\top: Type.Literal(\"edit\"),\n\t\t\tpath: Type.String({ minLength: 1, maxLength: MAX_WORKER_ACTION_PATH_CHARS }),\n\t\t\told: Type.String({ minLength: 1, maxLength: MAX_WORKER_ACTION_TEXT_CHARS }),\n\t\t\tnew: Type.String({ maxLength: MAX_WORKER_ACTION_TEXT_CHARS }),\n\t\t},\n\t\t{ additionalProperties: false },\n\t),\n]);\n\nconst workerActionsTool: Tool = {\n\tname: \"worker_actions\",\n\tdescription: \"Worker filesystem action list\",\n\tparameters: Type.Object(\n\t\t{ actions: Type.Array(workerActionSchema, { maxItems: MAX_WORKER_ACTIONS }) },\n\t\t{ additionalProperties: false },\n\t),\n};\n\nfunction rejectWorkerActions(reasonCode: WorkerActionRejectionCode): RejectedWorkerActions {\n\tconst messages: Record<WorkerActionRejectionCode, string> = {\n\t\tworker_actions_invalid_shape: \"worker actions must be a strict JSON write/edit action list\",\n\t\tworker_actions_too_many: `worker actions exceed the ${MAX_WORKER_ACTIONS}-action limit`,\n\t\tworker_actions_path_too_long: \"worker action path exceeds the allowed limit\",\n\t\tworker_actions_field_too_large: \"worker actions contain a field larger than the allowed limit\",\n\t\tworker_actions_payload_too_large: \"worker actions exceed the aggregate payload limit\",\n\t};\n\treturn { kind: \"rejected\", reasonCode, message: messages[reasonCode] };\n}\n\nfunction validateWorkerActions(\n\traw: unknown,\n\tvalidation?: ToolArgumentValidationOptions,\n): readonly unknown[] | undefined {\n\ttry {\n\t\tconst validated = validateToolArguments(\n\t\t\tworkerActionsTool,\n\t\t\t{ type: \"toolCall\", id: \"worker-actions\", name: \"worker_actions\", arguments: { actions: raw } },\n\t\t\tvalidation,\n\t\t).actions;\n\t\treturn Array.isArray(validated) ? validated : undefined;\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\n/**\n * Normalizes every model or direct caller before it can reach the gateway, journal, or filesystem.\n * Any malformed entry rejects the entire batch so a partially malformed request cannot mutate a\n * surprising prefix.\n */\nfunction normalizeWorkerActions(raw: readonly unknown[]): WorkerActionParseOutcome {\n\tif (raw.length > MAX_WORKER_ACTIONS) return rejectWorkerActions(\"worker_actions_too_many\");\n\tconst actions: WorkerAction[] = [];\n\tlet payloadChars = 0;\n\tfor (const entry of raw) {\n\t\tif (!isPlainRecord(entry)) return rejectWorkerActions(\"worker_actions_invalid_shape\");\n\t\tconst descriptors = Object.getOwnPropertyDescriptors(entry);\n\t\tconst op = descriptors.op?.value;\n\t\tif (op !== \"write\" && op !== \"edit\") return rejectWorkerActions(\"worker_actions_invalid_shape\");\n\t\tconst expectedKeys = op === \"write\" ? [\"op\", \"path\", \"content\"] : [\"op\", \"path\", \"old\", \"new\"];\n\t\tif (\n\t\t\tReflect.ownKeys(entry).length !== expectedKeys.length ||\n\t\t\t!expectedKeys.every((key) => {\n\t\t\t\tconst descriptor = descriptors[key];\n\t\t\t\treturn descriptor?.enumerable === true && \"value\" in descriptor;\n\t\t\t})\n\t\t)\n\t\t\treturn rejectWorkerActions(\"worker_actions_invalid_shape\");\n\t\tconst actionPath = descriptors.path?.value;\n\t\tif (typeof actionPath !== \"string\" || actionPath.length === 0)\n\t\t\treturn rejectWorkerActions(\"worker_actions_invalid_shape\");\n\t\tif (actionPath.length > MAX_WORKER_ACTION_PATH_CHARS) return rejectWorkerActions(\"worker_actions_path_too_long\");\n\t\tif (op === \"write\") {\n\t\t\tconst content = descriptors.content?.value;\n\t\t\tif (typeof content !== \"string\") return rejectWorkerActions(\"worker_actions_invalid_shape\");\n\t\t\tif (content.length > MAX_WORKER_ACTION_TEXT_CHARS)\n\t\t\t\treturn rejectWorkerActions(\"worker_actions_field_too_large\");\n\t\t\tif (payloadChars + content.length > MAX_WORKER_ACTION_PAYLOAD_CHARS)\n\t\t\t\treturn rejectWorkerActions(\"worker_actions_payload_too_large\");\n\t\t\tpayloadChars += content.length;\n\t\t\tactions.push({ op: \"write\", path: actionPath, content });\n\t\t} else {\n\t\t\tconst old = descriptors.old?.value;\n\t\t\tconst replacement = descriptors.new?.value;\n\t\t\tif (typeof old !== \"string\" || old.length === 0 || typeof replacement !== \"string\")\n\t\t\t\treturn rejectWorkerActions(\"worker_actions_invalid_shape\");\n\t\t\tif (old.length > MAX_WORKER_ACTION_TEXT_CHARS || replacement.length > MAX_WORKER_ACTION_TEXT_CHARS)\n\t\t\t\treturn rejectWorkerActions(\"worker_actions_field_too_large\");\n\t\t\tif (payloadChars + old.length + replacement.length > MAX_WORKER_ACTION_PAYLOAD_CHARS)\n\t\t\t\treturn rejectWorkerActions(\"worker_actions_payload_too_large\");\n\t\t\tpayloadChars += old.length + replacement.length;\n\t\t\tactions.push({ op: \"edit\", path: actionPath, old, new: replacement });\n\t\t}\n\t}\n\treturn { kind: \"accepted\", actions };\n}\n\nexport function parseWorkerActions(raw: unknown, validation?: ToolArgumentValidationOptions): WorkerActionParseOutcome {\n\tif (raw === undefined) return { kind: \"accepted\", actions: [] };\n\tconst candidate = Array.isArray(raw) ? normalizeWorkerActions(raw) : undefined;\n\tif (candidate?.kind === \"rejected\") return candidate;\n\tconst validated = validateWorkerActions(candidate?.actions ?? raw, validation);\n\tif (!validated) return rejectWorkerActions(\"worker_actions_invalid_shape\");\n\treturn normalizeWorkerActions(validated);\n}\n\nexport interface AppliedActionsReport {\n\t/** Repo-relative paths actually changed. */\n\tchangedFiles: string[];\n\t/** Grant refusals (execution-time enforcement) — surfaced, never silent. */\n\trefused: Array<{ path: string; reason: string }>;\n\t/** Actions that were in scope but could not be applied (missing file, old-text not found). */\n\tfailed: Array<{ path: string; reason: string }>;\n\t/** Durable replay blocks. The parent must inspect workspace/evidence instead of re-executing. */\n\tinspectionRequired: Array<{\n\t\tpath: string;\n\t\tactionId: string;\n\t\tstate: WorkerActionInspectionRequired[\"state\"];\n\t\treasonCode: string;\n\t\tevidencePointer?: string;\n\t}>;\n}\n\nexport function applyWorkerActions(args: {\n\tactions: readonly WorkerAction[];\n\tgateway: CapabilityGateway;\n\ttoolManifests: readonly ToolCapabilityManifest[];\n\tcwd: string;\n\t/** Optional durable mutation journal for one fenced worker attempt. */\n\tactionJournal?: WorkerActionJournal;\n}): AppliedActionsReport {\n\tconst report: AppliedActionsReport = { changedFiles: [], refused: [], failed: [], inspectionRequired: [] };\n\tconst manifests = new Map(args.toolManifests.map((manifest) => [manifest.toolName, manifest]));\n\tconst parsedActions = parseWorkerActions(args.actions);\n\tif (parsedActions.kind === \"rejected\") {\n\t\treport.failed.push({ path: \"<worker_actions>\", reason: `${parsedActions.reasonCode}: ${parsedActions.message}` });\n\t\treturn report;\n\t}\n\tfor (const [index, action] of parsedActions.actions.entries()) {\n\t\tconst manifest = manifests.get(action.op);\n\t\tif (!manifest) {\n\t\t\treport.refused.push({\n\t\t\t\tpath: action.path,\n\t\t\t\treason: `${action.op} is not present in the compiled tool manifest`,\n\t\t\t});\n\t\t\tcontinue;\n\t\t}\n\t\ttry {\n\t\t\targs.gateway.authorizeToolCall(manifest, action.op, { path: action.path });\n\t\t} catch (error) {\n\t\t\tif (error instanceof CapabilityGatewayDeniedError) {\n\t\t\t\treport.refused.push({ path: action.path, reason: `${error.reasonCode}: ${error.message}` });\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t\tlet target: string;\n\t\tlet relativePath: string;\n\t\ttry {\n\t\t\ttarget = safeRealpathSync(resolve(args.cwd, action.path));\n\t\t\trelativePath = relative(args.cwd, target).replaceAll(\"\\\\\", \"/\");\n\t\t} catch {\n\t\t\treport.failed.push({ path: action.path, reason: \"target path could not be resolved\" });\n\t\t\tcontinue;\n\t\t}\n\t\tlet journalPermit: ReturnType<WorkerActionJournal[\"begin\"]> | undefined;\n\t\tif (args.actionJournal) {\n\t\t\ttry {\n\t\t\t\tjournalPermit = args.actionJournal.begin({ index, action, targetPath: target });\n\t\t\t} catch {\n\t\t\t\treport.failed.push({ path: action.path, reason: \"mutation journal intent could not be persisted\" });\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (journalPermit.kind === \"inspection_required\") {\n\t\t\t\treport.inspectionRequired.push({\n\t\t\t\t\tpath: action.path,\n\t\t\t\t\tactionId: journalPermit.actionId,\n\t\t\t\t\tstate: journalPermit.state,\n\t\t\t\t\treasonCode: journalPermit.reasonCode,\n\t\t\t\t\t...(journalPermit.evidencePointer ? { evidencePointer: journalPermit.evidencePointer } : {}),\n\t\t\t\t});\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\t\tlet mutationStarted = false;\n\t\ttry {\n\t\t\tif (action.op === \"write\") {\n\t\t\t\t// mkdir may create one or more parents before an error or process interruption. Once it\n\t\t\t\t// is invoked the durable intent is conservatively unknown, never replayed as a precondition failure.\n\t\t\t\tmutationStarted = true;\n\t\t\t\tmkdirSync(dirname(target), { recursive: true });\n\t\t\t\twriteFileSync(target, action.content ?? \"\", \"utf-8\");\n\t\t\t} else {\n\t\t\t\tif (!existsSync(target)) {\n\t\t\t\t\tthrow new Error(\"worker_action_file_missing\");\n\t\t\t\t}\n\t\t\t\tconst current = readBoundedTextFileSync(\n\t\t\t\t\ttarget,\n\t\t\t\t\tMAX_WORKER_ACTION_EDIT_TARGET_BYTES,\n\t\t\t\t\t\"Worker action edit target\",\n\t\t\t\t);\n\t\t\t\tif (!action.old || !current.includes(action.old)) {\n\t\t\t\t\tthrow new Error(\"worker_action_old_text_missing\");\n\t\t\t\t}\n\t\t\t\tmutationStarted = true;\n\t\t\t\twriteFileSync(\n\t\t\t\t\ttarget,\n\t\t\t\t\tcurrent.replace(action.old, () => action.new ?? \"\"),\n\t\t\t\t\t\"utf-8\",\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (!report.changedFiles.includes(relativePath)) report.changedFiles.push(relativePath);\n\t\t\tjournalPermit?.kind === \"execute\" &&\n\t\t\t\targs.actionJournal?.recordSucceeded(journalPermit, {\n\t\t\t\t\tevidencePointer: `workspace:file:${target}`,\n\t\t\t\t});\n\t\t} catch {\n\t\t\tif (mutationStarted && journalPermit?.kind === \"execute\") {\n\t\t\t\treport.inspectionRequired.push({\n\t\t\t\t\tpath: action.path,\n\t\t\t\t\tactionId: journalPermit.actionId,\n\t\t\t\t\tstate: \"unknown\",\n\t\t\t\t\treasonCode: \"worker_action_outcome_unknown\",\n\t\t\t\t\tevidencePointer: `workspace:file:${target}`,\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tif (journalPermit?.kind === \"execute\") {\n\t\t\t\t\ttry {\n\t\t\t\t\t\targs.actionJournal?.recordFailed(journalPermit, \"worker_action_precondition_failed\", {\n\t\t\t\t\t\t\tevidencePointer: `workspace:file:${target}`,\n\t\t\t\t\t\t});\n\t\t\t\t\t} catch {\n\t\t\t\t\t\treport.inspectionRequired.push({\n\t\t\t\t\t\t\tpath: action.path,\n\t\t\t\t\t\t\tactionId: journalPermit.actionId,\n\t\t\t\t\t\t\tstate: \"unknown\",\n\t\t\t\t\t\t\treasonCode: \"worker_action_outcome_unknown\",\n\t\t\t\t\t\t\tevidencePointer: `workspace:file:${target}`,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treport.failed.push({ path: action.path, reason: \"action precondition or filesystem operation failed\" });\n\t\t\t}\n\t\t}\n\t}\n\treturn report;\n}\n"]}
|
|
@@ -1,72 +1,135 @@
|
|
|
1
|
-
import { existsSync, mkdirSync,
|
|
1
|
+
import { existsSync, mkdirSync, writeFileSync } from "node:fs";
|
|
2
2
|
import { dirname, relative, resolve } from "node:path";
|
|
3
3
|
import { validateToolArguments } from "@caupulican/pi-ai";
|
|
4
4
|
import { Type } from "typebox";
|
|
5
5
|
import { safeRealpathSync } from "../autonomy/path-scope.js";
|
|
6
6
|
import { CapabilityGatewayDeniedError } from "../orchestration/capability-gateway.js";
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
import { readBoundedTextFileSync } from "../util/bounded-file.js";
|
|
8
|
+
import { isPlainRecord } from "../util/value-guards.js";
|
|
9
|
+
/** Bounded model-to-filesystem mutation contract. All execution callers pass through this owner. */
|
|
10
|
+
export const MAX_WORKER_ACTIONS = 20;
|
|
11
|
+
export const MAX_WORKER_ACTION_PATH_CHARS = 2_048;
|
|
12
|
+
export const MAX_WORKER_ACTION_TEXT_CHARS = 512 * 1024;
|
|
13
|
+
/** Limits all source/replacement payloads for one atomic worker action batch. */
|
|
14
|
+
export const MAX_WORKER_ACTION_PAYLOAD_CHARS = 512 * 1024;
|
|
15
|
+
/**
|
|
16
|
+
* A structured edit only needs bounded source/replacement text. Limit the target read to 2 MiB:
|
|
17
|
+
* this admits the largest UTF-8 text payload (512 Ki code units at four bytes each)
|
|
18
|
+
* without letting a small edit cause an unbounded repository-file allocation.
|
|
19
|
+
*/
|
|
20
|
+
export const MAX_WORKER_ACTION_EDIT_TARGET_BYTES = 2 * 1024 * 1024;
|
|
9
21
|
const workerActionSchema = Type.Union([
|
|
10
22
|
Type.Object({
|
|
11
23
|
op: Type.Literal("write"),
|
|
12
|
-
path: Type.String({ minLength: 1 }),
|
|
13
|
-
content: Type.String({ maxLength:
|
|
14
|
-
}),
|
|
24
|
+
path: Type.String({ minLength: 1, maxLength: MAX_WORKER_ACTION_PATH_CHARS }),
|
|
25
|
+
content: Type.String({ maxLength: MAX_WORKER_ACTION_TEXT_CHARS }),
|
|
26
|
+
}, { additionalProperties: false }),
|
|
15
27
|
Type.Object({
|
|
16
28
|
op: Type.Literal("edit"),
|
|
17
|
-
path: Type.String({ minLength: 1 }),
|
|
18
|
-
old: Type.String({ minLength: 1 }),
|
|
19
|
-
new: Type.String({ maxLength:
|
|
20
|
-
}),
|
|
29
|
+
path: Type.String({ minLength: 1, maxLength: MAX_WORKER_ACTION_PATH_CHARS }),
|
|
30
|
+
old: Type.String({ minLength: 1, maxLength: MAX_WORKER_ACTION_TEXT_CHARS }),
|
|
31
|
+
new: Type.String({ maxLength: MAX_WORKER_ACTION_TEXT_CHARS }),
|
|
32
|
+
}, { additionalProperties: false }),
|
|
21
33
|
]);
|
|
22
34
|
const workerActionsTool = {
|
|
23
35
|
name: "worker_actions",
|
|
24
36
|
description: "Worker filesystem action list",
|
|
25
|
-
parameters: Type.Object({ actions: Type.Array(workerActionSchema) }),
|
|
37
|
+
parameters: Type.Object({ actions: Type.Array(workerActionSchema, { maxItems: MAX_WORKER_ACTIONS }) }, { additionalProperties: false }),
|
|
26
38
|
};
|
|
39
|
+
function rejectWorkerActions(reasonCode) {
|
|
40
|
+
const messages = {
|
|
41
|
+
worker_actions_invalid_shape: "worker actions must be a strict JSON write/edit action list",
|
|
42
|
+
worker_actions_too_many: `worker actions exceed the ${MAX_WORKER_ACTIONS}-action limit`,
|
|
43
|
+
worker_actions_path_too_long: "worker action path exceeds the allowed limit",
|
|
44
|
+
worker_actions_field_too_large: "worker actions contain a field larger than the allowed limit",
|
|
45
|
+
worker_actions_payload_too_large: "worker actions exceed the aggregate payload limit",
|
|
46
|
+
};
|
|
47
|
+
return { kind: "rejected", reasonCode, message: messages[reasonCode] };
|
|
48
|
+
}
|
|
27
49
|
function validateWorkerActions(raw, validation) {
|
|
28
50
|
try {
|
|
29
51
|
const validated = validateToolArguments(workerActionsTool, { type: "toolCall", id: "worker-actions", name: "worker_actions", arguments: { actions: raw } }, validation).actions;
|
|
30
|
-
return Array.isArray(validated) ? validated :
|
|
52
|
+
return Array.isArray(validated) ? validated : undefined;
|
|
31
53
|
}
|
|
32
54
|
catch {
|
|
33
|
-
return
|
|
55
|
+
return undefined;
|
|
34
56
|
}
|
|
35
57
|
}
|
|
36
|
-
|
|
58
|
+
/**
|
|
59
|
+
* Normalizes every model or direct caller before it can reach the gateway, journal, or filesystem.
|
|
60
|
+
* Any malformed entry rejects the entire batch so a partially malformed request cannot mutate a
|
|
61
|
+
* surprising prefix.
|
|
62
|
+
*/
|
|
63
|
+
function normalizeWorkerActions(raw) {
|
|
64
|
+
if (raw.length > MAX_WORKER_ACTIONS)
|
|
65
|
+
return rejectWorkerActions("worker_actions_too_many");
|
|
37
66
|
const actions = [];
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
if (
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
67
|
+
let payloadChars = 0;
|
|
68
|
+
for (const entry of raw) {
|
|
69
|
+
if (!isPlainRecord(entry))
|
|
70
|
+
return rejectWorkerActions("worker_actions_invalid_shape");
|
|
71
|
+
const descriptors = Object.getOwnPropertyDescriptors(entry);
|
|
72
|
+
const op = descriptors.op?.value;
|
|
73
|
+
if (op !== "write" && op !== "edit")
|
|
74
|
+
return rejectWorkerActions("worker_actions_invalid_shape");
|
|
75
|
+
const expectedKeys = op === "write" ? ["op", "path", "content"] : ["op", "path", "old", "new"];
|
|
76
|
+
if (Reflect.ownKeys(entry).length !== expectedKeys.length ||
|
|
77
|
+
!expectedKeys.every((key) => {
|
|
78
|
+
const descriptor = descriptors[key];
|
|
79
|
+
return descriptor?.enumerable === true && "value" in descriptor;
|
|
80
|
+
}))
|
|
81
|
+
return rejectWorkerActions("worker_actions_invalid_shape");
|
|
82
|
+
const actionPath = descriptors.path?.value;
|
|
83
|
+
if (typeof actionPath !== "string" || actionPath.length === 0)
|
|
84
|
+
return rejectWorkerActions("worker_actions_invalid_shape");
|
|
85
|
+
if (actionPath.length > MAX_WORKER_ACTION_PATH_CHARS)
|
|
86
|
+
return rejectWorkerActions("worker_actions_path_too_long");
|
|
87
|
+
if (op === "write") {
|
|
88
|
+
const content = descriptors.content?.value;
|
|
89
|
+
if (typeof content !== "string")
|
|
90
|
+
return rejectWorkerActions("worker_actions_invalid_shape");
|
|
91
|
+
if (content.length > MAX_WORKER_ACTION_TEXT_CHARS)
|
|
92
|
+
return rejectWorkerActions("worker_actions_field_too_large");
|
|
93
|
+
if (payloadChars + content.length > MAX_WORKER_ACTION_PAYLOAD_CHARS)
|
|
94
|
+
return rejectWorkerActions("worker_actions_payload_too_large");
|
|
95
|
+
payloadChars += content.length;
|
|
96
|
+
actions.push({ op: "write", path: actionPath, content });
|
|
50
97
|
}
|
|
51
98
|
else {
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
if (typeof
|
|
55
|
-
|
|
56
|
-
|
|
99
|
+
const old = descriptors.old?.value;
|
|
100
|
+
const replacement = descriptors.new?.value;
|
|
101
|
+
if (typeof old !== "string" || old.length === 0 || typeof replacement !== "string")
|
|
102
|
+
return rejectWorkerActions("worker_actions_invalid_shape");
|
|
103
|
+
if (old.length > MAX_WORKER_ACTION_TEXT_CHARS || replacement.length > MAX_WORKER_ACTION_TEXT_CHARS)
|
|
104
|
+
return rejectWorkerActions("worker_actions_field_too_large");
|
|
105
|
+
if (payloadChars + old.length + replacement.length > MAX_WORKER_ACTION_PAYLOAD_CHARS)
|
|
106
|
+
return rejectWorkerActions("worker_actions_payload_too_large");
|
|
107
|
+
payloadChars += old.length + replacement.length;
|
|
108
|
+
actions.push({ op: "edit", path: actionPath, old, new: replacement });
|
|
57
109
|
}
|
|
58
110
|
}
|
|
59
|
-
return actions;
|
|
111
|
+
return { kind: "accepted", actions };
|
|
60
112
|
}
|
|
61
113
|
export function parseWorkerActions(raw, validation) {
|
|
62
|
-
if (
|
|
63
|
-
return
|
|
64
|
-
|
|
114
|
+
if (raw === undefined)
|
|
115
|
+
return { kind: "accepted", actions: [] };
|
|
116
|
+
const candidate = Array.isArray(raw) ? normalizeWorkerActions(raw) : undefined;
|
|
117
|
+
if (candidate?.kind === "rejected")
|
|
118
|
+
return candidate;
|
|
119
|
+
const validated = validateWorkerActions(candidate?.actions ?? raw, validation);
|
|
120
|
+
if (!validated)
|
|
121
|
+
return rejectWorkerActions("worker_actions_invalid_shape");
|
|
122
|
+
return normalizeWorkerActions(validated);
|
|
65
123
|
}
|
|
66
124
|
export function applyWorkerActions(args) {
|
|
67
|
-
const report = { changedFiles: [], refused: [], failed: [] };
|
|
125
|
+
const report = { changedFiles: [], refused: [], failed: [], inspectionRequired: [] };
|
|
68
126
|
const manifests = new Map(args.toolManifests.map((manifest) => [manifest.toolName, manifest]));
|
|
69
|
-
|
|
127
|
+
const parsedActions = parseWorkerActions(args.actions);
|
|
128
|
+
if (parsedActions.kind === "rejected") {
|
|
129
|
+
report.failed.push({ path: "<worker_actions>", reason: `${parsedActions.reasonCode}: ${parsedActions.message}` });
|
|
130
|
+
return report;
|
|
131
|
+
}
|
|
132
|
+
for (const [index, action] of parsedActions.actions.entries()) {
|
|
70
133
|
const manifest = manifests.get(action.op);
|
|
71
134
|
if (!manifest) {
|
|
72
135
|
report.refused.push({
|
|
@@ -85,30 +148,92 @@ export function applyWorkerActions(args) {
|
|
|
85
148
|
}
|
|
86
149
|
throw error;
|
|
87
150
|
}
|
|
88
|
-
|
|
89
|
-
|
|
151
|
+
let target;
|
|
152
|
+
let relativePath;
|
|
153
|
+
try {
|
|
154
|
+
target = safeRealpathSync(resolve(args.cwd, action.path));
|
|
155
|
+
relativePath = relative(args.cwd, target).replaceAll("\\", "/");
|
|
156
|
+
}
|
|
157
|
+
catch {
|
|
158
|
+
report.failed.push({ path: action.path, reason: "target path could not be resolved" });
|
|
159
|
+
continue;
|
|
160
|
+
}
|
|
161
|
+
let journalPermit;
|
|
162
|
+
if (args.actionJournal) {
|
|
163
|
+
try {
|
|
164
|
+
journalPermit = args.actionJournal.begin({ index, action, targetPath: target });
|
|
165
|
+
}
|
|
166
|
+
catch {
|
|
167
|
+
report.failed.push({ path: action.path, reason: "mutation journal intent could not be persisted" });
|
|
168
|
+
continue;
|
|
169
|
+
}
|
|
170
|
+
if (journalPermit.kind === "inspection_required") {
|
|
171
|
+
report.inspectionRequired.push({
|
|
172
|
+
path: action.path,
|
|
173
|
+
actionId: journalPermit.actionId,
|
|
174
|
+
state: journalPermit.state,
|
|
175
|
+
reasonCode: journalPermit.reasonCode,
|
|
176
|
+
...(journalPermit.evidencePointer ? { evidencePointer: journalPermit.evidencePointer } : {}),
|
|
177
|
+
});
|
|
178
|
+
continue;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
let mutationStarted = false;
|
|
90
182
|
try {
|
|
91
183
|
if (action.op === "write") {
|
|
184
|
+
// mkdir may create one or more parents before an error or process interruption. Once it
|
|
185
|
+
// is invoked the durable intent is conservatively unknown, never replayed as a precondition failure.
|
|
186
|
+
mutationStarted = true;
|
|
92
187
|
mkdirSync(dirname(target), { recursive: true });
|
|
93
188
|
writeFileSync(target, action.content ?? "", "utf-8");
|
|
94
189
|
}
|
|
95
190
|
else {
|
|
96
191
|
if (!existsSync(target)) {
|
|
97
|
-
|
|
98
|
-
continue;
|
|
192
|
+
throw new Error("worker_action_file_missing");
|
|
99
193
|
}
|
|
100
|
-
const current =
|
|
194
|
+
const current = readBoundedTextFileSync(target, MAX_WORKER_ACTION_EDIT_TARGET_BYTES, "Worker action edit target");
|
|
101
195
|
if (!action.old || !current.includes(action.old)) {
|
|
102
|
-
|
|
103
|
-
continue;
|
|
196
|
+
throw new Error("worker_action_old_text_missing");
|
|
104
197
|
}
|
|
198
|
+
mutationStarted = true;
|
|
105
199
|
writeFileSync(target, current.replace(action.old, () => action.new ?? ""), "utf-8");
|
|
106
200
|
}
|
|
107
201
|
if (!report.changedFiles.includes(relativePath))
|
|
108
202
|
report.changedFiles.push(relativePath);
|
|
203
|
+
journalPermit?.kind === "execute" &&
|
|
204
|
+
args.actionJournal?.recordSucceeded(journalPermit, {
|
|
205
|
+
evidencePointer: `workspace:file:${target}`,
|
|
206
|
+
});
|
|
109
207
|
}
|
|
110
|
-
catch
|
|
111
|
-
|
|
208
|
+
catch {
|
|
209
|
+
if (mutationStarted && journalPermit?.kind === "execute") {
|
|
210
|
+
report.inspectionRequired.push({
|
|
211
|
+
path: action.path,
|
|
212
|
+
actionId: journalPermit.actionId,
|
|
213
|
+
state: "unknown",
|
|
214
|
+
reasonCode: "worker_action_outcome_unknown",
|
|
215
|
+
evidencePointer: `workspace:file:${target}`,
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
else {
|
|
219
|
+
if (journalPermit?.kind === "execute") {
|
|
220
|
+
try {
|
|
221
|
+
args.actionJournal?.recordFailed(journalPermit, "worker_action_precondition_failed", {
|
|
222
|
+
evidencePointer: `workspace:file:${target}`,
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
catch {
|
|
226
|
+
report.inspectionRequired.push({
|
|
227
|
+
path: action.path,
|
|
228
|
+
actionId: journalPermit.actionId,
|
|
229
|
+
state: "unknown",
|
|
230
|
+
reasonCode: "worker_action_outcome_unknown",
|
|
231
|
+
evidencePointer: `workspace:file:${target}`,
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
report.failed.push({ path: action.path, reason: "action precondition or filesystem operation failed" });
|
|
236
|
+
}
|
|
112
237
|
}
|
|
113
238
|
}
|
|
114
239
|
return report;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"worker-actions.js","sourceRoot":"","sources":["../../../src/core/delegation/worker-actions.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { dirname, relative, resolve } from \"node:path\";\nimport type { Tool, ToolArgumentValidationOptions } from \"@caupulican/pi-ai\";\nimport { validateToolArguments } from \"@caupulican/pi-ai\";\nimport { Type } from \"typebox\";\nimport { safeRealpathSync } from \"../autonomy/path-scope.ts\";\nimport { type CapabilityGateway, CapabilityGatewayDeniedError } from \"../orchestration/capability-gateway.ts\";\nimport type { ToolCapabilityManifest } from \"../orchestration/contracts.ts\";\n\n/**\n * Code-writing workers (G2): the worker MODEL never touches the filesystem — it emits strict-JSON\n * actions, and this RUNNER-side module applies them deterministically through the compiled\n * execution grant. That keeps the structural-contract philosophy (a local model without\n * tool-calling templates can still write code) and makes enforcement execution-time, not\n * validation-only: an out-of-scope action is REFUSED with a reason, never silently dropped, and\n * refusals surface as blockers on the result.\n */\n\nexport interface WorkerAction {\n\top: \"write\" | \"edit\";\n\tpath: string;\n\t/** write: full file content. */\n\tcontent?: string;\n\t/** edit: exact string to replace (must occur in the file). */\n\told?: string;\n\t/** edit: replacement text. */\n\tnew?: string;\n}\n\nconst MAX_ACTIONS = 20;\nconst MAX_CONTENT_CHARS = 512 * 1024;\n\nconst workerActionSchema = Type.Union([\n\tType.Object({\n\t\top: Type.Literal(\"write\"),\n\t\tpath: Type.String({ minLength: 1 }),\n\t\tcontent: Type.String({ maxLength: MAX_CONTENT_CHARS }),\n\t}),\n\tType.Object({\n\t\top: Type.Literal(\"edit\"),\n\t\tpath: Type.String({ minLength: 1 }),\n\t\told: Type.String({ minLength: 1 }),\n\t\tnew: Type.String({ maxLength: MAX_CONTENT_CHARS }),\n\t}),\n]);\n\nconst workerActionsTool: Tool = {\n\tname: \"worker_actions\",\n\tdescription: \"Worker filesystem action list\",\n\tparameters: Type.Object({ actions: Type.Array(workerActionSchema) }),\n};\n\nfunction validateWorkerActions(raw: unknown, validation?: ToolArgumentValidationOptions): unknown[] {\n\ttry {\n\t\tconst validated = validateToolArguments(\n\t\t\tworkerActionsTool,\n\t\t\t{ type: \"toolCall\", id: \"worker-actions\", name: \"worker_actions\", arguments: { actions: raw } },\n\t\t\tvalidation,\n\t\t).actions;\n\t\treturn Array.isArray(validated) ? validated : [];\n\t} catch {\n\t\treturn [];\n\t}\n}\n\nfunction sanitizeWorkerActions(raw: readonly unknown[]): WorkerAction[] {\n\tconst actions: WorkerAction[] = [];\n\tfor (const entry of raw.slice(0, MAX_ACTIONS)) {\n\t\tif (!entry || typeof entry !== \"object\") continue;\n\t\tconst record = entry as Record<string, unknown>;\n\t\tif (record.op !== \"write\" && record.op !== \"edit\") continue;\n\t\tif (typeof record.path !== \"string\" || record.path.length === 0) continue;\n\t\tif (record.op === \"write\") {\n\t\t\tif (typeof record.content !== \"string\" || record.content.length > MAX_CONTENT_CHARS) continue;\n\t\t\tactions.push({ op: \"write\", path: record.path, content: record.content });\n\t\t} else {\n\t\t\tif (typeof record.old !== \"string\" || record.old.length === 0) continue;\n\t\t\tif (typeof record.new !== \"string\" || record.new.length > MAX_CONTENT_CHARS) continue;\n\t\t\tactions.push({ op: \"edit\", path: record.path, old: record.old, new: record.new });\n\t\t}\n\t}\n\treturn actions;\n}\n\nexport function parseWorkerActions(raw: unknown, validation?: ToolArgumentValidationOptions): WorkerAction[] {\n\tif (Array.isArray(raw)) return sanitizeWorkerActions(validateWorkerActions(sanitizeWorkerActions(raw), validation));\n\treturn sanitizeWorkerActions(validateWorkerActions(raw, validation));\n}\n\nexport interface AppliedActionsReport {\n\t/** Repo-relative paths actually changed. */\n\tchangedFiles: string[];\n\t/** Grant refusals (execution-time enforcement) — surfaced, never silent. */\n\trefused: Array<{ path: string; reason: string }>;\n\t/** Actions that were in scope but could not be applied (missing file, old-text not found). */\n\tfailed: Array<{ path: string; reason: string }>;\n}\n\nexport function applyWorkerActions(args: {\n\tactions: readonly WorkerAction[];\n\tgateway: CapabilityGateway;\n\ttoolManifests: readonly ToolCapabilityManifest[];\n\tcwd: string;\n}): AppliedActionsReport {\n\tconst report: AppliedActionsReport = { changedFiles: [], refused: [], failed: [] };\n\tconst manifests = new Map(args.toolManifests.map((manifest) => [manifest.toolName, manifest]));\n\tfor (const action of args.actions) {\n\t\tconst manifest = manifests.get(action.op);\n\t\tif (!manifest) {\n\t\t\treport.refused.push({\n\t\t\t\tpath: action.path,\n\t\t\t\treason: `${action.op} is not present in the compiled tool manifest`,\n\t\t\t});\n\t\t\tcontinue;\n\t\t}\n\t\ttry {\n\t\t\targs.gateway.authorizeToolCall(manifest, action.op, { path: action.path });\n\t\t} catch (error) {\n\t\t\tif (error instanceof CapabilityGatewayDeniedError) {\n\t\t\t\treport.refused.push({ path: action.path, reason: `${error.reasonCode}: ${error.message}` });\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t\tconst target = safeRealpathSync(resolve(args.cwd, action.path));\n\t\tconst relativePath = relative(args.cwd, target).replaceAll(\"\\\\\", \"/\");\n\t\ttry {\n\t\t\tif (action.op === \"write\") {\n\t\t\t\tmkdirSync(dirname(target), { recursive: true });\n\t\t\t\twriteFileSync(target, action.content ?? \"\", \"utf-8\");\n\t\t\t} else {\n\t\t\t\tif (!existsSync(target)) {\n\t\t\t\t\treport.failed.push({ path: action.path, reason: \"file does not exist\" });\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tconst current = readFileSync(target, \"utf-8\");\n\t\t\t\tif (!action.old || !current.includes(action.old)) {\n\t\t\t\t\treport.failed.push({ path: action.path, reason: \"edit old-text not found in file\" });\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\twriteFileSync(\n\t\t\t\t\ttarget,\n\t\t\t\t\tcurrent.replace(action.old, () => action.new ?? \"\"),\n\t\t\t\t\t\"utf-8\",\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (!report.changedFiles.includes(relativePath)) report.changedFiles.push(relativePath);\n\t\t} catch (error) {\n\t\t\treport.failed.push({ path: action.path, reason: error instanceof Error ? error.message : String(error) });\n\t\t}\n\t}\n\treturn report;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"worker-actions.js","sourceRoot":"","sources":["../../../src/core/delegation/worker-actions.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync, mkdirSync, writeFileSync } from \"node:fs\";\nimport { dirname, relative, resolve } from \"node:path\";\nimport type { Tool, ToolArgumentValidationOptions } from \"@caupulican/pi-ai\";\nimport { validateToolArguments } from \"@caupulican/pi-ai\";\nimport { Type } from \"typebox\";\nimport { safeRealpathSync } from \"../autonomy/path-scope.ts\";\nimport { type CapabilityGateway, CapabilityGatewayDeniedError } from \"../orchestration/capability-gateway.ts\";\nimport type { ToolCapabilityManifest } from \"../orchestration/contracts.ts\";\nimport { readBoundedTextFileSync } from \"../util/bounded-file.ts\";\nimport { isPlainRecord } from \"../util/value-guards.ts\";\nimport type { WorkerActionInspectionRequired, WorkerActionJournal } from \"./worker-action-journal.ts\";\n\n/**\n * Code-writing workers (G2): the worker MODEL never touches the filesystem — it emits strict-JSON\n * actions, and this RUNNER-side module applies them deterministically through the compiled\n * execution grant. That keeps the structural-contract philosophy (a local model without\n * tool-calling templates can still write code) and makes enforcement execution-time, not\n * validation-only: an out-of-scope action is REFUSED with a reason, never silently dropped, and\n * refusals surface as blockers on the result.\n */\n\nexport interface WorkerAction {\n\top: \"write\" | \"edit\";\n\tpath: string;\n\t/** write: full file content. */\n\tcontent?: string;\n\t/** edit: exact string to replace (must occur in the file). */\n\told?: string;\n\t/** edit: replacement text. */\n\tnew?: string;\n}\n\nexport type WorkerActionRejectionCode =\n\t| \"worker_actions_invalid_shape\"\n\t| \"worker_actions_too_many\"\n\t| \"worker_actions_path_too_long\"\n\t| \"worker_actions_field_too_large\"\n\t| \"worker_actions_payload_too_large\";\n\nexport interface AcceptedWorkerActions {\n\tkind: \"accepted\";\n\tactions: WorkerAction[];\n}\n\nexport interface RejectedWorkerActions {\n\tkind: \"rejected\";\n\treasonCode: WorkerActionRejectionCode;\n\tmessage: string;\n}\n\n/** The sole structured-action admission result used before execution or worker-result projection. */\nexport type WorkerActionParseOutcome = AcceptedWorkerActions | RejectedWorkerActions;\n\n/** Bounded model-to-filesystem mutation contract. All execution callers pass through this owner. */\nexport const MAX_WORKER_ACTIONS = 20;\nexport const MAX_WORKER_ACTION_PATH_CHARS = 2_048;\nexport const MAX_WORKER_ACTION_TEXT_CHARS = 512 * 1024;\n/** Limits all source/replacement payloads for one atomic worker action batch. */\nexport const MAX_WORKER_ACTION_PAYLOAD_CHARS = 512 * 1024;\n/**\n * A structured edit only needs bounded source/replacement text. Limit the target read to 2 MiB:\n * this admits the largest UTF-8 text payload (512 Ki code units at four bytes each)\n * without letting a small edit cause an unbounded repository-file allocation.\n */\nexport const MAX_WORKER_ACTION_EDIT_TARGET_BYTES = 2 * 1024 * 1024;\n\nconst workerActionSchema = Type.Union([\n\tType.Object(\n\t\t{\n\t\t\top: Type.Literal(\"write\"),\n\t\t\tpath: Type.String({ minLength: 1, maxLength: MAX_WORKER_ACTION_PATH_CHARS }),\n\t\t\tcontent: Type.String({ maxLength: MAX_WORKER_ACTION_TEXT_CHARS }),\n\t\t},\n\t\t{ additionalProperties: false },\n\t),\n\tType.Object(\n\t\t{\n\t\t\top: Type.Literal(\"edit\"),\n\t\t\tpath: Type.String({ minLength: 1, maxLength: MAX_WORKER_ACTION_PATH_CHARS }),\n\t\t\told: Type.String({ minLength: 1, maxLength: MAX_WORKER_ACTION_TEXT_CHARS }),\n\t\t\tnew: Type.String({ maxLength: MAX_WORKER_ACTION_TEXT_CHARS }),\n\t\t},\n\t\t{ additionalProperties: false },\n\t),\n]);\n\nconst workerActionsTool: Tool = {\n\tname: \"worker_actions\",\n\tdescription: \"Worker filesystem action list\",\n\tparameters: Type.Object(\n\t\t{ actions: Type.Array(workerActionSchema, { maxItems: MAX_WORKER_ACTIONS }) },\n\t\t{ additionalProperties: false },\n\t),\n};\n\nfunction rejectWorkerActions(reasonCode: WorkerActionRejectionCode): RejectedWorkerActions {\n\tconst messages: Record<WorkerActionRejectionCode, string> = {\n\t\tworker_actions_invalid_shape: \"worker actions must be a strict JSON write/edit action list\",\n\t\tworker_actions_too_many: `worker actions exceed the ${MAX_WORKER_ACTIONS}-action limit`,\n\t\tworker_actions_path_too_long: \"worker action path exceeds the allowed limit\",\n\t\tworker_actions_field_too_large: \"worker actions contain a field larger than the allowed limit\",\n\t\tworker_actions_payload_too_large: \"worker actions exceed the aggregate payload limit\",\n\t};\n\treturn { kind: \"rejected\", reasonCode, message: messages[reasonCode] };\n}\n\nfunction validateWorkerActions(\n\traw: unknown,\n\tvalidation?: ToolArgumentValidationOptions,\n): readonly unknown[] | undefined {\n\ttry {\n\t\tconst validated = validateToolArguments(\n\t\t\tworkerActionsTool,\n\t\t\t{ type: \"toolCall\", id: \"worker-actions\", name: \"worker_actions\", arguments: { actions: raw } },\n\t\t\tvalidation,\n\t\t).actions;\n\t\treturn Array.isArray(validated) ? validated : undefined;\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\n/**\n * Normalizes every model or direct caller before it can reach the gateway, journal, or filesystem.\n * Any malformed entry rejects the entire batch so a partially malformed request cannot mutate a\n * surprising prefix.\n */\nfunction normalizeWorkerActions(raw: readonly unknown[]): WorkerActionParseOutcome {\n\tif (raw.length > MAX_WORKER_ACTIONS) return rejectWorkerActions(\"worker_actions_too_many\");\n\tconst actions: WorkerAction[] = [];\n\tlet payloadChars = 0;\n\tfor (const entry of raw) {\n\t\tif (!isPlainRecord(entry)) return rejectWorkerActions(\"worker_actions_invalid_shape\");\n\t\tconst descriptors = Object.getOwnPropertyDescriptors(entry);\n\t\tconst op = descriptors.op?.value;\n\t\tif (op !== \"write\" && op !== \"edit\") return rejectWorkerActions(\"worker_actions_invalid_shape\");\n\t\tconst expectedKeys = op === \"write\" ? [\"op\", \"path\", \"content\"] : [\"op\", \"path\", \"old\", \"new\"];\n\t\tif (\n\t\t\tReflect.ownKeys(entry).length !== expectedKeys.length ||\n\t\t\t!expectedKeys.every((key) => {\n\t\t\t\tconst descriptor = descriptors[key];\n\t\t\t\treturn descriptor?.enumerable === true && \"value\" in descriptor;\n\t\t\t})\n\t\t)\n\t\t\treturn rejectWorkerActions(\"worker_actions_invalid_shape\");\n\t\tconst actionPath = descriptors.path?.value;\n\t\tif (typeof actionPath !== \"string\" || actionPath.length === 0)\n\t\t\treturn rejectWorkerActions(\"worker_actions_invalid_shape\");\n\t\tif (actionPath.length > MAX_WORKER_ACTION_PATH_CHARS) return rejectWorkerActions(\"worker_actions_path_too_long\");\n\t\tif (op === \"write\") {\n\t\t\tconst content = descriptors.content?.value;\n\t\t\tif (typeof content !== \"string\") return rejectWorkerActions(\"worker_actions_invalid_shape\");\n\t\t\tif (content.length > MAX_WORKER_ACTION_TEXT_CHARS)\n\t\t\t\treturn rejectWorkerActions(\"worker_actions_field_too_large\");\n\t\t\tif (payloadChars + content.length > MAX_WORKER_ACTION_PAYLOAD_CHARS)\n\t\t\t\treturn rejectWorkerActions(\"worker_actions_payload_too_large\");\n\t\t\tpayloadChars += content.length;\n\t\t\tactions.push({ op: \"write\", path: actionPath, content });\n\t\t} else {\n\t\t\tconst old = descriptors.old?.value;\n\t\t\tconst replacement = descriptors.new?.value;\n\t\t\tif (typeof old !== \"string\" || old.length === 0 || typeof replacement !== \"string\")\n\t\t\t\treturn rejectWorkerActions(\"worker_actions_invalid_shape\");\n\t\t\tif (old.length > MAX_WORKER_ACTION_TEXT_CHARS || replacement.length > MAX_WORKER_ACTION_TEXT_CHARS)\n\t\t\t\treturn rejectWorkerActions(\"worker_actions_field_too_large\");\n\t\t\tif (payloadChars + old.length + replacement.length > MAX_WORKER_ACTION_PAYLOAD_CHARS)\n\t\t\t\treturn rejectWorkerActions(\"worker_actions_payload_too_large\");\n\t\t\tpayloadChars += old.length + replacement.length;\n\t\t\tactions.push({ op: \"edit\", path: actionPath, old, new: replacement });\n\t\t}\n\t}\n\treturn { kind: \"accepted\", actions };\n}\n\nexport function parseWorkerActions(raw: unknown, validation?: ToolArgumentValidationOptions): WorkerActionParseOutcome {\n\tif (raw === undefined) return { kind: \"accepted\", actions: [] };\n\tconst candidate = Array.isArray(raw) ? normalizeWorkerActions(raw) : undefined;\n\tif (candidate?.kind === \"rejected\") return candidate;\n\tconst validated = validateWorkerActions(candidate?.actions ?? raw, validation);\n\tif (!validated) return rejectWorkerActions(\"worker_actions_invalid_shape\");\n\treturn normalizeWorkerActions(validated);\n}\n\nexport interface AppliedActionsReport {\n\t/** Repo-relative paths actually changed. */\n\tchangedFiles: string[];\n\t/** Grant refusals (execution-time enforcement) — surfaced, never silent. */\n\trefused: Array<{ path: string; reason: string }>;\n\t/** Actions that were in scope but could not be applied (missing file, old-text not found). */\n\tfailed: Array<{ path: string; reason: string }>;\n\t/** Durable replay blocks. The parent must inspect workspace/evidence instead of re-executing. */\n\tinspectionRequired: Array<{\n\t\tpath: string;\n\t\tactionId: string;\n\t\tstate: WorkerActionInspectionRequired[\"state\"];\n\t\treasonCode: string;\n\t\tevidencePointer?: string;\n\t}>;\n}\n\nexport function applyWorkerActions(args: {\n\tactions: readonly WorkerAction[];\n\tgateway: CapabilityGateway;\n\ttoolManifests: readonly ToolCapabilityManifest[];\n\tcwd: string;\n\t/** Optional durable mutation journal for one fenced worker attempt. */\n\tactionJournal?: WorkerActionJournal;\n}): AppliedActionsReport {\n\tconst report: AppliedActionsReport = { changedFiles: [], refused: [], failed: [], inspectionRequired: [] };\n\tconst manifests = new Map(args.toolManifests.map((manifest) => [manifest.toolName, manifest]));\n\tconst parsedActions = parseWorkerActions(args.actions);\n\tif (parsedActions.kind === \"rejected\") {\n\t\treport.failed.push({ path: \"<worker_actions>\", reason: `${parsedActions.reasonCode}: ${parsedActions.message}` });\n\t\treturn report;\n\t}\n\tfor (const [index, action] of parsedActions.actions.entries()) {\n\t\tconst manifest = manifests.get(action.op);\n\t\tif (!manifest) {\n\t\t\treport.refused.push({\n\t\t\t\tpath: action.path,\n\t\t\t\treason: `${action.op} is not present in the compiled tool manifest`,\n\t\t\t});\n\t\t\tcontinue;\n\t\t}\n\t\ttry {\n\t\t\targs.gateway.authorizeToolCall(manifest, action.op, { path: action.path });\n\t\t} catch (error) {\n\t\t\tif (error instanceof CapabilityGatewayDeniedError) {\n\t\t\t\treport.refused.push({ path: action.path, reason: `${error.reasonCode}: ${error.message}` });\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t\tlet target: string;\n\t\tlet relativePath: string;\n\t\ttry {\n\t\t\ttarget = safeRealpathSync(resolve(args.cwd, action.path));\n\t\t\trelativePath = relative(args.cwd, target).replaceAll(\"\\\\\", \"/\");\n\t\t} catch {\n\t\t\treport.failed.push({ path: action.path, reason: \"target path could not be resolved\" });\n\t\t\tcontinue;\n\t\t}\n\t\tlet journalPermit: ReturnType<WorkerActionJournal[\"begin\"]> | undefined;\n\t\tif (args.actionJournal) {\n\t\t\ttry {\n\t\t\t\tjournalPermit = args.actionJournal.begin({ index, action, targetPath: target });\n\t\t\t} catch {\n\t\t\t\treport.failed.push({ path: action.path, reason: \"mutation journal intent could not be persisted\" });\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (journalPermit.kind === \"inspection_required\") {\n\t\t\t\treport.inspectionRequired.push({\n\t\t\t\t\tpath: action.path,\n\t\t\t\t\tactionId: journalPermit.actionId,\n\t\t\t\t\tstate: journalPermit.state,\n\t\t\t\t\treasonCode: journalPermit.reasonCode,\n\t\t\t\t\t...(journalPermit.evidencePointer ? { evidencePointer: journalPermit.evidencePointer } : {}),\n\t\t\t\t});\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\t\tlet mutationStarted = false;\n\t\ttry {\n\t\t\tif (action.op === \"write\") {\n\t\t\t\t// mkdir may create one or more parents before an error or process interruption. Once it\n\t\t\t\t// is invoked the durable intent is conservatively unknown, never replayed as a precondition failure.\n\t\t\t\tmutationStarted = true;\n\t\t\t\tmkdirSync(dirname(target), { recursive: true });\n\t\t\t\twriteFileSync(target, action.content ?? \"\", \"utf-8\");\n\t\t\t} else {\n\t\t\t\tif (!existsSync(target)) {\n\t\t\t\t\tthrow new Error(\"worker_action_file_missing\");\n\t\t\t\t}\n\t\t\t\tconst current = readBoundedTextFileSync(\n\t\t\t\t\ttarget,\n\t\t\t\t\tMAX_WORKER_ACTION_EDIT_TARGET_BYTES,\n\t\t\t\t\t\"Worker action edit target\",\n\t\t\t\t);\n\t\t\t\tif (!action.old || !current.includes(action.old)) {\n\t\t\t\t\tthrow new Error(\"worker_action_old_text_missing\");\n\t\t\t\t}\n\t\t\t\tmutationStarted = true;\n\t\t\t\twriteFileSync(\n\t\t\t\t\ttarget,\n\t\t\t\t\tcurrent.replace(action.old, () => action.new ?? \"\"),\n\t\t\t\t\t\"utf-8\",\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (!report.changedFiles.includes(relativePath)) report.changedFiles.push(relativePath);\n\t\t\tjournalPermit?.kind === \"execute\" &&\n\t\t\t\targs.actionJournal?.recordSucceeded(journalPermit, {\n\t\t\t\t\tevidencePointer: `workspace:file:${target}`,\n\t\t\t\t});\n\t\t} catch {\n\t\t\tif (mutationStarted && journalPermit?.kind === \"execute\") {\n\t\t\t\treport.inspectionRequired.push({\n\t\t\t\t\tpath: action.path,\n\t\t\t\t\tactionId: journalPermit.actionId,\n\t\t\t\t\tstate: \"unknown\",\n\t\t\t\t\treasonCode: \"worker_action_outcome_unknown\",\n\t\t\t\t\tevidencePointer: `workspace:file:${target}`,\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tif (journalPermit?.kind === \"execute\") {\n\t\t\t\t\ttry {\n\t\t\t\t\t\targs.actionJournal?.recordFailed(journalPermit, \"worker_action_precondition_failed\", {\n\t\t\t\t\t\t\tevidencePointer: `workspace:file:${target}`,\n\t\t\t\t\t\t});\n\t\t\t\t\t} catch {\n\t\t\t\t\t\treport.inspectionRequired.push({\n\t\t\t\t\t\t\tpath: action.path,\n\t\t\t\t\t\t\tactionId: journalPermit.actionId,\n\t\t\t\t\t\t\tstate: \"unknown\",\n\t\t\t\t\t\t\treasonCode: \"worker_action_outcome_unknown\",\n\t\t\t\t\t\t\tevidencePointer: `workspace:file:${target}`,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treport.failed.push({ path: action.path, reason: \"action precondition or filesystem operation failed\" });\n\t\t\t}\n\t\t}\n\t}\n\treturn report;\n}\n"]}
|