@ggui-ai/mcp-server 0.1.0-rc.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 (141) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +48 -0
  3. package/dist/admin-blueprints-transport.d.ts +114 -0
  4. package/dist/admin-blueprints-transport.d.ts.map +1 -0
  5. package/dist/admin-blueprints-transport.js +118 -0
  6. package/dist/admin-oauth-providers-transport.d.ts +40 -0
  7. package/dist/admin-oauth-providers-transport.d.ts.map +1 -0
  8. package/dist/admin-oauth-providers-transport.js +263 -0
  9. package/dist/auth.d.ts +39 -0
  10. package/dist/auth.d.ts.map +1 -0
  11. package/dist/auth.js +75 -0
  12. package/dist/build-mcp.d.ts +128 -0
  13. package/dist/build-mcp.d.ts.map +1 -0
  14. package/dist/build-mcp.js +113 -0
  15. package/dist/code-store-fs.d.ts +19 -0
  16. package/dist/code-store-fs.d.ts.map +1 -0
  17. package/dist/code-store-fs.js +98 -0
  18. package/dist/console-auth.d.ts +139 -0
  19. package/dist/console-auth.d.ts.map +1 -0
  20. package/dist/console-auth.js +102 -0
  21. package/dist/console-cache.d.ts +78 -0
  22. package/dist/console-cache.d.ts.map +1 -0
  23. package/dist/console-cache.js +105 -0
  24. package/dist/console-headers.d.ts +124 -0
  25. package/dist/console-headers.d.ts.map +1 -0
  26. package/dist/console-headers.js +49 -0
  27. package/dist/console-llm-trace.d.ts +66 -0
  28. package/dist/console-llm-trace.d.ts.map +1 -0
  29. package/dist/console-llm-trace.js +105 -0
  30. package/dist/console-payloads.d.ts +67 -0
  31. package/dist/console-payloads.d.ts.map +1 -0
  32. package/dist/console-payloads.js +105 -0
  33. package/dist/console-theme-routes.d.ts +111 -0
  34. package/dist/console-theme-routes.d.ts.map +1 -0
  35. package/dist/console-theme-routes.js +202 -0
  36. package/dist/console-timeline.d.ts +45 -0
  37. package/dist/console-timeline.d.ts.map +1 -0
  38. package/dist/console-timeline.js +169 -0
  39. package/dist/console-validator.d.ts +67 -0
  40. package/dist/console-validator.d.ts.map +1 -0
  41. package/dist/console-validator.js +105 -0
  42. package/dist/console-welcome.d.ts +7 -0
  43. package/dist/console-welcome.d.ts.map +1 -0
  44. package/dist/console-welcome.js +221 -0
  45. package/dist/csrf-middleware.d.ts +55 -0
  46. package/dist/csrf-middleware.d.ts.map +1 -0
  47. package/dist/csrf-middleware.js +138 -0
  48. package/dist/email-login.d.ts +174 -0
  49. package/dist/email-login.d.ts.map +1 -0
  50. package/dist/email-login.js +254 -0
  51. package/dist/email-resend.d.ts +29 -0
  52. package/dist/email-resend.d.ts.map +1 -0
  53. package/dist/email-resend.js +71 -0
  54. package/dist/email-sender-from-env.d.ts +34 -0
  55. package/dist/email-sender-from-env.d.ts.map +1 -0
  56. package/dist/email-sender-from-env.js +112 -0
  57. package/dist/email-smtp.d.ts +42 -0
  58. package/dist/email-smtp.d.ts.map +1 -0
  59. package/dist/email-smtp.js +81 -0
  60. package/dist/index.d.ts +102 -0
  61. package/dist/index.d.ts.map +1 -0
  62. package/dist/index.js +122 -0
  63. package/dist/instructions-presets.d.ts +112 -0
  64. package/dist/instructions-presets.d.ts.map +1 -0
  65. package/dist/instructions-presets.js +195 -0
  66. package/dist/llm-backed-negotiator.d.ts +178 -0
  67. package/dist/llm-backed-negotiator.d.ts.map +1 -0
  68. package/dist/llm-backed-negotiator.js +579 -0
  69. package/dist/logger.d.ts +23 -0
  70. package/dist/logger.d.ts.map +1 -0
  71. package/dist/logger.js +41 -0
  72. package/dist/mcp-apps-inbound.d.ts +86 -0
  73. package/dist/mcp-apps-inbound.d.ts.map +1 -0
  74. package/dist/mcp-apps-inbound.js +278 -0
  75. package/dist/mcp-apps-outbound.d.ts +448 -0
  76. package/dist/mcp-apps-outbound.d.ts.map +1 -0
  77. package/dist/mcp-apps-outbound.js +1163 -0
  78. package/dist/mcp-mounts.d.ts +239 -0
  79. package/dist/mcp-mounts.d.ts.map +1 -0
  80. package/dist/mcp-mounts.js +222 -0
  81. package/dist/oauth-login-types.d.ts +160 -0
  82. package/dist/oauth-login-types.d.ts.map +1 -0
  83. package/dist/oauth-login-types.js +9 -0
  84. package/dist/oauth-login.d.ts +77 -0
  85. package/dist/oauth-login.d.ts.map +1 -0
  86. package/dist/oauth-login.js +455 -0
  87. package/dist/oauth-providers/github.d.ts +17 -0
  88. package/dist/oauth-providers/github.d.ts.map +1 -0
  89. package/dist/oauth-providers/github.js +89 -0
  90. package/dist/oauth-providers/google.d.ts +18 -0
  91. package/dist/oauth-providers/google.d.ts.map +1 -0
  92. package/dist/oauth-providers/google.js +59 -0
  93. package/dist/oauth-providers-store.d.ts +32 -0
  94. package/dist/oauth-providers-store.d.ts.map +1 -0
  95. package/dist/oauth-providers-store.js +291 -0
  96. package/dist/oauth.d.ts +347 -0
  97. package/dist/oauth.d.ts.map +1 -0
  98. package/dist/oauth.js +686 -0
  99. package/dist/pairing-transport.d.ts +99 -0
  100. package/dist/pairing-transport.d.ts.map +1 -0
  101. package/dist/pairing-transport.js +223 -0
  102. package/dist/rate-limit-middleware.d.ts +36 -0
  103. package/dist/rate-limit-middleware.d.ts.map +1 -0
  104. package/dist/rate-limit-middleware.js +57 -0
  105. package/dist/render-gate.d.ts +87 -0
  106. package/dist/render-gate.d.ts.map +1 -0
  107. package/dist/render-gate.js +77 -0
  108. package/dist/render-rate-limit.d.ts +59 -0
  109. package/dist/render-rate-limit.d.ts.map +1 -0
  110. package/dist/render-rate-limit.js +73 -0
  111. package/dist/render-signing.d.ts +98 -0
  112. package/dist/render-signing.d.ts.map +1 -0
  113. package/dist/render-signing.js +113 -0
  114. package/dist/request-context.d.ts +113 -0
  115. package/dist/request-context.d.ts.map +1 -0
  116. package/dist/request-context.js +154 -0
  117. package/dist/reserved-validators.d.ts +22 -0
  118. package/dist/reserved-validators.d.ts.map +1 -0
  119. package/dist/reserved-validators.js +101 -0
  120. package/dist/schema-compat.d.ts +167 -0
  121. package/dist/schema-compat.d.ts.map +1 -0
  122. package/dist/schema-compat.js +187 -0
  123. package/dist/security-headers-middleware.d.ts +38 -0
  124. package/dist/security-headers-middleware.d.ts.map +1 -0
  125. package/dist/security-headers-middleware.js +30 -0
  126. package/dist/server.d.ts +2060 -0
  127. package/dist/server.d.ts.map +1 -0
  128. package/dist/server.js +6338 -0
  129. package/dist/session-channel.d.ts +651 -0
  130. package/dist/session-channel.d.ts.map +1 -0
  131. package/dist/session-channel.js +1756 -0
  132. package/dist/storage.d.ts +89 -0
  133. package/dist/storage.d.ts.map +1 -0
  134. package/dist/storage.js +171 -0
  135. package/dist/thread-transport.d.ts +118 -0
  136. package/dist/thread-transport.d.ts.map +1 -0
  137. package/dist/thread-transport.js +478 -0
  138. package/dist/user-session-auth.d.ts +167 -0
  139. package/dist/user-session-auth.d.ts.map +1 -0
  140. package/dist/user-session-auth.js +148 -0
  141. package/package.json +76 -0
@@ -0,0 +1,89 @@
1
+ import type { SessionStore, ThreadStore, VectorStore } from '@ggui-ai/mcp-server-core';
2
+ import type { StorageConfig } from '@ggui-ai/project-config';
3
+ export interface ResolveStorageFromConfigOptions {
4
+ /**
5
+ * Directory used to resolve relative `path` values in the storage
6
+ * config. Typically the directory containing `ggui.json` so a
7
+ * manifest saying `"path": "./ggui-sessions.sqlite"` lands next to
8
+ * the manifest (not CWD, which would silently create a file wherever
9
+ * the process happened to be started).
10
+ *
11
+ * Absolute paths in the config are honored verbatim. Omitting
12
+ * `baseDir` means relative paths resolve against `process.cwd()` —
13
+ * fine for ad-hoc programmatic callers, but `ggui serve` always
14
+ * passes the project root so the behavior is deterministic.
15
+ */
16
+ readonly baseDir?: string;
17
+ }
18
+ export interface ResolvedStorageStores {
19
+ /** Concrete SessionStore, iff the config declared one. Undefined =
20
+ * caller falls back to createGguiServer's in-memory default. */
21
+ readonly sessionStore?: SessionStore;
22
+ /** Concrete VectorStore, iff the config declared one. Undefined =
23
+ * caller falls back to createGguiServer's in-memory default. */
24
+ readonly vectors?: VectorStore;
25
+ /** Concrete ThreadStore, iff the config declared one. Undefined
26
+ * ONLY when `storage.threads` is absent from the manifest — in
27
+ * that case the caller skips the `threads:` opt-in on
28
+ * `createGguiServer` and no thread routes mount at all.
29
+ *
30
+ * When the manifest declares `storage.threads`, a store is
31
+ * ALWAYS returned:
32
+ * - `driver: 'memory'` → `InMemoryThreadStore` (ephemeral but
33
+ * real; routes mount and work until restart).
34
+ * - `driver: 'sqlite'` → `SqliteThreadStore` (durable).
35
+ *
36
+ * This is the one semantic deviation from sessions/vectors, which
37
+ * treat `driver: 'memory'` as a no-op because `createGguiServer`
38
+ * already defaults those to in-memory stores internally. Threads
39
+ * don't have an implicit default — the whole route family is
40
+ * opt-in — so `'memory'` has to resolve to a real store or be
41
+ * rejected at schema time. Resolving to `InMemoryThreadStore` is
42
+ * the less-surprising of the two. */
43
+ readonly threadStore?: ThreadStore;
44
+ /**
45
+ * Durability claim for the resolved thread store. Present iff
46
+ * `threadStore` is present. `'durable'` for sqlite; `'ephemeral'`
47
+ * for memory. Callers pass this straight through to
48
+ * `createGguiServer({ threads: { durability } })` so the server's
49
+ * `/ggui/health` advertisement matches the active store.
50
+ */
51
+ readonly threadDurability?: 'durable' | 'ephemeral';
52
+ }
53
+ /**
54
+ * Instantiate the concrete storage adapters declared in a parsed
55
+ * `ggui.json#storage` block.
56
+ *
57
+ * - Absent config → `{}` (every surface
58
+ * falls back to createGguiServer's
59
+ * in-memory defaults, or in the
60
+ * case of `threads:`, no thread
61
+ * routes at all).
62
+ *
63
+ * - `sessions` / `vectors`:
64
+ * - `driver: 'memory'` → omitted from the bundle
65
+ * (same fallback — declaring
66
+ * memory is the same outcome
67
+ * as omitting it; present
68
+ * for intent visibility).
69
+ * - `driver: 'sqlite'` → `SqliteSessionStore` /
70
+ * `SqliteVectorStore`.
71
+ *
72
+ * - `threads`:
73
+ * - `driver: 'memory'` → `InMemoryThreadStore` +
74
+ * `threadDurability: 'ephemeral'`.
75
+ * Routes mount; data lost on
76
+ * restart. Declaring this is
77
+ * how an operator asks for
78
+ * ephemeral threads.
79
+ * - `driver: 'sqlite'` → `SqliteThreadStore` +
80
+ * `threadDurability: 'durable'`.
81
+ *
82
+ * Dynamic import of `@ggui-ai/mcp-server-core/sqlite` means
83
+ * `better-sqlite3` is only required when the config actually declares
84
+ * sqlite somewhere. Memory-only configs don't touch the optional peer
85
+ * dep — `InMemoryThreadStore` is a static import because the in-memory
86
+ * subpath has no peer dep cost.
87
+ */
88
+ export declare function resolveStorageFromConfig(config: StorageConfig | undefined, opts?: ResolveStorageFromConfigOptions): Promise<ResolvedStorageStores>;
89
+ //# sourceMappingURL=storage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../src/storage.ts"],"names":[],"mappings":"AAqDA,OAAO,KAAK,EACV,YAAY,EACZ,WAAW,EACX,WAAW,EACZ,MAAM,0BAA0B,CAAC;AAQlC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAE7D,MAAM,WAAW,+BAA+B;IAC9C;;;;;;;;;;;OAWG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,qBAAqB;IACpC;oEACgE;IAChE,QAAQ,CAAC,YAAY,CAAC,EAAE,YAAY,CAAC;IACrC;oEACgE;IAChE,QAAQ,CAAC,OAAO,CAAC,EAAE,WAAW,CAAC;IAC/B;;;;;;;;;;;;;;;;;yCAiBqC;IACrC,QAAQ,CAAC,WAAW,CAAC,EAAE,WAAW,CAAC;IACnC;;;;;;OAMG;IACH,QAAQ,CAAC,gBAAgB,CAAC,EAAE,SAAS,GAAG,WAAW,CAAC;CACrD;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,wBAAsB,wBAAwB,CAC5C,MAAM,EAAE,aAAa,GAAG,SAAS,EACjC,IAAI,GAAE,+BAAoC,GACzC,OAAO,CAAC,qBAAqB,CAAC,CAgDhC"}
@@ -0,0 +1,171 @@
1
+ /**
2
+ * Storage config → concrete adapter resolver.
3
+ *
4
+ * Bridges `@ggui-ai/project-config`'s declarative `ggui.json#storage`
5
+ * block to the concrete `@ggui-ai/mcp-server-core` adapters. Thin and
6
+ * boring by design: one config → one set of instances.
7
+ *
8
+ * ## Why this lives in @ggui-ai/mcp-server (not core, not project-config)
9
+ *
10
+ * - `@ggui-ai/project-config` is browser-safe + purely declarative.
11
+ * It must not import `better-sqlite3` (which is a Node addon) or
12
+ * any concrete adapter — that would poison the import graph for
13
+ * paste-a-manifest validators, dev UIs, the Studio dashboard.
14
+ *
15
+ * - `@ggui-ai/mcp-server-core` is the interfaces + reference adapters
16
+ * layer. It exposes the adapters on subpath exports
17
+ * (`/sqlite`, `/in-memory`, …) but intentionally doesn't know about
18
+ * `ggui.json` — keeping the interface layer free of file-format
19
+ * coupling lets non-OSS consumers (hosted closed runtimes, future
20
+ * private adapters) bind the same interfaces without dragging the
21
+ * OSS manifest schema through their code.
22
+ *
23
+ * - `@ggui-ai/mcp-server` is the OSS runtime that actually reads
24
+ * `ggui.json` and serves requests. That's where the bridge
25
+ * belongs — one hop away from the actual `ggui serve` caller.
26
+ *
27
+ * ## Why `better-sqlite3` gets imported dynamically
28
+ *
29
+ * `better-sqlite3` is an optional peer dep of `@ggui-ai/mcp-server-core`.
30
+ * If we `import { SqliteSessionStore } from '@ggui-ai/mcp-server-core/sqlite'`
31
+ * at the top of this file, any consumer that doesn't opt into SQLite
32
+ * storage still pays the peer-dep cost (the module graph resolves the
33
+ * subpath at import time, which tries to load better-sqlite3's N-API
34
+ * binary). Dynamic `await import(...)` keeps the cost truly optional:
35
+ * SQLite is loaded only when `storage.sessions.driver === 'sqlite'` or
36
+ * `storage.vectors.driver === 'sqlite'`.
37
+ *
38
+ * ## Why this is async + returns a bundle instead of augmenting createGguiServer
39
+ *
40
+ * `createGguiServer` stays synchronous — no public API break. Callers
41
+ * who want storage from config write:
42
+ *
43
+ * ```ts
44
+ * const { sessionStore, vectors } =
45
+ * await resolveStorageFromConfig(manifest.storage, { baseDir: projectRoot });
46
+ * const server = createGguiServer({ sessionStore, vectors });
47
+ * ```
48
+ *
49
+ * Explicit instances passed to `createGguiServer` still win — this
50
+ * resolver is a convenience for the ggui.json path, not a requirement.
51
+ */
52
+ import { mkdirSync } from 'node:fs';
53
+ import path from 'node:path';
54
+ // `InMemoryThreadStore` is a static import — unlike the sqlite
55
+ // adapters, the in-memory subpath carries no optional peer dep cost
56
+ // (no `better-sqlite3`, no N-API binding). `storage.threads.driver =
57
+ // 'memory'` uses this to mount actual thread routes instead of being
58
+ // a silent no-op like sessions/vectors (which createGguiServer
59
+ // already defaults to in-memory internally).
60
+ import { InMemoryThreadStore } from '@ggui-ai/mcp-server-core/in-memory';
61
+ /**
62
+ * Instantiate the concrete storage adapters declared in a parsed
63
+ * `ggui.json#storage` block.
64
+ *
65
+ * - Absent config → `{}` (every surface
66
+ * falls back to createGguiServer's
67
+ * in-memory defaults, or in the
68
+ * case of `threads:`, no thread
69
+ * routes at all).
70
+ *
71
+ * - `sessions` / `vectors`:
72
+ * - `driver: 'memory'` → omitted from the bundle
73
+ * (same fallback — declaring
74
+ * memory is the same outcome
75
+ * as omitting it; present
76
+ * for intent visibility).
77
+ * - `driver: 'sqlite'` → `SqliteSessionStore` /
78
+ * `SqliteVectorStore`.
79
+ *
80
+ * - `threads`:
81
+ * - `driver: 'memory'` → `InMemoryThreadStore` +
82
+ * `threadDurability: 'ephemeral'`.
83
+ * Routes mount; data lost on
84
+ * restart. Declaring this is
85
+ * how an operator asks for
86
+ * ephemeral threads.
87
+ * - `driver: 'sqlite'` → `SqliteThreadStore` +
88
+ * `threadDurability: 'durable'`.
89
+ *
90
+ * Dynamic import of `@ggui-ai/mcp-server-core/sqlite` means
91
+ * `better-sqlite3` is only required when the config actually declares
92
+ * sqlite somewhere. Memory-only configs don't touch the optional peer
93
+ * dep — `InMemoryThreadStore` is a static import because the in-memory
94
+ * subpath has no peer dep cost.
95
+ */
96
+ export async function resolveStorageFromConfig(config, opts = {}) {
97
+ if (!config)
98
+ return {};
99
+ const sessionsSqlite = config.sessions?.driver === 'sqlite';
100
+ const vectorsSqlite = config.vectors?.driver === 'sqlite';
101
+ const threadsSqlite = config.threads?.driver === 'sqlite';
102
+ const threadsMemory = config.threads?.driver === 'memory';
103
+ const result = {};
104
+ // Handle the memory-threads branch BEFORE the sqlite dynamic import
105
+ // gate so `driver: 'memory'`-only configs don't pull in
106
+ // better-sqlite3 at all.
107
+ if (threadsMemory) {
108
+ result.threadStore = new InMemoryThreadStore();
109
+ result.threadDurability = 'ephemeral';
110
+ }
111
+ if (!sessionsSqlite && !vectorsSqlite && !threadsSqlite)
112
+ return result;
113
+ // Single dynamic import serves every sqlite adapter — better-sqlite3's
114
+ // N-API binding loads once even if the import lands twice; the
115
+ // subpath barrel is cached by Node's module loader.
116
+ const { SqliteSessionStore, SqliteVectorStore, SqliteThreadStore } = await import('@ggui-ai/mcp-server-core/sqlite');
117
+ if (config.sessions && config.sessions.driver === 'sqlite') {
118
+ const filename = resolveStoragePath(config.sessions.path, opts.baseDir);
119
+ ensureParentDir(filename);
120
+ result.sessionStore = new SqliteSessionStore({ filename });
121
+ }
122
+ if (config.vectors && config.vectors.driver === 'sqlite') {
123
+ const filename = resolveStoragePath(config.vectors.path, opts.baseDir);
124
+ ensureParentDir(filename);
125
+ result.vectors = new SqliteVectorStore({ filename });
126
+ }
127
+ if (config.threads && config.threads.driver === 'sqlite') {
128
+ const filename = resolveStoragePath(config.threads.path, opts.baseDir);
129
+ ensureParentDir(filename);
130
+ result.threadStore = new SqliteThreadStore({ filename });
131
+ result.threadDurability = 'durable';
132
+ }
133
+ return result;
134
+ }
135
+ /**
136
+ * Create the parent directory of a sqlite database file if it doesn't
137
+ * already exist. Turns the declarative `path: './data/sessions.sqlite'`
138
+ * into a working adapter without forcing the operator to mkdir by hand
139
+ * — better-sqlite3 refuses to open a file whose parent doesn't exist,
140
+ * and the parent is uninteresting bookkeeping the manifest already
141
+ * implies.
142
+ *
143
+ * Not "silent file creation" — the operator declared the path in
144
+ * `ggui.json`; honoring it is the whole point of opt-in. No-op for
145
+ * `:memory:` and for paths whose parent already exists.
146
+ */
147
+ function ensureParentDir(resolvedPath) {
148
+ if (resolvedPath === ':memory:')
149
+ return;
150
+ mkdirSync(path.dirname(resolvedPath), { recursive: true });
151
+ }
152
+ /**
153
+ * Resolve a storage `path` from the manifest. Absolute paths pass
154
+ * through; relative paths resolve against `baseDir` (typically the
155
+ * ggui.json directory). `baseDir` absent falls back to `process.cwd()`
156
+ * so ad-hoc programmatic callers still work.
157
+ *
158
+ * `:memory:` is intentionally NOT special-cased here — callers who
159
+ * want an in-memory database should declare `driver: 'memory'` in the
160
+ * manifest. An explicit `:memory:` as a sqlite path is honored (passes
161
+ * straight through to better-sqlite3), but it's a power-user escape
162
+ * hatch, not the documented path.
163
+ */
164
+ function resolveStoragePath(rawPath, baseDir) {
165
+ if (rawPath === ':memory:')
166
+ return rawPath;
167
+ if (path.isAbsolute(rawPath))
168
+ return rawPath;
169
+ const root = baseDir ?? process.cwd();
170
+ return path.resolve(root, rawPath);
171
+ }
@@ -0,0 +1,118 @@
1
+ /**
2
+ * Thread transport — HTTP routes for the persistent-chat surface.
3
+ *
4
+ * Thin binding over `@ggui-ai/mcp-server-handlers/threads`. Every
5
+ * route:
6
+ *
7
+ * 1. Resolves identity via the existing `AuthAdapter` (same path
8
+ * `/mcp` + pairing use — no second identity plane).
9
+ * 2. Maps the identity to a stable `ownerId` string (see
10
+ * {@link ThreadOwnerResolver}).
11
+ * 3. Calls the shared handler with `{ ownerId, requestId }`.
12
+ * 4. Maps handler / store errors to stable HTTP status codes.
13
+ *
14
+ * Routes mounted:
15
+ *
16
+ * POST /threads → createThread
17
+ * GET /threads → listThreads
18
+ * GET /threads/:id → getThread
19
+ * PATCH /threads/:id → applyThreadAction
20
+ * GET /threads/:id/messages → listMessages
21
+ * POST /threads/:id/messages → appendMessage
22
+ * GET /threads/:id/stream → observeMessages (SSE)
23
+ *
24
+ * Error mapping (the ONLY transport-level semantic):
25
+ *
26
+ * InvalidThreadRequestError → 400 bad_request
27
+ * ThreadNotFoundError → 404 not_found (wrong-owner + missing
28
+ * collapse to the same code)
29
+ * InvalidThreadActionError → 400 bad_request (defense-in-depth;
30
+ * handler-level schema parses first)
31
+ * ThreadActionInvalidStateError → 409 conflict
32
+ * UnauthenticatedError → 401 unauthenticated
33
+ * (anything else) → 500 internal
34
+ *
35
+ * Error envelopes match the pairing-transport shape so clients see one
36
+ * error-body contract across every non-/mcp route:
37
+ *
38
+ * { error: { code: 'bad_request' | 'not_found' | 'conflict' | ...,
39
+ * message: string,
40
+ * details?: unknown } }
41
+ */
42
+ import type { Express } from 'express';
43
+ import type { AuthAdapter, AuthResult, ThreadStore } from '@ggui-ai/mcp-server-core';
44
+ import type { Logger } from './logger.js';
45
+ /** Default URL prefix the thread routes are mounted at. */
46
+ export declare const DEFAULT_THREADS_PATH = "/threads";
47
+ /**
48
+ * Resolve the stable thread-partition key (`ownerId`) from the
49
+ * authenticated identity.
50
+ *
51
+ * The protocol pins the canonical shapes:
52
+ * - Closed-cloud variants: `cognito_<sub>` / `guest_<uuidv4>` (not
53
+ * our concern here — the closed binding supplies its own resolver).
54
+ * - Self-hosted: `paired_<pairingId>` for pairing-minted tokens;
55
+ * kind-scoped fallback for everything else.
56
+ *
57
+ * The default {@link defaultThreadOwnerFromIdentity} implements that
58
+ * rule. Operators who need a different partition key (e.g. a multi-
59
+ * user OSS fork) pass their own via `threads.ownerFromIdentity`.
60
+ */
61
+ export type ThreadOwnerResolver = (result: AuthResult) => string;
62
+ export declare const DEFAULT_BUILDER_OWNER_ID = "builder";
63
+ /**
64
+ * Default identity → ownerId mapping for the OSS server.
65
+ *
66
+ * Preserves the protocol's "self-hosted → typically `paired_<pairingId>`"
67
+ * convention whenever the token was minted by pairing: the bridge in
68
+ * `createGguiServer` passes `metadata: { pairingId }` on `onTokenIssued`,
69
+ * which surfaces here via `AuthResult.metadata.pairingId`. Fallbacks:
70
+ *
71
+ * - `source: 'cognito'` with a `sub` metadata field → `cognito_<sub>`
72
+ * (parallel adapters in any closed cloud runtime; not a shape the
73
+ * OSS server ships today but the mapping is stable so custom
74
+ * adapters are uniform).
75
+ * - `kind: 'user'` → `user_<workspaceId ?? userId>` — same partition
76
+ * rule `defaultAppIdFromIdentity` uses.
77
+ * - `kind: 'builder'` with no pairing metadata (dev mode / manual
78
+ * token) → {@link DEFAULT_BUILDER_OWNER_ID}.
79
+ *
80
+ * Keeping every OSS-reachable identity collapsed to ONE owner by
81
+ * default is correct: OSS is a single-operator tier. Operators who
82
+ * split owners across multiple tokens pass a custom resolver.
83
+ */
84
+ export declare function defaultThreadOwnerFromIdentity(result: AuthResult): string;
85
+ export interface ThreadTransportOptions {
86
+ /** Required. Store implementation the handlers call through to. */
87
+ readonly store: ThreadStore;
88
+ /**
89
+ * Required. Same AuthAdapter the `/mcp` + live-channel + pairing
90
+ * endpoints use. Identity resolution goes through this — thread
91
+ * routes never invent their own auth path.
92
+ */
93
+ readonly auth: AuthAdapter;
94
+ /** Structured logger. Child loggers are derived per-route. */
95
+ readonly logger: Logger;
96
+ /**
97
+ * URL prefix. Defaults to `/threads`. Six routes are registered
98
+ * beneath it:
99
+ * POST / GET on the prefix itself, GET / PATCH on `/:id`,
100
+ * GET / POST on `/:id/messages`.
101
+ */
102
+ readonly path?: string;
103
+ /**
104
+ * Identity → ownerId mapping. Defaults to
105
+ * {@link defaultThreadOwnerFromIdentity}. A hosted closed runtime
106
+ * overrides to map Cognito claims to `cognito_<sub>` / `guest_<id>`;
107
+ * OSS forks that partition multiple operators override as needed.
108
+ */
109
+ readonly ownerFromIdentity?: ThreadOwnerResolver;
110
+ }
111
+ /**
112
+ * Mount the six thread routes onto an existing Express app.
113
+ *
114
+ * Idempotent is NOT a goal — call once per server. `createGguiServer`
115
+ * owns the single call site via `opts.threads`.
116
+ */
117
+ export declare function mountThreadTransport(app: Express, opts: ThreadTransportOptions): void;
118
+ //# sourceMappingURL=thread-transport.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"thread-transport.d.ts","sourceRoot":"","sources":["../src/thread-transport.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AACH,OAAO,KAAK,EAAE,OAAO,EAAqB,MAAM,SAAS,CAAC;AAE1D,OAAO,KAAK,EACV,WAAW,EACX,UAAU,EACV,WAAW,EACZ,MAAM,0BAA0B,CAAC;AAiBlC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAE1C,2DAA2D;AAC3D,eAAO,MAAM,oBAAoB,aAAa,CAAC;AAE/C;;;;;;;;;;;;;GAaG;AACH,MAAM,MAAM,mBAAmB,GAAG,CAAC,MAAM,EAAE,UAAU,KAAK,MAAM,CAAC;AAEjE,eAAO,MAAM,wBAAwB,YAAY,CAAC;AAElD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,8BAA8B,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,CAqBzE;AAED,MAAM,WAAW,sBAAsB;IACrC,mEAAmE;IACnE,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC;IAC5B;;;;OAIG;IACH,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAC3B,8DAA8D;IAC9D,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB;;;;;OAKG;IACH,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB;;;;;OAKG;IACH,QAAQ,CAAC,iBAAiB,CAAC,EAAE,mBAAmB,CAAC;CAClD;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAClC,GAAG,EAAE,OAAO,EACZ,IAAI,EAAE,sBAAsB,GAC3B,IAAI,CAwYN"}