@volter/supercode-teams 0.3.193 → 0.3.195

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@volter/supercode-teams",
3
- "version": "0.3.193",
3
+ "version": "0.3.195",
4
4
  "type": "module",
5
5
  "description": "A machine daemon serving this machine's doors, and a local or remote Teams server for shared session discovery, OpenTelemetry ingestion and access to enrolled machines.",
6
6
  "license": "MIT",
@@ -84,7 +84,7 @@
84
84
  "@volter/supercode-frontend": "^0.2.2",
85
85
  "@volter/supercode-harness-sdk": "^0.3.58",
86
86
  "@volter/supercode-health": "^0.1.0",
87
- "@volter/supercode-interchange": "0.1.9",
87
+ "@volter/supercode-interchange": "0.1.10",
88
88
  "@volter/supercode-terminal": "^0.2.54",
89
89
  "@volter/supercode-trace": "^0.1.0",
90
90
  "@volter/teams": "0.2.46",
@@ -3,7 +3,7 @@ import * as zlib from 'node:zlib';
3
3
  import { basename, dirname, join, relative, resolve, sep } from 'node:path';
4
4
  import {
5
5
  HARNESSES, resolveHarnessHomes, selectedHarnesses, FILE_HARNESSES, fileRoot,
6
- normalizedSourcePath, pathUnder, sourceStat, sourceEntries, sameFingerprint,
6
+ normalizedSourcePath, pathUnder, sourceStat, sourceEntries, sameFingerprint, fileFingerprint,
7
7
  listSessionParts, sessionPartFor, readFileMetadata, verifySources,
8
8
  selectStoreFiles, storeRegistryDirectories, storeFingerprints,
9
9
  readForeignStore, readHermesStore, readOrchestratorStore, readGeminiProjects,
@@ -29,7 +29,7 @@ export class SessionIndexOwner extends EventEmitter {
29
29
  constructor({ database, env = process.env, log = () => {} }) {
30
30
  super(); requireSessionIndexRuntime(); this.database = database; this.store = new SessionIndexStore(database);
31
31
  this.env = env; this.log = log; this.sources = new Map(); this.pending = new Map();
32
- this.fileCaches = new Map(); this.projections = new Map();
32
+ this.fileCaches = new Map(); this.projections = new Map(); this.notSessions = new Set();
33
33
  this.metrics = {}; this.closed = false; this.running = null;
34
34
  this.watches = new SessionIndexWatches({
35
35
  changed: (id, event) => this.#event(id, event),
@@ -425,8 +425,9 @@ export class SessionIndexOwner extends EventEmitter {
425
425
 
426
426
  async #file(source, path) {
427
427
  const old = source.parts.get(path);
428
+ let info = null;
428
429
  try {
429
- const info = await sourceStat(path);
430
+ info = await sourceStat(path);
430
431
  if (this.closed) return;
431
432
  // Saved Supercode can retain a metadata row after both content files
432
433
  // disappear. Other formats require their native transcript file.
@@ -459,7 +460,24 @@ export class SessionIndexOwner extends EventEmitter {
459
460
  source.parts.set(path, { path, kind: 'file', state, stamps });
460
461
  this.metrics.changed_rows = (this.metrics.changed_rows ?? 0) + changed;
461
462
  } catch (error) {
462
- if (!this.closed) this.store.fail(source.id, path, 'file', error);
463
+ if (this.closed) return;
464
+ if (error?.code === 'not_a_session' && info) return this.#notSession(source, path, old, info, error);
465
+ this.store.fail(source.id, path, 'file', error);
466
+ }
467
+ }
468
+
469
+ /** A file in a harness's folder that is not one of its sessions (no session header) holds no rows and is no
470
+ * failure: it never makes the index, or the machine, unread. Its fingerprint, taken before the read, keeps it from
471
+ * being read again until it changes; the daemon log names it once. */
472
+ #notSession(source, path, old, info, error) {
473
+ const stamps = [{ path, fingerprint: fileFingerprint(info) }];
474
+ const state = { not_session: true, ...(source.harness === 'gemini' ? { projectsStamp: source.projectsStamp } : {}) };
475
+ this.store.commitPart(source.id, path, { kind: 'file', state, stamps, rows: [], invalidate: !sameStamps(stamps, old?.stamps) });
476
+ this.#apply(source, path, []);
477
+ source.parts.set(path, { path, kind: 'file', state, stamps });
478
+ if (!this.notSessions.has(path)) {
479
+ this.notSessions.add(path); this.metrics.not_sessions = this.notSessions.size;
480
+ this.log(`session index: left out ${path}: ${error.message} (${this.notSessions.size} file${this.notSessions.size === 1 ? '' : 's'} left out)`);
463
481
  }
464
482
  }
465
483
 
package/terminal-mail.mjs CHANGED
@@ -284,7 +284,8 @@ export class TerminalMailbox {
284
284
  let lost = true;
285
285
  for (let check = 0; lost && check < 2; check++) {
286
286
  const screen = await this.host.capture(this.session.id, { lines: 200, preserveEscapes: true });
287
- lost = composerText(batch.kind, screen) === '' && !/\besc to (?:interrupt|cancel)\b/iu.test(screen);
287
+ // Codex paints its hint as `\x1b[0;1mesc\x1b[0;2m to interrupt`: a running turn is read with the styling removed.
288
+ lost = composerText(batch.kind, screen) === '' && !/\besc to (?:interrupt|cancel)\b/iu.test(String(screen).replace(/\x1b\[[0-?]*[ -/]*[@-~]/g, ''));
288
289
  if (lost && check === 0) await pause(200);
289
290
  }
290
291
  if (lost && !confirmed(batch)) {