@jini-ai/http-kit 0.2.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.
Files changed (227) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +107 -0
  3. package/dist/active-context.d.ts +99 -0
  4. package/dist/active-context.d.ts.map +1 -0
  5. package/dist/active-context.js +77 -0
  6. package/dist/active-context.js.map +1 -0
  7. package/dist/adapter.d.ts +36 -0
  8. package/dist/adapter.d.ts.map +1 -0
  9. package/dist/adapter.js +92 -0
  10. package/dist/adapter.js.map +1 -0
  11. package/dist/agents.d.ts +55 -0
  12. package/dist/agents.d.ts.map +1 -0
  13. package/dist/agents.js +23 -0
  14. package/dist/agents.js.map +1 -0
  15. package/dist/api-security-middleware.d.ts +146 -0
  16. package/dist/api-security-middleware.d.ts.map +1 -0
  17. package/dist/api-security-middleware.js +276 -0
  18. package/dist/api-security-middleware.js.map +1 -0
  19. package/dist/attachments.d.ts +317 -0
  20. package/dist/attachments.d.ts.map +1 -0
  21. package/dist/attachments.js +664 -0
  22. package/dist/attachments.js.map +1 -0
  23. package/dist/cancel-owned-runs.d.ts +44 -0
  24. package/dist/cancel-owned-runs.d.ts.map +1 -0
  25. package/dist/cancel-owned-runs.js +35 -0
  26. package/dist/cancel-owned-runs.js.map +1 -0
  27. package/dist/compat.d.ts +22 -0
  28. package/dist/compat.d.ts.map +1 -0
  29. package/dist/compat.js +17 -0
  30. package/dist/compat.js.map +1 -0
  31. package/dist/component-catalog.d.ts +74 -0
  32. package/dist/component-catalog.d.ts.map +1 -0
  33. package/dist/component-catalog.js +74 -0
  34. package/dist/component-catalog.js.map +1 -0
  35. package/dist/connectors.d.ts +165 -0
  36. package/dist/connectors.d.ts.map +1 -0
  37. package/dist/connectors.js +474 -0
  38. package/dist/connectors.js.map +1 -0
  39. package/dist/daemon-status.d.ts +72 -0
  40. package/dist/daemon-status.d.ts.map +1 -0
  41. package/dist/daemon-status.js +60 -0
  42. package/dist/daemon-status.js.map +1 -0
  43. package/dist/db-ops.d.ts +116 -0
  44. package/dist/db-ops.d.ts.map +1 -0
  45. package/dist/db-ops.js +191 -0
  46. package/dist/db-ops.js.map +1 -0
  47. package/dist/delegated-tools.d.ts +46 -0
  48. package/dist/delegated-tools.d.ts.map +1 -0
  49. package/dist/delegated-tools.js +155 -0
  50. package/dist/delegated-tools.js.map +1 -0
  51. package/dist/express/run-stream.d.ts +15 -0
  52. package/dist/express/run-stream.d.ts.map +1 -0
  53. package/dist/express/run-stream.js +11 -0
  54. package/dist/express/run-stream.js.map +1 -0
  55. package/dist/express-index.d.ts +32 -0
  56. package/dist/express-index.d.ts.map +1 -0
  57. package/dist/express-index.js +14 -0
  58. package/dist/express-index.js.map +1 -0
  59. package/dist/fastify/adapter.d.ts +31 -0
  60. package/dist/fastify/adapter.d.ts.map +1 -0
  61. package/dist/fastify/adapter.js +64 -0
  62. package/dist/fastify/adapter.js.map +1 -0
  63. package/dist/fastify/agents.d.ts +13 -0
  64. package/dist/fastify/agents.d.ts.map +1 -0
  65. package/dist/fastify/agents.js +7 -0
  66. package/dist/fastify/agents.js.map +1 -0
  67. package/dist/fastify/api-security-middleware.d.ts +64 -0
  68. package/dist/fastify/api-security-middleware.d.ts.map +1 -0
  69. package/dist/fastify/api-security-middleware.js +139 -0
  70. package/dist/fastify/api-security-middleware.js.map +1 -0
  71. package/dist/fastify/compat.d.ts +22 -0
  72. package/dist/fastify/compat.d.ts.map +1 -0
  73. package/dist/fastify/compat.js +16 -0
  74. package/dist/fastify/compat.js.map +1 -0
  75. package/dist/fastify/daemon-status.d.ts +22 -0
  76. package/dist/fastify/daemon-status.d.ts.map +1 -0
  77. package/dist/fastify/daemon-status.js +9 -0
  78. package/dist/fastify/daemon-status.js.map +1 -0
  79. package/dist/fastify/host-tools.d.ts +13 -0
  80. package/dist/fastify/host-tools.d.ts.map +1 -0
  81. package/dist/fastify/host-tools.js +8 -0
  82. package/dist/fastify/host-tools.js.map +1 -0
  83. package/dist/fastify/index.d.ts +36 -0
  84. package/dist/fastify/index.d.ts.map +1 -0
  85. package/dist/fastify/index.js +18 -0
  86. package/dist/fastify/index.js.map +1 -0
  87. package/dist/fastify/local-daemon-request.d.ts +43 -0
  88. package/dist/fastify/local-daemon-request.d.ts.map +1 -0
  89. package/dist/fastify/local-daemon-request.js +155 -0
  90. package/dist/fastify/local-daemon-request.js.map +1 -0
  91. package/dist/fastify/origin.d.ts +21 -0
  92. package/dist/fastify/origin.d.ts.map +1 -0
  93. package/dist/fastify/origin.js +14 -0
  94. package/dist/fastify/origin.js.map +1 -0
  95. package/dist/fastify/request.d.ts +20 -0
  96. package/dist/fastify/request.d.ts.map +1 -0
  97. package/dist/fastify/request.js +25 -0
  98. package/dist/fastify/request.js.map +1 -0
  99. package/dist/fastify/response.d.ts +20 -0
  100. package/dist/fastify/response.d.ts.map +1 -0
  101. package/dist/fastify/response.js +41 -0
  102. package/dist/fastify/response.js.map +1 -0
  103. package/dist/fastify/route-registration-guard.d.ts +70 -0
  104. package/dist/fastify/route-registration-guard.d.ts.map +1 -0
  105. package/dist/fastify/route-registration-guard.js +69 -0
  106. package/dist/fastify/route-registration-guard.js.map +1 -0
  107. package/dist/fastify/run-stream.d.ts +18 -0
  108. package/dist/fastify/run-stream.d.ts.map +1 -0
  109. package/dist/fastify/run-stream.js +10 -0
  110. package/dist/fastify/run-stream.js.map +1 -0
  111. package/dist/fastify/runs.d.ts +17 -0
  112. package/dist/fastify/runs.d.ts.map +1 -0
  113. package/dist/fastify/runs.js +33 -0
  114. package/dist/fastify/runs.js.map +1 -0
  115. package/dist/frontend-control.d.ts +131 -0
  116. package/dist/frontend-control.d.ts.map +1 -0
  117. package/dist/frontend-control.js +77 -0
  118. package/dist/frontend-control.js.map +1 -0
  119. package/dist/frontend-sessions.d.ts +100 -0
  120. package/dist/frontend-sessions.d.ts.map +1 -0
  121. package/dist/frontend-sessions.js +180 -0
  122. package/dist/frontend-sessions.js.map +1 -0
  123. package/dist/health.d.ts +91 -0
  124. package/dist/health.d.ts.map +1 -0
  125. package/dist/health.js +53 -0
  126. package/dist/health.js.map +1 -0
  127. package/dist/host-tools.d.ts +174 -0
  128. package/dist/host-tools.d.ts.map +1 -0
  129. package/dist/host-tools.js +338 -0
  130. package/dist/host-tools.js.map +1 -0
  131. package/dist/index.d.ts +86 -0
  132. package/dist/index.d.ts.map +1 -0
  133. package/dist/index.js +40 -0
  134. package/dist/index.js.map +1 -0
  135. package/dist/local-daemon-request.d.ts +44 -0
  136. package/dist/local-daemon-request.d.ts.map +1 -0
  137. package/dist/local-daemon-request.js +145 -0
  138. package/dist/local-daemon-request.js.map +1 -0
  139. package/dist/media.d.ts +131 -0
  140. package/dist/media.d.ts.map +1 -0
  141. package/dist/media.js +352 -0
  142. package/dist/media.js.map +1 -0
  143. package/dist/memory.d.ts +230 -0
  144. package/dist/memory.d.ts.map +1 -0
  145. package/dist/memory.js +331 -0
  146. package/dist/memory.js.map +1 -0
  147. package/dist/model-proxy.d.ts +45 -0
  148. package/dist/model-proxy.d.ts.map +1 -0
  149. package/dist/model-proxy.js +619 -0
  150. package/dist/model-proxy.js.map +1 -0
  151. package/dist/origin-validation.d.ts +64 -0
  152. package/dist/origin-validation.d.ts.map +1 -0
  153. package/dist/origin-validation.js +226 -0
  154. package/dist/origin-validation.js.map +1 -0
  155. package/dist/origin.d.ts +32 -0
  156. package/dist/origin.d.ts.map +1 -0
  157. package/dist/origin.js +14 -0
  158. package/dist/origin.js.map +1 -0
  159. package/dist/pack-http.d.ts +30 -0
  160. package/dist/pack-http.d.ts.map +1 -0
  161. package/dist/pack-http.js +12 -0
  162. package/dist/pack-http.js.map +1 -0
  163. package/dist/raw-sse.d.ts +44 -0
  164. package/dist/raw-sse.d.ts.map +1 -0
  165. package/dist/raw-sse.js +93 -0
  166. package/dist/raw-sse.js.map +1 -0
  167. package/dist/remote-run-events.d.ts +66 -0
  168. package/dist/remote-run-events.d.ts.map +1 -0
  169. package/dist/remote-run-events.js +230 -0
  170. package/dist/remote-run-events.js.map +1 -0
  171. package/dist/request.d.ts +19 -0
  172. package/dist/request.d.ts.map +1 -0
  173. package/dist/request.js +25 -0
  174. package/dist/request.js.map +1 -0
  175. package/dist/research.d.ts +42 -0
  176. package/dist/research.d.ts.map +1 -0
  177. package/dist/research.js +316 -0
  178. package/dist/research.js.map +1 -0
  179. package/dist/response.d.ts +14 -0
  180. package/dist/response.d.ts.map +1 -0
  181. package/dist/response.js +45 -0
  182. package/dist/response.js.map +1 -0
  183. package/dist/route-manifest.d.ts +31 -0
  184. package/dist/route-manifest.d.ts.map +1 -0
  185. package/dist/route-manifest.js +103 -0
  186. package/dist/route-manifest.js.map +1 -0
  187. package/dist/route-registration-guard.d.ts +65 -0
  188. package/dist/route-registration-guard.d.ts.map +1 -0
  189. package/dist/route-registration-guard.js +71 -0
  190. package/dist/route-registration-guard.js.map +1 -0
  191. package/dist/routines.d.ts +114 -0
  192. package/dist/routines.d.ts.map +1 -0
  193. package/dist/routines.js +320 -0
  194. package/dist/routines.js.map +1 -0
  195. package/dist/run-stream.d.ts +60 -0
  196. package/dist/run-stream.d.ts.map +1 -0
  197. package/dist/run-stream.js +108 -0
  198. package/dist/run-stream.js.map +1 -0
  199. package/dist/runs.d.ts +79 -0
  200. package/dist/runs.d.ts.map +1 -0
  201. package/dist/runs.js +232 -0
  202. package/dist/runs.js.map +1 -0
  203. package/dist/sse.d.ts +139 -0
  204. package/dist/sse.d.ts.map +1 -0
  205. package/dist/sse.js +157 -0
  206. package/dist/sse.js.map +1 -0
  207. package/dist/terminals.d.ts +125 -0
  208. package/dist/terminals.d.ts.map +1 -0
  209. package/dist/terminals.js +349 -0
  210. package/dist/terminals.js.map +1 -0
  211. package/dist/tool-catalog.d.ts +68 -0
  212. package/dist/tool-catalog.d.ts.map +1 -0
  213. package/dist/tool-catalog.js +68 -0
  214. package/dist/tool-catalog.js.map +1 -0
  215. package/dist/types.d.ts +58 -0
  216. package/dist/types.d.ts.map +1 -0
  217. package/dist/types.js +5 -0
  218. package/dist/types.js.map +1 -0
  219. package/dist/workspace-root.d.ts +69 -0
  220. package/dist/workspace-root.d.ts.map +1 -0
  221. package/dist/workspace-root.js +63 -0
  222. package/dist/workspace-root.js.map +1 -0
  223. package/dist/xai.d.ts +86 -0
  224. package/dist/xai.d.ts.map +1 -0
  225. package/dist/xai.js +668 -0
  226. package/dist/xai.js.map +1 -0
  227. package/package.json +58 -0
@@ -0,0 +1,116 @@
1
+ import type { Express } from 'express';
2
+ import type { Principal, ToolPolicy, ToolRegistration } from '@jini-ai/core';
3
+ import type { ToolExecutor } from '@jini-ai/daemon';
4
+ import { type AdapterContext } from './adapter.js';
5
+ /** The `ToolRegistry` id `GET /api/daemon/db` executes through. */
6
+ export declare const DB_INSPECT_TOOL_ID = "daemon.db.inspect";
7
+ /** The `ToolRegistry` id `POST /api/daemon/db/verify` executes through. */
8
+ export declare const DB_VERIFY_TOOL_ID = "daemon.db.verify";
9
+ /** The `ToolRegistry` id `POST /api/daemon/db/vacuum` executes through. */
10
+ export declare const DB_VACUUM_TOOL_ID = "daemon.db.vacuum";
11
+ export interface DaemonDbTableInfo {
12
+ readonly name: string;
13
+ readonly rowCount: number;
14
+ }
15
+ /** Structurally identical to `@jini-ai/sqlite`'s `DaemonDbStatusReport` — defined locally so this package incurs no `better-sqlite3` dependency. */
16
+ export interface DaemonDbStatusReport {
17
+ readonly kind: 'sqlite' | 'postgres';
18
+ readonly location: string;
19
+ readonly sizeBytes: number;
20
+ readonly schemaVersion: number | null;
21
+ readonly tables: readonly DaemonDbTableInfo[];
22
+ readonly generatedAt: number;
23
+ }
24
+ export type DbIntegrityIssueKind = 'integrity' | 'foreign_key';
25
+ export interface DbIntegrityIssue {
26
+ readonly kind: DbIntegrityIssueKind;
27
+ readonly message: string;
28
+ }
29
+ /** Structurally identical to `@jini-ai/sqlite`'s `DbIntegrityReport`. */
30
+ export interface DbIntegrityReport {
31
+ readonly ok: boolean;
32
+ readonly mode: 'integrity_check' | 'quick_check';
33
+ readonly issues: readonly DbIntegrityIssue[];
34
+ readonly elapsedMs: number;
35
+ readonly generatedAt: number;
36
+ }
37
+ export interface DaemonDbVacuumResult {
38
+ readonly ok: true;
39
+ readonly beforeBytes: number;
40
+ readonly afterBytes: number;
41
+ readonly reclaimedBytes: number;
42
+ readonly elapsedMs: number;
43
+ }
44
+ /** The real collaborator a host injects — typically backed by `@jini-ai/sqlite`'s `inspectSqliteDatabase`/`verifySqliteIntegrity` plus a small `vacuum` wrapper around `db.exec('VACUUM')`. */
45
+ export interface DaemonDbOperations {
46
+ inspect(): Promise<DaemonDbStatusReport> | DaemonDbStatusReport;
47
+ verify(quick: boolean): Promise<DbIntegrityReport> | DbIntegrityReport;
48
+ vacuum(): Promise<DaemonDbVacuumResult> | DaemonDbVacuumResult;
49
+ }
50
+ /**
51
+ * Deny-by-default `ToolPolicy` shared by all three DB tools — every call is
52
+ * denied, unconditionally, regardless of principal. Matching
53
+ * `@jini-ai/deploy`'s `denyAllDeployPublishPolicy` precedent: a host must
54
+ * explicitly opt in with its own policy (e.g. role-gated, or "same principal
55
+ * that owns the daemon process") rather than getting a working DB inspector
56
+ * for free merely by registering the tools. `inspect`/`verify` disclose
57
+ * internal schema and row-count information; `vacuum` rewrites the database
58
+ * file in place — none of the three has a safe "mostly harmless" default the
59
+ * way a pure read-only, non-sensitive tool might.
60
+ */
61
+ export declare const denyAllDaemonDbPolicy: ToolPolicy;
62
+ export interface CreateDaemonDbToolRegistrationsOptions {
63
+ readonly operations: DaemonDbOperations;
64
+ /** Defaults to {@link denyAllDaemonDbPolicy} — see its doc for why a permissive default was rejected. Applies to all three tools; pass distinct `ToolRegistration.policy` values by registering them individually if a host wants per-operation rules. */
65
+ readonly policy?: ToolPolicy;
66
+ readonly requiresConfirmation?: boolean;
67
+ readonly timeoutMs?: number;
68
+ }
69
+ export interface DaemonDbToolRegistrations {
70
+ readonly inspect: ToolRegistration;
71
+ readonly verify: ToolRegistration;
72
+ readonly vacuum: ToolRegistration;
73
+ }
74
+ /**
75
+ * Builds the three `{descriptor, handler, policy}` triples a host registers
76
+ * against `@jini-ai/core`'s `ToolRegistry` so the DB operations become
77
+ * reachable only via `ToolExecutor.execute(principal, run, toolId, input)` —
78
+ * never by a route calling `operations.inspect()`/`verify()`/`vacuum()`
79
+ * directly, which would bypass authorization and the audit trail entirely.
80
+ *
81
+ * @complexity O(1) to build the three registrations; each handler's own cost is `operations`'s.
82
+ * @overallScore 100/100
83
+ */
84
+ export declare function createDaemonDbToolRegistrations(options: CreateDaemonDbToolRegistrationsOptions): DaemonDbToolRegistrations;
85
+ /** Diagnostic detail for an internal-error response the public API deliberately does not disclose (SEC-005, matching `runs.ts`'s `RunInternalErrorContext`): a `failed`/`timed-out`/`cancelled` tool execution can embed schema names, file paths, or a raw SQLite error message. */
86
+ export interface DaemonDbInternalErrorContext {
87
+ readonly source: 'db-inspect' | 'db-verify' | 'db-vacuum';
88
+ readonly correlationId: string;
89
+ readonly error: unknown;
90
+ }
91
+ export interface DaemonDbHttpDeps {
92
+ readonly toolExecutor: ToolExecutor;
93
+ /**
94
+ * The identity these routes execute tool calls as. A fixed, host-supplied
95
+ * value rather than derived per-request — this transport has no session/
96
+ * identity subsystem of its own (see `packages/http/source-map.md`'s
97
+ * `ExecutionDelegate` design-decision note); a host that needs per-request
98
+ * principals should resolve one from its own auth layer and construct
99
+ * `DaemonDbHttpDeps` per request, or supply a `ToolPolicy` that inspects
100
+ * something other than `Principal` to make its decision.
101
+ */
102
+ readonly principal: Principal;
103
+ /** Host-owned sink for the real exception behind a generic `INTERNAL_ERROR` response (SEC-005). Defaults to `console.error`. */
104
+ readonly onInternalError?: (context: DaemonDbInternalErrorContext) => void;
105
+ }
106
+ /** `GET /api/daemon/db` — the database inventory (schema version, tables, row counts, size). */
107
+ export declare const daemonDbInspectRoute: import("./types.js").JsonRouteSpec<void, DaemonDbStatusReport, DaemonDbHttpDeps>;
108
+ /** `POST /api/daemon/db/verify?quick=` — `PRAGMA integrity_check`/`quick_check` plus `foreign_key_check`. */
109
+ export declare const daemonDbVerifyRoute: import("./types.js").JsonRouteSpec<{
110
+ quick: boolean;
111
+ }, DbIntegrityReport, DaemonDbHttpDeps>;
112
+ /** `POST /api/daemon/db/vacuum` — runs `VACUUM` and reports bytes reclaimed. */
113
+ export declare const daemonDbVacuumRoute: import("./types.js").JsonRouteSpec<void, DaemonDbVacuumResult, DaemonDbHttpDeps>;
114
+ /** Mounts all three DB-ops routes on `app`. A pack's `http(app, services)` calls this directly. */
115
+ export declare function registerDaemonDbRoutes(app: Express, deps: DaemonDbHttpDeps, adapter: AdapterContext): void;
116
+ //# sourceMappingURL=db-ops.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"db-ops.d.ts","sourceRoot":"","sources":["../src/db-ops.ts"],"names":[],"mappings":"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"}
package/dist/db-ops.js ADDED
@@ -0,0 +1,191 @@
1
+ /**
2
+ * @module db-ops
3
+ *
4
+ * Daemon DB inspect/verify/vacuum operations, wired through the
5
+ * tool-execution boundary (`@jini-ai/core`'s `tool-registry.ts` + `@jini-ai/daemon`'s
6
+ * `tool-executor.ts`) rather than called directly from a route handler.
7
+ * Ported from OD's `apps/daemon/src/routes/daemon.ts` `GET /api/daemon/db`,
8
+ * `POST /api/daemon/db/verify`, `POST /api/daemon/db/vacuum` (see
9
+ * `source-map.md`'s routes-classification table, row `#12 daemon.ts`: "generic
10
+ * in shape but depend on a separate `storage/db-inspect.ts` port not built
11
+ * this round" — that port now exists as `@jini-ai/sqlite`'s `db-inspect.ts`).
12
+ *
13
+ * This module does **not** depend on `@jini-ai/sqlite` or `better-sqlite3` at
14
+ * all: `DaemonDbOperations` is a plain injected interface (structurally
15
+ * compatible with `@jini-ai/sqlite`'s `inspectSqliteDatabase`/
16
+ * `verifySqliteIntegrity` return shapes, so a caller can wire those in with
17
+ * zero adapter code) — the same "caller supplies the real collaborator"
18
+ * convention `daemon-status.ts`/`host-tools.ts` already established in this
19
+ * package.
20
+ *
21
+ * **Why the tool-execution boundary, not a plain route handler calling
22
+ * `DaemonDbOperations` directly:** these three operations reveal internal
23
+ * schema/row-count/file-size information (`inspect`/`verify`) and rewrite the
24
+ * database file in place (`vacuum`) — real security stakes the task brief
25
+ * that added this module named explicitly. OD's own origin gated only
26
+ * `verify`/`vacuum` behind `requireLocalDaemonRequest` and left `GET
27
+ * /api/daemon/db` completely ungated — a real pre-existing gap, not carried
28
+ * forward here. Per this repo's binding tool-execution-boundary precedent
29
+ * (`packages/deploy/src/tool.ts`'s `deploy.publish`, `packages/daemon/src/
30
+ * delegated-tool-bridge.ts`), the actual work happens only inside a
31
+ * `ToolHandler` `ToolExecutor.execute` invokes after `ToolPolicy.authorize`
32
+ * allows it — never directly from `registerDaemonDbRoutes`' handlers. All
33
+ * three routes also keep `requireSameOrigin: true` as a first line of
34
+ * defense (matching `daemon-status.ts`'s shutdown route), but that transport
35
+ * gate is defense in depth, not a substitute for the tool-execution
36
+ * boundary — see {@link denyAllDaemonDbPolicy}'s doc for why the default
37
+ * policy denies every call rather than allowing one.
38
+ */
39
+ import { randomUUID } from 'node:crypto';
40
+ import { createApiError } from '@jini-ai/protocol';
41
+ import { defineJsonRoute, mountJsonRoute } from './adapter.js';
42
+ import { validationError } from './request.js';
43
+ import { err, ok } from './types.js';
44
+ /** The `ToolRegistry` id `GET /api/daemon/db` executes through. */
45
+ export const DB_INSPECT_TOOL_ID = 'daemon.db.inspect';
46
+ /** The `ToolRegistry` id `POST /api/daemon/db/verify` executes through. */
47
+ export const DB_VERIFY_TOOL_ID = 'daemon.db.verify';
48
+ /** The `ToolRegistry` id `POST /api/daemon/db/vacuum` executes through. */
49
+ export const DB_VACUUM_TOOL_ID = 'daemon.db.vacuum';
50
+ /**
51
+ * Deny-by-default `ToolPolicy` shared by all three DB tools — every call is
52
+ * denied, unconditionally, regardless of principal. Matching
53
+ * `@jini-ai/deploy`'s `denyAllDeployPublishPolicy` precedent: a host must
54
+ * explicitly opt in with its own policy (e.g. role-gated, or "same principal
55
+ * that owns the daemon process") rather than getting a working DB inspector
56
+ * for free merely by registering the tools. `inspect`/`verify` disclose
57
+ * internal schema and row-count information; `vacuum` rewrites the database
58
+ * file in place — none of the three has a safe "mostly harmless" default the
59
+ * way a pure read-only, non-sensitive tool might.
60
+ */
61
+ export const denyAllDaemonDbPolicy = {
62
+ authorize: () => 'deny',
63
+ };
64
+ function isRecord(value) {
65
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
66
+ }
67
+ /**
68
+ * Builds the three `{descriptor, handler, policy}` triples a host registers
69
+ * against `@jini-ai/core`'s `ToolRegistry` so the DB operations become
70
+ * reachable only via `ToolExecutor.execute(principal, run, toolId, input)` —
71
+ * never by a route calling `operations.inspect()`/`verify()`/`vacuum()`
72
+ * directly, which would bypass authorization and the audit trail entirely.
73
+ *
74
+ * @complexity O(1) to build the three registrations; each handler's own cost is `operations`'s.
75
+ * @overallScore 100/100
76
+ */
77
+ export function createDaemonDbToolRegistrations(options) {
78
+ const { operations, policy = denyAllDaemonDbPolicy, requiresConfirmation, timeoutMs } = options;
79
+ const descriptorExtras = {
80
+ ...(requiresConfirmation !== undefined ? { requiresConfirmation } : {}),
81
+ ...(timeoutMs !== undefined ? { timeoutMs } : {}),
82
+ };
83
+ return {
84
+ inspect: {
85
+ descriptor: {
86
+ id: DB_INSPECT_TOOL_ID,
87
+ description: 'Inspects the daemon SQLite database: schema version, table list, row counts, on-disk size.',
88
+ ...descriptorExtras,
89
+ },
90
+ policy,
91
+ handler: async () => operations.inspect(),
92
+ },
93
+ verify: {
94
+ descriptor: {
95
+ id: DB_VERIFY_TOOL_ID,
96
+ description: 'Runs a SQLite integrity/foreign-key check against the daemon database.',
97
+ ...descriptorExtras,
98
+ },
99
+ policy,
100
+ handler: async (ctx) => {
101
+ const input = isRecord(ctx.input) ? ctx.input : {};
102
+ return operations.verify(input.quick === true);
103
+ },
104
+ },
105
+ vacuum: {
106
+ descriptor: {
107
+ id: DB_VACUUM_TOOL_ID,
108
+ description: 'Runs SQLite VACUUM against the daemon database and reports reclaimed bytes.',
109
+ ...descriptorExtras,
110
+ },
111
+ policy,
112
+ handler: async () => operations.vacuum(),
113
+ },
114
+ };
115
+ }
116
+ function defaultDaemonDbInternalErrorSink(context) {
117
+ // eslint-disable-next-line no-console
118
+ console.error(`[@jini-ai/http-kit] internal error (${context.source}, correlationId=${context.correlationId})`, context.error);
119
+ }
120
+ /** Every DB-ops call gets its own opaque, single-use `RunRef` — these are one-off operations requests, not steps of a longer-lived agent run, so there is no real run to attach the audit trail to. */
121
+ function freshRun() {
122
+ return { id: randomUUID() };
123
+ }
124
+ function toolResultToApiResult(deps, source, result) {
125
+ switch (result.status) {
126
+ case 'completed':
127
+ return ok(result.output);
128
+ case 'denied':
129
+ return err(createApiError('TOOL_OPERATION_DENIED', 'this operation was denied by policy'));
130
+ case 'confirmation-denied':
131
+ return err(createApiError('TOOL_OPERATION_DENIED', 'this operation was denied during confirmation'));
132
+ case 'timed-out':
133
+ case 'cancelled':
134
+ case 'failed': {
135
+ const correlationId = randomUUID();
136
+ const sink = deps.onInternalError ?? defaultDaemonDbInternalErrorSink;
137
+ sink({ source, correlationId, error: result.status === 'failed' ? result.error : result.status });
138
+ return err(createApiError('INTERNAL_ERROR', 'an internal error occurred', { requestId: correlationId }));
139
+ }
140
+ }
141
+ }
142
+ /** `GET /api/daemon/db` — the database inventory (schema version, tables, row counts, size). */
143
+ export const daemonDbInspectRoute = defineJsonRoute({
144
+ method: 'get',
145
+ path: '/api/daemon/db',
146
+ requireSameOrigin: true,
147
+ parse: () => ok(undefined),
148
+ handle: async (_input, deps) => {
149
+ const result = await deps.toolExecutor.execute(deps.principal, freshRun(), DB_INSPECT_TOOL_ID, undefined);
150
+ return toolResultToApiResult(deps, 'db-inspect', result);
151
+ },
152
+ });
153
+ function parseDbVerifyInput(input) {
154
+ const raw = input.query.quick;
155
+ if (raw === undefined)
156
+ return ok({ quick: false });
157
+ if (typeof raw !== 'string') {
158
+ return err(validationError('quick must be a single query-string value when provided'));
159
+ }
160
+ const normalized = raw.toLowerCase();
161
+ return ok({ quick: normalized === '1' || normalized === 'true' });
162
+ }
163
+ /** `POST /api/daemon/db/verify?quick=` — `PRAGMA integrity_check`/`quick_check` plus `foreign_key_check`. */
164
+ export const daemonDbVerifyRoute = defineJsonRoute({
165
+ method: 'post',
166
+ path: '/api/daemon/db/verify',
167
+ requireSameOrigin: true,
168
+ parse: parseDbVerifyInput,
169
+ handle: async (input, deps) => {
170
+ const result = await deps.toolExecutor.execute(deps.principal, freshRun(), DB_VERIFY_TOOL_ID, input);
171
+ return toolResultToApiResult(deps, 'db-verify', result);
172
+ },
173
+ });
174
+ /** `POST /api/daemon/db/vacuum` — runs `VACUUM` and reports bytes reclaimed. */
175
+ export const daemonDbVacuumRoute = defineJsonRoute({
176
+ method: 'post',
177
+ path: '/api/daemon/db/vacuum',
178
+ requireSameOrigin: true,
179
+ parse: () => ok(undefined),
180
+ handle: async (_input, deps) => {
181
+ const result = await deps.toolExecutor.execute(deps.principal, freshRun(), DB_VACUUM_TOOL_ID, undefined);
182
+ return toolResultToApiResult(deps, 'db-vacuum', result);
183
+ },
184
+ });
185
+ /** Mounts all three DB-ops routes on `app`. A pack's `http(app, services)` calls this directly. */
186
+ export function registerDaemonDbRoutes(app, deps, adapter) {
187
+ mountJsonRoute(app, daemonDbInspectRoute, deps, adapter);
188
+ mountJsonRoute(app, daemonDbVerifyRoute, deps, adapter);
189
+ mountJsonRoute(app, daemonDbVacuumRoute, deps, adapter);
190
+ }
191
+ //# sourceMappingURL=db-ops.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"db-ops.js","sourceRoot":"","sources":["../src/db-ops.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,46 @@
1
+ import type { Express } from 'express';
2
+ import type { Principal } from '@jini-ai/core';
3
+ import { type RunLifecycle, type ToolExecutionResult, type ToolExecutor } from '@jini-ai/daemon';
4
+ import { type AdapterContext } from './adapter.js';
5
+ export interface DelegatedToolExecuteRequest {
6
+ readonly runId: string;
7
+ readonly toolUseId: string;
8
+ readonly toolId: string;
9
+ readonly input?: unknown;
10
+ }
11
+ export interface DelegatedToolExecuteResponse {
12
+ readonly result: ToolExecutionResult;
13
+ }
14
+ /**
15
+ * Diagnostic detail for an internal-error response the public API deliberately does not
16
+ * disclose (SEC-005), matching `runs.ts`'s `RunInternalErrorContext` precedent: a thrown
17
+ * `ToolExecutor`/registry failure can embed tool-handler internals no HTTP caller should see.
18
+ */
19
+ export interface DelegatedToolsInternalErrorContext {
20
+ readonly source: 'delegated-tool-execute' | 'resolve-principal';
21
+ readonly runId: string;
22
+ readonly toolId: string;
23
+ readonly correlationId: string;
24
+ readonly error: unknown;
25
+ }
26
+ export interface DelegatedToolsHttpDeps {
27
+ readonly lifecycle: RunLifecycle;
28
+ readonly toolExecutor: ToolExecutor;
29
+ /** Host-owned: resolves the `Principal` a given delegated-tool-call request executes as. Mandatory — see module doc; there is no safe default identity this package could assume on a host's behalf. */
30
+ readonly resolvePrincipal: (request: DelegatedToolExecuteRequest) => Principal | Promise<Principal>;
31
+ /** Host-owned sink for the real exception behind a generic `INTERNAL_ERROR` response (SEC-005). Defaults to `console.error`. */
32
+ readonly onInternalError?: (context: DelegatedToolsInternalErrorContext) => void;
33
+ }
34
+ /**
35
+ * `POST /api/delegated-tool-calls` — executes one delegated tool call against an already-started
36
+ * run. Maps `ToolExecutionResult.status` to the HTTP response via `toolExecutionResultToApiResult`
37
+ * above — mirroring `db-ops.ts`'s precedent for the identical status union rather than treating
38
+ * every business outcome as a `200`. A genuinely unexpected throw (an unregistered `toolId` — a
39
+ * routing/programming error per `ToolExecutor.execute`'s own contract — or a race where the run
40
+ * became terminal between this route's existence check and the bridge's first emitted event)
41
+ * reaches the same SEC-005 redaction path.
42
+ */
43
+ export declare const delegatedToolExecuteRoute: import("./types.js").JsonRouteSpec<DelegatedToolExecuteRequest, DelegatedToolExecuteResponse, DelegatedToolsHttpDeps>;
44
+ /** Mounts `POST /api/delegated-tool-calls` on `app`. A pack's `http(app, services)` calls this directly. */
45
+ export declare function registerDelegatedToolRoutes(app: Express, deps: DelegatedToolsHttpDeps, adapter: AdapterContext): void;
46
+ //# sourceMappingURL=delegated-tools.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"delegated-tools.d.ts","sourceRoot":"","sources":["../src/delegated-tools.ts"],"names":[],"mappings":"AA4BA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAEvC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,EAA6B,KAAK,YAAY,EAAE,KAAK,mBAAmB,EAAE,KAAK,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC5H,OAAO,EAAmC,KAAK,cAAc,EAAE,MAAM,cAAc,CAAC;AAIpF,MAAM,WAAW,2BAA2B;IAC1C,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,MAAM,WAAW,4BAA4B;IAC3C,QAAQ,CAAC,MAAM,EAAE,mBAAmB,CAAC;CACtC;AAED;;;;GAIG;AACH,MAAM,WAAW,kCAAkC;IACjD,QAAQ,CAAC,MAAM,EAAE,wBAAwB,GAAG,mBAAmB,CAAC;IAChE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;CACzB;AAED,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,SAAS,EAAE,YAAY,CAAC;IACjC,QAAQ,CAAC,YAAY,EAAE,YAAY,CAAC;IACpC,wMAAwM;IACxM,QAAQ,CAAC,gBAAgB,EAAE,CAAC,OAAO,EAAE,2BAA2B,KAAK,SAAS,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;IACpG,gIAAgI;IAChI,QAAQ,CAAC,eAAe,CAAC,EAAE,CAAC,OAAO,EAAE,kCAAkC,KAAK,IAAI,CAAC;CAClF;AAyFD;;;;;;;;GAQG;AACH,eAAO,MAAM,yBAAyB,uHAyCpC,CAAC;AAEH,4GAA4G;AAC5G,wBAAgB,2BAA2B,CAAC,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,sBAAsB,EAAE,OAAO,EAAE,cAAc,GAAG,IAAI,CAErH"}
@@ -0,0 +1,155 @@
1
+ /**
2
+ * @module delegated-tools
3
+ *
4
+ * `POST /api/delegated-tool-calls` — the daemon-side half of gap 3's MCP-callback continuation
5
+ * transport spike (see `packages/daemon/source-map.md`'s "run/chat orchestration gap 3, part 1"
6
+ * addition and this package's own dated section in `source-map.md`). The swarm-consensus Final
7
+ * Recommendation asked for exactly this round trip: "inject the already-shipped MCP host into
8
+ * one MCP-capable CLI's launch config, prove a tool round-trip through the existing
9
+ * `delegated-tool-bridge.ts`." This route is that round trip's daemon-side half — an MCP server
10
+ * subprocess spawned alongside a `claude` run (`packages/mcp/src/bin/serve.ts`, injected via
11
+ * `packages/daemon/src/agent-executor.ts`'s optional `mcpJsonInjection` config) calls back into
12
+ * the daemon over loopback HTTP (`packages/mcp/src/server/daemon-client.ts`) with
13
+ * `{runId, toolUseId, toolId, input}`; this route decodes that request and calls the
14
+ * already-shipped, already-tested `createDelegatedToolBridge`
15
+ * (`packages/daemon/src/delegated-tool-bridge.ts`), which is the ONLY execution path from here:
16
+ * every injected byte still routes through `ToolExecutor`'s deny-by-default gate — no parallel
17
+ * authorization mechanism is introduced by this route.
18
+ *
19
+ * `resolvePrincipal` is host-owned and has no default (mirrors gap 3's own resolved
20
+ * human-in-the-loop answer — an explicit host-supplied allowlist/policy, never an invented
21
+ * mechanism): whatever `Principal` a host resolves for a given delegated-tool-call request is
22
+ * exactly what flows into `ToolExecutor.execute`'s own `ToolPolicy.authorize`/
23
+ * `ExecutionDelegate` gates. This route does not itself decide who is allowed to do what — it
24
+ * only decides *which run* a request may act against (an unknown or not-yet-started `runId` is
25
+ * rejected with `404` before the bridge is ever invoked, same precedent as `runs.ts`'s
26
+ * `runCancelRoute`).
27
+ */
28
+ import { randomUUID } from 'node:crypto';
29
+ import { createApiError } from '@jini-ai/protocol';
30
+ import { createDelegatedToolBridge } from '@jini-ai/daemon';
31
+ import { defineJsonRoute, mountJsonRoute } from './adapter.js';
32
+ import { validationError } from './request.js';
33
+ import { err, ok } from './types.js';
34
+ /** Logs the real failure server-side and returns the generic, correlation-id-bearing public error (SEC-005: never the raw exception). */
35
+ function defaultInternalErrorSink(context) {
36
+ // eslint-disable-next-line no-console
37
+ console.error(`[@jini-ai/http-kit] internal error (${context.source}, correlationId=${context.correlationId})`, context.error);
38
+ }
39
+ function reportInternalError(deps, source, error, runId, toolId) {
40
+ const correlationId = randomUUID();
41
+ const sink = deps.onInternalError ?? defaultInternalErrorSink;
42
+ sink({ source, runId, toolId, correlationId, error });
43
+ return createApiError('INTERNAL_ERROR', 'an internal error occurred', { requestId: correlationId });
44
+ }
45
+ function isRecord(value) {
46
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
47
+ }
48
+ function requireNonEmptyString(body, key) {
49
+ const value = body[key];
50
+ return typeof value === 'string' && value.trim().length > 0 ? value : undefined;
51
+ }
52
+ function parseDelegatedToolExecute(input) {
53
+ if (!isRecord(input.body))
54
+ return err(validationError('body must be a JSON object'));
55
+ const runId = requireNonEmptyString(input.body, 'runId');
56
+ if (runId === undefined) {
57
+ return err(validationError('runId must be a non-empty string', [{ path: 'runId', message: 'required non-empty string' }]));
58
+ }
59
+ const toolUseId = requireNonEmptyString(input.body, 'toolUseId');
60
+ if (toolUseId === undefined) {
61
+ return err(validationError('toolUseId must be a non-empty string', [{ path: 'toolUseId', message: 'required non-empty string' }]));
62
+ }
63
+ const toolId = requireNonEmptyString(input.body, 'toolId');
64
+ if (toolId === undefined) {
65
+ return err(validationError('toolId must be a non-empty string', [{ path: 'toolId', message: 'required non-empty string' }]));
66
+ }
67
+ return ok({ runId, toolUseId, toolId, input: input.body.input });
68
+ }
69
+ /**
70
+ * Maps a settled `ToolExecutionResult` to the wire `Result` — the same status mapping
71
+ * `db-ops.ts`'s `toolResultToApiResult` establishes for this identical `ToolExecutionResult`
72
+ * union, kept consistent here rather than reinvented: `completed` → `200 {result}`,
73
+ * `denied`/`confirmation-denied` → `403 TOOL_OPERATION_DENIED`, `timed-out`/`cancelled` → a
74
+ * SEC-005-redacted `500 INTERNAL_ERROR` (the real status/error goes to `onInternalError`, never the
75
+ * wire).
76
+ *
77
+ * `failed` splits in two, on `result.errorKind` (`@jini-ai/daemon`'s `ToolExecutor` sets it from
78
+ * whether the handler threw `@jini-ai/core`'s `ToolInputError`): `'validation'` means the CALLER's
79
+ * input was the problem — a wrong/missing/malformed field name, a `themeId` that doesn't exist, a
80
+ * path escaping its theme — so it is reported as a real `400 BAD_REQUEST` carrying the handler's own
81
+ * actionable message (the same one a model reads to retry correctly), not redacted. Everything else
82
+ * (`'internal'`, or no `errorKind` at all — e.g. an older `ToolExecutor` build) stays the SEC-005
83
+ * redacted 500 path, because a handler that threw for a reason OTHER than "your input was bad" can
84
+ * embed exactly the kind of internal detail that path exists to keep off the wire.
85
+ */
86
+ function toolExecutionResultToApiResult(deps, runId, toolId, result) {
87
+ switch (result.status) {
88
+ case 'completed':
89
+ return ok({ result });
90
+ case 'denied':
91
+ return err(createApiError('TOOL_OPERATION_DENIED', 'this operation was denied by policy'));
92
+ case 'confirmation-denied':
93
+ return err(createApiError('TOOL_OPERATION_DENIED', 'this operation was denied during confirmation'));
94
+ case 'timed-out':
95
+ case 'cancelled':
96
+ return err(reportInternalError(deps, 'delegated-tool-execute', result.status, runId, toolId));
97
+ case 'failed':
98
+ if (result.errorKind === 'validation') {
99
+ return err(createApiError('BAD_REQUEST', result.error ?? 'invalid tool input'));
100
+ }
101
+ return err(reportInternalError(deps, 'delegated-tool-execute', result.error ?? result.status, runId, toolId));
102
+ }
103
+ }
104
+ /**
105
+ * `POST /api/delegated-tool-calls` — executes one delegated tool call against an already-started
106
+ * run. Maps `ToolExecutionResult.status` to the HTTP response via `toolExecutionResultToApiResult`
107
+ * above — mirroring `db-ops.ts`'s precedent for the identical status union rather than treating
108
+ * every business outcome as a `200`. A genuinely unexpected throw (an unregistered `toolId` — a
109
+ * routing/programming error per `ToolExecutor.execute`'s own contract — or a race where the run
110
+ * became terminal between this route's existence check and the bridge's first emitted event)
111
+ * reaches the same SEC-005 redaction path.
112
+ */
113
+ export const delegatedToolExecuteRoute = defineJsonRoute({
114
+ method: 'post',
115
+ path: '/api/delegated-tool-calls',
116
+ requireSameOrigin: true,
117
+ parse: parseDelegatedToolExecute,
118
+ handle: async (input, deps, signal) => {
119
+ const run = await deps.lifecycle.get(input.runId);
120
+ if (run === undefined) {
121
+ return err(createApiError('NOT_FOUND', `run "${input.runId}" was not found`));
122
+ }
123
+ let principal;
124
+ try {
125
+ principal = await deps.resolvePrincipal(input);
126
+ }
127
+ catch (error) {
128
+ return err(reportInternalError(deps, 'resolve-principal', error, input.runId, input.toolId));
129
+ }
130
+ const bridge = createDelegatedToolBridge({ lifecycle: deps.lifecycle, toolExecutor: deps.toolExecutor });
131
+ try {
132
+ // `signal` carries the caller's HTTP connection dropping — see `mountJsonRoute`
133
+ // (`adapter.ts`). The bridge already combines it with the run's own cancellation
134
+ // (`DelegatedToolInvocation.signal`'s doc); this is the wire that was missing, not new
135
+ // behaviour in the bridge or `ToolExecutor`.
136
+ const result = await bridge.execute({
137
+ runId: input.runId,
138
+ toolUseId: input.toolUseId,
139
+ toolId: input.toolId,
140
+ principal,
141
+ input: input.input,
142
+ ...(signal !== undefined ? { signal } : {}),
143
+ });
144
+ return toolExecutionResultToApiResult(deps, input.runId, input.toolId, result);
145
+ }
146
+ catch (error) {
147
+ return err(reportInternalError(deps, 'delegated-tool-execute', error, input.runId, input.toolId));
148
+ }
149
+ },
150
+ });
151
+ /** Mounts `POST /api/delegated-tool-calls` on `app`. A pack's `http(app, services)` calls this directly. */
152
+ export function registerDelegatedToolRoutes(app, deps, adapter) {
153
+ mountJsonRoute(app, delegatedToolExecuteRoute, deps, adapter);
154
+ }
155
+ //# sourceMappingURL=delegated-tools.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"delegated-tools.js","sourceRoot":"","sources":["../src/delegated-tools.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * @module express/run-stream
3
+ *
4
+ * Express-specific mounting glue for the shared AG-UI SSE run-stream handler (`../run-stream.js`).
5
+ * Express's `Request`/`Response` already *are* Node's raw `http.IncomingMessage`/
6
+ * `http.ServerResponse` (Express's `Response` extends `http.ServerResponse` directly), so this
7
+ * file's only job is resolving `req.params.runId` and handing the request/response straight
8
+ * through — a few lines, not a reimplementation, per the design decision that motivated building
9
+ * the SSE primitive once instead of duplicating it per transport.
10
+ */
11
+ import type { Express } from 'express';
12
+ import { type RunStreamDeps } from '../run-stream.js';
13
+ /** Mounts the AG-UI SSE run-stream route on `app`. A pack's `http(app, services)` calls this directly. */
14
+ export declare function registerRunStreamRoute(app: Express, deps: RunStreamDeps): void;
15
+ //# sourceMappingURL=run-stream.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-stream.d.ts","sourceRoot":"","sources":["../../src/express/run-stream.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,KAAK,EAAE,OAAO,EAAqB,MAAM,SAAS,CAAC;AAC1D,OAAO,EAAiD,KAAK,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAErG,0GAA0G;AAC1G,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,aAAa,GAAG,IAAI,CAO9E"}
@@ -0,0 +1,11 @@
1
+ import { handleRunStreamRequest, RUN_STREAM_ROUTE_PATH } from '../run-stream.js';
2
+ /** Mounts the AG-UI SSE run-stream route on `app`. A pack's `http(app, services)` calls this directly. */
3
+ export function registerRunStreamRoute(app, deps) {
4
+ app.get(RUN_STREAM_ROUTE_PATH, async (req, res) => {
5
+ // `:runId` is a required path segment of RUN_STREAM_ROUTE_PATH — this handler is only ever
6
+ // reached via a URL that already matched it, so the param is always present at runtime even
7
+ // though @types/express types every param as possibly `undefined` in general.
8
+ await handleRunStreamRequest(req, res, req.params.runId, deps);
9
+ });
10
+ }
11
+ //# sourceMappingURL=run-stream.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-stream.js","sourceRoot":"","sources":["../../src/express/run-stream.ts"],"names":[],"mappings":"AAWA,OAAO,EAAE,sBAAsB,EAAE,qBAAqB,EAAsB,MAAM,kBAAkB,CAAC;AAErG,0GAA0G;AAC1G,MAAM,UAAU,sBAAsB,CAAC,GAAY,EAAE,IAAmB;IACtE,GAAG,CAAC,GAAG,CAAC,qBAAqB,EAAE,KAAK,EAAE,GAAY,EAAE,GAAa,EAAE,EAAE;QACnE,2FAA2F;QAC3F,4FAA4F;QAC5F,8EAA8E;QAC9E,MAAM,sBAAsB,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,MAAM,CAAC,KAAM,EAAE,IAAI,CAAC,CAAC;IAClE,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * @module @jini/http/express
3
+ *
4
+ * The Express-native transport namespace: re-exports this package's existing flat Express
5
+ * implementation (request parsing, response serialization, the mounting Adapter, the `/api`
6
+ * security middleware, the route-registration guard, compat error helpers, the daemon-status
7
+ * routes, and the runs/agents/host-tools route packs) under one namespace, mirroring
8
+ * `./fastify/index.js`'s shape so a transport-switchable caller (`@jini/node-host`'s
9
+ * `createLocalNodeDaemon`) can import either namespace symmetrically. Nothing here is a new
10
+ * implementation — every export is the same flat file every other consumer of this package
11
+ * already imports directly from the root barrel; this module exists only so `httpExpress.*` and
12
+ * `httpFastify.*` read the same at call sites that need to pick a transport explicitly.
13
+ */
14
+ export type { AdapterContext } from './adapter.js';
15
+ export { defineJsonRoute, mountJsonRoute } from './adapter.js';
16
+ export type { ApiBearerAuthMiddlewareDeps, ApiOriginGuardMiddlewareDeps } from './api-security-middleware.js';
17
+ export { registerApiBearerAuthMiddleware, registerApiOriginGuardMiddleware } from './api-security-middleware.js';
18
+ export { createCompatApiError, createCompatApiErrorResponse, sendApiError as sendCompatApiError, } from './compat.js';
19
+ export type { DaemonShutdownResponse, DaemonStatusDeps, DaemonStatusResponse, } from './daemon-status.js';
20
+ export { daemonShutdownRoute, daemonStatusRoute, registerDaemonStatusRoutes } from './daemon-status.js';
21
+ export { isLoopbackHostname, isLoopbackPeerAddress, localOriginFromHeader, normalizeLocalAuthority, requireLocalDaemonRequest, validateLocalDaemonRequest, } from './local-daemon-request.js';
22
+ export type { OriginContext } from './origin.js';
23
+ export { guardSameOrigin } from './origin.js';
24
+ export { rawInput, validationError } from './request.js';
25
+ export { registerRunStreamRoute } from './express/run-stream.js';
26
+ export { sendApiError, sendJson, statusForError } from './response.js';
27
+ export type { InstallRouteRegistrationGuardOptions, RouteRegistration } from './route-registration-guard.js';
28
+ export { getRouteRegistrationInventory, guardedRouteKey, installRouteRegistrationGuard, } from './route-registration-guard.js';
29
+ export { registerRunRoutes } from './runs.js';
30
+ export { registerAgentRoutes } from './agents.js';
31
+ export { registerHostToolsRoutes } from './host-tools.js';
32
+ //# sourceMappingURL=express-index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"express-index.d.ts","sourceRoot":"","sources":["../src/express-index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,YAAY,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAE/D,YAAY,EAAE,2BAA2B,EAAE,4BAA4B,EAAE,MAAM,8BAA8B,CAAC;AAC9G,OAAO,EAAE,+BAA+B,EAAE,gCAAgC,EAAE,MAAM,8BAA8B,CAAC;AAEjH,OAAO,EACL,oBAAoB,EACpB,4BAA4B,EAC5B,YAAY,IAAI,kBAAkB,GACnC,MAAM,aAAa,CAAC;AAErB,YAAY,EACV,sBAAsB,EACtB,gBAAgB,EAChB,oBAAoB,GACrB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,0BAA0B,EAAE,MAAM,oBAAoB,CAAC;AAExG,OAAO,EACL,kBAAkB,EAClB,qBAAqB,EACrB,qBAAqB,EACrB,uBAAuB,EACvB,yBAAyB,EACzB,0BAA0B,GAC3B,MAAM,2BAA2B,CAAC;AAEnC,YAAY,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAE9C,OAAO,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAEzD,OAAO,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AAEjE,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAEvE,YAAY,EAAE,oCAAoC,EAAE,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;AAC7G,OAAO,EACL,6BAA6B,EAC7B,eAAe,EACf,6BAA6B,GAC9B,MAAM,+BAA+B,CAAC;AAEvC,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAC9C,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAAE,uBAAuB,EAAE,MAAM,iBAAiB,CAAC"}
@@ -0,0 +1,14 @@
1
+ export { defineJsonRoute, mountJsonRoute } from './adapter.js';
2
+ export { registerApiBearerAuthMiddleware, registerApiOriginGuardMiddleware } from './api-security-middleware.js';
3
+ export { createCompatApiError, createCompatApiErrorResponse, sendApiError as sendCompatApiError, } from './compat.js';
4
+ export { daemonShutdownRoute, daemonStatusRoute, registerDaemonStatusRoutes } from './daemon-status.js';
5
+ export { isLoopbackHostname, isLoopbackPeerAddress, localOriginFromHeader, normalizeLocalAuthority, requireLocalDaemonRequest, validateLocalDaemonRequest, } from './local-daemon-request.js';
6
+ export { guardSameOrigin } from './origin.js';
7
+ export { rawInput, validationError } from './request.js';
8
+ export { registerRunStreamRoute } from './express/run-stream.js';
9
+ export { sendApiError, sendJson, statusForError } from './response.js';
10
+ export { getRouteRegistrationInventory, guardedRouteKey, installRouteRegistrationGuard, } from './route-registration-guard.js';
11
+ export { registerRunRoutes } from './runs.js';
12
+ export { registerAgentRoutes } from './agents.js';
13
+ export { registerHostToolsRoutes } from './host-tools.js';
14
+ //# sourceMappingURL=express-index.js.map