@threadbase-sh/streamer 1.62.0 → 1.64.0
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/agent/agent-client.d.ts +14 -0
- package/dist/agent/agent-client.d.ts.map +1 -0
- package/dist/agent/agent-config.d.ts +24 -0
- package/dist/agent/agent-config.d.ts.map +1 -0
- package/dist/agent/conversation-writer.d.ts +13 -0
- package/dist/agent/conversation-writer.d.ts.map +1 -0
- package/dist/agent/dedupe.d.ts +6 -0
- package/dist/agent/dedupe.d.ts.map +1 -0
- package/dist/agent/errors.d.ts +23 -0
- package/dist/agent/errors.d.ts.map +1 -0
- package/dist/agent/handle-send-agent-input.d.ts +21 -0
- package/dist/agent/handle-send-agent-input.d.ts.map +1 -0
- package/dist/agent/handle-start-agent-session.d.ts +21 -0
- package/dist/agent/handle-start-agent-session.d.ts.map +1 -0
- package/dist/agent/history-mapper.d.ts +4 -0
- package/dist/agent/history-mapper.d.ts.map +1 -0
- package/dist/agent/payload-guard.d.ts +29 -0
- package/dist/agent/payload-guard.d.ts.map +1 -0
- package/dist/api/app.d.ts +28 -0
- package/dist/api/app.d.ts.map +1 -0
- package/dist/api/handlers/conversations.handlers.d.ts +69 -0
- package/dist/api/handlers/conversations.handlers.d.ts.map +1 -0
- package/dist/api/handlers/http-helpers.d.ts +50 -0
- package/dist/api/handlers/http-helpers.d.ts.map +1 -0
- package/dist/api/handlers/sessions.handlers.d.ts +230 -0
- package/dist/api/handlers/sessions.handlers.d.ts.map +1 -0
- package/dist/api/middleware/auth.middleware.d.ts +5 -0
- package/dist/api/middleware/auth.middleware.d.ts.map +1 -0
- package/dist/api/middleware/cors.middleware.d.ts +5 -0
- package/dist/api/middleware/cors.middleware.d.ts.map +1 -0
- package/dist/api/middleware/error.middleware.d.ts +4 -0
- package/dist/api/middleware/error.middleware.d.ts.map +1 -0
- package/dist/api/routes/backup.routes.d.ts +5 -0
- package/dist/api/routes/backup.routes.d.ts.map +1 -0
- package/dist/api/routes/browse.routes.d.ts +5 -0
- package/dist/api/routes/browse.routes.d.ts.map +1 -0
- package/dist/api/routes/cacheAlert.routes.d.ts +5 -0
- package/dist/api/routes/cacheAlert.routes.d.ts.map +1 -0
- package/dist/api/routes/config.routes.d.ts +5 -0
- package/dist/api/routes/config.routes.d.ts.map +1 -0
- package/dist/api/routes/conversations.routes.d.ts +5 -0
- package/dist/api/routes/conversations.routes.d.ts.map +1 -0
- package/dist/api/routes/devices.routes.d.ts +17 -0
- package/dist/api/routes/devices.routes.d.ts.map +1 -0
- package/dist/api/routes/diagnostics.routes.d.ts +5 -0
- package/dist/api/routes/diagnostics.routes.d.ts.map +1 -0
- package/dist/api/routes/health.routes.d.ts +5 -0
- package/dist/api/routes/health.routes.d.ts.map +1 -0
- package/dist/api/routes/logs.routes.d.ts +3 -0
- package/dist/api/routes/logs.routes.d.ts.map +1 -0
- package/dist/api/routes/misc.routes.d.ts +77 -0
- package/dist/api/routes/misc.routes.d.ts.map +1 -0
- package/dist/api/routes/pair.routes.d.ts +5 -0
- package/dist/api/routes/pair.routes.d.ts.map +1 -0
- package/dist/api/routes/progress.routes.d.ts +39 -0
- package/dist/api/routes/progress.routes.d.ts.map +1 -0
- package/dist/api/routes/projects.routes.d.ts +5 -0
- package/dist/api/routes/projects.routes.d.ts.map +1 -0
- package/dist/api/routes/providers.routes.d.ts +19 -0
- package/dist/api/routes/providers.routes.d.ts.map +1 -0
- package/dist/api/routes/scanner.routes.d.ts +5 -0
- package/dist/api/routes/scanner.routes.d.ts.map +1 -0
- package/dist/api/routes/sessions.routes.d.ts +6 -0
- package/dist/api/routes/sessions.routes.d.ts.map +1 -0
- package/dist/api/routes/ws.routes.d.ts +7 -0
- package/dist/api/routes/ws.routes.d.ts.map +1 -0
- package/dist/api/types/api-deps.d.ts +114 -0
- package/dist/api/types/api-deps.d.ts.map +1 -0
- package/dist/auth.d.ts +81 -0
- package/dist/auth.d.ts.map +1 -0
- package/dist/browse.d.ts +17 -0
- package/dist/browse.d.ts.map +1 -0
- package/dist/claude-flags.d.ts +76 -0
- package/dist/claude-flags.d.ts.map +1 -0
- package/dist/cli.cjs +1917 -1795
- package/dist/cli.cjs.map +1 -1
- package/dist/codex-pty-runner.d.ts +90 -0
- package/dist/codex-pty-runner.d.ts.map +1 -0
- package/dist/config/update-config.d.ts +13 -0
- package/dist/config/update-config.d.ts.map +1 -0
- package/dist/conversation-cache.d.ts +336 -0
- package/dist/conversation-cache.d.ts.map +1 -0
- package/dist/db/config.d.ts +11 -0
- package/dist/db/config.d.ts.map +1 -0
- package/dist/db/index.d.ts +5 -0
- package/dist/db/index.d.ts.map +1 -0
- package/dist/db/migrations.d.ts +3 -0
- package/dist/db/migrations.d.ts.map +1 -0
- package/dist/db/pool.d.ts +5 -0
- package/dist/db/pool.d.ts.map +1 -0
- package/dist/db/query-timing.d.ts +52 -0
- package/dist/db/query-timing.d.ts.map +1 -0
- package/dist/db/repositories/cacheMetadata.repository.d.ts +12 -0
- package/dist/db/repositories/cacheMetadata.repository.d.ts.map +1 -0
- package/dist/db/repositories/conversations.repository.d.ts +27 -0
- package/dist/db/repositories/conversations.repository.d.ts.map +1 -0
- package/dist/db/repositories/devices.repository.d.ts +137 -0
- package/dist/db/repositories/devices.repository.d.ts.map +1 -0
- package/dist/db/repositories/managed-sessions.repository.d.ts +127 -0
- package/dist/db/repositories/managed-sessions.repository.d.ts.map +1 -0
- package/dist/db/repositories/projects.repository.d.ts +28 -0
- package/dist/db/repositories/projects.repository.d.ts.map +1 -0
- package/dist/db/repositories/push.repository.d.ts +186 -0
- package/dist/db/repositories/push.repository.d.ts.map +1 -0
- package/dist/db/repositories/sessions.repository.d.ts +16 -0
- package/dist/db/repositories/sessions.repository.d.ts.map +1 -0
- package/dist/db/runtime-store.d.ts +80 -0
- package/dist/db/runtime-store.d.ts.map +1 -0
- package/dist/db/sqlite-migrate.d.ts +13 -0
- package/dist/db/sqlite-migrate.d.ts.map +1 -0
- package/dist/db/upload-records.d.ts +11 -0
- package/dist/db/upload-records.d.ts.map +1 -0
- package/dist/e2ee/noise.d.ts +261 -0
- package/dist/e2ee/noise.d.ts.map +1 -0
- package/dist/e2ee/pair-payload.d.ts +60 -0
- package/dist/e2ee/pair-payload.d.ts.map +1 -0
- package/dist/e2ee/pair-request.d.ts +24 -0
- package/dist/e2ee/pair-request.d.ts.map +1 -0
- package/dist/external-tails.d.ts +91 -0
- package/dist/external-tails.d.ts.map +1 -0
- package/dist/feature-flags.d.ts +212 -0
- package/dist/feature-flags.d.ts.map +1 -0
- package/dist/handlers/handleListProjects.d.ts +3 -0
- package/dist/handlers/handleListProjects.d.ts.map +1 -0
- package/dist/index.cjs +84 -15
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +18 -2571
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +84 -15
- package/dist/index.js.map +1 -1
- package/dist/lifecycle/constants.d.ts +21 -0
- package/dist/lifecycle/constants.d.ts.map +1 -0
- package/dist/lifecycle/process-liveness.d.ts +7 -0
- package/dist/lifecycle/process-liveness.d.ts.map +1 -0
- package/dist/live-session-manager.d.ts +59 -0
- package/dist/live-session-manager.d.ts.map +1 -0
- package/dist/logger.d.ts +14 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/pair-store.d.ts +60 -0
- package/dist/pair-store.d.ts.map +1 -0
- package/dist/platform.d.ts +25 -0
- package/dist/platform.d.ts.map +1 -0
- package/dist/process-discovery.d.ts +35 -0
- package/dist/process-discovery.d.ts.map +1 -0
- package/dist/providers.d.ts +7 -0
- package/dist/providers.d.ts.map +1 -0
- package/dist/pty-host/protocol.d.ts +270 -0
- package/dist/pty-host/protocol.d.ts.map +1 -0
- package/dist/pty-host/remote-session-runner.d.ts +133 -0
- package/dist/pty-host/remote-session-runner.d.ts.map +1 -0
- package/dist/pty-host/socket.d.ts +54 -0
- package/dist/pty-host/socket.d.ts.map +1 -0
- package/dist/pty-host/spawn-host.d.ts +30 -0
- package/dist/pty-host/spawn-host.d.ts.map +1 -0
- package/dist/pty-manager.d.ts +65 -0
- package/dist/pty-manager.d.ts.map +1 -0
- package/dist/pty-shared.d.ts +27 -0
- package/dist/pty-shared.d.ts.map +1 -0
- package/dist/scanner-manager.d.ts +126 -0
- package/dist/scanner-manager.d.ts.map +1 -0
- package/dist/schemas/cacheAlert.schema.d.ts +14 -0
- package/dist/schemas/cacheAlert.schema.d.ts.map +1 -0
- package/dist/schemas/claudeFlags.schema.d.ts +7 -0
- package/dist/schemas/claudeFlags.schema.d.ts.map +1 -0
- package/dist/schemas/project.schema.d.ts +18 -0
- package/dist/schemas/project.schema.d.ts.map +1 -0
- package/dist/schemas/updateConfig.schema.d.ts +19 -0
- package/dist/schemas/updateConfig.schema.d.ts.map +1 -0
- package/dist/seal.d.ts +14 -0
- package/dist/seal.d.ts.map +1 -0
- package/dist/server-identity.d.ts +43 -0
- package/dist/server-identity.d.ts.map +1 -0
- package/dist/server-wiring.d.ts +184 -0
- package/dist/server-wiring.d.ts.map +1 -0
- package/dist/server.d.ts +390 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/services/backup/backup.d.ts +103 -0
- package/dist/services/backup/backup.d.ts.map +1 -0
- package/dist/services/cache/cacheMetadata.d.ts +8 -0
- package/dist/services/cache/cacheMetadata.d.ts.map +1 -0
- package/dist/services/cache-integrity/alertStore.d.ts +24 -0
- package/dist/services/cache-integrity/alertStore.d.ts.map +1 -0
- package/dist/services/cache-integrity/backup.d.ts +8 -0
- package/dist/services/cache-integrity/backup.d.ts.map +1 -0
- package/dist/services/cache-integrity/cacheIntegrityMonitor.d.ts +71 -0
- package/dist/services/cache-integrity/cacheIntegrityMonitor.d.ts.map +1 -0
- package/dist/services/conversations/conversationWatcher.d.ts +99 -0
- package/dist/services/conversations/conversationWatcher.d.ts.map +1 -0
- package/dist/services/conversations/findSearchTarget.d.ts +30 -0
- package/dist/services/conversations/findSearchTarget.d.ts.map +1 -0
- package/dist/services/conversations/isAgentConversation.d.ts +8 -0
- package/dist/services/conversations/isAgentConversation.d.ts.map +1 -0
- package/dist/services/conversations/pruneAgentConversations.d.ts +8 -0
- package/dist/services/conversations/pruneAgentConversations.d.ts.map +1 -0
- package/dist/services/conversations/refreshConversationCache.d.ts +27 -0
- package/dist/services/conversations/refreshConversationCache.d.ts.map +1 -0
- package/dist/services/conversations/shouldRefreshProjectsFromHdd.d.ts +33 -0
- package/dist/services/conversations/shouldRefreshProjectsFromHdd.d.ts.map +1 -0
- package/dist/services/diagnostics/diagnostics.d.ts +66 -0
- package/dist/services/diagnostics/diagnostics.d.ts.map +1 -0
- package/dist/services/projectChats/deriveProjectChatTitle.d.ts +15 -0
- package/dist/services/projectChats/deriveProjectChatTitle.d.ts.map +1 -0
- package/dist/services/projects/ensureProjectsForConversations.d.ts +15 -0
- package/dist/services/projects/ensureProjectsForConversations.d.ts.map +1 -0
- package/dist/services/providers/capabilities.d.ts +105 -0
- package/dist/services/providers/capabilities.d.ts.map +1 -0
- package/dist/services/providers/providerHealth.d.ts +72 -0
- package/dist/services/providers/providerHealth.d.ts.map +1 -0
- package/dist/services/push/apnsClient.d.ts +105 -0
- package/dist/services/push/apnsClient.d.ts.map +1 -0
- package/dist/services/push/expoPushSender.d.ts +37 -0
- package/dist/services/push/expoPushSender.d.ts.map +1 -0
- package/dist/services/push/liveActivityContentState.d.ts +60 -0
- package/dist/services/push/liveActivityContentState.d.ts.map +1 -0
- package/dist/services/push/liveActivityNotifier.d.ts +49 -0
- package/dist/services/push/liveActivityNotifier.d.ts.map +1 -0
- package/dist/services/push/liveActivityRenewal.d.ts +63 -0
- package/dist/services/push/liveActivityRenewal.d.ts.map +1 -0
- package/dist/services/push/liveActivitySender.d.ts +88 -0
- package/dist/services/push/liveActivitySender.d.ts.map +1 -0
- package/dist/services/push/waitingInputNotifier.d.ts +41 -0
- package/dist/services/push/waitingInputNotifier.d.ts.map +1 -0
- package/dist/services/questions/answersToKeystrokes.d.ts +8 -0
- package/dist/services/questions/answersToKeystrokes.d.ts.map +1 -0
- package/dist/services/questions/codexGateAnswers.d.ts +14 -0
- package/dist/services/questions/codexGateAnswers.d.ts.map +1 -0
- package/dist/services/questions/codexScreen.d.ts +74 -0
- package/dist/services/questions/codexScreen.d.ts.map +1 -0
- package/dist/services/questions/detectAskUserQuestion.d.ts +6 -0
- package/dist/services/questions/detectAskUserQuestion.d.ts.map +1 -0
- package/dist/services/questions/detectPermissionGate.d.ts +62 -0
- package/dist/services/questions/detectPermissionGate.d.ts.map +1 -0
- package/dist/services/questions/detectQuestionFromScreen.d.ts +30 -0
- package/dist/services/questions/detectQuestionFromScreen.d.ts.map +1 -0
- package/dist/services/questions/detectShellPrompt.d.ts +18 -0
- package/dist/services/questions/detectShellPrompt.d.ts.map +1 -0
- package/dist/services/questions/parseAgentPhase.d.ts +12 -0
- package/dist/services/questions/parseAgentPhase.d.ts.map +1 -0
- package/dist/services/questions/parseStatusLine.d.ts +19 -0
- package/dist/services/questions/parseStatusLine.d.ts.map +1 -0
- package/dist/services/questions/questionBroadcast.d.ts +18 -0
- package/dist/services/questions/questionBroadcast.d.ts.map +1 -0
- package/dist/services/questions/resolveAnswer.d.ts +16 -0
- package/dist/services/questions/resolveAnswer.d.ts.map +1 -0
- package/dist/services/search/searchQuery.d.ts +78 -0
- package/dist/services/search/searchQuery.d.ts.map +1 -0
- package/dist/services/security/capabilities.d.ts +50 -0
- package/dist/services/security/capabilities.d.ts.map +1 -0
- package/dist/services/sessions/autoResumeOnBoot.d.ts +28 -0
- package/dist/services/sessions/autoResumeOnBoot.d.ts.map +1 -0
- package/dist/services/sessions/codexRolloutOwner.d.ts +55 -0
- package/dist/services/sessions/codexRolloutOwner.d.ts.map +1 -0
- package/dist/services/sessions/conversationBusy.d.ts +32 -0
- package/dist/services/sessions/conversationBusy.d.ts.map +1 -0
- package/dist/services/sessions/idempotency.d.ts +67 -0
- package/dist/services/sessions/idempotency.d.ts.map +1 -0
- package/dist/services/sessions/reconcileSessions.d.ts +63 -0
- package/dist/services/sessions/reconcileSessions.d.ts.map +1 -0
- package/dist/services/sessions/rehydrateSessions.d.ts +68 -0
- package/dist/services/sessions/rehydrateSessions.d.ts.map +1 -0
- package/dist/services/sessions/resumeIdentity.d.ts +16 -0
- package/dist/services/sessions/resumeIdentity.d.ts.map +1 -0
- package/dist/session-registry-boot.d.ts +142 -0
- package/dist/session-registry-boot.d.ts.map +1 -0
- package/dist/session-store.d.ts +32 -0
- package/dist/session-store.d.ts.map +1 -0
- package/dist/session-watchers.d.ts +60 -0
- package/dist/session-watchers.d.ts.map +1 -0
- package/dist/types.d.ts +616 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/uploads.d.ts +16 -0
- package/dist/uploads.d.ts.map +1 -0
- package/dist/utils/bootToken.d.ts +3 -0
- package/dist/utils/bootToken.d.ts.map +1 -0
- package/dist/utils/canonicalizeFilePath.d.ts +75 -0
- package/dist/utils/canonicalizeFilePath.d.ts.map +1 -0
- package/dist/utils/canonicalizeProjectPath.d.ts +13 -0
- package/dist/utils/canonicalizeProjectPath.d.ts.map +1 -0
- package/dist/utils/codexConversationLine.d.ts +38 -0
- package/dist/utils/codexConversationLine.d.ts.map +1 -0
- package/dist/utils/conversationEtag.d.ts +19 -0
- package/dist/utils/conversationEtag.d.ts.map +1 -0
- package/dist/utils/dates.d.ts +12 -0
- package/dist/utils/dates.d.ts.map +1 -0
- package/dist/utils/debounce.d.ts +15 -0
- package/dist/utils/debounce.d.ts.map +1 -0
- package/dist/utils/deriveSessionName.d.ts +10 -0
- package/dist/utils/deriveSessionName.d.ts.map +1 -0
- package/dist/utils/fileIdentity.d.ts +36 -0
- package/dist/utils/fileIdentity.d.ts.map +1 -0
- package/dist/utils/isScannedSnapshotStale.d.ts +16 -0
- package/dist/utils/isScannedSnapshotStale.d.ts.map +1 -0
- package/dist/utils/scanProgressThrottle.d.ts +12 -0
- package/dist/utils/scanProgressThrottle.d.ts.map +1 -0
- package/dist/version.d.ts +3 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/ws-hub.d.ts +15 -0
- package/dist/ws-hub.d.ts.map +1 -0
- package/package.json +3 -4
- package/dist/index.d.cts +0 -2571
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Metadata export and restore (C9).
|
|
3
|
+
*
|
|
4
|
+
* Threadbase owns very little durable state, and knowing exactly which parts
|
|
5
|
+
* matter is the whole design:
|
|
6
|
+
*
|
|
7
|
+
* - **Provider history** (`~/.claude/projects/*.jsonl`, Codex rollouts) is the
|
|
8
|
+
* authoritative record of every conversation, and it is NOT ours. It is
|
|
9
|
+
* written by the provider CLIs and survives independently of this server.
|
|
10
|
+
* Exporting it would duplicate gigabytes of data the user already has, in a
|
|
11
|
+
* format we do not control.
|
|
12
|
+
* - **Threadbase metadata** (the `projects` table: stable project ids,
|
|
13
|
+
* names, and their mapping to paths) is ours, is small, and cannot be
|
|
14
|
+
* reconstructed — a fresh scan invents new project ids, breaking every
|
|
15
|
+
* deep link and per-project setting that referenced the old ones.
|
|
16
|
+
* - **The cache** (conversation metadata, tails, offset index) is derived
|
|
17
|
+
* entirely from provider history and is rebuilt by scanning. Exporting it
|
|
18
|
+
* would bloat a backup with data that regenerates itself.
|
|
19
|
+
*
|
|
20
|
+
* So an export carries metadata only, and the restore path is explicit that
|
|
21
|
+
* conversations come back by rescanning provider history rather than from the
|
|
22
|
+
* archive.
|
|
23
|
+
*
|
|
24
|
+
* Credentials are never exported by default. The API key is a live credential
|
|
25
|
+
* whose disclosure grants full control of the server; a backup file gets copied
|
|
26
|
+
* to cloud storage, pasted into issues, and emailed around.
|
|
27
|
+
*/
|
|
28
|
+
export declare const BACKUP_FORMAT_VERSION = 1;
|
|
29
|
+
export interface BackupProject {
|
|
30
|
+
id: string;
|
|
31
|
+
path: string;
|
|
32
|
+
name: string | null;
|
|
33
|
+
createdAt: string;
|
|
34
|
+
updatedAt: string;
|
|
35
|
+
}
|
|
36
|
+
export interface BackupManifest {
|
|
37
|
+
formatVersion: number;
|
|
38
|
+
createdAt: string;
|
|
39
|
+
streamerVersion: string;
|
|
40
|
+
/** Identity of the machine this was taken from, for path-remap decisions. */
|
|
41
|
+
sourceHost: string;
|
|
42
|
+
/**
|
|
43
|
+
* True when the operator explicitly opted into including secrets. Recorded so
|
|
44
|
+
* a restore can warn, and so an archive's sensitivity is self-describing
|
|
45
|
+
* rather than inferred.
|
|
46
|
+
*/
|
|
47
|
+
includesSecrets: boolean;
|
|
48
|
+
counts: {
|
|
49
|
+
projects: number;
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
export interface BackupArchive {
|
|
53
|
+
manifest: BackupManifest;
|
|
54
|
+
projects: BackupProject[];
|
|
55
|
+
}
|
|
56
|
+
export declare class BackupError extends Error {
|
|
57
|
+
readonly code: string;
|
|
58
|
+
constructor(message: string, code: string);
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Validate an archive before any of it is applied.
|
|
62
|
+
*
|
|
63
|
+
* Restore is destructive in the sense that it rewrites project identity, so a
|
|
64
|
+
* malformed archive must be rejected whole rather than applied halfway. This
|
|
65
|
+
* checks shape and version up front; the caller applies inside a transaction.
|
|
66
|
+
*/
|
|
67
|
+
export declare function validateArchive(input: unknown): BackupArchive;
|
|
68
|
+
/**
|
|
69
|
+
* Rewrite project paths from one machine's layout to another's.
|
|
70
|
+
*
|
|
71
|
+
* A backup restored onto a different machine — or the same machine after a home
|
|
72
|
+
* directory move — carries paths that no longer exist. Without remapping, every
|
|
73
|
+
* project points at nothing and the restore is useless.
|
|
74
|
+
*
|
|
75
|
+
* Longest-prefix wins, so a more specific rule beats a general one. Paths that
|
|
76
|
+
* match no rule are left untouched rather than mangled.
|
|
77
|
+
*/
|
|
78
|
+
export declare function remapPaths(projects: BackupProject[], rules: ReadonlyArray<{
|
|
79
|
+
from: string;
|
|
80
|
+
to: string;
|
|
81
|
+
}>): BackupProject[];
|
|
82
|
+
/**
|
|
83
|
+
* Classify how each incoming project relates to what already exists.
|
|
84
|
+
*
|
|
85
|
+
* Returned rather than applied so the caller can show the user what a restore
|
|
86
|
+
* would do before doing it — a restore that silently rewrites project identity
|
|
87
|
+
* is one the user cannot review.
|
|
88
|
+
*/
|
|
89
|
+
export interface RestorePlan {
|
|
90
|
+
create: BackupProject[];
|
|
91
|
+
/** Same id, different path — the machine-move case. */
|
|
92
|
+
update: BackupProject[];
|
|
93
|
+
/** Path already claimed by a DIFFERENT id. Requires an explicit decision. */
|
|
94
|
+
conflict: Array<{
|
|
95
|
+
incoming: BackupProject;
|
|
96
|
+
existingId: string;
|
|
97
|
+
}>;
|
|
98
|
+
}
|
|
99
|
+
export declare function planRestore(incoming: BackupProject[], existing: ReadonlyArray<{
|
|
100
|
+
id: string;
|
|
101
|
+
path: string;
|
|
102
|
+
}>): RestorePlan;
|
|
103
|
+
//# sourceMappingURL=backup.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"backup.d.ts","sourceRoot":"","sources":["../../../src/services/backup/backup.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,eAAO,MAAM,qBAAqB,IAAI,CAAC;AAEvC,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,cAAc;IAC7B,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,MAAM,CAAC;IACxB,6EAA6E;IAC7E,UAAU,EAAE,MAAM,CAAC;IACnB;;;;OAIG;IACH,eAAe,EAAE,OAAO,CAAC;IACzB,MAAM,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;CAC9B;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,cAAc,CAAC;IACzB,QAAQ,EAAE,aAAa,EAAE,CAAC;CAC3B;AAED,qBAAa,WAAY,SAAQ,KAAK;IAGlC,QAAQ,CAAC,IAAI,EAAE,MAAM;IAFvB,YACE,OAAO,EAAE,MAAM,EACN,IAAI,EAAE,MAAM,EAGtB;CACF;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,aAAa,CA2C7D;AAED;;;;;;;;;GASG;AACH,wBAAgB,UAAU,CACxB,QAAQ,EAAE,aAAa,EAAE,EACzB,KAAK,EAAE,aAAa,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,CAAC,GACjD,aAAa,EAAE,CAOjB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,aAAa,EAAE,CAAC;IACxB,uDAAuD;IACvD,MAAM,EAAE,aAAa,EAAE,CAAC;IACxB,6EAA6E;IAC7E,QAAQ,EAAE,KAAK,CAAC;QAAE,QAAQ,EAAE,aAAa,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAClE;AAED,wBAAgB,WAAW,CACzB,QAAQ,EAAE,aAAa,EAAE,EACzB,QAAQ,EAAE,aAAa,CAAC;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,GACpD,WAAW,CAuBb"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { CacheMetadataKey, CacheMetadataRepository } from "../../db/repositories/cacheMetadata.repository";
|
|
2
|
+
/**
|
|
3
|
+
* Functional accessors over the cache_metadata table. Repositories give us
|
|
4
|
+
* the SQL surface; these helpers give us the verbs the services use.
|
|
5
|
+
*/
|
|
6
|
+
export declare function getCacheMetadata(repo: CacheMetadataRepository, key: CacheMetadataKey): string | null;
|
|
7
|
+
export declare function setCacheMetadata(repo: CacheMetadataRepository, key: CacheMetadataKey, value: string): void;
|
|
8
|
+
//# sourceMappingURL=cacheMetadata.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cacheMetadata.d.ts","sourceRoot":"","sources":["../../../src/services/cache/cacheMetadata.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,gBAAgB,EAChB,uBAAuB,EACxB,MAAM,gDAAgD,CAAC;AAExD;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,uBAAuB,EAC7B,GAAG,EAAE,gBAAgB,GACpB,MAAM,GAAG,IAAI,CAEf;AAED,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,uBAAuB,EAC7B,GAAG,EAAE,gBAAgB,EACrB,KAAK,EAAE,MAAM,GACZ,IAAI,CAEN"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/** One missing conversation the alert covers. */
|
|
2
|
+
export interface MissingEntry {
|
|
3
|
+
id: string;
|
|
4
|
+
filePath: string;
|
|
5
|
+
title: string | null;
|
|
6
|
+
tailed: boolean;
|
|
7
|
+
}
|
|
8
|
+
export interface PendingAlert {
|
|
9
|
+
fingerprint: string;
|
|
10
|
+
severity: "high" | "low";
|
|
11
|
+
detectedAt: string;
|
|
12
|
+
missingCount: number;
|
|
13
|
+
totalRows: number;
|
|
14
|
+
backupPath?: string;
|
|
15
|
+
/** Capped at 1000 entries in the persisted file. */
|
|
16
|
+
missing: MissingEntry[];
|
|
17
|
+
}
|
|
18
|
+
export interface AlertState {
|
|
19
|
+
pending?: PendingAlert;
|
|
20
|
+
ignoredIds?: string[];
|
|
21
|
+
}
|
|
22
|
+
export declare function loadAlertState(): AlertState;
|
|
23
|
+
export declare function saveAlertState(state: AlertState): void;
|
|
24
|
+
//# sourceMappingURL=alertStore.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"alertStore.d.ts","sourceRoot":"","sources":["../../../src/services/cache-integrity/alertStore.ts"],"names":[],"mappings":"AASA,iDAAiD;AACjD,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,YAAY;IAC3B,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,GAAG,KAAK,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,oDAAoD;IACpD,OAAO,EAAE,YAAY,EAAE,CAAC;CACzB;AAED,MAAM,WAAW,UAAU;IACzB,OAAO,CAAC,EAAE,YAAY,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;CACvB;AAOD,wBAAgB,cAAc,IAAI,UAAU,CAO3C;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI,CAItD"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type Database from "better-sqlite3";
|
|
2
|
+
/**
|
|
3
|
+
* Back up the cache DB to `<cacheDir>/backups/cache-<timestamp>.db`, then prune
|
|
4
|
+
* all but the newest THREADBASE_CACHE_BACKUP_RETAIN backups. Returns the path
|
|
5
|
+
* of the backup just created.
|
|
6
|
+
*/
|
|
7
|
+
export declare function backupCacheDb(db: Database.Database, cacheDir: string): Promise<string>;
|
|
8
|
+
//# sourceMappingURL=backup.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"backup.d.ts","sourceRoot":"","sources":["../../../src/services/cache-integrity/backup.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAoB3C;;;;GAIG;AACH,wBAAsB,aAAa,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAoB5F"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import type { ConversationCache, ScannerMeta } from "../../conversation-cache";
|
|
2
|
+
import type { Logger } from "../../logger";
|
|
3
|
+
import type { CacheAlertResolveAction, WSMessage } from "../../types";
|
|
4
|
+
import type { WSHub } from "../../ws-hub";
|
|
5
|
+
import { type PendingAlert } from "./alertStore";
|
|
6
|
+
export type ResolveAction = CacheAlertResolveAction;
|
|
7
|
+
/** The `cache_alert` WS variant, narrowed from the WSMessage union. */
|
|
8
|
+
export type CacheAlertWsMessage = Extract<WSMessage, {
|
|
9
|
+
type: "cache_alert";
|
|
10
|
+
}>;
|
|
11
|
+
export type ResolveResult = {
|
|
12
|
+
ok: true;
|
|
13
|
+
action: ResolveAction;
|
|
14
|
+
pruned?: number;
|
|
15
|
+
backupPath?: string;
|
|
16
|
+
} | {
|
|
17
|
+
alreadyResolved: true;
|
|
18
|
+
} | {
|
|
19
|
+
conflict: true;
|
|
20
|
+
currentFingerprint: string;
|
|
21
|
+
};
|
|
22
|
+
export declare class CacheIntegrityMonitor {
|
|
23
|
+
private readonly cache;
|
|
24
|
+
private readonly wsHub;
|
|
25
|
+
private readonly log;
|
|
26
|
+
private readonly cacheDir;
|
|
27
|
+
private readonly rescan?;
|
|
28
|
+
private readonly runDuringReset?;
|
|
29
|
+
private _pending;
|
|
30
|
+
private ignoredIds;
|
|
31
|
+
private deferredUnlinks;
|
|
32
|
+
private unlinkTimes;
|
|
33
|
+
constructor(cache: ConversationCache, wsHub: WSHub, log: Logger, cacheDir: string, rescan?: (() => Promise<ScannerMeta[]>) | undefined, runDuringReset?: (<T>(operation: () => Promise<T>) => Promise<T>) | undefined);
|
|
34
|
+
get pending(): PendingAlert | null;
|
|
35
|
+
private persist;
|
|
36
|
+
private classifySeverity;
|
|
37
|
+
private sampleOf;
|
|
38
|
+
private buildWsMessage;
|
|
39
|
+
wsMessage(): CacheAlertWsMessage | null;
|
|
40
|
+
healthzField(): {
|
|
41
|
+
severity: "high" | "low";
|
|
42
|
+
missingCount: number;
|
|
43
|
+
fingerprint: string;
|
|
44
|
+
detectedAt: string;
|
|
45
|
+
} | undefined;
|
|
46
|
+
/**
|
|
47
|
+
* Scan the cache for rows whose file is gone, excluding ids the user chose to
|
|
48
|
+
* ignore. If none remain, clear any stale pending alert and return (the caller
|
|
49
|
+
* decides whether to run pruneGhostFiles). Otherwise classify severity, persist
|
|
50
|
+
* the pending record, back up on high severity, and broadcast the alert.
|
|
51
|
+
*/
|
|
52
|
+
runDetection(detectedAt?: string): Promise<void>;
|
|
53
|
+
/** Queue an unlink while an alert is pending — the row is not invalidated. */
|
|
54
|
+
deferUnlink(filePath: string): void;
|
|
55
|
+
/**
|
|
56
|
+
* Record a live unlink while NO alert is pending. Crossing the storm threshold
|
|
57
|
+
* (>= 10 unlinks within 30s) re-triggers detection.
|
|
58
|
+
*/
|
|
59
|
+
recordUnlink(filePath: string): void;
|
|
60
|
+
private ensureBackup;
|
|
61
|
+
private clearPending;
|
|
62
|
+
private applyDeferredUnlinks;
|
|
63
|
+
private broadcastResolved;
|
|
64
|
+
/**
|
|
65
|
+
* Apply the human's chosen resolution. Idempotent per fingerprint: no pending
|
|
66
|
+
* alert → alreadyResolved; a different fingerprint → conflict. See the spec's
|
|
67
|
+
* four-action semantics.
|
|
68
|
+
*/
|
|
69
|
+
resolve(fingerprint: string, action: ResolveAction, ids?: string[]): Promise<ResolveResult>;
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=cacheIntegrityMonitor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cacheIntegrityMonitor.d.ts","sourceRoot":"","sources":["../../../src/services/cache-integrity/cacheIntegrityMonitor.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAC/E,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,KAAK,EAAE,uBAAuB,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACtE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAIL,KAAK,YAAY,EAElB,MAAM,cAAc,CAAC;AAGtB,MAAM,MAAM,aAAa,GAAG,uBAAuB,CAAC;AAEpD,uEAAuE;AACvE,MAAM,MAAM,mBAAmB,GAAG,OAAO,CAAC,SAAS,EAAE;IAAE,IAAI,EAAE,aAAa,CAAA;CAAE,CAAC,CAAC;AAE9E,MAAM,MAAM,aAAa,GACrB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,aAAa,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE,GACzE;IAAE,eAAe,EAAE,IAAI,CAAA;CAAE,GACzB;IAAE,QAAQ,EAAE,IAAI,CAAC;IAAC,kBAAkB,EAAE,MAAM,CAAA;CAAE,CAAC;AAkBnD,qBAAa,qBAAqB;IAO9B,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,GAAG;IACpB,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAGzB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC;IACxB,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAC;IAblC,OAAO,CAAC,QAAQ,CAAsB;IACtC,OAAO,CAAC,UAAU,CAAc;IAChC,OAAO,CAAC,eAAe,CAAgB;IACvC,OAAO,CAAC,WAAW,CAAgB;IAEnC,YACmB,KAAK,EAAE,iBAAiB,EACxB,KAAK,EAAE,KAAK,EACZ,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,MAAM,EAGhB,MAAM,CAAC,GAAE,MAAM,OAAO,CAAC,WAAW,EAAE,CAAC,aAAA,EACrC,cAAc,CAAC,GAAE,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,aAAA,EAKjF;IAED,IAAI,OAAO,IAAI,YAAY,GAAG,IAAI,CAEjC;IAED,OAAO,CAAC,OAAO;IAYf,OAAO,CAAC,gBAAgB;IAQxB,OAAO,CAAC,QAAQ;IAOhB,OAAO,CAAC,cAAc;IAYtB,SAAS,IAAI,mBAAmB,GAAG,IAAI,CAEtC;IAED,YAAY,IACR;QAAE,QAAQ,EAAE,MAAM,GAAG,KAAK,CAAC;QAAC,YAAY,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,GAC3F,SAAS,CAQZ;IAED;;;;;OAKG;IACG,YAAY,CAAC,UAAU,GAAE,MAAiC,GAAG,OAAO,CAAC,IAAI,CAAC,CA8C/E;IAED,8EAA8E;IAC9E,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAElC;IAED;;;OAGG;IACH,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAcnC;YAEa,YAAY;IAa1B,OAAO,CAAC,YAAY;IAMpB,OAAO,CAAC,oBAAoB;IAK5B,OAAO,CAAC,iBAAiB;IAIzB;;;;OAIG;IACG,OAAO,CACX,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,aAAa,EACrB,GAAG,CAAC,EAAE,MAAM,EAAE,GACb,OAAO,CAAC,aAAa,CAAC,CAuFxB;CACF"}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { type LineSpan } from "../../utils/fileIdentity";
|
|
2
|
+
export interface ConversationWatcherEvents {
|
|
3
|
+
/** Fires once per new newline-terminated line appended to a watched file. */
|
|
4
|
+
onNewLine?: (filePath: string, line: string) => void;
|
|
5
|
+
/**
|
|
6
|
+
* Fires once per chokidar read with ALL new lines from that read, batched.
|
|
7
|
+
* When set, it REPLACES the per-line onNewLine dispatch for that file —
|
|
8
|
+
* callers pick one. Lets a burst of appended lines collapse into a single
|
|
9
|
+
* downstream cache write + WebSocket broadcast.
|
|
10
|
+
*/
|
|
11
|
+
onNewLines?: (filePath: string, lines: string[]) => void;
|
|
12
|
+
/**
|
|
13
|
+
* Like onNewLines but also carries each line's absolute byte span in the
|
|
14
|
+
* file (for the offset index). Fires ALONGSIDE onNewLines/onNewLine (it does
|
|
15
|
+
* not replace them) so the cache tail write and the index extend can both
|
|
16
|
+
* consume the same read. `readFrom` is the absolute byte offset the read
|
|
17
|
+
* started at; `spans` are complete lines only (a torn trailing line is held
|
|
18
|
+
* for the next read).
|
|
19
|
+
*/
|
|
20
|
+
onNewLineSpans?: (filePath: string, spans: LineSpan[], readFrom: number, endOffset: number) => void;
|
|
21
|
+
/** Fires when chokidar reports an add/change/unlink at the directory level. */
|
|
22
|
+
onConversationChanged?: (filePath: string) => void | Promise<void>;
|
|
23
|
+
/** Fires when a tailed file is deleted (per-file watcher unlink event). */
|
|
24
|
+
onFileDeleted?: (filePath: string) => void;
|
|
25
|
+
/**
|
|
26
|
+
* Fires when a tailed file shrank below our read offset (in-place truncation
|
|
27
|
+
* or replacement by a shorter file). The tail has already reset to byte 0;
|
|
28
|
+
* the consumer must discard any byte-offset index built for the old content,
|
|
29
|
+
* which no longer describes this file.
|
|
30
|
+
*/
|
|
31
|
+
onTruncated?: (filePath: string) => void;
|
|
32
|
+
/** Reported errors per file. */
|
|
33
|
+
onError?: (filePath: string, error: Error) => void;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Chokidar-backed replacement for src/file-watcher.ts.
|
|
37
|
+
*
|
|
38
|
+
* - watch(filePath) → tail a single JSONL file, emitting onNewLine
|
|
39
|
+
* for each appended line.
|
|
40
|
+
* - watchDirectory(dir) → mark cache dirty on add/change/unlink events
|
|
41
|
+
* for any file inside the directory.
|
|
42
|
+
*
|
|
43
|
+
* Per the refactor plan, file watching is an OPTIMIZATION; correctness
|
|
44
|
+
* still relies on refresh=1 / the latest HDD conversation id check.
|
|
45
|
+
*/
|
|
46
|
+
export declare class ConversationWatcher {
|
|
47
|
+
private files;
|
|
48
|
+
private directories;
|
|
49
|
+
private onNewLine;
|
|
50
|
+
private onNewLines;
|
|
51
|
+
private onNewLineSpans;
|
|
52
|
+
private onConversationChanged;
|
|
53
|
+
private onFileDeleted;
|
|
54
|
+
private onTruncated;
|
|
55
|
+
private onError;
|
|
56
|
+
constructor(events?: ConversationWatcherEvents);
|
|
57
|
+
watch(filePath: string): void;
|
|
58
|
+
unwatch(filePath: string): void;
|
|
59
|
+
/**
|
|
60
|
+
* Re-drive the tail read for a file that's already being tailed. A per-file
|
|
61
|
+
* chokidar handle can die silently (fs.watch stops firing after inode churn)
|
|
62
|
+
* while the coarser directory watcher keeps reporting changes — calling this
|
|
63
|
+
* from the directory-event path makes the tail self-healing. Reads are
|
|
64
|
+
* offset-based and coalesced, so a redundant poke after a normal change
|
|
65
|
+
* event is a cheap stat + no-op. Returns false for untailed paths.
|
|
66
|
+
*/
|
|
67
|
+
poke(filePath: string): boolean;
|
|
68
|
+
/**
|
|
69
|
+
* Watch a directory of conversation JSONL files. Fires
|
|
70
|
+
* onConversationChanged for any add/change/unlink event so the caller
|
|
71
|
+
* can mark the cache dirty without scanning everything immediately.
|
|
72
|
+
*
|
|
73
|
+
* **This costs one OS watch handle per file under `directory`, not one per
|
|
74
|
+
* directory.** chokidar recurses the tree and registers a separate fs.watch
|
|
75
|
+
* per entry, because a directory watch alone does not report writes to files
|
|
76
|
+
* inside it — and per-file `change` events are exactly what the caller needs
|
|
77
|
+
* (they drive poke()'s tail self-heal and the external-tail attach). So the
|
|
78
|
+
* handle count tracks the size of the conversation corpus on disk, not the
|
|
79
|
+
* number of live sessions, and it does not shrink until transcripts are
|
|
80
|
+
* deleted. `ignoreInitial` suppresses the startup *events*, not the walk.
|
|
81
|
+
*
|
|
82
|
+
* Measured 2026-08-09 on the live macOS instance: 2131 open .jsonl fds
|
|
83
|
+
* against 2133 files under the watched roots — 1:1, ~88% of all fds on the
|
|
84
|
+
* process, at 2.0% of that box's 122 880 per-process ceiling. Comfortable
|
|
85
|
+
* there. **Linux is the tight one**: these are inotify watches billed to the
|
|
86
|
+
* per-user `max_user_watches`, which can be 8192 and is shared with every
|
|
87
|
+
* other watcher the user runs. Exhaustion surfaces as ENOSPC on the `error`
|
|
88
|
+
* event — which is why server.ts wires onError rather than leaving it unset.
|
|
89
|
+
*
|
|
90
|
+
* Before trading handles for a bound here, note the regression it invites: a
|
|
91
|
+
* conversation excluded from the walk (by age or by an LRU cap) is one whose
|
|
92
|
+
* external appends produce no event at all, and that failure is silent.
|
|
93
|
+
*/
|
|
94
|
+
watchDirectory(directory: string): void;
|
|
95
|
+
unwatchDirectory(directory: string): void;
|
|
96
|
+
dispose(): void;
|
|
97
|
+
private readNewLines;
|
|
98
|
+
}
|
|
99
|
+
//# sourceMappingURL=conversationWatcher.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"conversationWatcher.d.ts","sourceRoot":"","sources":["../../../src/services/conversations/conversationWatcher.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,QAAQ,EAAsB,MAAM,0BAA0B,CAAC;AAE7E,MAAM,WAAW,yBAAyB;IACxC,6EAA6E;IAC7E,SAAS,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACrD;;;;;OAKG;IACH,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IACzD;;;;;;;OAOG;IACH,cAAc,CAAC,EAAE,CACf,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,QAAQ,EAAE,EACjB,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,KACd,IAAI,CAAC;IACV,+EAA+E;IAC/E,qBAAqB,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACnE,2EAA2E;IAC3E,aAAa,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3C;;;;;OAKG;IACH,WAAW,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IACzC,gCAAgC;IAChC,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CACpD;AAiBD;;;;;;;;;;GAUG;AACH,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,KAAK,CAAkC;IAC/C,OAAO,CAAC,WAAW,CAAgC;IACnD,OAAO,CAAC,SAAS,CAAyC;IAC1D,OAAO,CAAC,UAAU,CAA0C;IAC5D,OAAO,CAAC,cAAc,CAA8C;IACpE,OAAO,CAAC,qBAAqB,CAAqD;IAClF,OAAO,CAAC,aAAa,CAA6C;IAClE,OAAO,CAAC,WAAW,CAA2C;IAC9D,OAAO,CAAC,OAAO,CAAuC;IAEtD,YAAY,MAAM,GAAE,yBAA8B,EAQjD;IAED,KAAK,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAuC5B;IAED,OAAO,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAM9B;IAED;;;;;;;OAOG;IACH,IAAI,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAO9B;IAED;;;;;;;;;;;;;;;;;;;;;;;;;OAyBG;IACH,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAmBtC;IAED,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAKxC;IAED,OAAO,IAAI,IAAI,CAGd;YAEa,YAAY;CAyF3B"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export interface SearchTargetMatch {
|
|
2
|
+
messageIndex: number;
|
|
3
|
+
uuid: string | null;
|
|
4
|
+
snippet: string;
|
|
5
|
+
/**
|
|
6
|
+
* All matching message indexes, ascending. When any plain-text match exists
|
|
7
|
+
* only text matches are listed (they are the navigable/highlightable ones);
|
|
8
|
+
* otherwise the thinking/tool fallback matches are. Capped at the LAST
|
|
9
|
+
* MAX_MATCH_INDEXES entries — navigation starts at the tail-most match.
|
|
10
|
+
*/
|
|
11
|
+
matchIndexes: number[];
|
|
12
|
+
/** Uncapped true match count (the "of M" in the client counter). */
|
|
13
|
+
totalMatches: number;
|
|
14
|
+
}
|
|
15
|
+
export interface SearchableMessage {
|
|
16
|
+
text?: string;
|
|
17
|
+
uuid?: string | null;
|
|
18
|
+
isThinking?: boolean;
|
|
19
|
+
thinkingContent?: string;
|
|
20
|
+
metadata?: {
|
|
21
|
+
toolUseBlocks?: Array<{
|
|
22
|
+
input?: unknown;
|
|
23
|
+
}>;
|
|
24
|
+
toolResults?: Array<{
|
|
25
|
+
content?: unknown;
|
|
26
|
+
}>;
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
export declare function findSearchTarget(messages: SearchableMessage[], query: string): SearchTargetMatch | null;
|
|
30
|
+
//# sourceMappingURL=findSearchTarget.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"findSearchTarget.d.ts","sourceRoot":"","sources":["../../../src/services/conversations/findSearchTarget.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,iBAAiB;IAChC,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB;;;;;OAKG;IACH,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,oEAAoE;IACpE,YAAY,EAAE,MAAM,CAAC;CACtB;AAID,MAAM,WAAW,iBAAiB;IAChC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,EAAE;QACT,aAAa,CAAC,EAAE,KAAK,CAAC;YAAE,KAAK,CAAC,EAAE,OAAO,CAAA;SAAE,CAAC,CAAC;QAC3C,WAAW,CAAC,EAAE,KAAK,CAAC;YAAE,OAAO,CAAC,EAAE,OAAO,CAAA;SAAE,CAAC,CAAC;KAC5C,CAAC;CACH;AA4CD,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,iBAAiB,EAAE,EAC7B,KAAK,EAAE,MAAM,GACZ,iBAAiB,GAAG,IAAI,CAqB1B"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export declare const DEFAULT_AGENT_ENTRYPOINTS: ReadonlySet<string>;
|
|
2
|
+
export declare function isAgentLine(line: {
|
|
3
|
+
entrypoint?: string;
|
|
4
|
+
}, entrypoints?: ReadonlySet<string>): boolean;
|
|
5
|
+
export declare function isAgentFile(filePath: string, entrypoints?: ReadonlySet<string>): boolean;
|
|
6
|
+
export declare function parseAgentEntrypointsEnv(raw: string | undefined): ReadonlySet<string>;
|
|
7
|
+
export declare function clearAgentFileCacheForTests(): void;
|
|
8
|
+
//# sourceMappingURL=isAgentConversation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"isAgentConversation.d.ts","sourceRoot":"","sources":["../../../src/services/conversations/isAgentConversation.ts"],"names":[],"mappings":"AAUA,eAAO,MAAM,yBAAyB,EAAE,WAAW,CAAC,MAAM,CAAyC,CAAC;AA8BpG,wBAAgB,WAAW,CACzB,IAAI,EAAE;IAAE,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE,EAC7B,WAAW,GAAE,WAAW,CAAC,MAAM,CAA6B,GAC3D,OAAO,CAET;AAED,wBAAgB,WAAW,CACzB,QAAQ,EAAE,MAAM,EAChB,WAAW,GAAE,WAAW,CAAC,MAAM,CAA6B,GAC3D,OAAO,CA0DT;AAID,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,WAAW,CAAC,MAAM,CAAC,CAOrF;AAED,wBAAgB,2BAA2B,IAAI,IAAI,CAElD"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { ConversationCache } from "../../conversation-cache";
|
|
2
|
+
export interface PruneAgentConversationsResult {
|
|
3
|
+
scanned: number;
|
|
4
|
+
pruned: number;
|
|
5
|
+
missing: number;
|
|
6
|
+
}
|
|
7
|
+
export declare function pruneAgentConversations(cache: ConversationCache): PruneAgentConversationsResult;
|
|
8
|
+
//# sourceMappingURL=pruneAgentConversations.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pruneAgentConversations.d.ts","sourceRoot":"","sources":["../../../src/services/conversations/pruneAgentConversations.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAElE,MAAM,WAAW,6BAA6B;IAC5C,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;CACjB;AAKD,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,iBAAiB,GAAG,6BAA6B,CAqB/F"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { ConversationCache } from "../../conversation-cache";
|
|
2
|
+
import type { CacheMetadataRepository } from "../../db/repositories/cacheMetadata.repository";
|
|
3
|
+
import type { ConversationsRepository } from "../../db/repositories/conversations.repository";
|
|
4
|
+
import type { ProjectsRepository } from "../../db/repositories/projects.repository";
|
|
5
|
+
export interface RefreshConversationCacheDeps {
|
|
6
|
+
cache: ConversationCache;
|
|
7
|
+
projectsRepo: ProjectsRepository;
|
|
8
|
+
conversationsRepo: ConversationsRepository;
|
|
9
|
+
cacheMetadataRepo: CacheMetadataRepository;
|
|
10
|
+
}
|
|
11
|
+
export interface RefreshConversationCacheResult {
|
|
12
|
+
projectsTouched: number;
|
|
13
|
+
conversationsBackfilled: number;
|
|
14
|
+
latestConversationId: string | null;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* After a scanner-driven cache rebuild has run, walk the cache to:
|
|
18
|
+
* 1. Upsert one project row per unique canonical project_path.
|
|
19
|
+
* 2. Backfill conversation_meta.project_id for any rows missing it.
|
|
20
|
+
* 3. Update cache_metadata.last_conversation_id so subsequent freshness
|
|
21
|
+
* checks can short-circuit.
|
|
22
|
+
*
|
|
23
|
+
* The scanner itself runs in `server.ts` today; this function picks up
|
|
24
|
+
* after it has populated `conversation_meta`.
|
|
25
|
+
*/
|
|
26
|
+
export declare function refreshConversationCache(deps: RefreshConversationCacheDeps): RefreshConversationCacheResult;
|
|
27
|
+
//# sourceMappingURL=refreshConversationCache.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"refreshConversationCache.d.ts","sourceRoot":"","sources":["../../../src/services/conversations/refreshConversationCache.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,gDAAgD,CAAC;AAC9F,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,gDAAgD,CAAC;AAC9F,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2CAA2C,CAAC;AAKpF,MAAM,WAAW,4BAA4B;IAC3C,KAAK,EAAE,iBAAiB,CAAC;IACzB,YAAY,EAAE,kBAAkB,CAAC;IACjC,iBAAiB,EAAE,uBAAuB,CAAC;IAC3C,iBAAiB,EAAE,uBAAuB,CAAC;CAC5C;AAED,MAAM,WAAW,8BAA8B;IAC7C,eAAe,EAAE,MAAM,CAAC;IACxB,uBAAuB,EAAE,MAAM,CAAC;IAChC,oBAAoB,EAAE,MAAM,GAAG,IAAI,CAAC;CACrC;AAED;;;;;;;;;GASG;AACH,wBAAgB,wBAAwB,CACtC,IAAI,EAAE,4BAA4B,GACjC,8BAA8B,CA0ChC"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { CacheMetadataRepository } from "../../db/repositories/cacheMetadata.repository";
|
|
2
|
+
import type { ConversationsRepository } from "../../db/repositories/conversations.repository";
|
|
3
|
+
export interface ShouldRefreshOptions {
|
|
4
|
+
/** Override the disk path checked for drift. Defaults to ~/.claude/projects. */
|
|
5
|
+
projectsDir?: string;
|
|
6
|
+
/** Additional project roots (e.g. per-profile `configDir/projects`). */
|
|
7
|
+
projectsDirs?: string[];
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Newest mtime across a projects root and its immediate child directories.
|
|
11
|
+
*
|
|
12
|
+
* POSIX directory mtime updates when direct entries are added/removed/renamed,
|
|
13
|
+
* not when a file inside a child is appended. Checking one level of children
|
|
14
|
+
* catches new JSONLs in an existing project without stating every file.
|
|
15
|
+
*/
|
|
16
|
+
export declare function maxProjectsTreeMtimeMs(projectsDir: string): number | null;
|
|
17
|
+
/**
|
|
18
|
+
* Decide whether the projects/conversations cache needs a refresh.
|
|
19
|
+
*
|
|
20
|
+
* Returns true when either:
|
|
21
|
+
* 1. The cache has orphan rows — conversations with a project_path but no
|
|
22
|
+
* project_id. These need a backfill pass to become visible to
|
|
23
|
+
* /project-chats (which filters out null project_id).
|
|
24
|
+
* 2. A watched projects tree on disk has changed since the last scanner pass —
|
|
25
|
+
* max(root mtime, child-dir mtimes) is newer than
|
|
26
|
+
* cache_metadata.conversations_last_indexed_at. This catches new JSONLs
|
|
27
|
+
* that the file watcher missed (including under existing project dirs).
|
|
28
|
+
*
|
|
29
|
+
* Appends to existing JSONLs still rely on the directory watcher flipping
|
|
30
|
+
* scannerStale; this mtime gate does not see in-place file growth.
|
|
31
|
+
*/
|
|
32
|
+
export declare function shouldRefreshProjectsFromHdd(conversationsRepo: ConversationsRepository, cacheMetadataRepo: CacheMetadataRepository, opts?: ShouldRefreshOptions): boolean;
|
|
33
|
+
//# sourceMappingURL=shouldRefreshProjectsFromHdd.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shouldRefreshProjectsFromHdd.d.ts","sourceRoot":"","sources":["../../../src/services/conversations/shouldRefreshProjectsFromHdd.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,gDAAgD,CAAC;AAC9F,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,gDAAgD,CAAC;AAK9F,MAAM,WAAW,oBAAoB;IACnC,gFAAgF;IAChF,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,wEAAwE;IACxE,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;CACzB;AAED;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAuBzE;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,4BAA4B,CAC1C,iBAAiB,EAAE,uBAAuB,EAC1C,iBAAiB,EAAE,uBAAuB,EAC1C,IAAI,GAAE,oBAAyB,GAC9B,OAAO,CAwBT"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Diagnostics contract (C6).
|
|
3
|
+
*
|
|
4
|
+
* `/healthz` answers one question — is the process up — and returns
|
|
5
|
+
* `{ ok, version }`. When a user's session will not start, that tells them
|
|
6
|
+
* nothing about why: the provider CLI may be missing, the database may have
|
|
7
|
+
* failed to migrate, the PTY subsystem may be unavailable, or the clock may be
|
|
8
|
+
* skewed enough to break token validation.
|
|
9
|
+
*
|
|
10
|
+
* This produces a structured report where each subsystem is checked
|
|
11
|
+
* independently, so one failure never masks another, and every failure carries a
|
|
12
|
+
* STABLE remediation code the client can map to instructions without parsing
|
|
13
|
+
* English.
|
|
14
|
+
*
|
|
15
|
+
* Redaction is a contract requirement, not a nicety: this endpoint is designed
|
|
16
|
+
* to be copied into a bug report. See `redactPath` below.
|
|
17
|
+
*/
|
|
18
|
+
export declare const DIAGNOSTICS_CONTRACT_VERSION = 1;
|
|
19
|
+
export type CheckStatus = "ok" | "degraded" | "failed" | "unknown";
|
|
20
|
+
/**
|
|
21
|
+
* Stable, machine-readable remediation identifiers.
|
|
22
|
+
*
|
|
23
|
+
* Clients map these to localized instructions, so they are part of the contract:
|
|
24
|
+
* renaming one is a breaking change. New codes may be added; existing ones must
|
|
25
|
+
* keep their meaning.
|
|
26
|
+
*/
|
|
27
|
+
export type RemediationCode = "PROVIDER_NOT_INSTALLED" | "PROVIDER_VERSION_UNVERIFIED" | "DB_UNAVAILABLE" | "DB_MIGRATION_PENDING" | "PTY_UNAVAILABLE" | "CACHE_DEGRADED" | "CLOCK_SKEWED" | "FS_SCOPE_MISSING" | "NONE";
|
|
28
|
+
export interface DiagnosticCheck {
|
|
29
|
+
/** Stable identifier for the subsystem, e.g. "database". */
|
|
30
|
+
id: string;
|
|
31
|
+
status: CheckStatus;
|
|
32
|
+
/** Human-readable summary. Never contains secrets or full paths. */
|
|
33
|
+
summary: string;
|
|
34
|
+
remediation: RemediationCode;
|
|
35
|
+
/** Structured, redacted detail. Optional. */
|
|
36
|
+
detail?: Record<string, string | number | boolean | null>;
|
|
37
|
+
}
|
|
38
|
+
export interface DiagnosticsReport {
|
|
39
|
+
contractVersion: number;
|
|
40
|
+
generatedAt: string;
|
|
41
|
+
/** Worst status across all checks — a single field for a client to branch on. */
|
|
42
|
+
overall: CheckStatus;
|
|
43
|
+
checks: DiagnosticCheck[];
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Reduce a filesystem path to its last two segments.
|
|
47
|
+
*
|
|
48
|
+
* A full path leaks the user's home directory layout, their username, and often
|
|
49
|
+
* client or project names. The tail is enough to recognize *which* directory is
|
|
50
|
+
* meant when you already know your own machine, which is all a diagnostic needs.
|
|
51
|
+
*/
|
|
52
|
+
export declare function redactPath(path: string | null | undefined): string | null;
|
|
53
|
+
/** Worst status wins, so a single failure is never hidden by surrounding successes. */
|
|
54
|
+
export declare function worstStatus(checks: DiagnosticCheck[]): CheckStatus;
|
|
55
|
+
/**
|
|
56
|
+
* Clock skew against a trusted reference, in milliseconds.
|
|
57
|
+
*
|
|
58
|
+
* Matters because pair tokens carry a 180-second TTL: a device whose clock is
|
|
59
|
+
* far enough off will have every pairing attempt rejected as expired, with no
|
|
60
|
+
* indication that time is the cause.
|
|
61
|
+
*/
|
|
62
|
+
export declare const CLOCK_SKEW_WARN_MS = 60000;
|
|
63
|
+
export declare function clockSkewCheck(localNow: number, referenceNow: number | null): DiagnosticCheck;
|
|
64
|
+
export declare function buildReport(checks: DiagnosticCheck[], now?: Date): DiagnosticsReport;
|
|
65
|
+
export declare function redactValue<T>(value: T): T;
|
|
66
|
+
//# sourceMappingURL=diagnostics.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diagnostics.d.ts","sourceRoot":"","sources":["../../../src/services/diagnostics/diagnostics.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,eAAO,MAAM,4BAA4B,IAAI,CAAC;AAE9C,MAAM,MAAM,WAAW,GAAG,IAAI,GAAG,UAAU,GAAG,QAAQ,GAAG,SAAS,CAAC;AAEnE;;;;;;GAMG;AACH,MAAM,MAAM,eAAe,GACvB,wBAAwB,GACxB,6BAA6B,GAC7B,gBAAgB,GAChB,sBAAsB,GACtB,iBAAiB,GACjB,gBAAgB,GAChB,cAAc,GACd,kBAAkB,GAClB,MAAM,CAAC;AAEX,MAAM,WAAW,eAAe;IAC9B,4DAA4D;IAC5D,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,WAAW,CAAC;IACpB,oEAAoE;IACpE,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,eAAe,CAAC;IAC7B,6CAA6C;IAC7C,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,CAAC,CAAC;CAC3D;AAED,MAAM,WAAW,iBAAiB;IAChC,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,iFAAiF;IACjF,OAAO,EAAE,WAAW,CAAC;IACrB,MAAM,EAAE,eAAe,EAAE,CAAC;CAC3B;AAED;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,GAAG,IAAI,CAKzE;AAED,uFAAuF;AACvF,wBAAgB,WAAW,CAAC,MAAM,EAAE,eAAe,EAAE,GAAG,WAAW,CAMlE;AAED;;;;;;GAMG;AACH,eAAO,MAAM,kBAAkB,QAAS,CAAC;AAEzC,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,IAAI,GAAG,eAAe,CA6B7F;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,eAAe,EAAE,EAAE,GAAG,GAAE,IAAiB,GAAG,iBAAiB,CAOhG;AAcD,wBAAgB,WAAW,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,CAAC,CAY1C"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolve a user-visible title for a ProjectChat row.
|
|
3
|
+
*
|
|
4
|
+
* Mobile (ConversationListItem.tsx) renders `title?.trim() || pathSuffix ||
|
|
5
|
+
* ''`, so when title and projectPath are both blank the row appears empty.
|
|
6
|
+
* This helper produces a non-empty title for every input by falling back
|
|
7
|
+
* through title → slug-ish projectName → path suffix → short id.
|
|
8
|
+
*/
|
|
9
|
+
export declare function deriveProjectChatTitle(input: {
|
|
10
|
+
title: string | null | undefined;
|
|
11
|
+
projectName: string | null | undefined;
|
|
12
|
+
projectPath: string | null | undefined;
|
|
13
|
+
id: string;
|
|
14
|
+
}): string;
|
|
15
|
+
//# sourceMappingURL=deriveProjectChatTitle.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deriveProjectChatTitle.d.ts","sourceRoot":"","sources":["../../../src/services/projectChats/deriveProjectChatTitle.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE;IAC5C,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IACjC,WAAW,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IACvC,WAAW,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IACvC,EAAE,EAAE,MAAM,CAAC;CACZ,GAAG,MAAM,CAUT"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { ProjectsRepository } from "../../db/repositories/projects.repository";
|
|
2
|
+
export interface ConversationLikeForProjects {
|
|
3
|
+
id: string;
|
|
4
|
+
projectPath: string | null | undefined;
|
|
5
|
+
createdAt?: string | null;
|
|
6
|
+
latestMessageAt?: string | null;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Group cached conversations by their canonical project path, find the
|
|
10
|
+
* latest conversation per project, then upsert one project row per unique
|
|
11
|
+
* path. Returns a map from canonical path → projectId so callers can
|
|
12
|
+
* backfill conversation/session project_id columns afterwards.
|
|
13
|
+
*/
|
|
14
|
+
export declare function ensureProjectsForConversations(repo: ProjectsRepository, conversations: ConversationLikeForProjects[]): Map<string, string>;
|
|
15
|
+
//# sourceMappingURL=ensureProjectsForConversations.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ensureProjectsForConversations.d.ts","sourceRoot":"","sources":["../../../src/services/projects/ensureProjectsForConversations.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2CAA2C,CAAC;AAIpF,MAAM,WAAW,2BAA2B;IAC1C,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IACvC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACjC;AAED;;;;;GAKG;AACH,wBAAgB,8BAA8B,CAC5C,IAAI,EAAE,kBAAkB,EACxB,aAAa,EAAE,2BAA2B,EAAE,GAC3C,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CA2BrB"}
|