antechamber 1.0.8 → 1.0.9
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 +7 -0
- package/dist/sessions.d.ts +1 -0
- package/dist/sessions.js +10 -8
- package/dist/subagents.d.ts +0 -2
- package/dist/subagents.js +119 -40
- package/extensions/omo-compat/package.json +1 -1
- package/extensions/omo-dag/package.json +1 -1
- package/extensions/omo-work/package.json +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,13 @@ and this project uses [Semantic Versioning](https://semver.org/).
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [1.0.9] - 2026-10-21
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
|
|
14
|
+
- Reduce repeated native-title scans and task-record lookups while restoring and listing sessions,
|
|
15
|
+
preserving first-list costs, child-session identities and later native updates.
|
|
16
|
+
|
|
10
17
|
## [1.0.8] - 2026-10-20
|
|
11
18
|
|
|
12
19
|
### Fixed
|
package/dist/sessions.d.ts
CHANGED
|
@@ -107,6 +107,7 @@ export declare class SessionManager {
|
|
|
107
107
|
private rollbackCreate;
|
|
108
108
|
private applyNativeTitle;
|
|
109
109
|
private refreshNativeTitles;
|
|
110
|
+
private refreshNativeTitle;
|
|
110
111
|
private wirePi;
|
|
111
112
|
/** pi writes `<ts>_<sessionId>.jsonl` at startup — poll briefly for it. */
|
|
112
113
|
private resolvePiFile;
|
package/dist/sessions.js
CHANGED
|
@@ -209,13 +209,15 @@ export class SessionManager {
|
|
|
209
209
|
this.emit(s.info.directory, { type: "session.updated", properties: { info: s.info } });
|
|
210
210
|
}
|
|
211
211
|
refreshNativeTitles() {
|
|
212
|
-
for (const s of this.sessions.values())
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
212
|
+
for (const s of this.sessions.values())
|
|
213
|
+
this.refreshNativeTitle(s);
|
|
214
|
+
}
|
|
215
|
+
refreshNativeTitle(s) {
|
|
216
|
+
if (s.pi !== undefined || s.restored === undefined || !existsSync(s.restored.piPath))
|
|
217
|
+
return;
|
|
218
|
+
const metadata = readSessionTitle(s.restored.piPath, s.restored.piSessionId);
|
|
219
|
+
if (metadata.titleSource === "native")
|
|
220
|
+
this.applyNativeTitle(s, metadata.title);
|
|
219
221
|
}
|
|
220
222
|
wirePi(s, pi) {
|
|
221
223
|
s.unwirePi?.();
|
|
@@ -345,7 +347,7 @@ export class SessionManager {
|
|
|
345
347
|
return undefined;
|
|
346
348
|
const live = this.sessions.get(sessionId);
|
|
347
349
|
if (live !== undefined) {
|
|
348
|
-
this.
|
|
350
|
+
this.refreshNativeTitle(live);
|
|
349
351
|
this.sessionInfo(live);
|
|
350
352
|
return live;
|
|
351
353
|
}
|
package/dist/subagents.d.ts
CHANGED
|
@@ -51,8 +51,6 @@ export declare class SubagentBridge {
|
|
|
51
51
|
private readonly children;
|
|
52
52
|
private readonly calls;
|
|
53
53
|
private readonly removed;
|
|
54
|
-
/** Parent pi session of each task record already read; a record's parent never changes. */
|
|
55
|
-
private readonly taskParents;
|
|
56
54
|
constructor(store: SessionStore, sessions: Map<string, ManagedSession>, emit: (directory: string, event: OCEvent) => void, parse: ParseHistory);
|
|
57
55
|
private archive;
|
|
58
56
|
private sessionId;
|
package/dist/subagents.js
CHANGED
|
@@ -211,9 +211,81 @@ function childRecord(id, path) {
|
|
|
211
211
|
const data = jsonObject(path);
|
|
212
212
|
return data?.task_id === id && typeof data.parent_session_id === "string" ? data : undefined;
|
|
213
213
|
}
|
|
214
|
+
// History parsing calls the exported helpers synchronously, including from nested child discovery.
|
|
215
|
+
let taskLookupPass;
|
|
216
|
+
function withTaskLookups(store, action) {
|
|
217
|
+
if (taskLookupPass?.store === store)
|
|
218
|
+
return action();
|
|
219
|
+
const previous = taskLookupPass;
|
|
220
|
+
const pass = {
|
|
221
|
+
store,
|
|
222
|
+
childIds: store.childIds(),
|
|
223
|
+
identities: new Map(),
|
|
224
|
+
childByPi: new Map(),
|
|
225
|
+
piByChild: new Map(),
|
|
226
|
+
};
|
|
227
|
+
try {
|
|
228
|
+
taskLookupPass = pass;
|
|
229
|
+
for (const id of pass.childIds) {
|
|
230
|
+
const entry = store.get(id);
|
|
231
|
+
if (entry?.task)
|
|
232
|
+
indexChildIdentity(store, id, entry.task, entry.deleted ? undefined : entry.piSessionId);
|
|
233
|
+
}
|
|
234
|
+
return action();
|
|
235
|
+
}
|
|
236
|
+
finally {
|
|
237
|
+
taskLookupPass = previous;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
function indexChildIdentity(store, id, task, piSessionId) {
|
|
241
|
+
const pass = taskLookupPass;
|
|
242
|
+
if (pass?.store !== store)
|
|
243
|
+
return;
|
|
244
|
+
let parents = pass.identities.get(task.id);
|
|
245
|
+
if (parents === undefined)
|
|
246
|
+
pass.identities.set(task.id, (parents = new Map()));
|
|
247
|
+
if (!parents.has(task.parentPiId))
|
|
248
|
+
parents.set(task.parentPiId, id);
|
|
249
|
+
if (piSessionId !== undefined) {
|
|
250
|
+
const previous = pass.piByChild.get(id);
|
|
251
|
+
if (previous !== undefined && previous !== piSessionId && pass.childByPi.get(previous) === id)
|
|
252
|
+
pass.childByPi.delete(previous);
|
|
253
|
+
pass.piByChild.set(id, piSessionId);
|
|
254
|
+
pass.childByPi.set(piSessionId, id);
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
function indexedTaskRecords() {
|
|
258
|
+
const pass = taskLookupPass;
|
|
259
|
+
if (pass === undefined)
|
|
260
|
+
return undefined;
|
|
261
|
+
if (pass.records !== undefined)
|
|
262
|
+
return pass.records;
|
|
263
|
+
const all = [];
|
|
264
|
+
const byId = new Map();
|
|
265
|
+
const byParent = new Map();
|
|
266
|
+
for (const { id, path } of taskFiles()) {
|
|
267
|
+
const data = childRecord(id, path);
|
|
268
|
+
if (data === undefined)
|
|
269
|
+
continue;
|
|
270
|
+
const row = { id, path, data };
|
|
271
|
+
all.push(row);
|
|
272
|
+
const sameId = byId.get(id) ?? [];
|
|
273
|
+
sameId.push(row);
|
|
274
|
+
byId.set(id, sameId);
|
|
275
|
+
const parent = String(data.parent_session_id);
|
|
276
|
+
const sameParent = byParent.get(parent) ?? [];
|
|
277
|
+
sameParent.push(row);
|
|
278
|
+
byParent.set(parent, sameParent);
|
|
279
|
+
}
|
|
280
|
+
return (pass.records = { all, byId, byParent });
|
|
281
|
+
}
|
|
214
282
|
/** Keep bookmarks for known tasks; a bare native id is only safe while it has one parent. */
|
|
215
|
-
export function taskSessionId(id, parentPiId, store = new SessionStore()) {
|
|
216
|
-
|
|
283
|
+
export function taskSessionId(id, parentPiId, store = taskLookupPass?.store ?? new SessionStore()) {
|
|
284
|
+
const pass = taskLookupPass?.store === store ? taskLookupPass : undefined;
|
|
285
|
+
const known = pass?.identities.get(id)?.get(parentPiId);
|
|
286
|
+
if (known !== undefined)
|
|
287
|
+
return known;
|
|
288
|
+
for (const sessionID of pass === undefined ? store.childIds() : []) {
|
|
217
289
|
const task = store.get(sessionID)?.task;
|
|
218
290
|
if (task?.id === id && task.parentPiId === parentPiId)
|
|
219
291
|
return sessionID;
|
|
@@ -228,6 +300,10 @@ export function taskSessionId(id, parentPiId, store = new SessionStore()) {
|
|
|
228
300
|
const qualifiedID = ocIdFor(`${parentPiId}:${id}`);
|
|
229
301
|
if (store.get(qualifiedID))
|
|
230
302
|
return qualifiedID;
|
|
303
|
+
const indexed = indexedTaskRecords();
|
|
304
|
+
if (indexed !== undefined) {
|
|
305
|
+
return indexed.byId.get(id)?.some(({ data }) => data.parent_session_id !== parentPiId) ? qualifiedID : legacyID;
|
|
306
|
+
}
|
|
231
307
|
for (const root of taskStores()) {
|
|
232
308
|
const data = childRecord(id, join(root, "tasks", `${id}.json`));
|
|
233
309
|
if (data && data.parent_session_id !== parentPiId)
|
|
@@ -236,10 +312,11 @@ export function taskSessionId(id, parentPiId, store = new SessionStore()) {
|
|
|
236
312
|
return legacyID;
|
|
237
313
|
}
|
|
238
314
|
/** Reverse lookup never resolves an unbound, ambiguous bare id by store enumeration order. */
|
|
239
|
-
export function findTaskBySession(sessionId, store = new SessionStore()) {
|
|
315
|
+
export function findTaskBySession(sessionId, store = taskLookupPass?.store ?? new SessionStore()) {
|
|
240
316
|
let found;
|
|
241
|
-
|
|
242
|
-
|
|
317
|
+
const rows = indexedTaskRecords()?.all ?? taskFiles();
|
|
318
|
+
for (const { id, path, data: cached } of rows) {
|
|
319
|
+
const data = cached ?? childRecord(id, path);
|
|
243
320
|
if (!data || taskSessionId(id, String(data.parent_session_id), store) !== sessionId)
|
|
244
321
|
continue;
|
|
245
322
|
if (found && found.data.parent_session_id !== data.parent_session_id)
|
|
@@ -270,10 +347,11 @@ export function evalAgentSession(parentPiId, args, claimed, after) {
|
|
|
270
347
|
if (parentPiId === undefined || typeof args.prompt !== "string")
|
|
271
348
|
return undefined;
|
|
272
349
|
let best;
|
|
273
|
-
|
|
350
|
+
const rows = indexedTaskRecords()?.byParent.get(parentPiId) ?? (taskLookupPass ? [] : taskFiles());
|
|
351
|
+
for (const { id, path, data: cached } of rows) {
|
|
274
352
|
if (claimed.has(id))
|
|
275
353
|
continue;
|
|
276
|
-
const data = childRecord(id, path);
|
|
354
|
+
const data = cached ?? childRecord(id, path);
|
|
277
355
|
if (data?.parent_session_id !== parentPiId)
|
|
278
356
|
continue;
|
|
279
357
|
const spec = record(data.spawn_spec) ? data.spawn_spec : {};
|
|
@@ -306,6 +384,9 @@ export function evalAgentSession(parentPiId, args, claimed, after) {
|
|
|
306
384
|
export function findTask(id, parentPiId) {
|
|
307
385
|
if (!taskId(id))
|
|
308
386
|
return undefined;
|
|
387
|
+
const indexed = indexedTaskRecords();
|
|
388
|
+
if (indexed !== undefined)
|
|
389
|
+
return indexed.byId.get(id)?.find(({ data }) => data.parent_session_id === parentPiId);
|
|
309
390
|
for (const store of taskStores()) {
|
|
310
391
|
const path = join(store, "tasks", `${id}.json`);
|
|
311
392
|
const data = jsonObject(path);
|
|
@@ -391,8 +472,6 @@ export class SubagentBridge {
|
|
|
391
472
|
children = new Map();
|
|
392
473
|
calls = new Map();
|
|
393
474
|
removed = new Set();
|
|
394
|
-
/** Parent pi session of each task record already read; a record's parent never changes. */
|
|
395
|
-
taskParents = new Map();
|
|
396
475
|
constructor(store, sessions, emit, parse) {
|
|
397
476
|
this.store = store;
|
|
398
477
|
this.sessions = sessions;
|
|
@@ -501,7 +580,7 @@ export class SubagentBridge {
|
|
|
501
580
|
return true;
|
|
502
581
|
}
|
|
503
582
|
discover(parent, messages) {
|
|
504
|
-
this.discoverParts(parent, messages.flatMap((message) => message.parts), false);
|
|
583
|
+
withTaskLookups(this.store, () => this.discoverParts(parent, messages.flatMap((message) => message.parts), false));
|
|
505
584
|
}
|
|
506
585
|
discoverParts(parent, parts, live) {
|
|
507
586
|
this.wire(parent);
|
|
@@ -562,23 +641,26 @@ export class SubagentBridge {
|
|
|
562
641
|
};
|
|
563
642
|
this.children.set(session.info.id, child);
|
|
564
643
|
this.sessions.set(session.info.id, session);
|
|
644
|
+
indexChildIdentity(this.store, session.info.id, task);
|
|
565
645
|
this.wire(session);
|
|
566
646
|
this.emit(session.info.directory, { type: "session.created", properties: { info: session.info } });
|
|
567
647
|
return child;
|
|
568
648
|
}
|
|
569
649
|
restore(id) {
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
650
|
+
return withTaskLookups(this.store, () => {
|
|
651
|
+
const known = this.children.get(id);
|
|
652
|
+
if (known)
|
|
653
|
+
return known.session;
|
|
654
|
+
const entry = this.store.get(id);
|
|
655
|
+
if (!entry)
|
|
656
|
+
return this.removed.has(id) ? undefined : this.adopt(id);
|
|
657
|
+
if (entry.deleted || !entry.task || !entry.parentID)
|
|
658
|
+
return undefined;
|
|
659
|
+
const child = this.create(this.detachedParent(entry.parentID, entry.directory, entry), entry.task, id);
|
|
660
|
+
child.session.info.title = entry.title ?? child.session.info.title;
|
|
661
|
+
this.refresh(child, false);
|
|
662
|
+
return child.session;
|
|
663
|
+
});
|
|
582
664
|
}
|
|
583
665
|
/**
|
|
584
666
|
* Tasks spawned outside a `task` tool call (e.g. `agent()` inside an `eval`
|
|
@@ -623,6 +705,8 @@ export class SubagentBridge {
|
|
|
623
705
|
return this.sessions.get(id) ?? (entry ? this.detachedParent(id, entry.directory, entry) : undefined);
|
|
624
706
|
}
|
|
625
707
|
childIdsByPi() {
|
|
708
|
+
if (taskLookupPass?.store === this.store)
|
|
709
|
+
return taskLookupPass.childByPi;
|
|
626
710
|
const byPi = new Map();
|
|
627
711
|
for (const id of this.store.childIds()) {
|
|
628
712
|
const entry = this.store.get(id);
|
|
@@ -656,26 +740,20 @@ export class SubagentBridge {
|
|
|
656
740
|
};
|
|
657
741
|
}
|
|
658
742
|
restoreAll() {
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
const
|
|
666
|
-
if (
|
|
743
|
+
withTaskLookups(this.store, () => {
|
|
744
|
+
for (const id of taskLookupPass?.childIds ?? [])
|
|
745
|
+
this.restore(id);
|
|
746
|
+
const childByPi = this.childIdsByPi();
|
|
747
|
+
for (const { id, path, data } of indexedTaskRecords()?.all ?? []) {
|
|
748
|
+
const parentPi = String(data.parent_session_id);
|
|
749
|
+
const sessionId = taskSessionId(id, parentPi, this.store);
|
|
750
|
+
if (this.children.has(sessionId) || this.removed.has(sessionId) || this.store.get(sessionId))
|
|
751
|
+
continue;
|
|
752
|
+
if (!this.parentFor(parentPi, childByPi))
|
|
667
753
|
continue;
|
|
668
|
-
this.taskParents.set(path, (parentPi = parent));
|
|
669
|
-
}
|
|
670
|
-
const sessionId = taskSessionId(id, parentPi, this.store);
|
|
671
|
-
if (this.children.has(sessionId) || this.removed.has(sessionId) || this.store.get(sessionId))
|
|
672
|
-
continue;
|
|
673
|
-
if (!this.parentFor(parentPi, childByPi))
|
|
674
|
-
continue;
|
|
675
|
-
const data = childRecord(id, path);
|
|
676
|
-
if (data)
|
|
677
754
|
this.adopt(sessionId, { path, data });
|
|
678
|
-
|
|
755
|
+
}
|
|
756
|
+
});
|
|
679
757
|
}
|
|
680
758
|
owns(id) {
|
|
681
759
|
return this.children.has(id);
|
|
@@ -936,6 +1014,7 @@ export class SubagentBridge {
|
|
|
936
1014
|
created: info.time.created,
|
|
937
1015
|
updated: info.time.updated,
|
|
938
1016
|
});
|
|
1017
|
+
indexChildIdentity(this.store, info.id, child.task, child.session.piSessionId ?? child.task.id);
|
|
939
1018
|
}
|
|
940
1019
|
catch (error) {
|
|
941
1020
|
if (!(error instanceof SessionPersistenceError))
|