archer-wizard 0.1.1 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/dist/daemon/client.d.ts +4 -0
  2. package/dist/daemon/client.d.ts.map +1 -0
  3. package/dist/daemon/client.js +44 -0
  4. package/dist/daemon/client.js.map +1 -0
  5. package/dist/daemon/lifecycle.d.ts +9 -0
  6. package/dist/daemon/lifecycle.d.ts.map +1 -0
  7. package/dist/daemon/lifecycle.js +118 -0
  8. package/dist/daemon/lifecycle.js.map +1 -0
  9. package/dist/daemon/process.d.ts +2 -0
  10. package/dist/daemon/process.d.ts.map +1 -0
  11. package/dist/daemon/process.js +171 -0
  12. package/dist/daemon/process.js.map +1 -0
  13. package/dist/daemon/run.d.ts +2 -0
  14. package/dist/daemon/run.d.ts.map +1 -0
  15. package/dist/daemon/run.js +5 -0
  16. package/dist/daemon/run.js.map +1 -0
  17. package/dist/daemon/store.d.ts +9 -0
  18. package/dist/daemon/store.d.ts.map +1 -0
  19. package/dist/daemon/store.js +53 -0
  20. package/dist/daemon/store.js.map +1 -0
  21. package/dist/daemon/types.d.ts +47 -0
  22. package/dist/daemon/types.d.ts.map +1 -0
  23. package/dist/daemon/types.js +10 -0
  24. package/dist/daemon/types.js.map +1 -0
  25. package/dist/index.js +105 -21
  26. package/dist/index.js.map +1 -1
  27. package/dist/lib/ascii.d.ts.map +1 -1
  28. package/dist/lib/ascii.js +9 -41
  29. package/dist/lib/ascii.js.map +1 -1
  30. package/dist/tools/unwatch.d.ts +7 -0
  31. package/dist/tools/unwatch.d.ts.map +1 -0
  32. package/dist/tools/unwatch.js +20 -0
  33. package/dist/tools/unwatch.js.map +1 -0
  34. package/dist/tools/watch.d.ts +14 -34
  35. package/dist/tools/watch.d.ts.map +1 -1
  36. package/dist/tools/watch.js +36 -170
  37. package/dist/tools/watch.js.map +1 -1
  38. package/dist/tools/watches.d.ts +2 -0
  39. package/dist/tools/watches.d.ts.map +1 -0
  40. package/dist/tools/watches.js +33 -0
  41. package/dist/tools/watches.js.map +1 -0
  42. package/dist/wizard/index.d.ts.map +1 -1
  43. package/dist/wizard/index.js +57 -23
  44. package/dist/wizard/index.js.map +1 -1
  45. package/dist/wizard/scanner.d.ts.map +1 -1
  46. package/dist/wizard/scanner.js +0 -23
  47. package/dist/wizard/scanner.js.map +1 -1
  48. package/package.json +2 -1
  49. package/src/daemon/client.ts +50 -0
  50. package/src/daemon/lifecycle.ts +126 -0
  51. package/src/daemon/process.ts +207 -0
  52. package/src/daemon/run.ts +6 -0
  53. package/src/daemon/store.ts +60 -0
  54. package/src/daemon/types.ts +41 -0
  55. package/src/index.ts +111 -22
  56. package/src/lib/ascii.ts +9 -44
  57. package/src/tools/unwatch.ts +26 -0
  58. package/src/tools/watch.ts +46 -212
  59. package/src/tools/watches.ts +37 -0
  60. package/src/wizard/index.ts +54 -24
  61. package/src/wizard/scanner.ts +0 -23
@@ -0,0 +1,33 @@
1
+ import { sendCommand } from '../daemon/client.js';
2
+ // ─── Execute List Watches (via daemon IPC) ──────────────────
3
+ export async function executeListWatches() {
4
+ try {
5
+ const res = await sendCommand({ type: 'list_watches' });
6
+ if (!res.ok) {
7
+ return `❌ Failed to list watches: ${res.error}`;
8
+ }
9
+ if (res.type !== 'watch_list') {
10
+ return `❌ Unexpected response type: ${res.type}`;
11
+ }
12
+ if (res.watches.length === 0) {
13
+ return '📭 No active watches.';
14
+ }
15
+ const lines = [`📋 Active watches (${res.watches.length}):\n`];
16
+ for (const w of res.watches) {
17
+ lines.push(` 🔹 ${w.id}`);
18
+ lines.push(` table: ${w.table}`);
19
+ lines.push(` event: ${w.event}`);
20
+ if (w.filter)
21
+ lines.push(` filter: ${w.filter}`);
22
+ if (w.webhookUrl)
23
+ lines.push(` webhook: ${w.webhookUrl}`);
24
+ lines.push(` created: ${w.createdAt}`);
25
+ lines.push('');
26
+ }
27
+ return lines.join('\n');
28
+ }
29
+ catch (err) {
30
+ return `❌ Daemon error: ${err instanceof Error ? err.message : String(err)}\n\nIs the archer daemon running?`;
31
+ }
32
+ }
33
+ //# sourceMappingURL=watches.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"watches.js","sourceRoot":"","sources":["../../src/tools/watches.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAElD,+DAA+D;AAE/D,MAAM,CAAC,KAAK,UAAU,kBAAkB;IACtC,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,WAAW,CAAC,EAAE,IAAI,EAAE,cAAc,EAAE,CAAC,CAAC;QAExD,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,OAAO,6BAA6B,GAAG,CAAC,KAAK,EAAE,CAAC;QAClD,CAAC;QAED,IAAI,GAAG,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;YAC9B,OAAO,+BAA+B,GAAG,CAAC,IAAI,EAAE,CAAC;QACnD,CAAC;QAED,IAAI,GAAG,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC7B,OAAO,uBAAuB,CAAC;QACjC,CAAC;QAED,MAAM,KAAK,GAAG,CAAC,sBAAsB,GAAG,CAAC,OAAO,CAAC,MAAM,MAAM,CAAC,CAAC;QAE/D,KAAK,MAAM,CAAC,IAAI,GAAG,CAAC,OAAO,EAAE,CAAC;YAC5B,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YAC3B,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC;YACrC,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC;YACrC,IAAI,CAAC,CAAC,MAAM;gBAAE,KAAK,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC;YACrD,IAAI,CAAC,CAAC,UAAU;gBAAE,KAAK,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC;YAC9D,KAAK,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC;YAC3C,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACjB,CAAC;QAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,mBAAmB,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,mCAAmC,CAAC;IAChH,CAAC;AACH,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/wizard/index.ts"],"names":[],"mappings":"AAUA,wBAAsB,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC,CA0D/C"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/wizard/index.ts"],"names":[],"mappings":"AAcA,wBAAsB,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC,CAoF/C"}
@@ -1,10 +1,12 @@
1
1
  import * as clack from '@clack/prompts';
2
2
  import pc from 'picocolors';
3
- import { showAsciiArt, logAction, logSuccess, showSuccessBox } from '../lib/ascii.js';
3
+ import { showAsciiArt, showSuccessBox } from '../lib/ascii.js';
4
4
  import { scanProject, promptForMissing } from './scanner.js';
5
5
  import { detectAgents } from './detector.js';
6
6
  import { injectIntoAgents } from './injector.js';
7
7
  import { injectRules } from './rules.js';
8
+ // ─── Helpers ─────────────────────────────────────────────────
9
+ const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
8
10
  // ─── Wizard Sequence ────────────────────────────────────────
9
11
  export async function runWizard() {
10
12
  const cwd = process.cwd();
@@ -12,38 +14,70 @@ export async function runWizard() {
12
14
  showAsciiArt();
13
15
  // ─ Step 2: Start clack ─
14
16
  clack.intro(pc.bgGreen(pc.black(' archer setup ')));
15
- // ─ Step 3: Scanning
16
- logAction('scanning project for Supabase credentials...');
17
- console.log();
18
- // ─ Step 4-6: Scan env files ─
17
+ // ─ Step 3: Scan for Supabase credentials
18
+ const s = clack.spinner();
19
+ s.start('scanning project for supabase credentials');
20
+ await sleep(600);
19
21
  const scan = await scanProject(cwd);
20
- console.log();
21
- // Step 7: Framework detection ─
22
- if (scan.framework !== 'unknown') {
23
- logSuccess(`detected ${pc.bold(scan.framework)} project`);
22
+ await sleep(300);
23
+ // Build scan summary lines
24
+ const scanNotes = [];
25
+ if (scan.supabaseUrl)
26
+ scanNotes.push('SUPABASE_URL');
27
+ if (scan.serviceRoleKey)
28
+ scanNotes.push('SERVICE_ROLE_KEY');
29
+ if (scan.anonKey)
30
+ scanNotes.push('ANON_KEY');
31
+ if (scan.foundInFile)
32
+ scanNotes.push(`from ${scan.foundInFile}`);
33
+ if (scanNotes.length > 0) {
34
+ s.stop(`found ${pc.green(scanNotes.join(pc.dim(' · ')))}`);
35
+ }
36
+ else {
37
+ s.stop(pc.yellow('no credentials found — will prompt'));
24
38
  }
25
- if (scan.hasSupabaseInstalled) {
26
- logSuccess('found @supabase/supabase-js');
39
+ // Step 4: Framework detection ─
40
+ if (scan.framework !== 'unknown' || scan.hasSupabaseInstalled) {
41
+ const s2 = clack.spinner();
42
+ s2.start('detecting project framework');
43
+ await sleep(400);
44
+ const parts = [];
45
+ if (scan.framework !== 'unknown')
46
+ parts.push(pc.bold(scan.framework));
47
+ if (scan.hasSupabaseInstalled)
48
+ parts.push(pc.dim('@supabase/supabase-js'));
49
+ s2.stop(`detected ${parts.join(pc.dim(' + '))}`);
27
50
  }
28
- // ─ Step 8: Prompt for missing credentials ─
51
+ // ─ Step 5: Prompt for missing credentials ─
29
52
  const credentials = await promptForMissing(scan);
30
- console.log();
31
- // Step 9: Detect agents ─
32
- logAction('detecting AI agents...');
53
+ // ─ Step 6: Detect agents ─
54
+ const s3 = clack.spinner();
55
+ s3.start('scanning for AI agents');
56
+ await sleep(500);
33
57
  const agents = detectAgents();
34
- console.log();
35
- // Step 10-11: Inject into agents ─
58
+ await sleep(200);
59
+ if (agents.length > 0) {
60
+ const names = agents.map((a) => pc.bold(a.name)).join(pc.dim(', '));
61
+ s3.stop(`found ${pc.green(String(agents.length))} agent${agents.length !== 1 ? 's' : ''} — ${names}`);
62
+ }
63
+ else {
64
+ s3.stop(pc.yellow('no agents found'));
65
+ }
66
+ // ─ Step 7: Inject into agents ─
36
67
  const injectionResults = await injectIntoAgents(agents, credentials.supabaseUrl, credentials.serviceRoleKey);
37
- console.log();
38
- // ─ Step 12: Filter successful injections ─
68
+ // ─ Step 8: Filter successful injections ─
39
69
  const successfulAgents = agents.filter((a) => injectionResults.some((r) => r.agent === a.name && r.success));
40
- // ─ Step 13: Inject rules ─
70
+ // ─ Step 9: Inject rules ─
41
71
  if (successfulAgents.length > 0) {
42
- logAction('writing agent rules...');
72
+ const s4 = clack.spinner();
73
+ s4.start('writing agent rules');
74
+ await sleep(400);
43
75
  injectRules(successfulAgents);
44
- console.log();
76
+ await sleep(200);
77
+ s4.stop(`rules injected into ${pc.green(String(successfulAgents.length))} agent${successfulAgents.length !== 1 ? 's' : ''}`);
45
78
  }
46
- // ─ Step 14: Success ─
79
+ // ─ Step 10: Success ─
80
+ console.log();
47
81
  showSuccessBox(successfulAgents.length);
48
82
  clack.outro(pc.dim('docs → github.com/archer-mcp'));
49
83
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/wizard/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,gBAAgB,CAAC;AACxC,OAAO,EAAE,MAAM,YAAY,CAAC;AAC5B,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACtF,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAC7D,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAEzC,+DAA+D;AAE/D,MAAM,CAAC,KAAK,UAAU,SAAS;IAC7B,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IAE1B,wBAAwB;IACxB,YAAY,EAAE,CAAC;IAEf,0BAA0B;IAC1B,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC;IAEpD,uBAAuB;IACvB,SAAS,CAAC,8CAA8C,CAAC,CAAC;IAC1D,OAAO,CAAC,GAAG,EAAE,CAAC;IAEd,+BAA+B;IAC/B,MAAM,IAAI,GAAG,MAAM,WAAW,CAAC,GAAG,CAAC,CAAC;IACpC,OAAO,CAAC,GAAG,EAAE,CAAC;IAEd,kCAAkC;IAClC,IAAI,IAAI,CAAC,SAAS,KAAK,SAAS,EAAE,CAAC;QACjC,UAAU,CAAC,YAAY,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;IAC5D,CAAC;IACD,IAAI,IAAI,CAAC,oBAAoB,EAAE,CAAC;QAC9B,UAAU,CAAC,6BAA6B,CAAC,CAAC;IAC5C,CAAC;IAED,6CAA6C;IAC7C,MAAM,WAAW,GAAG,MAAM,gBAAgB,CAAC,IAAI,CAAC,CAAC;IACjD,OAAO,CAAC,GAAG,EAAE,CAAC;IAEd,4BAA4B;IAC5B,SAAS,CAAC,wBAAwB,CAAC,CAAC;IACpC,MAAM,MAAM,GAAG,YAAY,EAAE,CAAC;IAC9B,OAAO,CAAC,GAAG,EAAE,CAAC;IAEd,qCAAqC;IACrC,MAAM,gBAAgB,GAAG,MAAM,gBAAgB,CAC7C,MAAM,EACN,WAAW,CAAC,WAAW,EACvB,WAAW,CAAC,cAAc,CAC3B,CAAC;IACF,OAAO,CAAC,GAAG,EAAE,CAAC;IAEd,4CAA4C;IAC5C,MAAM,gBAAgB,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAC3C,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,OAAO,CAAC,CAC9D,CAAC;IAEF,4BAA4B;IAC5B,IAAI,gBAAgB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAChC,SAAS,CAAC,wBAAwB,CAAC,CAAC;QACpC,WAAW,CAAC,gBAAgB,CAAC,CAAC;QAC9B,OAAO,CAAC,GAAG,EAAE,CAAC;IAChB,CAAC;IAED,uBAAuB;IACvB,cAAc,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC;IAExC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,8BAA8B,CAAC,CAAC,CAAC;AACtD,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/wizard/index.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"scanner.d.ts","sourceRoot":"","sources":["../../src/wizard/scanner.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,UAAU,EAAa,MAAM,mBAAmB,CAAC;AAgL/D,wBAAsB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAwFlE;AAID,wBAAsB,gBAAgB,CACpC,IAAI,EAAE,UAAU,GACf,OAAO,CAAC;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,cAAc,EAAE,MAAM,CAAA;CAAE,CAAC,CAgD1D"}
1
+ {"version":3,"file":"scanner.d.ts","sourceRoot":"","sources":["../../src/wizard/scanner.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAa,MAAM,mBAAmB,CAAC;AAgL/D,wBAAsB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAkElE;AAID,wBAAsB,gBAAgB,CACpC,IAAI,EAAE,UAAU,GACf,OAAO,CAAC;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,cAAc,EAAE,MAAM,CAAA;CAAE,CAAC,CAgD1D"}
@@ -2,7 +2,6 @@ import fs from 'node:fs';
2
2
  import path from 'node:path';
3
3
  import * as clack from '@clack/prompts';
4
4
  import { z } from 'zod';
5
- import { logSuccess, logError, maskCredential } from '../lib/ascii.js';
6
5
  // Helper to search for keys in files
7
6
  function searchInFiles(cwd, patterns) {
8
7
  const results = new Map();
@@ -195,28 +194,6 @@ export async function scanProject(cwd) {
195
194
  const serviceRoleKey = findByAliases(mergedEnv, SERVICE_ROLE_KEY_ALIASES);
196
195
  const anonKey = findByAliases(mergedEnv, ANON_KEY_ALIASES);
197
196
  const { framework, hasSupabaseInstalled } = detectFramework(cwd);
198
- // Log found credentials
199
- if (supabaseUrl) {
200
- logSuccess(`SUPABASE_URL = ${maskCredential(supabaseUrl)}`);
201
- }
202
- else {
203
- logError('missing SUPABASE_URL');
204
- }
205
- if (serviceRoleKey) {
206
- logSuccess(`SUPABASE_SERVICE_ROLE_KEY = ${maskCredential(serviceRoleKey)}`);
207
- }
208
- else {
209
- logError('missing SUPABASE_SERVICE_ROLE_KEY');
210
- }
211
- if (anonKey) {
212
- logSuccess(`SUPABASE_ANON_KEY = ${maskCredential(anonKey)}`);
213
- }
214
- if (foundInFile) {
215
- logSuccess(`found credentials in ${foundInFile}`);
216
- }
217
- else if (codebaseResults.size > 0) {
218
- logSuccess(`found credentials in codebase`);
219
- }
220
197
  return {
221
198
  supabaseUrl,
222
199
  serviceRoleKey,
@@ -1 +1 @@
1
- {"version":3,"file":"scanner.js","sourceRoot":"","sources":["../../src/wizard/scanner.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,KAAK,KAAK,MAAM,gBAAgB,CAAC;AACxC,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAGvE,qCAAqC;AACrC,SAAS,aAAa,CAAC,GAAW,EAAE,QAAkB;IACpD,MAAM,OAAO,GAAG,IAAI,GAAG,EAAkB,CAAC;IAE1C,SAAS,OAAO,CAAC,GAAW;QAC1B,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,EAAE,CAAC,WAAW,CAAC,GAAG,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;YAE7D,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;gBAC5B,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;gBAE5C,wDAAwD;gBACxD,IAAI,KAAK,CAAC,WAAW,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,IAAI,KAAK,cAAc,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;oBACjH,OAAO,CAAC,QAAQ,CAAC,CAAC;gBACpB,CAAC;qBAAM,IAAI,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC;oBAC1B,IAAI,CAAC;wBACH,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;wBACnD,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;wBAElC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE;4BAC9B,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE;gCACzB,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;gCAClC,IAAI,KAAK,EAAE,CAAC;oCACV,0CAA0C;oCAC1C,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC;oCACnF,IAAI,KAAK,EAAE,CAAC;wCACV,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;wCAC1C,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;4CACtB,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;wCAC1B,CAAC;oCACH,CAAC;gCACH,CAAC;4BACH,CAAC,CAAC,CAAC;wBACL,CAAC,CAAC,CAAC;oBACL,CAAC;oBAAC,MAAM,CAAC;wBACP,wBAAwB;oBAC1B,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,8BAA8B;QAChC,CAAC;IACH,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,CAAC;IACb,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,+DAA+D;AAE/D,MAAM,SAAS,GAAG;IAChB,YAAY;IACZ,MAAM;IACN,kBAAkB;IAClB,iBAAiB;CACT,CAAC;AAEX,+DAA+D;AAE/D,MAAM,oBAAoB,GAAG;IAC3B,cAAc;IACd,0BAA0B;IAC1B,mBAAmB;CACX,CAAC;AAEX,MAAM,wBAAwB,GAAG;IAC/B,2BAA2B;IAC3B,sBAAsB;CACd,CAAC;AAEX,MAAM,gBAAgB,GAAG;IACvB,mBAAmB;IACnB,+BAA+B;IAC/B,wBAAwB;CAChB,CAAC;AAEX,+DAA+D;AAE/D,MAAM,iBAAiB,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,UAAU,EAAE;IAChE,OAAO,EAAE,uCAAuC;CACjD,CAAC,CAAC;AAEH,MAAM,oBAAoB,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE;IAC7C,OAAO,EAAE,sDAAsD;CAChE,CAAC,CAAC;AAEH,+DAA+D;AAE/D,SAAS,YAAY,CAAC,QAAgB;IACpC,MAAM,IAAI,GAAG,IAAI,GAAG,EAAkB,CAAC;IAEvC,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QACnD,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAElC,KAAK,MAAM,OAAO,IAAI,KAAK,EAAE,CAAC;YAC5B,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;YAC5B,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;gBAAE,SAAS;YAE5C,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;YAClC,IAAI,OAAO,KAAK,CAAC,CAAC;gBAAE,SAAS;YAE7B,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC;YAC1C,IAAI,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;YAE3C,2BAA2B;YAC3B,IACE,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;gBAC9C,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,EAC9C,CAAC;gBACD,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;YAC7B,CAAC;YAED,IAAI,GAAG,IAAI,KAAK,EAAE,CAAC;gBACjB,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;YACvB,CAAC;QACH,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,sDAAsD;IACxD,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED,+DAA+D;AAE/D,SAAS,aAAa,CACpB,MAA2B,EAC3B,OAA0B;IAE1B,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QAChC,IAAI,KAAK;YAAE,OAAO,KAAK,CAAC;IAC1B,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,+DAA+D;AAE/D,SAAS,eAAe,CAAC,GAAW;IAClC,IAAI,SAAS,GAAc,SAAS,CAAC;IACrC,IAAI,oBAAoB,GAAG,KAAK,CAAC;IAEjC,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,cAAc,CAAC,CAAC;QAC/C,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAClD,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAG7B,CAAC;QAEF,MAAM,OAAO,GAAG;YACd,GAAG,GAAG,CAAC,YAAY;YACnB,GAAG,GAAG,CAAC,eAAe;SACvB,CAAC;QAEF,IAAI,MAAM,IAAI,OAAO,EAAE,CAAC;YACtB,SAAS,GAAG,QAAQ,CAAC;QACvB,CAAC;aAAM,IAAI,MAAM,IAAI,OAAO,EAAE,CAAC;YAC7B,SAAS,GAAG,MAAM,CAAC;QACrB,CAAC;QAED,IAAI,uBAAuB,IAAI,OAAO,EAAE,CAAC;YACvC,oBAAoB,GAAG,IAAI,CAAC;QAC9B,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,qDAAqD;IACvD,CAAC;IAED,OAAO,EAAE,SAAS,EAAE,oBAAoB,EAAE,CAAC;AAC7C,CAAC;AAED,+DAA+D;AAE/D,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,GAAW;IAC3C,0CAA0C;IAC1C,MAAM,SAAS,GAAG,IAAI,GAAG,EAAkB,CAAC;IAC5C,IAAI,WAAW,GAAkB,IAAI,CAAC;IAEtC,wDAAwD;IACxD,KAAK,MAAM,IAAI,IAAI,CAAC,GAAG,SAAS,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC;QAC5C,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QACtC,MAAM,IAAI,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAC;QACpC,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,IAAI,EAAE,CAAC;YAChC,SAAS,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QAC5B,CAAC;QACD,IAAI,IAAI,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;YAClC,WAAW,GAAG,IAAI,CAAC;QACrB,CAAC;IACH,CAAC;IAED,2DAA2D;IAC3D,KAAK,MAAM,IAAI,IAAI,SAAS,EAAE,CAAC;QAC7B,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QACtC,MAAM,IAAI,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAC;QACpC,IAAI,IAAI,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;YAClB,WAAW,GAAG,IAAI,CAAC;YACnB,MAAM;QACR,CAAC;IACH,CAAC;IAED,uCAAuC;IACvC,MAAM,gBAAgB,GAAG;QACvB,oDAAoD;QACpD,gEAAgE;QAChE,yDAAyD;QACzD,iEAAiE;QACjE,4DAA4D;QAC5D,yDAAyD;KAC1D,CAAC;IAEF,MAAM,eAAe,GAAG,aAAa,CAAC,GAAG,EAAE,gBAAgB,CAAC,CAAC;IAE7D,qDAAqD;IACrD,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,eAAe,EAAE,CAAC;QAC3C,MAAM,QAAQ,GAAG,GAAG,CAAC,WAAW,EAAE,CAAC;QACnC,IAAI,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,cAAc,CAAC,EAAE,CAAC;YAC/D,SAAS,CAAC,GAAG,CAAC,cAAc,EAAE,KAAK,CAAC,CAAC;QACvC,CAAC;aAAM,IAAI,QAAQ,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,2BAA2B,CAAC,EAAE,CAAC;YACvF,SAAS,CAAC,GAAG,CAAC,2BAA2B,EAAE,KAAK,CAAC,CAAC;QACpD,CAAC;aAAM,IAAI,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,mBAAmB,CAAC,EAAE,CAAC;YAC5E,SAAS,CAAC,GAAG,CAAC,mBAAmB,EAAE,KAAK,CAAC,CAAC;QAC5C,CAAC;IACH,CAAC;IAED,MAAM,WAAW,GAAG,aAAa,CAAC,SAAS,EAAE,oBAAoB,CAAC,CAAC;IACnE,MAAM,cAAc,GAAG,aAAa,CAAC,SAAS,EAAE,wBAAwB,CAAC,CAAC;IAC1E,MAAM,OAAO,GAAG,aAAa,CAAC,SAAS,EAAE,gBAAgB,CAAC,CAAC;IAE3D,MAAM,EAAE,SAAS,EAAE,oBAAoB,EAAE,GAAG,eAAe,CAAC,GAAG,CAAC,CAAC;IAEjE,wBAAwB;IACxB,IAAI,WAAW,EAAE,CAAC;QAChB,UAAU,CAAC,kBAAkB,cAAc,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;IAC9D,CAAC;SAAM,CAAC;QACN,QAAQ,CAAC,sBAAsB,CAAC,CAAC;IACnC,CAAC;IAED,IAAI,cAAc,EAAE,CAAC;QACnB,UAAU,CAAC,+BAA+B,cAAc,CAAC,cAAc,CAAC,EAAE,CAAC,CAAC;IAC9E,CAAC;SAAM,CAAC;QACN,QAAQ,CAAC,mCAAmC,CAAC,CAAC;IAChD,CAAC;IAED,IAAI,OAAO,EAAE,CAAC;QACZ,UAAU,CAAC,uBAAuB,cAAc,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAC/D,CAAC;IAED,IAAI,WAAW,EAAE,CAAC;QAChB,UAAU,CAAC,wBAAwB,WAAW,EAAE,CAAC,CAAC;IACpD,CAAC;SAAM,IAAI,eAAe,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;QACpC,UAAU,CAAC,+BAA+B,CAAC,CAAC;IAC9C,CAAC;IAED,OAAO;QACL,WAAW;QACX,cAAc;QACd,OAAO;QACP,SAAS;QACT,oBAAoB;QACpB,WAAW;KACZ,CAAC;AACJ,CAAC;AAED,+DAA+D;AAE/D,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,IAAgB;IAEhB,IAAI,WAAW,GAAG,IAAI,CAAC,WAAW,CAAC;IACnC,IAAI,cAAc,GAAG,IAAI,CAAC,cAAc,CAAC;IAEzC,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,MAAM,KAAK,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC;YAC7B,OAAO,EAAE,yBAAyB;YAClC,WAAW,EAAE,kCAAkC;YAC/C,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE;gBAClB,MAAM,MAAM,GAAG,iBAAiB,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;gBAClD,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;oBACpB,OAAO,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,OAAO,IAAI,aAAa,CAAC;gBAC1D,CAAC;gBACD,OAAO,SAAS,CAAC;YACnB,CAAC;SACF,CAAC,CAAC;QAEH,IAAI,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;YAC1B,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,WAAW,GAAG,KAAe,CAAC;IAChC,CAAC;IAED,IAAI,CAAC,cAAc,EAAE,CAAC;QACpB,MAAM,KAAK,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC;YAC7B,OAAO,EAAE,sCAAsC;YAC/C,WAAW,EAAE,yCAAyC;YACtD,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE;gBAClB,MAAM,MAAM,GAAG,oBAAoB,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;gBACrD,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;oBACpB,OAAO,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,OAAO,IAAI,aAAa,CAAC;gBAC1D,CAAC;gBACD,OAAO,SAAS,CAAC;YACnB,CAAC;SACF,CAAC,CAAC;QAEH,IAAI,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;YAC1B,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,cAAc,GAAG,KAAe,CAAC;IACnC,CAAC;IAED,OAAO;QACL,WAAW,EAAE,iBAAiB,CAAC,KAAK,CAAC,WAAW,CAAC;QACjD,cAAc,EAAE,oBAAoB,CAAC,KAAK,CAAC,cAAc,CAAC;KAC3D,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"scanner.js","sourceRoot":"","sources":["../../src/wizard/scanner.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "archer-wizard",
3
- "version": "0.1.1",
3
+ "version": "0.2.1",
4
4
  "description": "event intelligence layer for AI agents",
5
5
  "type": "module",
6
6
  "bin": {
@@ -11,6 +11,7 @@
11
11
  "build": "tsc",
12
12
  "dev": "tsx src/index.ts",
13
13
  "dev:mcp": "tsx src/index.ts --mcp",
14
+ "dev:daemon": "tsx src/index.ts --daemon",
14
15
  "prepublishOnly": "npm run build"
15
16
  },
16
17
  "dependencies": {
@@ -0,0 +1,50 @@
1
+ import net from 'node:net';
2
+ import { DAEMON_PORT, DAEMON_HOST } from './types.js';
3
+ import type { IpcRequest, IpcResponse } from './types.js';
4
+
5
+ // ─── Send Command to Daemon ─────────────────────────────────
6
+
7
+ export function sendCommand(req: IpcRequest): Promise<IpcResponse> {
8
+ return new Promise((resolve, reject) => {
9
+ const socket = net.createConnection({ host: DAEMON_HOST, port: DAEMON_PORT }, () => {
10
+ socket.write(JSON.stringify(req) + '\n');
11
+ });
12
+
13
+ let buffer = '';
14
+
15
+ socket.on('data', (data) => {
16
+ buffer += data.toString();
17
+ const newlineIdx = buffer.indexOf('\n');
18
+ if (newlineIdx !== -1) {
19
+ const line = buffer.slice(0, newlineIdx).trim();
20
+ socket.end();
21
+ try {
22
+ resolve(JSON.parse(line) as IpcResponse);
23
+ } catch (err) {
24
+ reject(new Error(`invalid daemon response: ${line}`));
25
+ }
26
+ }
27
+ });
28
+
29
+ socket.on('error', (err) => {
30
+ reject(new Error(`daemon connection failed: ${err.message}`));
31
+ });
32
+
33
+ // Timeout after 5 seconds
34
+ socket.setTimeout(5_000, () => {
35
+ socket.destroy();
36
+ reject(new Error('daemon response timeout'));
37
+ });
38
+ });
39
+ }
40
+
41
+ // ─── Check if Daemon is Running ─────────────────────────────
42
+
43
+ export async function isDaemonRunning(): Promise<boolean> {
44
+ try {
45
+ const res = await sendCommand({ type: 'ping' });
46
+ return res.ok && res.type === 'pong';
47
+ } catch {
48
+ return false;
49
+ }
50
+ }
@@ -0,0 +1,126 @@
1
+ import { spawn } from 'node:child_process';
2
+ import fs from 'node:fs';
3
+ import path from 'node:path';
4
+ import { fileURLToPath } from 'node:url';
5
+ import { PID_FILE, ARCHER_DIR, LOG_FILE } from './types.js';
6
+ import { isDaemonRunning } from './client.js';
7
+
8
+ // ─── Start Daemon ───────────────────────────────────────────
9
+
10
+ export async function startDaemon(): Promise<{ pid: number; alreadyRunning: boolean }> {
11
+ // Check if already running
12
+ if (await isDaemonRunning()) {
13
+ const pid = readPid();
14
+ return { pid: pid ?? 0, alreadyRunning: true };
15
+ }
16
+
17
+ // Ensure directory exists
18
+ if (!fs.existsSync(ARCHER_DIR)) {
19
+ fs.mkdirSync(ARCHER_DIR, { recursive: true });
20
+ }
21
+
22
+ // Resolve the daemon entry script
23
+ // In compiled mode this is dist/daemon/process.js
24
+ // In dev mode with tsx this is src/daemon/process.ts
25
+ const thisFile = fileURLToPath(import.meta.url);
26
+ const thisDir = path.dirname(thisFile);
27
+
28
+ // Look for the daemon runner script
29
+ const daemonRunner = path.join(thisDir, 'run.js');
30
+ const daemonRunnerTs = path.join(thisDir, 'run.ts');
31
+
32
+ let cmd: string;
33
+ let args: string[];
34
+
35
+ if (fs.existsSync(daemonRunner)) {
36
+ // Compiled mode
37
+ cmd = process.execPath; // node
38
+ args = [daemonRunner];
39
+ } else if (fs.existsSync(daemonRunnerTs)) {
40
+ // Dev mode — use tsx
41
+ cmd = 'npx';
42
+ args = ['tsx', daemonRunnerTs];
43
+ } else {
44
+ // Fallback: assume we're in dist/ and run process.js directly
45
+ const processJs = path.join(thisDir, 'process.js');
46
+ cmd = process.execPath;
47
+ args = [processJs, '--run-daemon'];
48
+ }
49
+
50
+ // Open log file for daemon output
51
+ const logFd = fs.openSync(LOG_FILE, 'a');
52
+
53
+ const child = spawn(cmd, args, {
54
+ detached: true,
55
+ stdio: ['ignore', logFd, logFd],
56
+ env: { ...process.env },
57
+ });
58
+
59
+ child.unref();
60
+ fs.closeSync(logFd);
61
+
62
+ const pid = child.pid ?? 0;
63
+
64
+ // Wait briefly for daemon to start, then verify
65
+ await sleep(500);
66
+
67
+ const running = await isDaemonRunning();
68
+ if (!running) {
69
+ // Give it another moment
70
+ await sleep(1000);
71
+ }
72
+
73
+ return { pid, alreadyRunning: false };
74
+ }
75
+
76
+ // ─── Stop Daemon ────────────────────────────────────────────
77
+
78
+ export async function stopDaemon(): Promise<boolean> {
79
+ const pid = readPid();
80
+ if (pid === null) return false;
81
+
82
+ try {
83
+ process.kill(pid, 'SIGTERM');
84
+ // Wait for it to die
85
+ await sleep(500);
86
+ return true;
87
+ } catch {
88
+ // Process already dead — clean up PID file
89
+ try { fs.unlinkSync(PID_FILE); } catch {}
90
+ return false;
91
+ }
92
+ }
93
+
94
+ // ─── Ensure Daemon is Running ───────────────────────────────
95
+
96
+ export async function ensureDaemon(): Promise<{ pid: number }> {
97
+ const result = await startDaemon();
98
+ return { pid: result.pid };
99
+ }
100
+
101
+ // ─── Helpers ────────────────────────────────────────────────
102
+
103
+ function readPid(): number | null {
104
+ try {
105
+ if (!fs.existsSync(PID_FILE)) return null;
106
+ const raw = fs.readFileSync(PID_FILE, 'utf-8').trim();
107
+ const pid = parseInt(raw, 10);
108
+ if (isNaN(pid)) return null;
109
+
110
+ // Check if process is alive
111
+ try {
112
+ process.kill(pid, 0); // Signal 0 = existence check
113
+ return pid;
114
+ } catch {
115
+ // Process is dead — clean up stale PID
116
+ try { fs.unlinkSync(PID_FILE); } catch {}
117
+ return null;
118
+ }
119
+ } catch {
120
+ return null;
121
+ }
122
+ }
123
+
124
+ function sleep(ms: number): Promise<void> {
125
+ return new Promise((resolve) => setTimeout(resolve, ms));
126
+ }
@@ -0,0 +1,207 @@
1
+ import net from 'node:net';
2
+ import { createClient, type RealtimeChannel, type SupabaseClient } from '@supabase/supabase-js';
3
+ import { DAEMON_PORT, DAEMON_HOST, PID_FILE, ARCHER_DIR, LOG_FILE } from './types.js';
4
+ import type { IpcRequest, IpcResponse, WatchConfig } from './types.js';
5
+ import { loadWatches, addWatch, removeWatch } from './store.js';
6
+ import fs from 'node:fs';
7
+
8
+ // ─── Simple webhook delivery for daemon context ─────────────
9
+
10
+ async function deliverWebhook(url: string, payload: unknown): Promise<void> {
11
+ const res = await fetch(url, {
12
+ method: 'POST',
13
+ headers: {
14
+ 'Content-Type': 'application/json',
15
+ 'User-Agent': 'Archer/0.2.0',
16
+ },
17
+ body: JSON.stringify(payload),
18
+ });
19
+ if (!res.ok) {
20
+ throw new Error(`webhook ${res.status} ${res.statusText}`);
21
+ }
22
+ }
23
+
24
+ // ─── Active Channel Registry ────────────────────────────────
25
+
26
+ const channels = new Map<string, { client: SupabaseClient; channel: RealtimeChannel }>();
27
+
28
+ // ─── Subscribe to a Watch ───────────────────────────────────
29
+
30
+ function subscribe(watch: WatchConfig): void {
31
+ // Skip if already subscribed
32
+ if (channels.has(watch.id)) return;
33
+
34
+ const client = createClient(watch.supabaseUrl, watch.supabaseKey);
35
+
36
+ const channelName = `daemon-${watch.table}-${watch.id}`;
37
+ const channel = client
38
+ .channel(channelName)
39
+ .on(
40
+ 'postgres_changes',
41
+ {
42
+ event: watch.event,
43
+ schema: 'public',
44
+ table: watch.table,
45
+ ...(watch.filter ? { filter: watch.filter } : {}),
46
+ },
47
+ async (payload) => {
48
+ log(`[event] ${watch.table} ${payload.eventType} → watch ${watch.id}`);
49
+
50
+ if (watch.webhookUrl) {
51
+ try {
52
+ await deliverWebhook(watch.webhookUrl, payload);
53
+ log(`[webhook] delivered to ${watch.webhookUrl}`);
54
+ } catch (err) {
55
+ log(`[webhook] failed: ${err instanceof Error ? err.message : String(err)}`);
56
+ }
57
+ }
58
+ },
59
+ )
60
+ .subscribe((status) => {
61
+ log(`[channel] ${channelName} → ${status}`);
62
+ });
63
+
64
+ channels.set(watch.id, { client, channel });
65
+ }
66
+
67
+ // ─── Unsubscribe from a Watch ───────────────────────────────
68
+
69
+ async function unsubscribe(watchId: string): Promise<void> {
70
+ const entry = channels.get(watchId);
71
+ if (!entry) return;
72
+
73
+ await entry.client.removeChannel(entry.channel);
74
+ channels.delete(watchId);
75
+ }
76
+
77
+ // ─── Handle IPC Command ─────────────────────────────────────
78
+
79
+ async function handleCommand(req: IpcRequest): Promise<IpcResponse> {
80
+ switch (req.type) {
81
+ case 'add_watch': {
82
+ const watches = addWatch(req.watch);
83
+ subscribe(req.watch);
84
+ return { ok: true, type: 'watch_added', watchId: req.watch.id };
85
+ }
86
+
87
+ case 'remove_watch': {
88
+ const { watches, removed } = removeWatch(req.watchId);
89
+ if (!removed) {
90
+ return { ok: false, error: `watch ${req.watchId} not found` };
91
+ }
92
+ await unsubscribe(req.watchId);
93
+ return { ok: true, type: 'watch_removed', watchId: req.watchId };
94
+ }
95
+
96
+ case 'list_watches': {
97
+ const watches = loadWatches();
98
+ return { ok: true, type: 'watch_list', watches };
99
+ }
100
+
101
+ case 'ping': {
102
+ return { ok: true, type: 'pong' };
103
+ }
104
+
105
+ default:
106
+ return { ok: false, error: 'unknown command' };
107
+ }
108
+ }
109
+
110
+ // ─── Logging ────────────────────────────────────────────────
111
+
112
+ function log(message: string): void {
113
+ const ts = new Date().toISOString();
114
+ const line = `[${ts}] ${message}\n`;
115
+ try {
116
+ fs.appendFileSync(LOG_FILE, line);
117
+ } catch {
118
+ // If we can't write to log, just continue
119
+ }
120
+ }
121
+
122
+ // ─── Main: Start TCP Server ─────────────────────────────────
123
+
124
+ export function startDaemonProcess(): void {
125
+ // Ensure directory exists
126
+ if (!fs.existsSync(ARCHER_DIR)) {
127
+ fs.mkdirSync(ARCHER_DIR, { recursive: true });
128
+ }
129
+
130
+ // Write PID file
131
+ fs.writeFileSync(PID_FILE, String(process.pid), 'utf-8');
132
+
133
+ log('daemon starting');
134
+
135
+ // Re-subscribe all persisted watches
136
+ const watches = loadWatches();
137
+ for (const watch of watches) {
138
+ subscribe(watch);
139
+ log(`[restore] re-subscribed watch ${watch.id} on ${watch.table}`);
140
+ }
141
+ log(`restored ${watches.length} watch(es)`);
142
+
143
+ // Create TCP server
144
+ const server = net.createServer((socket) => {
145
+ let buffer = '';
146
+
147
+ socket.on('data', async (data) => {
148
+ buffer += data.toString();
149
+
150
+ // Process complete JSON lines
151
+ let newlineIdx: number;
152
+ while ((newlineIdx = buffer.indexOf('\n')) !== -1) {
153
+ const line = buffer.slice(0, newlineIdx).trim();
154
+ buffer = buffer.slice(newlineIdx + 1);
155
+
156
+ if (!line) continue;
157
+
158
+ try {
159
+ const req = JSON.parse(line) as IpcRequest;
160
+ const res = await handleCommand(req);
161
+ socket.write(JSON.stringify(res) + '\n');
162
+ } catch (err) {
163
+ const errRes: IpcResponse = {
164
+ ok: false,
165
+ error: `parse error: ${err instanceof Error ? err.message : String(err)}`,
166
+ };
167
+ socket.write(JSON.stringify(errRes) + '\n');
168
+ }
169
+ }
170
+ });
171
+
172
+ socket.on('error', (err) => {
173
+ log(`[socket] error: ${err.message}`);
174
+ });
175
+ });
176
+
177
+ server.listen(DAEMON_PORT, DAEMON_HOST, () => {
178
+ log(`daemon listening on ${DAEMON_HOST}:${DAEMON_PORT} (pid ${process.pid})`);
179
+ });
180
+
181
+ server.on('error', (err) => {
182
+ log(`[server] error: ${err.message}`);
183
+ process.exit(1);
184
+ });
185
+
186
+ // Clean shutdown
187
+ const shutdown = () => {
188
+ log('daemon shutting down');
189
+ server.close();
190
+
191
+ // Unsubscribe all channels
192
+ for (const [id, entry] of channels) {
193
+ entry.client.removeChannel(entry.channel).catch(() => {});
194
+ }
195
+ channels.clear();
196
+
197
+ // Remove PID file
198
+ try {
199
+ fs.unlinkSync(PID_FILE);
200
+ } catch {}
201
+
202
+ process.exit(0);
203
+ };
204
+
205
+ process.on('SIGTERM', shutdown);
206
+ process.on('SIGINT', shutdown);
207
+ }
@@ -0,0 +1,6 @@
1
+ // Daemon runner — this file is the entry point for the detached daemon process.
2
+ // It gets spawned by lifecycle.ts and runs startDaemonProcess().
3
+
4
+ import { startDaemonProcess } from './process.js';
5
+
6
+ startDaemonProcess();