@tangle-network/agent-interface 2.8.0 → 2.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -172,6 +172,13 @@ When caller environment values merge into a bridge or harness process, reject na
172
172
  Use `isCredentialBearingProfileConfigName(name)` before retaining public config.
173
173
  These checks do not apply to a replacement environment owned by caller code.
174
174
 
175
+ ## Failed execution accounting
176
+
177
+ An adapter can reject with `AgentExecutionError` and retain observed usage and timing in its immutable `receipt`.
178
+ Absent fields remain unknown.
179
+ The receipt records a lower bound, not complete accounting or a successful outcome.
180
+ Hosts must preserve it when publishing a failed or cancelled execution.
181
+
175
182
  ## Exact process environments
176
183
 
177
184
  Providers may expose the optional `exactProcess` capability for isolated, reproducible process execution.
@@ -12,6 +12,7 @@
12
12
  * fixed. This package is the canonical public home for these symbols.
13
13
  */
14
14
  import type { HarnessType } from "./harness.js";
15
+ import type { Sha256Digest } from "./agent-candidate.js";
15
16
  /**
16
17
  * Permission policy value for a capability.
17
18
  */
@@ -343,6 +344,53 @@ export interface AgentProfileConnection {
343
344
  */
344
345
  alias?: string;
345
346
  }
347
+ /** Router namespace reserved for checkpoint-backed models. Receipt-free profiles cannot use it. */
348
+ export declare const TRAINED_MODEL_PREFIX = "tangle-trained/";
349
+ /** An immutable Router alias; serving must independently attest this artifact-to-route binding. */
350
+ export declare function trainedModelIdForArtifact(digest: Sha256Digest): string;
351
+ /** Identity of a task whose data was exposed to training or model selection. */
352
+ export interface AgentTrainingTask {
353
+ benchmark: string;
354
+ task: string;
355
+ contentDigest: Sha256Digest;
356
+ }
357
+ /** Complete exposure inventory, derived from the exact dataset delivered to a trainer. */
358
+ export interface AgentTrainingDatasetIdentity {
359
+ digest: Sha256Digest;
360
+ taskSetDigest: Sha256Digest;
361
+ tasks: AgentTrainingTask[];
362
+ }
363
+ export interface AgentTrainingReceipt {
364
+ version: 1;
365
+ dataset: AgentTrainingDatasetIdentity;
366
+ parentProfileDigest: Sha256Digest;
367
+ /** Null only when the parent has no training receipt. */
368
+ parentReceiptDigest: Sha256Digest | null;
369
+ executionRef: Sha256Digest;
370
+ trainer: {
371
+ mode: "command" | "managed";
372
+ id: string;
373
+ revision: Sha256Digest;
374
+ /** Public hyperparameters only; credentials belong to the private executor. */
375
+ parameters: Record<string, string | number | boolean | null>;
376
+ };
377
+ checkpoint: {
378
+ artifactDigest: Sha256Digest;
379
+ artifactBytes: number;
380
+ routerModelId: string;
381
+ /** Digest of independently verified serving evidence, not trainer stdout. */
382
+ servingDigest: Sha256Digest;
383
+ };
384
+ }
385
+ export interface AgentProfileTraining {
386
+ receipt: AgentTrainingReceipt;
387
+ /** Immediate parent first, terminating at a receipt with parentReceiptDigest=null. */
388
+ ancestors: AgentTrainingReceipt[];
389
+ }
390
+ export interface AgentProfileMetadata extends Record<string, unknown> {
391
+ /** Reserved: a trained model is admitted only with a complete checkpoint receipt. */
392
+ training?: AgentProfileTraining;
393
+ }
346
394
  /**
347
395
  * Public provider-neutral agent profile contract.
348
396
  */
@@ -374,7 +422,7 @@ export interface AgentProfile {
374
422
  hooks?: Record<string, AgentProfileHookCommand[]>;
375
423
  modes?: Record<string, AgentProfileMode>;
376
424
  confidential?: AgentProfileConfidential;
377
- metadata?: Record<string, unknown>;
425
+ metadata?: AgentProfileMetadata;
378
426
  /**
379
427
  * Non-portable backend-specific extensions.
380
428
  *
@@ -63,6 +63,12 @@ export function defineAgentProfileSecretRef(key, format) {
63
63
  ...(format === undefined ? {} : { format }),
64
64
  };
65
65
  }
66
+ /** Router namespace reserved for checkpoint-backed models. Receipt-free profiles cannot use it. */
67
+ export const TRAINED_MODEL_PREFIX = "tangle-trained/";
68
+ /** An immutable Router alias; serving must independently attest this artifact-to-route binding. */
69
+ export function trainedModelIdForArtifact(digest) {
70
+ return `${TRAINED_MODEL_PREFIX}${digest.slice("sha256:".length)}`;
71
+ }
66
72
  /**
67
73
  * Helper for declaring typed profiles in application code.
68
74
  */
@@ -216,7 +216,7 @@ export declare const AgentInteractiveSessionStartSchema: z.ZodObject<{
216
216
  sealed: z.ZodOptional<z.ZodBoolean>;
217
217
  attestationRefresh: z.ZodOptional<z.ZodBoolean>;
218
218
  }, z.core.$strict>>;
219
- metadata: z.ZodOptional<z.ZodType<Record<string, unknown>, unknown, z.core.$ZodTypeInternals<Record<string, unknown>, unknown>>>;
219
+ metadata: z.ZodOptional<z.ZodType<import("./agent-profile.js").AgentProfileMetadata, unknown, z.core.$ZodTypeInternals<import("./agent-profile.js").AgentProfileMetadata, unknown>>>;
220
220
  extensions: z.ZodOptional<z.ZodType<Record<string, Record<string, unknown> | undefined>, unknown, z.core.$ZodTypeInternals<Record<string, Record<string, unknown> | undefined>, unknown>>>;
221
221
  }, z.core.$strict>;
222
222
  requestedProfileDigest: z.ZodType<`sha256:${string}`, unknown, z.core.$ZodTypeInternals<`sha256:${string}`, unknown>>;
@@ -5,7 +5,7 @@ import type { Sha256Digest } from "./agent-candidate.js";
5
5
  import type { AgentProfileCapabilities, AgentProfileValidationResult } from "./agent-profile.js";
6
6
  import type { InputPart } from "./parts.js";
7
7
  import type { StreamEvent } from "./stream-events.js";
8
- import type { TokenUsage } from "./execution-types.js";
8
+ import { type TokenUsage } from "./execution-types.js";
9
9
  import { type InteractionAcknowledgement, type InteractionCapabilities, type InteractionResponseCommand, type RequestedInteractions } from "./interaction.js";
10
10
  import { type ContextTransferReceipt, type ContextTransferRequest, type ContextTransferResult, type NativeContextBoundaryProof, type NativeContextContinuationRequest, type NativeContextContinuationTurn } from "./portable-context.js";
11
11
  import { type AgentExactRunControlRef, type AgentRunCancellationAcknowledgement, type AgentRunCancellationRequest, type AgentRunControlRef } from "./runtime-control.js";
@@ -1,6 +1,7 @@
1
1
  import { z } from "zod";
2
2
  export { AgentRuntimeAttachmentsSchema } from "./runtime-attachments.js";
3
3
  import { canonicalCandidateDigest, canonicalCandidateJson, } from "./agent-candidate-schema-common.js";
4
+ import { TokenUsageSchema } from "./execution-types.js";
4
5
  import { InteractionCapabilitiesSchema, RequestedInteractionsSchema } from "./interaction.js";
5
6
  import { ContextTransferReceiptSchema, ContextTransferRequestSchema, NativeContextBoundaryProofSchema, NativeContextContinuationAcknowledgementSchema, NativeContextContinuationRequestSchema, nativeContextContinuationAcknowledgementMatches } from "./portable-context.js";
6
7
  import { AgentExactRunControlRefSchema, AgentRunControlRefSchema, CanonicalStreamEventSchema } from "./runtime-control.js";
@@ -31,15 +32,6 @@ export const AgentTurnInputSchema = z.strictObject({
31
32
  signal: z.custom().optional(),
32
33
  providerOptions: boundedJsonRecordSchema.optional(),
33
34
  });
34
- const TokenUsageSchema = z.strictObject({
35
- inputTokens: z.number().int().nonnegative(),
36
- outputTokens: z.number().int().nonnegative(),
37
- totalTokens: z.number().int().nonnegative().optional(),
38
- cacheReadInputTokens: z.number().int().nonnegative().optional(),
39
- cacheCreationInputTokens: z.number().int().nonnegative().optional(),
40
- reasoningTokens: z.number().int().nonnegative().optional(),
41
- cost: z.number().finite().nonnegative().optional(),
42
- });
43
35
  const AgentEnvironmentEventSchema = z.strictObject({
44
36
  type: boundedIdentifierSchema,
45
37
  data: boundedEventContentRecordSchema,
@@ -0,0 +1,24 @@
1
+ import { z } from "zod";
2
+ export declare const AgentExecutionFailureReceiptSchema: z.ZodObject<{
3
+ tokenUsage: z.ZodOptional<z.ZodObject<{
4
+ inputTokens: z.ZodOptional<z.ZodNumber>;
5
+ outputTokens: z.ZodOptional<z.ZodNumber>;
6
+ totalTokens: z.ZodOptional<z.ZodOptional<z.ZodNumber>>;
7
+ cacheReadInputTokens: z.ZodOptional<z.ZodOptional<z.ZodNumber>>;
8
+ cacheCreationInputTokens: z.ZodOptional<z.ZodOptional<z.ZodNumber>>;
9
+ reasoningTokens: z.ZodOptional<z.ZodOptional<z.ZodNumber>>;
10
+ cost: z.ZodOptional<z.ZodOptional<z.ZodNumber>>;
11
+ }, z.core.$strict>>;
12
+ timing: z.ZodOptional<z.ZodObject<{
13
+ startedAt: z.ZodNumber;
14
+ completedAt: z.ZodNumber;
15
+ durationMs: z.ZodNumber;
16
+ }, z.core.$strict>>;
17
+ }, z.core.$strict>;
18
+ /** Observed accounting only; a failed execution may have additional unreported usage. */
19
+ export type AgentExecutionFailureReceipt = z.infer<typeof AgentExecutionFailureReceiptSchema>;
20
+ /** Retains observed resource use while preserving the adapter's rejection contract. */
21
+ export declare class AgentExecutionError extends Error {
22
+ readonly receipt: AgentExecutionFailureReceipt;
23
+ constructor(message: string, receipt: AgentExecutionFailureReceipt, options?: ErrorOptions);
24
+ }
@@ -0,0 +1,20 @@
1
+ import { z } from "zod";
2
+ import { deepFreeze } from "./deep-freeze.js";
3
+ import { TokenUsageSchema } from "./execution-types.js";
4
+ export const AgentExecutionFailureReceiptSchema = z.strictObject({
5
+ tokenUsage: TokenUsageSchema.partial().optional(),
6
+ timing: z.strictObject({
7
+ startedAt: z.number().finite().nonnegative(),
8
+ completedAt: z.number().finite().nonnegative(),
9
+ durationMs: z.number().finite().nonnegative(),
10
+ }).optional(),
11
+ });
12
+ /** Retains observed resource use while preserving the adapter's rejection contract. */
13
+ export class AgentExecutionError extends Error {
14
+ receipt;
15
+ constructor(message, receipt, options) {
16
+ super(message, options);
17
+ this.name = "AgentExecutionError";
18
+ this.receipt = deepFreeze(AgentExecutionFailureReceiptSchema.parse(receipt));
19
+ }
20
+ }
@@ -3,6 +3,7 @@ import type { InputPart } from "./parts.js";
3
3
  import type { ProviderConfig } from "./provider-config.js";
4
4
  import type { InteractionExecutionBinding } from "./interaction-envelope.js";
5
5
  import type { RequestedInteractions } from "./interaction-permissions.js";
6
+ import { z } from "zod";
6
7
  export type ToolInvocation = {
7
8
  toolName: string;
8
9
  input: unknown;
@@ -18,6 +19,15 @@ export type TokenUsage = {
18
19
  reasoningTokens?: number;
19
20
  cost?: number;
20
21
  };
22
+ export declare const TokenUsageSchema: z.ZodObject<{
23
+ inputTokens: z.ZodNumber;
24
+ outputTokens: z.ZodNumber;
25
+ totalTokens: z.ZodOptional<z.ZodNumber>;
26
+ cacheReadInputTokens: z.ZodOptional<z.ZodNumber>;
27
+ cacheCreationInputTokens: z.ZodOptional<z.ZodNumber>;
28
+ reasoningTokens: z.ZodOptional<z.ZodNumber>;
29
+ cost: z.ZodOptional<z.ZodNumber>;
30
+ }, z.core.$strict>;
21
31
  export type ExecutionTiming = {
22
32
  startedAt: number;
23
33
  completedAt: number;
@@ -1 +1,10 @@
1
- export {};
1
+ import { z } from "zod";
2
+ export const TokenUsageSchema = z.strictObject({
3
+ inputTokens: z.number().int().nonnegative(),
4
+ outputTokens: z.number().int().nonnegative(),
5
+ totalTokens: z.number().int().nonnegative().optional(),
6
+ cacheReadInputTokens: z.number().int().nonnegative().optional(),
7
+ cacheCreationInputTokens: z.number().int().nonnegative().optional(),
8
+ reasoningTokens: z.number().int().nonnegative().optional(),
9
+ cost: z.number().finite().nonnegative().optional(),
10
+ });
package/dist/index.d.ts CHANGED
@@ -2,6 +2,7 @@
2
2
  export * from "./parts.js";
3
3
  export * from "./stream-events.js";
4
4
  export * from "./execution-types.js";
5
+ export * from "./execution-failure.js";
5
6
  export * from "./backend-message.js";
6
7
  export * from "./provider-config.js";
7
8
  export * from "./host-services.js";
package/dist/index.js CHANGED
@@ -2,6 +2,7 @@
2
2
  export * from "./parts.js";
3
3
  export * from "./stream-events.js";
4
4
  export * from "./execution-types.js";
5
+ export * from "./execution-failure.js";
5
6
  export * from "./backend-message.js";
6
7
  export * from "./provider-config.js";
7
8
  export * from "./host-services.js";
@@ -1,5 +1,5 @@
1
1
  import { z } from "zod";
2
- import { type AgentProfile, type AgentProfileMcpServer } from "./agent-profile.js";
2
+ import { type AgentProfile, type AgentProfileMetadata, type AgentTrainingTask, type AgentProfileMcpServer } from "./agent-profile.js";
3
3
  import type { AgentProfileDiff } from "./profile-diff.js";
4
4
  import { type SandboxSizePreset } from "./sandbox-size.js";
5
5
  export declare const agentProfilePermissionValueSchema: z.ZodEnum<{
@@ -326,6 +326,116 @@ export declare const agentProfileDiffRemovalSchema: z.ZodObject<{
326
326
  metadata: z.ZodOptional<z.ZodUnion<readonly [z.ZodLiteral<true>, z.ZodArray<z.ZodString>]>>;
327
327
  extensions: z.ZodOptional<z.ZodUnion<readonly [z.ZodLiteral<true>, z.ZodArray<z.ZodString>]>>;
328
328
  }, z.core.$strict>;
329
+ export declare const agentTrainingTaskSchema: z.ZodObject<{
330
+ benchmark: z.ZodString;
331
+ task: z.ZodString;
332
+ contentDigest: z.ZodType<`sha256:${string}`, unknown, z.core.$ZodTypeInternals<`sha256:${string}`, unknown>>;
333
+ }, z.core.$strict>;
334
+ /** The same order is used by dataset ingestion, receipt admission and holdout checks. */
335
+ export declare function agentTrainingTaskKey(task: AgentTrainingTask): string;
336
+ export declare const agentTrainingDatasetIdentitySchema: z.ZodObject<{
337
+ digest: z.ZodType<`sha256:${string}`, unknown, z.core.$ZodTypeInternals<`sha256:${string}`, unknown>>;
338
+ taskSetDigest: z.ZodType<`sha256:${string}`, unknown, z.core.$ZodTypeInternals<`sha256:${string}`, unknown>>;
339
+ tasks: z.ZodArray<z.ZodObject<{
340
+ benchmark: z.ZodString;
341
+ task: z.ZodString;
342
+ contentDigest: z.ZodType<`sha256:${string}`, unknown, z.core.$ZodTypeInternals<`sha256:${string}`, unknown>>;
343
+ }, z.core.$strict>>;
344
+ }, z.core.$strict>;
345
+ export declare const agentTrainingParametersSchema: z.ZodType<Record<string, string | number | boolean | null>, unknown, z.core.$ZodTypeInternals<Record<string, string | number | boolean | null>, unknown>>;
346
+ export declare const agentTrainingReceiptSchema: z.ZodObject<{
347
+ version: z.ZodLiteral<1>;
348
+ dataset: z.ZodObject<{
349
+ digest: z.ZodType<`sha256:${string}`, unknown, z.core.$ZodTypeInternals<`sha256:${string}`, unknown>>;
350
+ taskSetDigest: z.ZodType<`sha256:${string}`, unknown, z.core.$ZodTypeInternals<`sha256:${string}`, unknown>>;
351
+ tasks: z.ZodArray<z.ZodObject<{
352
+ benchmark: z.ZodString;
353
+ task: z.ZodString;
354
+ contentDigest: z.ZodType<`sha256:${string}`, unknown, z.core.$ZodTypeInternals<`sha256:${string}`, unknown>>;
355
+ }, z.core.$strict>>;
356
+ }, z.core.$strict>;
357
+ parentProfileDigest: z.ZodType<`sha256:${string}`, unknown, z.core.$ZodTypeInternals<`sha256:${string}`, unknown>>;
358
+ parentReceiptDigest: z.ZodNullable<z.ZodType<`sha256:${string}`, unknown, z.core.$ZodTypeInternals<`sha256:${string}`, unknown>>>;
359
+ executionRef: z.ZodType<`sha256:${string}`, unknown, z.core.$ZodTypeInternals<`sha256:${string}`, unknown>>;
360
+ trainer: z.ZodObject<{
361
+ mode: z.ZodEnum<{
362
+ command: "command";
363
+ managed: "managed";
364
+ }>;
365
+ id: z.ZodString;
366
+ revision: z.ZodType<`sha256:${string}`, unknown, z.core.$ZodTypeInternals<`sha256:${string}`, unknown>>;
367
+ parameters: z.ZodType<Record<string, string | number | boolean | null>, unknown, z.core.$ZodTypeInternals<Record<string, string | number | boolean | null>, unknown>>;
368
+ }, z.core.$strict>;
369
+ checkpoint: z.ZodObject<{
370
+ artifactDigest: z.ZodType<`sha256:${string}`, unknown, z.core.$ZodTypeInternals<`sha256:${string}`, unknown>>;
371
+ artifactBytes: z.ZodNumber;
372
+ routerModelId: z.ZodString;
373
+ servingDigest: z.ZodType<`sha256:${string}`, unknown, z.core.$ZodTypeInternals<`sha256:${string}`, unknown>>;
374
+ }, z.core.$strict>;
375
+ }, z.core.$strict>;
376
+ export declare const agentProfileTrainingSchema: z.ZodObject<{
377
+ receipt: z.ZodObject<{
378
+ version: z.ZodLiteral<1>;
379
+ dataset: z.ZodObject<{
380
+ digest: z.ZodType<`sha256:${string}`, unknown, z.core.$ZodTypeInternals<`sha256:${string}`, unknown>>;
381
+ taskSetDigest: z.ZodType<`sha256:${string}`, unknown, z.core.$ZodTypeInternals<`sha256:${string}`, unknown>>;
382
+ tasks: z.ZodArray<z.ZodObject<{
383
+ benchmark: z.ZodString;
384
+ task: z.ZodString;
385
+ contentDigest: z.ZodType<`sha256:${string}`, unknown, z.core.$ZodTypeInternals<`sha256:${string}`, unknown>>;
386
+ }, z.core.$strict>>;
387
+ }, z.core.$strict>;
388
+ parentProfileDigest: z.ZodType<`sha256:${string}`, unknown, z.core.$ZodTypeInternals<`sha256:${string}`, unknown>>;
389
+ parentReceiptDigest: z.ZodNullable<z.ZodType<`sha256:${string}`, unknown, z.core.$ZodTypeInternals<`sha256:${string}`, unknown>>>;
390
+ executionRef: z.ZodType<`sha256:${string}`, unknown, z.core.$ZodTypeInternals<`sha256:${string}`, unknown>>;
391
+ trainer: z.ZodObject<{
392
+ mode: z.ZodEnum<{
393
+ command: "command";
394
+ managed: "managed";
395
+ }>;
396
+ id: z.ZodString;
397
+ revision: z.ZodType<`sha256:${string}`, unknown, z.core.$ZodTypeInternals<`sha256:${string}`, unknown>>;
398
+ parameters: z.ZodType<Record<string, string | number | boolean | null>, unknown, z.core.$ZodTypeInternals<Record<string, string | number | boolean | null>, unknown>>;
399
+ }, z.core.$strict>;
400
+ checkpoint: z.ZodObject<{
401
+ artifactDigest: z.ZodType<`sha256:${string}`, unknown, z.core.$ZodTypeInternals<`sha256:${string}`, unknown>>;
402
+ artifactBytes: z.ZodNumber;
403
+ routerModelId: z.ZodString;
404
+ servingDigest: z.ZodType<`sha256:${string}`, unknown, z.core.$ZodTypeInternals<`sha256:${string}`, unknown>>;
405
+ }, z.core.$strict>;
406
+ }, z.core.$strict>;
407
+ ancestors: z.ZodArray<z.ZodObject<{
408
+ version: z.ZodLiteral<1>;
409
+ dataset: z.ZodObject<{
410
+ digest: z.ZodType<`sha256:${string}`, unknown, z.core.$ZodTypeInternals<`sha256:${string}`, unknown>>;
411
+ taskSetDigest: z.ZodType<`sha256:${string}`, unknown, z.core.$ZodTypeInternals<`sha256:${string}`, unknown>>;
412
+ tasks: z.ZodArray<z.ZodObject<{
413
+ benchmark: z.ZodString;
414
+ task: z.ZodString;
415
+ contentDigest: z.ZodType<`sha256:${string}`, unknown, z.core.$ZodTypeInternals<`sha256:${string}`, unknown>>;
416
+ }, z.core.$strict>>;
417
+ }, z.core.$strict>;
418
+ parentProfileDigest: z.ZodType<`sha256:${string}`, unknown, z.core.$ZodTypeInternals<`sha256:${string}`, unknown>>;
419
+ parentReceiptDigest: z.ZodNullable<z.ZodType<`sha256:${string}`, unknown, z.core.$ZodTypeInternals<`sha256:${string}`, unknown>>>;
420
+ executionRef: z.ZodType<`sha256:${string}`, unknown, z.core.$ZodTypeInternals<`sha256:${string}`, unknown>>;
421
+ trainer: z.ZodObject<{
422
+ mode: z.ZodEnum<{
423
+ command: "command";
424
+ managed: "managed";
425
+ }>;
426
+ id: z.ZodString;
427
+ revision: z.ZodType<`sha256:${string}`, unknown, z.core.$ZodTypeInternals<`sha256:${string}`, unknown>>;
428
+ parameters: z.ZodType<Record<string, string | number | boolean | null>, unknown, z.core.$ZodTypeInternals<Record<string, string | number | boolean | null>, unknown>>;
429
+ }, z.core.$strict>;
430
+ checkpoint: z.ZodObject<{
431
+ artifactDigest: z.ZodType<`sha256:${string}`, unknown, z.core.$ZodTypeInternals<`sha256:${string}`, unknown>>;
432
+ artifactBytes: z.ZodNumber;
433
+ routerModelId: z.ZodString;
434
+ servingDigest: z.ZodType<`sha256:${string}`, unknown, z.core.$ZodTypeInternals<`sha256:${string}`, unknown>>;
435
+ }, z.core.$strict>;
436
+ }, z.core.$strict>>;
437
+ }, z.core.$strict>;
438
+ export declare const agentProfileMetadataSchema: z.ZodType<AgentProfileMetadata>;
329
439
  /**
330
440
  * The complete provider-neutral agent profile schema — the runtime validator for
331
441
  * the canonical {@link AgentProfile} TS contract. Kept structurally in lock-step
@@ -523,7 +633,7 @@ export declare const agentProfileSchema: z.ZodObject<{
523
633
  sealed: z.ZodOptional<z.ZodBoolean>;
524
634
  attestationRefresh: z.ZodOptional<z.ZodBoolean>;
525
635
  }, z.core.$strict>>;
526
- metadata: z.ZodOptional<z.ZodType<Record<string, unknown>, unknown, z.core.$ZodTypeInternals<Record<string, unknown>, unknown>>>;
636
+ metadata: z.ZodOptional<z.ZodType<AgentProfileMetadata, unknown, z.core.$ZodTypeInternals<AgentProfileMetadata, unknown>>>;
527
637
  extensions: z.ZodOptional<z.ZodType<Record<string, Record<string, unknown> | undefined>, unknown, z.core.$ZodTypeInternals<Record<string, Record<string, unknown> | undefined>, unknown>>>;
528
638
  }, z.core.$strict>;
529
639
  /**
@@ -1,6 +1,6 @@
1
1
  import { z } from "zod";
2
- import { REASONING_EFFORTS, } from "./agent-profile.js";
3
- import { environmentNameSchema, headerNameSchema, isSafeExecutable, isSafeRelativePath, isWellFormedUnicode, looksLikeCredential, } from "./agent-candidate-schema-common.js";
2
+ import { REASONING_EFFORTS, TRAINED_MODEL_PREFIX, trainedModelIdForArtifact, } from "./agent-profile.js";
3
+ import { canonicalCandidateDigest, sha256DigestSchema, environmentNameSchema, headerNameSchema, isSafeExecutable, isSafeRelativePath, isWellFormedUnicode, looksLikeCredential, } from "./agent-candidate-schema-common.js";
4
4
  import { harnessTypeSchema } from "./harness.js";
5
5
  import { SANDBOX_SIZE_PRESET_NAMES, } from "./sandbox-size.js";
6
6
  /**
@@ -322,6 +322,88 @@ export const agentProfileDiffRemovalSchema = z.strictObject({
322
322
  metadata: removeListSchema.optional(),
323
323
  extensions: removeListSchema.optional(),
324
324
  });
325
+ const trainingIdentitySchema = z.string().min(1).max(500).refine((value) => value.trim() === value && isWellFormedUnicode(value) &&
326
+ !controlCharacterPattern.test(value) && !looksLikeCredential(value), "training identity must be canonical public text");
327
+ export const agentTrainingTaskSchema = z.strictObject({
328
+ benchmark: trainingIdentitySchema,
329
+ task: trainingIdentitySchema,
330
+ contentDigest: sha256DigestSchema,
331
+ });
332
+ /** The same order is used by dataset ingestion, receipt admission and holdout checks. */
333
+ export function agentTrainingTaskKey(task) {
334
+ return JSON.stringify([task.benchmark, task.task, task.contentDigest]);
335
+ }
336
+ export const agentTrainingDatasetIdentitySchema = z.strictObject({
337
+ digest: sha256DigestSchema,
338
+ taskSetDigest: sha256DigestSchema,
339
+ tasks: z.array(agentTrainingTaskSchema).min(1).max(10_000),
340
+ }).superRefine((dataset, context) => {
341
+ const keys = dataset.tasks.map(agentTrainingTaskKey);
342
+ if (keys.some((key, index) => index > 0 && key <= keys[index - 1])) {
343
+ context.addIssue({ code: "custom", path: ["tasks"], message: "training tasks must be sorted and unique" });
344
+ }
345
+ if (canonicalCandidateDigest(dataset.tasks) !== dataset.taskSetDigest) {
346
+ context.addIssue({ code: "custom", path: ["taskSetDigest"], message: "training task inventory digest mismatch" });
347
+ }
348
+ });
349
+ export const agentTrainingParametersSchema = ownPropertyRecordSchema(z.union([z.string().max(2_048).pipe(publicProfileConfigStringSchema), z.number().finite(), z.boolean(), z.null()])).superRefine((parameters, context) => {
350
+ if (Object.keys(parameters).length > 100) {
351
+ context.addIssue({ code: "custom", message: "at most 100 public training parameters are allowed" });
352
+ }
353
+ for (const name of Object.keys(parameters)) {
354
+ if (!trainingIdentitySchema.safeParse(name).success || isCredentialBearingProfileConfigName(name)) {
355
+ context.addIssue({ code: "custom", path: [name], message: "training parameter name must be public and non-credential" });
356
+ }
357
+ }
358
+ });
359
+ export const agentTrainingReceiptSchema = z.strictObject({
360
+ version: z.literal(1),
361
+ dataset: agentTrainingDatasetIdentitySchema,
362
+ parentProfileDigest: sha256DigestSchema,
363
+ parentReceiptDigest: sha256DigestSchema.nullable(),
364
+ executionRef: sha256DigestSchema,
365
+ trainer: z.strictObject({
366
+ mode: z.enum(["command", "managed"]),
367
+ id: trainingIdentitySchema,
368
+ revision: sha256DigestSchema,
369
+ parameters: agentTrainingParametersSchema,
370
+ }),
371
+ checkpoint: z.strictObject({
372
+ artifactDigest: sha256DigestSchema,
373
+ artifactBytes: z.number().int().positive().max(Number.MAX_SAFE_INTEGER),
374
+ routerModelId: trainingIdentitySchema,
375
+ servingDigest: sha256DigestSchema,
376
+ }),
377
+ }).superRefine((receipt, context) => {
378
+ if (receipt.checkpoint.routerModelId !== trainedModelIdForArtifact(receipt.checkpoint.artifactDigest)) {
379
+ context.addIssue({ code: "custom", path: ["checkpoint", "routerModelId"], message: "trained Router model must be artifact-addressed" });
380
+ }
381
+ });
382
+ export const agentProfileTrainingSchema = z.strictObject({
383
+ receipt: agentTrainingReceiptSchema,
384
+ ancestors: z.array(agentTrainingReceiptSchema).max(8),
385
+ }).superRefine((training, context) => {
386
+ const chain = [training.receipt, ...training.ancestors];
387
+ const digests = chain.map(canonicalCandidateDigest);
388
+ if (new Set(digests).size !== digests.length) {
389
+ context.addIssue({ code: "custom", message: "training receipt ancestry must not repeat" });
390
+ }
391
+ for (let index = 0; index < chain.length; index++) {
392
+ if (chain[index].parentReceiptDigest !== (digests[index + 1] ?? null)) {
393
+ context.addIssue({ code: "custom", message: "training receipt ancestry is incomplete or has been altered" });
394
+ }
395
+ }
396
+ });
397
+ export const agentProfileMetadataSchema = ownPropertyRecordSchema(z.unknown()).superRefine((metadata, context) => {
398
+ if (!Object.hasOwn(metadata, "training"))
399
+ return;
400
+ const result = agentProfileTrainingSchema.safeParse(metadata.training);
401
+ if (!result.success) {
402
+ for (const issue of result.error.issues) {
403
+ context.addIssue({ code: "custom", path: ["training", ...issue.path], message: issue.message });
404
+ }
405
+ }
406
+ });
325
407
  /**
326
408
  * The complete provider-neutral agent profile schema — the runtime validator for
327
409
  * the canonical {@link AgentProfile} TS contract. Kept structurally in lock-step
@@ -345,11 +427,27 @@ export const agentProfileSchema = z
345
427
  hooks: ownPropertyRecordSchema(z.array(agentProfileHookCommandSchema)).optional(),
346
428
  modes: ownPropertyRecordSchema(agentProfileModeSchema).optional(),
347
429
  confidential: agentProfileConfidentialSchema.optional(),
348
- metadata: ownPropertyRecordSchema(z.unknown()).optional(),
430
+ metadata: agentProfileMetadataSchema.optional(),
349
431
  extensions: ownPropertyRecordSchema(z.union([ownPropertyRecordSchema(z.unknown()), z.undefined()])).optional(),
350
432
  })
351
433
  .superRefine((profile, context) => {
352
434
  validateNestedRecordKeys(profile, context, [], new Set());
435
+ const training = agentProfileTrainingSchema.safeParse(profile.metadata?.training);
436
+ if (profile.model?.default?.startsWith(TRAINED_MODEL_PREFIX) && !training.success) {
437
+ context.addIssue({ code: "custom", path: ["metadata", "training"], message: "trained model requires a checkpoint receipt" });
438
+ }
439
+ const auxiliaryModels = [
440
+ profile.model?.small,
441
+ ...Object.values(profile.subagents ?? {}).map((agent) => agent.model),
442
+ ...Object.values(profile.modes ?? {}).map((mode) => mode.model),
443
+ ];
444
+ if (auxiliaryModels.some((model) => model?.startsWith(TRAINED_MODEL_PREFIX) &&
445
+ (!training.success || model !== training.data.receipt.checkpoint.routerModelId))) {
446
+ context.addIssue({ code: "custom", message: "trained auxiliary models require the same receipted checkpoint" });
447
+ }
448
+ if (training.success && profile.model?.default !== training.data.receipt.checkpoint.routerModelId) {
449
+ context.addIssue({ code: "custom", path: ["model", "default"], message: "trained profile model must equal the receipt's Router model" });
450
+ }
353
451
  });
354
452
  const encodedRecordKeyPattern = "^u(?:[0-9a-f]{4})*$";
355
453
  function isEncodedRecordKeyPropertyNames(value) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tangle-network/agent-interface",
3
- "version": "2.8.0",
3
+ "version": "2.10.0",
4
4
  "type": "module",
5
5
  "sideEffects": false,
6
6
  "license": "MIT",