@ouro.bot/cli 0.1.0-alpha.653 → 0.1.0-alpha.654

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 (37) hide show
  1. package/changelog.json +7 -0
  2. package/dist/a2a/card.js +56 -0
  3. package/dist/a2a/client.js +143 -0
  4. package/dist/a2a/config.js +50 -0
  5. package/dist/a2a/onboarding.js +111 -0
  6. package/dist/a2a/server.js +498 -0
  7. package/dist/a2a/task-store.js +69 -0
  8. package/dist/a2a/types.js +3 -0
  9. package/dist/commerce/store.js +755 -0
  10. package/dist/commerce/types.js +3 -0
  11. package/dist/heart/daemon/cli-exec.js +118 -3
  12. package/dist/heart/daemon/cli-help.js +14 -2
  13. package/dist/heart/daemon/cli-parse.js +88 -4
  14. package/dist/heart/daemon/daemon.js +2 -1
  15. package/dist/heart/daemon/process-manager.js +2 -1
  16. package/dist/heart/daemon/runtime-logging.js +1 -1
  17. package/dist/heart/daemon/sense-manager.js +71 -15
  18. package/dist/heart/identity.js +4 -1
  19. package/dist/heart/sense-truth.js +2 -0
  20. package/dist/heart/turn-context.js +6 -0
  21. package/dist/mind/friends/channel.js +10 -1
  22. package/dist/mind/friends/resolver.js +13 -2
  23. package/dist/mind/friends/store-file.js +13 -0
  24. package/dist/mind/friends/types.js +1 -1
  25. package/dist/mind/prompt.js +11 -0
  26. package/dist/repertoire/guardrails.js +25 -2
  27. package/dist/repertoire/tools-a2a.js +283 -0
  28. package/dist/repertoire/tools-base.js +4 -0
  29. package/dist/repertoire/tools-commerce.js +253 -0
  30. package/dist/repertoire/tools-flight.js +68 -5
  31. package/dist/repertoire/tools-stripe.js +49 -7
  32. package/dist/repertoire/tools.js +50 -2
  33. package/dist/senses/a2a-entry.js +78 -0
  34. package/dist/senses/pipeline.js +13 -0
  35. package/dist/senses/shared-turn.js +30 -5
  36. package/package.json +1 -1
  37. package/skills/agent-commerce.md +17 -10
@@ -0,0 +1,498 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.startA2AServer = startA2AServer;
37
+ const http = __importStar(require("node:http"));
38
+ const node_crypto_1 = require("node:crypto");
39
+ const identity_1 = require("../heart/identity");
40
+ const runtime_1 = require("../nerves/runtime");
41
+ const shared_turn_1 = require("../senses/shared-turn");
42
+ const card_1 = require("./card");
43
+ const config_1 = require("./config");
44
+ const task_store_1 = require("./task-store");
45
+ const MAX_A2A_REQUEST_BYTES = 128 * 1024;
46
+ const MAX_A2A_MESSAGE_TEXT_CHARS = 16_000;
47
+ class A2ARequestError extends Error {
48
+ status;
49
+ code;
50
+ constructor(status, code, message) {
51
+ super(message);
52
+ this.status = status;
53
+ this.code = code;
54
+ }
55
+ }
56
+ function jsonResponse(id, result) {
57
+ return { jsonrpc: "2.0", id: id ?? null, result };
58
+ }
59
+ function errorResponse(id, code, message) {
60
+ return { jsonrpc: "2.0", id: id ?? null, error: { code, message } };
61
+ }
62
+ async function readBody(req) {
63
+ const chunks = [];
64
+ let total = 0;
65
+ for await (const chunk of req) {
66
+ /* v8 ignore next -- Node HTTP request bodies arrive as Buffers in this runtime; string chunks are defensive stream compatibility @preserve */
67
+ const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
68
+ total += buffer.byteLength;
69
+ if (total > MAX_A2A_REQUEST_BYTES) {
70
+ throw new A2ARequestError(413, -32000, `A2A request body exceeds ${MAX_A2A_REQUEST_BYTES} bytes`);
71
+ }
72
+ chunks.push(buffer);
73
+ }
74
+ return Buffer.concat(chunks).toString("utf-8");
75
+ }
76
+ function writeJson(res, status, payload) {
77
+ const body = `${JSON.stringify(payload, null, 2)}\n`;
78
+ res.writeHead(status, {
79
+ "content-type": "application/json; charset=utf-8",
80
+ "content-length": Buffer.byteLength(body),
81
+ });
82
+ res.end(body);
83
+ }
84
+ function textFromMessage(message) {
85
+ if (!message || typeof message !== "object")
86
+ return "";
87
+ const parts = message.parts;
88
+ if (!Array.isArray(parts))
89
+ return "";
90
+ return parts
91
+ .map((part) => {
92
+ if (!part || typeof part !== "object")
93
+ return "";
94
+ const text = part.text;
95
+ return typeof text === "string" ? text : "";
96
+ })
97
+ .filter(Boolean)
98
+ .join("\n")
99
+ .trim();
100
+ }
101
+ function messageFromParams(params) {
102
+ if (!params || typeof params !== "object")
103
+ return null;
104
+ const message = params.message;
105
+ if (!message || typeof message !== "object")
106
+ return null;
107
+ return message;
108
+ }
109
+ function metadataRecord(value) {
110
+ /* v8 ignore next -- protocol callers pass JSON-RPC param/message objects; this guard keeps malformed direct input inert @preserve */
111
+ if (!value || typeof value !== "object")
112
+ return undefined;
113
+ /* v8 ignore next -- JSON-RPC params/messages are objects in supported calls; array guard protects malformed direct input @preserve */
114
+ if (Array.isArray(value))
115
+ return undefined;
116
+ const metadata = value.metadata;
117
+ return metadata && typeof metadata === "object" && !Array.isArray(metadata) ? metadata : undefined;
118
+ }
119
+ function metadataStringFromRecord(metadata, key) {
120
+ const value = metadata?.[key];
121
+ return typeof value === "string" && value.trim() ? value.trim() : undefined;
122
+ }
123
+ function metadataString(message, key) {
124
+ return metadataStringFromRecord(metadataRecord(message), key);
125
+ }
126
+ function headerString(req, key) {
127
+ const value = req.headers[key];
128
+ /* v8 ignore next -- Node lower-cases singular request headers here; array values are defensive compatibility @preserve */
129
+ if (Array.isArray(value))
130
+ return value[0];
131
+ return typeof value === "string" && value.trim() ? value.trim() : undefined;
132
+ }
133
+ /* v8 ignore start -- default runner crosses into the full live agent pipeline; shared-turn covers that pipeline and server tests inject a deterministic runner @preserve */
134
+ function storageKeyFor(peerExternalId) {
135
+ return `a2a-${(0, node_crypto_1.createHash)("sha256").update(peerExternalId).digest("hex").slice(0, 24)}`;
136
+ }
137
+ async function defaultTurnRunner(input) {
138
+ const result = await (0, shared_turn_1.runSenseTurn)({
139
+ agentName: input.agentName,
140
+ channel: "a2a",
141
+ friendId: storageKeyFor(input.peerAgentId),
142
+ sessionKey: input.sessionKey,
143
+ userMessage: input.message,
144
+ latencyMode: "standard",
145
+ identity: {
146
+ provider: "a2a-agent",
147
+ externalId: input.peerAgentId,
148
+ displayName: input.peerName,
149
+ },
150
+ });
151
+ return { response: result.response };
152
+ }
153
+ /* v8 ignore stop */
154
+ function accessTokenHash(accessToken) {
155
+ return (0, node_crypto_1.createHash)("sha256").update(accessToken).digest("hex");
156
+ }
157
+ function accessTokenScope(accessToken) {
158
+ return `a2a-task-token:${accessTokenHash(accessToken)}`;
159
+ }
160
+ function untrustedTurnPeerExternalId() {
161
+ return "unauthenticated-a2a-peer";
162
+ }
163
+ function senderHintFromMessage(req, inbound) {
164
+ const idHint = metadataString(inbound, "senderAgentId")
165
+ ?? metadataString(inbound, "senderCardUrl")
166
+ ?? metadataString(inbound, "agentId")
167
+ ?? metadataString(inbound, "cardUrl")
168
+ ?? headerString(req, "x-a2a-agent-id");
169
+ const name = metadataString(inbound, "senderName")
170
+ ?? metadataString(inbound, "agentName")
171
+ ?? headerString(req, "x-a2a-agent-name")
172
+ ?? idHint
173
+ ?? "Unauthenticated A2A peer";
174
+ return { idHint, name };
175
+ }
176
+ function isTerminalTaskState(state) {
177
+ return state === "TASK_STATE_COMPLETED"
178
+ || state === "TASK_STATE_FAILED"
179
+ || state === "TASK_STATE_CANCELED"
180
+ || state === "TASK_STATE_REJECTED"
181
+ || state === "completed"
182
+ || state === "failed"
183
+ || state === "canceled"
184
+ || state === "rejected";
185
+ }
186
+ function accessTokenFromParams(params) {
187
+ /* v8 ignore next -- GetTask/CancelTask validate object params before token extraction; this keeps direct helper use defensive @preserve */
188
+ if (!params || typeof params !== "object" || Array.isArray(params))
189
+ return undefined;
190
+ const record = params;
191
+ const direct = record.accessToken ?? record.access_token;
192
+ if (typeof direct === "string" && direct.trim())
193
+ return direct.trim();
194
+ return metadataStringFromRecord(metadataRecord(params), "accessToken");
195
+ }
196
+ function taskA2AMetadata(task) {
197
+ const a2a = task.metadata?.a2a;
198
+ /* v8 ignore next -- server-created tasks always carry object auth metadata; fallback protects legacy/corrupt task files @preserve */
199
+ if (!a2a || typeof a2a !== "object" || Array.isArray(a2a))
200
+ return {};
201
+ return a2a;
202
+ }
203
+ function publicMessage(message, style) {
204
+ const parts = message.parts
205
+ .filter((part) => part && typeof part === "object" && typeof part.text === "string")
206
+ .map((part) => style === "legacy" ? { ...part, kind: part.kind ?? "text" } : part);
207
+ if (style === "latest")
208
+ return { ...message, kind: "message", parts };
209
+ return {
210
+ ...message,
211
+ kind: "message",
212
+ role: message.role === "ROLE_AGENT" ? "agent" : message.role === "ROLE_USER" ? "user" : message.role,
213
+ parts,
214
+ };
215
+ }
216
+ function legacyTaskState(state) {
217
+ if (state === "TASK_STATE_SUBMITTED")
218
+ return "submitted";
219
+ if (state === "TASK_STATE_WORKING")
220
+ return "working";
221
+ if (state === "TASK_STATE_COMPLETED")
222
+ return "completed";
223
+ if (state === "TASK_STATE_FAILED")
224
+ return "failed";
225
+ if (state === "TASK_STATE_CANCELED")
226
+ return "canceled";
227
+ if (state === "TASK_STATE_REJECTED")
228
+ return "rejected";
229
+ if (state === "TASK_STATE_AUTH_REQUIRED")
230
+ return "auth-required";
231
+ if (state === "TASK_STATE_INPUT_REQUIRED")
232
+ return "input-required";
233
+ return state;
234
+ }
235
+ function publicTask(task, accessToken, style, includeAccessToken) {
236
+ const a2a = taskA2AMetadata(task);
237
+ const { accessTokenHash: _accessTokenHash, taskScopeHash: _taskScopeHash, ...safeA2A } = a2a;
238
+ const statusMessage = task.status.message ? publicMessage(task.status.message, style) : undefined;
239
+ return {
240
+ ...task,
241
+ kind: task.kind ?? "task",
242
+ status: {
243
+ ...task.status,
244
+ state: style === "legacy" ? legacyTaskState(task.status.state) : task.status.state,
245
+ ...(statusMessage ? { message: statusMessage } : {}),
246
+ },
247
+ history: task.history.map((message) => publicMessage(message, style)),
248
+ ...(task.artifacts ? {
249
+ artifacts: task.artifacts.map((artifact) => ({
250
+ ...artifact,
251
+ parts: style === "legacy"
252
+ ? artifact.parts.map((part) => ({ ...part, kind: part.kind ?? "text" }))
253
+ : artifact.parts,
254
+ })),
255
+ } : {}),
256
+ metadata: {
257
+ ...task.metadata,
258
+ a2a: {
259
+ ...safeA2A,
260
+ ...(includeAccessToken ? { accessToken } : {}),
261
+ },
262
+ },
263
+ };
264
+ }
265
+ function taskAuthorized(task, accessToken) {
266
+ const a2a = taskA2AMetadata(task);
267
+ return a2a.accessTokenHash === accessTokenHash(accessToken);
268
+ }
269
+ function taskFor(input) {
270
+ const now = new Date().toISOString();
271
+ const history = [...(input.previousTask?.history ?? []), input.inbound];
272
+ const previousA2A = input.previousTask ? taskA2AMetadata(input.previousTask) : {};
273
+ const responseMessage = input.response
274
+ ? {
275
+ kind: "message",
276
+ role: "ROLE_AGENT",
277
+ taskId: input.taskId,
278
+ contextId: input.contextId,
279
+ messageId: (0, node_crypto_1.randomUUID)(),
280
+ parts: [{ text: input.response }],
281
+ }
282
+ : undefined;
283
+ if (responseMessage)
284
+ history.push(responseMessage);
285
+ return {
286
+ kind: "task",
287
+ id: input.taskId,
288
+ contextId: input.contextId,
289
+ status: {
290
+ state: input.state,
291
+ timestamp: now,
292
+ ...(responseMessage ? { message: responseMessage } : {}),
293
+ },
294
+ history,
295
+ metadata: {
296
+ ...input.previousTask?.metadata,
297
+ a2a: {
298
+ ...previousA2A,
299
+ accessTokenHash: accessTokenHash(input.accessToken),
300
+ ...(input.clientTaskId ? { clientTaskId: input.clientTaskId } : {}),
301
+ },
302
+ },
303
+ ...(responseMessage ? {
304
+ artifacts: [{
305
+ artifactId: `artifact-${input.taskId}`,
306
+ name: "response",
307
+ parts: responseMessage.parts,
308
+ }],
309
+ } : {}),
310
+ };
311
+ }
312
+ async function startA2AServer(options) {
313
+ const host = options.host ?? config_1.A2A_DEFAULT_HOST;
314
+ /* v8 ignore next -- daemon-managed A2A owns the default-port path; protocol tests bind port 0 to avoid collisions @preserve */
315
+ const port = options.port ?? (0, config_1.defaultA2APort)(options.agentName);
316
+ const a2aPath = (0, config_1.normalizeA2APath)(options.path);
317
+ /* v8 ignore next -- foreground CLI/default daemon paths own the ambient agent-root fallback; protocol tests inject an isolated root @preserve */
318
+ const taskStore = new task_store_1.FileA2ATaskStore(options.agentRoot ?? (0, identity_1.getAgentRoot)(options.agentName));
319
+ /* v8 ignore next -- default runner crosses into the full live agent pipeline; shared-turn covers that pipeline and server tests inject a deterministic runner @preserve */
320
+ const turnRunner = options.turnRunner ?? defaultTurnRunner;
321
+ let publicBaseUrl = options.baseUrl;
322
+ const server = http.createServer(async (req, res) => {
323
+ /* v8 ignore next -- Node always supplies url/host for accepted HTTP requests; fallback keeps malformed local calls safe @preserve */
324
+ const requestUrl = new URL(req.url ?? "/", `http://${req.headers.host ?? `${host}:${port}`}`);
325
+ /* v8 ignore next -- host fallback is defensive for malformed local requests; publicBaseUrl/default host branches are covered @preserve */
326
+ const currentBaseUrl = publicBaseUrl ?? `http://${req.headers.host ?? `${host}:${port}`}`;
327
+ if (req.method === "GET" && (requestUrl.pathname === "/.well-known/agent-card.json" || requestUrl.pathname === "/agent-card.json")) {
328
+ writeJson(res, 200, (0, card_1.buildA2AAgentCard)({ agentName: options.agentName, baseUrl: currentBaseUrl, path: a2aPath }));
329
+ return;
330
+ }
331
+ if (req.method !== "POST" || requestUrl.pathname !== a2aPath) {
332
+ writeJson(res, 404, { error: "not found" });
333
+ return;
334
+ }
335
+ let rpc;
336
+ try {
337
+ const rawBody = await readBody(req);
338
+ rpc = JSON.parse(rawBody);
339
+ }
340
+ catch (error) {
341
+ if (error instanceof A2ARequestError) {
342
+ writeJson(res, error.status, errorResponse(null, error.code, error.message));
343
+ return;
344
+ }
345
+ writeJson(res, 400, errorResponse(null, -32700, "invalid JSON"));
346
+ return;
347
+ }
348
+ try {
349
+ if (rpc.method === "SendMessage" || rpc.method === "message/send") {
350
+ const responseStyle = rpc.method === "message/send" ? "legacy" : "latest";
351
+ const parsedInbound = messageFromParams(rpc.params);
352
+ const inbound = parsedInbound ? { ...parsedInbound, kind: parsedInbound.kind ?? "message" } : null;
353
+ const text = textFromMessage(inbound);
354
+ if (!inbound || !text) {
355
+ writeJson(res, 200, errorResponse(rpc.id, -32602, "SendMessage requires a text message"));
356
+ return;
357
+ }
358
+ if (text.length > MAX_A2A_MESSAGE_TEXT_CHARS) {
359
+ writeJson(res, 200, errorResponse(rpc.id, -32602, `SendMessage text exceeds ${MAX_A2A_MESSAGE_TEXT_CHARS} characters`));
360
+ return;
361
+ }
362
+ const senderHint = senderHintFromMessage(req, inbound);
363
+ const peerAgentId = untrustedTurnPeerExternalId();
364
+ const peerName = senderHint.name;
365
+ const continuationToken = accessTokenFromParams(rpc.params);
366
+ const continuationTask = inbound.taskId && continuationToken
367
+ ? taskStore.get(inbound.taskId, accessTokenScope(continuationToken))
368
+ : null;
369
+ if (inbound.taskId && continuationToken && (!continuationTask || !taskAuthorized(continuationTask, continuationToken))) {
370
+ writeJson(res, 200, errorResponse(rpc.id, -32001, "task not found"));
371
+ return;
372
+ }
373
+ if (continuationTask && isTerminalTaskState(continuationTask.status.state)) {
374
+ writeJson(res, 200, errorResponse(rpc.id, -32002, "task is terminal; start a new task"));
375
+ return;
376
+ }
377
+ const contextId = inbound.contextId ?? continuationTask?.contextId ?? "default";
378
+ const taskId = continuationTask?.id ?? (0, node_crypto_1.randomUUID)();
379
+ const accessToken = continuationToken && continuationTask ? continuationToken : (0, node_crypto_1.randomUUID)();
380
+ const tokenScope = accessTokenScope(accessToken);
381
+ const clientTaskId = continuationTask ? taskA2AMetadata(continuationTask).clientTaskId : inbound.taskId;
382
+ taskStore.put(taskFor({ taskId, accessToken, contextId, inbound, state: "TASK_STATE_WORKING", clientTaskId, previousTask: continuationTask ?? undefined }), tokenScope);
383
+ const turn = await turnRunner({
384
+ agentName: options.agentName,
385
+ peerAgentId,
386
+ peerName,
387
+ sessionKey: contextId,
388
+ message: text,
389
+ });
390
+ const task = taskFor({ taskId, accessToken, contextId, inbound, state: "TASK_STATE_COMPLETED", response: turn.response, clientTaskId, previousTask: continuationTask ?? undefined });
391
+ taskStore.put(task, tokenScope);
392
+ writeJson(res, 200, jsonResponse(rpc.id, publicTask(task, accessToken, responseStyle, true)));
393
+ return;
394
+ }
395
+ if (rpc.method === "GetTask" || rpc.method === "tasks/get") {
396
+ const responseStyle = rpc.method === "tasks/get" ? "legacy" : "latest";
397
+ const taskId = rpc.params && typeof rpc.params === "object"
398
+ ? rpc.params.id
399
+ : undefined;
400
+ if (typeof taskId !== "string" || !taskId.trim()) {
401
+ writeJson(res, 200, errorResponse(rpc.id, -32602, "GetTask requires id"));
402
+ return;
403
+ }
404
+ const accessToken = accessTokenFromParams(rpc.params);
405
+ if (!accessToken) {
406
+ writeJson(res, 200, errorResponse(rpc.id, -32602, "GetTask requires accessToken"));
407
+ return;
408
+ }
409
+ const task = taskStore.get(taskId, accessTokenScope(accessToken));
410
+ writeJson(res, 200, task && taskAuthorized(task, accessToken)
411
+ ? jsonResponse(rpc.id, publicTask(task, accessToken, responseStyle, false))
412
+ : errorResponse(rpc.id, -32001, "task not found"));
413
+ return;
414
+ }
415
+ if (rpc.method === "CancelTask" || rpc.method === "tasks/cancel") {
416
+ const responseStyle = rpc.method === "tasks/cancel" ? "legacy" : "latest";
417
+ const taskId = rpc.params && typeof rpc.params === "object"
418
+ ? rpc.params.id
419
+ : undefined;
420
+ if (typeof taskId !== "string" || !taskId.trim()) {
421
+ writeJson(res, 200, errorResponse(rpc.id, -32602, "CancelTask requires id"));
422
+ return;
423
+ }
424
+ const accessToken = accessTokenFromParams(rpc.params);
425
+ if (!accessToken) {
426
+ writeJson(res, 200, errorResponse(rpc.id, -32602, "CancelTask requires accessToken"));
427
+ return;
428
+ }
429
+ const tokenScope = accessTokenScope(accessToken);
430
+ const task = taskStore.get(taskId, tokenScope);
431
+ if (!task || !taskAuthorized(task, accessToken)) {
432
+ writeJson(res, 200, errorResponse(rpc.id, -32001, "task not found"));
433
+ return;
434
+ }
435
+ const canceled = {
436
+ ...task,
437
+ status: { state: "TASK_STATE_CANCELED", timestamp: new Date().toISOString() },
438
+ };
439
+ taskStore.put(canceled, tokenScope);
440
+ writeJson(res, 200, jsonResponse(rpc.id, publicTask(canceled, accessToken, responseStyle, false)));
441
+ return;
442
+ }
443
+ writeJson(res, 200, errorResponse(rpc.id, -32601, `unknown method: ${rpc.method}`));
444
+ }
445
+ catch (error) {
446
+ const message = error instanceof Error ? error.message : /* v8 ignore next -- defensive non-Error throw branch @preserve */ String(error);
447
+ writeJson(res, 200, errorResponse(rpc.id, -32000, message));
448
+ }
449
+ });
450
+ await new Promise((resolve, reject) => {
451
+ const onError = (error) => {
452
+ server.off("listening", onListening);
453
+ reject(error);
454
+ };
455
+ const onListening = () => {
456
+ server.off("error", onError);
457
+ resolve();
458
+ };
459
+ server.once("error", onError);
460
+ server.once("listening", onListening);
461
+ server.listen(port, host);
462
+ });
463
+ const address = server.address();
464
+ /* v8 ignore next -- server.address() is an address object after successful listen on TCP @preserve */
465
+ const actualPort = typeof address === "object" && address ? address.port : port;
466
+ const localBaseUrl = `http://${host}:${actualPort}`;
467
+ publicBaseUrl = publicBaseUrl ?? localBaseUrl;
468
+ const endpointUrl = new URL(publicBaseUrl);
469
+ endpointUrl.pathname = a2aPath;
470
+ endpointUrl.search = "";
471
+ endpointUrl.hash = "";
472
+ (0, runtime_1.emitNervesEvent)({
473
+ component: "channels",
474
+ event: "channel.a2a_server_started",
475
+ message: "A2A sense server started",
476
+ meta: { agentName: options.agentName, url: publicBaseUrl, endpoint: endpointUrl.toString() },
477
+ });
478
+ return {
479
+ server,
480
+ url: publicBaseUrl,
481
+ endpointUrl: endpointUrl.toString(),
482
+ close: () => new Promise((resolve, reject) => {
483
+ server.close((error) => {
484
+ if (error) {
485
+ reject(error);
486
+ return;
487
+ }
488
+ (0, runtime_1.emitNervesEvent)({
489
+ component: "channels",
490
+ event: "channel.a2a_server_stopped",
491
+ message: "A2A sense server stopped",
492
+ meta: { agentName: options.agentName },
493
+ });
494
+ resolve();
495
+ });
496
+ }),
497
+ };
498
+ }
@@ -0,0 +1,69 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.FileA2ATaskStore = void 0;
37
+ const fs = __importStar(require("node:fs"));
38
+ const path = __importStar(require("node:path"));
39
+ const node_crypto_1 = require("node:crypto");
40
+ const runtime_1 = require("../nerves/runtime");
41
+ function taskFileName(taskId, ownerScope) {
42
+ return `${(0, node_crypto_1.createHash)("sha256").update(`${ownerScope}\n${taskId}`).digest("hex")}.json`;
43
+ }
44
+ class FileA2ATaskStore {
45
+ dir;
46
+ constructor(agentRoot) {
47
+ this.dir = path.join(agentRoot, "state", "a2a", "tasks");
48
+ fs.mkdirSync(this.dir, { recursive: true });
49
+ (0, runtime_1.emitNervesEvent)({
50
+ component: "channels",
51
+ event: "channel.a2a_task_store_init",
52
+ message: "initialized A2A task store",
53
+ meta: { dir: this.dir },
54
+ });
55
+ }
56
+ put(task, ownerScope = "legacy") {
57
+ fs.writeFileSync(path.join(this.dir, taskFileName(task.id, ownerScope)), `${JSON.stringify(task, null, 2)}\n`, "utf-8");
58
+ }
59
+ get(taskId, ownerScope = "legacy") {
60
+ try {
61
+ const raw = fs.readFileSync(path.join(this.dir, taskFileName(taskId, ownerScope)), "utf-8");
62
+ return JSON.parse(raw);
63
+ }
64
+ catch {
65
+ return null;
66
+ }
67
+ }
68
+ }
69
+ exports.FileA2ATaskStore = FileA2ATaskStore;
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ /* v8 ignore file -- type-only A2A protocol definitions */
3
+ Object.defineProperty(exports, "__esModule", { value: true });