spexcode 0.6.7 → 0.7.0-next.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.
Files changed (247) hide show
  1. package/README.md +12 -7
  2. package/node_modules/@spexcode/session-application/dist/index.d.ts +17 -0
  3. package/node_modules/@spexcode/session-application/dist/index.js +35 -0
  4. package/node_modules/@spexcode/session-application/dist/migration.d.ts +51 -0
  5. package/node_modules/@spexcode/session-application/dist/migration.js +694 -0
  6. package/node_modules/@spexcode/session-application/dist/production.d.ts +109 -0
  7. package/node_modules/@spexcode/session-application/dist/production.js +438 -0
  8. package/node_modules/@spexcode/session-application/dist/schema.d.ts +2 -0
  9. package/node_modules/@spexcode/session-application/dist/schema.js +39 -0
  10. package/node_modules/@spexcode/session-application/package.json +29 -0
  11. package/node_modules/@spexcode/session-events/dist/errors.d.ts +6 -0
  12. package/node_modules/@spexcode/session-events/dist/errors.js +11 -0
  13. package/node_modules/@spexcode/session-events/dist/index.d.ts +46 -0
  14. package/node_modules/@spexcode/session-events/dist/index.js +245 -0
  15. package/node_modules/@spexcode/session-events/dist/schema.d.ts +3 -0
  16. package/node_modules/@spexcode/session-events/dist/schema.js +44 -0
  17. package/node_modules/@spexcode/session-events/package.json +24 -0
  18. package/node_modules/@spexcode/session-protocol/dist/canonical.d.ts +36 -0
  19. package/node_modules/@spexcode/session-protocol/dist/canonical.js +139 -0
  20. package/node_modules/@spexcode/session-protocol/dist/engine.d.ts +22 -0
  21. package/node_modules/@spexcode/session-protocol/dist/engine.js +478 -0
  22. package/node_modules/@spexcode/session-protocol/dist/errors.d.ts +8 -0
  23. package/node_modules/@spexcode/session-protocol/dist/errors.js +39 -0
  24. package/node_modules/@spexcode/session-protocol/dist/index.d.ts +60 -0
  25. package/node_modules/@spexcode/session-protocol/dist/index.js +4 -0
  26. package/node_modules/@spexcode/session-protocol/dist/schema.d.ts +36 -0
  27. package/node_modules/@spexcode/session-protocol/dist/schema.js +192 -0
  28. package/node_modules/@spexcode/{session-core → session-protocol}/package.json +4 -8
  29. package/node_modules/@spexcode/session-runtime/dist/errors.d.ts +6 -0
  30. package/node_modules/@spexcode/session-runtime/dist/errors.js +11 -0
  31. package/node_modules/@spexcode/session-runtime/dist/index.d.ts +33 -0
  32. package/node_modules/@spexcode/session-runtime/dist/index.js +193 -0
  33. package/node_modules/@spexcode/session-runtime/dist/schema.d.ts +2 -0
  34. package/node_modules/@spexcode/session-runtime/dist/schema.js +37 -0
  35. package/node_modules/@spexcode/session-runtime/package.json +24 -0
  36. package/node_modules/@spexcode/session-selflaunch/bin/spex-session.mjs +4 -0
  37. package/node_modules/@spexcode/session-selflaunch/dist/cli.d.ts +25 -0
  38. package/node_modules/@spexcode/session-selflaunch/dist/cli.js +156 -0
  39. package/node_modules/@spexcode/session-selflaunch/dist/index.d.ts +28 -0
  40. package/node_modules/@spexcode/session-selflaunch/dist/index.js +25 -0
  41. package/node_modules/@spexcode/session-selflaunch/dist/locality.d.ts +31 -0
  42. package/node_modules/@spexcode/session-selflaunch/dist/locality.js +135 -0
  43. package/node_modules/@spexcode/session-selflaunch/dist/path.d.ts +13 -0
  44. package/node_modules/@spexcode/session-selflaunch/dist/path.js +45 -0
  45. package/node_modules/@spexcode/session-selflaunch/package.json +35 -0
  46. package/node_modules/@spexcode/session-topology/dist/errors.d.ts +6 -0
  47. package/node_modules/@spexcode/session-topology/dist/errors.js +11 -0
  48. package/node_modules/@spexcode/session-topology/dist/index.d.ts +24 -0
  49. package/node_modules/@spexcode/session-topology/dist/index.js +173 -0
  50. package/node_modules/@spexcode/session-topology/dist/schema.d.ts +3 -0
  51. package/node_modules/@spexcode/session-topology/dist/schema.js +27 -0
  52. package/node_modules/@spexcode/session-topology/package.json +24 -0
  53. package/node_modules/@spexcode/spec-cli/bin/spex.mjs +175 -21
  54. package/node_modules/@spexcode/spec-cli/dist/cli.js +121 -59
  55. package/node_modules/@spexcode/spec-cli/dist/client.d.ts +1 -3
  56. package/node_modules/@spexcode/spec-cli/dist/client.js +49 -30
  57. package/node_modules/@spexcode/spec-cli/dist/codex-runtime-generations.d.ts +11 -0
  58. package/node_modules/@spexcode/spec-cli/dist/codex-runtime-generations.js +46 -9
  59. package/node_modules/@spexcode/spec-cli/dist/delivery-lock.d.ts +2 -0
  60. package/node_modules/@spexcode/spec-cli/dist/delivery-lock.js +58 -0
  61. package/node_modules/@spexcode/spec-cli/dist/doctor.js +53 -11
  62. package/node_modules/@spexcode/spec-cli/dist/file-write.js +14 -2
  63. package/node_modules/@spexcode/spec-cli/dist/gateway-hub.js +2 -1
  64. package/node_modules/@spexcode/spec-cli/dist/gateway.js +6 -3
  65. package/node_modules/@spexcode/spec-cli/dist/graphCache.js +32 -2
  66. package/node_modules/@spexcode/spec-cli/dist/graphSnapshot.js +57 -2
  67. package/node_modules/@spexcode/spec-cli/dist/graphStream.d.ts +2 -0
  68. package/node_modules/@spexcode/spec-cli/dist/graphStream.js +83 -3
  69. package/node_modules/@spexcode/spec-cli/dist/guide.js +29 -18
  70. package/node_modules/@spexcode/spec-cli/dist/harness-select.js +16 -3
  71. package/node_modules/@spexcode/spec-cli/dist/harness.d.ts +24 -6
  72. package/node_modules/@spexcode/spec-cli/dist/harness.js +510 -72
  73. package/node_modules/@spexcode/spec-cli/dist/help.js +11 -8
  74. package/node_modules/@spexcode/spec-cli/dist/hook-prompts.js +8 -0
  75. package/node_modules/@spexcode/spec-cli/dist/host-resources.js +29 -8
  76. package/node_modules/@spexcode/spec-cli/dist/host.d.ts +7 -0
  77. package/node_modules/@spexcode/spec-cli/dist/host.js +98 -1
  78. package/node_modules/@spexcode/spec-cli/dist/index.js +294 -36
  79. package/node_modules/@spexcode/spec-cli/dist/init.js +1 -1
  80. package/node_modules/@spexcode/spec-cli/dist/lint.js +70 -35
  81. package/node_modules/@spexcode/spec-cli/dist/listen.d.ts +3 -2
  82. package/node_modules/@spexcode/spec-cli/dist/listen.js +14 -2
  83. package/node_modules/@spexcode/spec-cli/dist/machine-peer.d.ts +2 -1
  84. package/node_modules/@spexcode/spec-cli/dist/machine-peer.js +46 -15
  85. package/node_modules/@spexcode/spec-cli/dist/materialize.d.ts +2 -2
  86. package/node_modules/@spexcode/spec-cli/dist/materialize.js +176 -35
  87. package/node_modules/@spexcode/spec-cli/dist/opencode.js +10 -2
  88. package/node_modules/@spexcode/spec-cli/dist/pi-harness.js +18 -5
  89. package/node_modules/@spexcode/spec-cli/dist/pi-headless.d.ts +2 -0
  90. package/node_modules/@spexcode/spec-cli/dist/pi-headless.js +27 -0
  91. package/node_modules/@spexcode/spec-cli/dist/pty-bridge.js +14 -14
  92. package/node_modules/@spexcode/spec-cli/dist/reviews.js +12 -7
  93. package/node_modules/@spexcode/spec-cli/dist/runtime-ownership.d.ts +11 -0
  94. package/node_modules/@spexcode/spec-cli/dist/runtime-ownership.js +79 -1
  95. package/node_modules/@spexcode/spec-cli/dist/session-application.d.ts +23 -0
  96. package/node_modules/@spexcode/spec-cli/dist/session-application.js +189 -0
  97. package/node_modules/@spexcode/spec-cli/dist/session-declarations.js +13 -1
  98. package/node_modules/@spexcode/spec-cli/dist/session-files.d.ts +6 -0
  99. package/node_modules/@spexcode/spec-cli/dist/session-files.js +13 -1
  100. package/node_modules/@spexcode/spec-cli/dist/session-follow.js +39 -22
  101. package/node_modules/@spexcode/{session-core/dist/record-lock.d.ts → spec-cli/dist/session-record-lock.d.ts} +0 -4
  102. package/node_modules/@spexcode/spec-cli/dist/session-record-lock.js +94 -0
  103. package/node_modules/@spexcode/spec-cli/dist/session-runtime-adapter.d.ts +44 -0
  104. package/node_modules/@spexcode/spec-cli/dist/session-runtime-adapter.js +37 -0
  105. package/node_modules/@spexcode/spec-cli/dist/session-timeline.d.ts +25 -2
  106. package/node_modules/@spexcode/spec-cli/dist/session-timeline.js +68 -11
  107. package/node_modules/@spexcode/spec-cli/dist/session-transcript.d.ts +57 -0
  108. package/node_modules/@spexcode/spec-cli/dist/session-transcript.js +137 -0
  109. package/node_modules/@spexcode/spec-cli/dist/session-web.js +4 -4
  110. package/node_modules/@spexcode/spec-cli/dist/sessions.d.ts +112 -15
  111. package/node_modules/@spexcode/spec-cli/dist/sessions.js +1553 -764
  112. package/node_modules/@spexcode/spec-cli/dist/shim-runtime.js +14 -0
  113. package/node_modules/@spexcode/spec-cli/dist/source-list.d.ts +13 -0
  114. package/node_modules/@spexcode/spec-cli/dist/source-list.js +99 -0
  115. package/node_modules/@spexcode/spec-cli/dist/source-read.d.ts +16 -0
  116. package/node_modules/@spexcode/spec-cli/dist/source-read.js +84 -0
  117. package/node_modules/@spexcode/spec-cli/dist/spec-attachments.d.ts +7 -0
  118. package/node_modules/@spexcode/spec-cli/dist/spec-attachments.js +89 -0
  119. package/node_modules/@spexcode/spec-cli/dist/spec-body-edit.d.ts +23 -0
  120. package/node_modules/@spexcode/spec-cli/dist/spec-body-edit.js +138 -0
  121. package/node_modules/@spexcode/spec-cli/dist/supervise.js +15 -6
  122. package/node_modules/@spexcode/spec-cli/hooks/dispatch.sh +19 -31
  123. package/node_modules/@spexcode/spec-cli/hooks/harness.sh +6 -6
  124. package/node_modules/@spexcode/spec-cli/package.json +8 -6
  125. package/node_modules/@spexcode/spec-cli/templates/hooks/post-checkout +4 -2
  126. package/node_modules/@spexcode/spec-cli/templates/hooks/post-merge +2 -1
  127. package/node_modules/@spexcode/spec-cli/templates/hooks/pre-commit +5 -3
  128. package/node_modules/@spexcode/spec-cli/templates/hooks/reference-transaction +5 -3
  129. package/node_modules/@spexcode/spec-cli/templates/spec/project/.plugins/commands/spec.md +2 -7
  130. package/node_modules/@spexcode/spec-cli/templates/spec/project/.plugins/core/idle/idle.sh +4 -10
  131. package/node_modules/@spexcode/spec-cli/templates/spec/project/.plugins/core/idle/spec.md +1 -1
  132. package/node_modules/@spexcode/spec-cli/templates/spec/project/.plugins/core/mark-active/mark-active.sh +22 -24
  133. package/node_modules/@spexcode/spec-cli/templates/spec/project/.plugins/core/mark-active/spec.md +10 -2
  134. package/node_modules/@spexcode/spec-cli/templates/spec/project/.plugins/core/session-fail/fail.sh +8 -7
  135. package/node_modules/@spexcode/spec-cli/templates/spec/project/.plugins/core/session-fail/spec.md +3 -1
  136. package/node_modules/@spexcode/spec-cli/templates/spec/project/.plugins/core/session-listen/session-listen.sh +133 -0
  137. package/node_modules/@spexcode/spec-cli/templates/spec/project/.plugins/core/session-listen/spec.md +36 -0
  138. package/node_modules/@spexcode/spec-cli/templates/spec/project/.plugins/core/spec.md +2 -0
  139. package/node_modules/@spexcode/spec-cli/templates/spec/project/.plugins/core/stop-gate/spec.md +1 -1
  140. package/node_modules/@spexcode/spec-cli/templates/spec/project/.plugins/core/stop-gate/stop-gate.sh +17 -20
  141. package/node_modules/@spexcode/spec-cli/templates/spec/project/.plugins/skills/merge/spec.md +33 -0
  142. package/node_modules/@spexcode/spec-cli/templates/spec/project/.plugins/skills/spec.md +2 -6
  143. package/node_modules/@spexcode/spec-cli/templates/spec/project/.plugins/spec.md +7 -0
  144. package/node_modules/@spexcode/spec-core/dist/anchors.d.ts +13 -2
  145. package/node_modules/@spexcode/spec-core/dist/anchors.js +311 -15
  146. package/node_modules/@spexcode/spec-core/dist/git.d.ts +4 -0
  147. package/node_modules/@spexcode/spec-core/dist/git.js +9 -9
  148. package/node_modules/@spexcode/spec-core/dist/layout.d.ts +12 -1
  149. package/node_modules/@spexcode/spec-core/dist/layout.js +4 -2
  150. package/node_modules/@spexcode/spec-core/dist/resilience.d.ts +1 -0
  151. package/node_modules/@spexcode/spec-core/dist/resilience.js +8 -0
  152. package/node_modules/@spexcode/spec-core/dist/review/reviewFilters.d.ts +1 -0
  153. package/node_modules/@spexcode/spec-core/dist/review/reviewFilters.js +7 -3
  154. package/node_modules/@spexcode/spec-core/dist/review/reviewQuery.d.ts +1 -0
  155. package/node_modules/@spexcode/spec-core/dist/review/reviewQuery.js +4 -0
  156. package/node_modules/@spexcode/spec-core/dist/specs.d.ts +2 -0
  157. package/node_modules/@spexcode/spec-core/dist/specs.js +30 -0
  158. package/node_modules/@spexcode/spec-core/package.json +4 -1
  159. package/node_modules/@spexcode/spec-core/templates/spexcode.json +36 -13
  160. package/node_modules/@spexcode/spec-eval/dist/cli.js +1 -1
  161. package/node_modules/@spexcode/spec-eval/dist/evaltab.d.ts +1 -0
  162. package/node_modules/@spexcode/spec-eval/dist/evaltab.js +6 -1
  163. package/node_modules/@spexcode/spec-eval/dist/freshness.d.ts +1 -1
  164. package/node_modules/@spexcode/spec-eval/dist/freshness.js +12 -12
  165. package/node_modules/@spexcode/spec-eval/dist/host.d.ts +2 -1
  166. package/node_modules/@spexcode/spec-eval/dist/sessioneval.d.ts +2 -1
  167. package/node_modules/@spexcode/spec-eval/dist/sessioneval.js +20 -3
  168. package/node_modules/@spexcode/spec-eval/package.json +2 -2
  169. package/node_modules/@spexcode/spec-forge/package.json +2 -2
  170. package/node_modules/@spexcode/transcript/dist/frames.d.ts +44 -0
  171. package/node_modules/@spexcode/transcript/dist/frames.js +85 -0
  172. package/node_modules/@spexcode/transcript/dist/index.d.ts +5 -0
  173. package/node_modules/@spexcode/transcript/dist/index.js +5 -0
  174. package/node_modules/@spexcode/transcript/dist/live.d.ts +16 -0
  175. package/node_modules/@spexcode/transcript/dist/live.js +65 -0
  176. package/node_modules/@spexcode/transcript/dist/parsers.d.ts +47 -0
  177. package/node_modules/@spexcode/transcript/dist/parsers.js +285 -0
  178. package/node_modules/@spexcode/transcript/dist/readers.d.ts +10 -0
  179. package/node_modules/@spexcode/transcript/dist/readers.js +296 -0
  180. package/node_modules/@spexcode/transcript/dist/turns.d.ts +42 -0
  181. package/node_modules/@spexcode/transcript/dist/turns.js +11 -0
  182. package/node_modules/@spexcode/transcript/package.json +30 -0
  183. package/node_modules/@vscode/tree-sitter-wasm/LICENSE +21 -0
  184. package/node_modules/@vscode/tree-sitter-wasm/README.md +36 -0
  185. package/node_modules/@vscode/tree-sitter-wasm/SECURITY.md +41 -0
  186. package/node_modules/@vscode/tree-sitter-wasm/cgmanifest.json +16 -0
  187. package/node_modules/@vscode/tree-sitter-wasm/package.json +42 -0
  188. package/node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter-bash.wasm +0 -0
  189. package/node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter-c-sharp.wasm +0 -0
  190. package/node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter-cpp.wasm +0 -0
  191. package/node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter-css.wasm +0 -0
  192. package/node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter-go.wasm +0 -0
  193. package/node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter-ini.wasm +0 -0
  194. package/node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter-java.wasm +0 -0
  195. package/node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter-javascript.wasm +0 -0
  196. package/node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter-php.wasm +0 -0
  197. package/node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter-powershell.wasm +0 -0
  198. package/node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter-python.wasm +0 -0
  199. package/node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter-regex.wasm +0 -0
  200. package/node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter-ruby.wasm +0 -0
  201. package/node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter-rust.wasm +0 -0
  202. package/node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter-tsx.wasm +0 -0
  203. package/node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter-typescript.wasm +0 -0
  204. package/node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter.js +4075 -0
  205. package/node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter.wasm +0 -0
  206. package/node_modules/@vscode/tree-sitter-wasm/wasm/web-tree-sitter.d.ts +1027 -0
  207. package/node_modules/smol-toml/LICENSE +24 -0
  208. package/node_modules/smol-toml/README.md +418 -0
  209. package/node_modules/smol-toml/dist/date.d.ts +41 -0
  210. package/node_modules/smol-toml/dist/date.js +127 -0
  211. package/node_modules/smol-toml/dist/error.d.ts +38 -0
  212. package/node_modules/smol-toml/dist/error.js +63 -0
  213. package/node_modules/smol-toml/dist/extract.js +69 -0
  214. package/node_modules/smol-toml/dist/index.cjs +734 -0
  215. package/node_modules/smol-toml/dist/index.d.ts +43 -0
  216. package/node_modules/smol-toml/dist/index.js +33 -0
  217. package/node_modules/smol-toml/dist/parse.d.ts +36 -0
  218. package/node_modules/smol-toml/dist/parse.js +149 -0
  219. package/node_modules/smol-toml/dist/primitive.js +238 -0
  220. package/node_modules/smol-toml/dist/stringify.d.ts +31 -0
  221. package/node_modules/smol-toml/dist/stringify.js +181 -0
  222. package/node_modules/smol-toml/dist/struct.js +179 -0
  223. package/node_modules/smol-toml/dist/util.d.ts +38 -0
  224. package/node_modules/smol-toml/dist/util.js +89 -0
  225. package/node_modules/smol-toml/package.json +68 -0
  226. package/package.json +9 -3
  227. package/node_modules/@spexcode/session-core/dist/delivery-queue.d.ts +0 -24
  228. package/node_modules/@spexcode/session-core/dist/delivery-queue.js +0 -206
  229. package/node_modules/@spexcode/session-core/dist/index.d.ts +0 -5
  230. package/node_modules/@spexcode/session-core/dist/index.js +0 -5
  231. package/node_modules/@spexcode/session-core/dist/internal.d.ts +0 -3
  232. package/node_modules/@spexcode/session-core/dist/internal.js +0 -3
  233. package/node_modules/@spexcode/session-core/dist/message.d.ts +0 -22
  234. package/node_modules/@spexcode/session-core/dist/message.js +0 -53
  235. package/node_modules/@spexcode/session-core/dist/record-lock.js +0 -152
  236. package/node_modules/@spexcode/session-core/dist/runtime-session.d.ts +0 -62
  237. package/node_modules/@spexcode/session-core/dist/runtime-session.js +0 -326
  238. package/node_modules/@spexcode/session-core/dist/session-cursors.d.ts +0 -14
  239. package/node_modules/@spexcode/session-core/dist/session-cursors.js +0 -82
  240. package/node_modules/@spexcode/session-core/dist/session-timeline.d.ts +0 -47
  241. package/node_modules/@spexcode/session-core/dist/session-timeline.js +0 -216
  242. package/node_modules/@spexcode/spec-cli/dist/execution-trace.d.ts +0 -26
  243. package/node_modules/@spexcode/spec-cli/dist/execution-trace.js +0 -475
  244. package/node_modules/@spexcode/spec-cli/dist/session-execution.d.ts +0 -10
  245. package/node_modules/@spexcode/spec-cli/dist/session-execution.js +0 -70
  246. package/node_modules/@spexcode/spec-cli/hooks/compat/mark-active-0.5.2-eef1.fixture +0 -53
  247. package/node_modules/@spexcode/spec-cli/hooks/compat/mark-active-sed-v0.fixture +0 -46
@@ -0,0 +1,156 @@
1
+ import { LocalityError, requireLocalDatabasePath } from './locality.js';
2
+ import { DatabasePathError, resolveDatabasePath } from './path.js';
3
+ class UsageError extends Error {
4
+ code = 'USAGE';
5
+ }
6
+ const VALUE_FLAGS = {
7
+ initialize: new Set(['session-id', 'database-path']),
8
+ enqueue: new Set(['session-id', 'kind', 'body', 'sender-session-id', 'idempotency-key', 'database-path']),
9
+ dequeue: new Set(['session-id', 'database-path']),
10
+ pending: new Set(['session-id', 'database-path']),
11
+ };
12
+ const usage = () => {
13
+ throw new UsageError('usage: spex-session initialize|enqueue|dequeue|pending --session-id ID [command options]');
14
+ };
15
+ const isCommandName = (value) => (value === 'initialize' || value === 'enqueue' || value === 'dequeue' || value === 'pending');
16
+ export function parseCommand(argv) {
17
+ const command = argv[0];
18
+ if (!isCommandName(command))
19
+ return usage();
20
+ const commandName = command;
21
+ const values = new Map();
22
+ const headers = [];
23
+ let assumeLocal = false;
24
+ for (let index = 1; index < argv.length; index += 1) {
25
+ const token = argv[index];
26
+ if (token === '--assume-local-storage') {
27
+ if (assumeLocal)
28
+ throw new UsageError('duplicate --assume-local-storage');
29
+ assumeLocal = true;
30
+ continue;
31
+ }
32
+ if (!token.startsWith('--'))
33
+ throw new UsageError(`unexpected argument ${token}`);
34
+ const name = token.slice(2);
35
+ if (name === 'header' && commandName === 'enqueue') {
36
+ const raw = argv[++index];
37
+ if (raw === undefined)
38
+ throw new UsageError('missing value for --header');
39
+ const separator = raw.indexOf('=');
40
+ if (separator <= 0)
41
+ throw new UsageError('--header must be K=V');
42
+ headers.push([raw.slice(0, separator), raw.slice(separator + 1)]);
43
+ continue;
44
+ }
45
+ if (!VALUE_FLAGS[commandName].has(name))
46
+ throw new UsageError(`unknown option --${name}`);
47
+ if (values.has(name))
48
+ throw new UsageError(`duplicate --${name}`);
49
+ const value = argv[++index];
50
+ if (value === undefined)
51
+ throw new UsageError(`missing value for --${name}`);
52
+ values.set(name, value);
53
+ }
54
+ if (!values.has('session-id'))
55
+ throw new UsageError('missing --session-id');
56
+ if (commandName === 'enqueue' && !values.has('kind'))
57
+ throw new UsageError('missing --kind');
58
+ if (commandName === 'enqueue' && !values.has('body'))
59
+ throw new UsageError('missing --body');
60
+ return { command: commandName, values, headers, assumeLocal };
61
+ }
62
+ const renderMessage = (message) => {
63
+ const { body, ...fields } = message;
64
+ return { ...fields, bodyBase64: Buffer.from(body).toString('base64') };
65
+ };
66
+ const errorCode = (error) => {
67
+ if (error instanceof UsageError)
68
+ return error.code;
69
+ if (error instanceof DatabasePathError)
70
+ return error.code;
71
+ if (error instanceof LocalityError)
72
+ return error.code;
73
+ if (typeof error === 'object'
74
+ && error !== null
75
+ && 'code' in error
76
+ && typeof error.code === 'string'
77
+ && error.code.startsWith('PROTOCOL_'))
78
+ return error.code;
79
+ return 'INTERNAL';
80
+ };
81
+ const SQLITE_EXPERIMENTAL_WARNING = 'SQLite is an experimental feature and might change at any time';
82
+ // @@@node-sqlite-warning - Node 22 emits this during import; suppress only that exact warning so the
83
+ // CLI's stderr remains its frozen single line while every unrelated warning keeps its normal path.
84
+ const loadOpenProtocol = async () => {
85
+ const originalEmitWarning = process.emitWarning;
86
+ process.emitWarning = ((warning, ...args) => {
87
+ const message = warning instanceof Error ? warning.message : warning;
88
+ if (message === SQLITE_EXPERIMENTAL_WARNING)
89
+ return;
90
+ Reflect.apply(originalEmitWarning, process, [warning, ...args]);
91
+ });
92
+ try {
93
+ return (await import('@spexcode/session-protocol')).openProtocol;
94
+ }
95
+ finally {
96
+ process.emitWarning = originalEmitWarning;
97
+ }
98
+ };
99
+ export async function runCli(options = {}) {
100
+ const stdout = options.stdout ?? (text => process.stdout.write(text));
101
+ const stderr = options.stderr ?? (text => process.stderr.write(text));
102
+ let protocol;
103
+ try {
104
+ const parsed = parseCommand(options.argv ?? process.argv.slice(2));
105
+ const databasePath = resolveDatabasePath({
106
+ databasePath: parsed.values.get('database-path'),
107
+ env: options.env,
108
+ });
109
+ const dependencies = options.dependencies ?? {
110
+ open: await loadOpenProtocol(),
111
+ requireLocal: requireLocalDatabasePath,
112
+ };
113
+ dependencies.requireLocal(databasePath, { assumeLocal: parsed.assumeLocal });
114
+ protocol = dependencies.open(databasePath);
115
+ const sessionId = parsed.values.get('session-id');
116
+ let result;
117
+ if (parsed.command === 'initialize') {
118
+ result = protocol.initialize(sessionId);
119
+ }
120
+ else if (parsed.command === 'enqueue') {
121
+ const headers = Object.fromEntries(parsed.headers);
122
+ result = renderMessage(protocol.enqueue(sessionId, {
123
+ kind: parsed.values.get('kind'),
124
+ body: Buffer.from(parsed.values.get('body'), 'utf8'),
125
+ ...(parsed.values.has('sender-session-id')
126
+ ? { senderSessionId: parsed.values.get('sender-session-id') }
127
+ : {}),
128
+ ...(parsed.values.has('idempotency-key')
129
+ ? { idempotencyKey: parsed.values.get('idempotency-key') }
130
+ : {}),
131
+ ...(parsed.headers.length > 0 ? { headers } : {}),
132
+ }));
133
+ }
134
+ else if (parsed.command === 'dequeue') {
135
+ const message = protocol.dequeue(sessionId);
136
+ result = message === null ? null : renderMessage(message);
137
+ }
138
+ else {
139
+ result = protocol.listPending(sessionId).map(renderMessage);
140
+ }
141
+ stdout(`${JSON.stringify(result)}\n`);
142
+ return 0;
143
+ }
144
+ catch (error) {
145
+ const code = errorCode(error);
146
+ const message = error instanceof Error ? error.message : String(error);
147
+ const repair = code === 'PROTOCOL_PATH_PARENT_MISSING'
148
+ ? '; create the parent directory or choose --database-path with an existing parent'
149
+ : '';
150
+ stderr(`spex-session: ${code}: ${message}${repair}\n`);
151
+ return code === 'USAGE' ? 2 : 1;
152
+ }
153
+ finally {
154
+ protocol?.close();
155
+ }
156
+ }
@@ -0,0 +1,28 @@
1
+ export { LocalityError, requireLocalDatabasePath } from './locality.js';
2
+ export type { LocalityRefusalCode } from './locality.js';
3
+ export { resolveDatabasePath } from './path.js';
4
+ export type { ResolveDatabasePathOptions, SelfLaunchEnvironment } from './path.js';
5
+ import type { ProtocolTransaction } from '@spexcode/session-protocol';
6
+ import { type BindingOptions, type RuntimeBinding } from '@spexcode/session-runtime';
7
+ /**
8
+ * Native identity supplied by the harness adapter that owns this self-launch.
9
+ * The CLI session id is deliberately not accepted as a native identity.
10
+ */
11
+ export interface SelfLaunchRuntimeIdentity {
12
+ nativeSessionId: string;
13
+ nativeStartToken: string;
14
+ metadata?: Record<string, unknown>;
15
+ }
16
+ export interface SelfLaunchProtocol {
17
+ withTransaction<T>(body: (tx: ProtocolTransaction) => T): T;
18
+ }
19
+ export interface SelfLaunchBindingOptions extends BindingOptions {
20
+ runtimeKind?: string;
21
+ }
22
+ /**
23
+ * Attach a caller-owned native harness identity to an existing protocol address.
24
+ * This is the only self-launch/runtime seam; it does not launch, probe, or stop a harness.
25
+ */
26
+ export declare function bindSelfLaunchRuntime(protocol: SelfLaunchProtocol, protocolSessionId: string, identity: SelfLaunchRuntimeIdentity, options?: SelfLaunchBindingOptions): RuntimeBinding;
27
+ export declare function resolveSelfLaunchRuntime(protocol: SelfLaunchProtocol, protocolSessionId: string): RuntimeBinding | null;
28
+ export declare function unbindSelfLaunchRuntime(protocol: SelfLaunchProtocol, protocolSessionId: string, options?: BindingOptions): RuntimeBinding;
@@ -0,0 +1,25 @@
1
+ export { LocalityError, requireLocalDatabasePath } from './locality.js';
2
+ export { resolveDatabasePath } from './path.js';
3
+ import { openRuntimeBindings, } from '@spexcode/session-runtime';
4
+ const SELF_LAUNCH_NAMESPACE = 'self-launch';
5
+ /**
6
+ * Attach a caller-owned native harness identity to an existing protocol address.
7
+ * This is the only self-launch/runtime seam; it does not launch, probe, or stop a harness.
8
+ */
9
+ export function bindSelfLaunchRuntime(protocol, protocolSessionId, identity, options = {}) {
10
+ const bindings = openRuntimeBindings(protocol);
11
+ return protocol.withTransaction(tx => bindings.bind(tx, protocolSessionId, {
12
+ namespace: SELF_LAUNCH_NAMESPACE,
13
+ runtimeKind: options.runtimeKind ?? 'self-launch',
14
+ nativeSessionId: identity.nativeSessionId,
15
+ nativeStartToken: identity.nativeStartToken,
16
+ metadata: identity.metadata,
17
+ }, options));
18
+ }
19
+ export function resolveSelfLaunchRuntime(protocol, protocolSessionId) {
20
+ return openRuntimeBindings(protocol).resolve(SELF_LAUNCH_NAMESPACE, protocolSessionId);
21
+ }
22
+ export function unbindSelfLaunchRuntime(protocol, protocolSessionId, options = {}) {
23
+ const bindings = openRuntimeBindings(protocol);
24
+ return protocol.withTransaction(tx => bindings.unbind(tx, SELF_LAUNCH_NAMESPACE, protocolSessionId, options));
25
+ }
@@ -0,0 +1,31 @@
1
+ export type LocalityRefusalCode = 'LOCALITY_NETWORK_FILESYSTEM' | 'LOCALITY_UNDETERMINED' | 'LOCALITY_DETECTOR_UNAVAILABLE' | 'LOCALITY_PROBE_FAILED';
2
+ export declare class LocalityError extends Error {
3
+ readonly code: LocalityRefusalCode;
4
+ constructor(code: LocalityRefusalCode, message: string, cause?: unknown);
5
+ }
6
+ export interface FilesystemClassification {
7
+ readonly locality: 'local' | 'network' | 'undetermined';
8
+ readonly name: string;
9
+ }
10
+ export declare function classifyFilesystemType(type: number | bigint): FilesystemClassification;
11
+ export interface LocalityDetector {
12
+ readonly platform: string;
13
+ readonly classify?: (parentPath: string) => FilesystemClassification;
14
+ }
15
+ export declare const linuxLocalityDetector: (statfsType: (parentPath: string) => number | bigint) => LocalityDetector;
16
+ interface DarwinMountEntry {
17
+ readonly mountPoint: string;
18
+ readonly fstype: string;
19
+ readonly flags: ReadonlySet<string>;
20
+ }
21
+ export declare function parseDarwinMountTable(output: string): DarwinMountEntry[];
22
+ export declare function classifyDarwinMount(mountTable: string, resolvedPath: string): FilesystemClassification;
23
+ export declare const darwinLocalityDetector: (readMountTable: () => string) => LocalityDetector;
24
+ export declare function requireLocalDatabasePathWithDetector(databasePath: string, options: {
25
+ assumeLocal?: boolean;
26
+ }, detector: LocalityDetector): string;
27
+ export declare function localityDetectorForPlatform(platform: string): LocalityDetector;
28
+ export declare function requireLocalDatabasePath(databasePath: string, options?: {
29
+ assumeLocal?: boolean;
30
+ }): string;
31
+ export {};
@@ -0,0 +1,135 @@
1
+ import { execFileSync } from 'node:child_process';
2
+ import { realpathSync, statSync, statfsSync } from 'node:fs';
3
+ import { isAbsolute, dirname } from 'node:path';
4
+ import { DatabasePathError } from './path.js';
5
+ export class LocalityError extends Error {
6
+ code;
7
+ constructor(code, message, cause) {
8
+ super(message, cause === undefined ? undefined : { cause });
9
+ this.name = 'LocalityError';
10
+ this.code = code;
11
+ }
12
+ }
13
+ // @@@network-magic-evidence - These header values drive classifier vectors, not real-mount evidence;
14
+ // this host has no corresponding network mount on which to run them.
15
+ const NETWORK_FILESYSTEM_TYPES = [
16
+ { name: 'NFS', type: 0x6969 },
17
+ { name: 'SMB', type: 0x517b },
18
+ { name: 'CIFS', type: 0xff534d42 },
19
+ { name: 'SMB2', type: 0xfe534d42 },
20
+ { name: '9P', type: 0x01021997 },
21
+ { name: 'CEPH', type: 0x00c36400 },
22
+ { name: 'AFS', type: 0x5346414f },
23
+ { name: 'AFS_FS', type: 0x6b414653 },
24
+ { name: 'CODA', type: 0x73757245 },
25
+ { name: 'OCFS2', type: 0x7461636f },
26
+ { name: 'NCP', type: 0x564c },
27
+ ];
28
+ const LOCAL_FILESYSTEM_TYPES = [
29
+ { name: 'EXT2/3/4', type: 0xef53 },
30
+ { name: 'BTRFS', type: 0x9123683e },
31
+ { name: 'XFS', type: 0x58465342 },
32
+ { name: 'F2FS', type: 0xf2f52010 },
33
+ { name: 'TMPFS', type: 0x01021994 },
34
+ { name: 'OVERLAYFS', type: 0x794c7630 },
35
+ { name: 'ZFS', type: 0x2fc12fc1 },
36
+ ];
37
+ const unsignedMagic = (type) => Number(BigInt.asUintN(32, BigInt(type)));
38
+ export function classifyFilesystemType(type) {
39
+ const magic = unsignedMagic(type);
40
+ const network = NETWORK_FILESYSTEM_TYPES.find(candidate => candidate.type === magic);
41
+ if (network)
42
+ return { locality: 'network', name: network.name };
43
+ const local = LOCAL_FILESYSTEM_TYPES.find(candidate => candidate.type === magic);
44
+ if (local)
45
+ return { locality: 'local', name: local.name };
46
+ return { locality: 'undetermined', name: `0x${magic.toString(16)}` };
47
+ }
48
+ export const linuxLocalityDetector = (statfsType) => ({
49
+ platform: 'linux',
50
+ classify: parentPath => classifyFilesystemType(statfsType(parentPath)),
51
+ });
52
+ // Darwin filesystem type names that are network transports even when the mount table omits MNT_LOCAL. `local`
53
+ // wins when present (it is the kernel's own verdict); this list only names the refusal, so the operator reads
54
+ // "smbfs" instead of a bare "undetermined".
55
+ const DARWIN_NETWORK_FILESYSTEM_NAMES = new Set(['nfs', 'smbfs', 'afpfs', 'webdav', 'cifs', 'ftp']);
56
+ // `/sbin/mount` prints one `<device> on <mount point> (<fstype>, <flag>, …)` line per mount. The mount point may
57
+ // contain spaces (`/Volumes/My Disk`); the parenthesised list is always last and never contains `)`.
58
+ const DARWIN_MOUNT_LINE = /^.+ on (.+) \(([^)]*)\)$/;
59
+ export function parseDarwinMountTable(output) {
60
+ const entries = [];
61
+ for (const line of output.split('\n')) {
62
+ const match = DARWIN_MOUNT_LINE.exec(line.trim());
63
+ if (!match)
64
+ continue;
65
+ const [fstype = '', ...flags] = match[2].split(',').map(part => part.trim()).filter(Boolean);
66
+ entries.push({ mountPoint: match[1], fstype, flags: new Set(flags) });
67
+ }
68
+ return entries;
69
+ }
70
+ const mountPointCovers = (mountPoint, path) => mountPoint === '/' || path === mountPoint || path.startsWith(mountPoint.endsWith('/') ? mountPoint : `${mountPoint}/`);
71
+ export function classifyDarwinMount(mountTable, resolvedPath) {
72
+ let entry;
73
+ for (const candidate of parseDarwinMountTable(mountTable)) {
74
+ if (!mountPointCovers(candidate.mountPoint, resolvedPath))
75
+ continue;
76
+ if (!entry || candidate.mountPoint.length > entry.mountPoint.length)
77
+ entry = candidate;
78
+ }
79
+ if (!entry)
80
+ return { locality: 'undetermined', name: 'no mount table entry' };
81
+ if (entry.flags.has('local'))
82
+ return { locality: 'local', name: entry.fstype };
83
+ if (DARWIN_NETWORK_FILESYSTEM_NAMES.has(entry.fstype))
84
+ return { locality: 'network', name: entry.fstype };
85
+ return { locality: 'undetermined', name: entry.fstype };
86
+ }
87
+ export const darwinLocalityDetector = (readMountTable) => ({
88
+ platform: 'darwin',
89
+ classify: parentPath => {
90
+ // `mount` never fails for a missing directory, so the parent's absence must be raised here for the resolver
91
+ // to keep its actionable PROTOCOL_PATH_PARENT_MISSING error.
92
+ statSync(parentPath);
93
+ return classifyDarwinMount(readMountTable(), realpathSync(parentPath));
94
+ },
95
+ });
96
+ export function requireLocalDatabasePathWithDetector(databasePath, options, detector) {
97
+ if (!isAbsolute(databasePath)) {
98
+ throw new DatabasePathError('PROTOCOL_PATH_NOT_ABSOLUTE', 'databasePath must be absolute before locality detection');
99
+ }
100
+ if (options.assumeLocal)
101
+ return databasePath;
102
+ const parent = dirname(databasePath);
103
+ if (!detector.classify) {
104
+ throw new LocalityError('LOCALITY_DETECTOR_UNAVAILABLE', `no filesystem locality detector for platform ${detector.platform}; pass --assume-local-storage only after auditing ${parent}`);
105
+ }
106
+ let classification;
107
+ try {
108
+ classification = detector.classify(parent);
109
+ }
110
+ catch (error) {
111
+ // @@@missing-parent - Preserve the actionable path error without pretending locality was established.
112
+ if (typeof error === 'object' && error !== null && 'code' in error && error.code === 'ENOENT') {
113
+ throw new DatabasePathError('PROTOCOL_PATH_PARENT_MISSING', `database parent directory does not exist: ${parent}`, error);
114
+ }
115
+ throw new LocalityError('LOCALITY_PROBE_FAILED', `could not determine the filesystem of ${parent}`, error);
116
+ }
117
+ if (classification.locality === 'network') {
118
+ throw new LocalityError('LOCALITY_NETWORK_FILESYSTEM', `${parent} is ${classification.name}; advisory locking is not admitted there`);
119
+ }
120
+ if (classification.locality === 'undetermined') {
121
+ throw new LocalityError('LOCALITY_UNDETERMINED', `filesystem type ${classification.name} at ${parent} is not on the audited local allow-list`);
122
+ }
123
+ return databasePath;
124
+ }
125
+ const readDarwinMountTable = () => execFileSync('/sbin/mount', [], { encoding: 'utf8', timeout: 5_000, stdio: ['ignore', 'pipe', 'ignore'] });
126
+ export function localityDetectorForPlatform(platform) {
127
+ if (platform === 'linux')
128
+ return linuxLocalityDetector(parentPath => statfsSync(parentPath).type);
129
+ if (platform === 'darwin')
130
+ return darwinLocalityDetector(readDarwinMountTable);
131
+ return { platform };
132
+ }
133
+ export function requireLocalDatabasePath(databasePath, options = {}) {
134
+ return requireLocalDatabasePathWithDetector(databasePath, options, localityDetectorForPlatform(process.platform));
135
+ }
@@ -0,0 +1,13 @@
1
+ type DatabasePathErrorCode = 'PROTOCOL_PATH_NOT_ABSOLUTE' | 'PROTOCOL_PATH_INVALID' | 'PROTOCOL_PATH_PARENT_MISSING';
2
+ export declare class DatabasePathError extends Error {
3
+ readonly code: DatabasePathErrorCode;
4
+ constructor(code: DatabasePathErrorCode, message: string, cause?: unknown);
5
+ }
6
+ export type SelfLaunchEnvironment = Readonly<Record<string, string | undefined>>;
7
+ export interface ResolveDatabasePathOptions {
8
+ databasePath?: string;
9
+ env?: SelfLaunchEnvironment;
10
+ readFile?: (path: string) => string;
11
+ }
12
+ export declare function resolveDatabasePath(options?: ResolveDatabasePathOptions): string;
13
+ export {};
@@ -0,0 +1,45 @@
1
+ import { readFileSync } from 'node:fs';
2
+ import { isAbsolute, join } from 'node:path';
3
+ export class DatabasePathError extends Error {
4
+ code;
5
+ constructor(code, message, cause) {
6
+ super(message, cause === undefined ? undefined : { cause });
7
+ this.name = 'DatabasePathError';
8
+ this.code = code;
9
+ }
10
+ }
11
+ export function resolveDatabasePath(options = {}) {
12
+ const env = options.env ?? process.env;
13
+ let databasePath = options.databasePath ?? env.SPEX_SESSION_DATABASE_PATH;
14
+ if (databasePath === undefined && env.SPEX_SESSION_CONFIG) {
15
+ const configPath = env.SPEX_SESSION_CONFIG;
16
+ let config;
17
+ try {
18
+ config = JSON.parse((options.readFile ?? ((path) => readFileSync(path, 'utf8')))(configPath));
19
+ }
20
+ catch (error) {
21
+ throw new DatabasePathError('PROTOCOL_PATH_INVALID', `could not read session config ${configPath}`, error);
22
+ }
23
+ if (typeof config !== 'object'
24
+ || config === null
25
+ || typeof config.databasePath !== 'string'
26
+ || !config.databasePath) {
27
+ throw new DatabasePathError('PROTOCOL_PATH_INVALID', `session config ${configPath} must contain databasePath`);
28
+ }
29
+ databasePath = config.databasePath;
30
+ }
31
+ if (databasePath === undefined) {
32
+ const home = env.SPEXCODE_HOME || (env.HOME ? join(env.HOME, '.spexcode') : undefined);
33
+ if (!home) {
34
+ throw new DatabasePathError('PROTOCOL_PATH_INVALID', 'HOME or SPEXCODE_HOME is required for the default database path');
35
+ }
36
+ databasePath = join(home, 'sessions.sqlite');
37
+ }
38
+ if (databasePath.length === 0) {
39
+ throw new DatabasePathError('PROTOCOL_PATH_INVALID', 'databasePath must not be empty');
40
+ }
41
+ if (!isAbsolute(databasePath)) {
42
+ throw new DatabasePathError('PROTOCOL_PATH_NOT_ABSOLUTE', 'databasePath must be absolute and is never resolved from cwd');
43
+ }
44
+ return databasePath;
45
+ }
@@ -0,0 +1,35 @@
1
+ {
2
+ "name": "@spexcode/session-selflaunch",
3
+ "version": "0.7.0-next.0",
4
+ "publishConfig": { "access": "public" },
5
+ "type": "module",
6
+ "description": "A fail-closed self-launch adopter for the SpexCode session protocol.",
7
+ "bin": {
8
+ "spex-session": "./bin/spex-session.mjs"
9
+ },
10
+ "files": [
11
+ "dist",
12
+ "bin"
13
+ ],
14
+ "exports": {
15
+ ".": "./dist/index.js",
16
+ "./package.json": "./package.json"
17
+ },
18
+ "engines": {
19
+ "node": ">=22"
20
+ },
21
+ "scripts": {
22
+ "build": "node ../../scripts/build-dist.mjs",
23
+ "prepublishOnly": "node ../../scripts/release-publish.mjs --from-package-publish",
24
+ "test": "npm run build && tsx --import ../../scripts/test-home.mjs --test src/*.test.ts"
25
+ },
26
+ "dependencies": {
27
+ "@spexcode/session-protocol": "0.7.0-next.0",
28
+ "@spexcode/session-runtime": "0.7.0-next.0"
29
+ },
30
+ "devDependencies": {
31
+ "@types/node": "^20.16.0",
32
+ "tsx": "^4.19.2",
33
+ "typescript": "^5.6.3"
34
+ }
35
+ }
@@ -0,0 +1,6 @@
1
+ export type TopologyErrorCode = 'TOPOLOGY_EDGE_ID_INVALID' | 'TOPOLOGY_EDGE_UNKNOWN' | 'TOPOLOGY_EDGE_EXISTS' | 'TOPOLOGY_CYCLE_REFUSED' | 'TOPOLOGY_RELATION_TYPE_INVALID' | 'TOPOLOGY_SESSION_ID_INVALID' | 'TOPOLOGY_SESSION_UNKNOWN' | 'TOPOLOGY_SELF_EDGE' | 'TOPOLOGY_TRANSACTION_INVALID' | 'TOPOLOGY_STORAGE_ERROR';
2
+ export declare class TopologyError extends Error {
3
+ readonly code: TopologyErrorCode;
4
+ constructor(code: TopologyErrorCode, message: string, cause?: unknown);
5
+ }
6
+ export declare function failTopology(code: TopologyErrorCode, message: string, cause?: unknown): never;
@@ -0,0 +1,11 @@
1
+ export class TopologyError extends Error {
2
+ code;
3
+ constructor(code, message, cause) {
4
+ super(message, { cause });
5
+ this.name = 'TopologyError';
6
+ this.code = code;
7
+ }
8
+ }
9
+ export function failTopology(code, message, cause) {
10
+ throw new TopologyError(code, message, cause);
11
+ }
@@ -0,0 +1,24 @@
1
+ import type { ProtocolTransaction, SessionProtocol } from '@spexcode/session-protocol';
2
+ import { TopologyError } from './errors.js';
3
+ export interface TopologyEdge {
4
+ edgeId: string;
5
+ fromSessionId: string;
6
+ toSessionId: string;
7
+ relationType: string;
8
+ createdAtMs: number;
9
+ removedAtMs: number | null;
10
+ }
11
+ export interface SessionTopology {
12
+ attach(tx: ProtocolTransaction, fromSessionId: string, toSessionId: string, relationType: string): TopologyEdge;
13
+ detach(tx: ProtocolTransaction, edgeId: string): TopologyEdge;
14
+ reparent(tx: ProtocolTransaction, subjectSessionId: string, nextFromSessionId: string, relationType: string): TopologyEdge;
15
+ subscribe(tx: ProtocolTransaction, watcherSessionId: string, subjectSessionId: string, channel: string): TopologyEdge;
16
+ unsubscribe(tx: ProtocolTransaction, watcherSessionId: string, subjectSessionId: string, channel: string): TopologyEdge;
17
+ parents(sessionId: string, relationType?: string, tx?: ProtocolTransaction): TopologyEdge[];
18
+ children(sessionId: string, relationType?: string, tx?: ProtocolTransaction): TopologyEdge[];
19
+ subscriptions(sessionId: string, tx?: ProtocolTransaction): TopologyEdge[];
20
+ recipients(subjectSessionId: string, tx?: ProtocolTransaction): string[];
21
+ }
22
+ export declare function openTopology(protocol: SessionProtocol): SessionTopology;
23
+ export { TopologyError };
24
+ export type { TopologyErrorCode } from './errors.js';