negotium 0.2.2 → 0.2.4

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 (70) hide show
  1. package/dist/agent-helpers.js +3117 -2915
  2. package/dist/agent-helpers.js.map +38 -37
  3. package/dist/background-bash.js.map +1 -1
  4. package/dist/browser-runtime.js +137 -21
  5. package/dist/browser-runtime.js.map +10 -9
  6. package/dist/{chunk-kc5kmr95.js → chunk-1s9ryz8g.js} +1195 -21
  7. package/dist/chunk-1s9ryz8g.js.map +35 -0
  8. package/dist/hosted-agent.js +60 -48
  9. package/dist/hosted-agent.js.map +10 -10
  10. package/dist/main.js +3038 -3357
  11. package/dist/main.js.map +35 -35
  12. package/dist/mcp-factories.js +6227 -6021
  13. package/dist/mcp-factories.js.map +40 -39
  14. package/dist/prompts.js.map +1 -1
  15. package/dist/query-runtime.js +22 -2
  16. package/dist/query-runtime.js.map +4 -4
  17. package/dist/registry.js +169 -213
  18. package/dist/registry.js.map +8 -9
  19. package/dist/rollout.js +1 -1
  20. package/dist/runtime/src/agents/codex-app-server.ts +136 -0
  21. package/dist/runtime/src/agents/codex-native-multi-agent.ts +1 -1
  22. package/dist/runtime/src/agents/codex-provider.ts +21 -11
  23. package/dist/runtime/src/agents/codex-registry.ts +9 -17
  24. package/dist/runtime/src/agents/contracts.ts +2 -0
  25. package/dist/runtime/src/agents/execution-host.ts +6 -0
  26. package/dist/runtime/src/agents/fork.ts +24 -18
  27. package/dist/runtime/src/agents/idle-archiver.ts +7 -2
  28. package/dist/runtime/src/agents/index.ts +2 -1
  29. package/dist/runtime/src/agents/maestro-registry.ts +26 -7
  30. package/dist/runtime/src/agents/memory-archive-policy.ts +20 -0
  31. package/dist/runtime/src/agents/rollout/codex.ts +6 -5
  32. package/dist/runtime/src/agents/rollout/shared.ts +3 -5
  33. package/dist/runtime/src/mcp/factories/session-comm.ts +12 -0
  34. package/dist/runtime/src/mcp/session-comm/default-host.ts +16 -0
  35. package/dist/runtime/src/mcp/session-comm/server.ts +25 -0
  36. package/dist/runtime/src/platform/config.ts +4 -1
  37. package/dist/runtime/src/platform/playwright/manager.ts +57 -1
  38. package/dist/runtime/src/platform/playwright/profile-management.ts +33 -0
  39. package/dist/runtime/src/platform/playwright/public-runtime.ts +5 -0
  40. package/dist/runtime/src/platform/playwright/vault-broker.ts +9 -10
  41. package/dist/runtime/src/storage/browser-profiles.ts +35 -10
  42. package/dist/runtime/src/storage/storage-host.ts +31 -5
  43. package/dist/runtime/src/storage/vault.ts +30 -2
  44. package/dist/runtime/src/topics/derive.ts +38 -2
  45. package/dist/runtime/src/topics/lifecycle.ts +12 -2
  46. package/dist/runtime/src/version.ts +1 -1
  47. package/dist/runtime-helpers.js +22 -2
  48. package/dist/runtime-helpers.js.map +4 -4
  49. package/dist/storage.js +22 -2
  50. package/dist/storage.js.map +4 -4
  51. package/dist/types/packages/core/src/agents/codex-app-server.d.ts +13 -0
  52. package/dist/types/packages/core/src/agents/codex-native-multi-agent.d.ts +1 -0
  53. package/dist/types/packages/core/src/agents/contracts.d.ts +2 -0
  54. package/dist/types/packages/core/src/agents/execution-host.d.ts +2 -0
  55. package/dist/types/packages/core/src/agents/fork.d.ts +8 -7
  56. package/dist/types/packages/core/src/agents/memory-archive-policy.d.ts +10 -0
  57. package/dist/types/packages/core/src/agents/rollout/codex.d.ts +4 -2
  58. package/dist/types/packages/core/src/mcp/factories/session-comm.d.ts +1 -0
  59. package/dist/types/packages/core/src/platform/playwright/manager.d.ts +15 -0
  60. package/dist/types/packages/core/src/platform/playwright/profile-management.d.ts +8 -0
  61. package/dist/types/packages/core/src/platform/playwright/public-runtime.d.ts +2 -1
  62. package/dist/types/packages/core/src/storage/browser-profiles.d.ts +3 -1
  63. package/dist/types/packages/core/src/storage/storage-host.d.ts +1 -0
  64. package/dist/types/packages/core/src/storage/vault.d.ts +8 -0
  65. package/dist/types/packages/core/src/version.d.ts +1 -1
  66. package/dist/vault.js +19 -3
  67. package/dist/vault.js.map +4 -4
  68. package/package.json +2 -2
  69. package/dist/chunk-kc5kmr95.js.map +0 -19
  70. package/dist/runtime/src/migration/single-user.ts +0 -805
package/dist/registry.js CHANGED
@@ -11,10 +11,12 @@ import {
11
11
  encodeClaudeCwd,
12
12
  ensureCwdExists,
13
13
  extractChatPairs,
14
+ hostedCodexHomePath,
15
+ latestCodexRolloutPath,
14
16
  logger,
15
17
  writeClaudeRollout,
16
18
  writeCodexRollout
17
- } from "./chunk-kc5kmr95.js";
19
+ } from "./chunk-1s9ryz8g.js";
18
20
 
19
21
  // ../../packages/core/src/agents/claude-registry.ts
20
22
  import { existsSync, mkdirSync, readdirSync, renameSync, unlinkSync } from "fs";
@@ -98,209 +100,155 @@ var claudeRegistryOperations = {
98
100
 
99
101
  // ../../packages/core/src/agents/codex-registry.ts
100
102
  import { existsSync as existsSync3, unlinkSync as unlinkSync3 } from "fs";
101
- import { homedir as homedir3 } from "os";
102
- import { join as join4 } from "path";
103
+ import { join as join3 } from "path";
103
104
 
104
- // ../../packages/core/src/storage/conversations.ts
105
+ // ../../packages/core/src/agents/codex-app-server.ts
106
+ import { spawn } from "child_process";
107
+
108
+ // ../../packages/core/src/agents/codex-native-multi-agent.ts
105
109
  import {
110
+ chmodSync,
111
+ copyFileSync,
106
112
  existsSync as existsSync2,
107
- mkdirSync as mkdirSync3,
113
+ mkdtempSync,
108
114
  readFileSync,
109
115
  renameSync as renameSync2,
116
+ rmSync,
110
117
  unlinkSync as unlinkSync2,
111
118
  writeFileSync
112
119
  } from "fs";
113
- import { dirname as dirname2, join as join3 } from "path";
114
-
115
- // ../../packages/core/src/security/sanitize.ts
116
- function sanitizeTopicName(name, lowercase = false) {
117
- const safe = name.replace(/[^a-zA-Z0-9\uAC00-\uD7A3_-]/g, "_") || "_";
118
- return lowercase ? safe.toLowerCase() : safe;
119
- }
120
-
121
- // ../../packages/core/src/storage/storage-host.ts
122
- import { mkdirSync as mkdirSync2 } from "fs";
123
- import { homedir as homedir2 } from "os";
124
- import { dirname, join as join2, resolve } from "path";
120
+ import { createRequire } from "module";
121
+ import { dirname, join as join2 } from "path";
125
122
 
126
- // ../../packages/core/src/storage/sqlite.ts
127
- var isBun = typeof process.versions.bun === "string";
128
- var Database;
129
- if (isBun) {
130
- ({ Database } = await import("bun:sqlite"));
131
- } else {
132
- const nodeSqliteSpecifier = ["node", "sqlite"].join(":");
133
- const { DatabaseSync } = await import(nodeSqliteSpecifier);
123
+ // ../../packages/core/src/version.ts
124
+ var NEGOTIUM_VERSION = "0.2.4";
134
125
 
135
- class NodeDatabase {
136
- #db;
137
- constructor(path, options = {}) {
138
- this.#db = options.readonly ? new DatabaseSync(path, { readOnly: true }) : new DatabaseSync(path);
139
- }
140
- query(sql) {
141
- return this.#db.prepare(sql);
142
- }
143
- prepare(sql) {
144
- return this.#db.prepare(sql);
145
- }
146
- exec(sql) {
147
- this.#db.exec(sql);
148
- }
149
- run(sql, ...params) {
150
- return this.#db.prepare(sql).run(...params);
151
- }
152
- transaction(fn) {
153
- const run = (begin) => (...args) => {
154
- this.#db.exec(begin);
155
- try {
156
- const result = fn(...args);
157
- this.#db.exec("COMMIT");
158
- return result;
159
- } catch (err) {
160
- this.#db.exec("ROLLBACK");
161
- throw err;
162
- }
163
- };
164
- const tx = run("BEGIN");
165
- tx.deferred = run("BEGIN DEFERRED");
166
- tx.immediate = run("BEGIN IMMEDIATE");
167
- tx.exclusive = run("BEGIN EXCLUSIVE");
168
- return tx;
169
- }
170
- close() {
171
- this.#db.close();
172
- }
126
+ // ../../packages/core/src/agents/codex-native-multi-agent.ts
127
+ var moduleRequire = createRequire(import.meta.url);
128
+ var codexSdkPackagePath = moduleRequire.resolve("@openai/codex-sdk/package.json");
129
+ var codexSdkRequire = createRequire(codexSdkPackagePath);
130
+ var bundledCodexPackagePath = codexSdkRequire.resolve("@openai/codex/package.json");
131
+ function readPackageVersion(packageJsonPath) {
132
+ const parsed = JSON.parse(readFileSync(packageJsonPath, "utf8"));
133
+ if (typeof parsed.version !== "string" || !parsed.version.trim()) {
134
+ throw new Error(`Codex package has no valid version: ${packageJsonPath}`);
173
135
  }
174
- Database = NodeDatabase;
175
- }
176
-
177
- // ../../packages/core/src/storage/storage-host.ts
178
- var configuredHost = {};
179
- var fallbackDatabase = null;
180
- var fallbackDatabasePath = null;
181
- var schemaInitializers = [];
182
- var initializedSchemas = new WeakMap;
183
- var initializingDatabases = new WeakSet;
184
- function envPath(name, fallback) {
185
- const value = process.env[name]?.trim();
186
- return resolve(value || fallback);
136
+ return parsed.version;
187
137
  }
188
- function defaultStateDir() {
189
- return envPath("NEGOTIUM_STATE_DIR", join2(homedir2(), ".negotium"));
138
+ var BUNDLED_CODEX_VERSION = readPackageVersion(bundledCodexPackagePath);
139
+ var SAFE_BUNDLED_CODEX_VERSION = BUNDLED_CODEX_VERSION.replace(/[^a-zA-Z0-9._-]/g, "_");
140
+ var NEGOTIUM_MODEL_CACHE = `negotium-models-cache-${SAFE_BUNDLED_CODEX_VERSION}.json`;
141
+ var NEGOTIUM_MODEL_CATALOG = `negotium-model-catalog-${SAFE_BUNDLED_CODEX_VERSION}.json`;
142
+ function codexCliScriptPath() {
143
+ return join2(dirname(bundledCodexPackagePath), "bin", "codex.js");
190
144
  }
191
- function defaultDataDir() {
192
- return envPath("NEGOTIUM_DATA_DIR", join2(defaultStateDir(), "data"));
193
- }
194
- function defaultSessionsDatabasePath() {
195
- return envPath("SESSIONS_DB_PATH", join2(resolveStorageDataDir(), "sessions.db"));
196
- }
197
- function initializeDatabase(database) {
198
- database.exec("PRAGMA busy_timeout = 5000");
199
- database.exec("PRAGMA journal_mode = WAL");
200
- database.exec("PRAGMA foreign_keys = ON");
201
- database.exec("PRAGMA wal_autocheckpoint = 1000");
202
- try {
203
- database.exec("PRAGMA wal_checkpoint(TRUNCATE)");
204
- } catch {}
205
- }
206
- function defaultDatabase() {
207
- const path = defaultSessionsDatabasePath();
208
- if (fallbackDatabase && fallbackDatabasePath === path)
209
- return fallbackDatabase;
210
- if (fallbackDatabase)
211
- fallbackDatabase.close();
212
- mkdirSync2(dirname(path), { recursive: true });
213
- fallbackDatabase = new Database(path, { create: true });
214
- fallbackDatabasePath = path;
215
- initializeDatabase(fallbackDatabase);
216
- return fallbackDatabase;
217
- }
218
- function resolveStorageDatabase() {
219
- return configuredHost.database ?? defaultDatabase();
220
- }
221
- function resolveStorageDataDir() {
222
- return configuredHost.dataDir ?? defaultDataDir();
223
- }
224
- function ensureStorageSchemas(database = resolveStorageDatabase()) {
225
- if (initializingDatabases.has(database))
226
- return;
227
- let initialized = initializedSchemas.get(database);
228
- if (!initialized) {
229
- initialized = new Set;
230
- initializedSchemas.set(database, initialized);
231
- }
232
- initializingDatabases.add(database);
233
- try {
234
- for (const entry of schemaInitializers) {
235
- if (initialized.has(entry.initialize))
236
- continue;
237
- initialized.add(entry.initialize);
238
- try {
239
- entry.initialize(database);
240
- } catch (error) {
241
- initialized.delete(entry.initialize);
242
- throw error;
243
- }
244
- }
245
- } finally {
246
- initializingDatabases.delete(database);
247
- }
145
+
146
+ // ../../packages/core/src/agents/codex-app-server.ts
147
+ function createCodexAppServerForker(host) {
148
+ return async (parentThreadId) => {
149
+ const child = host.spawnServer();
150
+ return await new Promise((resolve, reject) => {
151
+ let settled = false;
152
+ let stdoutBuffer = "";
153
+ let stderr = "";
154
+ const timer = setTimeout(() => finish(new Error("Codex thread fork timed out")), host.timeoutMs);
155
+ const finish = (error, result) => {
156
+ if (settled)
157
+ return;
158
+ settled = true;
159
+ clearTimeout(timer);
160
+ try {
161
+ child.stdin.end();
162
+ child.kill();
163
+ } catch {}
164
+ if (error)
165
+ reject(error);
166
+ else if (result)
167
+ resolve(result);
168
+ else
169
+ reject(new Error("Codex thread fork returned no result"));
170
+ };
171
+ const send = (message) => {
172
+ child.stdin.write(`${JSON.stringify(message)}
173
+ `);
174
+ };
175
+ child.stderr.on("data", (chunk) => {
176
+ if (stderr.length < 8192)
177
+ stderr += String(chunk);
178
+ });
179
+ child.on("error", (error) => finish(error));
180
+ child.on("exit", (code, signal) => {
181
+ if (settled)
182
+ return;
183
+ const detail = signal ? `signal ${signal}` : `code ${code ?? 1}`;
184
+ finish(new Error(`Codex app server exited with ${detail}${stderr.trim() ? `: ${stderr.trim()}` : ""}`));
185
+ });
186
+ child.stdout.on("data", (chunk) => {
187
+ stdoutBuffer += String(chunk);
188
+ for (;; ) {
189
+ const newline = stdoutBuffer.indexOf(`
190
+ `);
191
+ if (newline < 0)
192
+ break;
193
+ const line = stdoutBuffer.slice(0, newline);
194
+ stdoutBuffer = stdoutBuffer.slice(newline + 1);
195
+ let message;
196
+ try {
197
+ message = JSON.parse(line);
198
+ } catch {
199
+ continue;
200
+ }
201
+ if (message.id === 1) {
202
+ if (message.error) {
203
+ finish(new Error(String(message.error.message || "Codex initialization failed")));
204
+ return;
205
+ }
206
+ send({ method: "initialized" });
207
+ send({ id: 2, method: "thread/fork", params: { threadId: parentThreadId } });
208
+ continue;
209
+ }
210
+ if (message.id !== 2)
211
+ continue;
212
+ if (message.error) {
213
+ finish(new Error(String(message.error.message || "Codex thread fork failed")));
214
+ return;
215
+ }
216
+ const forkId = message.result?.thread?.id;
217
+ if (typeof forkId !== "string" || !forkId) {
218
+ finish(new Error("Codex thread fork returned no thread id"));
219
+ return;
220
+ }
221
+ const rolloutPath = host.findRolloutPath(forkId);
222
+ if (!rolloutPath) {
223
+ finish(new Error(`Codex thread fork rollout was not found for ${forkId}`));
224
+ return;
225
+ }
226
+ finish(undefined, { forkId, rolloutPath });
227
+ return;
228
+ }
229
+ });
230
+ send({
231
+ id: 1,
232
+ method: "initialize",
233
+ params: {
234
+ clientInfo: { name: "negotium", version: NEGOTIUM_VERSION }
235
+ }
236
+ });
237
+ });
238
+ };
248
239
  }
249
- var internalStorageDatabase = new Proxy({}, {
250
- get(_target, property) {
251
- const database = resolveStorageDatabase();
252
- ensureStorageSchemas(database);
253
- const value = Reflect.get(database, property, database);
254
- return typeof value === "function" ? value.bind(database) : value;
240
+ var forkCodexThread = createCodexAppServerForker({
241
+ spawnServer() {
242
+ return spawn(process.execPath, [codexCliScriptPath(), "app-server", "--stdio"], {
243
+ env: { ...process.env, CODEX_HOME: hostedCodexHomePath() },
244
+ stdio: ["pipe", "pipe", "pipe"]
245
+ });
255
246
  },
256
- set(_target, property, value) {
257
- const database = resolveStorageDatabase();
258
- ensureStorageSchemas(database);
259
- return Reflect.set(database, property, value, database);
260
- }
247
+ findRolloutPath: latestCodexRolloutPath,
248
+ timeoutMs: 15000
261
249
  });
262
-
263
- // ../../packages/core/src/storage/conversations.ts
264
- function conversationDir(_userId) {
265
- return join3(resolveStorageDataDir(), "conversations");
266
- }
267
- function topicFilename(topicName) {
268
- const t = sanitizeTopicName(topicName, true);
269
- return `${t}.jsonl`;
270
- }
271
- function getConversationPath(userId, topicName) {
272
- return join3(conversationDir(userId), topicFilename(topicName));
273
- }
274
- function getActiveConversationPath(userId, topicName) {
275
- const rawPath = getConversationPath(userId, topicName);
276
- return rawPath.endsWith(".jsonl") ? `${rawPath.slice(0, -".jsonl".length)}.active.jsonl` : `${rawPath}.active`;
277
- }
278
- function readConversationPath(path) {
279
- const out = [];
280
- if (!existsSync2(path))
281
- return out;
282
- let raw;
283
- try {
284
- raw = readFileSync(path, "utf8");
285
- } catch (err) {
286
- logger.warn({ err, path }, "readConversation: read failed");
287
- return out;
288
- }
289
- for (const line of raw.split(`
290
- `)) {
291
- if (!line.trim())
292
- continue;
293
- try {
294
- out.push(JSON.parse(line));
295
- } catch (err) {
296
- logger.warn({ err, line: line.slice(0, 200) }, "readConversation: malformed JSONL line skipped");
297
- }
298
- }
299
- return out;
300
- }
301
- function readConversation(userId, topicName) {
302
- const activePath = getActiveConversationPath(userId, topicName);
303
- return readConversationPath(existsSync2(activePath) ? activePath : getConversationPath(userId, topicName));
250
+ async function forkCodexSession(parentThreadId) {
251
+ return await forkCodexThread(parentThreadId);
304
252
  }
305
253
 
306
254
  // ../../packages/core/src/agents/codex-registry.ts
@@ -333,20 +281,13 @@ var codexRegistryOperations = {
333
281
  });
334
282
  return { sessionId: threadId, rolloutPath };
335
283
  },
336
- async forkSession({ cwd, userId, topicName, model, effort }) {
337
- const entries = readConversation(userId, topicName);
338
- const { threadId, rolloutPath } = writeCodexRollout({
339
- cwd,
340
- entries,
341
- model: model ?? codexRegistry.defaultModel,
342
- ...effort ? { effort } : {}
343
- });
344
- return { forkId: threadId, rolloutPath };
284
+ async forkSession({ parentSessionId }) {
285
+ return await forkCodexSession(parentSessionId);
345
286
  },
346
287
  async cleanupRollouts({ sessionIds }) {
347
288
  if (sessionIds.length === 0)
348
289
  return;
349
- const sessionsDir = join4(process.env.CODEX_HOME || join4(homedir3(), ".codex"), "sessions");
290
+ const sessionsDir = join3(hostedCodexHomePath(), "sessions");
350
291
  if (!existsSync3(sessionsDir))
351
292
  return;
352
293
  const failures = [];
@@ -354,7 +295,7 @@ var codexRegistryOperations = {
354
295
  try {
355
296
  const glob = new Bun.Glob(`**/rollout-*-${tid}.jsonl`);
356
297
  for await (const rel of glob.scan({ cwd: sessionsDir, onlyFiles: true })) {
357
- const path = join4(sessionsDir, rel);
298
+ const path = join3(sessionsDir, rel);
358
299
  try {
359
300
  unlinkSync3(path);
360
301
  } catch (e) {
@@ -377,9 +318,9 @@ var codexRegistryOperations = {
377
318
 
378
319
  // ../../packages/core/src/agents/maestro-registry.ts
379
320
  import { randomUUID } from "crypto";
380
- import { existsSync as existsSync4, mkdirSync as mkdirSync4, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "fs";
381
- import { homedir as homedir4 } from "os";
382
- import { join as join5, resolve as resolve2 } from "path";
321
+ import { existsSync as existsSync4, mkdirSync as mkdirSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "fs";
322
+ import { homedir as homedir2 } from "os";
323
+ import { join as join4, resolve } from "path";
383
324
  var ALIAS_MAP2 = {
384
325
  "deepseek-pro": "deepseek-v4-pro",
385
326
  kimi: "kimi-k3",
@@ -407,13 +348,13 @@ var maestroRegistry = {
407
348
  }
408
349
  };
409
350
  function maestroSessionsDir() {
410
- return join5(process.env.MAESTRO_DATA_DIR ? resolve2(process.env.MAESTRO_DATA_DIR) : join5(homedir4(), ".maestro"), "sessions");
351
+ return join4(process.env.MAESTRO_DATA_DIR ? resolve(process.env.MAESTRO_DATA_DIR) : join4(homedir2(), ".maestro"), "sessions");
411
352
  }
412
353
  function maestroSessionPath(sessionId) {
413
- return join5(maestroSessionsDir(), `${sessionId}.jsonl`);
354
+ return join4(maestroSessionsDir(), `${sessionId}.jsonl`);
414
355
  }
415
356
  function maestroActiveSessionPath(sessionId) {
416
- return join5(maestroSessionsDir(), `${sessionId}.active.jsonl`);
357
+ return join4(maestroSessionsDir(), `${sessionId}.active.jsonl`);
417
358
  }
418
359
  function existingCreatedAt(path) {
419
360
  if (!existsSync4(path))
@@ -432,7 +373,7 @@ function writeRollout(options) {
432
373
  assertUuidLike("sessionId", sessionId);
433
374
  ensureCwdExists(options.cwd);
434
375
  const path = maestroSessionPath(sessionId);
435
- mkdirSync4(maestroSessionsDir(), { recursive: true });
376
+ mkdirSync2(maestroSessionsDir(), { recursive: true });
436
377
  const messages = extractChatPairs(options.entries).flatMap((pair) => [
437
378
  { role: "user", content: pair.userText },
438
379
  { role: "assistant", content: pair.assistantText }
@@ -443,7 +384,7 @@ function writeRollout(options) {
443
384
  version: 1,
444
385
  cwd: options.cwd,
445
386
  createdAt: existingCreatedAt(path) ?? new Date().toISOString(),
446
- sdkVersion: "0.1.54"
387
+ sdkVersion: "0.2.0"
447
388
  }
448
389
  },
449
390
  ...messages
@@ -460,13 +401,28 @@ var maestroRegistryOperations = {
460
401
  return writeRollout(options);
461
402
  },
462
403
  async forkSession(options) {
463
- const rollout = writeRollout({
404
+ const { deleteMaestroSession, forkSessionAt, loadRawMaestroSession } = await import("maestro-agent-sdk");
405
+ const parentMessages = loadRawMaestroSession(options.parentSessionId);
406
+ if (!parentMessages) {
407
+ throw new Error(`Maestro parent session not found: ${options.parentSessionId}`);
408
+ }
409
+ const parentHasActiveProjection = existsSync4(maestroActiveSessionPath(options.parentSessionId));
410
+ const fork = forkSessionAt({
411
+ parentSessionId: options.parentSessionId,
412
+ messageIndex: parentMessages.length,
464
413
  cwd: options.cwd,
465
- entries: readConversation(options.userId, options.topicName),
466
- ...options.model ? { model: options.model } : {},
467
- ...options.effort ? { effort: options.effort } : {}
414
+ userId: String(options.userId)
468
415
  });
469
- return { forkId: rollout.sessionId, rolloutPath: rollout.rolloutPath };
416
+ if (parentHasActiveProjection && !fork.activeProjectionForked) {
417
+ deleteMaestroSession(fork.sessionId);
418
+ throw new Error(`Maestro active projection could not be forked: ${options.parentSessionId}`);
419
+ }
420
+ const activePath = maestroActiveSessionPath(fork.sessionId);
421
+ return {
422
+ forkId: fork.sessionId,
423
+ rolloutPath: fork.rolloutPath,
424
+ ...existsSync4(activePath) ? { cleanupPaths: [activePath] } : {}
425
+ };
470
426
  },
471
427
  async cleanupRollouts(options) {
472
428
  const { deleteMaestroSession } = await import("maestro-agent-sdk");
@@ -518,4 +474,4 @@ export {
518
474
  getRegistry2 as getRegistry
519
475
  };
520
476
 
521
- //# debugId=6F48338E5A857EC064756E2164756E21
477
+ //# debugId=2C2992ACF93ADB3E64756E2164756E21