@tangle-network/agent-interface 3.0.0 → 3.1.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.
@@ -166,6 +166,35 @@ export declare const agentProfileModelHintsSchema: z.ZodObject<{
166
166
  maxTotalOutputTokens: z.ZodOptional<z.ZodNumber>;
167
167
  metadata: z.ZodOptional<z.ZodType<Record<string, unknown>, unknown, z.core.$ZodTypeInternals<Record<string, unknown>, unknown>>>;
168
168
  }, z.core.$strict>;
169
+ /** Ordered account selection policy, without credentials or ambient model defaults. */
170
+ export declare const agentProfileSeatSchema: z.ZodObject<{
171
+ harness: z.ZodEnum<{
172
+ acp: "acp";
173
+ amp: "amp";
174
+ "claude-code": "claude-code";
175
+ "cli-base": "cli-base";
176
+ codex: "codex";
177
+ cursor: "cursor";
178
+ "factory-droids": "factory-droids";
179
+ forge: "forge";
180
+ gemini: "gemini";
181
+ hermes: "hermes";
182
+ "kimi-code": "kimi-code";
183
+ nanoclaw: "nanoclaw";
184
+ openclaw: "openclaw";
185
+ opencode: "opencode";
186
+ pi: "pi";
187
+ prime: "prime";
188
+ }>;
189
+ provider: z.ZodString;
190
+ model: z.ZodString;
191
+ selector: z.ZodUnion<readonly [z.ZodObject<{
192
+ kind: z.ZodLiteral<"all-eligible">;
193
+ }, z.core.$strict>, z.ZodObject<{
194
+ kind: z.ZodLiteral<"seat">;
195
+ id: z.ZodString;
196
+ }, z.core.$strict>]>;
197
+ }, z.core.$strict>;
169
198
  /**
170
199
  * Replacement and addition are separate, independently optional fields, and the
171
200
  * pair is admitted on purpose: the effective prompt is `systemPrompt` followed
@@ -306,6 +335,7 @@ export declare const agentProfileDiffRemovalSchema: z.ZodObject<{
306
335
  }, z.core.$strict>]>>;
307
336
  model: z.ZodOptional<z.ZodUnion<readonly [z.ZodLiteral<true>, z.ZodArray<z.ZodString>]>>;
308
337
  harness: z.ZodOptional<z.ZodLiteral<true>>;
338
+ seats: z.ZodOptional<z.ZodLiteral<true>>;
309
339
  permissions: z.ZodOptional<z.ZodUnion<readonly [z.ZodLiteral<true>, z.ZodArray<z.ZodString>]>>;
310
340
  tools: z.ZodOptional<z.ZodUnion<readonly [z.ZodLiteral<true>, z.ZodArray<z.ZodString>]>>;
311
341
  mcp: z.ZodOptional<z.ZodUnion<readonly [z.ZodLiteral<true>, z.ZodArray<z.ZodString>]>>;
@@ -487,6 +517,34 @@ export declare const agentProfileSchema: z.ZodObject<{
487
517
  pi: "pi";
488
518
  prime: "prime";
489
519
  }>>;
520
+ seats: z.ZodOptional<z.ZodArray<z.ZodObject<{
521
+ harness: z.ZodEnum<{
522
+ acp: "acp";
523
+ amp: "amp";
524
+ "claude-code": "claude-code";
525
+ "cli-base": "cli-base";
526
+ codex: "codex";
527
+ cursor: "cursor";
528
+ "factory-droids": "factory-droids";
529
+ forge: "forge";
530
+ gemini: "gemini";
531
+ hermes: "hermes";
532
+ "kimi-code": "kimi-code";
533
+ nanoclaw: "nanoclaw";
534
+ openclaw: "openclaw";
535
+ opencode: "opencode";
536
+ pi: "pi";
537
+ prime: "prime";
538
+ }>;
539
+ provider: z.ZodString;
540
+ model: z.ZodString;
541
+ selector: z.ZodUnion<readonly [z.ZodObject<{
542
+ kind: z.ZodLiteral<"all-eligible">;
543
+ }, z.core.$strict>, z.ZodObject<{
544
+ kind: z.ZodLiteral<"seat">;
545
+ id: z.ZodString;
546
+ }, z.core.$strict>]>;
547
+ }, z.core.$strict>>>;
490
548
  permissions: z.ZodOptional<z.ZodType<Record<string, "allow" | "ask" | "deny" | Record<string, "allow" | "ask" | "deny">>, unknown, z.core.$ZodTypeInternals<Record<string, "allow" | "ask" | "deny" | Record<string, "allow" | "ask" | "deny">>, unknown>>>;
491
549
  tools: z.ZodOptional<z.ZodType<Record<string, boolean>, unknown, z.core.$ZodTypeInternals<Record<string, boolean>, unknown>>>;
492
550
  mcp: z.ZodOptional<z.ZodType<Record<string, AgentProfileMcpServer>, unknown, z.core.$ZodTypeInternals<Record<string, AgentProfileMcpServer>, unknown>>>;
@@ -2,6 +2,7 @@ import { z } from "zod";
2
2
  import { REASONING_EFFORTS, TRAINED_MODEL_PREFIX, trainedModelIdForArtifact, } from "./agent-profile.js";
3
3
  import { canonicalCandidateDigest, sha256DigestSchema, environmentNameSchema, headerNameSchema, isSafeExecutable, isSafeRelativePath, isWellFormedUnicode, looksLikeCredential, } from "./agent-candidate-schema-common.js";
4
4
  import { harnessTypeSchema } from "./harness.js";
5
+ import { harnessHonorsEffort, harnessHonorsModel, harnessModelSupport, harnessReasoningEfforts, harnessSystemPromptIntents, resolveModelProvider, } from "./harness-capabilities.js";
5
6
  import { SANDBOX_SIZE_PRESET_NAMES, } from "./sandbox-size.js";
6
7
  /**
7
8
  * Zod records currently assign parsed values onto an ordinary object. The
@@ -130,6 +131,16 @@ export const agentProfileModelHintsBaseSchema = z.strictObject({
130
131
  metadata: ownPropertyRecordSchema(z.unknown()).optional(),
131
132
  });
132
133
  export const agentProfileModelHintsSchema = agentProfileModelHintsBaseSchema.superRefine(enforceModelTokenBounds);
134
+ /** Ordered account selection policy, without credentials or ambient model defaults. */
135
+ export const agentProfileSeatSchema = z.strictObject({
136
+ harness: harnessTypeSchema,
137
+ provider: z.string().regex(/^[a-z][a-z0-9-]*$/),
138
+ model: z.string().min(1).refine((value) => value.trim() === value, "model must be canonical"),
139
+ selector: z.union([
140
+ z.strictObject({ kind: z.literal("all-eligible") }),
141
+ z.strictObject({ kind: z.literal("seat"), id: z.string().min(1).refine((value) => value.trim() === value, "seat id must be canonical") }),
142
+ ]),
143
+ });
133
144
  /**
134
145
  * Replacement and addition are separate, independently optional fields, and the
135
146
  * pair is admitted on purpose: the effective prompt is `systemPrompt` followed
@@ -308,6 +319,7 @@ export const agentProfileDiffRemovalSchema = z.strictObject({
308
319
  .optional(),
309
320
  model: removeListSchema.optional(),
310
321
  harness: z.literal(true).optional(),
322
+ seats: z.literal(true).optional(),
311
323
  permissions: removeListSchema.optional(),
312
324
  tools: removeListSchema.optional(),
313
325
  mcp: removeListSchema.optional(),
@@ -418,6 +430,7 @@ export const agentProfileSchema = z
418
430
  prompt: agentProfilePromptSchema.optional(),
419
431
  model: agentProfileModelHintsSchema.optional(),
420
432
  harness: harnessTypeSchema.optional(),
433
+ seats: z.array(agentProfileSeatSchema).nonempty().optional(),
421
434
  permissions: ownPropertyRecordSchema(agentProfilePermissionSchema).optional(),
422
435
  tools: ownPropertyRecordSchema(z.boolean()).optional(),
423
436
  mcp: ownPropertyRecordSchema(agentProfileMcpServerSchema).optional(),
@@ -432,6 +445,38 @@ export const agentProfileSchema = z
432
445
  })
433
446
  .superRefine((profile, context) => {
434
447
  validateNestedRecordKeys(profile, context, [], new Set());
448
+ if (profile.seats?.length) {
449
+ const first = profile.seats[0];
450
+ if (first.harness !== profile.harness || first.provider !== profile.model?.provider ||
451
+ first.model !== profile.model?.default) {
452
+ context.addIssue({ code: "custom", path: ["seats", 0], message: "first seat must match profile harness, model.provider, and model.default" });
453
+ }
454
+ for (const [index, seat] of profile.seats.entries()) {
455
+ const provider = resolveModelProvider(seat.model);
456
+ if (provider !== seat.provider) {
457
+ context.addIssue({ code: "custom", path: ["seats", index, "provider"], message: "seat provider must match the model provider" });
458
+ }
459
+ if (!harnessHonorsModel(seat.harness)) {
460
+ context.addIssue({ code: "custom", path: ["seats", index, "harness"], message: "seat harness does not honor an exact model choice" });
461
+ }
462
+ const support = harnessModelSupport(seat.harness, seat.model, { reasoningEffort: profile.model?.reasoningEffort });
463
+ if (!support.supported) {
464
+ context.addIssue({ code: "custom", path: ["seats", index, "model"], message: support.message });
465
+ }
466
+ const effort = profile.model?.reasoningEffort;
467
+ if (effort !== undefined && (!harnessHonorsEffort(seat.harness) ||
468
+ !harnessReasoningEfforts(seat.harness).includes(effort))) {
469
+ context.addIssue({ code: "custom", path: ["seats", index, "harness"], message: "seat harness cannot honor profile reasoning effort" });
470
+ }
471
+ const prompt = harnessSystemPromptIntents(seat.harness);
472
+ if (profile.prompt?.systemPrompt !== undefined && !prompt.replace) {
473
+ context.addIssue({ code: "custom", path: ["seats", index, "harness"], message: "seat harness cannot replace the system prompt" });
474
+ }
475
+ if (profile.prompt?.appendSystemPrompt !== undefined && !prompt.append) {
476
+ context.addIssue({ code: "custom", path: ["seats", index, "harness"], message: "seat harness cannot append the system prompt" });
477
+ }
478
+ }
479
+ }
435
480
  const training = agentProfileTrainingSchema.safeParse(profile.metadata?.training);
436
481
  if (profile.model?.default?.startsWith(TRAINED_MODEL_PREFIX) && !training.success) {
437
482
  context.addIssue({ code: "custom", path: ["metadata", "training"], message: "trained model requires a checkpoint receipt" });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tangle-network/agent-interface",
3
- "version": "3.0.0",
3
+ "version": "3.1.0",
4
4
  "type": "module",
5
5
  "sideEffects": false,
6
6
  "license": "MIT",