@agentuity/server 0.0.5 → 0.0.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 (82) hide show
  1. package/AGENTS.md +29 -96
  2. package/README.md +31 -196
  3. package/dist/config.d.ts +11 -0
  4. package/dist/config.d.ts.map +1 -0
  5. package/dist/config.js +13 -0
  6. package/dist/config.js.map +1 -0
  7. package/dist/index.d.ts +4 -5
  8. package/dist/index.d.ts.map +1 -1
  9. package/dist/index.js +4 -0
  10. package/dist/index.js.map +1 -0
  11. package/dist/server.d.ts +22 -0
  12. package/dist/server.d.ts.map +1 -0
  13. package/dist/server.js +107 -0
  14. package/dist/server.js.map +1 -0
  15. package/package.json +11 -32
  16. package/dist/_config.d.ts +0 -61
  17. package/dist/_config.d.ts.map +0 -1
  18. package/dist/_context.d.ts +0 -33
  19. package/dist/_context.d.ts.map +0 -1
  20. package/dist/_idle.d.ts +0 -7
  21. package/dist/_idle.d.ts.map +0 -1
  22. package/dist/_server.d.ts +0 -17
  23. package/dist/_server.d.ts.map +0 -1
  24. package/dist/_services.d.ts +0 -2
  25. package/dist/_services.d.ts.map +0 -1
  26. package/dist/_util.d.ts +0 -16
  27. package/dist/_util.d.ts.map +0 -1
  28. package/dist/_waituntil.d.ts +0 -20
  29. package/dist/_waituntil.d.ts.map +0 -1
  30. package/dist/agent.d.ts +0 -88
  31. package/dist/agent.d.ts.map +0 -1
  32. package/dist/app.d.ts +0 -24
  33. package/dist/app.d.ts.map +0 -1
  34. package/dist/logger/console.d.ts +0 -50
  35. package/dist/logger/console.d.ts.map +0 -1
  36. package/dist/logger/index.d.ts +0 -4
  37. package/dist/logger/index.d.ts.map +0 -1
  38. package/dist/logger/internal.d.ts +0 -79
  39. package/dist/logger/internal.d.ts.map +0 -1
  40. package/dist/logger/logger.d.ts +0 -41
  41. package/dist/logger/logger.d.ts.map +0 -1
  42. package/dist/logger/user.d.ts +0 -8
  43. package/dist/logger/user.d.ts.map +0 -1
  44. package/dist/logger/util.d.ts +0 -11
  45. package/dist/logger/util.d.ts.map +0 -1
  46. package/dist/otel/config.d.ts +0 -17
  47. package/dist/otel/config.d.ts.map +0 -1
  48. package/dist/otel/console.d.ts +0 -26
  49. package/dist/otel/console.d.ts.map +0 -1
  50. package/dist/otel/fetch.d.ts +0 -12
  51. package/dist/otel/fetch.d.ts.map +0 -1
  52. package/dist/otel/http.d.ts +0 -16
  53. package/dist/otel/http.d.ts.map +0 -1
  54. package/dist/otel/logger.d.ts +0 -36
  55. package/dist/otel/logger.d.ts.map +0 -1
  56. package/dist/otel/otel.d.ts +0 -58
  57. package/dist/otel/otel.d.ts.map +0 -1
  58. package/dist/router.d.ts +0 -37
  59. package/dist/router.d.ts.map +0 -1
  60. package/src/_config.ts +0 -101
  61. package/src/_context.ts +0 -88
  62. package/src/_idle.ts +0 -26
  63. package/src/_server.ts +0 -278
  64. package/src/_services.ts +0 -175
  65. package/src/_util.ts +0 -63
  66. package/src/_waituntil.ts +0 -246
  67. package/src/agent.ts +0 -287
  68. package/src/app.ts +0 -31
  69. package/src/index.ts +0 -5
  70. package/src/logger/console.ts +0 -111
  71. package/src/logger/index.ts +0 -3
  72. package/src/logger/internal.ts +0 -165
  73. package/src/logger/logger.ts +0 -44
  74. package/src/logger/user.ts +0 -11
  75. package/src/logger/util.ts +0 -80
  76. package/src/otel/config.ts +0 -81
  77. package/src/otel/console.ts +0 -56
  78. package/src/otel/fetch.ts +0 -103
  79. package/src/otel/http.ts +0 -51
  80. package/src/otel/logger.ts +0 -238
  81. package/src/otel/otel.ts +0 -317
  82. package/src/router.ts +0 -303
package/src/_server.ts DELETED
@@ -1,278 +0,0 @@
1
- /* eslint-disable @typescript-eslint/no-unused-vars */
2
- import {
3
- context,
4
- SpanKind,
5
- SpanStatusCode,
6
- type Context,
7
- type Tracer,
8
- trace,
9
- Attributes,
10
- } from '@opentelemetry/api';
11
- import { Span } from '@opentelemetry/sdk-trace-base';
12
- import type { SpanProcessor } from '@opentelemetry/sdk-trace-base';
13
- import { ServiceException } from '@agentuity/core';
14
- import { createMiddleware } from 'hono/factory';
15
- import { Hono } from 'hono';
16
- import { HTTPException } from 'hono/http-exception';
17
- import { BunWebSocketData, websocket } from 'hono/bun';
18
- import type { AppConfig, Env } from './app';
19
- import { extractTraceContextFromRequest } from './otel/http';
20
- import { register } from './otel/config';
21
- import type { Logger } from './logger';
22
- import { isIdle } from './_idle';
23
- import * as runtimeConfig from './_config';
24
- import { inAgentContext, getAgentContext } from './_context';
25
-
26
- let globalServerInstance: Bun.Server<BunWebSocketData> | null = null;
27
-
28
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
29
- let globalAppInstance: Hono<any> | null = null;
30
-
31
- let globalLogger: Logger | null = null;
32
- let globalTracer: Tracer | null = null;
33
-
34
- export function getServer() {
35
- return globalServerInstance;
36
- }
37
-
38
- export function getApp() {
39
- return globalAppInstance;
40
- }
41
-
42
- export function getLogger() {
43
- return globalLogger;
44
- }
45
-
46
- export function getTracer() {
47
- return globalTracer;
48
- }
49
-
50
- function isDevelopment(): boolean {
51
- const devmode = runtimeConfig.isDevMode();
52
- const environment = runtimeConfig.getEnvironment();
53
- return devmode || environment === 'development';
54
- }
55
-
56
- function getPort(): number {
57
- return Number.parseInt(process.env.AGENTUITY_PORT ?? process.env.PORT ?? '3000') || 3000;
58
- }
59
-
60
- const spanProcessors: SpanProcessor[] = [];
61
-
62
- /**
63
- * add a custom span processor that will be added to the otel configuration. this method must be
64
- * called before the createApp is called for it to be added.
65
- */
66
- export function addSpanProcessor(processor: SpanProcessor) {
67
- spanProcessors.push(processor);
68
- }
69
-
70
- function registerAgentuitySpanProcessor() {
71
- const orgId = runtimeConfig.getOrganizationId();
72
- const projectId = runtimeConfig.getProjectId();
73
- const deploymentId = runtimeConfig.getDeploymentId();
74
- const devmode = runtimeConfig.isDevMode();
75
- const environment = runtimeConfig.getEnvironment();
76
-
77
- class RegisterAgentSpanProcessor implements SpanProcessor {
78
- onStart(span: Span, _context: Context) {
79
- const attrs: Attributes = {
80
- '@agentuity/orgId': orgId,
81
- '@agentuity/projectId': projectId,
82
- '@agentuity/deploymentId': deploymentId,
83
- '@agentuity/devmode': devmode,
84
- '@agentuity/environment': environment,
85
- };
86
- if (inAgentContext()) {
87
- const agentCtx = getAgentContext();
88
- if (agentCtx.current?.metadata) {
89
- attrs['@agentuity/agentId'] = agentCtx.current.metadata.id;
90
- attrs['@agentuity/agentName'] = agentCtx.current.metadata.name;
91
- }
92
- }
93
- span.setAttributes(attrs);
94
- }
95
-
96
- onEnd(_span: Span) {
97
- /* */
98
- }
99
-
100
- forceFlush() {
101
- return Promise.resolve();
102
- }
103
-
104
- shutdown() {
105
- return Promise.resolve();
106
- }
107
- }
108
- addSpanProcessor(new RegisterAgentSpanProcessor());
109
- }
110
-
111
- export const createServer = <E extends Env>(app: Hono<E>, _config?: AppConfig) => {
112
- if (globalServerInstance) {
113
- return globalServerInstance;
114
- }
115
-
116
- registerAgentuitySpanProcessor();
117
-
118
- const server = Bun.serve({
119
- hostname: '127.0.0.1',
120
- development: isDevelopment(),
121
- fetch: app.fetch,
122
- idleTimeout: 0,
123
- port: getPort(),
124
- websocket,
125
- });
126
-
127
- const otel = register({ processors: spanProcessors });
128
-
129
- globalAppInstance = app;
130
- globalServerInstance = server;
131
- globalLogger = otel.logger;
132
- globalTracer = otel.tracer;
133
-
134
- let isShutdown = false;
135
-
136
- app.onError((error, _c) => {
137
- if (error instanceof HTTPException) {
138
- otel.logger.error('HTTP Error: %s (%d)', error.cause, error.status);
139
- return error.getResponse();
140
- }
141
- if (
142
- error instanceof ServiceException ||
143
- ('statusCode' in error && typeof error.statusCode === 'number')
144
- ) {
145
- otel.logger.error('Service Exception: %s (%d)', error.message, error.statusCode);
146
- return new Response(error.message, {
147
- status: (error.statusCode as number) ?? 500,
148
- });
149
- }
150
- return new Response('Internal Server Error', { status: 500 });
151
- });
152
-
153
- app.use(async (c, next) => {
154
- c.set('logger', otel.logger);
155
- c.set('tracer', otel.tracer);
156
- c.set('meter', otel.meter);
157
- const skipLogging = c.req.path.startsWith('/_agentuity/');
158
- const started = performance.now();
159
- if (!skipLogging) {
160
- otel.logger.debug('%s %s started', c.req.method, c.req.path);
161
- }
162
- await next();
163
- if (!skipLogging) {
164
- otel.logger.debug(
165
- '%s %s completed (%d) in %sms',
166
- c.req.method,
167
- c.req.path,
168
- c.res.status,
169
- Number(performance.now() - started).toFixed(2)
170
- );
171
- }
172
- });
173
-
174
- app.route('/_agentuity', createAgentuityAPIs());
175
-
176
- // Attach services to context for API routes
177
- app.use('/api/*', async (c, next) => {
178
- const { registerServices } = await import('./_services');
179
- registerServices(c);
180
- await next();
181
- });
182
-
183
- app.use('/api/*', otelMiddleware);
184
- app.use('/agent/*', otelMiddleware);
185
-
186
- const shutdown = async () => {
187
- if (isShutdown) {
188
- return;
189
- }
190
- otel.logger.info('shutdown started');
191
- isShutdown = true;
192
- // Force exit after timeout if cleanup hangs
193
- setTimeout(() => process.exit(1), 30_000).unref();
194
- await server.stop();
195
- await otel.shutdown();
196
- otel.logger.info('shutdown completed');
197
- };
198
-
199
- process.on('beforeExit', async () => await shutdown());
200
- process.on('exit', async () => await shutdown());
201
- process.once('SIGINT', async () => {
202
- await shutdown();
203
- process.exit(0);
204
- });
205
- process.once('SIGTERM', async () => {
206
- await shutdown();
207
- process.exit(0);
208
- });
209
- process.once('uncaughtException', async (err) => {
210
- otel.logger.error('An uncaught exception was received: %s', err);
211
- await shutdown();
212
- process.exit(1);
213
- });
214
- process.once('unhandledRejection', async (reason) => {
215
- otel.logger.error('An unhandled promise rejection was received: %s', reason);
216
- await shutdown();
217
- process.exit(1);
218
- });
219
-
220
- return server;
221
- };
222
-
223
- const createAgentuityAPIs = () => {
224
- const router = new Hono<Env>();
225
- router.get('idle', (c) => {
226
- if (isIdle()) {
227
- return new Response('OK', { status: 200 });
228
- }
229
- return new Response('NO', { status: 200 });
230
- });
231
- return router;
232
- };
233
-
234
- const otelMiddleware = createMiddleware<Env>(async (c, next) => {
235
- // Extract trace context from headers
236
- const extractedContext = extractTraceContextFromRequest(c.req.raw);
237
-
238
- const method = c.req.method;
239
- const url = new URL(c.req.url);
240
-
241
- // Execute the request handler within the extracted context
242
- await context.with(extractedContext, async (): Promise<void> => {
243
- // Create a span for this incoming request
244
- await trace.getTracer('http-server').startActiveSpan(
245
- `HTTP ${method}`,
246
- {
247
- kind: SpanKind.SERVER,
248
- attributes: {
249
- 'http.method': method,
250
- 'http.host': url.host,
251
- 'http.user_agent': c.req.header('user-agent') || '',
252
- 'http.path': url.pathname,
253
- },
254
- },
255
- async (span): Promise<void> => {
256
- try {
257
- await next();
258
- span.setStatus({
259
- code: SpanStatusCode.OK,
260
- });
261
- } catch (ex) {
262
- if (ex instanceof Error) {
263
- span.recordException(ex);
264
- }
265
- const message = (ex as Error).message ?? String(ex);
266
- span.setStatus({
267
- code: SpanStatusCode.ERROR,
268
- message,
269
- });
270
- c.var.logger.error('ERROR: %s', message);
271
- throw ex;
272
- } finally {
273
- span.end();
274
- }
275
- }
276
- );
277
- });
278
- });
package/src/_services.ts DELETED
@@ -1,175 +0,0 @@
1
- import { context, SpanKind, SpanStatusCode, trace } from '@opentelemetry/api';
2
- import {
3
- createServerFetchAdapter,
4
- KeyValueStorageService,
5
- ObjectStorageService,
6
- StreamStorageService,
7
- VectorStorageService,
8
- ListStreamsResponse,
9
- VectorUpsertResult,
10
- VectorSearchResult,
11
- } from '@agentuity/core';
12
- import { injectTraceContextToHeaders } from './otel/http';
13
- import { getLogger, getTracer } from './_server';
14
- import { getSDKVersion } from './_config';
15
-
16
- const userAgent = `Agentuity SDK/${getSDKVersion()}`;
17
- const bearerKey = `Bearer ${process.env.AGENTUITY_SDK_KEY}`;
18
-
19
- const kvBaseUrl =
20
- process.env.AGENTUITY_KEYVALUE_URL ||
21
- process.env.AGENTUITY_TRANSPORT_URL ||
22
- 'https://agentuity.ai';
23
-
24
- const streamBaseUrl = process.env.AGENTUITY_STREAM_URL || 'https://streams.agentuity.cloud';
25
-
26
- const vectorBaseUrl =
27
- process.env.AGENTUITY_VECTOR_URL ||
28
- process.env.AGENTUITY_TRANSPORT_URL ||
29
- 'https://agentuity.ai';
30
-
31
- const objectBaseUrl =
32
- process.env.AGENTUITY_OBJECTSTORE_URL ||
33
- process.env.AGENTUITY_TRANSPORT_URL ||
34
- 'https://agentuity.ai';
35
-
36
- const adapter = createServerFetchAdapter({
37
- headers: {
38
- Authorization: bearerKey,
39
- 'User-Agent': userAgent,
40
- },
41
- onBefore: async (url, options, callback) => {
42
- getLogger()?.debug('before request: %s with options: %s', url, options);
43
- if (!options.telemetry) {
44
- return callback();
45
- }
46
- options.headers = { ...options.headers, ...injectTraceContextToHeaders() };
47
- const tracer = getTracer() ?? trace.getTracer('agentuity');
48
- const currentContext = context.active();
49
- const span = tracer.startSpan(
50
- options.telemetry.name,
51
- { attributes: options.telemetry.attributes, kind: SpanKind.CLIENT },
52
- currentContext
53
- );
54
- const spanContext = trace.setSpan(currentContext, span);
55
- try {
56
- await context.with(spanContext, callback);
57
- span.setStatus({ code: SpanStatusCode.OK });
58
- } catch (err) {
59
- const e = err as Error;
60
- span.recordException(e);
61
- span.setStatus({ code: SpanStatusCode.ERROR, message: e?.message ?? String(err) });
62
- throw err;
63
- } finally {
64
- span.end();
65
- }
66
- },
67
- onAfter: async (url, options, result, err) => {
68
- getLogger()?.debug('after request: %s (%d) => %s', url, result.response.status, err);
69
- if (err) {
70
- return;
71
- }
72
- const span = trace.getSpan(context.active());
73
- switch (options.telemetry?.name) {
74
- case 'agentuity.keyvalue.get': {
75
- if (result.response.status === 404) {
76
- span?.addEvent('miss');
77
- } else if (result.response.ok) {
78
- span?.addEvent('hit');
79
- }
80
- break;
81
- }
82
- case 'agentuity.stream.create': {
83
- if (result.response.ok) {
84
- const res = result.data as { id: string };
85
- span?.setAttributes({
86
- 'stream.id': res.id,
87
- 'stream.url': `${streamBaseUrl}/${res.id}`,
88
- });
89
- }
90
- break;
91
- }
92
- case 'agentuity.stream.list': {
93
- const response = result.data as ListStreamsResponse;
94
- if (response && span) {
95
- span.setAttributes({
96
- 'stream.count': response.streams.length,
97
- 'stream.total': response.total,
98
- });
99
- }
100
- break;
101
- }
102
- case 'agentuity.vector.upsert': {
103
- if (result.response.ok) {
104
- const data = result.data as VectorUpsertResult[];
105
- span?.setAttributes({
106
- 'vector.count': data.length,
107
- });
108
- }
109
- break;
110
- }
111
- case 'agentuity.vector.search': {
112
- if (result.response.ok) {
113
- const data = result.data as VectorSearchResult[];
114
- span?.setAttributes({
115
- 'vector.results': data.length,
116
- });
117
- }
118
- break;
119
- }
120
- case 'agentuity.vector.get': {
121
- if (result.response.status === 404) {
122
- span?.addEvent('miss');
123
- } else if (result.response.ok) {
124
- span?.addEvent('hit');
125
- }
126
- break;
127
- }
128
- case 'agentuity.objectstore.get': {
129
- if (result.response.status === 404) {
130
- span?.addEvent('miss');
131
- } else if (result.response.ok) {
132
- span?.addEvent('hit');
133
- }
134
- break;
135
- }
136
- case 'agentuity.objectstore.delete': {
137
- if (result.response.status === 404) {
138
- span?.addEvent('not_found', { deleted: false });
139
- } else if (result.response.ok) {
140
- span?.addEvent('deleted', { deleted: true });
141
- }
142
- break;
143
- }
144
- }
145
- },
146
- });
147
-
148
- const kv = new KeyValueStorageService(kvBaseUrl, adapter);
149
- const objectStore = new ObjectStorageService(objectBaseUrl, adapter);
150
- const stream = new StreamStorageService(streamBaseUrl, adapter);
151
- const vector = new VectorStorageService(vectorBaseUrl, adapter);
152
-
153
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
154
- export function registerServices(o: any) {
155
- Object.defineProperty(o, 'kv', {
156
- get: () => kv,
157
- enumerable: false,
158
- configurable: false,
159
- });
160
- Object.defineProperty(o, 'objectstore', {
161
- get: () => objectStore,
162
- enumerable: false,
163
- configurable: false,
164
- });
165
- Object.defineProperty(o, 'stream', {
166
- get: () => stream,
167
- enumerable: false,
168
- configurable: false,
169
- });
170
- Object.defineProperty(o, 'vector', {
171
- get: () => vector,
172
- enumerable: false,
173
- configurable: false,
174
- });
175
- }
package/src/_util.ts DELETED
@@ -1,63 +0,0 @@
1
- import type { Context } from 'hono';
2
-
3
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
4
- export function returnResponse(ctx: Context, result: any) {
5
- if (result instanceof ReadableStream) return ctx.body(result);
6
- if (result instanceof Response) return result;
7
- if (typeof result === 'string') return ctx.text(result);
8
- if (typeof result === 'number' || typeof result === 'boolean') return ctx.text(String(result));
9
- return ctx.json(result);
10
- }
11
-
12
- /**
13
- * SHA256 hash of the given values
14
- *
15
- * @param val one or more strings to hash
16
- * @returns hash string in hex format
17
- */
18
- export function hash(...val: string[]): string {
19
- const hasher = new Bun.CryptoHasher('sha256');
20
- val.forEach((val) => hasher.update(val));
21
- return hasher.digest().toHex();
22
- }
23
-
24
- /**
25
- * Safely stringify an object to JSON, handling circular references
26
- * @param obj - The object to stringify
27
- * @returns JSON string representation
28
- */
29
- export function safeStringify(obj: unknown): string {
30
- const stack: unknown[] = [];
31
-
32
- function replacer(_key: string, value: unknown): unknown {
33
- if (typeof value === 'bigint') {
34
- return value.toString();
35
- }
36
-
37
- if (typeof value === 'object' && value !== null) {
38
- // Check if this object is already in our ancestor chain
39
- if (stack.includes(value)) {
40
- return '[Circular]';
41
- }
42
-
43
- // Add to stack before processing
44
- stack.push(value);
45
-
46
- // Process the object
47
- const result = Array.isArray(value) ? [] : {};
48
-
49
- for (const [k, v] of Object.entries(value)) {
50
- (result as Record<string, unknown>)[k] = replacer(k, v);
51
- }
52
-
53
- // Remove from stack after processing
54
- stack.pop();
55
-
56
- return result;
57
- }
58
-
59
- return value;
60
- }
61
-
62
- return JSON.stringify(replacer('', obj));
63
- }