@nylorun/harness 0.9.0-beta.1 → 0.11.1-beta

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 (46) hide show
  1. package/CHANGELOG.md +60 -0
  2. package/README.md +5 -79
  3. package/dist/build/bind-tool.js +4 -3
  4. package/dist/build/helpers.d.ts +2 -2
  5. package/dist/build/schema.d.ts +11 -16
  6. package/dist/build/schema.js +141 -22
  7. package/dist/errors.d.ts +1 -1
  8. package/dist/index.d.ts +6 -3
  9. package/dist/index.js +2 -0
  10. package/dist/model/adapters.d.ts +48 -5
  11. package/dist/model/adapters.js +142 -17
  12. package/dist/model/normalize.js +49 -6
  13. package/dist/model/prepared.d.ts +16 -0
  14. package/dist/model/prepared.js +11 -0
  15. package/dist/session/event-log.d.ts +4 -3
  16. package/dist/session/input-queue.d.ts +7 -4
  17. package/dist/session/input-queue.js +12 -0
  18. package/dist/session/output-contract.d.ts +6 -0
  19. package/dist/session/output-contract.js +12 -0
  20. package/dist/session/scheduler.js +1 -1
  21. package/dist/session/seed.js +80 -6
  22. package/dist/session/session.d.ts +8 -5
  23. package/dist/session/session.js +38 -2
  24. package/dist/session/state.d.ts +1 -1
  25. package/dist/session/submission-stream.d.ts +5 -4
  26. package/dist/step/canonicalize.js +3 -0
  27. package/dist/step/context-draft.js +1 -7
  28. package/dist/step/model-configuration.js +5 -19
  29. package/dist/step/project.js +31 -5
  30. package/dist/step/resolve.d.ts +1 -0
  31. package/dist/step/resolve.js +1 -0
  32. package/dist/step/run.d.ts +1 -0
  33. package/dist/step/run.js +24 -3
  34. package/dist/step/seal.d.ts +4 -2
  35. package/dist/step/seal.js +63 -12
  36. package/dist/turn/plan-runner.js +38 -3
  37. package/dist/turn/runner.d.ts +6 -4
  38. package/dist/turn/runner.js +6 -4
  39. package/dist/types/middleware.d.ts +1 -1
  40. package/dist/types/model.d.ts +30 -13
  41. package/dist/types/session.d.ts +34 -13
  42. package/dist/types/shared.d.ts +16 -3
  43. package/dist/types/tool.d.ts +54 -17
  44. package/package.json +11 -12
  45. package/dist/utils/digest.d.ts +0 -1
  46. package/dist/utils/digest.js +0 -14
@@ -13,11 +13,11 @@ export class TurnRunner {
13
13
  this.sessionId = sessionId;
14
14
  this.session = session;
15
15
  }
16
- async start(state, event, context) {
16
+ async start(state, event, context, output) {
17
17
  const turnId = createId("turn");
18
18
  state = await context.commit(beginTurn(state, turnId, event), "input");
19
19
  context.onConversation({ type: "input", event, turnId });
20
- return this.advance(state, turnId, 1, [event], [], context);
20
+ return this.advance(state, turnId, 1, [event], [], context, output);
21
21
  }
22
22
  async continue(state, context) {
23
23
  const turnId = createId("turn");
@@ -36,9 +36,9 @@ export class TurnRunner {
36
36
  state = await context.commit(commitToolResults(state, pending.turnId, pending.stepId, progress.results), "tool-results");
37
37
  pending.plan.publishSettlements(context.observe);
38
38
  const claimed = await context.claimInterrupts(state, pending.turnId);
39
- return this.advance(claimed.state, pending.turnId, pending.stepNumber + 1, claimed.arrivals, progress.results, context);
39
+ return this.advance(claimed.state, pending.turnId, pending.stepNumber + 1, claimed.arrivals, progress.results, context, pending.output);
40
40
  }
41
- async advance(initialState, turnId, firstStep, arrivals, initialResults, context) {
41
+ async advance(initialState, turnId, firstStep, arrivals, initialResults, context, output) {
42
42
  let state = initialState;
43
43
  let stepArrivals = arrivals;
44
44
  let toolResults = initialResults;
@@ -58,6 +58,7 @@ export class TurnRunner {
58
58
  signal: context.signal,
59
59
  session: this.session,
60
60
  states: context.states,
61
+ output,
61
62
  recordModelRequested: (next, active) => context.commit(next, "model-requested", active),
62
63
  });
63
64
  context.assertCurrent();
@@ -68,6 +69,7 @@ export class TurnRunner {
68
69
  turnId,
69
70
  stepId,
70
71
  stepNumber,
72
+ ...(output === undefined ? {} : { output }),
71
73
  }
72
74
  : undefined;
73
75
  if (run.candidate) {
@@ -72,7 +72,7 @@ export type CapabilityItems<Item> = readonly Item[] | Readonly<{
72
72
  /** A named capability that may supply static model surface and one typed middleware handler. */
73
73
  export interface CapabilityDeclaration<State = never> {
74
74
  readonly id: string;
75
- readonly tools?: CapabilityItems<ToolDefinition<ToolDefinition["parameters"], State>>;
75
+ readonly tools?: CapabilityItems<ToolDefinition<ToolDefinition["inputSchema"], State>>;
76
76
  readonly instructions?: CapabilityItems<string>;
77
77
  readonly model?: ModelDirective;
78
78
  readonly state?: CapabilityState<State>;
@@ -1,4 +1,4 @@
1
- import type { ContextItem, DeferredOutcome, JsonObject } from "./shared.js";
1
+ import type { ContextItem, DeferredOutcome, JsonObject, JsonValue } from "./shared.js";
2
2
  import type { InputEvent, TranscriptEntry } from "./session.js";
3
3
  import type { BoundToolDefinition, ToolResult } from "./tool.js";
4
4
  export interface ModelToolCall {
@@ -9,11 +9,17 @@ export interface ModelToolCall {
9
9
  export type ModelOutputBlock = {
10
10
  readonly type: "text";
11
11
  readonly text: string;
12
+ readonly providerMetadata?: JsonObject;
12
13
  } | {
13
14
  readonly type: "reasoning";
14
15
  readonly text: string;
16
+ readonly providerMetadata?: JsonObject;
17
+ } | {
18
+ readonly type: "json";
19
+ readonly value: JsonValue;
15
20
  } | {
16
21
  readonly type: "tool-call";
22
+ readonly providerMetadata?: JsonObject;
17
23
  readonly id: string;
18
24
  readonly name: string;
19
25
  readonly args: JsonObject;
@@ -58,34 +64,27 @@ export interface ModelConfigurationContributor {
58
64
  readonly middlewareId: string;
59
65
  readonly slot: string;
60
66
  readonly order: number;
61
- readonly digest: string;
62
67
  readonly reason?: string;
63
68
  }
64
69
  export interface ModelConfigurationTool {
65
70
  readonly name: string;
66
71
  readonly description?: string;
67
72
  readonly inputSchema: JsonObject;
68
- readonly digest: string;
73
+ readonly outputSchema?: JsonObject;
69
74
  readonly contributor: ModelConfigurationContributor;
70
75
  }
71
76
  export interface ModelConfigurationInstruction {
72
77
  readonly text: string;
73
- readonly digest: string;
74
78
  readonly contributor: ModelConfigurationContributor;
75
79
  }
76
80
  export interface ModelConfigurationSnapshot {
77
81
  readonly version: 1;
78
82
  readonly model?: ModelDirective;
79
83
  readonly instructions: readonly ModelConfigurationInstruction[];
80
- /** Bound tools are retained for execution; their digest covers only their provider-visible contract. */
84
+ /** Bound tools are retained for execution. */
81
85
  readonly tools: readonly BoundToolDefinition[];
82
86
  readonly toolContracts: readonly ModelConfigurationTool[];
83
87
  readonly contributors: readonly ModelConfigurationContributor[];
84
- readonly digests: Readonly<{
85
- readonly logical: string;
86
- readonly model: string;
87
- readonly request: string;
88
- }>;
89
88
  }
90
89
  /** A middleware-owned declaration for this model call's runtime context. */
91
90
  export interface ContextMutationOptions {
@@ -96,14 +95,12 @@ export interface ContextContributor {
96
95
  readonly middlewareId: string;
97
96
  readonly slot: string;
98
97
  readonly order: number;
99
- readonly digest: string;
100
98
  readonly reason?: string;
101
99
  }
102
- /** Canonical runtime context for one model call. Not part of the configuration digest. */
100
+ /** Canonical runtime context for one model call. */
103
101
  export interface ContextSnapshot {
104
102
  readonly items: readonly ContextItem[];
105
103
  readonly contributors: readonly ContextContributor[];
106
- readonly digest: string;
107
104
  }
108
105
  export interface ModelRequest {
109
106
  readonly sessionId: string;
@@ -119,12 +116,24 @@ export interface ModelRequest {
119
116
  readonly toolResults: readonly ToolResult[];
120
117
  /** Tools are normalized and immutable by the time a Model sees them. */
121
118
  readonly tools: readonly BoundToolDefinition[];
119
+ /** Optional portable contract for this turn's terminal JSON result. */
120
+ readonly outputSchema?: JsonObject;
122
121
  }
123
122
  export type PromptContentPart = {
123
+ readonly type: "reasoning";
124
+ readonly text: string;
125
+ readonly providerMetadata?: JsonObject;
126
+ } | {
124
127
  readonly type: "text";
125
128
  readonly text: string;
129
+ readonly providerMetadata?: JsonObject;
130
+ } | {
131
+ readonly type: "media";
132
+ readonly mediaType: string;
133
+ readonly reference: JsonValue;
126
134
  } | {
127
135
  readonly type: "tool-call";
136
+ readonly providerMetadata?: JsonObject;
128
137
  readonly id: string;
129
138
  readonly name: string;
130
139
  readonly args: JsonObject;
@@ -157,11 +166,19 @@ export interface ModelCall {
157
166
  readonly model?: ModelDirective;
158
167
  readonly prompt: readonly PromptItem[];
159
168
  readonly tools: readonly ModelCallTool[];
169
+ /** Optional portable contract for this turn's terminal JSON result. */
170
+ readonly outputSchema?: JsonObject;
160
171
  readonly sessionId: string;
161
172
  }
162
173
  export interface ModelAdapterContext {
163
174
  readonly request: ModelRequest;
164
175
  readonly invocationId: string;
165
176
  readonly signal: AbortSignal;
177
+ /** Publishes one JSON-safe provider request derived from the canonical ModelCall. */
178
+ reportPreparedCall(prepared: ModelPreparedCall): void;
179
+ }
180
+ export interface ModelPreparedCall {
181
+ readonly adapter: string;
182
+ readonly call: JsonValue;
166
183
  }
167
184
  export type ModelAdapter = (call: ModelCall, context: ModelAdapterContext) => Promise<ModelCandidate | string | DeferredOutcome>;
@@ -1,13 +1,15 @@
1
1
  import type { ModelCall, ModelCandidate } from "./model.js";
2
2
  import type { JsonObject, JsonValue, Observer, Tripwire } from "./shared.js";
3
- import type { RequiredInteraction, ToolExecutionResume, ToolOwner, ToolResult } from "./tool.js";
3
+ import type { RequiredInteraction, SchemaOutput, ToolExecutionResume, ToolOwner, ToolResult, ToolSchemaSource } from "./tool.js";
4
4
  export type InputEvent = {
5
- readonly kind: "user-message";
5
+ readonly kind: "user-message" | "interrupt";
6
6
  readonly text: string;
7
7
  readonly metadata?: JsonObject;
8
8
  } | {
9
- readonly kind: "interrupt";
10
- readonly text: string;
9
+ readonly kind: "user-message" | "interrupt";
10
+ readonly content: readonly UserContentPart[];
11
+ /** Undefined for content-bearing events; retained for text-event narrowing compatibility. */
12
+ readonly text?: undefined;
11
13
  readonly metadata?: JsonObject;
12
14
  } | {
13
15
  readonly kind: "approve";
@@ -18,7 +20,7 @@ export type InputEvent = {
18
20
  readonly interactionId: string;
19
21
  readonly value: JsonValue;
20
22
  };
21
- export type SessionEvent = {
23
+ export type SessionEvent<Output = string> = {
22
24
  readonly type: "input";
23
25
  readonly event: InputEvent;
24
26
  readonly turnId: string;
@@ -29,7 +31,7 @@ export type SessionEvent = {
29
31
  readonly candidate: ModelCandidate;
30
32
  } | {
31
33
  readonly type: "final";
32
- readonly output: string;
34
+ readonly output: Output;
33
35
  readonly turnId: string;
34
36
  } | {
35
37
  readonly type: "interaction.required";
@@ -58,14 +60,14 @@ export type SessionEvent = {
58
60
  readonly type: "session.stopped";
59
61
  readonly sessionId: string;
60
62
  };
61
- export interface InputCompletion {
63
+ export interface InputCompletion<Output = string> {
62
64
  readonly inputId: string;
63
65
  readonly status: "completed" | "waiting" | "rejected" | "cancelled" | "stopped";
64
- readonly events: readonly SessionEvent[];
66
+ readonly events: readonly SessionEvent<Output>[];
65
67
  }
66
- export interface InputHandle {
68
+ export interface InputHandle<Output = string> {
67
69
  readonly inputId: string;
68
- readonly completed: Promise<InputCompletion>;
70
+ readonly completed: Promise<InputCompletion<Output>>;
69
71
  }
70
72
  export interface SessionOptions {
71
73
  readonly id?: string;
@@ -91,9 +93,25 @@ export type SessionRunOptions = SessionOptions | SeededSessionOptions;
91
93
  export interface InputOptions {
92
94
  readonly signal?: AbortSignal;
93
95
  }
96
+ /** Per-turn, locally-enforced terminal JSON contract. */
97
+ export interface OutputInputOptions<Schema extends ToolSchemaSource = ToolSchemaSource> extends InputOptions {
98
+ readonly outputSchema?: Schema;
99
+ }
100
+ /** Ordered, model-visible user content. Media references stay host-owned JSON values. */
101
+ export type UserContentPart = {
102
+ readonly type: "text";
103
+ readonly text: string;
104
+ } | {
105
+ readonly type: "media";
106
+ readonly mediaType: string;
107
+ readonly reference: JsonValue;
108
+ };
94
109
  export type MessageInput = string | {
95
110
  readonly text: string;
96
111
  readonly metadata?: JsonObject;
112
+ } | {
113
+ readonly content: readonly UserContentPart[];
114
+ readonly metadata?: JsonObject;
97
115
  };
98
116
  export type InteractionReply = Extract<InputEvent, {
99
117
  kind: "approve" | "respond";
@@ -121,7 +139,7 @@ export interface TranscriptFinalEntry {
121
139
  readonly kind: "final";
122
140
  readonly turnId: string;
123
141
  readonly stepId: string;
124
- readonly output: string;
142
+ readonly output: JsonValue;
125
143
  }
126
144
  export type TranscriptEntry = TranscriptInputEntry | TranscriptCandidateEntry | TranscriptToolsEntry | TranscriptFinalEntry;
127
145
  export interface SessionSnapshot {
@@ -197,10 +215,13 @@ export interface SessionRecorder {
197
215
  export interface Session {
198
216
  readonly id: string;
199
217
  readonly state: SessionSnapshot;
200
- input(event: SessionInput, options?: InputOptions): InputHandle;
218
+ input<Schema extends ToolSchemaSource>(event: MessageInput, options: OutputInputOptions<Schema> & {
219
+ readonly outputSchema: Schema;
220
+ }): InputHandle<SchemaOutput<Schema>>;
221
+ input(event: SessionInput, options?: InputOptions): InputHandle<string>;
201
222
  interrupt(event: MessageInput, options?: InputOptions): InputHandle;
202
223
  continue(options?: InputOptions): InputHandle;
203
- stream(): AsyncIterable<SessionEvent>;
224
+ stream(): AsyncIterable<SessionEvent<JsonValue>>;
204
225
  observe(listener: Observer): () => void;
205
226
  stop(reason?: string): Promise<void>;
206
227
  }
@@ -33,7 +33,10 @@ export interface ObserveToolSnapshot {
33
33
  readonly middlewareId: string;
34
34
  readonly slot: string;
35
35
  };
36
- readonly parameters: {
36
+ readonly inputSchema: {
37
+ readonly jsonSchema: JsonObject;
38
+ };
39
+ readonly outputSchema?: {
37
40
  readonly jsonSchema: JsonObject;
38
41
  };
39
42
  }
@@ -55,7 +58,7 @@ export interface ObserveSealedCall {
55
58
  export interface ObserveModelRequested {
56
59
  /** The exact immutable logical input supplied to the ModelAdapter. */
57
60
  readonly call: ModelCall;
58
- /** Canonical configuration facts and attribution; hashes have no policy semantics. */
61
+ /** Canonical configuration facts and attribution. */
59
62
  readonly configuration: ObserveModelConfigurationSnapshot;
60
63
  /** Current-step runtime context and attribution. */
61
64
  readonly context: ContextSnapshot;
@@ -104,6 +107,16 @@ export type ObserveEvent = {
104
107
  readonly inputId?: string;
105
108
  readonly requestedModelId?: string;
106
109
  readonly attributes: ObserveModelRequested;
110
+ } | {
111
+ readonly type: "model.prepared";
112
+ readonly turnId: string;
113
+ readonly stepId: string;
114
+ readonly inputId?: string;
115
+ readonly requestedModelId?: string;
116
+ readonly attributes: {
117
+ readonly adapter: string;
118
+ readonly call: JsonValue;
119
+ };
107
120
  } | {
108
121
  readonly type: "model.completed";
109
122
  readonly turnId: string;
@@ -206,7 +219,7 @@ export type ObserveEvent = {
206
219
  readonly stepId: string;
207
220
  readonly inputId?: string;
208
221
  readonly attributes: {
209
- readonly output: string;
222
+ readonly output: JsonValue;
210
223
  };
211
224
  } | {
212
225
  readonly type: "interaction.required";
@@ -1,29 +1,61 @@
1
- import type { ZodObject, output } from "zod";
1
+ import type { ZodType } from "zod";
2
2
  import type { DeferredOutcome, JsonObject, JsonValue } from "./shared.js";
3
- type SchemaValidationSuccess<T> = {
3
+ export interface SchemaIssue {
4
+ readonly path: readonly (string | number)[];
5
+ readonly code: string;
6
+ readonly message: string;
7
+ }
8
+ export type SchemaValidation<T> = {
4
9
  readonly ok: true;
5
10
  readonly value: T;
6
- };
7
- type SchemaValidationFailure = {
11
+ } | {
8
12
  readonly ok: false;
9
- readonly issues: readonly string[];
13
+ readonly issues: readonly SchemaIssue[];
10
14
  };
11
- type SchemaValidation<T> = SchemaValidationSuccess<T> | SchemaValidationFailure;
12
- /** Harness tool parameters are synchronous Zod object schemas. */
13
- export type ToolObjectSchema = ZodObject;
14
- export interface BoundToolSchema<T> {
15
+ /** The portable, locally-enforced schema contract accepted by a Harness tool. */
16
+ export interface ToolSchema<T> {
15
17
  readonly jsonSchema: JsonObject;
16
18
  validate(value: unknown): SchemaValidation<T>;
17
19
  }
18
- export interface ToolDefinition<Parameters extends ToolObjectSchema = ToolObjectSchema, State = never> {
20
+ /** The synchronous Standard Schema subset required to project and validate a tool contract. */
21
+ export interface StandardToolSchema<Input = unknown, Output = unknown> {
22
+ readonly "~standard": {
23
+ readonly validate: (value: Input) => {
24
+ readonly value: Output;
25
+ readonly issues?: undefined;
26
+ } | {
27
+ readonly issues: readonly StandardSchemaIssue[];
28
+ readonly value?: undefined;
29
+ } | Promise<unknown>;
30
+ readonly jsonSchema: {
31
+ readonly input: () => unknown;
32
+ readonly output: () => unknown;
33
+ };
34
+ };
35
+ }
36
+ export interface StandardSchemaIssue {
37
+ readonly message?: string;
38
+ readonly path?: readonly (string | number | symbol)[];
39
+ readonly code?: string;
40
+ }
41
+ export type ToolSchemaSource<T = unknown> = ZodType<T> | StandardToolSchema<any, T> | ToolSchema<T>;
42
+ export type SchemaOutput<Schema> = Schema extends ZodType<infer Value> ? Value : Schema extends StandardToolSchema<any, infer Value> ? Value : Schema extends ToolSchema<infer Value> ? Value : never;
43
+ export type ToolInputSchema = ToolSchemaSource;
44
+ export type ToolOutputSchema = ToolSchemaSource;
45
+ export interface BoundToolSchema<T> extends ToolSchema<T> {
46
+ }
47
+ type OutputFor<Schema> = Schema extends ToolSchemaSource ? SchemaOutput<Schema> : ToolContent;
48
+ export interface ToolDefinition<InputSchema extends ToolInputSchema = ToolInputSchema, State = never, OutputSchema extends ToolOutputSchema | undefined = undefined> {
19
49
  readonly name: string;
20
50
  readonly description?: string;
21
- readonly parameters: Parameters;
22
- execute(args: output<Parameters>, context: ToolExecutionContext<State>): Promise<ToolOutcome>;
51
+ readonly inputSchema: InputSchema;
52
+ readonly outputSchema?: OutputSchema;
53
+ execute(args: SchemaOutput<InputSchema>, context: ToolExecutionContext<State>): Promise<ToolOutcome<OutputFor<OutputSchema>>>;
23
54
  }
24
- export interface BoundToolDefinition<Parameters extends ToolObjectSchema = ToolObjectSchema, State = never> extends Omit<ToolDefinition<Parameters, State>, "parameters" | "execute"> {
25
- readonly parameters: BoundToolSchema<output<Parameters>>;
26
- readonly execute: ToolDefinition<Parameters, State>["execute"];
55
+ export interface BoundToolDefinition<State = never> extends Omit<ToolDefinition<ToolInputSchema, State, ToolOutputSchema | undefined>, "inputSchema" | "outputSchema" | "execute"> {
56
+ readonly inputSchema: BoundToolSchema<unknown>;
57
+ readonly outputSchema?: BoundToolSchema<unknown>;
58
+ readonly execute: (args: unknown, context: ToolExecutionContext<State>) => Promise<ToolOutcome>;
27
59
  readonly owner: ToolOwner;
28
60
  }
29
61
  export interface ToolOwner {
@@ -64,9 +96,9 @@ export type ToolExecutionContext<State = never> = ToolExecutionContextBase & ([S
64
96
  readonly state: Promise<State>;
65
97
  });
66
98
  export type ToolContent = JsonValue;
67
- export type ToolOutcome = {
99
+ export type ToolOutcome<Output = ToolContent> = {
68
100
  readonly kind: "completed";
69
- readonly output: ToolContent;
101
+ readonly output: Output;
70
102
  } | {
71
103
  readonly kind: "denied";
72
104
  readonly reason: string;
@@ -79,6 +111,10 @@ export type ToolOutcome = {
79
111
  readonly interaction: Interaction;
80
112
  readonly token?: JsonValue;
81
113
  } | DeferredOutcome;
114
+ export interface ToolValidationFailureDetails {
115
+ readonly phase: "input" | "output";
116
+ readonly issues: readonly SchemaIssue[];
117
+ }
82
118
  export type ToolResult = {
83
119
  readonly callId: string;
84
120
  readonly toolName: string;
@@ -95,5 +131,6 @@ export type ToolResult = {
95
131
  readonly kind: "failed";
96
132
  readonly code: string;
97
133
  readonly message: string;
134
+ readonly details?: ToolValidationFailureDetails;
98
135
  };
99
136
  export {};
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@nylorun/harness",
3
- "version": "0.9.0-beta.1",
4
- "description": "A provider-neutral, in-memory agent loop for TypeScript.",
3
+ "version": "0.11.1-beta",
4
+ "description": "Nylorun's TypeScript agent runtime. See github.com/nylorun/harness.",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",
7
7
  "repository": {
@@ -9,7 +9,7 @@
9
9
  "url": "git+https://github.com/nylorun/harness.git",
10
10
  "directory": "harness"
11
11
  },
12
- "homepage": "https://github.com/nylorun/harness/tree/main/harness#readme",
12
+ "homepage": "https://github.com/nylorun/harness",
13
13
  "bugs": "https://github.com/nylorun/harness/issues",
14
14
  "author": "Nylo",
15
15
  "keywords": [
@@ -48,26 +48,25 @@
48
48
  "node": "^22.14.0 || ^24.0.0 || >=26.0.0"
49
49
  },
50
50
  "scripts": {
51
- "clean": "node -e \"import('node:fs').then(({rmSync})=>rmSync('dist',{recursive:true,force:true}))\"",
52
- "build": "npm run clean && tsc -p tsconfig.json",
51
+ "build": "npm run clean && node ../scripts/check-typescript-version.mjs && tsc -p tsconfig.json",
52
+ "check": "npm run format:check && npm run build && npm run test:types && npm test && node scripts/check-package.mjs",
53
+ "typecheck": "node ../scripts/check-typescript-version.mjs && tsc -p tsconfig.json --noEmit",
53
54
  "test": "vitest run",
55
+ "test:types": "tsc -p test/types/tsconfig.json",
54
56
  "format": "prettier --write .",
55
57
  "format:check": "prettier --check .",
56
- "test:types": "tsc -p test/types/tsconfig.json",
57
- "check": "npm run format:check && npm run build && npm run test:types && npm test && node scripts/check-package.mjs",
58
+ "clean": "node -e \"import('node:fs').then(({rmSync})=>rmSync('dist',{recursive:true,force:true}))\"",
58
59
  "prepack": "npm run build"
59
60
  },
60
61
  "devDependencies": {
61
62
  "@types/node": "^22.18.0",
63
+ "@typescript/native": "npm:typescript@^7.0.2",
62
64
  "prettier": "^3.9.6",
63
- "typescript": "^5.9.3",
64
- "vitest": "^3.2.4",
65
+ "typescript": "npm:@typescript/typescript6@^6.0.2",
66
+ "vitest": "^4.1.11",
65
67
  "zod": "^4.1.12"
66
68
  },
67
69
  "peerDependencies": {
68
70
  "zod": "^4.1.12"
69
- },
70
- "dependencies": {
71
- "@noble/hashes": "^2.3.0"
72
71
  }
73
72
  }
@@ -1 +0,0 @@
1
- export declare const digest: (value: unknown) => string;
@@ -1,14 +0,0 @@
1
- import { sha256 } from "@noble/hashes/sha2.js";
2
- import { bytesToHex, utf8ToBytes } from "@noble/hashes/utils.js";
3
- function canonical(value) {
4
- if (Array.isArray(value))
5
- return `[${value.map(canonical).join(",")}]`;
6
- if (value && typeof value === "object") {
7
- return `{${Object.entries(value)
8
- .sort(([a], [b]) => a.localeCompare(b))
9
- .map(([key, item]) => `${JSON.stringify(key)}:${canonical(item)}`)
10
- .join(",")}}`;
11
- }
12
- return JSON.stringify(value);
13
- }
14
- export const digest = (value) => bytesToHex(sha256(utf8ToBytes(canonical(value))));