@openscout/protocol 0.2.64 → 0.2.83

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.
Files changed (214) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +103 -52
  3. package/dist/a2a.d.ts +224 -0
  4. package/dist/a2a.d.ts.map +1 -0
  5. package/dist/a2a.js +225 -0
  6. package/dist/activity.d.ts +70 -0
  7. package/dist/activity.d.ts.map +1 -0
  8. package/dist/activity.js +1 -0
  9. package/dist/actors.d.ts +7 -3
  10. package/dist/actors.d.ts.map +1 -0
  11. package/dist/actors.js +15 -1
  12. package/dist/agent-broker-feed.d.ts +84 -0
  13. package/dist/agent-broker-feed.d.ts.map +1 -0
  14. package/dist/agent-broker-feed.js +1 -0
  15. package/dist/agent-identity.d.ts +23 -0
  16. package/dist/agent-identity.d.ts.map +1 -0
  17. package/dist/agent-identity.js +122 -8
  18. package/dist/agent-runs.d.ts +191 -0
  19. package/dist/agent-runs.d.ts.map +1 -0
  20. package/dist/agent-runs.js +365 -0
  21. package/dist/assigned-roles.d.ts +205 -0
  22. package/dist/assigned-roles.d.ts.map +1 -0
  23. package/dist/assigned-roles.js +228 -0
  24. package/dist/broker-routes.d.ts +40 -0
  25. package/dist/broker-routes.d.ts.map +1 -0
  26. package/dist/broker-routes.js +56 -0
  27. package/dist/budget.d.ts +65 -0
  28. package/dist/budget.d.ts.map +1 -0
  29. package/dist/budget.js +19 -0
  30. package/dist/capability-matrix.d.ts +230 -0
  31. package/dist/capability-matrix.d.ts.map +1 -0
  32. package/dist/capability-matrix.js +304 -0
  33. package/dist/channel-identity.d.ts +40 -0
  34. package/dist/channel-identity.d.ts.map +1 -0
  35. package/dist/channel-identity.js +108 -0
  36. package/dist/collaboration.d.ts +45 -16
  37. package/dist/collaboration.d.ts.map +1 -0
  38. package/dist/collaboration.js +39 -23
  39. package/dist/common.d.ts +4 -3
  40. package/dist/common.d.ts.map +1 -0
  41. package/dist/conversations.d.ts +1 -0
  42. package/dist/conversations.d.ts.map +1 -0
  43. package/dist/cursor-transport.d.ts +22 -0
  44. package/dist/cursor-transport.d.ts.map +1 -0
  45. package/dist/cursor-transport.js +10 -0
  46. package/dist/debug-attach.d.ts +29 -0
  47. package/dist/debug-attach.d.ts.map +1 -0
  48. package/dist/debug-attach.js +6 -0
  49. package/dist/deliveries.d.ts +16 -2
  50. package/dist/deliveries.d.ts.map +1 -0
  51. package/dist/durable-actions.d.ts +94 -0
  52. package/dist/durable-actions.d.ts.map +1 -0
  53. package/dist/durable-actions.js +1 -0
  54. package/dist/events.d.ts +27 -1
  55. package/dist/events.d.ts.map +1 -0
  56. package/dist/events.js +14 -1
  57. package/dist/harness-feature-support.d.ts +76 -0
  58. package/dist/harness-feature-support.d.ts.map +1 -0
  59. package/dist/harness-feature-support.js +29 -0
  60. package/dist/host-integrations.d.ts +22 -0
  61. package/dist/host-integrations.d.ts.map +1 -0
  62. package/dist/host-integrations.js +64 -0
  63. package/dist/inbox.d.ts +50 -0
  64. package/dist/inbox.d.ts.map +1 -0
  65. package/dist/inbox.js +9 -0
  66. package/dist/index.d.ts +35 -2
  67. package/dist/index.d.ts.map +1 -0
  68. package/dist/index.js +34 -2
  69. package/dist/invocations.d.ts +119 -4
  70. package/dist/invocations.d.ts.map +1 -0
  71. package/dist/invocations.js +201 -1
  72. package/dist/mesh.d.ts +98 -0
  73. package/dist/mesh.d.ts.map +1 -0
  74. package/dist/mesh.js +18 -1
  75. package/dist/messages.d.ts +3 -0
  76. package/dist/messages.d.ts.map +1 -0
  77. package/dist/native-interactions.d.ts +30 -0
  78. package/dist/native-interactions.d.ts.map +1 -0
  79. package/dist/native-interactions.js +51 -0
  80. package/dist/observed-status.d.ts +33 -0
  81. package/dist/observed-status.d.ts.map +1 -0
  82. package/dist/observed-status.js +6 -0
  83. package/dist/orchestrator-prompt.d.ts +10 -0
  84. package/dist/orchestrator-prompt.d.ts.map +1 -0
  85. package/dist/orchestrator-prompt.js +36 -0
  86. package/dist/permission-policy.d.ts +5 -0
  87. package/dist/permission-policy.d.ts.map +1 -0
  88. package/dist/permission-policy.js +15 -0
  89. package/dist/provisional-agent-names.d.ts +30 -0
  90. package/dist/provisional-agent-names.d.ts.map +1 -0
  91. package/dist/provisional-agent-names.js +224 -0
  92. package/dist/read-receipts.d.ts +12 -0
  93. package/dist/read-receipts.d.ts.map +1 -0
  94. package/dist/read-receipts.js +1 -0
  95. package/dist/relay-agent-card.d.ts +10 -0
  96. package/dist/relay-agent-card.d.ts.map +1 -0
  97. package/dist/rendezvous.d.ts +97 -0
  98. package/dist/rendezvous.d.ts.map +1 -0
  99. package/dist/rendezvous.js +35 -0
  100. package/dist/reserved-vocabulary.d.ts +21 -0
  101. package/dist/reserved-vocabulary.d.ts.map +1 -0
  102. package/dist/reserved-vocabulary.js +101 -0
  103. package/dist/route-aliases.d.ts +112 -0
  104. package/dist/route-aliases.d.ts.map +1 -0
  105. package/dist/route-aliases.js +1 -0
  106. package/dist/runtime-catalog-contract.d.ts +39 -0
  107. package/dist/runtime-catalog-contract.d.ts.map +1 -0
  108. package/dist/runtime-catalog-contract.js +17 -0
  109. package/dist/runtime-catalog.d.ts +11 -0
  110. package/dist/runtime-catalog.d.ts.map +1 -0
  111. package/dist/runtime-catalog.generated.d.ts +230 -0
  112. package/dist/runtime-catalog.generated.d.ts.map +1 -0
  113. package/dist/runtime-catalog.generated.js +299 -0
  114. package/dist/runtime-catalog.js +192 -0
  115. package/dist/runtime-execution.d.ts +161 -0
  116. package/dist/runtime-execution.d.ts.map +1 -0
  117. package/dist/runtime-execution.js +327 -0
  118. package/dist/runtime-profiles.d.ts +12 -0
  119. package/dist/runtime-profiles.d.ts.map +1 -0
  120. package/dist/runtime-profiles.js +20 -0
  121. package/dist/scout-agent-card.d.ts +10 -0
  122. package/dist/scout-agent-card.d.ts.map +1 -0
  123. package/dist/scout-composer.d.ts +27 -0
  124. package/dist/scout-composer.d.ts.map +1 -0
  125. package/dist/scout-composer.js +192 -0
  126. package/dist/scout-delivery.d.ts +99 -4
  127. package/dist/scout-delivery.d.ts.map +1 -0
  128. package/dist/scout-dispatch.d.ts +40 -3
  129. package/dist/scout-dispatch.d.ts.map +1 -0
  130. package/dist/scout-reply-context.d.ts +1 -0
  131. package/dist/scout-reply-context.d.ts.map +1 -0
  132. package/dist/session-display-state.d.ts +132 -0
  133. package/dist/session-display-state.d.ts.map +1 -0
  134. package/dist/session-display-state.js +94 -0
  135. package/dist/terminal-host-topology.d.ts +119 -0
  136. package/dist/terminal-host-topology.d.ts.map +1 -0
  137. package/dist/terminal-host-topology.js +21 -0
  138. package/dist/terminal-sessions.d.ts +142 -0
  139. package/dist/terminal-sessions.d.ts.map +1 -0
  140. package/dist/terminal-sessions.js +81 -0
  141. package/dist/terminal-surface-id.d.ts +73 -0
  142. package/dist/terminal-surface-id.d.ts.map +1 -0
  143. package/dist/terminal-surface-id.js +162 -0
  144. package/dist/terminal-workspaces.d.ts +199 -0
  145. package/dist/terminal-workspaces.d.ts.map +1 -0
  146. package/dist/terminal-workspaces.js +287 -0
  147. package/dist/thread-events.d.ts +1 -0
  148. package/dist/thread-events.d.ts.map +1 -0
  149. package/dist/time.d.ts +16 -0
  150. package/dist/time.d.ts.map +1 -0
  151. package/dist/time.js +33 -0
  152. package/dist/transports.d.ts +1 -0
  153. package/dist/transports.d.ts.map +1 -0
  154. package/package.json +37 -9
  155. package/src/a2a.ts +471 -0
  156. package/src/activity.ts +113 -0
  157. package/src/actors.ts +42 -8
  158. package/src/agent-broker-feed.ts +102 -0
  159. package/src/agent-identity.ts +143 -8
  160. package/src/agent-runs.ts +675 -0
  161. package/src/assigned-roles.ts +437 -0
  162. package/src/broker-routes.ts +62 -0
  163. package/src/budget.ts +88 -0
  164. package/src/capability-matrix.ts +648 -0
  165. package/src/channel-identity.ts +147 -0
  166. package/src/collaboration.ts +78 -48
  167. package/src/common.ts +24 -5
  168. package/src/cursor-transport.ts +34 -0
  169. package/src/debug-attach.ts +38 -0
  170. package/src/deliveries.ts +16 -1
  171. package/src/durable-actions.ts +125 -0
  172. package/src/events.ts +31 -0
  173. package/src/harness-feature-support.ts +116 -0
  174. package/src/host-integrations.ts +104 -0
  175. package/src/inbox.ts +68 -0
  176. package/src/index.ts +34 -2
  177. package/src/invocations.ts +351 -4
  178. package/src/mesh.ts +130 -0
  179. package/src/messages.ts +2 -0
  180. package/src/native-interactions.ts +100 -0
  181. package/src/observed-status.ts +90 -0
  182. package/src/orchestrator-prompt.ts +47 -0
  183. package/src/permission-policy.ts +21 -0
  184. package/src/provisional-agent-names.ts +272 -0
  185. package/src/read-receipts.ts +12 -0
  186. package/src/relay-agent-card.ts +73 -63
  187. package/src/rendezvous.ts +154 -0
  188. package/src/reserved-vocabulary.ts +135 -0
  189. package/src/route-aliases.ts +130 -0
  190. package/src/runtime-catalog-contract.ts +60 -0
  191. package/src/runtime-catalog.generated.ts +300 -0
  192. package/src/runtime-catalog.md +21 -0
  193. package/src/runtime-catalog.ts +193 -0
  194. package/src/runtime-catalog.v1.json +81 -0
  195. package/src/runtime-execution.ts +545 -0
  196. package/src/runtime-profiles.ts +37 -0
  197. package/src/scout-agent-card.ts +10 -0
  198. package/src/scout-composer.ts +249 -0
  199. package/src/scout-delivery.ts +113 -3
  200. package/src/scout-dispatch.ts +33 -2
  201. package/src/session-display-state.ts +202 -0
  202. package/src/terminal-host-topology.ts +132 -0
  203. package/src/terminal-sessions.ts +187 -0
  204. package/src/terminal-surface-id.ts +189 -0
  205. package/src/terminal-workspaces.ts +455 -0
  206. package/src/time.ts +49 -0
  207. package/dist/agent-address.d.ts +0 -1
  208. package/dist/agent-address.js +0 -1
  209. package/dist/agent-selectors.d.ts +0 -1
  210. package/dist/agent-selectors.js +0 -1
  211. package/src/agent-address.ts +0 -1
  212. package/src/agent-identity.test.ts +0 -435
  213. package/src/agent-selectors.ts +0 -1
  214. package/src/scout-agent-card.test.ts +0 -54
package/src/a2a.ts ADDED
@@ -0,0 +1,471 @@
1
+ import type { MetadataMap, ScoutId } from "./common.js";
2
+ import type { FlightRecord, InvocationRequest } from "./invocations.js";
3
+ import type { ScoutAgentCard } from "./scout-agent-card.js";
4
+
5
+ export const A2A_PROTOCOL_VERSION = "1.0";
6
+ export const A2A_JSON_RPC_CONTENT_TYPE = "application/json";
7
+ export const A2A_HTTP_JSON_CONTENT_TYPE = "application/a2a+json";
8
+
9
+ export const A2A_JSON_RPC_METHODS = {
10
+ sendMessage: "SendMessage",
11
+ sendStreamingMessage: "SendStreamingMessage",
12
+ getTask: "GetTask",
13
+ listTasks: "ListTasks",
14
+ cancelTask: "CancelTask",
15
+ subscribeToTask: "SubscribeToTask",
16
+ createTaskPushNotificationConfig: "CreateTaskPushNotificationConfig",
17
+ getTaskPushNotificationConfig: "GetTaskPushNotificationConfig",
18
+ listTaskPushNotificationConfigs: "ListTaskPushNotificationConfigs",
19
+ deleteTaskPushNotificationConfig: "DeleteTaskPushNotificationConfig",
20
+ getExtendedAgentCard: "GetExtendedAgentCard",
21
+ } as const;
22
+
23
+ export const A2A_LEGACY_JSON_RPC_METHODS = {
24
+ sendMessage: "message/send",
25
+ sendStreamingMessage: "message/stream",
26
+ getTask: "tasks/get",
27
+ listTasks: "tasks/list",
28
+ cancelTask: "tasks/cancel",
29
+ subscribeToTask: "tasks/subscribe",
30
+ getExtendedAgentCard: "agent/getAuthenticatedExtendedCard",
31
+ } as const;
32
+
33
+ export type A2AJsonRpcMethod =
34
+ typeof A2A_JSON_RPC_METHODS[keyof typeof A2A_JSON_RPC_METHODS]
35
+ | typeof A2A_LEGACY_JSON_RPC_METHODS[keyof typeof A2A_LEGACY_JSON_RPC_METHODS];
36
+
37
+ export type A2ARole = "ROLE_USER" | "ROLE_AGENT";
38
+
39
+ export type A2ATaskState =
40
+ | "TASK_STATE_SUBMITTED"
41
+ | "TASK_STATE_WORKING"
42
+ | "TASK_STATE_INPUT_REQUIRED"
43
+ | "TASK_STATE_AUTH_REQUIRED"
44
+ | "TASK_STATE_COMPLETED"
45
+ | "TASK_STATE_FAILED"
46
+ | "TASK_STATE_CANCELED"
47
+ | "TASK_STATE_REJECTED"
48
+ | "TASK_STATE_UNKNOWN";
49
+
50
+ export type A2APart =
51
+ | {
52
+ text: string;
53
+ metadata?: MetadataMap;
54
+ }
55
+ | {
56
+ file: {
57
+ name?: string;
58
+ mimeType?: string;
59
+ bytes?: string;
60
+ uri?: string;
61
+ };
62
+ metadata?: MetadataMap;
63
+ }
64
+ | {
65
+ data: unknown;
66
+ metadata?: MetadataMap;
67
+ };
68
+
69
+ export interface A2AMessage {
70
+ role: A2ARole;
71
+ parts: A2APart[];
72
+ messageId: ScoutId;
73
+ taskId?: ScoutId;
74
+ contextId?: ScoutId;
75
+ extensions?: string[];
76
+ metadata?: MetadataMap;
77
+ }
78
+
79
+ export interface A2AArtifact {
80
+ artifactId: ScoutId;
81
+ name?: string;
82
+ description?: string;
83
+ parts: A2APart[];
84
+ metadata?: MetadataMap;
85
+ }
86
+
87
+ export interface A2ATaskStatus {
88
+ state: A2ATaskState;
89
+ message?: A2AMessage;
90
+ timestamp?: string;
91
+ }
92
+
93
+ export interface A2ATask {
94
+ id: ScoutId;
95
+ contextId: ScoutId;
96
+ status: A2ATaskStatus;
97
+ artifacts?: A2AArtifact[];
98
+ history?: A2AMessage[];
99
+ metadata?: MetadataMap;
100
+ }
101
+
102
+ export interface A2ATaskStatusUpdateEvent {
103
+ taskId: ScoutId;
104
+ contextId: ScoutId;
105
+ status: A2ATaskStatus;
106
+ final?: boolean;
107
+ metadata?: MetadataMap;
108
+ }
109
+
110
+ export interface A2ATaskArtifactUpdateEvent {
111
+ taskId: ScoutId;
112
+ contextId: ScoutId;
113
+ artifact: A2AArtifact;
114
+ append?: boolean;
115
+ lastChunk?: boolean;
116
+ metadata?: MetadataMap;
117
+ }
118
+
119
+ export type A2AStreamResponse =
120
+ | { task: A2ATask }
121
+ | { message: A2AMessage }
122
+ | { statusUpdate: A2ATaskStatusUpdateEvent }
123
+ | { artifactUpdate: A2ATaskArtifactUpdateEvent };
124
+
125
+ export interface A2AAgentProvider {
126
+ organization: string;
127
+ url?: string;
128
+ }
129
+
130
+ export interface A2AAgentCapabilities {
131
+ streaming?: boolean;
132
+ pushNotifications?: boolean;
133
+ stateTransitionHistory?: boolean;
134
+ extendedAgentCard?: boolean;
135
+ extensions?: Array<{
136
+ uri: string;
137
+ description?: string;
138
+ required?: boolean;
139
+ params?: MetadataMap;
140
+ }>;
141
+ }
142
+
143
+ export interface A2AAgentSkill {
144
+ id: string;
145
+ name: string;
146
+ description: string;
147
+ tags?: string[];
148
+ examples?: string[];
149
+ inputModes?: string[];
150
+ outputModes?: string[];
151
+ }
152
+
153
+ export interface A2AAgentInterface {
154
+ url: string;
155
+ transport?: string;
156
+ protocolBinding: string;
157
+ protocolVersion?: string;
158
+ tenant?: string;
159
+ }
160
+
161
+ export interface A2AAgentCard {
162
+ protocolVersion: string;
163
+ name: string;
164
+ description: string;
165
+ url: string;
166
+ preferredTransport?: string;
167
+ provider?: A2AAgentProvider;
168
+ version?: string;
169
+ documentationUrl?: string;
170
+ capabilities: A2AAgentCapabilities;
171
+ defaultInputModes: string[];
172
+ defaultOutputModes: string[];
173
+ skills: A2AAgentSkill[];
174
+ supportedInterfaces?: A2AAgentInterface[];
175
+ securitySchemes?: Record<string, unknown>;
176
+ security?: Array<Record<string, string[]>>;
177
+ iconUrl?: string;
178
+ signatures?: unknown[];
179
+ metadata?: MetadataMap;
180
+ }
181
+
182
+ export interface A2AJsonRpcRequest<TParams = unknown> {
183
+ jsonrpc: "2.0";
184
+ id: string | number | null;
185
+ method: A2AJsonRpcMethod | string;
186
+ params?: TParams;
187
+ }
188
+
189
+ export interface A2AJsonRpcResponse<TResult = unknown> {
190
+ jsonrpc: "2.0";
191
+ id: string | number | null;
192
+ result?: TResult;
193
+ error?: A2AJsonRpcError;
194
+ }
195
+
196
+ export interface A2AJsonRpcError {
197
+ code: number;
198
+ message: string;
199
+ data?: unknown;
200
+ }
201
+
202
+ export interface A2ASendMessageParams {
203
+ message: A2AMessage;
204
+ configuration?: {
205
+ acceptedOutputModes?: string[];
206
+ historyLength?: number;
207
+ blocking?: boolean;
208
+ pushNotificationConfig?: unknown;
209
+ };
210
+ metadata?: MetadataMap;
211
+ }
212
+
213
+ export interface A2ATaskIdParams {
214
+ id?: string;
215
+ taskId?: string;
216
+ metadata?: MetadataMap;
217
+ }
218
+
219
+ export interface A2AListTasksParams {
220
+ contextId?: string;
221
+ limit?: number;
222
+ pageSize?: number;
223
+ pageToken?: string;
224
+ state?: A2ATaskState | string;
225
+ metadata?: MetadataMap;
226
+ }
227
+
228
+ export interface A2AListTasksResult {
229
+ tasks: A2ATask[];
230
+ pageSize: number;
231
+ nextPageToken?: string;
232
+ totalSize?: number;
233
+ }
234
+
235
+ export function a2aTaskStateFromFlightState(state: FlightRecord["state"]): A2ATaskState {
236
+ switch (state) {
237
+ case "queued":
238
+ case "waking":
239
+ return "TASK_STATE_SUBMITTED";
240
+ case "running":
241
+ return "TASK_STATE_WORKING";
242
+ case "waiting":
243
+ return "TASK_STATE_INPUT_REQUIRED";
244
+ case "completed":
245
+ return "TASK_STATE_COMPLETED";
246
+ case "failed":
247
+ return "TASK_STATE_FAILED";
248
+ case "cancelled":
249
+ return "TASK_STATE_CANCELED";
250
+ default: {
251
+ const exhaustive: never = state;
252
+ void exhaustive;
253
+ return "TASK_STATE_UNKNOWN";
254
+ }
255
+ }
256
+ }
257
+
258
+ export function isA2ATerminalTaskState(state: A2ATaskState): boolean {
259
+ return state === "TASK_STATE_COMPLETED"
260
+ || state === "TASK_STATE_FAILED"
261
+ || state === "TASK_STATE_CANCELED"
262
+ || state === "TASK_STATE_REJECTED";
263
+ }
264
+
265
+ export function a2aTextPart(text: string, metadata?: MetadataMap): A2APart {
266
+ return metadata && Object.keys(metadata).length > 0 ? { text, metadata } : { text };
267
+ }
268
+
269
+ export function a2aTextMessage(input: {
270
+ role: A2ARole;
271
+ text: string;
272
+ messageId: string;
273
+ contextId?: string;
274
+ taskId?: string;
275
+ metadata?: MetadataMap;
276
+ }): A2AMessage {
277
+ return {
278
+ role: input.role,
279
+ parts: [a2aTextPart(input.text)],
280
+ messageId: input.messageId,
281
+ ...(input.contextId ? { contextId: input.contextId } : {}),
282
+ ...(input.taskId ? { taskId: input.taskId } : {}),
283
+ ...(input.metadata && Object.keys(input.metadata).length > 0 ? { metadata: input.metadata } : {}),
284
+ };
285
+ }
286
+
287
+ export function a2aTextFromParts(parts: unknown): string {
288
+ if (!Array.isArray(parts)) {
289
+ return "";
290
+ }
291
+ return parts
292
+ .map((part) => {
293
+ if (!part || typeof part !== "object" || Array.isArray(part)) {
294
+ return "";
295
+ }
296
+ const record = part as Record<string, unknown>;
297
+ return typeof record.text === "string" ? record.text.trim() : "";
298
+ })
299
+ .filter(Boolean)
300
+ .join("\n\n")
301
+ .trim();
302
+ }
303
+
304
+ export function a2aTextFromMessage(message: unknown): string {
305
+ if (!message || typeof message !== "object" || Array.isArray(message)) {
306
+ return "";
307
+ }
308
+ return a2aTextFromParts((message as { parts?: unknown }).parts);
309
+ }
310
+
311
+ export function a2aContextIdForInvocation(invocation: InvocationRequest, fallback = "openscout"): string {
312
+ return invocation.conversationId
313
+ ?? (typeof invocation.metadata?.a2aContextId === "string" ? invocation.metadata.a2aContextId : undefined)
314
+ ?? fallback;
315
+ }
316
+
317
+ export function a2aTaskFromFlight(
318
+ flight: FlightRecord,
319
+ invocation?: InvocationRequest,
320
+ options: {
321
+ contextId?: string;
322
+ includeHistory?: boolean;
323
+ timestamp?: string;
324
+ } = {},
325
+ ): A2ATask {
326
+ const contextId = options.contextId ?? (invocation ? a2aContextIdForInvocation(invocation, flight.id) : flight.id);
327
+ const state = a2aTaskStateFromFlightState(flight.state);
328
+ const timestamp = options.timestamp ?? new Date(flight.completedAt ?? Date.now()).toISOString();
329
+ const statusText = flight.error ?? flight.summary;
330
+ const statusMessage = statusText
331
+ ? a2aTextMessage({
332
+ role: "ROLE_AGENT",
333
+ text: statusText,
334
+ messageId: `${flight.id}:status`,
335
+ taskId: flight.id,
336
+ contextId,
337
+ })
338
+ : undefined;
339
+ const output = typeof flight.output === "string" && flight.output.trim() ? flight.output.trim() : "";
340
+ const artifacts = output
341
+ ? [{
342
+ artifactId: `${flight.id}:output`,
343
+ name: "OpenScout output",
344
+ parts: [a2aTextPart(output)],
345
+ }]
346
+ : undefined;
347
+ const history: A2AMessage[] = [];
348
+ if (options.includeHistory && invocation?.task) {
349
+ history.push(a2aTextMessage({
350
+ role: "ROLE_USER",
351
+ text: invocation.task,
352
+ messageId: invocation.messageId ?? `${invocation.id}:message`,
353
+ contextId,
354
+ taskId: flight.id,
355
+ }));
356
+ if (output) {
357
+ history.push(a2aTextMessage({
358
+ role: "ROLE_AGENT",
359
+ text: output,
360
+ messageId: `${flight.id}:reply`,
361
+ contextId,
362
+ taskId: flight.id,
363
+ }));
364
+ }
365
+ }
366
+
367
+ return {
368
+ id: flight.id,
369
+ contextId,
370
+ status: {
371
+ state,
372
+ ...(statusMessage ? { message: statusMessage } : {}),
373
+ timestamp,
374
+ },
375
+ ...(artifacts ? { artifacts } : {}),
376
+ ...(history.length > 0 ? { history } : {}),
377
+ metadata: {
378
+ scoutInvocationId: flight.invocationId,
379
+ scoutRequesterId: flight.requesterId,
380
+ scoutTargetAgentId: flight.targetAgentId,
381
+ ...(flight.metadata ?? {}),
382
+ },
383
+ };
384
+ }
385
+
386
+ function a2aSkillId(input: string, fallback: string): string {
387
+ const normalized = input
388
+ .toLowerCase()
389
+ .replace(/[^a-z0-9._-]+/g, "-")
390
+ .replace(/^-+|-+$/g, "");
391
+ return normalized || fallback;
392
+ }
393
+
394
+ export function a2aAgentCardFromScoutCard(
395
+ card: ScoutAgentCard,
396
+ options: {
397
+ url: string;
398
+ protocolVersion?: string;
399
+ protocolBinding?: string;
400
+ transport?: string;
401
+ capabilities?: Partial<A2AAgentCapabilities>;
402
+ },
403
+ ): A2AAgentCard {
404
+ const inputModes = card.defaultInputModes?.length ? card.defaultInputModes : ["text/plain"];
405
+ const outputModes = card.defaultOutputModes?.length ? card.defaultOutputModes : ["text/plain"];
406
+ const skills = (card.skills?.length ? card.skills : [{
407
+ id: "chat",
408
+ name: "Chat",
409
+ description: `Route messages and invocations to ${card.displayName}.`,
410
+ tags: ["openscout", card.harness],
411
+ }]).map((skill, index) => ({
412
+ id: skill.id?.trim() || a2aSkillId(skill.name, `skill-${index + 1}`),
413
+ name: skill.name,
414
+ description: skill.description ?? skill.name,
415
+ ...(skill.tags?.length ? { tags: skill.tags } : {}),
416
+ ...(skill.examples?.length ? { examples: skill.examples } : {}),
417
+ inputModes,
418
+ outputModes,
419
+ }));
420
+
421
+ return {
422
+ protocolVersion: options.protocolVersion ?? A2A_PROTOCOL_VERSION,
423
+ name: card.displayName,
424
+ description: card.description ?? `OpenScout route for ${card.displayName}.`,
425
+ url: options.url,
426
+ preferredTransport: options.transport ?? "JSONRPC",
427
+ ...(card.provider?.organization ? {
428
+ provider: {
429
+ organization: card.provider.organization,
430
+ ...(card.provider.url ? { url: card.provider.url } : {}),
431
+ },
432
+ } : {}),
433
+ ...(card.version ? { version: card.version } : {}),
434
+ ...(card.documentationUrl ? { documentationUrl: card.documentationUrl } : {}),
435
+ capabilities: {
436
+ streaming: false,
437
+ pushNotifications: false,
438
+ stateTransitionHistory: true,
439
+ extendedAgentCard: true,
440
+ ...options.capabilities,
441
+ },
442
+ defaultInputModes: inputModes,
443
+ defaultOutputModes: outputModes,
444
+ skills,
445
+ supportedInterfaces: [
446
+ {
447
+ url: options.url,
448
+ protocolBinding: options.protocolBinding ?? "JSONRPC",
449
+ protocolVersion: options.protocolVersion ?? A2A_PROTOCOL_VERSION,
450
+ transport: options.transport ?? "http",
451
+ tenant: card.agentId,
452
+ },
453
+ ],
454
+ ...(card.securitySchemes ? { securitySchemes: card.securitySchemes } : {}),
455
+ ...(card.securityRequirements ? {
456
+ security: card.securityRequirements.map((requirement) => Object.fromEntries(
457
+ requirement.map((scheme) => [scheme, [] as string[]]),
458
+ )),
459
+ } : {}),
460
+ metadata: {
461
+ scoutAgentId: card.agentId,
462
+ scoutDefinitionId: card.definitionId,
463
+ scoutHandle: card.handle,
464
+ scoutSelector: card.selector,
465
+ scoutHarness: card.harness,
466
+ scoutTransport: card.transport,
467
+ brokerRegistered: card.brokerRegistered,
468
+ ...(card.metadata ?? {}),
469
+ },
470
+ };
471
+ }
@@ -0,0 +1,113 @@
1
+ import type { MetadataMap, ScoutId } from "./common.js";
2
+ import type {
3
+ ObservedActivity,
4
+ ObservedStatusPhase,
5
+ ObservedStatusProjection,
6
+ } from "./observed-status.js";
7
+
8
+ export type ScoutActivityAltitude = "shell" | "list" | "focused";
9
+
10
+ export type ScoutActivityMotionLevel =
11
+ | "none"
12
+ | "low"
13
+ | "medium"
14
+ | "high"
15
+ | "blocked";
16
+
17
+ export type ScoutActivitySeverity = "info" | "warning" | "critical";
18
+
19
+ export type ScoutActivityEventKind =
20
+ | "message"
21
+ | "invocation"
22
+ | "flight"
23
+ | "work_item"
24
+ | "question"
25
+ | "approval"
26
+ | "permission"
27
+ | "session"
28
+ | "tool"
29
+ | "edit"
30
+ | "result"
31
+ | "tail"
32
+ | "error";
33
+
34
+ export type ScoutActivitySourceKind =
35
+ | "broker_record"
36
+ | "message"
37
+ | "invocation"
38
+ | "flight"
39
+ | "collaboration_record"
40
+ | "work_item"
41
+ | "question"
42
+ | "endpoint"
43
+ | "tail_event"
44
+ | "session_projection"
45
+ | "observed_status";
46
+
47
+ export interface ScoutActivitySourceRef {
48
+ kind: ScoutActivitySourceKind;
49
+ refId: ScoutId | string;
50
+ label?: string;
51
+ }
52
+
53
+ export interface ScoutActivityEvent {
54
+ id: ScoutId | string;
55
+ kind: ScoutActivityEventKind;
56
+ agentId?: ScoutId;
57
+ sessionId?: ScoutId;
58
+ conversationId?: ScoutId;
59
+ title?: string;
60
+ summary: string;
61
+ at: number;
62
+ severity?: ScoutActivitySeverity;
63
+ source: ScoutActivitySourceRef;
64
+ metadata?: MetadataMap;
65
+ }
66
+
67
+ export interface ScoutActivityWorkSummary {
68
+ title?: string;
69
+ summary?: string;
70
+ source?: ScoutActivitySourceRef;
71
+ metadata?: MetadataMap;
72
+ }
73
+
74
+ export interface ScoutAgentActivitySummary {
75
+ agentId: ScoutId;
76
+ displayName?: string;
77
+ phase: ObservedStatusPhase;
78
+ activity: ObservedActivity;
79
+ motion: ScoutActivityMotionLevel;
80
+ needsYou: boolean;
81
+ currentWork?: ScoutActivityWorkSummary;
82
+ latestEvent?: ScoutActivityEvent;
83
+ updatedAt: number;
84
+ staleAt?: number;
85
+ status?: ObservedStatusProjection;
86
+ metadata?: MetadataMap;
87
+ }
88
+
89
+ export interface ScoutActivityDigest {
90
+ label: string;
91
+ summary: string;
92
+ motion: ScoutActivityMotionLevel;
93
+ updatedAt: number;
94
+ needsYouCount: number;
95
+ workingCount: number;
96
+ latestEvent?: ScoutActivityEvent;
97
+ metadata?: MetadataMap;
98
+ }
99
+
100
+ export interface ScoutFleetActivitySummary {
101
+ totalAgents: number;
102
+ workingCount: number;
103
+ needsYouCount: number;
104
+ activeCount: number;
105
+ quietCount: number;
106
+ updatedAt: number;
107
+ agents: ScoutAgentActivitySummary[];
108
+ currentlyWorking: ScoutAgentActivitySummary[];
109
+ needsYou: ScoutAgentActivitySummary[];
110
+ latestEvents: ScoutActivityEvent[];
111
+ digest: ScoutActivityDigest;
112
+ metadata?: MetadataMap;
113
+ }
package/src/actors.ts CHANGED
@@ -2,6 +2,7 @@ import type {
2
2
  ActorKind,
3
3
  AdvertiseScope,
4
4
  AgentState,
5
+ DeliveryTransport,
5
6
  MetadataMap,
6
7
  ScoutId,
7
8
  } from "./common.js";
@@ -26,14 +27,46 @@ export type AgentCapability =
26
27
  | "review"
27
28
  | "execute";
28
29
 
29
- export type AgentHarness =
30
- | "codex"
31
- | "claude"
32
- | "native"
33
- | "worker"
34
- | "bridge"
30
+ export type AgentEndpointTransport = Extract<
31
+ DeliveryTransport,
32
+ | "local_socket"
35
33
  | "http"
36
- | "pi";
34
+ | "websocket"
35
+ | "pairing_bridge"
36
+ | "claude_channel"
37
+ | "claude_stream_json"
38
+ | "codex_app_server"
39
+ | "codex_exec"
40
+ | "claude_resume"
41
+ | "pi_rpc"
42
+ | "grok_acp"
43
+ | "kimi_acp"
44
+ | "cursor_acp"
45
+ | "opencode_acp"
46
+ | "tmux"
47
+ | "cursor_exec"
48
+ | "cursor_cli_text"
49
+ | "cursor_cli_stream_json"
50
+ | "cursor_sdk_local"
51
+ >;
52
+
53
+ export const AGENT_HARNESSES = [
54
+ "codex",
55
+ "claude",
56
+ "grok",
57
+ "grok-acp",
58
+ "kimi",
59
+ "flue",
60
+ "cursor",
61
+ "opencode",
62
+ "native",
63
+ "worker",
64
+ "bridge",
65
+ "http",
66
+ "pi",
67
+ ] as const;
68
+
69
+ export type AgentHarness = typeof AGENT_HARNESSES[number];
37
70
 
38
71
  export type WakePolicy = "manual" | "on_demand" | "keep_warm";
39
72
 
@@ -75,8 +108,9 @@ export interface AgentEndpoint {
75
108
  agentId: ScoutId;
76
109
  nodeId: ScoutId;
77
110
  harness: AgentHarness;
78
- transport: "local_socket" | "http" | "websocket" | "pairing_bridge" | "claude_stream_json" | "codex_app_server" | "codex_exec" | "claude_resume" | "tmux";
111
+ transport: AgentEndpointTransport;
79
112
  state: AgentState;
113
+ preferred?: boolean;
80
114
  address?: string;
81
115
  sessionId?: string;
82
116
  pane?: string;