@namzu/sdk 32.0.0 → 33.1.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/CHANGELOG.md +157 -0
- package/dist/authorization/gate.d.ts +1 -1
- package/dist/authorization/gate.js +1 -1
- package/dist/bridge/a2a/mapper.d.ts.map +1 -1
- package/dist/bridge/a2a/mapper.js +13 -0
- package/dist/bridge/a2a/mapper.js.map +1 -1
- package/dist/bridge/sse/mapper.d.ts.map +1 -1
- package/dist/bridge/sse/mapper.js +3 -0
- package/dist/bridge/sse/mapper.js.map +1 -1
- package/dist/connector/index.d.ts +1 -1
- package/dist/connector/index.d.ts.map +1 -1
- package/dist/connector/index.js +1 -1
- package/dist/connector/index.js.map +1 -1
- package/dist/connector/mcp/adapter.d.ts.map +1 -1
- package/dist/connector/mcp/adapter.js +71 -16
- package/dist/connector/mcp/adapter.js.map +1 -1
- package/dist/connector/mcp/client.d.ts.map +1 -1
- package/dist/connector/mcp/client.js +3 -2
- package/dist/connector/mcp/client.js.map +1 -1
- package/dist/connector/mcp/http-redirect.d.ts +17 -0
- package/dist/connector/mcp/http-redirect.d.ts.map +1 -0
- package/dist/connector/mcp/http-redirect.js +31 -0
- package/dist/connector/mcp/http-redirect.js.map +1 -0
- package/dist/connector/mcp/http-sse.d.ts.map +1 -1
- package/dist/connector/mcp/http-sse.js +5 -0
- package/dist/connector/mcp/http-sse.js.map +1 -1
- package/dist/connector/mcp/image-admission.d.ts +16 -0
- package/dist/connector/mcp/image-admission.d.ts.map +1 -0
- package/dist/connector/mcp/image-admission.js +288 -0
- package/dist/connector/mcp/image-admission.js.map +1 -0
- package/dist/connector/mcp/stdio.d.ts +13 -0
- package/dist/connector/mcp/stdio.d.ts.map +1 -1
- package/dist/connector/mcp/stdio.js +66 -23
- package/dist/connector/mcp/stdio.js.map +1 -1
- package/dist/connector/mcp/streamable-http.d.ts.map +1 -1
- package/dist/connector/mcp/streamable-http.js +3 -0
- package/dist/connector/mcp/streamable-http.js.map +1 -1
- package/dist/constants/tools/index.js +1 -1
- package/dist/constants/tools/index.js.map +1 -1
- package/dist/execution/base.d.ts +13 -0
- package/dist/execution/base.d.ts.map +1 -1
- package/dist/execution/base.js +103 -8
- package/dist/execution/base.js.map +1 -1
- package/dist/execution/errors.d.ts +12 -0
- package/dist/execution/errors.d.ts.map +1 -0
- package/dist/execution/errors.js +21 -0
- package/dist/execution/errors.js.map +1 -0
- package/dist/execution/factory.d.ts.map +1 -1
- package/dist/execution/factory.js +1 -0
- package/dist/execution/factory.js.map +1 -1
- package/dist/execution/hybrid.d.ts +5 -0
- package/dist/execution/hybrid.d.ts.map +1 -1
- package/dist/execution/hybrid.js +36 -16
- package/dist/execution/hybrid.js.map +1 -1
- package/dist/execution/index.d.ts +1 -0
- package/dist/execution/index.d.ts.map +1 -1
- package/dist/execution/index.js +1 -0
- package/dist/execution/index.js.map +1 -1
- package/dist/execution/local.d.ts +13 -0
- package/dist/execution/local.d.ts.map +1 -1
- package/dist/execution/local.js +145 -19
- package/dist/execution/local.js.map +1 -1
- package/dist/execution/output.d.ts +27 -0
- package/dist/execution/output.d.ts.map +1 -0
- package/dist/execution/output.js +105 -0
- package/dist/execution/output.js.map +1 -0
- package/dist/execution/remote.d.ts +26 -2
- package/dist/execution/remote.d.ts.map +1 -1
- package/dist/execution/remote.js +86 -15
- package/dist/execution/remote.js.map +1 -1
- package/dist/plugin/lifecycle.d.ts.map +1 -1
- package/dist/plugin/lifecycle.js +9 -3
- package/dist/plugin/lifecycle.js.map +1 -1
- package/dist/process/kill-tree.d.ts +11 -13
- package/dist/process/kill-tree.d.ts.map +1 -1
- package/dist/process/kill-tree.js +11 -13
- package/dist/process/kill-tree.js.map +1 -1
- package/dist/provider/capabilities.d.ts +2 -0
- package/dist/provider/capabilities.d.ts.map +1 -1
- package/dist/provider/capabilities.js +6 -0
- package/dist/provider/capabilities.js.map +1 -1
- package/dist/provider/fallback.d.ts.map +1 -1
- package/dist/provider/fallback.js +31 -0
- package/dist/provider/fallback.js.map +1 -1
- package/dist/provider/idle-timeout.d.ts.map +1 -1
- package/dist/provider/idle-timeout.js +5 -0
- package/dist/provider/idle-timeout.js.map +1 -1
- package/dist/provider/retry.d.ts.map +1 -1
- package/dist/provider/retry.js +5 -0
- package/dist/provider/retry.js.map +1 -1
- package/dist/public-runtime.d.ts +2 -2
- package/dist/public-runtime.d.ts.map +1 -1
- package/dist/public-runtime.js +2 -2
- package/dist/public-runtime.js.map +1 -1
- package/dist/registry/tool/execute.d.ts +7 -1
- package/dist/registry/tool/execute.d.ts.map +1 -1
- package/dist/registry/tool/execute.js +201 -54
- package/dist/registry/tool/execute.js.map +1 -1
- package/dist/run/command-gate.d.ts.map +1 -1
- package/dist/run/command-gate.js +11 -0
- package/dist/run/command-gate.js.map +1 -1
- package/dist/run/workspace-fingerprint.d.ts +4 -4
- package/dist/run/workspace-fingerprint.d.ts.map +1 -1
- package/dist/run/workspace-fingerprint.js +6 -4
- package/dist/run/workspace-fingerprint.js.map +1 -1
- package/dist/runtime/bidi/index.d.ts +1 -1
- package/dist/runtime/bidi/index.d.ts.map +1 -1
- package/dist/runtime/bidi/index.js +1 -1
- package/dist/runtime/bidi/index.js.map +1 -1
- package/dist/runtime/bidi/session.d.ts +19 -0
- package/dist/runtime/bidi/session.d.ts.map +1 -1
- package/dist/runtime/bidi/session.js +150 -26
- package/dist/runtime/bidi/session.js.map +1 -1
- package/dist/runtime/query/executor.d.ts +43 -1
- package/dist/runtime/query/executor.d.ts.map +1 -1
- package/dist/runtime/query/executor.js +626 -161
- package/dist/runtime/query/executor.js.map +1 -1
- package/dist/runtime/query/index.d.ts +3 -1
- package/dist/runtime/query/index.d.ts.map +1 -1
- package/dist/runtime/query/index.js +48 -4
- package/dist/runtime/query/index.js.map +1 -1
- package/dist/runtime/query/iteration/index.d.ts +10 -0
- package/dist/runtime/query/iteration/index.d.ts.map +1 -1
- package/dist/runtime/query/iteration/index.js +67 -0
- package/dist/runtime/query/iteration/index.js.map +1 -1
- package/dist/runtime/query/iteration/phases/context.d.ts +5 -0
- package/dist/runtime/query/iteration/phases/context.d.ts.map +1 -1
- package/dist/runtime/query/iteration/phases/context.js.map +1 -1
- package/dist/runtime/query/iteration/phases/tool-review.d.ts.map +1 -1
- package/dist/runtime/query/iteration/phases/tool-review.js +84 -22
- package/dist/runtime/query/iteration/phases/tool-review.js.map +1 -1
- package/dist/runtime/query/request-rich-content.d.ts.map +1 -1
- package/dist/runtime/query/request-rich-content.js +33 -13
- package/dist/runtime/query/request-rich-content.js.map +1 -1
- package/dist/runtime/query/result.d.ts.map +1 -1
- package/dist/runtime/query/result.js +25 -22
- package/dist/runtime/query/result.js.map +1 -1
- package/dist/runtime/query/resume-pending.d.ts +5 -1
- package/dist/runtime/query/resume-pending.d.ts.map +1 -1
- package/dist/runtime/query/resume-pending.js +66 -1
- package/dist/runtime/query/resume-pending.js.map +1 -1
- package/dist/runtime/query/tool-output-budget.d.ts.map +1 -1
- package/dist/runtime/query/tool-output-budget.js +45 -16
- package/dist/runtime/query/tool-output-budget.js.map +1 -1
- package/dist/runtime/query/tooling.d.ts +6 -0
- package/dist/runtime/query/tooling.d.ts.map +1 -1
- package/dist/runtime/query/tooling.js +4 -0
- package/dist/runtime/query/tooling.js.map +1 -1
- package/dist/sandbox/provider/local.d.ts.map +1 -1
- package/dist/sandbox/provider/local.js +193 -41
- package/dist/sandbox/provider/local.js.map +1 -1
- package/dist/scheduler/delegating.d.ts +2 -1
- package/dist/scheduler/delegating.d.ts.map +1 -1
- package/dist/scheduler/delegating.js +6 -5
- package/dist/scheduler/delegating.js.map +1 -1
- package/dist/scheduler/local.d.ts +2 -1
- package/dist/scheduler/local.d.ts.map +1 -1
- package/dist/scheduler/local.js +2 -2
- package/dist/scheduler/local.js.map +1 -1
- package/dist/session/workspace/driver.d.ts +12 -4
- package/dist/session/workspace/driver.d.ts.map +1 -1
- package/dist/session/workspace/git-worktree.d.ts +17 -3
- package/dist/session/workspace/git-worktree.d.ts.map +1 -1
- package/dist/session/workspace/git-worktree.js +153 -34
- package/dist/session/workspace/git-worktree.js.map +1 -1
- package/dist/skills/registry.d.ts +15 -0
- package/dist/skills/registry.d.ts.map +1 -1
- package/dist/skills/registry.js +33 -0
- package/dist/skills/registry.js.map +1 -1
- package/dist/tools/builtins/computer-use.d.ts.map +1 -1
- package/dist/tools/builtins/computer-use.js +76 -2
- package/dist/tools/builtins/computer-use.js.map +1 -1
- package/dist/tools/builtins/run-code.d.ts.map +1 -1
- package/dist/tools/builtins/run-code.js +9 -11
- package/dist/tools/builtins/run-code.js.map +1 -1
- package/dist/tools/builtins/skill.d.ts +2 -1
- package/dist/tools/builtins/skill.d.ts.map +1 -1
- package/dist/tools/builtins/skill.js +250 -6
- package/dist/tools/builtins/skill.js.map +1 -1
- package/dist/tools/coordinator/agent.d.ts.map +1 -1
- package/dist/tools/coordinator/agent.js +100 -30
- package/dist/tools/coordinator/agent.js.map +1 -1
- package/dist/types/agent/manager.d.ts +1 -1
- package/dist/types/agent/manager.d.ts.map +1 -1
- package/dist/types/agent/scheduler.d.ts +10 -1
- package/dist/types/agent/scheduler.d.ts.map +1 -1
- package/dist/types/authorization/index.d.ts +12 -12
- package/dist/types/bidi/index.d.ts +19 -2
- package/dist/types/bidi/index.d.ts.map +1 -1
- package/dist/types/computer-use/index.d.ts +18 -0
- package/dist/types/computer-use/index.d.ts.map +1 -1
- package/dist/types/connector/execution-context.d.ts +3 -1
- package/dist/types/connector/execution-context.d.ts.map +1 -1
- package/dist/types/errors/catalog.d.ts.map +1 -1
- package/dist/types/errors/catalog.js +13 -6
- package/dist/types/errors/catalog.js.map +1 -1
- package/dist/types/errors/index.d.ts.map +1 -1
- package/dist/types/errors/index.js +21 -8
- package/dist/types/errors/index.js.map +1 -1
- package/dist/types/execution/index.d.ts +43 -1
- package/dist/types/execution/index.d.ts.map +1 -1
- package/dist/types/hitl/index.d.ts +11 -0
- package/dist/types/hitl/index.d.ts.map +1 -1
- package/dist/types/hitl/index.js.map +1 -1
- package/dist/types/message/index.d.ts +1 -1
- package/dist/types/message/index.d.ts.map +1 -1
- package/dist/types/message/index.js +2 -1
- package/dist/types/message/index.js.map +1 -1
- package/dist/types/plugin/index.d.ts +14 -1
- package/dist/types/plugin/index.d.ts.map +1 -1
- package/dist/types/plugin/index.js +1 -0
- package/dist/types/plugin/index.js.map +1 -1
- package/dist/types/provider/config.d.ts +9 -0
- package/dist/types/provider/config.d.ts.map +1 -1
- package/dist/types/provider/interface.d.ts +14 -0
- package/dist/types/provider/interface.d.ts.map +1 -1
- package/dist/types/run/events.d.ts +17 -0
- package/dist/types/run/events.d.ts.map +1 -1
- package/dist/types/run/events.js.map +1 -1
- package/dist/types/sandbox/index.d.ts +15 -10
- package/dist/types/sandbox/index.d.ts.map +1 -1
- package/dist/types/sandbox/index.js.map +1 -1
- package/dist/types/tool/index.d.ts +77 -6
- package/dist/types/tool/index.d.ts.map +1 -1
- package/dist/types/tool/index.js.map +1 -1
- package/dist/types/tool/presentation.d.ts +6 -2
- package/dist/types/tool/presentation.d.ts.map +1 -1
- package/dist/types/workspace/ref.d.ts +5 -0
- package/dist/types/workspace/ref.d.ts.map +1 -1
- package/dist/utils/abort.d.ts +8 -0
- package/dist/utils/abort.d.ts.map +1 -1
- package/dist/utils/abort.js +16 -0
- package/dist/utils/abort.js.map +1 -1
- package/package.json +4 -4
- package/src/authorization/gate.ts +1 -1
- package/src/bridge/a2a/mapper.ts +23 -4
- package/src/bridge/sse/mapper.ts +3 -0
- package/src/connector/index.ts +2 -0
- package/src/connector/mcp/adapter.ts +82 -21
- package/src/connector/mcp/client.ts +2 -1
- package/src/connector/mcp/http-redirect.ts +32 -0
- package/src/connector/mcp/http-sse.ts +5 -0
- package/src/connector/mcp/image-admission.ts +272 -0
- package/src/connector/mcp/stdio.ts +63 -21
- package/src/connector/mcp/streamable-http.ts +3 -0
- package/src/constants/tools/index.ts +1 -1
- package/src/execution/base.ts +124 -7
- package/src/execution/errors.ts +24 -0
- package/src/execution/factory.ts +1 -0
- package/src/execution/hybrid.ts +47 -16
- package/src/execution/index.ts +1 -0
- package/src/execution/local.ts +164 -19
- package/src/execution/output.ts +104 -0
- package/src/execution/remote.ts +122 -17
- package/src/plugin/lifecycle.ts +9 -3
- package/src/process/kill-tree.ts +11 -13
- package/src/provider/capabilities.ts +10 -0
- package/src/provider/fallback.ts +39 -0
- package/src/provider/idle-timeout.ts +8 -0
- package/src/provider/retry.ts +8 -0
- package/src/public-runtime.ts +7 -1
- package/src/registry/tool/execute.ts +230 -64
- package/src/run/command-gate.ts +12 -0
- package/src/run/workspace-fingerprint.ts +5 -4
- package/src/runtime/bidi/index.ts +1 -1
- package/src/runtime/bidi/session.ts +177 -28
- package/src/runtime/query/executor.ts +769 -163
- package/src/runtime/query/index.ts +58 -7
- package/src/runtime/query/iteration/index.ts +72 -0
- package/src/runtime/query/iteration/phases/context.ts +5 -0
- package/src/runtime/query/iteration/phases/tool-review.ts +87 -23
- package/src/runtime/query/request-rich-content.ts +39 -14
- package/src/runtime/query/result.ts +25 -23
- package/src/runtime/query/resume-pending.ts +83 -1
- package/src/runtime/query/tool-output-budget.ts +52 -17
- package/src/runtime/query/tooling.ts +10 -0
- package/src/sandbox/provider/local.ts +213 -45
- package/src/scheduler/delegating.ts +6 -5
- package/src/scheduler/local.ts +3 -2
- package/src/session/workspace/driver.ts +12 -4
- package/src/session/workspace/git-worktree.ts +173 -34
- package/src/skills/registry.ts +47 -0
- package/src/tools/builtins/computer-use.ts +86 -2
- package/src/tools/builtins/run-code.ts +9 -11
- package/src/tools/builtins/skill.ts +325 -7
- package/src/tools/coordinator/agent.ts +108 -33
- package/src/types/agent/manager.ts +1 -1
- package/src/types/agent/scheduler.ts +10 -1
- package/src/types/bidi/index.ts +19 -2
- package/src/types/computer-use/index.ts +19 -0
- package/src/types/connector/execution-context.ts +3 -0
- package/src/types/errors/catalog.ts +14 -6
- package/src/types/errors/index.ts +22 -8
- package/src/types/execution/index.ts +46 -1
- package/src/types/hitl/index.ts +11 -0
- package/src/types/message/index.ts +3 -2
- package/src/types/plugin/index.ts +15 -0
- package/src/types/provider/config.ts +9 -0
- package/src/types/provider/interface.ts +18 -0
- package/src/types/run/events.ts +17 -3
- package/src/types/sandbox/index.ts +15 -10
- package/src/types/tool/index.ts +85 -6
- package/src/types/tool/presentation.ts +10 -3
- package/src/types/workspace/ref.ts +5 -0
- package/src/utils/abort.ts +18 -0
package/src/provider/fallback.ts
CHANGED
|
@@ -230,6 +230,40 @@ function memberReasoningEffortLevels(
|
|
|
230
230
|
return member.provider.effortLevelsFor?.(model, thinking)
|
|
231
231
|
}
|
|
232
232
|
|
|
233
|
+
/** Read one member's model-owned default using its routed model id. */
|
|
234
|
+
function memberReasoningEffortDefault(
|
|
235
|
+
member: ProviderChainMember,
|
|
236
|
+
requestModel: string,
|
|
237
|
+
thinking?: ThinkingConfig,
|
|
238
|
+
): ReasoningEffort | undefined {
|
|
239
|
+
return member.provider.reasoningEffortDefaultFor?.(member.model ?? requestModel, thinking)
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* A fallback request has one unambiguous default only when every route agrees.
|
|
244
|
+
*
|
|
245
|
+
* Omitting effort lets whichever member serves the request choose its own
|
|
246
|
+
* default. Publishing the head's answer as the chain's answer can therefore
|
|
247
|
+
* make the same shortcut move in opposite directions after fallback. The
|
|
248
|
+
* agreed value must also survive the chain-wide exact menu.
|
|
249
|
+
*/
|
|
250
|
+
function commonReasoningEffortDefault(
|
|
251
|
+
members: readonly ProviderChainMember[],
|
|
252
|
+
requestModel: string,
|
|
253
|
+
thinking?: ThinkingConfig,
|
|
254
|
+
): ReasoningEffort | undefined {
|
|
255
|
+
const common = commonReasoningEffortLevels(members, requestModel, thinking)
|
|
256
|
+
if (common === undefined) return undefined
|
|
257
|
+
let agreed: ReasoningEffort | undefined
|
|
258
|
+
for (const member of members) {
|
|
259
|
+
const value = memberReasoningEffortDefault(member, requestModel, thinking)
|
|
260
|
+
if (value === undefined) return undefined
|
|
261
|
+
if (agreed !== undefined && value !== agreed) return undefined
|
|
262
|
+
agreed = value
|
|
263
|
+
}
|
|
264
|
+
return agreed !== undefined && common.includes(agreed) ? agreed : undefined
|
|
265
|
+
}
|
|
266
|
+
|
|
233
267
|
/**
|
|
234
268
|
* The levels one request may carry safely through every member it can reach.
|
|
235
269
|
*
|
|
@@ -463,6 +497,11 @@ export function withProviderFallback(
|
|
|
463
497
|
// answer when any member cannot enumerate its selected model.
|
|
464
498
|
reasoningEffortLevelsFor: (model: string, thinking?: ThinkingConfig) =>
|
|
465
499
|
commonReasoningEffortLevels(members, model, thinking),
|
|
500
|
+
// Present on the chain wrapper for the same reason the menu method is:
|
|
501
|
+
// `undefined` is the honest answer when a member cannot answer, defaults
|
|
502
|
+
// disagree, or the value is absent from the common exact menu.
|
|
503
|
+
reasoningEffortDefaultFor: (model: string, thinking?: ThinkingConfig) =>
|
|
504
|
+
commonReasoningEffortDefault(members, model, thinking),
|
|
466
505
|
// Compatibility projection only. Existing consumers of the deprecated
|
|
467
506
|
// member keep the head-only answer they had; new consumers use the
|
|
468
507
|
// canonical chain-aware member above.
|
|
@@ -220,6 +220,14 @@ export function withStreamIdleTimeout(
|
|
|
220
220
|
) => provider.reasoningEffortLevelsFor?.(model, thinking),
|
|
221
221
|
}
|
|
222
222
|
: {}),
|
|
223
|
+
...(provider.reasoningEffortDefaultFor
|
|
224
|
+
? {
|
|
225
|
+
reasoningEffortDefaultFor: (
|
|
226
|
+
model: string,
|
|
227
|
+
thinking?: Parameters<NonNullable<LLMProvider['reasoningEffortDefaultFor']>>[1],
|
|
228
|
+
) => provider.reasoningEffortDefaultFor?.(model, thinking),
|
|
229
|
+
}
|
|
230
|
+
: {}),
|
|
223
231
|
...(provider.effortLevelsFor
|
|
224
232
|
? {
|
|
225
233
|
effortLevelsFor: (
|
package/src/provider/retry.ts
CHANGED
|
@@ -275,6 +275,14 @@ export function withProviderRetry(
|
|
|
275
275
|
) => provider.reasoningEffortLevelsFor?.(model, thinking),
|
|
276
276
|
}
|
|
277
277
|
: {}),
|
|
278
|
+
...(provider.reasoningEffortDefaultFor
|
|
279
|
+
? {
|
|
280
|
+
reasoningEffortDefaultFor: (
|
|
281
|
+
model: string,
|
|
282
|
+
thinking?: Parameters<NonNullable<LLMProvider['reasoningEffortDefaultFor']>>[1],
|
|
283
|
+
) => provider.reasoningEffortDefaultFor?.(model, thinking),
|
|
284
|
+
}
|
|
285
|
+
: {}),
|
|
278
286
|
// Forwarded for the same reason `healthCheck` is, and both were
|
|
279
287
|
// missing until something consumed them. A member this wrapper drops
|
|
280
288
|
// does not fail — it reads as "this driver cannot answer", which is a
|
package/src/public-runtime.ts
CHANGED
|
@@ -293,7 +293,11 @@ export {
|
|
|
293
293
|
formatSteeringNote,
|
|
294
294
|
} from './runtime/query/steering.js'
|
|
295
295
|
export type { SteeringChannel } from './runtime/query/steering.js'
|
|
296
|
-
export {
|
|
296
|
+
export {
|
|
297
|
+
BidiSessionCloseTimeoutError,
|
|
298
|
+
createMockBidiProvider,
|
|
299
|
+
startBidiRun,
|
|
300
|
+
} from './runtime/bidi/index.js'
|
|
297
301
|
export { PromptCache } from './runtime/query/prompt-cache.js'
|
|
298
302
|
export {
|
|
299
303
|
CheckpointManager,
|
|
@@ -672,6 +676,7 @@ export {
|
|
|
672
676
|
export {
|
|
673
677
|
BaseConnector,
|
|
674
678
|
BaseExecutionContext,
|
|
679
|
+
CommandCancellationUnsupportedError,
|
|
675
680
|
ConnectorManager,
|
|
676
681
|
ConnectorRegistry,
|
|
677
682
|
EnvironmentConnectorManager,
|
|
@@ -695,6 +700,7 @@ export {
|
|
|
695
700
|
mcpToolResultToToolResult,
|
|
696
701
|
mcpToolToToolDefinition,
|
|
697
702
|
RemoteExecutionContext,
|
|
703
|
+
RemoteExecutionBusyError,
|
|
698
704
|
ScopedConnectorRegistry,
|
|
699
705
|
// The only transport in the tree that can RUN an `MCPServer`. It reached
|
|
700
706
|
// `connector/mcp/index.ts` and stopped there, so the server was public
|
|
@@ -7,10 +7,12 @@ import { isTrustedReadOnly } from '../../tools/trusted-read-only.js'
|
|
|
7
7
|
import type { ToolResultGuardrailSpec } from '../../types/guardrail/index.js'
|
|
8
8
|
import type {
|
|
9
9
|
LLMToolSchema,
|
|
10
|
+
PreparedToolExecution,
|
|
10
11
|
ToolAvailability,
|
|
11
12
|
ToolContext,
|
|
12
13
|
ToolDefinition,
|
|
13
14
|
ToolExecutionResult,
|
|
15
|
+
ToolPreparationResult,
|
|
14
16
|
ToolRegistryConfig,
|
|
15
17
|
ToolTierConfig,
|
|
16
18
|
} from '../../types/tool/index.js'
|
|
@@ -87,6 +89,82 @@ export function assertToolName(name: string): void {
|
|
|
87
89
|
)
|
|
88
90
|
}
|
|
89
91
|
|
|
92
|
+
function clonePreparedInput(value: unknown, freeze: boolean, path = '$'): unknown {
|
|
93
|
+
const active = new WeakSet<object>()
|
|
94
|
+
const copies = new WeakMap<object, object>()
|
|
95
|
+
|
|
96
|
+
const clone = (candidate: unknown, at: string): unknown => {
|
|
97
|
+
if (candidate === null || typeof candidate === 'string' || typeof candidate === 'boolean') {
|
|
98
|
+
return candidate
|
|
99
|
+
}
|
|
100
|
+
if (typeof candidate === 'number') {
|
|
101
|
+
if (!Number.isFinite(candidate) || Object.is(candidate, -0)) {
|
|
102
|
+
throw new TypeError(`${at} must be a finite JSON number`)
|
|
103
|
+
}
|
|
104
|
+
return candidate
|
|
105
|
+
}
|
|
106
|
+
if (typeof candidate !== 'object') {
|
|
107
|
+
throw new TypeError(`${at} must be a JSON value, not ${typeof candidate}`)
|
|
108
|
+
}
|
|
109
|
+
if (active.has(candidate)) throw new TypeError(`${at} contains a cycle`)
|
|
110
|
+
const existing = copies.get(candidate)
|
|
111
|
+
if (existing) return existing
|
|
112
|
+
|
|
113
|
+
active.add(candidate)
|
|
114
|
+
try {
|
|
115
|
+
if (Array.isArray(candidate)) {
|
|
116
|
+
const extra = Reflect.ownKeys(candidate).filter(
|
|
117
|
+
(key) => key !== 'length' && (typeof key !== 'string' || !/^(0|[1-9]\d*)$/.test(key)),
|
|
118
|
+
)
|
|
119
|
+
if (extra.length > 0) throw new TypeError(`${at} has non-JSON array properties`)
|
|
120
|
+
const result: unknown[] = new Array(candidate.length)
|
|
121
|
+
copies.set(candidate, result)
|
|
122
|
+
for (let index = 0; index < candidate.length; index++) {
|
|
123
|
+
const descriptor = Object.getOwnPropertyDescriptor(candidate, String(index))
|
|
124
|
+
if (!descriptor) throw new TypeError(`${at}[${index}] is a sparse array hole`)
|
|
125
|
+
if (!descriptor.enumerable || !('value' in descriptor)) {
|
|
126
|
+
throw new TypeError(`${at}[${index}] must be an enumerable data property`)
|
|
127
|
+
}
|
|
128
|
+
result[index] = clone(descriptor.value, `${at}[${index}]`)
|
|
129
|
+
}
|
|
130
|
+
if (freeze) Object.freeze(result)
|
|
131
|
+
return result
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
const prototype = Object.getPrototypeOf(candidate)
|
|
135
|
+
if (prototype !== Object.prototype && prototype !== null) {
|
|
136
|
+
throw new TypeError(`${at} must be a plain JSON object`)
|
|
137
|
+
}
|
|
138
|
+
// JSON does not preserve prototypes. Canonicalize both admitted plain
|
|
139
|
+
// shapes to an ordinary object so a disk checkpoint round-trip compares
|
|
140
|
+
// equal to a fresh preparation of the same semantic value. Properties
|
|
141
|
+
// are still defined explicitly, so a literal "__proto__" key remains
|
|
142
|
+
// data rather than changing this object's prototype.
|
|
143
|
+
const result: Record<string, unknown> = {}
|
|
144
|
+
copies.set(candidate, result)
|
|
145
|
+
for (const key of Reflect.ownKeys(candidate)) {
|
|
146
|
+
if (typeof key !== 'string') throw new TypeError(`${at} has a symbol property`)
|
|
147
|
+
const descriptor = Object.getOwnPropertyDescriptor(candidate, key)
|
|
148
|
+
if (!descriptor?.enumerable || !('value' in descriptor)) {
|
|
149
|
+
throw new TypeError(`${at}.${key} must be an enumerable data property`)
|
|
150
|
+
}
|
|
151
|
+
Object.defineProperty(result, key, {
|
|
152
|
+
value: clone(descriptor.value, `${at}.${key}`),
|
|
153
|
+
enumerable: true,
|
|
154
|
+
writable: !freeze,
|
|
155
|
+
configurable: !freeze,
|
|
156
|
+
})
|
|
157
|
+
}
|
|
158
|
+
if (freeze) Object.freeze(result)
|
|
159
|
+
return result
|
|
160
|
+
} finally {
|
|
161
|
+
active.delete(candidate)
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
return clone(value, path)
|
|
166
|
+
}
|
|
167
|
+
|
|
90
168
|
/**
|
|
91
169
|
* Two sources contributed the same tool name and neither may take it.
|
|
92
170
|
*
|
|
@@ -136,9 +214,17 @@ export class ToolRegistry extends ManagedRegistry<ToolDefinition> {
|
|
|
136
214
|
private availability: Map<string, ToolAvailability> = new Map()
|
|
137
215
|
private tierConfig?: ToolTierConfig
|
|
138
216
|
private resultGuardrails?: readonly ToolResultGuardrailSpec[]
|
|
217
|
+
private readonly preparations = new WeakMap<
|
|
218
|
+
PreparedToolExecution,
|
|
219
|
+
{ readonly tool: ToolDefinition; readonly input: unknown }
|
|
220
|
+
>()
|
|
139
221
|
|
|
140
222
|
constructor(config?: ToolRegistryConfig) {
|
|
141
|
-
super({
|
|
223
|
+
super({
|
|
224
|
+
componentName: 'ToolRegistry',
|
|
225
|
+
idField: 'name',
|
|
226
|
+
logger: config?.logger,
|
|
227
|
+
})
|
|
142
228
|
this.tierConfig = config?.tierConfig
|
|
143
229
|
this.resultGuardrails = config?.resultGuardrails
|
|
144
230
|
}
|
|
@@ -401,10 +487,106 @@ Executable tool names, descriptions, and JSON input schemas are attached through
|
|
|
401
487
|
return this.getByAvailability(['active'], toolNames)
|
|
402
488
|
}
|
|
403
489
|
|
|
490
|
+
prepareExecution(toolName: string, rawInput: unknown): ToolPreparationResult {
|
|
491
|
+
const tool = this.getOrThrow(toolName)
|
|
492
|
+
const parseResult = tool.inputSchema.safeParse(rawInput)
|
|
493
|
+
if (!parseResult.success) {
|
|
494
|
+
return {
|
|
495
|
+
success: false,
|
|
496
|
+
result: this.validationFailure(tool, rawInput, parseResult.error),
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
let retainedInput: unknown
|
|
501
|
+
let reviewInput: unknown
|
|
502
|
+
try {
|
|
503
|
+
retainedInput = clonePreparedInput(parseResult.data, false)
|
|
504
|
+
reviewInput = clonePreparedInput(retainedInput, true)
|
|
505
|
+
} catch (err) {
|
|
506
|
+
const message = `Tool "${toolName}" produced an input that cannot be safely prepared for review and execution: ${toErrorMessage(err)}`
|
|
507
|
+
this.log.error('Prepared tool input could not be detached for review and execution', {
|
|
508
|
+
'namzu.tool.name': toolName,
|
|
509
|
+
'exception.message': toErrorMessage(err),
|
|
510
|
+
})
|
|
511
|
+
return {
|
|
512
|
+
success: false,
|
|
513
|
+
result: { success: false, output: '', error: message },
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
const prepared = Object.freeze({ toolName, input: reviewInput })
|
|
518
|
+
this.preparations.set(prepared, { tool, input: retainedInput })
|
|
519
|
+
return { success: true, prepared }
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
async executePrepared(
|
|
523
|
+
prepared: PreparedToolExecution,
|
|
524
|
+
context: ToolContext,
|
|
525
|
+
): Promise<ToolExecutionResult> {
|
|
526
|
+
const retained = this.preparations.get(prepared)
|
|
527
|
+
if (!retained) {
|
|
528
|
+
return {
|
|
529
|
+
success: false,
|
|
530
|
+
output: '',
|
|
531
|
+
error: `Tool "${prepared.toolName}" preparation is not owned by this registry or is no longer valid.`,
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
if (this.get(prepared.toolName) !== retained.tool) {
|
|
535
|
+
return {
|
|
536
|
+
success: false,
|
|
537
|
+
output: '',
|
|
538
|
+
error: `Tool "${prepared.toolName}" changed after its input was reviewed; prepare the call again.`,
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
return this.executeRetained(prepared.toolName, retained.tool, retained.input, context)
|
|
542
|
+
}
|
|
543
|
+
|
|
404
544
|
async execute(
|
|
405
545
|
toolName: string,
|
|
406
546
|
rawInput: unknown,
|
|
407
547
|
context: ToolContext,
|
|
548
|
+
): Promise<ToolExecutionResult> {
|
|
549
|
+
let preparation: ToolPreparationResult
|
|
550
|
+
try {
|
|
551
|
+
preparation = this.prepareExecution(toolName, rawInput)
|
|
552
|
+
} catch (err) {
|
|
553
|
+
return this.rejectPreparationWithClosedSpan(toolName, context, err)
|
|
554
|
+
}
|
|
555
|
+
if (!preparation.success) return preparation.result
|
|
556
|
+
return this.executePrepared(preparation.prepared, context)
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
private rejectPreparationWithClosedSpan(
|
|
560
|
+
toolName: string,
|
|
561
|
+
context: ToolContext,
|
|
562
|
+
err: unknown,
|
|
563
|
+
): Promise<never> {
|
|
564
|
+
const tracer = getTracer()
|
|
565
|
+
const parentCtx = context.parentSpan
|
|
566
|
+
? trace.setSpan(otelContext.active(), context.parentSpan)
|
|
567
|
+
: otelContext.active()
|
|
568
|
+
return tracer.startActiveSpan(toolSpanName(toolName), {}, parentCtx, async (span) => {
|
|
569
|
+
try {
|
|
570
|
+
span.setAttributes({
|
|
571
|
+
[GENAI.TOOL_NAME]: toolName,
|
|
572
|
+
[GENAI.TOOL_TYPE]: 'function',
|
|
573
|
+
...(context.toolUseId !== undefined ? { [GENAI.TOOL_CALL_ID]: context.toolUseId } : {}),
|
|
574
|
+
[NAMZU.TOOL_SUCCESS]: false,
|
|
575
|
+
[NAMZU.TOOL_ERROR]: toErrorMessage(err),
|
|
576
|
+
})
|
|
577
|
+
span.setStatus({ code: SpanStatusCode.ERROR, message: toErrorMessage(err) })
|
|
578
|
+
throw err
|
|
579
|
+
} finally {
|
|
580
|
+
span.end()
|
|
581
|
+
}
|
|
582
|
+
})
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
private async executeRetained(
|
|
586
|
+
toolName: string,
|
|
587
|
+
tool: ToolDefinition,
|
|
588
|
+
finalInput: unknown,
|
|
589
|
+
context: ToolContext,
|
|
408
590
|
): Promise<ToolExecutionResult> {
|
|
409
591
|
const tracer = getTracer()
|
|
410
592
|
|
|
@@ -437,8 +619,6 @@ Executable tool names, descriptions, and JSON input schemas are attached through
|
|
|
437
619
|
...(context.toolUseId !== undefined ? { [GENAI.TOOL_CALL_ID]: context.toolUseId } : {}),
|
|
438
620
|
})
|
|
439
621
|
|
|
440
|
-
const tool = this.getOrThrow(toolName)
|
|
441
|
-
|
|
442
622
|
const availability = this.getAvailability(toolName)
|
|
443
623
|
if (availability !== 'active') {
|
|
444
624
|
const msg = `Tool "${toolName}" is ${availability} and cannot be executed`
|
|
@@ -492,7 +672,7 @@ Executable tool names, descriptions, and JSON input schemas are attached through
|
|
|
492
672
|
|
|
493
673
|
const mode = context.permissionContext?.mode ?? 'auto'
|
|
494
674
|
if (mode === 'plan') {
|
|
495
|
-
const isReadOnly = isTrustedReadOnly(tool,
|
|
675
|
+
const isReadOnly = isTrustedReadOnly(tool, finalInput)
|
|
496
676
|
if (!isReadOnly) {
|
|
497
677
|
const msg = `plan mode: non-read-only tool "${toolName}" blocked`
|
|
498
678
|
span.setAttributes({
|
|
@@ -510,63 +690,6 @@ Executable tool names, descriptions, and JSON input schemas are attached through
|
|
|
510
690
|
}
|
|
511
691
|
}
|
|
512
692
|
|
|
513
|
-
const parseResult = tool.inputSchema.safeParse(rawInput)
|
|
514
|
-
if (!parseResult.success) {
|
|
515
|
-
const errorMessage = parseResult.error.issues
|
|
516
|
-
.map((i) => `${i.path.join('.')}: ${i.message}`)
|
|
517
|
-
.join('; ')
|
|
518
|
-
|
|
519
|
-
// Distinguish "model sent an empty/no-arg call" from
|
|
520
|
-
// "model sent partial args" — the first is most often a
|
|
521
|
-
// streaming hiccup or a definition-test ping (a provider
|
|
522
|
-
// occasionally pings tool surfaces with `{}` while the
|
|
523
|
-
// schema is still loading), the second is a genuine
|
|
524
|
-
// programming mistake by the model. The model self-
|
|
525
|
-
// corrects MUCH more reliably when the error tells it
|
|
526
|
-
// (a) which fields are required, (b) their types, and
|
|
527
|
-
// (c) a minimal example call. Without these hints the
|
|
528
|
-
// downstream UI just shows a red "Failed" row and the
|
|
529
|
-
// model rarely retries with the right args.
|
|
530
|
-
const isEmptyInput =
|
|
531
|
-
rawInput === null ||
|
|
532
|
-
rawInput === undefined ||
|
|
533
|
-
(typeof rawInput === 'object' &&
|
|
534
|
-
!Array.isArray(rawInput) &&
|
|
535
|
-
Object.keys(rawInput as Record<string, unknown>).length === 0)
|
|
536
|
-
|
|
537
|
-
const requiredHint = describeRequiredInput(tool.inputSchema)
|
|
538
|
-
// A conditional schema's required shape cannot be reconstructed
|
|
539
|
-
// from JSON Schema's top-level `required`, so the author gets to
|
|
540
|
-
// say what a valid retry looks like.
|
|
541
|
-
const recoveryHint = tool.validationErrorHint?.trim()
|
|
542
|
-
? ` ${tool.validationErrorHint.trim()}`
|
|
543
|
-
: ''
|
|
544
|
-
|
|
545
|
-
const enrichedMessage = isEmptyInput
|
|
546
|
-
? `Tool "${toolName}" was called with no arguments. ${requiredHint}${recoveryHint} Retry the call with the required parameters populated.`
|
|
547
|
-
: `Validation failed for "${toolName}": ${errorMessage}. ${requiredHint}${recoveryHint}`
|
|
548
|
-
|
|
549
|
-
this.log.error('Tool input validation failed', {
|
|
550
|
-
'namzu.tool.name': toolName,
|
|
551
|
-
'namzu.registry.errors': errorMessage,
|
|
552
|
-
'namzu.registry.empty': isEmptyInput,
|
|
553
|
-
})
|
|
554
|
-
|
|
555
|
-
span.setAttributes({
|
|
556
|
-
[NAMZU.TOOL_SUCCESS]: false,
|
|
557
|
-
[NAMZU.TOOL_ERROR]: `Validation: ${errorMessage}`,
|
|
558
|
-
})
|
|
559
|
-
span.setStatus({ code: SpanStatusCode.ERROR, message: errorMessage })
|
|
560
|
-
|
|
561
|
-
return {
|
|
562
|
-
success: false,
|
|
563
|
-
output: '',
|
|
564
|
-
error: enrichedMessage,
|
|
565
|
-
}
|
|
566
|
-
}
|
|
567
|
-
|
|
568
|
-
const finalInput = parseResult.data
|
|
569
|
-
|
|
570
693
|
try {
|
|
571
694
|
this.log.debug('Executing tool', { 'namzu.tool.name': toolName })
|
|
572
695
|
const startedAt = Date.now()
|
|
@@ -604,7 +727,10 @@ Executable tool names, descriptions, and JSON input schemas are attached through
|
|
|
604
727
|
)
|
|
605
728
|
if (!result.success && result.error) {
|
|
606
729
|
span.setAttribute(NAMZU.TOOL_ERROR, result.error)
|
|
607
|
-
span.setStatus({
|
|
730
|
+
span.setStatus({
|
|
731
|
+
code: SpanStatusCode.ERROR,
|
|
732
|
+
message: result.error,
|
|
733
|
+
})
|
|
608
734
|
} else {
|
|
609
735
|
span.setStatus({ code: SpanStatusCode.OK })
|
|
610
736
|
}
|
|
@@ -622,7 +748,10 @@ Executable tool names, descriptions, and JSON input schemas are attached through
|
|
|
622
748
|
[NAMZU.TOOL_SUCCESS]: false,
|
|
623
749
|
[NAMZU.TOOL_ERROR]: err.message,
|
|
624
750
|
})
|
|
625
|
-
span.setStatus({
|
|
751
|
+
span.setStatus({
|
|
752
|
+
code: SpanStatusCode.ERROR,
|
|
753
|
+
message: err.message,
|
|
754
|
+
})
|
|
626
755
|
throw err
|
|
627
756
|
}
|
|
628
757
|
const errorMessage = toErrorMessage(err)
|
|
@@ -635,7 +764,10 @@ Executable tool names, descriptions, and JSON input schemas are attached through
|
|
|
635
764
|
[NAMZU.TOOL_SUCCESS]: false,
|
|
636
765
|
[NAMZU.TOOL_ERROR]: errorMessage,
|
|
637
766
|
})
|
|
638
|
-
span.setStatus({
|
|
767
|
+
span.setStatus({
|
|
768
|
+
code: SpanStatusCode.ERROR,
|
|
769
|
+
message: errorMessage,
|
|
770
|
+
})
|
|
639
771
|
span.recordException(err instanceof Error ? err : new Error(errorMessage))
|
|
640
772
|
|
|
641
773
|
return {
|
|
@@ -655,6 +787,40 @@ Executable tool names, descriptions, and JSON input schemas are attached through
|
|
|
655
787
|
})
|
|
656
788
|
}
|
|
657
789
|
|
|
790
|
+
private validationFailure(
|
|
791
|
+
tool: ToolDefinition,
|
|
792
|
+
rawInput: unknown,
|
|
793
|
+
error: {
|
|
794
|
+
readonly issues: readonly {
|
|
795
|
+
readonly path: readonly PropertyKey[]
|
|
796
|
+
readonly message: string
|
|
797
|
+
}[]
|
|
798
|
+
},
|
|
799
|
+
): ToolExecutionResult {
|
|
800
|
+
const errorMessage = error.issues
|
|
801
|
+
.map((issue) => `${issue.path.join('.')}: ${issue.message}`)
|
|
802
|
+
.join('; ')
|
|
803
|
+
const isEmptyInput =
|
|
804
|
+
rawInput === null ||
|
|
805
|
+
rawInput === undefined ||
|
|
806
|
+
(typeof rawInput === 'object' &&
|
|
807
|
+
!Array.isArray(rawInput) &&
|
|
808
|
+
Object.keys(rawInput as Record<string, unknown>).length === 0)
|
|
809
|
+
const requiredHint = describeRequiredInput(tool.inputSchema)
|
|
810
|
+
const recoveryHint = tool.validationErrorHint?.trim()
|
|
811
|
+
? ` ${tool.validationErrorHint.trim()}`
|
|
812
|
+
: ''
|
|
813
|
+
const enrichedMessage = isEmptyInput
|
|
814
|
+
? `Tool "${tool.name}" was called with no arguments. ${requiredHint}${recoveryHint} Retry the call with the required parameters populated.`
|
|
815
|
+
: `Validation failed for "${tool.name}": ${errorMessage}. ${requiredHint}${recoveryHint}`
|
|
816
|
+
this.log.error('Tool input validation failed', {
|
|
817
|
+
'namzu.tool.name': tool.name,
|
|
818
|
+
'namzu.registry.errors': errorMessage,
|
|
819
|
+
'namzu.registry.empty': isEmptyInput,
|
|
820
|
+
})
|
|
821
|
+
return { success: false, output: '', error: enrichedMessage }
|
|
822
|
+
}
|
|
823
|
+
|
|
658
824
|
private getByAvailability(states: ToolAvailability[], filter?: string[]): ToolDefinition[] {
|
|
659
825
|
const candidates = filter ? filter.map((n) => this.getOrThrow(n)) : this.getAll()
|
|
660
826
|
return candidates.filter((t) => states.includes(this.getAvailability(t.name)))
|
package/src/run/command-gate.ts
CHANGED
|
@@ -130,6 +130,17 @@ function failureFeedback(
|
|
|
130
130
|
maxOutputChars: number,
|
|
131
131
|
): string {
|
|
132
132
|
const output = clipOutput(`${result.stdout}\n${result.stderr}`, maxOutputChars)
|
|
133
|
+
const truncatedStreams = [
|
|
134
|
+
result.stdoutTruncated === true ? 'stdout' : undefined,
|
|
135
|
+
result.stderrTruncated === true ? 'stderr' : undefined,
|
|
136
|
+
].filter((stream): stream is string => stream !== undefined)
|
|
137
|
+
const truncationWarning =
|
|
138
|
+
truncatedStreams.length === 0
|
|
139
|
+
? []
|
|
140
|
+
: [
|
|
141
|
+
'',
|
|
142
|
+
`Retained output is incomplete: ${truncatedStreams.join(' and ')} ${truncatedStreams.length === 1 ? 'was' : 'were'} truncated by the execution context. Re-run with a narrower command or filter to recover the missing diagnostics.`,
|
|
143
|
+
]
|
|
133
144
|
return [
|
|
134
145
|
`The answer was not accepted: \`${command}\` failed (attempt ${attempt}, exit ${result.exitCode}).`,
|
|
135
146
|
'',
|
|
@@ -137,6 +148,7 @@ function failureFeedback(
|
|
|
137
148
|
'```',
|
|
138
149
|
output || '(no output)',
|
|
139
150
|
'```',
|
|
151
|
+
...truncationWarning,
|
|
140
152
|
'',
|
|
141
153
|
'Fix the cause and then finish. Do not restate the failure back to me; change the code so the command passes.',
|
|
142
154
|
].join('\n')
|
|
@@ -41,10 +41,10 @@
|
|
|
41
41
|
* told to edit something it had already edited.
|
|
42
42
|
*
|
|
43
43
|
* So: a non-zero exit from any git invocation, a repository with no commits,
|
|
44
|
-
* a timeout, or output past the size
|
|
45
|
-
* partial hash. A truncated diff that
|
|
46
|
-
* outcome available here, because two
|
|
47
|
-
* same point collide.
|
|
44
|
+
* a timeout, an executor-reported truncated stream, or output past the size
|
|
45
|
+
* cap all produce `null` rather than a partial hash. A truncated diff that
|
|
46
|
+
* hashed successfully would be the worst outcome available here, because two
|
|
47
|
+
* different workspaces truncated at the same point collide.
|
|
48
48
|
*/
|
|
49
49
|
|
|
50
50
|
import { createHash } from 'node:crypto'
|
|
@@ -156,6 +156,7 @@ export async function fingerprintWorkspace(
|
|
|
156
156
|
// repository" and "no commits yet". All three mean the same thing to
|
|
157
157
|
// this function: it has no basis for a comparison.
|
|
158
158
|
if (result.exitCode !== 0) return null
|
|
159
|
+
if (result.stdoutTruncated === true || result.stderrTruncated === true) return null
|
|
159
160
|
if (Buffer.byteLength(result.stdout, 'utf8') > maxBytes) return null
|
|
160
161
|
return result.stdout
|
|
161
162
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export { createMockBidiProvider } from './mock.js'
|
|
2
2
|
export type { MockBidiScript, MockBidiSession } from './mock.js'
|
|
3
|
-
export { startBidiRun } from './session.js'
|
|
3
|
+
export { BidiSessionCloseTimeoutError, startBidiRun } from './session.js'
|
|
4
4
|
export type { BidiRun, BidiRunParams } from './session.js'
|