@agentapplicationprotocol/server 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.
@@ -54,7 +54,7 @@ const agent = new agent_js_1.Agent("basic-agent", {
54
54
  });
55
55
  const handler = {
56
56
  getMeta() {
57
- return { version: 1, agents: [agent.info] };
57
+ return { agents: [agent.info] };
58
58
  },
59
59
  createSession(req) {
60
60
  const sessionId = `sess_${(0, node_crypto_1.randomUUID)()}`;
@@ -74,16 +74,21 @@ const handler = {
74
74
  throw new Error(`Session not found: ${sessionId}`);
75
75
  return session.runTurn(req);
76
76
  },
77
- async getSession(sessionId, history) {
77
+ async getSession(sessionId) {
78
+ const session = sessions.get(sessionId);
79
+ if (!session)
80
+ throw new Error(`Session not found: ${sessionId}`);
81
+ return session.toSessionResponse();
82
+ },
83
+ async getSessionHistory(sessionId, type) {
78
84
  const session = sessions.get(sessionId);
79
85
  if (!session)
80
86
  throw new Error(`Session not found: ${sessionId}`);
81
87
  // history is never compacted, so compacted and full are the same
82
- const historyData = history ? { [history]: session.history } : undefined;
83
- return { ...session.toSessionResponse(), history: historyData };
88
+ return session.history;
84
89
  },
85
90
  async listSessions() {
86
- return { sessions: [...sessions.keys()] };
91
+ return { sessions: [...sessions.values()].map((s) => s.toSessionResponse()) };
87
92
  },
88
93
  async deleteSession(sessionId) {
89
94
  sessions.delete(sessionId);
@@ -52,7 +52,7 @@ const agent = new agent_js_1.Agent("compact-history-agent", {
52
52
  });
53
53
  const handler = {
54
54
  getMeta() {
55
- return { version: 1, agents: [agent.info] };
55
+ return { agents: [agent.info] };
56
56
  },
57
57
  createSession(req) {
58
58
  const sessionId = `sess_${(0, node_crypto_1.randomUUID)()}`;
@@ -72,20 +72,20 @@ const handler = {
72
72
  throw new Error(`Session not found: ${sessionId}`);
73
73
  return session.runTurn(req);
74
74
  },
75
- async getSession(sessionId, history) {
75
+ async getSession(sessionId) {
76
76
  const session = session_js_1.sessions.get(sessionId);
77
77
  if (!session)
78
78
  throw new Error(`Session not found: ${sessionId}`);
79
- // history exposes both the compacted window and the full uncompacted history
80
- const historyData = history === "compacted"
81
- ? { compacted: session.history }
82
- : history === "full"
83
- ? { full: session.fullHistory }
84
- : undefined;
85
- return { ...session.toSessionResponse(), history: historyData };
79
+ return session.toSessionResponse();
80
+ },
81
+ async getSessionHistory(sessionId, type) {
82
+ const session = session_js_1.sessions.get(sessionId);
83
+ if (!session)
84
+ throw new Error(`Session not found: ${sessionId}`);
85
+ return type === "compacted" ? session.history : session.fullHistory;
86
86
  },
87
87
  async listSessions() {
88
- return { sessions: [...session_js_1.sessions.keys()] };
88
+ return { sessions: [...session_js_1.sessions.values()].map((s) => s.toSessionResponse()) };
89
89
  },
90
90
  async deleteSession(sessionId) {
91
91
  session_js_1.sessions.delete(sessionId);
@@ -1,11 +1,12 @@
1
1
  import { Hono } from "hono";
2
- import { AgentResponse, CreateSessionRequest, CreateSessionResponse, MetaResponse, SessionListResponse, SessionResponse, SessionTurnRequest, SSEEvent } from "@agentapplicationprotocol/core";
2
+ import { AgentResponse, CreateSessionRequest, CreateSessionResponse, HistoryMessage, MetaResponse, SessionListResponse, SessionResponse, SessionTurnRequest, SSEEvent } from "@agentapplicationprotocol/core";
3
3
  export interface Handler {
4
- getMeta(): MetaResponse;
4
+ getMeta(): Omit<MetaResponse, "version">;
5
5
  listSessions(params: {
6
6
  after?: string;
7
7
  }): Promise<SessionListResponse>;
8
- getSession(sessionId: string, history?: "compacted" | "full"): Promise<SessionResponse>;
8
+ getSession(sessionId: string): Promise<SessionResponse>;
9
+ getSessionHistory(sessionId: string, type: "compacted" | "full"): Promise<HistoryMessage[]>;
9
10
  /** The last message in `req.messages` is guaranteed to be a user message. */
10
11
  createSession(req: CreateSessionRequest): Promise<CreateSessionResponse> | AsyncIterable<SSEEvent>;
11
12
  sendTurn(sessionId: string, req: SessionTurnRequest): Promise<AgentResponse> | AsyncIterable<SSEEvent>;
@@ -41,7 +41,7 @@ function redactSecretOptions(session, agents) {
41
41
  */
42
42
  function aap(handler) {
43
43
  const router = new hono_1.Hono();
44
- router.get("/meta", (c) => c.json(handler.getMeta()));
44
+ router.get("/meta", (c) => c.json({ version: 2, ...handler.getMeta() }));
45
45
  router.put("/session", async (c) => {
46
46
  const req = await c.req.json();
47
47
  if (req.messages.at(-1)?.role !== "user")
@@ -61,20 +61,16 @@ function aap(handler) {
61
61
  return c.json(result);
62
62
  });
63
63
  router.get("/session/:id", async (c) => {
64
- const historyParam = c.req.query("history");
65
- const history = historyParam === "compacted" || historyParam === "full" ? historyParam : undefined;
66
- const session = await handler.getSession(c.req.param("id"), history);
67
- // strip history fields not matching the requested mode
68
- if (session.history) {
69
- if (history === "compacted")
70
- delete session.history.full;
71
- else if (history === "full")
72
- delete session.history.compacted;
73
- else
74
- session.history = undefined;
75
- }
76
- const meta = handler.getMeta();
77
- return c.json(redactSecretOptions(session, meta.agents));
64
+ const session = await handler.getSession(c.req.param("id"));
65
+ const { agents } = handler.getMeta();
66
+ return c.json(redactSecretOptions(session, agents));
67
+ });
68
+ router.get("/session/:id/history", async (c) => {
69
+ const typeParam = c.req.query("type");
70
+ if (typeParam !== "compacted" && typeParam !== "full")
71
+ return c.json({ error: 'type must be "compacted" or "full"' }, 400);
72
+ const messages = await handler.getSessionHistory(c.req.param("id"), typeParam);
73
+ return c.json({ history: { [typeParam]: messages } });
78
74
  });
79
75
  router.get("/sessions", async (c) => {
80
76
  const after = c.req.query("after");
@@ -5,11 +5,11 @@ const hono_1 = require("hono");
5
5
  const bearer_auth_1 = require("hono/bearer-auth");
6
6
  const cors_1 = require("hono/cors");
7
7
  const server_1 = require("./server");
8
- const meta = { version: 1, agents: [] };
8
+ const meta = { version: 2, agents: [] };
9
9
  const session = { sessionId: "s1", agent: { name: "a" } };
10
10
  const agentResponse = { stopReason: "end_turn", messages: [] };
11
11
  const createSessionResponse = { ...agentResponse, sessionId: "s1" };
12
- const sessionList = { sessions: ["s1"] };
12
+ const sessionList = { sessions: [session] };
13
13
  async function* sseEvents() {
14
14
  yield { event: "turn_start" };
15
15
  yield { event: "text", text: "hi" };
@@ -17,9 +17,10 @@ async function* sseEvents() {
17
17
  }
18
18
  function makeHandler(overrides = {}) {
19
19
  return {
20
- getMeta: vitest_1.vi.fn().mockReturnValue(meta),
20
+ getMeta: vitest_1.vi.fn().mockReturnValue({ agents: [] }),
21
21
  listSessions: vitest_1.vi.fn().mockResolvedValue(sessionList),
22
22
  getSession: vitest_1.vi.fn().mockResolvedValue(session),
23
+ getSessionHistory: vitest_1.vi.fn().mockResolvedValue([]),
23
24
  createSession: vitest_1.vi.fn().mockResolvedValue(createSessionResponse),
24
25
  sendTurn: vitest_1.vi.fn().mockResolvedValue(agentResponse),
25
26
  deleteSession: vitest_1.vi.fn().mockResolvedValue(undefined),
@@ -57,22 +58,20 @@ function req(method, path, body, headers) {
57
58
  sessionId: "s1",
58
59
  agent: { name: "a", options: { key: "mysecret", model: "gpt-4" } },
59
60
  };
60
- const secretMeta = {
61
- version: 1,
62
- agents: [
63
- {
64
- name: "a",
65
- version: "1.0.0",
66
- options: [
67
- { type: "secret", name: "key", default: "" },
68
- { type: "text", name: "model", default: "" },
69
- ],
70
- },
71
- ],
72
- };
73
61
  const app = makeApp(makeHandler({
74
62
  getSession: vitest_1.vi.fn().mockResolvedValue(secretSession),
75
- getMeta: vitest_1.vi.fn().mockReturnValue(secretMeta),
63
+ getMeta: vitest_1.vi.fn().mockReturnValue({
64
+ agents: [
65
+ {
66
+ name: "a",
67
+ version: "1.0.0",
68
+ options: [
69
+ { type: "secret", name: "key", default: "" },
70
+ { type: "text", name: "model", default: "" },
71
+ ],
72
+ },
73
+ ],
74
+ }),
76
75
  }));
77
76
  const res = await app.fetch(req("GET", "/session/s1"));
78
77
  (0, vitest_1.expect)(res.status).toBe(200);
@@ -158,7 +157,7 @@ function req(method, path, body, headers) {
158
157
  };
159
158
  const app = makeApp(makeHandler({
160
159
  getSession: vitest_1.vi.fn().mockResolvedValue(sessionWithOptions),
161
- getMeta: vitest_1.vi.fn().mockReturnValue({ version: 1, agents: [] }),
160
+ getMeta: vitest_1.vi.fn().mockReturnValue({ agents: [] }),
162
161
  }));
163
162
  const res = await app.fetch(req("GET", "/session/s1"));
164
163
  (0, vitest_1.expect)(await res.json()).toEqual(sessionWithOptions);
@@ -171,7 +170,6 @@ function req(method, path, body, headers) {
171
170
  const app = makeApp(makeHandler({
172
171
  getSession: vitest_1.vi.fn().mockResolvedValue(sessionWithOptions),
173
172
  getMeta: vitest_1.vi.fn().mockReturnValue({
174
- version: 1,
175
173
  agents: [
176
174
  {
177
175
  name: "a",
@@ -184,46 +182,27 @@ function req(method, path, body, headers) {
184
182
  const res = await app.fetch(req("GET", "/session/s1"));
185
183
  (0, vitest_1.expect)(await res.json()).toEqual(sessionWithOptions);
186
184
  });
187
- (0, vitest_1.it)("GET /session/:id?history=compacted passes param and strips full", async () => {
188
- const handler = makeHandler({
189
- getSession: vitest_1.vi.fn().mockResolvedValue({
190
- ...session,
191
- history: { compacted: [], full: [] },
192
- }),
193
- });
185
+ (0, vitest_1.it)("GET /session/:id/history?type=compacted calls getSessionHistory", async () => {
186
+ const messages = [{ role: "user", content: "hi" }];
187
+ const handler = makeHandler({ getSessionHistory: vitest_1.vi.fn().mockResolvedValue(messages) });
194
188
  const app = makeApp(handler);
195
- const res = await app.fetch(req("GET", "/session/s1?history=compacted"));
196
- (0, vitest_1.expect)(handler.getSession).toHaveBeenCalledWith("s1", "compacted");
197
- (0, vitest_1.expect)(await res.json()).toEqual({ ...session, history: { compacted: [] } });
198
- });
199
- (0, vitest_1.it)("GET /session/:id?history=full passes param and strips compacted", async () => {
200
- const handler = makeHandler({
201
- getSession: vitest_1.vi.fn().mockResolvedValue({
202
- ...session,
203
- history: { compacted: [], full: [] },
204
- }),
205
- });
206
- const app = makeApp(handler);
207
- const res = await app.fetch(req("GET", "/session/s1?history=full"));
208
- (0, vitest_1.expect)(handler.getSession).toHaveBeenCalledWith("s1", "full");
209
- (0, vitest_1.expect)(await res.json()).toEqual({ ...session, history: { full: [] } });
210
- });
211
- (0, vitest_1.it)("GET /session/:id without ?history passes undefined and strips history from response", async () => {
212
- const handler = makeHandler({
213
- getSession: vitest_1.vi.fn().mockResolvedValue({
214
- ...session,
215
- history: { compacted: [], full: [] },
216
- }),
217
- });
218
- const app = makeApp(handler);
219
- const res = await app.fetch(req("GET", "/session/s1"));
220
- (0, vitest_1.expect)(handler.getSession).toHaveBeenCalledWith("s1", undefined);
221
- (0, vitest_1.expect)(await res.json()).toEqual(session);
189
+ const res = await app.fetch(req("GET", "/session/s1/history?type=compacted"));
190
+ (0, vitest_1.expect)(res.status).toBe(200);
191
+ (0, vitest_1.expect)(handler.getSessionHistory).toHaveBeenCalledWith("s1", "compacted");
192
+ (0, vitest_1.expect)(await res.json()).toEqual({ history: { compacted: messages } });
222
193
  });
223
- (0, vitest_1.it)("GET /session/:id with invalid ?history passes undefined", async () => {
224
- const handler = makeHandler();
194
+ (0, vitest_1.it)("GET /session/:id/history?type=full calls getSessionHistory", async () => {
195
+ const messages = [{ role: "user", content: "hi" }];
196
+ const handler = makeHandler({ getSessionHistory: vitest_1.vi.fn().mockResolvedValue(messages) });
225
197
  const app = makeApp(handler);
226
- await app.fetch(req("GET", "/session/s1?history=invalid"));
227
- (0, vitest_1.expect)(handler.getSession).toHaveBeenCalledWith("s1", undefined);
198
+ const res = await app.fetch(req("GET", "/session/s1/history?type=full"));
199
+ (0, vitest_1.expect)(res.status).toBe(200);
200
+ (0, vitest_1.expect)(handler.getSessionHistory).toHaveBeenCalledWith("s1", "full");
201
+ (0, vitest_1.expect)(await res.json()).toEqual({ history: { full: messages } });
202
+ });
203
+ (0, vitest_1.it)("GET /session/:id/history without valid ?type returns 400", async () => {
204
+ const app = makeApp(makeHandler());
205
+ const res = await app.fetch(req("GET", "/session/s1/history"));
206
+ (0, vitest_1.expect)(res.status).toBe(400);
228
207
  });
229
208
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentapplicationprotocol/server",
3
- "version": "0.5.0",
3
+ "version": "0.6.0",
4
4
  "description": "AAP server",
5
5
  "keywords": [
6
6
  "aap",
@@ -31,7 +31,7 @@
31
31
  "ai": "^6.0.141",
32
32
  "hono": "^4.12.8",
33
33
  "zod": "^4.3.6",
34
- "@agentapplicationprotocol/core": "0.5.0"
34
+ "@agentapplicationprotocol/core": "0.6.0"
35
35
  },
36
36
  "devDependencies": {
37
37
  "@ai-sdk/openai": "^3.0.48",