@agentapplicationprotocol/client 0.5.0 → 0.6.0

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.
@@ -1,4 +1,4 @@
1
- import { AgentResponse, CreateSessionRequest, CreateSessionResponse, MetaResponse, SessionListResponse, SessionResponse, SessionTurnRequest, SSEEvent } from "@agentapplicationprotocol/core";
1
+ import { AgentResponse, CreateSessionRequest, CreateSessionResponse, MetaResponse, SessionHistoryResponse, SessionListResponse, SessionResponse, SessionTurnRequest, SSEEvent } from "@agentapplicationprotocol/core";
2
2
  export interface ClientOptions {
3
3
  baseUrl: string;
4
4
  apiKey: string;
@@ -22,10 +22,12 @@ export declare class Client {
22
22
  listSessions(params?: {
23
23
  after?: string;
24
24
  }): Promise<SessionListResponse>;
25
- /** Fetches all session IDs across all pages. */
26
- listAllSessions(): Promise<string[]>;
25
+ /** Fetches all sessions across all pages. */
26
+ listAllSessions(): Promise<SessionResponse[]>;
27
27
  /** GET /session/:id */
28
- getSession(sessionId: string, history?: "compacted" | "full"): Promise<SessionResponse>;
28
+ getSession(sessionId: string): Promise<SessionResponse>;
29
+ /** GET /session/:id/history */
30
+ getSessionHistory(sessionId: string, type: "compacted" | "full"): Promise<SessionHistoryResponse>;
29
31
  /** PUT /session — non-streaming */
30
32
  createSession(req: CreateSessionRequest & {
31
33
  stream?: "none";
@@ -50,8 +50,12 @@ class Client {
50
50
  return parseSSE(res.body);
51
51
  }
52
52
  /** GET /meta */
53
- getMeta() {
54
- return this.request("GET", "/meta");
53
+ async getMeta() {
54
+ const meta = await this.request("GET", "/meta");
55
+ if (meta.version !== 2) {
56
+ throw new Error(`Protocol version mismatch: expected 2, got ${meta.version}`);
57
+ }
58
+ return meta;
55
59
  }
56
60
  /** GET /sessions */
57
61
  listSessions(params) {
@@ -61,7 +65,7 @@ class Client {
61
65
  }
62
66
  return this.request("GET", path);
63
67
  }
64
- /** Fetches all session IDs across all pages. */
68
+ /** Fetches all sessions across all pages. */
65
69
  async listAllSessions() {
66
70
  const sessions = [];
67
71
  let after;
@@ -73,11 +77,12 @@ class Client {
73
77
  return sessions;
74
78
  }
75
79
  /** GET /session/:id */
76
- getSession(sessionId, history) {
77
- const path = history
78
- ? `/session/${sessionId}?${new URLSearchParams({ history }).toString()}`
79
- : `/session/${sessionId}`;
80
- return this.request("GET", path);
80
+ getSession(sessionId) {
81
+ return this.request("GET", `/session/${sessionId}`);
82
+ }
83
+ /** GET /session/:id/history */
84
+ getSessionHistory(sessionId, type) {
85
+ return this.request("GET", `/session/${sessionId}/history?${new URLSearchParams({ type }).toString()}`);
81
86
  }
82
87
  createSession(req) {
83
88
  if (req.messages.at(-1)?.role !== "user")
@@ -37,19 +37,19 @@ let client;
37
37
  (0, vitest_1.describe)("Client", () => {
38
38
  (0, vitest_1.it)("strips trailing slash from baseUrl", () => {
39
39
  const c = new client_1.Client({ baseUrl: BASE_URL + "/", apiKey: API_KEY });
40
- const fetch = mockFetch({});
40
+ const fetch = mockFetch({ version: 2, agents: [] });
41
41
  vitest_1.vi.stubGlobal("fetch", fetch);
42
42
  c.getMeta();
43
43
  (0, vitest_1.expect)(fetch.mock.calls[0][0]).toBe(`${BASE_URL}/meta`);
44
44
  });
45
45
  (0, vitest_1.it)("sends Authorization header", async () => {
46
- const fetch = mockFetch({ version: 1, agents: [] });
46
+ const fetch = mockFetch({ version: 2, agents: [] });
47
47
  vitest_1.vi.stubGlobal("fetch", fetch);
48
48
  await client.getMeta();
49
49
  (0, vitest_1.expect)(fetch.mock.calls[0][1].headers["Authorization"]).toBe(`Bearer ${API_KEY}`);
50
50
  });
51
51
  (0, vitest_1.it)("getMeta: GET /meta", async () => {
52
- const meta = { version: 1, agents: [] };
52
+ const meta = { version: 2, agents: [] };
53
53
  vitest_1.vi.stubGlobal("fetch", mockFetch(meta));
54
54
  (0, vitest_1.expect)(await client.getMeta()).toEqual(meta);
55
55
  });
@@ -58,20 +58,20 @@ let client;
58
58
  vitest_1.vi.stubGlobal("fetch", mockFetch(session));
59
59
  (0, vitest_1.expect)(await client.getSession("s1")).toEqual(session);
60
60
  });
61
- (0, vitest_1.it)("getSession: appends ?history=compacted", async () => {
62
- const fetch = mockFetch({ sessionId: "s1", agent: { name: "a" } });
61
+ (0, vitest_1.it)("getSessionHistory: appends ?type=compacted", async () => {
62
+ const fetch = mockFetch({ history: { compacted: [] } });
63
63
  vitest_1.vi.stubGlobal("fetch", fetch);
64
- await client.getSession("s1", "compacted");
65
- (0, vitest_1.expect)(fetch.mock.calls[0][0]).toBe(`${BASE_URL}/session/s1?history=compacted`);
64
+ await client.getSessionHistory("s1", "compacted");
65
+ (0, vitest_1.expect)(fetch.mock.calls[0][0]).toBe(`${BASE_URL}/session/s1/history?type=compacted`);
66
66
  });
67
- (0, vitest_1.it)("getSession: appends ?history=full", async () => {
68
- const fetch = mockFetch({ sessionId: "s1", agent: { name: "a" } });
67
+ (0, vitest_1.it)("getSessionHistory: appends ?type=full", async () => {
68
+ const fetch = mockFetch({ history: { full: [] } });
69
69
  vitest_1.vi.stubGlobal("fetch", fetch);
70
- await client.getSession("s1", "full");
71
- (0, vitest_1.expect)(fetch.mock.calls[0][0]).toBe(`${BASE_URL}/session/s1?history=full`);
70
+ await client.getSessionHistory("s1", "full");
71
+ (0, vitest_1.expect)(fetch.mock.calls[0][0]).toBe(`${BASE_URL}/session/s1/history?type=full`);
72
72
  });
73
73
  (0, vitest_1.it)("listSessions: GET /sessions without cursor", async () => {
74
- const res = { sessions: ["s1"] };
74
+ const res = { sessions: [{ sessionId: "s1", agent: { name: "a" } }] };
75
75
  const fetch = mockFetch(res);
76
76
  vitest_1.vi.stubGlobal("fetch", fetch);
77
77
  await client.listSessions();
@@ -84,20 +84,22 @@ let client;
84
84
  (0, vitest_1.expect)(fetch.mock.calls[0][0]).toBe(`${BASE_URL}/sessions?after=cursor1`);
85
85
  });
86
86
  (0, vitest_1.it)("listAllSessions: paginates until no next", async () => {
87
+ const s1 = { sessionId: "s1", agent: { name: "a" } };
88
+ const s2 = { sessionId: "s2", agent: { name: "a" } };
87
89
  const fetch = vitest_1.vi
88
90
  .fn()
89
91
  .mockResolvedValueOnce({
90
92
  ok: true,
91
93
  status: 200,
92
- json: () => Promise.resolve({ sessions: ["s1"], next: "c1" }),
94
+ json: () => Promise.resolve({ sessions: [s1], next: "c1" }),
93
95
  })
94
96
  .mockResolvedValueOnce({
95
97
  ok: true,
96
98
  status: 200,
97
- json: () => Promise.resolve({ sessions: ["s2"] }),
99
+ json: () => Promise.resolve({ sessions: [s2] }),
98
100
  });
99
101
  vitest_1.vi.stubGlobal("fetch", fetch);
100
- (0, vitest_1.expect)(await client.listAllSessions()).toEqual(["s1", "s2"]);
102
+ (0, vitest_1.expect)(await client.listAllSessions()).toEqual([s1, s2]);
101
103
  (0, vitest_1.expect)(fetch).toHaveBeenCalledTimes(2);
102
104
  });
103
105
  (0, vitest_1.it)("deleteSession: DELETE /session/:id returns void on 204", async () => {
@@ -1,4 +1,4 @@
1
- import { AgentConfig, AgentInfo, CreateSessionRequest, HistoryMessage, SessionTurnRequest, SSEEvent, ToolCallEvent, ToolSpec } from "@agentapplicationprotocol/core";
1
+ import { AgentConfig, AgentInfo, CreateSessionRequest, HistoryMessage, SessionResponse, SessionTurnRequest, SSEEvent, ToolCallEvent, ToolSpec } from "@agentapplicationprotocol/core";
2
2
  import { Client } from "./client";
3
3
  /** Unresolved tool calls from a turn, split by origin. */
4
4
  export interface PendingToolUse {
@@ -31,10 +31,12 @@ export declare class Session {
31
31
  }>;
32
32
  /**
33
33
  * Loads an existing session and resolves any pending tool use.
34
- * @param agents - List of known agents to match against the session's agent name.
34
+ * @param res - Session response from `client.getSession()`.
35
+ * @param agentInfo - Agent metadata matching the session's agent.
36
+ * @param history - If provided, fetches history of the given type.
35
37
  * @returns The loaded session and any pending tool calls.
36
38
  */
37
- static load(client: Client, sessionId: string, agents: AgentInfo[], history?: "full" | "compacted"): Promise<{
39
+ static load(client: Client, res: SessionResponse, agentInfo: AgentInfo, history?: "full" | "compacted"): Promise<{
38
40
  session: Session;
39
41
  pending: PendingToolUse;
40
42
  }>;
@@ -45,17 +45,18 @@ class Session {
45
45
  }
46
46
  /**
47
47
  * Loads an existing session and resolves any pending tool use.
48
- * @param agents - List of known agents to match against the session's agent name.
48
+ * @param res - Session response from `client.getSession()`.
49
+ * @param agentInfo - Agent metadata matching the session's agent.
50
+ * @param history - If provided, fetches history of the given type.
49
51
  * @returns The loaded session and any pending tool calls.
50
52
  */
51
- static async load(client, sessionId, agents, history) {
52
- const res = await client.getSession(sessionId, history);
53
- const agentInfo = agents.find((a) => a.name === res.agent.name);
54
- if (!agentInfo)
55
- throw new Error(`Unknown agent: ${res.agent.name}`);
56
- const session = new Session(sessionId, client, agentInfo, res.agent, res.tools);
57
- const h = history === "compacted" ? res.history?.compacted : res.history?.full;
58
- session.history.push(...(h ?? []));
53
+ static async load(client, res, agentInfo, history) {
54
+ const session = new Session(res.sessionId, client, agentInfo, res.agent, res.tools);
55
+ if (history) {
56
+ const histRes = await client.getSessionHistory(res.sessionId, history);
57
+ const h = history === "compacted" ? histRes.history.compacted : histRes.history.full;
58
+ session.history.push(...(h ?? []));
59
+ }
59
60
  return { session, pending: (0, utils_1.resolvePendingToolUse)(session.history, session.tools) };
60
61
  }
61
62
  /**
@@ -32,40 +32,28 @@ let client;
32
32
  client = new client_1.Client({ baseUrl: BASE_URL, apiKey: "key" });
33
33
  });
34
34
  (0, vitest_1.describe)("Session.load", () => {
35
+ const sessionRes = { sessionId: "s1", agent: { name: "test-agent" } };
35
36
  (0, vitest_1.it)("returns session with correct sessionId and agentConfig", async () => {
36
- const res = { sessionId: "s1", agent: { name: "test-agent" } };
37
- vitest_1.vi.stubGlobal("fetch", mockFetch(res));
38
- const { session } = await session_1.Session.load(client, "s1", [agentInfo]);
37
+ const { session } = await session_1.Session.load(client, sessionRes, agentInfo);
39
38
  (0, vitest_1.expect)(session.sessionId).toBe("s1");
40
39
  (0, vitest_1.expect)(session.agentConfig).toEqual({ name: "test-agent" });
41
40
  (0, vitest_1.expect)(session.agent).toBe(agentInfo);
42
41
  });
43
42
  (0, vitest_1.it)("populates history from full history", async () => {
44
43
  const history = [{ role: "user", content: "hi" }];
45
- const res = {
46
- sessionId: "s1",
47
- agent: { name: "test-agent" },
48
- history: { full: history },
49
- };
50
- vitest_1.vi.stubGlobal("fetch", mockFetch(res));
51
- const { session } = await session_1.Session.load(client, "s1", [agentInfo], "full");
44
+ vitest_1.vi.stubGlobal("fetch", mockFetch({ history: { full: history } }));
45
+ const { session } = await session_1.Session.load(client, sessionRes, agentInfo, "full");
52
46
  (0, vitest_1.expect)(session.history).toEqual(history);
53
47
  });
54
48
  (0, vitest_1.it)("populates history from compacted history", async () => {
55
49
  const history = [{ role: "user", content: "summary" }];
56
- const res = {
57
- sessionId: "s1",
58
- agent: { name: "test-agent" },
59
- history: { compacted: history },
60
- };
61
- vitest_1.vi.stubGlobal("fetch", mockFetch(res));
62
- const { session } = await session_1.Session.load(client, "s1", [agentInfo], "compacted");
50
+ vitest_1.vi.stubGlobal("fetch", mockFetch({ history: { compacted: history } }));
51
+ const { session } = await session_1.Session.load(client, sessionRes, agentInfo, "compacted");
63
52
  (0, vitest_1.expect)(session.history).toEqual(history);
64
53
  });
65
54
  (0, vitest_1.it)("returns empty history when no history in response", async () => {
66
- const res = { sessionId: "s1", agent: { name: "test-agent" } };
67
- vitest_1.vi.stubGlobal("fetch", mockFetch(res));
68
- const { session } = await session_1.Session.load(client, "s1", [agentInfo], "full");
55
+ vitest_1.vi.stubGlobal("fetch", mockFetch({ history: {} }));
56
+ const { session } = await session_1.Session.load(client, sessionRes, agentInfo, "full");
69
57
  (0, vitest_1.expect)(session.history).toEqual([]);
70
58
  });
71
59
  (0, vitest_1.it)("resolves pending client tool use from history", async () => {
@@ -83,30 +71,23 @@ let client;
83
71
  content: [{ type: "tool_use", toolCallId: "tc1", name: "myTool", input: {} }],
84
72
  },
85
73
  ];
86
- const res = {
87
- sessionId: "s1",
88
- agent: { name: "test-agent" },
89
- tools,
90
- history: { full: history },
91
- };
92
- vitest_1.vi.stubGlobal("fetch", mockFetch(res));
93
- const { pending } = await session_1.Session.load(client, "s1", [agentInfo], "full");
74
+ vitest_1.vi.stubGlobal("fetch", mockFetch({ history: { full: history } }));
75
+ const res = { sessionId: "s1", agent: { name: "test-agent" }, tools };
76
+ const { pending } = await session_1.Session.load(client, res, agentInfo, "full");
94
77
  (0, vitest_1.expect)(pending.client).toEqual([{ toolCallId: "tc1", name: "myTool", input: {} }]);
95
78
  (0, vitest_1.expect)(pending.server).toEqual([]);
96
79
  });
97
- (0, vitest_1.it)("calls getSession with correct history param", async () => {
98
- const fetch = mockFetch({
99
- sessionId: "s1",
100
- agent: { name: "test-agent" },
101
- });
80
+ (0, vitest_1.it)("calls getSessionHistory with correct type param", async () => {
81
+ const fetch = mockFetch({ history: { compacted: [] } });
102
82
  vitest_1.vi.stubGlobal("fetch", fetch);
103
- await session_1.Session.load(client, "s1", [agentInfo], "compacted");
104
- (0, vitest_1.expect)(fetch.mock.calls[0][0]).toBe(`${BASE_URL}/session/s1?history=compacted`);
83
+ await session_1.Session.load(client, sessionRes, agentInfo, "compacted");
84
+ (0, vitest_1.expect)(fetch.mock.calls[0][0]).toBe(`${BASE_URL}/session/s1/history?type=compacted`);
105
85
  });
106
- (0, vitest_1.it)("throws if agent name not found in list", async () => {
107
- const res = { sessionId: "s1", agent: { name: "unknown-agent" } };
108
- vitest_1.vi.stubGlobal("fetch", mockFetch(res));
109
- await (0, vitest_1.expect)(session_1.Session.load(client, "s1", [agentInfo])).rejects.toThrow("Unknown agent: unknown-agent");
86
+ (0, vitest_1.it)("does not fetch when no history requested", async () => {
87
+ const fetch = vitest_1.vi.fn();
88
+ vitest_1.vi.stubGlobal("fetch", fetch);
89
+ await session_1.Session.load(client, sessionRes, agentInfo);
90
+ (0, vitest_1.expect)(fetch).not.toHaveBeenCalled();
110
91
  });
111
92
  });
112
93
  (0, vitest_1.describe)("Session.create", () => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentapplicationprotocol/client",
3
- "version": "0.5.0",
3
+ "version": "0.6.0",
4
4
  "description": "AAP client",
5
5
  "keywords": [
6
6
  "aap",
@@ -29,7 +29,7 @@
29
29
  "types": "dist/src/index.d.ts",
30
30
  "dependencies": {
31
31
  "eventsource-parser": "^3.0.6",
32
- "@agentapplicationprotocol/core": "0.5.0"
32
+ "@agentapplicationprotocol/core": "0.6.0"
33
33
  },
34
34
  "scripts": {
35
35
  "build": "tsc",