@agentuity/server 2.0.10 → 3.0.0-alpha.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.
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -2
- package/dist/index.js.map +1 -1
- package/dist/runtime-bootstrap.d.ts +2 -6
- package/dist/runtime-bootstrap.d.ts.map +1 -1
- package/dist/runtime-bootstrap.js +2 -6
- package/dist/runtime-bootstrap.js.map +1 -1
- package/package.json +14 -8
- package/src/index.ts +12 -6
- package/src/runtime-bootstrap.ts +2 -6
- package/dist/server.d.ts +0 -60
- package/dist/server.d.ts.map +0 -1
- package/dist/server.js +0 -360
- package/dist/server.js.map +0 -1
- package/src/server.ts +0 -424
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
export { createServerFetchAdapter, buildClientHeaders, type BuildClientHeadersOptions, type ServiceAdapterConfig, redact, } from '@agentuity/adapter';
|
|
1
2
|
export * from '@agentuity/core';
|
|
2
3
|
export { type ColorScheme, ConsoleLogger, createLogger } from './logger.ts';
|
|
3
|
-
export { createServerFetchAdapter, buildClientHeaders, type BuildClientHeadersOptions, } from './server.ts';
|
|
4
4
|
export { toJSONSchema } from './schema.ts';
|
|
5
5
|
export { getContentType, mimeTypes } from './util/mime.ts';
|
|
6
6
|
export { validateCPUSpec, validateMemorySpec, validateResources, type ResourceValidationResult, type ResourcesConfig, type ValidatedResources, } from './util/resources.ts';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EACN,wBAAwB,EACxB,kBAAkB,EAClB,KAAK,yBAAyB,EAC9B,KAAK,oBAAoB,EACzB,MAAM,GACN,MAAM,oBAAoB,CAAC;AAK5B,cAAc,iBAAiB,CAAC;AAGhC,OAAO,EAAE,KAAK,WAAW,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC5E,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3D,OAAO,EACN,eAAe,EACf,kBAAkB,EAClB,iBAAiB,EACjB,KAAK,wBAAwB,EAC7B,KAAK,eAAe,EACpB,KAAK,kBAAkB,GACvB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,mBAAmB,EAAE,KAAK,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AAC3F,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
|
-
// Re-export
|
|
1
|
+
// Re-export adapter functions (backward compatibility - prefer @agentuity/adapter)
|
|
2
|
+
export { createServerFetchAdapter, buildClientHeaders, redact, } from '@agentuity/adapter';
|
|
3
|
+
// Re-export commonly used types from core
|
|
4
|
+
// Note: Full re-export maintained for backward compatibility with CLI and other packages
|
|
5
|
+
// TODO: Phase 2 - Migrate CLI imports to @agentuity/core directly, then remove this re-export
|
|
2
6
|
export * from '@agentuity/core';
|
|
3
7
|
// Server-specific exports (these remain in @agentuity/server only)
|
|
4
8
|
export { ConsoleLogger, createLogger } from "./logger.js";
|
|
5
|
-
export { createServerFetchAdapter, buildClientHeaders, } from "./server.js";
|
|
6
9
|
export { toJSONSchema } from "./schema.js";
|
|
7
10
|
export { getContentType, mimeTypes } from "./util/mime.js";
|
|
8
11
|
export { validateCPUSpec, validateMemorySpec, validateResources, } from "./util/resources.js";
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,mFAAmF;AACnF,OAAO,EACN,wBAAwB,EACxB,kBAAkB,EAGlB,MAAM,GACN,MAAM,oBAAoB,CAAC;AAE5B,0CAA0C;AAC1C,yFAAyF;AACzF,8FAA8F;AAC9F,cAAc,iBAAiB,CAAC;AAEhC,mEAAmE;AACnE,OAAO,EAAoB,aAAa,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC5E,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3D,OAAO,EACN,eAAe,EACf,kBAAkB,EAClB,iBAAiB,GAIjB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,mBAAmB,EAAgC,MAAM,wBAAwB,CAAC;AAC3F,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC"}
|
|
@@ -26,18 +26,14 @@ export interface RuntimeBootstrapOptions {
|
|
|
26
26
|
* Note: This does NOT load .env files. Use a proper .env loader
|
|
27
27
|
* (like dotenv) in your app.ts before calling this function.
|
|
28
28
|
*
|
|
29
|
-
* Call this
|
|
29
|
+
* Call this early in your app entry point:
|
|
30
30
|
*
|
|
31
31
|
* @example
|
|
32
32
|
* ```ts
|
|
33
33
|
* import { bootstrapRuntimeEnv } from '@agentuity/server';
|
|
34
|
-
* import { createApp } from '@agentuity/runtime';
|
|
35
34
|
*
|
|
36
|
-
* // Set up service URLs
|
|
35
|
+
* // Set up service URLs before initializing your app
|
|
37
36
|
* bootstrapRuntimeEnv();
|
|
38
|
-
*
|
|
39
|
-
* // Now createApp() will use the correct env vars
|
|
40
|
-
* const app = await createApp();
|
|
41
37
|
* ```
|
|
42
38
|
*/
|
|
43
39
|
export declare function bootstrapRuntimeEnv(options?: RuntimeBootstrapOptions): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtime-bootstrap.d.ts","sourceRoot":"","sources":["../src/runtime-bootstrap.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,MAAM,WAAW,uBAAuB;IACvC;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB;AAED
|
|
1
|
+
{"version":3,"file":"runtime-bootstrap.d.ts","sourceRoot":"","sources":["../src/runtime-bootstrap.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,MAAM,WAAW,uBAAuB;IACvC;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,GAAE,uBAA4B,GAAG,IAAI,CA6C/E"}
|
|
@@ -16,18 +16,14 @@ import { getServiceUrls } from "./config.js";
|
|
|
16
16
|
* Note: This does NOT load .env files. Use a proper .env loader
|
|
17
17
|
* (like dotenv) in your app.ts before calling this function.
|
|
18
18
|
*
|
|
19
|
-
* Call this
|
|
19
|
+
* Call this early in your app entry point:
|
|
20
20
|
*
|
|
21
21
|
* @example
|
|
22
22
|
* ```ts
|
|
23
23
|
* import { bootstrapRuntimeEnv } from '@agentuity/server';
|
|
24
|
-
* import { createApp } from '@agentuity/runtime';
|
|
25
24
|
*
|
|
26
|
-
* // Set up service URLs
|
|
25
|
+
* // Set up service URLs before initializing your app
|
|
27
26
|
* bootstrapRuntimeEnv();
|
|
28
|
-
*
|
|
29
|
-
* // Now createApp() will use the correct env vars
|
|
30
|
-
* const app = await createApp();
|
|
31
27
|
* ```
|
|
32
28
|
*/
|
|
33
29
|
export function bootstrapRuntimeEnv(options = {}) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtime-bootstrap.js","sourceRoot":"","sources":["../src/runtime-bootstrap.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAe7C
|
|
1
|
+
{"version":3,"file":"runtime-bootstrap.js","sourceRoot":"","sources":["../src/runtime-bootstrap.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAe7C;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,UAAU,mBAAmB,CAAC,UAAmC,EAAE;IACxE,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,OAAO,CAAC,GAAG,CAAC,iBAAiB,IAAI,OAAO,CAAC;IAE5E,6DAA6D;IAC7D,IACC,CAAC,OAAO,KAAK,OAAO,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,aAAa,CAAC;QAC/D,CAAC,OAAO,CAAC,GAAG,CAAC,gBAAgB,EAC5B,CAAC;QACF,OAAO,CAAC,GAAG,CAAC,gBAAgB,GAAG,OAAO,CAAC;IACxC,CAAC;IAED,kDAAkD;IAClD,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,iBAAiB,EAAE,CAAC;QACpC,OAAO,CAAC,GAAG,CAAC,iBAAiB,GAAG,OAAO,CAAC;IACzC,CAAC;IAED,mCAAmC;IACnC,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC;IAC5C,MAAM,WAAW,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC;IAE3C,2EAA2E;IAC3E,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,uBAAuB,EAAE,CAAC;QAC1C,OAAO,CAAC,GAAG,CAAC,uBAAuB,GAAG,WAAW,CAAC,QAAQ,CAAC;IAC5D,CAAC;IACD,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,sBAAsB,EAAE,CAAC;QACzC,OAAO,CAAC,GAAG,CAAC,sBAAsB,GAAG,WAAW,CAAC,QAAQ,CAAC;IAC3D,CAAC;IACD,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,qBAAqB,EAAE,CAAC;QACxC,OAAO,CAAC,GAAG,CAAC,qBAAqB,GAAG,WAAW,CAAC,OAAO,CAAC;IACzD,CAAC;IACD,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,oBAAoB,EAAE,CAAC;QACvC,OAAO,CAAC,GAAG,CAAC,oBAAoB,GAAG,WAAW,CAAC,MAAM,CAAC;IACvD,CAAC;IACD,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,oBAAoB,EAAE,CAAC;QACvC,OAAO,CAAC,GAAG,CAAC,oBAAoB,GAAG,WAAW,CAAC,MAAM,CAAC;IACvD,CAAC;IACD,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,sBAAsB,EAAE,CAAC;QACzC,OAAO,CAAC,GAAG,CAAC,sBAAsB,GAAG,WAAW,CAAC,QAAQ,CAAC;IAC3D,CAAC;IACD,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,kBAAkB,EAAE,CAAC;QACrC,OAAO,CAAC,GAAG,CAAC,kBAAkB,GAAG,WAAW,CAAC,IAAI,CAAC;IACnD,CAAC;IACD,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,mBAAmB,EAAE,CAAC;QACtC,OAAO,CAAC,GAAG,CAAC,mBAAmB,GAAG,WAAW,CAAC,KAAK,CAAC;IACrD,CAAC;AACF,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agentuity/server",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.0-alpha.0",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"author": "Agentuity employees and contributors",
|
|
6
6
|
"type": "module",
|
|
@@ -20,24 +20,30 @@
|
|
|
20
20
|
},
|
|
21
21
|
"scripts": {
|
|
22
22
|
"clean": "rm -rf dist tsconfig.tsbuildinfo",
|
|
23
|
-
"build": "
|
|
24
|
-
"typecheck": "
|
|
23
|
+
"build": "tsgo --build --force",
|
|
24
|
+
"typecheck": "tsgo --noEmit",
|
|
25
25
|
"prepublishOnly": "bun run clean && bun run build"
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@agentuity/
|
|
29
|
-
"@agentuity/
|
|
28
|
+
"@agentuity/adapter": "3.0.0-alpha.0",
|
|
29
|
+
"@agentuity/core": "3.0.0-alpha.0",
|
|
30
|
+
"@agentuity/schema": "3.0.0-alpha.0",
|
|
30
31
|
"zod": "^4.3.5"
|
|
31
32
|
},
|
|
32
33
|
"devDependencies": {
|
|
33
|
-
"@agentuity/test-utils": "
|
|
34
|
+
"@agentuity/test-utils": "3.0.0-alpha.0",
|
|
34
35
|
"@types/bun": "latest",
|
|
35
36
|
"@types/node": "^22.0.0",
|
|
36
37
|
"bun-types": "latest",
|
|
37
|
-
"typescript": "^
|
|
38
|
+
"typescript": "^6.0.2"
|
|
38
39
|
},
|
|
39
40
|
"publishConfig": {
|
|
40
41
|
"access": "public"
|
|
41
42
|
},
|
|
42
|
-
"sideEffects": false
|
|
43
|
+
"sideEffects": false,
|
|
44
|
+
"repository": {
|
|
45
|
+
"type": "git",
|
|
46
|
+
"url": "https://github.com/agentuity/sdk.git",
|
|
47
|
+
"directory": "packages/server"
|
|
48
|
+
}
|
|
43
49
|
}
|
package/src/index.ts
CHANGED
|
@@ -1,13 +1,19 @@
|
|
|
1
|
-
// Re-export
|
|
2
|
-
export * from '@agentuity/core';
|
|
3
|
-
|
|
4
|
-
// Server-specific exports (these remain in @agentuity/server only)
|
|
5
|
-
export { type ColorScheme, ConsoleLogger, createLogger } from './logger.ts';
|
|
1
|
+
// Re-export adapter functions (backward compatibility - prefer @agentuity/adapter)
|
|
6
2
|
export {
|
|
7
3
|
createServerFetchAdapter,
|
|
8
4
|
buildClientHeaders,
|
|
9
5
|
type BuildClientHeadersOptions,
|
|
10
|
-
|
|
6
|
+
type ServiceAdapterConfig,
|
|
7
|
+
redact,
|
|
8
|
+
} from '@agentuity/adapter';
|
|
9
|
+
|
|
10
|
+
// Re-export commonly used types from core
|
|
11
|
+
// Note: Full re-export maintained for backward compatibility with CLI and other packages
|
|
12
|
+
// TODO: Phase 2 - Migrate CLI imports to @agentuity/core directly, then remove this re-export
|
|
13
|
+
export * from '@agentuity/core';
|
|
14
|
+
|
|
15
|
+
// Server-specific exports (these remain in @agentuity/server only)
|
|
16
|
+
export { type ColorScheme, ConsoleLogger, createLogger } from './logger.ts';
|
|
11
17
|
export { toJSONSchema } from './schema.ts';
|
|
12
18
|
export { getContentType, mimeTypes } from './util/mime.ts';
|
|
13
19
|
export {
|
package/src/runtime-bootstrap.ts
CHANGED
|
@@ -31,18 +31,14 @@ export interface RuntimeBootstrapOptions {
|
|
|
31
31
|
* Note: This does NOT load .env files. Use a proper .env loader
|
|
32
32
|
* (like dotenv) in your app.ts before calling this function.
|
|
33
33
|
*
|
|
34
|
-
* Call this
|
|
34
|
+
* Call this early in your app entry point:
|
|
35
35
|
*
|
|
36
36
|
* @example
|
|
37
37
|
* ```ts
|
|
38
38
|
* import { bootstrapRuntimeEnv } from '@agentuity/server';
|
|
39
|
-
* import { createApp } from '@agentuity/runtime';
|
|
40
39
|
*
|
|
41
|
-
* // Set up service URLs
|
|
40
|
+
* // Set up service URLs before initializing your app
|
|
42
41
|
* bootstrapRuntimeEnv();
|
|
43
|
-
*
|
|
44
|
-
* // Now createApp() will use the correct env vars
|
|
45
|
-
* const app = await createApp();
|
|
46
42
|
* ```
|
|
47
43
|
*/
|
|
48
44
|
export function bootstrapRuntimeEnv(options: RuntimeBootstrapOptions = {}): void {
|
package/dist/server.d.ts
DELETED
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
import type { FetchRequest, FetchResponse, FetchAdapter, Logger } from '@agentuity/core';
|
|
2
|
-
import { ServiceException } from '@agentuity/core';
|
|
3
|
-
interface ServiceAdapterConfig {
|
|
4
|
-
headers: Record<string, string>;
|
|
5
|
-
queryParams?: Record<string, string>;
|
|
6
|
-
onBefore?: (url: string, options: FetchRequest, invoke: () => Promise<void>) => Promise<void>;
|
|
7
|
-
onAfter?: <T>(url: string, options: FetchRequest, response: FetchResponse<T>, err?: InstanceType<typeof ServiceException>) => Promise<void>;
|
|
8
|
-
}
|
|
9
|
-
/**
|
|
10
|
-
* Options for building client request headers.
|
|
11
|
-
*/
|
|
12
|
-
export interface BuildClientHeadersOptions {
|
|
13
|
-
/** API key for authentication (Bearer token) */
|
|
14
|
-
apiKey?: string;
|
|
15
|
-
/** Organization ID for multi-tenant requests */
|
|
16
|
-
orgId?: string;
|
|
17
|
-
}
|
|
18
|
-
/**
|
|
19
|
-
* Builds standard headers for Agentuity service clients.
|
|
20
|
-
*
|
|
21
|
-
* This helper creates the header object needed by `createServerFetchAdapter`,
|
|
22
|
-
* handling authentication and multi-tenant scoping consistently across all clients.
|
|
23
|
-
*
|
|
24
|
-
* @param options - Options containing apiKey and/or orgId
|
|
25
|
-
* @returns Headers object ready to pass to createServerFetchAdapter
|
|
26
|
-
*
|
|
27
|
-
* @example
|
|
28
|
-
* ```typescript
|
|
29
|
-
* import { buildClientHeaders, createServerFetchAdapter } from '@agentuity/server';
|
|
30
|
-
*
|
|
31
|
-
* const headers = buildClientHeaders({ apiKey: 'sk_xxx', orgId: 'org_xxx' });
|
|
32
|
-
* const adapter = createServerFetchAdapter({ headers }, logger);
|
|
33
|
-
* ```
|
|
34
|
-
*/
|
|
35
|
-
export declare function buildClientHeaders(options: BuildClientHeadersOptions): Record<string, string>;
|
|
36
|
-
/**
|
|
37
|
-
* Redacts the middle of a string while keeping a prefix and suffix visible.
|
|
38
|
-
* Ensures that if the string is too short, everything is redacted.
|
|
39
|
-
*
|
|
40
|
-
* @param input The string to redact
|
|
41
|
-
* @param prefix Number of chars to keep at the start
|
|
42
|
-
* @param suffix Number of chars to keep at the end
|
|
43
|
-
* @param mask Character used for redaction
|
|
44
|
-
*/
|
|
45
|
-
export declare function redact(input: string, prefix?: number, suffix?: number, mask?: string): string;
|
|
46
|
-
declare class ServerFetchAdapter implements FetchAdapter {
|
|
47
|
-
#private;
|
|
48
|
-
constructor(config: ServiceAdapterConfig, logger: Logger);
|
|
49
|
-
private _invoke;
|
|
50
|
-
invoke<T>(url: string, options?: FetchRequest): Promise<FetchResponse<T>>;
|
|
51
|
-
}
|
|
52
|
-
/**
|
|
53
|
-
* Create a Server Side Fetch Adapter to allow the server to add headers and track outgoing requests
|
|
54
|
-
*
|
|
55
|
-
* @param config the service config
|
|
56
|
-
* @returns
|
|
57
|
-
*/
|
|
58
|
-
export declare function createServerFetchAdapter(config: ServiceAdapterConfig, logger: Logger): ServerFetchAdapter;
|
|
59
|
-
export {};
|
|
60
|
-
//# sourceMappingURL=server.d.ts.map
|
package/dist/server.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACX,YAAY,EAEZ,aAAa,EACb,YAAY,EACZ,MAAM,EAEN,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,gBAAgB,EAAoC,MAAM,iBAAiB,CAAC;AAGrF,UAAU,oBAAoB;IAC7B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACrC,QAAQ,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9F,OAAO,CAAC,EAAE,CAAC,CAAC,EACX,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,YAAY,EACrB,QAAQ,EAAE,aAAa,CAAC,CAAC,CAAC,EAC1B,GAAG,CAAC,EAAE,YAAY,CAAC,OAAO,gBAAgB,CAAC,KACvC,OAAO,CAAC,IAAI,CAAC,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,yBAAyB;IACzC,gDAAgD;IAChD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gDAAgD;IAChD,KAAK,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,yBAAyB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAa7F;AAqKD;;;;;;;;GAQG;AACH,wBAAgB,MAAM,CACrB,KAAK,EAAE,MAAM,EACb,MAAM,GAAE,MAAU,EAClB,MAAM,GAAE,MAAU,EAClB,IAAI,GAAE,MAAY,GAChB,MAAM,CAaR;AAmBD,cAAM,kBAAmB,YAAW,YAAY;;gBAInC,MAAM,EAAE,oBAAoB,EAAE,MAAM,EAAE,MAAM;YAoB1C,OAAO;IA0Ef,MAAM,CAAC,CAAC,EACb,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,YAAiC,GACxC,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;CAsC5B;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,oBAAoB,EAAE,MAAM,EAAE,MAAM,sBAEpF"}
|
package/dist/server.js
DELETED
|
@@ -1,360 +0,0 @@
|
|
|
1
|
-
import { ServiceException, toServiceException, fromResponse } from '@agentuity/core';
|
|
2
|
-
import { appendFileSync } from 'node:fs';
|
|
3
|
-
/**
|
|
4
|
-
* Builds standard headers for Agentuity service clients.
|
|
5
|
-
*
|
|
6
|
-
* This helper creates the header object needed by `createServerFetchAdapter`,
|
|
7
|
-
* handling authentication and multi-tenant scoping consistently across all clients.
|
|
8
|
-
*
|
|
9
|
-
* @param options - Options containing apiKey and/or orgId
|
|
10
|
-
* @returns Headers object ready to pass to createServerFetchAdapter
|
|
11
|
-
*
|
|
12
|
-
* @example
|
|
13
|
-
* ```typescript
|
|
14
|
-
* import { buildClientHeaders, createServerFetchAdapter } from '@agentuity/server';
|
|
15
|
-
*
|
|
16
|
-
* const headers = buildClientHeaders({ apiKey: 'sk_xxx', orgId: 'org_xxx' });
|
|
17
|
-
* const adapter = createServerFetchAdapter({ headers }, logger);
|
|
18
|
-
* ```
|
|
19
|
-
*/
|
|
20
|
-
export function buildClientHeaders(options) {
|
|
21
|
-
const headers = options.apiKey
|
|
22
|
-
? {
|
|
23
|
-
Authorization: `Bearer ${options.apiKey}`,
|
|
24
|
-
'Content-Type': 'application/json',
|
|
25
|
-
}
|
|
26
|
-
: { 'Content-Type': 'application/json' };
|
|
27
|
-
if (options.orgId) {
|
|
28
|
-
headers['x-agentuity-orgid'] = options.orgId;
|
|
29
|
-
}
|
|
30
|
-
return headers;
|
|
31
|
-
}
|
|
32
|
-
/**
|
|
33
|
-
* Headers that contain sensitive information and should be redacted in debug logs.
|
|
34
|
-
* Includes authentication tokens, API keys, cookies, and proxy credentials.
|
|
35
|
-
*/
|
|
36
|
-
const sensitiveHeaders = new Set([
|
|
37
|
-
'authorization',
|
|
38
|
-
'x-api-key',
|
|
39
|
-
'cookie',
|
|
40
|
-
'set-cookie',
|
|
41
|
-
'proxy-authorization',
|
|
42
|
-
]);
|
|
43
|
-
/**
|
|
44
|
-
* Check if API debug logging is enabled and return the output destination.
|
|
45
|
-
* Returns:
|
|
46
|
-
* - 'console' if CI=1/true or AGENTUITY_API_DEBUG=1/true
|
|
47
|
-
* - file path string if AGENTUITY_API_DEBUG is set to a path
|
|
48
|
-
* - null if debug logging is disabled (including AGENTUITY_API_DEBUG=0/false)
|
|
49
|
-
*/
|
|
50
|
-
function getDebugOutput() {
|
|
51
|
-
const apiDebug = process.env.AGENTUITY_API_DEBUG?.trim();
|
|
52
|
-
if (apiDebug) {
|
|
53
|
-
const normalized = apiDebug.toLowerCase();
|
|
54
|
-
// Check if explicitly disabled
|
|
55
|
-
if (normalized === '0' || normalized === 'false') {
|
|
56
|
-
return null;
|
|
57
|
-
}
|
|
58
|
-
// Check if it's a truthy value (console output)
|
|
59
|
-
if (normalized === '1' || normalized === 'true') {
|
|
60
|
-
return 'console';
|
|
61
|
-
}
|
|
62
|
-
// Treat any other non-empty value as a file path
|
|
63
|
-
return apiDebug;
|
|
64
|
-
}
|
|
65
|
-
// Fall back to CI environment check
|
|
66
|
-
if (process.env.CI === '1' || process.env.CI === 'true') {
|
|
67
|
-
return 'console';
|
|
68
|
-
}
|
|
69
|
-
return null;
|
|
70
|
-
}
|
|
71
|
-
/**
|
|
72
|
-
* Format request body for CI debug logging
|
|
73
|
-
*/
|
|
74
|
-
function formatRequestBody(body) {
|
|
75
|
-
if (body === undefined || body === null) {
|
|
76
|
-
return '[no body]';
|
|
77
|
-
}
|
|
78
|
-
if (typeof body === 'string') {
|
|
79
|
-
return body;
|
|
80
|
-
}
|
|
81
|
-
if (body instanceof Uint8Array) {
|
|
82
|
-
return `[binary data: ${body.length} bytes]`;
|
|
83
|
-
}
|
|
84
|
-
if (body instanceof ArrayBuffer) {
|
|
85
|
-
return `[binary data: ${body.byteLength} bytes]`;
|
|
86
|
-
}
|
|
87
|
-
if (body instanceof ReadableStream) {
|
|
88
|
-
return '[stream]';
|
|
89
|
-
}
|
|
90
|
-
return String(body);
|
|
91
|
-
}
|
|
92
|
-
/**
|
|
93
|
-
* Format a sensitive header value, preserving Bearer prefix if present.
|
|
94
|
-
*/
|
|
95
|
-
function redactSensitiveHeader(key, value) {
|
|
96
|
-
const _k = key.toLowerCase();
|
|
97
|
-
// Handle Bearer tokens in authorization and proxy-authorization headers
|
|
98
|
-
if ((_k === 'authorization' || _k === 'proxy-authorization') && value.startsWith('Bearer ')) {
|
|
99
|
-
return `Bearer ${redact(value.substring(7))}`;
|
|
100
|
-
}
|
|
101
|
-
return redact(value);
|
|
102
|
-
}
|
|
103
|
-
/**
|
|
104
|
-
* Format headers as a readable string for debug logging.
|
|
105
|
-
* Sensitive headers (auth tokens, cookies, API keys) are redacted.
|
|
106
|
-
*/
|
|
107
|
-
function formatHeaders(headers) {
|
|
108
|
-
const entries = [];
|
|
109
|
-
if (headers instanceof Headers) {
|
|
110
|
-
headers.forEach((value, key) => {
|
|
111
|
-
const _k = key.toLowerCase();
|
|
112
|
-
if (sensitiveHeaders.has(_k)) {
|
|
113
|
-
entries.push(` ${key}: ${redactSensitiveHeader(key, value)}`);
|
|
114
|
-
}
|
|
115
|
-
else {
|
|
116
|
-
entries.push(` ${key}: ${value}`);
|
|
117
|
-
}
|
|
118
|
-
});
|
|
119
|
-
}
|
|
120
|
-
else {
|
|
121
|
-
for (const [key, value] of Object.entries(headers)) {
|
|
122
|
-
const _k = key.toLowerCase();
|
|
123
|
-
if (sensitiveHeaders.has(_k)) {
|
|
124
|
-
entries.push(` ${key}: ${redactSensitiveHeader(key, value)}`);
|
|
125
|
-
}
|
|
126
|
-
else {
|
|
127
|
-
entries.push(` ${key}: ${value}`);
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
return entries.join('\n');
|
|
132
|
-
}
|
|
133
|
-
/**
|
|
134
|
-
* Log detailed debug information when API requests fail.
|
|
135
|
-
* Output destination is determined by AGENTUITY_API_DEBUG or CI environment variables.
|
|
136
|
-
*/
|
|
137
|
-
function logAPIDebug(url, method, requestHeaders, requestBody, response, responseBody) {
|
|
138
|
-
const output = getDebugOutput();
|
|
139
|
-
if (!output) {
|
|
140
|
-
return;
|
|
141
|
-
}
|
|
142
|
-
const separator = '='.repeat(60);
|
|
143
|
-
const timestamp = new Date().toISOString();
|
|
144
|
-
const lines = [
|
|
145
|
-
'',
|
|
146
|
-
separator,
|
|
147
|
-
`API DEBUG: Request Failed [${timestamp}]`,
|
|
148
|
-
separator,
|
|
149
|
-
'',
|
|
150
|
-
'>>> REQUEST',
|
|
151
|
-
`URL: ${url}`,
|
|
152
|
-
`Method: ${method}`,
|
|
153
|
-
'Headers:',
|
|
154
|
-
formatHeaders(requestHeaders),
|
|
155
|
-
'Body:',
|
|
156
|
-
` ${formatRequestBody(requestBody)}`,
|
|
157
|
-
'',
|
|
158
|
-
'<<< RESPONSE',
|
|
159
|
-
`Status: ${response.status} ${response.statusText}`,
|
|
160
|
-
'Headers:',
|
|
161
|
-
formatHeaders(response.headers),
|
|
162
|
-
'Body:',
|
|
163
|
-
` ${responseBody || '[empty]'}`,
|
|
164
|
-
'',
|
|
165
|
-
separator,
|
|
166
|
-
'',
|
|
167
|
-
];
|
|
168
|
-
const content = lines.join('\n');
|
|
169
|
-
if (output === 'console') {
|
|
170
|
-
console.error(content);
|
|
171
|
-
}
|
|
172
|
-
else {
|
|
173
|
-
// Append to file
|
|
174
|
-
try {
|
|
175
|
-
appendFileSync(output, content + '\n');
|
|
176
|
-
}
|
|
177
|
-
catch {
|
|
178
|
-
// If file write fails, fall back to console.error
|
|
179
|
-
console.error(`[API DEBUG] Failed to write to ${output}, falling back to console`);
|
|
180
|
-
console.error(content);
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
/**
|
|
185
|
-
* Redacts the middle of a string while keeping a prefix and suffix visible.
|
|
186
|
-
* Ensures that if the string is too short, everything is redacted.
|
|
187
|
-
*
|
|
188
|
-
* @param input The string to redact
|
|
189
|
-
* @param prefix Number of chars to keep at the start
|
|
190
|
-
* @param suffix Number of chars to keep at the end
|
|
191
|
-
* @param mask Character used for redaction
|
|
192
|
-
*/
|
|
193
|
-
export function redact(input, prefix = 4, suffix = 4, mask = '*') {
|
|
194
|
-
if (!input)
|
|
195
|
-
return '';
|
|
196
|
-
// If revealing prefix+suffix would leak too much, fully mask
|
|
197
|
-
if (input.length <= prefix + suffix) {
|
|
198
|
-
return mask.repeat(input.length);
|
|
199
|
-
}
|
|
200
|
-
const start = input.slice(0, prefix);
|
|
201
|
-
const end = input.slice(-suffix);
|
|
202
|
-
const hiddenLength = input.length - prefix - suffix;
|
|
203
|
-
return start + mask.repeat(hiddenLength) + end;
|
|
204
|
-
}
|
|
205
|
-
const redactHeaders = (kv) => {
|
|
206
|
-
const values = [];
|
|
207
|
-
for (const k of Object.keys(kv)) {
|
|
208
|
-
const _k = k.toLowerCase();
|
|
209
|
-
const v = kv[k];
|
|
210
|
-
if (v === undefined) {
|
|
211
|
-
continue;
|
|
212
|
-
}
|
|
213
|
-
if (sensitiveHeaders.has(_k)) {
|
|
214
|
-
values.push(`${_k}=${redactSensitiveHeader(k, v)}`);
|
|
215
|
-
}
|
|
216
|
-
else {
|
|
217
|
-
values.push(`${_k}=${v}`);
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
return '[' + values.join(',') + ']';
|
|
221
|
-
};
|
|
222
|
-
class ServerFetchAdapter {
|
|
223
|
-
#config;
|
|
224
|
-
#logger;
|
|
225
|
-
constructor(config, logger) {
|
|
226
|
-
this.#config = config;
|
|
227
|
-
this.#logger = logger;
|
|
228
|
-
}
|
|
229
|
-
/**
|
|
230
|
-
* Build the final URL with query params appended.
|
|
231
|
-
* This is extracted so both invoke() and _invoke() use the same URL.
|
|
232
|
-
*/
|
|
233
|
-
#buildUrl(url) {
|
|
234
|
-
if (this.#config.queryParams && Object.keys(this.#config.queryParams).length > 0) {
|
|
235
|
-
const urlObj = new URL(url);
|
|
236
|
-
for (const [key, value] of Object.entries(this.#config.queryParams)) {
|
|
237
|
-
urlObj.searchParams.set(key, value);
|
|
238
|
-
}
|
|
239
|
-
return urlObj.toString();
|
|
240
|
-
}
|
|
241
|
-
return url;
|
|
242
|
-
}
|
|
243
|
-
async _invoke(url, options) {
|
|
244
|
-
// URL already has query params appended by invoke() or direct caller
|
|
245
|
-
const headers = {
|
|
246
|
-
...options.headers,
|
|
247
|
-
...this.#config.headers,
|
|
248
|
-
};
|
|
249
|
-
if (options.contentType) {
|
|
250
|
-
headers['Content-Type'] = options.contentType;
|
|
251
|
-
}
|
|
252
|
-
else if (typeof options.body === 'string' ||
|
|
253
|
-
options.body instanceof Uint8Array ||
|
|
254
|
-
options.body instanceof ArrayBuffer) {
|
|
255
|
-
headers['Content-Type'] = 'application/octet-stream';
|
|
256
|
-
}
|
|
257
|
-
// Ensure we request JSON responses for proper error handling
|
|
258
|
-
if (!headers['Accept'] && !headers['accept']) {
|
|
259
|
-
headers['Accept'] = 'application/json';
|
|
260
|
-
}
|
|
261
|
-
const method = options.method ?? 'POST';
|
|
262
|
-
this.#logger.trace('sending %s to %s with headers: %s', method, url, redactHeaders(headers));
|
|
263
|
-
const res = await fetch(url, {
|
|
264
|
-
method,
|
|
265
|
-
body: options.body,
|
|
266
|
-
headers,
|
|
267
|
-
signal: options.signal,
|
|
268
|
-
...(options.duplex ? { duplex: options.duplex } : {}),
|
|
269
|
-
});
|
|
270
|
-
if (res.ok) {
|
|
271
|
-
switch (res.status) {
|
|
272
|
-
case 100:
|
|
273
|
-
case 101:
|
|
274
|
-
case 102:
|
|
275
|
-
case 204:
|
|
276
|
-
case 304:
|
|
277
|
-
return {
|
|
278
|
-
ok: true,
|
|
279
|
-
data: undefined,
|
|
280
|
-
response: res,
|
|
281
|
-
};
|
|
282
|
-
default:
|
|
283
|
-
break;
|
|
284
|
-
}
|
|
285
|
-
if (options?.binary) {
|
|
286
|
-
return {
|
|
287
|
-
ok: true,
|
|
288
|
-
data: undefined,
|
|
289
|
-
response: res,
|
|
290
|
-
};
|
|
291
|
-
}
|
|
292
|
-
const data = await fromResponse(res);
|
|
293
|
-
return {
|
|
294
|
-
ok: true,
|
|
295
|
-
data,
|
|
296
|
-
response: res,
|
|
297
|
-
};
|
|
298
|
-
}
|
|
299
|
-
if (res.status === 404) {
|
|
300
|
-
// Log debug info for 404 errors if debugging is enabled
|
|
301
|
-
if (getDebugOutput()) {
|
|
302
|
-
const responseBody = await res.clone().text();
|
|
303
|
-
logAPIDebug(url, method, headers, options.body, res, responseBody);
|
|
304
|
-
}
|
|
305
|
-
return {
|
|
306
|
-
ok: false,
|
|
307
|
-
response: res,
|
|
308
|
-
};
|
|
309
|
-
}
|
|
310
|
-
// Clone response to read body for debug logging before toServiceException consumes it
|
|
311
|
-
const responseBody = getDebugOutput() ? await res.clone().text() : '';
|
|
312
|
-
logAPIDebug(url, method, headers, options.body, res, responseBody);
|
|
313
|
-
const err = await toServiceException(method, url, res);
|
|
314
|
-
throw err;
|
|
315
|
-
}
|
|
316
|
-
async invoke(url, options = { method: 'POST' }) {
|
|
317
|
-
// Build final URL with query params BEFORE hooks, so hooks receive the actual URL
|
|
318
|
-
const finalUrl = this.#buildUrl(url);
|
|
319
|
-
if (this.#config.onBefore) {
|
|
320
|
-
let result = undefined;
|
|
321
|
-
let err = undefined;
|
|
322
|
-
await this.#config.onBefore(finalUrl, options, async () => {
|
|
323
|
-
try {
|
|
324
|
-
result = await this._invoke(finalUrl, options);
|
|
325
|
-
if (this.#config.onAfter) {
|
|
326
|
-
await this.#config.onAfter(finalUrl, options, result);
|
|
327
|
-
}
|
|
328
|
-
}
|
|
329
|
-
catch (ex) {
|
|
330
|
-
err = ex;
|
|
331
|
-
if (this.#config.onAfter && err instanceof ServiceException) {
|
|
332
|
-
await this.#config.onAfter(finalUrl, options, {
|
|
333
|
-
ok: false,
|
|
334
|
-
response: new Response(err.message, {
|
|
335
|
-
status: err.statusCode,
|
|
336
|
-
}),
|
|
337
|
-
}, err);
|
|
338
|
-
}
|
|
339
|
-
}
|
|
340
|
-
});
|
|
341
|
-
if (err) {
|
|
342
|
-
throw err;
|
|
343
|
-
}
|
|
344
|
-
return result;
|
|
345
|
-
}
|
|
346
|
-
else {
|
|
347
|
-
return await this._invoke(finalUrl, options);
|
|
348
|
-
}
|
|
349
|
-
}
|
|
350
|
-
}
|
|
351
|
-
/**
|
|
352
|
-
* Create a Server Side Fetch Adapter to allow the server to add headers and track outgoing requests
|
|
353
|
-
*
|
|
354
|
-
* @param config the service config
|
|
355
|
-
* @returns
|
|
356
|
-
*/
|
|
357
|
-
export function createServerFetchAdapter(config, logger) {
|
|
358
|
-
return new ServerFetchAdapter(config, logger);
|
|
359
|
-
}
|
|
360
|
-
//# sourceMappingURL=server.js.map
|
package/dist/server.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
|
package/src/server.ts
DELETED
|
@@ -1,424 +0,0 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
FetchRequest,
|
|
3
|
-
FetchErrorResponse,
|
|
4
|
-
FetchResponse,
|
|
5
|
-
FetchAdapter,
|
|
6
|
-
Logger,
|
|
7
|
-
HttpMethod,
|
|
8
|
-
} from '@agentuity/core';
|
|
9
|
-
import { ServiceException, toServiceException, fromResponse } from '@agentuity/core';
|
|
10
|
-
import { appendFileSync } from 'node:fs';
|
|
11
|
-
|
|
12
|
-
interface ServiceAdapterConfig {
|
|
13
|
-
headers: Record<string, string>;
|
|
14
|
-
queryParams?: Record<string, string>;
|
|
15
|
-
onBefore?: (url: string, options: FetchRequest, invoke: () => Promise<void>) => Promise<void>;
|
|
16
|
-
onAfter?: <T>(
|
|
17
|
-
url: string,
|
|
18
|
-
options: FetchRequest,
|
|
19
|
-
response: FetchResponse<T>,
|
|
20
|
-
err?: InstanceType<typeof ServiceException>
|
|
21
|
-
) => Promise<void>;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Options for building client request headers.
|
|
26
|
-
*/
|
|
27
|
-
export interface BuildClientHeadersOptions {
|
|
28
|
-
/** API key for authentication (Bearer token) */
|
|
29
|
-
apiKey?: string;
|
|
30
|
-
/** Organization ID for multi-tenant requests */
|
|
31
|
-
orgId?: string;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* Builds standard headers for Agentuity service clients.
|
|
36
|
-
*
|
|
37
|
-
* This helper creates the header object needed by `createServerFetchAdapter`,
|
|
38
|
-
* handling authentication and multi-tenant scoping consistently across all clients.
|
|
39
|
-
*
|
|
40
|
-
* @param options - Options containing apiKey and/or orgId
|
|
41
|
-
* @returns Headers object ready to pass to createServerFetchAdapter
|
|
42
|
-
*
|
|
43
|
-
* @example
|
|
44
|
-
* ```typescript
|
|
45
|
-
* import { buildClientHeaders, createServerFetchAdapter } from '@agentuity/server';
|
|
46
|
-
*
|
|
47
|
-
* const headers = buildClientHeaders({ apiKey: 'sk_xxx', orgId: 'org_xxx' });
|
|
48
|
-
* const adapter = createServerFetchAdapter({ headers }, logger);
|
|
49
|
-
* ```
|
|
50
|
-
*/
|
|
51
|
-
export function buildClientHeaders(options: BuildClientHeadersOptions): Record<string, string> {
|
|
52
|
-
const headers: Record<string, string> = options.apiKey
|
|
53
|
-
? {
|
|
54
|
-
Authorization: `Bearer ${options.apiKey}`,
|
|
55
|
-
'Content-Type': 'application/json',
|
|
56
|
-
}
|
|
57
|
-
: { 'Content-Type': 'application/json' };
|
|
58
|
-
|
|
59
|
-
if (options.orgId) {
|
|
60
|
-
headers['x-agentuity-orgid'] = options.orgId;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
return headers;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* Headers that contain sensitive information and should be redacted in debug logs.
|
|
68
|
-
* Includes authentication tokens, API keys, cookies, and proxy credentials.
|
|
69
|
-
*/
|
|
70
|
-
const sensitiveHeaders = new Set([
|
|
71
|
-
'authorization',
|
|
72
|
-
'x-api-key',
|
|
73
|
-
'cookie',
|
|
74
|
-
'set-cookie',
|
|
75
|
-
'proxy-authorization',
|
|
76
|
-
]);
|
|
77
|
-
|
|
78
|
-
/**
|
|
79
|
-
* Check if API debug logging is enabled and return the output destination.
|
|
80
|
-
* Returns:
|
|
81
|
-
* - 'console' if CI=1/true or AGENTUITY_API_DEBUG=1/true
|
|
82
|
-
* - file path string if AGENTUITY_API_DEBUG is set to a path
|
|
83
|
-
* - null if debug logging is disabled (including AGENTUITY_API_DEBUG=0/false)
|
|
84
|
-
*/
|
|
85
|
-
function getDebugOutput(): 'console' | string | null {
|
|
86
|
-
const apiDebug = process.env.AGENTUITY_API_DEBUG?.trim();
|
|
87
|
-
if (apiDebug) {
|
|
88
|
-
const normalized = apiDebug.toLowerCase();
|
|
89
|
-
// Check if explicitly disabled
|
|
90
|
-
if (normalized === '0' || normalized === 'false') {
|
|
91
|
-
return null;
|
|
92
|
-
}
|
|
93
|
-
// Check if it's a truthy value (console output)
|
|
94
|
-
if (normalized === '1' || normalized === 'true') {
|
|
95
|
-
return 'console';
|
|
96
|
-
}
|
|
97
|
-
// Treat any other non-empty value as a file path
|
|
98
|
-
return apiDebug;
|
|
99
|
-
}
|
|
100
|
-
// Fall back to CI environment check
|
|
101
|
-
if (process.env.CI === '1' || process.env.CI === 'true') {
|
|
102
|
-
return 'console';
|
|
103
|
-
}
|
|
104
|
-
return null;
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
/**
|
|
108
|
-
* Format request body for CI debug logging
|
|
109
|
-
*/
|
|
110
|
-
function formatRequestBody(body: unknown): string {
|
|
111
|
-
if (body === undefined || body === null) {
|
|
112
|
-
return '[no body]';
|
|
113
|
-
}
|
|
114
|
-
if (typeof body === 'string') {
|
|
115
|
-
return body;
|
|
116
|
-
}
|
|
117
|
-
if (body instanceof Uint8Array) {
|
|
118
|
-
return `[binary data: ${body.length} bytes]`;
|
|
119
|
-
}
|
|
120
|
-
if (body instanceof ArrayBuffer) {
|
|
121
|
-
return `[binary data: ${body.byteLength} bytes]`;
|
|
122
|
-
}
|
|
123
|
-
if (body instanceof ReadableStream) {
|
|
124
|
-
return '[stream]';
|
|
125
|
-
}
|
|
126
|
-
return String(body);
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
/**
|
|
130
|
-
* Format a sensitive header value, preserving Bearer prefix if present.
|
|
131
|
-
*/
|
|
132
|
-
function redactSensitiveHeader(key: string, value: string): string {
|
|
133
|
-
const _k = key.toLowerCase();
|
|
134
|
-
// Handle Bearer tokens in authorization and proxy-authorization headers
|
|
135
|
-
if ((_k === 'authorization' || _k === 'proxy-authorization') && value.startsWith('Bearer ')) {
|
|
136
|
-
return `Bearer ${redact(value.substring(7))}`;
|
|
137
|
-
}
|
|
138
|
-
return redact(value);
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
/**
|
|
142
|
-
* Format headers as a readable string for debug logging.
|
|
143
|
-
* Sensitive headers (auth tokens, cookies, API keys) are redacted.
|
|
144
|
-
*/
|
|
145
|
-
function formatHeaders(headers: Headers | Record<string, string>): string {
|
|
146
|
-
const entries: string[] = [];
|
|
147
|
-
if (headers instanceof Headers) {
|
|
148
|
-
headers.forEach((value, key) => {
|
|
149
|
-
const _k = key.toLowerCase();
|
|
150
|
-
if (sensitiveHeaders.has(_k)) {
|
|
151
|
-
entries.push(` ${key}: ${redactSensitiveHeader(key, value)}`);
|
|
152
|
-
} else {
|
|
153
|
-
entries.push(` ${key}: ${value}`);
|
|
154
|
-
}
|
|
155
|
-
});
|
|
156
|
-
} else {
|
|
157
|
-
for (const [key, value] of Object.entries(headers)) {
|
|
158
|
-
const _k = key.toLowerCase();
|
|
159
|
-
if (sensitiveHeaders.has(_k)) {
|
|
160
|
-
entries.push(` ${key}: ${redactSensitiveHeader(key, value)}`);
|
|
161
|
-
} else {
|
|
162
|
-
entries.push(` ${key}: ${value}`);
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
return entries.join('\n');
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
/**
|
|
170
|
-
* Log detailed debug information when API requests fail.
|
|
171
|
-
* Output destination is determined by AGENTUITY_API_DEBUG or CI environment variables.
|
|
172
|
-
*/
|
|
173
|
-
function logAPIDebug(
|
|
174
|
-
url: string,
|
|
175
|
-
method: string,
|
|
176
|
-
requestHeaders: Record<string, string>,
|
|
177
|
-
requestBody: unknown,
|
|
178
|
-
response: Response,
|
|
179
|
-
responseBody: string
|
|
180
|
-
): void {
|
|
181
|
-
const output = getDebugOutput();
|
|
182
|
-
if (!output) {
|
|
183
|
-
return;
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
const separator = '='.repeat(60);
|
|
187
|
-
const timestamp = new Date().toISOString();
|
|
188
|
-
const lines = [
|
|
189
|
-
'',
|
|
190
|
-
separator,
|
|
191
|
-
`API DEBUG: Request Failed [${timestamp}]`,
|
|
192
|
-
separator,
|
|
193
|
-
'',
|
|
194
|
-
'>>> REQUEST',
|
|
195
|
-
`URL: ${url}`,
|
|
196
|
-
`Method: ${method}`,
|
|
197
|
-
'Headers:',
|
|
198
|
-
formatHeaders(requestHeaders),
|
|
199
|
-
'Body:',
|
|
200
|
-
` ${formatRequestBody(requestBody)}`,
|
|
201
|
-
'',
|
|
202
|
-
'<<< RESPONSE',
|
|
203
|
-
`Status: ${response.status} ${response.statusText}`,
|
|
204
|
-
'Headers:',
|
|
205
|
-
formatHeaders(response.headers),
|
|
206
|
-
'Body:',
|
|
207
|
-
` ${responseBody || '[empty]'}`,
|
|
208
|
-
'',
|
|
209
|
-
separator,
|
|
210
|
-
'',
|
|
211
|
-
];
|
|
212
|
-
|
|
213
|
-
const content = lines.join('\n');
|
|
214
|
-
|
|
215
|
-
if (output === 'console') {
|
|
216
|
-
console.error(content);
|
|
217
|
-
} else {
|
|
218
|
-
// Append to file
|
|
219
|
-
try {
|
|
220
|
-
appendFileSync(output, content + '\n');
|
|
221
|
-
} catch {
|
|
222
|
-
// If file write fails, fall back to console.error
|
|
223
|
-
console.error(`[API DEBUG] Failed to write to ${output}, falling back to console`);
|
|
224
|
-
console.error(content);
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
/**
|
|
230
|
-
* Redacts the middle of a string while keeping a prefix and suffix visible.
|
|
231
|
-
* Ensures that if the string is too short, everything is redacted.
|
|
232
|
-
*
|
|
233
|
-
* @param input The string to redact
|
|
234
|
-
* @param prefix Number of chars to keep at the start
|
|
235
|
-
* @param suffix Number of chars to keep at the end
|
|
236
|
-
* @param mask Character used for redaction
|
|
237
|
-
*/
|
|
238
|
-
export function redact(
|
|
239
|
-
input: string,
|
|
240
|
-
prefix: number = 4,
|
|
241
|
-
suffix: number = 4,
|
|
242
|
-
mask: string = '*'
|
|
243
|
-
): string {
|
|
244
|
-
if (!input) return '';
|
|
245
|
-
|
|
246
|
-
// If revealing prefix+suffix would leak too much, fully mask
|
|
247
|
-
if (input.length <= prefix + suffix) {
|
|
248
|
-
return mask.repeat(input.length);
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
const start = input.slice(0, prefix);
|
|
252
|
-
const end = input.slice(-suffix);
|
|
253
|
-
const hiddenLength = input.length - prefix - suffix;
|
|
254
|
-
|
|
255
|
-
return start + mask.repeat(hiddenLength) + end;
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
const redactHeaders = (kv: Record<string, string>): string => {
|
|
259
|
-
const values: string[] = [];
|
|
260
|
-
for (const k of Object.keys(kv)) {
|
|
261
|
-
const _k = k.toLowerCase();
|
|
262
|
-
const v = kv[k];
|
|
263
|
-
if (v === undefined) {
|
|
264
|
-
continue;
|
|
265
|
-
}
|
|
266
|
-
if (sensitiveHeaders.has(_k)) {
|
|
267
|
-
values.push(`${_k}=${redactSensitiveHeader(k, v)}`);
|
|
268
|
-
} else {
|
|
269
|
-
values.push(`${_k}=${v}`);
|
|
270
|
-
}
|
|
271
|
-
}
|
|
272
|
-
return '[' + values.join(',') + ']';
|
|
273
|
-
};
|
|
274
|
-
|
|
275
|
-
class ServerFetchAdapter implements FetchAdapter {
|
|
276
|
-
#config: ServiceAdapterConfig;
|
|
277
|
-
#logger: Logger;
|
|
278
|
-
|
|
279
|
-
constructor(config: ServiceAdapterConfig, logger: Logger) {
|
|
280
|
-
this.#config = config;
|
|
281
|
-
this.#logger = logger;
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
/**
|
|
285
|
-
* Build the final URL with query params appended.
|
|
286
|
-
* This is extracted so both invoke() and _invoke() use the same URL.
|
|
287
|
-
*/
|
|
288
|
-
#buildUrl(url: string): string {
|
|
289
|
-
if (this.#config.queryParams && Object.keys(this.#config.queryParams).length > 0) {
|
|
290
|
-
const urlObj = new URL(url);
|
|
291
|
-
for (const [key, value] of Object.entries(this.#config.queryParams)) {
|
|
292
|
-
urlObj.searchParams.set(key, value);
|
|
293
|
-
}
|
|
294
|
-
return urlObj.toString();
|
|
295
|
-
}
|
|
296
|
-
return url;
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
private async _invoke<T>(url: string, options: FetchRequest): Promise<FetchResponse<T>> {
|
|
300
|
-
// URL already has query params appended by invoke() or direct caller
|
|
301
|
-
const headers: Record<string, string> = {
|
|
302
|
-
...options.headers,
|
|
303
|
-
...this.#config.headers,
|
|
304
|
-
};
|
|
305
|
-
if (options.contentType) {
|
|
306
|
-
headers['Content-Type'] = options.contentType;
|
|
307
|
-
} else if (
|
|
308
|
-
typeof options.body === 'string' ||
|
|
309
|
-
options.body instanceof Uint8Array ||
|
|
310
|
-
options.body instanceof ArrayBuffer
|
|
311
|
-
) {
|
|
312
|
-
headers['Content-Type'] = 'application/octet-stream';
|
|
313
|
-
}
|
|
314
|
-
// Ensure we request JSON responses for proper error handling
|
|
315
|
-
if (!headers['Accept'] && !headers['accept']) {
|
|
316
|
-
headers['Accept'] = 'application/json';
|
|
317
|
-
}
|
|
318
|
-
const method: HttpMethod = options.method ?? 'POST';
|
|
319
|
-
this.#logger.trace('sending %s to %s with headers: %s', method, url, redactHeaders(headers));
|
|
320
|
-
const res = await fetch(url, {
|
|
321
|
-
method,
|
|
322
|
-
body: options.body,
|
|
323
|
-
headers,
|
|
324
|
-
signal: options.signal,
|
|
325
|
-
...(options.duplex ? { duplex: options.duplex } : {}),
|
|
326
|
-
});
|
|
327
|
-
if (res.ok) {
|
|
328
|
-
switch (res.status) {
|
|
329
|
-
case 100:
|
|
330
|
-
case 101:
|
|
331
|
-
case 102:
|
|
332
|
-
case 204:
|
|
333
|
-
case 304:
|
|
334
|
-
return {
|
|
335
|
-
ok: true,
|
|
336
|
-
data: undefined as T,
|
|
337
|
-
response: res,
|
|
338
|
-
};
|
|
339
|
-
default:
|
|
340
|
-
break;
|
|
341
|
-
}
|
|
342
|
-
if (options?.binary) {
|
|
343
|
-
return {
|
|
344
|
-
ok: true,
|
|
345
|
-
data: undefined as T,
|
|
346
|
-
response: res,
|
|
347
|
-
};
|
|
348
|
-
}
|
|
349
|
-
const data = await fromResponse<T>(res);
|
|
350
|
-
return {
|
|
351
|
-
ok: true,
|
|
352
|
-
data,
|
|
353
|
-
response: res,
|
|
354
|
-
};
|
|
355
|
-
}
|
|
356
|
-
if (res.status === 404) {
|
|
357
|
-
// Log debug info for 404 errors if debugging is enabled
|
|
358
|
-
if (getDebugOutput()) {
|
|
359
|
-
const responseBody = await res.clone().text();
|
|
360
|
-
logAPIDebug(url, method, headers, options.body, res, responseBody);
|
|
361
|
-
}
|
|
362
|
-
return {
|
|
363
|
-
ok: false,
|
|
364
|
-
response: res,
|
|
365
|
-
} as FetchErrorResponse;
|
|
366
|
-
}
|
|
367
|
-
// Clone response to read body for debug logging before toServiceException consumes it
|
|
368
|
-
const responseBody = getDebugOutput() ? await res.clone().text() : '';
|
|
369
|
-
logAPIDebug(url, method, headers, options.body, res, responseBody);
|
|
370
|
-
const err = await toServiceException(method, url, res);
|
|
371
|
-
throw err;
|
|
372
|
-
}
|
|
373
|
-
async invoke<T>(
|
|
374
|
-
url: string,
|
|
375
|
-
options: FetchRequest = { method: 'POST' }
|
|
376
|
-
): Promise<FetchResponse<T>> {
|
|
377
|
-
// Build final URL with query params BEFORE hooks, so hooks receive the actual URL
|
|
378
|
-
const finalUrl = this.#buildUrl(url);
|
|
379
|
-
|
|
380
|
-
if (this.#config.onBefore) {
|
|
381
|
-
let result: FetchResponse<T> | undefined = undefined;
|
|
382
|
-
let err: Error | undefined = undefined;
|
|
383
|
-
await this.#config.onBefore(finalUrl, options, async () => {
|
|
384
|
-
try {
|
|
385
|
-
result = await this._invoke(finalUrl, options);
|
|
386
|
-
if (this.#config.onAfter) {
|
|
387
|
-
await this.#config.onAfter(finalUrl, options, result);
|
|
388
|
-
}
|
|
389
|
-
} catch (ex) {
|
|
390
|
-
err = ex as Error;
|
|
391
|
-
if (this.#config.onAfter && err instanceof ServiceException) {
|
|
392
|
-
await this.#config.onAfter(
|
|
393
|
-
finalUrl,
|
|
394
|
-
options,
|
|
395
|
-
{
|
|
396
|
-
ok: false,
|
|
397
|
-
response: new Response(err.message, {
|
|
398
|
-
status: err.statusCode,
|
|
399
|
-
}),
|
|
400
|
-
} as FetchErrorResponse,
|
|
401
|
-
err
|
|
402
|
-
);
|
|
403
|
-
}
|
|
404
|
-
}
|
|
405
|
-
});
|
|
406
|
-
if (err) {
|
|
407
|
-
throw err;
|
|
408
|
-
}
|
|
409
|
-
return result as unknown as FetchResponse<T>;
|
|
410
|
-
} else {
|
|
411
|
-
return await this._invoke(finalUrl, options);
|
|
412
|
-
}
|
|
413
|
-
}
|
|
414
|
-
}
|
|
415
|
-
|
|
416
|
-
/**
|
|
417
|
-
* Create a Server Side Fetch Adapter to allow the server to add headers and track outgoing requests
|
|
418
|
-
*
|
|
419
|
-
* @param config the service config
|
|
420
|
-
* @returns
|
|
421
|
-
*/
|
|
422
|
-
export function createServerFetchAdapter(config: ServiceAdapterConfig, logger: Logger) {
|
|
423
|
-
return new ServerFetchAdapter(config, logger);
|
|
424
|
-
}
|