@adhdev/daemon-core 0.9.82-rc.534 → 0.9.82-rc.535

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": "@adhdev/daemon-core",
3
- "version": "0.9.82-rc.534",
3
+ "version": "0.9.82-rc.535",
4
4
  "description": "ADHDev daemon core — CDP, IDE detection, providers, command execution",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -47,8 +47,8 @@
47
47
  "author": "vilmire",
48
48
  "license": "AGPL-3.0-or-later",
49
49
  "dependencies": {
50
- "@adhdev/mesh-shared": "0.9.82-rc.534",
51
- "@adhdev/session-host-core": "0.9.82-rc.534",
50
+ "@adhdev/mesh-shared": "0.9.82-rc.535",
51
+ "@adhdev/session-host-core": "0.9.82-rc.535",
52
52
  "@agentclientprotocol/sdk": "^0.16.1",
53
53
  "ajv": "^8.20.0",
54
54
  "ajv-formats": "^3.0.1",
@@ -1206,7 +1206,19 @@ export class CliStateEngine {
1206
1206
  const detectFn = typeof this.transport.runDetectStatus === 'function'
1207
1207
  ? () => this.transport.runDetectStatus!(snap.recentOutputBuffer)
1208
1208
  : () => this.runDetectStatus(snap);
1209
- const latestStatus = detectFn() || this.currentStatus;
1209
+ // Only a POSITIVE `generating` verdict from the live detector defers the
1210
+ // finish. A null verdict is "no cue matched", NOT "still generating" — for
1211
+ // a provider whose only idle cue is a composer placeholder (opencode's
1212
+ // `Ask anything`) that can momentarily fall out of the captured frame while
1213
+ // the TUI redraws its status chip, detectStatus returns null under the
1214
+ // manifest's `onNoMatch: preserve-last` policy. Collapsing that null to
1215
+ // `this.currentStatus` (which is `generating` while the hold is armed) made
1216
+ // the finish defer on EVERY tick, so the completion never fired and the
1217
+ // session wedged in `generating` forever even though its assistant reply had
1218
+ // already landed in native-history. Treat null as "no evidence to defer" and
1219
+ // let the idle-finish proceed; a real in-flight turn still re-reports a
1220
+ // positive `generating` here and defers as before.
1221
+ const latestStatus = detectFn();
1210
1222
  if (latestStatus === 'generating') {
1211
1223
  this.evaluateSettled(snap);
1212
1224
  return true;
@@ -1339,13 +1339,24 @@ export class ProviderLoader {
1339
1339
  candidates.push(path.join(providerDir, 'specs', 'default.json'));
1340
1340
  candidates.push(path.join(providerDir, 'spec.json'));
1341
1341
  const specPath = candidates.find((p: string) => fs.existsSync(p));
1342
+ // native_history block, resolved from either the separate spec file
1343
+ // (snake_case `native_history`) or — for v1-manifest-only providers that
1344
+ // ship no specs/*.json — the inline camelCase `nativeHistory` on the
1345
+ // manifest itself. The separate spec file wins when both exist. Without
1346
+ // the v1-manifest fallback, a provider whose ONLY declaration is an
1347
+ // inline `nativeHistory.source` (e.g. opencode's sqlite source) never got
1348
+ // its `scripts.readNativeHistory` wired: the whole block was gated on
1349
+ // `specPath`, so read_chat returned native-unavailable, the assistant
1350
+ // reply (only in the on-disk store, never in the PTY snapshot) was
1351
+ // dropped, providerSessionId stayed null, and the session wedged in
1352
+ // `generating` because no native completion evidence ever arrived.
1353
+ let nh: any | undefined;
1342
1354
  if (specPath) {
1343
1355
  // Hand the resolved spec path off to route.ts via a hidden field
1344
1356
  // so the routing layer doesn't have to repeat the candidate walk.
1345
1357
  (resolved as any)._resolvedSpecPath = specPath;
1346
1358
  // Extract control_bar + native_history directly from the JSON header.
1347
1359
  let specControls: any[] | undefined;
1348
- let nh: any | undefined;
1349
1360
  try {
1350
1361
  const rawSpec = JSON.parse(fs.readFileSync(specPath, 'utf8'));
1351
1362
  specControls = rawSpec.control_bar;
@@ -1382,44 +1393,56 @@ export class ProviderLoader {
1382
1393
  }
1383
1394
  }
1384
1395
  }
1385
- if (nh) {
1386
- let reader: ((input: any) => any) | null = null;
1387
- let format = 'spec';
1388
-
1389
- if (nh.source) {
1390
- format = `spec-${nh.source.kind}`;
1391
- reader = (input: any) => executeNativeHistory(nh, input);
1392
- } else if (nh.override_path) {
1393
- const overrideFile = path.resolve(providerDir, nh.override_path);
1394
- if (fs.existsSync(overrideFile)) {
1395
- try {
1396
- registerProviderScriptRootSafely(path.dirname(path.dirname(providerDir)));
1397
- delete require.cache[require.resolve(overrideFile)];
1398
- // eslint-disable-next-line @typescript-eslint/no-var-requires
1399
- const mod = require(overrideFile);
1400
- const fn = typeof mod === 'function' ? mod : (mod && typeof mod.default === 'function' ? mod.default : null);
1401
- if (fn) {
1402
- format = 'spec-override';
1403
- reader = (input: any) => fn(input);
1404
- }
1405
- } catch { /* fall through — leave native unavailable */ }
1406
- }
1407
- } else if (nh.reader) {
1408
- const dispatch = createNativeHistoryDispatcher(nh.reader as ReaderId);
1409
- format = nh.reader;
1410
- reader = (input: any) => dispatch(input);
1396
+ }
1397
+ // Fall back to the v1 manifest's inline `nativeHistory` (camelCase) when
1398
+ // no separate spec file provided a `native_history` block. Only treat it
1399
+ // as a declarative reader source when it actually carries source/
1400
+ // override_path/reader — a bare `nativeHistory` marker that only names
1401
+ // `scripts.readSession` (claude/codex/antigravity, whose real reader is
1402
+ // wired from their specs/*.json) must not be mistaken for one.
1403
+ if (!nh) {
1404
+ const inlineNh = (base as any)?.nativeHistory || (resolved as any)?.nativeHistory;
1405
+ if (inlineNh && (inlineNh.source || inlineNh.override_path || inlineNh.reader)) {
1406
+ nh = inlineNh;
1407
+ }
1408
+ }
1409
+ if (nh) {
1410
+ let reader: ((input: any) => any) | null = null;
1411
+ let format = 'spec';
1412
+
1413
+ if (nh.source) {
1414
+ format = `spec-${nh.source.kind}`;
1415
+ reader = (input: any) => executeNativeHistory(nh, input);
1416
+ } else if (nh.override_path) {
1417
+ const overrideFile = path.resolve(providerDir, nh.override_path);
1418
+ if (fs.existsSync(overrideFile)) {
1419
+ try {
1420
+ registerProviderScriptRootSafely(path.dirname(path.dirname(providerDir)));
1421
+ delete require.cache[require.resolve(overrideFile)];
1422
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
1423
+ const mod = require(overrideFile);
1424
+ const fn = typeof mod === 'function' ? mod : (mod && typeof mod.default === 'function' ? mod.default : null);
1425
+ if (fn) {
1426
+ format = 'spec-override';
1427
+ reader = (input: any) => fn(input);
1428
+ }
1429
+ } catch { /* fall through — leave native unavailable */ }
1411
1430
  }
1431
+ } else if (nh.reader) {
1432
+ const dispatch = createNativeHistoryDispatcher(nh.reader as ReaderId);
1433
+ format = nh.reader;
1434
+ reader = (input: any) => dispatch(input);
1435
+ }
1412
1436
 
1413
- if (reader) {
1414
- resolved.scripts = { ...(resolved.scripts || {}) };
1415
- (resolved.scripts as any).readNativeHistory = reader;
1416
- (resolved as any).nativeHistory = {
1417
- format,
1418
- watchPath: undefined,
1419
- scripts: { readSession: 'readNativeHistory' },
1420
- mode: 'native-source',
1421
- };
1422
- }
1437
+ if (reader) {
1438
+ resolved.scripts = { ...(resolved.scripts || {}) };
1439
+ (resolved.scripts as any).readNativeHistory = reader;
1440
+ (resolved as any).nativeHistory = {
1441
+ format,
1442
+ watchPath: undefined,
1443
+ scripts: { readSession: 'readNativeHistory' },
1444
+ mode: 'native-source',
1445
+ };
1423
1446
  }
1424
1447
  }
1425
1448
  } catch {