@grackle-ai/server 0.0.2

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 (110) hide show
  1. package/README.md +5 -0
  2. package/dist/adapter-manager.d.ts +18 -0
  3. package/dist/adapter-manager.d.ts.map +1 -0
  4. package/dist/adapter-manager.js +67 -0
  5. package/dist/adapter-manager.js.map +1 -0
  6. package/dist/adapters/adapter.d.ts +40 -0
  7. package/dist/adapters/adapter.d.ts.map +1 -0
  8. package/dist/adapters/adapter.js +2 -0
  9. package/dist/adapters/adapter.js.map +1 -0
  10. package/dist/adapters/docker.d.ts +26 -0
  11. package/dist/adapters/docker.d.ts.map +1 -0
  12. package/dist/adapters/docker.js +274 -0
  13. package/dist/adapters/docker.js.map +1 -0
  14. package/dist/adapters/local.d.ts +15 -0
  15. package/dist/adapters/local.d.ts.map +1 -0
  16. package/dist/adapters/local.js +57 -0
  17. package/dist/adapters/local.js.map +1 -0
  18. package/dist/adapters/powerline-transport.d.ts +7 -0
  19. package/dist/adapters/powerline-transport.d.ts.map +1 -0
  20. package/dist/adapters/powerline-transport.js +22 -0
  21. package/dist/adapters/powerline-transport.js.map +1 -0
  22. package/dist/api-key.d.ts +8 -0
  23. package/dist/api-key.d.ts.map +1 -0
  24. package/dist/api-key.js +58 -0
  25. package/dist/api-key.js.map +1 -0
  26. package/dist/crypto.d.ts +5 -0
  27. package/dist/crypto.d.ts.map +1 -0
  28. package/dist/crypto.js +74 -0
  29. package/dist/crypto.js.map +1 -0
  30. package/dist/db.d.ts +11 -0
  31. package/dist/db.d.ts.map +1 -0
  32. package/dist/db.js +140 -0
  33. package/dist/db.js.map +1 -0
  34. package/dist/env-registry.d.ts +20 -0
  35. package/dist/env-registry.d.ts.map +1 -0
  36. package/dist/env-registry.js +55 -0
  37. package/dist/env-registry.js.map +1 -0
  38. package/dist/finding-store.d.ts +9 -0
  39. package/dist/finding-store.d.ts.map +1 -0
  40. package/dist/finding-store.js +68 -0
  41. package/dist/finding-store.js.map +1 -0
  42. package/dist/grpc-service.d.ts +4 -0
  43. package/dist/grpc-service.d.ts.map +1 -0
  44. package/dist/grpc-service.js +594 -0
  45. package/dist/grpc-service.js.map +1 -0
  46. package/dist/index.d.ts +2 -0
  47. package/dist/index.d.ts.map +1 -0
  48. package/dist/index.js +108 -0
  49. package/dist/index.js.map +1 -0
  50. package/dist/json-helpers.d.ts +7 -0
  51. package/dist/json-helpers.d.ts.map +1 -0
  52. package/dist/json-helpers.js +22 -0
  53. package/dist/json-helpers.js.map +1 -0
  54. package/dist/log-writer.d.ts +18 -0
  55. package/dist/log-writer.d.ts.map +1 -0
  56. package/dist/log-writer.js +44 -0
  57. package/dist/log-writer.js.map +1 -0
  58. package/dist/logger.d.ts +4 -0
  59. package/dist/logger.d.ts.map +1 -0
  60. package/dist/logger.js +10 -0
  61. package/dist/logger.js.map +1 -0
  62. package/dist/paths.d.ts +7 -0
  63. package/dist/paths.d.ts.map +1 -0
  64. package/dist/paths.js +12 -0
  65. package/dist/paths.js.map +1 -0
  66. package/dist/project-store.d.ts +11 -0
  67. package/dist/project-store.d.ts.map +1 -0
  68. package/dist/project-store.js +32 -0
  69. package/dist/project-store.js.map +1 -0
  70. package/dist/schema.d.ts +1199 -0
  71. package/dist/schema.d.ts.map +1 -0
  72. package/dist/schema.js +82 -0
  73. package/dist/schema.js.map +1 -0
  74. package/dist/session-store.d.ts +22 -0
  75. package/dist/session-store.d.ts.map +1 -0
  76. package/dist/session-store.js +73 -0
  77. package/dist/session-store.js.map +1 -0
  78. package/dist/stream-hub.d.ts +14 -0
  79. package/dist/stream-hub.d.ts.map +1 -0
  80. package/dist/stream-hub.js +95 -0
  81. package/dist/stream-hub.js.map +1 -0
  82. package/dist/task-store.d.ts +28 -0
  83. package/dist/task-store.d.ts.map +1 -0
  84. package/dist/task-store.js +121 -0
  85. package/dist/task-store.js.map +1 -0
  86. package/dist/token-broker.d.ts +27 -0
  87. package/dist/token-broker.d.ts.map +1 -0
  88. package/dist/token-broker.js +76 -0
  89. package/dist/token-broker.js.map +1 -0
  90. package/dist/transcript.d.ts +5 -0
  91. package/dist/transcript.d.ts.map +1 -0
  92. package/dist/transcript.js +51 -0
  93. package/dist/transcript.js.map +1 -0
  94. package/dist/utils/exec.d.ts +17 -0
  95. package/dist/utils/exec.d.ts.map +1 -0
  96. package/dist/utils/exec.js +21 -0
  97. package/dist/utils/exec.js.map +1 -0
  98. package/dist/utils/ports.d.ts +3 -0
  99. package/dist/utils/ports.d.ts.map +1 -0
  100. package/dist/utils/ports.js +19 -0
  101. package/dist/utils/ports.js.map +1 -0
  102. package/dist/utils/sleep.d.ts +3 -0
  103. package/dist/utils/sleep.d.ts.map +1 -0
  104. package/dist/utils/sleep.js +5 -0
  105. package/dist/utils/sleep.js.map +1 -0
  106. package/dist/ws-bridge.d.ts +10 -0
  107. package/dist/ws-bridge.d.ts.map +1 -0
  108. package/dist/ws-bridge.js +846 -0
  109. package/dist/ws-bridge.js.map +1 -0
  110. package/package.json +50 -0
package/README.md ADDED
@@ -0,0 +1,5 @@
1
+ # @grackle-ai/server
2
+
3
+ Central gRPC server with SQLite storage and WebSocket bridge for Grackle.
4
+
5
+ See the [main repository](https://github.com/nick-pape/grackle) for full documentation.
@@ -0,0 +1,18 @@
1
+ import type { EnvironmentAdapter, PowerLineConnection } from "./adapters/adapter.js";
2
+ /** Register an environment adapter so it can be looked up by type. */
3
+ export declare function registerAdapter(adapter: EnvironmentAdapter): void;
4
+ /** Retrieve a registered adapter by its type name. */
5
+ export declare function getAdapter(type: string): EnvironmentAdapter | undefined;
6
+ /** Store an active PowerLine connection for an environment. */
7
+ export declare function setConnection(environmentId: string, conn: PowerLineConnection): void;
8
+ /** Get the active PowerLine connection for an environment, if connected. */
9
+ export declare function getConnection(environmentId: string): PowerLineConnection | undefined;
10
+ /** Remove the stored connection for an environment. */
11
+ export declare function removeConnection(environmentId: string): void;
12
+ /** Return the map of all active environment connections. */
13
+ export declare function listConnections(): Map<string, PowerLineConnection>;
14
+ /** Start a periodic health-check loop that calls `onDisconnect` when a PowerLine becomes unreachable. */
15
+ export declare function startHeartbeat(onDisconnect: (environmentId: string) => void): void;
16
+ /** Stop the periodic health-check loop. */
17
+ export declare function stopHeartbeat(): void;
18
+ //# sourceMappingURL=adapter-manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapter-manager.d.ts","sourceRoot":"","sources":["../src/adapter-manager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAUrF,sEAAsE;AACtE,wBAAgB,eAAe,CAAC,OAAO,EAAE,kBAAkB,GAAG,IAAI,CAEjE;AAED,sDAAsD;AACtD,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,kBAAkB,GAAG,SAAS,CAEvE;AAED,+DAA+D;AAC/D,wBAAgB,aAAa,CAAC,aAAa,EAAE,MAAM,EAAE,IAAI,EAAE,mBAAmB,GAAG,IAAI,CAEpF;AAED,4EAA4E;AAC5E,wBAAgB,aAAa,CAAC,aAAa,EAAE,MAAM,GAAG,mBAAmB,GAAG,SAAS,CAEpF;AAED,uDAAuD;AACvD,wBAAgB,gBAAgB,CAAC,aAAa,EAAE,MAAM,GAAG,IAAI,CAE5D;AAED,4DAA4D;AAC5D,wBAAgB,eAAe,IAAI,GAAG,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAElE;AAED,yGAAyG;AACzG,wBAAgB,cAAc,CAAC,YAAY,EAAE,CAAC,aAAa,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI,CA4BlF;AAED,2CAA2C;AAC3C,wBAAgB,aAAa,IAAI,IAAI,CAKpC"}
@@ -0,0 +1,67 @@
1
+ import * as envRegistry from "./env-registry.js";
2
+ import { logger } from "./logger.js";
3
+ const HEARTBEAT_INTERVAL_MS = 30_000;
4
+ const adapters = new Map();
5
+ const connections = new Map();
6
+ let heartbeatInterval = undefined;
7
+ /** Register an environment adapter so it can be looked up by type. */
8
+ export function registerAdapter(adapter) {
9
+ adapters.set(adapter.type, adapter);
10
+ }
11
+ /** Retrieve a registered adapter by its type name. */
12
+ export function getAdapter(type) {
13
+ return adapters.get(type);
14
+ }
15
+ /** Store an active PowerLine connection for an environment. */
16
+ export function setConnection(environmentId, conn) {
17
+ connections.set(environmentId, conn);
18
+ }
19
+ /** Get the active PowerLine connection for an environment, if connected. */
20
+ export function getConnection(environmentId) {
21
+ return connections.get(environmentId);
22
+ }
23
+ /** Remove the stored connection for an environment. */
24
+ export function removeConnection(environmentId) {
25
+ connections.delete(environmentId);
26
+ }
27
+ /** Return the map of all active environment connections. */
28
+ export function listConnections() {
29
+ return connections;
30
+ }
31
+ /** Start a periodic health-check loop that calls `onDisconnect` when a PowerLine becomes unreachable. */
32
+ export function startHeartbeat(onDisconnect) {
33
+ if (heartbeatInterval !== undefined) {
34
+ return;
35
+ }
36
+ heartbeatInterval = setInterval(async () => {
37
+ for (const [environmentId, conn] of connections) {
38
+ const env = envRegistry.getEnvironment(environmentId);
39
+ if (!env) {
40
+ continue;
41
+ }
42
+ const adapter = adapters.get(env.adapterType);
43
+ if (!adapter) {
44
+ continue;
45
+ }
46
+ try {
47
+ const ok = await adapter.healthCheck(conn);
48
+ if (!ok) {
49
+ logger.warn({ environmentId }, "Health check failed");
50
+ onDisconnect(environmentId);
51
+ }
52
+ }
53
+ catch {
54
+ logger.warn({ environmentId }, "Connection lost");
55
+ onDisconnect(environmentId);
56
+ }
57
+ }
58
+ }, HEARTBEAT_INTERVAL_MS);
59
+ }
60
+ /** Stop the periodic health-check loop. */
61
+ export function stopHeartbeat() {
62
+ if (heartbeatInterval !== undefined) {
63
+ clearInterval(heartbeatInterval);
64
+ heartbeatInterval = undefined;
65
+ }
66
+ }
67
+ //# sourceMappingURL=adapter-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapter-manager.js","sourceRoot":"","sources":["../src/adapter-manager.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,WAAW,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,MAAM,qBAAqB,GAAW,MAAM,CAAC;AAE7C,MAAM,QAAQ,GAAoC,IAAI,GAAG,EAA8B,CAAC;AACxF,MAAM,WAAW,GAAqC,IAAI,GAAG,EAA+B,CAAC;AAC7F,IAAI,iBAAiB,GAA+C,SAAS,CAAC;AAE9E,sEAAsE;AACtE,MAAM,UAAU,eAAe,CAAC,OAA2B;IACzD,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;AACtC,CAAC;AAED,sDAAsD;AACtD,MAAM,UAAU,UAAU,CAAC,IAAY;IACrC,OAAO,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AAC5B,CAAC;AAED,+DAA+D;AAC/D,MAAM,UAAU,aAAa,CAAC,aAAqB,EAAE,IAAyB;IAC5E,WAAW,CAAC,GAAG,CAAC,aAAa,EAAE,IAAI,CAAC,CAAC;AACvC,CAAC;AAED,4EAA4E;AAC5E,MAAM,UAAU,aAAa,CAAC,aAAqB;IACjD,OAAO,WAAW,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;AACxC,CAAC;AAED,uDAAuD;AACvD,MAAM,UAAU,gBAAgB,CAAC,aAAqB;IACpD,WAAW,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;AACpC,CAAC;AAED,4DAA4D;AAC5D,MAAM,UAAU,eAAe;IAC7B,OAAO,WAAW,CAAC;AACrB,CAAC;AAED,yGAAyG;AACzG,MAAM,UAAU,cAAc,CAAC,YAA6C;IAC1E,IAAI,iBAAiB,KAAK,SAAS,EAAE,CAAC;QACpC,OAAO;IACT,CAAC;IAED,iBAAiB,GAAG,WAAW,CAAC,KAAK,IAAI,EAAE;QACzC,KAAK,MAAM,CAAC,aAAa,EAAE,IAAI,CAAC,IAAI,WAAW,EAAE,CAAC;YAChD,MAAM,GAAG,GAAG,WAAW,CAAC,cAAc,CAAC,aAAa,CAAC,CAAC;YACtD,IAAI,CAAC,GAAG,EAAE,CAAC;gBACT,SAAS;YACX,CAAC;YACD,MAAM,OAAO,GAAG,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;YAC9C,IAAI,CAAC,OAAO,EAAE,CAAC;gBACb,SAAS;YACX,CAAC;YAED,IAAI,CAAC;gBACH,MAAM,EAAE,GAAG,MAAM,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;gBAC3C,IAAI,CAAC,EAAE,EAAE,CAAC;oBACR,MAAM,CAAC,IAAI,CAAC,EAAE,aAAa,EAAE,EAAE,qBAAqB,CAAC,CAAC;oBACtD,YAAY,CAAC,aAAa,CAAC,CAAC;gBAC9B,CAAC;YACH,CAAC;YAAC,MAAM,CAAC;gBACP,MAAM,CAAC,IAAI,CAAC,EAAE,aAAa,EAAE,EAAE,iBAAiB,CAAC,CAAC;gBAClD,YAAY,CAAC,aAAa,CAAC,CAAC;YAC9B,CAAC;QACH,CAAC;IACH,CAAC,EAAE,qBAAqB,CAAC,CAAC;AAC5B,CAAC;AAED,2CAA2C;AAC3C,MAAM,UAAU,aAAa;IAC3B,IAAI,iBAAiB,KAAK,SAAS,EAAE,CAAC;QACpC,aAAa,CAAC,iBAAiB,CAAC,CAAC;QACjC,iBAAiB,GAAG,SAAS,CAAC;IAChC,CAAC;AACH,CAAC"}
@@ -0,0 +1,40 @@
1
+ import type { Client } from "@connectrpc/connect";
2
+ import type { powerline } from "@grackle-ai/common";
3
+ /** Type-safe ConnectRPC client for the PowerLine gRPC service. */
4
+ export type PowerLineClient = Client<typeof powerline.GracklePowerLine>;
5
+ /** An active connection to a PowerLine, including the gRPC client and port info. */
6
+ export interface PowerLineConnection {
7
+ client: PowerLineClient;
8
+ environmentId: string;
9
+ port: number;
10
+ }
11
+ /** Progress event emitted during environment provisioning. */
12
+ export interface ProvisionEvent {
13
+ stage: string;
14
+ message: string;
15
+ progress: number;
16
+ }
17
+ /** Base configuration shared by all environment adapters. */
18
+ export interface BaseEnvironmentConfig {
19
+ /** Override the default PowerLine port. */
20
+ port?: number;
21
+ /** Override the host to connect to. */
22
+ host?: string;
23
+ }
24
+ /** Contract that all environment adapter backends must implement. */
25
+ export interface EnvironmentAdapter {
26
+ type: string;
27
+ /** Provision infrastructure and yield progress events. */
28
+ provision(environmentId: string, config: Record<string, unknown>, powerlineToken: string): AsyncGenerator<ProvisionEvent>;
29
+ /** Establish a gRPC connection to the PowerLine running in the environment. */
30
+ connect(environmentId: string, config: Record<string, unknown>, powerlineToken: string): Promise<PowerLineConnection>;
31
+ /** Release resources associated with a connection without stopping the environment. */
32
+ disconnect(environmentId: string): Promise<void>;
33
+ /** Stop the environment's underlying compute (e.g. stop a Docker container). */
34
+ stop(environmentId: string, config: Record<string, unknown>): Promise<void>;
35
+ /** Permanently destroy the environment's underlying compute. */
36
+ destroy(environmentId: string, config: Record<string, unknown>): Promise<void>;
37
+ /** Return true if the PowerLine is reachable via ping. */
38
+ healthCheck(connection: PowerLineConnection): Promise<boolean>;
39
+ }
40
+ //# sourceMappingURL=adapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../../src/adapters/adapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAEpD,kEAAkE;AAClE,MAAM,MAAM,eAAe,GAAG,MAAM,CAAC,OAAO,SAAS,CAAC,gBAAgB,CAAC,CAAC;AAExE,oFAAoF;AACpF,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,eAAe,CAAC;IACxB,aAAa,EAAE,MAAM,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,8DAA8D;AAC9D,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,6DAA6D;AAC7D,MAAM,WAAW,qBAAqB;IACpC,2CAA2C;IAC3C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,uCAAuC;IACvC,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,qEAAqE;AACrE,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IAEb,0DAA0D;IAC1D,SAAS,CAAC,aAAa,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,cAAc,EAAE,MAAM,GAAG,cAAc,CAAC,cAAc,CAAC,CAAC;IAC1H,+EAA+E;IAC/E,OAAO,CAAC,aAAa,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAAC;IACtH,uFAAuF;IACvF,UAAU,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACjD,gFAAgF;IAChF,IAAI,CAAC,aAAa,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5E,gEAAgE;IAChE,OAAO,CAAC,aAAa,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/E,0DAA0D;IAC1D,WAAW,CAAC,UAAU,EAAE,mBAAmB,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CAChE"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=adapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapter.js","sourceRoot":"","sources":["../../src/adapters/adapter.ts"],"names":[],"mappings":""}
@@ -0,0 +1,26 @@
1
+ import type { EnvironmentAdapter, BaseEnvironmentConfig, PowerLineConnection, ProvisionEvent } from "./adapter.js";
2
+ /** Docker-specific environment configuration. */
3
+ export interface DockerEnvironmentConfig extends BaseEnvironmentConfig {
4
+ image: string;
5
+ containerName?: string;
6
+ localPort?: number;
7
+ volumes?: string[];
8
+ env?: Record<string, string>;
9
+ /** Git repo URL to clone into the container workspace. */
10
+ repo?: string;
11
+ /** Enable GPU passthrough (e.g. "all" for --gpus all). */
12
+ gpus?: string;
13
+ }
14
+ /** Environment adapter that provisions and manages Docker containers running the PowerLine. */
15
+ export declare class DockerAdapter implements EnvironmentAdapter {
16
+ type: string;
17
+ provision(environmentId: string, config: Record<string, unknown>, powerlineToken: string): AsyncGenerator<ProvisionEvent>;
18
+ connect(environmentId: string, config: Record<string, unknown>, powerlineToken: string): Promise<PowerLineConnection>;
19
+ disconnect(environmentId: string): Promise<void>;
20
+ stop(environmentId: string, config: Record<string, unknown>): Promise<void>;
21
+ destroy(environmentId: string, config: Record<string, unknown>): Promise<void>;
22
+ healthCheck(connection: PowerLineConnection): Promise<boolean>;
23
+ /** Build the `docker run` argument array from config and token. */
24
+ private buildRunArgs;
25
+ }
26
+ //# sourceMappingURL=docker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"docker.d.ts","sourceRoot":"","sources":["../../src/adapters/docker.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAmBnH,iDAAiD;AACjD,MAAM,WAAW,uBAAwB,SAAQ,qBAAqB;IACpE,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,0DAA0D;IAC1D,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,0DAA0D;IAC1D,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAgID,+FAA+F;AAC/F,qBAAa,aAAc,YAAW,kBAAkB;IAC/C,IAAI,EAAE,MAAM,CAAY;IAEjB,SAAS,CAAC,aAAa,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,cAAc,EAAE,MAAM,GAAG,cAAc,CAAC,cAAc,CAAC;IAkC1H,OAAO,CAAC,aAAa,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAoBrH,UAAU,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIhD,IAAI,CAAC,aAAa,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAW3E,OAAO,CAAC,aAAa,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAW9E,WAAW,CAAC,UAAU,EAAE,mBAAmB,GAAG,OAAO,CAAC,OAAO,CAAC;IAS3E,mEAAmE;IACnE,OAAO,CAAC,YAAY;CAqErB"}
@@ -0,0 +1,274 @@
1
+ import { DEFAULT_POWERLINE_PORT } from "@grackle-ai/common";
2
+ import { createPowerLineClient } from "./powerline-transport.js";
3
+ import { exec } from "../utils/exec.js";
4
+ import { findFreePort } from "../utils/ports.js";
5
+ import { sleep } from "../utils/sleep.js";
6
+ import { readFileSync } from "node:fs";
7
+ import { join } from "node:path";
8
+ import { homedir } from "node:os";
9
+ import { logger } from "../logger.js";
10
+ const DOCKER_PULL_TIMEOUT_MS = 120_000;
11
+ const GIT_CLONE_TIMEOUT_MS = 120_000;
12
+ const GIT_PULL_TIMEOUT_MS = 60_000;
13
+ const CONTAINER_POLL_DELAY_MS = 1_000;
14
+ const CONTAINER_POLL_MAX_ATTEMPTS = 30;
15
+ const CONNECT_RETRY_DELAY_MS = 1_500;
16
+ const CONNECT_MAX_RETRIES = 10;
17
+ const WORKSPACE_PATH = "/workspace";
18
+ const containerPorts = new Map();
19
+ // ─── Docker CLI Helpers ────────────────────────────────────
20
+ /** Pull a Docker image, suppressing errors if the image exists locally. */
21
+ async function pullImage(image) {
22
+ try {
23
+ await exec("docker", ["pull", image], { timeout: DOCKER_PULL_TIMEOUT_MS });
24
+ return true;
25
+ }
26
+ catch {
27
+ logger.debug({ image }, "Docker pull failed, trying local image");
28
+ return false;
29
+ }
30
+ }
31
+ /** Start a new Docker container with the given arguments. Returns true if created; false if it already existed. */
32
+ async function createOrStartContainer(containerName, runArgs) {
33
+ try {
34
+ await exec("docker", ["inspect", containerName]);
35
+ // Container exists — just start it
36
+ await exec("docker", ["start", containerName]);
37
+ return false;
38
+ }
39
+ catch {
40
+ // Container doesn't exist — create it
41
+ await exec("docker", runArgs);
42
+ return true;
43
+ }
44
+ }
45
+ /** Discover the host-mapped port of an existing container. */
46
+ async function discoverHostPort(containerName, containerPort, fallback) {
47
+ try {
48
+ const { stdout } = await exec("docker", [
49
+ "inspect", "-f",
50
+ `{{(index (index .NetworkSettings.Ports "${containerPort}/tcp") 0).HostPort}}`,
51
+ containerName,
52
+ ]);
53
+ const parsed = parseInt(stdout, 10);
54
+ if (!isNaN(parsed)) {
55
+ return parsed;
56
+ }
57
+ }
58
+ catch {
59
+ logger.debug({ containerName }, "Could not discover host port, using fallback");
60
+ }
61
+ return fallback;
62
+ }
63
+ /** Poll until a Docker container reaches the Running state. */
64
+ async function waitForContainerRunning(containerName) {
65
+ for (let i = 0; i < CONTAINER_POLL_MAX_ATTEMPTS; i++) {
66
+ try {
67
+ const { stdout } = await exec("docker", ["inspect", "-f", "{{.State.Running}}", containerName]);
68
+ if (stdout === "true") {
69
+ return;
70
+ }
71
+ }
72
+ catch {
73
+ logger.debug({ containerName, attempt: i }, "Container not yet running");
74
+ }
75
+ await sleep(CONTAINER_POLL_DELAY_MS);
76
+ }
77
+ }
78
+ /** Clone or pull a git repo inside a container's workspace. */
79
+ async function ensureRepoInContainer(containerName, repo) {
80
+ // Check if already cloned
81
+ try {
82
+ const { stdout } = await exec("docker", [
83
+ "exec", containerName, "bash", "-c", `ls ${WORKSPACE_PATH}/.git 2>/dev/null && echo exists`,
84
+ ]);
85
+ if (stdout.includes("exists")) {
86
+ await exec("docker", [
87
+ "exec", "-w", WORKSPACE_PATH, containerName, "git", "pull", "--ff-only",
88
+ ], { timeout: GIT_PULL_TIMEOUT_MS }).catch((err) => {
89
+ logger.warn({ containerName, err }, "Git pull failed (may be detached HEAD)");
90
+ });
91
+ return;
92
+ }
93
+ }
94
+ catch {
95
+ // Not cloned — proceed to clone below
96
+ }
97
+ const ghToken = await getGitHubToken();
98
+ const cloneUrl = repo.startsWith("https://") ? repo : `https://github.com/${repo}.git`;
99
+ if (ghToken) {
100
+ await exec("docker", [
101
+ "exec", containerName, "git", "config", "--global",
102
+ "credential.helper", `!f() { echo "username=x-access-token"; echo "password=${ghToken}"; }; f`,
103
+ ]);
104
+ await exec("docker", [
105
+ "exec", containerName, "git", "clone", cloneUrl, WORKSPACE_PATH,
106
+ ], { timeout: GIT_CLONE_TIMEOUT_MS });
107
+ await exec("docker", [
108
+ "exec", containerName, "git", "config", "--global", "--unset", "credential.helper",
109
+ ]).catch((err) => {
110
+ logger.warn({ err }, "Failed to unset credential helper");
111
+ });
112
+ }
113
+ else {
114
+ await exec("docker", [
115
+ "exec", containerName, "git", "clone", cloneUrl, WORKSPACE_PATH,
116
+ ], { timeout: GIT_CLONE_TIMEOUT_MS });
117
+ }
118
+ }
119
+ /** Validate that a token contains only safe characters (alphanumeric, underscore, hyphen). */
120
+ const SAFE_TOKEN_PATTERN = /^[a-zA-Z0-9_\-]+$/;
121
+ /** Get a GitHub token from the local `gh` CLI for private repo cloning. */
122
+ async function getGitHubToken() {
123
+ try {
124
+ const { stdout } = await exec("gh", ["auth", "token"]);
125
+ if (!stdout) {
126
+ return undefined;
127
+ }
128
+ if (!SAFE_TOKEN_PATTERN.test(stdout)) {
129
+ logger.warn("GitHub token contains unexpected characters, skipping credential setup");
130
+ return undefined;
131
+ }
132
+ return stdout;
133
+ }
134
+ catch {
135
+ return undefined;
136
+ }
137
+ }
138
+ // ─── Docker Adapter ────────────────────────────────────────
139
+ /** Environment adapter that provisions and manages Docker containers running the PowerLine. */
140
+ export class DockerAdapter {
141
+ type = "docker";
142
+ async *provision(environmentId, config, powerlineToken) {
143
+ const cfg = config;
144
+ const image = cfg.image || "grackle-powerline:latest";
145
+ const containerName = cfg.containerName || `grackle-${environmentId}`;
146
+ const localPort = cfg.localPort || await findFreePort();
147
+ yield { stage: "creating", message: `Pulling image ${image}...`, progress: 0.1 };
148
+ await pullImage(image);
149
+ yield { stage: "creating", message: `Creating container ${containerName}...`, progress: 0.3 };
150
+ const runArgs = this.buildRunArgs(containerName, localPort, image, cfg, powerlineToken);
151
+ const isNew = await createOrStartContainer(containerName, runArgs);
152
+ let actualPort = localPort;
153
+ if (!isNew) {
154
+ yield { stage: "starting", message: "Container exists, starting...", progress: 0.4 };
155
+ actualPort = await discoverHostPort(containerName, DEFAULT_POWERLINE_PORT, localPort);
156
+ }
157
+ containerPorts.set(environmentId, actualPort);
158
+ yield { stage: "starting", message: "Waiting for container...", progress: 0.5 };
159
+ await waitForContainerRunning(containerName);
160
+ if (cfg.repo) {
161
+ yield { stage: "cloning", message: `Cloning ${cfg.repo}...`, progress: 0.6 };
162
+ await ensureRepoInContainer(containerName, cfg.repo);
163
+ yield { stage: "cloning", message: "Repo ready", progress: 0.75 };
164
+ }
165
+ yield { stage: "connecting", message: `Connecting on port ${actualPort}...`, progress: 0.8 };
166
+ }
167
+ async connect(environmentId, config, powerlineToken) {
168
+ const cfg = config;
169
+ const localPort = containerPorts.get(environmentId) || cfg.localPort || DEFAULT_POWERLINE_PORT;
170
+ const client = createPowerLineClient(`http://127.0.0.1:${localPort}`, powerlineToken);
171
+ let lastErr;
172
+ for (let attempt = 0; attempt < CONNECT_MAX_RETRIES; attempt++) {
173
+ try {
174
+ await client.ping({});
175
+ return { client, environmentId, port: localPort };
176
+ }
177
+ catch (err) {
178
+ lastErr = err;
179
+ await sleep(CONNECT_RETRY_DELAY_MS);
180
+ }
181
+ }
182
+ throw new Error(`Could not reach PowerLine after ${CONNECT_MAX_RETRIES} attempts: ${lastErr}`);
183
+ }
184
+ async disconnect(environmentId) {
185
+ containerPorts.delete(environmentId);
186
+ }
187
+ async stop(environmentId, config) {
188
+ const cfg = config;
189
+ const containerName = cfg.containerName || `grackle-${environmentId}`;
190
+ try {
191
+ await exec("docker", ["stop", containerName]);
192
+ }
193
+ catch (err) {
194
+ logger.debug({ environmentId, err }, "Container may already be stopped");
195
+ }
196
+ containerPorts.delete(environmentId);
197
+ }
198
+ async destroy(environmentId, config) {
199
+ const cfg = config;
200
+ const containerName = cfg.containerName || `grackle-${environmentId}`;
201
+ try {
202
+ await exec("docker", ["rm", "-f", containerName]);
203
+ }
204
+ catch (err) {
205
+ logger.debug({ environmentId, err }, "Container may not exist");
206
+ }
207
+ containerPorts.delete(environmentId);
208
+ }
209
+ async healthCheck(connection) {
210
+ try {
211
+ await connection.client.ping({});
212
+ return true;
213
+ }
214
+ catch {
215
+ return false;
216
+ }
217
+ }
218
+ /** Build the `docker run` argument array from config and token. */
219
+ buildRunArgs(containerName, localPort, image, cfg, powerlineToken) {
220
+ const args = [
221
+ "run", "-d",
222
+ "--name", containerName,
223
+ "-p", `127.0.0.1:${localPort}:${DEFAULT_POWERLINE_PORT}`,
224
+ ];
225
+ if (cfg.volumes) {
226
+ for (const vol of cfg.volumes) {
227
+ args.push("-v", vol);
228
+ }
229
+ }
230
+ if (cfg.env) {
231
+ for (const [key, val] of Object.entries(cfg.env)) {
232
+ args.push("-e", `${key}=${val}`);
233
+ }
234
+ }
235
+ // Forward ANTHROPIC_API_KEY if set on host
236
+ if (process.env.ANTHROPIC_API_KEY && !cfg.env?.ANTHROPIC_API_KEY) {
237
+ args.push("-e", `ANTHROPIC_API_KEY=${process.env.ANTHROPIC_API_KEY}`);
238
+ }
239
+ // Forward GitHub tokens for Copilot runtime
240
+ for (const tokenVar of ["GITHUB_TOKEN", "GH_TOKEN", "COPILOT_GITHUB_TOKEN"]) {
241
+ if (process.env[tokenVar] && !cfg.env?.[tokenVar]) {
242
+ args.push("-e", `${tokenVar}=${process.env[tokenVar]}`);
243
+ }
244
+ }
245
+ // Forward Copilot-specific configuration environment variables
246
+ for (const envVar of ["COPILOT_CLI_URL", "COPILOT_CLI_PATH", "COPILOT_PROVIDER_CONFIG"]) {
247
+ if (process.env[envVar] && !cfg.env?.[envVar]) {
248
+ args.push("-e", `${envVar}=${process.env[envVar]}`);
249
+ }
250
+ }
251
+ // Pass PowerLine token for authentication
252
+ if (powerlineToken) {
253
+ args.push("-e", `GRACKLE_POWERLINE_TOKEN=${powerlineToken}`);
254
+ }
255
+ // Mount Claude Code credentials for subscription auth
256
+ const hostCredsPath = join(homedir(), ".claude", ".credentials.json");
257
+ try {
258
+ readFileSync(hostCredsPath); // verify it exists
259
+ args.push("-v", `${hostCredsPath}:/home/grackle/.claude/.credentials.json:ro`);
260
+ }
261
+ catch {
262
+ logger.debug("No Claude credentials file found, skipping mount");
263
+ }
264
+ // Chromium needs >64MB shared memory for rendering
265
+ args.push("--shm-size=1gb");
266
+ // GPU passthrough for accelerated inference (e.g. TTS, ML models)
267
+ if (cfg.gpus) {
268
+ args.push("--gpus", cfg.gpus);
269
+ }
270
+ args.push(image);
271
+ return args;
272
+ }
273
+ }
274
+ //# sourceMappingURL=docker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"docker.js","sourceRoot":"","sources":["../../src/adapters/docker.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ import type { EnvironmentAdapter, BaseEnvironmentConfig, PowerLineConnection, ProvisionEvent } from "./adapter.js";
2
+ /** Local-specific environment configuration. */
3
+ export interface LocalEnvironmentConfig extends BaseEnvironmentConfig {
4
+ }
5
+ /** Environment adapter that connects to a locally-running PowerLine process. */
6
+ export declare class LocalAdapter implements EnvironmentAdapter {
7
+ type: string;
8
+ provision(environmentId: string, config: Record<string, unknown>, powerlineToken: string): AsyncGenerator<ProvisionEvent>;
9
+ connect(environmentId: string, config: Record<string, unknown>, powerlineToken: string): Promise<PowerLineConnection>;
10
+ disconnect(): Promise<void>;
11
+ stop(): Promise<void>;
12
+ destroy(): Promise<void>;
13
+ healthCheck(connection: PowerLineConnection): Promise<boolean>;
14
+ }
15
+ //# sourceMappingURL=local.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"local.d.ts","sourceRoot":"","sources":["../../src/adapters/local.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAOnH,gDAAgD;AAChD,MAAM,WAAW,sBAAuB,SAAQ,qBAAqB;CAEpE;AAED,gFAAgF;AAChF,qBAAa,YAAa,YAAW,kBAAkB;IAC9C,IAAI,EAAE,MAAM,CAAW;IAEhB,SAAS,CAAC,aAAa,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,cAAc,EAAE,MAAM,GAAG,cAAc,CAAC,cAAc,CAAC;IAyB1H,OAAO,CAAC,aAAa,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAWrH,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAI3B,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAIrB,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAIxB,WAAW,CAAC,UAAU,EAAE,mBAAmB,GAAG,OAAO,CAAC,OAAO,CAAC;CAQ5E"}
@@ -0,0 +1,57 @@
1
+ import { DEFAULT_POWERLINE_PORT } from "@grackle-ai/common";
2
+ import { createPowerLineClient } from "./powerline-transport.js";
3
+ import { sleep } from "../utils/sleep.js";
4
+ const POWERLINE_RETRY_DELAY_MS = 1_000;
5
+ const POWERLINE_MAX_RETRIES = 5;
6
+ /** Environment adapter that connects to a locally-running PowerLine process. */
7
+ export class LocalAdapter {
8
+ type = "local";
9
+ async *provision(environmentId, config, powerlineToken) {
10
+ const cfg = config;
11
+ const port = cfg.port || DEFAULT_POWERLINE_PORT;
12
+ const host = cfg.host || "localhost";
13
+ yield { stage: "connecting", message: `Connecting to PowerLine at ${host}:${port}...`, progress: 0.5 };
14
+ const client = createPowerLineClient(`http://${host}:${port}`, powerlineToken);
15
+ let lastErr;
16
+ for (let attempt = 0; attempt < POWERLINE_MAX_RETRIES; attempt++) {
17
+ try {
18
+ await client.ping({});
19
+ yield { stage: "ready", message: "Connected to local PowerLine", progress: 1 };
20
+ return;
21
+ }
22
+ catch (err) {
23
+ lastErr = err;
24
+ yield { stage: "connecting", message: `Waiting for PowerLine (attempt ${attempt + 1}/${POWERLINE_MAX_RETRIES})...`, progress: 0.5 + attempt * 0.1 };
25
+ await sleep(POWERLINE_RETRY_DELAY_MS);
26
+ }
27
+ }
28
+ yield { stage: "error", message: `Could not reach PowerLine: ${lastErr}`, progress: 0 };
29
+ }
30
+ async connect(environmentId, config, powerlineToken) {
31
+ const cfg = config;
32
+ const port = cfg.port || DEFAULT_POWERLINE_PORT;
33
+ const host = cfg.host || "localhost";
34
+ const client = createPowerLineClient(`http://${host}:${port}`, powerlineToken);
35
+ await client.ping({});
36
+ return { client, environmentId, port };
37
+ }
38
+ async disconnect() {
39
+ // Nothing to clean up for local connections
40
+ }
41
+ async stop() {
42
+ // Local PowerLine lifecycle is managed externally
43
+ }
44
+ async destroy() {
45
+ // Local PowerLine lifecycle is managed externally
46
+ }
47
+ async healthCheck(connection) {
48
+ try {
49
+ await connection.client.ping({});
50
+ return true;
51
+ }
52
+ catch {
53
+ return false;
54
+ }
55
+ }
56
+ }
57
+ //# sourceMappingURL=local.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"local.js","sourceRoot":"","sources":["../../src/adapters/local.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AAE5D,OAAO,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAE1C,MAAM,wBAAwB,GAAW,KAAK,CAAC;AAC/C,MAAM,qBAAqB,GAAW,CAAC,CAAC;AAOxC,gFAAgF;AAChF,MAAM,OAAO,YAAY;IAChB,IAAI,GAAW,OAAO,CAAC;IAEvB,KAAK,CAAC,CAAC,SAAS,CAAC,aAAqB,EAAE,MAA+B,EAAE,cAAsB;QACpG,MAAM,GAAG,GAAG,MAA2C,CAAC;QACxD,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,IAAI,sBAAsB,CAAC;QAChD,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,IAAI,WAAW,CAAC;QAErC,MAAM,EAAE,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,8BAA8B,IAAI,IAAI,IAAI,KAAK,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC;QAEvG,MAAM,MAAM,GAAG,qBAAqB,CAAC,UAAU,IAAI,IAAI,IAAI,EAAE,EAAE,cAAc,CAAC,CAAC;QAE/E,IAAI,OAAgB,CAAC;QACrB,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,GAAG,qBAAqB,EAAE,OAAO,EAAE,EAAE,CAAC;YACjE,IAAI,CAAC;gBACH,MAAM,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;gBACtB,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,8BAA8B,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC;gBAC/E,OAAO;YACT,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,OAAO,GAAG,GAAG,CAAC;gBACd,MAAM,EAAE,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,kCAAkC,OAAO,GAAG,CAAC,IAAI,qBAAqB,MAAM,EAAE,QAAQ,EAAE,GAAG,GAAG,OAAO,GAAG,GAAG,EAAE,CAAC;gBACpJ,MAAM,KAAK,CAAC,wBAAwB,CAAC,CAAC;YACxC,CAAC;QACH,CAAC;QAED,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,8BAA8B,OAAO,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC;IAC1F,CAAC;IAEM,KAAK,CAAC,OAAO,CAAC,aAAqB,EAAE,MAA+B,EAAE,cAAsB;QACjG,MAAM,GAAG,GAAG,MAA2C,CAAC;QACxD,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,IAAI,sBAAsB,CAAC;QAChD,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,IAAI,WAAW,CAAC;QAErC,MAAM,MAAM,GAAG,qBAAqB,CAAC,UAAU,IAAI,IAAI,IAAI,EAAE,EAAE,cAAc,CAAC,CAAC;QAC/E,MAAM,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAEtB,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC;IACzC,CAAC;IAEM,KAAK,CAAC,UAAU;QACrB,4CAA4C;IAC9C,CAAC;IAEM,KAAK,CAAC,IAAI;QACf,kDAAkD;IACpD,CAAC;IAEM,KAAK,CAAC,OAAO;QAClB,kDAAkD;IACpD,CAAC;IAEM,KAAK,CAAC,WAAW,CAAC,UAA+B;QACtD,IAAI,CAAC;YACH,MAAM,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACjC,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;CACF"}
@@ -0,0 +1,7 @@
1
+ import type { PowerLineClient } from "./adapter.js";
2
+ /**
3
+ * Create an authenticated gRPC client for a PowerLine.
4
+ * The PowerLine token is sent as a Bearer token on every request.
5
+ */
6
+ export declare function createPowerLineClient(baseUrl: string, powerlineToken: string): PowerLineClient;
7
+ //# sourceMappingURL=powerline-transport.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"powerline-transport.d.ts","sourceRoot":"","sources":["../../src/adapters/powerline-transport.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAEpD;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,eAAe,CAa9F"}
@@ -0,0 +1,22 @@
1
+ import { createClient } from "@connectrpc/connect";
2
+ import { createGrpcTransport } from "@connectrpc/connect-node";
3
+ import { powerline } from "@grackle-ai/common";
4
+ /**
5
+ * Create an authenticated gRPC client for a PowerLine.
6
+ * The PowerLine token is sent as a Bearer token on every request.
7
+ */
8
+ export function createPowerLineClient(baseUrl, powerlineToken) {
9
+ const transport = createGrpcTransport({
10
+ baseUrl,
11
+ interceptors: powerlineToken
12
+ ? [
13
+ (next) => async (req) => {
14
+ req.header.set("Authorization", `Bearer ${powerlineToken}`);
15
+ return next(req);
16
+ },
17
+ ]
18
+ : [],
19
+ });
20
+ return createClient(powerline.GracklePowerLine, transport);
21
+ }
22
+ //# sourceMappingURL=powerline-transport.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"powerline-transport.js","sourceRoot":"","sources":["../../src/adapters/powerline-transport.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAG/C;;;GAGG;AACH,MAAM,UAAU,qBAAqB,CAAC,OAAe,EAAE,cAAsB;IAC3E,MAAM,SAAS,GAAG,mBAAmB,CAAC;QACpC,OAAO;QACP,YAAY,EAAE,cAAc;YAC1B,CAAC,CAAC;gBACE,CAAC,IAAI,EAAE,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE;oBACtB,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,eAAe,EAAE,UAAU,cAAc,EAAE,CAAC,CAAC;oBAC5D,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC;gBACnB,CAAC;aACF;YACH,CAAC,CAAC,EAAE;KACP,CAAC,CAAC;IACH,OAAO,YAAY,CAAC,SAAS,CAAC,gBAAgB,EAAE,SAAS,CAAC,CAAC;AAC7D,CAAC"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Load or create the API key. On first run, a random 256-bit key is
3
+ * generated and written to ~/.grackle/api-key with 0600 permissions.
4
+ */
5
+ export declare function loadOrCreateApiKey(): string;
6
+ /** Verify a bearer token matches the API key. */
7
+ export declare function verifyApiKey(token: string): boolean;
8
+ //# sourceMappingURL=api-key.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-key.d.ts","sourceRoot":"","sources":["../src/api-key.ts"],"names":[],"mappings":"AAwCA;;;GAGG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,CAO3C;AAED,iDAAiD;AACjD,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAYnD"}