@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.d.cts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { C as CodingSessionsMethod, a as CodingSessionsApi, b as CodingEvent, c as CodingSessionsEngine, d as CodingSessionsEngineOptions } from '../index-
|
|
1
|
+
import { C as CodingSessionsMethod, a as CodingSessionsApi, b as CodingEvent, c as CodingSessionsEngine, d as CodingSessionsEngineOptions } from '../index-CDeDKQHe.cjs';
|
|
2
|
+
export { e as CodingSessionsAgentsOptions } from '../index-CDeDKQHe.cjs';
|
|
2
3
|
import '@ai-matrx/agents/portable';
|
|
3
4
|
import '@ai-matrx/data';
|
|
4
5
|
import '@ai-matrx/agents/portable/mcp';
|
package/dist/server/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { C as CodingSessionsMethod, a as CodingSessionsApi, b as CodingEvent, c as CodingSessionsEngine, d as CodingSessionsEngineOptions } from '../index-
|
|
1
|
+
import { C as CodingSessionsMethod, a as CodingSessionsApi, b as CodingEvent, c as CodingSessionsEngine, d as CodingSessionsEngineOptions } from '../index-CDeDKQHe.js';
|
|
2
|
+
export { e as CodingSessionsAgentsOptions } from '../index-CDeDKQHe.js';
|
|
2
3
|
import '@ai-matrx/agents/portable';
|
|
3
4
|
import '@ai-matrx/data';
|
|
4
5
|
import '@ai-matrx/agents/portable/mcp';
|
package/dist/server/index.js
CHANGED
|
@@ -73,8 +73,25 @@ function createRawBackupScheduler(options) {
|
|
|
73
73
|
// src/engine/agent-attach.ts
|
|
74
74
|
import fs2 from "fs/promises";
|
|
75
75
|
import path from "path";
|
|
76
|
+
|
|
77
|
+
// src/normalize/agent-block.ts
|
|
78
|
+
var AGENT_BLOCK_MARKER = "<ai_matrx_agent ";
|
|
79
|
+
function stripAgentBlock(text) {
|
|
80
|
+
const removed = text.match(/^<ai_matrx_agent_removed>[\s\S]*?<\/ai_matrx_agent_removed>\s*/);
|
|
81
|
+
if (removed) return text.slice(removed[0].length);
|
|
82
|
+
if (!text.startsWith(AGENT_BLOCK_MARKER)) return text;
|
|
83
|
+
const end = text.indexOf("</ai_matrx_agent>");
|
|
84
|
+
if (end < 0) return text;
|
|
85
|
+
let rest = text.slice(end + "</ai_matrx_agent>".length);
|
|
86
|
+
const skills = rest.match(/^\s*<skills_instructions>[\s\S]*?<\/skills_instructions>/);
|
|
87
|
+
if (skills) rest = rest.slice(skills[0].length);
|
|
88
|
+
return rest.replace(/^\s+/, "");
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// src/engine/agent-attach.ts
|
|
76
92
|
var AGENT_MCP_SERVER_NAME = "matrx-agent";
|
|
77
93
|
var AGENT_PLUGIN_NAME = "matrx-agent";
|
|
94
|
+
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.";
|
|
78
95
|
function escapeAttr(value) {
|
|
79
96
|
return value.replace(/&/g, "&").replace(/"/g, """).replace(/</g, "<");
|
|
80
97
|
}
|
|
@@ -123,6 +140,20 @@ function renderCodexSkillsList(bundle, skillsRoot) {
|
|
|
123
140
|
];
|
|
124
141
|
return lines.join("\n");
|
|
125
142
|
}
|
|
143
|
+
function renderFallbackBlock(bundle, skillsRoot, options = {}) {
|
|
144
|
+
const skills = renderCodexSkillsList(bundle, skillsRoot);
|
|
145
|
+
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.";
|
|
146
|
+
const body = renderAgentInstructions(bundle).trim().replace(/^(<ai_matrx_agent [^>]*>)/, `$1
|
|
147
|
+
|
|
148
|
+
${lead}`);
|
|
149
|
+
return skills ? `${body}
|
|
150
|
+
|
|
151
|
+
${skills}
|
|
152
|
+
|
|
153
|
+
` : `${body}
|
|
154
|
+
|
|
155
|
+
`;
|
|
156
|
+
}
|
|
126
157
|
function tomlString(value) {
|
|
127
158
|
const scalar = value.replace(/[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?<![\uD800-\uDBFF])[\uDC00-\uDFFF]/g, "\uFFFD");
|
|
128
159
|
return JSON.stringify(scalar).replace(/\u007f/g, "\\u007f");
|
|
@@ -183,10 +214,16 @@ async function writeAgentAttachment(dir, bundle, options) {
|
|
|
183
214
|
pluginDir,
|
|
184
215
|
mcpConfigFile,
|
|
185
216
|
mcpUrl,
|
|
186
|
-
// Same order as Claude's: the skills list first, the agent's words last
|
|
187
|
-
|
|
217
|
+
// Same order as Claude's: the skills list first, the agent's words last —
|
|
218
|
+
// then the one sentence that lets a later block replace them. Codex ranks
|
|
219
|
+
// developer instructions above a user message, so without this permission
|
|
220
|
+
// a mid-chat switch or update is ignored (measured live: the v2 block was
|
|
221
|
+
// delivered and Codex kept ending with v1's line).
|
|
222
|
+
codexInstructions: `${skillsList ? `${skillsList}
|
|
188
223
|
|
|
189
|
-
|
|
224
|
+
` : ""}${instructions}
|
|
225
|
+
${CODEX_REPLACEMENT_CLAUSE}
|
|
226
|
+
`
|
|
190
227
|
};
|
|
191
228
|
}
|
|
192
229
|
function agentArgsFor(provider, attachment, options) {
|
|
@@ -238,16 +275,37 @@ function sessionAgentRecord(bundle, options) {
|
|
|
238
275
|
name: bundle.name,
|
|
239
276
|
definitionHash: bundle.definition_hash,
|
|
240
277
|
loaded,
|
|
241
|
-
unavailable
|
|
278
|
+
unavailable,
|
|
279
|
+
skills: bundle.skills.map((skill) => skill.label),
|
|
280
|
+
tools: options.toolsServed ? bundle.tools.map((tool) => tool.canonical_name) : [],
|
|
281
|
+
...options.variables ? { variables: options.variables } : {}
|
|
242
282
|
};
|
|
243
283
|
}
|
|
284
|
+
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";
|
|
285
|
+
async function codexCompactionDroppedAgent(rolloutFile, sinceIso) {
|
|
286
|
+
const text = await fs2.readFile(rolloutFile, "utf8").catch(() => "");
|
|
287
|
+
if (!text.includes('"type":"compacted"')) return false;
|
|
288
|
+
let latest = null;
|
|
289
|
+
for (const line of text.split("\n")) {
|
|
290
|
+
if (!line.includes('"type":"compacted"')) continue;
|
|
291
|
+
try {
|
|
292
|
+
const entry = JSON.parse(line);
|
|
293
|
+
if (entry.type === "compacted") latest = entry;
|
|
294
|
+
} catch {
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
if (!latest) return false;
|
|
298
|
+
if (sinceIso && latest.timestamp && latest.timestamp <= sinceIso) return false;
|
|
299
|
+
return !JSON.stringify(latest.payload?.replacement_history ?? "").includes(AGENT_BLOCK_MARKER.trim());
|
|
300
|
+
}
|
|
244
301
|
|
|
245
302
|
// src/engine/agents.ts
|
|
246
|
-
import { randomBytes, randomUUID } from "crypto";
|
|
303
|
+
import { createHash as createHash2, randomBytes, randomUUID } from "crypto";
|
|
247
304
|
import fs3 from "fs/promises";
|
|
248
305
|
import path2 from "path";
|
|
249
306
|
var DEFAULT_SERVER_URL = "https://server.app.matrxserver.com";
|
|
250
307
|
var DEFAULT_SUPABASE_URL = "https://db.matrxserver.com";
|
|
308
|
+
var DEFAULT_SUPABASE_KEY = "sb_publishable_scm0jzEJiFUB5ItiqOx5Fg_8BOjB6oA";
|
|
251
309
|
var AGENT_CATALOG_RPCS = /* @__PURE__ */ new Set([
|
|
252
310
|
"agx_get_list_full",
|
|
253
311
|
"agx_search",
|
|
@@ -265,6 +323,10 @@ var agentsClient = async () => {
|
|
|
265
323
|
]);
|
|
266
324
|
return { ...matrx, ...portable, ...mcp };
|
|
267
325
|
};
|
|
326
|
+
function sortedValues(values) {
|
|
327
|
+
return Object.keys(values).sort().map((key) => [key, values[key]]);
|
|
328
|
+
}
|
|
329
|
+
var BUNDLE_CACHE_MS = 24 * 60 * 60 * 1e3;
|
|
268
330
|
var SIGNED_OUT_AGENT_MESSAGE = "Sign in to AI Matrx to use your agents.";
|
|
269
331
|
function userIdOf(credential) {
|
|
270
332
|
if (!credential || credential.kind !== "user") return null;
|
|
@@ -281,21 +343,26 @@ function createAgentConnection(options, dataDir) {
|
|
|
281
343
|
const credentials = options?.credentials ?? null;
|
|
282
344
|
const serverUrl = (options?.serverUrl ?? DEFAULT_SERVER_URL).replace(/\/+$/, "");
|
|
283
345
|
const supabaseUrl = (options?.supabaseUrl ?? DEFAULT_SUPABASE_URL).replace(/\/+$/, "");
|
|
284
|
-
const supabaseKey = options?.supabaseKey ?? null;
|
|
346
|
+
const supabaseKey = options?.supabaseKey ?? (options?.supabaseUrl ? null : DEFAULT_SUPABASE_KEY);
|
|
285
347
|
const root = path2.join(dataDir, "agents");
|
|
286
348
|
let mcpBaseUrl = null;
|
|
287
349
|
const handlers = /* @__PURE__ */ new Map();
|
|
288
350
|
const secretToSession = /* @__PURE__ */ new Map();
|
|
289
|
-
const organizationId = () => {
|
|
290
|
-
const raw = typeof options?.organizationId === "function" ? options.organizationId() : options?.organizationId;
|
|
351
|
+
const organizationId = async () => {
|
|
352
|
+
const raw = typeof options?.organizationId === "function" ? await options.organizationId() : options?.organizationId;
|
|
291
353
|
return raw && raw.trim() ? raw.trim() : null;
|
|
292
354
|
};
|
|
293
|
-
const transport = async () =>
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
355
|
+
const transport = async () => {
|
|
356
|
+
const org = await organizationId();
|
|
357
|
+
return (await agentsClient()).createMatrxTransport({
|
|
358
|
+
baseUrl: serverUrl,
|
|
359
|
+
...credentials ? { credentials } : {},
|
|
360
|
+
...org ? { organizationId: org } : {},
|
|
361
|
+
source: "codingSessionsAgents"
|
|
362
|
+
});
|
|
363
|
+
};
|
|
364
|
+
const cacheDir = path2.join(dataDir, "agents", ".bundles");
|
|
365
|
+
const cacheKey = (definitionHash, selection, surface) => createHash2("sha256").update(JSON.stringify([definitionHash, sortedValues(selection.variables ?? {}), surface])).digest("hex");
|
|
299
366
|
const credential = async () => credentials ? credentials.get() : null;
|
|
300
367
|
const requireSignedIn = async () => {
|
|
301
368
|
if (!await credential()) throw new Error(SIGNED_OUT_AGENT_MESSAGE);
|
|
@@ -331,7 +398,7 @@ function createAgentConnection(options, dataDir) {
|
|
|
331
398
|
configured: credentials !== null && supabaseKey !== null,
|
|
332
399
|
signedIn: userId !== null,
|
|
333
400
|
userId,
|
|
334
|
-
organizationId: organizationId()
|
|
401
|
+
organizationId: await organizationId().catch(() => null)
|
|
335
402
|
};
|
|
336
403
|
},
|
|
337
404
|
async catalogRpc(request) {
|
|
@@ -378,27 +445,39 @@ function createAgentConnection(options, dataDir) {
|
|
|
378
445
|
},
|
|
379
446
|
async details(agentId) {
|
|
380
447
|
await requireSignedIn();
|
|
381
|
-
const
|
|
382
|
-
const [bundle, versions] = await Promise.all([
|
|
383
|
-
fetchPortableAgent(await transport(), { agentId }),
|
|
384
|
-
fetchPortableAgentVersions(await transport(), agentId).catch(() => [])
|
|
385
|
-
]);
|
|
448
|
+
const summary = await (await agentsClient()).fetchPortableAgentSummary(await transport(), agentId);
|
|
386
449
|
return {
|
|
387
|
-
agentId:
|
|
388
|
-
name:
|
|
389
|
-
variables:
|
|
390
|
-
versions: versions.map((v) => ({ id: v.id, versionNumber: v.version_number, changedAt: v.changed_at }))
|
|
391
|
-
latestVersionNumber:
|
|
450
|
+
agentId: summary.agent_id,
|
|
451
|
+
name: summary.name,
|
|
452
|
+
variables: summary.variables,
|
|
453
|
+
versions: summary.versions.map((v) => ({ id: v.id, versionNumber: v.version_number, changedAt: v.changed_at })),
|
|
454
|
+
latestVersionNumber: summary.version_number,
|
|
455
|
+
latestVersionId: summary.version_id
|
|
392
456
|
};
|
|
393
457
|
},
|
|
394
458
|
async loadBundle(selection) {
|
|
395
459
|
await requireSignedIn();
|
|
396
|
-
const
|
|
397
|
-
|
|
460
|
+
const client = await agentsClient();
|
|
461
|
+
const summary = await client.fetchPortableAgentSummary(await transport(), selection.agentId);
|
|
462
|
+
const versionId = selection.versionId ?? summary.version_id;
|
|
463
|
+
const definitionHash = versionId ? summary.versions.find((v) => v.id === versionId)?.definition_hash ?? null : summary.definition_hash;
|
|
464
|
+
const surface = "matrx-user/code-editor";
|
|
465
|
+
const file = definitionHash ? path2.join(cacheDir, `${cacheKey(definitionHash, selection, surface)}.json`) : null;
|
|
466
|
+
if (file) {
|
|
467
|
+
const cached = await fs3.readFile(file, "utf8").then((text) => JSON.parse(text)).catch(() => null);
|
|
468
|
+
const fresh = await fs3.stat(file).then((st) => Date.now() - st.mtimeMs < BUNDLE_CACHE_MS).catch(() => false);
|
|
469
|
+
if (cached && fresh && cached.definition_hash === definitionHash) return cached;
|
|
470
|
+
}
|
|
471
|
+
const bundle = await client.fetchPortableAgent(
|
|
398
472
|
await transport(),
|
|
399
|
-
|
|
400
|
-
{ variables: selection.variables ?? {} }
|
|
473
|
+
versionId ? { versionId } : { agentId: selection.agentId },
|
|
474
|
+
{ variables: selection.variables ?? {}, surface }
|
|
401
475
|
);
|
|
476
|
+
if (file && bundle.definition_hash === definitionHash) {
|
|
477
|
+
await fs3.mkdir(cacheDir, { recursive: true, mode: 448 });
|
|
478
|
+
await fs3.writeFile(file, JSON.stringify(bundle), { mode: 384 });
|
|
479
|
+
}
|
|
480
|
+
return bundle;
|
|
402
481
|
},
|
|
403
482
|
async saveSessionBundle(sessionId, bundle) {
|
|
404
483
|
await fs3.mkdir(sessionDir(sessionId), { recursive: true, mode: 448 });
|
|
@@ -534,7 +613,7 @@ function createClaudeNormalizer() {
|
|
|
534
613
|
if (typeof content === "string") {
|
|
535
614
|
if (isSyntheticClaudeUserText(content) || content.trim().length === 0) return [];
|
|
536
615
|
userCounter += 1;
|
|
537
|
-
return [{ kind: "user", id: str(entry.uuid) ?? `user-${userCounter}`, text: content, at }];
|
|
616
|
+
return [{ kind: "user", id: str(entry.uuid) ?? `user-${userCounter}`, text: stripAgentBlock(content), at }];
|
|
538
617
|
}
|
|
539
618
|
if (!Array.isArray(content)) return [];
|
|
540
619
|
const items = [];
|
|
@@ -558,7 +637,7 @@ function createClaudeNormalizer() {
|
|
|
558
637
|
items.unshift({
|
|
559
638
|
kind: "user",
|
|
560
639
|
id: str(entry.uuid) ?? `user-${userCounter}`,
|
|
561
|
-
text: typed.join("\n\n"),
|
|
640
|
+
text: stripAgentBlock(typed.join("\n\n")),
|
|
562
641
|
at
|
|
563
642
|
});
|
|
564
643
|
}
|
|
@@ -813,7 +892,7 @@ function rolloutItem(item, fallbackId, at) {
|
|
|
813
892
|
const id = str2(item.id) ?? fallbackId;
|
|
814
893
|
switch (item.type) {
|
|
815
894
|
case "UserMessage": {
|
|
816
|
-
const text = stripCodexInjectedContext(itemText(item.content));
|
|
895
|
+
const text = stripCodexInjectedContext(stripAgentBlock(itemText(item.content)));
|
|
817
896
|
return text.trim() ? [{ kind: "user", id, text, at }] : [];
|
|
818
897
|
}
|
|
819
898
|
case "AgentMessage": {
|
|
@@ -896,7 +975,7 @@ function createCodexRolloutNormalizer() {
|
|
|
896
975
|
return rolloutItem(payload.item, fallbackId, at);
|
|
897
976
|
}
|
|
898
977
|
if (payload.type === "user_message" && !appItems) {
|
|
899
|
-
const text = stripCodexInjectedContext(str2(payload.message) ?? "");
|
|
978
|
+
const text = stripCodexInjectedContext(stripAgentBlock(str2(payload.message) ?? ""));
|
|
900
979
|
return text.trim() ? [{ kind: "user", id: fallbackId, text, at }] : [];
|
|
901
980
|
}
|
|
902
981
|
return [];
|
|
@@ -2374,6 +2453,12 @@ async function createCodingSessionsEngine(options = {}) {
|
|
|
2374
2453
|
if (file) fileOffset = (await fs8.stat(file).catch(() => null))?.size ?? null;
|
|
2375
2454
|
}
|
|
2376
2455
|
let agentArgs = [];
|
|
2456
|
+
let cliPrompt = prompt;
|
|
2457
|
+
let delivered = null;
|
|
2458
|
+
if (!session.agent && session.agentRemovedDue) {
|
|
2459
|
+
cliPrompt = `${AGENT_REMOVED_BLOCK}${prompt}`;
|
|
2460
|
+
delivered = { agentRemovedDue: false };
|
|
2461
|
+
}
|
|
2377
2462
|
if (session.agent) {
|
|
2378
2463
|
const bundle = await agents.readSessionBundle(session.id);
|
|
2379
2464
|
if (!bundle) {
|
|
@@ -2391,6 +2476,10 @@ async function createCodingSessionsEngine(options = {}) {
|
|
|
2391
2476
|
mcpUrl: await agents.mcpUrlFor(session.id)
|
|
2392
2477
|
});
|
|
2393
2478
|
agentArgs = agentArgsFor(provider, attachment, { resuming: session.providerSessionId !== null });
|
|
2479
|
+
if (session.agent.blockDue) {
|
|
2480
|
+
cliPrompt = `${renderFallbackBlock(bundle, path9.join(attachment.dir, "skills"), { replaces: session.agent.replaces })}${prompt}`;
|
|
2481
|
+
}
|
|
2482
|
+
delivered = { agent: { ...session.agent, blockDue: false, deliveredAt: run.startedAt } };
|
|
2394
2483
|
}
|
|
2395
2484
|
const child = forkWorker();
|
|
2396
2485
|
const liveRun = {
|
|
@@ -2406,6 +2495,10 @@ async function createCodingSessionsEngine(options = {}) {
|
|
|
2406
2495
|
};
|
|
2407
2496
|
live.set(runId, liveRun);
|
|
2408
2497
|
emitItem(liveRun, { kind: "user", id: `run-${runId}`, text: prompt, at: run.startedAt });
|
|
2498
|
+
if (delivered) {
|
|
2499
|
+
const current = index.session(session.id);
|
|
2500
|
+
if (current) saveSession({ ...current, ...delivered });
|
|
2501
|
+
}
|
|
2409
2502
|
const splitter = createLineSplitter();
|
|
2410
2503
|
const claude = provider === "claude" ? createClaudeNormalizer() : null;
|
|
2411
2504
|
const codex = provider === "codex" ? createCodexStreamNormalizer(runId.slice(0, 8)) : null;
|
|
@@ -2444,6 +2537,7 @@ async function createCodingSessionsEngine(options = {}) {
|
|
|
2444
2537
|
}
|
|
2445
2538
|
}
|
|
2446
2539
|
void pruneDriverScratch();
|
|
2540
|
+
if (provider === "codex" && final.status === "completed") void checkCompaction(session.id);
|
|
2447
2541
|
};
|
|
2448
2542
|
let settled = false;
|
|
2449
2543
|
child.on("message", (raw) => {
|
|
@@ -2558,7 +2652,7 @@ async function createCodingSessionsEngine(options = {}) {
|
|
|
2558
2652
|
provider,
|
|
2559
2653
|
runId,
|
|
2560
2654
|
cwd: session.cwd,
|
|
2561
|
-
prompt,
|
|
2655
|
+
prompt: cliPrompt,
|
|
2562
2656
|
model,
|
|
2563
2657
|
effort: session.effort ?? null,
|
|
2564
2658
|
resumeSessionId: session.providerSessionId,
|
|
@@ -2569,6 +2663,29 @@ async function createCodingSessionsEngine(options = {}) {
|
|
|
2569
2663
|
});
|
|
2570
2664
|
return run;
|
|
2571
2665
|
}
|
|
2666
|
+
async function checkCompaction(sessionId) {
|
|
2667
|
+
const session = index.session(sessionId);
|
|
2668
|
+
if (!session?.agent || session.agent.blockDue || !session.providerSessionId) return;
|
|
2669
|
+
const file = await findSessionFile("codex", session.providerSessionId, homes);
|
|
2670
|
+
if (!file || !await codexCompactionDroppedAgent(file, session.agent.deliveredAt ?? null)) return;
|
|
2671
|
+
const current = index.session(sessionId);
|
|
2672
|
+
if (current?.agent) {
|
|
2673
|
+
saveSession({ ...current, agent: { ...current.agent, blockDue: true } });
|
|
2674
|
+
}
|
|
2675
|
+
}
|
|
2676
|
+
async function attachAgent(sessionId, selection, options2) {
|
|
2677
|
+
const bundle = await agents.loadBundle(selection);
|
|
2678
|
+
await agents.saveSessionBundle(sessionId, bundle);
|
|
2679
|
+
return {
|
|
2680
|
+
...sessionAgentRecord(bundle, {
|
|
2681
|
+
toolsServed: await agents.mcpUrlFor(sessionId) !== null,
|
|
2682
|
+
variables: selection.variables ?? {}
|
|
2683
|
+
}),
|
|
2684
|
+
blockDue: options2.blockDue,
|
|
2685
|
+
deliveredAt: null,
|
|
2686
|
+
replaces: options2.replaces ?? null
|
|
2687
|
+
};
|
|
2688
|
+
}
|
|
2572
2689
|
function killGroup(liveRun) {
|
|
2573
2690
|
const target = liveRun.pgid;
|
|
2574
2691
|
if (target === null) return;
|
|
@@ -2825,7 +2942,6 @@ async function createCodingSessionsEngine(options = {}) {
|
|
|
2825
2942
|
const prompt = input.prompt.trim();
|
|
2826
2943
|
if (!prompt) throw new Error("Type what you want done before starting.");
|
|
2827
2944
|
const cwd = await assertFolder(input.cwd);
|
|
2828
|
-
const bundle = input.agent ? await agents.loadBundle(input.agent) : null;
|
|
2829
2945
|
const draft = newSession({
|
|
2830
2946
|
provider: input.provider,
|
|
2831
2947
|
cwd,
|
|
@@ -2835,28 +2951,43 @@ async function createCodingSessionsEngine(options = {}) {
|
|
|
2835
2951
|
origin: "started",
|
|
2836
2952
|
providerSessionId: null
|
|
2837
2953
|
});
|
|
2838
|
-
if (
|
|
2839
|
-
await agents.saveSessionBundle(draft.id, bundle);
|
|
2840
|
-
draft.agent = sessionAgentRecord(bundle, { toolsServed: await agents.mcpUrlFor(draft.id) !== null });
|
|
2841
|
-
}
|
|
2954
|
+
if (input.agent) draft.agent = await attachAgent(draft.id, input.agent, { blockDue: false });
|
|
2842
2955
|
const session = saveSession(draft);
|
|
2843
2956
|
const run = await startRun(session, prompt);
|
|
2844
2957
|
return { session: index.session(session.id) ?? session, run, queued: false };
|
|
2845
2958
|
},
|
|
2846
2959
|
async takeover(input) {
|
|
2847
2960
|
const existing = index.session(input.providerSessionId);
|
|
2848
|
-
if (existing)
|
|
2961
|
+
if (existing) {
|
|
2962
|
+
if (!input.agent) return existing;
|
|
2963
|
+
return engine.setAgent(existing.id, input.agent);
|
|
2964
|
+
}
|
|
2849
2965
|
const cwd = await assertFolder(input.cwd);
|
|
2850
|
-
|
|
2851
|
-
|
|
2852
|
-
|
|
2853
|
-
|
|
2854
|
-
|
|
2855
|
-
|
|
2856
|
-
|
|
2857
|
-
|
|
2858
|
-
|
|
2859
|
-
);
|
|
2966
|
+
const draft = newSession({
|
|
2967
|
+
provider: input.provider,
|
|
2968
|
+
cwd,
|
|
2969
|
+
title: input.title?.trim() || "Taken-over chat",
|
|
2970
|
+
model: null,
|
|
2971
|
+
origin: "takeover",
|
|
2972
|
+
providerSessionId: input.providerSessionId
|
|
2973
|
+
});
|
|
2974
|
+
if (input.agent) draft.agent = await attachAgent(draft.id, input.agent, { blockDue: input.provider === "codex" });
|
|
2975
|
+
return saveSession(draft);
|
|
2976
|
+
},
|
|
2977
|
+
async setAgent(sessionId, selection) {
|
|
2978
|
+
const session = index.session(String(sessionId ?? ""));
|
|
2979
|
+
if (!session) throw new Error("This session is not in the list anymore.");
|
|
2980
|
+
if (!selection) {
|
|
2981
|
+
const told = session.agent?.deliveredAt != null;
|
|
2982
|
+
return saveSession({ ...session, agent: null, agentRemovedDue: told });
|
|
2983
|
+
}
|
|
2984
|
+
const previous = session.agent && session.agent.deliveredAt != null ? session.agent : null;
|
|
2985
|
+
const started = session.providerSessionId !== null;
|
|
2986
|
+
const agent = await attachAgent(session.id, selection, {
|
|
2987
|
+
blockDue: started,
|
|
2988
|
+
replaces: previous ? `${previous.name}${previous.versionNumber !== null ? ` v${previous.versionNumber}` : ""}` : null
|
|
2989
|
+
});
|
|
2990
|
+
return saveSession({ ...session, agent, agentRemovedDue: false });
|
|
2860
2991
|
},
|
|
2861
2992
|
async send(sessionId, rawPrompt) {
|
|
2862
2993
|
const prompt = rawPrompt.trim();
|
|
@@ -2995,7 +3126,8 @@ var BRIDGE_METHODS = [
|
|
|
2995
3126
|
"setSessionOptions",
|
|
2996
3127
|
"agentAccess",
|
|
2997
3128
|
"agentCatalogRpc",
|
|
2998
|
-
"agentDetails"
|
|
3129
|
+
"agentDetails",
|
|
3130
|
+
"setAgent"
|
|
2999
3131
|
];
|
|
3000
3132
|
var BridgeError = class extends Error {
|
|
3001
3133
|
constructor(message, code) {
|