@hivemagnus/ardent-studio 0.1.0 → 0.1.1

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.
@@ -12,7 +12,7 @@ export declare function operationView(record: AgentOperationRecord, operation: M
12
12
  kind: "hivemem" | "deploy";
13
13
  status: "failed" | "running" | "succeeded";
14
14
  steps: {
15
- name: string;
15
+ name: "profile-create" | "config-save" | "skill-set" | "service-start" | "service-restart" | "profile-check" | "identity-soul" | "identity-identity" | "hivemem-enroll" | "ready-probe";
16
16
  status: "pending" | "failed" | "running" | "succeeded" | "skipped";
17
17
  started_at: string | null;
18
18
  finished_at: string | null;
@@ -3,7 +3,7 @@
3
3
  // its step receipts as `agent.operation.updated` events, from Magnus's operation stream, or by
4
4
  // polling when the stream fails. Running operations are picked up again after a restart.
5
5
  import { setTimeout as delay } from 'node:timers/promises';
6
- import { agentOperationSchema } from '../clients/magnus.js';
6
+ import { ardentAgentOperationSchema } from '../clients/magnus.js';
7
7
  /** An operation as the browser sees it. */
8
8
  export function operationView(record, operation) {
9
9
  return {
@@ -71,7 +71,7 @@ export class OperationRelay {
71
71
  for await (const message of this.magnus.streamAgentOperation(id, { signal })) {
72
72
  if (message.event !== 'operation' && message.event !== 'done')
73
73
  continue;
74
- const parsed = agentOperationSchema.safeParse(JSON.parse(message.data));
74
+ const parsed = ardentAgentOperationSchema.safeParse(JSON.parse(message.data));
75
75
  if (parsed.success && this.apply(id, parsed.data))
76
76
  return;
77
77
  }
@@ -1,6 +1,9 @@
1
+ import { ARDENT_SERVICE_CONFIG_PATHS, ardentAgentDeployRequestSchema, ardentAgentOperationSchema, ardentConfigFileSchema, ardentConfigSavedSchema, ardentContextItemSchema, ardentDevelopmentNoteSchema, ardentDevelopmentRecordSchema, ardentIdentityFileSchema, ardentMissionSubmitSchema, ardentPreviewSubmitSchema, ardentServiceProfileSchema, ardentSessionContextSchema, ardentSessionOpenSchema, ardentSkillInstallResultSchema, ardentSkillInstallSchema, ardentTaskJournalEventSchema, ardentTeamMissionSchema } from '@hivemagnus/magnus-contracts/ardent-service';
1
2
  import { z } from 'zod';
2
3
  import { type SseMessage } from './sse.js';
3
4
  import type { ServiceTokenProvider } from './service-token.js';
5
+ export { ARDENT_SERVICE_ADMIN_ACTIONS, ARDENT_SERVICE_CONFIG_PATHS, ARDENT_STUDIO_CAPABILITY, ARDENT_STUDIO_EVENT_KINDS, ardentAgentOperationSchema, ardentTaskDoneEventSchema, ardentTaskJournalEventSchema, ardentTaskTextEventSchema, ardentTeamMissionSchema, } from '@hivemagnus/magnus-contracts/ardent-service';
6
+ export { ARDENT_CONTEXT_ITEMS_MAX_BYTES } from '@hivemagnus/magnus-contracts/browser';
4
7
  export declare const ACTING_SUBJECT_HEADER = "x-acting-subject";
5
8
  export declare class MagnusError extends Error {
6
9
  readonly status: number;
@@ -19,25 +22,11 @@ export interface CallContext {
19
22
  actingSubject?: string | undefined;
20
23
  signal?: AbortSignal | undefined;
21
24
  }
22
- export declare const magnusArdentProfileSchema: z.ZodObject<{
23
- id: z.ZodString;
24
- name: z.ZodString;
25
- backend: z.ZodNullable<z.ZodEnum<{
26
- llamacpp: "llamacpp";
27
- codex: "codex";
28
- }>>;
29
- apiPort: z.ZodNullable<z.ZodNumber>;
30
- running: z.ZodBoolean;
31
- a2aEnabled: z.ZodBoolean;
32
- channels: z.ZodRecord<z.ZodString, z.ZodBoolean>;
33
- error: z.ZodNullable<z.ZodString>;
34
- nodeId: z.ZodString;
35
- nodeName: z.ZodString;
36
- hostname: z.ZodString;
37
- installationVersion: z.ZodNullable<z.ZodString>;
38
- reachable: z.ZodBoolean;
39
- }, z.core.$strip>;
40
- export type MagnusArdentProfile = z.infer<typeof magnusArdentProfileSchema>;
25
+ export type MagnusArdentProfile = z.infer<typeof ardentServiceProfileSchema>;
26
+ /**
27
+ * GET /ardent/installations and /ardent/installations/{nodeId}. The service contract answers these
28
+ * as records, so Studio reads only the fields it uses (Magnus ArdentFleetInstallationSchema).
29
+ */
41
30
  export declare const magnusArdentInstallationSchema: z.ZodObject<{
42
31
  installed: z.ZodBoolean;
43
32
  version: z.ZodNullable<z.ZodString>;
@@ -101,13 +90,6 @@ export declare const ardentTaskSchema: z.ZodObject<{
101
90
  created_ms: z.ZodNumber;
102
91
  updated_ms: z.ZodNumber;
103
92
  }, z.core.$strip>;
104
- export declare const ardentTaskEventSchema: z.ZodObject<{
105
- sequence: z.ZodNumber;
106
- task_id: z.ZodString;
107
- kind: z.ZodString;
108
- detail: z.ZodOptional<z.ZodUnknown>;
109
- created_ms: z.ZodNumber;
110
- }, z.core.$strip>;
111
93
  export declare const ardentStatusSchema: z.ZodObject<{
112
94
  version: z.ZodString;
113
95
  profile: z.ZodString;
@@ -129,13 +111,8 @@ export declare const ardentSkillSchema: z.ZodObject<{
129
111
  name: z.ZodString;
130
112
  enabled: z.ZodBoolean;
131
113
  }, z.core.$loose>;
132
- /** Admission of task-submit, mission-submit and preview-submit: durable acceptance, never completion. */
133
- export declare const ardentAcceptedTaskSchema: z.ZodObject<{
134
- task_id: z.ZodString;
135
- state: z.ZodString;
136
- }, z.core.$strip>;
137
- /** Profile resources released Magnus lets a caller read (routes/ardent.ts allow-list). */
138
- export type ArdentResource = 'openapi' | 'status' | 'profile' | 'config' | 'config/schema' | 'providers' | 'channels' | 'peers' | 'peers/config' | 'memory/status' | 'skills' | 'sessions' | 'tasks' | `tasks/${string}` | `tasks/${string}/events` | `sessions/${string}/messages` | 'identity/soul' | 'identity/identity' | 'identity/soul/history' | 'identity/identity/history' | `tasks/${string}/artifacts` | `artifacts/${string}/manifest` | 'development';
114
+ /** Profile resources Magnus lets a service identity read (the resource note of ardentServiceRoutes). */
115
+ export type ArdentResource = 'status' | 'profile' | 'skills' | 'memory/status' | 'sessions' | `sessions/${string}/messages` | 'tasks' | `tasks/${string}` | `tasks/${string}/events` | 'identity/soul' | 'identity/identity' | 'config' | `tasks/${string}/artifacts` | `artifacts/${string}/manifest` | 'development';
139
116
  /** Actions released Magnus accepts on POST …/action (an ADMIN person; a service identity gets the Studio subset below). */
140
117
  export declare const RELEASED_ACTIONS: readonly ["profile-create", "config-validate", "config-save", "peer-validate", "peer-save", "identity-save", "identity-restore", "provider-test", "channel-test", "peer-test", "memory-search", "task-submit", "task-cancel", "skill-set", "service-start", "service-stop", "service-restart", "package-install", "context-stage", "context-adopt", "context-rollback"];
141
118
  /**
@@ -144,18 +121,7 @@ export declare const RELEASED_ACTIONS: readonly ["profile-create", "config-valid
144
121
  */
145
122
  export declare const STUDIO_ACTIONS: readonly ["session-open", "mission-submit", "task-pause", "task-resume", "preview-submit", "development-note", "skill-install"];
146
123
  export type MagnusArdentAction = typeof RELEASED_ACTIONS[number] | typeof STUDIO_ACTIONS[number];
147
- /**
148
- * Agent changes Magnus runs for a service identity only with x-acting-subject naming a linked Magnus
149
- * ADMIN (Magnus ARDENT_SERVICE_ADMIN_ACTIONS). Without one: 403 ACTING_ADMIN_REQUIRED; an unlinked
150
- * subject: 403 ACTING_SUBJECT_UNLINKED. A stale revision answers 409 CONFLICT. Reading config needs
151
- * the same acting ADMIN.
152
- */
153
- export declare const ARDENT_SERVICE_ADMIN_ACTIONS: readonly ["identity-save", "skill-set", "config-save", "skill-install"];
154
- /**
155
- * The only configuration values a service's config-save may change (Magnus ARDENT_SERVICE_CONFIG_PATHS).
156
- * A change anywhere else answers 403 CONFIG_PATH_FORBIDDEN. An array is one value.
157
- */
158
- export declare const ARDENT_SERVICE_CONFIG_PATHS: readonly ["execution.backend", "providers.llamacpp.model", "providers.llamacpp.request_timeout_seconds", "providers.llamacpp.context_window_tokens", "providers.llamacpp.max_output_tokens", "providers.llamacpp.reasoning_effort", "providers.codex.model", "skills.enabled", "artifacts.max_bytes"];
124
+ /** A configuration value a service's config-save may change (ARDENT_SERVICE_CONFIG_PATHS); anything else answers 403 CONFIG_PATH_FORBIDDEN. */
159
125
  export type ArdentServiceConfigPath = typeof ARDENT_SERVICE_CONFIG_PATHS[number];
160
126
  /**
161
127
  * Whether Magnus lets the Studio service identity run service-restart. It does not: a service may run
@@ -163,433 +129,23 @@ export type ArdentServiceConfigPath = typeof ARDENT_SERVICE_CONFIG_PATHS[number]
163
129
  * profile restart stays a person's act in the Magnus console.
164
130
  */
165
131
  export declare const ARDENT_SERVICE_CAN_RESTART = false;
166
- /** Node agent Studio levels (Magnus ARDENT_STUDIO_CAPABILITY). */
167
- export declare const ARDENT_STUDIO_CAPABILITY: {
168
- readonly bridge: 1;
169
- readonly missions: 2;
170
- readonly skillInstall: 3;
171
- };
172
- /** Journal event kinds Ardent 2.2.0 adds. Others appear too; readers accept unknown kinds. */
173
- export declare const ARDENT_STUDIO_EVENT_KINDS: readonly ["mission", "team_handoff", "team_ask_user", "team_propose_decision", "artifact_registered", "development_note", "team_result", "team_result_rejected", "pause_requested", "paused", "resumed", "preview"];
174
- export declare const ardentSessionContextSchema: z.ZodEnum<{
175
- direct: "direct";
176
- mission: "mission";
177
- preview: "preview";
178
- }>;
179
132
  export type ArdentSessionContext = z.infer<typeof ardentSessionContextSchema>;
180
- /** GET …/identity/soul and …/identity/identity, and the identity-save answer. */
181
- export declare const ardentIdentityFileSchema: z.ZodObject<{
182
- kind: z.ZodEnum<{
183
- soul: "soul";
184
- identity: "identity";
185
- }>;
186
- name: z.ZodString;
187
- text: z.ZodString;
188
- revision: z.ZodString;
189
- }, z.core.$strip>;
190
133
  export type ArdentIdentityFile = z.infer<typeof ardentIdentityFileSchema>;
191
- /** GET …/config: the raw config.yaml and its revision (the base for skill-set and config-save). Secrets appear only as environment variable names. */
192
- export declare const ardentConfigFileSchema: z.ZodObject<{
193
- revision: z.ZodString;
194
- text: z.ZodString;
195
- }, z.core.$strip>;
196
134
  export type ArdentConfigFile = z.infer<typeof ardentConfigFileSchema>;
197
- /** The skill-set and config-save answer: the new configuration revision. The change applies once the profile restarts. */
198
- export declare const ardentConfigSavedSchema: z.ZodObject<{
199
- revision: z.ZodString;
200
- activation_required: z.ZodBoolean;
201
- }, z.core.$strip>;
202
135
  export type ArdentConfigSaved = z.infer<typeof ardentConfigSavedSchema>;
203
- /** action identity-save */
204
- export declare const ardentIdentityEditSchema: z.ZodObject<{
205
- text: z.ZodString;
206
- revision: z.ZodString;
207
- }, z.core.$strict>;
208
- /** action skill-set: revision is the configuration revision. */
209
- export declare const ardentSkillEditSchema: z.ZodObject<{
210
- enabled: z.ZodBoolean;
211
- revision: z.ZodString;
212
- }, z.core.$strict>;
213
- export declare const ardentSkillTargetSchema: z.ZodString;
214
- /**
215
- * action skill-install (Magnus ardentSkillInstallSchema): a HiveSkills catalog release that Magnus fetches,
216
- * checks against the catalog digest and installs onto the profile; with enable, the configuration revision.
217
- */
218
- export declare const ardentSkillInstallSchema: z.ZodObject<{
219
- source: z.ZodLiteral<"hiveskills">;
220
- name: z.ZodString;
221
- version: z.ZodString;
222
- channel: z.ZodOptional<z.ZodEnum<{
223
- stable: "stable";
224
- canary: "canary";
225
- }>>;
226
- enable: z.ZodOptional<z.ZodBoolean>;
227
- revision: z.ZodOptional<z.ZodString>;
228
- }, z.core.$strict>;
229
- /** The skill-install answer. A failed enable leaves the skill installed, with enable_error saying why. */
230
- export declare const ardentSkillInstallResultSchema: z.ZodObject<{
231
- source: z.ZodLiteral<"hiveskills">;
232
- name: z.ZodString;
233
- version: z.ZodString;
234
- sha256: z.ZodString;
235
- files: z.ZodNumber;
236
- changed: z.ZodBoolean;
237
- enabled: z.ZodBoolean;
238
- revision: z.ZodNullable<z.ZodString>;
239
- enable_error: z.ZodNullable<z.ZodString>;
240
- activation_required: z.ZodBoolean;
241
- }, z.core.$strip>;
242
136
  export type ArdentSkillInstallResult = z.infer<typeof ardentSkillInstallResultSchema>;
243
- /** action config-save: the whole config.yaml and the configuration revision it replaces. */
244
- export declare const ardentConfigEditSchema: z.ZodObject<{
245
- text: z.ZodString;
246
- revision: z.ZodString;
247
- }, z.core.$strict>;
248
- /** action session-open */
249
- export declare const ardentSessionOpenSchema: z.ZodObject<{
250
- key: z.ZodString;
251
- reset: z.ZodOptional<z.ZodBoolean>;
252
- context: z.ZodOptional<z.ZodEnum<{
253
- direct: "direct";
254
- mission: "mission";
255
- preview: "preview";
256
- }>>;
257
- }, z.core.$strict>;
258
- export declare const ardentSessionSchema: z.ZodObject<{
259
- id: z.ZodString;
260
- caller: z.ZodString;
261
- context: z.ZodString;
262
- key: z.ZodString;
263
- created_ms: z.ZodNumber;
264
- updated_ms: z.ZodNumber;
265
- }, z.core.$strip>;
266
- /** action task-submit */
267
- export declare const ardentTaskSubmitSchema: z.ZodObject<{
268
- prompt: z.ZodString;
269
- idempotency_key: z.ZodString;
270
- session_id: z.ZodOptional<z.ZodString>;
271
- }, z.core.$strict>;
272
- /** Ardent TeamMission 1.0 (src/team-contract.ts). */
273
- export declare const ardentTeamMissionSchema: z.ZodObject<{
274
- id: z.ZodString;
275
- revision: z.ZodNumber;
276
- parent_task: z.ZodNullable<z.ZodString>;
277
- constraints: z.ZodArray<z.ZodString>;
278
- allowed_actions: z.ZodArray<z.ZodEnum<{
279
- deploy: "deploy";
280
- observe: "observe";
281
- analyze: "analyze";
282
- create_artifact: "create_artifact";
283
- create_draft: "create_draft";
284
- reversible_change: "reversible_change";
285
- external_publish: "external_publish";
286
- destructive_response: "destructive_response";
287
- }>>;
288
- resources: z.ZodArray<z.ZodString>;
289
- deadline: z.ZodNumber;
290
- acceptance_criteria: z.ZodArray<z.ZodString>;
291
- expected_artifacts: z.ZodArray<z.ZodString>;
292
- }, z.core.$strict>;
293
137
  export type ArdentTeamMission = z.infer<typeof ardentTeamMissionSchema>;
294
- export declare const ARDENT_CONTEXT_ITEMS_MAX_BYTES: number;
295
- export declare const ardentContextItemSchema: z.ZodObject<{
296
- title: z.ZodString;
297
- mime: z.ZodOptional<z.ZodString>;
298
- text: z.ZodString;
299
- }, z.core.$strict>;
300
138
  export type ArdentContextItem = z.infer<typeof ardentContextItemSchema>;
301
- /** action mission-submit (the whole action body is at most 200 KB). The session must have context mission. */
302
- export declare const ardentMissionSubmitSchema: z.ZodObject<{
303
- session_id: z.ZodOptional<z.ZodString>;
304
- objective: z.ZodString;
305
- mission: z.ZodObject<{
306
- id: z.ZodString;
307
- revision: z.ZodNumber;
308
- parent_task: z.ZodNullable<z.ZodString>;
309
- constraints: z.ZodArray<z.ZodString>;
310
- allowed_actions: z.ZodArray<z.ZodEnum<{
311
- deploy: "deploy";
312
- observe: "observe";
313
- analyze: "analyze";
314
- create_artifact: "create_artifact";
315
- create_draft: "create_draft";
316
- reversible_change: "reversible_change";
317
- external_publish: "external_publish";
318
- destructive_response: "destructive_response";
319
- }>>;
320
- resources: z.ZodArray<z.ZodString>;
321
- deadline: z.ZodNumber;
322
- acceptance_criteria: z.ZodArray<z.ZodString>;
323
- expected_artifacts: z.ZodArray<z.ZodString>;
324
- }, z.core.$strict>;
325
- context_items: z.ZodOptional<z.ZodArray<z.ZodObject<{
326
- title: z.ZodString;
327
- mime: z.ZodOptional<z.ZodString>;
328
- text: z.ZodString;
329
- }, z.core.$strict>>>;
330
- labels: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
331
- idempotency_key: z.ZodString;
332
- }, z.core.$strict>;
333
- export type ArdentMissionSubmit = z.infer<typeof ardentMissionSubmitSchema>;
334
- /** action preview-submit (at most 300 KB). Needs x-acting-subject. */
335
- export declare const ardentPreviewOverridesSchema: z.ZodObject<{
336
- soul: z.ZodOptional<z.ZodString>;
337
- identity: z.ZodOptional<z.ZodString>;
338
- skills_enabled: z.ZodOptional<z.ZodArray<z.ZodString>>;
339
- model: z.ZodOptional<z.ZodString>;
340
- }, z.core.$strict>;
341
- export declare const ardentPreviewSubmitSchema: z.ZodObject<{
139
+ export type ArdentDevelopmentRecord = z.infer<typeof ardentDevelopmentRecordSchema>;
140
+ export type ArdentTaskEvent = z.infer<typeof ardentTaskJournalEventSchema>;
141
+ export type NewAgentRequest = z.input<typeof ardentAgentDeployRequestSchema>;
142
+ export type MagnusAgentOperation = z.infer<typeof ardentAgentOperationSchema>;
143
+ /** action task-submit: the prompt is at most 16000 characters and the idempotency key a UUID. */
144
+ declare const ardentTaskSubmitSchema: z.ZodObject<{
342
145
  prompt: z.ZodString;
343
- overrides: z.ZodOptional<z.ZodObject<{
344
- soul: z.ZodOptional<z.ZodString>;
345
- identity: z.ZodOptional<z.ZodString>;
346
- skills_enabled: z.ZodOptional<z.ZodArray<z.ZodString>>;
347
- model: z.ZodOptional<z.ZodString>;
348
- }, z.core.$strict>>;
146
+ idempotency_key: z.ZodString;
349
147
  session_id: z.ZodOptional<z.ZodString>;
350
- idempotency_key: z.ZodOptional<z.ZodString>;
351
148
  }, z.core.$strict>;
352
- export type ArdentPreviewSubmit = z.infer<typeof ardentPreviewSubmitSchema>;
353
- /** action development-note. Needs x-acting-subject. */
354
- export declare const ardentDevelopmentNoteSchema: z.ZodObject<{
355
- kind: z.ZodString;
356
- title: z.ZodString;
357
- body: z.ZodString;
358
- sources: z.ZodOptional<z.ZodArray<z.ZodObject<{
359
- kind: z.ZodEnum<{
360
- url: "url";
361
- task: "task";
362
- identity: "identity";
363
- note: "note";
364
- artifact: "artifact";
365
- memory: "memory";
366
- skill: "skill";
367
- }>;
368
- ref: z.ZodString;
369
- }, z.core.$strict>>>;
370
- author: z.ZodOptional<z.ZodEnum<{
371
- agent: "agent";
372
- operator: "operator";
373
- }>>;
374
- }, z.core.$strict>;
375
- export declare const ardentDevelopmentRecordSchema: z.ZodObject<{
376
- id: z.ZodString;
377
- agent_ref: z.ZodString;
378
- kind: z.ZodString;
379
- title: z.ZodString;
380
- body: z.ZodString;
381
- author: z.ZodEnum<{
382
- agent: "agent";
383
- operator: "operator";
384
- runtime: "runtime";
385
- }>;
386
- epistemic: z.ZodEnum<{
387
- agent_reported: "agent_reported";
388
- operator_reported: "operator_reported";
389
- observed: "observed";
390
- }>;
391
- before_sha256: z.ZodNullable<z.ZodString>;
392
- after_sha256: z.ZodNullable<z.ZodString>;
393
- sources: z.ZodArray<z.ZodObject<{
394
- kind: z.ZodString;
395
- ref: z.ZodString;
396
- }, z.core.$strip>>;
397
- created_at: z.ZodString;
398
- }, z.core.$strip>;
399
- export type ArdentDevelopmentRecord = z.infer<typeof ardentDevelopmentRecordSchema>;
400
- export declare const ardentDevelopmentPageSchema: z.ZodObject<{
401
- records: z.ZodArray<z.ZodObject<{
402
- id: z.ZodString;
403
- agent_ref: z.ZodString;
404
- kind: z.ZodString;
405
- title: z.ZodString;
406
- body: z.ZodString;
407
- author: z.ZodEnum<{
408
- agent: "agent";
409
- operator: "operator";
410
- runtime: "runtime";
411
- }>;
412
- epistemic: z.ZodEnum<{
413
- agent_reported: "agent_reported";
414
- operator_reported: "operator_reported";
415
- observed: "observed";
416
- }>;
417
- before_sha256: z.ZodNullable<z.ZodString>;
418
- after_sha256: z.ZodNullable<z.ZodString>;
419
- sources: z.ZodArray<z.ZodObject<{
420
- kind: z.ZodString;
421
- ref: z.ZodString;
422
- }, z.core.$strip>>;
423
- created_at: z.ZodString;
424
- }, z.core.$strip>>;
425
- next: z.ZodNullable<z.ZodString>;
426
- }, z.core.$strip>;
427
- /** actions task-pause and task-resume. A finished task answers 409. */
428
- export declare const ardentTaskPauseStateSchema: z.ZodObject<{
429
- task_id: z.ZodString;
430
- state: z.ZodString;
431
- admission: z.ZodEnum<{
432
- paused: "paused";
433
- open: "open";
434
- }>;
435
- }, z.core.$strip>;
436
- /** Ardent artifact manifest 1.0 (key fields; Ardent adds others). */
437
- export declare const ardentArtifactManifestSchema: z.ZodObject<{
438
- schema_version: z.ZodString;
439
- name: z.ZodString;
440
- mime: z.ZodString;
441
- sha256: z.ZodString;
442
- size: z.ZodNumber;
443
- revision: z.ZodNumber;
444
- supersedes_sha256: z.ZodNullable<z.ZodString>;
445
- acceptance_status: z.ZodEnum<{
446
- partial: "partial";
447
- unreviewed: "unreviewed";
448
- rejected: "rejected";
449
- approved: "approved";
450
- }>;
451
- created_at: z.ZodNumber;
452
- expires_at: z.ZodOptional<z.ZodNumber>;
453
- }, z.core.$loose>;
454
- export type ArdentArtifactManifest = z.infer<typeof ardentArtifactManifestSchema>;
455
- export declare const ardentArtifactRecordSchema: z.ZodObject<{
456
- task_id: z.ZodString;
457
- superseded_by_sha256: z.ZodNullable<z.ZodString>;
458
- manifest: z.ZodObject<{
459
- schema_version: z.ZodString;
460
- name: z.ZodString;
461
- mime: z.ZodString;
462
- sha256: z.ZodString;
463
- size: z.ZodNumber;
464
- revision: z.ZodNumber;
465
- supersedes_sha256: z.ZodNullable<z.ZodString>;
466
- acceptance_status: z.ZodEnum<{
467
- partial: "partial";
468
- unreviewed: "unreviewed";
469
- rejected: "rejected";
470
- approved: "approved";
471
- }>;
472
- created_at: z.ZodNumber;
473
- expires_at: z.ZodOptional<z.ZodNumber>;
474
- }, z.core.$loose>;
475
- }, z.core.$strip>;
476
- export declare const ardentTaskArtifactsSchema: z.ZodObject<{
477
- artifacts: z.ZodArray<z.ZodObject<{
478
- task_id: z.ZodString;
479
- superseded_by_sha256: z.ZodNullable<z.ZodString>;
480
- manifest: z.ZodObject<{
481
- schema_version: z.ZodString;
482
- name: z.ZodString;
483
- mime: z.ZodString;
484
- sha256: z.ZodString;
485
- size: z.ZodNumber;
486
- revision: z.ZodNumber;
487
- supersedes_sha256: z.ZodNullable<z.ZodString>;
488
- acceptance_status: z.ZodEnum<{
489
- partial: "partial";
490
- unreviewed: "unreviewed";
491
- rejected: "rejected";
492
- approved: "approved";
493
- }>;
494
- created_at: z.ZodNumber;
495
- expires_at: z.ZodOptional<z.ZodNumber>;
496
- }, z.core.$loose>;
497
- }, z.core.$strip>>;
498
- }, z.core.$strip>;
499
- /** task.text: the current step's visible reply text (on connect and when a step starts). task.delta appends to it. Never replayed. */
500
- export declare const ardentTaskTextEventSchema: z.ZodObject<{
501
- step: z.ZodNumber;
502
- text: z.ZodString;
503
- }, z.core.$strip>;
504
- /** task.event: one journal event; its SSE id is the sequence to resume after. */
505
- export declare const ardentTaskJournalEventSchema: z.ZodObject<{
506
- sequence: z.ZodNumber;
507
- task_id: z.ZodString;
508
- kind: z.ZodString;
509
- detail: z.ZodOptional<z.ZodUnknown>;
510
- created_ms: z.ZodNumber;
511
- }, z.core.$strip>;
512
- /** task.done: the final task record. */
513
- export declare const ardentTaskDoneEventSchema: z.ZodObject<{
514
- id: z.ZodString;
515
- state: z.ZodString;
516
- result: z.ZodOptional<z.ZodNullable<z.ZodString>>;
517
- error: z.ZodOptional<z.ZodNullable<z.ZodString>>;
518
- }, z.core.$loose>;
519
- export type ArdentTaskEvent = z.infer<typeof ardentTaskEventSchema>;
520
- /** An Emberpath alias or an OpenAI-compatible endpoint and model. Never credentials. */
521
- export declare const ardentAgentModelSchema: z.ZodUnion<readonly [z.ZodObject<{
522
- emberpath_alias: z.ZodString;
523
- }, z.core.$strict>, z.ZodObject<{
524
- base_url: z.ZodString;
525
- model: z.ZodString;
526
- }, z.core.$strict>]>;
527
- export declare const ardentAgentDeployRequestSchema: z.ZodObject<{
528
- nodeId: z.ZodString;
529
- profile: z.ZodString;
530
- apiPort: z.ZodOptional<z.ZodNumber>;
531
- soul_md: z.ZodString;
532
- identity_md: z.ZodString;
533
- model: z.ZodUnion<readonly [z.ZodObject<{
534
- emberpath_alias: z.ZodString;
535
- }, z.core.$strict>, z.ZodObject<{
536
- base_url: z.ZodString;
537
- model: z.ZodString;
538
- }, z.core.$strict>]>;
539
- skills: z.ZodDefault<z.ZodArray<z.ZodString>>;
540
- hivemem: z.ZodLiteral<true>;
541
- artifacts_max_bytes: z.ZodOptional<z.ZodNumber>;
542
- }, z.core.$strict>;
543
- export type NewAgentRequest = z.input<typeof ardentAgentDeployRequestSchema>;
544
- export declare const ardentAgentStepSchema: z.ZodObject<{
545
- name: z.ZodString;
546
- status: z.ZodEnum<{
547
- pending: "pending";
548
- failed: "failed";
549
- running: "running";
550
- succeeded: "succeeded";
551
- skipped: "skipped";
552
- }>;
553
- startedAt: z.ZodNullable<z.ZodString>;
554
- finishedAt: z.ZodNullable<z.ZodString>;
555
- receipt: z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
556
- error: z.ZodNullable<z.ZodString>;
557
- }, z.core.$strip>;
558
- export declare const agentOperationSchema: z.ZodObject<{
559
- id: z.ZodString;
560
- kind: z.ZodEnum<{
561
- hivemem: "hivemem";
562
- deploy: "deploy";
563
- }>;
564
- nodeId: z.ZodString;
565
- profile: z.ZodString;
566
- status: z.ZodEnum<{
567
- failed: "failed";
568
- running: "running";
569
- succeeded: "succeeded";
570
- }>;
571
- steps: z.ZodArray<z.ZodObject<{
572
- name: z.ZodString;
573
- status: z.ZodEnum<{
574
- pending: "pending";
575
- failed: "failed";
576
- running: "running";
577
- succeeded: "succeeded";
578
- skipped: "skipped";
579
- }>;
580
- startedAt: z.ZodNullable<z.ZodString>;
581
- finishedAt: z.ZodNullable<z.ZodString>;
582
- receipt: z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
583
- error: z.ZodNullable<z.ZodString>;
584
- }, z.core.$strip>>;
585
- error: z.ZodNullable<z.ZodString>;
586
- createdBy: z.ZodString;
587
- attempts: z.ZodNumber;
588
- createdAt: z.ZodString;
589
- updatedAt: z.ZodString;
590
- completedAt: z.ZodNullable<z.ZodString>;
591
- }, z.core.$loose>;
592
- export type MagnusAgentOperation = z.infer<typeof agentOperationSchema>;
593
149
  export interface MagnusClientOptions {
594
150
  baseUrl: string;
595
151
  tokens: Pick<ServiceTokenProvider, 'token' | 'invalidate'>;
@@ -673,7 +229,6 @@ export declare class MagnusClient {
673
229
  state: string;
674
230
  }>;
675
231
  cancelTask(ref: string, taskId: string, context?: CallContext): Promise<unknown>;
676
- memorySearch(ref: string, query: string, context?: CallContext): Promise<unknown>;
677
232
  /** Ardent rejects a stale revision with 409, so concurrent edits never overwrite each other. */
678
233
  saveIdentity(ref: string, kind: 'soul' | 'identity', body: {
679
234
  text: string;
@@ -818,14 +373,13 @@ export declare class MagnusClient {
818
373
  }>;
819
374
  /** Step receipts of a New Agent or Enable HiveMem operation. */
820
375
  agentOperation(operationId: string, context?: CallContext): Promise<{
821
- [x: string]: unknown;
822
376
  id: string;
823
377
  kind: "hivemem" | "deploy";
824
378
  nodeId: string;
825
379
  profile: string;
826
380
  status: "failed" | "running" | "succeeded";
827
381
  steps: {
828
- name: string;
382
+ name: "profile-create" | "config-save" | "skill-set" | "service-start" | "service-restart" | "profile-check" | "identity-soul" | "identity-identity" | "hivemem-enroll" | "ready-probe";
829
383
  status: "pending" | "failed" | "running" | "succeeded" | "skipped";
830
384
  startedAt: string | null;
831
385
  finishedAt: string | null;
@@ -835,6 +389,18 @@ export declare class MagnusClient {
835
389
  error: string | null;
836
390
  createdBy: string;
837
391
  attempts: number;
392
+ request: {
393
+ apiPort: number | null;
394
+ model: {
395
+ emberpath_alias: string;
396
+ } | {
397
+ base_url: string;
398
+ model: string;
399
+ } | null;
400
+ skills: string[];
401
+ hivemem: boolean;
402
+ artifacts_max_bytes: number | null;
403
+ };
838
404
  createdAt: string;
839
405
  updatedAt: string;
840
406
  completedAt: string | null;
@@ -3,19 +3,22 @@
3
3
  // for, forwards that person's Oathweave subject in x-acting-subject so Magnus can check
4
4
  // and audit both. ArdentStudio never talks to nodes or Ardent directly and holds no Ardent token.
5
5
  //
6
- // Released Magnus 2.1.x serves the profile, installation, resource and action routes. The Studio
7
- // routes (sessions, task streams, streamed artifacts, New Agent, missions, pause, previews,
8
- // development) are typed here from Magnus's `packages/contracts/src/ardent-service.ts`
9
- // (`ardentServiceRoutes`) and `browser.ts`, because the published @hivemagnus/magnus-contracts
10
- // does not contain them yet. Switch these local schemas to that package once a release ships them.
11
- // The agent changes (identity-save, skill-set, config-save and reading config) need an acting
12
- // Magnus ADMIN in x-acting-subject; their shapes are typed here from the same file.
13
- // A node agent reports `capabilities.studio`: 1 for sessions, streams and artifacts, 2 for missions,
14
- // pause and resume, previews and development; below that Magnus answers 409 AGENT_UPGRADE_REQUIRED.
6
+ // The routes, action bodies and answers come from @hivemagnus/magnus-contracts/ardent-service
7
+ // (`ardentServiceRoutes`, the routes a linked service identity may call), pinned to the Magnus
8
+ // release Studio is built against. Only shapes that contract leaves open are typed here: the
9
+ // installation (which it answers as a record) and the Ardent management resources it relays as-is.
10
+ // The agent changes (identity-save, skill-set, config-save, skill-install and reading config) need an
11
+ // acting Magnus ADMIN in x-acting-subject (ARDENT_SERVICE_ADMIN_ACTIONS).
12
+ // A node agent reports `capabilities.studio` (ARDENT_STUDIO_CAPABILITY): 1 for sessions, streams and
13
+ // artifacts, 2 for missions, pause and resume, previews and development, 3 for skill-install; below
14
+ // that Magnus answers 409 AGENT_UPGRADE_REQUIRED.
15
+ import { ARDENT_ACTING_SUBJECT_HEADER, ardentAgentDeployRequestSchema, ardentAgentOperationSchema, ardentConfigEditSchema, ardentConfigFileSchema, ardentConfigSavedSchema, ardentDevelopmentNoteSchema, ardentDevelopmentPageSchema, ardentDevelopmentRecordSchema, ardentIdentityEditSchema, ardentIdentityFileSchema, ardentMissionSubmitSchema, ardentPreviewSubmitSchema, ardentServiceProfileSchema, ardentServiceSessionSchema, ardentServiceSkillSetRequestSchema, ardentServiceTaskSubmitRequestSchema, ardentSessionOpenSchema, ardentSkillEditSchema, ardentSkillInstallResultSchema, ardentSkillInstallSchema, ardentTaskAdmissionSchema, ardentTaskArtifactsSchema, ardentArtifactRecordSchema, ardentTaskJournalEventSchema, ardentTaskPauseStateSchema, } from '@hivemagnus/magnus-contracts/ardent-service';
15
16
  import { z } from 'zod';
16
17
  import { parseSse } from './sse.js';
17
18
  import { trimTrailingSlashes } from '../url.js';
18
- export const ACTING_SUBJECT_HEADER = 'x-acting-subject';
19
+ export { ARDENT_SERVICE_ADMIN_ACTIONS, ARDENT_SERVICE_CONFIG_PATHS, ARDENT_STUDIO_CAPABILITY, ARDENT_STUDIO_EVENT_KINDS, ardentAgentOperationSchema, ardentTaskDoneEventSchema, ardentTaskJournalEventSchema, ardentTaskTextEventSchema, ardentTeamMissionSchema, } from '@hivemagnus/magnus-contracts/ardent-service';
20
+ export { ARDENT_CONTEXT_ITEMS_MAX_BYTES } from '@hivemagnus/magnus-contracts/browser';
21
+ export const ACTING_SUBJECT_HEADER = ARDENT_ACTING_SUBJECT_HEADER;
19
22
  export class MagnusError extends Error {
20
23
  status;
21
24
  code;
@@ -36,27 +39,15 @@ export function parseAgentRef(ref) {
36
39
  export function agentRef(nodeId, profile) {
37
40
  return `${nodeId}~${profile}`;
38
41
  }
39
- // ── Shapes of the released Magnus routes (packages/contracts ardent.ts, routes/ardent.ts) ──
40
- export const magnusArdentProfileSchema = z.object({
41
- id: z.string(),
42
- name: z.string(),
43
- backend: z.enum(['llamacpp', 'codex']).nullable(),
44
- apiPort: z.number().int().nullable(),
45
- running: z.boolean(),
46
- a2aEnabled: z.boolean(),
47
- channels: z.record(z.string(), z.boolean()),
48
- error: z.string().nullable(),
49
- nodeId: z.string(),
50
- nodeName: z.string(),
51
- hostname: z.string(),
52
- installationVersion: z.string().nullable(),
53
- reachable: z.boolean(),
54
- });
42
+ /**
43
+ * GET /ardent/installations and /ardent/installations/{nodeId}. The service contract answers these
44
+ * as records, so Studio reads only the fields it uses (Magnus ArdentFleetInstallationSchema).
45
+ */
55
46
  export const magnusArdentInstallationSchema = z.object({
56
47
  installed: z.boolean(),
57
48
  version: z.string().nullable(),
58
49
  owner: z.string(),
59
- profiles: z.array(magnusArdentProfileSchema.pick({ id: true, name: true, backend: true, apiPort: true, running: true, a2aEnabled: true, channels: true, error: true })),
50
+ profiles: z.array(ardentServiceProfileSchema.pick({ id: true, name: true, backend: true, apiPort: true, running: true, a2aEnabled: true, channels: true, error: true })),
60
51
  checkedAt: z.string(),
61
52
  nodeId: z.string(),
62
53
  nodeName: z.string(),
@@ -66,22 +57,19 @@ export const magnusArdentInstallationSchema = z.object({
66
57
  /** The node agent's Studio level (ARDENT_STUDIO_CAPABILITY). Absent on agents that predate it. */
67
58
  capabilities: z.object({ studio: z.number().int().min(0).optional() }).loose().optional(),
68
59
  });
69
- // Ardent management shapes, as Ardent's OpenAPI document defines them.
60
+ // Ardent management shapes, as Ardent's OpenAPI document defines them. Magnus relays these resources unchanged.
70
61
  export const ardentTaskStateSchema = z.enum(['queued', 'running', 'input_required', 'completed', 'partial', 'failed', 'cancelled', 'unknown']);
71
62
  export const ardentTaskSchema = z.object({
72
63
  id: z.string(), caller: z.string(), context: z.string(), session_id: z.string().nullable(), prompt: z.string(), content_hash: z.string(),
73
64
  idempotency_key: z.string().nullable(), backend: z.string(), state: ardentTaskStateSchema, result: z.string().nullable(), error: z.string().nullable(),
74
65
  deadline_ms: z.number(), created_ms: z.number(), updated_ms: z.number(),
75
66
  });
76
- export const ardentTaskEventSchema = z.object({ sequence: z.number().int(), task_id: z.string(), kind: z.string(), detail: z.unknown().optional(), created_ms: z.number() });
77
67
  export const ardentStatusSchema = z.object({ version: z.string(), profile: z.string(), backend: z.string(), tasks: z.number().int() });
78
68
  export const ardentMemoryStatusSchema = z.object({
79
69
  status: z.enum(['ready', 'degraded']), agent_id: z.string(), workspace_id: z.string(),
80
70
  retrieval: z.string().nullable(), storage: z.string().nullable(), reason: z.string().nullable(),
81
71
  });
82
72
  export const ardentSkillSchema = z.object({ name: z.string(), enabled: z.boolean() }).loose();
83
- /** Admission of task-submit, mission-submit and preview-submit: durable acceptance, never completion. */
84
- export const ardentAcceptedTaskSchema = z.object({ task_id: z.string(), state: z.string() });
85
73
  /** Actions released Magnus accepts on POST …/action (an ADMIN person; a service identity gets the Studio subset below). */
86
74
  export const RELEASED_ACTIONS = ['profile-create', 'config-validate', 'config-save', 'peer-validate', 'peer-save', 'identity-save', 'identity-restore',
87
75
  'provider-test', 'channel-test', 'peer-test', 'memory-search', 'task-submit', 'task-cancel', 'skill-set', 'service-start', 'service-stop',
@@ -91,201 +79,18 @@ export const RELEASED_ACTIONS = ['profile-create', 'config-validate', 'config-sa
91
79
  * Magnus with a HiveSkills registry, the others studio >= 2 and Ardent 2.2.0.
92
80
  */
93
81
  export const STUDIO_ACTIONS = ['session-open', 'mission-submit', 'task-pause', 'task-resume', 'preview-submit', 'development-note', 'skill-install'];
94
- /**
95
- * Agent changes Magnus runs for a service identity only with x-acting-subject naming a linked Magnus
96
- * ADMIN (Magnus ARDENT_SERVICE_ADMIN_ACTIONS). Without one: 403 ACTING_ADMIN_REQUIRED; an unlinked
97
- * subject: 403 ACTING_SUBJECT_UNLINKED. A stale revision answers 409 CONFLICT. Reading config needs
98
- * the same acting ADMIN.
99
- */
100
- export const ARDENT_SERVICE_ADMIN_ACTIONS = ['identity-save', 'skill-set', 'config-save', 'skill-install'];
101
- /**
102
- * The only configuration values a service's config-save may change (Magnus ARDENT_SERVICE_CONFIG_PATHS).
103
- * A change anywhere else answers 403 CONFIG_PATH_FORBIDDEN. An array is one value.
104
- */
105
- export const ARDENT_SERVICE_CONFIG_PATHS = [
106
- 'execution.backend',
107
- 'providers.llamacpp.model', 'providers.llamacpp.request_timeout_seconds', 'providers.llamacpp.context_window_tokens',
108
- 'providers.llamacpp.max_output_tokens', 'providers.llamacpp.reasoning_effort',
109
- 'providers.codex.model',
110
- 'skills.enabled',
111
- 'artifacts.max_bytes',
112
- ];
113
82
  /**
114
83
  * Whether Magnus lets the Studio service identity run service-restart. It does not: a service may run
115
84
  * only the session, task, mission, preview, development and ARDENT_SERVICE_ADMIN_ACTIONS actions, so a
116
85
  * profile restart stays a person's act in the Magnus console.
117
86
  */
118
87
  export const ARDENT_SERVICE_CAN_RESTART = false;
119
- /** Node agent Studio levels (Magnus ARDENT_STUDIO_CAPABILITY). */
120
- export const ARDENT_STUDIO_CAPABILITY = { bridge: 1, missions: 2, skillInstall: 3 };
121
- /** Journal event kinds Ardent 2.2.0 adds. Others appear too; readers accept unknown kinds. */
122
- export const ARDENT_STUDIO_EVENT_KINDS = ['mission', 'team_handoff', 'team_ask_user', 'team_propose_decision', 'artifact_registered', 'development_note',
123
- 'team_result', 'team_result_rejected', 'pause_requested', 'paused', 'resumed', 'preview'];
124
- const utf8Length = (value) => Buffer.byteLength(value, 'utf8');
125
- const guid = z.string().regex(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/);
126
- const digest = z.string().regex(/^[a-f0-9]{64}$/);
127
- const boundedId = z.string().regex(/^[A-Za-z0-9._:-]{1,128}$/);
128
- const missionText = (bytes) => z.string().trim().min(1).refine(value => utf8Length(value) <= bytes, `Exceeds ${bytes} bytes`);
129
- const missionTexts = (minimum = 0) => z.array(missionText(1000)).min(minimum).max(32).refine(value => new Set(value).size === value.length, 'Duplicate entries');
130
- export const ardentSessionContextSchema = z.enum(['direct', 'mission', 'preview']);
131
- /** GET …/identity/soul and …/identity/identity, and the identity-save answer. */
132
- export const ardentIdentityFileSchema = z.object({ kind: z.enum(['soul', 'identity']), name: z.string(), text: z.string(), revision: digest });
133
- /** GET …/config: the raw config.yaml and its revision (the base for skill-set and config-save). Secrets appear only as environment variable names. */
134
- export const ardentConfigFileSchema = z.object({ revision: digest, text: z.string() });
135
- /** The skill-set and config-save answer: the new configuration revision. The change applies once the profile restarts. */
136
- export const ardentConfigSavedSchema = z.object({ revision: digest, activation_required: z.boolean() });
137
- /** action identity-save */
138
- export const ardentIdentityEditSchema = z.object({ text: z.string().min(1).max(128 * 1024), revision: digest }).strict();
139
- /** action skill-set: revision is the configuration revision. */
140
- export const ardentSkillEditSchema = z.object({ enabled: z.boolean(), revision: digest }).strict();
141
- export const ardentSkillTargetSchema = z.string().regex(/^[A-Za-z0-9_-]{1,100}$/);
142
- /**
143
- * action skill-install (Magnus ardentSkillInstallSchema): a HiveSkills catalog release that Magnus fetches,
144
- * checks against the catalog digest and installs onto the profile; with enable, the configuration revision.
145
- */
146
- export const ardentSkillInstallSchema = z.object({
147
- source: z.literal('hiveskills'),
148
- name: z.string().regex(/^[a-z0-9][a-z0-9-]{1,62}$/),
149
- version: z.string().max(64).regex(/^v?\d+\.\d+\.\d+(?:-[a-z0-9.-]+)?$/i),
150
- channel: z.enum(['stable', 'canary']).optional(),
151
- enable: z.boolean().optional(),
152
- revision: digest.optional(),
153
- }).strict().refine(value => !value.enable || value.revision !== undefined, { message: 'enable needs the configuration revision', path: ['revision'] });
154
- /** The skill-install answer. A failed enable leaves the skill installed, with enable_error saying why. */
155
- export const ardentSkillInstallResultSchema = z.object({
156
- source: z.literal('hiveskills'), name: z.string(), version: z.string(), sha256: digest, files: z.number().int(),
157
- changed: z.boolean(), enabled: z.boolean(), revision: digest.nullable(), enable_error: z.string().nullable(), activation_required: z.boolean(),
158
- });
159
- /** action config-save: the whole config.yaml and the configuration revision it replaces. */
160
- export const ardentConfigEditSchema = z.object({ text: z.string().min(1).max(200_000), revision: digest }).strict();
161
- /** action session-open */
162
- export const ardentSessionOpenSchema = z.object({ key: z.string().trim().min(1).max(256), reset: z.boolean().optional(), context: ardentSessionContextSchema.optional() }).strict();
163
- export const ardentSessionSchema = z.object({ id: guid, caller: z.string(), context: z.string(), key: z.string(), created_ms: z.number(), updated_ms: z.number() });
164
- /** action task-submit */
165
- export const ardentTaskSubmitSchema = z.object({ prompt: z.string().trim().min(1).max(16_000), idempotency_key: guid, session_id: guid.optional() }).strict();
166
- /** Ardent TeamMission 1.0 (src/team-contract.ts). */
167
- export const ardentTeamMissionSchema = z.object({
168
- id: boundedId,
169
- revision: z.number().int().min(1).max(2_147_483_647),
170
- parent_task: boundedId.nullable(),
171
- constraints: missionTexts(),
172
- allowed_actions: z.array(z.enum(['observe', 'analyze', 'create_artifact', 'create_draft', 'reversible_change', 'deploy', 'external_publish', 'destructive_response']))
173
- .min(1).max(8).refine(value => new Set(value).size === value.length, 'Duplicate action'),
174
- /** Tool and memory grants, such as tool:artifact_write or project:<id>. */
175
- resources: missionTexts(1),
176
- /** Unix seconds. */
177
- deadline: z.number().int().min(1).max(253_402_300_799),
178
- acceptance_criteria: missionTexts(1),
179
- expected_artifacts: missionTexts(),
180
- }).strict();
181
- export const ARDENT_CONTEXT_ITEMS_MAX_BYTES = 64 * 1024;
182
- export const ardentContextItemSchema = z.object({
183
- title: z.string().trim().min(1).max(200), mime: z.string().regex(/^[a-z]+\/[A-Za-z0-9.+-]+$/).max(100).optional(), text: z.string().min(1),
184
- }).strict();
185
- /** action mission-submit (the whole action body is at most 200 KB). The session must have context mission. */
186
- export const ardentMissionSubmitSchema = z.object({
187
- session_id: guid.optional(),
188
- objective: z.string().trim().min(1).max(16_000),
189
- mission: ardentTeamMissionSchema,
190
- context_items: z.array(ardentContextItemSchema).max(64).optional()
191
- .refine(items => utf8Length((items ?? []).map(item => item.title + item.text).join('')) <= ARDENT_CONTEXT_ITEMS_MAX_BYTES, 'Context items exceed 64 KiB'),
192
- labels: z.record(z.string().regex(/^[a-z][a-z0-9._:-]{0,63}$/), z.string().max(256)).refine(value => Object.keys(value).length <= 32, 'At most 32 labels').optional(),
193
- idempotency_key: z.string().min(1).max(128),
194
- }).strict();
195
- /** action preview-submit (at most 300 KB). Needs x-acting-subject. */
196
- export const ardentPreviewOverridesSchema = z.object({
197
- soul: z.string().min(1).max(131_072).optional(),
198
- identity: z.string().min(1).max(131_072).optional(),
199
- skills_enabled: z.array(z.string().regex(/^[A-Za-z0-9][A-Za-z0-9._-]{0,99}$/)).max(100).optional(),
200
- model: z.string().trim().min(1).max(200).optional(),
201
- }).strict();
202
- export const ardentPreviewSubmitSchema = z.object({
203
- prompt: z.string().trim().min(1).max(16_000),
204
- overrides: ardentPreviewOverridesSchema.optional(),
205
- session_id: guid.optional(),
206
- idempotency_key: z.string().min(1).max(128).optional(),
207
- }).strict();
208
- /** action development-note. Needs x-acting-subject. */
209
- export const ardentDevelopmentNoteSchema = z.object({
210
- kind: z.string().regex(/^[a-z][a-z0-9_]{0,63}$/),
211
- title: z.string().trim().min(1).max(200),
212
- body: z.string().trim().min(1).max(8000),
213
- sources: z.array(z.object({ kind: z.enum(['task', 'artifact', 'memory', 'url', 'identity', 'skill', 'note']), ref: z.string().trim().min(1).max(512) }).strict()).max(16).optional(),
214
- author: z.enum(['operator', 'agent']).optional(),
215
- }).strict();
216
- export const ardentDevelopmentRecordSchema = z.object({
217
- id: z.string(), agent_ref: z.string(), kind: z.string(), title: z.string(), body: z.string(),
218
- author: z.enum(['agent', 'operator', 'runtime']), epistemic: z.enum(['agent_reported', 'operator_reported', 'observed']),
219
- before_sha256: digest.nullable(), after_sha256: digest.nullable(),
220
- sources: z.array(z.object({ kind: z.string(), ref: z.string() })), created_at: z.string(),
221
- });
222
- export const ardentDevelopmentPageSchema = z.object({ records: z.array(ardentDevelopmentRecordSchema), next: z.string().nullable() });
223
- /** actions task-pause and task-resume. A finished task answers 409. */
224
- export const ardentTaskPauseStateSchema = z.object({ task_id: z.string(), state: z.string(), admission: z.enum(['open', 'paused']) });
225
- /** Ardent artifact manifest 1.0 (key fields; Ardent adds others). */
226
- export const ardentArtifactManifestSchema = z.looseObject({
227
- schema_version: z.string(), name: z.string(), mime: z.string(), sha256: digest, size: z.number().int().min(0),
228
- revision: z.number().int(), supersedes_sha256: digest.nullable(),
229
- acceptance_status: z.enum(['unreviewed', 'approved', 'partial', 'rejected']), created_at: z.number(), expires_at: z.number().optional(),
230
- });
231
- export const ardentArtifactRecordSchema = z.object({ task_id: z.string(), superseded_by_sha256: digest.nullable(), manifest: ardentArtifactManifestSchema });
232
- export const ardentTaskArtifactsSchema = z.object({ artifacts: z.array(ardentArtifactRecordSchema) });
233
- // Task stream events (GET …/tasks/:taskId/stream).
234
- /** task.text: the current step's visible reply text (on connect and when a step starts). task.delta appends to it. Never replayed. */
235
- export const ardentTaskTextEventSchema = z.object({ step: z.number().int(), text: z.string() });
236
- /** task.event: one journal event; its SSE id is the sequence to resume after. */
237
- export const ardentTaskJournalEventSchema = ardentTaskEventSchema;
238
- /** task.done: the final task record. */
239
- export const ardentTaskDoneEventSchema = z.object({ id: z.string(), state: z.string(), result: z.string().nullable().optional(), error: z.string().nullable().optional() }).loose();
240
- // New Agent (POST /ardent/agents) and its operations.
241
- const credentialFreeUrl = (value) => {
242
- try {
243
- const url = new URL(value);
244
- return ['http:', 'https:'].includes(url.protocol) && !url.username && !url.password && !url.search && !url.hash;
245
- }
246
- catch {
247
- return false;
248
- }
249
- };
250
- const identityText = z.string().max(131_072).refine(value => value.trim().length > 0 && utf8Length(value) <= 131_072, 'Identity text must be 1 to 128 KiB');
251
- /** An Emberpath alias or an OpenAI-compatible endpoint and model. Never credentials. */
252
- export const ardentAgentModelSchema = z.union([
253
- z.object({ emberpath_alias: z.string().regex(/^[A-Za-z0-9][A-Za-z0-9._:/-]{0,199}$/) }).strict(),
254
- z.object({ base_url: z.string().max(2048).refine(credentialFreeUrl, 'Expected an HTTP(S) URL without credentials, query or fragment'), model: z.string().min(1).max(200) }).strict(),
255
- ]);
256
- export const ardentAgentDeployRequestSchema = z.object({
257
- nodeId: z.string().regex(/^[A-Za-z0-9._-]{1,128}$/),
258
- profile: z.string().regex(/^[A-Za-z0-9_-]{1,64}$/),
259
- apiPort: z.number().int().min(1024).max(65535).optional(),
260
- soul_md: identityText,
261
- identity_md: identityText,
262
- model: ardentAgentModelSchema,
263
- skills: z.array(z.string().regex(/^[A-Za-z0-9_-]{1,100}$/)).max(100).default([]),
264
- hivemem: z.literal(true),
265
- artifacts_max_bytes: z.number().int().min(1024).max(67_108_864).optional(),
266
- }).strict();
267
- export const ardentAgentStepSchema = z.object({
268
- name: z.string(),
269
- status: z.enum(['pending', 'running', 'succeeded', 'skipped', 'failed']),
270
- startedAt: z.string().nullable(),
271
- finishedAt: z.string().nullable(),
272
- receipt: z.record(z.string(), z.unknown()).nullable(),
273
- error: z.string().nullable(),
274
- });
275
- export const agentOperationSchema = z.object({
276
- id: z.string(),
277
- kind: z.enum(['deploy', 'hivemem']),
278
- nodeId: z.string(),
279
- profile: z.string(),
280
- status: z.enum(['running', 'succeeded', 'failed']),
281
- steps: z.array(ardentAgentStepSchema),
282
- error: z.string().nullable(),
283
- createdBy: z.string(),
284
- attempts: z.number().int(),
285
- createdAt: z.string(),
286
- updatedAt: z.string(),
287
- completedAt: z.string().nullable(),
288
- }).loose();
88
+ /** action task-submit: the prompt is at most 16000 characters and the idempotency key a UUID. */
89
+ const ardentTaskSubmitSchema = ardentServiceTaskSubmitRequestSchema.shape.body;
90
+ /** action skill-set: the skill name is the target. */
91
+ const ardentSkillTargetSchema = ardentServiceSkillSetRequestSchema.shape.target;
92
+ /** The New Agent and resume answers. */
93
+ const operationAcceptedSchema = z.object({ operationId: z.string() });
289
94
  const envelope = z.object({ success: z.literal(true), data: z.unknown() });
290
95
  const failure = z.object({ success: z.literal(false), error: z.object({ code: z.string(), message: z.string() }) });
291
96
  export class MagnusClient {
@@ -300,7 +105,7 @@ export class MagnusClient {
300
105
  // ── Released routes ──
301
106
  /** Every Magnus-managed Ardent profile across the fleet. */
302
107
  async listProfiles(context = {}) {
303
- return z.array(magnusArdentProfileSchema).parse(await this.json('GET', '/api/v1/ardent/profiles', context));
108
+ return z.array(ardentServiceProfileSchema).parse(await this.json('GET', '/api/v1/ardent/profiles', context));
304
109
  }
305
110
  async listInstallations(context = {}) {
306
111
  return z.array(magnusArdentInstallationSchema).parse(await this.json('GET', '/api/v1/ardent/installations', context));
@@ -329,7 +134,7 @@ export class MagnusClient {
329
134
  return Array.isArray(list) ? list : list.skills;
330
135
  }
331
136
  async taskEvents(ref, taskId, after = 0, context = {}) {
332
- return z.object({ events: z.array(ardentTaskEventSchema) }).parse(await this.resource(ref, `tasks/${uuid(taskId)}/events`, { ...context, query: { after } })).events;
137
+ return z.object({ events: z.array(ardentTaskJournalEventSchema) }).parse(await this.resource(ref, `tasks/${uuid(taskId)}/events`, { ...context, query: { after } })).events;
333
138
  }
334
139
  async identity(ref, kind, context = {}) {
335
140
  return ardentIdentityFileSchema.parse(await this.resource(ref, `identity/${kind}`, context));
@@ -369,14 +174,11 @@ export class MagnusClient {
369
174
  const parsed = ardentTaskSubmitSchema.safeParse(body);
370
175
  if (!parsed.success)
371
176
  throw new MagnusError(`Task submission is invalid: ${parsed.error.issues[0]?.message ?? 'invalid'}`, 400, 'VALIDATION_ERROR');
372
- return ardentAcceptedTaskSchema.parse(await this.action(ref, 'task-submit', { body: parsed.data }, context));
177
+ return ardentTaskAdmissionSchema.parse(await this.action(ref, 'task-submit', { body: parsed.data }, context));
373
178
  }
374
179
  async cancelTask(ref, taskId, context = {}) {
375
180
  return this.action(ref, 'task-cancel', { target: uuid(taskId) }, context);
376
181
  }
377
- async memorySearch(ref, query, context = {}) {
378
- return this.action(ref, 'memory-search', { body: { query } }, context);
379
- }
380
182
  /** Ardent rejects a stale revision with 409, so concurrent edits never overwrite each other. */
381
183
  async saveIdentity(ref, kind, body, context = {}) {
382
184
  return ardentIdentityFileSchema.parse(await this.action(ref, 'identity-save', { target: kind, body: validated(ardentIdentityEditSchema, body, 'identity-save') }, context));
@@ -398,21 +200,21 @@ export class MagnusClient {
398
200
  async saveConfig(ref, body, context = {}) {
399
201
  return ardentConfigSavedSchema.parse(await this.action(ref, 'config-save', { body: validated(ardentConfigEditSchema, body, 'config-save') }, context));
400
202
  }
401
- // ── Studio routes (typed locally; see the header) ──
203
+ // ── Studio routes ──
402
204
  /** The node agent's Studio level for a node: 0 when it reports none. */
403
205
  async studioLevel(nodeId, context = {}) {
404
206
  return (await this.getInstallation(nodeId, context)).capabilities?.studio ?? 0;
405
207
  }
406
208
  /** Open (or reopen: the same key answers the same session) an Ardent session. studio >= 1; a context needs studio >= 2. */
407
209
  async openSession(ref, body, context = {}) {
408
- return ardentSessionSchema.parse(await this.action(ref, 'session-open', { body: ardentSessionOpenSchema.parse(body) }, context));
210
+ return ardentServiceSessionSchema.parse(await this.action(ref, 'session-open', { body: ardentSessionOpenSchema.parse(body) }, context));
409
211
  }
410
212
  /** Submit a team mission in a session opened with context mission. studio >= 2. */
411
213
  async submitMission(ref, body, context = {}) {
412
214
  const parsed = ardentMissionSubmitSchema.safeParse(body);
413
215
  if (!parsed.success)
414
216
  throw new MagnusError(`Mission is invalid: ${parsed.error.issues[0]?.message ?? 'invalid'}`, 400, 'VALIDATION_ERROR');
415
- return ardentAcceptedTaskSchema.parse(await this.action(ref, 'mission-submit', { body: parsed.data }, context));
217
+ return ardentTaskAdmissionSchema.parse(await this.action(ref, 'mission-submit', { body: parsed.data }, context));
416
218
  }
417
219
  /** Pause at the next step boundary. studio >= 2; a finished task answers 409. */
418
220
  async pauseTask(ref, taskId, context = {}) {
@@ -425,7 +227,7 @@ export class MagnusClient {
425
227
  async submitPreview(ref, body, context) {
426
228
  if (!context.actingSubject)
427
229
  throw new MagnusError('A preview needs the acting person', 400, 'ACTING_SUBJECT_REQUIRED');
428
- return ardentAcceptedTaskSchema.parse(await this.action(ref, 'preview-submit', { body: ardentPreviewSubmitSchema.parse(body) }, context));
230
+ return ardentTaskAdmissionSchema.parse(await this.action(ref, 'preview-submit', { body: ardentPreviewSubmitSchema.parse(body) }, context));
429
231
  }
430
232
  /** Record a development note. studio >= 2; needs the acting person. */
431
233
  async addDevelopmentNote(ref, body, context) {
@@ -466,11 +268,11 @@ export class MagnusClient {
466
268
  async createAgent(body, context) {
467
269
  if (!context.actingSubject)
468
270
  throw new MagnusError('New Agent needs the acting person', 400, 'ACTING_SUBJECT_REQUIRED');
469
- return z.object({ operationId: z.string() }).parse(await this.json('POST', '/api/v1/ardent/agents', context, ardentAgentDeployRequestSchema.parse(body)));
271
+ return operationAcceptedSchema.parse(await this.json('POST', '/api/v1/ardent/agents', context, ardentAgentDeployRequestSchema.parse(body)));
470
272
  }
471
273
  /** Step receipts of a New Agent or Enable HiveMem operation. */
472
274
  async agentOperation(operationId, context = {}) {
473
- return agentOperationSchema.parse(await this.json('GET', `/api/v1/ardent/agents/operations/${operationIdOf(operationId)}`, context));
275
+ return ardentAgentOperationSchema.parse(await this.json('GET', `/api/v1/ardent/agents/operations/${operationIdOf(operationId)}`, context));
474
276
  }
475
277
  /** Live operation updates: `operation` events, then one `done`. */
476
278
  async *streamAgentOperation(operationId, options = {}) {
@@ -483,7 +285,7 @@ export class MagnusClient {
483
285
  async resumeAgentOperation(operationId, context) {
484
286
  if (!context.actingSubject)
485
287
  throw new MagnusError('Resuming an operation needs the acting person', 400, 'ACTING_SUBJECT_REQUIRED');
486
- return z.object({ operationId: z.string() }).parse(await this.json('POST', `/api/v1/ardent/agents/operations/${operationIdOf(operationId)}/resume`, context));
288
+ return operationAcceptedSchema.parse(await this.json('POST', `/api/v1/ardent/agents/operations/${operationIdOf(operationId)}/resume`, context));
487
289
  }
488
290
  // ── Transport ──
489
291
  async json(method, path, context, body) {
@@ -3,7 +3,7 @@
3
3
  // so a clean end reconnects. When the stream fails, the follower polls the journal and the task
4
4
  // every 1 to 5 seconds, then tries the stream again.
5
5
  import { setTimeout as delay } from 'node:timers/promises';
6
- import { ardentTaskDoneEventSchema, ardentTaskEventSchema, ardentTaskTextEventSchema, MagnusError } from '../clients/magnus.js';
6
+ import { ardentTaskDoneEventSchema, ardentTaskJournalEventSchema, ardentTaskTextEventSchema, MagnusError } from '../clients/magnus.js';
7
7
  /** Ardent states after which a task's turn is over. Ardent keeps `input_required` out of its stream's done set, so it is listed here. */
8
8
  export const ARDENT_FINISHED = ['completed', 'partial', 'failed', 'cancelled', 'unknown', 'input_required'];
9
9
  export class TaskFollower {
@@ -83,7 +83,7 @@ export class TaskFollower {
83
83
  this.hooks.text(parsed.data.step, parsed.data.text, message.event === 'task.text' ? 'replace' : 'append');
84
84
  }
85
85
  else if (message.event === 'task.event') {
86
- const parsed = ardentTaskEventSchema.safeParse(parseJson(message.data));
86
+ const parsed = ardentTaskJournalEventSchema.safeParse(parseJson(message.data));
87
87
  if (!parsed.success)
88
88
  continue;
89
89
  if (await this.hooks.event(parsed.data))
@@ -4,7 +4,7 @@
4
4
  import { streamSSE } from 'hono/streaming';
5
5
  import { ConfigEditError, configuredSkills, editConfig, modelPath } from '../../agents/config-edit.js';
6
6
  import { operationView } from '../../agents/operations.js';
7
- import { agentOperationSchema, ARDENT_SERVICE_CAN_RESTART, ardentTaskDoneEventSchema, ardentTaskEventSchema, ardentTaskTextEventSchema, MagnusError, parseAgentRef, } from '../../clients/magnus.js';
7
+ import { ardentAgentOperationSchema, ARDENT_SERVICE_CAN_RESTART, ardentTaskDoneEventSchema, ardentTaskJournalEventSchema, ardentTaskTextEventSchema, MagnusError, parseAgentRef, } from '../../clients/magnus.js';
8
8
  import { ARDENT_FINISHED } from '../../conductor/follower.js';
9
9
  import { agentRefSchema, APPLY_PARTS, IDEMPOTENCY_HEADER, idempotencyKeySchema, } from '../../shared/browser.js';
10
10
  import { actorOf, requireProject } from '../deps.js';
@@ -56,7 +56,7 @@ export function agentStudioRoutes(register, deps) {
56
56
  return { body: operationView(store.agents.operation(record.id), current) };
57
57
  }
58
58
  catch {
59
- const stored = agentOperationSchema.safeParse(record.operation);
59
+ const stored = ardentAgentOperationSchema.safeParse(record.operation);
60
60
  return { body: operationView(record, stored.success ? stored.data : undefined) };
61
61
  }
62
62
  });
@@ -207,7 +207,7 @@ export function agentStudioRoutes(register, deps) {
207
207
  await send(message.event === 'task.text' ? 'preview.text' : 'preview.delta', text.data);
208
208
  }
209
209
  else if (message.event === 'task.event') {
210
- const event = ardentTaskEventSchema.safeParse(JSON.parse(message.data));
210
+ const event = ardentTaskJournalEventSchema.safeParse(JSON.parse(message.data));
211
211
  if (!event.success)
212
212
  continue;
213
213
  cursor = event.data.sequence;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hivemagnus/ardent-studio",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Ardent Project Studio service: projects, team assignment, conversation room and deliverable review for Ardent agents managed by Magnus",
5
5
  "keywords": [
6
6
  "ardent",
@@ -67,6 +67,7 @@
67
67
  "verify": "npm run privacy:test && npm run scan:secrets && npm run check:private && npm run typecheck && npm run lint && npm test && npm run build && npm run check:contracts && npm run pack:check"
68
68
  },
69
69
  "dependencies": {
70
+ "@hivemagnus/magnus-contracts": "2.2.0",
70
71
  "@hono/node-server": "^2.1.5",
71
72
  "better-sqlite3": "^13.0.3",
72
73
  "fflate": "^0.8.3",
@@ -89,5 +90,8 @@
89
90
  "allowScripts": {
90
91
  "better-sqlite3@13.0.3": true,
91
92
  "esbuild@0.28.2": true
93
+ },
94
+ "overrides": {
95
+ "minimatch": "11.0.5"
92
96
  }
93
97
  }