@threadbase-sh/streamer 1.40.0 → 1.41.1
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/README.md +1 -1
- package/dist/cli.cjs +358 -65
- package/dist/cli.cjs.map +1 -1
- package/dist/index.cjs +356 -63
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +69 -0
- package/dist/index.d.ts +69 -0
- package/dist/index.js +356 -63
- package/dist/index.js.map +1 -1
- package/dist/{migrations/010_create_managed_sessions.sql → runtime-migrations/001_create_managed_sessions.sql} +6 -0
- package/package.json +2 -2
package/dist/index.d.cts
CHANGED
|
@@ -182,6 +182,16 @@ interface ManagedSession {
|
|
|
182
182
|
statusUpdatedAt?: Date;
|
|
183
183
|
filePath?: string;
|
|
184
184
|
resumedFromConversationId?: string;
|
|
185
|
+
/**
|
|
186
|
+
* This session was seeded from the durable registry at boot, not spawned by
|
|
187
|
+
* this run — there is no PTY behind it and never was one in this process.
|
|
188
|
+
*
|
|
189
|
+
* INTERNAL. It never reaches the wire: `managedToResponse` translates it into
|
|
190
|
+
* the already-defined `ownership: "historical"` + `lifecycle: "resumable"`
|
|
191
|
+
* pair, so no client needs to learn a new field to render a recovered session.
|
|
192
|
+
* Cleared implicitly when a resume overwrites the stub with a real session.
|
|
193
|
+
*/
|
|
194
|
+
rehydrated?: boolean;
|
|
185
195
|
/**
|
|
186
196
|
* Set once a live session's underlying persisted conversation file is
|
|
187
197
|
* discovered after the fact (currently: fresh Codex sessions, whose
|
|
@@ -501,6 +511,7 @@ interface ServerConfig {
|
|
|
501
511
|
skipStartupWarmup?: boolean;
|
|
502
512
|
ptyGracePeriodMs?: number;
|
|
503
513
|
cacheDir?: string;
|
|
514
|
+
runtimeDbPath?: string;
|
|
504
515
|
tailSize?: number;
|
|
505
516
|
directoryScanDebounceMs?: number;
|
|
506
517
|
defaultSystemPrompt?: string;
|
|
@@ -1251,6 +1262,41 @@ declare class SessionsRepository {
|
|
|
1251
1262
|
listManagedSessions(): ManagedSession[];
|
|
1252
1263
|
}
|
|
1253
1264
|
|
|
1265
|
+
/**
|
|
1266
|
+
* `~/.threadbase/runtime.db` — the authoritative, non-derived half of the
|
|
1267
|
+
* streamer's SQLite state.
|
|
1268
|
+
*
|
|
1269
|
+
* Deliberately a separate file from `cache/cache.db`, and deliberately not
|
|
1270
|
+
* under `cache/`. The conversation cache is rebuildable from the provider
|
|
1271
|
+
* JSONLs at any time, which is why "delete the cache and restart" is reasonable
|
|
1272
|
+
* support advice and why the integrity monitor offers a reset-and-rescan
|
|
1273
|
+
* action. The managed-session registry is not rebuildable from anything on
|
|
1274
|
+
* disk, so it must not sit one plausible instruction away from deletion — nor
|
|
1275
|
+
* share a handle whose failure (a better-sqlite3 ABI mismatch, most commonly)
|
|
1276
|
+
* would silently disable session persistence along with the cache.
|
|
1277
|
+
*
|
|
1278
|
+
* Runs its own migrations from `src/db/runtime-migrations/`, tracked in this
|
|
1279
|
+
* file's own `schema_migrations` table.
|
|
1280
|
+
*/
|
|
1281
|
+
declare class RuntimeStore {
|
|
1282
|
+
private readonly db;
|
|
1283
|
+
private constructor();
|
|
1284
|
+
static open(dbPath: string, migrationsDir?: string): RuntimeStore;
|
|
1285
|
+
getDatabase(): Database.Database;
|
|
1286
|
+
/**
|
|
1287
|
+
* One-time move of `managed_sessions` rows out of a pre-split `cache.db`.
|
|
1288
|
+
*
|
|
1289
|
+
* Non-destructive by design: the source table is left in place so an older
|
|
1290
|
+
* streamer rolled back onto the same machine still finds its registry. Runs
|
|
1291
|
+
* only when this file's table is empty, so a second boot is a no-op rather
|
|
1292
|
+
* than a re-copy that would resurrect rows deleted since.
|
|
1293
|
+
*
|
|
1294
|
+
* Returns the number of rows copied.
|
|
1295
|
+
*/
|
|
1296
|
+
importLegacyManagedSessions(source: Database.Database): number;
|
|
1297
|
+
close(): void;
|
|
1298
|
+
}
|
|
1299
|
+
|
|
1254
1300
|
declare class LiveSessionManager {
|
|
1255
1301
|
private runners;
|
|
1256
1302
|
constructor(options?: PTYManagerOptions);
|
|
@@ -1413,6 +1459,8 @@ type ApiDeps = {
|
|
|
1413
1459
|
conversationsRepo: () => ConversationsRepository | null;
|
|
1414
1460
|
sessionsRepo: () => SessionsRepository | null;
|
|
1415
1461
|
cacheMetadataRepo: () => CacheMetadataRepository | null;
|
|
1462
|
+
/** Authoritative session registry (~/.threadbase/runtime.db). Null when it failed to open. */
|
|
1463
|
+
runtimeStore: () => RuntimeStore | null;
|
|
1416
1464
|
ptyAttachedIds: () => Set<string>;
|
|
1417
1465
|
handleListSessions: (url: URL, res: ServerResponse) => Promise<void>;
|
|
1418
1466
|
handleSessionsCount: (res: ServerResponse) => void;
|
|
@@ -1533,6 +1581,7 @@ declare class PTYManager implements SessionRunner {
|
|
|
1533
1581
|
private chunkIndex;
|
|
1534
1582
|
private lastChunkAt;
|
|
1535
1583
|
private quietCheckers;
|
|
1584
|
+
private readyFallbackTimers;
|
|
1536
1585
|
private startPromises;
|
|
1537
1586
|
constructor(options?: PTYManagerOptions);
|
|
1538
1587
|
start(sessionId: string, options: StartSessionOptions): Promise<ManagedSession>;
|
|
@@ -1558,6 +1607,8 @@ declare class PTYManager implements SessionRunner {
|
|
|
1558
1607
|
private detectLivePrompts;
|
|
1559
1608
|
private handleQuiet;
|
|
1560
1609
|
private recheckReadyFromScreen;
|
|
1610
|
+
private armReadyFallback;
|
|
1611
|
+
private clearReadyFallback;
|
|
1561
1612
|
private markReady;
|
|
1562
1613
|
private handleExit;
|
|
1563
1614
|
}
|
|
@@ -1632,6 +1683,7 @@ declare class StreamerServer {
|
|
|
1632
1683
|
private conversationsRepo;
|
|
1633
1684
|
private sessionsRepo;
|
|
1634
1685
|
private managedSessionsRepo;
|
|
1686
|
+
private runtimeStore;
|
|
1635
1687
|
private readonly streamerInstanceId;
|
|
1636
1688
|
private cacheMetadataRepo;
|
|
1637
1689
|
private pushRepo;
|
|
@@ -1641,6 +1693,7 @@ declare class StreamerServer {
|
|
|
1641
1693
|
private liveActivityRenewal;
|
|
1642
1694
|
private discoveryCache;
|
|
1643
1695
|
private cacheDir;
|
|
1696
|
+
private runtimeDbPath;
|
|
1644
1697
|
private tailSize;
|
|
1645
1698
|
private directoryDebounceMs;
|
|
1646
1699
|
private markScannerStaleDebounced;
|
|
@@ -1702,6 +1755,22 @@ declare class StreamerServer {
|
|
|
1702
1755
|
* signals anything. `orphaned` is a report, not a cleanup trigger.
|
|
1703
1756
|
*/
|
|
1704
1757
|
private reconcilePreviousSessions;
|
|
1758
|
+
/**
|
|
1759
|
+
* Seed the session list with what previous runs left behind (persistence plan
|
|
1760
|
+
* Phase 1, gaps G1/G2/G8).
|
|
1761
|
+
*
|
|
1762
|
+
* Reconciliation classifies rows and stops there; a verdict is overlaid onto a
|
|
1763
|
+
* SessionResponse that already exists, and after a clean restart none does —
|
|
1764
|
+
* `SessionStore` starts empty. So the user's session did not become
|
|
1765
|
+
* `resumable`, it became *absent*. This is the half that puts it back.
|
|
1766
|
+
*
|
|
1767
|
+
* The seeded stubs hold no PTY and are never handed to `LiveSessionManager`,
|
|
1768
|
+
* so `reapIdleSessions` and `startGraceTimer` — both of which iterate
|
|
1769
|
+
* `ptyManager.listSessions()` — cannot observe them. A later resume calls
|
|
1770
|
+
* `sessionStore.addManaged` with the real session, which overwrites the stub
|
|
1771
|
+
* by id rather than duplicating it.
|
|
1772
|
+
*/
|
|
1773
|
+
private rehydratePreviousSessions;
|
|
1705
1774
|
/**
|
|
1706
1775
|
* Pick a token guaranteed to appear in the spawned process's argv, for the
|
|
1707
1776
|
* reconciler's pid-reuse guard.
|
package/dist/index.d.ts
CHANGED
|
@@ -182,6 +182,16 @@ interface ManagedSession {
|
|
|
182
182
|
statusUpdatedAt?: Date;
|
|
183
183
|
filePath?: string;
|
|
184
184
|
resumedFromConversationId?: string;
|
|
185
|
+
/**
|
|
186
|
+
* This session was seeded from the durable registry at boot, not spawned by
|
|
187
|
+
* this run — there is no PTY behind it and never was one in this process.
|
|
188
|
+
*
|
|
189
|
+
* INTERNAL. It never reaches the wire: `managedToResponse` translates it into
|
|
190
|
+
* the already-defined `ownership: "historical"` + `lifecycle: "resumable"`
|
|
191
|
+
* pair, so no client needs to learn a new field to render a recovered session.
|
|
192
|
+
* Cleared implicitly when a resume overwrites the stub with a real session.
|
|
193
|
+
*/
|
|
194
|
+
rehydrated?: boolean;
|
|
185
195
|
/**
|
|
186
196
|
* Set once a live session's underlying persisted conversation file is
|
|
187
197
|
* discovered after the fact (currently: fresh Codex sessions, whose
|
|
@@ -501,6 +511,7 @@ interface ServerConfig {
|
|
|
501
511
|
skipStartupWarmup?: boolean;
|
|
502
512
|
ptyGracePeriodMs?: number;
|
|
503
513
|
cacheDir?: string;
|
|
514
|
+
runtimeDbPath?: string;
|
|
504
515
|
tailSize?: number;
|
|
505
516
|
directoryScanDebounceMs?: number;
|
|
506
517
|
defaultSystemPrompt?: string;
|
|
@@ -1251,6 +1262,41 @@ declare class SessionsRepository {
|
|
|
1251
1262
|
listManagedSessions(): ManagedSession[];
|
|
1252
1263
|
}
|
|
1253
1264
|
|
|
1265
|
+
/**
|
|
1266
|
+
* `~/.threadbase/runtime.db` — the authoritative, non-derived half of the
|
|
1267
|
+
* streamer's SQLite state.
|
|
1268
|
+
*
|
|
1269
|
+
* Deliberately a separate file from `cache/cache.db`, and deliberately not
|
|
1270
|
+
* under `cache/`. The conversation cache is rebuildable from the provider
|
|
1271
|
+
* JSONLs at any time, which is why "delete the cache and restart" is reasonable
|
|
1272
|
+
* support advice and why the integrity monitor offers a reset-and-rescan
|
|
1273
|
+
* action. The managed-session registry is not rebuildable from anything on
|
|
1274
|
+
* disk, so it must not sit one plausible instruction away from deletion — nor
|
|
1275
|
+
* share a handle whose failure (a better-sqlite3 ABI mismatch, most commonly)
|
|
1276
|
+
* would silently disable session persistence along with the cache.
|
|
1277
|
+
*
|
|
1278
|
+
* Runs its own migrations from `src/db/runtime-migrations/`, tracked in this
|
|
1279
|
+
* file's own `schema_migrations` table.
|
|
1280
|
+
*/
|
|
1281
|
+
declare class RuntimeStore {
|
|
1282
|
+
private readonly db;
|
|
1283
|
+
private constructor();
|
|
1284
|
+
static open(dbPath: string, migrationsDir?: string): RuntimeStore;
|
|
1285
|
+
getDatabase(): Database.Database;
|
|
1286
|
+
/**
|
|
1287
|
+
* One-time move of `managed_sessions` rows out of a pre-split `cache.db`.
|
|
1288
|
+
*
|
|
1289
|
+
* Non-destructive by design: the source table is left in place so an older
|
|
1290
|
+
* streamer rolled back onto the same machine still finds its registry. Runs
|
|
1291
|
+
* only when this file's table is empty, so a second boot is a no-op rather
|
|
1292
|
+
* than a re-copy that would resurrect rows deleted since.
|
|
1293
|
+
*
|
|
1294
|
+
* Returns the number of rows copied.
|
|
1295
|
+
*/
|
|
1296
|
+
importLegacyManagedSessions(source: Database.Database): number;
|
|
1297
|
+
close(): void;
|
|
1298
|
+
}
|
|
1299
|
+
|
|
1254
1300
|
declare class LiveSessionManager {
|
|
1255
1301
|
private runners;
|
|
1256
1302
|
constructor(options?: PTYManagerOptions);
|
|
@@ -1413,6 +1459,8 @@ type ApiDeps = {
|
|
|
1413
1459
|
conversationsRepo: () => ConversationsRepository | null;
|
|
1414
1460
|
sessionsRepo: () => SessionsRepository | null;
|
|
1415
1461
|
cacheMetadataRepo: () => CacheMetadataRepository | null;
|
|
1462
|
+
/** Authoritative session registry (~/.threadbase/runtime.db). Null when it failed to open. */
|
|
1463
|
+
runtimeStore: () => RuntimeStore | null;
|
|
1416
1464
|
ptyAttachedIds: () => Set<string>;
|
|
1417
1465
|
handleListSessions: (url: URL, res: ServerResponse) => Promise<void>;
|
|
1418
1466
|
handleSessionsCount: (res: ServerResponse) => void;
|
|
@@ -1533,6 +1581,7 @@ declare class PTYManager implements SessionRunner {
|
|
|
1533
1581
|
private chunkIndex;
|
|
1534
1582
|
private lastChunkAt;
|
|
1535
1583
|
private quietCheckers;
|
|
1584
|
+
private readyFallbackTimers;
|
|
1536
1585
|
private startPromises;
|
|
1537
1586
|
constructor(options?: PTYManagerOptions);
|
|
1538
1587
|
start(sessionId: string, options: StartSessionOptions): Promise<ManagedSession>;
|
|
@@ -1558,6 +1607,8 @@ declare class PTYManager implements SessionRunner {
|
|
|
1558
1607
|
private detectLivePrompts;
|
|
1559
1608
|
private handleQuiet;
|
|
1560
1609
|
private recheckReadyFromScreen;
|
|
1610
|
+
private armReadyFallback;
|
|
1611
|
+
private clearReadyFallback;
|
|
1561
1612
|
private markReady;
|
|
1562
1613
|
private handleExit;
|
|
1563
1614
|
}
|
|
@@ -1632,6 +1683,7 @@ declare class StreamerServer {
|
|
|
1632
1683
|
private conversationsRepo;
|
|
1633
1684
|
private sessionsRepo;
|
|
1634
1685
|
private managedSessionsRepo;
|
|
1686
|
+
private runtimeStore;
|
|
1635
1687
|
private readonly streamerInstanceId;
|
|
1636
1688
|
private cacheMetadataRepo;
|
|
1637
1689
|
private pushRepo;
|
|
@@ -1641,6 +1693,7 @@ declare class StreamerServer {
|
|
|
1641
1693
|
private liveActivityRenewal;
|
|
1642
1694
|
private discoveryCache;
|
|
1643
1695
|
private cacheDir;
|
|
1696
|
+
private runtimeDbPath;
|
|
1644
1697
|
private tailSize;
|
|
1645
1698
|
private directoryDebounceMs;
|
|
1646
1699
|
private markScannerStaleDebounced;
|
|
@@ -1702,6 +1755,22 @@ declare class StreamerServer {
|
|
|
1702
1755
|
* signals anything. `orphaned` is a report, not a cleanup trigger.
|
|
1703
1756
|
*/
|
|
1704
1757
|
private reconcilePreviousSessions;
|
|
1758
|
+
/**
|
|
1759
|
+
* Seed the session list with what previous runs left behind (persistence plan
|
|
1760
|
+
* Phase 1, gaps G1/G2/G8).
|
|
1761
|
+
*
|
|
1762
|
+
* Reconciliation classifies rows and stops there; a verdict is overlaid onto a
|
|
1763
|
+
* SessionResponse that already exists, and after a clean restart none does —
|
|
1764
|
+
* `SessionStore` starts empty. So the user's session did not become
|
|
1765
|
+
* `resumable`, it became *absent*. This is the half that puts it back.
|
|
1766
|
+
*
|
|
1767
|
+
* The seeded stubs hold no PTY and are never handed to `LiveSessionManager`,
|
|
1768
|
+
* so `reapIdleSessions` and `startGraceTimer` — both of which iterate
|
|
1769
|
+
* `ptyManager.listSessions()` — cannot observe them. A later resume calls
|
|
1770
|
+
* `sessionStore.addManaged` with the real session, which overwrites the stub
|
|
1771
|
+
* by id rather than duplicating it.
|
|
1772
|
+
*/
|
|
1773
|
+
private rehydratePreviousSessions;
|
|
1705
1774
|
/**
|
|
1706
1775
|
* Pick a token guaranteed to appear in the spawned process's argv, for the
|
|
1707
1776
|
* reconciler's pid-reuse guard.
|