@electric-agent/studio 1.0.0 → 1.1.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 (68) hide show
  1. package/dist/active-sessions.d.ts +28 -0
  2. package/dist/active-sessions.d.ts.map +1 -0
  3. package/dist/active-sessions.js +50 -0
  4. package/dist/active-sessions.js.map +1 -0
  5. package/dist/bridge/claude-code-docker.d.ts +59 -0
  6. package/dist/bridge/claude-code-docker.d.ts.map +1 -0
  7. package/dist/bridge/claude-code-docker.js +258 -0
  8. package/dist/bridge/claude-code-docker.js.map +1 -0
  9. package/dist/bridge/claude-code-sprites.d.ts +49 -0
  10. package/dist/bridge/claude-code-sprites.d.ts.map +1 -0
  11. package/dist/bridge/claude-code-sprites.js +231 -0
  12. package/dist/bridge/claude-code-sprites.js.map +1 -0
  13. package/dist/bridge/claude-md-generator.d.ts +24 -0
  14. package/dist/bridge/claude-md-generator.d.ts.map +1 -0
  15. package/dist/bridge/claude-md-generator.js +299 -0
  16. package/dist/bridge/claude-md-generator.js.map +1 -0
  17. package/dist/bridge/index.d.ts +3 -0
  18. package/dist/bridge/index.d.ts.map +1 -1
  19. package/dist/bridge/index.js +3 -0
  20. package/dist/bridge/index.js.map +1 -1
  21. package/dist/bridge/stream-json-parser.d.ts +30 -0
  22. package/dist/bridge/stream-json-parser.d.ts.map +1 -0
  23. package/dist/bridge/stream-json-parser.js +207 -0
  24. package/dist/bridge/stream-json-parser.js.map +1 -0
  25. package/dist/client/assets/index-BeZ6CTGd.css +1 -0
  26. package/dist/client/assets/index-DRLXdDNp.js +241 -0
  27. package/dist/client/index.html +2 -2
  28. package/dist/index.d.ts +5 -1
  29. package/dist/index.d.ts.map +1 -1
  30. package/dist/index.js +4 -1
  31. package/dist/index.js.map +1 -1
  32. package/dist/project-utils.d.ts +2 -1
  33. package/dist/project-utils.d.ts.map +1 -1
  34. package/dist/project-utils.js +2 -6
  35. package/dist/project-utils.js.map +1 -1
  36. package/dist/registry.d.ts +52 -0
  37. package/dist/registry.d.ts.map +1 -0
  38. package/dist/registry.js +204 -0
  39. package/dist/registry.js.map +1 -0
  40. package/dist/room-registry.d.ts +40 -0
  41. package/dist/room-registry.d.ts.map +1 -0
  42. package/dist/room-registry.js +112 -0
  43. package/dist/room-registry.js.map +1 -0
  44. package/dist/sandbox/sprites-bootstrap.d.ts.map +1 -1
  45. package/dist/sandbox/sprites-bootstrap.js +7 -1
  46. package/dist/sandbox/sprites-bootstrap.js.map +1 -1
  47. package/dist/sandbox/sprites.d.ts +5 -0
  48. package/dist/sandbox/sprites.d.ts.map +1 -1
  49. package/dist/sandbox/sprites.js +22 -2
  50. package/dist/sandbox/sprites.js.map +1 -1
  51. package/dist/server.d.ts +9 -2
  52. package/dist/server.d.ts.map +1 -1
  53. package/dist/server.js +616 -58
  54. package/dist/server.js.map +1 -1
  55. package/dist/sessions.d.ts +2 -0
  56. package/dist/sessions.d.ts.map +1 -1
  57. package/dist/sessions.js.map +1 -1
  58. package/dist/shared-sessions.d.ts +16 -0
  59. package/dist/shared-sessions.d.ts.map +1 -0
  60. package/dist/shared-sessions.js +52 -0
  61. package/dist/shared-sessions.js.map +1 -0
  62. package/dist/streams.d.ts +8 -0
  63. package/dist/streams.d.ts.map +1 -1
  64. package/dist/streams.js +22 -0
  65. package/dist/streams.js.map +1 -1
  66. package/package.json +15 -2
  67. package/dist/client/assets/index-CK__1-6e.css +0 -1
  68. package/dist/client/assets/index-DKL-jl7t.js +0 -241
@@ -7,8 +7,8 @@
7
7
  <link rel="icon" type="image/svg+xml" href="/img/brand/favicon.svg" />
8
8
  <link rel="icon" type="image/png" href="/img/brand/favicon.png" />
9
9
  <link rel="shortcut icon" href="/favicon.ico" />
10
- <script type="module" crossorigin src="/assets/index-DKL-jl7t.js"></script>
11
- <link rel="stylesheet" crossorigin href="/assets/index-CK__1-6e.css">
10
+ <script type="module" crossorigin src="/assets/index-DRLXdDNp.js"></script>
11
+ <link rel="stylesheet" crossorigin href="/assets/index-BeZ6CTGd.css">
12
12
  </head>
13
13
  <body>
14
14
  <div id="root"></div>
package/dist/index.d.ts CHANGED
@@ -1,8 +1,12 @@
1
+ export { ActiveSessions } from "./active-sessions.js";
1
2
  export { createGate, rejectAllGates, resolveGate } from "./gate.js";
2
3
  export { resolveProjectDir } from "./project-utils.js";
4
+ export type { RoomInfo } from "./room-registry.js";
5
+ export { RoomRegistry } from "./room-registry.js";
3
6
  export { createApp, startWebServer } from "./server.js";
4
7
  export type { SessionInfo } from "./sessions.js";
5
8
  export { addSession, cleanupStaleSessions, deleteSession, getSession, readSessionIndex, updateSessionInfo, } from "./sessions.js";
9
+ export { generateInviteCode } from "./shared-sessions.js";
6
10
  export type { StreamConfig, StreamConnectionInfo } from "./streams.js";
7
- export { getStreamConfig, getStreamConnectionInfo, getStreamEnvVars } from "./streams.js";
11
+ export { getSharedStreamConnectionInfo, getStreamConfig, getStreamConnectionInfo, getStreamEnvVars, } from "./streams.js";
8
12
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,WAAW,CAAA;AACnE,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAA;AACtD,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AACvD,YAAY,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAChD,OAAO,EACN,UAAU,EACV,oBAAoB,EACpB,aAAa,EACb,UAAU,EACV,gBAAgB,EAChB,iBAAiB,GACjB,MAAM,eAAe,CAAA;AACtB,YAAY,EAAE,YAAY,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAA;AACtE,OAAO,EAAE,eAAe,EAAE,uBAAuB,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AACrD,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,WAAW,CAAA;AACnE,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAA;AACtD,YAAY,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAA;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AACjD,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AACvD,YAAY,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAChD,OAAO,EACN,UAAU,EACV,oBAAoB,EACpB,aAAa,EACb,UAAU,EACV,gBAAgB,EAChB,iBAAiB,GACjB,MAAM,eAAe,CAAA;AACtB,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAA;AACzD,YAAY,EAAE,YAAY,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAA;AACtE,OAAO,EACN,6BAA6B,EAC7B,eAAe,EACf,uBAAuB,EACvB,gBAAgB,GAChB,MAAM,cAAc,CAAA"}
package/dist/index.js CHANGED
@@ -1,6 +1,9 @@
1
+ export { ActiveSessions } from "./active-sessions.js";
1
2
  export { createGate, rejectAllGates, resolveGate } from "./gate.js";
2
3
  export { resolveProjectDir } from "./project-utils.js";
4
+ export { RoomRegistry } from "./room-registry.js";
3
5
  export { createApp, startWebServer } from "./server.js";
4
6
  export { addSession, cleanupStaleSessions, deleteSession, getSession, readSessionIndex, updateSessionInfo, } from "./sessions.js";
5
- export { getStreamConfig, getStreamConnectionInfo, getStreamEnvVars } from "./streams.js";
7
+ export { generateInviteCode } from "./shared-sessions.js";
8
+ export { getSharedStreamConnectionInfo, getStreamConfig, getStreamConnectionInfo, getStreamEnvVars, } from "./streams.js";
6
9
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,WAAW,CAAA;AACnE,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAA;AACtD,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAEvD,OAAO,EACN,UAAU,EACV,oBAAoB,EACpB,aAAa,EACb,UAAU,EACV,gBAAgB,EAChB,iBAAiB,GACjB,MAAM,eAAe,CAAA;AAEtB,OAAO,EAAE,eAAe,EAAE,uBAAuB,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AACrD,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,WAAW,CAAA;AACnE,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAA;AAEtD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AACjD,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAEvD,OAAO,EACN,UAAU,EACV,oBAAoB,EACpB,aAAa,EACb,UAAU,EACV,gBAAgB,EAChB,iBAAiB,GACjB,MAAM,eAAe,CAAA;AACtB,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAA;AAEzD,OAAO,EACN,6BAA6B,EAC7B,eAAe,EACf,uBAAuB,EACvB,gBAAgB,GAChB,MAAM,cAAc,CAAA"}
@@ -1,6 +1,7 @@
1
1
  /**
2
2
  * Resolve a unique project directory name under `baseDir`.
3
- * If the directory already exists, appends a random 4-char hex suffix.
3
+ * Always appends a random 4-char hex suffix to avoid container/volume
4
+ * collisions when Docker compose project names overlap across sessions.
4
5
  */
5
6
  export declare function resolveProjectDir(baseDir: string, name: string): {
6
7
  projectName: string;
@@ -1 +1 @@
1
- {"version":3,"file":"project-utils.d.ts","sourceRoot":"","sources":["../src/project-utils.ts"],"names":[],"mappings":"AAIA;;;GAGG;AACH,wBAAgB,iBAAiB,CAChC,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,GACV;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAQ7C"}
1
+ {"version":3,"file":"project-utils.d.ts","sourceRoot":"","sources":["../src/project-utils.ts"],"names":[],"mappings":"AAIA;;;;GAIG;AACH,wBAAgB,iBAAiB,CAChC,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,GACV;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAI7C"}
@@ -1,15 +1,11 @@
1
1
  import crypto from "node:crypto";
2
- import fs from "node:fs";
3
2
  import path from "node:path";
4
3
  /**
5
4
  * Resolve a unique project directory name under `baseDir`.
6
- * If the directory already exists, appends a random 4-char hex suffix.
5
+ * Always appends a random 4-char hex suffix to avoid container/volume
6
+ * collisions when Docker compose project names overlap across sessions.
7
7
  */
8
8
  export function resolveProjectDir(baseDir, name) {
9
- const candidate = path.resolve(baseDir, name);
10
- if (!fs.existsSync(candidate)) {
11
- return { projectName: name, projectDir: candidate };
12
- }
13
9
  const suffix = crypto.randomBytes(2).toString("hex");
14
10
  const uniqueName = `${name}-${suffix}`;
15
11
  return { projectName: uniqueName, projectDir: path.resolve(baseDir, uniqueName) };
@@ -1 +1 @@
1
- {"version":3,"file":"project-utils.js","sourceRoot":"","sources":["../src/project-utils.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,aAAa,CAAA;AAChC,OAAO,EAAE,MAAM,SAAS,CAAA;AACxB,OAAO,IAAI,MAAM,WAAW,CAAA;AAE5B;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAChC,OAAe,EACf,IAAY;IAEZ,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC,CAAA;IAC7C,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QAC/B,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,UAAU,EAAE,SAAS,EAAE,CAAA;IACpD,CAAC;IACD,MAAM,MAAM,GAAG,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAA;IACpD,MAAM,UAAU,GAAG,GAAG,IAAI,IAAI,MAAM,EAAE,CAAA;IACtC,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,UAAU,EAAE,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,UAAU,CAAC,EAAE,CAAA;AAClF,CAAC"}
1
+ {"version":3,"file":"project-utils.js","sourceRoot":"","sources":["../src/project-utils.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,aAAa,CAAA;AAEhC,OAAO,IAAI,MAAM,WAAW,CAAA;AAE5B;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAChC,OAAe,EACf,IAAY;IAEZ,MAAM,MAAM,GAAG,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAA;IACpD,MAAM,UAAU,GAAG,GAAG,IAAI,IAAI,MAAM,EAAE,CAAA;IACtC,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,UAAU,EAAE,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,UAAU,CAAC,EAAE,CAAA;AAClF,CAAC"}
@@ -0,0 +1,52 @@
1
+ import type { SessionInfo } from "./sessions.js";
2
+ import type { SharedSessionEntry } from "./shared-sessions.js";
3
+ import { type StreamConfig } from "./streams.js";
4
+ /**
5
+ * In-memory registry backed by a Durable Streams log.
6
+ *
7
+ * On startup, replays the registry stream to hydrate Maps.
8
+ * On mutations, appends to stream then updates in-memory state.
9
+ */
10
+ export declare class Registry {
11
+ private sessions;
12
+ private transcriptToSession;
13
+ private rooms;
14
+ private roomsByCode;
15
+ private stream;
16
+ private constructor();
17
+ /**
18
+ * Create and hydrate a Registry from the durable stream.
19
+ * Creates the stream if it doesn't exist yet.
20
+ */
21
+ static create(config: StreamConfig): Promise<Registry>;
22
+ /** Replay the stream to rebuild in-memory state. */
23
+ private hydrate;
24
+ /** Apply a single event to in-memory state (no stream write). */
25
+ private applyEvent;
26
+ /** Append an event to the stream and apply it in-memory. */
27
+ private append;
28
+ addSession(session: SessionInfo): Promise<void>;
29
+ updateSession(id: string, update: Partial<SessionInfo>): Promise<void>;
30
+ deleteSession(id: string): Promise<boolean>;
31
+ getSession(id: string): SessionInfo | undefined;
32
+ listSessions(): SessionInfo[];
33
+ /**
34
+ * Mark stale running sessions as "error".
35
+ * Returns the number of sessions cleaned up.
36
+ */
37
+ cleanupStaleSessions(thresholdMs?: number): number;
38
+ /**
39
+ * Look up the EA session ID for a Claude Code transcript path.
40
+ * Returns undefined if no mapping exists or the session has been deleted.
41
+ */
42
+ getSessionByTranscript(transcriptPath: string): string | undefined;
43
+ /**
44
+ * Durably map a transcript path to an EA session ID.
45
+ */
46
+ mapTranscriptToSession(transcriptPath: string, sessionId: string): Promise<void>;
47
+ addRoom(entry: SharedSessionEntry): Promise<void>;
48
+ getRoom(id: string): SharedSessionEntry | undefined;
49
+ getRoomByCode(code: string): SharedSessionEntry | undefined;
50
+ revokeRoom(id: string): Promise<boolean>;
51
+ }
52
+ //# sourceMappingURL=registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAChD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAA;AAC9D,OAAO,EAA6B,KAAK,YAAY,EAAE,MAAM,cAAc,CAAA;AAY3E;;;;;GAKG;AACH,qBAAa,QAAQ;IACpB,OAAO,CAAC,QAAQ,CAAiC;IACjD,OAAO,CAAC,mBAAmB,CAA4B;IACvD,OAAO,CAAC,KAAK,CAAwC;IACrD,OAAO,CAAC,WAAW,CAAwC;IAC3D,OAAO,CAAC,MAAM,CAAe;IAE7B,OAAO;IAIP;;;OAGG;WACU,MAAM,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,QAAQ,CAAC;IAyB5D,oDAAoD;YACtC,OAAO;IAwBrB,iEAAiE;IACjE,OAAO,CAAC,UAAU;IAgClB,4DAA4D;YAC9C,MAAM;IAOd,UAAU,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAQ/C,aAAa,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,WAAW,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAUtE,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAUjD,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS;IAI/C,YAAY,IAAI,WAAW,EAAE;IAI7B;;;OAGG;IACH,oBAAoB,CAAC,WAAW,SAAqB,GAAG,MAAM;IAqB9D;;;OAGG;IACH,sBAAsB,CAAC,cAAc,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAOlE;;OAEG;IACG,sBAAsB,CAAC,cAAc,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAWhF,OAAO,CAAC,KAAK,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC;IAQvD,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,kBAAkB,GAAG,SAAS;IAInD,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,kBAAkB,GAAG,SAAS;IAIrD,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;CAS9C"}
@@ -0,0 +1,204 @@
1
+ import { DurableStream } from "@durable-streams/client";
2
+ import { getRegistryConnectionInfo } from "./streams.js";
3
+ /**
4
+ * In-memory registry backed by a Durable Streams log.
5
+ *
6
+ * On startup, replays the registry stream to hydrate Maps.
7
+ * On mutations, appends to stream then updates in-memory state.
8
+ */
9
+ export class Registry {
10
+ sessions = new Map();
11
+ transcriptToSession = new Map();
12
+ rooms = new Map();
13
+ roomsByCode = new Map();
14
+ stream;
15
+ constructor(stream) {
16
+ this.stream = stream;
17
+ }
18
+ /**
19
+ * Create and hydrate a Registry from the durable stream.
20
+ * Creates the stream if it doesn't exist yet.
21
+ */
22
+ static async create(config) {
23
+ const conn = getRegistryConnectionInfo(config);
24
+ // Ensure the stream exists
25
+ try {
26
+ await DurableStream.create({
27
+ url: conn.url,
28
+ headers: conn.headers,
29
+ contentType: "application/json",
30
+ });
31
+ }
32
+ catch {
33
+ // Stream may already exist — that's fine
34
+ }
35
+ const stream = new DurableStream({
36
+ url: conn.url,
37
+ headers: conn.headers,
38
+ contentType: "application/json",
39
+ });
40
+ const registry = new Registry(stream);
41
+ await registry.hydrate();
42
+ return registry;
43
+ }
44
+ /** Replay the stream to rebuild in-memory state. */
45
+ async hydrate() {
46
+ const response = await this.stream.stream({
47
+ offset: "-1",
48
+ live: false,
49
+ });
50
+ await new Promise((resolve) => {
51
+ const cancel = response.subscribeJson((batch) => {
52
+ for (const event of batch.items) {
53
+ this.applyEvent(event);
54
+ }
55
+ });
56
+ // For non-live streams, the subscription ends when all data is consumed.
57
+ // Use a short delay to ensure all batches are processed.
58
+ setTimeout(() => {
59
+ cancel();
60
+ resolve();
61
+ }, 500);
62
+ });
63
+ console.log(`[registry] Hydrated: ${this.sessions.size} session(s), ${this.rooms.size} room(s)`);
64
+ }
65
+ /** Apply a single event to in-memory state (no stream write). */
66
+ applyEvent(event) {
67
+ switch (event.type) {
68
+ case "session_registered":
69
+ this.sessions.set(event.session.id, event.session);
70
+ break;
71
+ case "session_updated": {
72
+ const session = this.sessions.get(event.sessionId);
73
+ if (session) {
74
+ Object.assign(session, event.update);
75
+ }
76
+ break;
77
+ }
78
+ case "session_deleted":
79
+ this.sessions.delete(event.sessionId);
80
+ break;
81
+ case "session_mapped":
82
+ this.transcriptToSession.set(event.transcriptPath, event.sessionId);
83
+ break;
84
+ case "room_created":
85
+ this.rooms.set(event.room.id, event.room);
86
+ this.roomsByCode.set(event.room.code, event.room);
87
+ break;
88
+ case "room_revoked": {
89
+ const room = this.rooms.get(event.roomId);
90
+ if (room) {
91
+ room.revoked = true;
92
+ }
93
+ break;
94
+ }
95
+ }
96
+ }
97
+ /** Append an event to the stream and apply it in-memory. */
98
+ async append(event) {
99
+ await this.stream.append(JSON.stringify(event));
100
+ this.applyEvent(event);
101
+ }
102
+ // --- Session CRUD ---
103
+ async addSession(session) {
104
+ await this.append({
105
+ type: "session_registered",
106
+ session,
107
+ ts: new Date().toISOString(),
108
+ });
109
+ }
110
+ async updateSession(id, update) {
111
+ const merged = { ...update, lastActiveAt: new Date().toISOString() };
112
+ await this.append({
113
+ type: "session_updated",
114
+ sessionId: id,
115
+ update: merged,
116
+ ts: new Date().toISOString(),
117
+ });
118
+ }
119
+ async deleteSession(id) {
120
+ if (!this.sessions.has(id))
121
+ return false;
122
+ await this.append({
123
+ type: "session_deleted",
124
+ sessionId: id,
125
+ ts: new Date().toISOString(),
126
+ });
127
+ return true;
128
+ }
129
+ getSession(id) {
130
+ return this.sessions.get(id);
131
+ }
132
+ listSessions() {
133
+ return Array.from(this.sessions.values());
134
+ }
135
+ /**
136
+ * Mark stale running sessions as "error".
137
+ * Returns the number of sessions cleaned up.
138
+ */
139
+ cleanupStaleSessions(thresholdMs = 2 * 60 * 60 * 1000) {
140
+ const now = Date.now();
141
+ let count = 0;
142
+ for (const session of this.sessions.values()) {
143
+ if (session.status !== "running")
144
+ continue;
145
+ const lastActive = new Date(session.lastActiveAt).getTime();
146
+ if (now - lastActive > thresholdMs) {
147
+ session.status = "error";
148
+ count++;
149
+ }
150
+ }
151
+ // Note: stale cleanup is best-effort and does not persist to stream
152
+ // (avoids async in a sync hot path). The status will be corrected on
153
+ // next real mutation or server restart.
154
+ return count;
155
+ }
156
+ // --- Transcript → Session Mapping ---
157
+ /**
158
+ * Look up the EA session ID for a Claude Code transcript path.
159
+ * Returns undefined if no mapping exists or the session has been deleted.
160
+ */
161
+ getSessionByTranscript(transcriptPath) {
162
+ const sessionId = this.transcriptToSession.get(transcriptPath);
163
+ if (!sessionId)
164
+ return undefined;
165
+ // Only return if the session still exists
166
+ return this.sessions.has(sessionId) ? sessionId : undefined;
167
+ }
168
+ /**
169
+ * Durably map a transcript path to an EA session ID.
170
+ */
171
+ async mapTranscriptToSession(transcriptPath, sessionId) {
172
+ await this.append({
173
+ type: "session_mapped",
174
+ transcriptPath,
175
+ sessionId,
176
+ ts: new Date().toISOString(),
177
+ });
178
+ }
179
+ // --- Room (Shared Session) CRUD ---
180
+ async addRoom(entry) {
181
+ await this.append({
182
+ type: "room_created",
183
+ room: entry,
184
+ ts: new Date().toISOString(),
185
+ });
186
+ }
187
+ getRoom(id) {
188
+ return this.rooms.get(id);
189
+ }
190
+ getRoomByCode(code) {
191
+ return this.roomsByCode.get(code);
192
+ }
193
+ async revokeRoom(id) {
194
+ if (!this.rooms.has(id))
195
+ return false;
196
+ await this.append({
197
+ type: "room_revoked",
198
+ roomId: id,
199
+ ts: new Date().toISOString(),
200
+ });
201
+ return true;
202
+ }
203
+ }
204
+ //# sourceMappingURL=registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,40 @@
1
+ import { type StreamConfig } from "./streams.js";
2
+ export interface RoomInfo {
3
+ id: string;
4
+ /** 8-char random invite code (e.g. "ABCD-1234") */
5
+ code: string;
6
+ name: string;
7
+ createdAt: string;
8
+ revoked: boolean;
9
+ }
10
+ /**
11
+ * Durable Streams-backed room registry.
12
+ *
13
+ * On startup, replays the registry stream to hydrate in-memory Maps.
14
+ * On mutations, appends to stream then updates in-memory state.
15
+ *
16
+ * This only tracks room metadata (not sessions — those are private
17
+ * to each user's browser localStorage).
18
+ */
19
+ export declare class RoomRegistry {
20
+ private rooms;
21
+ private roomsByCode;
22
+ private stream;
23
+ private constructor();
24
+ /**
25
+ * Create and hydrate a RoomRegistry from the durable stream.
26
+ * Creates the stream if it doesn't exist yet.
27
+ */
28
+ static create(config: StreamConfig): Promise<RoomRegistry>;
29
+ /** Replay the stream to rebuild in-memory state. */
30
+ private hydrate;
31
+ /** Apply a single event to in-memory state (no stream write). */
32
+ private applyEvent;
33
+ /** Append an event to the stream and apply it in-memory. */
34
+ private append;
35
+ addRoom(room: RoomInfo): Promise<void>;
36
+ getRoom(id: string): RoomInfo | undefined;
37
+ getRoomByCode(code: string): RoomInfo | undefined;
38
+ revokeRoom(id: string): Promise<boolean>;
39
+ }
40
+ //# sourceMappingURL=room-registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"room-registry.d.ts","sourceRoot":"","sources":["../src/room-registry.ts"],"names":[],"mappings":"AACA,OAAO,EAA6B,KAAK,YAAY,EAAE,MAAM,cAAc,CAAA;AAE3E,MAAM,WAAW,QAAQ;IACxB,EAAE,EAAE,MAAM,CAAA;IACV,mDAAmD;IACnD,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,EAAE,MAAM,CAAA;IACjB,OAAO,EAAE,OAAO,CAAA;CAChB;AAQD;;;;;;;;GAQG;AACH,qBAAa,YAAY;IACxB,OAAO,CAAC,KAAK,CAA8B;IAC3C,OAAO,CAAC,WAAW,CAA8B;IACjD,OAAO,CAAC,MAAM,CAAe;IAE7B,OAAO;IAIP;;;OAGG;WACU,MAAM,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC;IAyBhE,oDAAoD;YACtC,OAAO;IAwBrB,iEAAiE;IACjE,OAAO,CAAC,UAAU;IAgBlB,4DAA4D;YAC9C,MAAM;IAOd,OAAO,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAQ5C,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,QAAQ,GAAG,SAAS;IAIzC,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,QAAQ,GAAG,SAAS;IAI3C,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;CAS9C"}
@@ -0,0 +1,112 @@
1
+ import { DurableStream } from "@durable-streams/client";
2
+ import { getRegistryConnectionInfo } from "./streams.js";
3
+ /**
4
+ * Durable Streams-backed room registry.
5
+ *
6
+ * On startup, replays the registry stream to hydrate in-memory Maps.
7
+ * On mutations, appends to stream then updates in-memory state.
8
+ *
9
+ * This only tracks room metadata (not sessions — those are private
10
+ * to each user's browser localStorage).
11
+ */
12
+ export class RoomRegistry {
13
+ rooms = new Map();
14
+ roomsByCode = new Map();
15
+ stream;
16
+ constructor(stream) {
17
+ this.stream = stream;
18
+ }
19
+ /**
20
+ * Create and hydrate a RoomRegistry from the durable stream.
21
+ * Creates the stream if it doesn't exist yet.
22
+ */
23
+ static async create(config) {
24
+ const conn = getRegistryConnectionInfo(config);
25
+ // Ensure the stream exists
26
+ try {
27
+ await DurableStream.create({
28
+ url: conn.url,
29
+ headers: conn.headers,
30
+ contentType: "application/json",
31
+ });
32
+ }
33
+ catch {
34
+ // Stream may already exist — that's fine
35
+ }
36
+ const stream = new DurableStream({
37
+ url: conn.url,
38
+ headers: conn.headers,
39
+ contentType: "application/json",
40
+ });
41
+ const registry = new RoomRegistry(stream);
42
+ await registry.hydrate();
43
+ return registry;
44
+ }
45
+ /** Replay the stream to rebuild in-memory state. */
46
+ async hydrate() {
47
+ const response = await this.stream.stream({
48
+ offset: "-1",
49
+ live: false,
50
+ });
51
+ await new Promise((resolve) => {
52
+ const cancel = response.subscribeJson((batch) => {
53
+ for (const event of batch.items) {
54
+ this.applyEvent(event);
55
+ }
56
+ });
57
+ // For non-live streams, the subscription ends when all data is consumed.
58
+ // Use a short delay to ensure all batches are processed.
59
+ setTimeout(() => {
60
+ cancel();
61
+ resolve();
62
+ }, 500);
63
+ });
64
+ console.log(`[room-registry] Hydrated: ${this.rooms.size} room(s)`);
65
+ }
66
+ /** Apply a single event to in-memory state (no stream write). */
67
+ applyEvent(event) {
68
+ switch (event.type) {
69
+ case "room_created":
70
+ this.rooms.set(event.room.id, event.room);
71
+ this.roomsByCode.set(event.room.code, event.room);
72
+ break;
73
+ case "room_revoked": {
74
+ const room = this.rooms.get(event.roomId);
75
+ if (room) {
76
+ room.revoked = true;
77
+ }
78
+ break;
79
+ }
80
+ }
81
+ }
82
+ /** Append an event to the stream and apply it in-memory. */
83
+ async append(event) {
84
+ await this.stream.append(JSON.stringify(event));
85
+ this.applyEvent(event);
86
+ }
87
+ // --- Room CRUD ---
88
+ async addRoom(room) {
89
+ await this.append({
90
+ type: "room_created",
91
+ room,
92
+ ts: new Date().toISOString(),
93
+ });
94
+ }
95
+ getRoom(id) {
96
+ return this.rooms.get(id);
97
+ }
98
+ getRoomByCode(code) {
99
+ return this.roomsByCode.get(code);
100
+ }
101
+ async revokeRoom(id) {
102
+ if (!this.rooms.has(id))
103
+ return false;
104
+ await this.append({
105
+ type: "room_revoked",
106
+ roomId: id,
107
+ ts: new Date().toISOString(),
108
+ });
109
+ return true;
110
+ }
111
+ }
112
+ //# sourceMappingURL=room-registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"room-registry.js","sourceRoot":"","sources":["../src/room-registry.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"sprites-bootstrap.d.ts","sourceRoot":"","sources":["../../src/sandbox/sprites-bootstrap.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAA;AAO1C,MAAM,WAAW,gBAAgB;IAChC,sGAAsG;IACtG,UAAU,CAAC,EAAE,MAAM,CAAA;CACnB;AAED;;;GAGG;AACH,wBAAsB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAoD5F;AAED;;;;;;GAMG;AACH,wBAAsB,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAoC/F"}
1
+ {"version":3,"file":"sprites-bootstrap.d.ts","sourceRoot":"","sources":["../../src/sandbox/sprites-bootstrap.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAA;AAO1C,MAAM,WAAW,gBAAgB;IAChC,sGAAsG;IACtG,UAAU,CAAC,EAAE,MAAM,CAAA;CACnB;AAED;;;GAGG;AACH,wBAAsB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CA2D5F;AAED;;;;;;GAMG;AACH,wBAAsB,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAoC/F"}
@@ -14,7 +14,7 @@ const CHECKPOINT_COMMENT = `bootstrapped:${version}`;
14
14
  * This runs inside a freshly-created sprite that has Node.js but nothing else.
15
15
  */
16
16
  export async function bootstrapSprite(sprite, opts) {
17
- const packageSpec = opts?.packageUrl ?? "electric-agent";
17
+ const packageSpec = opts?.packageUrl ?? "@electric-agent/agent";
18
18
  console.log(`[sprites-bootstrap] Installing pnpm...`);
19
19
  await sprite.exec("npm install -g pnpm", { maxBuffer: 50 * 1024 * 1024 });
20
20
  console.log(`[sprites-bootstrap] Installing electric-agent from: ${packageSpec}`);
@@ -22,6 +22,12 @@ export async function bootstrapSprite(sprite, opts) {
22
22
  "-c",
23
23
  `source /etc/profile.d/npm-global.sh 2>/dev/null; npm install -g ${packageSpec}`,
24
24
  ]);
25
+ // Install Claude Code CLI (for claude-code bridge mode)
26
+ console.log(`[sprites-bootstrap] Installing Claude Code CLI...`);
27
+ await sprite.execFile("bash", [
28
+ "-c",
29
+ "source /etc/profile.d/npm-global.sh 2>/dev/null; npm install -g @anthropic-ai/claude-code",
30
+ ]);
25
31
  // Create the workspace directory structure matching other runtimes
26
32
  await sprite.exec("mkdir -p /home/agent/workspace");
27
33
  // Write a profile script that adds npm global bin and nvm paths to PATH.
@@ -1 +1 @@
1
- {"version":3,"file":"sprites-bootstrap.js","sourceRoot":"","sources":["../../src/sandbox/sprites-bootstrap.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"sprites-bootstrap.js","sourceRoot":"","sources":["../../src/sandbox/sprites-bootstrap.ts"],"names":[],"mappings":"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"}
@@ -24,6 +24,11 @@ export declare class SpritesSandboxProvider implements SandboxProvider {
24
24
  * The JS SDK doesn't expose this yet, so we call the REST API directly.
25
25
  */
26
26
  private setNetworkPolicyAllowAll;
27
+ /**
28
+ * Set the sprite URL to public access (no login required).
29
+ * By default sprites require authentication to access their URL.
30
+ */
31
+ private setUrlPublic;
27
32
  create(sessionId: string, opts?: CreateSandboxOpts): Promise<SandboxHandle>;
28
33
  destroy(handle: SandboxHandle): Promise<void>;
29
34
  restartAgent(handle: SandboxHandle): Promise<SandboxHandle>;
@@ -1 +1 @@
1
- {"version":3,"file":"sprites.d.ts","sourceRoot":"","sources":["../../src/sandbox/sprites.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,MAAM,EAAiB,MAAM,cAAc,CAAA;AAEzD,OAAO,KAAK,EACX,iBAAiB,EACjB,SAAS,EAET,aAAa,EACb,eAAe,EACf,MAAM,YAAY,CAAA;AAUnB,qBAAa,sBAAuB,YAAW,eAAe;IAC7D,QAAQ,CAAC,OAAO,EAAG,SAAS,CAAS;IAErC,OAAO,CAAC,MAAM,CAAe;IAC7B,OAAO,CAAC,KAAK,CAAQ;IACrB,OAAO,CAAC,OAAO,CAAQ;IACvB,OAAO,CAAC,OAAO,CAAmC;IAClD,OAAO,CAAC,OAAO,CAA4B;gBAE/B,IAAI,CAAC,EAAE;QAClB,KAAK,CAAC,EAAE,MAAM,CAAA;QACd,MAAM,CAAC,EAAE,MAAM,CAAA;QACf,KAAK,CAAC,EAAE,MAAM,CAAA;QACd,IAAI,CAAC,EAAE,MAAM,CAAA;KACb;IAMD,OAAO,CAAC,SAAS;IAMjB;;;OAGG;YACW,YAAY;IAa1B;;;OAGG;YACW,wBAAwB;IAiBhC,MAAM,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,aAAa,CAAC;IA6F3E,OAAO,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAc7C,YAAY,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC;IAejE;;;OAGG;IACG,UAAU,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAUtD,oEAAoE;IACpE,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAItD,GAAG,CAAC,SAAS,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS;IAIjD,IAAI,IAAI,aAAa,EAAE;IAIvB,OAAO,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO;IAIjC,IAAI,CAAC,MAAM,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAW7D,SAAS,CAAC,MAAM,EAAE,aAAa,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAoBhE,QAAQ,CAAC,MAAM,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAYzE,QAAQ,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,OAAO,CAAC;IASjD,OAAO,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,OAAO,CAAC;IAShD,YAAY,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,OAAO,CAAC;IAYrD,SAAS,CAAC,MAAM,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC;IA6DxE,aAAa,CAAC,MAAM,EAAE,aAAa,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAI3E,cAAc,CACnB,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,EACf,IAAI,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,GAChF,OAAO,CAAC,aAAa,CAAC;CA2BzB"}
1
+ {"version":3,"file":"sprites.d.ts","sourceRoot":"","sources":["../../src/sandbox/sprites.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,MAAM,EAAiB,MAAM,cAAc,CAAA;AAEzD,OAAO,KAAK,EACX,iBAAiB,EACjB,SAAS,EAET,aAAa,EACb,eAAe,EACf,MAAM,YAAY,CAAA;AAUnB,qBAAa,sBAAuB,YAAW,eAAe;IAC7D,QAAQ,CAAC,OAAO,EAAG,SAAS,CAAS;IAErC,OAAO,CAAC,MAAM,CAAe;IAC7B,OAAO,CAAC,KAAK,CAAQ;IACrB,OAAO,CAAC,OAAO,CAAQ;IACvB,OAAO,CAAC,OAAO,CAAmC;IAClD,OAAO,CAAC,OAAO,CAA4B;gBAE/B,IAAI,CAAC,EAAE;QAClB,KAAK,CAAC,EAAE,MAAM,CAAA;QACd,MAAM,CAAC,EAAE,MAAM,CAAA;QACf,KAAK,CAAC,EAAE,MAAM,CAAA;QACd,IAAI,CAAC,EAAE,MAAM,CAAA;KACb;IAMD,OAAO,CAAC,SAAS;IAMjB;;;OAGG;YACW,YAAY;IAa1B;;;OAGG;YACW,wBAAwB;IAiBtC;;;OAGG;YACW,YAAY;IAiBpB,MAAM,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,aAAa,CAAC;IA6F3E,OAAO,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAc7C,YAAY,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC;IAejE;;;OAGG;IACG,UAAU,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAUtD,oEAAoE;IACpE,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAItD,GAAG,CAAC,SAAS,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS;IAIjD,IAAI,IAAI,aAAa,EAAE;IAIvB,OAAO,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO;IAIjC,IAAI,CAAC,MAAM,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAW7D,SAAS,CAAC,MAAM,EAAE,aAAa,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAoBhE,QAAQ,CAAC,MAAM,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAYzE,QAAQ,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,OAAO,CAAC;IASjD,OAAO,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,OAAO,CAAC;IAShD,YAAY,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,OAAO,CAAC;IAYrD,SAAS,CAAC,MAAM,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC;IA6DxE,aAAa,CAAC,MAAM,EAAE,aAAa,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAI3E,cAAc,CACnB,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,EACf,IAAI,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,GAChF,OAAO,CAAC,aAAa,CAAC;CA2BzB"}
@@ -60,6 +60,26 @@ export class SpritesSandboxProvider {
60
60
  console.warn(`[sprites] Failed to set network policy (${resp.status}): ${await resp.text()}`);
61
61
  }
62
62
  }
63
+ /**
64
+ * Set the sprite URL to public access (no login required).
65
+ * By default sprites require authentication to access their URL.
66
+ */
67
+ async setUrlPublic(spriteName) {
68
+ const url = `${this.baseURL}/v1/sprites/${encodeURIComponent(spriteName)}`;
69
+ const resp = await fetch(url, {
70
+ method: "PUT",
71
+ headers: {
72
+ Authorization: `Bearer ${this.token}`,
73
+ "Content-Type": "application/json",
74
+ },
75
+ body: JSON.stringify({
76
+ url_settings: { auth: "public" },
77
+ }),
78
+ });
79
+ if (!resp.ok) {
80
+ console.warn(`[sprites] Failed to set URL to public (${resp.status}): ${await resp.text()}`);
81
+ }
82
+ }
63
83
  async create(sessionId, opts) {
64
84
  const infra = opts?.infra ?? { mode: "local" };
65
85
  const projectName = opts?.projectName || sessionId.slice(0, 8);
@@ -71,8 +91,8 @@ export class SpritesSandboxProvider {
71
91
  cpus: DEFAULT_CPUS,
72
92
  region: DEFAULT_REGION,
73
93
  });
74
- // Enable outbound internet access
75
- await this.setNetworkPolicyAllowAll(spriteName);
94
+ // Enable outbound internet access and public URL access (no login page)
95
+ await Promise.all([this.setNetworkPolicyAllowAll(spriteName), this.setUrlPublic(spriteName)]);
76
96
  // Bootstrap (or restore from checkpoint).
77
97
  // When AGENT_PACKAGE_URL is set (e.g. PR preview), install from that URL
78
98
  // instead of the published electric-agent package.