@ai-matrx/coding-sessions 0.1.85 → 0.1.87
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.
- package/CHANGELOG.md +12 -0
- package/dist/engine/index.cjs +184 -49
- package/dist/engine/index.cjs.map +1 -1
- package/dist/engine/index.d.cts +1 -1
- package/dist/engine/index.d.ts +1 -1
- package/dist/engine/index.js +183 -50
- package/dist/engine/index.js.map +1 -1
- package/dist/engine/worker.js +5 -3
- package/dist/engine/worker.js.map +1 -1
- package/dist/{index-DEPwyr2j.d.cts → index-CDeDKQHe.d.cts} +37 -5
- package/dist/{index-DEPwyr2j.d.ts → index-CDeDKQHe.d.ts} +37 -5
- package/dist/index.cjs +18 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +28 -1
- package/dist/index.d.ts +28 -1
- package/dist/index.js +18 -4
- package/dist/index.js.map +1 -1
- package/dist/react/index.cjs +176 -25
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.d.cts +29 -2
- package/dist/react/index.d.ts +29 -2
- package/dist/react/index.js +224 -62
- package/dist/react/index.js.map +1 -1
- package/dist/server/index.cjs +182 -50
- package/dist/server/index.cjs.map +1 -1
- package/dist/server/index.d.cts +2 -1
- package/dist/server/index.d.ts +2 -1
- package/dist/server/index.js +183 -51
- package/dist/server/index.js.map +1 -1
- package/dist/ui/assets/{index-DSWoryQZ.js → index-crORYlzR.js} +1 -2
- package/dist/ui/assets/index-eqe0sxR4.css +2 -0
- package/dist/ui/index.html +2 -2
- package/package.json +3 -3
- package/dist/ui/assets/index-Gp2bMDtx.css +0 -2
package/dist/server/index.cjs
CHANGED
|
@@ -117,8 +117,25 @@ function createRawBackupScheduler(options) {
|
|
|
117
117
|
// src/engine/agent-attach.ts
|
|
118
118
|
var import_promises2 = __toESM(require("fs/promises"), 1);
|
|
119
119
|
var import_node_path = __toESM(require("path"), 1);
|
|
120
|
+
|
|
121
|
+
// src/normalize/agent-block.ts
|
|
122
|
+
var AGENT_BLOCK_MARKER = "<ai_matrx_agent ";
|
|
123
|
+
function stripAgentBlock(text) {
|
|
124
|
+
const removed = text.match(/^<ai_matrx_agent_removed>[\s\S]*?<\/ai_matrx_agent_removed>\s*/);
|
|
125
|
+
if (removed) return text.slice(removed[0].length);
|
|
126
|
+
if (!text.startsWith(AGENT_BLOCK_MARKER)) return text;
|
|
127
|
+
const end = text.indexOf("</ai_matrx_agent>");
|
|
128
|
+
if (end < 0) return text;
|
|
129
|
+
let rest = text.slice(end + "</ai_matrx_agent>".length);
|
|
130
|
+
const skills = rest.match(/^\s*<skills_instructions>[\s\S]*?<\/skills_instructions>/);
|
|
131
|
+
if (skills) rest = rest.slice(skills[0].length);
|
|
132
|
+
return rest.replace(/^\s+/, "");
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// src/engine/agent-attach.ts
|
|
120
136
|
var AGENT_MCP_SERVER_NAME = "matrx-agent";
|
|
121
137
|
var AGENT_PLUGIN_NAME = "matrx-agent";
|
|
138
|
+
var CODEX_REPLACEMENT_CLAUSE = "If a later message in this chat begins with an <ai_matrx_agent> block, that block replaces these AI Matrx agent instructions from then on; an <ai_matrx_agent_removed> block withdraws them.";
|
|
122
139
|
function escapeAttr(value) {
|
|
123
140
|
return value.replace(/&/g, "&").replace(/"/g, """).replace(/</g, "<");
|
|
124
141
|
}
|
|
@@ -167,6 +184,20 @@ function renderCodexSkillsList(bundle, skillsRoot) {
|
|
|
167
184
|
];
|
|
168
185
|
return lines.join("\n");
|
|
169
186
|
}
|
|
187
|
+
function renderFallbackBlock(bundle, skillsRoot, options = {}) {
|
|
188
|
+
const skills = renderCodexSkillsList(bundle, skillsRoot);
|
|
189
|
+
const lead = options.replaces ? `These instructions REPLACE the earlier AI Matrx agent "${options.replaces}" from this message on. Where they differ from anything said before \u2014 including how earlier replies ended \u2014 follow these.` : "The instructions below are your AI Matrx agent for this chat from now on; they replace any AI Matrx agent instructions given earlier.";
|
|
190
|
+
const body = renderAgentInstructions(bundle).trim().replace(/^(<ai_matrx_agent [^>]*>)/, `$1
|
|
191
|
+
|
|
192
|
+
${lead}`);
|
|
193
|
+
return skills ? `${body}
|
|
194
|
+
|
|
195
|
+
${skills}
|
|
196
|
+
|
|
197
|
+
` : `${body}
|
|
198
|
+
|
|
199
|
+
`;
|
|
200
|
+
}
|
|
170
201
|
function tomlString(value) {
|
|
171
202
|
const scalar = value.replace(/[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?<![\uD800-\uDBFF])[\uDC00-\uDFFF]/g, "\uFFFD");
|
|
172
203
|
return JSON.stringify(scalar).replace(/\u007f/g, "\\u007f");
|
|
@@ -227,10 +258,16 @@ async function writeAgentAttachment(dir, bundle, options) {
|
|
|
227
258
|
pluginDir,
|
|
228
259
|
mcpConfigFile,
|
|
229
260
|
mcpUrl,
|
|
230
|
-
// Same order as Claude's: the skills list first, the agent's words last
|
|
231
|
-
|
|
261
|
+
// Same order as Claude's: the skills list first, the agent's words last —
|
|
262
|
+
// then the one sentence that lets a later block replace them. Codex ranks
|
|
263
|
+
// developer instructions above a user message, so without this permission
|
|
264
|
+
// a mid-chat switch or update is ignored (measured live: the v2 block was
|
|
265
|
+
// delivered and Codex kept ending with v1's line).
|
|
266
|
+
codexInstructions: `${skillsList ? `${skillsList}
|
|
232
267
|
|
|
233
|
-
|
|
268
|
+
` : ""}${instructions}
|
|
269
|
+
${CODEX_REPLACEMENT_CLAUSE}
|
|
270
|
+
`
|
|
234
271
|
};
|
|
235
272
|
}
|
|
236
273
|
function agentArgsFor(provider, attachment, options) {
|
|
@@ -282,9 +319,29 @@ function sessionAgentRecord(bundle, options) {
|
|
|
282
319
|
name: bundle.name,
|
|
283
320
|
definitionHash: bundle.definition_hash,
|
|
284
321
|
loaded,
|
|
285
|
-
unavailable
|
|
322
|
+
unavailable,
|
|
323
|
+
skills: bundle.skills.map((skill) => skill.label),
|
|
324
|
+
tools: options.toolsServed ? bundle.tools.map((tool) => tool.canonical_name) : [],
|
|
325
|
+
...options.variables ? { variables: options.variables } : {}
|
|
286
326
|
};
|
|
287
327
|
}
|
|
328
|
+
var AGENT_REMOVED_BLOCK = "<ai_matrx_agent_removed>The AI Matrx agent instructions given earlier in this chat no longer apply \u2014 including any rule about how replies end. Answer normally from this message on.</ai_matrx_agent_removed>\n\n";
|
|
329
|
+
async function codexCompactionDroppedAgent(rolloutFile, sinceIso) {
|
|
330
|
+
const text = await import_promises2.default.readFile(rolloutFile, "utf8").catch(() => "");
|
|
331
|
+
if (!text.includes('"type":"compacted"')) return false;
|
|
332
|
+
let latest = null;
|
|
333
|
+
for (const line of text.split("\n")) {
|
|
334
|
+
if (!line.includes('"type":"compacted"')) continue;
|
|
335
|
+
try {
|
|
336
|
+
const entry = JSON.parse(line);
|
|
337
|
+
if (entry.type === "compacted") latest = entry;
|
|
338
|
+
} catch {
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
if (!latest) return false;
|
|
342
|
+
if (sinceIso && latest.timestamp && latest.timestamp <= sinceIso) return false;
|
|
343
|
+
return !JSON.stringify(latest.payload?.replacement_history ?? "").includes(AGENT_BLOCK_MARKER.trim());
|
|
344
|
+
}
|
|
288
345
|
|
|
289
346
|
// src/engine/agents.ts
|
|
290
347
|
var import_node_crypto2 = require("crypto");
|
|
@@ -292,6 +349,7 @@ var import_promises3 = __toESM(require("fs/promises"), 1);
|
|
|
292
349
|
var import_node_path2 = __toESM(require("path"), 1);
|
|
293
350
|
var DEFAULT_SERVER_URL = "https://server.app.matrxserver.com";
|
|
294
351
|
var DEFAULT_SUPABASE_URL = "https://db.matrxserver.com";
|
|
352
|
+
var DEFAULT_SUPABASE_KEY = "sb_publishable_scm0jzEJiFUB5ItiqOx5Fg_8BOjB6oA";
|
|
295
353
|
var AGENT_CATALOG_RPCS = /* @__PURE__ */ new Set([
|
|
296
354
|
"agx_get_list_full",
|
|
297
355
|
"agx_search",
|
|
@@ -309,6 +367,10 @@ var agentsClient = async () => {
|
|
|
309
367
|
]);
|
|
310
368
|
return { ...matrx, ...portable, ...mcp };
|
|
311
369
|
};
|
|
370
|
+
function sortedValues(values) {
|
|
371
|
+
return Object.keys(values).sort().map((key) => [key, values[key]]);
|
|
372
|
+
}
|
|
373
|
+
var BUNDLE_CACHE_MS = 24 * 60 * 60 * 1e3;
|
|
312
374
|
var SIGNED_OUT_AGENT_MESSAGE = "Sign in to AI Matrx to use your agents.";
|
|
313
375
|
function userIdOf(credential) {
|
|
314
376
|
if (!credential || credential.kind !== "user") return null;
|
|
@@ -325,21 +387,26 @@ function createAgentConnection(options, dataDir) {
|
|
|
325
387
|
const credentials = options?.credentials ?? null;
|
|
326
388
|
const serverUrl = (options?.serverUrl ?? DEFAULT_SERVER_URL).replace(/\/+$/, "");
|
|
327
389
|
const supabaseUrl = (options?.supabaseUrl ?? DEFAULT_SUPABASE_URL).replace(/\/+$/, "");
|
|
328
|
-
const supabaseKey = options?.supabaseKey ?? null;
|
|
390
|
+
const supabaseKey = options?.supabaseKey ?? (options?.supabaseUrl ? null : DEFAULT_SUPABASE_KEY);
|
|
329
391
|
const root = import_node_path2.default.join(dataDir, "agents");
|
|
330
392
|
let mcpBaseUrl = null;
|
|
331
393
|
const handlers = /* @__PURE__ */ new Map();
|
|
332
394
|
const secretToSession = /* @__PURE__ */ new Map();
|
|
333
|
-
const organizationId = () => {
|
|
334
|
-
const raw = typeof options?.organizationId === "function" ? options.organizationId() : options?.organizationId;
|
|
395
|
+
const organizationId = async () => {
|
|
396
|
+
const raw = typeof options?.organizationId === "function" ? await options.organizationId() : options?.organizationId;
|
|
335
397
|
return raw && raw.trim() ? raw.trim() : null;
|
|
336
398
|
};
|
|
337
|
-
const transport = async () =>
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
399
|
+
const transport = async () => {
|
|
400
|
+
const org = await organizationId();
|
|
401
|
+
return (await agentsClient()).createMatrxTransport({
|
|
402
|
+
baseUrl: serverUrl,
|
|
403
|
+
...credentials ? { credentials } : {},
|
|
404
|
+
...org ? { organizationId: org } : {},
|
|
405
|
+
source: "codingSessionsAgents"
|
|
406
|
+
});
|
|
407
|
+
};
|
|
408
|
+
const cacheDir = import_node_path2.default.join(dataDir, "agents", ".bundles");
|
|
409
|
+
const cacheKey = (definitionHash, selection, surface) => (0, import_node_crypto2.createHash)("sha256").update(JSON.stringify([definitionHash, sortedValues(selection.variables ?? {}), surface])).digest("hex");
|
|
343
410
|
const credential = async () => credentials ? credentials.get() : null;
|
|
344
411
|
const requireSignedIn = async () => {
|
|
345
412
|
if (!await credential()) throw new Error(SIGNED_OUT_AGENT_MESSAGE);
|
|
@@ -375,7 +442,7 @@ function createAgentConnection(options, dataDir) {
|
|
|
375
442
|
configured: credentials !== null && supabaseKey !== null,
|
|
376
443
|
signedIn: userId !== null,
|
|
377
444
|
userId,
|
|
378
|
-
organizationId: organizationId()
|
|
445
|
+
organizationId: await organizationId().catch(() => null)
|
|
379
446
|
};
|
|
380
447
|
},
|
|
381
448
|
async catalogRpc(request) {
|
|
@@ -422,27 +489,39 @@ function createAgentConnection(options, dataDir) {
|
|
|
422
489
|
},
|
|
423
490
|
async details(agentId) {
|
|
424
491
|
await requireSignedIn();
|
|
425
|
-
const
|
|
426
|
-
const [bundle, versions] = await Promise.all([
|
|
427
|
-
fetchPortableAgent(await transport(), { agentId }),
|
|
428
|
-
fetchPortableAgentVersions(await transport(), agentId).catch(() => [])
|
|
429
|
-
]);
|
|
492
|
+
const summary = await (await agentsClient()).fetchPortableAgentSummary(await transport(), agentId);
|
|
430
493
|
return {
|
|
431
|
-
agentId:
|
|
432
|
-
name:
|
|
433
|
-
variables:
|
|
434
|
-
versions: versions.map((v) => ({ id: v.id, versionNumber: v.version_number, changedAt: v.changed_at }))
|
|
435
|
-
latestVersionNumber:
|
|
494
|
+
agentId: summary.agent_id,
|
|
495
|
+
name: summary.name,
|
|
496
|
+
variables: summary.variables,
|
|
497
|
+
versions: summary.versions.map((v) => ({ id: v.id, versionNumber: v.version_number, changedAt: v.changed_at })),
|
|
498
|
+
latestVersionNumber: summary.version_number,
|
|
499
|
+
latestVersionId: summary.version_id
|
|
436
500
|
};
|
|
437
501
|
},
|
|
438
502
|
async loadBundle(selection) {
|
|
439
503
|
await requireSignedIn();
|
|
440
|
-
const
|
|
441
|
-
|
|
504
|
+
const client = await agentsClient();
|
|
505
|
+
const summary = await client.fetchPortableAgentSummary(await transport(), selection.agentId);
|
|
506
|
+
const versionId = selection.versionId ?? summary.version_id;
|
|
507
|
+
const definitionHash = versionId ? summary.versions.find((v) => v.id === versionId)?.definition_hash ?? null : summary.definition_hash;
|
|
508
|
+
const surface = "matrx-user/code-editor";
|
|
509
|
+
const file = definitionHash ? import_node_path2.default.join(cacheDir, `${cacheKey(definitionHash, selection, surface)}.json`) : null;
|
|
510
|
+
if (file) {
|
|
511
|
+
const cached = await import_promises3.default.readFile(file, "utf8").then((text) => JSON.parse(text)).catch(() => null);
|
|
512
|
+
const fresh = await import_promises3.default.stat(file).then((st) => Date.now() - st.mtimeMs < BUNDLE_CACHE_MS).catch(() => false);
|
|
513
|
+
if (cached && fresh && cached.definition_hash === definitionHash) return cached;
|
|
514
|
+
}
|
|
515
|
+
const bundle = await client.fetchPortableAgent(
|
|
442
516
|
await transport(),
|
|
443
|
-
|
|
444
|
-
{ variables: selection.variables ?? {} }
|
|
517
|
+
versionId ? { versionId } : { agentId: selection.agentId },
|
|
518
|
+
{ variables: selection.variables ?? {}, surface }
|
|
445
519
|
);
|
|
520
|
+
if (file && bundle.definition_hash === definitionHash) {
|
|
521
|
+
await import_promises3.default.mkdir(cacheDir, { recursive: true, mode: 448 });
|
|
522
|
+
await import_promises3.default.writeFile(file, JSON.stringify(bundle), { mode: 384 });
|
|
523
|
+
}
|
|
524
|
+
return bundle;
|
|
446
525
|
},
|
|
447
526
|
async saveSessionBundle(sessionId, bundle) {
|
|
448
527
|
await import_promises3.default.mkdir(sessionDir(sessionId), { recursive: true, mode: 448 });
|
|
@@ -578,7 +657,7 @@ function createClaudeNormalizer() {
|
|
|
578
657
|
if (typeof content === "string") {
|
|
579
658
|
if (isSyntheticClaudeUserText(content) || content.trim().length === 0) return [];
|
|
580
659
|
userCounter += 1;
|
|
581
|
-
return [{ kind: "user", id: str(entry.uuid) ?? `user-${userCounter}`, text: content, at }];
|
|
660
|
+
return [{ kind: "user", id: str(entry.uuid) ?? `user-${userCounter}`, text: stripAgentBlock(content), at }];
|
|
582
661
|
}
|
|
583
662
|
if (!Array.isArray(content)) return [];
|
|
584
663
|
const items = [];
|
|
@@ -602,7 +681,7 @@ function createClaudeNormalizer() {
|
|
|
602
681
|
items.unshift({
|
|
603
682
|
kind: "user",
|
|
604
683
|
id: str(entry.uuid) ?? `user-${userCounter}`,
|
|
605
|
-
text: typed.join("\n\n"),
|
|
684
|
+
text: stripAgentBlock(typed.join("\n\n")),
|
|
606
685
|
at
|
|
607
686
|
});
|
|
608
687
|
}
|
|
@@ -857,7 +936,7 @@ function rolloutItem(item, fallbackId, at) {
|
|
|
857
936
|
const id = str2(item.id) ?? fallbackId;
|
|
858
937
|
switch (item.type) {
|
|
859
938
|
case "UserMessage": {
|
|
860
|
-
const text = stripCodexInjectedContext(itemText(item.content));
|
|
939
|
+
const text = stripCodexInjectedContext(stripAgentBlock(itemText(item.content)));
|
|
861
940
|
return text.trim() ? [{ kind: "user", id, text, at }] : [];
|
|
862
941
|
}
|
|
863
942
|
case "AgentMessage": {
|
|
@@ -940,7 +1019,7 @@ function createCodexRolloutNormalizer() {
|
|
|
940
1019
|
return rolloutItem(payload.item, fallbackId, at);
|
|
941
1020
|
}
|
|
942
1021
|
if (payload.type === "user_message" && !appItems) {
|
|
943
|
-
const text = stripCodexInjectedContext(str2(payload.message) ?? "");
|
|
1022
|
+
const text = stripCodexInjectedContext(stripAgentBlock(str2(payload.message) ?? ""));
|
|
944
1023
|
return text.trim() ? [{ kind: "user", id: fallbackId, text, at }] : [];
|
|
945
1024
|
}
|
|
946
1025
|
return [];
|
|
@@ -2418,6 +2497,12 @@ async function createCodingSessionsEngine(options = {}) {
|
|
|
2418
2497
|
if (file) fileOffset = (await import_promises8.default.stat(file).catch(() => null))?.size ?? null;
|
|
2419
2498
|
}
|
|
2420
2499
|
let agentArgs = [];
|
|
2500
|
+
let cliPrompt = prompt;
|
|
2501
|
+
let delivered = null;
|
|
2502
|
+
if (!session.agent && session.agentRemovedDue) {
|
|
2503
|
+
cliPrompt = `${AGENT_REMOVED_BLOCK}${prompt}`;
|
|
2504
|
+
delivered = { agentRemovedDue: false };
|
|
2505
|
+
}
|
|
2421
2506
|
if (session.agent) {
|
|
2422
2507
|
const bundle = await agents.readSessionBundle(session.id);
|
|
2423
2508
|
if (!bundle) {
|
|
@@ -2435,6 +2520,10 @@ async function createCodingSessionsEngine(options = {}) {
|
|
|
2435
2520
|
mcpUrl: await agents.mcpUrlFor(session.id)
|
|
2436
2521
|
});
|
|
2437
2522
|
agentArgs = agentArgsFor(provider, attachment, { resuming: session.providerSessionId !== null });
|
|
2523
|
+
if (session.agent.blockDue) {
|
|
2524
|
+
cliPrompt = `${renderFallbackBlock(bundle, import_node_path9.default.join(attachment.dir, "skills"), { replaces: session.agent.replaces })}${prompt}`;
|
|
2525
|
+
}
|
|
2526
|
+
delivered = { agent: { ...session.agent, blockDue: false, deliveredAt: run.startedAt } };
|
|
2438
2527
|
}
|
|
2439
2528
|
const child = forkWorker();
|
|
2440
2529
|
const liveRun = {
|
|
@@ -2450,6 +2539,10 @@ async function createCodingSessionsEngine(options = {}) {
|
|
|
2450
2539
|
};
|
|
2451
2540
|
live.set(runId, liveRun);
|
|
2452
2541
|
emitItem(liveRun, { kind: "user", id: `run-${runId}`, text: prompt, at: run.startedAt });
|
|
2542
|
+
if (delivered) {
|
|
2543
|
+
const current = index.session(session.id);
|
|
2544
|
+
if (current) saveSession({ ...current, ...delivered });
|
|
2545
|
+
}
|
|
2453
2546
|
const splitter = createLineSplitter();
|
|
2454
2547
|
const claude = provider === "claude" ? createClaudeNormalizer() : null;
|
|
2455
2548
|
const codex = provider === "codex" ? createCodexStreamNormalizer(runId.slice(0, 8)) : null;
|
|
@@ -2488,6 +2581,7 @@ async function createCodingSessionsEngine(options = {}) {
|
|
|
2488
2581
|
}
|
|
2489
2582
|
}
|
|
2490
2583
|
void pruneDriverScratch();
|
|
2584
|
+
if (provider === "codex" && final.status === "completed") void checkCompaction(session.id);
|
|
2491
2585
|
};
|
|
2492
2586
|
let settled = false;
|
|
2493
2587
|
child.on("message", (raw) => {
|
|
@@ -2602,7 +2696,7 @@ async function createCodingSessionsEngine(options = {}) {
|
|
|
2602
2696
|
provider,
|
|
2603
2697
|
runId,
|
|
2604
2698
|
cwd: session.cwd,
|
|
2605
|
-
prompt,
|
|
2699
|
+
prompt: cliPrompt,
|
|
2606
2700
|
model,
|
|
2607
2701
|
effort: session.effort ?? null,
|
|
2608
2702
|
resumeSessionId: session.providerSessionId,
|
|
@@ -2613,6 +2707,29 @@ async function createCodingSessionsEngine(options = {}) {
|
|
|
2613
2707
|
});
|
|
2614
2708
|
return run;
|
|
2615
2709
|
}
|
|
2710
|
+
async function checkCompaction(sessionId) {
|
|
2711
|
+
const session = index.session(sessionId);
|
|
2712
|
+
if (!session?.agent || session.agent.blockDue || !session.providerSessionId) return;
|
|
2713
|
+
const file = await findSessionFile("codex", session.providerSessionId, homes);
|
|
2714
|
+
if (!file || !await codexCompactionDroppedAgent(file, session.agent.deliveredAt ?? null)) return;
|
|
2715
|
+
const current = index.session(sessionId);
|
|
2716
|
+
if (current?.agent) {
|
|
2717
|
+
saveSession({ ...current, agent: { ...current.agent, blockDue: true } });
|
|
2718
|
+
}
|
|
2719
|
+
}
|
|
2720
|
+
async function attachAgent(sessionId, selection, options2) {
|
|
2721
|
+
const bundle = await agents.loadBundle(selection);
|
|
2722
|
+
await agents.saveSessionBundle(sessionId, bundle);
|
|
2723
|
+
return {
|
|
2724
|
+
...sessionAgentRecord(bundle, {
|
|
2725
|
+
toolsServed: await agents.mcpUrlFor(sessionId) !== null,
|
|
2726
|
+
variables: selection.variables ?? {}
|
|
2727
|
+
}),
|
|
2728
|
+
blockDue: options2.blockDue,
|
|
2729
|
+
deliveredAt: null,
|
|
2730
|
+
replaces: options2.replaces ?? null
|
|
2731
|
+
};
|
|
2732
|
+
}
|
|
2616
2733
|
function killGroup(liveRun) {
|
|
2617
2734
|
const target = liveRun.pgid;
|
|
2618
2735
|
if (target === null) return;
|
|
@@ -2869,7 +2986,6 @@ async function createCodingSessionsEngine(options = {}) {
|
|
|
2869
2986
|
const prompt = input.prompt.trim();
|
|
2870
2987
|
if (!prompt) throw new Error("Type what you want done before starting.");
|
|
2871
2988
|
const cwd = await assertFolder(input.cwd);
|
|
2872
|
-
const bundle = input.agent ? await agents.loadBundle(input.agent) : null;
|
|
2873
2989
|
const draft = newSession({
|
|
2874
2990
|
provider: input.provider,
|
|
2875
2991
|
cwd,
|
|
@@ -2879,28 +2995,43 @@ async function createCodingSessionsEngine(options = {}) {
|
|
|
2879
2995
|
origin: "started",
|
|
2880
2996
|
providerSessionId: null
|
|
2881
2997
|
});
|
|
2882
|
-
if (
|
|
2883
|
-
await agents.saveSessionBundle(draft.id, bundle);
|
|
2884
|
-
draft.agent = sessionAgentRecord(bundle, { toolsServed: await agents.mcpUrlFor(draft.id) !== null });
|
|
2885
|
-
}
|
|
2998
|
+
if (input.agent) draft.agent = await attachAgent(draft.id, input.agent, { blockDue: false });
|
|
2886
2999
|
const session = saveSession(draft);
|
|
2887
3000
|
const run = await startRun(session, prompt);
|
|
2888
3001
|
return { session: index.session(session.id) ?? session, run, queued: false };
|
|
2889
3002
|
},
|
|
2890
3003
|
async takeover(input) {
|
|
2891
3004
|
const existing = index.session(input.providerSessionId);
|
|
2892
|
-
if (existing)
|
|
3005
|
+
if (existing) {
|
|
3006
|
+
if (!input.agent) return existing;
|
|
3007
|
+
return engine.setAgent(existing.id, input.agent);
|
|
3008
|
+
}
|
|
2893
3009
|
const cwd = await assertFolder(input.cwd);
|
|
2894
|
-
|
|
2895
|
-
|
|
2896
|
-
|
|
2897
|
-
|
|
2898
|
-
|
|
2899
|
-
|
|
2900
|
-
|
|
2901
|
-
|
|
2902
|
-
|
|
2903
|
-
);
|
|
3010
|
+
const draft = newSession({
|
|
3011
|
+
provider: input.provider,
|
|
3012
|
+
cwd,
|
|
3013
|
+
title: input.title?.trim() || "Taken-over chat",
|
|
3014
|
+
model: null,
|
|
3015
|
+
origin: "takeover",
|
|
3016
|
+
providerSessionId: input.providerSessionId
|
|
3017
|
+
});
|
|
3018
|
+
if (input.agent) draft.agent = await attachAgent(draft.id, input.agent, { blockDue: input.provider === "codex" });
|
|
3019
|
+
return saveSession(draft);
|
|
3020
|
+
},
|
|
3021
|
+
async setAgent(sessionId, selection) {
|
|
3022
|
+
const session = index.session(String(sessionId ?? ""));
|
|
3023
|
+
if (!session) throw new Error("This session is not in the list anymore.");
|
|
3024
|
+
if (!selection) {
|
|
3025
|
+
const told = session.agent?.deliveredAt != null;
|
|
3026
|
+
return saveSession({ ...session, agent: null, agentRemovedDue: told });
|
|
3027
|
+
}
|
|
3028
|
+
const previous = session.agent && session.agent.deliveredAt != null ? session.agent : null;
|
|
3029
|
+
const started = session.providerSessionId !== null;
|
|
3030
|
+
const agent = await attachAgent(session.id, selection, {
|
|
3031
|
+
blockDue: started,
|
|
3032
|
+
replaces: previous ? `${previous.name}${previous.versionNumber !== null ? ` v${previous.versionNumber}` : ""}` : null
|
|
3033
|
+
});
|
|
3034
|
+
return saveSession({ ...session, agent, agentRemovedDue: false });
|
|
2904
3035
|
},
|
|
2905
3036
|
async send(sessionId, rawPrompt) {
|
|
2906
3037
|
const prompt = rawPrompt.trim();
|
|
@@ -3039,7 +3170,8 @@ var BRIDGE_METHODS = [
|
|
|
3039
3170
|
"setSessionOptions",
|
|
3040
3171
|
"agentAccess",
|
|
3041
3172
|
"agentCatalogRpc",
|
|
3042
|
-
"agentDetails"
|
|
3173
|
+
"agentDetails",
|
|
3174
|
+
"setAgent"
|
|
3043
3175
|
];
|
|
3044
3176
|
var BridgeError = class extends Error {
|
|
3045
3177
|
constructor(message, code) {
|