@treeseed/sdk 0.13.0-rc.50 → 0.13.0-rc.52

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.
@@ -1,4 +1,5 @@
1
1
  import { z } from "zod";
2
+ import { AI_MODE_INTERNAL_PATH } from "./ai-mode.js";
2
3
  const identifier = z.string().regex(/^[a-z][a-z0-9.-]{1,63}$/u);
3
4
  const digest = z.string().regex(/^sha256:[a-f0-9]{64}$/u);
4
5
  const gitCommit = z.string().regex(/^[a-f0-9]{40}$/u);
@@ -131,7 +132,9 @@ const environmentName = z.string().regex(/^[A-Z][A-Z0-9_]{0,127}$/u, "Environmen
131
132
  const componentSecretPath = z.string().regex(/^\/etc\/treeseed\/credentials\/[a-z0-9][a-z0-9._-]{0,127}$/u, "Secret inputs must use manager-owned credential paths.");
132
133
  const componentConfigurationPath = z.string().regex(/^\/etc\/treeseed\/components\/[a-z][a-z0-9.-]*\/[a-z0-9][a-z0-9._-]{0,127}$/u, "Configuration inputs must use manager-owned component paths.");
133
134
  const componentRuntimeConfigurationSchema = z.object({
134
- environment: z.array(z.object({ name: environmentName, required: z.boolean(), default: z.string().max(16384).optional() }).strict()).default([]),
135
+ environment: z.array(z.object({ name: environmentName, required: z.boolean(), source: z.enum(["configuration", "manager"]).default("configuration"), default: z.string().max(16384).optional() }).strict().superRefine((input, context) => {
136
+ if (input.source === "manager" && input.default !== void 0) context.addIssue({ code: z.ZodIssueCode.custom, path: ["default"], message: "Manager-derived environment inputs cannot declare configuration defaults." });
137
+ })).default([]),
135
138
  secretEnvironment: z.array(z.object({ name: environmentName, required: z.boolean() }).strict()).default([]),
136
139
  secretFiles: z.array(z.object({ id: identifier, path: componentSecretPath, required: z.boolean() }).strict()).default([]),
137
140
  files: z.array(z.object({ id: identifier, path: componentConfigurationPath, required: z.boolean(), sensitive: z.boolean().default(false) }).strict()).default([])
@@ -164,11 +167,36 @@ const packageRuntimeSchema = z.object({
164
167
  capability: identifier,
165
168
  locality: z.enum(["local", "remote", "either"]),
166
169
  optional: z.boolean().default(false)
167
- }).strict()).default([])
170
+ }).strict()).default([]),
171
+ modeControl: z.object({
172
+ resource: z.literal("ai-gpu"),
173
+ role: z.enum(["inference", "training", "controller"]),
174
+ gate: z.object({
175
+ service: identifier,
176
+ executable: z.literal("/usr/local/bin/treeseed-ai-gpu-gate")
177
+ }).strict().optional(),
178
+ services: z.object({
179
+ base: z.array(identifier).min(1),
180
+ gpu: z.array(identifier).max(2),
181
+ warm: identifier.optional()
182
+ }).strict(),
183
+ internalControl: z.object({
184
+ transport: z.literal("mtls"),
185
+ clientCommonName: z.literal("client-ai-lab-mode"),
186
+ path: z.literal(AI_MODE_INTERNAL_PATH)
187
+ }).strict().optional()
188
+ }).strict().optional()
168
189
  }).strict().superRefine((runtime, context) => {
169
190
  const endpointIds = runtime.services.flatMap((service) => service.endpoints.map((endpoint) => `${service.id}.${endpoint.id}`));
170
191
  if (new Set(endpointIds).size !== endpointIds.length) context.addIssue({ code: z.ZodIssueCode.custom, path: ["services"], message: "Endpoint identities must be unique within a component." });
171
192
  for (const file of runtime.configuration.files) if (!file.path.startsWith(`/etc/treeseed/components/${runtime.componentId}/`)) context.addIssue({ code: z.ZodIssueCode.custom, path: ["configuration", "files"], message: `Configuration file ${file.id} is outside component ${runtime.componentId} custody.` });
193
+ if (runtime.modeControl) {
194
+ const services = new Set(runtime.services.map(({ composeService }) => composeService));
195
+ for (const service of [...runtime.modeControl.services.base, ...runtime.modeControl.services.gpu, ...runtime.modeControl.services.warm ? [runtime.modeControl.services.warm] : []]) if (!services.has(service)) context.addIssue({ code: z.ZodIssueCode.custom, path: ["modeControl", "services"], message: `AI mode service ${service} is not declared by the component runtime.` });
196
+ if (runtime.modeControl.gate && !services.has(runtime.modeControl.gate.service)) context.addIssue({ code: z.ZodIssueCode.custom, path: ["modeControl", "gate"], message: `AI mode gate service ${runtime.modeControl.gate.service} is not declared by the component runtime.` });
197
+ if (runtime.modeControl.role === "controller" && (!runtime.modeControl.internalControl || runtime.modeControl.gate || runtime.modeControl.services.gpu.length)) context.addIssue({ code: z.ZodIssueCode.custom, path: ["modeControl"], message: "The AI controller may declare only the scoped internal control surface." });
198
+ if (runtime.modeControl.role !== "controller" && (!runtime.modeControl.gate || runtime.modeControl.internalControl || runtime.modeControl.services.gpu.length === 0)) context.addIssue({ code: z.ZodIssueCode.custom, path: ["modeControl"], message: "AI GPU components require a fixed gate and at least one GPU service." });
199
+ }
172
200
  });
173
201
  const catalogPackageSchema = z.object({ name: z.string().regex(/^treeseed(?:-[a-z0-9-]+)?$/u), version: packageVersion, architecture: z.enum(["amd64", "all"]), origin: z.literal("TreeSeed Deployment"), order: z.number().int().nonnegative() }).strict();
174
202
  const catalogImageSchema = z.object({ role: identifier, repository: ociRepository, digest, platforms: z.array(z.enum(["linux/amd64", "linux/arm64"])).min(1), consumers: z.array(identifier).min(1) }).strict();
@@ -112,8 +112,8 @@ const operationBindings = {
112
112
  "projects treedx workspaces show": operation("treedx.workspaces.show", [field("path", "projectId", "context", "project", true), field("path", "workspaceId", "argument", "workspace", true)]),
113
113
  "projects treedx workspaces abandon": operation("treedx.workspaces.abandon", [field("path", "projectId", "context", "project", true), field("path", "workspaceId", "argument", "workspace", true)]),
114
114
  "ai status": operation("treeai.qualification.get.status", [aiNode()]),
115
- "ai mode show": operation("treeai.qualification.get.mode", [aiNode()]),
116
- "ai mode set": operation("treeai.qualification.post.mode", [aiNode(), field("body", "mode", "argument", "mode", true)]),
115
+ "ai mode show": local("local.host.ai.mode.show"),
116
+ "ai mode set": local("local.host.ai.mode.set"),
117
117
  "ai inference models": operation("treeai.inference.get.models", [aiNode()]),
118
118
  "ai inference jobs": operation("treeai.inference.get.jobs", [aiNode()]),
119
119
  "ai inference rollback": operation("treeai.inference.post.deployments.rollback", [aiNode()]),
@@ -178,6 +178,19 @@ function hostReset() {
178
178
  value.options = [...value.options ?? [], { name: "--confirm", description: "Confirm deletion of all manager-owned component data and receipts.", type: "boolean" }];
179
179
  return value;
180
180
  }
181
+ function aiModeSet() {
182
+ const value = leaf("set", "mutation", "mode", "authority");
183
+ if (value.nodeType !== "leaf") throw new Error("AI mode set must be a leaf command.");
184
+ value.description = "Transition the exclusive AI GPU resource to awake or sleep.";
185
+ value.options = [
186
+ ...value.options ?? [],
187
+ { name: "--idempotency-key", description: "Replay-safe transition identity.", type: "string" },
188
+ { name: "--drain-timeout", description: "Maximum drain wait in seconds.", type: "number" }
189
+ ];
190
+ value.authorization = { capability: "host.ai.mode", confirmation: "authority" };
191
+ value.resultSchemaId = "treeseed.ai-mode-transition-receipt/v1";
192
+ return value;
193
+ }
181
194
  function userCreate() {
182
195
  const value = leaf("create", "mutation");
183
196
  if (value.nodeType !== "leaf") throw new Error("User creation must be a leaf command.");
@@ -317,7 +330,7 @@ const commandTree = {
317
330
  ])]),
318
331
  branch("ai", [
319
332
  leaf("status"),
320
- branch("mode", [leaf("show"), leaf("set", "mutation", "mode", "authority")]),
333
+ branch("mode", [leaf("show"), aiModeSet()]),
321
334
  branch("inference", [leaf("models"), leaf("jobs"), leaf("rollback", "mutation", void 0, "destructive")]),
322
335
  branch("training", [leaf("libraries"), leaf("jobs"), leaf("runs")]),
323
336
  branch("lab", [leaf("status"), leaf("agents"), leaf("libraries")]),
@@ -8,7 +8,7 @@ export declare function communicationOperations(): {
8
8
  timeoutSeconds?: number | undefined;
9
9
  recipients?: string[] | undefined;
10
10
  }, {
11
- status: "failed" | "partial" | "complete" | "running" | "queued";
11
+ status: "failed" | "running" | "partial" | "complete" | "queued";
12
12
  schemaVersion: "treeseed.communication-send-receipt/v2";
13
13
  targets: {
14
14
  status: "failed" | "running" | "cancelled" | "queued" | "responded" | "abstained";
@@ -81,7 +81,7 @@ export declare function communicationOperations(): {
81
81
  teamId: string;
82
82
  sendId: string;
83
83
  }, {}, undefined, {
84
- status: "failed" | "partial" | "complete" | "running" | "queued";
84
+ status: "failed" | "running" | "partial" | "complete" | "queued";
85
85
  schemaVersion: "treeseed.communication-send-receipt/v2";
86
86
  targets: {
87
87
  status: "failed" | "running" | "cancelled" | "queued" | "responded" | "abstained";
@@ -425,7 +425,7 @@ export declare const communicationSendReceiptSchema: z.ZodObject<{
425
425
  updatedAt: z.ZodString;
426
426
  replayed: z.ZodBoolean;
427
427
  }, "strict", z.ZodTypeAny, {
428
- status: "failed" | "partial" | "complete" | "running" | "queued";
428
+ status: "failed" | "running" | "partial" | "complete" | "queued";
429
429
  schemaVersion: "treeseed.communication-send-receipt/v2";
430
430
  targets: {
431
431
  status: "failed" | "running" | "cancelled" | "queued" | "responded" | "abstained";
@@ -494,7 +494,7 @@ export declare const communicationSendReceiptSchema: z.ZodObject<{
494
494
  sourceMessage: string;
495
495
  replayed: boolean;
496
496
  }, {
497
- status: "failed" | "partial" | "complete" | "running" | "queued";
497
+ status: "failed" | "running" | "partial" | "complete" | "queued";
498
498
  schemaVersion: "treeseed.communication-send-receipt/v2";
499
499
  targets: {
500
500
  status: "failed" | "running" | "cancelled" | "queued" | "responded" | "abstained";
@@ -503,7 +503,7 @@ export declare const CONTROL_PLANE_OPERATIONS: {
503
503
  timeoutSeconds?: number | undefined;
504
504
  recipients?: string[] | undefined;
505
505
  }, {
506
- status: "failed" | "partial" | "complete" | "running" | "queued";
506
+ status: "failed" | "running" | "partial" | "complete" | "queued";
507
507
  schemaVersion: "treeseed.communication-send-receipt/v2";
508
508
  targets: {
509
509
  status: "failed" | "running" | "cancelled" | "queued" | "responded" | "abstained";
@@ -576,7 +576,7 @@ export declare const CONTROL_PLANE_OPERATIONS: {
576
576
  teamId: string;
577
577
  sendId: string;
578
578
  }, {}, undefined, {
579
- status: "failed" | "partial" | "complete" | "running" | "queued";
579
+ status: "failed" | "running" | "partial" | "complete" | "queued";
580
580
  schemaVersion: "treeseed.communication-send-receipt/v2";
581
581
  targets: {
582
582
  status: "failed" | "running" | "cancelled" | "queued" | "responded" | "abstained";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@treeseed/sdk",
3
- "version": "0.13.0-rc.50",
3
+ "version": "0.13.0-rc.52",
4
4
  "description": "Portable TreeSeed contracts, standards, and typed remote control-plane clients.",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {