@vibecook/ghosttea-electron 0.2.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 (59) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +41 -0
  3. package/dist/automation.d.ts +2 -0
  4. package/dist/automation.d.ts.map +1 -0
  5. package/dist/automation.js +2 -0
  6. package/dist/automation.js.map +1 -0
  7. package/dist/backend.d.ts +28 -0
  8. package/dist/backend.d.ts.map +1 -0
  9. package/dist/backend.js +63 -0
  10. package/dist/backend.js.map +1 -0
  11. package/dist/bridge-entry.d.ts +2 -0
  12. package/dist/bridge-entry.d.ts.map +1 -0
  13. package/dist/bridge-entry.js +154 -0
  14. package/dist/bridge-entry.js.map +1 -0
  15. package/dist/bridge-socket.d.ts +4 -0
  16. package/dist/bridge-socket.d.ts.map +1 -0
  17. package/dist/bridge-socket.js +91 -0
  18. package/dist/bridge-socket.js.map +1 -0
  19. package/dist/bridge.d.ts +18 -0
  20. package/dist/bridge.d.ts.map +1 -0
  21. package/dist/bridge.js +59 -0
  22. package/dist/bridge.js.map +1 -0
  23. package/dist/clipboard.d.ts +18 -0
  24. package/dist/clipboard.d.ts.map +1 -0
  25. package/dist/clipboard.js +65 -0
  26. package/dist/clipboard.js.map +1 -0
  27. package/dist/deadline.d.ts +2 -0
  28. package/dist/deadline.d.ts.map +1 -0
  29. package/dist/deadline.js +16 -0
  30. package/dist/deadline.js.map +1 -0
  31. package/dist/edit-commands.d.ts +45 -0
  32. package/dist/edit-commands.d.ts.map +1 -0
  33. package/dist/edit-commands.js +42 -0
  34. package/dist/edit-commands.js.map +1 -0
  35. package/dist/frame-flow.d.ts +18 -0
  36. package/dist/frame-flow.d.ts.map +1 -0
  37. package/dist/frame-flow.js +52 -0
  38. package/dist/frame-flow.js.map +1 -0
  39. package/dist/index.d.ts +9 -0
  40. package/dist/index.d.ts.map +1 -0
  41. package/dist/index.js +8 -0
  42. package/dist/index.js.map +1 -0
  43. package/dist/main.d.ts +9 -0
  44. package/dist/main.d.ts.map +1 -0
  45. package/dist/main.js +8 -0
  46. package/dist/main.js.map +1 -0
  47. package/dist/preload.d.ts +4 -0
  48. package/dist/preload.d.ts.map +1 -0
  49. package/dist/preload.js +9 -0
  50. package/dist/preload.js.map +1 -0
  51. package/dist/supervisor.d.ts +30 -0
  52. package/dist/supervisor.d.ts.map +1 -0
  53. package/dist/supervisor.js +160 -0
  54. package/dist/supervisor.js.map +1 -0
  55. package/dist/types.d.ts +13 -0
  56. package/dist/types.d.ts.map +1 -0
  57. package/dist/types.js +12 -0
  58. package/dist/types.js.map +1 -0
  59. package/package.json +78 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clipboard.js","sourceRoot":"","sources":["../src/clipboard.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare function allSettledWithin(tasks: Iterable<PromiseLike<unknown>>, timeoutMs: number): Promise<boolean>;
2
+ //# sourceMappingURL=deadline.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deadline.d.ts","sourceRoot":"","sources":["../src/deadline.ts"],"names":[],"mappings":"AAAA,wBAAsB,gBAAgB,CAAC,KAAK,EAAE,QAAQ,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAYjH"}
@@ -0,0 +1,16 @@
1
+ export async function allSettledWithin(tasks, timeoutMs) {
2
+ let timeout;
3
+ try {
4
+ return await Promise.race([
5
+ Promise.allSettled([...tasks]).then(() => true),
6
+ new Promise((resolve) => {
7
+ timeout = setTimeout(() => resolve(false), timeoutMs);
8
+ }),
9
+ ]);
10
+ }
11
+ finally {
12
+ if (timeout)
13
+ clearTimeout(timeout);
14
+ }
15
+ }
16
+ //# sourceMappingURL=deadline.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deadline.js","sourceRoot":"","sources":["../src/deadline.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,KAAqC,EAAE,SAAiB;IAC7F,IAAI,OAAkD,CAAC;IACvD,IAAI,CAAC;QACH,OAAO,MAAM,OAAO,CAAC,IAAI,CAAC;YACxB,OAAO,CAAC,UAAU,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC;YAC/C,IAAI,OAAO,CAAU,CAAC,OAAO,EAAE,EAAE;gBAC/B,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,SAAS,CAAC,CAAC;YACxD,CAAC,CAAC;SACH,CAAC,CAAC;IACL,CAAC;YAAS,CAAC;QACT,IAAI,OAAO;YAAE,YAAY,CAAC,OAAO,CAAC,CAAC;IACrC,CAAC;AACH,CAAC"}
@@ -0,0 +1,45 @@
1
+ import type { WebContents } from "electron";
2
+ export type GhostteaEditCommand = "copy" | "paste" | "select-all";
3
+ /**
4
+ * Ghostty actions that Chromium would otherwise steal as DOM edit roles.
5
+ * Full binding table lives in `@vibecook/ghosttea-react` (`bindings/`); this
6
+ * package only claims the subset that must run in the main process.
7
+ *
8
+ * Paste is deliberately omitted: the focused terminal textarea needs the
9
+ * renderer keydown/paste path to inject clipboard text into the PTY.
10
+ */
11
+ export type GhostteaMainClaimGhosttyAction = "copy_to_clipboard" | "select_all";
12
+ export interface GhostteaMainClaim {
13
+ /** Canonical Ghostty action name (ground truth). */
14
+ ghosttyAction: GhostteaMainClaimGhosttyAction;
15
+ /** Renderer menu / surface command string. */
16
+ command: Exclude<GhostteaEditCommand, "paste">;
17
+ /** Key identity (letter), matched case-insensitively. */
18
+ key: string;
19
+ }
20
+ /** Allowlist aligned with Ghostty default copy / select-all binds. */
21
+ export declare const GHOSTTEA_MAIN_EDIT_CLAIMS: readonly GhostteaMainClaim[];
22
+ export interface GhostteaKeyInput {
23
+ type: string;
24
+ key: string;
25
+ alt: boolean;
26
+ control: boolean;
27
+ meta: boolean;
28
+ shift: boolean;
29
+ isAutoRepeat: boolean;
30
+ }
31
+ /**
32
+ * Resolve edit shortcuts that must bypass Chromium's DOM editing path.
33
+ *
34
+ * Modifiers match Ghostty defaults:
35
+ * - macOS: super (+ no ctrl/shift/alt)
36
+ * - Linux/Windows: ctrl+shift (+ no meta/alt)
37
+ */
38
+ export declare function ghostteaEditCommand(input: GhostteaKeyInput, platform: NodeJS.Platform): GhostteaEditCommand | null;
39
+ /**
40
+ * Claim terminal copy/select-all accelerators before Electron's DOM edit roles
41
+ * and route them to the host's renderer command channel. Paste remains on the
42
+ * normal renderer input path. Returns an uninstall function.
43
+ */
44
+ export declare function installGhostteaEditShortcuts(webContents: WebContents, onCommand: (command: GhostteaEditCommand) => void, platform?: NodeJS.Platform, canPerform?: (command: GhostteaEditCommand) => boolean): () => void;
45
+ //# sourceMappingURL=edit-commands.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"edit-commands.d.ts","sourceRoot":"","sources":["../src/edit-commands.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAgB,WAAW,EAAE,MAAM,UAAU,CAAC;AAE1D,MAAM,MAAM,mBAAmB,GAAG,MAAM,GAAG,OAAO,GAAG,YAAY,CAAC;AAElE;;;;;;;GAOG;AACH,MAAM,MAAM,8BAA8B,GAAG,mBAAmB,GAAG,YAAY,CAAC;AAEhF,MAAM,WAAW,iBAAiB;IAChC,oDAAoD;IACpD,aAAa,EAAE,8BAA8B,CAAC;IAC9C,8CAA8C;IAC9C,OAAO,EAAE,OAAO,CAAC,mBAAmB,EAAE,OAAO,CAAC,CAAC;IAC/C,yDAAyD;IACzD,GAAG,EAAE,MAAM,CAAC;CACb;AAED,sEAAsE;AACtE,eAAO,MAAM,yBAAyB,EAAE,SAAS,iBAAiB,EAGxD,CAAC;AAEX,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,OAAO,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,OAAO,CAAC;IACd,KAAK,EAAE,OAAO,CAAC;IACf,YAAY,EAAE,OAAO,CAAC;CACvB;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,gBAAgB,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,GAAG,mBAAmB,GAAG,IAAI,CAYlH;AAED;;;;GAIG;AACH,wBAAgB,4BAA4B,CAC1C,WAAW,EAAE,WAAW,EACxB,SAAS,EAAE,CAAC,OAAO,EAAE,mBAAmB,KAAK,IAAI,EACjD,QAAQ,GAAE,MAAM,CAAC,QAA2B,EAC5C,UAAU,GAAE,CAAC,OAAO,EAAE,mBAAmB,KAAK,OAAoB,GACjE,MAAM,IAAI,CASZ"}
@@ -0,0 +1,42 @@
1
+ /** Allowlist aligned with Ghostty default copy / select-all binds. */
2
+ export const GHOSTTEA_MAIN_EDIT_CLAIMS = [
3
+ { ghosttyAction: "copy_to_clipboard", command: "copy", key: "c" },
4
+ { ghosttyAction: "select_all", command: "select-all", key: "a" },
5
+ ];
6
+ /**
7
+ * Resolve edit shortcuts that must bypass Chromium's DOM editing path.
8
+ *
9
+ * Modifiers match Ghostty defaults:
10
+ * - macOS: super (+ no ctrl/shift/alt)
11
+ * - Linux/Windows: ctrl+shift (+ no meta/alt)
12
+ */
13
+ export function ghostteaEditCommand(input, platform) {
14
+ if (input.type !== "keyDown" || input.isAutoRepeat || input.alt)
15
+ return null;
16
+ const hasEditModifier = platform === "darwin" ? input.meta && !input.control && !input.shift : input.control && input.shift && !input.meta;
17
+ if (!hasEditModifier)
18
+ return null;
19
+ const key = input.key.toLowerCase();
20
+ for (const claim of GHOSTTEA_MAIN_EDIT_CLAIMS) {
21
+ if (claim.key === key)
22
+ return claim.command;
23
+ }
24
+ return null;
25
+ }
26
+ /**
27
+ * Claim terminal copy/select-all accelerators before Electron's DOM edit roles
28
+ * and route them to the host's renderer command channel. Paste remains on the
29
+ * normal renderer input path. Returns an uninstall function.
30
+ */
31
+ export function installGhostteaEditShortcuts(webContents, onCommand, platform = process.platform, canPerform = () => true) {
32
+ const listener = (event, input) => {
33
+ const command = ghostteaEditCommand(input, platform);
34
+ if (!command || !canPerform(command))
35
+ return;
36
+ event.preventDefault();
37
+ onCommand(command);
38
+ };
39
+ webContents.on("before-input-event", listener);
40
+ return () => webContents.removeListener("before-input-event", listener);
41
+ }
42
+ //# sourceMappingURL=edit-commands.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"edit-commands.js","sourceRoot":"","sources":["../src/edit-commands.ts"],"names":[],"mappings":"AAuBA,sEAAsE;AACtE,MAAM,CAAC,MAAM,yBAAyB,GAAiC;IACrE,EAAE,aAAa,EAAE,mBAAmB,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,EAAE;IACjE,EAAE,aAAa,EAAE,YAAY,EAAE,OAAO,EAAE,YAAY,EAAE,GAAG,EAAE,GAAG,EAAE;CACxD,CAAC;AAYX;;;;;;GAMG;AACH,MAAM,UAAU,mBAAmB,CAAC,KAAuB,EAAE,QAAyB;IACpF,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS,IAAI,KAAK,CAAC,YAAY,IAAI,KAAK,CAAC,GAAG;QAAE,OAAO,IAAI,CAAC;IAE7E,MAAM,eAAe,GACnB,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,IAAI,KAAK,CAAC,KAAK,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;IACrH,IAAI,CAAC,eAAe;QAAE,OAAO,IAAI,CAAC;IAElC,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC;IACpC,KAAK,MAAM,KAAK,IAAI,yBAAyB,EAAE,CAAC;QAC9C,IAAI,KAAK,CAAC,GAAG,KAAK,GAAG;YAAE,OAAO,KAAK,CAAC,OAAO,CAAC;IAC9C,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,4BAA4B,CAC1C,WAAwB,EACxB,SAAiD,EACjD,QAAQ,GAAoB,OAAO,CAAC,QAAQ,EAC5C,UAAU,GAA8C,GAAG,EAAE,CAAC,IAAI;IAElE,MAAM,QAAQ,GAAG,CAAC,KAAY,EAAE,KAAY,EAAQ,EAAE;QACpD,MAAM,OAAO,GAAG,mBAAmB,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;QACrD,IAAI,CAAC,OAAO,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC;YAAE,OAAO;QAC7C,KAAK,CAAC,cAAc,EAAE,CAAC;QACvB,SAAS,CAAC,OAAO,CAAC,CAAC;IACrB,CAAC,CAAC;IACF,WAAW,CAAC,EAAE,CAAC,oBAAoB,EAAE,QAAQ,CAAC,CAAC;IAC/C,OAAO,GAAG,EAAE,CAAC,WAAW,CAAC,cAAc,CAAC,oBAAoB,EAAE,QAAQ,CAAC,CAAC;AAC1E,CAAC"}
@@ -0,0 +1,18 @@
1
+ export declare const FRAME_IN_FLIGHT_HIGH_WATER_BYTES: number;
2
+ export declare const FRAME_IN_FLIGHT_LOW_WATER_BYTES: number;
3
+ export declare const FRAME_BRIDGE_CAPABILITY_VERSION = 1;
4
+ export interface FrameBridgeCapabilities {
5
+ type: "bridge-capabilities";
6
+ requestId: number;
7
+ protocolVersion: typeof FRAME_BRIDGE_CAPABILITY_VERSION;
8
+ frameCredits: true;
9
+ }
10
+ export declare function requestedFrameBridgeCapabilities(message: unknown): FrameBridgeCapabilities | undefined;
11
+ export declare class FrameFlowControl {
12
+ #private;
13
+ get inFlightBytes(): number;
14
+ get paused(): boolean;
15
+ accept(bytes: number): "pause" | undefined;
16
+ release(bytes: number): "resume" | undefined;
17
+ }
18
+ //# sourceMappingURL=frame-flow.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"frame-flow.d.ts","sourceRoot":"","sources":["../src/frame-flow.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,gCAAgC,QAAmB,CAAC;AACjE,eAAO,MAAM,+BAA+B,QAAmB,CAAC;AAChE,eAAO,MAAM,+BAA+B,IAAI,CAAC;AAEjD,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,qBAAqB,CAAC;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,OAAO,+BAA+B,CAAC;IACxD,YAAY,EAAE,IAAI,CAAC;CACpB;AAED,wBAAgB,gCAAgC,CAAC,OAAO,EAAE,OAAO,GAAG,uBAAuB,GAAG,SAAS,CAgBtG;AAED,qBAAa,gBAAgB;;IAI3B,IAAI,aAAa,IAAI,MAAM,CAE1B;IAED,IAAI,MAAM,IAAI,OAAO,CAEpB;IAED,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,CASzC;IAED,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,QAAQ,GAAG,SAAS,CAS3C;CACF"}
@@ -0,0 +1,52 @@
1
+ export const FRAME_IN_FLIGHT_HIGH_WATER_BYTES = 32 * 1024 * 1024;
2
+ export const FRAME_IN_FLIGHT_LOW_WATER_BYTES = 16 * 1024 * 1024;
3
+ export const FRAME_BRIDGE_CAPABILITY_VERSION = 1;
4
+ export function requestedFrameBridgeCapabilities(message) {
5
+ if (!message || typeof message !== "object")
6
+ return undefined;
7
+ const candidate = message;
8
+ if (candidate.type !== "subscribe" ||
9
+ candidate.bridgeCapabilities !== FRAME_BRIDGE_CAPABILITY_VERSION ||
10
+ !Number.isSafeInteger(candidate.requestId) ||
11
+ Number(candidate.requestId) < 0)
12
+ return undefined;
13
+ return {
14
+ type: "bridge-capabilities",
15
+ requestId: Number(candidate.requestId),
16
+ protocolVersion: FRAME_BRIDGE_CAPABILITY_VERSION,
17
+ frameCredits: true,
18
+ };
19
+ }
20
+ export class FrameFlowControl {
21
+ #inFlightBytes = 0;
22
+ #paused = false;
23
+ get inFlightBytes() {
24
+ return this.#inFlightBytes;
25
+ }
26
+ get paused() {
27
+ return this.#paused;
28
+ }
29
+ accept(bytes) {
30
+ if (!Number.isSafeInteger(bytes) || bytes < 0)
31
+ throw new RangeError("frame byte count must be a non-negative integer");
32
+ this.#inFlightBytes += bytes;
33
+ if (!this.#paused && this.#inFlightBytes >= FRAME_IN_FLIGHT_HIGH_WATER_BYTES) {
34
+ this.#paused = true;
35
+ return "pause";
36
+ }
37
+ return undefined;
38
+ }
39
+ release(bytes) {
40
+ if (!Number.isSafeInteger(bytes) || bytes < 0)
41
+ throw new RangeError("frame credit must be a non-negative integer");
42
+ if (bytes > this.#inFlightBytes)
43
+ throw new RangeError("frame credit exceeds in-flight bytes");
44
+ this.#inFlightBytes -= bytes;
45
+ if (this.#paused && this.#inFlightBytes <= FRAME_IN_FLIGHT_LOW_WATER_BYTES) {
46
+ this.#paused = false;
47
+ return "resume";
48
+ }
49
+ return undefined;
50
+ }
51
+ }
52
+ //# sourceMappingURL=frame-flow.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"frame-flow.js","sourceRoot":"","sources":["../src/frame-flow.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,gCAAgC,GAAG,EAAE,GAAG,IAAI,GAAG,IAAI,CAAC;AACjE,MAAM,CAAC,MAAM,+BAA+B,GAAG,EAAE,GAAG,IAAI,GAAG,IAAI,CAAC;AAChE,MAAM,CAAC,MAAM,+BAA+B,GAAG,CAAC,CAAC;AASjD,MAAM,UAAU,gCAAgC,CAAC,OAAgB;IAC/D,IAAI,CAAC,OAAO,IAAI,OAAO,OAAO,KAAK,QAAQ;QAAE,OAAO,SAAS,CAAC;IAC9D,MAAM,SAAS,GAAG,OAAgF,CAAC;IACnG,IACE,SAAS,CAAC,IAAI,KAAK,WAAW;QAC9B,SAAS,CAAC,kBAAkB,KAAK,+BAA+B;QAChE,CAAC,MAAM,CAAC,aAAa,CAAC,SAAS,CAAC,SAAS,CAAC;QAC1C,MAAM,CAAC,SAAS,CAAC,SAAS,CAAC,GAAG,CAAC;QAE/B,OAAO,SAAS,CAAC;IACnB,OAAO;QACL,IAAI,EAAE,qBAAqB;QAC3B,SAAS,EAAE,MAAM,CAAC,SAAS,CAAC,SAAS,CAAC;QACtC,eAAe,EAAE,+BAA+B;QAChD,YAAY,EAAE,IAAI;KACnB,CAAC;AACJ,CAAC;AAED,MAAM,OAAO,gBAAgB;IAC3B,cAAc,GAAG,CAAC,CAAC;IACnB,OAAO,GAAG,KAAK,CAAC;IAEhB,IAAI,aAAa;QACf,OAAO,IAAI,CAAC,cAAc,CAAC;IAC7B,CAAC;IAED,IAAI,MAAM;QACR,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;IAED,MAAM,CAAC,KAAa;QAClB,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC;YAC3C,MAAM,IAAI,UAAU,CAAC,iDAAiD,CAAC,CAAC;QAC1E,IAAI,CAAC,cAAc,IAAI,KAAK,CAAC;QAC7B,IAAI,CAAC,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,cAAc,IAAI,gCAAgC,EAAE,CAAC;YAC7E,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;YACpB,OAAO,OAAO,CAAC;QACjB,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,OAAO,CAAC,KAAa;QACnB,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC;YAAE,MAAM,IAAI,UAAU,CAAC,6CAA6C,CAAC,CAAC;QACnH,IAAI,KAAK,GAAG,IAAI,CAAC,cAAc;YAAE,MAAM,IAAI,UAAU,CAAC,sCAAsC,CAAC,CAAC;QAC9F,IAAI,CAAC,cAAc,IAAI,KAAK,CAAC;QAC7B,IAAI,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,cAAc,IAAI,+BAA+B,EAAE,CAAC;YAC3E,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC;YACrB,OAAO,QAAQ,CAAC;QAClB,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;CACF"}
@@ -0,0 +1,9 @@
1
+ export { GhostteaElectronBackend, type GhostteaElectronBackendOptions } from "./backend.js";
2
+ export { GhostteaAutomationClient, type AutomationInputResult, type GhostteaAutomationClientOptions, type GhostteaControlCommand, type GhostteaControlConnection, type SessionExitedEvent, } from "./automation.js";
3
+ export { GhostteaElectronBridge, type GhostteaElectronBridgeOptions } from "./bridge.js";
4
+ export { allSettledWithin } from "./deadline.js";
5
+ export { ghostteaEditCommand, installGhostteaEditShortcuts, type GhostteaEditCommand, type GhostteaKeyInput, } from "./edit-commands.js";
6
+ export { forwardGhostteaRendererPorts } from "./preload.js";
7
+ export { TerminalSupervisor, type GhostteaBinary, type TerminalSupervisorOptions } from "./supervisor.js";
8
+ export type { RendererPortBootstrapMessage, TerminalDaemonConnection } from "./types.js";
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,KAAK,8BAA8B,EAAE,MAAM,cAAc,CAAC;AAC5F,OAAO,EACL,wBAAwB,EACxB,KAAK,qBAAqB,EAC1B,KAAK,+BAA+B,EACpC,KAAK,sBAAsB,EAC3B,KAAK,yBAAyB,EAC9B,KAAK,kBAAkB,GACxB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,sBAAsB,EAAE,KAAK,6BAA6B,EAAE,MAAM,aAAa,CAAC;AACzF,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EACL,mBAAmB,EACnB,4BAA4B,EAC5B,KAAK,mBAAmB,EACxB,KAAK,gBAAgB,GACtB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,4BAA4B,EAAE,MAAM,cAAc,CAAC;AAC5D,OAAO,EAAE,kBAAkB,EAAE,KAAK,cAAc,EAAE,KAAK,yBAAyB,EAAE,MAAM,iBAAiB,CAAC;AAC1G,YAAY,EAAE,4BAA4B,EAAE,wBAAwB,EAAE,MAAM,YAAY,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,8 @@
1
+ export { GhostteaElectronBackend } from "./backend.js";
2
+ export { GhostteaAutomationClient, } from "./automation.js";
3
+ export { GhostteaElectronBridge } from "./bridge.js";
4
+ export { allSettledWithin } from "./deadline.js";
5
+ export { ghostteaEditCommand, installGhostteaEditShortcuts, } from "./edit-commands.js";
6
+ export { forwardGhostteaRendererPorts } from "./preload.js";
7
+ export { TerminalSupervisor } from "./supervisor.js";
8
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAuC,MAAM,cAAc,CAAC;AAC5F,OAAO,EACL,wBAAwB,GAMzB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,sBAAsB,EAAsC,MAAM,aAAa,CAAC;AACzF,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EACL,mBAAmB,EACnB,4BAA4B,GAG7B,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,4BAA4B,EAAE,MAAM,cAAc,CAAC;AAC5D,OAAO,EAAE,kBAAkB,EAAuD,MAAM,iBAAiB,CAAC"}
package/dist/main.d.ts ADDED
@@ -0,0 +1,9 @@
1
+ export { GhostteaElectronBackend, type GhostteaElectronBackendOptions } from "./backend.js";
2
+ export { GhostteaAutomationClient, type AutomationInputResult, type GhostteaAutomationClientOptions, type GhostteaControlCommand, type GhostteaControlConnection, type SessionExitedEvent, } from "./automation.js";
3
+ export { GhostteaElectronBridge, type GhostteaElectronBridgeOptions } from "./bridge.js";
4
+ export { installGhostteaClipboardHost, type GhostteaClipboardHost } from "./clipboard.js";
5
+ export { allSettledWithin } from "./deadline.js";
6
+ export { ghostteaEditCommand, installGhostteaEditShortcuts, type GhostteaEditCommand, type GhostteaKeyInput, } from "./edit-commands.js";
7
+ export { TerminalSupervisor, type GhostteaBinary, type TerminalSupervisorOptions } from "./supervisor.js";
8
+ export type { TerminalDaemonConnection } from "./types.js";
9
+ //# sourceMappingURL=main.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,KAAK,8BAA8B,EAAE,MAAM,cAAc,CAAC;AAC5F,OAAO,EACL,wBAAwB,EACxB,KAAK,qBAAqB,EAC1B,KAAK,+BAA+B,EACpC,KAAK,sBAAsB,EAC3B,KAAK,yBAAyB,EAC9B,KAAK,kBAAkB,GACxB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,sBAAsB,EAAE,KAAK,6BAA6B,EAAE,MAAM,aAAa,CAAC;AACzF,OAAO,EAAE,4BAA4B,EAAE,KAAK,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AAC1F,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EACL,mBAAmB,EACnB,4BAA4B,EAC5B,KAAK,mBAAmB,EACxB,KAAK,gBAAgB,GACtB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,kBAAkB,EAAE,KAAK,cAAc,EAAE,KAAK,yBAAyB,EAAE,MAAM,iBAAiB,CAAC;AAC1G,YAAY,EAAE,wBAAwB,EAAE,MAAM,YAAY,CAAC"}
package/dist/main.js ADDED
@@ -0,0 +1,8 @@
1
+ export { GhostteaElectronBackend } from "./backend.js";
2
+ export { GhostteaAutomationClient, } from "./automation.js";
3
+ export { GhostteaElectronBridge } from "./bridge.js";
4
+ export { installGhostteaClipboardHost } from "./clipboard.js";
5
+ export { allSettledWithin } from "./deadline.js";
6
+ export { ghostteaEditCommand, installGhostteaEditShortcuts, } from "./edit-commands.js";
7
+ export { TerminalSupervisor } from "./supervisor.js";
8
+ //# sourceMappingURL=main.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"main.js","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAuC,MAAM,cAAc,CAAC;AAC5F,OAAO,EACL,wBAAwB,GAMzB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,sBAAsB,EAAsC,MAAM,aAAa,CAAC;AACzF,OAAO,EAAE,4BAA4B,EAA8B,MAAM,gBAAgB,CAAC;AAC1F,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EACL,mBAAmB,EACnB,4BAA4B,GAG7B,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,kBAAkB,EAAuD,MAAM,iBAAiB,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { IpcRenderer } from "electron";
2
+ export { createGhostteaClipboardBridge, type GhostteaClipboardBridge } from "./clipboard.js";
3
+ export declare function forwardGhostteaRendererPorts(ipcRenderer: IpcRenderer, channel?: string): () => void;
4
+ //# sourceMappingURL=preload.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"preload.d.ts","sourceRoot":"","sources":["../src/preload.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAoB,MAAM,UAAU,CAAC;AAC9D,OAAO,EAAE,6BAA6B,EAAE,KAAK,uBAAuB,EAAE,MAAM,gBAAgB,CAAC;AAG7F,wBAAgB,4BAA4B,CAAC,WAAW,EAAE,WAAW,EAAE,OAAO,SAAmB,GAAG,MAAM,IAAI,CAM7G"}
@@ -0,0 +1,9 @@
1
+ export { createGhostteaClipboardBridge } from "./clipboard.js";
2
+ export function forwardGhostteaRendererPorts(ipcRenderer, channel = "terminal-ports") {
3
+ const listener = (event) => {
4
+ window.postMessage({ type: "ghosttea:ports" }, "*", event.ports);
5
+ };
6
+ ipcRenderer.on(channel, listener);
7
+ return () => ipcRenderer.removeListener(channel, listener);
8
+ }
9
+ //# sourceMappingURL=preload.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"preload.js","sourceRoot":"","sources":["../src/preload.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,6BAA6B,EAAgC,MAAM,gBAAgB,CAAC;AAG7F,MAAM,UAAU,4BAA4B,CAAC,WAAwB,EAAE,OAAO,GAAG,gBAAgB;IAC/F,MAAM,QAAQ,GAAG,CAAC,KAAuB,EAAQ,EAAE;QACjD,MAAM,CAAC,WAAW,CAAC,EAAE,IAAI,EAAE,gBAAgB,EAAyC,EAAE,GAAG,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;IAC1G,CAAC,CAAC;IACF,WAAW,CAAC,EAAE,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;IAClC,OAAO,GAAG,EAAE,CAAC,WAAW,CAAC,cAAc,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;AAC7D,CAAC"}
@@ -0,0 +1,30 @@
1
+ import { EventEmitter } from "node:events";
2
+ import type { TerminalDaemonConnection } from "./types.js";
3
+ export type GhostteaBinary = {
4
+ kind: "executable";
5
+ path: string;
6
+ args?: string[];
7
+ cwd?: string;
8
+ } | {
9
+ kind: "cargo";
10
+ manifestPath: string;
11
+ release: boolean;
12
+ cargoPath?: string;
13
+ args?: string[];
14
+ };
15
+ export interface TerminalSupervisorOptions {
16
+ binary: GhostteaBinary;
17
+ runtimeDirectory?: string;
18
+ environment?: NodeJS.ProcessEnv;
19
+ startupTimeoutMs?: number;
20
+ onStderr?: (line: string) => void;
21
+ }
22
+ export declare class TerminalSupervisor extends EventEmitter {
23
+ #private;
24
+ readonly connection: TerminalDaemonConnection;
25
+ constructor(options: TerminalSupervisorOptions);
26
+ start(): Promise<void>;
27
+ get running(): boolean;
28
+ stop(): void;
29
+ }
30
+ //# sourceMappingURL=supervisor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"supervisor.d.ts","sourceRoot":"","sources":["../src/supervisor.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAI3C,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,YAAY,CAAC;AAE3D,MAAM,MAAM,cAAc,GACtB;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GACnE;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC;AAEnG,MAAM,WAAW,yBAAyB;IACxC,MAAM,EAAE,cAAc,CAAC;IACvB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,WAAW,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IAChC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CACnC;AAED,qBAAa,kBAAmB,SAAQ,YAAY;;IAQlD,QAAQ,CAAC,UAAU,EAAE,wBAAwB,CAAC;IAE9C,YAAY,OAAO,EAAE,yBAAyB,EAc7C;IAEK,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAM3B;IA+DD,IAAI,OAAO,IAAI,OAAO,CAErB;IAED,IAAI,IAAI,IAAI,CAWX;CAyCF"}
@@ -0,0 +1,160 @@
1
+ import { randomBytes } from "node:crypto";
2
+ import { spawn } from "node:child_process";
3
+ import { EventEmitter } from "node:events";
4
+ import { existsSync, mkdirSync, mkdtempSync, rmSync } from "node:fs";
5
+ import { tmpdir } from "node:os";
6
+ import { dirname, join } from "node:path";
7
+ export class TerminalSupervisor extends EventEmitter {
8
+ #child;
9
+ #startPromise;
10
+ #ready = false;
11
+ #expectedExits = new WeakSet();
12
+ #options;
13
+ #runtimeDir;
14
+ #ownsRuntimeDir;
15
+ connection;
16
+ constructor(options) {
17
+ super();
18
+ this.#options = options;
19
+ this.#ownsRuntimeDir = options.runtimeDirectory === undefined;
20
+ this.#runtimeDir =
21
+ options.runtimeDirectory !== undefined
22
+ ? options.runtimeDirectory
23
+ : mkdtempSync(join(tmpdir(), `ghosttea-${process.getuid?.() ?? "user"}-${process.pid}-`));
24
+ if (options.runtimeDirectory !== undefined)
25
+ mkdirSync(this.#runtimeDir, { recursive: true, mode: 0o700 });
26
+ this.connection = {
27
+ controlSocket: join(this.#runtimeDir, "control.sock"),
28
+ frameSocket: join(this.#runtimeDir, "frames.sock"),
29
+ authToken: randomBytes(32).toString("hex"),
30
+ };
31
+ }
32
+ async start() {
33
+ if (this.#ready)
34
+ return;
35
+ this.#startPromise ??= this.#start().finally(() => {
36
+ this.#startPromise = undefined;
37
+ });
38
+ return this.#startPromise;
39
+ }
40
+ async #start() {
41
+ this.#ready = false;
42
+ mkdirSync(this.#runtimeDir, { recursive: true, mode: 0o700 });
43
+ rmSync(this.connection.controlSocket, { force: true });
44
+ rmSync(this.connection.frameSocket, { force: true });
45
+ const environment = {
46
+ ...process.env,
47
+ ...this.#options.environment,
48
+ GHOSTTEA_CONTROL_SOCKET: this.connection.controlSocket,
49
+ GHOSTTEA_FRAME_SOCKET: this.connection.frameSocket,
50
+ GHOSTTEA_AUTH_TOKEN: this.connection.authToken,
51
+ };
52
+ const binary = this.#options.binary;
53
+ if (binary.kind === "executable") {
54
+ if (!existsSync(binary.path))
55
+ throw new Error(`ghosttead executable not found at ${binary.path}`);
56
+ this.#child = spawn(binary.path, binary.args ?? [], {
57
+ cwd: binary.cwd,
58
+ env: environment,
59
+ stdio: ["ignore", "pipe", "pipe"],
60
+ });
61
+ }
62
+ else {
63
+ if (!existsSync(binary.manifestPath))
64
+ throw new Error(`ghosttead manifest not found at ${binary.manifestPath}`);
65
+ this.#child = spawn(binary.cargoPath ?? "cargo", [
66
+ "run",
67
+ "--quiet",
68
+ ...(binary.release ? ["--release"] : []),
69
+ "--manifest-path",
70
+ binary.manifestPath,
71
+ ...(binary.args ?? []),
72
+ ], {
73
+ cwd: dirname(binary.manifestPath),
74
+ env: environment,
75
+ stdio: ["ignore", "pipe", "pipe"],
76
+ });
77
+ }
78
+ this.#child.stderr?.on("data", (chunk) => {
79
+ const line = String(chunk).trimEnd();
80
+ if (this.#options.onStderr)
81
+ this.#options.onStderr(line);
82
+ else
83
+ console.error(`[ghosttead] ${line}`);
84
+ });
85
+ await this.#waitUntilReady();
86
+ const running = this.#child;
87
+ if (!running || running.exitCode !== null || running.signalCode !== null) {
88
+ this.#child = undefined;
89
+ throw new Error("ghosttead exited immediately after startup");
90
+ }
91
+ this.#ready = true;
92
+ running?.once("exit", (code, signal) => {
93
+ const expected = this.#expectedExits.delete(running);
94
+ if (this.#child !== running)
95
+ return;
96
+ this.#child = undefined;
97
+ this.#ready = false;
98
+ if (!expected)
99
+ this.emit("unexpected-exit", { code, signal });
100
+ });
101
+ }
102
+ get running() {
103
+ return this.#ready && this.#child !== undefined;
104
+ }
105
+ stop() {
106
+ this.#ready = false;
107
+ const child = this.#child;
108
+ if (child) {
109
+ this.#expectedExits.add(child);
110
+ child.kill("SIGTERM");
111
+ if (this.#child === child)
112
+ this.#child = undefined;
113
+ }
114
+ rmSync(this.connection.controlSocket, { force: true });
115
+ rmSync(this.connection.frameSocket, { force: true });
116
+ if (this.#ownsRuntimeDir)
117
+ rmSync(this.#runtimeDir, { recursive: true, force: true });
118
+ }
119
+ async #waitUntilReady() {
120
+ const child = this.#child;
121
+ if (!child?.stdout)
122
+ throw new Error("ghosttead did not expose stdout");
123
+ const stdout = child.stdout;
124
+ await new Promise((resolveReady, reject) => {
125
+ let output = "";
126
+ let settled = false;
127
+ const cleanup = () => {
128
+ clearTimeout(timeout);
129
+ stdout.off("data", onData);
130
+ child.off("error", onError);
131
+ child.off("exit", onExit);
132
+ };
133
+ const fail = (error) => {
134
+ if (settled)
135
+ return;
136
+ settled = true;
137
+ cleanup();
138
+ child.kill("SIGTERM");
139
+ if (this.#child === child)
140
+ this.#child = undefined;
141
+ reject(error);
142
+ };
143
+ const timeout = setTimeout(() => fail(new Error("ghosttead startup timed out")), this.#options.startupTimeoutMs ?? 120_000);
144
+ const onData = (chunk) => {
145
+ output = `${output}${String(chunk)}`.slice(-4096);
146
+ if (!output.includes("ghosttead ready") || settled)
147
+ return;
148
+ settled = true;
149
+ cleanup();
150
+ resolveReady();
151
+ };
152
+ const onError = (error) => fail(error);
153
+ const onExit = (code) => fail(new Error(`ghosttead exited during startup (${code})`));
154
+ child.once("error", onError);
155
+ child.once("exit", onExit);
156
+ stdout.on("data", onData);
157
+ });
158
+ }
159
+ }
160
+ //# sourceMappingURL=supervisor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"supervisor.js","sourceRoot":"","sources":["../src/supervisor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ import type { GhostteaControlConnection } from "@vibecook/ghosttea-client";
2
+ export interface TerminalDaemonConnection extends GhostteaControlConnection {
3
+ frameSocket: string;
4
+ }
5
+ export interface MainToBridgeMessage {
6
+ type: "connect";
7
+ connection: TerminalDaemonConnection;
8
+ }
9
+ export interface RendererPortBootstrapMessage {
10
+ type: "ghosttea:ports";
11
+ }
12
+ export declare function isMainToBridgeMessage(value: unknown): value is MainToBridgeMessage;
13
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,2BAA2B,CAAC;AAE3E,MAAM,WAAW,wBAAyB,SAAQ,yBAAyB;IACzE,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,SAAS,CAAC;IAChB,UAAU,EAAE,wBAAwB,CAAC;CACtC;AAED,MAAM,WAAW,4BAA4B;IAC3C,IAAI,EAAE,gBAAgB,CAAC;CACxB;AAED,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,mBAAmB,CAUlF"}
package/dist/types.js ADDED
@@ -0,0 +1,12 @@
1
+ export function isMainToBridgeMessage(value) {
2
+ if (!value || typeof value !== "object")
3
+ return false;
4
+ const candidate = value;
5
+ if (candidate.type !== "connect" || !candidate.connection || typeof candidate.connection !== "object")
6
+ return false;
7
+ const connection = candidate.connection;
8
+ return (typeof connection.controlSocket === "string" &&
9
+ typeof connection.frameSocket === "string" &&
10
+ typeof connection.authToken === "string");
11
+ }
12
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAeA,MAAM,UAAU,qBAAqB,CAAC,KAAc;IAClD,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IACtD,MAAM,SAAS,GAAG,KAAgC,CAAC;IACnD,IAAI,SAAS,CAAC,IAAI,KAAK,SAAS,IAAI,CAAC,SAAS,CAAC,UAAU,IAAI,OAAO,SAAS,CAAC,UAAU,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IACpH,MAAM,UAAU,GAAG,SAAS,CAAC,UAAqC,CAAC;IACnE,OAAO,CACL,OAAO,UAAU,CAAC,aAAa,KAAK,QAAQ;QAC5C,OAAO,UAAU,CAAC,WAAW,KAAK,QAAQ;QAC1C,OAAO,UAAU,CAAC,SAAS,KAAK,QAAQ,CACzC,CAAC;AACJ,CAAC"}
package/package.json ADDED
@@ -0,0 +1,78 @@
1
+ {
2
+ "name": "@vibecook/ghosttea-electron",
3
+ "version": "0.2.0",
4
+ "description": "Electron lifecycle and direct renderer transport for Ghosttea.",
5
+ "license": "MIT",
6
+ "author": "James Yong",
7
+ "type": "module",
8
+ "sideEffects": [
9
+ "./dist/bridge-entry.js"
10
+ ],
11
+ "main": "./dist/index.js",
12
+ "types": "./dist/index.d.ts",
13
+ "exports": {
14
+ ".": {
15
+ "types": "./dist/index.d.ts",
16
+ "import": "./dist/index.js"
17
+ },
18
+ "./main": {
19
+ "types": "./dist/main.d.ts",
20
+ "import": "./dist/main.js"
21
+ },
22
+ "./automation": {
23
+ "types": "./dist/automation.d.ts",
24
+ "import": "./dist/automation.js"
25
+ },
26
+ "./preload": {
27
+ "types": "./dist/preload.d.ts",
28
+ "import": "./dist/preload.js"
29
+ },
30
+ "./types": {
31
+ "types": "./dist/types.d.ts",
32
+ "import": "./dist/types.js"
33
+ },
34
+ "./bridge-entry": "./dist/bridge-entry.js"
35
+ },
36
+ "files": [
37
+ "dist",
38
+ "README.md",
39
+ "LICENSE"
40
+ ],
41
+ "repository": {
42
+ "type": "git",
43
+ "url": "git+https://github.com/jamesyong-42/ghosttea.git",
44
+ "directory": "packages/terminal-electron"
45
+ },
46
+ "homepage": "https://github.com/jamesyong-42/ghosttea#readme",
47
+ "bugs": {
48
+ "url": "https://github.com/jamesyong-42/ghosttea/issues"
49
+ },
50
+ "keywords": [
51
+ "electron",
52
+ "ghostty",
53
+ "terminal"
54
+ ],
55
+ "publishConfig": {
56
+ "access": "public",
57
+ "provenance": true
58
+ },
59
+ "scripts": {
60
+ "clean": "node -e \"require('node:fs').rmSync('dist',{recursive:true,force:true})\"",
61
+ "build": "npm run clean && tsc -p tsconfig.build.json",
62
+ "check": "tsc --noEmit",
63
+ "test": "vitest run",
64
+ "prepublishOnly": "npm run build"
65
+ },
66
+ "dependencies": {
67
+ "@vibecook/ghosttea-client": "0.2.0"
68
+ },
69
+ "peerDependencies": {
70
+ "electron": ">=35"
71
+ },
72
+ "devDependencies": {
73
+ "@types/node": "26.1.1",
74
+ "electron": "43.1.1",
75
+ "typescript": "7.0.2",
76
+ "vitest": "4.1.10"
77
+ }
78
+ }