@qvac/harness 0.2.7 → 0.2.9

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.
Files changed (184) hide show
  1. package/dist/harness.bundle +70 -16
  2. package/dist/prebuilds-manifest.json +8 -0
  3. package/dist-lib/index.d.ts +2 -1
  4. package/dist-lib/index.js +60 -59
  5. package/dist-lib/lib/audio-transcode-bare.js +2 -2
  6. package/dist-lib/lib/capabilities/completion.d.ts +35 -2
  7. package/dist-lib/lib/capabilities/completion.js +114 -48
  8. package/dist-lib/lib/capabilities/download.js +2 -2
  9. package/dist-lib/lib/capabilities/speech-text.js +1 -1
  10. package/dist-lib/lib/capabilities/tool-prompt-log.js +1 -1
  11. package/dist-lib/lib/capabilities/tool-selection.js +2 -2
  12. package/dist-lib/lib/capabilities/tool-turns.js +1 -1
  13. package/dist-lib/lib/capabilities/usage-breakdown.js +1 -1
  14. package/dist-lib/lib/capabilities/voice.js +3 -3
  15. package/dist-lib/lib/connect.js +12 -11
  16. package/dist-lib/lib/context-window.js +1 -1
  17. package/dist-lib/lib/contract-types.d.ts +1 -0
  18. package/dist-lib/lib/docx/index.js +3 -3
  19. package/dist-lib/lib/hardware/capability-probe.js +3 -3
  20. package/dist-lib/lib/hardware/gpu-probe-addon.js +2 -2
  21. package/dist-lib/lib/hardware/gpu-probe-entry.js +1 -1
  22. package/dist-lib/lib/helpers/markup-stream-filter.js +1 -1
  23. package/dist-lib/lib/helpers/run-outcome.js +1 -1
  24. package/dist-lib/lib/helpers/spawn-path.d.ts +1 -1
  25. package/dist-lib/lib/helpers/thinking.js +2 -2
  26. package/dist-lib/lib/helpers/tool-intent.js +1 -1
  27. package/dist-lib/lib/helpers/tool-label.js +3 -3
  28. package/dist-lib/lib/hooks/built-in/arg-repair.d.ts +1 -1
  29. package/dist-lib/lib/hooks/built-in/arg-repair.js +1 -1
  30. package/dist-lib/lib/hooks/built-in/egress.d.ts +1 -1
  31. package/dist-lib/lib/hooks/built-in/egress.js +2 -2
  32. package/dist-lib/lib/hooks/built-in/index.js +3 -3
  33. package/dist-lib/lib/hooks/built-in/skill-catalog.d.ts +1 -1
  34. package/dist-lib/lib/hooks/pipeline.js +4 -4
  35. package/dist-lib/lib/hooks/registry.js +1 -1
  36. package/dist-lib/lib/hooks/run.js +1 -1
  37. package/dist-lib/lib/models/model-catalog.js +4 -4
  38. package/dist-lib/lib/models/model-delete.js +1 -1
  39. package/dist-lib/lib/models/model-handle.js +1 -1
  40. package/dist-lib/lib/models/model-list.js +1 -1
  41. package/dist-lib/lib/models/model-pool.js +8 -8
  42. package/dist-lib/lib/models/model-source.js +1 -1
  43. package/dist-lib/lib/models/music-catalog.d.ts +1 -1
  44. package/dist-lib/lib/no-redirect-fetch-bare.js +3 -3
  45. package/dist-lib/lib/no-redirect-fetch-impl.js +1 -1
  46. package/dist-lib/lib/no-redirect-fetch-node.js +2 -2
  47. package/dist-lib/lib/resolution-detector.js +1 -1
  48. package/dist-lib/lib/sdk-loader.js +2 -2
  49. package/dist-lib/lib/sdk-storage.js +1 -1
  50. package/dist-lib/lib/serve.js +11 -10
  51. package/dist-lib/lib/spawn.js +3 -3
  52. package/dist-lib/lib/staging.js +1 -1
  53. package/dist-lib/lib/tools/catalog.js +1 -1
  54. package/dist-lib/lib/tools/create-documents.js +2 -2
  55. package/dist-lib/lib/tools/edit-documents.js +2 -2
  56. package/dist-lib/lib/tools/edit-image.js +2 -2
  57. package/dist-lib/lib/tools/exec/adapters/python/attachments.js +2 -2
  58. package/dist-lib/lib/tools/exec/adapters/python/create-effect.js +1 -1
  59. package/dist-lib/lib/tools/exec/adapters/python/loader.js +1 -1
  60. package/dist-lib/lib/tools/exec/adapters/python/memfs.js +2 -2
  61. package/dist-lib/lib/tools/exec/adapters/python/pyodide.js +6 -6
  62. package/dist-lib/lib/tools/exec/adapters/python/python-adapter.js +3 -3
  63. package/dist-lib/lib/tools/exec/adapters/python/run-session.js +5 -5
  64. package/dist-lib/lib/tools/exec/adapters/python/wheels.js +1 -1
  65. package/dist-lib/lib/tools/exec/adapters/python/worker/client.js +3 -3
  66. package/dist-lib/lib/tools/exec/adapters/python/worker/entry.js +4 -4
  67. package/dist-lib/lib/tools/exec/adapters/shell/shell-adapter.js +1 -1
  68. package/dist-lib/lib/tools/exec/obsidian/cli-process.js +2 -2
  69. package/dist-lib/lib/tools/exec/obsidian/cli.js +4 -4
  70. package/dist-lib/lib/tools/exec/obsidian/command.js +1 -1
  71. package/dist-lib/lib/tools/exec/obsidian/route.js +7 -7
  72. package/dist-lib/lib/tools/exec/obsidian/vault-create.js +2 -2
  73. package/dist-lib/lib/tools/exec/obsidian/vault-fs.js +6 -6
  74. package/dist-lib/lib/tools/exec/obsidian/vault-paths.js +2 -2
  75. package/dist-lib/lib/tools/exec/obsidian/vault-read.js +1 -1
  76. package/dist-lib/lib/tools/exec/obsidian/vault-write.js +2 -2
  77. package/dist-lib/lib/tools/exec/runner.js +1 -1
  78. package/dist-lib/lib/tools/exec.js +13 -13
  79. package/dist-lib/lib/tools/file-glob.js +3 -3
  80. package/dist-lib/lib/tools/fs/local.js +1 -1
  81. package/dist-lib/lib/tools/fs/remote.js +1 -1
  82. package/dist-lib/lib/tools/fs/walk.js +2 -2
  83. package/dist-lib/lib/tools/generate-image.js +4 -4
  84. package/dist-lib/lib/tools/generate-music.js +6 -6
  85. package/dist-lib/lib/tools/grep.js +6 -6
  86. package/dist-lib/lib/tools/http-request/truncate-response.js +1 -1
  87. package/dist-lib/lib/tools/http-request.js +9 -9
  88. package/dist-lib/lib/tools/mcp/utils.js +1 -1
  89. package/dist-lib/lib/tools/mcp-call.js +8 -8
  90. package/dist-lib/lib/tools/operations/builders.d.ts +1 -1
  91. package/dist-lib/lib/tools/operations/builders.js +1 -1
  92. package/dist-lib/lib/tools/operations/compile.js +1 -1
  93. package/dist-lib/lib/tools/operations/manifest.d.ts +16 -16
  94. package/dist-lib/lib/tools/operations/manifest.js +1 -1
  95. package/dist-lib/lib/tools/outbound-guard.js +1 -1
  96. package/dist-lib/lib/tools/rag-search.js +1 -1
  97. package/dist-lib/lib/tools/read-files.js +3 -3
  98. package/dist-lib/lib/tools/skill.js +8 -8
  99. package/dist-lib/lib/tools/skills/auth-resolver.js +2 -2
  100. package/dist-lib/lib/tools/skills/bin-check.js +1 -1
  101. package/dist-lib/lib/tools/skills/bundled-dir.js +2 -2
  102. package/dist-lib/lib/tools/skills/catalog.js +10 -10
  103. package/dist-lib/lib/tools/skills/cli-schema-check.js +1 -1
  104. package/dist-lib/lib/tools/skills/cli-schema-load.js +1 -1
  105. package/dist-lib/lib/tools/skills/cli-schema.js +4 -4
  106. package/dist-lib/lib/tools/skills/credential-check.js +3 -3
  107. package/dist-lib/lib/tools/skills/credential-grants.js +1 -1
  108. package/dist-lib/lib/tools/skills/credential-health.js +2 -2
  109. package/dist-lib/lib/tools/skills/frontmatter-parser.js +1 -1
  110. package/dist-lib/lib/tools/skills/index.js +5 -5
  111. package/dist-lib/lib/tools/skills/mention.js +1 -1
  112. package/dist-lib/lib/tools/skills/overlay-crud.js +1 -1
  113. package/dist-lib/lib/tools/skills/setup-routes.js +1 -1
  114. package/dist-lib/lib/tools/skills/skill-settings.js +1 -1
  115. package/dist-lib/lib/tools/skills/skill-state-constants.d.ts +8 -8
  116. package/dist-lib/lib/tools/skills/skill-state.js +9 -9
  117. package/dist-lib/lib/tools/toolsets.d.ts +1 -1
  118. package/dist-lib/lib/tools/url-guard.js +2 -2
  119. package/dist-lib/lib/tools/weather-lookup/place.d.ts +11 -0
  120. package/dist-lib/lib/tools/weather-lookup/place.js +152 -0
  121. package/dist-lib/lib/tools/weather-lookup/report.d.ts +37 -0
  122. package/dist-lib/lib/tools/weather-lookup/report.js +56 -0
  123. package/dist-lib/lib/tools/weather-lookup.d.ts +8 -0
  124. package/dist-lib/lib/tools/weather-lookup.js +110 -0
  125. package/dist-lib/lib/tools/web-fetch.js +10 -10
  126. package/dist-lib/lib/tools/web-search.js +2 -2
  127. package/dist-lib/lib/transport.js +1 -1
  128. package/dist-lib/lib/validating-lookup.js +1 -1
  129. package/dist-lib/lib/web-fetch/embedded-state.js +1 -1
  130. package/dist-lib/lib/web-fetch/extract.js +1 -1
  131. package/dist-lib/lib/web-fetch/images.js +1 -1
  132. package/dist-lib/lib/web-fetch/video.js +1 -1
  133. package/dist-lib/lib/web-search/engine-registry.js +7 -7
  134. package/dist-lib/lib/web-search/engines/aol.js +3 -3
  135. package/dist-lib/lib/web-search/engines/bing.js +4 -4
  136. package/dist-lib/lib/web-search/engines/brave.js +2 -2
  137. package/dist-lib/lib/web-search/engines/duckduckgo.js +3 -3
  138. package/dist-lib/lib/web-search/engines/google.js +4 -4
  139. package/dist-lib/lib/web-search/engines/wikipedia.js +2 -2
  140. package/dist-lib/lib/web-search/engines/yahoo.js +3 -3
  141. package/dist-lib/lib/web-search/fetch-html.js +1 -1
  142. package/dist-lib/lib/web-search/merge-results.js +1 -1
  143. package/dist-lib/lib/web-search/orchestrator.js +3 -3
  144. package/dist-lib/lib/wire.js +28 -0
  145. package/dist-lib/schema/baseline.js +1 -1
  146. package/dist-lib/schema/build.js +3 -3
  147. package/dist-lib/schema/harness.js +5 -2
  148. package/dist-lib/schema/release-tags.d.ts +2 -1
  149. package/dist-lib/schema/release-tags.js +9 -7
  150. package/dist-lib/spec/hrpc/messages.js +22 -7
  151. package/dist-lib/spec/hyperschema/index.js +22 -7
  152. package/dist-lib/spec/hyperschema/schema.json +14 -1
  153. package/dist-lib/spec/hyperschema/types.d.ts +3 -2
  154. package/package.json +21 -8
  155. package/worker/harness-sidecar.mjs +2 -0
  156. package/.claude/skills/asana/SKILL.md +0 -86
  157. package/.claude/skills/gh-stack/SKILL.md +0 -181
  158. package/.claude/skills/gh-stack/references/commands.md +0 -177
  159. package/.claude/skills/gh-stack/references/stack-design.md +0 -97
  160. package/.claude/skills/gh-stack/references/troubleshooting.md +0 -159
  161. package/.claude/skills/js-house-style/SKILL.md +0 -671
  162. package/.claude/skills/kvcache/SKILL.md +0 -171
  163. package/.claude/skills/pr-create/SKILL.md +0 -180
  164. package/.claude/skills/pr-review/SKILL.md +0 -217
  165. package/CLAUDE.md +0 -39
  166. package/docs/decisions/2026-05-29-kvcache-tool-turns.md +0 -75
  167. package/docs/decisions/2026-06-02-kvcache-tool-turns-reenabled.md +0 -127
  168. package/docs/decisions/2026-06-23-android-cpu-llm-defaults.md +0 -126
  169. package/docs/decisions/2026-07-29-assistant-owned-storage-layout.md +0 -88
  170. package/docs/decisions/2026-08-04-sidecar-orphan-reaping.md +0 -79
  171. package/docs/decisions/2026-08-11-pyodide-worker-thread.md +0 -68
  172. package/docs/decisions/2026-08-17-harness-hook-pipeline.md +0 -84
  173. package/docs/decisions/2026-08-17-harness-outbound-egress-guard.md +0 -176
  174. package/docs/decisions/2026-08-20-chat-prompt-prefix-is-stable.md +0 -95
  175. package/docs/decisions/2026-08-20-kvcache-static-placement.md +0 -109
  176. package/docs/decisions/2026-08-21-vendored-python-wheels.md +0 -85
  177. package/docs/decisions/2026-08-26-exec-is-not-gated-by-skills.md +0 -64
  178. package/docs/decisions/2026-08-27-writable-skills-overlay.md +0 -56
  179. package/docs/decisions/2026-09-01-skill-operation-manifests.md +0 -53
  180. package/docs/decisions/2026-09-01-usage-breakdown-is-measured.md +0 -78
  181. package/docs/decisions/2026-09-03-usage-breakdown-reported-by-the-harness.md +0 -136
  182. package/docs/decisions/INDEX.md +0 -38
  183. package/docs/decisions/TEMPLATE.md +0 -32
  184. package/docs/kvcache-reference.md +0 -655
@@ -272,6 +272,14 @@
272
272
  "win32-arm64",
273
273
  "win32-x64"
274
274
  ],
275
+ "bare-tty/node_modules/bare-signals": [
276
+ "darwin-arm64",
277
+ "darwin-x64",
278
+ "linux-arm64",
279
+ "linux-x64",
280
+ "win32-arm64",
281
+ "win32-x64"
282
+ ],
275
283
  "bare-tty": [
276
284
  "darwin-arm64",
277
285
  "darwin-x64",
@@ -93,6 +93,7 @@ export interface CompletionContext {
93
93
  toolConfigs?: Record<string, Record<string, unknown>>;
94
94
  generationParams?: LlmGenerationParams;
95
95
  responseFormat?: ResponseFormat;
96
+ captureInferenceCalls?: boolean;
96
97
  grantedDirs?: string[];
97
98
  grantedDrives?: GrantedDrive[];
98
99
  driveOp?: DriveOpFn;
@@ -239,7 +240,7 @@ export declare class Harness extends ReadyResource {
239
240
  agent?: Agent;
240
241
  signal?: BareAbortSignal;
241
242
  }): Promise<void>;
242
- completion({ model, agent, messages, cacheKey, thinkingDefault, toolConfigs, generationParams, responseFormat, grantedDirs, grantedDrives, driveOp, grantedWriteDirs, approve, attach, fetchAttachment, ragSearch, progress, askUser, signal }: CompletionContext): AsyncGenerator<CompletionEvent>;
243
+ completion({ model, agent, messages, cacheKey, thinkingDefault, toolConfigs, generationParams, responseFormat, captureInferenceCalls, grantedDirs, grantedDrives, driveOp, grantedWriteDirs, approve, attach, fetchAttachment, ragSearch, progress, askUser, signal }: CompletionContext): AsyncGenerator<CompletionEvent>;
243
244
  private _makeRoomForCompletion;
244
245
  private _evictWedgedModel;
245
246
  private _evictAfterLeases;
package/dist-lib/index.js CHANGED
@@ -2,65 +2,65 @@ import fs from 'fs';
2
2
  import { platform, totalmem } from 'os';
3
3
  import process from 'process';
4
4
  import ReadyResource from 'ready-resource';
5
- import { probeGpuStats } from "./lib/hardware/gpu-probe.js";
6
- import { probeCapabilityProfile } from "./lib/hardware/capability-probe.js";
7
- import { closePythonWorker } from "./lib/tools/exec/adapters/python/worker/client.js";
8
- import { completion } from "./lib/capabilities/completion.js";
9
- import { download } from "./lib/capabilities/download.js";
10
- import { createEmbedLane } from "./lib/capabilities/embed.js";
11
- import { deleteAllKvCaches, deleteKvCacheKey } from "./lib/capabilities/kv-cache.js";
12
- import { pcmForTranscription } from "./lib/capabilities/audio-resample.js";
13
- import { buildWavBuffer } from "./lib/wav-encode.js";
14
- import { createVoiceLane, packSamples, speakOnce, speakStreamOnce, transcribeOnce, transcribeStreaming, SUPERTONIC_SAMPLE_RATE } from "./lib/capabilities/voice.js";
15
- import { pushQueue } from "./lib/queue.js";
16
- import { AbortedError, raceAbort } from "./lib/helpers/race-abort.js";
17
- import { audioGenDownloadMetadata, customProjectionMap, defaultProjectionMap, defaultTtsFor, defaultVoiceModel, diffusionDownloadMetadata, infraModelsFor, modelNameToCapabilityProfile, musicModelSet, setCustomModels } from "./lib/models/model-catalog.js";
18
- import { createModelStatusCache, invalidateModelStatusCache, listModels } from "./lib/models/model-list.js";
19
- import { deleteModelFiles, summarizeDelete } from "./lib/models/model-delete.js";
20
- import { createEmbedPool, createLoadTracker, createModelPool, createVoicePool, awaitModelCapacity, evictIdle, evictModelWithin, isResident, leaseCount, loadedModels, modelKey, releaseModel, resolveLoadOptions, progressState } from "./lib/models/model-pool.js";
21
- import { resolveMainGpu } from "./lib/models/gpu-selection.js";
22
- import { openclCacheDir } from "./lib/models/opencl-cache.js";
23
- import { assertEmbedDevice, createEmbedConfig } from "./lib/models/embed-config.js";
24
- import { createGpuFaultState, isSdkGpuDeviceLostError, isSdkModelWedgedError } from "./lib/models/sdk-faults.js";
25
- import { createSdkLoader } from "./lib/sdk-loader.js";
26
- import { createEditImageTool } from "./lib/tools/edit-image.js";
27
- import { toolCatalog } from "./lib/tools/catalog.js";
28
- import { createDiffusionRuntime, createGenerateImageTool } from "./lib/tools/generate-image.js";
29
- import { createGenerateMusicTool, createMusicRuntime } from "./lib/tools/generate-music.js";
30
- import { availableSkills, detectPlatform, loadSkillCatalog, resolveSkillStatuses, skillSupportsPlatform, versionProbeSkills } from "./lib/tools/skills/catalog.js";
31
- import { ensureBundledSkillsDir } from "./lib/tools/skills/bundled-dir.js";
32
- import { ensureSkillsOverlayDir } from "./lib/tools/skills/overlay-dir.js";
33
- import { copyBaseForEdit, deleteOverlaySkill, listManagedSkills, readSkillFile, writeSkillFile } from "./lib/tools/skills/overlay-crud.js";
34
- import { watchSkillsOverlay } from "./lib/tools/skills/overlay-watch.js";
35
- import { hlog } from "./lib/log.js";
5
+ import { probeGpuStats } from './lib/hardware/gpu-probe.js';
6
+ import { probeCapabilityProfile } from './lib/hardware/capability-probe.js';
7
+ import { closePythonWorker } from './lib/tools/exec/adapters/python/worker/client.js';
8
+ import { completion } from './lib/capabilities/completion.js';
9
+ import { download } from './lib/capabilities/download.js';
10
+ import { createEmbedLane } from './lib/capabilities/embed.js';
11
+ import { deleteAllKvCaches, deleteKvCacheKey } from './lib/capabilities/kv-cache.js';
12
+ import { pcmForTranscription } from './lib/capabilities/audio-resample.js';
13
+ import { buildWavBuffer } from './lib/wav-encode.js';
14
+ import { createVoiceLane, packSamples, speakOnce, speakStreamOnce, transcribeOnce, transcribeStreaming, SUPERTONIC_SAMPLE_RATE } from './lib/capabilities/voice.js';
15
+ import { pushQueue } from './lib/queue.js';
16
+ import { AbortedError, raceAbort } from './lib/helpers/race-abort.js';
17
+ import { audioGenDownloadMetadata, customProjectionMap, defaultProjectionMap, defaultTtsFor, defaultVoiceModel, diffusionDownloadMetadata, infraModelsFor, modelNameToCapabilityProfile, musicModelSet, setCustomModels } from './lib/models/model-catalog.js';
18
+ import { createModelStatusCache, invalidateModelStatusCache, listModels } from './lib/models/model-list.js';
19
+ import { deleteModelFiles, summarizeDelete } from './lib/models/model-delete.js';
20
+ import { createEmbedPool, createLoadTracker, createModelPool, createVoicePool, awaitModelCapacity, evictIdle, evictModelWithin, isResident, leaseCount, loadedModels, modelKey, releaseModel, resolveLoadOptions, progressState } from './lib/models/model-pool.js';
21
+ import { resolveMainGpu } from './lib/models/gpu-selection.js';
22
+ import { openclCacheDir } from './lib/models/opencl-cache.js';
23
+ import { assertEmbedDevice, createEmbedConfig } from './lib/models/embed-config.js';
24
+ import { createGpuFaultState, isSdkGpuDeviceLostError, isSdkModelWedgedError } from './lib/models/sdk-faults.js';
25
+ import { createSdkLoader } from './lib/sdk-loader.js';
26
+ import { createEditImageTool } from './lib/tools/edit-image.js';
27
+ import { toolCatalog } from './lib/tools/catalog.js';
28
+ import { createDiffusionRuntime, createGenerateImageTool } from './lib/tools/generate-image.js';
29
+ import { createGenerateMusicTool, createMusicRuntime } from './lib/tools/generate-music.js';
30
+ import { availableSkills, detectPlatform, loadSkillCatalog, resolveSkillStatuses, skillSupportsPlatform, versionProbeSkills } from './lib/tools/skills/catalog.js';
31
+ import { ensureBundledSkillsDir } from './lib/tools/skills/bundled-dir.js';
32
+ import { ensureSkillsOverlayDir } from './lib/tools/skills/overlay-dir.js';
33
+ import { copyBaseForEdit, deleteOverlaySkill, listManagedSkills, readSkillFile, writeSkillFile } from './lib/tools/skills/overlay-crud.js';
34
+ import { watchSkillsOverlay } from './lib/tools/skills/overlay-watch.js';
35
+ import { hlog } from './lib/log.js';
36
36
  import { harness } from './spec/index.js';
37
- import { installResolutionDetector, resolutionDetail } from "./lib/resolution-detector.js";
38
- import { probeBinVersions } from "./lib/tools/skills/bin-check.js";
39
- import { bareRuntime } from "./lib/tools/exec.js";
40
- import { runCommand } from "./lib/tools/exec/runner.js";
41
- import { createLocalRoots } from "./lib/tools/fs/local.js";
42
- import { createRemoteRoots } from "./lib/tools/fs/remote.js";
43
- import { resetCredentialHealth as resetCredentialHealthAfterSnapshot } from "./lib/tools/skills/credential-health.js";
44
- import { isDeviceSharedCredentialKey, scopeKey } from "./lib/tools/skills/scope-key.js";
45
- import { settingsScopeKey } from "./lib/tools/skills/skill-settings.js";
46
- export * from "./lib/capabilities/completion.js";
47
- export { attachmentTurn, loadedSkillsFrom, skillLoadedTurn } from "./lib/capabilities/tool-turns.js";
48
- export * from "./lib/capabilities/download.js";
49
- export * from "./lib/models/model-catalog.js";
50
- export * from "./lib/models/model-list.js";
51
- export { harnessChild, spawnHarness } from "./lib/spawn.js";
52
- export { settingsDimension, settingsSteps } from "./lib/tools/generate-image.js";
53
- export * from "./lib/tools/skills/catalog.js";
54
- export { requiredSettings, settingEnvName } from "./lib/tools/skills/skill-settings.js";
55
- export { TOOLSETS, toolsetEnabled } from "./lib/tools/toolsets.js";
56
- export { markCredentialRejected, markCredentialValid, recordCredentialHealth, resetAllCredentialHealth, resetCredentialHealth } from "./lib/tools/skills/credential-health.js";
57
- export { readSetup as normalizeSkillSetup } from "./lib/tools/skills/manifest-parse.js";
58
- export { isAvailableState, SKILL_STATE } from "./lib/tools/skills/skill-state.js";
59
- export { connectHarness, HARNESS_DIED, RemoteHarness } from "./lib/connect.js";
60
- export { serveHarness } from "./lib/serve.js";
61
- export { hlog, setHarnessLog, setHarnessLogSink } from "./lib/log.js";
62
- export { harnessHooks } from "./lib/hooks/registry.js";
63
- export { EgressGuardHook, SkillCatalogGuardHook } from "./lib/hooks/built-in/index.js";
37
+ import { installResolutionDetector, resolutionDetail } from './lib/resolution-detector.js';
38
+ import { probeBinVersions } from './lib/tools/skills/bin-check.js';
39
+ import { bareRuntime } from './lib/tools/exec.js';
40
+ import { runCommand } from './lib/tools/exec/runner.js';
41
+ import { createLocalRoots } from './lib/tools/fs/local.js';
42
+ import { createRemoteRoots } from './lib/tools/fs/remote.js';
43
+ import { resetCredentialHealth as resetCredentialHealthAfterSnapshot } from './lib/tools/skills/credential-health.js';
44
+ import { isDeviceSharedCredentialKey, scopeKey } from './lib/tools/skills/scope-key.js';
45
+ import { settingsScopeKey } from './lib/tools/skills/skill-settings.js';
46
+ export * from './lib/capabilities/completion.js';
47
+ export { attachmentTurn, loadedSkillsFrom, skillLoadedTurn } from './lib/capabilities/tool-turns.js';
48
+ export * from './lib/capabilities/download.js';
49
+ export * from './lib/models/model-catalog.js';
50
+ export * from './lib/models/model-list.js';
51
+ export { harnessChild, spawnHarness } from './lib/spawn.js';
52
+ export { settingsDimension, settingsSteps } from './lib/tools/generate-image.js';
53
+ export * from './lib/tools/skills/catalog.js';
54
+ export { requiredSettings, settingEnvName } from './lib/tools/skills/skill-settings.js';
55
+ export { TOOLSETS, toolsetEnabled } from './lib/tools/toolsets.js';
56
+ export { markCredentialRejected, markCredentialValid, recordCredentialHealth, resetAllCredentialHealth, resetCredentialHealth } from './lib/tools/skills/credential-health.js';
57
+ export { readSetup as normalizeSkillSetup } from './lib/tools/skills/manifest-parse.js';
58
+ export { isAvailableState, SKILL_STATE } from './lib/tools/skills/skill-state.js';
59
+ export { connectHarness, HARNESS_DIED, RemoteHarness } from './lib/connect.js';
60
+ export { serveHarness } from './lib/serve.js';
61
+ export { hlog, setHarnessLog, setHarnessLogSink } from './lib/log.js';
62
+ export { harnessHooks } from './lib/hooks/registry.js';
63
+ export { EgressGuardHook, SkillCatalogGuardHook } from './lib/hooks/built-in/index.js';
64
64
  const HarnessState = harness.getEnum('@harness/state');
65
65
  const BIN_VERSION_PROBE_TTL_MS = 45_000;
66
66
  const TRANSCRIBE_STREAM_MIN_BYTES = 16_000 * 2 * 60;
@@ -943,7 +943,7 @@ export class Harness extends ReadyResource {
943
943
  releaseModel(pool, key);
944
944
  }
945
945
  }
946
- async *completion({ model, agent, messages, cacheKey, thinkingDefault, toolConfigs, generationParams, responseFormat, grantedDirs, grantedDrives, driveOp, grantedWriteDirs, approve, attach, fetchAttachment, ragSearch, progress, askUser, signal }) {
946
+ async *completion({ model, agent, messages, cacheKey, thinkingDefault, toolConfigs, generationParams, responseFormat, captureInferenceCalls, grantedDirs, grantedDrives, driveOp, grantedWriteDirs, approve, attach, fetchAttachment, ragSearch, progress, askUser, signal }) {
947
947
  await this.ready();
948
948
  if (this.suspended)
949
949
  throw new Error('harness is suspended');
@@ -1016,6 +1016,7 @@ export class Harness extends ReadyResource {
1016
1016
  thinkingDefault,
1017
1017
  generationParams,
1018
1018
  responseFormat,
1019
+ captureInferenceCalls,
1019
1020
  messages: turns,
1020
1021
  tools: this._tools,
1021
1022
  skillCatalog: await this._completionSkills(agent?.id ?? null, model),
@@ -1,6 +1,6 @@
1
1
  import ffmpeg from 'bare-ffmpeg';
2
- import { hlog } from "./log.js";
3
- import { buildWavBuffer, TARGET_SAMPLE_RATE } from "./wav-encode.js";
2
+ import { hlog } from './log.js';
3
+ import { buildWavBuffer, TARGET_SAMPLE_RATE } from './wav-encode.js';
4
4
  function bufferReadIO(input) {
5
5
  let offset = 0;
6
6
  return new ffmpeg.IOContext(Buffer.alloc(4096), {
@@ -221,8 +221,40 @@ export type MetricsEvent = {
221
221
  ctxSize?: number | undefined;
222
222
  backends?: RunBackendUse[] | undefined;
223
223
  usage?: UsageBreakdown | undefined;
224
+ stopReason?: string | undefined;
224
225
  };
225
- export type CompletionEvent = TextEvent | ToolCallEvent | ToolResultEvent | ToolActivityEvent | ErrorEvent | AbortedEvent | MetricsEvent;
226
+ export interface InferenceCall {
227
+ round: number;
228
+ droppedTurns: number;
229
+ modelId: string;
230
+ messages: Message[];
231
+ tools: SdkTool[] | undefined;
232
+ generationParams: LlmGenerationParams | undefined;
233
+ responseFormat: ResponseFormat | undefined;
234
+ toolDialect: ToolDialect | undefined;
235
+ cacheKey: string | undefined;
236
+ promptPrefix: string;
237
+ }
238
+ export type InferenceCallEvent = {
239
+ type: 'inference-call';
240
+ call: InferenceCall;
241
+ };
242
+ export type InferenceSentEvent = {
243
+ type: 'inference-sent';
244
+ round: number;
245
+ droppedTurns: number;
246
+ messages: Message[] | undefined;
247
+ tokens: InferenceTokens | undefined;
248
+ outcome: 'completed' | 'overflowed' | 'failed';
249
+ reason: string | undefined;
250
+ };
251
+ export interface InferenceTokens {
252
+ prompt?: number | undefined;
253
+ generated?: number | undefined;
254
+ cached?: number | undefined;
255
+ timeToFirstToken?: number | undefined;
256
+ }
257
+ export type CompletionEvent = TextEvent | ToolCallEvent | ToolResultEvent | ToolActivityEvent | ErrorEvent | AbortedEvent | MetricsEvent | InferenceCallEvent | InferenceSentEvent;
226
258
  export interface CompletionSdkResult {
227
259
  requestId?: string;
228
260
  tokenStream: AsyncIterable<string>;
@@ -283,6 +315,7 @@ interface CompletionArgs {
283
315
  toolConfigs?: Record<string, Record<string, unknown>>;
284
316
  fsRoots?: readonly DriveRoot[];
285
317
  fsWriteRoots?: readonly DriveRoot[];
318
+ captureInferenceCalls?: boolean;
286
319
  }
287
320
  export declare const CONTEXT_OVERFLOW_MESSAGE = "This message is too large for the model context window.";
288
321
  export declare function trustedSourcesFrom(history: readonly Message[]): TrustedSource[];
@@ -290,5 +323,5 @@ export declare function toSdkTool(tool: ToolDefinition): SdkTool;
290
323
  export type CompletionSkillEntry = SkillCatalogEntry & {
291
324
  readonly status?: SkillState;
292
325
  };
293
- export declare function completion(sdk: CompletionSdk, { 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 }: CompletionArgs): AsyncGenerator<CompletionEvent>;
326
+ export declare function completion(sdk: CompletionSdk, { 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 }: CompletionArgs): AsyncGenerator<CompletionEvent>;
294
327
  export {};
@@ -1,34 +1,34 @@
1
1
  import process from 'process';
2
- import { contextCandidates } from "../context-window.js";
3
- import { errorCode, errorMessage } from "../error-fields.js";
4
- import { bufferBurst } from "../helpers/buffer-burst.js";
5
- import { endsTurn, stopAtControlToken, stripControlTokens, truncateAtControlToken } from "../helpers/control-tokens.js";
6
- import { createMarkupStreamFilter } from "../helpers/markup-stream-filter.js";
7
- import { AbortedError, raceAbort } from "../helpers/race-abort.js";
8
- import { createRunOutcomeTracker, degenerateAnswer, unnamedWrites, writeReport } from "../helpers/run-outcome.js";
9
- import { splitThinking } from "../helpers/thinking.js";
10
- import { clipRawCall, normalizeToolArgs, recoverMarkupToolCalls, recoverPrintedSkillLoad, recoverSkillNamedCall, stripToolCallMarkup, stripToolResponseBlocks, toolCallMarkup } from "../helpers/tool-call-markup.js";
11
- import { INTENT_PARAM, INTENT_PARAM_DESCRIPTION, takeToolIntent } from "../helpers/tool-intent.js";
12
- import { HookPipeline } from "../hooks/pipeline.js";
13
- import { fallbackToolLabel } from "../helpers/tool-label.js";
14
- import { hlog } from "../log.js";
15
- import { resolveLlmGenerationParams } from "../models/llm-presets.js";
16
- import { customToolDialect } from "../models/model-catalog.js";
17
- import { isContextOverflowError, isSdkModelWedgedError } from "../models/sdk-faults.js";
18
- import { annotateLastUserTime, skillsPromptSection, systemPromptParts } from "../prompt.js";
19
- import { isMetadataMethod } from "../tools/mcp/utils.js";
20
- import { unquoteArg } from "../tools/model-args.js";
21
- import { SKILL_TOOL_NAME, WEB_SEARCH_TOOL_NAME } from "./tool-names.js";
22
- import { promptUsageParts, usageBreakdown } from "./usage-breakdown.js";
23
- import { collectToolGrants, enabledTools, isSelected, skillIsActive, skillsAreSelected } from "./tool-selection.js";
24
- import { guardToolCall } from "../tools/outbound-guard.js";
25
- import { isAvailableState } from "../tools/skills/skill-state-constants.js";
26
- import { resolveImplicitSkill, resolveSkillMention, skillPreloadMessage } from "../tools/skills/mention.js";
27
- import { permittedTools } from "../tools/toolsets.js";
28
- import { promptPrefixHash } from "./prompt-prefix.js";
29
- import { logToolPrompt } from "./tool-prompt-log.js";
30
- import { DIRECT_CALL_ID, loadedSkillFilesFrom, loadedSkillsFrom, TOOL_CONTINUATION_NUDGE, toolResultTurn, withoutSkillLoadTurns } from "./tool-turns.js";
31
- import { projectVisionHistory, visionHistoryCacheKey } from "./vision-history.js";
2
+ import { contextCandidates } from '../context-window.js';
3
+ import { errorCode, errorMessage } from '../error-fields.js';
4
+ import { bufferBurst } from '../helpers/buffer-burst.js';
5
+ import { endsTurn, stopAtControlToken, stripControlTokens, truncateAtControlToken } from '../helpers/control-tokens.js';
6
+ import { createMarkupStreamFilter } from '../helpers/markup-stream-filter.js';
7
+ import { AbortedError, raceAbort } from '../helpers/race-abort.js';
8
+ import { createRunOutcomeTracker, degenerateAnswer, unnamedWrites, writeReport } from '../helpers/run-outcome.js';
9
+ import { splitThinking } from '../helpers/thinking.js';
10
+ import { clipRawCall, normalizeToolArgs, recoverMarkupToolCalls, recoverPrintedSkillLoad, recoverSkillNamedCall, stripToolCallMarkup, stripToolResponseBlocks, toolCallMarkup } from '../helpers/tool-call-markup.js';
11
+ import { INTENT_PARAM, INTENT_PARAM_DESCRIPTION, takeToolIntent } from '../helpers/tool-intent.js';
12
+ import { HookPipeline } from '../hooks/pipeline.js';
13
+ import { fallbackToolLabel } from '../helpers/tool-label.js';
14
+ import { hlog } from '../log.js';
15
+ import { resolveLlmGenerationParams } from '../models/llm-presets.js';
16
+ import { customToolDialect } from '../models/model-catalog.js';
17
+ import { isContextOverflowError, isSdkModelWedgedError } from '../models/sdk-faults.js';
18
+ import { annotateLastUserTime, skillsPromptSection, systemPromptParts } from '../prompt.js';
19
+ import { isMetadataMethod } from '../tools/mcp/utils.js';
20
+ import { unquoteArg } from '../tools/model-args.js';
21
+ import { SKILL_TOOL_NAME, WEB_SEARCH_TOOL_NAME } from './tool-names.js';
22
+ import { promptUsageParts, usageBreakdown } from './usage-breakdown.js';
23
+ import { collectToolGrants, enabledTools, isSelected, skillIsActive, skillsAreSelected } from './tool-selection.js';
24
+ import { guardToolCall } from '../tools/outbound-guard.js';
25
+ import { isAvailableState } from '../tools/skills/skill-state-constants.js';
26
+ import { resolveImplicitSkill, resolveSkillMention, skillPreloadMessage } from '../tools/skills/mention.js';
27
+ import { permittedTools } from '../tools/toolsets.js';
28
+ import { promptPrefixHash } from './prompt-prefix.js';
29
+ import { logToolPrompt } from './tool-prompt-log.js';
30
+ import { DIRECT_CALL_ID, loadedSkillFilesFrom, loadedSkillsFrom, TOOL_CONTINUATION_NUDGE, toolResultTurn, withoutSkillLoadTurns } from './tool-turns.js';
31
+ import { projectVisionHistory, visionHistoryCacheKey } from './vision-history.js';
32
32
  export function imageSettingsFrom(agent) {
33
33
  if (!agent)
34
34
  return undefined;
@@ -157,7 +157,8 @@ function preloadLastUser(messages, name, body) {
157
157
  }
158
158
  return messages;
159
159
  }
160
- function collectStats(state, stats) {
160
+ function collectStats(state, stats, stopReason) {
161
+ state.stopReason = stopReason;
161
162
  if (!stats)
162
163
  return;
163
164
  if (state.ttft === undefined && stats.timeToFirstToken)
@@ -191,7 +192,8 @@ function metricsEvent(state, usage) {
191
192
  cacheTokens: state.cacheTokens,
192
193
  ...(state.ctxSize ? { ctxSize: state.ctxSize } : {}),
193
194
  ...(state.backends.length ? { backends: state.backends } : {}),
194
- ...(usage ? { usage } : {})
195
+ ...(usage ? { usage } : {}),
196
+ ...(state.stopReason ? { stopReason: state.stopReason } : {})
195
197
  };
196
198
  }
197
199
  const TOOL_DENIED_MESSAGE = 'The user declined this call. Do not retry it or call it with different arguments to get ' +
@@ -463,6 +465,21 @@ async function* runRoundTokens(sdk, result, state, signal, startInThink = false)
463
465
  await events.return(null);
464
466
  }
465
467
  }
468
+ function sentMessages(stats) {
469
+ const sent = stats?.sentMessages;
470
+ return Array.isArray(sent) ? sent : null;
471
+ }
472
+ function roundTokens(stats) {
473
+ if (!stats)
474
+ return undefined;
475
+ const tokens = {
476
+ prompt: stats.promptTokens,
477
+ generated: stats.generatedTokens,
478
+ cached: stats.cacheTokens,
479
+ timeToFirstToken: stats.timeToFirstToken
480
+ };
481
+ return Object.values(tokens).some((value) => value !== undefined) ? tokens : undefined;
482
+ }
466
483
  const TRUNCATED_FINAL_MS = 2000;
467
484
  function truncatedFinal(final, contentText) {
468
485
  const accepted = { contentText, toolCalls: [], raw: { fullText: contentText } };
@@ -496,17 +513,35 @@ async function* runRecoveredRoundWith(sdk, args, modelId) {
496
513
  let emitted = false;
497
514
  const state = { stopToken: null, unproven: null, rawContentText: '' };
498
515
  const cacheable = candidate.history === args.history;
516
+ const params = {
517
+ modelId,
518
+ history: projectVisionHistory(candidate.history),
519
+ stream: true,
520
+ tools: args.tools,
521
+ generationParams: args.generationParams,
522
+ responseFormat: args.responseFormat,
523
+ toolDialect: args.toolDialect,
524
+ kvCache: cacheable ? args.cacheKey : undefined
525
+ };
526
+ if (args.capture) {
527
+ yield {
528
+ type: 'inference-call',
529
+ call: {
530
+ round: args.round,
531
+ droppedTurns: candidate.droppedTurns,
532
+ modelId,
533
+ messages: params.history,
534
+ tools: params.tools,
535
+ generationParams: params.generationParams,
536
+ responseFormat: params.responseFormat,
537
+ toolDialect: params.toolDialect,
538
+ cacheKey: params.kvCache,
539
+ promptPrefix: args.promptPrefix
540
+ }
541
+ };
542
+ }
499
543
  try {
500
- const result = sdk.completion({
501
- modelId,
502
- history: projectVisionHistory(candidate.history),
503
- stream: true,
504
- tools: args.tools,
505
- generationParams: args.generationParams,
506
- ...(args.responseFormat ? { responseFormat: args.responseFormat } : {}),
507
- toolDialect: args.toolDialect,
508
- ...(cacheable && args.cacheKey ? { kvCache: args.cacheKey } : {})
509
- });
544
+ const result = sdk.completion(params);
510
545
  result.final.catch(noop);
511
546
  const startInThink = args.generationParams?.reasoning_budget === -1;
512
547
  for await (const event of runRoundTokens(sdk, result, state, args.signal, startInThink)) {
@@ -518,6 +553,17 @@ async function* runRecoveredRoundWith(sdk, args, modelId) {
518
553
  const final = state.stopToken
519
554
  ? await truncatedFinal(result.final, state.rawContentText)
520
555
  : await raceAbort(result.final, args.signal);
556
+ if (args.capture) {
557
+ yield {
558
+ type: 'inference-sent',
559
+ round: args.round,
560
+ droppedTurns: candidate.droppedTurns,
561
+ messages: sentMessages(final.stats) ?? undefined,
562
+ tokens: roundTokens(final.stats),
563
+ outcome: 'completed',
564
+ reason: undefined
565
+ };
566
+ }
521
567
  const replay = unprovenReplay(state, final);
522
568
  hlog('final', {
523
569
  stopReason: final.stopReason,
@@ -535,6 +581,17 @@ async function* runRecoveredRoundWith(sdk, args, modelId) {
535
581
  };
536
582
  }
537
583
  catch (err) {
584
+ if (args.capture) {
585
+ yield {
586
+ type: 'inference-sent',
587
+ round: args.round,
588
+ droppedTurns: candidate.droppedTurns,
589
+ messages: undefined,
590
+ tokens: undefined,
591
+ outcome: isContextOverflowError(err) ? 'overflowed' : 'failed',
592
+ reason: err instanceof Error ? err.message : String(err)
593
+ };
594
+ }
538
595
  if (!isContextOverflowError(err))
539
596
  throw err;
540
597
  if (emitted)
@@ -551,7 +608,7 @@ function* reportUnnamedWrites(said, landed) {
551
608
  if (unreported)
552
609
  yield { type: 'content', text: unreported };
553
610
  }
554
- 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 = [] }) {
611
+ 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 }) {
555
612
  const pipeline = new HookPipeline();
556
613
  const agentId = agent?.id ?? null;
557
614
  const tools = permittedTools(allTools, agent?.disabledToolsets);
@@ -789,7 +846,9 @@ export async function* completion(sdk, { modelId, acquireRound, model, agent, ct
789
846
  let mute = 0;
790
847
  let narrated = false;
791
848
  let cappedRounds = 0;
792
- for (let round = 0; round < MAX_TOOL_ROUNDS; round++) {
849
+ let roundsSent = 0;
850
+ let round = 0;
851
+ for (; round < MAX_TOOL_ROUNDS; round++) {
793
852
  if (signal?.aborted)
794
853
  throw new AbortedError();
795
854
  if (Date.now() >= runBudget.deadlineMs) {
@@ -820,13 +879,17 @@ export async function* completion(sdk, { modelId, acquireRound, model, agent, ct
820
879
  responseFormat,
821
880
  toolDialect,
822
881
  cacheKey: roundCacheKey,
823
- signal
882
+ signal,
883
+ round,
884
+ promptPrefix,
885
+ capture: captureInferenceCalls
824
886
  });
887
+ roundsSent = round + 1;
825
888
  const final = recovered.final;
826
889
  if (!recovered.cacheable)
827
890
  roundCacheKey = undefined;
828
891
  history = recovered.history;
829
- collectStats(stats, final.stats);
892
+ collectStats(stats, final.stats, final.stopReason);
830
893
  hlog('round stats', { round, wallMs: Date.now() - roundStarted, ...(final.stats ?? {}) });
831
894
  const markup = stripToolResponseBlocks(truncateAtControlToken(final.raw.fullText) || recovered.unproven || '');
832
895
  let toolCalls = final.toolCalls?.length
@@ -1060,9 +1123,12 @@ export async function* completion(sdk, { modelId, acquireRound, model, agent, ct
1060
1123
  tools: undefined,
1061
1124
  generationParams,
1062
1125
  cacheKey: roundCacheKey,
1063
- signal
1126
+ signal,
1127
+ round: roundsSent,
1128
+ promptPrefix: promptPrefixHash({ system: systemContent, tools: undefined }),
1129
+ capture: captureInferenceCalls
1064
1130
  });
1065
- collectStats(stats, recovered.final.stats);
1131
+ collectStats(stats, recovered.final.stats, recovered.final.stopReason);
1066
1132
  const answer = recovered.replay ? stripToolCallMarkup(recovered.replay) : '';
1067
1133
  if (answer)
1068
1134
  yield { type: 'content', text: answer };
@@ -1,6 +1,6 @@
1
1
  import { Readable } from 'streamx';
2
- import { errorMessage } from "../error-fields.js";
3
- import { resolveModelSrc } from "../models/model-source.js";
2
+ import { errorMessage } from '../error-fields.js';
3
+ import { resolveModelSrc } from '../models/model-source.js';
4
4
  const noop = () => { };
5
5
  export function download(sdkOrLoader, args, onSettled) {
6
6
  const { model, addon = 'llm', seed, signal, projection, companions = [], assetSizes } = args;
@@ -1,5 +1,5 @@
1
1
  import { ascii } from 'asenion';
2
- import { CURRENCY_CODES, SPEECH_LEXICON } from "./speech-lexicon.js";
2
+ import { CURRENCY_CODES, SPEECH_LEXICON } from './speech-lexicon.js';
3
3
  const EMOJI_MODIFIERS = /[\uFE0E\uFE0F\u200D\u{1F3FB}-\u{1F3FF}]/gu;
4
4
  const UNSPEAKABLE = /[^\nA-Za-z0-9 .,;:!?'"()\u002D_]/gu;
5
5
  export function normalizeForSpeech(text, lang = 'en') {
@@ -1,4 +1,4 @@
1
- import { harnessLogEnabled, hlog } from "../log.js";
1
+ import { harnessLogEnabled, hlog } from '../log.js';
2
2
  export function logToolPrompt({ promptPrefix, modelId, cacheKey, agentId, messageCount, responseFormat, tools = [], definitions, activeSkills, skillsSelected, enabledSkills, mentionedSkill, loadedSkills, toolOps }) {
3
3
  if (!harnessLogEnabled())
4
4
  return;
@@ -1,5 +1,5 @@
1
- import { parseToolGrant } from "../tools/skills/tool-grants.js";
2
- import { SKILL_TOOL_NAME, WEB_SEARCH_TOOL_NAME } from "./tool-names.js";
1
+ import { parseToolGrant } from '../tools/skills/tool-grants.js';
2
+ import { SKILL_TOOL_NAME, WEB_SEARCH_TOOL_NAME } from './tool-names.js';
3
3
  export function collectToolGrants(skills) {
4
4
  const grants = {
5
5
  grantedNames: new Set(),
@@ -1,4 +1,4 @@
1
- import { SKILL_TOOL_NAME } from "./tool-names.js";
1
+ import { SKILL_TOOL_NAME } from './tool-names.js';
2
2
  export const DIRECT_CALL_ID = 'call-direct';
3
3
  export const TOOL_CONTINUATION_NUDGE = "[Tool results above. Continue the user's request: call the next tool, or answer.]";
4
4
  export function toolResultTurn(name, id, output) {
@@ -1,4 +1,4 @@
1
- import { detectToolDialect } from "../models/tool-dialect.js";
1
+ import { detectToolDialect } from '../models/tool-dialect.js';
2
2
  const QWEN35 = { prose: 4.38, schema: 4.08, toolBlockTokens: 189 };
3
3
  const DENSITY_BY_DIALECT = new Map([['qwen35', QWEN35]]);
4
4
  export function densityFor(modelName) {
@@ -1,7 +1,7 @@
1
1
  import b4a from 'b4a';
2
- import { AbortedError } from "../helpers/race-abort.js";
3
- import { hlog } from "../log.js";
4
- import { normalizeForSpeech } from "./speech-text.js";
2
+ import { AbortedError } from '../helpers/race-abort.js';
3
+ import { hlog } from '../log.js';
4
+ import { normalizeForSpeech } from './speech-text.js';
5
5
  export const SUPERTONIC_SAMPLE_RATE = 44100;
6
6
  export function createVoiceLane() {
7
7
  let tail = Promise.resolve();
@@ -1,18 +1,18 @@
1
1
  import EventEmitter from 'events';
2
2
  import fs from 'fs';
3
- import { settleOnClose } from "./rpc-session.js";
3
+ import { settleOnClose } from './rpc-session.js';
4
4
  import { harnessClient } from '../spec/calls.js';
5
5
  import HRPC from '../spec/hrpc/index.js';
6
- import { unsupportedKvCacheDeletion } from "./capabilities/kv-cache.js";
7
- import { hlog } from "./log.js";
8
- import { assertEmbedDevice } from "./models/embed-config.js";
9
- import { errorCode, errorMessage } from "./error-fields.js";
10
- import { pushQueue } from "./queue.js";
11
- import { stageFile, sweepStaging } from "./staging.js";
12
- import { readInstall, readSetup } from "./tools/skills/manifest-parse.js";
13
- import { SKILL_STATE } from "./tools/skills/skill-state.js";
14
- import { asToolset } from "./tools/toolsets.js";
15
- import { fromDownloadWire, fromWire, unpackVectors } from "./wire.js";
6
+ import { unsupportedKvCacheDeletion } from './capabilities/kv-cache.js';
7
+ import { hlog } from './log.js';
8
+ import { assertEmbedDevice } from './models/embed-config.js';
9
+ import { errorCode, errorMessage } from './error-fields.js';
10
+ import { pushQueue } from './queue.js';
11
+ import { stageFile, sweepStaging } from './staging.js';
12
+ import { readInstall, readSetup } from './tools/skills/manifest-parse.js';
13
+ import { SKILL_STATE } from './tools/skills/skill-state.js';
14
+ import { asToolset } from './tools/toolsets.js';
15
+ import { fromDownloadWire, fromWire, unpackVectors } from './wire.js';
16
16
  export const HARNESS_DIED = 'HARNESS_DIED';
17
17
  export function connectHarness(transport) {
18
18
  return new RemoteHarness(transport);
@@ -112,6 +112,7 @@ export class RemoteHarness extends EventEmitter {
112
112
  thinkingDefault: context.thinkingDefault,
113
113
  generationParams: context.generationParams,
114
114
  responseFormat: context.responseFormat,
115
+ captureInferenceCalls: context.captureInferenceCalls,
115
116
  messages: context.messages.map(({ role, content, attachments }) => ({
116
117
  role,
117
118
  content,
@@ -1,4 +1,4 @@
1
- import { TOOL_CONTINUATION_NUDGE } from "./capabilities/tool-turns.js";
1
+ import { TOOL_CONTINUATION_NUDGE } from './capabilities/tool-turns.js';
2
2
  export const TOOL_RESULT_TRUNCATION_MARKER = '\n[tool result truncated for context]\n';
3
3
  function isTurnBoundary(message) {
4
4
  return message.role === 'user' && message.content !== TOOL_CONTINUATION_NUDGE;
@@ -48,6 +48,7 @@ export interface CompletionContext {
48
48
  toolConfigs?: Record<string, Record<string, unknown>>;
49
49
  generationParams?: LlmGenerationParams;
50
50
  responseFormat?: ResponseFormat;
51
+ captureInferenceCalls?: boolean;
51
52
  grantedDirs?: string[];
52
53
  grantedDrives?: GrantedDrive[];
53
54
  driveOp?: DriveOpFn;
@@ -1,8 +1,8 @@
1
1
  import b4a from 'b4a';
2
2
  import fs from 'fs';
3
- import { runPython } from "../tools/exec/adapters/python/pyodide.js";
4
- import { planVendoredInstall, vendoredManifest, wheelsDir } from "../tools/exec/adapters/python/wheels.js";
5
- export { closePythonWorker as closeDocxWorker } from "../tools/exec/adapters/python/worker/client.js";
3
+ import { runPython } from '../tools/exec/adapters/python/pyodide.js';
4
+ import { planVendoredInstall, vendoredManifest, wheelsDir } from '../tools/exec/adapters/python/wheels.js';
5
+ export { closePythonWorker as closeDocxWorker } from '../tools/exec/adapters/python/worker/client.js';
6
6
  const MAX_OFFICE_BYTES = 20 * 1024 * 1024;
7
7
  const PACKAGES = ['python-docx==1.2.0'];
8
8
  const EXTRACT = `from docx import Document