@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,276 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { normalizeSessionReference } from "../session-profile.js";
3
+ import { envelopeSchema } from "./protocol.js";
4
+ /** Bridges durable local task events to transport-independent relay envelopes. */
5
+ export class RemoteTaskManager {
6
+ #service;
7
+ #remote;
8
+ #unsubscribe;
9
+ constructor(service, remote) {
10
+ this.#service = service;
11
+ this.#remote = remote;
12
+ this.#unsubscribe = remote.onEnvelope((serverUrl, envelope) => this.#receive(serverUrl, envelope));
13
+ }
14
+ close() {
15
+ this.#unsubscribe();
16
+ }
17
+ async delegate(input) {
18
+ const sender = this.#requireLocalSession(input.senderSessionId);
19
+ const serverUrl = this.#requireServer(input.senderSessionId);
20
+ const localPresence = await this.#requireLocalPresence(serverUrl, input.senderSessionId);
21
+ const candidates = await this.#resolveCandidates(input.senderSessionId, input.target);
22
+ if (candidates.length !== 1) {
23
+ return {
24
+ delivery: "not_sent",
25
+ resolution: candidates.length === 0 ? "unresolved" : "ambiguous",
26
+ candidates: candidates.map(toCandidate),
27
+ };
28
+ }
29
+ const target = candidates[0];
30
+ const now = new Date();
31
+ const ttlSeconds = input.ttlSeconds ?? 3_600;
32
+ if (!Number.isInteger(ttlSeconds) || ttlSeconds < 30 || ttlSeconds > 86_400) {
33
+ throw new RangeError("remote task TTL must be between 30 and 86400 seconds");
34
+ }
35
+ const expiresAt = new Date(now.getTime() + ttlSeconds * 1_000);
36
+ const taskId = `task_${randomUUID()}`;
37
+ const event = {
38
+ eventId: `event_${randomUUID()}`,
39
+ taskId,
40
+ kind: "offer",
41
+ state: "offered",
42
+ createdAt: now.toISOString(),
43
+ objective: input.objective,
44
+ ...(input.context === undefined ? {} : { context: input.context }),
45
+ ...(input.expectedResult === undefined ? {} : { expectedResult: input.expectedResult }),
46
+ };
47
+ const envelope = createEnvelope(localPresence.routeId, target.routeId, event, now, expiresAt);
48
+ const record = this.#service.index.repository.recordRemoteTaskEvent({
49
+ serverUrl,
50
+ taskId,
51
+ eventId: event.eventId,
52
+ envelopeId: envelope.envelopeId,
53
+ localSessionId: sender.portalSessionId,
54
+ localRouteId: localPresence.routeId,
55
+ remoteRouteId: target.routeId,
56
+ direction: "outbound",
57
+ kind: event.kind,
58
+ state: event.state,
59
+ payload: event,
60
+ senderLabel: localSessionLabel(this.#service, sender.portalSessionId),
61
+ senderReference: localPresence.routeId,
62
+ authenticated: false,
63
+ occurredAt: now,
64
+ expiresAt,
65
+ });
66
+ const acknowledgement = await this.#remote.sendEnvelope(serverUrl, envelope);
67
+ if (acknowledgement.status !== "received") {
68
+ await this.#sendInternalUpdate(record.task, sender.portalSessionId, {
69
+ action: "failed",
70
+ error: acknowledgement.error ?? "remote agent rejected the task offer",
71
+ }, false);
72
+ throw new Error(acknowledgement.error ?? "remote agent rejected the task offer");
73
+ }
74
+ return { delivery: "delivered", task: record.task, target: toCandidate(target), acknowledgement };
75
+ }
76
+ async update(localSessionId, taskId, update) {
77
+ this.#requireLocalSession(localSessionId);
78
+ const serverUrl = this.#requireServer(localSessionId);
79
+ const task = this.#service.index.repository.getRemoteTask(serverUrl, taskId);
80
+ if (task === null || task.localSessionId !== localSessionId)
81
+ throw new Error(`unknown remote task: ${taskId}`);
82
+ return this.#sendInternalUpdate(task, localSessionId, update, true);
83
+ }
84
+ async runnerCompleted(completion) {
85
+ if (!isRemoteEvent(completion) || completion.kind !== "offer")
86
+ return;
87
+ const task = this.#service.index.repository.getRemoteTask(completion.serverUrl, completion.taskId);
88
+ if (task === null || (task.state !== "accepted" && task.state !== "running"))
89
+ return;
90
+ await this.#sendInternalUpdate(task, completion.localSessionId, {
91
+ action: "completed",
92
+ result: completion.answer?.trim() || "Remote agent completed the task without a textual result.",
93
+ }, true);
94
+ }
95
+ async runnerFailed(completion) {
96
+ if (!isRemoteEvent(completion) || completion.kind !== "offer" || completion.deliveryState !== "failed")
97
+ return;
98
+ const task = this.#service.index.repository.getRemoteTask(completion.serverUrl, completion.taskId);
99
+ if (task === null || task.state === "declined" || task.state === "completed" || task.state === "failed")
100
+ return;
101
+ await this.#sendInternalUpdate(task, completion.localSessionId, {
102
+ action: "failed",
103
+ error: completion.error ?? "managed remote task turn failed",
104
+ }, true);
105
+ }
106
+ async #receive(serverUrl, envelope) {
107
+ const receivedAt = new Date();
108
+ const localSessionId = await this.#remote.localSessionForRoute(serverUrl, envelope.targetRouteId);
109
+ if (localSessionId === null) {
110
+ await this.#remote.acknowledge(serverUrl, {
111
+ targetRouteId: envelope.targetRouteId,
112
+ envelopeId: envelope.envelopeId,
113
+ eventId: envelope.event.eventId,
114
+ status: "rejected",
115
+ receivedAt: receivedAt.toISOString(),
116
+ error: "target route is not owned by a local managed session",
117
+ });
118
+ return;
119
+ }
120
+ try {
121
+ if (Date.parse(envelope.expiresAt) <= receivedAt.getTime())
122
+ throw new Error("remote task event has expired");
123
+ let peer = null;
124
+ try {
125
+ peer = await this.#remote.peerByRoute(serverUrl, envelope.senderRouteId);
126
+ }
127
+ catch {
128
+ // The routed envelope remains usable if presence changes after dispatch.
129
+ }
130
+ this.#service.index.repository.recordRemoteTaskEvent({
131
+ serverUrl,
132
+ taskId: envelope.event.taskId,
133
+ eventId: envelope.event.eventId,
134
+ envelopeId: envelope.envelopeId,
135
+ localSessionId,
136
+ localRouteId: envelope.targetRouteId,
137
+ remoteRouteId: envelope.senderRouteId,
138
+ direction: "inbound",
139
+ kind: envelope.event.kind,
140
+ state: envelope.event.state,
141
+ payload: envelope.event,
142
+ senderLabel: peer?.agentName ?? `remote-${envelope.senderRouteId}`,
143
+ senderReference: envelope.senderRouteId,
144
+ authenticated: false,
145
+ occurredAt: new Date(envelope.event.createdAt),
146
+ expiresAt: new Date(envelope.expiresAt),
147
+ });
148
+ await this.#remote.acknowledge(serverUrl, {
149
+ targetRouteId: envelope.targetRouteId,
150
+ envelopeId: envelope.envelopeId,
151
+ eventId: envelope.event.eventId,
152
+ status: "received",
153
+ receivedAt: receivedAt.toISOString(),
154
+ });
155
+ }
156
+ catch (error) {
157
+ await this.#remote.acknowledge(serverUrl, {
158
+ targetRouteId: envelope.targetRouteId,
159
+ envelopeId: envelope.envelopeId,
160
+ eventId: envelope.event.eventId,
161
+ status: "rejected",
162
+ receivedAt: receivedAt.toISOString(),
163
+ error: errorMessage(error).slice(0, 2_048),
164
+ });
165
+ }
166
+ }
167
+ async #sendInternalUpdate(task, localSessionId, update, send) {
168
+ if (task.localSessionId !== localSessionId)
169
+ throw new Error("remote task belongs to another local session");
170
+ const now = new Date();
171
+ if (task.expiresAt.getTime() <= now.getTime())
172
+ throw new Error("remote task has expired");
173
+ const event = taskEvent(task.taskId, update, now);
174
+ const envelope = createEnvelope(task.localRouteId, task.remoteRouteId, event, now, task.expiresAt);
175
+ const record = this.#service.index.repository.recordRemoteTaskEvent({
176
+ serverUrl: task.serverUrl,
177
+ taskId: task.taskId,
178
+ eventId: event.eventId,
179
+ envelopeId: envelope.envelopeId,
180
+ localSessionId,
181
+ localRouteId: task.localRouteId,
182
+ remoteRouteId: task.remoteRouteId,
183
+ direction: "outbound",
184
+ kind: event.kind,
185
+ state: event.state,
186
+ payload: event,
187
+ senderLabel: localSessionLabel(this.#service, localSessionId),
188
+ senderReference: task.localRouteId,
189
+ authenticated: false,
190
+ occurredAt: now,
191
+ expiresAt: task.expiresAt,
192
+ });
193
+ if (send) {
194
+ const acknowledgement = await this.#remote.sendEnvelope(task.serverUrl, envelope);
195
+ if (acknowledgement.status !== "received") {
196
+ throw new Error(acknowledgement.error ?? `remote agent rejected task event ${event.kind}`);
197
+ }
198
+ }
199
+ return record.event;
200
+ }
201
+ async #resolveCandidates(localSessionId, target) {
202
+ const routeLookup = target.startsWith("route_");
203
+ const sessionLookup = target.startsWith("ps_");
204
+ const peers = await this.#remote.discoverForSession(localSessionId, routeLookup || sessionLookup
205
+ ? { capability: "task", limit: 100 }
206
+ : { query: target, capability: "task", limit: 20 });
207
+ if (routeLookup)
208
+ return peers.filter(({ routeId }) => routeId === target);
209
+ if (sessionLookup)
210
+ return peers.filter(({ sessionId }) => sessionId === target);
211
+ const normalized = normalizeSessionReference(target);
212
+ return peers.filter(({ agentName }) => normalizeSessionReference(agentName) === normalized);
213
+ }
214
+ #requireLocalSession(sessionId) {
215
+ const session = this.#service.index.repository.getSession(sessionId);
216
+ if (session === null)
217
+ throw new Error(`unknown Portal session: ${sessionId}`);
218
+ return session;
219
+ }
220
+ #requireServer(sessionId) {
221
+ const serverUrl = this.#remote.serverForSession(sessionId);
222
+ if (serverUrl === null)
223
+ throw new Error("calling session is not connected to a remote Portal server");
224
+ return serverUrl;
225
+ }
226
+ async #requireLocalPresence(serverUrl, sessionId) {
227
+ const presence = await this.#remote.localRoute(serverUrl, sessionId);
228
+ if (presence === null)
229
+ throw new Error("calling session is not advertised on its Portal server");
230
+ return presence;
231
+ }
232
+ }
233
+ function createEnvelope(senderRouteId, targetRouteId, event, sentAt, expiresAt) {
234
+ return envelopeSchema.parse({
235
+ envelopeId: `envelope_${randomUUID()}`,
236
+ senderRouteId,
237
+ targetRouteId,
238
+ sentAt: sentAt.toISOString(),
239
+ expiresAt: expiresAt.toISOString(),
240
+ event,
241
+ });
242
+ }
243
+ function taskEvent(taskId, update, now) {
244
+ const base = { eventId: `event_${randomUUID()}`, taskId, createdAt: now.toISOString() };
245
+ switch (update.action) {
246
+ case "accepted": return { ...base, kind: "accepted", state: "accepted", ...(update.message === undefined ? {} : { message: update.message }) };
247
+ case "declined": return { ...base, kind: "declined", state: "declined", ...(update.reason === undefined ? {} : { reason: update.reason }) };
248
+ case "running": return { ...base, kind: "running", state: "running", ...(update.message === undefined ? {} : { message: update.message }) };
249
+ case "progress": return { ...base, kind: "progress", state: "running", message: update.message };
250
+ case "question": return { ...base, kind: "question", state: "running", question: update.question };
251
+ case "answer": return { ...base, kind: "answer", state: "running", answer: update.answer };
252
+ case "completed": return { ...base, kind: "completed", state: "completed", result: update.result, ...(update.artifactReferences === undefined ? {} : { artifactReferences: update.artifactReferences }) };
253
+ case "failed": return { ...base, kind: "failed", state: "failed", error: update.error };
254
+ }
255
+ }
256
+ function localSessionLabel(service, sessionId) {
257
+ const session = service.index.repository.getSession(sessionId);
258
+ const profile = service.index.repository.getSessionProfile(sessionId);
259
+ return profile?.displayName ?? session?.managedName ?? session?.title ?? session?.provider ?? "local-agent";
260
+ }
261
+ function toCandidate(peer) {
262
+ return {
263
+ routeId: peer.routeId,
264
+ agentName: peer.agentName,
265
+ description: peer.description,
266
+ state: peer.state,
267
+ authenticated: false,
268
+ };
269
+ }
270
+ function isRemoteEvent(value) {
271
+ return "eventId" in value && "serverUrl" in value;
272
+ }
273
+ function errorMessage(error) {
274
+ return error instanceof Error ? error.message : String(error);
275
+ }
276
+ //# sourceMappingURL=tasks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tasks.js","sourceRoot":"","sources":["../../../src/network/tasks.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ import type { TranscriptEntry } from "./provider/types.js";
2
+ import { type EmbeddingProvider } from "./recall/embedding.js";
3
+ import type { RecallBundle, RecallOptions } from "./recall/types.js";
4
+ import { PortalDatabase } from "./storage/database.js";
5
+ import { PortalRepository, type IngestionResult, type SessionUpsert, type StoredSession } from "./storage/repository.js";
6
+ export interface PortalIndexOptions {
7
+ databasePath: string;
8
+ embeddingProvider?: EmbeddingProvider;
9
+ }
10
+ /** Durable session inventory, transcript ingestion, and bounded hybrid recall. */
11
+ export declare class PortalIndex {
12
+ readonly database: PortalDatabase;
13
+ readonly repository: PortalRepository;
14
+ readonly embeddingProvider: EmbeddingProvider;
15
+ constructor(options: PortalIndexOptions);
16
+ close(): void;
17
+ upsertSession(input: SessionUpsert): StoredSession;
18
+ ingestTranscript(portalSessionId: string, entries: readonly TranscriptEntry[]): Promise<IngestionResult>;
19
+ recall(query: string, options: RecallOptions): Promise<RecallBundle>;
20
+ }
21
+ export declare function redactSecrets(text: string): string;
@@ -0,0 +1,140 @@
1
+ import { DeterministicFeatureHashEmbedding, } from "./recall/embedding.js";
2
+ import { PortalDatabase } from "./storage/database.js";
3
+ import { compileFtsQuery, PortalRepository, } from "./storage/repository.js";
4
+ /** Durable session inventory, transcript ingestion, and bounded hybrid recall. */
5
+ export class PortalIndex {
6
+ database;
7
+ repository;
8
+ embeddingProvider;
9
+ constructor(options) {
10
+ this.database = new PortalDatabase(options.databasePath);
11
+ this.repository = new PortalRepository(this.database);
12
+ this.embeddingProvider = options.embeddingProvider ?? new DeterministicFeatureHashEmbedding();
13
+ }
14
+ close() {
15
+ this.database.close();
16
+ }
17
+ upsertSession(input) {
18
+ return this.repository.upsertSession(input);
19
+ }
20
+ async ingestTranscript(portalSessionId, entries) {
21
+ const sanitized = entries.map((entry) => ({ ...entry, text: redactSecrets(entry.text) }));
22
+ const result = this.repository.ingestTranscript(portalSessionId, sanitized);
23
+ const missing = this.repository.chunksNeedingEmbedding(portalSessionId, this.embeddingProvider.id);
24
+ const embeddings = [];
25
+ for (let offset = 0; offset < missing.length; offset += 32) {
26
+ embeddings.push(...await Promise.all(missing.slice(offset, offset + 32).map(async (chunk) => ({
27
+ chunkId: chunk.chunkId,
28
+ vector: await this.embeddingProvider.embed(chunk.text),
29
+ }))));
30
+ }
31
+ for (const { vector } of embeddings) {
32
+ if (vector.length !== this.embeddingProvider.dimensions) {
33
+ throw new Error(`embedding provider ${this.embeddingProvider.id} returned ${vector.length} dimensions; expected ${this.embeddingProvider.dimensions}`);
34
+ }
35
+ }
36
+ this.repository.saveEmbeddings(this.embeddingProvider.id, embeddings);
37
+ this.repository.markSessionIndexed(portalSessionId);
38
+ return result;
39
+ }
40
+ async recall(query, options) {
41
+ if (options.workspace.length === 0)
42
+ throw new TypeError("recall requires a non-empty workspace");
43
+ const limit = clampInteger(options.limit ?? 5, 1, 50, "limit");
44
+ const maxPerSession = clampInteger(options.maxPerSession ?? Math.min(2, limit), 1, limit, "maxPerSession");
45
+ const candidateLimit = clampInteger(options.candidateLimit ?? Math.max(limit * 8, 40), limit, 500, "candidateLimit");
46
+ const candidateQuery = {
47
+ workspace: options.workspace,
48
+ ...(options.providers === undefined ? {} : { providers: options.providers }),
49
+ ...(options.occurredAfter === undefined ? {} : { occurredAfter: options.occurredAfter }),
50
+ ...(options.occurredBefore === undefined ? {} : { occurredBefore: options.occurredBefore }),
51
+ limit: candidateLimit,
52
+ };
53
+ const lexical = this.repository.lexicalCandidates(compileFtsQuery(query), candidateQuery);
54
+ const vector = await this.embeddingProvider.embed(query);
55
+ if (vector.length !== this.embeddingProvider.dimensions) {
56
+ throw new Error(`embedding provider ${this.embeddingProvider.id} returned ${vector.length} dimensions; expected ${this.embeddingProvider.dimensions}`);
57
+ }
58
+ const semantic = this.repository.semanticCandidates(this.embeddingProvider.id, vector, candidateQuery);
59
+ const candidates = new Map();
60
+ for (let index = 0; index < lexical.length; index += 1) {
61
+ const candidate = lexical[index];
62
+ if (candidate === undefined)
63
+ continue;
64
+ candidates.set(candidate.chunkId, {
65
+ chunkId: candidate.chunkId,
66
+ excerpt: candidate.text,
67
+ portalSessionId: candidate.citation.portalSessionId,
68
+ citation: candidate.citation,
69
+ score: 1 / (60 + index + 1),
70
+ lexicalScore: 1 / (1 + Math.abs(candidate.lexicalRank)),
71
+ semanticScore: null,
72
+ });
73
+ }
74
+ for (let index = 0; index < semantic.length; index += 1) {
75
+ const candidate = semantic[index];
76
+ if (candidate === undefined)
77
+ continue;
78
+ const current = candidates.get(candidate.chunkId);
79
+ if (current === undefined) {
80
+ candidates.set(candidate.chunkId, {
81
+ chunkId: candidate.chunkId,
82
+ excerpt: candidate.text,
83
+ portalSessionId: candidate.citation.portalSessionId,
84
+ citation: candidate.citation,
85
+ score: 0.9 / (60 + index + 1),
86
+ lexicalScore: null,
87
+ semanticScore: candidate.similarity,
88
+ });
89
+ }
90
+ else {
91
+ current.score += 0.9 / (60 + index + 1);
92
+ current.semanticScore = candidate.similarity;
93
+ }
94
+ }
95
+ const ranked = [...candidates.values()].sort((left, right) => right.score - left.score || left.chunkId.localeCompare(right.chunkId));
96
+ const sessionCounts = new Map();
97
+ const evidence = [];
98
+ for (const candidate of ranked) {
99
+ const count = sessionCounts.get(candidate.portalSessionId) ?? 0;
100
+ if (count >= maxPerSession)
101
+ continue;
102
+ sessionCounts.set(candidate.portalSessionId, count + 1);
103
+ evidence.push({
104
+ chunkId: candidate.chunkId,
105
+ excerpt: candidate.excerpt,
106
+ score: candidate.score,
107
+ lexicalScore: candidate.lexicalScore,
108
+ semanticScore: candidate.semanticScore,
109
+ citation: candidate.citation,
110
+ });
111
+ if (evidence.length === limit)
112
+ break;
113
+ }
114
+ return {
115
+ query,
116
+ workspace: options.workspace,
117
+ evidence,
118
+ truncated: ranked.length > evidence.length,
119
+ indexFreshness: this.repository.workspaceFreshness(options.workspace),
120
+ };
121
+ }
122
+ }
123
+ const SECRET_PATTERNS = [
124
+ /-----BEGIN [A-Z ]*PRIVATE KEY-----[\s\S]*?-----END [A-Z ]*PRIVATE KEY-----/g,
125
+ /\b(?:sk-(?:proj-)?|sk-ant-)[A-Za-z0-9_-]{16,}\b/g,
126
+ /\b(?:ghp|github_pat)_[A-Za-z0-9_]{20,}\b/g,
127
+ /\bAKIA[0-9A-Z]{16}\b/g,
128
+ /\bBearer\s+[A-Za-z0-9._~+\/-]{16,}=*/gi,
129
+ /\b(?:API_KEY|ACCESS_TOKEN|AUTH_TOKEN|SECRET_KEY|PASSWORD)\s*[=:]\s*[^\s,;]+/gi,
130
+ ];
131
+ export function redactSecrets(text) {
132
+ return SECRET_PATTERNS.reduce((value, pattern) => value.replace(pattern, "[REDACTED_SECRET]"), text);
133
+ }
134
+ function clampInteger(value, minimum, maximum, name) {
135
+ if (!Number.isInteger(value) || value < minimum || value > maximum) {
136
+ throw new RangeError(`${name} must be an integer between ${minimum} and ${maximum}`);
137
+ }
138
+ return value;
139
+ }
140
+ //# sourceMappingURL=portal-index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"portal-index.js","sourceRoot":"","sources":["../../src/portal-index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,34 @@
1
+ import type { Options, SDKMessage, SDKUserMessage } from "@anthropic-ai/claude-agent-sdk";
2
+ export type ClaudeManagedState = "launching" | "active" | "idle" | "requires_action" | "closed";
3
+ export interface ClaudeManagedSessionStatus {
4
+ vendorSessionId: string | null;
5
+ state: ClaudeManagedState;
6
+ connected: boolean;
7
+ messageable: boolean;
8
+ }
9
+ export interface ClaudeManagedSessionOptions {
10
+ cwd: string;
11
+ /** Optional caller-minted UUID for stable identity before the init event. */
12
+ sessionId?: string;
13
+ }
14
+ export interface ClaudeManagedQuery extends AsyncIterable<SDKMessage> {
15
+ close(): void;
16
+ interrupt(): Promise<unknown>;
17
+ }
18
+ export type ClaudeManagedQueryFactory = (params: {
19
+ prompt: AsyncIterable<SDKUserMessage>;
20
+ options: Pick<Options, "cwd" | "persistSession" | "sessionId">;
21
+ }) => ClaudeManagedQuery;
22
+ /**
23
+ * A live handle only for a Claude process Portal launches and keeps attached.
24
+ * It does not attach to, or prove liveness for, independently launched sessions.
25
+ */
26
+ export declare class ClaudeManagedSession {
27
+ #private;
28
+ constructor(options: ClaudeManagedSessionOptions, queryFactory?: ClaudeManagedQueryFactory);
29
+ get status(): Readonly<ClaudeManagedSessionStatus>;
30
+ send(text: string): string;
31
+ interrupt(): Promise<void>;
32
+ close(): void;
33
+ events(): AsyncGenerator<SDKMessage, void>;
34
+ }
@@ -0,0 +1,125 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { query } from "@anthropic-ai/claude-agent-sdk";
3
+ const defaultQueryFactory = (params) => query(params);
4
+ class AsyncInputQueue {
5
+ #pending = [];
6
+ #waiters = [];
7
+ #ended = false;
8
+ push(message) {
9
+ if (this.#ended)
10
+ throw new Error("Claude managed session input is closed");
11
+ const waiter = this.#waiters.shift();
12
+ if (waiter)
13
+ waiter({ done: false, value: message });
14
+ else
15
+ this.#pending.push(message);
16
+ }
17
+ end() {
18
+ if (this.#ended)
19
+ return;
20
+ this.#ended = true;
21
+ for (const waiter of this.#waiters.splice(0))
22
+ waiter({ done: true, value: undefined });
23
+ }
24
+ [Symbol.asyncIterator]() {
25
+ return {
26
+ next: () => {
27
+ const message = this.#pending.shift();
28
+ if (message)
29
+ return Promise.resolve({ done: false, value: message });
30
+ if (this.#ended)
31
+ return Promise.resolve({ done: true, value: undefined });
32
+ return new Promise((resolve) => this.#waiters.push(resolve));
33
+ },
34
+ };
35
+ }
36
+ }
37
+ /**
38
+ * A live handle only for a Claude process Portal launches and keeps attached.
39
+ * It does not attach to, or prove liveness for, independently launched sessions.
40
+ */
41
+ export class ClaudeManagedSession {
42
+ #input = new AsyncInputQueue();
43
+ #query;
44
+ #eventsClaimed = false;
45
+ #status;
46
+ constructor(options, queryFactory = defaultQueryFactory) {
47
+ this.#status = {
48
+ vendorSessionId: options.sessionId ?? null,
49
+ state: "launching",
50
+ connected: false,
51
+ messageable: true,
52
+ };
53
+ this.#query = queryFactory({
54
+ prompt: this.#input,
55
+ options: {
56
+ cwd: options.cwd,
57
+ persistSession: true,
58
+ ...(options.sessionId === undefined ? {} : { sessionId: options.sessionId }),
59
+ },
60
+ });
61
+ }
62
+ get status() {
63
+ return { ...this.#status };
64
+ }
65
+ send(text) {
66
+ if (!this.#status.messageable)
67
+ throw new Error("Claude managed session is not messageable");
68
+ if (text.trim().length === 0)
69
+ throw new Error("Claude managed session input cannot be empty");
70
+ const uuid = randomUUID();
71
+ this.#input.push({
72
+ type: "user",
73
+ message: { role: "user", content: text },
74
+ parent_tool_use_id: null,
75
+ timestamp: new Date().toISOString(),
76
+ uuid,
77
+ });
78
+ return uuid;
79
+ }
80
+ async interrupt() {
81
+ if (this.#status.state === "closed")
82
+ return;
83
+ await this.#query.interrupt();
84
+ }
85
+ close() {
86
+ if (this.#status.state === "closed")
87
+ return;
88
+ this.#input.end();
89
+ this.#query.close();
90
+ this.#markClosed();
91
+ }
92
+ async *events() {
93
+ if (this.#eventsClaimed)
94
+ throw new Error("Claude managed session events can only be consumed once");
95
+ this.#eventsClaimed = true;
96
+ try {
97
+ for await (const event of this.#query) {
98
+ this.#status = { ...this.#status, connected: true };
99
+ if (event.type === "system" && event.subtype === "init") {
100
+ this.#status = { ...this.#status, vendorSessionId: event.session_id, state: "active" };
101
+ }
102
+ else if (event.type === "system" && event.subtype === "session_state_changed") {
103
+ this.#status = {
104
+ ...this.#status,
105
+ state: event.state === "running" ? "active" : event.state,
106
+ };
107
+ }
108
+ yield event;
109
+ }
110
+ }
111
+ finally {
112
+ this.#input.end();
113
+ this.#markClosed();
114
+ }
115
+ }
116
+ #markClosed() {
117
+ this.#status = {
118
+ ...this.#status,
119
+ state: "closed",
120
+ connected: false,
121
+ messageable: false,
122
+ };
123
+ }
124
+ }
125
+ //# sourceMappingURL=claude-managed.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude-managed.js","sourceRoot":"","sources":["../../../src/provider/claude-managed.ts"],"names":[],"mappings":"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"}