@tangle-network/agent-interface 0.32.0 → 0.34.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 (35) hide show
  1. package/dist/agent-candidate-code-schema.d.ts +0 -3
  2. package/dist/agent-candidate-execution-plan-schema.d.ts +11 -17
  3. package/dist/agent-candidate-lineage-schema.d.ts +2 -2
  4. package/dist/agent-candidate-outcome-schema.d.ts +4 -4
  5. package/dist/agent-candidate-profile-schema.d.ts +0 -3
  6. package/dist/agent-candidate-promotion-schema.d.ts +1411 -885
  7. package/dist/agent-candidate-promotion-schema.js +46 -346
  8. package/dist/agent-candidate-receipt-schema.d.ts +8 -11
  9. package/dist/agent-candidate-schema.d.ts +0 -6
  10. package/dist/agent-candidate-schema.js +1 -3
  11. package/dist/agent-candidate.d.ts +14 -7
  12. package/dist/agent-improvement-measurement-schema.d.ts +198 -0
  13. package/dist/agent-improvement-measurement-schema.js +349 -0
  14. package/dist/agent-improvement-source.d.ts +23 -0
  15. package/dist/agent-improvement-source.js +38 -0
  16. package/dist/agent-profile-improvement-schema.d.ts +1085 -0
  17. package/dist/agent-profile-improvement-schema.js +553 -0
  18. package/dist/agent-profile-improvement.d.ts +139 -0
  19. package/dist/agent-profile-improvement.js +1 -0
  20. package/dist/agent-profile.d.ts +2 -2
  21. package/dist/agent-profile.js +2 -2
  22. package/dist/certified-context.d.ts +118 -0
  23. package/dist/certified-context.js +228 -0
  24. package/dist/harness-capabilities.d.ts +1 -1
  25. package/dist/harness-capabilities.js +9 -12
  26. package/dist/harness.d.ts +1 -10
  27. package/dist/harness.js +0 -13
  28. package/dist/index.d.ts +6 -1
  29. package/dist/index.js +5 -0
  30. package/dist/interaction.d.ts +0 -17
  31. package/dist/interaction.js +0 -23
  32. package/dist/number-validation.d.ts +1 -0
  33. package/dist/number-validation.js +4 -0
  34. package/dist/profile-schema.d.ts +0 -3
  35. package/package.json +1 -1
@@ -3,8 +3,8 @@
3
3
  *
4
4
  * These model portable agent intent at the application boundary. Individual
5
5
  * backends translate this shape into their own native profile/configuration
6
- * formats internally. This is the canonical home; `@tangle-network/sandbox`
7
- * re-exports these symbols for backward compatibility.
6
+ * formats internally. This package is the canonical public home for these
7
+ * symbols.
8
8
  */
9
9
  import type { HarnessType } from "./harness.js";
10
10
  /**
@@ -3,8 +3,8 @@
3
3
  *
4
4
  * These model portable agent intent at the application boundary. Individual
5
5
  * backends translate this shape into their own native profile/configuration
6
- * formats internally. This is the canonical home; `@tangle-network/sandbox`
7
- * re-exports these symbols for backward compatibility.
6
+ * formats internally. This package is the canonical public home for these
7
+ * symbols.
8
8
  */
9
9
  /**
10
10
  * Helper for creating typed inline resource refs.
@@ -0,0 +1,118 @@
1
+ import { z } from "zod";
2
+ import type { Sha256Digest } from "./agent-candidate.js";
3
+ export type CertifiedContextKind = "prompt" | "skill" | "instructions";
4
+ export type CertifiedContextDelivery = {
5
+ readonly kind: "inline";
6
+ readonly content: string;
7
+ } | {
8
+ readonly kind: "file";
9
+ readonly path: string;
10
+ readonly content: string;
11
+ };
12
+ export interface CertifiedContextProvenance {
13
+ /** SHA-256 of the entry id, kind, name, and delivery. */
14
+ readonly contentHash: Sha256Digest;
15
+ /** Positive release number, or null when the source has no released version. */
16
+ readonly version: number | null;
17
+ readonly promotedAt: string;
18
+ }
19
+ export interface CertifiedContextEntry {
20
+ readonly id: string;
21
+ readonly kind: CertifiedContextKind;
22
+ readonly name: string;
23
+ readonly delivery: CertifiedContextDelivery;
24
+ readonly provenance: CertifiedContextProvenance;
25
+ }
26
+ /**
27
+ * Tenant-bound context delivered by Intelligence.
28
+ *
29
+ * This contract intentionally excludes tools, credentials, executable files,
30
+ * profile patches, MCP servers, and arbitrary network requests.
31
+ */
32
+ export interface CertifiedContext {
33
+ readonly tenantId: string;
34
+ readonly target: string;
35
+ readonly state: "active" | "revoked";
36
+ /** Monotonic decimal revision for this tenant and target. */
37
+ readonly revision: string;
38
+ readonly generatedAt: string;
39
+ readonly expiresAt: string;
40
+ readonly entries: readonly CertifiedContextEntry[];
41
+ /** SHA-256 of tenantId, target, state, revision, and entries. */
42
+ readonly contentHash: Sha256Digest;
43
+ }
44
+ export declare const certifiedContextDeliverySchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
45
+ kind: z.ZodLiteral<"inline">;
46
+ content: z.ZodString;
47
+ }, z.core.$strict>, z.ZodObject<{
48
+ kind: z.ZodLiteral<"file">;
49
+ path: z.ZodString;
50
+ content: z.ZodString;
51
+ }, z.core.$strict>], "kind">;
52
+ export declare const certifiedContextProvenanceSchema: z.ZodObject<{
53
+ contentHash: z.ZodType<`sha256:${string}`, unknown, z.core.$ZodTypeInternals<`sha256:${string}`, unknown>>;
54
+ version: z.ZodNullable<z.ZodNumber>;
55
+ promotedAt: z.ZodISODateTime;
56
+ }, z.core.$strict>;
57
+ /** Compute the exact digest stored in an entry's provenance. */
58
+ export declare function certifiedContextEntryContentHash(entry: Pick<CertifiedContextEntry, "id" | "kind" | "name" | "delivery">): Sha256Digest;
59
+ export declare const certifiedContextEntrySchema: z.ZodObject<{
60
+ id: z.ZodString;
61
+ kind: z.ZodEnum<{
62
+ prompt: "prompt";
63
+ instructions: "instructions";
64
+ skill: "skill";
65
+ }>;
66
+ name: z.ZodString;
67
+ delivery: z.ZodDiscriminatedUnion<[z.ZodObject<{
68
+ kind: z.ZodLiteral<"inline">;
69
+ content: z.ZodString;
70
+ }, z.core.$strict>, z.ZodObject<{
71
+ kind: z.ZodLiteral<"file">;
72
+ path: z.ZodString;
73
+ content: z.ZodString;
74
+ }, z.core.$strict>], "kind">;
75
+ provenance: z.ZodObject<{
76
+ contentHash: z.ZodType<`sha256:${string}`, unknown, z.core.$ZodTypeInternals<`sha256:${string}`, unknown>>;
77
+ version: z.ZodNullable<z.ZodNumber>;
78
+ promotedAt: z.ZodISODateTime;
79
+ }, z.core.$strict>;
80
+ }, z.core.$strict>;
81
+ /** Compute the stable hash for one context revision. */
82
+ export declare function certifiedContextContentHash(context: Pick<CertifiedContext, "tenantId" | "target" | "state" | "revision" | "entries">): Sha256Digest;
83
+ export declare const certifiedContextSchema: z.ZodObject<{
84
+ tenantId: z.ZodString;
85
+ target: z.ZodString;
86
+ state: z.ZodEnum<{
87
+ active: "active";
88
+ revoked: "revoked";
89
+ }>;
90
+ revision: z.ZodString;
91
+ generatedAt: z.ZodISODateTime;
92
+ expiresAt: z.ZodISODateTime;
93
+ entries: z.ZodArray<z.ZodObject<{
94
+ id: z.ZodString;
95
+ kind: z.ZodEnum<{
96
+ prompt: "prompt";
97
+ instructions: "instructions";
98
+ skill: "skill";
99
+ }>;
100
+ name: z.ZodString;
101
+ delivery: z.ZodDiscriminatedUnion<[z.ZodObject<{
102
+ kind: z.ZodLiteral<"inline">;
103
+ content: z.ZodString;
104
+ }, z.core.$strict>, z.ZodObject<{
105
+ kind: z.ZodLiteral<"file">;
106
+ path: z.ZodString;
107
+ content: z.ZodString;
108
+ }, z.core.$strict>], "kind">;
109
+ provenance: z.ZodObject<{
110
+ contentHash: z.ZodType<`sha256:${string}`, unknown, z.core.$ZodTypeInternals<`sha256:${string}`, unknown>>;
111
+ version: z.ZodNullable<z.ZodNumber>;
112
+ promotedAt: z.ZodISODateTime;
113
+ }, z.core.$strict>;
114
+ }, z.core.$strict>>;
115
+ contentHash: z.ZodType<`sha256:${string}`, unknown, z.core.$ZodTypeInternals<`sha256:${string}`, unknown>>;
116
+ }, z.core.$strict>;
117
+ /** Parse, clone, and recursively freeze one untrusted context response. */
118
+ export declare function parseCertifiedContext(value: unknown): CertifiedContext;
@@ -0,0 +1,228 @@
1
+ import { z } from "zod";
2
+ import { canonicalCandidateDigest, isSafeRelativePath, sha256DigestSchema, } from "./agent-candidate-schema-common.js";
3
+ const MAX_INLINE_CONTEXT_BYTES = 65_536;
4
+ const MAX_TOTAL_INLINE_CONTEXT_BYTES = 131_072;
5
+ const MAX_FILE_CONTEXT_BYTES = 1_048_576;
6
+ const MAX_CERTIFIED_CONTEXT_BYTES = 16_777_216;
7
+ const MAX_CERTIFIED_CONTEXT_LIFETIME_MS = 900_000;
8
+ const revisionPattern = /^(0|[1-9]\d{0,18})$/;
9
+ const nonBlankStringSchema = z
10
+ .string()
11
+ .refine((value) => value.trim().length > 0, "value cannot be blank");
12
+ const identifierSchema = nonBlankStringSchema.max(256);
13
+ const relativePathSchema = nonBlankStringSchema
14
+ .max(1_024)
15
+ .refine((value) => isSafeRelativePath(value, false), "value must be a canonical relative path");
16
+ const inlineContentSchema = z
17
+ .string()
18
+ .max(MAX_INLINE_CONTEXT_BYTES)
19
+ .refine((value) => new TextEncoder().encode(value).byteLength <= MAX_INLINE_CONTEXT_BYTES, `inline content exceeds ${MAX_INLINE_CONTEXT_BYTES} UTF-8 bytes`);
20
+ const fileContentSchema = z
21
+ .string()
22
+ .max(MAX_FILE_CONTEXT_BYTES)
23
+ .refine((value) => new TextEncoder().encode(value).byteLength <= MAX_FILE_CONTEXT_BYTES, `file content exceeds ${MAX_FILE_CONTEXT_BYTES} UTF-8 bytes`);
24
+ export const certifiedContextDeliverySchema = z.discriminatedUnion("kind", [
25
+ z.strictObject({
26
+ kind: z.literal("inline"),
27
+ content: inlineContentSchema,
28
+ }),
29
+ z.strictObject({
30
+ kind: z.literal("file"),
31
+ path: relativePathSchema,
32
+ content: fileContentSchema,
33
+ }),
34
+ ]);
35
+ export const certifiedContextProvenanceSchema = z.strictObject({
36
+ contentHash: sha256DigestSchema,
37
+ version: z.number().int().positive().max(Number.MAX_SAFE_INTEGER).nullable(),
38
+ promotedAt: z.iso.datetime(),
39
+ });
40
+ function jsonMaterial(value) {
41
+ const serialized = JSON.stringify(value);
42
+ if (serialized === undefined) {
43
+ throw new Error("certified context material must be JSON serializable");
44
+ }
45
+ return JSON.parse(serialized);
46
+ }
47
+ /** Compute the exact digest stored in an entry's provenance. */
48
+ export function certifiedContextEntryContentHash(entry) {
49
+ return canonicalCandidateDigest(jsonMaterial({
50
+ id: entry.id,
51
+ kind: entry.kind,
52
+ name: entry.name,
53
+ delivery: entry.delivery,
54
+ }));
55
+ }
56
+ export const certifiedContextEntrySchema = z
57
+ .strictObject({
58
+ id: identifierSchema,
59
+ kind: z.enum(["prompt", "skill", "instructions"]),
60
+ name: identifierSchema,
61
+ delivery: certifiedContextDeliverySchema,
62
+ provenance: certifiedContextProvenanceSchema,
63
+ })
64
+ .superRefine((entry, context) => {
65
+ if (entry.kind === "skill" && entry.delivery.kind !== "file") {
66
+ context.addIssue({
67
+ code: "custom",
68
+ path: ["delivery", "kind"],
69
+ message: "skills must be delivered as files",
70
+ });
71
+ }
72
+ if (entry.kind !== "skill" && entry.delivery.kind !== "inline") {
73
+ context.addIssue({
74
+ code: "custom",
75
+ path: ["delivery", "kind"],
76
+ message: "prompts and instructions must be delivered inline",
77
+ });
78
+ }
79
+ if (entry.delivery.kind === "inline" &&
80
+ entry.delivery.content.trim().length === 0) {
81
+ context.addIssue({
82
+ code: "custom",
83
+ path: ["delivery", "content"],
84
+ message: "inline context cannot be blank",
85
+ });
86
+ }
87
+ if (entry.provenance.contentHash !== certifiedContextEntryContentHash(entry)) {
88
+ context.addIssue({
89
+ code: "custom",
90
+ path: ["provenance", "contentHash"],
91
+ message: "entry content hash does not match the delivered context",
92
+ });
93
+ }
94
+ });
95
+ /** Compute the stable hash for one context revision. */
96
+ export function certifiedContextContentHash(context) {
97
+ return canonicalCandidateDigest(jsonMaterial(context));
98
+ }
99
+ export const certifiedContextSchema = z
100
+ .strictObject({
101
+ tenantId: identifierSchema,
102
+ target: identifierSchema,
103
+ state: z.enum(["active", "revoked"]),
104
+ revision: z
105
+ .string()
106
+ .regex(revisionPattern)
107
+ .refine((value) => !revisionPattern.test(value) ||
108
+ BigInt(value) <= 9223372036854775807n, "revision exceeds signed 64-bit range"),
109
+ generatedAt: z.iso.datetime(),
110
+ expiresAt: z.iso.datetime(),
111
+ entries: z.array(certifiedContextEntrySchema).max(128),
112
+ contentHash: sha256DigestSchema,
113
+ })
114
+ .superRefine((context, refinement) => {
115
+ const generatedAt = Date.parse(context.generatedAt);
116
+ const expiresAt = Date.parse(context.expiresAt);
117
+ if (expiresAt <= generatedAt) {
118
+ refinement.addIssue({
119
+ code: "custom",
120
+ path: ["expiresAt"],
121
+ message: "expiresAt must be after generatedAt",
122
+ });
123
+ }
124
+ else if (expiresAt - generatedAt >
125
+ MAX_CERTIFIED_CONTEXT_LIFETIME_MS) {
126
+ refinement.addIssue({
127
+ code: "custom",
128
+ path: ["expiresAt"],
129
+ message: "certified context cannot live longer than 15 minutes",
130
+ });
131
+ }
132
+ const serialized = JSON.stringify(context);
133
+ if (new TextEncoder().encode(serialized).byteLength >
134
+ MAX_CERTIFIED_CONTEXT_BYTES) {
135
+ refinement.addIssue({
136
+ code: "too_big",
137
+ maximum: MAX_CERTIFIED_CONTEXT_BYTES,
138
+ origin: "string",
139
+ inclusive: true,
140
+ message: `serialized context exceeds ${MAX_CERTIFIED_CONTEXT_BYTES} UTF-8 bytes`,
141
+ });
142
+ }
143
+ const ids = new Set();
144
+ const filePaths = new Set();
145
+ let inlineBytes = 0;
146
+ for (const [index, entry] of context.entries.entries()) {
147
+ if (ids.has(entry.id)) {
148
+ refinement.addIssue({
149
+ code: "custom",
150
+ path: ["entries", index, "id"],
151
+ message: `duplicate context id: ${entry.id}`,
152
+ });
153
+ }
154
+ ids.add(entry.id);
155
+ if (entry.delivery.kind === "file") {
156
+ if (filePaths.has(entry.delivery.path)) {
157
+ refinement.addIssue({
158
+ code: "custom",
159
+ path: ["entries", index, "delivery", "path"],
160
+ message: `duplicate file path: ${entry.delivery.path}`,
161
+ });
162
+ }
163
+ filePaths.add(entry.delivery.path);
164
+ }
165
+ else {
166
+ inlineBytes += new TextEncoder().encode(entry.delivery.content).byteLength;
167
+ }
168
+ if (Date.parse(entry.provenance.promotedAt) > generatedAt) {
169
+ refinement.addIssue({
170
+ code: "custom",
171
+ path: ["entries", index, "provenance", "promotedAt"],
172
+ message: "context cannot be promoted after bundle generation",
173
+ });
174
+ }
175
+ }
176
+ if (inlineBytes > MAX_TOTAL_INLINE_CONTEXT_BYTES) {
177
+ refinement.addIssue({
178
+ code: "custom",
179
+ path: ["entries"],
180
+ message: `inline context exceeds ${MAX_TOTAL_INLINE_CONTEXT_BYTES} UTF-8 bytes`,
181
+ });
182
+ }
183
+ if ((context.state === "active" && context.entries.length === 0) ||
184
+ (context.state === "revoked" && context.entries.length !== 0)) {
185
+ refinement.addIssue({
186
+ code: "custom",
187
+ path: ["entries"],
188
+ message: "active context requires entries and revoked context requires none",
189
+ });
190
+ }
191
+ const material = {
192
+ tenantId: context.tenantId,
193
+ target: context.target,
194
+ state: context.state,
195
+ revision: context.revision,
196
+ entries: context.entries,
197
+ };
198
+ if (context.contentHash !== certifiedContextContentHash(material)) {
199
+ refinement.addIssue({
200
+ code: "custom",
201
+ path: ["contentHash"],
202
+ message: "context content hash does not match the delivered context",
203
+ });
204
+ }
205
+ });
206
+ function deepFreeze(value) {
207
+ if (value !== null && typeof value === "object" && !Object.isFrozen(value)) {
208
+ for (const child of Object.values(value)) {
209
+ deepFreeze(child);
210
+ }
211
+ Object.freeze(value);
212
+ }
213
+ return value;
214
+ }
215
+ const _certifiedContextDeliverySchemaMatches = true;
216
+ const _certifiedContextProvenanceSchemaMatches = true;
217
+ const _certifiedContextEntrySchemaMatches = true;
218
+ const _certifiedContextSchemaMatches = true;
219
+ void [
220
+ _certifiedContextDeliverySchemaMatches,
221
+ _certifiedContextProvenanceSchemaMatches,
222
+ _certifiedContextEntrySchemaMatches,
223
+ _certifiedContextSchemaMatches,
224
+ ];
225
+ /** Parse, clone, and recursively freeze one untrusted context response. */
226
+ export function parseCertifiedContext(value) {
227
+ return deepFreeze(certifiedContextSchema.parse(value));
228
+ }
@@ -1,5 +1,5 @@
1
1
  import type { ReasoningEffort } from "./agent-profile.js";
2
- import { type HarnessType } from "./harness.js";
2
+ import type { HarnessType } from "./harness.js";
3
3
  /**
4
4
  * The unified harness capability layer — the single source of truth for:
5
5
  * 1. harness ↔ model compatibility (which models a harness can run), and
@@ -1,4 +1,3 @@
1
- import { canonicalizeHarness } from "./harness.js";
2
1
  /**
3
2
  * The unified harness capability layer — the single source of truth for:
4
3
  * 1. harness ↔ model compatibility (which models a harness can run), and
@@ -28,8 +27,7 @@ export const reasoningLadder = [
28
27
  // ── Harness ↔ model compatibility ────────────────────────────────────────────
29
28
  /**
30
29
  * Provider prefixes a harness is vendor-locked to (canonical-id prefix, e.g. `anthropic`, `openai`).
31
- * A harness with no entry is router-backed: it runs any model. Keyed by the BASE runner — aliases
32
- * (`claude`/`claudish`/`kimi`) resolve through `canonicalizeHarness` first.
30
+ * A harness with no entry is router-backed: it runs any model.
33
31
  *
34
32
  * `nanoclaw` is deliberately absent despite the "claw" name: its runner routes every provider through
35
33
  * the Tangle router (canonical model id straight to the gateway), so it is router-backed like
@@ -47,7 +45,7 @@ export function modelProvider(modelId) {
47
45
  }
48
46
  /** The providers a harness is locked to, or `null` when it is router-backed (any model). */
49
47
  export function harnessProviders(harness) {
50
- return harnessProviderLock[canonicalizeHarness(harness)] ?? null;
48
+ return harnessProviderLock[harness] ?? null;
51
49
  }
52
50
  /**
53
51
  * Whether a harness can run a model. Router-backed harnesses (no provider lock) accept anything;
@@ -76,7 +74,7 @@ export function preferredHarnessForModel(modelId) {
76
74
  /**
77
75
  * Per-harness ranking patterns for {@link snapModelToHarness}, best first; within one pattern the
78
76
  * highest version wins (numeric-aware). Only vendor-locked harnesses need an entry — a router-backed
79
- * harness never snaps (it runs the model as-is). Keyed by the BASE runner (aliases canonicalized).
77
+ * harness never snaps (it runs the model as-is).
80
78
  */
81
79
  const harnessPreferredModelPatterns = {
82
80
  "claude-code": [
@@ -101,7 +99,7 @@ const numericDesc = new Intl.Collator(undefined, {
101
99
  export function snapModelToHarness(harness, modelId, candidateIds) {
102
100
  if (harnessSupportsModel(harness, modelId))
103
101
  return modelId;
104
- const patterns = harnessPreferredModelPatterns[canonicalizeHarness(harness)] ?? [];
102
+ const patterns = harnessPreferredModelPatterns[harness] ?? [];
105
103
  for (const pattern of patterns) {
106
104
  const matches = candidateIds
107
105
  .filter((id) => pattern.test(id))
@@ -164,11 +162,10 @@ const harnessReasoningCeiling = {
164
162
  /** The reasoning efforts a harness can express, independent of model — its explicit override set, or
165
163
  * `none` up to its ceiling (default `ultracode` for router/model-driven harnesses). */
166
164
  export function harnessReasoningEfforts(harness) {
167
- const canonical = canonicalizeHarness(harness);
168
- const override = harnessReasoningEffortsOverride[canonical];
165
+ const override = harnessReasoningEffortsOverride[harness];
169
166
  if (override)
170
167
  return override;
171
- const ceiling = harnessReasoningCeiling[canonical] ?? "ultracode";
168
+ const ceiling = harnessReasoningCeiling[harness] ?? "ultracode";
172
169
  return reasoningLadder.slice(0, reasoningLadder.indexOf(ceiling) + 1);
173
170
  }
174
171
  /**
@@ -191,7 +188,7 @@ export function reasoningEffortsFor(harness, model) {
191
188
  /**
192
189
  * Harnesses whose runner DROPS a per-turn selector — grounded in the cli-bridge adapter audit, NOT a
193
190
  * guess. Most harnesses honor both selectors, so only the exceptions are listed; a harness absent from
194
- * a set honors that selector. Keyed by the BASE runner (aliases canonicalized).
191
+ * a set honors that selector.
195
192
  *
196
193
  * - model dropped: `amp` (own agent picks the model), `openclaw` (dispatcher routes by its own
197
194
  * config), `nanoclaw` (socket-bridge runner is config/env-driven).
@@ -215,11 +212,11 @@ const harnessIgnoresEffort = new Set([
215
212
  ]);
216
213
  /** Whether the harness's runner honors a per-turn MODEL override (vs. picking the model itself). */
217
214
  export function harnessHonorsModel(harness) {
218
- return !harnessIgnoresModel.has(canonicalizeHarness(harness));
215
+ return !harnessIgnoresModel.has(harness);
219
216
  }
220
217
  /** Whether the harness's runner honors a reasoning-EFFORT override (vs. dropping it). */
221
218
  export function harnessHonorsEffort(harness) {
222
- return !harnessIgnoresEffort.has(canonicalizeHarness(harness));
219
+ return !harnessIgnoresEffort.has(harness);
223
220
  }
224
221
  /** Whether the harness honors BOTH chat selectors — i.e. the model and effort pickers are live. */
225
222
  export function harnessHonorsSelectors(harness) {
package/dist/harness.d.ts CHANGED
@@ -14,20 +14,15 @@ import { z } from "zod";
14
14
  * a one-shot) with no full coding-agent harness. The rest are full agentic harnesses run in a
15
15
  * sandbox or locally via the CLI bridge.
16
16
  *
17
- * Some values are input aliases that collapse to a base runner (`claude`/`claudish` → `claude-code`,
18
- * `kimi` → `kimi-code`); normalize with {@link canonicalizeHarness} before keying per-runner config.
19
17
  */
20
- export type HarnessType = "claude-code" | "claude" | "claudish" | "nanoclaw" | "codex" | "opencode" | "kimi-code" | "kimi" | "pi" | "gemini" | "hermes" | "openclaw" | "amp" | "factory-droids" | "acp" | "cli-base";
18
+ export type HarnessType = "claude-code" | "nanoclaw" | "codex" | "opencode" | "kimi-code" | "pi" | "gemini" | "hermes" | "openclaw" | "amp" | "factory-droids" | "acp" | "cli-base";
21
19
  /** Runtime validator for {@link HarnessType}. Kept in lockstep with the type by the drift guard below. */
22
20
  export declare const harnessTypeSchema: z.ZodEnum<{
23
21
  "claude-code": "claude-code";
24
- claude: "claude";
25
- claudish: "claudish";
26
22
  nanoclaw: "nanoclaw";
27
23
  codex: "codex";
28
24
  opencode: "opencode";
29
25
  "kimi-code": "kimi-code";
30
- kimi: "kimi";
31
26
  pi: "pi";
32
27
  gemini: "gemini";
33
28
  hermes: "hermes";
@@ -37,7 +32,3 @@ export declare const harnessTypeSchema: z.ZodEnum<{
37
32
  acp: "acp";
38
33
  "cli-base": "cli-base";
39
34
  }>;
40
- /** Input alias → canonical base runner. Aliases accept legacy/shorthand harness names. */
41
- export declare const harnessAliases: Partial<Record<HarnessType, HarnessType>>;
42
- /** Collapse an alias to its base runner (idempotent on canonical values). */
43
- export declare function canonicalizeHarness(harness: HarnessType): HarnessType;
package/dist/harness.js CHANGED
@@ -2,13 +2,10 @@ import { z } from "zod";
2
2
  /** Runtime validator for {@link HarnessType}. Kept in lockstep with the type by the drift guard below. */
3
3
  export const harnessTypeSchema = z.enum([
4
4
  "claude-code",
5
- "claude",
6
- "claudish",
7
5
  "nanoclaw",
8
6
  "codex",
9
7
  "opencode",
10
8
  "kimi-code",
11
- "kimi",
12
9
  "pi",
13
10
  "gemini",
14
11
  "hermes",
@@ -18,15 +15,5 @@ export const harnessTypeSchema = z.enum([
18
15
  "acp",
19
16
  "cli-base",
20
17
  ]);
21
- /** Input alias → canonical base runner. Aliases accept legacy/shorthand harness names. */
22
- export const harnessAliases = {
23
- claude: "claude-code",
24
- claudish: "claude-code",
25
- kimi: "kimi-code",
26
- };
27
- /** Collapse an alias to its base runner (idempotent on canonical values). */
28
- export function canonicalizeHarness(harness) {
29
- return harnessAliases[harness] ?? harness;
30
- }
31
18
  const _harnessSchemaMatchesType = true;
32
19
  void _harnessSchemaMatchesType;
package/dist/index.d.ts CHANGED
@@ -157,7 +157,7 @@ export declare function normalizeInputParts(input: {
157
157
  export declare function renderInputPartsAsText(parts: InputPart[]): string;
158
158
  /**
159
159
  * The primary event for all part updates from OpenCode.
160
- * This is the canonical event - use this instead of legacy events.
160
+ * This is the canonical event for all part updates.
161
161
  */
162
162
  export type MessagePartUpdatedEvent = {
163
163
  type: "message.part.updated";
@@ -614,7 +614,12 @@ export * from "./interaction.js";
614
614
  export * from "./agent-candidate.js";
615
615
  export * from "./agent-candidate-schema.js";
616
616
  export * from "./agent-candidate-promotion-schema.js";
617
+ export { agentCandidateEvaluationPolicySchema } from "./agent-improvement-measurement-schema.js";
618
+ export * from "./agent-improvement-source.js";
619
+ export * from "./agent-profile-improvement.js";
620
+ export * from "./agent-profile-improvement-schema.js";
617
621
  export * from "./agent-profile.js";
622
+ export * from "./certified-context.js";
618
623
  export * from "./profile-diff.js";
619
624
  export * from "./harness.js";
620
625
  export * from "./harness-capabilities.js";
package/dist/index.js CHANGED
@@ -127,7 +127,12 @@ export * from "./interaction.js";
127
127
  export * from "./agent-candidate.js";
128
128
  export * from "./agent-candidate-schema.js";
129
129
  export * from "./agent-candidate-promotion-schema.js";
130
+ export { agentCandidateEvaluationPolicySchema } from "./agent-improvement-measurement-schema.js";
131
+ export * from "./agent-improvement-source.js";
132
+ export * from "./agent-profile-improvement.js";
133
+ export * from "./agent-profile-improvement-schema.js";
130
134
  export * from "./agent-profile.js";
135
+ export * from "./certified-context.js";
131
136
  export * from "./profile-diff.js";
132
137
  export * from "./harness.js";
133
138
  export * from "./harness-capabilities.js";
@@ -256,23 +256,6 @@ export type PermissionGrant = z.infer<typeof PermissionGrantSchema>;
256
256
  export declare function permissionAnswerSpec(opts?: {
257
257
  allowFeedback?: boolean;
258
258
  }): InteractionAnswerSpec;
259
- /** Shape of one legacy question (kept for the back-compat shim). */
260
- export type LegacyQuestion = {
261
- question: string;
262
- options?: Array<{
263
- label: string;
264
- description?: string;
265
- }>;
266
- multiSelect?: boolean;
267
- /** When true the select field accepts write-in answers beyond `options`. */
268
- allowCustom?: boolean;
269
- };
270
- /**
271
- * Build an answer spec from the legacy `question` event shape. Each question
272
- * becomes one select field (free text when it declares no options), so the old
273
- * question/answer path is expressible as a `question` interaction.
274
- */
275
- export declare function questionAnswerSpec(questions: LegacyQuestion[]): InteractionAnswerSpec;
276
259
  export type InteractionValidation = {
277
260
  ok: true;
278
261
  } | {
@@ -176,29 +176,6 @@ export function permissionAnswerSpec(opts) {
176
176
  }
177
177
  return { fields };
178
178
  }
179
- /**
180
- * Build an answer spec from the legacy `question` event shape. Each question
181
- * becomes one select field (free text when it declares no options), so the old
182
- * question/answer path is expressible as a `question` interaction.
183
- */
184
- export function questionAnswerSpec(questions) {
185
- const fields = questions.map((q, i) => {
186
- const name = `q${i}`;
187
- if (q.options && q.options.length > 0) {
188
- return {
189
- type: "select",
190
- name,
191
- label: q.question,
192
- required: true,
193
- multi: q.multiSelect === true,
194
- ...(q.allowCustom === true ? { allowCustom: true } : {}),
195
- options: q.options.map((o) => ({ value: o.label, label: o.label, description: o.description })),
196
- };
197
- }
198
- return { type: "text", name, label: q.question, required: true };
199
- });
200
- return { fields };
201
- }
202
179
  /**
203
180
  * Validate an accepted answer against its spec. Used by the broker before a
204
181
  * response reaches the adapter, so malformed answers are rejected centrally.
@@ -0,0 +1 @@
1
+ export declare function numbersApproximatelyEqual(left: number, right: number): boolean;
@@ -0,0 +1,4 @@
1
+ export function numbersApproximatelyEqual(left, right) {
2
+ const tolerance = Number.EPSILON * Math.max(1, Math.abs(left), Math.abs(right)) * 16;
3
+ return Math.abs(left - right) <= tolerance;
4
+ }
@@ -268,13 +268,10 @@ export declare const agentProfileSchema: z.ZodObject<{
268
268
  }, z.core.$strict>>;
269
269
  harness: z.ZodOptional<z.ZodEnum<{
270
270
  "claude-code": "claude-code";
271
- claude: "claude";
272
- claudish: "claudish";
273
271
  nanoclaw: "nanoclaw";
274
272
  codex: "codex";
275
273
  opencode: "opencode";
276
274
  "kimi-code": "kimi-code";
277
- kimi: "kimi";
278
275
  pi: "pi";
279
276
  gemini: "gemini";
280
277
  hermes: "hermes";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tangle-network/agent-interface",
3
- "version": "0.32.0",
3
+ "version": "0.34.0",
4
4
  "type": "module",
5
5
  "sideEffects": false,
6
6
  "license": "MIT",