@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/engine/index.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { c as CodingSessionsEngine, d as CodingSessionsEngineOptions, E as EFFORT_LEVELS, P as PreferenceStore,
|
|
1
|
+
export { e as CodingSessionsAgentsOptions, c as CodingSessionsEngine, d as CodingSessionsEngineOptions, D as DEFAULT_SERVER_URL, f as DEFAULT_SUPABASE_URL, E as EFFORT_LEVELS, P as PreferenceStore, g as ProviderHomes, R as RAW_TRANSCRIPT_MAX_BYTES, h as RawBackupPolicy, i as RawBackupSink, j as RunStatus, k as buildCleanEnv, l as claudeDefaults, m as codexDefaults, n as createAiMatrxRawBackupSink, o as createCodingSessionsEngine, p as createRawBackupScheduler, q as defaultProviderHomes, r as describeActivity, s as describeProviderStatus, t as discoverLocalSessions, u as endsWithOpenToolCall, v as findDrivingProcess, w as findSessionFile, x as isAllowedEnvName, y as listProcesses, z as readSessionFile, A as searchLocalChats, B as sessionActivity, F as snippetAround } from '../index-CDeDKQHe.cjs';
|
|
2
2
|
import '@ai-matrx/agents/portable/mcp';
|
|
3
3
|
import '@ai-matrx/agents/portable';
|
|
4
4
|
import '@ai-matrx/data';
|
package/dist/engine/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { c as CodingSessionsEngine, d as CodingSessionsEngineOptions, E as EFFORT_LEVELS, P as PreferenceStore,
|
|
1
|
+
export { e as CodingSessionsAgentsOptions, c as CodingSessionsEngine, d as CodingSessionsEngineOptions, D as DEFAULT_SERVER_URL, f as DEFAULT_SUPABASE_URL, E as EFFORT_LEVELS, P as PreferenceStore, g as ProviderHomes, R as RAW_TRANSCRIPT_MAX_BYTES, h as RawBackupPolicy, i as RawBackupSink, j as RunStatus, k as buildCleanEnv, l as claudeDefaults, m as codexDefaults, n as createAiMatrxRawBackupSink, o as createCodingSessionsEngine, p as createRawBackupScheduler, q as defaultProviderHomes, r as describeActivity, s as describeProviderStatus, t as discoverLocalSessions, u as endsWithOpenToolCall, v as findDrivingProcess, w as findSessionFile, x as isAllowedEnvName, y as listProcesses, z as readSessionFile, A as searchLocalChats, B as sessionActivity, F as snippetAround } from '../index-CDeDKQHe.js';
|
|
2
2
|
import '@ai-matrx/agents/portable/mcp';
|
|
3
3
|
import '@ai-matrx/agents/portable';
|
|
4
4
|
import '@ai-matrx/data';
|
package/dist/engine/index.js
CHANGED
|
@@ -101,8 +101,25 @@ function createAiMatrxRawBackupSink(options) {
|
|
|
101
101
|
// src/engine/agent-attach.ts
|
|
102
102
|
import fs2 from "fs/promises";
|
|
103
103
|
import path from "path";
|
|
104
|
+
|
|
105
|
+
// src/normalize/agent-block.ts
|
|
106
|
+
var AGENT_BLOCK_MARKER = "<ai_matrx_agent ";
|
|
107
|
+
function stripAgentBlock(text) {
|
|
108
|
+
const removed = text.match(/^<ai_matrx_agent_removed>[\s\S]*?<\/ai_matrx_agent_removed>\s*/);
|
|
109
|
+
if (removed) return text.slice(removed[0].length);
|
|
110
|
+
if (!text.startsWith(AGENT_BLOCK_MARKER)) return text;
|
|
111
|
+
const end = text.indexOf("</ai_matrx_agent>");
|
|
112
|
+
if (end < 0) return text;
|
|
113
|
+
let rest = text.slice(end + "</ai_matrx_agent>".length);
|
|
114
|
+
const skills = rest.match(/^\s*<skills_instructions>[\s\S]*?<\/skills_instructions>/);
|
|
115
|
+
if (skills) rest = rest.slice(skills[0].length);
|
|
116
|
+
return rest.replace(/^\s+/, "");
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// src/engine/agent-attach.ts
|
|
104
120
|
var AGENT_MCP_SERVER_NAME = "matrx-agent";
|
|
105
121
|
var AGENT_PLUGIN_NAME = "matrx-agent";
|
|
122
|
+
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.";
|
|
106
123
|
function escapeAttr(value) {
|
|
107
124
|
return value.replace(/&/g, "&").replace(/"/g, """).replace(/</g, "<");
|
|
108
125
|
}
|
|
@@ -151,6 +168,20 @@ function renderCodexSkillsList(bundle, skillsRoot) {
|
|
|
151
168
|
];
|
|
152
169
|
return lines.join("\n");
|
|
153
170
|
}
|
|
171
|
+
function renderFallbackBlock(bundle, skillsRoot, options = {}) {
|
|
172
|
+
const skills = renderCodexSkillsList(bundle, skillsRoot);
|
|
173
|
+
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.";
|
|
174
|
+
const body = renderAgentInstructions(bundle).trim().replace(/^(<ai_matrx_agent [^>]*>)/, `$1
|
|
175
|
+
|
|
176
|
+
${lead}`);
|
|
177
|
+
return skills ? `${body}
|
|
178
|
+
|
|
179
|
+
${skills}
|
|
180
|
+
|
|
181
|
+
` : `${body}
|
|
182
|
+
|
|
183
|
+
`;
|
|
184
|
+
}
|
|
154
185
|
function tomlString(value) {
|
|
155
186
|
const scalar = value.replace(/[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?<![\uD800-\uDBFF])[\uDC00-\uDFFF]/g, "\uFFFD");
|
|
156
187
|
return JSON.stringify(scalar).replace(/\u007f/g, "\\u007f");
|
|
@@ -211,10 +242,16 @@ async function writeAgentAttachment(dir, bundle, options) {
|
|
|
211
242
|
pluginDir,
|
|
212
243
|
mcpConfigFile,
|
|
213
244
|
mcpUrl,
|
|
214
|
-
// Same order as Claude's: the skills list first, the agent's words last
|
|
215
|
-
|
|
245
|
+
// Same order as Claude's: the skills list first, the agent's words last —
|
|
246
|
+
// then the one sentence that lets a later block replace them. Codex ranks
|
|
247
|
+
// developer instructions above a user message, so without this permission
|
|
248
|
+
// a mid-chat switch or update is ignored (measured live: the v2 block was
|
|
249
|
+
// delivered and Codex kept ending with v1's line).
|
|
250
|
+
codexInstructions: `${skillsList ? `${skillsList}
|
|
216
251
|
|
|
217
|
-
|
|
252
|
+
` : ""}${instructions}
|
|
253
|
+
${CODEX_REPLACEMENT_CLAUSE}
|
|
254
|
+
`
|
|
218
255
|
};
|
|
219
256
|
}
|
|
220
257
|
function agentArgsFor(provider, attachment, options) {
|
|
@@ -266,16 +303,37 @@ function sessionAgentRecord(bundle, options) {
|
|
|
266
303
|
name: bundle.name,
|
|
267
304
|
definitionHash: bundle.definition_hash,
|
|
268
305
|
loaded,
|
|
269
|
-
unavailable
|
|
306
|
+
unavailable,
|
|
307
|
+
skills: bundle.skills.map((skill) => skill.label),
|
|
308
|
+
tools: options.toolsServed ? bundle.tools.map((tool) => tool.canonical_name) : [],
|
|
309
|
+
...options.variables ? { variables: options.variables } : {}
|
|
270
310
|
};
|
|
271
311
|
}
|
|
312
|
+
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";
|
|
313
|
+
async function codexCompactionDroppedAgent(rolloutFile, sinceIso) {
|
|
314
|
+
const text = await fs2.readFile(rolloutFile, "utf8").catch(() => "");
|
|
315
|
+
if (!text.includes('"type":"compacted"')) return false;
|
|
316
|
+
let latest = null;
|
|
317
|
+
for (const line of text.split("\n")) {
|
|
318
|
+
if (!line.includes('"type":"compacted"')) continue;
|
|
319
|
+
try {
|
|
320
|
+
const entry = JSON.parse(line);
|
|
321
|
+
if (entry.type === "compacted") latest = entry;
|
|
322
|
+
} catch {
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
if (!latest) return false;
|
|
326
|
+
if (sinceIso && latest.timestamp && latest.timestamp <= sinceIso) return false;
|
|
327
|
+
return !JSON.stringify(latest.payload?.replacement_history ?? "").includes(AGENT_BLOCK_MARKER.trim());
|
|
328
|
+
}
|
|
272
329
|
|
|
273
330
|
// src/engine/agents.ts
|
|
274
|
-
import { randomBytes, randomUUID } from "crypto";
|
|
331
|
+
import { createHash as createHash2, randomBytes, randomUUID } from "crypto";
|
|
275
332
|
import fs3 from "fs/promises";
|
|
276
333
|
import path2 from "path";
|
|
277
334
|
var DEFAULT_SERVER_URL = "https://server.app.matrxserver.com";
|
|
278
335
|
var DEFAULT_SUPABASE_URL = "https://db.matrxserver.com";
|
|
336
|
+
var DEFAULT_SUPABASE_KEY = "sb_publishable_scm0jzEJiFUB5ItiqOx5Fg_8BOjB6oA";
|
|
279
337
|
var AGENT_CATALOG_RPCS = /* @__PURE__ */ new Set([
|
|
280
338
|
"agx_get_list_full",
|
|
281
339
|
"agx_search",
|
|
@@ -293,6 +351,10 @@ var agentsClient = async () => {
|
|
|
293
351
|
]);
|
|
294
352
|
return { ...matrx, ...portable, ...mcp };
|
|
295
353
|
};
|
|
354
|
+
function sortedValues(values) {
|
|
355
|
+
return Object.keys(values).sort().map((key) => [key, values[key]]);
|
|
356
|
+
}
|
|
357
|
+
var BUNDLE_CACHE_MS = 24 * 60 * 60 * 1e3;
|
|
296
358
|
var SIGNED_OUT_AGENT_MESSAGE = "Sign in to AI Matrx to use your agents.";
|
|
297
359
|
function userIdOf(credential) {
|
|
298
360
|
if (!credential || credential.kind !== "user") return null;
|
|
@@ -309,21 +371,26 @@ function createAgentConnection(options, dataDir) {
|
|
|
309
371
|
const credentials = options?.credentials ?? null;
|
|
310
372
|
const serverUrl = (options?.serverUrl ?? DEFAULT_SERVER_URL).replace(/\/+$/, "");
|
|
311
373
|
const supabaseUrl = (options?.supabaseUrl ?? DEFAULT_SUPABASE_URL).replace(/\/+$/, "");
|
|
312
|
-
const supabaseKey = options?.supabaseKey ?? null;
|
|
374
|
+
const supabaseKey = options?.supabaseKey ?? (options?.supabaseUrl ? null : DEFAULT_SUPABASE_KEY);
|
|
313
375
|
const root = path2.join(dataDir, "agents");
|
|
314
376
|
let mcpBaseUrl = null;
|
|
315
377
|
const handlers = /* @__PURE__ */ new Map();
|
|
316
378
|
const secretToSession = /* @__PURE__ */ new Map();
|
|
317
|
-
const organizationId = () => {
|
|
318
|
-
const raw = typeof options?.organizationId === "function" ? options.organizationId() : options?.organizationId;
|
|
379
|
+
const organizationId = async () => {
|
|
380
|
+
const raw = typeof options?.organizationId === "function" ? await options.organizationId() : options?.organizationId;
|
|
319
381
|
return raw && raw.trim() ? raw.trim() : null;
|
|
320
382
|
};
|
|
321
|
-
const transport = async () =>
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
383
|
+
const transport = async () => {
|
|
384
|
+
const org = await organizationId();
|
|
385
|
+
return (await agentsClient()).createMatrxTransport({
|
|
386
|
+
baseUrl: serverUrl,
|
|
387
|
+
...credentials ? { credentials } : {},
|
|
388
|
+
...org ? { organizationId: org } : {},
|
|
389
|
+
source: "codingSessionsAgents"
|
|
390
|
+
});
|
|
391
|
+
};
|
|
392
|
+
const cacheDir = path2.join(dataDir, "agents", ".bundles");
|
|
393
|
+
const cacheKey = (definitionHash, selection, surface) => createHash2("sha256").update(JSON.stringify([definitionHash, sortedValues(selection.variables ?? {}), surface])).digest("hex");
|
|
327
394
|
const credential = async () => credentials ? credentials.get() : null;
|
|
328
395
|
const requireSignedIn = async () => {
|
|
329
396
|
if (!await credential()) throw new Error(SIGNED_OUT_AGENT_MESSAGE);
|
|
@@ -359,7 +426,7 @@ function createAgentConnection(options, dataDir) {
|
|
|
359
426
|
configured: credentials !== null && supabaseKey !== null,
|
|
360
427
|
signedIn: userId !== null,
|
|
361
428
|
userId,
|
|
362
|
-
organizationId: organizationId()
|
|
429
|
+
organizationId: await organizationId().catch(() => null)
|
|
363
430
|
};
|
|
364
431
|
},
|
|
365
432
|
async catalogRpc(request) {
|
|
@@ -406,27 +473,39 @@ function createAgentConnection(options, dataDir) {
|
|
|
406
473
|
},
|
|
407
474
|
async details(agentId) {
|
|
408
475
|
await requireSignedIn();
|
|
409
|
-
const
|
|
410
|
-
const [bundle, versions] = await Promise.all([
|
|
411
|
-
fetchPortableAgent(await transport(), { agentId }),
|
|
412
|
-
fetchPortableAgentVersions(await transport(), agentId).catch(() => [])
|
|
413
|
-
]);
|
|
476
|
+
const summary = await (await agentsClient()).fetchPortableAgentSummary(await transport(), agentId);
|
|
414
477
|
return {
|
|
415
|
-
agentId:
|
|
416
|
-
name:
|
|
417
|
-
variables:
|
|
418
|
-
versions: versions.map((v) => ({ id: v.id, versionNumber: v.version_number, changedAt: v.changed_at }))
|
|
419
|
-
latestVersionNumber:
|
|
478
|
+
agentId: summary.agent_id,
|
|
479
|
+
name: summary.name,
|
|
480
|
+
variables: summary.variables,
|
|
481
|
+
versions: summary.versions.map((v) => ({ id: v.id, versionNumber: v.version_number, changedAt: v.changed_at })),
|
|
482
|
+
latestVersionNumber: summary.version_number,
|
|
483
|
+
latestVersionId: summary.version_id
|
|
420
484
|
};
|
|
421
485
|
},
|
|
422
486
|
async loadBundle(selection) {
|
|
423
487
|
await requireSignedIn();
|
|
424
|
-
const
|
|
425
|
-
|
|
488
|
+
const client = await agentsClient();
|
|
489
|
+
const summary = await client.fetchPortableAgentSummary(await transport(), selection.agentId);
|
|
490
|
+
const versionId = selection.versionId ?? summary.version_id;
|
|
491
|
+
const definitionHash = versionId ? summary.versions.find((v) => v.id === versionId)?.definition_hash ?? null : summary.definition_hash;
|
|
492
|
+
const surface = "matrx-user/code-editor";
|
|
493
|
+
const file = definitionHash ? path2.join(cacheDir, `${cacheKey(definitionHash, selection, surface)}.json`) : null;
|
|
494
|
+
if (file) {
|
|
495
|
+
const cached = await fs3.readFile(file, "utf8").then((text) => JSON.parse(text)).catch(() => null);
|
|
496
|
+
const fresh = await fs3.stat(file).then((st) => Date.now() - st.mtimeMs < BUNDLE_CACHE_MS).catch(() => false);
|
|
497
|
+
if (cached && fresh && cached.definition_hash === definitionHash) return cached;
|
|
498
|
+
}
|
|
499
|
+
const bundle = await client.fetchPortableAgent(
|
|
426
500
|
await transport(),
|
|
427
|
-
|
|
428
|
-
{ variables: selection.variables ?? {} }
|
|
501
|
+
versionId ? { versionId } : { agentId: selection.agentId },
|
|
502
|
+
{ variables: selection.variables ?? {}, surface }
|
|
429
503
|
);
|
|
504
|
+
if (file && bundle.definition_hash === definitionHash) {
|
|
505
|
+
await fs3.mkdir(cacheDir, { recursive: true, mode: 448 });
|
|
506
|
+
await fs3.writeFile(file, JSON.stringify(bundle), { mode: 384 });
|
|
507
|
+
}
|
|
508
|
+
return bundle;
|
|
430
509
|
},
|
|
431
510
|
async saveSessionBundle(sessionId, bundle) {
|
|
432
511
|
await fs3.mkdir(sessionDir(sessionId), { recursive: true, mode: 448 });
|
|
@@ -562,7 +641,7 @@ function createClaudeNormalizer() {
|
|
|
562
641
|
if (typeof content === "string") {
|
|
563
642
|
if (isSyntheticClaudeUserText(content) || content.trim().length === 0) return [];
|
|
564
643
|
userCounter += 1;
|
|
565
|
-
return [{ kind: "user", id: str(entry.uuid) ?? `user-${userCounter}`, text: content, at }];
|
|
644
|
+
return [{ kind: "user", id: str(entry.uuid) ?? `user-${userCounter}`, text: stripAgentBlock(content), at }];
|
|
566
645
|
}
|
|
567
646
|
if (!Array.isArray(content)) return [];
|
|
568
647
|
const items = [];
|
|
@@ -586,7 +665,7 @@ function createClaudeNormalizer() {
|
|
|
586
665
|
items.unshift({
|
|
587
666
|
kind: "user",
|
|
588
667
|
id: str(entry.uuid) ?? `user-${userCounter}`,
|
|
589
|
-
text: typed.join("\n\n"),
|
|
668
|
+
text: stripAgentBlock(typed.join("\n\n")),
|
|
590
669
|
at
|
|
591
670
|
});
|
|
592
671
|
}
|
|
@@ -841,7 +920,7 @@ function rolloutItem(item, fallbackId, at) {
|
|
|
841
920
|
const id = str2(item.id) ?? fallbackId;
|
|
842
921
|
switch (item.type) {
|
|
843
922
|
case "UserMessage": {
|
|
844
|
-
const text = stripCodexInjectedContext(itemText(item.content));
|
|
923
|
+
const text = stripCodexInjectedContext(stripAgentBlock(itemText(item.content)));
|
|
845
924
|
return text.trim() ? [{ kind: "user", id, text, at }] : [];
|
|
846
925
|
}
|
|
847
926
|
case "AgentMessage": {
|
|
@@ -924,7 +1003,7 @@ function createCodexRolloutNormalizer() {
|
|
|
924
1003
|
return rolloutItem(payload.item, fallbackId, at);
|
|
925
1004
|
}
|
|
926
1005
|
if (payload.type === "user_message" && !appItems) {
|
|
927
|
-
const text = stripCodexInjectedContext(str2(payload.message) ?? "");
|
|
1006
|
+
const text = stripCodexInjectedContext(stripAgentBlock(str2(payload.message) ?? ""));
|
|
928
1007
|
return text.trim() ? [{ kind: "user", id: fallbackId, text, at }] : [];
|
|
929
1008
|
}
|
|
930
1009
|
return [];
|
|
@@ -2402,6 +2481,12 @@ async function createCodingSessionsEngine(options = {}) {
|
|
|
2402
2481
|
if (file) fileOffset = (await fs8.stat(file).catch(() => null))?.size ?? null;
|
|
2403
2482
|
}
|
|
2404
2483
|
let agentArgs = [];
|
|
2484
|
+
let cliPrompt = prompt;
|
|
2485
|
+
let delivered = null;
|
|
2486
|
+
if (!session.agent && session.agentRemovedDue) {
|
|
2487
|
+
cliPrompt = `${AGENT_REMOVED_BLOCK}${prompt}`;
|
|
2488
|
+
delivered = { agentRemovedDue: false };
|
|
2489
|
+
}
|
|
2405
2490
|
if (session.agent) {
|
|
2406
2491
|
const bundle = await agents.readSessionBundle(session.id);
|
|
2407
2492
|
if (!bundle) {
|
|
@@ -2419,6 +2504,10 @@ async function createCodingSessionsEngine(options = {}) {
|
|
|
2419
2504
|
mcpUrl: await agents.mcpUrlFor(session.id)
|
|
2420
2505
|
});
|
|
2421
2506
|
agentArgs = agentArgsFor(provider, attachment, { resuming: session.providerSessionId !== null });
|
|
2507
|
+
if (session.agent.blockDue) {
|
|
2508
|
+
cliPrompt = `${renderFallbackBlock(bundle, path9.join(attachment.dir, "skills"), { replaces: session.agent.replaces })}${prompt}`;
|
|
2509
|
+
}
|
|
2510
|
+
delivered = { agent: { ...session.agent, blockDue: false, deliveredAt: run.startedAt } };
|
|
2422
2511
|
}
|
|
2423
2512
|
const child = forkWorker();
|
|
2424
2513
|
const liveRun = {
|
|
@@ -2434,6 +2523,10 @@ async function createCodingSessionsEngine(options = {}) {
|
|
|
2434
2523
|
};
|
|
2435
2524
|
live.set(runId, liveRun);
|
|
2436
2525
|
emitItem(liveRun, { kind: "user", id: `run-${runId}`, text: prompt, at: run.startedAt });
|
|
2526
|
+
if (delivered) {
|
|
2527
|
+
const current = index.session(session.id);
|
|
2528
|
+
if (current) saveSession({ ...current, ...delivered });
|
|
2529
|
+
}
|
|
2437
2530
|
const splitter = createLineSplitter();
|
|
2438
2531
|
const claude = provider === "claude" ? createClaudeNormalizer() : null;
|
|
2439
2532
|
const codex = provider === "codex" ? createCodexStreamNormalizer(runId.slice(0, 8)) : null;
|
|
@@ -2472,6 +2565,7 @@ async function createCodingSessionsEngine(options = {}) {
|
|
|
2472
2565
|
}
|
|
2473
2566
|
}
|
|
2474
2567
|
void pruneDriverScratch();
|
|
2568
|
+
if (provider === "codex" && final.status === "completed") void checkCompaction(session.id);
|
|
2475
2569
|
};
|
|
2476
2570
|
let settled = false;
|
|
2477
2571
|
child.on("message", (raw) => {
|
|
@@ -2586,7 +2680,7 @@ async function createCodingSessionsEngine(options = {}) {
|
|
|
2586
2680
|
provider,
|
|
2587
2681
|
runId,
|
|
2588
2682
|
cwd: session.cwd,
|
|
2589
|
-
prompt,
|
|
2683
|
+
prompt: cliPrompt,
|
|
2590
2684
|
model,
|
|
2591
2685
|
effort: session.effort ?? null,
|
|
2592
2686
|
resumeSessionId: session.providerSessionId,
|
|
@@ -2597,6 +2691,29 @@ async function createCodingSessionsEngine(options = {}) {
|
|
|
2597
2691
|
});
|
|
2598
2692
|
return run;
|
|
2599
2693
|
}
|
|
2694
|
+
async function checkCompaction(sessionId) {
|
|
2695
|
+
const session = index.session(sessionId);
|
|
2696
|
+
if (!session?.agent || session.agent.blockDue || !session.providerSessionId) return;
|
|
2697
|
+
const file = await findSessionFile("codex", session.providerSessionId, homes);
|
|
2698
|
+
if (!file || !await codexCompactionDroppedAgent(file, session.agent.deliveredAt ?? null)) return;
|
|
2699
|
+
const current = index.session(sessionId);
|
|
2700
|
+
if (current?.agent) {
|
|
2701
|
+
saveSession({ ...current, agent: { ...current.agent, blockDue: true } });
|
|
2702
|
+
}
|
|
2703
|
+
}
|
|
2704
|
+
async function attachAgent(sessionId, selection, options2) {
|
|
2705
|
+
const bundle = await agents.loadBundle(selection);
|
|
2706
|
+
await agents.saveSessionBundle(sessionId, bundle);
|
|
2707
|
+
return {
|
|
2708
|
+
...sessionAgentRecord(bundle, {
|
|
2709
|
+
toolsServed: await agents.mcpUrlFor(sessionId) !== null,
|
|
2710
|
+
variables: selection.variables ?? {}
|
|
2711
|
+
}),
|
|
2712
|
+
blockDue: options2.blockDue,
|
|
2713
|
+
deliveredAt: null,
|
|
2714
|
+
replaces: options2.replaces ?? null
|
|
2715
|
+
};
|
|
2716
|
+
}
|
|
2600
2717
|
function killGroup(liveRun) {
|
|
2601
2718
|
const target = liveRun.pgid;
|
|
2602
2719
|
if (target === null) return;
|
|
@@ -2853,7 +2970,6 @@ async function createCodingSessionsEngine(options = {}) {
|
|
|
2853
2970
|
const prompt = input.prompt.trim();
|
|
2854
2971
|
if (!prompt) throw new Error("Type what you want done before starting.");
|
|
2855
2972
|
const cwd = await assertFolder(input.cwd);
|
|
2856
|
-
const bundle = input.agent ? await agents.loadBundle(input.agent) : null;
|
|
2857
2973
|
const draft = newSession({
|
|
2858
2974
|
provider: input.provider,
|
|
2859
2975
|
cwd,
|
|
@@ -2863,28 +2979,43 @@ async function createCodingSessionsEngine(options = {}) {
|
|
|
2863
2979
|
origin: "started",
|
|
2864
2980
|
providerSessionId: null
|
|
2865
2981
|
});
|
|
2866
|
-
if (
|
|
2867
|
-
await agents.saveSessionBundle(draft.id, bundle);
|
|
2868
|
-
draft.agent = sessionAgentRecord(bundle, { toolsServed: await agents.mcpUrlFor(draft.id) !== null });
|
|
2869
|
-
}
|
|
2982
|
+
if (input.agent) draft.agent = await attachAgent(draft.id, input.agent, { blockDue: false });
|
|
2870
2983
|
const session = saveSession(draft);
|
|
2871
2984
|
const run = await startRun(session, prompt);
|
|
2872
2985
|
return { session: index.session(session.id) ?? session, run, queued: false };
|
|
2873
2986
|
},
|
|
2874
2987
|
async takeover(input) {
|
|
2875
2988
|
const existing = index.session(input.providerSessionId);
|
|
2876
|
-
if (existing)
|
|
2989
|
+
if (existing) {
|
|
2990
|
+
if (!input.agent) return existing;
|
|
2991
|
+
return engine.setAgent(existing.id, input.agent);
|
|
2992
|
+
}
|
|
2877
2993
|
const cwd = await assertFolder(input.cwd);
|
|
2878
|
-
|
|
2879
|
-
|
|
2880
|
-
|
|
2881
|
-
|
|
2882
|
-
|
|
2883
|
-
|
|
2884
|
-
|
|
2885
|
-
|
|
2886
|
-
|
|
2887
|
-
);
|
|
2994
|
+
const draft = newSession({
|
|
2995
|
+
provider: input.provider,
|
|
2996
|
+
cwd,
|
|
2997
|
+
title: input.title?.trim() || "Taken-over chat",
|
|
2998
|
+
model: null,
|
|
2999
|
+
origin: "takeover",
|
|
3000
|
+
providerSessionId: input.providerSessionId
|
|
3001
|
+
});
|
|
3002
|
+
if (input.agent) draft.agent = await attachAgent(draft.id, input.agent, { blockDue: input.provider === "codex" });
|
|
3003
|
+
return saveSession(draft);
|
|
3004
|
+
},
|
|
3005
|
+
async setAgent(sessionId, selection) {
|
|
3006
|
+
const session = index.session(String(sessionId ?? ""));
|
|
3007
|
+
if (!session) throw new Error("This session is not in the list anymore.");
|
|
3008
|
+
if (!selection) {
|
|
3009
|
+
const told = session.agent?.deliveredAt != null;
|
|
3010
|
+
return saveSession({ ...session, agent: null, agentRemovedDue: told });
|
|
3011
|
+
}
|
|
3012
|
+
const previous = session.agent && session.agent.deliveredAt != null ? session.agent : null;
|
|
3013
|
+
const started = session.providerSessionId !== null;
|
|
3014
|
+
const agent = await attachAgent(session.id, selection, {
|
|
3015
|
+
blockDue: started,
|
|
3016
|
+
replaces: previous ? `${previous.name}${previous.versionNumber !== null ? ` v${previous.versionNumber}` : ""}` : null
|
|
3017
|
+
});
|
|
3018
|
+
return saveSession({ ...session, agent, agentRemovedDue: false });
|
|
2888
3019
|
},
|
|
2889
3020
|
async send(sessionId, rawPrompt) {
|
|
2890
3021
|
const prompt = rawPrompt.trim();
|
|
@@ -2999,6 +3130,8 @@ function openFolderIn(folder, target) {
|
|
|
2999
3130
|
});
|
|
3000
3131
|
}
|
|
3001
3132
|
export {
|
|
3133
|
+
DEFAULT_SERVER_URL,
|
|
3134
|
+
DEFAULT_SUPABASE_URL,
|
|
3002
3135
|
EFFORT_LEVELS,
|
|
3003
3136
|
PreferenceStore,
|
|
3004
3137
|
RAW_TRANSCRIPT_MAX_BYTES,
|