@the-open-engine/zeroshot 6.38.1 → 6.39.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cli/event-copy.js +8 -7
- package/cli/event-copy.ts +12 -0
- package/cli/index.js +7 -31
- package/cli/json-export.js +61 -64
- package/cli/json-export.ts +112 -0
- package/cli/message-formatter-utils.js +68 -56
- package/cli/message-formatter-utils.ts +121 -0
- package/cli/message-formatters-normal.js +124 -259
- package/cli/message-formatters-normal.ts +250 -0
- package/cli/message-formatters-watch.js +81 -84
- package/cli/message-formatters-watch.ts +189 -0
- package/lib/cluster/generated/protocol-schema.cjs +1 -1
- package/lib/cluster/generated/protocol-schema.mjs +1 -1
- package/lib/cluster/generated/protocol.d.cts +8 -0
- package/lib/cluster/generated/protocol.d.mts +8 -0
- package/lib/cluster/generated/protocol.d.ts +8 -0
- package/lib/clusters-registry.d.ts +23 -0
- package/lib/clusters-registry.js +17 -29
- package/lib/completion.d.ts +12 -0
- package/lib/completion.js +84 -94
- package/lib/compose-utils.d.ts +32 -0
- package/lib/compose-utils.js +57 -72
- package/lib/detached-startup.d.ts +83 -0
- package/lib/detached-startup.js +231 -302
- package/lib/docker-config.d.ts +43 -0
- package/lib/docker-config.js +150 -325
- package/lib/docker-env-auth.d.ts +17 -0
- package/lib/docker-env-auth.js +75 -0
- package/lib/git-remote-utils.d.ts +48 -0
- package/lib/git-remote-utils.js +147 -213
- package/lib/id-detector.d.ts +15 -0
- package/lib/id-detector.js +37 -41
- package/lib/path-check.d.ts +30 -0
- package/lib/path-check.js +42 -45
- package/lib/process-liveness.d.ts +16 -0
- package/lib/process-liveness.js +19 -12
- package/lib/provider-credential-path.d.ts +16 -0
- package/lib/provider-credential-path.js +31 -29
- package/lib/provider-defaults.d.ts +30 -0
- package/lib/provider-defaults.js +47 -42
- package/lib/provider-detection.d.ts +11 -0
- package/lib/provider-detection.js +91 -54
- package/lib/provider-names.d.ts +38 -0
- package/lib/provider-names.js +56 -64
- package/lib/repo-settings.d.ts +28 -0
- package/lib/repo-settings.js +83 -59
- package/lib/run-mode.d.ts +21 -0
- package/lib/run-mode.js +21 -20
- package/lib/run-plan.d.ts +28 -0
- package/lib/run-plan.js +17 -16
- package/lib/settings/claude-auth.d.ts +35 -0
- package/lib/settings/claude-auth.js +30 -47
- package/lib/settings-defaults.d.ts +20 -0
- package/lib/settings-defaults.js +149 -0
- package/lib/settings-error.d.ts +7 -0
- package/lib/settings-error.js +8 -0
- package/lib/settings-issue-providers.d.ts +10 -0
- package/lib/settings-issue-providers.js +12 -0
- package/lib/settings-models.d.ts +22 -0
- package/lib/settings-models.js +93 -0
- package/lib/settings-storage.d.ts +23 -0
- package/lib/settings-storage.js +205 -0
- package/lib/settings-validation.d.ts +7 -0
- package/lib/settings-validation.js +182 -0
- package/lib/settings.d.ts +29 -0
- package/lib/settings.js +41 -736
- package/lib/setup-apply-types.d.ts +66 -0
- package/lib/setup-apply-types.js +2 -0
- package/lib/setup-apply.d.ts +39 -0
- package/lib/setup-apply.js +267 -264
- package/lib/setup-journal.d.ts +41 -0
- package/lib/setup-journal.js +119 -76
- package/lib/setup-plan-types.d.ts +102 -0
- package/lib/setup-plan-types.js +2 -0
- package/lib/setup-plan.d.ts +30 -0
- package/lib/setup-plan.js +300 -324
- package/lib/setup-undo.d.ts +44 -0
- package/lib/setup-undo.js +61 -74
- package/lib/start-cluster-config.d.ts +26 -0
- package/lib/start-cluster-config.js +56 -0
- package/lib/start-cluster-environment.d.ts +40 -0
- package/lib/start-cluster-environment.js +134 -0
- package/lib/start-cluster-run-options.d.ts +53 -0
- package/lib/start-cluster-run-options.js +147 -0
- package/lib/start-cluster.d.ts +64 -0
- package/lib/start-cluster.js +98 -454
- package/lib/stream-json-parser.d.ts +17 -0
- package/lib/stream-json-parser.js +51 -52
- package/npm-shrinkwrap.json +2 -2
- package/package.json +12 -6
- package/scripts/postinstall.js +27 -0
- package/scripts/rust-distribution.js +23 -14
- package/src/agent/agent-command-proofs-context.js +35 -45
- package/src/agent/agent-command-proofs-context.ts +87 -0
- package/src/agent/agent-config-settings.js +19 -0
- package/src/agent/agent-config-settings.ts +41 -0
- package/src/agent/agent-config.js +122 -231
- package/src/agent/agent-config.ts +285 -0
- package/src/agent/agent-context-builder.js +38 -273
- package/src/agent/agent-context-builder.ts +51 -0
- package/src/agent/agent-context-environment-sections.js +105 -0
- package/src/agent/agent-context-environment-sections.ts +134 -0
- package/src/agent/agent-context-packs.js +165 -0
- package/src/agent/agent-context-packs.ts +296 -0
- package/src/agent/agent-context-prompt-sections.js +100 -0
- package/src/agent/agent-context-prompt-sections.ts +148 -0
- package/src/agent/agent-context-sections.js +25 -334
- package/src/agent/agent-context-sections.ts +36 -0
- package/src/agent/agent-context-sources.js +96 -149
- package/src/agent/agent-context-sources.ts +253 -0
- package/src/agent/agent-context-types.js +2 -0
- package/src/agent/agent-context-types.ts +132 -0
- package/src/agent/agent-context-validation-sections.js +73 -0
- package/src/agent/agent-context-validation-sections.ts +129 -0
- package/src/agent/agent-input-injector.js +99 -118
- package/src/agent/agent-input-injector.ts +195 -0
- package/src/agent/agent-liveness-poll.js +74 -78
- package/src/agent/agent-liveness-poll.ts +163 -0
- package/src/agent/agent-quality-gate-schema.js +77 -86
- package/src/agent/agent-quality-gate-schema.ts +135 -0
- package/src/agent/agent-quality-gates-context.js +44 -50
- package/src/agent/agent-quality-gates-context.ts +91 -0
- package/src/agent/agent-stuck-detector.js +171 -239
- package/src/agent/agent-stuck-detector.ts +288 -0
- package/src/agent/agent-trigger-evaluator.js +29 -46
- package/src/agent/agent-trigger-evaluator.ts +98 -0
- package/src/agent/context-metrics.js +110 -141
- package/src/agent/context-metrics.ts +261 -0
- package/src/agent/context-pack-builder.js +72 -358
- package/src/agent/context-pack-builder.ts +105 -0
- package/src/agent/context-pack-core.js +70 -0
- package/src/agent/context-pack-core.ts +96 -0
- package/src/agent/context-pack-selection.js +119 -0
- package/src/agent/context-pack-selection.ts +187 -0
- package/src/agent/context-pack-truncation.js +139 -0
- package/src/agent/context-pack-truncation.ts +208 -0
- package/src/agent/context-pack-types.js +2 -0
- package/src/agent/context-pack-types.ts +98 -0
- package/src/agent/context-replay-policy.js +30 -39
- package/src/agent/context-replay-policy.ts +71 -0
- package/src/agent/critical-agent-policy.js +6 -10
- package/src/agent/critical-agent-policy.ts +20 -0
- package/src/agent/guidance-queue.js +74 -87
- package/src/agent/guidance-queue.ts +166 -0
- package/src/agent/output-extraction-error-detail.js +45 -0
- package/src/agent/output-extraction-error-detail.ts +49 -0
- package/src/agent/output-extraction-failures.js +125 -0
- package/src/agent/output-extraction-failures.ts +149 -0
- package/src/agent/output-extraction-json.js +234 -0
- package/src/agent/output-extraction-json.ts +235 -0
- package/src/agent/output-extraction-pi.js +124 -0
- package/src/agent/output-extraction-pi.ts +137 -0
- package/src/agent/output-extraction-types.js +2 -0
- package/src/agent/output-extraction-types.ts +49 -0
- package/src/agent/output-extraction.js +17 -617
- package/src/agent/output-extraction.ts +30 -0
- package/src/agent/output-reformatter-errors.js +83 -0
- package/src/agent/output-reformatter-errors.ts +106 -0
- package/src/agent/output-reformatter-types.js +2 -0
- package/src/agent/output-reformatter-types.ts +86 -0
- package/src/agent/output-reformatter.js +140 -185
- package/src/agent/output-reformatter.ts +238 -0
- package/src/agent/pi-terminal-lifecycle-types.js +2 -0
- package/src/agent/pi-terminal-lifecycle-types.ts +41 -0
- package/src/agent/pi-terminal-lifecycle.js +186 -206
- package/src/agent/pi-terminal-lifecycle.ts +297 -0
- package/src/agent/provider-control-plane.js +22 -21
- package/src/agent/provider-control-plane.ts +52 -0
- package/src/agent/provider-terminal-failure-types.js +2 -0
- package/src/agent/provider-terminal-failure-types.ts +60 -0
- package/src/agent/provider-terminal-failure.js +194 -191
- package/src/agent/provider-terminal-failure.ts +262 -0
- package/src/agent/rate-limit-backoff.js +31 -74
- package/src/agent/rate-limit-backoff.ts +71 -0
- package/src/agent/schema-utils.js +85 -125
- package/src/agent/schema-utils.ts +148 -0
- package/src/agent/structured-output-error.js +34 -33
- package/src/agent/structured-output-error.ts +105 -0
- package/src/agent/validation-platform.js +27 -27
- package/src/agent/validation-platform.ts +49 -0
- package/src/attach/attach-client.js +232 -405
- package/src/attach/attach-client.ts +300 -0
- package/src/attach/attach-server-cleanup.js +43 -0
- package/src/attach/attach-server-cleanup.ts +39 -0
- package/src/attach/attach-server-clients.js +117 -0
- package/src/attach/attach-server-clients.ts +122 -0
- package/src/attach/attach-server-events.js +38 -0
- package/src/attach/attach-server-events.ts +36 -0
- package/src/attach/attach-server-pty.js +45 -0
- package/src/attach/attach-server-pty.ts +64 -0
- package/src/attach/attach-server-runtime.js +73 -0
- package/src/attach/attach-server-runtime.ts +62 -0
- package/src/attach/attach-server-socket.js +28 -0
- package/src/attach/attach-server-socket.ts +23 -0
- package/src/attach/attach-server-types.js +2 -0
- package/src/attach/attach-server-types.ts +82 -0
- package/src/attach/attach-server.js +106 -523
- package/src/attach/attach-server.ts +158 -0
- package/src/attach/index.js +18 -35
- package/src/attach/index.ts +18 -0
- package/src/attach/protocol.js +95 -184
- package/src/attach/protocol.ts +181 -0
- package/src/attach/ring-buffer.js +76 -102
- package/src/attach/ring-buffer.ts +109 -0
- package/src/attach/send-input.js +64 -75
- package/src/attach/send-input.ts +94 -0
- package/src/attach/socket-discovery.js +164 -218
- package/src/attach/socket-discovery.ts +230 -0
- package/src/attach/socket-paths.js +42 -61
- package/src/attach/socket-paths.ts +81 -0
- package/src/claude-credentials.js +51 -54
- package/src/claude-credentials.ts +89 -0
- package/src/cluster/generated/protocol-schema.ts +1 -1
- package/src/cluster/generated/protocol.ts +2 -1
- package/src/command-proofs.js +110 -141
- package/src/command-proofs.ts +216 -0
- package/src/config-router.js +81 -73
- package/src/config-router.ts +131 -0
- package/src/copy-worker.js +53 -29
- package/src/copy-worker.ts +75 -0
- package/src/darwin-keychain-boundary.js +80 -111
- package/src/darwin-keychain-boundary.ts +148 -0
- package/src/guidance-topics.js +4 -5
- package/src/guidance-topics.ts +10 -0
- package/src/input-helpers.js +33 -54
- package/src/input-helpers.ts +58 -0
- package/src/ledger-sequence.js +45 -48
- package/src/ledger-sequence.ts +63 -0
- package/src/legacy-lib/clusters-registry.ts +40 -0
- package/src/legacy-lib/completion.ts +148 -0
- package/src/legacy-lib/compose-utils.ts +102 -0
- package/src/legacy-lib/detached-startup.ts +449 -0
- package/src/legacy-lib/docker-config.ts +282 -0
- package/src/legacy-lib/docker-env-auth.ts +116 -0
- package/src/legacy-lib/git-remote-utils.ts +244 -0
- package/src/legacy-lib/id-detector.ts +57 -0
- package/src/legacy-lib/js-yaml.d.ts +3 -0
- package/src/legacy-lib/omelette.d.ts +15 -0
- package/src/legacy-lib/path-check.ts +89 -0
- package/src/legacy-lib/process-liveness.ts +36 -0
- package/src/legacy-lib/provider-credential-path.ts +57 -0
- package/src/legacy-lib/provider-defaults.ts +114 -0
- package/src/legacy-lib/provider-detection.ts +67 -0
- package/src/legacy-lib/provider-names.ts +126 -0
- package/src/legacy-lib/repo-settings.ts +88 -0
- package/src/legacy-lib/run-mode.ts +58 -0
- package/src/legacy-lib/run-plan.ts +49 -0
- package/src/legacy-lib/settings/claude-auth.ts +80 -0
- package/src/legacy-lib/settings-defaults.ts +212 -0
- package/src/legacy-lib/settings-error.ts +8 -0
- package/src/legacy-lib/settings-issue-providers.ts +18 -0
- package/src/legacy-lib/settings-models.ts +124 -0
- package/src/legacy-lib/settings-storage.ts +277 -0
- package/src/legacy-lib/settings-validation.ts +220 -0
- package/src/legacy-lib/settings.ts +87 -0
- package/src/legacy-lib/setup-apply-types.ts +70 -0
- package/src/legacy-lib/setup-apply.ts +456 -0
- package/src/legacy-lib/setup-journal.ts +185 -0
- package/src/legacy-lib/setup-plan-types.ts +96 -0
- package/src/legacy-lib/setup-plan.ts +500 -0
- package/src/legacy-lib/setup-undo.ts +142 -0
- package/src/legacy-lib/start-cluster-config.ts +124 -0
- package/src/legacy-lib/start-cluster-environment.ts +165 -0
- package/src/legacy-lib/start-cluster-run-options.ts +279 -0
- package/src/legacy-lib/start-cluster.ts +237 -0
- package/src/legacy-lib/stream-json-parser.ts +88 -0
- package/src/message-buffer.js +55 -71
- package/src/message-buffer.ts +107 -0
- package/src/message-bus-bridge.js +92 -133
- package/src/message-bus-bridge.ts +149 -0
- package/src/name-generator-shared.js +220 -0
- package/src/name-generator-shared.ts +231 -0
- package/src/name-generator.js +8 -217
- package/src/name-generator.ts +27 -0
- package/src/omp-blob-root.js +83 -64
- package/src/omp-blob-root.ts +116 -0
- package/src/omp-config-overlay.js +65 -38
- package/src/omp-config-overlay.ts +110 -0
- package/src/omp-execution-fingerprint.js +38 -43
- package/src/omp-execution-fingerprint.ts +92 -0
- package/src/omp-session-limits.js +10 -15
- package/src/omp-session-limits.ts +53 -0
- package/src/omp-session-partition.js +2 -2
- package/src/omp-session-verifier.js +1 -1
- package/src/orchestrator.js +19 -4
- package/src/providers/anthropic/index.js +3 -1
- package/src/providers/anthropic/index.ts +13 -0
- package/src/providers/capabilities.js +19 -27
- package/src/providers/capabilities.ts +44 -0
- package/src/providers/google/index.js +3 -1
- package/src/providers/google/index.ts +13 -0
- package/src/providers/openai/index.js +3 -1
- package/src/providers/openai/index.ts +13 -0
- package/src/providers/opencode/index.js +3 -1
- package/src/providers/opencode/index.ts +13 -0
- package/src/quality-gates.js +67 -127
- package/src/quality-gates.ts +149 -0
- package/src/repo-settings-access.js +40 -0
- package/src/repo-settings-access.ts +64 -0
- package/src/schemas/sub-cluster.js +127 -183
- package/src/schemas/sub-cluster.ts +238 -0
- package/src/state-snapshot-normalization.js +224 -0
- package/src/state-snapshot-normalization.ts +222 -0
- package/src/state-snapshot.js +192 -359
- package/src/state-snapshot.ts +291 -0
- package/src/state-snapshotter.js +118 -130
- package/src/state-snapshotter.ts +167 -0
- package/src/sub-cluster-wrapper.js +4 -13
- package/src/task-run-model-args.js +87 -124
- package/src/task-run-model-args.ts +204 -0
- package/src/task-runner.js +5 -25
- package/src/task-runner.ts +28 -0
- package/src/task-startup-error.js +73 -58
- package/src/task-startup-error.ts +126 -0
- package/src/template-validation/consensus-gate-contracts.js +2 -0
- package/src/template-validation/consensus-gate-contracts.ts +70 -0
- package/src/template-validation/consensus-gate-scenarios.js +76 -0
- package/src/template-validation/consensus-gate-scenarios.ts +130 -0
- package/src/template-validation/consensus-gate-stage.js +34 -0
- package/src/template-validation/consensus-gate-stage.ts +56 -0
- package/src/template-validation/random-topology-contracts.js +2 -0
- package/src/template-validation/random-topology-contracts.ts +54 -0
- package/src/template-validation/random-topology-dispatch.js +25 -0
- package/src/template-validation/random-topology-dispatch.ts +33 -0
- package/src/template-validation/random-topology-message-loop.js +53 -0
- package/src/template-validation/random-topology-message-loop.ts +73 -0
- package/src/template-validation/random-topology-operations.js +79 -0
- package/src/template-validation/random-topology-operations.ts +101 -0
- package/src/template-validation/random-topology-runtime.js +25 -0
- package/src/template-validation/random-topology-runtime.ts +43 -0
- package/src/template-validation/random-topology-scenario.js +52 -0
- package/src/template-validation/random-topology-scenario.ts +57 -0
- package/src/template-validation/random-topology-schema.js +159 -0
- package/src/template-validation/random-topology-schema.ts +190 -0
- package/src/template-validation/random-topology-state.js +28 -0
- package/src/template-validation/random-topology-state.ts +30 -0
- package/src/template-validation/random-topology-trigger-evaluation.js +45 -0
- package/src/template-validation/random-topology-trigger-evaluation.ts +65 -0
- package/src/template-validation/random-topology-trigger.js +75 -0
- package/src/template-validation/random-topology-trigger.ts +88 -0
- package/src/template-validation/report-formatter.js +40 -46
- package/src/template-validation/report-formatter.ts +101 -0
- package/src/template-validation/simulate-consensus-gates.js +111 -302
- package/src/template-validation/simulate-consensus-gates.ts +196 -0
- package/src/template-validation/simulate-random-topology.js +26 -519
- package/src/template-validation/simulate-random-topology.ts +57 -0
- package/src/template-validation/simulate-two-stage-validation.js +41 -265
- package/src/template-validation/simulate-two-stage-validation.ts +55 -0
- package/src/template-validation/simulation-agent-runtime.js +25 -0
- package/src/template-validation/simulation-agent-runtime.ts +40 -0
- package/src/template-validation/simulation-agent.js +29 -0
- package/src/template-validation/simulation-agent.ts +73 -0
- package/src/template-validation/simulation-runtime.js +34 -0
- package/src/template-validation/simulation-runtime.ts +72 -0
- package/src/template-validation/two-stage-contracts.js +2 -0
- package/src/template-validation/two-stage-contracts.ts +41 -0
- package/src/template-validation/two-stage-inputs.js +21 -0
- package/src/template-validation/two-stage-inputs.ts +29 -0
- package/src/template-validation/two-stage-results.js +30 -0
- package/src/template-validation/two-stage-results.ts +40 -0
- package/src/template-validation/two-stage-scenario.js +86 -0
- package/src/template-validation/two-stage-scenario.ts +120 -0
- package/src/worktree-claude-config.js +182 -220
- package/src/worktree-claude-config.ts +272 -0
- package/src/worktree-tooling-env.js +103 -125
- package/src/worktree-tooling-env.ts +142 -0
- package/task-lib/completion.js +2 -3
- package/task-lib/completion.ts +9 -0
- package/task-lib/config.js +1 -4
- package/task-lib/config.ts +11 -0
- package/task-lib/name-generator.js +4 -226
- package/task-lib/name-generator.ts +11 -0
- package/task-lib/omp-session-cleanup.js +1 -1
- package/task-lib/omp-storage-root.js +8 -12
- package/task-lib/omp-storage-root.ts +62 -0
- package/task-lib/process-termination.js +143 -166
- package/task-lib/process-termination.ts +268 -0
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
const INVOCATION_METADATA_FIELDS = [
|
|
3
|
+
'code',
|
|
4
|
+
'permanent',
|
|
5
|
+
'provider',
|
|
6
|
+
'capability',
|
|
7
|
+
'nestedExecutionCancellation',
|
|
8
|
+
'nestedExecutionLifecycle',
|
|
9
|
+
'retainTaskHandle',
|
|
10
|
+
'terminationExhausted',
|
|
11
|
+
'taskId',
|
|
12
|
+
];
|
|
13
|
+
function isProvidersBoundary(value) {
|
|
14
|
+
return (value !== null &&
|
|
15
|
+
typeof value === 'object' &&
|
|
16
|
+
!Array.isArray(value) &&
|
|
17
|
+
'getProvider' in value &&
|
|
18
|
+
typeof value.getProvider === 'function');
|
|
19
|
+
}
|
|
20
|
+
const rawProviders = require('../providers');
|
|
21
|
+
if (!isProvidersBoundary(rawProviders)) {
|
|
22
|
+
throw new TypeError('providers module must expose getProvider');
|
|
23
|
+
}
|
|
24
|
+
const { getProvider } = rawProviders;
|
|
25
|
+
function isRecoveryError(value) {
|
|
26
|
+
return value instanceof Error;
|
|
27
|
+
}
|
|
28
|
+
function invocationError(result) {
|
|
29
|
+
let error;
|
|
30
|
+
if (isRecoveryError(result?.error)) {
|
|
31
|
+
error = result.error;
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
const message = result?.error ? String(result.error) : 'Structured-output recovery task failed';
|
|
35
|
+
error = new Error(message);
|
|
36
|
+
}
|
|
37
|
+
if (!result)
|
|
38
|
+
return error;
|
|
39
|
+
for (const field of INVOCATION_METADATA_FIELDS) {
|
|
40
|
+
if (result[field] !== undefined && error[field] === undefined) {
|
|
41
|
+
error[field] = result[field];
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return error;
|
|
45
|
+
}
|
|
46
|
+
function isImmediateRecoveryFailure(error, providerName) {
|
|
47
|
+
if (error.code === 'REFORMAT_CANCELLED' ||
|
|
48
|
+
error.code === 'AGENT_TASK_TIMEOUT' ||
|
|
49
|
+
error.nestedExecutionCancellation === true ||
|
|
50
|
+
error.nestedExecutionLifecycle === true ||
|
|
51
|
+
error.retainTaskHandle === true ||
|
|
52
|
+
error.permanent === true ||
|
|
53
|
+
error.terminationExhausted === true) {
|
|
54
|
+
return true;
|
|
55
|
+
}
|
|
56
|
+
return !getProvider(providerName).isRetryableError(error);
|
|
57
|
+
}
|
|
58
|
+
function markImmediateRecoveryFailure(error, providerName) {
|
|
59
|
+
if (!isImmediateRecoveryFailure(error, providerName))
|
|
60
|
+
return false;
|
|
61
|
+
error.recoveryAbort = true;
|
|
62
|
+
const operationalControl = error.code === 'REFORMAT_CANCELLED' ||
|
|
63
|
+
error.code === 'AGENT_TASK_TIMEOUT' ||
|
|
64
|
+
error.nestedExecutionCancellation === true ||
|
|
65
|
+
error.nestedExecutionLifecycle === true ||
|
|
66
|
+
error.retainTaskHandle === true ||
|
|
67
|
+
error.terminationExhausted === true;
|
|
68
|
+
if (!operationalControl && error.permanent !== true)
|
|
69
|
+
error.permanent = true;
|
|
70
|
+
return true;
|
|
71
|
+
}
|
|
72
|
+
function recoveryErrorMessage(error, providerName) {
|
|
73
|
+
if (!isRecoveryError(error))
|
|
74
|
+
return null;
|
|
75
|
+
if (markImmediateRecoveryFailure(error, providerName))
|
|
76
|
+
throw error;
|
|
77
|
+
return error.message;
|
|
78
|
+
}
|
|
79
|
+
module.exports = {
|
|
80
|
+
invocationError,
|
|
81
|
+
markImmediateRecoveryFailure,
|
|
82
|
+
recoveryErrorMessage,
|
|
83
|
+
};
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
ProvidersBoundary,
|
|
3
|
+
RecoveryError,
|
|
4
|
+
ReformatInvocationResult,
|
|
5
|
+
} from './output-reformatter-types';
|
|
6
|
+
|
|
7
|
+
const INVOCATION_METADATA_FIELDS: readonly (
|
|
8
|
+
| 'code'
|
|
9
|
+
| 'permanent'
|
|
10
|
+
| 'provider'
|
|
11
|
+
| 'capability'
|
|
12
|
+
| 'nestedExecutionCancellation'
|
|
13
|
+
| 'nestedExecutionLifecycle'
|
|
14
|
+
| 'retainTaskHandle'
|
|
15
|
+
| 'terminationExhausted'
|
|
16
|
+
| 'taskId'
|
|
17
|
+
)[] = [
|
|
18
|
+
'code',
|
|
19
|
+
'permanent',
|
|
20
|
+
'provider',
|
|
21
|
+
'capability',
|
|
22
|
+
'nestedExecutionCancellation',
|
|
23
|
+
'nestedExecutionLifecycle',
|
|
24
|
+
'retainTaskHandle',
|
|
25
|
+
'terminationExhausted',
|
|
26
|
+
'taskId',
|
|
27
|
+
];
|
|
28
|
+
|
|
29
|
+
function isProvidersBoundary(value: unknown): value is ProvidersBoundary {
|
|
30
|
+
return (
|
|
31
|
+
value !== null &&
|
|
32
|
+
typeof value === 'object' &&
|
|
33
|
+
!Array.isArray(value) &&
|
|
34
|
+
'getProvider' in value &&
|
|
35
|
+
typeof value.getProvider === 'function'
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const rawProviders: unknown = require('../providers');
|
|
40
|
+
if (!isProvidersBoundary(rawProviders)) {
|
|
41
|
+
throw new TypeError('providers module must expose getProvider');
|
|
42
|
+
}
|
|
43
|
+
const { getProvider } = rawProviders;
|
|
44
|
+
|
|
45
|
+
function isRecoveryError(value: unknown): value is RecoveryError {
|
|
46
|
+
return value instanceof Error;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function invocationError(result: ReformatInvocationResult | null | undefined): RecoveryError {
|
|
50
|
+
let error: RecoveryError;
|
|
51
|
+
if (isRecoveryError(result?.error)) {
|
|
52
|
+
error = result.error;
|
|
53
|
+
} else {
|
|
54
|
+
const message = result?.error ? String(result.error) : 'Structured-output recovery task failed';
|
|
55
|
+
error = new Error(message);
|
|
56
|
+
}
|
|
57
|
+
if (!result) return error;
|
|
58
|
+
|
|
59
|
+
for (const field of INVOCATION_METADATA_FIELDS) {
|
|
60
|
+
if (result[field] !== undefined && error[field] === undefined) {
|
|
61
|
+
error[field] = result[field];
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return error;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function isImmediateRecoveryFailure(error: RecoveryError, providerName: string): boolean {
|
|
68
|
+
if (
|
|
69
|
+
error.code === 'REFORMAT_CANCELLED' ||
|
|
70
|
+
error.code === 'AGENT_TASK_TIMEOUT' ||
|
|
71
|
+
error.nestedExecutionCancellation === true ||
|
|
72
|
+
error.nestedExecutionLifecycle === true ||
|
|
73
|
+
error.retainTaskHandle === true ||
|
|
74
|
+
error.permanent === true ||
|
|
75
|
+
error.terminationExhausted === true
|
|
76
|
+
) {
|
|
77
|
+
return true;
|
|
78
|
+
}
|
|
79
|
+
return !getProvider(providerName).isRetryableError(error);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function markImmediateRecoveryFailure(error: RecoveryError, providerName: string): boolean {
|
|
83
|
+
if (!isImmediateRecoveryFailure(error, providerName)) return false;
|
|
84
|
+
error.recoveryAbort = true;
|
|
85
|
+
const operationalControl =
|
|
86
|
+
error.code === 'REFORMAT_CANCELLED' ||
|
|
87
|
+
error.code === 'AGENT_TASK_TIMEOUT' ||
|
|
88
|
+
error.nestedExecutionCancellation === true ||
|
|
89
|
+
error.nestedExecutionLifecycle === true ||
|
|
90
|
+
error.retainTaskHandle === true ||
|
|
91
|
+
error.terminationExhausted === true;
|
|
92
|
+
if (!operationalControl && error.permanent !== true) error.permanent = true;
|
|
93
|
+
return true;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function recoveryErrorMessage(error: unknown, providerName: string): string | null {
|
|
97
|
+
if (!isRecoveryError(error)) return null;
|
|
98
|
+
if (markImmediateRecoveryFailure(error, providerName)) throw error;
|
|
99
|
+
return error.message;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export = {
|
|
103
|
+
invocationError,
|
|
104
|
+
markImmediateRecoveryFailure,
|
|
105
|
+
recoveryErrorMessage,
|
|
106
|
+
};
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import type { ErrorObject, Schema } from 'ajv';
|
|
2
|
+
|
|
3
|
+
export interface RuntimeProviderBoundary {
|
|
4
|
+
isRetryableError(error: Error): boolean;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export interface ProvidersBoundary {
|
|
8
|
+
getProvider(name: string): RuntimeProviderBoundary;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface SchemaUtilsBoundary {
|
|
12
|
+
normalizeEnumValues(result: unknown, schema: unknown): unknown;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface RecoveryError extends Error {
|
|
16
|
+
code?: unknown;
|
|
17
|
+
permanent?: unknown;
|
|
18
|
+
provider?: unknown;
|
|
19
|
+
capability?: unknown;
|
|
20
|
+
nestedExecutionCancellation?: unknown;
|
|
21
|
+
nestedExecutionLifecycle?: unknown;
|
|
22
|
+
retainTaskHandle?: unknown;
|
|
23
|
+
recoveryAbort?: unknown;
|
|
24
|
+
terminationExhausted?: unknown;
|
|
25
|
+
taskId?: unknown;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface ReformatInvocationResult {
|
|
29
|
+
success?: unknown;
|
|
30
|
+
output?: string;
|
|
31
|
+
error?: unknown;
|
|
32
|
+
code?: unknown;
|
|
33
|
+
permanent?: unknown;
|
|
34
|
+
provider?: unknown;
|
|
35
|
+
capability?: unknown;
|
|
36
|
+
nestedExecutionCancellation?: unknown;
|
|
37
|
+
nestedExecutionLifecycle?: unknown;
|
|
38
|
+
retainTaskHandle?: unknown;
|
|
39
|
+
terminationExhausted?: unknown;
|
|
40
|
+
taskId?: unknown;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export interface StructuredValidationResult {
|
|
44
|
+
valid: boolean;
|
|
45
|
+
value: unknown;
|
|
46
|
+
errors: ErrorObject[];
|
|
47
|
+
error: string | null;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export type StructuredOutputValidator = (candidate: unknown) => StructuredValidationResult;
|
|
51
|
+
|
|
52
|
+
export type RunReformat = (
|
|
53
|
+
prompt: string
|
|
54
|
+
) =>
|
|
55
|
+
| ReformatInvocationResult
|
|
56
|
+
| null
|
|
57
|
+
| undefined
|
|
58
|
+
| Promise<ReformatInvocationResult | null | undefined>;
|
|
59
|
+
|
|
60
|
+
export interface ReformatOutputArguments {
|
|
61
|
+
rawOutput: string;
|
|
62
|
+
schema: Schema;
|
|
63
|
+
providerName: string;
|
|
64
|
+
maxAttempts?: number;
|
|
65
|
+
initialError?: string | null;
|
|
66
|
+
validateCandidate?: StructuredOutputValidator;
|
|
67
|
+
onAttempt?(attempt: number, lastError: string | null): unknown;
|
|
68
|
+
isCancelled?(): boolean;
|
|
69
|
+
runReformat?: RunReformat;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export interface RecoveryAttemptArguments {
|
|
73
|
+
prompt: string;
|
|
74
|
+
providerName: string;
|
|
75
|
+
validateCandidate: StructuredOutputValidator;
|
|
76
|
+
isCancelled(): boolean;
|
|
77
|
+
runReformat: RunReformat;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export type RecoveryAttemptOutcome =
|
|
81
|
+
| { status: 'recovered'; value: unknown }
|
|
82
|
+
| { status: 'retry'; error: string | null };
|
|
83
|
+
|
|
84
|
+
export type ReformatOutcome =
|
|
85
|
+
| { status: 'recovered'; value: unknown; attempts: number }
|
|
86
|
+
| { status: 'exhausted'; attempts: number; lastError: string };
|
|
@@ -1,20 +1,38 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
const ajv_1 = __importDefault(require("ajv"));
|
|
6
|
+
const outputReformatterErrors = require("./output-reformatter-errors");
|
|
7
|
+
function isRecord(value) {
|
|
8
|
+
return value !== null && typeof value === 'object' && !Array.isArray(value);
|
|
9
|
+
}
|
|
10
|
+
function isSchemaUtilsBoundary(value) {
|
|
11
|
+
return isRecord(value) && typeof value.normalizeEnumValues === 'function';
|
|
12
|
+
}
|
|
13
|
+
function isOutputExtractionBoundary(value) {
|
|
14
|
+
return (isRecord(value) &&
|
|
15
|
+
typeof value.extractCliError === 'function' &&
|
|
16
|
+
typeof value.extractJsonFromOutput === 'function');
|
|
17
|
+
}
|
|
18
|
+
const { invocationError, markImmediateRecoveryFailure, recoveryErrorMessage } = outputReformatterErrors;
|
|
19
|
+
const rawSchemaUtils = require('./schema-utils');
|
|
20
|
+
if (!isSchemaUtilsBoundary(rawSchemaUtils)) {
|
|
21
|
+
throw new TypeError('schema-utils module must expose normalizeEnumValues');
|
|
22
|
+
}
|
|
23
|
+
const { normalizeEnumValues } = rawSchemaUtils;
|
|
5
24
|
const DEFAULT_MAX_ATTEMPTS = 3;
|
|
6
25
|
const MAX_REFORMAT_INPUT_BYTES = 65_536;
|
|
7
26
|
const MAX_CONFIGURED_ATTEMPTS = 10;
|
|
8
|
-
|
|
9
27
|
function createCancellationError() {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
28
|
+
const error = new Error('Output reformatting cancelled');
|
|
29
|
+
error.code = 'REFORMAT_CANCELLED';
|
|
30
|
+
error.recoveryAbort = true;
|
|
31
|
+
return error;
|
|
14
32
|
}
|
|
15
|
-
|
|
16
33
|
function buildReformatPrompt(rawOutput, schema, previousError = null) {
|
|
17
|
-
|
|
34
|
+
let prompt = 'CRITICAL: Do NOT use any tools. Do NOT read, write, or edit any files. ' +
|
|
35
|
+
`Do NOT explore the codebase. This is a pure text-to-JSON transformation — respond with JSON only.
|
|
18
36
|
|
|
19
37
|
Convert the JSON-encoded source text into a JSON object matching the schema.
|
|
20
38
|
|
|
@@ -32,200 +50,137 @@ ${JSON.stringify(rawOutput)}
|
|
|
32
50
|
- NO explanations
|
|
33
51
|
- Start with { end with }
|
|
34
52
|
- Match ALL required fields from schema`;
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
prompt += `
|
|
53
|
+
if (previousError) {
|
|
54
|
+
prompt += `
|
|
38
55
|
|
|
39
56
|
## PREVIOUS CANDIDATE FAILED
|
|
40
57
|
${previousError}
|
|
41
58
|
Fix this issue in your response.`;
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
return prompt;
|
|
59
|
+
}
|
|
60
|
+
return prompt;
|
|
45
61
|
}
|
|
46
|
-
|
|
47
62
|
function formatValidationErrors(errors, limit = 5) {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
63
|
+
return errors
|
|
64
|
+
.slice(0, limit)
|
|
65
|
+
.map((error) => `${error.instancePath || error.schemaPath || '#'} ${error.message}`)
|
|
66
|
+
.join('; ');
|
|
52
67
|
}
|
|
53
|
-
|
|
54
68
|
function createStructuredOutputValidator(schema) {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
69
|
+
const ajv = new ajv_1.default({
|
|
70
|
+
allErrors: true,
|
|
71
|
+
strict: false,
|
|
72
|
+
coerceTypes: false,
|
|
73
|
+
useDefaults: true,
|
|
74
|
+
removeAdditional: true,
|
|
75
|
+
});
|
|
76
|
+
const validate = ajv.compile(schema);
|
|
77
|
+
return (candidate) => {
|
|
78
|
+
normalizeEnumValues(candidate, schema);
|
|
79
|
+
const valid = validate(candidate);
|
|
80
|
+
const errors = (validate.errors ?? []).map((error) => ({ ...error }));
|
|
81
|
+
return {
|
|
82
|
+
valid,
|
|
83
|
+
value: candidate,
|
|
84
|
+
errors,
|
|
85
|
+
error: valid ? null : formatValidationErrors(errors) || 'Schema validation failed',
|
|
86
|
+
};
|
|
73
87
|
};
|
|
74
|
-
};
|
|
75
88
|
}
|
|
76
|
-
|
|
77
89
|
function validateAgainstSchema(parsed, schema) {
|
|
78
|
-
|
|
90
|
+
return createStructuredOutputValidator(schema)(parsed).error;
|
|
79
91
|
}
|
|
80
|
-
|
|
81
92
|
function assertReformatRequest(rawOutput, maxAttempts) {
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
);
|
|
94
|
-
error.code = 'REFORMAT_INPUT_TOO_LARGE';
|
|
95
|
-
error.permanent = true;
|
|
96
|
-
throw error;
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
function invocationError(result) {
|
|
101
|
-
const error =
|
|
102
|
-
result?.error instanceof Error
|
|
103
|
-
? result.error
|
|
104
|
-
: new Error(result?.error || 'Structured-output recovery task failed');
|
|
105
|
-
for (const field of [
|
|
106
|
-
'code',
|
|
107
|
-
'permanent',
|
|
108
|
-
'provider',
|
|
109
|
-
'capability',
|
|
110
|
-
'nestedExecutionCancellation',
|
|
111
|
-
'nestedExecutionLifecycle',
|
|
112
|
-
'retainTaskHandle',
|
|
113
|
-
'terminationExhausted',
|
|
114
|
-
'taskId',
|
|
115
|
-
]) {
|
|
116
|
-
if (result?.[field] !== undefined && error[field] === undefined) {
|
|
117
|
-
error[field] = result[field];
|
|
93
|
+
if (!Number.isInteger(maxAttempts) || maxAttempts < 1 || maxAttempts > MAX_CONFIGURED_ATTEMPTS) {
|
|
94
|
+
const error = new RangeError(`Output reformatting maxAttempts must be an integer from 1 through ${MAX_CONFIGURED_ATTEMPTS}`);
|
|
95
|
+
error.code = 'REFORMAT_INVALID_ATTEMPT_LIMIT';
|
|
96
|
+
error.permanent = true;
|
|
97
|
+
throw error;
|
|
98
|
+
}
|
|
99
|
+
if (Buffer.byteLength(rawOutput || '', 'utf8') > MAX_REFORMAT_INPUT_BYTES) {
|
|
100
|
+
const error = new Error(`Output reformatting input exceeds ${MAX_REFORMAT_INPUT_BYTES} UTF-8 bytes`);
|
|
101
|
+
error.code = 'REFORMAT_INPUT_TOO_LARGE';
|
|
102
|
+
error.permanent = true;
|
|
103
|
+
throw error;
|
|
118
104
|
}
|
|
119
|
-
}
|
|
120
|
-
return error;
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
function isImmediateRecoveryFailure(error, providerName) {
|
|
124
|
-
if (
|
|
125
|
-
error?.code === 'REFORMAT_CANCELLED' ||
|
|
126
|
-
error?.code === 'AGENT_TASK_TIMEOUT' ||
|
|
127
|
-
error?.nestedExecutionCancellation === true ||
|
|
128
|
-
error?.nestedExecutionLifecycle === true ||
|
|
129
|
-
error?.retainTaskHandle === true ||
|
|
130
|
-
error?.permanent === true ||
|
|
131
|
-
error?.terminationExhausted === true
|
|
132
|
-
) {
|
|
133
|
-
return true;
|
|
134
|
-
}
|
|
135
|
-
return !getProvider(providerName).isRetryableError(error);
|
|
136
105
|
}
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
error.code === 'AGENT_TASK_TIMEOUT' ||
|
|
144
|
-
error.nestedExecutionCancellation === true ||
|
|
145
|
-
error.nestedExecutionLifecycle === true ||
|
|
146
|
-
error.retainTaskHandle === true ||
|
|
147
|
-
error.terminationExhausted === true;
|
|
148
|
-
if (!operationalControl && error.permanent !== true) error.permanent = true;
|
|
149
|
-
return true;
|
|
106
|
+
function loadOutputExtraction() {
|
|
107
|
+
const rawOutputExtraction = require('./output-extraction');
|
|
108
|
+
if (!isOutputExtractionBoundary(rawOutputExtraction)) {
|
|
109
|
+
throw new TypeError('output-extraction module must expose structured-output extractors');
|
|
110
|
+
}
|
|
111
|
+
return rawOutputExtraction;
|
|
150
112
|
}
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
maxAttempts = DEFAULT_MAX_ATTEMPTS,
|
|
157
|
-
initialError = null,
|
|
158
|
-
validateCandidate = createStructuredOutputValidator(schema),
|
|
159
|
-
onAttempt,
|
|
160
|
-
isCancelled = () => false,
|
|
161
|
-
runReformat,
|
|
162
|
-
}) {
|
|
163
|
-
assertReformatRequest(rawOutput, maxAttempts);
|
|
164
|
-
if (typeof runReformat !== 'function') {
|
|
165
|
-
throw new Error('Output reformatting requires the active agent execution context');
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
const { extractCliError, extractJsonFromOutput } = require('./output-extraction');
|
|
169
|
-
let lastError = initialError;
|
|
170
|
-
|
|
171
|
-
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
172
|
-
if (isCancelled()) throw createCancellationError();
|
|
173
|
-
onAttempt?.(attempt, lastError);
|
|
174
|
-
const prompt = buildReformatPrompt(rawOutput, schema, lastError);
|
|
175
|
-
|
|
176
|
-
try {
|
|
177
|
-
const result = await runReformat(prompt);
|
|
178
|
-
if (isCancelled()) throw createCancellationError();
|
|
179
|
-
if (!result?.success) {
|
|
113
|
+
async function recoverCandidate({ prompt, providerName, validateCandidate, isCancelled, runReformat, }) {
|
|
114
|
+
const result = await runReformat(prompt);
|
|
115
|
+
if (isCancelled())
|
|
116
|
+
throw createCancellationError();
|
|
117
|
+
if (!result?.success) {
|
|
180
118
|
const error = invocationError(result);
|
|
181
|
-
if (markImmediateRecoveryFailure(error, providerName))
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
if (terminalError) {
|
|
119
|
+
if (markImmediateRecoveryFailure(error, providerName))
|
|
120
|
+
throw error;
|
|
121
|
+
return { status: 'retry', error: error.message };
|
|
122
|
+
}
|
|
123
|
+
if (!result.output)
|
|
124
|
+
return { status: 'retry', error: 'Recovery task returned no output' };
|
|
125
|
+
const { extractCliError, extractJsonFromOutput } = loadOutputExtraction();
|
|
126
|
+
const terminalError = extractCliError(result.output, providerName);
|
|
127
|
+
if (terminalError) {
|
|
191
128
|
const error = new Error(terminalError.error);
|
|
192
129
|
error.provider = terminalError.provider;
|
|
193
|
-
if (markImmediateRecoveryFailure(error, providerName))
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
const parsed = extractJsonFromOutput(result.output, providerName);
|
|
199
|
-
if (!parsed) {
|
|
200
|
-
lastError = 'Could not extract JSON from recovery output';
|
|
201
|
-
continue;
|
|
202
|
-
}
|
|
203
|
-
const validation = validateCandidate(parsed);
|
|
204
|
-
if (!validation.valid) {
|
|
205
|
-
lastError = validation.error;
|
|
206
|
-
continue;
|
|
207
|
-
}
|
|
208
|
-
return { status: 'recovered', value: validation.value, attempts: attempt };
|
|
209
|
-
} catch (error) {
|
|
210
|
-
if (isCancelled()) throw createCancellationError();
|
|
211
|
-
if (markImmediateRecoveryFailure(error, providerName)) throw error;
|
|
212
|
-
lastError = error.message;
|
|
130
|
+
if (markImmediateRecoveryFailure(error, providerName))
|
|
131
|
+
throw error;
|
|
132
|
+
return { status: 'retry', error: error.message };
|
|
213
133
|
}
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
134
|
+
const parsed = extractJsonFromOutput(result.output, providerName);
|
|
135
|
+
if (!parsed)
|
|
136
|
+
return { status: 'retry', error: 'Could not extract JSON from recovery output' };
|
|
137
|
+
const validation = validateCandidate(parsed);
|
|
138
|
+
return validation.valid
|
|
139
|
+
? { status: 'recovered', value: validation.value }
|
|
140
|
+
: { status: 'retry', error: validation.error };
|
|
141
|
+
}
|
|
142
|
+
async function reformatOutput({ rawOutput, schema, providerName, maxAttempts = DEFAULT_MAX_ATTEMPTS, initialError = null, validateCandidate = createStructuredOutputValidator(schema), onAttempt, isCancelled = () => false, runReformat, }) {
|
|
143
|
+
assertReformatRequest(rawOutput, maxAttempts);
|
|
144
|
+
if (typeof runReformat !== 'function') {
|
|
145
|
+
throw new Error('Output reformatting requires the active agent execution context');
|
|
146
|
+
}
|
|
147
|
+
let lastError = initialError;
|
|
148
|
+
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
149
|
+
if (isCancelled())
|
|
150
|
+
throw createCancellationError();
|
|
151
|
+
onAttempt?.(attempt, lastError);
|
|
152
|
+
const prompt = buildReformatPrompt(rawOutput, schema, lastError);
|
|
153
|
+
try {
|
|
154
|
+
const outcome = await recoverCandidate({
|
|
155
|
+
prompt,
|
|
156
|
+
providerName,
|
|
157
|
+
validateCandidate,
|
|
158
|
+
isCancelled,
|
|
159
|
+
runReformat,
|
|
160
|
+
});
|
|
161
|
+
if (outcome.status === 'recovered') {
|
|
162
|
+
return { status: 'recovered', value: outcome.value, attempts: attempt };
|
|
163
|
+
}
|
|
164
|
+
lastError = outcome.error;
|
|
165
|
+
}
|
|
166
|
+
catch (caught) {
|
|
167
|
+
if (isCancelled())
|
|
168
|
+
throw createCancellationError();
|
|
169
|
+
lastError = recoveryErrorMessage(caught, providerName);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
return {
|
|
173
|
+
status: 'exhausted',
|
|
174
|
+
attempts: maxAttempts,
|
|
175
|
+
lastError: lastError || 'Recovery attempts produced no schema-valid JSON object',
|
|
176
|
+
};
|
|
221
177
|
}
|
|
222
|
-
|
|
223
178
|
module.exports = {
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
179
|
+
reformatOutput,
|
|
180
|
+
buildReformatPrompt,
|
|
181
|
+
createStructuredOutputValidator,
|
|
182
|
+
validateAgainstSchema,
|
|
183
|
+
DEFAULT_MAX_ATTEMPTS,
|
|
184
|
+
MAX_REFORMAT_INPUT_BYTES,
|
|
185
|
+
MAX_CONFIGURED_ATTEMPTS,
|
|
231
186
|
};
|