@agentick/express 0.0.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/dist/index.js ADDED
@@ -0,0 +1,114 @@
1
+ /**
2
+ * @agentick/express - Express adapter for Agentick Gateway
3
+ *
4
+ * Provides an Express middleware that delegates to Gateway.
5
+ * This is a thin adapter - all business logic lives in @agentick/gateway.
6
+ *
7
+ * @example Quick start
8
+ * ```typescript
9
+ * import express from "express";
10
+ * import { createAgentickMiddleware } from "@agentick/express";
11
+ * import { createApp } from "@agentick/core";
12
+ *
13
+ * const app = express();
14
+ * app.use(express.json());
15
+ *
16
+ * const agentickApp = createApp(<MyAgent />);
17
+ *
18
+ * app.use("/api", createAgentickMiddleware({
19
+ * apps: { assistant: agentickApp },
20
+ * defaultApp: "assistant",
21
+ * }));
22
+ *
23
+ * const server = app.listen(3000);
24
+ *
25
+ * // Cleanup on shutdown
26
+ * process.on("SIGTERM", () => server.close());
27
+ * ```
28
+ *
29
+ * @example With custom methods and auth
30
+ * ```typescript
31
+ * import { createAgentickMiddleware, method } from "@agentick/express";
32
+ * import { z } from "zod";
33
+ *
34
+ * app.use("/api", createAgentickMiddleware({
35
+ * apps: { assistant: agentickApp },
36
+ * defaultApp: "assistant",
37
+ * auth: {
38
+ * type: "custom",
39
+ * validate: async (token) => {
40
+ * const user = await verifyToken(token);
41
+ * return user ? { valid: true, user } : { valid: false };
42
+ * },
43
+ * },
44
+ * methods: {
45
+ * tasks: {
46
+ * list: method({
47
+ * schema: z.object({ sessionId: z.string() }),
48
+ * handler: async (params) => todoService.list(params.sessionId),
49
+ * }),
50
+ * },
51
+ * },
52
+ * }));
53
+ * ```
54
+ *
55
+ * @module @agentick/express
56
+ */
57
+ import { Router } from "express";
58
+ import { Gateway } from "@agentick/gateway";
59
+ /**
60
+ * Create Express middleware that delegates to Gateway.
61
+ *
62
+ * @param gatewayConfig - Gateway configuration (apps, methods, auth, etc.)
63
+ * @param options - Optional Express-specific options
64
+ * @returns Express Router middleware with attached gateway
65
+ *
66
+ * @example
67
+ * ```typescript
68
+ * const middleware = createAgentickMiddleware({
69
+ * apps: { assistant: myApp },
70
+ * defaultApp: "assistant",
71
+ * });
72
+ *
73
+ * app.use("/api", middleware);
74
+ *
75
+ * // Access gateway for lifecycle management
76
+ * process.on("SIGTERM", () => middleware.gateway.close());
77
+ * ```
78
+ */
79
+ export function createAgentickMiddleware(gatewayConfig, options = {}) {
80
+ // Create gateway in embedded mode
81
+ const gateway = new Gateway({
82
+ ...gatewayConfig,
83
+ embedded: true,
84
+ });
85
+ const router = Router();
86
+ // Attach gateway for lifecycle management
87
+ router.gateway = gateway;
88
+ // Delegate all requests to gateway
89
+ router.use((req, res, next) => {
90
+ // Optionally inject token from custom extractor
91
+ if (options.getToken) {
92
+ const token = options.getToken(req);
93
+ if (token) {
94
+ req.headers.authorization = `Bearer ${token}`;
95
+ }
96
+ }
97
+ // Delegate to gateway
98
+ gateway.handleRequest(req, res).catch(next);
99
+ });
100
+ return router;
101
+ }
102
+ /**
103
+ * Get the Gateway instance from middleware for advanced use.
104
+ * Useful for lifecycle management, events, etc.
105
+ */
106
+ export function createAgentickGateway(gatewayConfig) {
107
+ return new Gateway({
108
+ ...gatewayConfig,
109
+ embedded: true,
110
+ });
111
+ }
112
+ // Re-export gateway types for convenience
113
+ export { Gateway, method, } from "@agentick/gateway";
114
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuDG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAEjC,OAAO,EAAE,OAAO,EAAsB,MAAM,mBAAmB,CAAC;AA2BhE;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,UAAU,wBAAwB,CACtC,aAAoC,EACpC,UAAqC,EAAE;IAEvC,kCAAkC;IAClC,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC;QAC1B,GAAG,aAAa;QAChB,QAAQ,EAAE,IAAI;KACf,CAAC,CAAC;IAEH,MAAM,MAAM,GAAG,MAAM,EAAoB,CAAC;IAE1C,0CAA0C;IAC1C,MAAM,CAAC,OAAO,GAAG,OAAO,CAAC;IAEzB,mCAAmC;IACnC,MAAM,CAAC,GAAG,CAAC,CAAC,GAAY,EAAE,GAAa,EAAE,IAAkB,EAAE,EAAE;QAC7D,gDAAgD;QAChD,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;YACrB,MAAM,KAAK,GAAG,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;YACpC,IAAI,KAAK,EAAE,CAAC;gBACV,GAAG,CAAC,OAAO,CAAC,aAAa,GAAG,UAAU,KAAK,EAAE,CAAC;YAChD,CAAC;QACH,CAAC;QAED,sBAAsB;QACtB,OAAO,CAAC,aAAa,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC9C,CAAC,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,qBAAqB,CAAC,aAAoC;IACxE,OAAO,IAAI,OAAO,CAAC;QACjB,GAAG,aAAa;QAChB,QAAQ,EAAE,IAAI;KACf,CAAC,CAAC;AACL,CAAC;AAED,0CAA0C;AAC1C,OAAO,EACL,OAAO,EACP,MAAM,GAIP,MAAM,mBAAmB,CAAC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Express handler factory for Tentickle (multiplexed sessions).
3
+ *
4
+ * @module @tentickle/express/router
5
+ */
6
+ import { Router } from "express";
7
+ import type { App } from "@tentickle/core/app";
8
+ import type { TentickleHandlerOptions } from "./types";
9
+ export declare function createTentickleHandler<User = unknown>(app: App, options?: TentickleHandlerOptions<User>): Router;
10
+ //# sourceMappingURL=router.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../src/router.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAEjC,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,qBAAqB,CAAC;AAW/C,OAAO,KAAK,EAAE,uBAAuB,EAAoB,MAAM,SAAS,CAAC;AAiCzE,wBAAgB,sBAAsB,CAAC,IAAI,GAAG,OAAO,EACnD,GAAG,EAAE,GAAG,EACR,OAAO,GAAE,uBAAuB,CAAC,IAAI,CAAM,GAC1C,MAAM,CAiXR"}
package/dist/router.js ADDED
@@ -0,0 +1,367 @@
1
+ /**
2
+ * Express handler factory for Tentickle (multiplexed sessions).
3
+ *
4
+ * @module @tentickle/express/router
5
+ */
6
+ import { Router } from "express";
7
+ import { createSSEWriter, setSSEHeaders } from "@tentickle/server";
8
+ function parseSubscribeParam(value) {
9
+ if (!value)
10
+ return [];
11
+ if (Array.isArray(value)) {
12
+ return value
13
+ .flatMap((entry) => String(entry).split(","))
14
+ .map((id) => id.trim())
15
+ .filter(Boolean);
16
+ }
17
+ return String(value)
18
+ .split(",")
19
+ .map((id) => id.trim())
20
+ .filter(Boolean);
21
+ }
22
+ function isSendInput(value) {
23
+ if (!value || typeof value !== "object")
24
+ return false;
25
+ const input = value;
26
+ const hasMessage = !!input.message;
27
+ const hasMessages = Array.isArray(input.messages);
28
+ return (hasMessage && !hasMessages) || (!hasMessage && hasMessages);
29
+ }
30
+ export function createTentickleHandler(app, options = {}) {
31
+ const router = Router();
32
+ const paths = {
33
+ events: options.paths?.events ?? "/events",
34
+ send: options.paths?.send ?? "/send",
35
+ subscribe: options.paths?.subscribe ?? "/subscribe",
36
+ abort: options.paths?.abort ?? "/abort",
37
+ close: options.paths?.close ?? "/close",
38
+ toolResponse: options.paths?.toolResponse ?? "/tool-response",
39
+ channel: options.paths?.channel ?? "/channel",
40
+ };
41
+ const sseKeepaliveInterval = options.sseKeepaliveInterval ?? 15000;
42
+ const connections = new Map();
43
+ const sessionSubscribers = new Map();
44
+ const sessionListeners = new Map();
45
+ // Track channel listeners per session: Map<sessionId, Map<channelName, unsubscribe>>
46
+ const sessionChannelListeners = new Map();
47
+ const getUserContext = async (req) => {
48
+ const user = options.authenticate ? await options.authenticate(req) : undefined;
49
+ const userId = options.getUserId ? await options.getUserId(req, user) : undefined;
50
+ return { user, userId };
51
+ };
52
+ const authorize = async (req, user, sessionId) => {
53
+ if (!options.authorize)
54
+ return true;
55
+ return await options.authorize(user, sessionId, req);
56
+ };
57
+ const ensureSessionListener = (sessionId) => {
58
+ if (sessionListeners.has(sessionId))
59
+ return;
60
+ const session = app.session(sessionId);
61
+ const listener = (event) => {
62
+ const subscribers = sessionSubscribers.get(sessionId);
63
+ if (!subscribers)
64
+ return;
65
+ for (const connectionId of subscribers) {
66
+ const connection = connections.get(connectionId);
67
+ if (!connection || connection.closed)
68
+ continue;
69
+ connection.writer.writeEvent({ ...event, sessionId });
70
+ }
71
+ };
72
+ session.on("event", listener);
73
+ session.once("close", () => {
74
+ sessionListeners.delete(sessionId);
75
+ sessionSubscribers.delete(sessionId);
76
+ // Clean up channel listeners for this session
77
+ const channelListeners = sessionChannelListeners.get(sessionId);
78
+ if (channelListeners) {
79
+ for (const unsubscribe of channelListeners.values()) {
80
+ unsubscribe();
81
+ }
82
+ sessionChannelListeners.delete(sessionId);
83
+ }
84
+ });
85
+ sessionListeners.set(sessionId, listener);
86
+ };
87
+ /**
88
+ * Ensure we're subscribed to a specific channel on a session.
89
+ * Channel events are forwarded to all connections subscribed to the session.
90
+ */
91
+ const ensureChannelListener = (sessionId, channelName) => {
92
+ let channelListeners = sessionChannelListeners.get(sessionId);
93
+ if (!channelListeners) {
94
+ channelListeners = new Map();
95
+ sessionChannelListeners.set(sessionId, channelListeners);
96
+ }
97
+ if (channelListeners.has(channelName))
98
+ return;
99
+ const session = app.session(sessionId);
100
+ const channel = session.channel(channelName);
101
+ const unsubscribe = channel.subscribe((event) => {
102
+ const subscribers = sessionSubscribers.get(sessionId);
103
+ if (!subscribers)
104
+ return;
105
+ const sseEvent = {
106
+ type: "channel",
107
+ sessionId,
108
+ channel: channelName,
109
+ event,
110
+ };
111
+ for (const connectionId of subscribers) {
112
+ const connection = connections.get(connectionId);
113
+ if (!connection || connection.closed)
114
+ continue;
115
+ connection.writer.writeEvent(sseEvent);
116
+ }
117
+ });
118
+ channelListeners.set(channelName, unsubscribe);
119
+ };
120
+ const subscribeConnection = async (connectionId, sessionId, req, user) => {
121
+ const connection = connections.get(connectionId);
122
+ if (!connection || connection.closed)
123
+ return;
124
+ if (!(await authorize(req, user, sessionId))) {
125
+ throw new Error("Unauthorized");
126
+ }
127
+ app.session(sessionId);
128
+ ensureSessionListener(sessionId);
129
+ connection.subscriptions.add(sessionId);
130
+ const subscribers = sessionSubscribers.get(sessionId) ?? new Set();
131
+ subscribers.add(connectionId);
132
+ sessionSubscribers.set(sessionId, subscribers);
133
+ };
134
+ const unsubscribeConnection = (connectionId, sessionId) => {
135
+ const connection = connections.get(connectionId);
136
+ if (!connection)
137
+ return;
138
+ connection.subscriptions.delete(sessionId);
139
+ const subscribers = sessionSubscribers.get(sessionId);
140
+ if (!subscribers)
141
+ return;
142
+ subscribers.delete(connectionId);
143
+ if (subscribers.size === 0) {
144
+ sessionSubscribers.delete(sessionId);
145
+ const listener = sessionListeners.get(sessionId);
146
+ if (listener && app.has(sessionId)) {
147
+ const session = app.session(sessionId);
148
+ session.off("event", listener);
149
+ }
150
+ sessionListeners.delete(sessionId);
151
+ }
152
+ };
153
+ router.get(paths.events, async (req, res, next) => {
154
+ try {
155
+ const { user, userId } = await getUserContext(req);
156
+ req.tentickle = { user, userId };
157
+ setSSEHeaders(res);
158
+ const writer = createSSEWriter(res, { keepaliveInterval: sseKeepaliveInterval });
159
+ const connectionId = `conn-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`;
160
+ const connection = {
161
+ id: connectionId,
162
+ writer,
163
+ subscriptions: new Set(),
164
+ user,
165
+ userId,
166
+ closed: false,
167
+ };
168
+ connections.set(connectionId, connection);
169
+ const initialSubscriptions = parseSubscribeParam(req.query.subscribe);
170
+ for (const sessionId of initialSubscriptions) {
171
+ await subscribeConnection(connectionId, sessionId, req, user);
172
+ }
173
+ writer.writeEvent({
174
+ type: "connection",
175
+ connectionId,
176
+ subscriptions: Array.from(connection.subscriptions),
177
+ });
178
+ req.on("close", () => {
179
+ connection.closed = true;
180
+ for (const sessionId of connection.subscriptions) {
181
+ unsubscribeConnection(connectionId, sessionId);
182
+ }
183
+ connections.delete(connectionId);
184
+ writer.close();
185
+ });
186
+ }
187
+ catch (err) {
188
+ next(err);
189
+ }
190
+ });
191
+ router.post(paths.subscribe, async (req, res, next) => {
192
+ try {
193
+ const { user } = await getUserContext(req);
194
+ const { connectionId, add, remove } = req.body ?? {};
195
+ if (!connectionId) {
196
+ res.status(400).json({ error: "INVALID_REQUEST", message: "connectionId is required" });
197
+ return;
198
+ }
199
+ for (const sessionId of add ?? []) {
200
+ await subscribeConnection(connectionId, sessionId, req, user);
201
+ }
202
+ for (const sessionId of remove ?? []) {
203
+ unsubscribeConnection(connectionId, sessionId);
204
+ }
205
+ res.json({ success: true });
206
+ }
207
+ catch (err) {
208
+ if (err instanceof Error && err.message === "Unauthorized") {
209
+ res.status(403).json({ error: "UNAUTHORIZED", message: "Unauthorized" });
210
+ return;
211
+ }
212
+ next(err);
213
+ }
214
+ });
215
+ router.post(paths.send, async (req, res, next) => {
216
+ try {
217
+ const { sessionId, ...rest } = req.body ?? {};
218
+ if (!isSendInput(rest)) {
219
+ res.status(400).json({
220
+ error: "INVALID_REQUEST",
221
+ message: "Provide either message or messages (but not both).",
222
+ });
223
+ return;
224
+ }
225
+ const handle = app.send(rest, { sessionId });
226
+ setSSEHeaders(res);
227
+ for await (const event of handle) {
228
+ res.write(`data: ${JSON.stringify({ ...event, sessionId: handle.sessionId })}\n\n`);
229
+ }
230
+ res.end();
231
+ }
232
+ catch (err) {
233
+ next(err);
234
+ }
235
+ });
236
+ router.post(paths.abort, async (req, res, next) => {
237
+ try {
238
+ const { sessionId, reason } = req.body ?? {};
239
+ if (!sessionId || !app.has(sessionId)) {
240
+ res.status(404).json({ error: "SESSION_NOT_FOUND", message: "Session not found" });
241
+ return;
242
+ }
243
+ const session = app.session(sessionId);
244
+ session.interrupt(undefined, reason);
245
+ res.json({ success: true });
246
+ }
247
+ catch (err) {
248
+ next(err);
249
+ }
250
+ });
251
+ router.post(paths.close, async (req, res, next) => {
252
+ try {
253
+ const { sessionId } = req.body ?? {};
254
+ if (!sessionId) {
255
+ res.status(400).json({ error: "INVALID_REQUEST", message: "sessionId is required" });
256
+ return;
257
+ }
258
+ await app.close(sessionId);
259
+ res.json({ success: true });
260
+ }
261
+ catch (err) {
262
+ next(err);
263
+ }
264
+ });
265
+ router.post(paths.toolResponse, async (req, res, next) => {
266
+ try {
267
+ const { sessionId, toolUseId, response } = req.body ?? {};
268
+ if (!sessionId || !app.has(sessionId)) {
269
+ res.status(404).json({ error: "SESSION_NOT_FOUND", message: "Session not found" });
270
+ return;
271
+ }
272
+ if (!toolUseId || !response) {
273
+ res
274
+ .status(400)
275
+ .json({ error: "INVALID_REQUEST", message: "toolUseId and response are required" });
276
+ return;
277
+ }
278
+ const session = app.session(sessionId);
279
+ await session.submitToolResult(toolUseId, response);
280
+ res.json({ success: true });
281
+ }
282
+ catch (err) {
283
+ next(err);
284
+ }
285
+ });
286
+ /**
287
+ * Publish to a session channel.
288
+ * This allows client → server channel communication.
289
+ */
290
+ router.post(paths.channel, async (req, res, next) => {
291
+ try {
292
+ const { user } = await getUserContext(req);
293
+ const body = req.body;
294
+ if (!body?.sessionId) {
295
+ res.status(400).json({ error: "INVALID_REQUEST", message: "sessionId is required" });
296
+ return;
297
+ }
298
+ if (!body?.channel) {
299
+ res.status(400).json({ error: "INVALID_REQUEST", message: "channel is required" });
300
+ return;
301
+ }
302
+ if (!body?.type) {
303
+ res.status(400).json({ error: "INVALID_REQUEST", message: "type is required" });
304
+ return;
305
+ }
306
+ // Authorize access to session
307
+ if (!(await authorize(req, user, body.sessionId))) {
308
+ res.status(403).json({ error: "UNAUTHORIZED", message: "Unauthorized" });
309
+ return;
310
+ }
311
+ if (!app.has(body.sessionId)) {
312
+ res.status(404).json({ error: "SESSION_NOT_FOUND", message: "Session not found" });
313
+ return;
314
+ }
315
+ const session = app.session(body.sessionId);
316
+ // Publish to the channel
317
+ const event = {
318
+ type: body.type,
319
+ channel: body.channel,
320
+ payload: body.payload,
321
+ id: body.id,
322
+ metadata: {
323
+ timestamp: Date.now(),
324
+ ...body.metadata,
325
+ },
326
+ };
327
+ session.channel(body.channel).publish(event);
328
+ res.json({ success: true });
329
+ }
330
+ catch (err) {
331
+ next(err);
332
+ }
333
+ });
334
+ /**
335
+ * Subscribe to a channel on a session.
336
+ * This ensures server → client channel events are forwarded.
337
+ */
338
+ router.post(`${paths.channel}/subscribe`, async (req, res, next) => {
339
+ try {
340
+ const { user } = await getUserContext(req);
341
+ const { sessionId, channel: channelName } = req.body ?? {};
342
+ if (!sessionId) {
343
+ res.status(400).json({ error: "INVALID_REQUEST", message: "sessionId is required" });
344
+ return;
345
+ }
346
+ if (!channelName) {
347
+ res.status(400).json({ error: "INVALID_REQUEST", message: "channel is required" });
348
+ return;
349
+ }
350
+ // Authorize access to session
351
+ if (!(await authorize(req, user, sessionId))) {
352
+ res.status(403).json({ error: "UNAUTHORIZED", message: "Unauthorized" });
353
+ return;
354
+ }
355
+ // Get or create session (creates if doesn't exist)
356
+ app.session(sessionId);
357
+ // Set up channel listener for this session (uses session internally)
358
+ ensureChannelListener(sessionId, channelName);
359
+ res.json({ success: true });
360
+ }
361
+ catch (err) {
362
+ next(err);
363
+ }
364
+ });
365
+ return router;
366
+ }
367
+ //# sourceMappingURL=router.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"router.js","sourceRoot":"","sources":["../src/router.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,75 @@
1
+ /**
2
+ * Express integration types for Tentickle.
3
+ *
4
+ * @module @tentickle/express/types
5
+ */
6
+ import type { Request } from "express";
7
+ /**
8
+ * Configuration for the Tentickle Express router.
9
+ */
10
+ export interface TentickleHandlerOptions<User = unknown> {
11
+ /**
12
+ * Extract authentication token from request.
13
+ * Called for each request to get user identity.
14
+ *
15
+ * @example
16
+ * ```typescript
17
+ * authenticate: (req) => req.headers.authorization?.replace('Bearer ', '')
18
+ * ```
19
+ */
20
+ authenticate?: (req: Request) => User | undefined | Promise<User | undefined>;
21
+ /**
22
+ * Authorization hook for session access.
23
+ * Return true to allow, false to deny.
24
+ */
25
+ authorize?: (user: User | undefined, sessionId: string, req: Request) => boolean | Promise<boolean>;
26
+ /**
27
+ * Extract user ID from request.
28
+ * Called after authenticate, can use req.user if set by auth middleware.
29
+ *
30
+ * @example
31
+ * ```typescript
32
+ * getUserId: (req) => (req as any).user?.id
33
+ * ```
34
+ */
35
+ getUserId?: (req: Request, user?: User) => string | undefined | Promise<string | undefined>;
36
+ /**
37
+ * Custom path prefix for routes.
38
+ * @default ""
39
+ */
40
+ pathPrefix?: string;
41
+ /**
42
+ * Custom route paths.
43
+ */
44
+ paths?: {
45
+ /** @default "/events" */
46
+ events?: string;
47
+ /** @default "/send" */
48
+ send?: string;
49
+ /** @default "/subscribe" */
50
+ subscribe?: string;
51
+ /** @default "/abort" */
52
+ abort?: string;
53
+ /** @default "/close" */
54
+ close?: string;
55
+ /** @default "/tool-response" */
56
+ toolResponse?: string;
57
+ /** @default "/channel" */
58
+ channel?: string;
59
+ };
60
+ /**
61
+ * SSE keepalive interval in milliseconds.
62
+ * @default 15000
63
+ */
64
+ sseKeepaliveInterval?: number;
65
+ }
66
+ /**
67
+ * Extended Express Request with Tentickle context.
68
+ */
69
+ export interface TentickleRequest<User = unknown> extends Request {
70
+ tentickle?: {
71
+ user?: User;
72
+ userId?: string;
73
+ };
74
+ }
75
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAEvC;;GAEG;AACH,MAAM,WAAW,uBAAuB,CAAC,IAAI,GAAG,OAAO;IACrD;;;;;;;;OAQG;IACH,YAAY,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,IAAI,GAAG,SAAS,GAAG,OAAO,CAAC,IAAI,GAAG,SAAS,CAAC,CAAC;IAE9E;;;OAGG;IACH,SAAS,CAAC,EAAE,CACV,IAAI,EAAE,IAAI,GAAG,SAAS,EACtB,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,OAAO,KACT,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAEhC;;;;;;;;OAQG;IACH,SAAS,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,KAAK,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IAE5F;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB;;OAEG;IACH,KAAK,CAAC,EAAE;QACN,yBAAyB;QACzB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,uBAAuB;QACvB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,4BAA4B;QAC5B,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,wBAAwB;QACxB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,wBAAwB;QACxB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,gCAAgC;QAChC,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,0BAA0B;QAC1B,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB,CAAC;IAEF;;;OAGG;IACH,oBAAoB,CAAC,EAAE,MAAM,CAAC;CAC/B;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB,CAAC,IAAI,GAAG,OAAO,CAAE,SAAQ,OAAO;IAC/D,SAAS,CAAC,EAAE;QACV,IAAI,CAAC,EAAE,IAAI,CAAC;QACZ,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,CAAC;CACH"}
package/dist/types.js ADDED
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Express integration types for Tentickle.
3
+ *
4
+ * @module @tentickle/express/types
5
+ */
6
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG"}
package/package.json ADDED
@@ -0,0 +1,41 @@
1
+ {
2
+ "name": "@agentick/express",
3
+ "version": "0.0.1",
4
+ "description": "Express middleware and router for Agentick applications",
5
+ "files": [
6
+ "dist",
7
+ "src"
8
+ ],
9
+ "type": "module",
10
+ "main": "./dist/index.js",
11
+ "types": "./dist/index.d.ts",
12
+ "exports": {
13
+ ".": {
14
+ "types": "./dist/index.d.ts",
15
+ "import": "./dist/index.js"
16
+ }
17
+ },
18
+ "dependencies": {
19
+ "@agentick/gateway": "0.0.1"
20
+ },
21
+ "devDependencies": {
22
+ "@types/express": "^4.17.21",
23
+ "@types/node": "^22.10.5",
24
+ "@types/supertest": "^6.0.2",
25
+ "express": "^4.21.0",
26
+ "supertest": "^7.0.0",
27
+ "typescript": "^5.7.3",
28
+ "vitest": "^3.0.0"
29
+ },
30
+ "peerDependencies": {
31
+ "express": "^4.0.0 || ^5.0.0"
32
+ },
33
+ "scripts": {
34
+ "build": "tsc -p tsconfig.build.json",
35
+ "dev": "tsc --watch",
36
+ "typecheck": "tsc --noEmit",
37
+ "clean": "rm -rf dist",
38
+ "test": "vitest run",
39
+ "test:watch": "vitest"
40
+ }
41
+ }