agent-relay-sdk 0.2.0 → 0.2.2

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/src/types.ts CHANGED
@@ -13,6 +13,8 @@ export interface AgentCard {
13
13
  status: AgentStatus;
14
14
  instanceId?: string;
15
15
  epoch: number;
16
+ providerCapabilities?: ProviderCapabilities;
17
+ context?: ContextState;
16
18
  meta?: Record<string, unknown>;
17
19
  lastSeen: number;
18
20
  createdAt: number;
@@ -20,6 +22,291 @@ export interface AgentCard {
20
22
 
21
23
  export type AgentStatus = "online" | "idle" | "busy" | "stale" | "offline";
22
24
 
25
+ export type CapabilitySource = "catalog" | "provider" | "runtime" | "override" | "estimate";
26
+ export type CapabilityConfidence = "declared" | "reported" | "verified" | "estimated" | "unknown";
27
+
28
+ export interface ProviderCapabilities {
29
+ lifecycle: {
30
+ managed: boolean;
31
+ shutdownHard: boolean;
32
+ restartHard: boolean;
33
+ semanticStatus?: boolean;
34
+ reconnect?: boolean;
35
+ hibernate?: boolean;
36
+ resume?: boolean;
37
+ };
38
+ model?: {
39
+ provider?: SpawnProvider | string;
40
+ id?: string;
41
+ alias?: string;
42
+ providerModel?: string;
43
+ effort?: SpawnEffort | string;
44
+ source: CapabilitySource;
45
+ confidence: CapabilityConfidence;
46
+ lastUpdatedAt?: number;
47
+ };
48
+ session?: {
49
+ approvalMode?: SpawnApprovalMode | string;
50
+ fileRead?: boolean;
51
+ fileWrite?: boolean;
52
+ shell?: boolean;
53
+ source: CapabilitySource;
54
+ confidence: CapabilityConfidence;
55
+ lastUpdatedAt?: number;
56
+ };
57
+ context?: {
58
+ stats?: {
59
+ source: "api" | "statusline" | "hook" | "estimate";
60
+ confidence: "exact" | "reported" | "estimated";
61
+ };
62
+ compact?: boolean;
63
+ clear?: boolean;
64
+ inject?: boolean;
65
+ fork?: boolean;
66
+ rollback?: boolean;
67
+ archive?: boolean;
68
+ };
69
+ terminal?: {
70
+ live?: {
71
+ read?: boolean;
72
+ write?: boolean;
73
+ };
74
+ attach?: {
75
+ create?: boolean;
76
+ read?: boolean;
77
+ write?: boolean;
78
+ detach?: boolean;
79
+ };
80
+ };
81
+ source: CapabilitySource;
82
+ confidence: CapabilityConfidence;
83
+ lastUpdatedAt: number;
84
+ }
85
+
86
+ export type ContextLifecycleState =
87
+ | "fresh"
88
+ | "primed"
89
+ | "working"
90
+ | "cooling"
91
+ | "compacting"
92
+ | "hibernating";
93
+
94
+ export interface ContextProbeMetrics {
95
+ agentId: string;
96
+ contextPercent: number;
97
+ tokensUsed?: number;
98
+ tokensMax?: number;
99
+ quotaUsed?: number;
100
+ quotaLimit?: number;
101
+ quotaResetIn?: number;
102
+ model?: string;
103
+ effort?: string;
104
+ source: "statusline" | "hook" | "api" | "estimate";
105
+ confidence: "exact" | "reported" | "estimated";
106
+ timestamp: number;
107
+ }
108
+
109
+ export interface ContextState {
110
+ utilization: number;
111
+ tokensUsed?: number;
112
+ tokensMax?: number;
113
+ lifecycleState: ContextLifecycleState;
114
+ warmTopics: string[];
115
+ activeMemories: string[];
116
+ tasksSinceCompact: number;
117
+ lastCompactedAt?: number;
118
+ lastUpdatedAt: number;
119
+ source: "statusline" | "hook" | "api" | "estimate";
120
+ confidence: "exact" | "reported" | "estimated";
121
+ }
122
+
123
+ export interface ContextSnapshot {
124
+ id: number;
125
+ agentId: string;
126
+ context: ContextState;
127
+ utilization: number;
128
+ lifecycleState: ContextLifecycleState;
129
+ tokensUsed?: number;
130
+ tokensMax?: number;
131
+ source: ContextState["source"];
132
+ confidence: ContextState["confidence"];
133
+ capturedAt: number;
134
+ }
135
+
136
+ export type MemoryType = "organization" | "role" | "project" | "task" | "interaction" | "agent";
137
+ export type MemoryVisibility = "private" | "project" | "org" | "public";
138
+ export type MemorySensitivity = "public" | "normal" | "sensitive" | "secret";
139
+ export type MemoryConfidence = "reported" | "inferred" | "verified";
140
+ export type MemoryRedactionState = "raw" | "redacted" | "rejected";
141
+
142
+ export interface Memory {
143
+ id: string;
144
+ type: MemoryType;
145
+ scope: string;
146
+ title: string;
147
+ content: string;
148
+ tags: string[];
149
+ visibility: MemoryVisibility;
150
+ sensitivity: MemorySensitivity;
151
+ confidence: MemoryConfidence;
152
+ redactionState: MemoryRedactionState;
153
+ relevanceScore: number;
154
+ sourceAgent?: string;
155
+ sourceTask?: number;
156
+ createdBy?: string;
157
+ contentHash?: string;
158
+ metadata: Record<string, unknown>;
159
+ accessCount: number;
160
+ lastAccessedAt?: number;
161
+ createdAt: number;
162
+ updatedAt: number;
163
+ expiresAt?: number;
164
+ }
165
+
166
+ export interface CreateMemoryInput {
167
+ type: MemoryType;
168
+ scope: string;
169
+ title: string;
170
+ content: string;
171
+ tags?: string[];
172
+ visibility?: MemoryVisibility;
173
+ sensitivity?: MemorySensitivity;
174
+ confidence?: MemoryConfidence;
175
+ redactionState?: MemoryRedactionState;
176
+ relevanceScore?: number;
177
+ sourceAgent?: string;
178
+ sourceTask?: number;
179
+ createdBy?: string;
180
+ metadata?: Record<string, unknown>;
181
+ ttlMs?: number;
182
+ }
183
+
184
+ export interface UpdateMemoryInput {
185
+ title?: string;
186
+ content?: string;
187
+ tags?: string[];
188
+ visibility?: MemoryVisibility;
189
+ sensitivity?: MemorySensitivity;
190
+ confidence?: MemoryConfidence;
191
+ redactionState?: MemoryRedactionState;
192
+ relevanceScore?: number;
193
+ metadata?: Record<string, unknown>;
194
+ expiresAt?: number | null;
195
+ }
196
+
197
+ export interface MemoryQuery {
198
+ type?: MemoryType;
199
+ scope?: string;
200
+ tags?: string[];
201
+ minRelevance?: number;
202
+ limit?: number;
203
+ includeExpired?: boolean;
204
+ visibility?: MemoryVisibility;
205
+ includeSensitive?: boolean;
206
+ }
207
+
208
+ export interface MemorySearchResult {
209
+ memories: Memory[];
210
+ total: number;
211
+ }
212
+
213
+ export interface PackagedMemory {
214
+ memory: Memory;
215
+ reason: string;
216
+ priority: 1 | 2 | 3;
217
+ score?: number;
218
+ }
219
+
220
+ export interface TaskRoutingHints {
221
+ id?: number;
222
+ title?: string;
223
+ text?: string;
224
+ scope?: string;
225
+ tags?: string[];
226
+ capabilities?: string[];
227
+ target?: string;
228
+ }
229
+
230
+ export interface ContextBudget {
231
+ maxTokens: number;
232
+ maxMemories: number;
233
+ priorityCutoff: 1 | 2 | 3;
234
+ }
235
+
236
+ export interface TaskHistorySummary {
237
+ taskId: number;
238
+ agentId: string;
239
+ status: string;
240
+ summary?: string;
241
+ completedAt?: number;
242
+ }
243
+
244
+ export interface ContextPackage {
245
+ memories: PackagedMemory[];
246
+ rolePrompt?: string;
247
+ recentContext?: string;
248
+ taskHistory?: TaskHistorySummary[];
249
+ estimatedTokens: number;
250
+ }
251
+
252
+ export interface ContextPackageRequest {
253
+ task: TaskRoutingHints;
254
+ agent: AgentCard;
255
+ budget: ContextBudget;
256
+ memories?: Memory[];
257
+ }
258
+
259
+ export interface MemoryStats {
260
+ total: number;
261
+ byType: Partial<Record<MemoryType, number>>;
262
+ byScope: Record<string, number>;
263
+ bySensitivity: Partial<Record<MemorySensitivity, number>>;
264
+ }
265
+
266
+ export type ActiveMemoryClearReason = "compact" | "clearContext" | "restart" | "shutdown" | "manual";
267
+
268
+ export interface MemoryBrokerCapabilities {
269
+ search: true;
270
+ create: boolean;
271
+ update: boolean;
272
+ delete: boolean;
273
+ stats: boolean;
274
+ assemble: boolean;
275
+ activeTracking: boolean;
276
+ activeList: boolean;
277
+ external: boolean;
278
+ }
279
+
280
+ export interface MemoryBrokerContext {
281
+ now: number;
282
+ actor: string;
283
+ scopes: string[];
284
+ relayUrl?: string;
285
+ requestId?: string;
286
+ }
287
+
288
+ export type MemoryBrokerKind = "sqlite" | "http" | "command";
289
+
290
+ export interface SqliteMemoryBrokerConfig {
291
+ type: "sqlite";
292
+ }
293
+
294
+ export interface HttpMemoryBrokerConfig {
295
+ type: "http";
296
+ url: string;
297
+ tokenEnv?: string;
298
+ timeoutMs?: number;
299
+ }
300
+
301
+ export interface CommandMemoryBrokerConfig {
302
+ type: "command";
303
+ command: string;
304
+ args?: string[];
305
+ timeoutMs?: number;
306
+ }
307
+
308
+ export type MemoryBrokerConfig = SqliteMemoryBrokerConfig | HttpMemoryBrokerConfig | CommandMemoryBrokerConfig;
309
+
23
310
  export type MessageKind =
24
311
  | "chat"
25
312
  | "channel.event"
@@ -28,6 +315,71 @@ export type MessageKind =
28
315
  | "control"
29
316
  | "system";
30
317
 
318
+ export type ArtifactKind = "image" | "audio" | "video" | "document" | "archive" | "other";
319
+ export type ArtifactSensitivity = "public" | "normal" | "sensitive" | "secret";
320
+ export type ArtifactVisibility = "private" | "project" | "org";
321
+ export type ArtifactRole = "media" | "patch" | "report" | "log" | "output" | "input";
322
+
323
+ export interface ArtifactBlob {
324
+ digest: string;
325
+ storageUri: string;
326
+ mediaType: string;
327
+ size: number;
328
+ createdAt: number;
329
+ }
330
+
331
+ export interface ArtifactLink {
332
+ id: string;
333
+ artifactId: string;
334
+ entityType: "message" | "task" | "recipeRun" | "recipeStep" | "channelEvent";
335
+ entityId: string;
336
+ role?: ArtifactRole;
337
+ title?: string;
338
+ createdBy: string;
339
+ createdAt: number;
340
+ }
341
+
342
+ export interface Artifact {
343
+ id: string;
344
+ blobDigest: string;
345
+ mediaType: string;
346
+ kind: ArtifactKind;
347
+ filename?: string;
348
+ size: number;
349
+ digest: string;
350
+ visibility: ArtifactVisibility;
351
+ sensitivity: ArtifactSensitivity;
352
+ createdBy: string;
353
+ createdAt: number;
354
+ expiresAt?: number;
355
+ metadata: Record<string, unknown>;
356
+ links?: ArtifactLink[];
357
+ url?: string;
358
+ }
359
+
360
+ export interface AttachmentRef {
361
+ artifactId: string;
362
+ kind?: ArtifactKind;
363
+ role?: ArtifactRole;
364
+ title?: string;
365
+ ref?: AttachmentSourceRef;
366
+ metadata?: Record<string, unknown>;
367
+ }
368
+
369
+ export interface ChannelAttachmentRef {
370
+ artifactId?: string;
371
+ kind?: ArtifactKind;
372
+ role?: ArtifactRole;
373
+ title?: string;
374
+ ref?: AttachmentSourceRef;
375
+ metadata?: Record<string, unknown>;
376
+ }
377
+
378
+ export type AttachmentSourceRef =
379
+ | { type: "relay-blob"; id: string; [key: string]: unknown }
380
+ | { type: "external-url"; url: string; [key: string]: unknown }
381
+ | { type: "channel-file"; id: string; provider?: string; uniqueId?: string; [key: string]: unknown };
382
+
31
383
  export interface Message {
32
384
  id: number;
33
385
  from: string;
@@ -43,12 +395,93 @@ export interface Message {
43
395
  claimedAt?: number;
44
396
  claimExpiresAt?: number;
45
397
  idempotencyKey?: string;
398
+ deliveryStatus?: MessageDeliveryStatus;
399
+ deliveryAttempts?: number;
400
+ deliveryLastError?: string;
401
+ deliveryNextRetryAt?: number;
402
+ deliveryPoisonReason?: string;
403
+ deliveryUpdatedAt?: number;
404
+ queuedAt?: number;
405
+ maxAgeSeconds?: number;
406
+ resolvedToAgent?: string;
46
407
  payload: Record<string, unknown>;
47
408
  meta?: Record<string, unknown>;
409
+ reactions?: MessageReaction[];
48
410
  readBy: string[];
49
411
  createdAt: number;
50
412
  }
51
413
 
414
+ export interface ReplyObligation {
415
+ messageId: number;
416
+ agentId: string;
417
+ from: string;
418
+ kind: MessageKind;
419
+ subject?: string;
420
+ channel?: string;
421
+ bodyPreview: string;
422
+ createdAt: number;
423
+ replyCommand: string;
424
+ }
425
+
426
+ export interface MessageReaction {
427
+ messageId: number;
428
+ actorId: string;
429
+ emoji: string;
430
+ createdAt: number;
431
+ updatedAt: number;
432
+ }
433
+
434
+ export type RelayNotificationKind =
435
+ | "message"
436
+ | "reply"
437
+ | "error"
438
+ | "agent.blocked";
439
+
440
+ export type RelayNotificationSeverity = "info" | "warning" | "error";
441
+
442
+ export interface RelayNotification {
443
+ id: string;
444
+ kind: RelayNotificationKind;
445
+ severity: RelayNotificationSeverity;
446
+ title: string;
447
+ body: string;
448
+ messageId?: number;
449
+ agentId?: string;
450
+ threadPeer?: string;
451
+ view?: "chat" | "messages" | "agents" | "work" | "tasks" | "channels" | "overview";
452
+ createdAt: number;
453
+ }
454
+
455
+ export type MessageDeliveryStatus = "pending" | "delivered" | "queued" | "failed" | "dead";
456
+
457
+ export interface MessageDeliveryAttempt {
458
+ id: number;
459
+ messageId: number;
460
+ agentId?: string;
461
+ action: "attempt" | "retry-now" | "mark-dead" | "clear";
462
+ status: MessageDeliveryStatus;
463
+ error?: string;
464
+ nextRetryAt?: number;
465
+ poisonReason?: string;
466
+ createdAt: number;
467
+ }
468
+
469
+ export interface MessageDeliveryState extends Pick<Message,
470
+ | "id"
471
+ | "to"
472
+ | "deliveryStatus"
473
+ | "deliveryAttempts"
474
+ | "deliveryLastError"
475
+ | "deliveryNextRetryAt"
476
+ | "deliveryPoisonReason"
477
+ | "deliveryUpdatedAt"
478
+ | "queuedAt"
479
+ | "maxAgeSeconds"
480
+ | "resolvedToAgent"
481
+ > {
482
+ attempts: MessageDeliveryAttempt[];
483
+ }
484
+
52
485
  export interface SendMessageInput {
53
486
  from: string;
54
487
  to: string;
@@ -59,6 +492,8 @@ export interface SendMessageInput {
59
492
  replyTo?: number;
60
493
  claimable?: boolean;
61
494
  idempotencyKey?: string;
495
+ maxAgeSeconds?: number;
496
+ attachments?: AttachmentRef[];
62
497
  payload?: Record<string, unknown>;
63
498
  meta?: Record<string, unknown>;
64
499
  }
@@ -175,6 +610,8 @@ export interface RegisterAgentInput {
175
610
  ready?: boolean;
176
611
  status?: AgentCard["status"];
177
612
  instanceId?: string;
613
+ providerCapabilities?: ProviderCapabilities;
614
+ context?: ContextState;
178
615
  meta?: Record<string, unknown>;
179
616
  }
180
617
 
@@ -280,6 +717,7 @@ export interface IntegrationEventInput {
280
717
  channel?: string;
281
718
  dedupeKey?: string;
282
719
  externalUrl?: string;
720
+ attachments?: AttachmentRef[];
283
721
  metadata?: Record<string, unknown>;
284
722
  }
285
723
 
@@ -295,8 +733,19 @@ export interface IntegrationTaskStats {
295
733
 
296
734
  export interface IntegrationSummary {
297
735
  name: string;
736
+ displayName?: string;
737
+ description?: string;
738
+ enabled: boolean;
298
739
  configured: boolean;
299
740
  observed: boolean;
741
+ type?: string;
742
+ icon?: string;
743
+ accentColor?: string;
744
+ tags: string[];
745
+ homepageUrl?: string;
746
+ repositoryUrl?: string;
747
+ docsUrl?: string;
748
+ manifest?: Record<string, unknown>;
300
749
  scopes: string[];
301
750
  targets: string[];
302
751
  channels: string[];
@@ -310,6 +759,32 @@ export interface IntegrationSummary {
310
759
  taskStats: IntegrationTaskStats;
311
760
  }
312
761
 
762
+ export type RuntimeContractName =
763
+ | "relayApi"
764
+ | "orchestratorProtocol"
765
+ | "runnerProtocol"
766
+ | "providerPluginProtocol";
767
+
768
+ export type RuntimeContracts = Partial<Record<RuntimeContractName, number>>;
769
+ export type RuntimeCapabilities = Record<string, boolean>;
770
+
771
+ export interface RuntimePackageMetadata {
772
+ name: string;
773
+ version: string;
774
+ }
775
+
776
+ export interface ContractCompatibilityIssue {
777
+ contract: string;
778
+ expected: string;
779
+ actual?: number;
780
+ }
781
+
782
+ export interface ContractCompatibility {
783
+ status: "compatible" | "incompatible" | "unknown";
784
+ compatible: boolean;
785
+ issues: ContractCompatibilityIssue[];
786
+ }
787
+
313
788
  export type AutomationKind = "scheduled_task";
314
789
  export type AutomationCatchUpPolicy = "skip" | "run_once" | "run_all";
315
790
  export type AutomationConcurrencyPolicy = "skip" | "queue" | "replace";
@@ -337,15 +812,25 @@ export interface AutomationExistingAgentPolicy {
337
812
  export interface AutomationOnDemandAgentPolicy {
338
813
  mode: "on_demand_agent";
339
814
  provider: SpawnProvider;
815
+ model?: string;
816
+ effort?: SpawnEffort;
340
817
  cwd?: string;
818
+ workspaceMode?: WorkspaceMode;
341
819
  profile?: string;
342
820
  approvalMode?: SpawnApprovalMode;
343
821
  keepAlive?: boolean;
822
+ runtimeBudget?: AutomationRuntimeBudget;
344
823
  shutdownAfterMs?: number;
345
824
  }
346
825
 
347
826
  export type AutomationTargetPolicy = AutomationExistingAgentPolicy | AutomationOnDemandAgentPolicy;
348
827
 
828
+ export interface AutomationRuntimeBudget {
829
+ maxRuntimeMs: number;
830
+ warnAtMs?: number;
831
+ warningMessage?: string;
832
+ }
833
+
349
834
  export interface AutomationTaskTemplate {
350
835
  title: string;
351
836
  body: string;
@@ -429,7 +914,8 @@ export type ChannelRouteTarget =
429
914
  | { type: "capability"; id: string }
430
915
  | { type: "broadcast" }
431
916
  | { type: "orchestrator"; id: string }
432
- | { type: "pool"; id: string };
917
+ | { type: "pool"; id: string }
918
+ | { type: "policy"; id: string };
433
919
 
434
920
  export type ChannelBindingMode = "exclusive" | "broadcast";
435
921
 
@@ -484,6 +970,22 @@ export interface ChannelSummary {
484
970
  meta?: Record<string, unknown>;
485
971
  }
486
972
 
973
+ export interface ChannelEventInput {
974
+ body?: string;
975
+ payload: Record<string, unknown>;
976
+ attachments?: ChannelAttachmentRef[];
977
+ conversationId?: string;
978
+ idempotencyKey?: string;
979
+ instanceId?: string;
980
+ epoch?: number;
981
+ }
982
+
983
+ export interface ChannelEventResult {
984
+ messages: Message[];
985
+ bindings: ChannelBinding[];
986
+ created: boolean;
987
+ }
988
+
487
989
  export interface TaskStatusInput {
488
990
  status: TaskStatus;
489
991
  agentId?: string;
@@ -517,6 +1019,28 @@ export interface InboxState {
517
1019
  drafts: InboxDraft[];
518
1020
  }
519
1021
 
1022
+ export interface ChatHistoryImportEntry {
1023
+ position: number;
1024
+ originalMessageId: number;
1025
+ originalFrom: string;
1026
+ originalTo: string;
1027
+ originalCreatedAt: number;
1028
+ message: Message;
1029
+ }
1030
+
1031
+ export interface ChatHistoryImport {
1032
+ id: string;
1033
+ targetAgentId?: string;
1034
+ targetSpawnRequestId?: string;
1035
+ sourcePeerId: string;
1036
+ sourceAgentId?: string;
1037
+ sourceThreadId?: string;
1038
+ sourceAgentLabel?: string;
1039
+ importedBy: string;
1040
+ importedAt: number;
1041
+ entries: ChatHistoryImportEntry[];
1042
+ }
1043
+
520
1044
  export type ActivityKind = "message" | "reply" | "question" | "operator" | "pair" | "task" | "state";
521
1045
 
522
1046
  export interface ActivityEvent {
@@ -560,6 +1084,342 @@ export interface ActivityEventInput {
560
1084
  export type OrchestratorStatus = "online" | "offline";
561
1085
  export type SpawnProvider = "claude" | "codex";
562
1086
  export type SpawnApprovalMode = "open" | "guarded" | "read-only";
1087
+ export type SpawnEffort = "low" | "medium" | "high" | "xhigh" | "max";
1088
+ export type WorkspaceMode = "isolated" | "shared" | "inherit";
1089
+ export type WorkspaceStatus = "active" | "ready" | "conflict" | "review_requested" | "merge_planned" | "merged" | "abandoned" | "cleanup_requested" | "cleaned";
1090
+
1091
+ /** How a workspace's work is integrated back into its base branch. */
1092
+ export type WorkspaceMergeStrategy = "pr" | "rebase-ff" | "auto";
1093
+
1094
+ export interface WorkspaceProbeWorktree {
1095
+ path: string;
1096
+ branch?: string;
1097
+ headSha?: string;
1098
+ bare?: boolean;
1099
+ detached?: boolean;
1100
+ prunable?: boolean;
1101
+ locked?: boolean;
1102
+ reason?: string;
1103
+ }
1104
+
1105
+ export interface WorkspaceProbe {
1106
+ path: string;
1107
+ isGitRepo: boolean;
1108
+ repoRoot?: string;
1109
+ branch?: string;
1110
+ headSha?: string;
1111
+ dirty?: boolean;
1112
+ detached?: boolean;
1113
+ worktrees?: WorkspaceProbeWorktree[];
1114
+ error?: string;
1115
+ }
1116
+
1117
+ export interface WorkspaceGitCommit {
1118
+ sha: string;
1119
+ message: string;
1120
+ at?: number;
1121
+ }
1122
+
1123
+ /**
1124
+ * Live git state of a workspace worktree, computed on the host by the
1125
+ * orchestrator. Used to surface whether a worktree contains actual work
1126
+ * (commits ahead of base, dirty files) so the dashboard isn't a black box and
1127
+ * so exit-time reconcile can decide cleanup-vs-flag.
1128
+ */
1129
+ export interface WorkspaceGitState {
1130
+ /** Commits on the agent branch not yet in base (work the agent produced). */
1131
+ ahead?: number;
1132
+ /** Commits in base not in the agent branch (how far base moved on). */
1133
+ behind?: number;
1134
+ /** True if the worktree has uncommitted/untracked changes. */
1135
+ dirty?: boolean;
1136
+ /** Number of dirty (porcelain) entries. */
1137
+ dirtyCount?: number;
1138
+ /** Most recent commit in the worktree. */
1139
+ lastCommit?: WorkspaceGitCommit;
1140
+ /** Ref/sha the ahead/behind counts were computed against. */
1141
+ baseRef?: string;
1142
+ /** Set when the worktree path no longer exists on disk. */
1143
+ missing?: boolean;
1144
+ /** Populated when git interrogation failed. */
1145
+ error?: string;
1146
+ }
1147
+
1148
+ /**
1149
+ * Pre-flight check for integrating a workspace's work, computed on the host.
1150
+ * Reports whether the merge would be clean, conflict, or is a no-op, and which
1151
+ * strategy `auto` would pick — so the dashboard can warn before the user acts.
1152
+ */
1153
+ export interface WorkspaceMergePreview {
1154
+ /** Strategy `auto` would resolve to given the repo's remote/gh state. */
1155
+ strategy: "pr" | "rebase-ff";
1156
+ /** Commits on the agent branch not yet in base. */
1157
+ ahead?: number;
1158
+ /** Commits in base not in the agent branch. */
1159
+ behind?: number;
1160
+ /** Uncommitted/untracked entries in the worktree. */
1161
+ dirtyCount?: number;
1162
+ /** True if the three-way merge of base and the branch would conflict. */
1163
+ conflict?: boolean;
1164
+ /** True if base can fast-forward to the branch with no rebase needed. */
1165
+ cleanFastForward?: boolean;
1166
+ /** Whether an `origin` remote is configured. */
1167
+ hasRemote?: boolean;
1168
+ /** Whether the `gh` CLI is available on the host. */
1169
+ ghAvailable?: boolean;
1170
+ /** Resolved base branch name the work would land on. */
1171
+ baseRef?: string;
1172
+ /** Human-readable reason a merge can't proceed (no work, dirty, missing). */
1173
+ reason?: string;
1174
+ /** Set when the worktree path no longer exists. */
1175
+ missing?: boolean;
1176
+ /** Populated when git interrogation failed. */
1177
+ error?: string;
1178
+ }
1179
+
1180
+ /** Outcome of a `workspace.merge` command executed on the host. */
1181
+ export interface WorkspaceMergeResult {
1182
+ workspaceId?: string;
1183
+ /** Strategy actually used. */
1184
+ strategy: "pr" | "rebase-ff";
1185
+ /** True when work was landed locally (rebase-ff into base). */
1186
+ merged: boolean;
1187
+ /** True when a merge was prevented by conflicts. */
1188
+ conflict?: boolean;
1189
+ /** PR URL when the pr strategy opened one. */
1190
+ prUrl?: string;
1191
+ branch?: string;
1192
+ baseRef?: string;
1193
+ /** SHA base now points at after a successful rebase-ff. */
1194
+ mergedSha?: string;
1195
+ branchDeleted?: boolean;
1196
+ worktreeRemoved?: boolean;
1197
+ /** Resulting workspace status the relay should record. */
1198
+ status: WorkspaceStatus;
1199
+ /** Populated when the merge could not complete. */
1200
+ error?: string;
1201
+ }
1202
+
1203
+ /** One changed file in a workspace diff against its base. */
1204
+ export interface WorkspaceDiffFile {
1205
+ path: string;
1206
+ /** Lines added (undefined for binary files). */
1207
+ additions?: number;
1208
+ /** Lines removed (undefined for binary files). */
1209
+ deletions?: number;
1210
+ binary?: boolean;
1211
+ }
1212
+
1213
+ /** Diff of a workspace's committed work against its base, computed on the host. */
1214
+ export interface WorkspaceDiff {
1215
+ baseRef?: string;
1216
+ ahead?: number;
1217
+ files: WorkspaceDiffFile[];
1218
+ /** Unified patch text (may be truncated). */
1219
+ patch?: string;
1220
+ /** True when the patch was capped at the size limit. */
1221
+ truncated?: boolean;
1222
+ /** Uncommitted entries in the worktree, not part of the committed diff. */
1223
+ dirtyCount?: number;
1224
+ missing?: boolean;
1225
+ error?: string;
1226
+ }
1227
+
1228
+ /** A worktree found on disk with no matching active workspace row. */
1229
+ export interface WorkspaceOrphan {
1230
+ worktreePath: string;
1231
+ repoRoot: string;
1232
+ branch?: string;
1233
+ headSha?: string;
1234
+ /** True if a DB row exists for this path but is already terminal (cleaned/merged). */
1235
+ hadTerminalRow?: boolean;
1236
+ }
1237
+
1238
+ export interface WorkspaceMetadata {
1239
+ id?: string;
1240
+ mode: WorkspaceMode;
1241
+ requestedMode?: WorkspaceMode;
1242
+ repoRoot?: string;
1243
+ sourceCwd?: string;
1244
+ worktreePath?: string;
1245
+ branch?: string;
1246
+ baseRef?: string;
1247
+ baseSha?: string;
1248
+ status?: WorkspaceStatus;
1249
+ stewardAgentId?: string;
1250
+ probe?: WorkspaceProbe;
1251
+ }
1252
+
1253
+ export interface WorkspaceRecord {
1254
+ id: string;
1255
+ repoRoot: string;
1256
+ sourceCwd: string;
1257
+ worktreePath: string;
1258
+ branch?: string;
1259
+ baseRef?: string;
1260
+ baseSha?: string;
1261
+ mode: WorkspaceMode;
1262
+ requestedMode?: WorkspaceMode;
1263
+ status: WorkspaceStatus;
1264
+ ownerAgentId?: string;
1265
+ ownerPolicyName?: string;
1266
+ ownerAutomationRunId?: string;
1267
+ stewardAgentId?: string;
1268
+ metadata: Record<string, unknown>;
1269
+ createdAt: number;
1270
+ updatedAt: number;
1271
+ readyAt?: number;
1272
+ cleanedAt?: number;
1273
+ }
1274
+
1275
+ export interface ConfigEntry<T = unknown> {
1276
+ namespace: string;
1277
+ key: string;
1278
+ value: T;
1279
+ version: number;
1280
+ updatedAt: string;
1281
+ updatedBy?: string;
1282
+ }
1283
+
1284
+ export interface ConfigHistoryEntry<T = unknown> {
1285
+ id: number;
1286
+ namespace: string;
1287
+ key: string;
1288
+ value: T;
1289
+ version: number;
1290
+ changedAt: string;
1291
+ changedBy?: string;
1292
+ }
1293
+
1294
+ export type ManagedAgentStatus = "stopped" | "starting" | "running" | "stopping" | "backoff";
1295
+
1296
+ export interface ManagedAgentState {
1297
+ policyName: string;
1298
+ status: ManagedAgentStatus;
1299
+ agentId?: string;
1300
+ orchestratorId: string;
1301
+ provider: SpawnProvider;
1302
+ tmuxSession?: string;
1303
+ spawnRequestId?: string;
1304
+ workspaceId?: string;
1305
+ workspacePath?: string;
1306
+ workspaceBranch?: string;
1307
+ lastSpawnAt?: number;
1308
+ lastStopAt?: number;
1309
+ healthySince?: number;
1310
+ restartCount: number;
1311
+ consecutiveFailures: number;
1312
+ backoffUntil?: number;
1313
+ lastError?: string;
1314
+ updatedAt: number;
1315
+ }
1316
+
1317
+ export type SpawnPolicyMode = "always-on" | "on-demand";
1318
+
1319
+ export type AgentProfileProvider = SpawnProvider | "any";
1320
+ export type AgentProfileBase = "host" | "minimal" | "isolated";
1321
+ export type AgentProfileInstructionPolicy = "allow" | "ignore";
1322
+ export type AgentProfileCategoryMode = "host" | "profile" | "repo" | "none";
1323
+ export type AgentProfileFilesystemScope = "repo" | "workspace" | "host";
1324
+
1325
+ export interface AgentProfileAssetRef {
1326
+ source: "relay" | "repo" | "inline" | "provider";
1327
+ ref: string;
1328
+ enabled: boolean;
1329
+ provider?: AgentProfileProvider;
1330
+ meta?: Record<string, unknown>;
1331
+ }
1332
+
1333
+ export interface AgentProfile {
1334
+ name: string;
1335
+ description?: string;
1336
+ provider?: AgentProfileProvider;
1337
+ base: AgentProfileBase;
1338
+ builtIn?: boolean;
1339
+ instructions: {
1340
+ system?: string;
1341
+ append: string[];
1342
+ repoInstructions: AgentProfileInstructionPolicy;
1343
+ globalInstructions: AgentProfileInstructionPolicy;
1344
+ };
1345
+ relay: {
1346
+ context: boolean;
1347
+ skills: boolean;
1348
+ plugins: boolean;
1349
+ statusLine: boolean;
1350
+ };
1351
+ skills: AgentProfileAssetRef[];
1352
+ plugins: AgentProfileAssetRef[];
1353
+ mcp: {
1354
+ mode: AgentProfileCategoryMode;
1355
+ servers?: Record<string, unknown>;
1356
+ };
1357
+ hooks: {
1358
+ mode: AgentProfileCategoryMode;
1359
+ };
1360
+ permissions: {
1361
+ mode?: SpawnApprovalMode;
1362
+ filesystem: AgentProfileFilesystemScope;
1363
+ };
1364
+ env: Record<string, string>;
1365
+ providerOptions: Record<string, unknown>;
1366
+ }
1367
+
1368
+ export type AgentProfileProjectionResult = "applied" | "partial" | "unsupported" | "not-applicable";
1369
+
1370
+ export interface AgentProfileProjectionEntry {
1371
+ capability: string;
1372
+ requested: string;
1373
+ result: AgentProfileProjectionResult;
1374
+ detail: string;
1375
+ }
1376
+
1377
+ export interface AgentProfileProjectionReport {
1378
+ profileName: string;
1379
+ provider: SpawnProvider;
1380
+ base: AgentProfileBase;
1381
+ generatedAt: number;
1382
+ entries: AgentProfileProjectionEntry[];
1383
+ warnings: string[];
1384
+ unsupported: string[];
1385
+ }
1386
+
1387
+ export interface SpawnPolicy {
1388
+ name: string;
1389
+ description?: string;
1390
+ // Desired on/off switch. `false` keeps the policy from (re)spawning even for
1391
+ // always-on mode, so a manual stop survives reconcile ticks. Defaults to true.
1392
+ enabled?: boolean;
1393
+ orchestratorId: string;
1394
+ cwd: string;
1395
+ provider: SpawnProvider;
1396
+ workspaceMode?: WorkspaceMode;
1397
+ rig?: string;
1398
+ model?: string;
1399
+ effort?: SpawnEffort;
1400
+ profile?: string;
1401
+ providerArgs: string[];
1402
+ prompt?: string;
1403
+ tags: string[];
1404
+ capabilities: string[];
1405
+ label?: string;
1406
+ mode: SpawnPolicyMode;
1407
+ permissionMode: SpawnApprovalMode;
1408
+ restartOnUpdate: boolean;
1409
+ scheduledDailyRestart: boolean;
1410
+ onDemand?: {
1411
+ keepaliveSeconds: number;
1412
+ idleDefinition: "no-activity";
1413
+ };
1414
+ backoff: {
1415
+ schedule: number[];
1416
+ resetAfterSeconds: number;
1417
+ };
1418
+ binding?: {
1419
+ type: "channel";
1420
+ channelId: string;
1421
+ };
1422
+ }
563
1423
 
564
1424
  export interface Orchestrator {
565
1425
  id: string;
@@ -567,24 +1427,51 @@ export interface Orchestrator {
567
1427
  status: OrchestratorStatus;
568
1428
  agentId: string; // relay agent id for messaging
569
1429
  providers: SpawnProvider[];
1430
+ providerStatus?: ProviderStatusReport[];
1431
+ providerCatalog?: ProviderCatalogSummary[];
570
1432
  baseDir: string;
571
1433
  apiUrl?: string;
572
1434
  envKeys: string[]; // names only, never values
1435
+ package?: RuntimePackageMetadata;
1436
+ contracts?: RuntimeContracts;
1437
+ capabilities?: RuntimeCapabilities;
1438
+ contractCompatibility?: ContractCompatibility;
573
1439
  version?: string;
574
1440
  protocolVersion?: number;
575
1441
  gitSha?: string;
576
1442
  health?: OrchestratorHealth;
1443
+ // Self-reported host supervision (how the orchestrator's own process is run),
1444
+ // used to target a remote self-upgrade at the right unit.
1445
+ supervisor?: "process" | "systemd" | "unknown";
1446
+ selfUnit?: string;
1447
+ runtimePrefix?: string;
1448
+ // In-flight / last remote upgrade state, reconciled by the relay against the
1449
+ // version the orchestrator reports after it restarts.
1450
+ upgrade?: OrchestratorUpgradeState;
577
1451
  meta: Record<string, unknown>;
578
1452
  managedAgents: ManagedAgent[];
579
1453
  lastSeen: number;
580
1454
  createdAt: number;
581
1455
  }
582
1456
 
1457
+ export interface OrchestratorUpgradeState {
1458
+ desiredVersion: string;
1459
+ status: "pending" | "succeeded" | "failed";
1460
+ commandId?: string;
1461
+ providers?: string[];
1462
+ fromVersion?: string;
1463
+ requestedBy?: string;
1464
+ requestedAt: number;
1465
+ settledAt?: number;
1466
+ error?: string;
1467
+ }
1468
+
583
1469
  export interface OrchestratorHealth {
584
- status: "ok" | "warn" | "error";
1470
+ status: "ok" | "warn" | "restart-required" | "upgrade-required" | "unknown";
585
1471
  restartRequired: boolean;
1472
+ upgradeRequired?: boolean;
586
1473
  issues: Array<{
587
- code: "missing-version" | "outdated" | "protocol-mismatch" | "restart-required";
1474
+ code: "missing-version" | "package-drift" | "missing-contract" | "protocol-mismatch" | "restart-required" | "upgrade-required";
588
1475
  detail: string;
589
1476
  }>;
590
1477
  }
@@ -592,21 +1479,80 @@ export interface OrchestratorHealth {
592
1479
  export interface ManagedAgent {
593
1480
  agentId: string;
594
1481
  provider: SpawnProvider;
1482
+ model?: string;
1483
+ effort?: SpawnEffort;
1484
+ profile?: string;
1485
+ workspaceMode?: WorkspaceMode;
1486
+ workspace?: WorkspaceMetadata;
1487
+ sessionName?: string;
1488
+ supervisor?: "process" | "systemd" | "unknown";
1489
+ systemdUnit?: string;
1490
+ terminalSession?: string;
1491
+ terminalAvailable?: boolean;
595
1492
  tmuxSession: string;
596
1493
  cwd: string;
597
1494
  label?: string;
598
1495
  approvalMode: SpawnApprovalMode;
1496
+ policyName?: string;
1497
+ spawnRequestId?: string;
1498
+ automationRunId?: string;
599
1499
  pid?: number;
600
1500
  startedAt: number;
601
1501
  }
602
1502
 
1503
+ export interface ManagedSessionExitDiagnostics {
1504
+ agentId: string;
1505
+ provider: SpawnProvider;
1506
+ workspaceMode?: WorkspaceMode;
1507
+ workspace?: WorkspaceMetadata;
1508
+ sessionName?: string;
1509
+ tmuxSession: string;
1510
+ cwd: string;
1511
+ label?: string;
1512
+ policyName?: string;
1513
+ spawnRequestId?: string;
1514
+ automationRunId?: string;
1515
+ supervisor: "process" | "systemd" | "unknown";
1516
+ systemdUnit?: string;
1517
+ terminalSession?: string;
1518
+ terminalAvailable?: boolean;
1519
+ pid?: number;
1520
+ currentPid?: number;
1521
+ startedAt: number;
1522
+ detectedAt: number;
1523
+ runtimeMs: number;
1524
+ logFile?: string;
1525
+ logBytes?: number;
1526
+ logEmpty?: boolean;
1527
+ logTail?: string[];
1528
+ runnerInfoFile?: string;
1529
+ runnerInfoPresent?: boolean;
1530
+ systemd?: {
1531
+ unit: string;
1532
+ activeState?: string;
1533
+ subState?: string;
1534
+ result?: string;
1535
+ execMainCode?: string;
1536
+ execMainStatus?: string;
1537
+ mainPid?: number;
1538
+ unavailable?: string;
1539
+ };
1540
+ unavailable?: string[];
1541
+ lastError: string;
1542
+ }
1543
+
603
1544
  export interface RegisterOrchestratorInput {
604
1545
  id: string;
605
1546
  hostname: string;
606
1547
  providers: SpawnProvider[];
1548
+ providerStatus?: ProviderStatusReport[];
1549
+ providerCatalog?: ProviderCatalogSummary[];
607
1550
  baseDir: string;
608
1551
  apiUrl?: string;
609
1552
  envKeys?: string[];
1553
+ package?: RuntimePackageMetadata;
1554
+ contracts?: RuntimeContracts;
1555
+ capabilities?: RuntimeCapabilities;
610
1556
  version?: string;
611
1557
  protocolVersion?: number;
612
1558
  gitSha?: string;
@@ -614,23 +1560,120 @@ export interface RegisterOrchestratorInput {
614
1560
  }
615
1561
 
616
1562
  export interface OrchestratorRuntimeInput {
1563
+ package?: RuntimePackageMetadata;
1564
+ contracts?: RuntimeContracts;
1565
+ capabilities?: RuntimeCapabilities;
617
1566
  version?: string;
618
1567
  protocolVersion?: number;
619
1568
  gitSha?: string;
1569
+ providers?: SpawnProvider[];
1570
+ providerStatus?: ProviderStatusReport[];
1571
+ providerCatalog?: ProviderCatalogSummary[];
620
1572
  }
621
1573
 
622
1574
  export interface OrchestratorSpawnInput {
623
1575
  provider: SpawnProvider;
1576
+ model?: string;
1577
+ effort?: SpawnEffort;
624
1578
  cwd?: string;
1579
+ workspaceMode?: WorkspaceMode;
625
1580
  label?: string;
626
1581
  approvalMode?: SpawnApprovalMode;
627
1582
  prompt?: string;
1583
+ systemPromptAppend?: string;
628
1584
  env?: Record<string, string>;
629
1585
  }
630
1586
 
1587
+ export interface ProviderStatusReport {
1588
+ name: SpawnProvider;
1589
+ available: boolean;
1590
+ checkedAt: number;
1591
+ reason?: string;
1592
+ version?: string;
1593
+ features?: Record<string, boolean>;
1594
+ cli?: {
1595
+ command: string;
1596
+ path?: string;
1597
+ ok: boolean;
1598
+ version?: string;
1599
+ error?: string;
1600
+ };
1601
+ runner?: {
1602
+ command: string;
1603
+ path?: string;
1604
+ ok: boolean;
1605
+ version?: string;
1606
+ error?: string;
1607
+ };
1608
+ }
1609
+
1610
+ export interface ProviderCatalogSummary {
1611
+ provider: SpawnProvider;
1612
+ label: string;
1613
+ defaultModel?: string;
1614
+ models: Array<{
1615
+ alias: string;
1616
+ label: string;
1617
+ providerModel: string;
1618
+ efforts: SpawnEffort[];
1619
+ defaultEffort?: SpawnEffort;
1620
+ limits?: {
1621
+ contextWindowTokens?: {
1622
+ value: number;
1623
+ source: "catalog" | "provider" | "runtime" | "override";
1624
+ confidence: "declared" | "verified" | "estimated" | "unknown";
1625
+ lastUpdatedAt?: number;
1626
+ };
1627
+ maxOutputTokens?: {
1628
+ value: number;
1629
+ source: "catalog" | "provider" | "runtime" | "override";
1630
+ confidence: "declared" | "verified" | "estimated" | "unknown";
1631
+ lastUpdatedAt?: number;
1632
+ };
1633
+ };
1634
+ capabilities?: {
1635
+ modalities: {
1636
+ input: {
1637
+ text: boolean;
1638
+ image?: boolean;
1639
+ audio?: boolean;
1640
+ video?: boolean;
1641
+ pdf?: boolean;
1642
+ };
1643
+ output: {
1644
+ text: boolean;
1645
+ image?: boolean;
1646
+ audio?: boolean;
1647
+ video?: boolean;
1648
+ };
1649
+ };
1650
+ tools?: {
1651
+ code?: boolean;
1652
+ review?: boolean;
1653
+ debug?: boolean;
1654
+ refactor?: boolean;
1655
+ shell?: boolean;
1656
+ fileRead?: boolean;
1657
+ fileWrite?: boolean;
1658
+ webSearch?: boolean;
1659
+ imageGeneration?: boolean;
1660
+ imageEditing?: boolean;
1661
+ };
1662
+ source: "catalog" | "provider" | "runtime" | "override";
1663
+ confidence: "declared" | "verified" | "estimated" | "unknown";
1664
+ lastUpdatedAt?: number;
1665
+ };
1666
+ }>;
1667
+ }
1668
+
631
1669
  export interface OrchestratorSpawnResult {
632
1670
  orchestratorId: string;
633
1671
  provider: SpawnProvider;
1672
+ sessionName?: string;
1673
+ supervisor?: "process" | "systemd" | "unknown";
1674
+ systemdUnit?: string;
1675
+ terminalSession?: string;
1676
+ terminalAvailable?: boolean;
634
1677
  tmuxSession: string;
635
1678
  cwd: string;
636
1679
  label?: string;
@@ -656,9 +1699,11 @@ export interface RecipeAgent {
656
1699
  capabilities: string[];
657
1700
  label?: string;
658
1701
  tags?: string[];
1702
+ memoryTags?: string[];
659
1703
  approvalMode?: "open" | "guarded" | "read-only";
660
1704
  prompt?: string;
661
1705
  model?: string;
1706
+ effort?: SpawnEffort;
662
1707
  env?: Record<string, string>;
663
1708
  }
664
1709
 
@@ -677,6 +1722,20 @@ export interface RecipeRoute {
677
1722
  export interface RecipeLifecycle {
678
1723
  mode?: "persistent" | "ephemeral";
679
1724
  idleTimeoutMs?: number;
1725
+ memory?: RecipeMemoryPolicy;
1726
+ }
1727
+
1728
+ export interface RecipeMemoryPolicy {
1729
+ injectOnAssign?: boolean;
1730
+ autoCapture?: boolean;
1731
+ captureTypes?: MemoryType[];
1732
+ memoryTags?: string[];
1733
+ alwaysReload?: string[];
1734
+ scope?: string;
1735
+ maxTokens?: number;
1736
+ maxMemories?: number;
1737
+ priorityCutoff?: 1 | 2 | 3;
1738
+ ttlMs?: number;
680
1739
  }
681
1740
 
682
1741
  export interface RecipeInstance {
@@ -687,6 +1746,7 @@ export interface RecipeInstance {
687
1746
  orchestratorId: string;
688
1747
  status: "starting" | "running" | "stopping" | "stopped" | "failed";
689
1748
  agents: RecipeAgentInstance[];
1749
+ artifacts?: Artifact[];
690
1750
  startedAt: number;
691
1751
  stoppedAt?: number;
692
1752
  startedBy: string;
@@ -705,30 +1765,142 @@ export interface ComponentToken {
705
1765
  sub: string;
706
1766
  role: "provider" | "channel" | "orchestrator" | "admin" | "dashboard" | string;
707
1767
  scope: string[];
1768
+ constraints?: TokenConstraints;
708
1769
  iat: number;
709
1770
  exp?: number;
710
1771
  jti?: string;
711
1772
  }
712
1773
 
1774
+ export interface TokenRecord {
1775
+ jti: string;
1776
+ sub: string;
1777
+ role: string;
1778
+ scope: string[];
1779
+ constraints?: TokenConstraints;
1780
+ profileId?: string;
1781
+ issuedAt: number;
1782
+ expiresAt?: number;
1783
+ revokedAt?: number;
1784
+ createdBy?: string;
1785
+ }
1786
+
1787
+ export interface TokenProfile {
1788
+ id: string;
1789
+ name: string;
1790
+ description?: string;
1791
+ role: string;
1792
+ scope: string[];
1793
+ constraints?: TokenConstraints;
1794
+ ttlSeconds?: number;
1795
+ builtIn: boolean;
1796
+ createdAt: number;
1797
+ updatedAt: number;
1798
+ createdBy?: string;
1799
+ }
1800
+
1801
+ export interface CreateTokenProfileInput {
1802
+ id?: string;
1803
+ name: string;
1804
+ description?: string;
1805
+ role: string;
1806
+ scope: string[];
1807
+ constraints?: TokenConstraints;
1808
+ ttlSeconds?: number;
1809
+ createdBy?: string;
1810
+ }
1811
+
1812
+ export type UpdateTokenProfileInput = Partial<Omit<CreateTokenProfileInput, "id">>;
1813
+
1814
+ export interface TokenConstraints {
1815
+ agents?: string[];
1816
+ policies?: string[];
1817
+ parentAgents?: string[];
1818
+ targets?: string[];
1819
+ channels?: string[];
1820
+ orchestrators?: string[];
1821
+ hosts?: string[];
1822
+ cwd?: string;
1823
+ cwdPrefixes?: string[];
1824
+ taskIds?: string[];
1825
+ memoryScopes?: string[];
1826
+ integrationNames?: string[];
1827
+ spawnRequestIds?: string[];
1828
+ terminalAttach?: boolean;
1829
+ logsRead?: boolean;
1830
+ canDelegate?: boolean;
1831
+ }
1832
+
713
1833
  export type TokenScope =
1834
+ | "system:admin"
1835
+ | "token:read"
1836
+ | "token:write"
714
1837
  | "agent:read"
715
1838
  | "agent:write"
716
- | "message:send"
717
1839
  | "message:read"
718
- | "command:spawn"
719
- | "command:shutdown"
720
- | "command:*"
1840
+ | "message:send"
721
1841
  | "task:read"
722
1842
  | "task:write"
1843
+ | "command:read"
1844
+ | "command:write"
1845
+ | "command:*"
1846
+ | "artifact:read"
1847
+ | "artifact:write"
1848
+ | "artifact:admin"
1849
+ | "memory:read"
1850
+ | "memory:write"
1851
+ | "memory:admin"
1852
+ | "mcp:use"
1853
+ | "terminal:attach"
1854
+ | "logs:read"
1855
+ | "integration:read"
1856
+ | "integration:write"
1857
+ | "channel:read"
1858
+ | "channel:write"
1859
+ | "stats:read"
1860
+ | "health:read"
1861
+ | "events:read"
1862
+ | "command:spawn"
1863
+ | "command:shutdown"
723
1864
  | "recipe:start"
724
1865
  | "recipe:stop"
725
1866
  | "admin:*";
726
1867
 
1868
+ export interface MaintenanceJob {
1869
+ id: string;
1870
+ title: string;
1871
+ description?: string;
1872
+ intervalMs: number;
1873
+ timeoutMs: number;
1874
+ enabled: boolean;
1875
+ runOnStart: boolean;
1876
+ lastRunAt?: number;
1877
+ nextRunAt?: number;
1878
+ lastDurationMs?: number;
1879
+ lastStatus: "idle" | "running" | "succeeded" | "failed" | "disabled";
1880
+ lastError?: string;
1881
+ lastResult?: Record<string, unknown>;
1882
+ consecutiveFailures: number;
1883
+ running: boolean;
1884
+ leaseUntil?: number;
1885
+ updatedAt: number;
1886
+ }
1887
+
1888
+ export interface MaintenanceJobRun {
1889
+ id: string;
1890
+ status: "succeeded" | "failed" | "skipped";
1891
+ startedAt: number;
1892
+ finishedAt: number;
1893
+ durationMs: number;
1894
+ result?: Record<string, unknown>;
1895
+ error?: string;
1896
+ }
1897
+
727
1898
  export interface HealthCheck {
728
1899
  name: string;
729
1900
  status: "ok" | "warn" | "error";
730
1901
  detail?: string;
731
1902
  count?: number;
1903
+ subjects?: Array<{ id: string; label?: string; status?: string; detail?: string }>;
732
1904
  }
733
1905
 
734
1906
  export interface HealthReport {