salmon-loop 0.3.2 → 0.5.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/dist/cli/authorization/non-interactive.js +9 -13
- package/dist/cli/authorization/provider.js +2 -10
- package/dist/cli/chat.js +12 -6
- package/dist/cli/commands/allowlist.js +1 -1
- package/dist/cli/commands/chat.js +13 -13
- package/dist/cli/commands/config.js +2 -2
- package/dist/cli/commands/mode.js +2 -2
- package/dist/cli/commands/parallel.js +1 -1
- package/dist/cli/commands/run/handler.js +9 -4
- package/dist/cli/commands/run/loop-params.js +2 -0
- package/dist/cli/commands/run/parse-options.js +14 -26
- package/dist/cli/commands/run/runtime-llm.js +15 -12
- package/dist/cli/commands/run/runtime-options.js +3 -1
- package/dist/cli/config.js +0 -8
- package/dist/cli/headless/openai-responses-canonical-applier.js +1 -7
- package/dist/cli/locales/en.js +2 -2
- package/dist/cli/reporters/standard.js +12 -3
- package/dist/cli/reporters/stream-json.js +2 -1
- package/dist/cli/slash/runtime.js +2 -2
- package/dist/cli/ui/hooks/useLoopEvents.js +1 -1
- package/dist/cli/ui/hooks/useLoopState.js +1 -1
- package/dist/core/adapters/fs/file-adapter.js +3 -1
- package/dist/core/adapters/git/git-adapter.js +6 -3
- package/dist/core/adapters/git/git-runner.js +5 -2
- package/dist/core/adapters/git/lock-manager.js +7 -4
- package/dist/core/ast/parser.js +18 -9
- package/dist/core/checkpoint-domain/manifest-store.js +21 -13
- package/dist/core/checkpoint-domain/service.js +3 -1
- package/dist/core/config/limits.js +1 -1
- package/dist/core/config/model-pricing.js +61 -0
- package/dist/core/config/schema.js +738 -0
- package/dist/core/config/validate.js +11 -922
- package/dist/core/context/ast/skeleton-extractor.js +225 -0
- package/dist/core/context/ast/source-outline.js +24 -1
- package/dist/core/context/budget/dynamic-adjuster.js +20 -5
- package/dist/core/context/builder.js +7 -3
- package/dist/core/context/cache/store-factory.js +3 -1
- package/dist/core/context/dependencies.js +2 -1
- package/dist/core/context/effectiveness/persistence.js +50 -0
- package/dist/core/context/effectiveness/tracker.js +24 -0
- package/dist/core/context/gatherers/architecture-gatherer.js +2 -1
- package/dist/core/context/gatherers/artifact-gatherer.js +7 -4
- package/dist/core/context/gatherers/ast-gatherer.js +34 -40
- package/dist/core/context/gatherers/ghost-dependency-gatherer.js +0 -1
- package/dist/core/context/gatherers/git-history-gatherer.js +3 -1
- package/dist/core/context/gatherers/knowledge-gatherer.js +21 -2
- package/dist/core/context/gatherers/metadata-gatherer.js +12 -7
- package/dist/core/context/gatherers/ripgrep-gatherer.js +6 -3
- package/dist/core/context/service.js +12 -2
- package/dist/core/context/steps/context-gather.js +14 -3
- package/dist/core/context/steps/context-targets.js +1 -0
- package/dist/core/context/targeting/target-resolver.js +29 -11
- package/dist/core/context/token/cache.js +5 -2
- package/dist/core/context/token/encoding-registry.js +7 -6
- package/dist/core/context/truncation/strategies/json.js +5 -2
- package/dist/core/context/truncation/type-detector.js +3 -1
- package/dist/core/extensions/index.js +48 -3
- package/dist/core/extensions/load.js +3 -2
- package/dist/core/extensions/merge.js +5 -1
- package/dist/core/extensions/paths.js +8 -2
- package/dist/core/extensions/schemas.js +21 -0
- package/dist/core/facades/cli-authorization-provider.js +1 -0
- package/dist/core/facades/cli-command-chat.js +2 -0
- package/dist/core/facades/cli-run-handler.js +1 -0
- package/dist/core/facades/cli-utils-serialize.js +2 -0
- package/dist/core/feedback/parsers.js +290 -1
- package/dist/core/grizzco/dsl/llm-strategy.js +4 -3
- package/dist/core/grizzco/engine/observability/loop-telemetry.js +5 -2
- package/dist/core/grizzco/engine/outcome/loop-result-mapper.js +30 -13
- package/dist/core/grizzco/engine/pipeline/pipeline.js +149 -240
- package/dist/core/grizzco/engine/transaction/attempt-failure.js +49 -24
- package/dist/core/grizzco/engine/transaction/authorization-summary.js +2 -1
- package/dist/core/grizzco/engine/transaction/transaction-runner.js +40 -34
- package/dist/core/grizzco/execution/RejectionManager.js +7 -5
- package/dist/core/grizzco/runtime/apply-back-runtime.js +5 -2
- package/dist/core/grizzco/services/implementations/default/GitConfigService.js +2 -1
- package/dist/core/grizzco/services/registry.js +18 -0
- package/dist/core/grizzco/steps/audit.js +20 -10
- package/dist/core/grizzco/steps/autopilot.js +21 -32
- package/dist/core/grizzco/steps/display-report.js +4 -11
- package/dist/core/grizzco/steps/explore.js +14 -4
- package/dist/core/grizzco/steps/generateReview.js +3 -1
- package/dist/core/grizzco/steps/patch/prompt-input.js +4 -1
- package/dist/core/grizzco/steps/patch.js +1 -0
- package/dist/core/grizzco/steps/plan.js +58 -49
- package/dist/core/grizzco/steps/research.js +3 -1
- package/dist/core/grizzco/steps/tool-runtime.js +3 -0
- package/dist/core/grizzco/steps/verify.js +7 -1
- package/dist/core/grizzco/validation/AstValidationService.js +3 -1
- package/dist/core/grizzco/workers/strata-sync-worker.js +2 -1
- package/dist/core/history/input-history.js +3 -1
- package/dist/core/intent/chat-intent.js +3 -1
- package/dist/core/llm/ai-sdk/message-mapper.js +37 -26
- package/dist/core/llm/ai-sdk/request-params.js +2 -6
- package/dist/core/llm/ai-sdk/result-mapper.js +14 -8
- package/dist/core/llm/ai-sdk/retry-classifier.js +17 -7
- package/dist/core/llm/ai-sdk/retry-executor.js +1 -1
- package/dist/core/llm/contracts/repair.js +16 -8
- package/dist/core/llm/errors.js +18 -14
- package/dist/core/llm/output-policy.js +8 -0
- package/dist/core/llm/redact.js +1 -3
- package/dist/core/llm/retry-utils.js +8 -2
- package/dist/core/llm/stream-utils.js +5 -3
- package/dist/core/llm/sub-agent-factory.js +51 -0
- package/dist/core/llm/tool-calling-stub.js +48 -0
- package/dist/core/llm/utils.js +17 -6
- package/dist/core/mcp/bridge/prompt-command-provider.js +4 -3
- package/dist/core/mcp/bridge/resource-context-provider.js +3 -1
- package/dist/core/mcp/bridge/tool-bridge.js +5 -14
- package/dist/core/mcp/catalog/discovery.js +3 -1
- package/dist/core/mcp/client/connection-manager.js +7 -4
- package/dist/core/mcp/client/transport-factory.js +7 -3
- package/dist/core/mcp/host/sampling-provider.js +1 -1
- package/dist/core/mcp/schema/json-schema-to-zod.js +2 -1
- package/dist/core/memory/relevant-retrieval.js +6 -4
- package/dist/core/observability/audit-file.js +2 -1
- package/dist/core/observability/audit-trail.js +3 -1
- package/dist/core/observability/authorization-decisions.js +13 -12
- package/dist/core/observability/error-mapping.js +2 -1
- package/dist/core/observability/logger.js +2 -1
- package/dist/core/observability/monitor.js +24 -0
- package/dist/core/observability/run-outcome-reporter.js +1 -0
- package/dist/core/observability/token-usage.js +5 -4
- package/dist/core/permission-gate/default-gate.js +5 -8
- package/dist/core/plan/storage.js +7 -4
- package/dist/core/plugin/loader.js +8 -5
- package/dist/core/prompts/registry.js +12 -30
- package/dist/core/prompts/runtime.js +3 -1
- package/dist/core/prompts/templates/system/autopilot_system.hbs +28 -4
- package/dist/core/protocols/a2a/sdk/executor.js +3 -1
- package/dist/core/protocols/a2a/sdk/server.js +5 -4
- package/dist/core/protocols/acp/acp-command-runner.js +7 -6
- package/dist/core/protocols/acp/acp-session-persistence.js +13 -10
- package/dist/core/protocols/acp/formal-agent.js +13 -6
- package/dist/core/protocols/acp/permission-provider.js +3 -2
- package/dist/core/protocols/acp/stdio-server.js +6 -6
- package/dist/core/reflection/engine.js +114 -14
- package/dist/core/runtime/agent-server-runtime.js +3 -2
- package/dist/core/runtime/batch-runner.js +81 -0
- package/dist/core/runtime/initialize.js +71 -6
- package/dist/core/runtime/loop-finalize.js +3 -0
- package/dist/core/runtime/loop-session-runner.js +5 -0
- package/dist/core/runtime/loop.js +4 -0
- package/dist/core/runtime/paths.js +9 -6
- package/dist/core/runtime/spawn-interactive.js +5 -4
- package/dist/core/security/redaction.js +3 -2
- package/dist/core/session/compaction/index.js +4 -3
- package/dist/core/session/compression.js +3 -1
- package/dist/core/session/manager.js +26 -38
- package/dist/core/session/pruning-strategy.js +2 -1
- package/dist/core/session/token-tracker.js +27 -9
- package/dist/core/skills/parser.js +3 -2
- package/dist/core/skills/permissions.js +2 -2
- package/dist/core/skills/runtime/MicroTaskRunner.js +1 -1
- package/dist/core/skills/runtime/SkillRunner.js +5 -2
- package/dist/core/slash/steps/slash-execute.js +7 -5
- package/dist/core/slash/strategy.js +1 -1
- package/dist/core/strata/checkpoint/manager.js +16 -10
- package/dist/core/strata/checkpoint/snapshot-create.js +5 -4
- package/dist/core/strata/checkpoint/snapshot-write-tree.js +7 -3
- package/dist/core/strata/engine/shadow-merge-engine.js +4 -2
- package/dist/core/strata/interaction/file-system-provider.js +2 -1
- package/dist/core/strata/layers/file-state-resolver.js +9 -7
- package/dist/core/strata/layers/immutable-git-layer.js +3 -1
- package/dist/core/strata/layers/shadow-driver/readonly-lock.js +8 -6
- package/dist/core/strata/layers/shadow-driver/shadow-driver.js +2 -1
- package/dist/core/strata/layers/worktree.js +9 -10
- package/dist/core/strata/runtime/environment.js +2 -1
- package/dist/core/strata/runtime/synchronizer.js +28 -26
- package/dist/core/streaming/canonical/parts-from-llm-stream-chunk.js +1 -11
- package/dist/core/structured-output/json-extract.js +3 -1
- package/dist/core/structured-output/json-schema-validator.js +1 -13
- package/dist/core/sub-agent/artifacts/store.js +2 -1
- package/dist/core/sub-agent/context-snapshot.js +12 -6
- package/dist/core/sub-agent/controller.js +70 -1
- package/dist/core/sub-agent/core/loop.js +25 -3
- package/dist/core/sub-agent/core/manager.js +343 -117
- package/dist/core/sub-agent/registry-defaults.js +12 -0
- package/dist/core/sub-agent/registry.js +8 -0
- package/dist/core/sub-agent/summary.js +96 -0
- package/dist/core/sub-agent/team.js +98 -0
- package/dist/core/sub-agent/tools/task-await.js +109 -0
- package/dist/core/sub-agent/tools/task-spawn.js +52 -7
- package/dist/core/sub-agent/tools/team.js +92 -0
- package/dist/core/sub-agent/types.js +11 -2
- package/dist/core/target-runtime/profile.js +3 -1
- package/dist/core/tools/audit.js +3 -2
- package/dist/core/tools/budget.js +7 -12
- package/dist/core/tools/builtin/ast.js +144 -0
- package/dist/core/tools/builtin/code-search/backends/powershell.js +3 -1
- package/dist/core/tools/builtin/code-search/backends/rg.js +3 -1
- package/dist/core/tools/builtin/code-search/executor.js +46 -43
- package/dist/core/tools/builtin/code-search/parse/plain-grep.js +3 -1
- package/dist/core/tools/builtin/code-search/parse/rg-json.js +3 -1
- package/dist/core/tools/builtin/fs.js +90 -7
- package/dist/core/tools/builtin/git.js +242 -0
- package/dist/core/tools/builtin/glob.js +79 -0
- package/dist/core/tools/builtin/index.js +53 -111
- package/dist/core/tools/builtin/interaction.js +13 -15
- package/dist/core/tools/builtin/knowledge.js +146 -4
- package/dist/core/tools/builtin/proposal.js +14 -3
- package/dist/core/tools/builtin/verify.js +35 -3
- package/dist/core/tools/capability/executor.js +5 -5
- package/dist/core/tools/headless-payload.js +1 -3
- package/dist/core/tools/mapper.js +8 -42
- package/dist/core/tools/parallel/persistence.js +17 -5
- package/dist/core/tools/parallel/scheduler.js +23 -21
- package/dist/core/tools/permissions/permission-rules.js +69 -115
- package/dist/core/tools/plugins/loader.js +4 -3
- package/dist/core/tools/router.js +112 -58
- package/dist/core/tools/session.js +64 -102
- package/dist/core/tools/streaming/ToolCallAccumulator.js +1 -3
- package/dist/core/tools/tool-visibility.js +2 -1
- package/dist/core/tools/types.js +10 -0
- package/dist/core/types/batch.js +2 -0
- package/dist/core/utils/error.js +79 -0
- package/dist/core/utils/sanitizer.js +5 -2
- package/dist/core/utils/serialize.js +66 -0
- package/dist/core/utils/zod.js +29 -0
- package/dist/core/verification/detect-runner.js +86 -0
- package/dist/core/verification/runner.js +76 -0
- package/dist/core/version.js +3 -1
- package/dist/core/workspace/capabilities.js +3 -2
- package/dist/integrations/langfuse/litellm-langfuse-outcome-reporter.js +9 -8
- package/dist/languages/python/index.js +154 -0
- package/dist/locales/en.js +8 -1
- package/package.json +2 -1
|
@@ -8,7 +8,9 @@ import { CanonicalResponsesEventEmitter, } from '../streaming/canonical/canonica
|
|
|
8
8
|
import { mapLlmStreamChunkToCanonicalStreamParts } from '../streaming/canonical/parts-from-llm-stream-chunk.js';
|
|
9
9
|
import { ArtifactStore } from '../sub-agent/artifacts/store.js';
|
|
10
10
|
import { Phase } from '../types/runtime.js';
|
|
11
|
+
import { extractNetworkCode, extractProvider, extractStatusCode } from '../utils/error.js';
|
|
11
12
|
import { isSafeRelativePath, normalizePath } from '../utils/path.js';
|
|
13
|
+
import { isRecord } from '../utils/serialize.js';
|
|
12
14
|
import { buildHeadlessToolInputPayload } from './headless-payload.js';
|
|
13
15
|
import { toolToOpenAI } from './mapper.js';
|
|
14
16
|
import { InMemoryLockManager } from './parallel/lock-manager.js';
|
|
@@ -17,6 +19,13 @@ import { ParallelScheduler } from './parallel/scheduler.js';
|
|
|
17
19
|
import { isRecoverableToolInputErrorCode } from './recoverable-tool-errors.js';
|
|
18
20
|
import { ToolCallAccumulator } from './streaming/ToolCallAccumulator.js';
|
|
19
21
|
import { resolveVisibleToolSpecs } from './tool-visibility.js';
|
|
22
|
+
function findLast(array, predicate) {
|
|
23
|
+
for (let i = array.length - 1; i >= 0; i--) {
|
|
24
|
+
if (predicate(array[i]))
|
|
25
|
+
return array[i];
|
|
26
|
+
}
|
|
27
|
+
return undefined;
|
|
28
|
+
}
|
|
20
29
|
function safeParseJson(argsText) {
|
|
21
30
|
if (typeof argsText !== 'string') {
|
|
22
31
|
return { ok: true, value: argsText };
|
|
@@ -37,8 +46,9 @@ function safeParseJson(argsText) {
|
|
|
37
46
|
try {
|
|
38
47
|
value = JSON.parse(nested);
|
|
39
48
|
}
|
|
40
|
-
catch {
|
|
49
|
+
catch (error) {
|
|
41
50
|
// Ignore: fall back to the first parse result to preserve observability.
|
|
51
|
+
getLogger().debug(`[ToolSession] Double-decoded JSON parse fallback: ${error instanceof Error ? error.message : String(error)}`);
|
|
42
52
|
}
|
|
43
53
|
}
|
|
44
54
|
}
|
|
@@ -62,7 +72,8 @@ function formatToolResultForModel(result) {
|
|
|
62
72
|
try {
|
|
63
73
|
return JSON.stringify(payload);
|
|
64
74
|
}
|
|
65
|
-
catch {
|
|
75
|
+
catch (error) {
|
|
76
|
+
getLogger().debug(`[ToolSession] Failed to serialize tool result: ${error instanceof Error ? error.message : String(error)}`);
|
|
66
77
|
return JSON.stringify({
|
|
67
78
|
id: result.id,
|
|
68
79
|
toolName: result.toolName,
|
|
@@ -79,7 +90,8 @@ function safeStringifyForAudit(value) {
|
|
|
79
90
|
try {
|
|
80
91
|
return redactJsonString(JSON.stringify(redactValue(value)));
|
|
81
92
|
}
|
|
82
|
-
catch {
|
|
93
|
+
catch (error) {
|
|
94
|
+
getLogger().debug(`[ToolSession] Failed to stringify value for audit: ${error instanceof Error ? error.message : String(error)}`);
|
|
83
95
|
return '[Unserializable]';
|
|
84
96
|
}
|
|
85
97
|
}
|
|
@@ -126,7 +138,7 @@ function isArtifactHandleRecord(value) {
|
|
|
126
138
|
typeof candidate.size === 'number');
|
|
127
139
|
}
|
|
128
140
|
function extractArtifactHandlesFromToolOutput(output) {
|
|
129
|
-
if (!
|
|
141
|
+
if (!isRecord(output)) {
|
|
130
142
|
return {};
|
|
131
143
|
}
|
|
132
144
|
const patchArtifact = isArtifactHandleRecord(output.patchArtifact)
|
|
@@ -144,12 +156,12 @@ function extractRecentReadResult(params) {
|
|
|
144
156
|
if (params.toolName !== 'fs.read' && params.toolName !== 'code.read') {
|
|
145
157
|
return undefined;
|
|
146
158
|
}
|
|
147
|
-
if (!
|
|
159
|
+
if (!isRecord(params.output) || typeof params.output.content !== 'string') {
|
|
148
160
|
return undefined;
|
|
149
161
|
}
|
|
150
162
|
const args = safeParseJson(params.rawArgs);
|
|
151
163
|
const argsValue = args.ok ? args.value : params.rawArgs;
|
|
152
|
-
if (!
|
|
164
|
+
if (!isRecord(argsValue))
|
|
153
165
|
return undefined;
|
|
154
166
|
const file = argsValue.file ?? argsValue.file_path ?? argsValue.filePath ?? argsValue.path;
|
|
155
167
|
if (typeof file !== 'string' || !file.trim())
|
|
@@ -206,7 +218,8 @@ function serializeToolResultOutputForArtifact(output) {
|
|
|
206
218
|
fileExt: 'json',
|
|
207
219
|
};
|
|
208
220
|
}
|
|
209
|
-
catch {
|
|
221
|
+
catch (error) {
|
|
222
|
+
getLogger().debug(`[ToolSession] Failed to serialize tool output for artifact: ${error instanceof Error ? error.message : String(error)}`);
|
|
210
223
|
return undefined;
|
|
211
224
|
}
|
|
212
225
|
}
|
|
@@ -703,7 +716,7 @@ export async function chatWithTools(initialMessages, chatOptions, session) {
|
|
|
703
716
|
tool_calls: assistant.tool_calls,
|
|
704
717
|
});
|
|
705
718
|
const toolCalls = assistant.tool_calls || [];
|
|
706
|
-
if (
|
|
719
|
+
if (toolCalls.length === 0) {
|
|
707
720
|
if (session.llmOutput) {
|
|
708
721
|
emitLlmOutput({
|
|
709
722
|
emit: session.emit,
|
|
@@ -728,7 +741,7 @@ export async function chatWithTools(initialMessages, chatOptions, session) {
|
|
|
728
741
|
message: `Tool calling exceeded maximum rounds (${maxRounds}); continuing without further tool execution`,
|
|
729
742
|
timestamp: new Date(),
|
|
730
743
|
});
|
|
731
|
-
const lastAssistant =
|
|
744
|
+
const lastAssistant = findLast(messages, (m) => m.role === 'assistant');
|
|
732
745
|
if (session.llmOutput && lastAssistant?.content) {
|
|
733
746
|
emitLlmOutput({
|
|
734
747
|
emit: session.emit,
|
|
@@ -740,11 +753,8 @@ export async function chatWithTools(initialMessages, chatOptions, session) {
|
|
|
740
753
|
}
|
|
741
754
|
return lastAssistant || { role: 'assistant', content: '' };
|
|
742
755
|
}
|
|
743
|
-
function isObjectRecord(value) {
|
|
744
|
-
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
745
|
-
}
|
|
746
756
|
function isPlainObject(value) {
|
|
747
|
-
if (!
|
|
757
|
+
if (!isRecord(value))
|
|
748
758
|
return false;
|
|
749
759
|
const proto = Object.getPrototypeOf(value);
|
|
750
760
|
return proto === Object.prototype || proto === null;
|
|
@@ -783,67 +793,13 @@ function coercePlanUpdatePatch(args) {
|
|
|
783
793
|
coercedPatchSource: 'stringified',
|
|
784
794
|
};
|
|
785
795
|
}
|
|
786
|
-
catch {
|
|
796
|
+
catch (error) {
|
|
797
|
+
getLogger().debug(`[ToolSession] Failed to parse plan.update patch JSON: ${error instanceof Error ? error.message : String(error)}`);
|
|
787
798
|
return { args, error: formatPlanUpdatePatchTypeError('string') };
|
|
788
799
|
}
|
|
789
800
|
}
|
|
790
801
|
return { args, error: formatPlanUpdatePatchTypeError(describeValueType(patch)) };
|
|
791
802
|
}
|
|
792
|
-
function unwrapRetryError(err) {
|
|
793
|
-
if (!err || typeof err !== 'object')
|
|
794
|
-
return err;
|
|
795
|
-
const candidate = err;
|
|
796
|
-
if (candidate.lastError)
|
|
797
|
-
return candidate.lastError;
|
|
798
|
-
return err;
|
|
799
|
-
}
|
|
800
|
-
function extractStatusCode(err) {
|
|
801
|
-
const unwrapped = unwrapRetryError(err);
|
|
802
|
-
if (!unwrapped || typeof unwrapped !== 'object')
|
|
803
|
-
return undefined;
|
|
804
|
-
const meta = unwrapped?.meta;
|
|
805
|
-
if (meta && typeof meta === 'object' && typeof meta.statusCode === 'number') {
|
|
806
|
-
return meta.statusCode;
|
|
807
|
-
}
|
|
808
|
-
const statusCode = unwrapped?.statusCode;
|
|
809
|
-
if (typeof statusCode === 'number')
|
|
810
|
-
return statusCode;
|
|
811
|
-
const response = unwrapped?.response;
|
|
812
|
-
if (response && typeof response === 'object' && typeof response.status === 'number') {
|
|
813
|
-
return response.status;
|
|
814
|
-
}
|
|
815
|
-
return undefined;
|
|
816
|
-
}
|
|
817
|
-
function extractNetworkCode(err) {
|
|
818
|
-
const unwrapped = unwrapRetryError(err);
|
|
819
|
-
if (!unwrapped || typeof unwrapped !== 'object')
|
|
820
|
-
return undefined;
|
|
821
|
-
const code = unwrapped?.code;
|
|
822
|
-
if (typeof code === 'string')
|
|
823
|
-
return code;
|
|
824
|
-
const cause = unwrapped?.cause;
|
|
825
|
-
if (cause && typeof cause === 'object' && typeof cause.code === 'string') {
|
|
826
|
-
return cause.code;
|
|
827
|
-
}
|
|
828
|
-
const meta = unwrapped?.meta;
|
|
829
|
-
if (meta && typeof meta === 'object' && typeof meta.causeName === 'string') {
|
|
830
|
-
return meta.causeName;
|
|
831
|
-
}
|
|
832
|
-
return undefined;
|
|
833
|
-
}
|
|
834
|
-
function extractProvider(err) {
|
|
835
|
-
const unwrapped = unwrapRetryError(err);
|
|
836
|
-
if (!unwrapped || typeof unwrapped !== 'object')
|
|
837
|
-
return undefined;
|
|
838
|
-
const meta = unwrapped?.meta;
|
|
839
|
-
if (meta && typeof meta === 'object' && typeof meta.provider === 'string') {
|
|
840
|
-
return meta.provider;
|
|
841
|
-
}
|
|
842
|
-
const provider = unwrapped?.provider;
|
|
843
|
-
if (typeof provider === 'string')
|
|
844
|
-
return provider;
|
|
845
|
-
return undefined;
|
|
846
|
-
}
|
|
847
803
|
const ENABLE_TOOL_ARG_REPAIR = process.env.SALMONLOOP_ENABLE_TOOL_ARG_REPAIR === '1' ||
|
|
848
804
|
process.env.SALMONLOOP_ENABLE_TOOL_ARG_REPAIR === 'true';
|
|
849
805
|
const SAFE_INFERRED_EXTENSIONS = new Set([
|
|
@@ -901,7 +857,7 @@ function inferHighConfidenceFiles(instruction) {
|
|
|
901
857
|
return Array.from(new Set(candidates));
|
|
902
858
|
}
|
|
903
859
|
function extractInstructionText(messages) {
|
|
904
|
-
const lastUser =
|
|
860
|
+
const lastUser = findLast(messages, (m) => m.role === 'user');
|
|
905
861
|
const text = typeof lastUser?.content === 'string' ? lastUser.content : '';
|
|
906
862
|
if (!text)
|
|
907
863
|
return '';
|
|
@@ -921,7 +877,7 @@ function prepareToolCallRequests(calls) {
|
|
|
921
877
|
async function runToolExecutionPlan(params) {
|
|
922
878
|
const scheduler = new ParallelScheduler(params.session.toolstack.router, new InMemoryLockManager());
|
|
923
879
|
const runSignal = params.signal ?? new AbortController().signal;
|
|
924
|
-
let result =
|
|
880
|
+
let result = await scheduler.run(params.plan, { ...params.session.runtime, phase: params.phase }, runSignal);
|
|
925
881
|
const persistEnabled = process.env.NODE_ENV !== 'test';
|
|
926
882
|
const persistenceRoot = params.session.runtime.persistenceRoot || params.session.runtime.repoRoot;
|
|
927
883
|
if (persistEnabled) {
|
|
@@ -943,10 +899,10 @@ async function runToolExecutionPlan(params) {
|
|
|
943
899
|
await Promise.all(result.blockedApprovals.map(async (a) => {
|
|
944
900
|
await waitForAuthorization?.(a.nodeId, runSignal);
|
|
945
901
|
}));
|
|
946
|
-
result =
|
|
902
|
+
result = await scheduler.run(params.plan, { ...params.session.runtime, phase: params.phase }, runSignal, {
|
|
947
903
|
initialResults: result.nodeResults,
|
|
948
904
|
resumeBlockedApprovals: true,
|
|
949
|
-
})
|
|
905
|
+
});
|
|
950
906
|
if (persistEnabled) {
|
|
951
907
|
await PlanPersistence.save(persistenceRoot, params.plan, result, {
|
|
952
908
|
repoRoot: params.session.runtime.repoRoot,
|
|
@@ -983,12 +939,14 @@ function applyStrictToolOutputSchemaValidation(params) {
|
|
|
983
939
|
}
|
|
984
940
|
async function executeToolCalls(session, phase, round, calls, messages, signal) {
|
|
985
941
|
const prepared = prepareToolCallRequests(calls);
|
|
942
|
+
const specByName = new Map();
|
|
943
|
+
for (const spec of session.toolstack.registry.listAll()) {
|
|
944
|
+
specByName.set(spec.name, spec);
|
|
945
|
+
}
|
|
986
946
|
const bucketByCallId = new Map();
|
|
987
947
|
const preparedCounts = { regular: 0, agent: 0 };
|
|
988
948
|
for (const item of prepared) {
|
|
989
|
-
const spec = typeof item.toolName === 'string'
|
|
990
|
-
? session.toolstack.registry.listAll().find((s) => s.name === item.toolName)
|
|
991
|
-
: undefined;
|
|
949
|
+
const spec = typeof item.toolName === 'string' ? specByName.get(item.toolName) : undefined;
|
|
992
950
|
const bucket = spec?.intent === 'AGENT' ? 'agent' : 'regular';
|
|
993
951
|
bucketByCallId.set(item.callId, bucket);
|
|
994
952
|
preparedCounts[bucket]++;
|
|
@@ -1031,7 +989,7 @@ async function executeToolCalls(session, phase, round, calls, messages, signal)
|
|
|
1031
989
|
ENABLE_TOOL_ARG_REPAIR &&
|
|
1032
990
|
phase === Phase.EXPLORE &&
|
|
1033
991
|
normalizedToolName === 'fs.read' &&
|
|
1034
|
-
|
|
992
|
+
isRecord(argsValue) &&
|
|
1035
993
|
typeof argsValue.file !== 'string') {
|
|
1036
994
|
const instruction = extractInstructionText(messages);
|
|
1037
995
|
const inferred = inferHighConfidenceFiles(instruction);
|
|
@@ -1040,7 +998,7 @@ async function executeToolCalls(session, phase, round, calls, messages, signal)
|
|
|
1040
998
|
}
|
|
1041
999
|
}
|
|
1042
1000
|
let planUpdatePatchError;
|
|
1043
|
-
if (parsedArgsOk && normalizedToolName === 'plan.update' &&
|
|
1001
|
+
if (parsedArgsOk && normalizedToolName === 'plan.update' && isRecord(argsValue)) {
|
|
1044
1002
|
const patchGuard = coercePlanUpdatePatch(argsValue);
|
|
1045
1003
|
argsValue = patchGuard.args;
|
|
1046
1004
|
if (patchGuard.coercedPatchSource) {
|
|
@@ -1056,9 +1014,7 @@ async function executeToolCalls(session, phase, round, calls, messages, signal)
|
|
|
1056
1014
|
const input = session.eventPayload?.includeToolInput && parsedArgsOk
|
|
1057
1015
|
? buildHeadlessToolInputPayload(argsValue)
|
|
1058
1016
|
: undefined;
|
|
1059
|
-
const spec = typeof toolName === 'string'
|
|
1060
|
-
? session.toolstack.registry.listAll().find((s) => s.name === toolName)
|
|
1061
|
-
: undefined;
|
|
1017
|
+
const spec = typeof toolName === 'string' ? specByName.get(toolName) : undefined;
|
|
1062
1018
|
if (typeof toolName === 'string') {
|
|
1063
1019
|
session.emit?.({
|
|
1064
1020
|
type: 'log',
|
|
@@ -1177,7 +1133,8 @@ async function executeToolCalls(session, phase, round, calls, messages, signal)
|
|
|
1177
1133
|
};
|
|
1178
1134
|
const patchCoercionSource = patchCoercionByCallId.get(callId);
|
|
1179
1135
|
if (patchCoercionSource) {
|
|
1180
|
-
parsedAuditEntry.coercedPatchSource =
|
|
1136
|
+
parsedAuditEntry.coercedPatchSource =
|
|
1137
|
+
patchCoercionSource;
|
|
1181
1138
|
}
|
|
1182
1139
|
session.toolCallingAudit?.event(parsedAuditEntry);
|
|
1183
1140
|
if (planUpdatePatchError) {
|
|
@@ -1269,9 +1226,10 @@ async function executeToolCalls(session, phase, round, calls, messages, signal)
|
|
|
1269
1226
|
if (result.status !== 'ok' &&
|
|
1270
1227
|
result.error?.code === 'INTERRUPT_REQUIRED' &&
|
|
1271
1228
|
result.meta?.interrupt) {
|
|
1272
|
-
const err = new Error(result.error.message || 'Interrupt required')
|
|
1273
|
-
|
|
1274
|
-
|
|
1229
|
+
const err = Object.assign(new Error(result.error.message || 'Interrupt required'), {
|
|
1230
|
+
code: 'INTERRUPT_REQUIRED',
|
|
1231
|
+
interrupt: result.meta.interrupt,
|
|
1232
|
+
});
|
|
1275
1233
|
throw err;
|
|
1276
1234
|
}
|
|
1277
1235
|
if (result.status !== 'ok') {
|
|
@@ -1295,26 +1253,30 @@ async function executeToolCalls(session, phase, round, calls, messages, signal)
|
|
|
1295
1253
|
};
|
|
1296
1254
|
const patchCoercionSource = patchCoercionByCallId.get(callId);
|
|
1297
1255
|
if (patchCoercionSource) {
|
|
1298
|
-
errorAuditEntry.coercedPatchSource =
|
|
1256
|
+
errorAuditEntry.coercedPatchSource =
|
|
1257
|
+
patchCoercionSource;
|
|
1299
1258
|
}
|
|
1300
1259
|
session.toolCallingAudit?.event(errorAuditEntry);
|
|
1301
1260
|
}
|
|
1302
1261
|
else {
|
|
1303
|
-
const toolResultOutputOk =
|
|
1262
|
+
const toolResultOutputOk = isRecord(result.output) && typeof result.output.ok === 'boolean'
|
|
1304
1263
|
? result.output.ok
|
|
1305
1264
|
: undefined;
|
|
1306
1265
|
const artifacts = extractArtifactHandlesFromToolOutput(result.output);
|
|
1307
|
-
const
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1266
|
+
const resolvedToolName = typeof toolName === 'string' ? toolName : 'unknown';
|
|
1267
|
+
const [recentReadArtifact, toolResultPreviewArtifact] = await Promise.all([
|
|
1268
|
+
persistRecentReadArtifact({
|
|
1269
|
+
toolName: resolvedToolName,
|
|
1270
|
+
rawArgs,
|
|
1271
|
+
output: result.output,
|
|
1272
|
+
}),
|
|
1273
|
+
persistToolResultPreviewArtifact({
|
|
1274
|
+
toolName: resolvedToolName,
|
|
1275
|
+
output: result.output,
|
|
1276
|
+
summary: result.summary,
|
|
1277
|
+
outputSummary: result.outputSummary,
|
|
1278
|
+
}),
|
|
1279
|
+
]);
|
|
1318
1280
|
session.toolCallingAudit?.event({
|
|
1319
1281
|
timestamp: new Date().toISOString(),
|
|
1320
1282
|
phase,
|
|
@@ -1410,9 +1372,9 @@ export async function chatWithToolsStreaming(initialMessages, chatOptions, sessi
|
|
|
1410
1372
|
statusCode: extractStatusCode(e),
|
|
1411
1373
|
networkCode: extractNetworkCode(e),
|
|
1412
1374
|
errorName: e instanceof Error ? e.name : 'UnknownError',
|
|
1413
|
-
errorCode: typeof e
|
|
1375
|
+
errorCode: isRecord(e) && typeof e.llmCode === 'string'
|
|
1414
1376
|
? e.llmCode
|
|
1415
|
-
: typeof e
|
|
1377
|
+
: isRecord(e) && typeof e.code === 'string'
|
|
1416
1378
|
? e.code
|
|
1417
1379
|
: undefined,
|
|
1418
1380
|
}, { source: 'llm', severity: 'low', scope: 'session', phase });
|
|
@@ -1470,7 +1432,7 @@ export async function chatWithToolsStreaming(initialMessages, chatOptions, sessi
|
|
|
1470
1432
|
}, { source: 'llm', severity: 'low', scope: 'session', phase });
|
|
1471
1433
|
messages.push(assistant);
|
|
1472
1434
|
const calls = assistant.tool_calls || [];
|
|
1473
|
-
if (
|
|
1435
|
+
if (calls.length === 0) {
|
|
1474
1436
|
if (session.llmOutput) {
|
|
1475
1437
|
emitLlmStreamEnd({
|
|
1476
1438
|
emit: session.emit,
|
|
@@ -1509,7 +1471,7 @@ export async function chatWithToolsStreaming(initialMessages, chatOptions, sessi
|
|
|
1509
1471
|
message: `Tool calling exceeded maximum rounds (${maxRounds}); continuing without further tool execution`,
|
|
1510
1472
|
timestamp: new Date(),
|
|
1511
1473
|
});
|
|
1512
|
-
const lastAssistant =
|
|
1474
|
+
const lastAssistant = findLast(messages, (m) => m.role === 'assistant');
|
|
1513
1475
|
return lastAssistant || { role: 'assistant', content: '' };
|
|
1514
1476
|
}
|
|
1515
1477
|
//# sourceMappingURL=session.js.map
|
|
@@ -46,7 +46,8 @@ export function resolvePhaseVisibleTools(params) {
|
|
|
46
46
|
export function resolveVisibleToolSpecs(params) {
|
|
47
47
|
if (!params.toolstack)
|
|
48
48
|
return [];
|
|
49
|
-
const
|
|
49
|
+
const { toolstack } = params;
|
|
50
|
+
const allowedSpecs = toolstack.registry.listAll().filter((spec) => toolstack.policy.decide(params.phase, spec, {
|
|
50
51
|
worktreeRoot: params.worktreeRoot,
|
|
51
52
|
flowMode: params.flowMode,
|
|
52
53
|
}).allowed);
|
package/dist/core/tools/types.js
CHANGED
|
@@ -7,4 +7,14 @@ export const TOOL_INTENTS = [
|
|
|
7
7
|
'AGENT',
|
|
8
8
|
'REPORT',
|
|
9
9
|
];
|
|
10
|
+
/**
|
|
11
|
+
* Type-safe helper to create a fully-formed ToolSpec from a spec definition and executor.
|
|
12
|
+
* Eliminates the `{ ...spec, executor: exec as any }` boilerplate pattern.
|
|
13
|
+
*
|
|
14
|
+
* The executor parameter accepts a superset of ToolRuntimeCtx (e.g., with phase narrowed
|
|
15
|
+
* to non-optional) to support tools that require the router-injected phase field.
|
|
16
|
+
*/
|
|
17
|
+
export function defineTool(spec, executor) {
|
|
18
|
+
return { ...spec, executor: executor };
|
|
19
|
+
}
|
|
10
20
|
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { isRecord } from './serialize.js';
|
|
2
|
+
/**
|
|
3
|
+
* Extract a human-readable error message from an unknown thrown value.
|
|
4
|
+
* Handles Error instances, strings, and falls back to String(value).
|
|
5
|
+
*/
|
|
6
|
+
export function errorMessage(error) {
|
|
7
|
+
if (error instanceof Error)
|
|
8
|
+
return error.message;
|
|
9
|
+
if (typeof error === 'string')
|
|
10
|
+
return error;
|
|
11
|
+
return String(error);
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Unwrap retry-style errors that wrap the real error in a `lastError` property.
|
|
15
|
+
*/
|
|
16
|
+
export function unwrapRetryError(err) {
|
|
17
|
+
if (!isRecord(err))
|
|
18
|
+
return err;
|
|
19
|
+
if (err.lastError)
|
|
20
|
+
return err.lastError;
|
|
21
|
+
return err;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Extract an HTTP-style status code from an error object.
|
|
25
|
+
* Checks: meta.statusCode, statusCode, response.status
|
|
26
|
+
*/
|
|
27
|
+
export function extractStatusCode(err) {
|
|
28
|
+
const unwrapped = unwrapRetryError(err);
|
|
29
|
+
if (!isRecord(unwrapped))
|
|
30
|
+
return undefined;
|
|
31
|
+
const meta = unwrapped.meta;
|
|
32
|
+
if (isRecord(meta) && typeof meta.statusCode === 'number') {
|
|
33
|
+
return meta.statusCode;
|
|
34
|
+
}
|
|
35
|
+
if (typeof unwrapped.statusCode === 'number')
|
|
36
|
+
return unwrapped.statusCode;
|
|
37
|
+
const response = unwrapped.response;
|
|
38
|
+
if (isRecord(response) && typeof response.status === 'number') {
|
|
39
|
+
return response.status;
|
|
40
|
+
}
|
|
41
|
+
return undefined;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Extract a network error code from an error object.
|
|
45
|
+
* Checks: code, cause.code, meta.causeName
|
|
46
|
+
*/
|
|
47
|
+
export function extractNetworkCode(err) {
|
|
48
|
+
const unwrapped = unwrapRetryError(err);
|
|
49
|
+
if (!isRecord(unwrapped))
|
|
50
|
+
return undefined;
|
|
51
|
+
if (typeof unwrapped.code === 'string')
|
|
52
|
+
return unwrapped.code;
|
|
53
|
+
const cause = unwrapped.cause;
|
|
54
|
+
if (isRecord(cause) && typeof cause.code === 'string') {
|
|
55
|
+
return cause.code;
|
|
56
|
+
}
|
|
57
|
+
const meta = unwrapped.meta;
|
|
58
|
+
if (isRecord(meta) && typeof meta.causeName === 'string') {
|
|
59
|
+
return meta.causeName;
|
|
60
|
+
}
|
|
61
|
+
return undefined;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Extract a provider name from an error object.
|
|
65
|
+
* Checks: meta.provider, provider
|
|
66
|
+
*/
|
|
67
|
+
export function extractProvider(err) {
|
|
68
|
+
const unwrapped = unwrapRetryError(err);
|
|
69
|
+
if (!isRecord(unwrapped))
|
|
70
|
+
return undefined;
|
|
71
|
+
const meta = unwrapped.meta;
|
|
72
|
+
if (isRecord(meta) && typeof meta.provider === 'string') {
|
|
73
|
+
return meta.provider;
|
|
74
|
+
}
|
|
75
|
+
if (typeof unwrapped.provider === 'string')
|
|
76
|
+
return unwrapped.provider;
|
|
77
|
+
return undefined;
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=error.js.map
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { getLogger } from '../observability/logger.js';
|
|
1
2
|
/**
|
|
2
3
|
* Sanitizes any error input (object, string, or mixed) to prevent leakage
|
|
3
4
|
* of sensitive technical data like Zod dumps or stack traces.
|
|
@@ -10,7 +11,8 @@ export function sanitizeErrorMessage(err) {
|
|
|
10
11
|
try {
|
|
11
12
|
msg = err instanceof Error ? err.message : typeof err === 'string' ? err : JSON.stringify(err);
|
|
12
13
|
}
|
|
13
|
-
catch {
|
|
14
|
+
catch (error) {
|
|
15
|
+
getLogger().debug(`[Sanitizer] Failed to convert error to string: ${error instanceof Error ? error.message : String(error)}`);
|
|
14
16
|
msg = String(err);
|
|
15
17
|
}
|
|
16
18
|
// 2. Strict Whitelist Detection
|
|
@@ -87,7 +89,8 @@ export function sanitizeObject(obj, maxDepth = MAX_DEPTH, depth = 0) {
|
|
|
87
89
|
try {
|
|
88
90
|
result[key] = sanitizeObject(value, maxDepth, depth + 1);
|
|
89
91
|
}
|
|
90
|
-
catch {
|
|
92
|
+
catch (error) {
|
|
93
|
+
getLogger().debug(`[Sanitizer] Circular reference detected during object sanitization: ${error instanceof Error ? error.message : String(error)}`);
|
|
91
94
|
result[key] = '[CIRCULAR]';
|
|
92
95
|
}
|
|
93
96
|
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { getLogger } from '../observability/logger.js';
|
|
2
|
+
/**
|
|
3
|
+
* Safely serialize a value to JSON string.
|
|
4
|
+
* Returns '[Unserializable]' if JSON.stringify throws and String() also fails.
|
|
5
|
+
*/
|
|
6
|
+
export function safeStringify(value, options) {
|
|
7
|
+
try {
|
|
8
|
+
const raw = JSON.stringify(value, null, options?.indent);
|
|
9
|
+
if (options?.maxLength && raw.length > options.maxLength) {
|
|
10
|
+
return `${raw.slice(0, options.maxLength)}...`;
|
|
11
|
+
}
|
|
12
|
+
return raw;
|
|
13
|
+
}
|
|
14
|
+
catch (error) {
|
|
15
|
+
getLogger().debug(`[Serialize] JSON.stringify failed, falling back to String(): ${error instanceof Error ? error.message : String(error)}`);
|
|
16
|
+
try {
|
|
17
|
+
return String(value);
|
|
18
|
+
}
|
|
19
|
+
catch (innerError) {
|
|
20
|
+
getLogger().debug(`[Serialize] String() conversion also failed: ${innerError instanceof Error ? innerError.message : String(innerError)}`);
|
|
21
|
+
return '[Unserializable]';
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Type guard: narrow an unknown value to Record<string, unknown>.
|
|
27
|
+
* Returns false for arrays, primitives, null, and undefined.
|
|
28
|
+
*/
|
|
29
|
+
export function isRecord(value) {
|
|
30
|
+
return Boolean(value && typeof value === 'object' && !Array.isArray(value));
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Narrow an unknown value to a Record<string, unknown>.
|
|
34
|
+
* Returns an empty object for non-object inputs (arrays, primitives, null, undefined).
|
|
35
|
+
*/
|
|
36
|
+
export function asRecord(value) {
|
|
37
|
+
return isRecord(value) ? value : {};
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Extract a string value from a record by key.
|
|
41
|
+
* Returns null if the key doesn't exist or the value isn't a string.
|
|
42
|
+
*/
|
|
43
|
+
export function getString(record, key) {
|
|
44
|
+
const value = record[key];
|
|
45
|
+
return typeof value === 'string' ? value : null;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Extract a nested record from a record by key.
|
|
49
|
+
* Returns null if the key doesn't exist or the value isn't a record.
|
|
50
|
+
*/
|
|
51
|
+
export function getRecord(record, key) {
|
|
52
|
+
const value = record[key];
|
|
53
|
+
return isRecord(value) ? value : null;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Extract a human-readable error message from an unknown thrown value.
|
|
57
|
+
* Handles Error instances, strings, and falls back to String(value).
|
|
58
|
+
*/
|
|
59
|
+
export function errorMessage(error) {
|
|
60
|
+
if (error instanceof Error)
|
|
61
|
+
return error.message;
|
|
62
|
+
if (typeof error === 'string')
|
|
63
|
+
return error;
|
|
64
|
+
return String(error);
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=serialize.js.map
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
/**
|
|
3
|
+
* Unwrap Zod wrapper types (ZodPipe, ZodOptional, ZodNullable, ZodDefault)
|
|
4
|
+
* to get the underlying schema. Useful for schema generation and hint building.
|
|
5
|
+
*/
|
|
6
|
+
export function unwrapZodSchema(schema) {
|
|
7
|
+
let current = schema;
|
|
8
|
+
for (let depth = 0; depth < 20; depth++) {
|
|
9
|
+
if (current instanceof z.ZodPipe) {
|
|
10
|
+
current = current.def.out;
|
|
11
|
+
continue;
|
|
12
|
+
}
|
|
13
|
+
if (current instanceof z.ZodOptional) {
|
|
14
|
+
current = current.def.innerType;
|
|
15
|
+
continue;
|
|
16
|
+
}
|
|
17
|
+
if (current instanceof z.ZodNullable) {
|
|
18
|
+
current = current.def.innerType;
|
|
19
|
+
continue;
|
|
20
|
+
}
|
|
21
|
+
if (current instanceof z.ZodDefault) {
|
|
22
|
+
current = current.def.innerType;
|
|
23
|
+
continue;
|
|
24
|
+
}
|
|
25
|
+
break;
|
|
26
|
+
}
|
|
27
|
+
return current;
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=zod.js.map
|