@ytspar/sweetlink 1.13.0 → 1.14.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 (78) hide show
  1. package/README.md +91 -12
  2. package/claude-skills/screenshot/SKILL.md +121 -20
  3. package/dist/cli/outputSchemas.d.ts +16 -0
  4. package/dist/cli/outputSchemas.d.ts.map +1 -1
  5. package/dist/cli/outputSchemas.js +33 -0
  6. package/dist/cli/outputSchemas.js.map +1 -1
  7. package/dist/cli/sweetlink-dev.js +0 -0
  8. package/dist/cli/sweetlink.js +347 -11
  9. package/dist/cli/sweetlink.js.map +1 -1
  10. package/dist/daemon/browser.d.ts +51 -0
  11. package/dist/daemon/browser.d.ts.map +1 -0
  12. package/dist/daemon/browser.js +153 -0
  13. package/dist/daemon/browser.js.map +1 -0
  14. package/dist/daemon/client.d.ts +32 -0
  15. package/dist/daemon/client.d.ts.map +1 -0
  16. package/dist/daemon/client.js +133 -0
  17. package/dist/daemon/client.js.map +1 -0
  18. package/dist/daemon/cursor.d.ts +15 -0
  19. package/dist/daemon/cursor.d.ts.map +1 -0
  20. package/dist/daemon/cursor.js +76 -0
  21. package/dist/daemon/cursor.js.map +1 -0
  22. package/dist/daemon/devices.d.ts +39 -0
  23. package/dist/daemon/devices.d.ts.map +1 -0
  24. package/dist/daemon/devices.js +101 -0
  25. package/dist/daemon/devices.js.map +1 -0
  26. package/dist/daemon/diff.d.ts +20 -0
  27. package/dist/daemon/diff.d.ts.map +1 -0
  28. package/dist/daemon/diff.js +181 -0
  29. package/dist/daemon/diff.js.map +1 -0
  30. package/dist/daemon/evidence.d.ts +29 -0
  31. package/dist/daemon/evidence.d.ts.map +1 -0
  32. package/dist/daemon/evidence.js +130 -0
  33. package/dist/daemon/evidence.js.map +1 -0
  34. package/dist/daemon/index.d.ts +10 -0
  35. package/dist/daemon/index.d.ts.map +1 -0
  36. package/dist/daemon/index.js +90 -0
  37. package/dist/daemon/index.js.map +1 -0
  38. package/dist/daemon/listeners.d.ts +55 -0
  39. package/dist/daemon/listeners.d.ts.map +1 -0
  40. package/dist/daemon/listeners.js +129 -0
  41. package/dist/daemon/listeners.js.map +1 -0
  42. package/dist/daemon/recording.d.ts +44 -0
  43. package/dist/daemon/recording.d.ts.map +1 -0
  44. package/dist/daemon/recording.js +133 -0
  45. package/dist/daemon/recording.js.map +1 -0
  46. package/dist/daemon/refs.d.ts +70 -0
  47. package/dist/daemon/refs.d.ts.map +1 -0
  48. package/dist/daemon/refs.js +185 -0
  49. package/dist/daemon/refs.js.map +1 -0
  50. package/dist/daemon/ringBuffer.d.ts +26 -0
  51. package/dist/daemon/ringBuffer.d.ts.map +1 -0
  52. package/dist/daemon/ringBuffer.js +54 -0
  53. package/dist/daemon/ringBuffer.js.map +1 -0
  54. package/dist/daemon/server.d.ts +23 -0
  55. package/dist/daemon/server.d.ts.map +1 -0
  56. package/dist/daemon/server.js +508 -0
  57. package/dist/daemon/server.js.map +1 -0
  58. package/dist/daemon/session.d.ts +41 -0
  59. package/dist/daemon/session.d.ts.map +1 -0
  60. package/dist/daemon/session.js +8 -0
  61. package/dist/daemon/session.js.map +1 -0
  62. package/dist/daemon/stateFile.d.ts +49 -0
  63. package/dist/daemon/stateFile.d.ts.map +1 -0
  64. package/dist/daemon/stateFile.js +162 -0
  65. package/dist/daemon/stateFile.js.map +1 -0
  66. package/dist/daemon/types.d.ts +72 -0
  67. package/dist/daemon/types.d.ts.map +1 -0
  68. package/dist/daemon/types.js +28 -0
  69. package/dist/daemon/types.js.map +1 -0
  70. package/dist/daemon/viewer.d.ts +33 -0
  71. package/dist/daemon/viewer.d.ts.map +1 -0
  72. package/dist/daemon/viewer.js +226 -0
  73. package/dist/daemon/viewer.js.map +1 -0
  74. package/dist/daemon/visualDiff.d.ts +34 -0
  75. package/dist/daemon/visualDiff.d.ts.map +1 -0
  76. package/dist/daemon/visualDiff.js +80 -0
  77. package/dist/daemon/visualDiff.js.map +1 -0
  78. package/package.json +20 -12
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Ref System
3
+ *
4
+ * Uses Playwright's ariaSnapshot API to assign sequential @e refs to interactive elements.
5
+ * No DOM mutation — works through Shadow DOM and CSP-restricted pages.
6
+ *
7
+ * ariaSnapshot() returns YAML-like lines:
8
+ * - heading "Hello" [level=1]
9
+ * - button "Click me"
10
+ * - textbox "Search"
11
+ * - link "Home"
12
+ */
13
+ type Page = import('playwright').Page;
14
+ type Locator = import('playwright').Locator;
15
+ export interface RefEntry {
16
+ ref: string;
17
+ role: string;
18
+ name: string;
19
+ attrs: Record<string, string>;
20
+ }
21
+ export interface RefMap {
22
+ entries: RefEntry[];
23
+ byRef: Map<string, RefEntry>;
24
+ rawSnapshot: string;
25
+ timestamp: number;
26
+ }
27
+ /**
28
+ * Parse ariaSnapshot YAML output into RefEntry objects.
29
+ *
30
+ * Format examples:
31
+ * - heading "Dashboard" [level=1]
32
+ * - button "Submit"
33
+ * - textbox "Email" [disabled]
34
+ * - link "Settings":
35
+ * - /url: /settings
36
+ */
37
+ export declare function parseAriaSnapshot(snapshot: string, options?: {
38
+ interactive?: boolean;
39
+ }): RefEntry[];
40
+ /**
41
+ * Build a ref map from the page's accessibility tree.
42
+ * Uses locator.ariaSnapshot() (Playwright 1.49+).
43
+ */
44
+ export declare function buildRefMap(page: Page, options?: {
45
+ interactive?: boolean;
46
+ }): Promise<RefMap>;
47
+ /**
48
+ * Resolve a @ref to a Playwright Locator.
49
+ * Uses getByRole with name matching for robustness.
50
+ */
51
+ export declare function resolveRef(page: Page, ref: string): Locator;
52
+ /**
53
+ * Check if a ref is still valid (element exists in DOM).
54
+ * ~5ms overhead vs 30s Playwright timeout on stale refs.
55
+ */
56
+ export declare function checkRefStale(page: Page, ref: string): Promise<boolean>;
57
+ /**
58
+ * Format a ref map as human-readable text.
59
+ */
60
+ export declare function formatRefMap(refMap: RefMap): string;
61
+ /** Store current snapshot as baseline for future diffs. */
62
+ export declare function setBaseline(): void;
63
+ /** Get the current baseline ref map. */
64
+ export declare function getBaseline(): RefMap | null;
65
+ /** Get the current ref map. */
66
+ export declare function getCurrentRefMap(): RefMap | null;
67
+ /** Clear both current and baseline ref maps. */
68
+ export declare function clearRefMaps(): void;
69
+ export {};
70
+ //# sourceMappingURL=refs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"refs.d.ts","sourceRoot":"","sources":["../../src/daemon/refs.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,KAAK,IAAI,GAAG,OAAO,YAAY,EAAE,IAAI,CAAC;AACtC,KAAK,OAAO,GAAG,OAAO,YAAY,EAAE,OAAO,CAAC;AAM5C,MAAM,WAAW,QAAQ;IACvB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC/B;AAED,MAAM,WAAW,MAAM;IACrB,OAAO,EAAE,QAAQ,EAAE,CAAC;IACpB,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;CACnB;AAkCD;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE;IAAE,WAAW,CAAC,EAAE,OAAO,CAAA;CAAE,GAClC,QAAQ,EAAE,CA0CZ;AAMD;;;GAGG;AACH,wBAAsB,WAAW,CAC/B,IAAI,EAAE,IAAI,EACV,OAAO,CAAC,EAAE;IAAE,WAAW,CAAC,EAAE,OAAO,CAAA;CAAE,GAClC,OAAO,CAAC,MAAM,CAAC,CAYjB;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAmB3D;AAED;;;GAGG;AACH,wBAAsB,aAAa,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAQ7E;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAqBnD;AAMD,2DAA2D;AAC3D,wBAAgB,WAAW,IAAI,IAAI,CAGlC;AAED,wCAAwC;AACxC,wBAAgB,WAAW,IAAI,MAAM,GAAG,IAAI,CAE3C;AAED,+BAA+B;AAC/B,wBAAgB,gBAAgB,IAAI,MAAM,GAAG,IAAI,CAEhD;AAED,gDAAgD;AAChD,wBAAgB,YAAY,IAAI,IAAI,CAGnC"}
@@ -0,0 +1,185 @@
1
+ /**
2
+ * Ref System
3
+ *
4
+ * Uses Playwright's ariaSnapshot API to assign sequential @e refs to interactive elements.
5
+ * No DOM mutation — works through Shadow DOM and CSP-restricted pages.
6
+ *
7
+ * ariaSnapshot() returns YAML-like lines:
8
+ * - heading "Hello" [level=1]
9
+ * - button "Click me"
10
+ * - textbox "Search"
11
+ * - link "Home"
12
+ */
13
+ // ============================================================================
14
+ // State
15
+ // ============================================================================
16
+ let currentRefMap = null;
17
+ let baselineRefMap = null;
18
+ // Roles that are interactive and worth assigning refs to
19
+ const INTERACTIVE_ROLES = new Set([
20
+ 'button',
21
+ 'link',
22
+ 'textbox',
23
+ 'checkbox',
24
+ 'radio',
25
+ 'combobox',
26
+ 'listbox',
27
+ 'menuitem',
28
+ 'menuitemcheckbox',
29
+ 'menuitemradio',
30
+ 'option',
31
+ 'searchbox',
32
+ 'slider',
33
+ 'spinbutton',
34
+ 'switch',
35
+ 'tab',
36
+ 'treeitem',
37
+ ]);
38
+ // ============================================================================
39
+ // Parsing
40
+ // ============================================================================
41
+ /**
42
+ * Parse ariaSnapshot YAML output into RefEntry objects.
43
+ *
44
+ * Format examples:
45
+ * - heading "Dashboard" [level=1]
46
+ * - button "Submit"
47
+ * - textbox "Email" [disabled]
48
+ * - link "Settings":
49
+ * - /url: /settings
50
+ */
51
+ export function parseAriaSnapshot(snapshot, options) {
52
+ const entries = [];
53
+ let counter = 1;
54
+ for (const line of snapshot.split('\n')) {
55
+ // Match lines like: - role "name" [attr=value, ...]
56
+ const match = line.match(/^\s*-\s+(\w+)\s+"([^"]*)"(?:\s+\[([^\]]*)\])?/);
57
+ if (!match)
58
+ continue;
59
+ const role = match[1];
60
+ const name = match[2];
61
+ const attrStr = match[3];
62
+ // Filter by role if interactive-only mode
63
+ if (options?.interactive && !INTERACTIVE_ROLES.has(role))
64
+ continue;
65
+ // Skip elements without names (they're structural, not actionable)
66
+ if (!name.trim())
67
+ continue;
68
+ const attrs = {};
69
+ if (attrStr) {
70
+ // Parse attrs like "level=1, disabled, checked=true"
71
+ for (const part of attrStr.split(',')) {
72
+ const trimmed = part.trim();
73
+ const eqIdx = trimmed.indexOf('=');
74
+ if (eqIdx !== -1) {
75
+ attrs[trimmed.slice(0, eqIdx)] = trimmed.slice(eqIdx + 1);
76
+ }
77
+ else {
78
+ attrs[trimmed] = 'true';
79
+ }
80
+ }
81
+ }
82
+ entries.push({
83
+ ref: `@e${counter++}`,
84
+ role,
85
+ name,
86
+ attrs,
87
+ });
88
+ }
89
+ return entries;
90
+ }
91
+ // ============================================================================
92
+ // Core Functions
93
+ // ============================================================================
94
+ /**
95
+ * Build a ref map from the page's accessibility tree.
96
+ * Uses locator.ariaSnapshot() (Playwright 1.49+).
97
+ */
98
+ export async function buildRefMap(page, options) {
99
+ const snapshot = await page.locator('body').ariaSnapshot();
100
+ const entries = parseAriaSnapshot(snapshot, options);
101
+ const byRef = new Map();
102
+ for (const entry of entries) {
103
+ byRef.set(entry.ref, entry);
104
+ }
105
+ const refMap = { entries, byRef, rawSnapshot: snapshot, timestamp: Date.now() };
106
+ currentRefMap = refMap;
107
+ return refMap;
108
+ }
109
+ /**
110
+ * Resolve a @ref to a Playwright Locator.
111
+ * Uses getByRole with name matching for robustness.
112
+ */
113
+ export function resolveRef(page, ref) {
114
+ if (!currentRefMap) {
115
+ throw new Error('No snapshot taken yet. Run `snapshot -i` first.');
116
+ }
117
+ const entry = currentRefMap.byRef.get(ref);
118
+ if (!entry) {
119
+ throw new Error(`Unknown ref ${ref}. Available refs: ${Array.from(currentRefMap.byRef.keys()).join(', ')}`);
120
+ }
121
+ // Build locator from role + name
122
+ const locator = page.getByRole(entry.role, {
123
+ name: entry.name,
124
+ exact: false,
125
+ });
126
+ return locator;
127
+ }
128
+ /**
129
+ * Check if a ref is still valid (element exists in DOM).
130
+ * ~5ms overhead vs 30s Playwright timeout on stale refs.
131
+ */
132
+ export async function checkRefStale(page, ref) {
133
+ try {
134
+ const locator = resolveRef(page, ref);
135
+ const count = await locator.count();
136
+ return count === 0;
137
+ }
138
+ catch {
139
+ return true;
140
+ }
141
+ }
142
+ /**
143
+ * Format a ref map as human-readable text.
144
+ */
145
+ export function formatRefMap(refMap) {
146
+ if (refMap.entries.length === 0) {
147
+ return '(no elements found)';
148
+ }
149
+ const lines = [];
150
+ for (const entry of refMap.entries) {
151
+ let line = ` ${entry.ref} [${entry.role}] "${entry.name}"`;
152
+ const attrParts = [];
153
+ for (const [key, value] of Object.entries(entry.attrs)) {
154
+ attrParts.push(value === 'true' ? key : `${key}=${value}`);
155
+ }
156
+ if (attrParts.length > 0) {
157
+ line += ` [${attrParts.join(', ')}]`;
158
+ }
159
+ lines.push(line);
160
+ }
161
+ return lines.join('\n');
162
+ }
163
+ // ============================================================================
164
+ // Baseline / Diff
165
+ // ============================================================================
166
+ /** Store current snapshot as baseline for future diffs. */
167
+ export function setBaseline() {
168
+ if (!currentRefMap)
169
+ throw new Error('No snapshot taken yet. Run `snapshot` first.');
170
+ baselineRefMap = currentRefMap;
171
+ }
172
+ /** Get the current baseline ref map. */
173
+ export function getBaseline() {
174
+ return baselineRefMap;
175
+ }
176
+ /** Get the current ref map. */
177
+ export function getCurrentRefMap() {
178
+ return currentRefMap;
179
+ }
180
+ /** Clear both current and baseline ref maps. */
181
+ export function clearRefMaps() {
182
+ currentRefMap = null;
183
+ baselineRefMap = null;
184
+ }
185
+ //# sourceMappingURL=refs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"refs.js","sourceRoot":"","sources":["../../src/daemon/refs.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Ring Buffer
3
+ *
4
+ * Fixed-capacity circular buffer with O(1) push.
5
+ * Used for always-on console/network/dialog event capture.
6
+ */
7
+ export declare class RingBuffer<T> {
8
+ private readonly capacity;
9
+ private buffer;
10
+ private head;
11
+ private count;
12
+ constructor(capacity?: number);
13
+ /** Add an item. Overwrites oldest if at capacity. */
14
+ push(item: T): void;
15
+ /** Get all items in insertion order (oldest first). */
16
+ toArray(): T[];
17
+ /** Get items matching a predicate. */
18
+ filter(predicate: (item: T) => boolean): T[];
19
+ /** Get the last N items. */
20
+ last(n: number): T[];
21
+ /** Clear all items. */
22
+ clear(): void;
23
+ /** Current number of items. */
24
+ get size(): number;
25
+ }
26
+ //# sourceMappingURL=ringBuffer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ringBuffer.d.ts","sourceRoot":"","sources":["../../src/daemon/ringBuffer.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,qBAAa,UAAU,CAAC,CAAC;IAKX,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAJrC,OAAO,CAAC,MAAM,CAAoB;IAClC,OAAO,CAAC,IAAI,CAAK;IACjB,OAAO,CAAC,KAAK,CAAK;gBAEW,QAAQ,GAAE,MAAe;IAItD,qDAAqD;IACrD,IAAI,CAAC,IAAI,EAAE,CAAC,GAAG,IAAI;IAMnB,uDAAuD;IACvD,OAAO,IAAI,CAAC,EAAE;IAUd,sCAAsC;IACtC,MAAM,CAAC,SAAS,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,OAAO,GAAG,CAAC,EAAE;IAI5C,4BAA4B;IAC5B,IAAI,CAAC,CAAC,EAAE,MAAM,GAAG,CAAC,EAAE;IAKpB,uBAAuB;IACvB,KAAK,IAAI,IAAI;IAMb,+BAA+B;IAC/B,IAAI,IAAI,IAAI,MAAM,CAEjB;CACF"}
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Ring Buffer
3
+ *
4
+ * Fixed-capacity circular buffer with O(1) push.
5
+ * Used for always-on console/network/dialog event capture.
6
+ */
7
+ export class RingBuffer {
8
+ capacity;
9
+ buffer;
10
+ head = 0;
11
+ count = 0;
12
+ constructor(capacity = 50_000) {
13
+ this.capacity = capacity;
14
+ this.buffer = new Array(capacity);
15
+ }
16
+ /** Add an item. Overwrites oldest if at capacity. */
17
+ push(item) {
18
+ this.buffer[this.head] = item;
19
+ this.head = (this.head + 1) % this.capacity;
20
+ if (this.count < this.capacity)
21
+ this.count++;
22
+ }
23
+ /** Get all items in insertion order (oldest first). */
24
+ toArray() {
25
+ if (this.count === 0)
26
+ return [];
27
+ const result = [];
28
+ const start = this.count < this.capacity ? 0 : this.head;
29
+ for (let i = 0; i < this.count; i++) {
30
+ result.push(this.buffer[(start + i) % this.capacity]);
31
+ }
32
+ return result;
33
+ }
34
+ /** Get items matching a predicate. */
35
+ filter(predicate) {
36
+ return this.toArray().filter(predicate);
37
+ }
38
+ /** Get the last N items. */
39
+ last(n) {
40
+ const all = this.toArray();
41
+ return all.slice(Math.max(0, all.length - n));
42
+ }
43
+ /** Clear all items. */
44
+ clear() {
45
+ this.buffer = new Array(this.capacity);
46
+ this.head = 0;
47
+ this.count = 0;
48
+ }
49
+ /** Current number of items. */
50
+ get size() {
51
+ return this.count;
52
+ }
53
+ }
54
+ //# sourceMappingURL=ringBuffer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ringBuffer.js","sourceRoot":"","sources":["../../src/daemon/ringBuffer.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,OAAO,UAAU;IAKQ;IAJrB,MAAM,CAAoB;IAC1B,IAAI,GAAG,CAAC,CAAC;IACT,KAAK,GAAG,CAAC,CAAC;IAElB,YAA6B,WAAmB,MAAM;QAAzB,aAAQ,GAAR,QAAQ,CAAiB;QACpD,IAAI,CAAC,MAAM,GAAG,IAAI,KAAK,CAAC,QAAQ,CAAC,CAAC;IACpC,CAAC;IAED,qDAAqD;IACrD,IAAI,CAAC,IAAO;QACV,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;QAC9B,IAAI,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC;QAC5C,IAAI,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,QAAQ;YAAE,IAAI,CAAC,KAAK,EAAE,CAAC;IAC/C,CAAC;IAED,uDAAuD;IACvD,OAAO;QACL,IAAI,IAAI,CAAC,KAAK,KAAK,CAAC;YAAE,OAAO,EAAE,CAAC;QAChC,MAAM,MAAM,GAAQ,EAAE,CAAC;QACvB,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;QACzD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC;YACpC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAE,CAAC,CAAC;QACzD,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,sCAAsC;IACtC,MAAM,CAAC,SAA+B;QACpC,OAAO,IAAI,CAAC,OAAO,EAAE,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IAC1C,CAAC;IAED,4BAA4B;IAC5B,IAAI,CAAC,CAAS;QACZ,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC;QAC3B,OAAO,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC;IAChD,CAAC;IAED,uBAAuB;IACvB,KAAK;QACH,IAAI,CAAC,MAAM,GAAG,IAAI,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACvC,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC;QACd,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC;IACjB,CAAC;IAED,+BAA+B;IAC/B,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,KAAK,CAAC;IACpB,CAAC;CACF"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Daemon HTTP Server
3
+ *
4
+ * Localhost-only HTTP server with bearer token auth.
5
+ * Routes POST requests to /api/{action} and dispatches to handlers.
6
+ * Manages idle timer for auto-shutdown.
7
+ */
8
+ export interface StartServerOptions {
9
+ port: number;
10
+ token: string;
11
+ url: string;
12
+ onShutdown: () => void;
13
+ }
14
+ /**
15
+ * Start the daemon HTTP server.
16
+ * Binds to 127.0.0.1 (localhost only) on the specified port.
17
+ */
18
+ export declare function startServer(options: StartServerOptions): Promise<void>;
19
+ /**
20
+ * Shut down the daemon: close browser, close HTTP server, call shutdown callback.
21
+ */
22
+ export declare function shutdown(): Promise<void>;
23
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/daemon/server.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AA2hBH,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,EAAE,MAAM,IAAI,CAAC;CACxB;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CAqEtE;AAED;;GAEG;AACH,wBAAsB,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CAgB9C"}