@mquan/portal 0.0.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.
Files changed (116) hide show
  1. package/README.md +168 -0
  2. package/dist/src/api.d.ts +5 -0
  3. package/dist/src/api.js +357 -0
  4. package/dist/src/api.js.map +1 -0
  5. package/dist/src/cli.d.ts +17 -0
  6. package/dist/src/cli.js +618 -0
  7. package/dist/src/cli.js.map +1 -0
  8. package/dist/src/daemon-lifecycle.d.ts +24 -0
  9. package/dist/src/daemon-lifecycle.js +107 -0
  10. package/dist/src/daemon-lifecycle.js.map +1 -0
  11. package/dist/src/daemon.d.ts +17 -0
  12. package/dist/src/daemon.js +90 -0
  13. package/dist/src/daemon.js.map +1 -0
  14. package/dist/src/doctor.d.ts +14 -0
  15. package/dist/src/doctor.js +51 -0
  16. package/dist/src/doctor.js.map +1 -0
  17. package/dist/src/entrypoint.d.ts +2 -0
  18. package/dist/src/entrypoint.js +14 -0
  19. package/dist/src/entrypoint.js.map +1 -0
  20. package/dist/src/index.d.ts +5 -0
  21. package/dist/src/index.js +5 -0
  22. package/dist/src/index.js.map +1 -0
  23. package/dist/src/launch.d.ts +41 -0
  24. package/dist/src/launch.js +186 -0
  25. package/dist/src/launch.js.map +1 -0
  26. package/dist/src/mcp.d.ts +9 -0
  27. package/dist/src/mcp.js +132 -0
  28. package/dist/src/mcp.js.map +1 -0
  29. package/dist/src/network/client.d.ts +67 -0
  30. package/dist/src/network/client.js +540 -0
  31. package/dist/src/network/client.js.map +1 -0
  32. package/dist/src/network/coordinator.d.ts +83 -0
  33. package/dist/src/network/coordinator.js +225 -0
  34. package/dist/src/network/coordinator.js.map +1 -0
  35. package/dist/src/network/protocol.d.ts +1352 -0
  36. package/dist/src/network/protocol.js +360 -0
  37. package/dist/src/network/protocol.js.map +1 -0
  38. package/dist/src/network/server.d.ts +28 -0
  39. package/dist/src/network/server.js +474 -0
  40. package/dist/src/network/server.js.map +1 -0
  41. package/dist/src/network/tasks.d.ts +65 -0
  42. package/dist/src/network/tasks.js +276 -0
  43. package/dist/src/network/tasks.js.map +1 -0
  44. package/dist/src/portal-index.d.ts +21 -0
  45. package/dist/src/portal-index.js +140 -0
  46. package/dist/src/portal-index.js.map +1 -0
  47. package/dist/src/provider/claude-managed.d.ts +34 -0
  48. package/dist/src/provider/claude-managed.js +125 -0
  49. package/dist/src/provider/claude-managed.js.map +1 -0
  50. package/dist/src/provider/claude.d.ts +24 -0
  51. package/dist/src/provider/claude.js +114 -0
  52. package/dist/src/provider/claude.js.map +1 -0
  53. package/dist/src/provider/codex/app-server-client.d.ts +43 -0
  54. package/dist/src/provider/codex/app-server-client.js +143 -0
  55. package/dist/src/provider/codex/app-server-client.js.map +1 -0
  56. package/dist/src/provider/codex/index.d.ts +3 -0
  57. package/dist/src/provider/codex/index.js +4 -0
  58. package/dist/src/provider/codex/index.js.map +1 -0
  59. package/dist/src/provider/codex/managed-runner.d.ts +12 -0
  60. package/dist/src/provider/codex/managed-runner.js +162 -0
  61. package/dist/src/provider/codex/managed-runner.js.map +1 -0
  62. package/dist/src/provider/codex/probe.d.ts +2 -0
  63. package/dist/src/provider/codex/probe.js +33 -0
  64. package/dist/src/provider/codex/probe.js.map +1 -0
  65. package/dist/src/provider/codex/protocol.d.ts +193 -0
  66. package/dist/src/provider/codex/protocol.js +10 -0
  67. package/dist/src/provider/codex/protocol.js.map +1 -0
  68. package/dist/src/provider/codex/provider.d.ts +35 -0
  69. package/dist/src/provider/codex/provider.js +289 -0
  70. package/dist/src/provider/codex/provider.js.map +1 -0
  71. package/dist/src/provider/codex/remote-app-server.d.ts +16 -0
  72. package/dist/src/provider/codex/remote-app-server.js +80 -0
  73. package/dist/src/provider/codex/remote-app-server.js.map +1 -0
  74. package/dist/src/provider/codex/websocket-client.d.ts +40 -0
  75. package/dist/src/provider/codex/websocket-client.js +174 -0
  76. package/dist/src/provider/codex/websocket-client.js.map +1 -0
  77. package/dist/src/provider/types.d.ts +35 -0
  78. package/dist/src/provider/types.js +2 -0
  79. package/dist/src/provider/types.js.map +1 -0
  80. package/dist/src/recall/embedding.d.ts +28 -0
  81. package/dist/src/recall/embedding.js +142 -0
  82. package/dist/src/recall/embedding.js.map +1 -0
  83. package/dist/src/recall/types.d.ts +35 -0
  84. package/dist/src/recall/types.js +2 -0
  85. package/dist/src/recall/types.js.map +1 -0
  86. package/dist/src/rpc/client.d.ts +6 -0
  87. package/dist/src/rpc/client.js +58 -0
  88. package/dist/src/rpc/client.js.map +1 -0
  89. package/dist/src/rpc/protocol.d.ts +21 -0
  90. package/dist/src/rpc/protocol.js +11 -0
  91. package/dist/src/rpc/protocol.js.map +1 -0
  92. package/dist/src/rpc/server.d.ts +12 -0
  93. package/dist/src/rpc/server.js +154 -0
  94. package/dist/src/rpc/server.js.map +1 -0
  95. package/dist/src/runtime/paths.d.ts +8 -0
  96. package/dist/src/runtime/paths.js +18 -0
  97. package/dist/src/runtime/paths.js.map +1 -0
  98. package/dist/src/service.d.ts +127 -0
  99. package/dist/src/service.js +637 -0
  100. package/dist/src/service.js.map +1 -0
  101. package/dist/src/session-profile.d.ts +39 -0
  102. package/dist/src/session-profile.js +186 -0
  103. package/dist/src/session-profile.js.map +1 -0
  104. package/dist/src/storage/database.d.ts +9 -0
  105. package/dist/src/storage/database.js +354 -0
  106. package/dist/src/storage/database.js.map +1 -0
  107. package/dist/src/storage/repository.d.ts +275 -0
  108. package/dist/src/storage/repository.js +1291 -0
  109. package/dist/src/storage/repository.js.map +1 -0
  110. package/dist/src/version.d.ts +1 -0
  111. package/dist/src/version.js +2 -0
  112. package/dist/src/version.js.map +1 -0
  113. package/docs/architecture-plan.md +191 -0
  114. package/docs/mvp-plan.md +111 -0
  115. package/docs/remote-demo.md +346 -0
  116. package/package.json +47 -0
@@ -0,0 +1,40 @@
1
+ import type { CodexAppServerMethod, CodexAppServerMethods, CodexAppServerNotification, CodexAppServerNotifications, InitializeResponse } from "./protocol.js";
2
+ type NotificationListener<M extends CodexAppServerNotification> = (params: CodexAppServerNotifications[M]) => void;
3
+ export interface WebSocketLike {
4
+ readonly readyState: number;
5
+ send(data: string): void;
6
+ close(): void;
7
+ addEventListener(type: "open", listener: () => void, options?: {
8
+ once?: boolean;
9
+ }): void;
10
+ addEventListener(type: "message", listener: (event: {
11
+ data: unknown;
12
+ }) => void): void;
13
+ addEventListener(type: "error", listener: () => void, options?: {
14
+ once?: boolean;
15
+ }): void;
16
+ addEventListener(type: "close", listener: () => void, options?: {
17
+ once?: boolean;
18
+ }): void;
19
+ }
20
+ export interface CodexWebSocketClientOptions {
21
+ requestTimeoutMs?: number;
22
+ clientVersion?: string;
23
+ webSocketFactory?: (address: string) => WebSocketLike;
24
+ }
25
+ /** JSON-RPC client for a Codex app-server WebSocket endpoint. */
26
+ export declare class CodexWebSocketClient {
27
+ #private;
28
+ private constructor();
29
+ static connect(address: string, options?: CodexWebSocketClientOptions): Promise<CodexWebSocketClient>;
30
+ get initializeResult(): InitializeResponse;
31
+ request<M extends CodexAppServerMethod>(method: M, params: CodexAppServerMethods[M]["params"]): Promise<CodexAppServerMethods[M]["result"]>;
32
+ /**
33
+ * Subscribe to one app-server notification. The returned function is
34
+ * idempotent and removes only this listener.
35
+ */
36
+ subscribe<M extends CodexAppServerNotification>(method: M, listener: NotificationListener<M>): () => void;
37
+ close(): void;
38
+ private notify;
39
+ }
40
+ export {};
@@ -0,0 +1,174 @@
1
+ /** JSON-RPC client for a Codex app-server WebSocket endpoint. */
2
+ export class CodexWebSocketClient {
3
+ #initializeResult;
4
+ #socket;
5
+ #timeoutMs;
6
+ #pending = new Map();
7
+ #notificationListeners = new Map();
8
+ #nextId = 1;
9
+ #closed = false;
10
+ constructor(socket, timeoutMs, initializeResult) {
11
+ this.#socket = socket;
12
+ this.#timeoutMs = timeoutMs;
13
+ this.#initializeResult = initializeResult;
14
+ socket.addEventListener("message", (event) => this.#handleMessage(event.data));
15
+ socket.addEventListener("close", () => this.#handleClose(new Error("Codex app-server WebSocket closed")));
16
+ socket.addEventListener("error", () => this.#handleClose(new Error("Codex app-server WebSocket failed")));
17
+ }
18
+ static async connect(address, options = {}) {
19
+ const socket = (options.webSocketFactory ?? defaultWebSocketFactory)(address);
20
+ await waitForOpen(socket, options.requestTimeoutMs ?? 10_000);
21
+ const client = new CodexWebSocketClient(socket, options.requestTimeoutMs ?? 10_000, { userAgent: "", codexHome: "", platformFamily: "", platformOs: "" });
22
+ try {
23
+ const initialized = await client.request("initialize", {
24
+ clientInfo: {
25
+ name: "portal",
26
+ title: "Portal",
27
+ version: options.clientVersion ?? "0.0.1",
28
+ },
29
+ capabilities: null,
30
+ });
31
+ client.#initializeResult = initialized;
32
+ client.notify("initialized");
33
+ return client;
34
+ }
35
+ catch (error) {
36
+ client.close();
37
+ throw error;
38
+ }
39
+ }
40
+ get initializeResult() {
41
+ return this.#initializeResult;
42
+ }
43
+ request(method, params) {
44
+ if (this.#closed)
45
+ return Promise.reject(new Error("Codex app-server WebSocket client is closed"));
46
+ const id = this.#nextId++;
47
+ return new Promise((resolve, reject) => {
48
+ const timer = setTimeout(() => {
49
+ this.#pending.delete(id);
50
+ reject(new Error(`Codex app-server request timed out: ${method}`));
51
+ }, this.#timeoutMs);
52
+ timer.unref();
53
+ this.#pending.set(id, { method, timer, resolve, reject });
54
+ this.#socket.send(JSON.stringify({ id, method, params }));
55
+ });
56
+ }
57
+ /**
58
+ * Subscribe to one app-server notification. The returned function is
59
+ * idempotent and removes only this listener.
60
+ */
61
+ subscribe(method, listener) {
62
+ if (this.#closed)
63
+ throw new Error("Codex app-server WebSocket client is closed");
64
+ const listeners = this.#notificationListeners.get(method) ?? new Set();
65
+ const untypedListener = listener;
66
+ listeners.add(untypedListener);
67
+ this.#notificationListeners.set(method, listeners);
68
+ let subscribed = true;
69
+ return () => {
70
+ if (!subscribed)
71
+ return;
72
+ subscribed = false;
73
+ listeners.delete(untypedListener);
74
+ if (listeners.size === 0)
75
+ this.#notificationListeners.delete(method);
76
+ };
77
+ }
78
+ close() {
79
+ if (this.#closed)
80
+ return;
81
+ this.#closed = true;
82
+ this.#failPending(new Error("Codex app-server WebSocket client closed"));
83
+ this.#notificationListeners.clear();
84
+ this.#socket.close();
85
+ }
86
+ notify(method) {
87
+ this.#socket.send(JSON.stringify({ method }));
88
+ }
89
+ #handleMessage(data) {
90
+ let message;
91
+ try {
92
+ message = JSON.parse(typeof data === "string" ? data : String(data));
93
+ }
94
+ catch {
95
+ return;
96
+ }
97
+ if (isRpcNotification(message)) {
98
+ this.#dispatchNotification(message);
99
+ return;
100
+ }
101
+ if (!isRpcResponse(message))
102
+ return;
103
+ const pending = this.#pending.get(message.id);
104
+ if (pending === undefined)
105
+ return;
106
+ this.#pending.delete(message.id);
107
+ clearTimeout(pending.timer);
108
+ if (message.error !== undefined) {
109
+ pending.reject(new Error(`${pending.method}: ${message.error.message}`));
110
+ }
111
+ else {
112
+ pending.resolve(message.result);
113
+ }
114
+ }
115
+ #handleClose(error) {
116
+ if (this.#closed)
117
+ return;
118
+ this.#closed = true;
119
+ this.#failPending(error);
120
+ this.#notificationListeners.clear();
121
+ }
122
+ #dispatchNotification(notification) {
123
+ const listeners = this.#notificationListeners.get(notification.method);
124
+ if (listeners === undefined)
125
+ return;
126
+ // Snapshot so listeners can safely unsubscribe themselves while handling an event.
127
+ for (const listener of [...listeners])
128
+ listener(notification.params);
129
+ }
130
+ #failPending(error) {
131
+ for (const pending of this.#pending.values()) {
132
+ clearTimeout(pending.timer);
133
+ pending.reject(error);
134
+ }
135
+ this.#pending.clear();
136
+ }
137
+ }
138
+ function defaultWebSocketFactory(address) {
139
+ return new WebSocket(address);
140
+ }
141
+ function waitForOpen(socket, timeoutMs) {
142
+ return new Promise((resolve, reject) => {
143
+ let settled = false;
144
+ const finish = (error) => {
145
+ if (settled)
146
+ return;
147
+ settled = true;
148
+ clearTimeout(timer);
149
+ if (error === undefined)
150
+ resolve();
151
+ else
152
+ reject(error);
153
+ };
154
+ const timer = setTimeout(() => finish(new Error("Codex app-server WebSocket connection timed out")), timeoutMs);
155
+ timer.unref();
156
+ socket.addEventListener("open", () => finish(), { once: true });
157
+ socket.addEventListener("error", () => finish(new Error("Codex app-server WebSocket connection failed")), {
158
+ once: true,
159
+ });
160
+ });
161
+ }
162
+ function isRpcResponse(value) {
163
+ if (value === null || typeof value !== "object")
164
+ return false;
165
+ const candidate = value;
166
+ return typeof candidate.id === "number" && ("result" in candidate || "error" in candidate);
167
+ }
168
+ function isRpcNotification(value) {
169
+ if (value === null || typeof value !== "object")
170
+ return false;
171
+ const candidate = value;
172
+ return candidate.id === undefined && typeof candidate.method === "string";
173
+ }
174
+ //# sourceMappingURL=websocket-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"websocket-client.js","sourceRoot":"","sources":["../../../../src/provider/codex/websocket-client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,35 @@
1
+ export type ProviderName = "codex" | "claude";
2
+ export type SessionState = "active" | "idle" | "historical" | "unknown";
3
+ export type CapabilityConfidence = "verified" | "inferred" | "unavailable";
4
+ export interface ProviderSession {
5
+ provider: ProviderName;
6
+ vendorSessionId: string;
7
+ workspace: string | null;
8
+ title: string | null;
9
+ createdAt: Date | null;
10
+ updatedAt: Date | null;
11
+ state: SessionState;
12
+ stateConfidence: CapabilityConfidence;
13
+ indexed: boolean;
14
+ connected: boolean;
15
+ messageable: boolean;
16
+ }
17
+ export interface TranscriptEntry {
18
+ sourceId: string;
19
+ vendorSessionId: string;
20
+ role: "user" | "assistant" | "tool" | "system" | "other";
21
+ text: string;
22
+ occurredAt: Date | null;
23
+ }
24
+ export interface ProviderAdapter {
25
+ readonly name: ProviderName;
26
+ doctor(): Promise<ProviderDiagnostic>;
27
+ listSessions(): Promise<ProviderSession[]>;
28
+ readTranscript(vendorSessionId: string): Promise<TranscriptEntry[]>;
29
+ }
30
+ export interface ProviderDiagnostic {
31
+ provider: ProviderName;
32
+ available: boolean;
33
+ version: string | null;
34
+ detail: string;
35
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/provider/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,28 @@
1
+ export interface EmbeddingProvider {
2
+ /** Changes whenever embeddings produced by the provider are incompatible. */
3
+ readonly id: string;
4
+ readonly dimensions: number;
5
+ embed(text: string): readonly number[] | Promise<readonly number[]>;
6
+ }
7
+ export interface FeatureHashEmbeddingOptions {
8
+ dimensions?: number;
9
+ aliases?: Readonly<Record<string, readonly string[]>>;
10
+ }
11
+ /**
12
+ * A zero-dependency embedding for offline use and deterministic tests.
13
+ *
14
+ * It hashes word, word-pair, stem, character-trigram, and small alias features
15
+ * into a normalized vector. It is deliberately a lexical-semantic baseline,
16
+ * not a replacement for a learned embedding model.
17
+ */
18
+ export declare class DeterministicFeatureHashEmbedding implements EmbeddingProvider {
19
+ readonly id: string;
20
+ readonly dimensions: number;
21
+ private readonly aliases;
22
+ private readonly aliasLookup;
23
+ constructor(options?: FeatureHashEmbeddingOptions);
24
+ embed(text: string): readonly number[];
25
+ }
26
+ export declare function cosineSimilarity(left: readonly number[], right: readonly number[]): number;
27
+ /** High-entropy signed feature pairs used to select candidates without scanning chunks. */
28
+ export declare function embeddingBuckets(vector: readonly number[], limit?: number): string[];
@@ -0,0 +1,142 @@
1
+ const DEFAULT_ALIASES = {
2
+ authentication: ["auth", "login", "signin"],
3
+ database: ["db", "sqlite", "postgres", "mysql"],
4
+ failure: ["error", "failed", "outage", "incident"],
5
+ migration: ["migrate", "schema"],
6
+ retry: ["retries", "backoff", "reattempt"],
7
+ };
8
+ /**
9
+ * A zero-dependency embedding for offline use and deterministic tests.
10
+ *
11
+ * It hashes word, word-pair, stem, character-trigram, and small alias features
12
+ * into a normalized vector. It is deliberately a lexical-semantic baseline,
13
+ * not a replacement for a learned embedding model.
14
+ */
15
+ export class DeterministicFeatureHashEmbedding {
16
+ id;
17
+ dimensions;
18
+ aliases;
19
+ aliasLookup;
20
+ constructor(options = {}) {
21
+ this.dimensions = options.dimensions ?? 384;
22
+ if (!Number.isInteger(this.dimensions) || this.dimensions < 32) {
23
+ throw new RangeError("feature-hash dimensions must be an integer of at least 32");
24
+ }
25
+ this.aliases = options.aliases ?? DEFAULT_ALIASES;
26
+ this.aliasLookup = buildAliasLookup(this.aliases);
27
+ this.id = `feature-hash-v2:${this.dimensions}:${hashString(JSON.stringify(this.aliases)).toString(16)}`;
28
+ }
29
+ embed(text) {
30
+ const vector = new Float64Array(this.dimensions);
31
+ const words = normalizeWords(text);
32
+ const features = [];
33
+ for (let index = 0; index < words.length; index += 1) {
34
+ const word = words[index];
35
+ if (word === undefined)
36
+ continue;
37
+ features.push([`w:${word}`, 1]);
38
+ const stem = simpleStem(word);
39
+ if (stem !== word)
40
+ features.push([`s:${stem}`, 0.7]);
41
+ const concept = this.aliasLookup.get(word);
42
+ if (concept !== undefined)
43
+ features.push([`a:${concept}`, 1.1]);
44
+ const next = words[index + 1];
45
+ if (next !== undefined)
46
+ features.push([`b:${word}_${next}`, 0.8]);
47
+ if (word.length >= 4) {
48
+ const padded = `^${word}$`;
49
+ for (let offset = 0; offset <= padded.length - 3; offset += 1) {
50
+ features.push([`c:${padded.slice(offset, offset + 3)}`, 0.25]);
51
+ }
52
+ }
53
+ }
54
+ for (const [feature, weight] of features) {
55
+ const hash = hashString(feature);
56
+ const position = hash % this.dimensions;
57
+ const sign = (hash & 0x80000000) === 0 ? 1 : -1;
58
+ vector[position] = (vector[position] ?? 0) + sign * weight;
59
+ }
60
+ let magnitude = 0;
61
+ for (const value of vector)
62
+ magnitude += value * value;
63
+ magnitude = Math.sqrt(magnitude);
64
+ if (magnitude > 0) {
65
+ for (let index = 0; index < vector.length; index += 1) {
66
+ vector[index] = (vector[index] ?? 0) / magnitude;
67
+ }
68
+ }
69
+ return Array.from(vector);
70
+ }
71
+ }
72
+ export function cosineSimilarity(left, right) {
73
+ if (left.length !== right.length || left.length === 0)
74
+ return 0;
75
+ let dot = 0;
76
+ let leftMagnitude = 0;
77
+ let rightMagnitude = 0;
78
+ for (let index = 0; index < left.length; index += 1) {
79
+ const leftValue = left[index] ?? 0;
80
+ const rightValue = right[index] ?? 0;
81
+ dot += leftValue * rightValue;
82
+ leftMagnitude += leftValue * leftValue;
83
+ rightMagnitude += rightValue * rightValue;
84
+ }
85
+ if (leftMagnitude === 0 || rightMagnitude === 0)
86
+ return 0;
87
+ return dot / Math.sqrt(leftMagnitude * rightMagnitude);
88
+ }
89
+ /** High-entropy signed feature pairs used to select candidates without scanning chunks. */
90
+ export function embeddingBuckets(vector, limit = 8) {
91
+ const features = vector
92
+ .map((value, index) => ({ index, value }))
93
+ .filter(({ value }) => Math.abs(value) > 1e-9)
94
+ .sort((left, right) => Math.abs(right.value) - Math.abs(left.value) || left.index - right.index)
95
+ .slice(0, limit);
96
+ if (features.length === 1) {
97
+ const feature = features[0];
98
+ return [`single:${feature.index}:${feature.value >= 0 ? "+" : "-"}`];
99
+ }
100
+ const buckets = [];
101
+ for (let left = 0; left < features.length; left += 1) {
102
+ for (let right = left + 1; right < features.length; right += 1) {
103
+ const first = features[left];
104
+ const second = features[right];
105
+ if (first === undefined || second === undefined)
106
+ continue;
107
+ const ordered = first.index < second.index ? [first, second] : [second, first];
108
+ buckets.push(`pair:${ordered.map(({ index, value }) => `${index}:${value >= 0 ? "+" : "-"}`).join("|")}`);
109
+ }
110
+ }
111
+ return buckets;
112
+ }
113
+ function normalizeWords(text) {
114
+ return (text
115
+ .normalize("NFKD")
116
+ .replace(/\p{Mark}/gu, "")
117
+ .toLocaleLowerCase("en-US")
118
+ .match(/[\p{Letter}\p{Number}]+/gu) ?? []);
119
+ }
120
+ function simpleStem(word) {
121
+ if (word.length <= 4)
122
+ return word;
123
+ return word.replace(/(ingly|edly|ation|ments|ment|ing|ies|ied|ed|es|s)$/u, (suffix) => suffix === "ies" || suffix === "ied" ? "y" : "");
124
+ }
125
+ function buildAliasLookup(aliases) {
126
+ const lookup = new Map();
127
+ for (const [concept, words] of Object.entries(aliases)) {
128
+ lookup.set(concept, concept);
129
+ for (const word of words)
130
+ lookup.set(word, concept);
131
+ }
132
+ return lookup;
133
+ }
134
+ function hashString(value) {
135
+ let hash = 0x811c9dc5;
136
+ for (let index = 0; index < value.length; index += 1) {
137
+ hash ^= value.charCodeAt(index);
138
+ hash = Math.imul(hash, 0x01000193);
139
+ }
140
+ return hash >>> 0;
141
+ }
142
+ //# sourceMappingURL=embedding.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"embedding.js","sourceRoot":"","sources":["../../../src/recall/embedding.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,35 @@
1
+ import type { ProviderName } from "../provider/types.js";
2
+ export interface RecallOptions {
3
+ workspace: string;
4
+ providers?: readonly ProviderName[];
5
+ occurredAfter?: Date;
6
+ occurredBefore?: Date;
7
+ limit?: number;
8
+ maxPerSession?: number;
9
+ candidateLimit?: number;
10
+ }
11
+ export interface RecallCitation {
12
+ portalSessionId: string;
13
+ vendorSessionId: string;
14
+ provider: ProviderName;
15
+ workspace: string;
16
+ sourceId: string;
17
+ entryId: string;
18
+ occurredAt: Date | null;
19
+ uri: string;
20
+ }
21
+ export interface RecallEvidence {
22
+ chunkId: string;
23
+ excerpt: string;
24
+ score: number;
25
+ lexicalScore: number | null;
26
+ semanticScore: number | null;
27
+ citation: RecallCitation;
28
+ }
29
+ export interface RecallBundle {
30
+ query: string;
31
+ workspace: string;
32
+ evidence: RecallEvidence[];
33
+ truncated: boolean;
34
+ indexFreshness: Date | null;
35
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/recall/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,6 @@
1
+ export interface RpcClientOptions {
2
+ socketPath: string;
3
+ timeoutMs?: number;
4
+ signal?: AbortSignal;
5
+ }
6
+ export declare function callRpc<T>(options: RpcClientOptions, method: string, params?: unknown): Promise<T>;
@@ -0,0 +1,58 @@
1
+ import net from "node:net";
2
+ import { randomUUID } from "node:crypto";
3
+ import { isRpcFailure } from "./protocol.js";
4
+ export async function callRpc(options, method, params) {
5
+ const id = randomUUID();
6
+ const socket = net.createConnection(options.socketPath);
7
+ socket.setEncoding("utf8");
8
+ const timeoutMs = options.timeoutMs ?? 5_000;
9
+ return new Promise((resolve, reject) => {
10
+ let buffered = "";
11
+ let settled = false;
12
+ const timer = setTimeout(() => {
13
+ socket.destroy();
14
+ finish(() => reject(new Error(`RPC ${method} timed out after ${timeoutMs}ms`)));
15
+ }, timeoutMs);
16
+ const finish = (callback) => {
17
+ if (settled)
18
+ return;
19
+ settled = true;
20
+ clearTimeout(timer);
21
+ options.signal?.removeEventListener("abort", onAbort);
22
+ socket.end();
23
+ callback();
24
+ };
25
+ const onAbort = () => {
26
+ socket.destroy();
27
+ finish(() => reject(options.signal?.reason ?? new Error(`RPC ${method} aborted`)));
28
+ };
29
+ if (options.signal?.aborted === true) {
30
+ onAbort();
31
+ return;
32
+ }
33
+ options.signal?.addEventListener("abort", onAbort, { once: true });
34
+ socket.once("error", (error) => finish(() => reject(error)));
35
+ socket.on("data", (chunk) => {
36
+ buffered += chunk;
37
+ const newline = buffered.indexOf("\n");
38
+ if (newline < 0)
39
+ return;
40
+ try {
41
+ const response = JSON.parse(buffered.slice(0, newline));
42
+ if (response.id !== id)
43
+ throw new Error("RPC response ID mismatch");
44
+ if (isRpcFailure(response))
45
+ throw new Error(`${response.error.code}: ${response.error.message}`);
46
+ finish(() => resolve(response.result));
47
+ }
48
+ catch (error) {
49
+ finish(() => reject(error));
50
+ }
51
+ });
52
+ socket.once("connect", () => {
53
+ const request = params === undefined ? { id, method } : { id, method, params };
54
+ socket.write(`${JSON.stringify(request)}\n`);
55
+ });
56
+ });
57
+ }
58
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../../src/rpc/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ export declare const MAX_RPC_LINE_BYTES: number;
2
+ export interface RpcRequest {
3
+ id: string;
4
+ method: string;
5
+ params?: unknown;
6
+ }
7
+ export interface RpcSuccess {
8
+ id: string;
9
+ result: unknown;
10
+ }
11
+ export interface RpcFailure {
12
+ id: string;
13
+ error: {
14
+ code: string;
15
+ message: string;
16
+ data?: unknown;
17
+ };
18
+ }
19
+ export type RpcResponse = RpcSuccess | RpcFailure;
20
+ export declare function isRpcRequest(value: unknown): value is RpcRequest;
21
+ export declare function isRpcFailure(response: RpcResponse): response is RpcFailure;
@@ -0,0 +1,11 @@
1
+ export const MAX_RPC_LINE_BYTES = 1024 * 1024;
2
+ export function isRpcRequest(value) {
3
+ if (typeof value !== "object" || value === null)
4
+ return false;
5
+ const candidate = value;
6
+ return typeof candidate.id === "string" && typeof candidate.method === "string";
7
+ }
8
+ export function isRpcFailure(response) {
9
+ return "error" in response;
10
+ }
11
+ //# sourceMappingURL=protocol.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"protocol.js","sourceRoot":"","sources":["../../../src/rpc/protocol.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,kBAAkB,GAAG,IAAI,GAAG,IAAI,CAAC;AAwB9C,MAAM,UAAU,YAAY,CAAC,KAAc;IACzC,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,KAAK,CAAC;IAC9D,MAAM,SAAS,GAAG,KAAgC,CAAC;IACnD,OAAO,OAAO,SAAS,CAAC,EAAE,KAAK,QAAQ,IAAI,OAAO,SAAS,CAAC,MAAM,KAAK,QAAQ,CAAC;AAClF,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,QAAqB;IAChD,OAAO,OAAO,IAAI,QAAQ,CAAC;AAC7B,CAAC"}
@@ -0,0 +1,12 @@
1
+ import { type RpcRequest } from "./protocol.js";
2
+ export type RpcHandler = (request: RpcRequest) => Promise<unknown>;
3
+ export interface RpcServerOptions {
4
+ socketPath: string;
5
+ handler: RpcHandler;
6
+ }
7
+ export declare class RpcServer {
8
+ #private;
9
+ constructor(options: RpcServerOptions);
10
+ start(): Promise<void>;
11
+ close(): Promise<void>;
12
+ }