@qvac/harness 0.3.3 → 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/CHANGELOG.md +700 -126
- package/README.md +156 -0
- package/dist/harness.bundle +71 -103
- package/dist/prebuilds-manifest.json +0 -8
- package/dist-lib/index.d.ts +42 -40
- package/dist-lib/index.js +307 -117
- package/dist-lib/lib/audio-transcode-bare.d.ts +2 -2
- package/dist-lib/lib/audio-transcode-bare.js +28 -18
- package/dist-lib/lib/audio-transcode-node.d.ts +2 -2
- package/dist-lib/lib/capabilities/audio-resample.d.ts +7 -6
- package/dist-lib/lib/capabilities/audio-resample.js +30 -18
- package/dist-lib/lib/capabilities/completion.d.ts +20 -19
- package/dist-lib/lib/capabilities/completion.js +194 -135
- package/dist-lib/lib/capabilities/download.d.ts +6 -6
- package/dist-lib/lib/capabilities/download.js +15 -8
- package/dist-lib/lib/capabilities/embed.js +2 -1
- package/dist-lib/lib/capabilities/enhance.d.ts +6 -1
- package/dist-lib/lib/capabilities/enhance.js +7 -4
- package/dist-lib/lib/capabilities/invoke.js +7 -4
- package/dist-lib/lib/capabilities/kv-cache.js +2 -1
- package/dist-lib/lib/capabilities/preview-model-source.d.ts +69 -0
- package/dist-lib/lib/capabilities/preview-model-source.js +439 -0
- package/dist-lib/lib/capabilities/speech-text.js +5 -4
- package/dist-lib/lib/capabilities/tool-selection.js +10 -9
- package/dist-lib/lib/capabilities/tool-turns.js +30 -16
- package/dist-lib/lib/capabilities/usage-breakdown.js +2 -1
- package/dist-lib/lib/capabilities/voice.d.ts +5 -1
- package/dist-lib/lib/capabilities/voice.js +22 -12
- package/dist-lib/lib/connect.d.ts +15 -37
- package/dist-lib/lib/connect.js +161 -112
- package/dist-lib/lib/context-window.js +25 -21
- package/dist-lib/lib/contract-types.d.ts +26 -20
- package/dist-lib/lib/diagram-repair.d.ts +4 -4
- package/dist-lib/lib/diagram-repair.js +6 -3
- package/dist-lib/lib/docx/index.d.ts +3 -2
- package/dist-lib/lib/{error-fields.d.ts → guards.d.ts} +1 -0
- package/dist-lib/lib/{error-fields.js → guards.js} +3 -0
- package/dist-lib/lib/hardware/capability-probe.js +20 -10
- package/dist-lib/lib/hardware/gpu-classify.js +6 -3
- package/dist-lib/lib/hardware/gpu-probe-addon.js +8 -4
- package/dist-lib/lib/hardware/gpu-probe.js +4 -2
- package/dist-lib/lib/hardware/gpu-stats.native.cjs +8 -9
- package/dist-lib/lib/hardware/parsers.js +8 -4
- package/dist-lib/lib/helpers/buffer-burst.js +4 -2
- package/dist-lib/lib/helpers/control-tokens.js +4 -2
- package/dist-lib/lib/helpers/join-guard.d.ts +2 -2
- package/dist-lib/lib/helpers/join-guard.js +4 -2
- package/dist-lib/lib/helpers/load-stall.js +4 -2
- package/dist-lib/lib/helpers/markup-stream-filter.d.ts +2 -2
- package/dist-lib/lib/helpers/markup-stream-filter.js +6 -3
- package/dist-lib/lib/helpers/race-abort.js +2 -1
- package/dist-lib/lib/helpers/race-timeout.d.ts +5 -0
- package/dist-lib/lib/helpers/race-timeout.js +14 -0
- package/dist-lib/lib/helpers/run-outcome.d.ts +6 -8
- package/dist-lib/lib/helpers/run-outcome.js +36 -20
- package/dist-lib/lib/helpers/spawn-path.js +6 -3
- package/dist-lib/lib/helpers/text-coalescer.js +6 -3
- package/dist-lib/lib/helpers/thinking.js +38 -45
- package/dist-lib/lib/helpers/tool-call-markup.d.ts +9 -7
- package/dist-lib/lib/helpers/tool-call-markup.js +36 -20
- package/dist-lib/lib/helpers/tool-intent.d.ts +3 -2
- package/dist-lib/lib/helpers/tool-intent.js +4 -2
- package/dist-lib/lib/helpers/tool-label.js +18 -9
- package/dist-lib/lib/hooks/built-in/arg-repair.js +23 -13
- package/dist-lib/lib/hooks/built-in/egress.js +2 -1
- package/dist-lib/lib/hooks/built-in/skill-catalog.js +2 -1
- package/dist-lib/lib/hooks/pipeline.d.ts +5 -4
- package/dist-lib/lib/hooks/pipeline.js +6 -3
- package/dist-lib/lib/hooks/run.js +12 -8
- package/dist-lib/lib/model-download-progress.js +10 -8
- package/dist-lib/lib/models/context.d.ts +1 -1
- package/dist-lib/lib/models/context.js +5 -1
- package/dist-lib/lib/models/custom-model-cache.d.ts +13 -0
- package/dist-lib/lib/models/custom-model-cache.js +70 -0
- package/dist-lib/lib/models/gguf-header.d.ts +31 -0
- package/dist-lib/lib/models/gguf-header.js +230 -0
- package/dist-lib/lib/models/idle-unload.d.ts +14 -0
- package/dist-lib/lib/models/idle-unload.js +51 -0
- package/dist-lib/lib/models/kv-cache.d.ts +3 -2
- package/dist-lib/lib/models/kv-cache.js +4 -3
- package/dist-lib/lib/models/llm-presets.d.ts +2 -2
- package/dist-lib/lib/models/llm-presets.js +4 -2
- package/dist-lib/lib/models/model-catalog-constants.js +3 -2
- package/dist-lib/lib/models/model-catalog.d.ts +19 -21
- package/dist-lib/lib/models/model-catalog.js +66 -33
- package/dist-lib/lib/models/model-delete.d.ts +4 -1
- package/dist-lib/lib/models/model-delete.js +30 -15
- package/dist-lib/lib/models/model-handle.js +2 -1
- package/dist-lib/lib/models/model-list.d.ts +14 -3
- package/dist-lib/lib/models/model-list.js +33 -6
- package/dist-lib/lib/models/model-pool.d.ts +44 -10
- package/dist-lib/lib/models/model-pool.js +47 -42
- package/dist-lib/lib/models/model-source.js +11 -6
- package/dist-lib/lib/models/music-catalog.d.ts +2 -2
- package/dist-lib/lib/models/nmt-catalog.d.ts +4 -3
- package/dist-lib/lib/models/nmt-catalog.js +10 -5
- package/dist-lib/lib/models/opencl-cache.d.ts +6 -1
- package/dist-lib/lib/models/opencl-cache.js +5 -3
- package/dist-lib/lib/models/sdk-faults.d.ts +11 -8
- package/dist-lib/lib/models/sdk-faults.js +9 -6
- package/dist-lib/lib/models/shards.d.ts +11 -0
- package/dist-lib/lib/models/shards.js +15 -0
- package/dist-lib/lib/models/tool-dialect.js +10 -5
- package/dist-lib/lib/no-redirect-fetch-bare.d.ts +3 -3
- package/dist-lib/lib/no-redirect-fetch-bare.js +1 -1
- package/dist-lib/lib/no-redirect-fetch-impl.js +6 -3
- package/dist-lib/lib/no-redirect-fetch-node.d.ts +1 -1
- package/dist-lib/lib/no-redirect-fetch-node.js +9 -9
- package/dist-lib/lib/office/index.d.ts +3 -2
- package/dist-lib/lib/office/python.d.ts +3 -2
- package/dist-lib/lib/office/python.js +2 -1
- package/dist-lib/lib/prompt.d.ts +5 -4
- package/dist-lib/lib/prompt.js +8 -4
- package/dist-lib/lib/queue.js +10 -5
- package/dist-lib/lib/resolution-detector.js +21 -11
- package/dist-lib/lib/rpc-session.js +2 -1
- package/dist-lib/lib/sdk-loader.js +2 -1
- package/dist-lib/lib/sdk-storage.js +4 -2
- package/dist-lib/lib/serve.js +128 -68
- package/dist-lib/lib/spawn.js +7 -4
- package/dist-lib/lib/tmp-path.d.ts +7 -6
- package/dist-lib/lib/tool-call-display.d.ts +2 -2
- package/dist-lib/lib/tools/create-documents.js +18 -10
- package/dist-lib/lib/tools/edit-documents.js +23 -13
- package/dist-lib/lib/tools/edit-image.d.ts +2 -2
- package/dist-lib/lib/tools/edit-image.js +60 -36
- package/dist-lib/lib/tools/exec/adapters/adapter.d.ts +10 -10
- package/dist-lib/lib/tools/exec/adapters/python/attachments.d.ts +17 -11
- package/dist-lib/lib/tools/exec/adapters/python/attachments.js +53 -40
- package/dist-lib/lib/tools/exec/adapters/python/create-effect.d.ts +2 -2
- package/dist-lib/lib/tools/exec/adapters/python/create-effect.js +60 -32
- package/dist-lib/lib/tools/exec/adapters/python/guarded-fetch.d.ts +33 -22
- package/dist-lib/lib/tools/exec/adapters/python/guarded-fetch.js +58 -29
- package/dist-lib/lib/tools/exec/adapters/python/interrupt-timer.d.ts +2 -2
- package/dist-lib/lib/tools/exec/adapters/python/loader.js +23 -12
- package/dist-lib/lib/tools/exec/adapters/python/memfs.d.ts +13 -11
- package/dist-lib/lib/tools/exec/adapters/python/memfs.js +10 -5
- package/dist-lib/lib/tools/exec/adapters/python/net-shim.js +3 -1
- package/dist-lib/lib/tools/exec/adapters/python/output-policy.d.ts +6 -4
- package/dist-lib/lib/tools/exec/adapters/python/output-policy.js +20 -10
- package/dist-lib/lib/tools/exec/adapters/python/pyodide.d.ts +2 -2
- package/dist-lib/lib/tools/exec/adapters/python/pyodide.js +14 -7
- package/dist-lib/lib/tools/exec/adapters/python/python-adapter.d.ts +41 -34
- package/dist-lib/lib/tools/exec/adapters/python/python-adapter.js +316 -166
- package/dist-lib/lib/tools/exec/adapters/python/run-session.d.ts +9 -8
- package/dist-lib/lib/tools/exec/adapters/python/run-session.js +56 -28
- package/dist-lib/lib/tools/exec/adapters/python/wheels.d.ts +8 -10
- package/dist-lib/lib/tools/exec/adapters/python/wheels.js +22 -11
- package/dist-lib/lib/tools/exec/adapters/python/worker/client.d.ts +3 -2
- package/dist-lib/lib/tools/exec/adapters/python/worker/client.js +41 -26
- package/dist-lib/lib/tools/exec/adapters/python/worker/entry.js +27 -18
- package/dist-lib/lib/tools/exec/adapters/python/worker/protocol.d.ts +2 -2
- package/dist-lib/lib/tools/exec/adapters/python/worker/protocol.js +14 -13
- package/dist-lib/lib/tools/exec/adapters/python/worker/spawn-node.d.ts +4 -4
- package/dist-lib/lib/tools/exec/adapters/python/worker/spawn-node.js +10 -5
- package/dist-lib/lib/tools/exec/adapters/shell/shell-adapter.d.ts +4 -4
- package/dist-lib/lib/tools/exec/adapters/shell/shell-adapter.js +2 -1
- package/dist-lib/lib/tools/exec/obsidian/cli-process.d.ts +6 -1
- package/dist-lib/lib/tools/exec/obsidian/cli-process.js +8 -5
- package/dist-lib/lib/tools/exec/obsidian/cli.d.ts +6 -6
- package/dist-lib/lib/tools/exec/obsidian/cli.js +4 -4
- package/dist-lib/lib/tools/exec/obsidian/command.d.ts +3 -2
- package/dist-lib/lib/tools/exec/obsidian/command.js +6 -3
- package/dist-lib/lib/tools/exec/obsidian/output.js +2 -1
- package/dist-lib/lib/tools/exec/obsidian/route.d.ts +4 -6
- package/dist-lib/lib/tools/exec/obsidian/route.js +17 -11
- package/dist-lib/lib/tools/exec/obsidian/safe-path.js +2 -1
- package/dist-lib/lib/tools/exec/obsidian/vault-create.js +15 -7
- package/dist-lib/lib/tools/exec/obsidian/vault-paths.d.ts +2 -2
- package/dist-lib/lib/tools/exec/obsidian/vault-paths.js +20 -10
- package/dist-lib/lib/tools/exec/obsidian/vault-read.js +20 -13
- package/dist-lib/lib/tools/exec/obsidian/vault-write.js +24 -12
- package/dist-lib/lib/tools/exec/runner.d.ts +14 -14
- package/dist-lib/lib/tools/exec/runner.js +5 -3
- package/dist-lib/lib/tools/exec/scope.js +52 -28
- package/dist-lib/lib/tools/exec/shell-argv.js +31 -18
- package/dist-lib/lib/tools/exec/shell-guidance.d.ts +6 -1
- package/dist-lib/lib/tools/exec/shell-guidance.js +35 -20
- package/dist-lib/lib/tools/exec/video-tools.js +2 -2
- package/dist-lib/lib/tools/exec.d.ts +6 -8
- package/dist-lib/lib/tools/exec.js +113 -54
- package/dist-lib/lib/tools/file-glob.d.ts +4 -5
- package/dist-lib/lib/tools/file-glob.js +16 -11
- package/dist-lib/lib/tools/fs/glob.js +13 -18
- package/dist-lib/lib/tools/fs/remote-protocol.d.ts +10 -10
- package/dist-lib/lib/tools/fs/remote.d.ts +3 -2
- package/dist-lib/lib/tools/fs/remote.js +13 -7
- package/dist-lib/lib/tools/fs/scope.d.ts +8 -3
- package/dist-lib/lib/tools/fs/scope.js +20 -12
- package/dist-lib/lib/tools/fs/walk.js +6 -3
- package/dist-lib/lib/tools/fs/write.d.ts +3 -2
- package/dist-lib/lib/tools/generate-image.d.ts +11 -9
- package/dist-lib/lib/tools/generate-image.js +73 -37
- package/dist-lib/lib/tools/generate-music.d.ts +22 -11
- package/dist-lib/lib/tools/generate-music.js +79 -48
- package/dist-lib/lib/tools/grep.js +66 -41
- package/dist-lib/lib/tools/http-request/encode-fields.js +18 -9
- package/dist-lib/lib/tools/http-request/{utils.js → request.js} +20 -11
- package/dist-lib/lib/tools/http-request/truncate-response.js +57 -46
- package/dist-lib/lib/tools/http-request.d.ts +1 -1
- package/dist-lib/lib/tools/http-request.js +33 -18
- package/dist-lib/lib/tools/mcp/protocol.d.ts +53 -0
- package/dist-lib/lib/tools/mcp/{utils.js → protocol.js} +45 -23
- package/dist-lib/lib/tools/mcp-call.d.ts +1 -1
- package/dist-lib/lib/tools/mcp-call.js +37 -16
- package/dist-lib/lib/tools/operations/builders.js +10 -6
- package/dist-lib/lib/tools/operations/compile.js +20 -10
- package/dist-lib/lib/tools/operations/decoders.js +12 -6
- package/dist-lib/lib/tools/operations/gmail-message.js +3 -2
- package/dist-lib/lib/tools/outbound-guard.d.ts +4 -3
- package/dist-lib/lib/tools/outbound-guard.js +14 -8
- package/dist-lib/lib/tools/private-ip.js +8 -7
- package/dist-lib/lib/tools/rag-search.js +14 -7
- package/dist-lib/lib/tools/read-files.js +23 -20
- package/dist-lib/lib/tools/skill.js +19 -10
- package/dist-lib/lib/tools/skills/auth-resolver.d.ts +11 -18
- package/dist-lib/lib/tools/skills/auth-resolver.js +30 -18
- package/dist-lib/lib/tools/skills/bin-check.d.ts +3 -2
- package/dist-lib/lib/tools/skills/bin-check.js +10 -3
- package/dist-lib/lib/tools/skills/bundled-dir.js +20 -10
- package/dist-lib/lib/tools/skills/bundled-hash.d.ts +3 -2
- package/dist-lib/lib/tools/skills/bundled-hash.js +6 -1
- package/dist-lib/lib/tools/skills/catalog.d.ts +3 -2
- package/dist-lib/lib/tools/skills/catalog.js +33 -28
- package/dist-lib/lib/tools/skills/cli-argv.d.ts +3 -2
- package/dist-lib/lib/tools/skills/cli-argv.js +55 -52
- package/dist-lib/lib/tools/skills/cli-schema-check.js +21 -10
- package/dist-lib/lib/tools/skills/cli-schema-load.js +28 -20
- package/dist-lib/lib/tools/skills/cli-schema-types.d.ts +6 -6
- package/dist-lib/lib/tools/skills/cli-schema.js +2 -1
- package/dist-lib/lib/tools/skills/credential-check.d.ts +6 -3
- package/dist-lib/lib/tools/skills/credential-check.js +24 -12
- package/dist-lib/lib/tools/skills/credential-grants.js +1 -6
- package/dist-lib/lib/tools/skills/credential-health.d.ts +5 -1
- package/dist-lib/lib/tools/skills/credential-health.js +5 -3
- package/dist-lib/lib/tools/skills/frontmatter-parser.js +10 -5
- package/dist-lib/lib/tools/skills/manifest-parse.js +84 -64
- package/dist-lib/lib/tools/skills/mention.js +7 -6
- package/dist-lib/lib/tools/skills/obsidian-readiness.d.ts +2 -2
- package/dist-lib/lib/tools/skills/obsidian-readiness.js +11 -3
- package/dist-lib/lib/tools/skills/overlay-crud.d.ts +6 -4
- package/dist-lib/lib/tools/skills/overlay-crud.js +12 -6
- package/dist-lib/lib/tools/skills/overlay-dir.js +4 -2
- package/dist-lib/lib/tools/skills/overlay-watch.d.ts +3 -2
- package/dist-lib/lib/tools/skills/overlay-watch.js +8 -4
- package/dist-lib/lib/tools/skills/setup-routes.js +1 -3
- package/dist-lib/lib/tools/skills/skill-settings.js +4 -1
- package/dist-lib/lib/tools/skills/skill-state.d.ts +6 -11
- package/dist-lib/lib/tools/skills/skill-state.js +48 -29
- package/dist-lib/lib/tools/skills/tool-grants.js +6 -3
- package/dist-lib/lib/tools/toolsets.js +2 -1
- package/dist-lib/lib/tools/translate.d.ts +4 -5
- package/dist-lib/lib/tools/translate.js +31 -14
- package/dist-lib/lib/tools/url-guard.js +2 -1
- package/dist-lib/lib/tools/weather-lookup/place.js +8 -4
- package/dist-lib/lib/tools/weather-lookup/report.d.ts +7 -1
- package/dist-lib/lib/tools/weather-lookup/report.js +46 -9
- package/dist-lib/lib/tools/weather-lookup.js +18 -12
- package/dist-lib/lib/tools/web-fetch.js +47 -24
- package/dist-lib/lib/tools/web-search.js +8 -3
- package/dist-lib/lib/validating-lookup.d.ts +4 -4
- package/dist-lib/lib/wav-encode.d.ts +1 -1
- package/dist-lib/lib/wav-encode.js +11 -10
- package/dist-lib/lib/web-fetch/embedded-state.js +24 -12
- package/dist-lib/lib/web-fetch/extract.js +4 -2
- package/dist-lib/lib/web-fetch/images.js +8 -4
- package/dist-lib/lib/web-fetch/video.d.ts +2 -2
- package/dist-lib/lib/web-fetch/video.js +8 -4
- package/dist-lib/lib/web-search/engine-registry.d.ts +2 -2
- package/dist-lib/lib/web-search/engines/aol.js +1 -1
- package/dist-lib/lib/web-search/engines/bing.js +1 -1
- package/dist-lib/lib/web-search/engines/brave.js +4 -1
- package/dist-lib/lib/web-search/engines/duckduckgo.js +3 -2
- package/dist-lib/lib/web-search/engines/google.js +7 -3
- package/dist-lib/lib/web-search/engines/wikipedia.js +5 -4
- package/dist-lib/lib/web-search/engines/yahoo.js +1 -1
- package/dist-lib/lib/web-search/fetch-html.d.ts +5 -4
- package/dist-lib/lib/web-search/fetch-html.js +13 -7
- package/dist-lib/lib/web-search/orchestrator.d.ts +9 -5
- package/dist-lib/lib/web-search/orchestrator.js +3 -3
- package/dist-lib/lib/wire.d.ts +3 -2
- package/dist-lib/lib/wire.js +23 -15
- package/dist-lib/schema/baseline.js +10 -5
- package/dist-lib/schema/build.js +2 -1
- package/dist-lib/schema/harness.d.ts +15 -2
- package/dist-lib/schema/harness.js +55 -2
- package/dist-lib/schema/release-tags.d.ts +3 -2
- package/dist-lib/schema/release-tags.js +6 -3
- package/dist-lib/spec/bind.js +6 -0
- package/dist-lib/spec/calls.js +2 -0
- package/dist-lib/spec/hrpc/hrpc.json +26 -0
- package/dist-lib/spec/hrpc/index.js +27 -3
- package/dist-lib/spec/hrpc/messages.js +207 -8
- package/dist-lib/spec/hyperschema/index.js +207 -8
- package/dist-lib/spec/hyperschema/schema.json +165 -1
- package/dist-lib/spec/hyperschema/types.d.ts +42 -1
- package/package.json +13 -14
- package/worker/harness-sidecar.mjs +16 -22
- package/worker/stow-entry.mjs +7 -4
- package/dist-lib/lib/tools/mcp/utils.d.ts +0 -47
- /package/dist-lib/lib/tools/http-request/{utils.d.ts → request.d.ts} +0 -0
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import process from 'process';
|
|
2
2
|
import { contextCandidates } from '../context-window.js';
|
|
3
|
-
import { errorCode, errorMessage } from '../
|
|
3
|
+
import { errorCode, errorMessage, isRecord } from '../guards.js';
|
|
4
4
|
import { bufferBurst } from '../helpers/buffer-burst.js';
|
|
5
5
|
import { endsTurn, stopAtControlToken, stripControlTokens, truncateAtControlToken } from '../helpers/control-tokens.js';
|
|
6
6
|
import { createMarkupStreamFilter } from '../helpers/markup-stream-filter.js';
|
|
7
7
|
import { AbortedError, raceAbort } from '../helpers/race-abort.js';
|
|
8
|
+
import { raceTimeout } from '../helpers/race-timeout.js';
|
|
8
9
|
import { createRunOutcomeTracker, degenerateAnswer, unnamedWrites, writeReport } from '../helpers/run-outcome.js';
|
|
9
10
|
import { splitThinking } from '../helpers/thinking.js';
|
|
10
11
|
import { clipRawCall, normalizeToolArgs, recoverMarkupToolCalls, recoverPrintedSkillLoad, recoverSkillNamedCall, stripToolCallMarkup, stripToolResponseBlocks, toolCallMarkup } from '../helpers/tool-call-markup.js';
|
|
@@ -16,7 +17,7 @@ import { resolveLlmGenerationParams } from '../models/llm-presets.js';
|
|
|
16
17
|
import { customToolDialect } from '../models/model-catalog.js';
|
|
17
18
|
import { isContextOverflowError, isSdkModelWedgedError } from '../models/sdk-faults.js';
|
|
18
19
|
import { annotateLastUserTime, skillsPromptSection, systemPromptParts } from '../prompt.js';
|
|
19
|
-
import { isMetadataMethod } from '../tools/mcp/
|
|
20
|
+
import { isMetadataMethod } from '../tools/mcp/protocol.js';
|
|
20
21
|
import { unquoteArg } from '../tools/model-args.js';
|
|
21
22
|
import { SKILL_TOOL_NAME, WEB_SEARCH_TOOL_NAME } from './tool-names.js';
|
|
22
23
|
import { mainFileRequested, skillFileArg, skillFileStem } from '../tools/skill.js';
|
|
@@ -33,14 +34,18 @@ export function imageSettingsFrom(agent) {
|
|
|
33
34
|
if (!agent)
|
|
34
35
|
return undefined;
|
|
35
36
|
const settings = {};
|
|
36
|
-
if (agent.imageModelChoice)
|
|
37
|
+
if (agent.imageModelChoice) {
|
|
37
38
|
settings.modelChoice = agent.imageModelChoice;
|
|
38
|
-
|
|
39
|
+
}
|
|
40
|
+
if (agent.imageSteps) {
|
|
39
41
|
settings.steps = agent.imageSteps;
|
|
40
|
-
|
|
42
|
+
}
|
|
43
|
+
if (agent.imageWidth) {
|
|
41
44
|
settings.width = agent.imageWidth;
|
|
42
|
-
|
|
45
|
+
}
|
|
46
|
+
if (agent.imageHeight) {
|
|
43
47
|
settings.height = agent.imageHeight;
|
|
48
|
+
}
|
|
44
49
|
return Object.keys(settings).length ? settings : undefined;
|
|
45
50
|
}
|
|
46
51
|
const BURST_WINDOW_MS = 100;
|
|
@@ -62,10 +67,12 @@ export function trustedSourcesFrom(history) {
|
|
|
62
67
|
const sources = [];
|
|
63
68
|
for (const entry of history) {
|
|
64
69
|
const text = String(entry.content ?? '');
|
|
65
|
-
if (entry.role === 'user')
|
|
70
|
+
if (entry.role === 'user') {
|
|
66
71
|
sources.push({ origin: 'user', text });
|
|
67
|
-
|
|
72
|
+
}
|
|
73
|
+
else if (entry.role === 'tool') {
|
|
68
74
|
sources.push({ origin: originOfToolTurn(text), text });
|
|
75
|
+
}
|
|
69
76
|
}
|
|
70
77
|
return sources;
|
|
71
78
|
}
|
|
@@ -102,16 +109,18 @@ function sanitizeTurn(turn) {
|
|
|
102
109
|
function lastUserContent(messages) {
|
|
103
110
|
for (let i = messages.length - 1; i >= 0; i--) {
|
|
104
111
|
const turn = messages[i];
|
|
105
|
-
if (turn?.role === 'user')
|
|
112
|
+
if (turn?.role === 'user') {
|
|
106
113
|
return turn.content;
|
|
114
|
+
}
|
|
107
115
|
}
|
|
108
116
|
return '';
|
|
109
117
|
}
|
|
110
118
|
function lastUserImages(messages) {
|
|
111
119
|
for (let i = messages.length - 1; i >= 0; i--) {
|
|
112
120
|
const turn = messages[i];
|
|
113
|
-
if (turn?.role === 'user')
|
|
121
|
+
if (turn?.role === 'user') {
|
|
114
122
|
return turn.attachments ?? [];
|
|
123
|
+
}
|
|
115
124
|
}
|
|
116
125
|
return [];
|
|
117
126
|
}
|
|
@@ -149,8 +158,9 @@ function assistantToolTurn(contentText, calls) {
|
|
|
149
158
|
function preloadLastUser(messages, name, body) {
|
|
150
159
|
for (let i = messages.length - 1; i >= 0; i--) {
|
|
151
160
|
const turn = messages[i];
|
|
152
|
-
if (turn?.role !== 'user')
|
|
161
|
+
if (turn?.role !== 'user') {
|
|
153
162
|
continue;
|
|
163
|
+
}
|
|
154
164
|
const next = [...messages];
|
|
155
165
|
next[i] = { ...turn, content: skillPreloadMessage(turn.content, name, body) };
|
|
156
166
|
return next;
|
|
@@ -159,10 +169,12 @@ function preloadLastUser(messages, name, body) {
|
|
|
159
169
|
}
|
|
160
170
|
function collectStats(state, stats, stopReason) {
|
|
161
171
|
state.stopReason = stopReason;
|
|
162
|
-
if (!stats)
|
|
172
|
+
if (!stats) {
|
|
163
173
|
return;
|
|
164
|
-
|
|
174
|
+
}
|
|
175
|
+
if (state.ttft === undefined && stats.timeToFirstToken) {
|
|
165
176
|
state.ttft = stats.timeToFirstToken;
|
|
177
|
+
}
|
|
166
178
|
if (state.promptTokensPerSecond === undefined && stats.promptTokensPerSecond) {
|
|
167
179
|
state.promptTokensPerSecond = stats.promptTokensPerSecond;
|
|
168
180
|
}
|
|
@@ -173,10 +185,12 @@ function collectStats(state, stats, stopReason) {
|
|
|
173
185
|
state.timedTokens += stats.generatedTokens;
|
|
174
186
|
}
|
|
175
187
|
}
|
|
176
|
-
if (stats.promptTokens)
|
|
188
|
+
if (stats.promptTokens) {
|
|
177
189
|
state.promptTokens = stats.promptTokens;
|
|
178
|
-
|
|
190
|
+
}
|
|
191
|
+
if (stats.cacheTokens) {
|
|
179
192
|
state.cacheTokens = stats.cacheTokens;
|
|
193
|
+
}
|
|
180
194
|
}
|
|
181
195
|
function metricsEvent(state, usage) {
|
|
182
196
|
if (!state.tokens)
|
|
@@ -190,10 +204,10 @@ function metricsEvent(state, usage) {
|
|
|
190
204
|
tokensPerSecond: state.durationMs > 0 ? (state.timedTokens / state.durationMs) * 1000 : undefined,
|
|
191
205
|
promptTokens: state.promptTokens,
|
|
192
206
|
cacheTokens: state.cacheTokens,
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
207
|
+
ctxSize: state.ctxSize || undefined,
|
|
208
|
+
backends: state.backends.length ? state.backends : undefined,
|
|
209
|
+
usage: usage ?? undefined,
|
|
210
|
+
stopReason: state.stopReason || undefined
|
|
197
211
|
};
|
|
198
212
|
}
|
|
199
213
|
const TOOL_DENIED_MESSAGE = 'The user declined this call. Do not retry it or call it with different arguments to get ' +
|
|
@@ -215,16 +229,17 @@ const RETRYABLE_CODE = new Set(['timeout', 'transport', 'busy']);
|
|
|
215
229
|
function callSucceeded(result, outcome) {
|
|
216
230
|
if (outcome.kind !== 'success')
|
|
217
231
|
return false;
|
|
218
|
-
const exitCode = result
|
|
232
|
+
const exitCode = isRecord(result) ? result.exitCode : undefined;
|
|
219
233
|
return typeof exitCode !== 'number' || exitCode === 0;
|
|
220
234
|
}
|
|
221
235
|
function retryHints(result) {
|
|
222
236
|
if (!result || typeof result !== 'object' || Array.isArray(result))
|
|
223
237
|
return {};
|
|
224
|
-
const
|
|
238
|
+
const status = 'status' in result ? result.status : undefined;
|
|
239
|
+
const code = 'code' in result ? result.code : undefined;
|
|
225
240
|
return {
|
|
226
|
-
|
|
227
|
-
|
|
241
|
+
status: typeof status === 'number' ? status : undefined,
|
|
242
|
+
code: typeof code === 'string' ? code : undefined
|
|
228
243
|
};
|
|
229
244
|
}
|
|
230
245
|
function settledFailure(result, outcome) {
|
|
@@ -233,8 +248,9 @@ function settledFailure(result, outcome) {
|
|
|
233
248
|
if (outcome.kind === 'error' && outcome.error !== undefined)
|
|
234
249
|
return false;
|
|
235
250
|
const { code, status } = retryHints(result);
|
|
236
|
-
if (code !== undefined && RETRYABLE_CODE.has(code))
|
|
251
|
+
if (code !== undefined && RETRYABLE_CODE.has(code)) {
|
|
237
252
|
return false;
|
|
253
|
+
}
|
|
238
254
|
return status === undefined || (status < 500 && !RETRYABLE_STATUS.has(status));
|
|
239
255
|
}
|
|
240
256
|
const MAX_BLOCKED_REPEATS = 3;
|
|
@@ -257,13 +273,14 @@ function deniedCall() {
|
|
|
257
273
|
executed: false
|
|
258
274
|
});
|
|
259
275
|
}
|
|
260
|
-
async function executeCall(tool, args, ctx,
|
|
276
|
+
async function executeCall(tool, args, { ctx, approve, signal, denied, sources = [], effect: classified, skipApprovals, onToolActivity, intent, display }) {
|
|
261
277
|
const validationError = tool.validate?.(args, ctx);
|
|
262
278
|
if (validationError) {
|
|
263
279
|
hlog('tool rejected: arguments failed validation', { tool: tool.name });
|
|
264
280
|
return guidanceResult(validationError);
|
|
265
281
|
}
|
|
266
|
-
const refusal = guardToolCall(tool.name, args,
|
|
282
|
+
const refusal = guardToolCall(tool.name, args, {
|
|
283
|
+
sources,
|
|
267
284
|
externalWrite: tool.externalWrite === true
|
|
268
285
|
});
|
|
269
286
|
if (refusal) {
|
|
@@ -304,13 +321,11 @@ async function executeCall(tool, args, ctx, { approve, signal, denied, sources =
|
|
|
304
321
|
}), signal)
|
|
305
322
|
: false);
|
|
306
323
|
hlog(`tool ${approved ? 'approved' : 'denied'}`, { tool: tool.name });
|
|
307
|
-
const decision =
|
|
308
|
-
|
|
309
|
-
: skipApprovals === true
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
? 'allowed'
|
|
313
|
-
: 'denied';
|
|
324
|
+
const decision = toolDecision({
|
|
325
|
+
auto: tool.autoApprove === true || effect === 'read',
|
|
326
|
+
skipAll: skipApprovals === true,
|
|
327
|
+
approved
|
|
328
|
+
});
|
|
314
329
|
onToolActivity?.({
|
|
315
330
|
type: 'tool-activity',
|
|
316
331
|
name: tool.name,
|
|
@@ -343,15 +358,15 @@ function runToolContext(scope) {
|
|
|
343
358
|
return (turnImages = [], ctxSize) => ({
|
|
344
359
|
agentId: agent?.id ?? null,
|
|
345
360
|
ctxSize,
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
361
|
+
image,
|
|
362
|
+
turnImages: turnImages.length ? turnImages : undefined,
|
|
363
|
+
attach,
|
|
364
|
+
fetchAttachment,
|
|
365
|
+
ragSearch,
|
|
366
|
+
progress,
|
|
367
|
+
askUser,
|
|
368
|
+
signal,
|
|
369
|
+
runBudget
|
|
355
370
|
});
|
|
356
371
|
}
|
|
357
372
|
function labelOf(name, args, emoji) {
|
|
@@ -394,24 +409,21 @@ function blockedSkillMessage(name, catalog, listShown) {
|
|
|
394
409
|
`skill is available this turn — do not guess another name, and answer from what you ` +
|
|
395
410
|
`already have.`;
|
|
396
411
|
}
|
|
397
|
-
async function resolveToolCalls(toolCalls, enabled, agentId, pipeline, skillNames,
|
|
412
|
+
async function resolveToolCalls(toolCalls, { enabled, agentId, pipeline, skillNames, sandboxMode, signal }) {
|
|
398
413
|
const resolved = [];
|
|
399
414
|
for (const call of toolCalls) {
|
|
400
415
|
if (signal?.aborted)
|
|
401
416
|
throw new AbortedError();
|
|
402
417
|
const tool = enabled.find((t) => t.name === call.name);
|
|
418
|
+
const rawCall = call.raw === undefined ? undefined : clipRawCall(call.raw);
|
|
403
419
|
if (!tool) {
|
|
404
420
|
const { args } = takeToolIntent(call.arguments);
|
|
405
|
-
resolved.push({
|
|
406
|
-
call,
|
|
407
|
-
args,
|
|
408
|
-
...(call.raw === undefined ? {} : { rawCall: clipRawCall(call.raw) })
|
|
409
|
-
});
|
|
421
|
+
resolved.push({ call, args, rawCall });
|
|
410
422
|
continue;
|
|
411
423
|
}
|
|
412
424
|
const taken = takeToolIntent(call.arguments);
|
|
413
425
|
const args = normalizeToolArgs(taken.args, Object.keys(tool.parameters.properties));
|
|
414
|
-
const
|
|
426
|
+
const intent = taken.intent || undefined;
|
|
415
427
|
const fold = await pipeline.runPreToolFold({
|
|
416
428
|
toolName: tool.name,
|
|
417
429
|
args,
|
|
@@ -422,37 +434,27 @@ async function resolveToolCalls(toolCalls, enabled, agentId, pipeline, skillName
|
|
|
422
434
|
signal
|
|
423
435
|
});
|
|
424
436
|
resolved.push(fold.ok
|
|
425
|
-
? {
|
|
426
|
-
|
|
427
|
-
tool,
|
|
428
|
-
args: fold.args,
|
|
429
|
-
...(call.raw === undefined ? {} : { rawCall: clipRawCall(call.raw) }),
|
|
430
|
-
...(intent ? { intent } : {})
|
|
431
|
-
}
|
|
432
|
-
: {
|
|
433
|
-
call,
|
|
434
|
-
tool,
|
|
435
|
-
args,
|
|
436
|
-
rejection: fold.rejection,
|
|
437
|
-
...(call.raw === undefined ? {} : { rawCall: clipRawCall(call.raw) }),
|
|
438
|
-
...(intent ? { intent } : {})
|
|
439
|
-
});
|
|
437
|
+
? { call, tool, args: fold.args, rawCall, intent }
|
|
438
|
+
: { call, tool, args, rejection: fold.rejection, rawCall, intent });
|
|
440
439
|
}
|
|
441
440
|
return resolved;
|
|
442
441
|
}
|
|
443
442
|
function unprovenReplay(state, final) {
|
|
444
443
|
if (!state.unproven)
|
|
445
444
|
return null;
|
|
446
|
-
if (state.stopToken)
|
|
445
|
+
if (state.stopToken) {
|
|
447
446
|
return endsTurn(state.stopToken) ? state.unproven : null;
|
|
448
|
-
|
|
447
|
+
}
|
|
448
|
+
if (final.stopReason === 'length' || final.stopReason === 'cancelled') {
|
|
449
449
|
return null;
|
|
450
|
+
}
|
|
450
451
|
return state.unproven;
|
|
451
452
|
}
|
|
452
|
-
async function* runRoundTokens(
|
|
453
|
+
async function* runRoundTokens(result, state, { sdk, signal, startInThink = false }) {
|
|
453
454
|
const cancelThisRound = () => {
|
|
454
|
-
if (result.requestId)
|
|
455
|
+
if (result.requestId) {
|
|
455
456
|
sdk.cancel?.({ requestId: result.requestId });
|
|
457
|
+
}
|
|
456
458
|
};
|
|
457
459
|
signal?.addEventListener('abort', cancelThisRound, { once: true });
|
|
458
460
|
const tokens = stopAtControlToken(result.tokenStream, (token) => {
|
|
@@ -467,27 +469,33 @@ async function* runRoundTokens(sdk, result, state, signal, startInThink = false)
|
|
|
467
469
|
const next = await events.next();
|
|
468
470
|
if (next.done) {
|
|
469
471
|
state.unproven = next.value;
|
|
470
|
-
const thinkingTail = thinkingFilter.flush();
|
|
471
|
-
if (thinkingTail)
|
|
472
|
-
yield { type: 'thinking', text: thinkingTail };
|
|
473
|
-
const contentTail = contentFilter.flush();
|
|
474
|
-
if (contentTail)
|
|
475
|
-
yield { type: 'content', text: contentTail };
|
|
476
472
|
break;
|
|
477
473
|
}
|
|
478
|
-
if (signal?.aborted)
|
|
474
|
+
if (signal?.aborted) {
|
|
479
475
|
throw new AbortedError();
|
|
476
|
+
}
|
|
480
477
|
tokenEvents++;
|
|
481
|
-
if (next.value.type === 'content')
|
|
478
|
+
if (next.value.type === 'content') {
|
|
482
479
|
state.rawContentText += next.value.text;
|
|
480
|
+
}
|
|
483
481
|
const filter = next.value.type === 'thinking' ? thinkingFilter : contentFilter;
|
|
484
482
|
const text = filter.push(next.value.text);
|
|
485
|
-
if (text)
|
|
483
|
+
if (text) {
|
|
486
484
|
yield { type: next.value.type, text };
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
const thinkingTail = thinkingFilter.flush();
|
|
488
|
+
if (thinkingTail) {
|
|
489
|
+
yield { type: 'thinking', text: thinkingTail };
|
|
490
|
+
}
|
|
491
|
+
const contentTail = contentFilter.flush();
|
|
492
|
+
if (contentTail) {
|
|
493
|
+
yield { type: 'content', text: contentTail };
|
|
487
494
|
}
|
|
488
495
|
hlog('stream ended', { events: tokenEvents, stopToken: state.stopToken });
|
|
489
|
-
if (state.stopToken)
|
|
496
|
+
if (state.stopToken) {
|
|
490
497
|
cancelThisRound();
|
|
498
|
+
}
|
|
491
499
|
}
|
|
492
500
|
finally {
|
|
493
501
|
signal?.removeEventListener('abort', cancelThisRound);
|
|
@@ -512,17 +520,13 @@ function roundTokens(stats) {
|
|
|
512
520
|
const TRUNCATED_FINAL_MS = 2000;
|
|
513
521
|
function truncatedFinal(final, contentText) {
|
|
514
522
|
const accepted = { contentText, toolCalls: [], raw: { fullText: contentText } };
|
|
515
|
-
let timer;
|
|
516
|
-
const expired = new Promise((resolve) => {
|
|
517
|
-
timer = setTimeout(() => resolve(accepted), TRUNCATED_FINAL_MS);
|
|
518
|
-
});
|
|
519
523
|
const guarded = final.catch((err) => {
|
|
520
524
|
if (isSdkModelWedgedError(err))
|
|
521
525
|
throw err;
|
|
522
526
|
return accepted;
|
|
523
527
|
});
|
|
524
528
|
guarded.catch(noop);
|
|
525
|
-
return
|
|
529
|
+
return raceTimeout(guarded, { ms: TRUNCATED_FINAL_MS, fallback: accepted });
|
|
526
530
|
}
|
|
527
531
|
async function* runRecoveredRound(sdk, args) {
|
|
528
532
|
const lease = args.acquireRound ? await args.acquireRound() : null;
|
|
@@ -573,9 +577,12 @@ async function* runRecoveredRoundWith(sdk, args, modelId) {
|
|
|
573
577
|
const result = sdk.completion(params);
|
|
574
578
|
result.final.catch(noop);
|
|
575
579
|
const startInThink = args.generationParams?.reasoning_budget === -1;
|
|
576
|
-
for await (const event of runRoundTokens(
|
|
577
|
-
|
|
578
|
-
|
|
580
|
+
for await (const event of runRoundTokens(result, state, {
|
|
581
|
+
sdk,
|
|
582
|
+
signal: args.signal,
|
|
583
|
+
startInThink
|
|
584
|
+
})) {
|
|
585
|
+
contentText += event.type === 'content' ? event.text : '';
|
|
579
586
|
emitted = true;
|
|
580
587
|
yield event;
|
|
581
588
|
}
|
|
@@ -618,24 +625,28 @@ async function* runRecoveredRoundWith(sdk, args, modelId) {
|
|
|
618
625
|
messages: undefined,
|
|
619
626
|
tokens: undefined,
|
|
620
627
|
outcome: isContextOverflowError(err) ? 'overflowed' : 'failed',
|
|
621
|
-
reason:
|
|
628
|
+
reason: errorMessage(err)
|
|
622
629
|
};
|
|
623
630
|
}
|
|
624
|
-
if (!isContextOverflowError(err))
|
|
631
|
+
if (!isContextOverflowError(err)) {
|
|
625
632
|
throw err;
|
|
626
|
-
|
|
633
|
+
}
|
|
634
|
+
if (emitted) {
|
|
627
635
|
throw new Error(CONTEXT_OVERFLOW_MESSAGE, { cause: err });
|
|
636
|
+
}
|
|
628
637
|
lastOverflow = err;
|
|
629
638
|
}
|
|
630
639
|
}
|
|
631
|
-
if (lastOverflow)
|
|
640
|
+
if (lastOverflow) {
|
|
632
641
|
throw new Error(CONTEXT_OVERFLOW_MESSAGE, { cause: lastOverflow });
|
|
642
|
+
}
|
|
633
643
|
throw new Error('context recovery produced no completion candidate');
|
|
634
644
|
}
|
|
635
645
|
function* reportUnnamedWrites(said, landed) {
|
|
636
646
|
const unreported = writeReport(unnamedWrites(said, landed));
|
|
637
|
-
if (unreported)
|
|
647
|
+
if (unreported) {
|
|
638
648
|
yield { type: 'content', text: unreported };
|
|
649
|
+
}
|
|
639
650
|
}
|
|
640
651
|
export async function* completion(sdk, { modelId, acquireRound, model, agent, ctxSize, cacheKey, thinkingDefault, generationParams: generationParamsOverride, responseFormat, messages: storedMessages, tools: allTools = [], skillCatalog = [], approve, attach, fetchAttachment, ragSearch, progress, askUser, signal, toolConfigs, fsRoots = [], fsWriteRoots = [], captureInferenceCalls = false }) {
|
|
641
652
|
const pipeline = new HookPipeline();
|
|
@@ -654,7 +665,7 @@ export async function* completion(sdk, { modelId, acquireRound, model, agent, ct
|
|
|
654
665
|
let runError;
|
|
655
666
|
const runOutcomes = createRunOutcomeTracker();
|
|
656
667
|
const landed = runOutcomes.confirmedWrites;
|
|
657
|
-
|
|
668
|
+
async function* runTurn() {
|
|
658
669
|
if (signal?.aborted)
|
|
659
670
|
throw new AbortedError();
|
|
660
671
|
await pipeline.onRunStart({ agentId, messages });
|
|
@@ -702,8 +713,8 @@ export async function* completion(sdk, { modelId, acquireRound, model, agent, ct
|
|
|
702
713
|
hasActiveSkills: activeSkills.length > 0
|
|
703
714
|
});
|
|
704
715
|
}
|
|
705
|
-
const reasoningEnabled = agent?.reasoning
|
|
706
|
-
const deviceReasoning = thinkingDefault
|
|
716
|
+
const reasoningEnabled = reasoningFlag(agent?.reasoning);
|
|
717
|
+
const deviceReasoning = reasoningFlag(thinkingDefault);
|
|
707
718
|
const resolvedGenerationParams = resolveLlmGenerationParams(model, reasoningEnabled, deviceReasoning);
|
|
708
719
|
const generationParams = generationParamsOverride
|
|
709
720
|
? { ...resolvedGenerationParams, ...generationParamsOverride }
|
|
@@ -714,10 +725,27 @@ export async function* completion(sdk, { modelId, acquireRound, model, agent, ct
|
|
|
714
725
|
let skillIcon = null;
|
|
715
726
|
const skillEmoji = (name) => skillCatalog.find((entry) => entry.name === name)?.emoji ?? null;
|
|
716
727
|
const nudgedSkills = new Set();
|
|
728
|
+
function recordSkillLoad(skillName, output, { mainRequested, askedFile }) {
|
|
729
|
+
if (!output || typeof output !== 'object' || !('content' in output)) {
|
|
730
|
+
return;
|
|
731
|
+
}
|
|
732
|
+
loadedSkills.add(skillName);
|
|
733
|
+
if ('file' in output && typeof output.file === 'string') {
|
|
734
|
+
const files = loadedSkillFiles.get(skillName) ?? new Set();
|
|
735
|
+
files.add(output.file);
|
|
736
|
+
loadedSkillFiles.set(skillName, files);
|
|
737
|
+
}
|
|
738
|
+
if (mainRequested) {
|
|
739
|
+
loadedThisTurn.add(skillName);
|
|
740
|
+
}
|
|
741
|
+
else {
|
|
742
|
+
loadedFilesThisTurn.add(fileKey(skillName, unquoteArg(askedFile)));
|
|
743
|
+
}
|
|
744
|
+
skillIcon = skillEmoji(skillName) ?? skillIcon;
|
|
745
|
+
}
|
|
717
746
|
const toolDialect = model ? customToolDialect(model) : undefined;
|
|
718
747
|
let turns = messages;
|
|
719
748
|
let preloadedSkill = null;
|
|
720
|
-
let stubDropped = false;
|
|
721
749
|
const preload = mention ?? resolveImplicitSkill(lastUserContent(messages), activeSkills);
|
|
722
750
|
if (preload) {
|
|
723
751
|
const loader = tools.find((tool) => tool.name === SKILL_TOOL_NAME);
|
|
@@ -726,7 +754,6 @@ export async function* completion(sdk, { modelId, acquireRound, model, agent, ct
|
|
|
726
754
|
preloadedSkill = String(loaded.content);
|
|
727
755
|
const inlined = preloadLastUser(messages, preload.name, preloadedSkill);
|
|
728
756
|
turns = withoutSkillLoadTurns(inlined, preload.name);
|
|
729
|
-
stubDropped = turns.length < inlined.length;
|
|
730
757
|
if (!loadedSkills.has(preload.name)) {
|
|
731
758
|
const preloadArgs = { name: preload.name };
|
|
732
759
|
const preloadEffect = 'read';
|
|
@@ -797,15 +824,16 @@ export async function* completion(sdk, { modelId, acquireRound, model, agent, ct
|
|
|
797
824
|
}
|
|
798
825
|
logSelection();
|
|
799
826
|
let history = annotateLastUserTime(systemContent ? [{ role: 'system', content: systemContent }, ...turns] : turns);
|
|
800
|
-
let roundCacheKey =
|
|
827
|
+
let roundCacheKey = preloadedSkill === null ? cacheKey : undefined;
|
|
801
828
|
const runUsage = () => usageBreakdown(promptParts, stats.cacheTokens, model);
|
|
802
829
|
const denied = new Set();
|
|
803
830
|
const failed = new Map();
|
|
804
831
|
let blockedRepeats = 0;
|
|
805
832
|
let webSearches = 0;
|
|
806
833
|
const sources = trustedSourcesFrom(messages);
|
|
807
|
-
if (preloadedSkill)
|
|
834
|
+
if (preloadedSkill) {
|
|
808
835
|
sources.push({ origin: 'skill', text: preloadedSkill });
|
|
836
|
+
}
|
|
809
837
|
const query = explicitWebSearchQuery(lastUserContent(messages), enabled, {
|
|
810
838
|
skillPreloaded: preloadedSkill !== null
|
|
811
839
|
});
|
|
@@ -822,8 +850,9 @@ export async function* completion(sdk, { modelId, acquireRound, model, agent, ct
|
|
|
822
850
|
const searchEffect = webSearch.effect(args);
|
|
823
851
|
const searchResource = webSearch.resource?.(args) ?? null;
|
|
824
852
|
const searchCallDisplay = labelOf(webSearch.name, args, null);
|
|
825
|
-
if (signal?.aborted)
|
|
853
|
+
if (signal?.aborted) {
|
|
826
854
|
throw new AbortedError();
|
|
855
|
+
}
|
|
827
856
|
yield {
|
|
828
857
|
type: 'tool-call',
|
|
829
858
|
name: webSearch.name,
|
|
@@ -833,7 +862,8 @@ export async function* completion(sdk, { modelId, acquireRound, model, agent, ct
|
|
|
833
862
|
};
|
|
834
863
|
let activity = null;
|
|
835
864
|
const execution = fold.ok
|
|
836
|
-
? await executeCall(webSearch, args,
|
|
865
|
+
? await executeCall(webSearch, args, {
|
|
866
|
+
ctx: toolContext(turnImages, ctxSize),
|
|
837
867
|
approve,
|
|
838
868
|
signal,
|
|
839
869
|
denied,
|
|
@@ -856,8 +886,9 @@ export async function* completion(sdk, { modelId, acquireRound, model, agent, ct
|
|
|
856
886
|
const executionOutcome = settled.outcome;
|
|
857
887
|
runOutcomes.record(output, executionOutcome);
|
|
858
888
|
runOutcomes.finishRound();
|
|
859
|
-
if (fold.ok)
|
|
889
|
+
if (fold.ok) {
|
|
860
890
|
webSearches++;
|
|
891
|
+
}
|
|
861
892
|
if (!activity && !fold.ok) {
|
|
862
893
|
activity = {
|
|
863
894
|
type: 'tool-activity',
|
|
@@ -868,8 +899,9 @@ export async function* completion(sdk, { modelId, acquireRound, model, agent, ct
|
|
|
868
899
|
decision: 'blocked'
|
|
869
900
|
};
|
|
870
901
|
}
|
|
871
|
-
if (activity)
|
|
902
|
+
if (activity) {
|
|
872
903
|
yield activity;
|
|
904
|
+
}
|
|
873
905
|
yield {
|
|
874
906
|
type: 'tool-result',
|
|
875
907
|
name: webSearch.name,
|
|
@@ -922,11 +954,12 @@ export async function* completion(sdk, { modelId, acquireRound, model, agent, ct
|
|
|
922
954
|
});
|
|
923
955
|
roundsSent = round + 1;
|
|
924
956
|
const final = recovered.final;
|
|
925
|
-
if (!recovered.cacheable)
|
|
957
|
+
if (!recovered.cacheable) {
|
|
926
958
|
roundCacheKey = undefined;
|
|
959
|
+
}
|
|
927
960
|
history = recovered.history;
|
|
928
961
|
collectStats(stats, final.stats, final.stopReason);
|
|
929
|
-
hlog('round stats', { round, wallMs: Date.now() - roundStarted, ...
|
|
962
|
+
hlog('round stats', { round, wallMs: Date.now() - roundStarted, ...final.stats });
|
|
930
963
|
const markup = stripToolResponseBlocks(truncateAtControlToken(final.raw.fullText) || recovered.unproven || '');
|
|
931
964
|
let toolCalls = final.toolCalls?.length
|
|
932
965
|
? final.toolCalls
|
|
@@ -937,24 +970,29 @@ export async function* completion(sdk, { modelId, acquireRound, model, agent, ct
|
|
|
937
970
|
const alreadyLoaded = rescuedArgs !== undefined &&
|
|
938
971
|
(loadedSkillFiles.get(unquoteArg(rescuedArgs.name))?.has(unquoteArg(rescuedArgs.file)) ??
|
|
939
972
|
false);
|
|
940
|
-
if (!alreadyLoaded)
|
|
973
|
+
if (!alreadyLoaded) {
|
|
941
974
|
toolCalls = rescued;
|
|
942
|
-
|
|
975
|
+
}
|
|
976
|
+
if (toolCalls.length) {
|
|
943
977
|
hlog('recovered printed skill load', { round });
|
|
978
|
+
}
|
|
944
979
|
}
|
|
945
980
|
if (!toolCalls.length && enabled.some((tool) => tool.name === SKILL_TOOL_NAME)) {
|
|
946
981
|
toolCalls = recoverSkillNamedCall(markup, inContextSkills
|
|
947
982
|
.filter((skill) => !nudgedSkills.has(skill.name))
|
|
948
983
|
.map((skill) => skill.name), SKILL_TOOL_NAME);
|
|
949
|
-
for (const call of toolCalls)
|
|
984
|
+
for (const call of toolCalls) {
|
|
950
985
|
nudgedSkills.add(unquoteArg(call.arguments.name));
|
|
951
|
-
|
|
986
|
+
}
|
|
987
|
+
if (toolCalls.length) {
|
|
952
988
|
hlog('recovered skill-named call', { round });
|
|
989
|
+
}
|
|
953
990
|
}
|
|
954
991
|
if (!toolCalls.length) {
|
|
955
992
|
const replay = recovered.replay ? stripToolCallMarkup(recovered.replay) : '';
|
|
956
|
-
if (replay)
|
|
993
|
+
if (replay) {
|
|
957
994
|
yield { type: 'content', text: replay };
|
|
995
|
+
}
|
|
958
996
|
const spoken = recovered.contentText.trim();
|
|
959
997
|
if (enabled.length && !narrated && !replay && NARRATED_INTENT.test(spoken)) {
|
|
960
998
|
hlog('round narrated a tool call instead of making it', { round });
|
|
@@ -972,16 +1010,25 @@ export async function* completion(sdk, { modelId, acquireRound, model, agent, ct
|
|
|
972
1010
|
break;
|
|
973
1011
|
}
|
|
974
1012
|
hlog('round produced no answer', { round, mute });
|
|
975
|
-
if (mute++ < MAX_MUTE_ROUNDS)
|
|
1013
|
+
if (mute++ < MAX_MUTE_ROUNDS) {
|
|
976
1014
|
continue;
|
|
1015
|
+
}
|
|
977
1016
|
outcome = 'mute';
|
|
978
1017
|
break;
|
|
979
1018
|
}
|
|
980
1019
|
mute = 0;
|
|
981
1020
|
narrated = false;
|
|
982
|
-
const resolved = await resolveToolCalls(toolCalls,
|
|
983
|
-
|
|
1021
|
+
const resolved = await resolveToolCalls(toolCalls, {
|
|
1022
|
+
enabled,
|
|
1023
|
+
agentId: agent?.id ?? null,
|
|
1024
|
+
pipeline,
|
|
1025
|
+
skillNames: inContextSkills.map((skill) => skill.name),
|
|
1026
|
+
sandboxMode: agent?.sandboxMode === true,
|
|
1027
|
+
signal
|
|
1028
|
+
});
|
|
1029
|
+
if (signal?.aborted) {
|
|
984
1030
|
throw new AbortedError();
|
|
1031
|
+
}
|
|
985
1032
|
history = [
|
|
986
1033
|
...history,
|
|
987
1034
|
{
|
|
@@ -1064,7 +1111,8 @@ export async function* completion(sdk, { modelId, acquireRound, model, agent, ct
|
|
|
1064
1111
|
});
|
|
1065
1112
|
}
|
|
1066
1113
|
else if (tool) {
|
|
1067
|
-
execution = await executeCall(tool, args,
|
|
1114
|
+
execution = await executeCall(tool, args, {
|
|
1115
|
+
ctx: callCtx,
|
|
1068
1116
|
approve,
|
|
1069
1117
|
signal,
|
|
1070
1118
|
denied,
|
|
@@ -1105,21 +1153,8 @@ export async function* completion(sdk, { modelId, acquireRound, model, agent, ct
|
|
|
1105
1153
|
else if (tool?.name === WEB_SEARCH_TOOL_NAME && !rejection && !priorFailure) {
|
|
1106
1154
|
webSearches++;
|
|
1107
1155
|
}
|
|
1108
|
-
if (call.name === SKILL_TOOL_NAME
|
|
1109
|
-
output
|
|
1110
|
-
typeof output === 'object' &&
|
|
1111
|
-
'content' in output) {
|
|
1112
|
-
loadedSkills.add(skillName);
|
|
1113
|
-
if ('file' in output && typeof output.file === 'string') {
|
|
1114
|
-
const files = loadedSkillFiles.get(skillName) ?? new Set();
|
|
1115
|
-
files.add(output.file);
|
|
1116
|
-
loadedSkillFiles.set(skillName, files);
|
|
1117
|
-
}
|
|
1118
|
-
if (mainRequested)
|
|
1119
|
-
loadedThisTurn.add(skillName);
|
|
1120
|
-
else
|
|
1121
|
-
loadedFilesThisTurn.add(fileKey(skillName, unquoteArg(askedFile)));
|
|
1122
|
-
skillIcon = skillEmoji(skillName) ?? skillIcon;
|
|
1156
|
+
if (call.name === SKILL_TOOL_NAME) {
|
|
1157
|
+
recordSkillLoad(skillName, output, { mainRequested, askedFile });
|
|
1123
1158
|
}
|
|
1124
1159
|
if (!activity &&
|
|
1125
1160
|
!silent &&
|
|
@@ -1133,8 +1168,9 @@ export async function* completion(sdk, { modelId, acquireRound, model, agent, ct
|
|
|
1133
1168
|
decision: 'blocked'
|
|
1134
1169
|
};
|
|
1135
1170
|
}
|
|
1136
|
-
if (activity)
|
|
1171
|
+
if (activity) {
|
|
1137
1172
|
yield activity;
|
|
1173
|
+
}
|
|
1138
1174
|
if (!silent) {
|
|
1139
1175
|
yield {
|
|
1140
1176
|
type: 'tool-result',
|
|
@@ -1162,8 +1198,9 @@ export async function* completion(sdk, { modelId, acquireRound, model, agent, ct
|
|
|
1162
1198
|
blockedRepeats = 0;
|
|
1163
1199
|
}
|
|
1164
1200
|
history.push({ role: 'user', content: TOOL_CONTINUATION_NUDGE });
|
|
1165
|
-
if (blockedRepeats >= MAX_BLOCKED_REPEATS)
|
|
1201
|
+
if (blockedRepeats >= MAX_BLOCKED_REPEATS) {
|
|
1166
1202
|
break;
|
|
1203
|
+
}
|
|
1167
1204
|
if (cappedCalls === resolved.length) {
|
|
1168
1205
|
if (cappedRounds++ >= MAX_CAPPED_ROUNDS) {
|
|
1169
1206
|
outcome = 'search-capped';
|
|
@@ -1178,12 +1215,14 @@ export async function* completion(sdk, { modelId, acquireRound, model, agent, ct
|
|
|
1178
1215
|
yield* reportUnnamedWrites(said, landed);
|
|
1179
1216
|
const answered = metricsEvent(stats, runUsage());
|
|
1180
1217
|
runOutcome = 'done';
|
|
1181
|
-
if (answered)
|
|
1218
|
+
if (answered) {
|
|
1182
1219
|
yield answered;
|
|
1220
|
+
}
|
|
1183
1221
|
return;
|
|
1184
1222
|
}
|
|
1185
|
-
if (signal?.aborted)
|
|
1223
|
+
if (signal?.aborted) {
|
|
1186
1224
|
throw new AbortedError();
|
|
1225
|
+
}
|
|
1187
1226
|
const recovered = yield* runRecoveredRound(sdk, {
|
|
1188
1227
|
modelId,
|
|
1189
1228
|
acquireRound,
|
|
@@ -1198,8 +1237,9 @@ export async function* completion(sdk, { modelId, acquireRound, model, agent, ct
|
|
|
1198
1237
|
});
|
|
1199
1238
|
collectStats(stats, recovered.final.stats, recovered.final.stopReason);
|
|
1200
1239
|
const answer = recovered.replay ? stripToolCallMarkup(recovered.replay) : '';
|
|
1201
|
-
if (answer)
|
|
1240
|
+
if (answer) {
|
|
1202
1241
|
yield { type: 'content', text: answer };
|
|
1242
|
+
}
|
|
1203
1243
|
said = `${recovered.contentText}\n${answer}`;
|
|
1204
1244
|
if (!said.trim()) {
|
|
1205
1245
|
hlog('degenerate wrap-up', { outcome });
|
|
@@ -1213,13 +1253,18 @@ export async function* completion(sdk, { modelId, acquireRound, model, agent, ct
|
|
|
1213
1253
|
}
|
|
1214
1254
|
const metrics = metricsEvent(stats, runUsage());
|
|
1215
1255
|
runOutcome = 'done';
|
|
1216
|
-
if (metrics)
|
|
1256
|
+
if (metrics) {
|
|
1217
1257
|
yield metrics;
|
|
1258
|
+
}
|
|
1259
|
+
}
|
|
1260
|
+
try {
|
|
1261
|
+
yield* runTurn();
|
|
1218
1262
|
}
|
|
1219
1263
|
catch (err) {
|
|
1220
1264
|
const written = writeReport(landed);
|
|
1221
|
-
if (written)
|
|
1265
|
+
if (written) {
|
|
1222
1266
|
yield { type: 'content', text: written };
|
|
1267
|
+
}
|
|
1223
1268
|
if (err instanceof AbortedError) {
|
|
1224
1269
|
runOutcome = 'aborted';
|
|
1225
1270
|
yield { type: 'aborted' };
|
|
@@ -1242,3 +1287,17 @@ export async function* completion(sdk, { modelId, acquireRound, model, agent, ct
|
|
|
1242
1287
|
});
|
|
1243
1288
|
}
|
|
1244
1289
|
}
|
|
1290
|
+
function toolDecision({ auto, skipAll, approved }) {
|
|
1291
|
+
if (auto)
|
|
1292
|
+
return 'auto';
|
|
1293
|
+
if (skipAll)
|
|
1294
|
+
return 'skip-all';
|
|
1295
|
+
return approved ? 'allowed' : 'denied';
|
|
1296
|
+
}
|
|
1297
|
+
function reasoningFlag(setting) {
|
|
1298
|
+
if (setting === 'enabled')
|
|
1299
|
+
return true;
|
|
1300
|
+
if (setting === 'disabled')
|
|
1301
|
+
return false;
|
|
1302
|
+
return undefined;
|
|
1303
|
+
}
|