om-memory-system 3.0.0 → 3.1.0-next.3
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/{LICENSE → LICENSE.md} +4 -2
- package/README.md +108 -532
- package/dist/adapters/opencode/auto-capture-summary.js +23 -17
- package/dist/adapters/opencode/import-command.d.ts +42 -0
- package/dist/adapters/opencode/import-command.js +154 -0
- package/dist/adapters/pi/extension.js +4 -5
- package/dist/adapters/pi/import-command.d.ts +7 -19
- package/dist/adapters/pi/import-command.js +46 -161
- package/dist/adapters/pi/live-model.d.ts +17 -0
- package/dist/adapters/pi/live-model.js +86 -0
- package/dist/adapters/pi/profile.d.ts +7 -17
- package/dist/adapters/pi/profile.js +28 -66
- package/dist/adapters/pi/provider.d.ts +8 -1
- package/dist/adapters/pi/provider.js +34 -6
- package/dist/cli/index.d.ts +7 -0
- package/dist/cli/index.js +94 -0
- package/dist/config.d.ts +7 -20
- package/dist/config.js +24 -61
- package/dist/core/extraction.d.ts +2 -2
- package/dist/core/extraction.js +8 -3
- package/dist/core/profile-analysis.d.ts +16 -0
- package/dist/core/profile-analysis.js +47 -0
- package/dist/importer/import-args.d.ts +44 -0
- package/dist/importer/import-args.js +219 -0
- package/dist/importer/importer.d.ts +33 -9
- package/dist/importer/importer.js +153 -89
- package/dist/importer/ledger.d.ts +9 -2
- package/dist/importer/ledger.js +16 -2
- package/dist/importer/model-selection.d.ts +16 -0
- package/dist/importer/model-selection.js +84 -0
- package/dist/importer/opencode-import.d.ts +28 -0
- package/dist/importer/opencode-import.js +87 -0
- package/dist/importer/opencode-project.d.ts +11 -0
- package/dist/importer/opencode-project.js +38 -0
- package/dist/importer/opencode-reader.d.ts +19 -0
- package/dist/importer/opencode-reader.js +214 -0
- package/dist/importer/profile-import.d.ts +29 -0
- package/dist/importer/profile-import.js +111 -0
- package/dist/importer/run-import.d.ts +49 -0
- package/dist/importer/run-import.js +123 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +37 -1
- package/dist/services/ai/internal-capture-sessions.d.ts +2 -0
- package/dist/services/ai/internal-capture-sessions.js +7 -0
- package/dist/services/ai/live-model-choice.d.ts +52 -0
- package/dist/services/ai/live-model-choice.js +83 -0
- package/dist/services/ai/profile-llm-client.js +7 -5
- package/dist/services/user-memory-learning.js +9 -8
- package/dist/services/user-profile/ai-cleanup.js +8 -5
- package/dist/services/user-profile/user-profile-manager.js +11 -10
- package/dist/v2/adapter.js +27 -0
- package/package.json +5 -2
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { UserProfileData } from "../services/user-profile/types.js";
|
|
2
|
+
export interface ModelPort {
|
|
3
|
+
provider: string;
|
|
4
|
+
modelId: string;
|
|
5
|
+
complete(systemPrompt: string, userPrompt: string): Promise<string>;
|
|
6
|
+
}
|
|
7
|
+
export interface ExistingProfileInput {
|
|
8
|
+
id: string;
|
|
9
|
+
profileData: string;
|
|
10
|
+
}
|
|
11
|
+
export interface ProfileAnalysisResult {
|
|
12
|
+
raw: UserProfileData;
|
|
13
|
+
merged: UserProfileData | null;
|
|
14
|
+
}
|
|
15
|
+
/** Analyse prompts with a host-neutral model and merge the validated profile. */
|
|
16
|
+
export declare function analyzeProfile(model: ModelPort, context: string, existingProfile: ExistingProfileInput | null, timeoutMs?: number): Promise<ProfileAnalysisResult>;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { createUserProfileAnalysisSchema, extractJsonObject } from "./extraction.js";
|
|
3
|
+
import { log } from "../services/logger.js";
|
|
4
|
+
function buildProfileAnalysisSystemPrompt(existingProfile) {
|
|
5
|
+
return `You are a user behavior analyst for a coding assistant.
|
|
6
|
+
|
|
7
|
+
Your task is to analyze user prompts and ${existingProfile ? "update" : "create"} a comprehensive user profile.
|
|
8
|
+
|
|
9
|
+
CRITICAL: Detect the language used by the user in their prompts. You MUST output all descriptions, categories, and text in the SAME language as the user's prompts.
|
|
10
|
+
|
|
11
|
+
CRITICAL: All JSON string values MUST escape double quotes with backslash. Do NOT use unescaped quotation marks inside string values.
|
|
12
|
+
|
|
13
|
+
Respond with a single JSON object matching the update_user_profile contract.`;
|
|
14
|
+
}
|
|
15
|
+
/** Analyse prompts with a host-neutral model and merge the validated profile. */
|
|
16
|
+
export async function analyzeProfile(model, context, existingProfile, timeoutMs = 120000) {
|
|
17
|
+
let timeoutId;
|
|
18
|
+
try {
|
|
19
|
+
const reply = await Promise.race([
|
|
20
|
+
model.complete(buildProfileAnalysisSystemPrompt(Boolean(existingProfile)), context),
|
|
21
|
+
new Promise((_, reject) => {
|
|
22
|
+
timeoutId = setTimeout(() => reject(new Error("pi profile analysis: timeout")), timeoutMs);
|
|
23
|
+
timeoutId?.unref?.();
|
|
24
|
+
}),
|
|
25
|
+
]);
|
|
26
|
+
const schema = createUserProfileAnalysisSchema(z);
|
|
27
|
+
const parsed = schema.safeParse(extractJsonObject(reply));
|
|
28
|
+
if (!parsed.success) {
|
|
29
|
+
log("pi profile analysis: model reply failed shared schema validation", {
|
|
30
|
+
provider: model.provider,
|
|
31
|
+
modelId: model.modelId,
|
|
32
|
+
});
|
|
33
|
+
throw new Error("pi profile analysis: invalid profile payload");
|
|
34
|
+
}
|
|
35
|
+
const raw = parsed.data;
|
|
36
|
+
if (!existingProfile)
|
|
37
|
+
return { raw, merged: null };
|
|
38
|
+
const { userProfileManager } = await import("../services/user-profile/user-profile-manager.js");
|
|
39
|
+
const existingData = JSON.parse(existingProfile.profileData);
|
|
40
|
+
const merged = await userProfileManager.mergeProfileData(existingData, raw, undefined, existingProfile.id);
|
|
41
|
+
return { raw, merged };
|
|
42
|
+
}
|
|
43
|
+
finally {
|
|
44
|
+
if (timeoutId)
|
|
45
|
+
clearTimeout(timeoutId);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { ImportPathMap } from "./importer.js";
|
|
2
|
+
/**
|
|
3
|
+
* One option grammar for every history-import surface: the Pi and OpenCode
|
|
4
|
+
* slash commands and the `om-memory-system` CLI. Hosts differ only in where
|
|
5
|
+
* their history lives (`--root` for Pi, `--db` for OpenCode) and in how a
|
|
6
|
+
* model is chosen (a session uses its host's sign-in; the CLI uses an
|
|
7
|
+
* external API and key).
|
|
8
|
+
*/
|
|
9
|
+
export type ImportHost = "pi" | "opencode";
|
|
10
|
+
export type ImportSurface = "session" | "cli";
|
|
11
|
+
export interface HistoryImportArgs {
|
|
12
|
+
help: boolean;
|
|
13
|
+
dryRun: boolean;
|
|
14
|
+
force: boolean;
|
|
15
|
+
skipMemories: boolean;
|
|
16
|
+
skipProfile: boolean;
|
|
17
|
+
profileBatch?: number;
|
|
18
|
+
/** Session: `provider/id` from the host's signed-in models. CLI: a model id for `--provider`. */
|
|
19
|
+
model?: string;
|
|
20
|
+
scope: "current-project" | "all-projects";
|
|
21
|
+
/** Project directory for `current-project` scope; defaults to the working directory. */
|
|
22
|
+
project?: string;
|
|
23
|
+
session?: string;
|
|
24
|
+
since?: number;
|
|
25
|
+
until?: number;
|
|
26
|
+
maxSessions?: number;
|
|
27
|
+
pathMaps: ImportPathMap[];
|
|
28
|
+
/** History location: Pi session root (`--root`) or OpenCode database (`--db`). */
|
|
29
|
+
source?: string;
|
|
30
|
+
provider?: string;
|
|
31
|
+
apiUrl?: string;
|
|
32
|
+
apiKeyEnv?: string;
|
|
33
|
+
errors: string[];
|
|
34
|
+
}
|
|
35
|
+
export declare const SOURCE_FLAG: Record<ImportHost, string>;
|
|
36
|
+
/** Split a slash-command argument string, honouring single and double quotes. */
|
|
37
|
+
export declare function tokenizeImportArgs(raw: string): string[];
|
|
38
|
+
export declare function parseHistoryImportArgs(tokens: string[], options: {
|
|
39
|
+
host: ImportHost;
|
|
40
|
+
surface: ImportSurface;
|
|
41
|
+
}): HistoryImportArgs;
|
|
42
|
+
/** True when the run calls a model: a real import of memories or the profile. */
|
|
43
|
+
export declare function importNeedsModel(args: HistoryImportArgs): boolean;
|
|
44
|
+
export declare function historyImportUsage(host: ImportHost, surface: ImportSurface): string;
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
export const SOURCE_FLAG = { pi: "--root", opencode: "--db" };
|
|
2
|
+
const CLI_ONLY_FLAGS = new Set(["--provider", "--api-url", "--api-key-env"]);
|
|
3
|
+
const BOOLEAN_FLAGS = new Set([
|
|
4
|
+
"--help",
|
|
5
|
+
"-h",
|
|
6
|
+
"--dry-run",
|
|
7
|
+
"--force",
|
|
8
|
+
"--skip-memories",
|
|
9
|
+
"--skip-profile",
|
|
10
|
+
]);
|
|
11
|
+
const VALUE_FLAGS = new Set([
|
|
12
|
+
"--profile-batch",
|
|
13
|
+
"--model",
|
|
14
|
+
"--scope",
|
|
15
|
+
"--project",
|
|
16
|
+
"--session",
|
|
17
|
+
"--since",
|
|
18
|
+
"--until",
|
|
19
|
+
"--max-sessions",
|
|
20
|
+
"--map",
|
|
21
|
+
"--root",
|
|
22
|
+
"--db",
|
|
23
|
+
...CLI_ONLY_FLAGS,
|
|
24
|
+
]);
|
|
25
|
+
/** Split a slash-command argument string, honouring single and double quotes. */
|
|
26
|
+
export function tokenizeImportArgs(raw) {
|
|
27
|
+
const tokens = [];
|
|
28
|
+
const pattern = /"([^"]*)"|'([^']*)'|(\S+)/g;
|
|
29
|
+
for (const match of raw.matchAll(pattern)) {
|
|
30
|
+
tokens.push(match[1] ?? match[2] ?? match[3] ?? "");
|
|
31
|
+
}
|
|
32
|
+
return tokens;
|
|
33
|
+
}
|
|
34
|
+
function parseTimestamp(raw, endOfDay) {
|
|
35
|
+
if (/^\d+$/.test(raw))
|
|
36
|
+
return Number(raw);
|
|
37
|
+
const parsed = Date.parse(raw);
|
|
38
|
+
if (!Number.isFinite(parsed))
|
|
39
|
+
return undefined;
|
|
40
|
+
// A bare YYYY-MM-DD parses to UTC midnight; an inclusive end date covers that whole day.
|
|
41
|
+
return endOfDay && /^\d{4}-\d{2}-\d{2}$/.test(raw) ? parsed + 86_399_999 : parsed;
|
|
42
|
+
}
|
|
43
|
+
function positiveInt(raw) {
|
|
44
|
+
const parsed = Number(raw);
|
|
45
|
+
return Number.isSafeInteger(parsed) && parsed > 0 ? parsed : undefined;
|
|
46
|
+
}
|
|
47
|
+
export function parseHistoryImportArgs(tokens, options) {
|
|
48
|
+
const result = {
|
|
49
|
+
help: false,
|
|
50
|
+
dryRun: false,
|
|
51
|
+
force: false,
|
|
52
|
+
skipMemories: false,
|
|
53
|
+
skipProfile: false,
|
|
54
|
+
scope: "current-project",
|
|
55
|
+
pathMaps: [],
|
|
56
|
+
errors: [],
|
|
57
|
+
};
|
|
58
|
+
const sourceFlag = SOURCE_FLAG[options.host];
|
|
59
|
+
for (let i = 0; i < tokens.length; i++) {
|
|
60
|
+
const token = tokens[i];
|
|
61
|
+
const equals = token.startsWith("--") ? token.indexOf("=") : -1;
|
|
62
|
+
const flag = equals === -1 ? token : token.slice(0, equals);
|
|
63
|
+
if (BOOLEAN_FLAGS.has(flag)) {
|
|
64
|
+
if (equals !== -1) {
|
|
65
|
+
result.errors.push(`${flag} takes no value`);
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
if (flag === "--help" || flag === "-h")
|
|
69
|
+
result.help = true;
|
|
70
|
+
else if (flag === "--dry-run")
|
|
71
|
+
result.dryRun = true;
|
|
72
|
+
else if (flag === "--force")
|
|
73
|
+
result.force = true;
|
|
74
|
+
else if (flag === "--skip-memories")
|
|
75
|
+
result.skipMemories = true;
|
|
76
|
+
else
|
|
77
|
+
result.skipProfile = true;
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
if (!VALUE_FLAGS.has(flag) || ((flag === "--root" || flag === "--db") && flag !== sourceFlag)) {
|
|
81
|
+
result.errors.push(`Unknown option: "${token}"`);
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
if (CLI_ONLY_FLAGS.has(flag) && options.surface !== "cli") {
|
|
85
|
+
result.errors.push(`${flag} is only for the om-memory-system CLI; use --model provider/id`);
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
let value;
|
|
89
|
+
if (equals !== -1) {
|
|
90
|
+
value = token.slice(equals + 1);
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
const next = tokens[i + 1];
|
|
94
|
+
value = next !== undefined && !next.startsWith("--") ? next : "";
|
|
95
|
+
if (value)
|
|
96
|
+
i++;
|
|
97
|
+
}
|
|
98
|
+
if (!value) {
|
|
99
|
+
result.errors.push(`${flag} requires a value`);
|
|
100
|
+
continue;
|
|
101
|
+
}
|
|
102
|
+
switch (flag) {
|
|
103
|
+
case "--profile-batch":
|
|
104
|
+
result.profileBatch = positiveInt(value);
|
|
105
|
+
if (result.profileBatch === undefined)
|
|
106
|
+
result.errors.push("--profile-batch needs a positive integer");
|
|
107
|
+
break;
|
|
108
|
+
case "--max-sessions":
|
|
109
|
+
result.maxSessions = positiveInt(value);
|
|
110
|
+
if (result.maxSessions === undefined)
|
|
111
|
+
result.errors.push("--max-sessions needs a positive integer");
|
|
112
|
+
break;
|
|
113
|
+
case "--model":
|
|
114
|
+
result.model = value;
|
|
115
|
+
break;
|
|
116
|
+
case "--scope":
|
|
117
|
+
if (value === "current-project" || value === "all-projects")
|
|
118
|
+
result.scope = value;
|
|
119
|
+
else
|
|
120
|
+
result.errors.push(`--scope must be current-project or all-projects, got "${value}"`);
|
|
121
|
+
break;
|
|
122
|
+
case "--project":
|
|
123
|
+
result.project = value;
|
|
124
|
+
break;
|
|
125
|
+
case "--session":
|
|
126
|
+
result.session = value;
|
|
127
|
+
break;
|
|
128
|
+
case "--since":
|
|
129
|
+
case "--until":
|
|
130
|
+
{
|
|
131
|
+
const parsed = parseTimestamp(value, flag === "--until");
|
|
132
|
+
if (parsed === undefined)
|
|
133
|
+
result.errors.push(`${flag} is not a valid date: "${value}"`);
|
|
134
|
+
else if (flag === "--since")
|
|
135
|
+
result.since = parsed;
|
|
136
|
+
else
|
|
137
|
+
result.until = parsed;
|
|
138
|
+
}
|
|
139
|
+
break;
|
|
140
|
+
case "--map": {
|
|
141
|
+
const separator = value.indexOf("=");
|
|
142
|
+
if (separator > 0 && separator < value.length - 1) {
|
|
143
|
+
result.pathMaps.push({ from: value.slice(0, separator), to: value.slice(separator + 1) });
|
|
144
|
+
}
|
|
145
|
+
else {
|
|
146
|
+
result.errors.push(`--map must be <oldPath>=<newPath>, got "${value}"`);
|
|
147
|
+
}
|
|
148
|
+
break;
|
|
149
|
+
}
|
|
150
|
+
case "--root":
|
|
151
|
+
case "--db":
|
|
152
|
+
result.source = value;
|
|
153
|
+
break;
|
|
154
|
+
case "--provider":
|
|
155
|
+
result.provider = value;
|
|
156
|
+
break;
|
|
157
|
+
case "--api-url":
|
|
158
|
+
result.apiUrl = value;
|
|
159
|
+
break;
|
|
160
|
+
case "--api-key-env":
|
|
161
|
+
result.apiKeyEnv = value;
|
|
162
|
+
break;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
if (result.since !== undefined && result.until !== undefined && result.since > result.until) {
|
|
166
|
+
result.errors.push("--since must be before --until");
|
|
167
|
+
}
|
|
168
|
+
if (result.project !== undefined && result.scope === "all-projects") {
|
|
169
|
+
result.errors.push("--project cannot be combined with --scope=all-projects");
|
|
170
|
+
}
|
|
171
|
+
if (options.surface === "session" && result.model !== undefined) {
|
|
172
|
+
const separator = result.model.indexOf("/");
|
|
173
|
+
if (separator < 1 || separator === result.model.length - 1) {
|
|
174
|
+
result.errors.push(`--model must be provider/id, got "${result.model}"`);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
return result;
|
|
178
|
+
}
|
|
179
|
+
/** True when the run calls a model: a real import of memories or the profile. */
|
|
180
|
+
export function importNeedsModel(args) {
|
|
181
|
+
return !args.dryRun && (!args.skipMemories || !args.skipProfile);
|
|
182
|
+
}
|
|
183
|
+
export function historyImportUsage(host, surface) {
|
|
184
|
+
const name = host === "pi" ? "pi" : "opencode";
|
|
185
|
+
const invoke = surface === "session"
|
|
186
|
+
? `/memory-import-${name}-history`
|
|
187
|
+
: `om-memory-system import-${name}-history`;
|
|
188
|
+
const source = host === "pi"
|
|
189
|
+
? " --root <dir> Pi session root (default ~/.pi/agent/sessions)"
|
|
190
|
+
: " --db <path> OpenCode database (default ~/.local/share/opencode/opencode.db)";
|
|
191
|
+
const model = surface === "session"
|
|
192
|
+
? ` --model <provider/id> Use another signed-in model (default: this session's model)`
|
|
193
|
+
: ` --model <id> Model id (default: saved memoryModel)
|
|
194
|
+
--provider <type> Provider type (default: saved memoryProvider)
|
|
195
|
+
--api-url <url> Endpoint; required when --provider differs from the saved one
|
|
196
|
+
--api-key-env <name> Read the API key from this environment variable`;
|
|
197
|
+
return `Usage: ${invoke} [options]
|
|
198
|
+
|
|
199
|
+
Preview first: ${invoke} --dry-run
|
|
200
|
+
|
|
201
|
+
Options:
|
|
202
|
+
--dry-run Preview counts; no model calls or writes
|
|
203
|
+
${model}
|
|
204
|
+
--scope <scope> current-project (default) or all-projects
|
|
205
|
+
--project <dir> Project for current-project scope (default: working directory)
|
|
206
|
+
--session <id> Import one session
|
|
207
|
+
--since <date> Inclusive start (ISO 8601 or epoch ms)
|
|
208
|
+
--until <date> Inclusive end; a bare date covers the whole day
|
|
209
|
+
--max-sessions <n> Read at most n sessions, oldest first
|
|
210
|
+
--map <old>=<new> Map a recorded directory that no longer exists (repeatable)
|
|
211
|
+
${source}
|
|
212
|
+
--skip-memories Record profile prompts only
|
|
213
|
+
--skip-profile Import memories only
|
|
214
|
+
--profile-batch <n> Prompts per profile analysis batch (default: 50)
|
|
215
|
+
--force Reprocess already-handled memory work units
|
|
216
|
+
--help Show this help
|
|
217
|
+
|
|
218
|
+
Values may follow the flag or use --flag=value.`;
|
|
219
|
+
}
|
|
@@ -1,15 +1,14 @@
|
|
|
1
|
-
import type { CaptureSummaryProvider } from "../core/host.js";
|
|
2
|
-
import {
|
|
1
|
+
import type { CaptureConversation, CaptureSummaryProvider } from "../core/host.js";
|
|
2
|
+
import type { ModelPort } from "../core/profile-analysis.js";
|
|
3
|
+
import type { ProfileImportReport } from "./profile-import.js";
|
|
3
4
|
import { PiImportLedger } from "./ledger.js";
|
|
4
5
|
import type { LoadedPiSession } from "./session-loader.js";
|
|
6
|
+
import type { MemoryHost } from "../types/index.js";
|
|
5
7
|
/**
|
|
6
|
-
*
|
|
8
|
+
* Historical-session import orchestration for both hosts.
|
|
7
9
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
* resolve the recorded cwd through the shared project identity, select the
|
|
11
|
-
* active branch, and rebuild the same work units live capture would have
|
|
12
|
-
* produced. Source files are only ever read.
|
|
10
|
+
* The shared source pipeline handles capture and ledger reconciliation.
|
|
11
|
+
* The Pi adapter discovers sessions and selects conversation windows.
|
|
13
12
|
*/
|
|
14
13
|
export interface ImportPathMap {
|
|
15
14
|
from: string;
|
|
@@ -26,6 +25,8 @@ export interface ImportFilters {
|
|
|
26
25
|
maxSessions?: number;
|
|
27
26
|
force?: boolean;
|
|
28
27
|
dryRun?: boolean;
|
|
28
|
+
/** Record profile prompts only; leave memory work units untouched. */
|
|
29
|
+
skipMemories?: boolean;
|
|
29
30
|
pathMaps?: ImportPathMap[];
|
|
30
31
|
root?: string;
|
|
31
32
|
}
|
|
@@ -70,18 +71,41 @@ export interface ImportReport {
|
|
|
70
71
|
skipReasons: Record<string, number>;
|
|
71
72
|
projects: ImportProjectReport[];
|
|
72
73
|
units: ImportUnitReport[];
|
|
74
|
+
profile?: ProfileImportReport;
|
|
73
75
|
}
|
|
74
76
|
export interface ImporterDeps {
|
|
75
77
|
loadSession: (file: string) => LoadedPiSession;
|
|
76
78
|
provider: CaptureSummaryProvider;
|
|
77
79
|
onProgress?: (processed: number, total: number, promptPreview: string) => void;
|
|
78
80
|
ledger?: PiImportLedger;
|
|
81
|
+
profile?: {
|
|
82
|
+
model?: ModelPort;
|
|
83
|
+
batchSize?: number;
|
|
84
|
+
};
|
|
79
85
|
}
|
|
80
|
-
export
|
|
86
|
+
export interface ImportWindow extends CaptureConversation {
|
|
87
|
+
userEntryId: string;
|
|
88
|
+
userPrompt: string;
|
|
89
|
+
userTimestamp?: number;
|
|
90
|
+
}
|
|
91
|
+
export interface ImportSourceSession {
|
|
92
|
+
sessionId: string;
|
|
93
|
+
directory: string;
|
|
94
|
+
sourceFile: string;
|
|
95
|
+
units: ImportWindow[];
|
|
96
|
+
}
|
|
97
|
+
export declare function buildImportKey(sessionId: string, window: ImportWindow, host?: string): string | null;
|
|
81
98
|
/**
|
|
82
99
|
* Find a stored memory by its deterministic import identity. Used to
|
|
83
100
|
* reconcile crash windows: the memory insert landed but the ledger update did
|
|
84
101
|
* not commit.
|
|
85
102
|
*/
|
|
86
103
|
export declare function findMemoryIdByImportId(projectHash: string, importId: string): Promise<string | null>;
|
|
104
|
+
/**
|
|
105
|
+
* Project tag for scope filtering only. Symlinked paths (macOS /var vs
|
|
106
|
+
* /private/var) name one project, so compare through the real path.
|
|
107
|
+
*/
|
|
108
|
+
export declare function projectFilterTag(directory: string): string;
|
|
109
|
+
/** Process host-labelled work units through the shared capture and ledger pipeline. */
|
|
110
|
+
export declare function importHistorySource(source: AsyncIterable<ImportSourceSession> | Iterable<ImportSourceSession>, host: MemoryHost, deps: Pick<ImporterDeps, "provider" | "ledger" | "onProgress">, filters: Pick<ImportFilters, "dryRun" | "force" | "since" | "until">, report: ImportReport): Promise<void>;
|
|
87
111
|
export declare function importPiHistory(deps: ImporterDeps, filters: ImportFilters): Promise<ImportReport>;
|