@artinet/sdk 0.6.0 → 0.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -3,7 +3,7 @@
3
3
  <a href="https://www.npmjs.com/package/@artinet/sdk"><img src="https://img.shields.io/npm/v/@artinet/sdk?color=black" alt="Version"></a>
4
4
  <a href="https://www.npmjs.com/package/@artinet/sdk"><img src="https://img.shields.io/npm/dt/@artinet/sdk?color=black" alt="Downloads"></a>
5
5
  <a><img src="https://img.shields.io/badge/License-Apache_2.0-black.svg" alt="License"></a>
6
- <a href="https://reddit.com/r/artinet"><img src="https://img.shields.io/reddit/subreddit-subscribers/theartinet?label=reddit&style=flat&color=black" alt="Subreddit"></a>
6
+ <a href="https://reddit.com/r/theartinet"><img src="https://img.shields.io/reddit/subreddit-subscribers/theartinet?label=reddit&style=flat&color=black" alt="Subreddit"></a>
7
7
  <a><img src="https://img.shields.io/github/stars/the-artinet-project/artinet-sdk?style=social&color=black" alt="Github"></a>
8
8
  <a href="https://snyk.io/test/npm/@artinet/sdk"><img src="https://snyk.io/test/npm/@artinet/sdk/badge.svg" alt="Known Vulnerabilities"></a>
9
9
  </p>
@@ -177,6 +177,10 @@ const strict_update = (params) => {
177
177
  return TaskStatusUpdateEvent.create(params);
178
178
  };
179
179
  function _buildUpdate(state, params, final) {
180
+ if (params.message) {
181
+ params.message.contextId = params.contextId;
182
+ params.message.taskId = params.taskId;
183
+ }
180
184
  return strict_update({
181
185
  taskId: params.taskId,
182
186
  contextId: params.contextId,
@@ -9,7 +9,7 @@ export interface MessengerParams {
9
9
  baseUrl: URL | string;
10
10
  headers?: Record<string, string>;
11
11
  fallbackPath?: string;
12
- factory?: ClientFactoryOptions;
12
+ factory?: Partial<ClientFactoryOptions>;
13
13
  config?: ClientConfig;
14
14
  }
15
15
  /**
@@ -76,7 +76,7 @@ declare class Messenger implements Omit<Transport, "getAuthenticatedExtendedAgen
76
76
  * @param capability The capability to check (e.g., 'streaming', 'pushNotifications').
77
77
  * @returns A promise resolving to true if the capability is supported.
78
78
  */
79
- supports(capability: "streaming" | "pushNotifications" | "stateTransitionHistory" | "extentions"): Promise<boolean>;
79
+ supports(capability: "streaming" | "pushNotifications" | "stateTransitionHistory" | "extensions"): Promise<boolean>;
80
80
  /**
81
81
  * Adds a single header to be included in all requests.
82
82
  * @param name The header name.
@@ -6,7 +6,7 @@ import { A2A } from "../types/index.js";
6
6
  import { validateSchema } from "../utils/schema-validation.js";
7
7
  import { logger } from "../config/index.js";
8
8
  import * as describe from "../create/describe.js";
9
- import { ClientFactory, ClientFactoryOptions, } from "@a2a-js/sdk/client";
9
+ import { ClientFactory, ClientFactoryOptions, AgentCardResolver, } from "@a2a-js/sdk/client";
10
10
  class HeaderInterceptor {
11
11
  constructor(_getCustomHeaders) {
12
12
  this._getCustomHeaders = _getCustomHeaders;
@@ -25,6 +25,33 @@ class HeaderInterceptor {
25
25
  return Promise.resolve();
26
26
  }
27
27
  }
28
+ class NestedAgentCardResolver {
29
+ constructor(_options) {
30
+ this._options = _options;
31
+ this._fetchImpl = _options.fetchImpl ?? fetch;
32
+ }
33
+ get options() {
34
+ return this._options;
35
+ }
36
+ async resolve(baseUrl, _path) {
37
+ const path = _path ?? this._options?.path;
38
+ const agentCard = await AgentCardResolver.default
39
+ .resolve(baseUrl, path)
40
+ .catch((error) => {
41
+ logger.error("Failed to fetch agent card", { error });
42
+ return undefined;
43
+ });
44
+ if (agentCard) {
45
+ return agentCard;
46
+ }
47
+ logger.warn("Fetching agent card from", { baseUrl });
48
+ const response = await this._fetchImpl(baseUrl + (path ?? "/well-known/agent-card.json"));
49
+ if (!response.ok) {
50
+ throw new Error(`Failed to fetch Agent Card from ${baseUrl}: ${response.status}`);
51
+ }
52
+ return await validateSchema(A2A.AgentCardSchema, await response.json());
53
+ }
54
+ }
28
55
  /**
29
56
  * Messenger is the main communication client for interacting with remote A2A-compatible services.
30
57
  * It provides methods for sending messages, retrieving tasks, canceling operations, and handling streaming responses.
@@ -44,6 +71,7 @@ class Messenger {
44
71
  ],
45
72
  },
46
73
  }));
74
+ //RAII
47
75
  this.clientPromise = this.reset(this._baseUrl, this._fallbackPath);
48
76
  }
49
77
  async reset(baseUrl = this._baseUrl, fallbackPath = this._fallbackPath) {
@@ -187,7 +215,7 @@ class Messenger {
187
215
  return !!card.capabilities.pushNotifications;
188
216
  case "stateTransitionHistory":
189
217
  return !!card.capabilities.stateTransitionHistory;
190
- case "extentions":
218
+ case "extensions":
191
219
  return !!card.capabilities.extensions;
192
220
  default:
193
221
  return false;
@@ -209,7 +237,14 @@ class Messenger {
209
237
  delete this.headers[name];
210
238
  }
211
239
  static async create({ baseUrl, headers, fallbackPath, factory, config, }) {
212
- const messenger = new Messenger(baseUrl, headers, fallbackPath, factory, config);
240
+ const _factory = {
241
+ ...ClientFactoryOptions.default,
242
+ cardResolver: new NestedAgentCardResolver({
243
+ path: "/.well-known/agent-card.json",
244
+ }),
245
+ ...factory,
246
+ };
247
+ const messenger = new Messenger(baseUrl, headers, fallbackPath, _factory, config);
213
248
  const card = await messenger.getAgentCard();
214
249
  /**Validate the agent card to ensure the target conforms to the A2A specification */
215
250
  await validateSchema(A2A.AgentCardSchema, card).catch((error) => {
@@ -1,6 +1,9 @@
1
1
  import { validateSchema } from "./schema-validation.js";
2
2
  import { logger } from "../config/index.js";
3
3
  export function safeParse(json) {
4
+ if (!json || json === "{}" || json === "[]" || json === "") {
5
+ return {};
6
+ }
4
7
  try {
5
8
  return JSON.parse(json);
6
9
  }
@@ -182,6 +182,10 @@ const strict_update = (params) => {
182
182
  return TaskStatusUpdateEvent.create(params);
183
183
  };
184
184
  function _buildUpdate(state, params, final) {
185
+ if (params.message) {
186
+ params.message.contextId = params.contextId;
187
+ params.message.taskId = params.taskId;
188
+ }
185
189
  return strict_update({
186
190
  taskId: params.taskId,
187
191
  contextId: params.contextId,
@@ -9,7 +9,7 @@ export interface MessengerParams {
9
9
  baseUrl: URL | string;
10
10
  headers?: Record<string, string>;
11
11
  fallbackPath?: string;
12
- factory?: ClientFactoryOptions;
12
+ factory?: Partial<ClientFactoryOptions>;
13
13
  config?: ClientConfig;
14
14
  }
15
15
  /**
@@ -76,7 +76,7 @@ declare class Messenger implements Omit<Transport, "getAuthenticatedExtendedAgen
76
76
  * @param capability The capability to check (e.g., 'streaming', 'pushNotifications').
77
77
  * @returns A promise resolving to true if the capability is supported.
78
78
  */
79
- supports(capability: "streaming" | "pushNotifications" | "stateTransitionHistory" | "extentions"): Promise<boolean>;
79
+ supports(capability: "streaming" | "pushNotifications" | "stateTransitionHistory" | "extensions"): Promise<boolean>;
80
80
  /**
81
81
  * Adds a single header to be included in all requests.
82
82
  * @param name The header name.
@@ -6,7 +6,7 @@ import { A2A } from "../types/index.js";
6
6
  import { validateSchema } from "../utils/schema-validation.js";
7
7
  import { logger } from "../config/index.js";
8
8
  import * as describe from "../create/describe.js";
9
- import { ClientFactory, ClientFactoryOptions, } from "@a2a-js/sdk/client";
9
+ import { ClientFactory, ClientFactoryOptions, AgentCardResolver, } from "@a2a-js/sdk/client";
10
10
  class HeaderInterceptor {
11
11
  _getCustomHeaders;
12
12
  constructor(_getCustomHeaders) {
@@ -26,6 +26,35 @@ class HeaderInterceptor {
26
26
  return Promise.resolve();
27
27
  }
28
28
  }
29
+ class NestedAgentCardResolver {
30
+ _options;
31
+ _fetchImpl;
32
+ constructor(_options) {
33
+ this._options = _options;
34
+ this._fetchImpl = _options.fetchImpl ?? fetch;
35
+ }
36
+ get options() {
37
+ return this._options;
38
+ }
39
+ async resolve(baseUrl, _path) {
40
+ const path = _path ?? this._options?.path;
41
+ const agentCard = await AgentCardResolver.default
42
+ .resolve(baseUrl, path)
43
+ .catch((error) => {
44
+ logger.error("Failed to fetch agent card", { error });
45
+ return undefined;
46
+ });
47
+ if (agentCard) {
48
+ return agentCard;
49
+ }
50
+ logger.warn("Fetching agent card from", { baseUrl });
51
+ const response = await this._fetchImpl(baseUrl + (path ?? "/well-known/agent-card.json"));
52
+ if (!response.ok) {
53
+ throw new Error(`Failed to fetch Agent Card from ${baseUrl}: ${response.status}`);
54
+ }
55
+ return await validateSchema(A2A.AgentCardSchema, await response.json());
56
+ }
57
+ }
29
58
  /**
30
59
  * Messenger is the main communication client for interacting with remote A2A-compatible services.
31
60
  * It provides methods for sending messages, retrieving tasks, canceling operations, and handling streaming responses.
@@ -50,6 +79,7 @@ class Messenger {
50
79
  ],
51
80
  },
52
81
  }));
82
+ //RAII
53
83
  this.clientPromise = this.reset(this._baseUrl, this._fallbackPath);
54
84
  }
55
85
  async reset(baseUrl = this._baseUrl, fallbackPath = this._fallbackPath) {
@@ -193,7 +223,7 @@ class Messenger {
193
223
  return !!card.capabilities.pushNotifications;
194
224
  case "stateTransitionHistory":
195
225
  return !!card.capabilities.stateTransitionHistory;
196
- case "extentions":
226
+ case "extensions":
197
227
  return !!card.capabilities.extensions;
198
228
  default:
199
229
  return false;
@@ -215,7 +245,14 @@ class Messenger {
215
245
  delete this.headers[name];
216
246
  }
217
247
  static async create({ baseUrl, headers, fallbackPath, factory, config, }) {
218
- const messenger = new Messenger(baseUrl, headers, fallbackPath, factory, config);
248
+ const _factory = {
249
+ ...ClientFactoryOptions.default,
250
+ cardResolver: new NestedAgentCardResolver({
251
+ path: "/.well-known/agent-card.json",
252
+ }),
253
+ ...factory,
254
+ };
255
+ const messenger = new Messenger(baseUrl, headers, fallbackPath, _factory, config);
219
256
  const card = await messenger.getAgentCard();
220
257
  /**Validate the agent card to ensure the target conforms to the A2A specification */
221
258
  await validateSchema(A2A.AgentCardSchema, card).catch((error) => {
@@ -12,9 +12,9 @@ import { createService } from "./factory/service.js";
12
12
  import { getReferences } from "./helpers/references.js";
13
13
  import { logger } from "../../config/index.js";
14
14
  const taskToMessageParams = (task) => {
15
- const latestUserMessage = task.history
16
- ?.filter((msg) => msg.role === "user")
17
- ?.pop();
15
+ const latestUserMessage = task.history?.filter((msg) => msg.role === "user")?.pop() ??
16
+ /**fallback to the first message if no user message is found */
17
+ task.history?.[0];
18
18
  if (!latestUserMessage) {
19
19
  throw INVALID_REQUEST("No user message found");
20
20
  }
@@ -1,6 +1,9 @@
1
1
  import { validateSchema } from "./schema-validation.js";
2
2
  import { logger } from "../config/index.js";
3
3
  export function safeParse(json) {
4
+ if (!json || json === "{}" || json === "[]" || json === "") {
5
+ return {};
6
+ }
4
7
  try {
5
8
  return JSON.parse(json);
6
9
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@artinet/sdk",
3
- "version": "0.6.0",
3
+ "version": "0.6.1",
4
4
  "description": "A TypeScript SDK for building collaborative AI agents.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -95,7 +95,7 @@
95
95
  "license": "Apache-2.0",
96
96
  "repository": {
97
97
  "type": "git",
98
- "url": "https://github.com/the-artinet-project/artinet"
98
+ "url": "https://github.com/the-artinet-project/artinet-sdk.git"
99
99
  },
100
100
  "bugs": {
101
101
  "url": "https://github.com/the-artinet-project/artinet/issues"