antechamber 0.2.15 → 0.2.16

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 CHANGED
@@ -7,6 +7,15 @@ and this project uses [Semantic Versioning](https://semver.org/).
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.2.16] - 2026-10-17
11
+
12
+ ### Fixed
13
+
14
+ - Keep deleted subagent sessions deleted. They came back when their parent's history was read again or when the
15
+ adapter restarted, because OmO still holds their task record.
16
+ - Keep subagent sessions archived after an adapter restart. Archiving a parent with its subagents left the
17
+ subagents active as orphans once the adapter restarted.
18
+
10
19
  ## [0.2.15] - 2026-10-17
11
20
 
12
21
  ### Fixed
@@ -35,6 +35,8 @@ export type TitleSource = "user" | "native" | "fallback" | "generated";
35
35
  export interface SessionRegistryEntry {
36
36
  /** Created by this connector, rather than discovered from another OmO client. */
37
37
  connectorOwned?: true;
38
+ /** A child the user deleted; kept so its task record or parent history cannot list it again. */
39
+ deleted?: true;
38
40
  tree?: SessionTreeState;
39
41
  parentID?: string | undefined;
40
42
  parentMessageID?: string;
@@ -346,6 +346,8 @@ function registryEntry(value) {
346
346
  return false;
347
347
  if (value.connectorOwned !== undefined && value.connectorOwned !== true)
348
348
  return false;
349
+ if (value.deleted !== undefined && value.deleted !== true)
350
+ return false;
349
351
  if (value.tree !== undefined && !sessionTreeState(value.tree))
350
352
  return false;
351
353
  if (value.parentID !== undefined && typeof value.parentID !== "string")
package/dist/sessions.js CHANGED
@@ -344,7 +344,7 @@ export class SessionManager {
344
344
  this.emit(s.info.directory, { type: "session.deleted", properties: { info: s.info } });
345
345
  await this.lifecycle.dormant(s);
346
346
  const piPath = this.subagents.owns(sessionId) || this.monitors.owns(sessionId) ? undefined : (s.piPath ?? s.restored?.piPath);
347
- this.subagents.remove(sessionId);
347
+ const child = this.subagents.remove(sessionId);
348
348
  this.monitors.remove(sessionId);
349
349
  if (piPath !== undefined) {
350
350
  try {
@@ -355,7 +355,9 @@ export class SessionManager {
355
355
  throw error;
356
356
  }
357
357
  }
358
- this.store.remove(sessionId);
358
+ // A deleted child keeps its tombstone; OmO still holds the task record that would list it again.
359
+ if (!child)
360
+ this.store.remove(sessionId);
359
361
  return true;
360
362
  }
361
363
  /**
@@ -391,7 +393,9 @@ export class SessionManager {
391
393
  delete s.info.time.archived; // 0 = unarchive
392
394
  }
393
395
  s.info.time.updated = Date.now();
394
- this.persistMeta(s);
396
+ // Child sessions have no pi path of their own, so persistMeta would skip them.
397
+ if (!this.subagents.save(s.info.id))
398
+ this.persistMeta(s);
395
399
  this.emit(s.info.directory, { type: "session.updated", properties: { info: s.info } });
396
400
  return s.info;
397
401
  }
@@ -1318,6 +1322,8 @@ export class SessionManager {
1318
1322
  /** Resolve a bare session id (e.g. deep link after restart) via known directories. */
1319
1323
  resolveRestored(sessionId) {
1320
1324
  const reg = this.store.get(sessionId);
1325
+ if (reg?.deleted)
1326
+ return undefined;
1321
1327
  if (reg && existsSync(reg.piPath)) {
1322
1328
  return this.adopt({
1323
1329
  piSessionId: reg.piSessionId,
@@ -78,12 +78,16 @@ export declare class SubagentBridge {
78
78
  private publishRefresh;
79
79
  private saveArchive;
80
80
  private fallback;
81
+ /** Save a rename or archive made through the session routes; false when `id` is not a child. */
82
+ save(id: string): boolean;
81
83
  private persist;
82
84
  private emitPart;
83
85
  private closeWatchers;
84
86
  finishCalls(parentID: string, cancelled?: boolean): void;
85
87
  stopParent(parentID: string): void;
86
- remove(id: string): void;
88
+ /** Forget a deleted child and leave a registry tombstone; false when `id` is not a child. */
89
+ remove(id: string): boolean;
90
+ private deleted;
87
91
  dispose(): void;
88
92
  }
89
93
  export {};
package/dist/subagents.js CHANGED
@@ -319,6 +319,8 @@ export class SubagentBridge {
319
319
  const id = metadata.taskID;
320
320
  const details = record(metadata.task) ? metadata.task : {};
321
321
  let child = this.children.get(ocIdFor(id));
322
+ if (!child && this.deleted(ocIdFor(id)))
323
+ continue;
322
324
  if (!child) {
323
325
  child = this.create(parent, {
324
326
  id,
@@ -340,6 +342,7 @@ export class SubagentBridge {
340
342
  }
341
343
  }
342
344
  create(parent, task) {
345
+ const archived = this.store.get(ocIdFor(task.id))?.archived;
343
346
  const session = this.managedSession({
344
347
  id: ocIdFor(task.id),
345
348
  parentID: parent.info.id,
@@ -347,7 +350,7 @@ export class SubagentBridge {
347
350
  directory: parent.info.directory,
348
351
  title: typeof task.input.description === "string" ? task.input.description : task.id,
349
352
  version: parent.info.version,
350
- time: { ...parent.info.time },
353
+ time: { ...parent.info.time, ...(archived !== undefined ? { archived } : {}) },
351
354
  });
352
355
  const child = {
353
356
  session,
@@ -373,7 +376,7 @@ export class SubagentBridge {
373
376
  const entry = this.store.get(id);
374
377
  if (!entry)
375
378
  return this.removed.has(id) ? undefined : this.adopt(id);
376
- if (!entry.task || !entry.parentID)
379
+ if (entry.deleted || !entry.task || !entry.parentID)
377
380
  return undefined;
378
381
  const child = this.create(this.detachedParent(entry.parentID, entry.directory, entry), entry.task);
379
382
  child.session.info.title = entry.title ?? child.session.info.title;
@@ -682,6 +685,14 @@ export class SubagentBridge {
682
685
  });
683
686
  return this.parse(child.session, `${request}\n${response}\n`);
684
687
  }
688
+ /** Save a rename or archive made through the session routes; false when `id` is not a child. */
689
+ save(id) {
690
+ const child = this.children.get(id);
691
+ if (!child)
692
+ return false;
693
+ this.persist(child);
694
+ return true;
695
+ }
685
696
  persist(child) {
686
697
  const { info } = child.session;
687
698
  try {
@@ -691,6 +702,7 @@ export class SubagentBridge {
691
702
  directory: info.directory,
692
703
  title: info.title,
693
704
  parentID: info.parentID,
705
+ ...(info.time.archived !== undefined ? { archived: info.time.archived } : {}),
694
706
  task: child.task,
695
707
  created: info.time.created,
696
708
  updated: info.time.updated,
@@ -746,14 +758,29 @@ export class SubagentBridge {
746
758
  this.closeWatchers(child);
747
759
  }
748
760
  }
761
+ /** Forget a deleted child and leave a registry tombstone; false when `id` is not a child. */
749
762
  remove(id) {
750
763
  const child = this.children.get(id);
751
764
  if (!child)
752
- return;
765
+ return false;
753
766
  this.closeWatchers(child);
754
767
  child.parts.clear();
755
768
  this.children.delete(id);
756
769
  this.removed.add(id);
770
+ const { info } = child.session;
771
+ this.store.set(id, {
772
+ deleted: true,
773
+ piSessionId: child.session.piSessionId ?? child.task.id,
774
+ piPath: this.archive(child.task.id),
775
+ directory: info.directory,
776
+ ...(info.parentID !== undefined ? { parentID: info.parentID } : {}),
777
+ created: info.time.created,
778
+ updated: info.time.updated,
779
+ });
780
+ return true;
781
+ }
782
+ deleted(id) {
783
+ return this.removed.has(id) || this.store.get(id)?.deleted === true;
757
784
  }
758
785
  dispose() {
759
786
  for (const child of this.children.values()) {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "antechamber-omo-graph",
3
- "version": "0.2.15",
3
+ "version": "0.2.16",
4
4
  "description": "OpenChamber extension: live, interactive graph of the OmO sub-agents behind the current session",
5
5
  "private": true,
6
6
  "type": "module",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "antechamber",
3
- "version": "0.2.15",
3
+ "version": "0.2.16",
4
4
  "description": "OpenCode-compatible HTTP/SSE server that lets OpenChamber drive the pi coding agent (and OmO) over RPC",
5
5
  "type": "module",
6
6
  "license": "MIT",