@skill-harness/adapters 0.17.0 → 0.19.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.
Files changed (121) hide show
  1. package/dist/index.d.ts +0 -30
  2. package/dist/index.js +0 -30
  3. package/dist/model-pricing.d.ts +3 -0
  4. package/dist/model-pricing.js +24 -0
  5. package/dist/pi.js +26 -135
  6. package/package.json +5 -4
  7. package/prices/model-prices.json +43 -0
  8. package/dist/archive-access.d.ts +0 -58
  9. package/dist/archive-access.js +0 -61
  10. package/dist/archive-checkpoint.d.ts +0 -47
  11. package/dist/archive-checkpoint.js +0 -116
  12. package/dist/archive-facts.d.ts +0 -19
  13. package/dist/archive-facts.js +0 -20
  14. package/dist/archive-observer.d.ts +0 -21
  15. package/dist/archive-observer.js +0 -79
  16. package/dist/archive-policy.d.ts +0 -107
  17. package/dist/archive-policy.js +0 -135
  18. package/dist/archive-read-capability.d.ts +0 -49
  19. package/dist/archive-read-capability.js +0 -45
  20. package/dist/archive-retention-policy.d.ts +0 -52
  21. package/dist/archive-retention-policy.js +0 -49
  22. package/dist/archived-work.d.ts +0 -45
  23. package/dist/archived-work.js +0 -78
  24. package/dist/blind-intervention.d.ts +0 -35
  25. package/dist/blind-intervention.js +0 -218
  26. package/dist/codex-diagnostic-model.d.ts +0 -14
  27. package/dist/codex-diagnostic-model.js +0 -39
  28. package/dist/codex-host-observer.d.ts +0 -111
  29. package/dist/codex-host-observer.js +0 -309
  30. package/dist/codex-https.d.ts +0 -7
  31. package/dist/codex-https.js +0 -221
  32. package/dist/codex-model-profile.d.ts +0 -38
  33. package/dist/codex-model-profile.js +0 -54
  34. package/dist/codex-producer-ipc.d.ts +0 -55
  35. package/dist/codex-producer-ipc.js +0 -67
  36. package/dist/codex-sdk-transport.d.ts +0 -50
  37. package/dist/codex-sdk-transport.js +0 -294
  38. package/dist/codex-subscription.d.ts +0 -114
  39. package/dist/codex-subscription.js +0 -268
  40. package/dist/evidence-archive.d.ts +0 -65
  41. package/dist/evidence-archive.js +0 -225
  42. package/dist/execution-projection-schema.d.ts +0 -10
  43. package/dist/execution-projection-schema.js +0 -30
  44. package/dist/execution-retention-archive.d.ts +0 -69
  45. package/dist/execution-retention-archive.js +0 -154
  46. package/dist/generated/retention-v2-contract.d.ts +0 -72
  47. package/dist/generated/retention-v2-contract.js +0 -105
  48. package/dist/generated/retention-v2-json.d.ts +0 -24
  49. package/dist/generated/retention-v2-json.js +0 -268
  50. package/dist/generated/retention-v2-native-json.d.ts +0 -2
  51. package/dist/generated/retention-v2-native-json.js +0 -33
  52. package/dist/generated/retention-v2-native.d.ts +0 -58
  53. package/dist/generated/retention-v2-native.js +0 -155
  54. package/dist/generated/retention-v2-pin.d.ts +0 -2
  55. package/dist/generated/retention-v2-pin.js +0 -4
  56. package/dist/generated/retention-v2-types.d.ts +0 -49
  57. package/dist/generated/retention-v2-types.js +0 -2
  58. package/dist/generated/retention-v2-work-types.d.ts +0 -260
  59. package/dist/generated/retention-v2-work-types.js +0 -13
  60. package/dist/generated/work-v4/execution-id.d.ts +0 -5
  61. package/dist/generated/work-v4/execution-id.js +0 -14
  62. package/dist/generated/work-v4/json.d.ts +0 -24
  63. package/dist/generated/work-v4/json.js +0 -268
  64. package/dist/generated/work-v4/occurrences.d.ts +0 -226
  65. package/dist/generated/work-v4/occurrences.js +0 -116
  66. package/dist/generated/work-v4/pin.d.ts +0 -1
  67. package/dist/generated/work-v4/pin.js +0 -3
  68. package/dist/generated/work-v4/projection.d.ts +0 -294
  69. package/dist/generated/work-v4/projection.js +0 -238
  70. package/dist/generated/work-v4/reader.d.ts +0 -24
  71. package/dist/generated/work-v4/reader.js +0 -109
  72. package/dist/generated/work-v4/snapshot.d.ts +0 -28
  73. package/dist/generated/work-v4/snapshot.js +0 -268
  74. package/dist/generated/work-v4/types.d.ts +0 -260
  75. package/dist/generated/work-v4/types.js +0 -13
  76. package/dist/generated/work-v4/validation.d.ts +0 -13
  77. package/dist/generated/work-v4/validation.js +0 -227
  78. package/dist/installed-review-session.d.ts +0 -28
  79. package/dist/installed-review-session.js +0 -166
  80. package/dist/intervention-run.d.ts +0 -403
  81. package/dist/intervention-run.js +0 -169
  82. package/dist/learning-case.d.ts +0 -12
  83. package/dist/learning-case.js +0 -15
  84. package/dist/learning-journal.d.ts +0 -18
  85. package/dist/learning-journal.js +0 -256
  86. package/dist/learning-lifecycle.d.ts +0 -28
  87. package/dist/learning-lifecycle.js +0 -66
  88. package/dist/learning-trust-setup.d.ts +0 -64
  89. package/dist/learning-trust-setup.js +0 -55
  90. package/dist/learning-workspace.d.ts +0 -1084
  91. package/dist/learning-workspace.js +0 -705
  92. package/dist/principal-payload-port.d.ts +0 -25
  93. package/dist/principal-payload-port.js +0 -40
  94. package/dist/producer-product.d.ts +0 -70
  95. package/dist/producer-product.js +0 -186
  96. package/dist/producer-review.d.ts +0 -53
  97. package/dist/producer-review.js +0 -207
  98. package/dist/prompt-capture-extension.d.ts +0 -10
  99. package/dist/prompt-capture-extension.js +0 -26
  100. package/dist/prompt-provenance.d.ts +0 -22
  101. package/dist/prompt-provenance.js +0 -146
  102. package/dist/reviewed-archive-export.d.ts +0 -42
  103. package/dist/reviewed-archive-export.js +0 -78
  104. package/dist/session-observation.d.ts +0 -50
  105. package/dist/session-observation.js +0 -186
  106. package/dist/session-retention.d.ts +0 -48
  107. package/dist/session-retention.js +0 -121
  108. package/dist/trust-lifecycle.d.ts +0 -152
  109. package/dist/trust-lifecycle.js +0 -209
  110. package/dist/weekly-investigation.d.ts +0 -237
  111. package/dist/weekly-investigation.js +0 -330
  112. package/dist/work-candidates.d.ts +0 -29
  113. package/dist/work-candidates.js +0 -78
  114. package/dist/work-case-archive.d.ts +0 -25
  115. package/dist/work-case-archive.js +0 -63
  116. package/dist/work-case-review.d.ts +0 -45
  117. package/dist/work-case-review.js +0 -220
  118. package/dist/work-signal-cases.d.ts +0 -15
  119. package/dist/work-signal-cases.js +0 -54
  120. package/dist/work-signal-observation.d.ts +0 -23
  121. package/dist/work-signal-observation.js +0 -89
package/dist/index.d.ts CHANGED
@@ -1,36 +1,6 @@
1
- export * from './producer-product.js';
2
1
  import type { HarnessAdapter } from "@skill-harness/core";
3
2
  import { piAdapter } from "./pi.js";
4
3
  export declare function getAdapter(name: string): HarnessAdapter;
5
4
  export { piAdapter };
6
- export * from "./prompt-provenance.js";
7
5
  export * from "./trajectory.js";
8
6
  export * from "./pi-daddy-ledger-v3.js";
9
- export * from "./evidence-archive.js";
10
- export * from "./archive-checkpoint.js";
11
- export * from "./archive-policy.js";
12
- export * from "./execution-retention-archive.js";
13
- export * from "./work-candidates.js";
14
- export * from "./work-case-archive.js";
15
- export * from "./work-signal-observation.js";
16
- export * from "./work-signal-cases.js";
17
- export * from "./work-case-review.js";
18
- export * from "./archive-read-capability.js";
19
- export * from "./archived-work.js";
20
- export * from "./blind-intervention.js";
21
- export * from "./learning-lifecycle.js";
22
- export * from "./learning-workspace.js";
23
- export * from "./learning-trust-setup.js";
24
- export { learningHash, learningFile } from "./learning-journal.js";
25
- export * from "./learning-case.js";
26
- export * from "./archive-observer.js";
27
- export * from "./weekly-investigation.js";
28
- export * from "./intervention-run.js";
29
- export * from "./principal-payload-port.js";
30
- export * from "./reviewed-archive-export.js";
31
- export * from "./archive-access.js";
32
- export * from "./archive-facts.js";
33
- export * from "./trust-lifecycle.js";
34
- export * from "./producer-review.js";
35
- export * from './session-observation.js';
36
- export * from './session-retention.js';
package/dist/index.js CHANGED
@@ -1,4 +1,3 @@
1
- export * from './producer-product.js';
2
1
  import { piAdapter } from "./pi.js";
3
2
  /**
4
3
  * Registered harnesses. pi is the only one (per project scope). The interface
@@ -15,35 +14,6 @@ export function getAdapter(name) {
15
14
  return a;
16
15
  }
17
16
  export { piAdapter };
18
- export * from "./prompt-provenance.js";
19
17
  export * from "./trajectory.js";
20
18
  export * from "./pi-daddy-ledger-v3.js";
21
- export * from "./evidence-archive.js";
22
- export * from "./archive-checkpoint.js";
23
- export * from "./archive-policy.js";
24
- export * from "./execution-retention-archive.js";
25
- export * from "./work-candidates.js";
26
- export * from "./work-case-archive.js";
27
- export * from "./work-signal-observation.js";
28
- export * from "./work-signal-cases.js";
29
- export * from "./work-case-review.js";
30
- export * from "./archive-read-capability.js";
31
- export * from "./archived-work.js";
32
- export * from "./blind-intervention.js";
33
- export * from "./learning-lifecycle.js";
34
- export * from "./learning-workspace.js";
35
- export * from "./learning-trust-setup.js";
36
- export { learningHash, learningFile } from "./learning-journal.js";
37
- export * from "./learning-case.js";
38
- export * from "./archive-observer.js";
39
- export * from "./weekly-investigation.js";
40
- export * from "./intervention-run.js";
41
- export * from "./principal-payload-port.js";
42
- export * from "./reviewed-archive-export.js";
43
- export * from "./archive-access.js";
44
- export * from "./archive-facts.js";
45
- export * from "./trust-lifecycle.js";
46
- export * from "./producer-review.js";
47
- export * from './session-observation.js';
48
- export * from './session-retention.js';
49
19
  //# sourceMappingURL=index.js.map
@@ -0,0 +1,3 @@
1
+ import { type ExecutionTraceV1 } from "@skill-harness/core";
2
+ /** Apply the repository's dated token prices to one Pi execution trace. */
3
+ export declare function priceSubjectUsage(trace: ExecutionTraceV1): ExecutionTraceV1;
@@ -0,0 +1,24 @@
1
+ import { traceSha256 } from "@skill-harness/core";
2
+ import table from "../prices/model-prices.json" with { type: "json" };
3
+ const prices = table.models;
4
+ const MILLION = 1_000_000;
5
+ /** Apply the repository's dated token prices to one Pi execution trace. */
6
+ export function priceSubjectUsage(trace) {
7
+ if (!trace.metrics)
8
+ return trace;
9
+ const price = prices[trace.subject.model];
10
+ const { input_tokens, output_tokens, cache_read_tokens } = trace.metrics;
11
+ const hasUsage = input_tokens !== null || output_tokens !== null || cache_read_tokens !== null;
12
+ const cost = price && hasUsage
13
+ ? ((input_tokens ?? 0) * price.input + (cache_read_tokens ?? 0) * price.cachedInput + (output_tokens ?? 0) * price.output) / MILLION
14
+ : null;
15
+ const metrics = {
16
+ ...trace.metrics,
17
+ cost_usd: cost !== null && cost > 0 ? cost : null,
18
+ cost_source: cost !== null && cost > 0 ? "price-table" : "unreported",
19
+ price_as_of: table.asOf,
20
+ };
21
+ const priced = { ...trace, cost_usd: metrics.cost_usd, metrics };
22
+ return { ...priced, trace_sha256: traceSha256(priced) };
23
+ }
24
+ //# sourceMappingURL=model-pricing.js.map
package/dist/pi.js CHANGED
@@ -1,72 +1,10 @@
1
- import { existsSync, mkdtempSync, readFileSync, rmSync, statSync, writeFileSync } from "node:fs";
1
+ import { existsSync, mkdtempSync, readFileSync, statSync } from "node:fs";
2
2
  import { tmpdir, homedir } from "node:os";
3
- import { randomBytes } from "node:crypto";
4
3
  import { join, resolve } from "node:path";
5
- import { fileURLToPath } from "node:url";
6
4
  import { runPiJson } from "./pi-json.js";
7
- import { collectTrajectorySources, normalizePiTraces, resequence } from "./trajectory.js";
8
- import { bindPromptObservation, observeProviderPayload, promptCaptureIsTrusted, verifyPromptSummary } from "./prompt-provenance.js";
9
- import { exec, onPath, envNum, traceSha256, withProviderFailure, splitPromptDoc } from "@skill-harness/core";
5
+ import { priceSubjectUsage } from "./model-pricing.js";
6
+ import { exec, onPath, envNum, traceSha256, withProviderFailure } from "@skill-harness/core";
10
7
  const PI_TIMEOUT_MS = envNum("PI_TIMEOUT_MS", 300_000);
11
- const PROMPT_CAPTURE_EXTENSION = fileURLToPath(new URL("./prompt-capture-extension.js", import.meta.url));
12
- function contractFor(req) {
13
- if (req.systemPromptFile) {
14
- const raw = readFileSync(req.systemPromptFile, "utf8");
15
- return { text: raw, raw, mechanism: "system-prompt-file" };
16
- }
17
- const raw = readFileSync(join(requireSkillDir(req.skillDir, req.mode), "SKILL.md"), "utf8");
18
- const body = splitPromptDoc(raw).body;
19
- if (req.mode === "red")
20
- return { text: body, raw, mechanism: "none" };
21
- return { text: body, raw, mechanism: req.mode === "green" ? "pi-skill" : "append-system-prompt" };
22
- }
23
- const RUNTIME_INJECTION_ENV = ["NODE_OPTIONS", "NODE_PATH", "LD_PRELOAD", "DYLD_INSERT_LIBRARIES"];
24
- function hasRuntimeInjection(req) {
25
- return Boolean(req.armEnv && Object.keys(req.armEnv).length) || RUNTIME_INJECTION_ENV.some(key => Boolean(process.env[key]));
26
- }
27
- function captureSetup(req, env, contract, counter) {
28
- if (!req.onPromptObservation)
29
- return { env, finish: () => { } };
30
- // Arbitrary scenario/arm extensions and runtime-injection env execute in Pi's
31
- // process with full Node authority. Refuse a forgeable positive observation.
32
- if (!promptCaptureIsTrusted(req.extensions?.length ?? 0, hasRuntimeInjection(req)))
33
- return { env, finish: () => {
34
- const empty = observeProviderPayload({}, contract.text, contract.mechanism, counter.value++);
35
- req.onPromptObservation?.({ ...empty, status: "ERROR", error: "prompt delivery provenance is unauthenticated when subject extensions or runtime-injection env share Pi's process" });
36
- } };
37
- const dir = mkdtempSync(join(tmpdir(), "skill-harness-prompt-"));
38
- const path = join(dir, "observations.jsonl"), contractPath = join(dir, "contract.json");
39
- const authenticationKey = randomBytes(32).toString("hex");
40
- writeFileSync(path, "", { mode: 0o600 });
41
- writeFileSync(contractPath, JSON.stringify({ text: contract.text, mechanism: contract.mechanism, authentication_key: authenticationKey }), { mode: 0o600 });
42
- const finish = () => {
43
- try {
44
- const lines = readFileSync(path, "utf8").split("\n").filter(Boolean);
45
- const parsed = lines.map(line => { try {
46
- return JSON.parse(line);
47
- }
48
- catch {
49
- return null;
50
- } });
51
- const records = parsed.slice(0, -1), summary = parsed.at(-1);
52
- if (!verifyPromptSummary(summary, records.length, authenticationKey)) {
53
- const empty = observeProviderPayload({}, contract.text, contract.mechanism, counter.value++);
54
- req.onPromptObservation?.({ ...empty, status: "ERROR", error: "Pi prompt observation log is missing, truncated, replayed, or unauthenticated" });
55
- }
56
- else
57
- records.forEach((record, observerRequestIndex) => {
58
- req.onPromptObservation?.(bindPromptObservation(record, contract.text, contract.mechanism, counter.value++, authenticationKey, observerRequestIndex));
59
- });
60
- }
61
- finally {
62
- rmSync(dir, { recursive: true, force: true });
63
- }
64
- };
65
- return { env: { ...(env ?? process.env), SKILL_HARNESS_PROMPT_CAPTURE_FILE: path, SKILL_HARNESS_PROMPT_CONTRACT_FILE: contractPath }, finish };
66
- }
67
- function observerFlags(req) {
68
- return req.onPromptObservation && promptCaptureIsTrusted(req.extensions?.length ?? 0, hasRuntimeInjection(req)) ? ["--extension", PROMPT_CAPTURE_EXTENSION] : [];
69
- }
70
8
  /**
71
9
  * stderr fragments that mean the provider refused the request, so the run measured
72
10
  * nothing about the model. Substring matching on a message pi passes through from
@@ -160,7 +98,7 @@ function header(turnNo, total, text) {
160
98
  }
161
99
  export const piAdapter = {
162
100
  name: "pi",
163
- observesPrompts: true,
101
+ preferStructured: true,
164
102
  available() {
165
103
  return Promise.resolve(onPath("pi"));
166
104
  },
@@ -196,18 +134,14 @@ export const piAdapter = {
196
134
  "--no-context-files",
197
135
  "--no-extensions",
198
136
  ...extensionFlags(req.extensions),
199
- ...observerFlags(req),
200
137
  "--provider",
201
138
  req.model.provider,
202
139
  "--model",
203
140
  req.model.model,
204
141
  ];
205
- // Bind bytes once: argv and provenance must describe the same contract even if a file changes mid-run.
206
- const contract = contractFor(req);
207
142
  const flags = req.systemPromptFile
208
- ? ["--no-skills", "--append-system-prompt", contract.raw]
209
- : skillFlags(req.mode, req.skillDir, contract.raw);
210
- const requestCounter = { value: 0 };
143
+ ? ["--no-skills", "--append-system-prompt", readFileSync(req.systemPromptFile, "utf8")]
144
+ : skillFlags(req.mode, req.skillDir);
211
145
  const total = req.turns.length;
212
146
  const parts = [];
213
147
  // The arm's env, merged over the harness's own — undefined (not `process.env`)
@@ -222,14 +156,7 @@ export const piAdapter = {
222
156
  let providerFailure = null;
223
157
  if (total === 1) {
224
158
  const args = [...flags, ...common, "--no-session", "-p", req.turns[0]];
225
- const capture = captureSetup(req, env, contract, requestCounter);
226
- let r;
227
- try {
228
- r = await exec("pi", args, { cwd: req.cwd, timeoutMs: PI_TIMEOUT_MS, env: capture.env });
229
- }
230
- finally {
231
- capture.finish();
232
- }
159
+ const r = await exec("pi", args, { cwd: req.cwd, timeoutMs: PI_TIMEOUT_MS, env });
233
160
  parts.push(header(1, 1, req.turns[0]));
234
161
  parts.push(`<<< ASSISTANT:\n${r.stdout.trim()}\n`);
235
162
  if (r.code !== 0) {
@@ -243,14 +170,7 @@ export const piAdapter = {
243
170
  for (let i = 0; i < total; i++) {
244
171
  const turnFlags = i === 0 ? ["--session-dir", session] : ["--session-dir", session, "-c"];
245
172
  const args = [...flags, ...common, ...turnFlags, "-p", req.turns[i]];
246
- const capture = captureSetup(req, env, contract, requestCounter);
247
- let r;
248
- try {
249
- r = await exec("pi", args, { cwd: req.cwd, timeoutMs: PI_TIMEOUT_MS, env: capture.env });
250
- }
251
- finally {
252
- capture.finish();
253
- }
173
+ const r = await exec("pi", args, { cwd: req.cwd, timeoutMs: PI_TIMEOUT_MS, env });
254
174
  parts.push(header(i + 1, total, req.turns[i]));
255
175
  parts.push(`<<< ASSISTANT:\n${r.stdout.trim()}\n`);
256
176
  if (r.code !== 0) {
@@ -282,17 +202,14 @@ export const piAdapter = {
282
202
  "--no-context-files",
283
203
  "--no-extensions",
284
204
  ...extensionFlags(req.extensions),
285
- ...observerFlags(req),
286
205
  "--provider",
287
206
  req.model.provider,
288
207
  "--model",
289
208
  req.model.model,
290
209
  ];
291
- const contract = contractFor(req);
292
210
  const flags = req.systemPromptFile
293
- ? ["--no-skills", "--append-system-prompt", contract.raw]
294
- : skillFlags(req.mode, req.skillDir, contract.raw);
295
- const requestCounter = { value: 0 };
211
+ ? ["--no-skills", "--append-system-prompt", readFileSync(req.systemPromptFile, "utf8")]
212
+ : skillFlags(req.mode, req.skillDir);
296
213
  const piVersion = await this.version();
297
214
  const total = req.turns.length;
298
215
  const traces = [];
@@ -309,26 +226,19 @@ export const piAdapter = {
309
226
  ? ["--session-dir", session]
310
227
  : ["--session-dir", session, "-c"];
311
228
  const args = [...flags, ...common, "--mode", "json", ...turnFlags, "-p", req.turns[i]];
312
- const capture = captureSetup(req, env, contract, requestCounter);
313
- let r;
314
- try {
315
- r = await runPiJson({
316
- args,
317
- cwd: req.cwd,
318
- timeoutMs: PI_TIMEOUT_MS,
319
- piVersion,
320
- subject: req.model,
321
- scenarioId: req.scenarioId ?? "(unknown)",
322
- mode: req.mode,
323
- rep: req.rep ?? 0,
324
- turn: i,
325
- homeDir: homedir(),
326
- env: capture.env,
327
- });
328
- }
329
- finally {
330
- capture.finish();
331
- }
229
+ const r = await runPiJson({
230
+ args,
231
+ cwd: req.cwd,
232
+ timeoutMs: PI_TIMEOUT_MS,
233
+ piVersion,
234
+ subject: req.model,
235
+ scenarioId: req.scenarioId ?? "(unknown)",
236
+ mode: req.mode,
237
+ rep: req.rep ?? 0,
238
+ turn: i,
239
+ homeDir: homedir(),
240
+ env,
241
+ });
332
242
  // A stream with no terminal events at all is not evidence of a clean run.
333
243
  // Fail loudly here rather than let an empty trace satisfy a `forbid_calls`
334
244
  // gate — "the model called nothing" and "we recorded nothing" must not
@@ -350,35 +260,16 @@ export const piAdapter = {
350
260
  // leaves it unrecoverable from the saved transcript.
351
261
  if (providerFailure === null && r.providerFailure)
352
262
  providerFailure = r.providerFailure;
353
- traces.push(r.trace);
263
+ const pricedTrace = priceSubjectUsage(r.trace);
264
+ traces.push(pricedTrace);
354
265
  parts.push(header(i + 1, total, req.turns[i]));
355
- parts.push(`<<< ASSISTANT:\n${r.trace.final_text.trim()}\n`);
266
+ parts.push(`<<< ASSISTANT:\n${pricedTrace.final_text.trim()}\n`);
356
267
  if (r.code !== 0)
357
268
  parts.push(`[pi exited ${r.code} on turn ${i + 1}]\n${r.stderr.trim()}\n`);
358
269
  }
359
- const native = req.eventSources?.length
360
- ? collectTrajectorySources(req.cwd, req.eventSources)
361
- : { events: [], errors: [] };
362
- const piEvents = normalizePiTraces(traces);
363
- const combined = [...piEvents, ...native.events];
364
- const chronologyErrors = [];
365
- if (piEvents.length && native.events.length) {
366
- if (combined.some((event) => !event.at || !Number.isFinite(Date.parse(event.at)))) {
367
- chronologyErrors.push("pi/native events cannot be globally ordered because at least one event has no valid `at` timestamp");
368
- }
369
- else {
370
- const piTimes = new Set(piEvents.map((event) => Date.parse(event.at)));
371
- if (native.events.some((event) => piTimes.has(Date.parse(event.at)))) {
372
- chronologyErrors.push("pi/native events contain equal timestamps, so strict cross-source order is ambiguous");
373
- }
374
- }
375
- }
376
- const eventErrors = [...native.errors, ...chronologyErrors];
377
270
  return {
378
271
  transcript: withProviderFailure(parts.join("\n"), providerFailure),
379
272
  traces,
380
- events: resequence(combined),
381
- ...(eventErrors.length ? { eventErrors } : {}),
382
273
  ...(providerFailure ? { providerFailure } : {}),
383
274
  };
384
275
  },
package/package.json CHANGED
@@ -1,13 +1,14 @@
1
1
  {
2
2
  "name": "@skill-harness/adapters",
3
- "version": "0.17.0",
3
+ "version": "0.19.0",
4
4
  "description": "skill-harness harness adapters — pi runner + claude-code judge routing (internal API)",
5
5
  "type": "module",
6
6
  "license": "MIT",
7
7
  "main": "./dist/index.js",
8
8
  "types": "./dist/index.d.ts",
9
9
  "exports": {
10
- ".": "./dist/index.js"
10
+ ".": "./dist/index.js",
11
+ "./prices/*.json": "./prices/*.json"
11
12
  },
12
13
  "keywords": [
13
14
  "agent-skills",
@@ -23,6 +24,7 @@
23
24
  "files": [
24
25
  "dist/**/*.js",
25
26
  "dist/**/*.d.ts",
27
+ "prices/*.json",
26
28
  "LICENSE",
27
29
  "README.md"
28
30
  ],
@@ -40,7 +42,6 @@
40
42
  "prepack": "node ../../scripts/release-pack.mjs --guard"
41
43
  },
42
44
  "dependencies": {
43
- "@skill-harness/core": "0.17.0",
44
- "typebox": "1.3.4"
45
+ "@skill-harness/core": "0.19.0"
45
46
  }
46
47
  }
@@ -0,0 +1,43 @@
1
+ {
2
+ "asOf": "2026-09-29",
3
+ "currency": "USD",
4
+ "unit": "per_million_tokens",
5
+ "models": {
6
+ "accounts/fireworks/models/deepseek-v4-flash-0731": {
7
+ "input": 0.14,
8
+ "cachedInput": 0.028,
9
+ "output": 0.28,
10
+ "source": "https://fireworks.ai/models/deepseek-ai/deepseek-v4-flash-0731"
11
+ },
12
+ "accounts/fireworks/models/deepseek-v4-pro": {
13
+ "input": 1.32,
14
+ "cachedInput": 0.044,
15
+ "output": 3.96,
16
+ "source": "https://fireworks.ai/models/deepseek-ai/deepseek-v4-pro-0813"
17
+ },
18
+ "accounts/fireworks/models/deepseek-v4-pro-0813": {
19
+ "input": 1.32,
20
+ "cachedInput": 0.044,
21
+ "output": 3.96,
22
+ "source": "https://fireworks.ai/models/deepseek-ai/deepseek-v4-pro-0813"
23
+ },
24
+ "accounts/fireworks/models/glm-5p2": {
25
+ "input": 1.4,
26
+ "cachedInput": 0.14,
27
+ "output": 4.4,
28
+ "source": "https://fireworks.ai/models/fireworks/glm-5p2"
29
+ },
30
+ "accounts/fireworks/models/glm-5p3-flash": {
31
+ "input": 0.15,
32
+ "cachedInput": 0.03,
33
+ "output": 0.5,
34
+ "source": "https://fireworks.ai/models/fireworks/glm-5p3-flash"
35
+ },
36
+ "accounts/fireworks/models/kimi-k3": {
37
+ "input": 3.0,
38
+ "cachedInput": 0.3,
39
+ "output": 15.0,
40
+ "source": "https://fireworks.ai/models/fireworks/kimi-k3"
41
+ }
42
+ }
43
+ }
@@ -1,58 +0,0 @@
1
- export interface ArchiveAccessPolicy {
2
- archiveRoot: string;
3
- id: string;
4
- expiresAt: number;
5
- maxCalls: number;
6
- maxBytes: number;
7
- purposes: string[];
8
- }
9
- export interface ArchiveConsent {
10
- manifestId: string;
11
- purpose: string;
12
- expiresAt: number;
13
- }
14
- export interface GovernedArchiveRoute {
15
- directory: string;
16
- purpose: string;
17
- }
18
- export declare function createArchiveAccess(path: string, raw: ArchiveAccessPolicy, permissions: string[]): {
19
- inspect: () => {
20
- policy: ArchiveAccessPolicy;
21
- lastObservedNow: number;
22
- consents: {
23
- id: unknown;
24
- grant: ArchiveConsent;
25
- state: string;
26
- }[];
27
- calls: number;
28
- bytes: number;
29
- pending: number;
30
- };
31
- previewConsent: (g: ArchiveConsent) => string;
32
- previewRevocation: (id: string) => string;
33
- consent(raw: ArchiveConsent, permissions: string[], now: number): string;
34
- revoke(id: string, permissions: string[], now: number): void;
35
- read(manifestId: string, purpose: string, maxBytes: number, now?: number): import("./evidence-archive.js").ArchiveRead;
36
- };
37
- /** Shared cooperative access owner. No history deletion, authentication, OS
38
- * deadline guarantee, or reinterpretation of legacy raw archive APIs. */
39
- export declare function openArchiveAccess(path: string): {
40
- inspect: () => {
41
- policy: ArchiveAccessPolicy;
42
- lastObservedNow: number;
43
- consents: {
44
- id: unknown;
45
- grant: ArchiveConsent;
46
- state: string;
47
- }[];
48
- calls: number;
49
- bytes: number;
50
- pending: number;
51
- };
52
- previewConsent: (g: ArchiveConsent) => string;
53
- previewRevocation: (id: string) => string;
54
- consent(raw: ArchiveConsent, permissions: string[], now: number): string;
55
- revoke(id: string, permissions: string[], now: number): void;
56
- read(manifestId: string, purpose: string, maxBytes: number, now?: number): import("./evidence-archive.js").ArchiveRead;
57
- };
58
- export declare function readGovernedArchive(root: string, manifestId: string, maxBytes: number, route: GovernedArchiveRoute, now?: number): import("./evidence-archive.js").ArchiveRead;
@@ -1,61 +0,0 @@
1
- import { learningCopy, learningHash, learningJournal, registerLearningStore, verifyLearningStore } from './learning-journal.js';
2
- import { readArchiveSource } from './evidence-archive.js';
3
- export function createArchiveAccess(path, raw, permissions) {
4
- const policy = learningCopy(raw), binding = learningHash(policy);
5
- if (!permissions.includes(binding))
6
- throw Error('exact archive policy permission required');
7
- validate(policy);
8
- registerLearningStore(policy.archiveRoot, 'access', learningHash(policy.id), path, binding);
9
- learningJournal(path, { type: 'archive-access-v1', policy, binding });
10
- return openArchiveAccess(path);
11
- }
12
- function validate(p) { if (typeof p.id !== 'string' || !p.id.length || p.id.length > 128 || !Number.isSafeInteger(p.expiresAt) || p.expiresAt < 0 || !Number.isSafeInteger(p.maxCalls) || p.maxCalls < 1 || p.maxCalls > 1024 || !Number.isSafeInteger(p.maxBytes) || p.maxBytes < 1 || p.maxBytes > 64 * 1024 * 1024 || !Array.isArray(p.purposes) || !p.purposes.length || p.purposes.length > 16 || new Set(p.purposes).size !== p.purposes.length || p.purposes.some(s => typeof s !== 'string' || !s.length || s.length > 128))
13
- throw Error('bounded archive access policy required'); }
14
- /** Shared cooperative access owner. No history deletion, authentication, OS
15
- * deadline guarantee, or reinterpretation of legacy raw archive APIs. */
16
- export function openArchiveAccess(path) {
17
- const journal = learningJournal(path), first = journal.read()[0].value, policy = learningCopy(first.policy);
18
- validate(policy);
19
- if (first.type !== 'archive-access-v1' || learningHash(policy) !== first.binding)
20
- throw Error('archive policy changed');
21
- const history = () => { verifyLearningStore(policy.archiveRoot, 'access', learningHash(policy.id), path, String(first.binding)); return journal.read(); };
22
- const clock = (now) => { const rows = history(); if (!Number.isSafeInteger(now) || now < Math.max(0, ...rows.map(e => Number(e.value.now ?? 0))))
23
- throw Error('archive access clock rewind'); journal.append(rows.at(-1).id, { type: 'clock', now }); if (now >= policy.expiresAt)
24
- throw Error('archive access expired'); };
25
- const consent = (raw) => { const g = learningCopy(raw); if (!/^[a-f0-9]{64}$/.test(g.manifestId) || !policy.purposes.includes(g.purpose) || !Number.isSafeInteger(g.expiresAt) || g.expiresAt < 0 || g.expiresAt > policy.expiresAt)
26
- throw Error('consent outside policy'); return g; };
27
- const digest = (g) => learningHash({ policy: String(first.binding), consent: consent(g) });
28
- const revokeDigest = (id) => learningHash({ policy: String(first.binding), revoke: id });
29
- const inspect = () => { const rows = history(), claims = rows.filter(e => e.value.type === 'read-claim'), lastObservedNow = Math.max(0, ...rows.map(e => Number(e.value.now ?? 0))); return { policy: learningCopy(policy), lastObservedNow, consents: rows.filter(e => e.value.type === 'consented').map(e => { const grant = e.value.grant; return { id: e.value.consentId, grant: learningCopy(grant), state: rows.some(r => r.value.type === 'revoked' && r.value.consentId === e.value.consentId) ? 'revoked' : lastObservedNow >= Math.min(policy.expiresAt, grant.expiresAt) ? 'expired' : 'not-revoked-at-last-observed-clock' }; }), calls: claims.length, bytes: claims.reduce((n, e) => { const settled = rows.find(s => s.value.type === 'read-settled' && s.value.claim === e.id); return n + Number(settled ? settled.value.bytes : e.value.reserved); }, 0), pending: claims.filter(e => !rows.some(s => s.value.type === 'read-settled' && s.value.claim === e.id)).length }; };
30
- return { inspect, previewConsent: digest, previewRevocation: revokeDigest,
31
- consent(raw, permissions, now) { clock(now); const g = consent(raw), id = digest(g), rows = history(); if (!permissions.includes(id) || now >= g.expiresAt)
32
- throw Error('exact current consent permission required'); if (rows.some(e => e.value.type === 'revoked' && e.value.consentId === id))
33
- throw Error('consent revoked'); if (!rows.some(e => e.value.type === 'consented' && e.value.consentId === id))
34
- journal.append(rows.at(-1).id, { type: 'consented', consentId: id, grant: g, now }); return id; },
35
- revoke(id, permissions, now) { clock(now); const rows = history(); if (!permissions.includes(revokeDigest(id)) || !rows.some(e => e.value.type === 'consented' && e.value.consentId === id))
36
- throw Error('exact revocation permission required'); if (!rows.some(e => e.value.type === 'revoked' && e.value.consentId === id))
37
- journal.append(rows.at(-1).id, { type: 'revoked', consentId: id, now }); },
38
- read(manifestId, purpose, maxBytes, now = Date.now()) {
39
- clock(now);
40
- const rows = history(), valid = rows.filter(e => e.value.type === 'consented').filter(e => { const g = e.value.grant; return g.manifestId === manifestId && g.purpose === purpose && now < g.expiresAt && !rows.some(r => r.value.type === 'revoked' && r.value.consentId === e.value.consentId); });
41
- if (valid.length !== 1)
42
- throw Error('unique active manifest/purpose consent required');
43
- if (!Number.isSafeInteger(maxBytes) || maxBytes < 0 || maxBytes > 8 * 1024 * 1024)
44
- throw Error('archive read bound');
45
- const used = inspect();
46
- if (used.calls >= policy.maxCalls || maxBytes > policy.maxBytes - used.bytes)
47
- throw Error('shared archive budget exhausted');
48
- const claim = journal.append(rows.at(-1).id, { type: 'read-claim', manifestId, purpose, consentId: valid[0].value.consentId, reserved: maxBytes, now });
49
- const result = readArchiveSource(policy.archiveRoot, manifestId, maxBytes);
50
- journal.append(claim.id, { type: 'read-settled', claim: claim.id, bytes: result.status === 'available' ? result.bytes.length : 0, status: result.status, now });
51
- return result;
52
- },
53
- };
54
- }
55
- export function readGovernedArchive(root, manifestId, maxBytes, route, now = Date.now()) {
56
- const access = openArchiveAccess(route.directory);
57
- if (access.inspect().policy.archiveRoot !== root)
58
- throw Error('governed archive root mismatch');
59
- return access.read(manifestId, route.purpose, maxBytes, now);
60
- }
61
- //# sourceMappingURL=archive-access.js.map
@@ -1,47 +0,0 @@
1
- import { type ArchiveRead, type ArchiveSourceInput, type ArchiveRetention } from "./evidence-archive.js";
2
- export type SnapshotChange = "initial" | "append" | "replaced" | "unknown";
3
- export interface ArchiveCheckpoint {
4
- version: "archive-checkpoint-v1";
5
- sourceId: string;
6
- sourceManifestId: string;
7
- sourceSha256: string;
8
- sourceBytes: number;
9
- previousCheckpointId: string | null;
10
- lineage: string;
11
- declaredParser: {
12
- id: string;
13
- version: string;
14
- };
15
- reader: "jsonl-syntax-v1";
16
- retention: ArchiveRetention;
17
- change: SnapshotChange;
18
- syntax: "complete" | "partial" | "error" | "unavailable";
19
- completeBytes: number;
20
- pendingBytes: number;
21
- invalidLines: number;
22
- issues: string[];
23
- activeBranch: null;
24
- acceptance: "not-assessed";
25
- }
26
- export interface ArchivedRecord {
27
- id: string;
28
- line: number;
29
- start: number;
30
- end: number;
31
- value: unknown;
32
- }
33
- export interface CheckpointRead {
34
- checkpoint: ArchiveCheckpoint;
35
- source: ArchiveRead;
36
- records: ArchivedRecord[];
37
- }
38
- /** Restart from the immutable checkpoint ID. This never advances a worker or invokes a gate. */
39
- export declare function readArchiveCheckpoint(root: string, checkpointId: string): CheckpointRead;
40
- /** Caller supplies an explicit snapshot, policy and prior receipt. No inferred active branch or acceptance. */
41
- export declare function ingestArchiveSnapshot(root: string, input: ArchiveSourceInput & {
42
- previousCheckpointId?: string;
43
- }): CheckpointRead & {
44
- checkpointId: string;
45
- change: SnapshotChange | "repeat";
46
- newRecords: ArchivedRecord[];
47
- };