@adhdev/daemon-core 0.9.82-rc.464 → 0.9.82-rc.466
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/dist/index.js +1022 -823
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1028 -829
- package/dist/index.mjs.map +1 -1
- package/dist/mesh/mesh-events-pending.d.ts +18 -0
- package/dist/mesh/mesh-reconcile-acked-hold.d.ts +17 -0
- package/dist/mesh/mesh-reconcile-identity.d.ts +6 -0
- package/dist/mesh/mesh-reconcile-loop.d.ts +2 -14
- package/dist/mesh/mesh-reconcile-v2-backstop.d.ts +16 -0
- package/dist/mesh/mesh-runtime-store.d.ts +26 -0
- package/dist/providers/cli-provider-history-dedup.d.ts +17 -0
- package/dist/providers/cli-provider-input-prompt.d.ts +12 -0
- package/dist/providers/cli-provider-instance.d.ts +43 -35
- package/dist/providers/cli-provider-status-helpers.d.ts +46 -0
- package/package.json +3 -3
- package/src/mesh/mesh-event-forwarding.ts +16 -1
- package/src/mesh/mesh-events-pending.ts +94 -5
- package/src/mesh/mesh-ledger.ts +10 -0
- package/src/mesh/mesh-reconcile-acked-hold.ts +230 -0
- package/src/mesh/mesh-reconcile-identity.ts +103 -0
- package/src/mesh/mesh-reconcile-loop.ts +28 -393
- package/src/mesh/mesh-reconcile-v2-backstop.ts +62 -0
- package/src/mesh/mesh-runtime-store.ts +53 -0
- package/src/providers/cli-provider-history-dedup.ts +75 -0
- package/src/providers/cli-provider-input-prompt.ts +133 -0
- package/src/providers/cli-provider-instance.ts +139 -298
- package/src/providers/cli-provider-status-helpers.ts +123 -0
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI provider status/launch pure helpers.
|
|
3
|
+
*
|
|
4
|
+
* Pure move out of cli-provider-instance.ts (no behavior change): the
|
|
5
|
+
* side-effect-free status predicates, the turn-anchored duration computation,
|
|
6
|
+
* the forced-new-session script resolver, the adapter-ready poll, and the lazy
|
|
7
|
+
* node:sqlite DatabaseSync loader. cli-provider-instance re-exports the
|
|
8
|
+
* public symbols (computeTurnAnchoredDurationMs, getForcedNewSessionScriptName,
|
|
9
|
+
* waitForCliAdapterReady) so existing importers/tests keep their path.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import * as path from 'path';
|
|
13
|
+
import { createRequire } from 'node:module';
|
|
14
|
+
import type { ProviderModule } from './contracts.js';
|
|
15
|
+
|
|
16
|
+
export function isIdleStatus(value: unknown): boolean {
|
|
17
|
+
const status = typeof value === 'string' ? value.trim().toLowerCase() : '';
|
|
18
|
+
return !status || status === 'idle' || status === 'ready';
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function getMessageTime(message: unknown): number {
|
|
22
|
+
if (!message || typeof message !== 'object') return 0;
|
|
23
|
+
const record = message as { receivedAt?: unknown; timestamp?: unknown };
|
|
24
|
+
const value = Number(record.receivedAt ?? record.timestamp ?? 0);
|
|
25
|
+
return Number.isFinite(value) ? value : 0;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function hasNonEmptyCliModalButtons(activeModal: unknown): boolean {
|
|
29
|
+
const buttons = (activeModal as any)?.buttons;
|
|
30
|
+
return Array.isArray(buttons) && buttons.some((button) => String(button || '').trim().length > 0);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function isCliGeneratingLikeStatus(status: unknown): boolean {
|
|
34
|
+
return status === 'generating' || status === 'streaming' || status === 'no_progress' || status === 'long_generating' || status === 'starting';
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* NOTIF Defect-2a: the REPORTED short-generating duration, anchored on the IMMUTABLE turn
|
|
39
|
+
* start. generatingStartedAt is reset to 0 on every mid-turn waiting_approval/idle blip and
|
|
40
|
+
* re-armed on the next →generating, so a long turn that blips would otherwise measure only the
|
|
41
|
+
* final 1.5-2.5s sliver. engine.currentTurnStartedAt (set once at onTurnStarted, surviving
|
|
42
|
+
* mid-turn blips until the next turn starts) is preferred; generatingStartedAt is the fallback
|
|
43
|
+
* for turns that never recorded an engine turn start. Returns 0 when neither anchor is set.
|
|
44
|
+
* Pure / unit-testable.
|
|
45
|
+
*/
|
|
46
|
+
export function computeTurnAnchoredDurationMs(
|
|
47
|
+
engineTurnStartedAt: number | undefined,
|
|
48
|
+
generatingStartedAt: number,
|
|
49
|
+
now: number,
|
|
50
|
+
): { durationMs: number; anchor: 'turn-start' | 'generatingStartedAt' | 'none' } {
|
|
51
|
+
const engineStart = typeof engineTurnStartedAt === 'number' && Number.isFinite(engineTurnStartedAt)
|
|
52
|
+
? engineTurnStartedAt
|
|
53
|
+
: 0;
|
|
54
|
+
if (engineStart > 0) return { durationMs: now - engineStart, anchor: 'turn-start' };
|
|
55
|
+
if (generatingStartedAt > 0) return { durationMs: now - generatingStartedAt, anchor: 'generatingStartedAt' };
|
|
56
|
+
return { durationMs: 0, anchor: 'none' };
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
let CachedDatabaseSync: (new (path: string, options?: { readOnly?: boolean }) => {
|
|
60
|
+
prepare(sql: string): { get(...params: Array<string | number>): unknown };
|
|
61
|
+
close(): void;
|
|
62
|
+
}) | null = null;
|
|
63
|
+
|
|
64
|
+
export function getDatabaseSync() {
|
|
65
|
+
if (CachedDatabaseSync) return CachedDatabaseSync;
|
|
66
|
+
const requireFn = typeof require === 'function'
|
|
67
|
+
? require
|
|
68
|
+
: createRequire(path.join(process.cwd(), '__adhdev_sqlite_loader__.js'));
|
|
69
|
+
const sqliteModule = requireFn(`node:${'sqlite'}`) as {
|
|
70
|
+
DatabaseSync: typeof CachedDatabaseSync;
|
|
71
|
+
};
|
|
72
|
+
CachedDatabaseSync = sqliteModule.DatabaseSync;
|
|
73
|
+
if (!CachedDatabaseSync) {
|
|
74
|
+
throw new Error('node:sqlite DatabaseSync unavailable');
|
|
75
|
+
}
|
|
76
|
+
return CachedDatabaseSync;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export function getForcedNewSessionScriptName(
|
|
80
|
+
provider: ProviderModule | undefined,
|
|
81
|
+
launchMode: 'new' | 'resume' | 'manual',
|
|
82
|
+
): string | null {
|
|
83
|
+
if (!provider || launchMode !== 'new') return null;
|
|
84
|
+
const resume = provider.resume;
|
|
85
|
+
if (!resume?.supported) return null;
|
|
86
|
+
if (Array.isArray(resume.newSessionArgs) && resume.newSessionArgs.length > 0) return null;
|
|
87
|
+
|
|
88
|
+
const controls = Array.isArray((provider as any).controls) ? (provider as any).controls : [];
|
|
89
|
+
for (const control of controls) {
|
|
90
|
+
if (control?.type !== 'action') continue;
|
|
91
|
+
if (typeof control?.confirmTitle === 'string' && control.confirmTitle.trim()) continue;
|
|
92
|
+
if (typeof control?.confirmMessage === 'string' && control.confirmMessage.trim()) continue;
|
|
93
|
+
if (typeof control?.confirmLabel === 'string' && control.confirmLabel.trim()) continue;
|
|
94
|
+
const invokeScript = typeof control?.invokeScript === 'string' ? control.invokeScript.trim() : '';
|
|
95
|
+
if (!invokeScript) continue;
|
|
96
|
+
const controlId = typeof control?.id === 'string' ? control.id.trim() : '';
|
|
97
|
+
if (controlId === 'new_session' || /^new.?session$/i.test(invokeScript)) {
|
|
98
|
+
return invokeScript;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
return null;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export async function waitForCliAdapterReady(
|
|
106
|
+
adapter: { isReady?: () => boolean; getStatus?: () => { status?: string } },
|
|
107
|
+
options?: { timeoutMs?: number; pollMs?: number },
|
|
108
|
+
): Promise<void> {
|
|
109
|
+
const timeoutMs = Math.max(100, options?.timeoutMs ?? 15_000);
|
|
110
|
+
const pollMs = Math.max(10, options?.pollMs ?? 50);
|
|
111
|
+
const deadline = Date.now() + timeoutMs;
|
|
112
|
+
|
|
113
|
+
while (Date.now() < deadline) {
|
|
114
|
+
if (adapter?.isReady?.()) return;
|
|
115
|
+
const status = adapter?.getStatus?.()?.status;
|
|
116
|
+
if (status === 'stopped') {
|
|
117
|
+
throw new Error('CLI runtime stopped before it became ready');
|
|
118
|
+
}
|
|
119
|
+
await new Promise((resolve) => setTimeout(resolve, pollMs));
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
throw new Error(`CLI runtime did not become ready within ${timeoutMs}ms`);
|
|
123
|
+
}
|