@artinet/fleet 0.1.5 → 0.1.7

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 (34) hide show
  1. package/README.md +109 -230
  2. package/dist/default.d.ts +1 -0
  3. package/dist/default.js +1 -0
  4. package/dist/routes/create/index.d.ts +47 -46
  5. package/dist/routes/create/index.js +1 -1
  6. package/dist/routes/request/implementation/load.d.ts +1 -1
  7. package/dist/routes/request/implementation/load.js +17 -20
  8. package/dist/routes/request/types/definitions.d.ts +55 -53
  9. package/dist/routes/request/types/definitions.js +5 -7
  10. package/dist/server/express/agent-request.d.ts +6 -15
  11. package/dist/server/express/agent-request.js +33 -29
  12. package/dist/server/express/deploy-request.d.ts +6 -14
  13. package/dist/server/express/deploy-request.js +18 -18
  14. package/dist/server/express/server.d.ts +14 -13
  15. package/dist/server/express/server.js +23 -49
  16. package/dist/server/express/test-request.d.ts +16 -14
  17. package/dist/server/express/test-request.js +25 -25
  18. package/dist/server/express/types.d.ts +10 -0
  19. package/dist/server/express/types.js +5 -0
  20. package/dist/server/hono/agent-request.d.ts +6 -14
  21. package/dist/server/hono/agent-request.js +25 -21
  22. package/dist/server/hono/deploy-request.d.ts +6 -13
  23. package/dist/server/hono/deploy-request.js +14 -13
  24. package/dist/server/hono/rpc.d.ts +9 -11
  25. package/dist/server/hono/rpc.js +19 -20
  26. package/dist/server/hono/server.d.ts +15 -14
  27. package/dist/server/hono/server.js +20 -44
  28. package/dist/server/hono/test-request.d.ts +6 -13
  29. package/dist/server/hono/test-request.js +26 -26
  30. package/dist/server/hono/types.d.ts +9 -0
  31. package/dist/server/hono/types.js +5 -0
  32. package/dist/utils.d.ts +11 -0
  33. package/dist/utils.js +13 -0
  34. package/package.json +108 -107
@@ -2,26 +2,27 @@
2
2
  * Copyright 2025 The Artinet Project
3
3
  * SPDX-License-Identifier: Apache-2.0
4
4
  */
5
- import * as sdk from "@artinet/sdk";
6
- import { CreateAgent, CreateAgentRequestSchema, } from "../../routes/create/index.js";
7
- import { generateRequestId, generateRegistrationId } from "./utils.js";
8
- export async function handle(ctx, _next, context, deploy = CreateAgent) {
5
+ import * as sdk from '@artinet/sdk';
6
+ import { CreateAgent, CreateAgentRequestSchema, } from '../../routes/create/index.js';
7
+ import { generateRequestId, generateRegistrationId } from './utils.js';
8
+ export const factory = ({ implementation = CreateAgent }) => async (params) => await handle(params, implementation);
9
+ export const handle = async ({ session: { ctx }, context, intercepts }, implementation = CreateAgent) => {
9
10
  /* hono.Context.req uses a raw JSON.parse() so we prefer to use the text() and our own safeParse() */
10
11
  const req = sdk.safeParse(await ctx.req.text());
11
12
  const request = await sdk.validateSchema(CreateAgentRequestSchema, req);
12
13
  sdk.logger.info(`deploying agent: ${request.config.name}`);
13
14
  sdk.logger.debug(`deploying agent: ${sdk.formatJson(request)}`);
14
15
  context.registrationId = generateRegistrationId(request.config.uri);
15
- const result = await deploy(request, context);
16
+ const result = await implementation(request, context, intercepts);
16
17
  ctx.res = ctx.json(result);
17
- }
18
- export const factory = (deploy = CreateAgent) => async (ctx, next, context) => await handle(ctx, next, context, deploy);
19
- export async function request({ ctx, next, context, handler = handle, user, }) {
20
- const reqId = ctx.req.header("x-request-id") ?? sdk.safeParse(await ctx.req.text())?.id;
21
- const requestContext = {
18
+ };
19
+ export const request = async ({ session, context, handler = handle, user, intercepts }, implementation = CreateAgent) => {
20
+ const { ctx } = session;
21
+ const reqId = ctx.req.header('x-request-id') ?? sdk.safeParse(await ctx.req.text())?.id;
22
+ const _context = {
22
23
  ...context,
23
24
  requestId: generateRequestId(context, reqId),
24
- userId: await user?.(ctx),
25
+ userId: await user?.(session),
25
26
  };
26
- await handler(ctx, next, requestContext);
27
- }
27
+ await handler({ session, context: _context, intercepts }, implementation);
28
+ };
@@ -2,15 +2,13 @@
2
2
  * Copyright 2025 The Artinet Project
3
3
  * SPDX-License-Identifier: Apache-2.0
4
4
  */
5
- import * as hono from "hono";
6
- import { ResultOrError } from "../../types.js";
7
- export declare function toJSONRPCResponse(id: string, result_or_error: ResultOrError): {
8
- jsonrpc: "2.0";
9
- id: string;
10
- result: unknown;
11
- } | {
12
- jsonrpc: "2.0";
13
- id: string;
14
- error: unknown;
15
- };
5
+ import * as hono from 'hono';
6
+ import { ResultOrError } from '../../types.js';
7
+ /**
8
+ * Handle JSON-RPC response for Hono.
9
+ *
10
+ * Used by the deployment server to provide a standard agent endpoint interface.
11
+ *
12
+ * @module server/handlers/rpc
13
+ */
16
14
  export declare function handleJSONRPCResponse(ctx: hono.Context, id: string, method: string, response: ResultOrError): Promise<void>;
@@ -2,48 +2,47 @@
2
2
  * Copyright 2025 The Artinet Project
3
3
  * SPDX-License-Identifier: Apache-2.0
4
4
  */
5
- import * as sdk from "@artinet/sdk";
6
- import { streamSSE } from "hono/streaming";
7
- export function toJSONRPCResponse(id, result_or_error) {
8
- if (result_or_error.type === "success") {
9
- return { jsonrpc: "2.0", id, result: result_or_error.result };
10
- }
11
- if (result_or_error.type === "error") {
12
- return { jsonrpc: "2.0", id, error: result_or_error.error };
13
- }
14
- throw new Error("Invalid response type");
15
- }
5
+ import * as sdk from '@artinet/sdk';
6
+ import { streamSSE } from 'hono/streaming';
7
+ import { toJSONRPCResponse } from '../../utils.js';
8
+ /**
9
+ * Handle JSON-RPC response for Hono.
10
+ *
11
+ * Used by the deployment server to provide a standard agent endpoint interface.
12
+ *
13
+ * @module server/handlers/rpc
14
+ */
16
15
  export async function handleJSONRPCResponse(ctx, id, method, response) {
17
- if (response.type === "success" && method === "agentcard/get") {
16
+ if (response.type === 'success' && method === 'agentcard/get') {
18
17
  ctx.status(200);
19
18
  ctx.res = ctx.json(response.result);
20
19
  return;
21
20
  }
22
- if (response.type === "success") {
21
+ if (response.type === 'success') {
23
22
  ctx.status(200);
24
23
  ctx.res = ctx.json(toJSONRPCResponse(String(id), response));
25
24
  return;
26
25
  }
27
- if (response.type === "error") {
26
+ if (response.type === 'error') {
28
27
  ctx.status(500);
29
28
  ctx.res = ctx.json(toJSONRPCResponse(String(id), response));
30
29
  return;
31
30
  }
32
- if (response.type === "stream") {
31
+ if (response.type === 'stream') {
33
32
  const stream = response.stream;
34
33
  ctx.res = streamSSE(ctx, async (responseStream) => {
35
34
  for await (const data of stream) {
36
35
  responseStream.writeSSE({
37
- data: JSON.stringify({ jsonrpc: "2.0", id, result: data }),
36
+ data: JSON.stringify({ jsonrpc: '2.0', id, result: data }),
38
37
  });
39
38
  }
40
39
  responseStream.close();
41
40
  });
42
41
  ctx.status(200);
43
- ctx.res.headers.set("Content-Type", "text/event-stream");
44
- ctx.res.headers.set("Cache-Control", "no-cache");
45
- ctx.res.headers.set("Connection", "keep-alive");
42
+ ctx.res.headers.set('Content-Type', 'text/event-stream');
43
+ ctx.res.headers.set('Cache-Control', 'no-cache');
44
+ ctx.res.headers.set('Connection', 'keep-alive');
46
45
  return;
47
46
  }
48
- throw sdk.INTERNAL_ERROR({ message: "Unknown response type" });
47
+ throw sdk.INTERNAL_ERROR({ message: 'Unknown response type' });
49
48
  }
@@ -2,13 +2,14 @@
2
2
  * Copyright 2025 The Artinet Project
3
3
  * SPDX-License-Identifier: Apache-2.0
4
4
  */
5
- import * as hono from "hono";
6
- import { type ServerType } from "@hono/node-server";
7
- import { CreateAgentRoute } from "../../routes/create/index.js";
8
- import { Settings as FleetSettings } from "../../settings.js";
9
- import * as agent from "./agent-request.js";
10
- import * as testing from "./test-request.js";
11
- import * as deployment from "./deploy-request.js";
5
+ import * as hono from 'hono';
6
+ import { type ServerType } from '@hono/node-server';
7
+ import { CreateAgentRoute } from '../../routes/create/index.js';
8
+ import { Settings as FleetSettings } from '../../settings.js';
9
+ import * as agent from './agent-request.js';
10
+ import * as testing from './test-request.js';
11
+ import * as deployment from './deploy-request.js';
12
+ import { Session } from './types.js';
12
13
  /**
13
14
  * Extended settings for the Hono Fleet server.
14
15
  *
@@ -18,14 +19,14 @@ import * as deployment from "./deploy-request.js";
18
19
  * @see {@link https://hono.dev/docs/guides/middleware Hono Middleware Guide}
19
20
  */
20
21
  export type Settings = FleetSettings & {
21
- /** Extracts the user ID from the Hono context. Used for multi-tenant agent isolation. */
22
- user?: (ctx: hono.Context) => Promise<string>;
22
+ /** Extracts the user ID from the session. Used for multi-tenant agent isolation. */
23
+ user?: (session: Session) => Promise<string>;
23
24
  /** Handler for agent retrieval requests. Generated via {@link agent.factory}. */
24
- retrieve?: agent.handler;
25
+ retrieve?: agent.Mount['handler'];
25
26
  /** Handler for agent deployment requests. Generated via {@link deployment.factory}. */
26
- deploy?: deployment.handler;
27
+ deploy?: deployment.Mount['handler'];
27
28
  /** Handler for agent test/evaluation requests. Generated via {@link testing.factory}. */
28
- evaluate?: testing.handler;
29
+ evaluate?: testing.Mount['handler'];
29
30
  /**
30
31
  * Authentication middleware applied to protected routes.
31
32
  * @see {@link https://hono.dev/docs/guides/middleware#middleware-argument Middleware Guide}
@@ -89,10 +90,10 @@ export interface Options {
89
90
  * export default app; // For Cloudflare Workers
90
91
  * ```
91
92
  */
92
- export declare function fleet(settings?: Partial<Settings>, { app, authOnRetrieve, enableTesting, }?: Options): {
93
+ export declare function fleet(settings?: Partial<Settings>, { app, authOnRetrieve, enableTesting }?: Options): {
93
94
  app: hono.Hono;
94
95
  launch: (port: number) => ServerType;
95
- ship: (agents: CreateAgentRoute["request"][], userId?: string) => Promise<{
96
+ ship: (agents: CreateAgentRoute['request'][], userId?: string) => Promise<{
96
97
  launch: (port?: number) => ServerType;
97
98
  }>;
98
99
  };
@@ -2,27 +2,22 @@
2
2
  * Copyright 2025 The Artinet Project
3
3
  * SPDX-License-Identifier: Apache-2.0
4
4
  */
5
- import * as hono from "hono";
6
- import { serve } from "@hono/node-server";
7
- import * as sdk from "@artinet/sdk";
8
- import { DEFAULTS } from "../../default.js";
9
- import * as agent from "./agent-request.js";
10
- import * as testing from "./test-request.js";
11
- import * as deployment from "./deploy-request.js";
12
- import { AGENT_FIELD_NAME } from "./agent-request.js";
13
- import { errorHandler } from "./error-handler.js";
5
+ import * as hono from 'hono';
6
+ import { serve } from '@hono/node-server';
7
+ import * as sdk from '@artinet/sdk';
8
+ import { DEFAULTS, AGENT_FIELD_NAME } from '../../default.js';
9
+ import * as agent from './agent-request.js';
10
+ import * as testing from './test-request.js';
11
+ import * as deployment from './deploy-request.js';
12
+ import { errorHandler } from './error-handler.js';
14
13
  const createContext = (settings) => {
15
14
  const _settings = {
16
15
  ...DEFAULTS,
17
16
  ...settings,
18
- retrieve: agent.factory(settings.get ?? DEFAULTS.get,
19
- /**Middleware addons are currently only supported on the agent request route */
20
- settings.middleware?.build() ?? []),
21
- deploy: deployment.factory(settings.set ?? DEFAULTS.set),
22
- evaluate: testing.factory(settings.test ?? DEFAULTS.test),
23
- user: settings.user
24
- ? settings.user
25
- : (_ctx) => Promise.resolve(settings.userId ?? "default"),
17
+ retrieve: agent.factory({ implementation: settings.get ?? DEFAULTS.get }),
18
+ deploy: deployment.factory({ implementation: settings.set ?? DEFAULTS.set }),
19
+ evaluate: testing.factory({ implementation: settings.test ?? DEFAULTS.test }),
20
+ user: settings.user ? settings.user : (_session) => Promise.resolve(settings.userId ?? 'default'),
26
21
  };
27
22
  return _settings;
28
23
  };
@@ -85,11 +80,10 @@ const createRequestContext = (context) => {
85
80
  * export default app; // For Cloudflare Workers
86
81
  * ```
87
82
  */
88
- export function fleet(settings = DEFAULTS, { app = new hono.Hono(), authOnRetrieve = false, enableTesting = true, } = {}) {
83
+ export function fleet(settings = DEFAULTS, { app = new hono.Hono(), authOnRetrieve = false, enableTesting = true } = {}) {
89
84
  const context = createContext(settings);
90
- const { basePath, agentPath, fallbackPath, deploymentPath, testPath, auth, user, evaluate, deploy, retrieve, set, } = context;
85
+ const { basePath, agentPath, fallbackPath, deploymentPath, testPath, auth, user, evaluate, deploy, retrieve, set } = context;
91
86
  const router = new hono.Hono();
92
- // router.use(hono.json());
93
87
  router.onError(errorHandler);
94
88
  if (auth) {
95
89
  router.use(testPath, auth);
@@ -101,33 +95,31 @@ export function fleet(settings = DEFAULTS, { app = new hono.Hono(), authOnRetrie
101
95
  }
102
96
  if (enableTesting === true && evaluate !== undefined) {
103
97
  router.post(testPath, async (ctx, next) => await testing.request({
104
- ctx,
105
- next,
98
+ session: { ctx, next },
106
99
  context: createRequestContext(context),
107
100
  handler: evaluate,
108
101
  user,
109
102
  }));
110
103
  }
111
104
  router.post(deploymentPath, async (ctx, next) => await deployment.request({
112
- ctx,
113
- next,
105
+ session: { ctx, next },
114
106
  context: createRequestContext(context),
115
107
  handler: deploy,
116
108
  user,
117
109
  }));
118
110
  router.use(`${agentPath}/:${AGENT_FIELD_NAME}/*`, async (ctx, next) => await agent.request({
119
- ctx,
120
- next,
111
+ session: { ctx, next },
121
112
  context: createRequestContext(context),
122
113
  handler: retrieve,
123
114
  user,
115
+ intercepts: settings.middleware?.build() ?? [],
124
116
  }));
125
117
  router.use(`${fallbackPath}/:${AGENT_FIELD_NAME}/*`, async (ctx, next) => await agent.request({
126
- ctx,
127
- next,
118
+ session: { ctx, next },
128
119
  context: createRequestContext(context),
129
120
  handler: retrieve,
130
121
  user,
122
+ intercepts: settings.middleware?.build() ?? [],
131
123
  }));
132
124
  app.route(basePath, router);
133
125
  const launch = (port = 3000) => {
@@ -147,19 +139,3 @@ export function fleet(settings = DEFAULTS, { app = new hono.Hono(), authOnRetrie
147
139
  };
148
140
  return { app, launch, ship };
149
141
  }
150
- // const swarm = await fleet().ship([
151
- // {
152
- // config: {
153
- // uri: "my-agent",
154
- // name: "my-agent",
155
- // description: "A helpful assistant",
156
- // modelId: "gpt-4",
157
- // instructions: "You are a helpful assistant.",
158
- // version: "1.0.0",
159
- // skills: [],
160
- // capabilities: {},
161
- // services: [],
162
- // },
163
- // },
164
- // ]);
165
- // swarm.launch(3000);
@@ -2,16 +2,9 @@
2
2
  * Copyright 2025 The Artinet Project
3
3
  * SPDX-License-Identifier: Apache-2.0
4
4
  */
5
- import * as hono from "hono";
6
- import { TestAgentRoute } from "../../routes/request/index.js";
7
- export type handler = (ctx: hono.Context, next: hono.Next, context: TestAgentRoute["context"], test?: TestAgentRoute["implementation"]) => Promise<void>;
8
- export declare function handle(ctx: hono.Context, _next: hono.Next, context: TestAgentRoute["context"], test?: TestAgentRoute["implementation"]): Promise<void>;
9
- export declare const factory: (test?: TestAgentRoute["implementation"]) => handler;
10
- export interface Params {
11
- ctx: hono.Context;
12
- next: hono.Next;
13
- context: Omit<TestAgentRoute["context"], "agentId">;
14
- handler: handler;
15
- user: (ctx: hono.Context) => Promise<string>;
16
- }
17
- export declare function request({ ctx, next, context, handler, user, }: Params): Promise<hono.Context["res"]>;
5
+ import { TestAgentMount } from '../../routes/request/index.js';
6
+ import { Session } from './types.js';
7
+ export type Mount = TestAgentMount<Session>;
8
+ export declare const factory: Mount['factory'];
9
+ export declare const handle: Mount['handler'];
10
+ export declare const request: Mount['request'];
@@ -2,25 +2,11 @@
2
2
  * Copyright 2025 The Artinet Project
3
3
  * SPDX-License-Identifier: Apache-2.0
4
4
  */
5
- import * as sdk from "@artinet/sdk";
6
- import { TestAgent, TestRequestSchema, } from "../../routes/request/index.js";
7
- import { v4 as uuidv4 } from "uuid";
8
- import { handleJSONRPCResponse } from "./rpc.js";
9
- import { generateRequestId } from "./utils.js";
10
- export async function handle(ctx, _next, context, test = TestAgent) {
11
- /* hono.Context.req uses a raw JSON.parse() so we prefer to use the text() and our own safeParse() */
12
- const req = sdk.safeParse(await ctx.req.text());
13
- let parsed = await sdk.validateSchema(TestRequestSchema, req);
14
- let id = parsed.id ?? uuidv4();
15
- parsed.id = id;
16
- let request = parsed;
17
- context.target = parsed.config;
18
- request.method = "test/invoke";
19
- request.params = null;
20
- const response = await test(request, context);
21
- await handleJSONRPCResponse(ctx, String(id), request.method, response);
22
- }
23
- export const factory = (test = TestAgent) => async (ctx, next, context) => await handle(ctx, next, context, test);
5
+ import * as sdk from '@artinet/sdk';
6
+ import { TestAgent, TestRequestSchema, } from '../../routes/request/index.js';
7
+ import { v4 as uuidv4 } from 'uuid';
8
+ import { handleJSONRPCResponse } from './rpc.js';
9
+ import { generateRequestId } from './utils.js';
24
10
  const MAX_TEST_ID_ATTEMPTS = 10;
25
11
  const getTestId = async (context) => {
26
12
  let testId = uuidv4();
@@ -42,15 +28,29 @@ const getTestId = async (context) => {
42
28
  }
43
29
  return testId;
44
30
  };
45
- export async function request({ ctx, next, context, handler = handle, user, }) {
31
+ export const factory = ({ implementation = TestAgent }) => async (params) => await handle(params, implementation);
32
+ export const handle = async ({ session: { ctx }, context, intercepts }, implementation = TestAgent) => {
33
+ /* hono.Context.req uses a raw JSON.parse() so we prefer to use the text() and our own safeParse() */
34
+ const req = sdk.safeParse(await ctx.req.text());
35
+ let parsed = await sdk.validateSchema(TestRequestSchema, req);
36
+ let id = parsed.id ?? uuidv4();
37
+ parsed.id = id;
38
+ let request = parsed;
39
+ context.target = parsed.config;
40
+ request.method = 'test/invoke';
41
+ request.params = null;
42
+ const response = await implementation(request, context, intercepts);
43
+ return await handleJSONRPCResponse(ctx, String(id), request.method, response);
44
+ };
45
+ export const request = async ({ session, context, handler = handle, user, intercepts }, implementation = TestAgent) => {
46
+ const { ctx } = session;
46
47
  /* hono.Context.req uses a raw JSON.parse() so we prefer to use the text() and our own safeParse() */
47
- const reqId = ctx.req.header("x-request-id") ?? sdk.safeParse(await ctx.req.text())?.id;
48
- const requestContext = {
48
+ const reqId = ctx.req.header('x-request-id') ?? sdk.safeParse(await ctx.req.text())?.id;
49
+ const _context = {
49
50
  ...context,
50
51
  agentId: await getTestId(context),
51
52
  requestId: generateRequestId(context, reqId),
52
- userId: await user?.(ctx),
53
+ userId: await user?.(session),
53
54
  };
54
- await handler(ctx, next, requestContext);
55
- return ctx.res;
56
- }
55
+ return await handler({ session, context: _context, intercepts }, implementation);
56
+ };
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Copyright 2025 The Artinet Project
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+ import * as hono from 'hono';
6
+ export type Session = {
7
+ ctx: hono.Context;
8
+ next: hono.Next;
9
+ };
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Copyright 2025 The Artinet Project
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+ export {};
@@ -0,0 +1,11 @@
1
+ import { ResultOrError } from './types.js';
2
+ export declare function sanitizeString(str: string): string;
3
+ export declare function toJSONRPCResponse(id: string, result_or_error: ResultOrError): {
4
+ jsonrpc: '2.0';
5
+ id: string;
6
+ result: unknown;
7
+ } | {
8
+ jsonrpc: '2.0';
9
+ id: string;
10
+ error: unknown;
11
+ };
package/dist/utils.js ADDED
@@ -0,0 +1,13 @@
1
+ import escapeHtml from 'escape-html';
2
+ export function sanitizeString(str) {
3
+ return escapeHtml(str).trim();
4
+ }
5
+ export function toJSONRPCResponse(id, result_or_error) {
6
+ if (result_or_error.type === 'success') {
7
+ return { jsonrpc: '2.0', id: sanitizeString(id), result: result_or_error.result };
8
+ }
9
+ if (result_or_error.type === 'error') {
10
+ return { jsonrpc: '2.0', id: sanitizeString(id), error: result_or_error.error };
11
+ }
12
+ throw new Error('Invalid response type');
13
+ }