spidersan 0.6.0 → 0.9.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 (214) hide show
  1. package/CHANGELOG.md +42 -52
  2. package/README.md +238 -3
  3. package/dist/bin/spidersan.d.ts.map +1 -1
  4. package/dist/bin/spidersan.js +13 -1
  5. package/dist/bin/spidersan.js.map +1 -1
  6. package/dist/commands/abandon.d.ts.map +1 -1
  7. package/dist/commands/abandon.js +1 -9
  8. package/dist/commands/abandon.js.map +1 -1
  9. package/dist/commands/ai.d.ts +15 -0
  10. package/dist/commands/ai.d.ts.map +1 -0
  11. package/dist/commands/ai.js +498 -0
  12. package/dist/commands/ai.js.map +1 -0
  13. package/dist/commands/auto.d.ts.map +1 -1
  14. package/dist/commands/auto.js +2 -1
  15. package/dist/commands/auto.js.map +1 -1
  16. package/dist/commands/bot.d.ts +16 -0
  17. package/dist/commands/bot.d.ts.map +1 -0
  18. package/dist/commands/bot.js +398 -0
  19. package/dist/commands/bot.js.map +1 -0
  20. package/dist/commands/conflicts.d.ts.map +1 -1
  21. package/dist/commands/conflicts.js +260 -277
  22. package/dist/commands/conflicts.js.map +1 -1
  23. package/dist/commands/context.d.ts +8 -0
  24. package/dist/commands/context.d.ts.map +1 -0
  25. package/dist/commands/context.js +104 -0
  26. package/dist/commands/context.js.map +1 -0
  27. package/dist/commands/cross-conflicts.d.ts.map +1 -1
  28. package/dist/commands/cross-conflicts.js +1 -41
  29. package/dist/commands/cross-conflicts.js.map +1 -1
  30. package/dist/commands/depends.d.ts.map +1 -1
  31. package/dist/commands/depends.js +1 -9
  32. package/dist/commands/depends.js.map +1 -1
  33. package/dist/commands/fleet-status.d.ts +14 -0
  34. package/dist/commands/fleet-status.d.ts.map +1 -0
  35. package/dist/commands/fleet-status.js +127 -0
  36. package/dist/commands/fleet-status.js.map +1 -0
  37. package/dist/commands/git-watch.d.ts +24 -0
  38. package/dist/commands/git-watch.d.ts.map +1 -0
  39. package/dist/commands/git-watch.js +84 -0
  40. package/dist/commands/git-watch.js.map +1 -0
  41. package/dist/commands/index.d.ts +5 -0
  42. package/dist/commands/index.d.ts.map +1 -1
  43. package/dist/commands/index.js +7 -0
  44. package/dist/commands/index.js.map +1 -1
  45. package/dist/commands/merge-order.d.ts.map +1 -1
  46. package/dist/commands/merge-order.js +18 -67
  47. package/dist/commands/merge-order.js.map +1 -1
  48. package/dist/commands/merged.d.ts.map +1 -1
  49. package/dist/commands/merged.js +1 -9
  50. package/dist/commands/merged.js.map +1 -1
  51. package/dist/commands/pulse.d.ts.map +1 -1
  52. package/dist/commands/pulse.js +134 -63
  53. package/dist/commands/pulse.js.map +1 -1
  54. package/dist/commands/queen.d.ts.map +1 -1
  55. package/dist/commands/queen.js +11 -7
  56. package/dist/commands/queen.js.map +1 -1
  57. package/dist/commands/ready-check.d.ts +2 -1
  58. package/dist/commands/ready-check.d.ts.map +1 -1
  59. package/dist/commands/ready-check.js +6 -30
  60. package/dist/commands/ready-check.js.map +1 -1
  61. package/dist/commands/register.d.ts.map +1 -1
  62. package/dist/commands/register.js +7 -29
  63. package/dist/commands/register.js.map +1 -1
  64. package/dist/commands/torrent.d.ts.map +1 -1
  65. package/dist/commands/torrent.js +29 -18
  66. package/dist/commands/torrent.js.map +1 -1
  67. package/dist/commands/watch.d.ts.map +1 -1
  68. package/dist/commands/watch.js +13 -34
  69. package/dist/commands/watch.js.map +1 -1
  70. package/dist/lib/ai/context-builder.d.ts +16 -0
  71. package/dist/lib/ai/context-builder.d.ts.map +1 -0
  72. package/dist/lib/ai/context-builder.js +216 -0
  73. package/dist/lib/ai/context-builder.js.map +1 -0
  74. package/dist/lib/ai/event-handler.d.ts +21 -0
  75. package/dist/lib/ai/event-handler.d.ts.map +1 -0
  76. package/dist/lib/ai/event-handler.js +98 -0
  77. package/dist/lib/ai/event-handler.js.map +1 -0
  78. package/dist/lib/ai/index.d.ts +13 -0
  79. package/dist/lib/ai/index.d.ts.map +1 -0
  80. package/dist/lib/ai/index.js +11 -0
  81. package/dist/lib/ai/index.js.map +1 -0
  82. package/dist/lib/ai/llm-client.d.ts +37 -0
  83. package/dist/lib/ai/llm-client.d.ts.map +1 -0
  84. package/dist/lib/ai/llm-client.js +225 -0
  85. package/dist/lib/ai/llm-client.js.map +1 -0
  86. package/dist/lib/ai/reasoner.d.ts +11 -0
  87. package/dist/lib/ai/reasoner.d.ts.map +1 -0
  88. package/dist/lib/ai/reasoner.js +246 -0
  89. package/dist/lib/ai/reasoner.js.map +1 -0
  90. package/dist/lib/ai/setup.d.ts +40 -0
  91. package/dist/lib/ai/setup.d.ts.map +1 -0
  92. package/dist/lib/ai/setup.js +154 -0
  93. package/dist/lib/ai/setup.js.map +1 -0
  94. package/dist/lib/ai/types.d.ts +135 -0
  95. package/dist/lib/ai/types.d.ts.map +1 -0
  96. package/dist/lib/ai/types.js +39 -0
  97. package/dist/lib/ai/types.js.map +1 -0
  98. package/dist/lib/colony-subscriber.d.ts +15 -12
  99. package/dist/lib/colony-subscriber.d.ts.map +1 -1
  100. package/dist/lib/colony-subscriber.js +146 -65
  101. package/dist/lib/colony-subscriber.js.map +1 -1
  102. package/dist/lib/config.d.ts.map +1 -1
  103. package/dist/lib/config.js +18 -4
  104. package/dist/lib/config.js.map +1 -1
  105. package/dist/lib/conflict-analyzer.d.ts +33 -0
  106. package/dist/lib/conflict-analyzer.d.ts.map +1 -0
  107. package/dist/lib/conflict-analyzer.js +114 -0
  108. package/dist/lib/conflict-analyzer.js.map +1 -0
  109. package/dist/lib/conflict-renderer.d.ts +7 -0
  110. package/dist/lib/conflict-renderer.d.ts.map +1 -0
  111. package/dist/lib/conflict-renderer.js +162 -0
  112. package/dist/lib/conflict-renderer.js.map +1 -0
  113. package/dist/lib/conflict-tier.d.ts +20 -0
  114. package/dist/lib/conflict-tier.d.ts.map +1 -0
  115. package/dist/lib/conflict-tier.js +49 -0
  116. package/dist/lib/conflict-tier.js.map +1 -0
  117. package/dist/lib/crypto.js +1 -1
  118. package/dist/lib/crypto.js.map +1 -1
  119. package/dist/lib/git-events-subscriber.d.ts +59 -0
  120. package/dist/lib/git-events-subscriber.d.ts.map +1 -0
  121. package/dist/lib/git-events-subscriber.js +779 -0
  122. package/dist/lib/git-events-subscriber.js.map +1 -0
  123. package/dist/lib/git.d.ts +15 -0
  124. package/dist/lib/git.d.ts.map +1 -0
  125. package/dist/lib/git.js +180 -0
  126. package/dist/lib/git.js.map +1 -0
  127. package/dist/lib/github.d.ts.map +1 -1
  128. package/dist/lib/github.js +14 -9
  129. package/dist/lib/github.js.map +1 -1
  130. package/dist/lib/graph.d.ts +23 -0
  131. package/dist/lib/graph.d.ts.map +1 -0
  132. package/dist/lib/graph.js +134 -0
  133. package/dist/lib/graph.js.map +1 -0
  134. package/dist/lib/hub.d.ts +31 -0
  135. package/dist/lib/hub.d.ts.map +1 -0
  136. package/dist/lib/hub.js +92 -0
  137. package/dist/lib/hub.js.map +1 -0
  138. package/dist/lib/remote-drift.d.ts +60 -0
  139. package/dist/lib/remote-drift.d.ts.map +1 -0
  140. package/dist/lib/remote-drift.js +225 -0
  141. package/dist/lib/remote-drift.js.map +1 -0
  142. package/dist/lib/salvage-analyzer.d.ts.map +1 -1
  143. package/dist/lib/salvage-analyzer.js +2 -3
  144. package/dist/lib/salvage-analyzer.js.map +1 -1
  145. package/dist/lib/security.d.ts +11 -0
  146. package/dist/lib/security.d.ts.map +1 -1
  147. package/dist/lib/security.js +24 -1
  148. package/dist/lib/security.js.map +1 -1
  149. package/dist/lib/session-logger.d.ts +54 -0
  150. package/dist/lib/session-logger.d.ts.map +1 -0
  151. package/dist/lib/session-logger.js +136 -0
  152. package/dist/lib/session-logger.js.map +1 -0
  153. package/dist/storage/adapter.d.ts +4 -0
  154. package/dist/storage/adapter.d.ts.map +1 -1
  155. package/dist/storage/branch-registry-store.d.ts +13 -0
  156. package/dist/storage/branch-registry-store.d.ts.map +1 -0
  157. package/dist/storage/branch-registry-store.js +2 -0
  158. package/dist/storage/branch-registry-store.js.map +1 -0
  159. package/dist/storage/factory.d.ts +4 -0
  160. package/dist/storage/factory.d.ts.map +1 -1
  161. package/dist/storage/factory.js +25 -9
  162. package/dist/storage/factory.js.map +1 -1
  163. package/dist/storage/git-messages.d.ts +53 -0
  164. package/dist/storage/git-messages.d.ts.map +1 -0
  165. package/dist/storage/git-messages.js +376 -0
  166. package/dist/storage/git-messages.js.map +1 -0
  167. package/dist/storage/index.d.ts +5 -0
  168. package/dist/storage/index.d.ts.map +1 -1
  169. package/dist/storage/index.js +5 -0
  170. package/dist/storage/index.js.map +1 -1
  171. package/dist/storage/json-branch-registry-store.d.ts +19 -0
  172. package/dist/storage/json-branch-registry-store.d.ts.map +1 -0
  173. package/dist/storage/json-branch-registry-store.js +112 -0
  174. package/dist/storage/json-branch-registry-store.js.map +1 -0
  175. package/dist/storage/local-messages.d.ts +37 -0
  176. package/dist/storage/local-messages.d.ts.map +1 -0
  177. package/dist/storage/local-messages.js +151 -0
  178. package/dist/storage/local-messages.js.map +1 -0
  179. package/dist/storage/local.d.ts +2 -6
  180. package/dist/storage/local.d.ts.map +1 -1
  181. package/dist/storage/local.js +13 -76
  182. package/dist/storage/local.js.map +1 -1
  183. package/dist/storage/memory-branch-registry-store.d.ts +16 -0
  184. package/dist/storage/memory-branch-registry-store.d.ts.map +1 -0
  185. package/dist/storage/memory-branch-registry-store.js +65 -0
  186. package/dist/storage/memory-branch-registry-store.js.map +1 -0
  187. package/dist/storage/message-adapter.d.ts +86 -0
  188. package/dist/storage/message-adapter.d.ts.map +1 -0
  189. package/dist/storage/message-adapter.js +28 -0
  190. package/dist/storage/message-adapter.js.map +1 -0
  191. package/dist/storage/message-factory.d.ts +36 -0
  192. package/dist/storage/message-factory.d.ts.map +1 -0
  193. package/dist/storage/message-factory.js +99 -0
  194. package/dist/storage/message-factory.js.map +1 -0
  195. package/dist/storage/mycmail-adapter.d.ts +38 -0
  196. package/dist/storage/mycmail-adapter.d.ts.map +1 -0
  197. package/dist/storage/mycmail-adapter.js +300 -0
  198. package/dist/storage/mycmail-adapter.js.map +1 -0
  199. package/dist/storage/supabase-registry-sync-client-impl.d.ts +46 -0
  200. package/dist/storage/supabase-registry-sync-client-impl.d.ts.map +1 -0
  201. package/dist/storage/supabase-registry-sync-client-impl.js +322 -0
  202. package/dist/storage/supabase-registry-sync-client-impl.js.map +1 -0
  203. package/dist/storage/supabase-registry-sync-client.d.ts +9 -0
  204. package/dist/storage/supabase-registry-sync-client.d.ts.map +1 -0
  205. package/dist/storage/supabase-registry-sync-client.js +2 -0
  206. package/dist/storage/supabase-registry-sync-client.js.map +1 -0
  207. package/dist/storage/supabase.d.ts +8 -46
  208. package/dist/storage/supabase.d.ts.map +1 -1
  209. package/dist/storage/supabase.js +30 -342
  210. package/dist/storage/supabase.js.map +1 -1
  211. package/dist/tui/screen.d.ts.map +1 -1
  212. package/dist/tui/screen.js +5 -3
  213. package/dist/tui/screen.js.map +1 -1
  214. package/package.json +92 -90
@@ -0,0 +1,136 @@
1
+ /**
2
+ * Session Logger — captures raw spidersan ask/advise/explain sessions for training.
3
+ *
4
+ * Writes to ~/.spidersan/sessions/YYYY-MM-DD.jsonl (one JSON object per line).
5
+ * Each entry is a raw session: context + result + outcome.
6
+ *
7
+ * Outcome is what makes this a gold pair. Without it we just have questions.
8
+ * Outcome is captured inline (TTY prompt after response) or left null.
9
+ *
10
+ * Anonymization + gold pair transformation happens at `watsan index-pair` time,
11
+ * not here. This logger stores raw data locally — nothing leaves the machine.
12
+ *
13
+ * Design:
14
+ * - Never throws — session logging must not crash spidersan ask
15
+ * - Append-only JSONL — safe for concurrent writes, easy to process
16
+ * - File per day — easy to hand to watsan for a given date range
17
+ */
18
+ import { appendFileSync, readFileSync, writeFileSync, mkdirSync, existsSync } from 'fs';
19
+ import { join } from 'path';
20
+ import { homedir } from 'os';
21
+ import { randomUUID } from 'crypto';
22
+ // ─── Paths ────────────────────────────────────────────────────
23
+ function sessionsDir() {
24
+ return join(homedir(), '.spidersan', 'sessions');
25
+ }
26
+ function dateFile(offsetDays = 0) {
27
+ const d = new Date(Date.now() - offsetDays * 86_400_000);
28
+ const ymd = `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`;
29
+ return join(sessionsDir(), `${ymd}.jsonl`);
30
+ }
31
+ function ensureDir() {
32
+ const dir = sessionsDir();
33
+ if (!existsSync(dir))
34
+ mkdirSync(dir, { recursive: true, mode: 0o700 });
35
+ }
36
+ // ─── Write ────────────────────────────────────────────────────
37
+ /**
38
+ * Append a session entry to today's log file.
39
+ * Returns the session_id so the caller can later capture the outcome.
40
+ * Never throws.
41
+ */
42
+ export function logSession(mode, context, result, opts) {
43
+ const session_id = randomUUID();
44
+ try {
45
+ ensureDir();
46
+ const entry = {
47
+ session_id,
48
+ logged_at: new Date().toISOString(),
49
+ mode,
50
+ question: opts?.question,
51
+ branch: opts?.branch,
52
+ context,
53
+ result,
54
+ outcome: null,
55
+ outcome_captured_at: null,
56
+ };
57
+ appendFileSync(dateFile(), JSON.stringify(entry) + '\n', { encoding: 'utf-8' });
58
+ }
59
+ catch {
60
+ // Silent — logging must never crash the main command
61
+ }
62
+ return session_id;
63
+ }
64
+ /**
65
+ * Update the outcome for a previously logged session.
66
+ * Checks today's and yesterday's log files.
67
+ * Never throws.
68
+ */
69
+ export function captureOutcome(session_id, outcome) {
70
+ try {
71
+ const now = new Date().toISOString();
72
+ // Check today and yesterday (covers sessions that started near midnight)
73
+ for (const filePath of [dateFile(0), dateFile(1)]) {
74
+ if (!existsSync(filePath))
75
+ continue;
76
+ const lines = readFileSync(filePath, 'utf-8').split('\n').filter(Boolean);
77
+ const idx = lines.findIndex(line => {
78
+ try {
79
+ return JSON.parse(line).session_id === session_id;
80
+ }
81
+ catch {
82
+ return false;
83
+ }
84
+ });
85
+ if (idx === -1)
86
+ continue;
87
+ const entry = JSON.parse(lines[idx]);
88
+ entry.outcome = outcome;
89
+ entry.outcome_captured_at = now;
90
+ lines[idx] = JSON.stringify(entry);
91
+ writeFileSync(filePath, lines.join('\n') + '\n', { encoding: 'utf-8' });
92
+ return;
93
+ }
94
+ }
95
+ catch {
96
+ // Silent
97
+ }
98
+ }
99
+ // ─── Inline outcome prompt ────────────────────────────────────
100
+ /**
101
+ * Show a brief outcome prompt after a response (TTY only).
102
+ * Non-blocking: skips if stdin is not a TTY or SPIDERSAN_NO_OUTCOME_PROMPT=1.
103
+ * Returns the captured outcome (or null if skipped).
104
+ */
105
+ export async function promptOutcome(session_id, rl) {
106
+ if (!process.stdin.isTTY || process.env['SPIDERSAN_NO_OUTCOME_PROMPT'] === '1') {
107
+ return null;
108
+ }
109
+ return new Promise((resolve) => {
110
+ process.stdout.write('\x1b[2m Follow this advice? [y/n/m=modified, Enter to skip] \x1b[0m');
111
+ rl.once('line', (answer) => {
112
+ const a = answer.trim().toLowerCase();
113
+ if (a === 'y' || a === 'yes') {
114
+ captureOutcome(session_id, 'followed');
115
+ resolve('followed');
116
+ }
117
+ else if (a === 'n' || a === 'no') {
118
+ captureOutcome(session_id, 'ignored');
119
+ resolve('ignored');
120
+ }
121
+ else if (a.startsWith('m')) {
122
+ process.stdout.write('\x1b[2m What changed? (one line) \x1b[0m');
123
+ rl.once('line', (desc) => {
124
+ const outcome = `modified:${desc.trim().slice(0, 200)}`;
125
+ captureOutcome(session_id, outcome);
126
+ resolve(outcome);
127
+ });
128
+ }
129
+ else {
130
+ // Enter / anything else → skip
131
+ resolve(null);
132
+ }
133
+ });
134
+ });
135
+ }
136
+ //# sourceMappingURL=session-logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-logger.js","sourceRoot":"","sources":["../../src/lib/session-logger.ts"],"names":[],"mappings":"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"}
@@ -17,6 +17,10 @@ export interface BranchRegistry {
17
17
  version: string;
18
18
  projectId?: string;
19
19
  }
20
+ /**
21
+ * @deprecated Use BranchRegistryStore for local registry access and
22
+ * SupabaseRegistrySyncClient for cross-machine sync.
23
+ */
20
24
  export interface StorageAdapter {
21
25
  /**
22
26
  * Initialize the storage (create directories, connect to DB, etc.)
@@ -1 +1 @@
1
- {"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../../src/storage/adapter.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,WAAW,MAAM;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,YAAY,EAAE,IAAI,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,QAAQ,GAAG,WAAW,GAAG,WAAW,CAAC;IAC7C,WAAW,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,cAAc;IAC3B,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,cAAc;IAC3B;;OAEG;IACH,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAEtB;;OAEG;IACH,aAAa,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IAElC;;OAEG;IACH,IAAI,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAE1B;;OAEG;IACH,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,cAAc,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAEhE;;OAEG;IACH,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAEvE;;OAEG;IACH,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAE3C;;OAEG;IACH,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAE1C;;OAEG;IACH,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAEhD;;OAEG;IACH,OAAO,CAAC,SAAS,EAAE,IAAI,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;CAC/C"}
1
+ {"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../../src/storage/adapter.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,WAAW,MAAM;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,YAAY,EAAE,IAAI,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,QAAQ,GAAG,WAAW,GAAG,WAAW,CAAC;IAC7C,WAAW,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,cAAc;IAC3B,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC3B;;OAEG;IACH,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAEtB;;OAEG;IACH,aAAa,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IAElC;;OAEG;IACH,IAAI,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAE1B;;OAEG;IACH,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,cAAc,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAEhE;;OAEG;IACH,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAEvE;;OAEG;IACH,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAE3C;;OAEG;IACH,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAE1C;;OAEG;IACH,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAEhD;;OAEG;IACH,OAAO,CAAC,SAAS,EAAE,IAAI,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;CAC/C"}
@@ -0,0 +1,13 @@
1
+ import type { Branch } from './adapter.js';
2
+ export interface BranchRegistryStore {
3
+ init(): Promise<void>;
4
+ isInitialized(): Promise<boolean>;
5
+ list(): Promise<Branch[]>;
6
+ register(branch: Omit<Branch, 'registeredAt'>): Promise<Branch>;
7
+ update(name: string, updates: Partial<Branch>): Promise<Branch | null>;
8
+ unregister(name: string): Promise<boolean>;
9
+ get(name: string): Promise<Branch | null>;
10
+ findByFiles(files: string[]): Promise<Branch[]>;
11
+ cleanup(olderThan: Date): Promise<string[]>;
12
+ }
13
+ //# sourceMappingURL=branch-registry-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"branch-registry-store.d.ts","sourceRoot":"","sources":["../../src/storage/branch-registry-store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAE3C,MAAM,WAAW,mBAAmB;IAChC,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACtB,aAAa,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IAClC,IAAI,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,cAAc,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAChE,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IACvE,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC3C,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC1C,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAChD,OAAO,CAAC,SAAS,EAAE,IAAI,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;CAC/C"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=branch-registry-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"branch-registry-store.js","sourceRoot":"","sources":["../../src/storage/branch-registry-store.ts"],"names":[],"mappings":""}
@@ -2,5 +2,9 @@
2
2
  * Storage factory - selects the right storage backend
3
3
  */
4
4
  import type { StorageAdapter } from './adapter.js';
5
+ import type { BranchRegistryStore } from './branch-registry-store.js';
6
+ import type { SupabaseRegistrySyncClient } from './supabase-registry-sync-client.js';
7
+ export declare function getBranchRegistryStore(basePath?: string): Promise<BranchRegistryStore>;
8
+ export declare function getSupabaseRegistrySyncClient(): Promise<SupabaseRegistrySyncClient | null>;
5
9
  export declare function getStorage(): Promise<StorageAdapter>;
6
10
  //# sourceMappingURL=factory.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../../src/storage/factory.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAGnD,wBAAsB,UAAU,IAAI,OAAO,CAAC,cAAc,CAAC,CAiB1D"}
1
+ {"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../../src/storage/factory.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AACtE,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,oCAAoC,CAAC;AAwBrF,wBAAsB,sBAAsB,CAAC,QAAQ,GAAE,MAAsB,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAE3G;AAED,wBAAsB,6BAA6B,IAAI,OAAO,CAAC,0BAA0B,GAAG,IAAI,CAAC,CAOhG;AAED,wBAAsB,UAAU,IAAI,OAAO,CAAC,cAAc,CAAC,CAQ1D"}
@@ -1,22 +1,38 @@
1
1
  /**
2
2
  * Storage factory - selects the right storage backend
3
3
  */
4
+ import { JsonBranchRegistryStore } from './json-branch-registry-store.js';
4
5
  import { LocalStorage } from './local.js';
5
6
  import { SupabaseStorage } from './supabase.js';
7
+ import { SupabaseRegistrySyncClientImpl } from './supabase-registry-sync-client-impl.js';
6
8
  import { loadConfig } from '../lib/config.js';
7
- export async function getStorage() {
9
+ async function getSupabaseConfig() {
8
10
  const config = await loadConfig();
9
- // Check environment variables first
10
11
  const supabaseUrl = process.env.SUPABASE_URL || config.storage.supabaseUrl;
11
12
  const supabaseKey = process.env.SUPABASE_KEY || config.storage.supabaseKey;
12
- // Use Supabase if credentials are available
13
- if (supabaseUrl && supabaseKey) {
14
- return new SupabaseStorage({
15
- url: supabaseUrl,
16
- key: supabaseKey,
17
- });
13
+ if (!supabaseUrl || !supabaseKey) {
14
+ return null;
15
+ }
16
+ return {
17
+ url: supabaseUrl,
18
+ key: supabaseKey,
19
+ };
20
+ }
21
+ export async function getBranchRegistryStore(basePath = process.cwd()) {
22
+ return new JsonBranchRegistryStore(basePath);
23
+ }
24
+ export async function getSupabaseRegistrySyncClient() {
25
+ const config = await getSupabaseConfig();
26
+ if (!config) {
27
+ return null;
28
+ }
29
+ return new SupabaseRegistrySyncClientImpl(config);
30
+ }
31
+ export async function getStorage() {
32
+ const supabaseConfig = await getSupabaseConfig();
33
+ if (supabaseConfig) {
34
+ return new SupabaseStorage(supabaseConfig);
18
35
  }
19
- // Default to local storage
20
36
  return new LocalStorage();
21
37
  }
22
38
  //# sourceMappingURL=factory.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"factory.js","sourceRoot":"","sources":["../../src/storage/factory.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAEhD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAE9C,MAAM,CAAC,KAAK,UAAU,UAAU;IAC5B,MAAM,MAAM,GAAG,MAAM,UAAU,EAAE,CAAC;IAElC,oCAAoC;IACpC,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC;IAC3E,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC;IAE3E,4CAA4C;IAC5C,IAAI,WAAW,IAAI,WAAW,EAAE,CAAC;QAC7B,OAAO,IAAI,eAAe,CAAC;YACvB,GAAG,EAAE,WAAW;YAChB,GAAG,EAAE,WAAW;SACnB,CAAC,CAAC;IACP,CAAC;IAED,2BAA2B;IAC3B,OAAO,IAAI,YAAY,EAAE,CAAC;AAC9B,CAAC"}
1
+ {"version":3,"file":"factory.js","sourceRoot":"","sources":["../../src/storage/factory.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,uBAAuB,EAAE,MAAM,iCAAiC,CAAC;AAC1E,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAIhD,OAAO,EAAE,8BAA8B,EAAE,MAAM,yCAAyC,CAAC;AACzF,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAO9C,KAAK,UAAU,iBAAiB;IAC5B,MAAM,MAAM,GAAG,MAAM,UAAU,EAAE,CAAC;IAClC,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC;IAC3E,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC;IAE3E,IAAI,CAAC,WAAW,IAAI,CAAC,WAAW,EAAE,CAAC;QAC/B,OAAO,IAAI,CAAC;IAChB,CAAC;IAED,OAAO;QACH,GAAG,EAAE,WAAW;QAChB,GAAG,EAAE,WAAW;KACnB,CAAC;AACN,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAAC,WAAmB,OAAO,CAAC,GAAG,EAAE;IACzE,OAAO,IAAI,uBAAuB,CAAC,QAAQ,CAAC,CAAC;AACjD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,6BAA6B;IAC/C,MAAM,MAAM,GAAG,MAAM,iBAAiB,EAAE,CAAC;IACzC,IAAI,CAAC,MAAM,EAAE,CAAC;QACV,OAAO,IAAI,CAAC;IAChB,CAAC;IAED,OAAO,IAAI,8BAA8B,CAAC,MAAM,CAAC,CAAC;AACtD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU;IAC5B,MAAM,cAAc,GAAG,MAAM,iBAAiB,EAAE,CAAC;IAEjD,IAAI,cAAc,EAAE,CAAC;QACjB,OAAO,IAAI,eAAe,CAAC,cAAc,CAAC,CAAC;IAC/C,CAAC;IAED,OAAO,IAAI,YAAY,EAAE,CAAC;AAC9B,CAAC"}
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Git Coordination Branch Message Storage Adapter (Tier 2)
3
+ *
4
+ * Stores messages in an orphan branch: spidersan/messages
5
+ * Structure:
6
+ * inbox/<agent-id>/<timestamp>_<from>_<subject-slug>.json
7
+ * outbox/<agent-id>/<timestamp>_<to>_<subject-slug>.json
8
+ *
9
+ * Near-real-time coordination on pull. Works across machines with git remote.
10
+ */
11
+ import type { MessageStorageAdapter, Message, SendMessageInput, InboxOptions, TierStatus } from './message-adapter.js';
12
+ export declare class GitMessagesAdapter implements MessageStorageAdapter {
13
+ private basePath;
14
+ private branchInitialized;
15
+ constructor(basePath?: string);
16
+ getTier(): number;
17
+ getTierName(): string;
18
+ isAvailable(): Promise<boolean>;
19
+ getStatus(): Promise<TierStatus>;
20
+ /**
21
+ * Check if the messages branch exists
22
+ */
23
+ private branchExists;
24
+ /**
25
+ * Initialize the orphan branch if it doesn't exist
26
+ */
27
+ private ensureBranch;
28
+ /**
29
+ * Generate filename for a message
30
+ */
31
+ private generateFilename;
32
+ /**
33
+ * Read a file from the messages branch without checkout
34
+ */
35
+ private readFromBranch;
36
+ /**
37
+ * List files in a directory on the messages branch
38
+ */
39
+ private listFromBranch;
40
+ /**
41
+ * Write a file to the messages branch
42
+ */
43
+ private writeToBranch;
44
+ /**
45
+ * Update a file on the messages branch (for marking read)
46
+ */
47
+ private updateOnBranch;
48
+ send(input: SendMessageInput): Promise<Message>;
49
+ inbox(agentId: string, options?: InboxOptions): Promise<Message[]>;
50
+ read(messageId: string): Promise<Message | null>;
51
+ markRead(messageId: string): Promise<boolean>;
52
+ }
53
+ //# sourceMappingURL=git-messages.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git-messages.d.ts","sourceRoot":"","sources":["../../src/storage/git-messages.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAKH,OAAO,KAAK,EACR,qBAAqB,EACrB,OAAO,EACP,gBAAgB,EAChB,YAAY,EACZ,UAAU,EACb,MAAM,sBAAsB,CAAC;AAM9B,qBAAa,kBAAmB,YAAW,qBAAqB;IAC5D,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,iBAAiB,CAAwB;gBAErC,QAAQ,GAAE,MAAsB;IAI5C,OAAO,IAAI,MAAM;IAIjB,WAAW,IAAI,MAAM;IAIf,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IAa/B,SAAS,IAAI,OAAO,CAAC,UAAU,CAAC;IAYtC;;OAEG;IACH,OAAO,CAAC,YAAY;IAYpB;;OAEG;YACW,YAAY;IAuE1B;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAOxB;;OAEG;IACH,OAAO,CAAC,cAAc;IAatB;;OAEG;IACH,OAAO,CAAC,cAAc;IAoBtB;;OAEG;YACW,aAAa;IAsF3B;;OAEG;YACW,cAAc;IAOtB,IAAI,CAAC,KAAK,EAAE,gBAAgB,GAAG,OAAO,CAAC,OAAO,CAAC;IAoC/C,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,YAAiB,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;IA8CtE,IAAI,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC;IAwChD,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;CAWtD"}