@agent-native/core 0.111.4 → 0.112.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/corpus/README.md +2 -2
- package/corpus/core/CHANGELOG.md +12 -0
- package/corpus/core/package.json +3 -1
- package/corpus/core/src/cli/code-agent-executor.ts +17 -5
- package/corpus/core/src/cli/code-agent-runs.ts +43 -2
- package/corpus/core/src/cli/multi-frontier-runs.ts +841 -0
- package/corpus/core/src/coding-tools/index.ts +27 -8
- package/corpus/core/src/embeddings/index.ts +233 -0
- package/corpus/core/src/index.ts +2 -0
- package/corpus/core/src/search/index.ts +413 -0
- package/corpus/templates/brain/.agents/skills/brain/RUNBOOK.md +48 -5
- package/corpus/templates/brain/.agents/skills/brain/SKILL.md +46 -14
- package/corpus/templates/brain/README.md +34 -3
- package/corpus/templates/brain/actions/approve-proposal.ts +2 -0
- package/corpus/templates/brain/actions/claim-distillation.ts +24 -27
- package/corpus/templates/brain/actions/create-source.ts +1 -1
- package/corpus/templates/brain/actions/get-knowledge.ts +6 -2
- package/corpus/templates/brain/actions/get-pilot-report.ts +44 -8
- package/corpus/templates/brain/actions/import-capture.ts +21 -9
- package/corpus/templates/brain/actions/import-transcript.ts +42 -14
- package/corpus/templates/brain/actions/list-captures.ts +10 -1
- package/corpus/templates/brain/actions/list-distillation-queue.ts +39 -14
- package/corpus/templates/brain/actions/list-projects.ts +51 -0
- package/corpus/templates/brain/actions/list-proposals.ts +80 -4
- package/corpus/templates/brain/actions/list-sources.ts +17 -3
- package/corpus/templates/brain/actions/manage-project.ts +118 -0
- package/corpus/templates/brain/actions/mark-capture-distilled.ts +68 -20
- package/corpus/templates/brain/actions/navigate.ts +1 -0
- package/corpus/templates/brain/actions/reject-proposal.ts +6 -1
- package/corpus/templates/brain/actions/resanitize-captures.ts +159 -33
- package/corpus/templates/brain/actions/review-proposal.ts +2 -0
- package/corpus/templates/brain/actions/search-everything.ts +10 -1
- package/corpus/templates/brain/actions/search-knowledge.ts +1 -1
- package/corpus/templates/brain/actions/set-settings.ts +36 -1
- package/corpus/templates/brain/actions/update-proposal.ts +2 -0
- package/corpus/templates/brain/app/hooks/use-distillation-bridge.ts +18 -9
- package/corpus/templates/brain/app/hooks/use-navigation-state.ts +3 -0
- package/corpus/templates/brain/app/i18n-data.ts +731 -2
- package/corpus/templates/brain/app/lib/brain.ts +33 -1
- package/corpus/templates/brain/app/routes/ops.tsx +47 -0
- package/corpus/templates/brain/app/routes/review.tsx +41 -2
- package/corpus/templates/brain/app/routes/search.tsx +33 -2
- package/corpus/templates/brain/app/routes/settings.tsx +158 -0
- package/corpus/templates/brain/app/routes/sources.tsx +31 -0
- package/corpus/templates/brain/changelog/2026-07-19-added-private-source-safe-semantic-search.md +6 -0
- package/corpus/templates/brain/jobs/process-ingest-queue.ts +270 -36
- package/corpus/templates/brain/package.json +1 -0
- package/corpus/templates/brain/server/db/index.ts +18 -0
- package/corpus/templates/brain/server/db/schema.ts +197 -1
- package/corpus/templates/brain/server/jobs/distillation-queue.ts +12 -5
- package/corpus/templates/brain/server/lib/audiences.ts +708 -0
- package/corpus/templates/brain/server/lib/brain-health.ts +251 -38
- package/corpus/templates/brain/server/lib/brain.ts +877 -50
- package/corpus/templates/brain/server/lib/capture-sanitization.ts +217 -53
- package/corpus/templates/brain/server/lib/connectors.ts +556 -70
- package/corpus/templates/brain/server/lib/demo.ts +17 -4
- package/corpus/templates/brain/server/lib/hybrid-search.ts +363 -0
- package/corpus/templates/brain/server/lib/ingest-queue.ts +104 -0
- package/corpus/templates/brain/server/lib/privacy-readiness.ts +24 -0
- package/corpus/templates/brain/server/lib/search-index-contracts.ts +72 -0
- package/corpus/templates/brain/server/lib/search-index.ts +714 -0
- package/corpus/templates/brain/server/lib/search.ts +120 -4
- package/corpus/templates/brain/server/lib/sensitivity-policy.ts +174 -0
- package/corpus/templates/brain/server/lib/slack-events.ts +281 -0
- package/corpus/templates/brain/server/onboarding.ts +29 -0
- package/corpus/templates/brain/server/plugins/db.ts +204 -0
- package/corpus/templates/brain/server/register-secrets.ts +46 -0
- package/corpus/templates/brain/server/routes/api/_agent-native/brain/ingest.post.ts +36 -16
- package/corpus/templates/brain/server/routes/api/_agent-native/brain/slack-events.post.ts +28 -0
- package/corpus/templates/brain/shared/types.ts +10 -0
- package/dist/cli/code-agent-executor.d.ts +8 -9
- package/dist/cli/code-agent-executor.d.ts.map +1 -1
- package/dist/cli/code-agent-executor.js +9 -3
- package/dist/cli/code-agent-executor.js.map +1 -1
- package/dist/cli/code-agent-runs.d.ts +5 -0
- package/dist/cli/code-agent-runs.d.ts.map +1 -1
- package/dist/cli/code-agent-runs.js +33 -2
- package/dist/cli/code-agent-runs.js.map +1 -1
- package/dist/cli/multi-frontier-runs.d.ts +131 -0
- package/dist/cli/multi-frontier-runs.d.ts.map +1 -0
- package/dist/cli/multi-frontier-runs.js +529 -0
- package/dist/cli/multi-frontier-runs.js.map +1 -0
- package/dist/coding-tools/index.d.ts +1 -0
- package/dist/coding-tools/index.d.ts.map +1 -1
- package/dist/coding-tools/index.js +25 -7
- package/dist/coding-tools/index.js.map +1 -1
- package/dist/collab/awareness.d.ts +2 -2
- package/dist/collab/awareness.d.ts.map +1 -1
- package/dist/embeddings/index.d.ts +24 -0
- package/dist/embeddings/index.d.ts.map +1 -0
- package/dist/embeddings/index.js +172 -0
- package/dist/embeddings/index.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/notifications/routes.d.ts +3 -3
- package/dist/progress/routes.d.ts +1 -1
- package/dist/resources/handlers.d.ts +1 -1
- package/dist/search/index.d.ts +88 -0
- package/dist/search/index.d.ts.map +1 -0
- package/dist/search/index.js +267 -0
- package/dist/search/index.js.map +1 -0
- package/package.json +3 -1
|
@@ -1,9 +1,11 @@
|
|
|
1
|
+
import { getDbExec } from "@agent-native/core/db";
|
|
1
2
|
import { runWithRequestContext } from "@agent-native/core/server/request-context";
|
|
2
3
|
import { and, asc, eq, isNull, lte, or } from "drizzle-orm";
|
|
3
4
|
|
|
4
5
|
import { getDb, schema } from "../server/db/index.js";
|
|
5
6
|
import {
|
|
6
7
|
nowIso,
|
|
8
|
+
nanoid,
|
|
7
9
|
parseJson,
|
|
8
10
|
readBrainAgentGuidance,
|
|
9
11
|
stableJson,
|
|
@@ -15,6 +17,7 @@ type SourceRow = typeof schema.brainSources.$inferSelect;
|
|
|
15
17
|
|
|
16
18
|
export interface DistillationAgentContext {
|
|
17
19
|
queue: QueueRow;
|
|
20
|
+
claimToken: string;
|
|
18
21
|
capture: CaptureRow;
|
|
19
22
|
source: SourceRow;
|
|
20
23
|
payload: Record<string, unknown>;
|
|
@@ -91,7 +94,26 @@ async function loadCaptureAndSource(row: QueueRow) {
|
|
|
91
94
|
return { capture, source };
|
|
92
95
|
}
|
|
93
96
|
|
|
94
|
-
|
|
97
|
+
function claimedRowCondition(row: QueueRow, claimToken?: string) {
|
|
98
|
+
return claimToken
|
|
99
|
+
? and(
|
|
100
|
+
eq(schema.brainIngestQueue.id, row.id),
|
|
101
|
+
eq(schema.brainIngestQueue.status, "processing"),
|
|
102
|
+
eq(schema.brainIngestQueue.leaseToken, claimToken),
|
|
103
|
+
)
|
|
104
|
+
: and(
|
|
105
|
+
eq(schema.brainIngestQueue.id, row.id),
|
|
106
|
+
eq(schema.brainIngestQueue.status, row.status),
|
|
107
|
+
eq(schema.brainIngestQueue.updatedAt, row.updatedAt),
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
async function markFailed(
|
|
112
|
+
row: QueueRow,
|
|
113
|
+
message: string,
|
|
114
|
+
payload: object,
|
|
115
|
+
claimToken?: string,
|
|
116
|
+
) {
|
|
95
117
|
const now = nowIso();
|
|
96
118
|
await getDb()
|
|
97
119
|
.update(schema.brainIngestQueue)
|
|
@@ -99,15 +121,18 @@ async function markFailed(row: QueueRow, message: string, payload: object) {
|
|
|
99
121
|
status: "failed",
|
|
100
122
|
payloadJson: stableJson(payload),
|
|
101
123
|
error: message,
|
|
124
|
+
leaseToken: null,
|
|
125
|
+
leaseExpiresAt: null,
|
|
102
126
|
updatedAt: now,
|
|
103
127
|
})
|
|
104
|
-
.where(
|
|
128
|
+
.where(claimedRowCondition(row, claimToken));
|
|
105
129
|
}
|
|
106
130
|
|
|
107
131
|
async function requeueDistillation(
|
|
108
132
|
row: QueueRow,
|
|
109
133
|
message: string,
|
|
110
134
|
payload: object,
|
|
135
|
+
claimToken: string,
|
|
111
136
|
) {
|
|
112
137
|
const now = nowIso();
|
|
113
138
|
await getDb()
|
|
@@ -117,24 +142,61 @@ async function requeueDistillation(
|
|
|
117
142
|
payloadJson: stableJson(payload),
|
|
118
143
|
error: message,
|
|
119
144
|
runAfter: recheckAt(now),
|
|
145
|
+
leaseToken: null,
|
|
146
|
+
leaseExpiresAt: null,
|
|
120
147
|
updatedAt: now,
|
|
121
148
|
})
|
|
122
|
-
.where(
|
|
149
|
+
.where(claimedRowCondition(row, claimToken));
|
|
123
150
|
}
|
|
124
151
|
|
|
125
|
-
async function claimForHeadlessRunner(row: QueueRow, payload: object) {
|
|
152
|
+
export async function claimForHeadlessRunner(row: QueueRow, payload: object) {
|
|
126
153
|
const now = nowIso();
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
.
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
error
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
154
|
+
const claimToken = nanoid(16);
|
|
155
|
+
const leaseExpiresAt = new Date(
|
|
156
|
+
Date.parse(now) + STALE_PROCESSING_MS,
|
|
157
|
+
).toISOString();
|
|
158
|
+
const result = await getDbExec().execute({
|
|
159
|
+
sql: `UPDATE brain_ingest_queue
|
|
160
|
+
SET status = ?, attempts = ?, payload_json = ?, error = NULL,
|
|
161
|
+
run_after = NULL, lease_token = ?, lease_expires_at = ?, updated_at = ?
|
|
162
|
+
WHERE id = ? AND status = ? AND updated_at = ?`,
|
|
163
|
+
args: [
|
|
164
|
+
"processing",
|
|
165
|
+
row.attempts + 1,
|
|
166
|
+
stableJson(payload),
|
|
167
|
+
claimToken,
|
|
168
|
+
leaseExpiresAt,
|
|
169
|
+
now,
|
|
170
|
+
row.id,
|
|
171
|
+
row.status,
|
|
172
|
+
row.updatedAt,
|
|
173
|
+
],
|
|
174
|
+
});
|
|
175
|
+
return result.rowsAffected > 0 ? claimToken : null;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
async function runDeterministicOperation(
|
|
179
|
+
row: QueueRow,
|
|
180
|
+
context: NonNullable<Awaited<ReturnType<typeof loadCaptureAndSource>>>,
|
|
181
|
+
) {
|
|
182
|
+
if (row.operation === "search-index") {
|
|
183
|
+
const { indexBrainCapture } = await import("../server/lib/search-index.js");
|
|
184
|
+
await indexBrainCapture(context.capture.id);
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
if (row.operation === "search-unindex") {
|
|
188
|
+
const { unindexBrainCapture } =
|
|
189
|
+
await import("../server/lib/search-index.js");
|
|
190
|
+
await unindexBrainCapture(context.capture.id);
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
if (row.operation === "slack-thread-refresh") {
|
|
194
|
+
const { refreshSlackThreadCapture } =
|
|
195
|
+
await import("../server/lib/connectors.js");
|
|
196
|
+
await refreshSlackThreadCapture(context.source, row.payloadJson);
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
throw new Error(`Unsupported ingest queue operation: ${row.operation}`);
|
|
138
200
|
}
|
|
139
201
|
|
|
140
202
|
async function latestQueueRow(rowId: string) {
|
|
@@ -146,6 +208,19 @@ async function latestQueueRow(rowId: string) {
|
|
|
146
208
|
return updated;
|
|
147
209
|
}
|
|
148
210
|
|
|
211
|
+
async function markOperationDone(row: QueueRow, claimToken: string) {
|
|
212
|
+
await getDb()
|
|
213
|
+
.update(schema.brainIngestQueue)
|
|
214
|
+
.set({
|
|
215
|
+
status: "done",
|
|
216
|
+
leaseToken: null,
|
|
217
|
+
leaseExpiresAt: null,
|
|
218
|
+
error: null,
|
|
219
|
+
updatedAt: nowIso(),
|
|
220
|
+
})
|
|
221
|
+
.where(claimedRowCondition(row, claimToken));
|
|
222
|
+
}
|
|
223
|
+
|
|
149
224
|
function buildDistillationMessage(
|
|
150
225
|
context: DistillationAgentContext,
|
|
151
226
|
guidance: Awaited<ReturnType<typeof readBrainAgentGuidance>>["guidance"],
|
|
@@ -176,7 +251,7 @@ function buildDistillationMessage(
|
|
|
176
251
|
"1. Call get-capture with includeRawContent=true for this capture id when exact quote validation is needed.",
|
|
177
252
|
"2. Extract only durable company knowledge with exact source quotes.",
|
|
178
253
|
"3. Call write-knowledge for supported entries or proposals.",
|
|
179
|
-
|
|
254
|
+
`4. Call mark-capture-distilled with captureId=${context.capture.id}, queueId=${context.queue.id}, and claimToken=${context.claimToken} when finished, or mark ignored if excluded.`,
|
|
180
255
|
]
|
|
181
256
|
.filter(Boolean)
|
|
182
257
|
.join("\n");
|
|
@@ -260,11 +335,13 @@ export async function processBrainIngestQueueOnce(
|
|
|
260
335
|
const payload = parseJson<Record<string, unknown>>(row.payloadJson, {});
|
|
261
336
|
if (row.operation === "distill") {
|
|
262
337
|
if (!options.runDistillation) {
|
|
263
|
-
await claimForHeadlessRunner(row, payload);
|
|
338
|
+
const claimToken = await claimForHeadlessRunner(row, payload);
|
|
339
|
+
if (!claimToken) continue;
|
|
264
340
|
await requeueDistillation(
|
|
265
341
|
row,
|
|
266
342
|
"Distillation is still queued; no distillation worker completed this item.",
|
|
267
343
|
{ ...payload, lastDistillationCheckAt: now },
|
|
344
|
+
claimToken,
|
|
268
345
|
);
|
|
269
346
|
deferred.push(row.id);
|
|
270
347
|
continue;
|
|
@@ -288,7 +365,8 @@ export async function processBrainIngestQueueOnce(
|
|
|
288
365
|
? payload.headlessClaimCount + 1
|
|
289
366
|
: 1,
|
|
290
367
|
};
|
|
291
|
-
await claimForHeadlessRunner(row, nextPayload);
|
|
368
|
+
const claimToken = await claimForHeadlessRunner(row, nextPayload);
|
|
369
|
+
if (!claimToken) continue;
|
|
292
370
|
|
|
293
371
|
try {
|
|
294
372
|
const runner =
|
|
@@ -300,7 +378,14 @@ export async function processBrainIngestQueueOnce(
|
|
|
300
378
|
},
|
|
301
379
|
() =>
|
|
302
380
|
runner({
|
|
303
|
-
queue:
|
|
381
|
+
queue: {
|
|
382
|
+
...row,
|
|
383
|
+
attempts: row.attempts + 1,
|
|
384
|
+
payloadJson: stableJson(nextPayload),
|
|
385
|
+
status: "processing",
|
|
386
|
+
leaseToken: claimToken,
|
|
387
|
+
},
|
|
388
|
+
claimToken,
|
|
304
389
|
capture: contextRows.capture,
|
|
305
390
|
source: contextRows.source,
|
|
306
391
|
payload: nextPayload,
|
|
@@ -310,16 +395,23 @@ export async function processBrainIngestQueueOnce(
|
|
|
310
395
|
const message = err instanceof Error ? err.message : String(err);
|
|
311
396
|
const failedPermanently = row.attempts + 1 >= MAX_ATTEMPTS;
|
|
312
397
|
if (failedPermanently) {
|
|
313
|
-
await markFailed(
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
398
|
+
await markFailed(
|
|
399
|
+
row,
|
|
400
|
+
message,
|
|
401
|
+
{ ...nextPayload, failedAt: nowIso() },
|
|
402
|
+
claimToken,
|
|
403
|
+
);
|
|
317
404
|
failed.push(row.id);
|
|
318
405
|
} else {
|
|
319
|
-
await requeueDistillation(
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
406
|
+
await requeueDistillation(
|
|
407
|
+
row,
|
|
408
|
+
message,
|
|
409
|
+
{
|
|
410
|
+
...nextPayload,
|
|
411
|
+
lastHeadlessDistillationErrorAt: nowIso(),
|
|
412
|
+
},
|
|
413
|
+
claimToken,
|
|
414
|
+
);
|
|
323
415
|
deferred.push(row.id);
|
|
324
416
|
}
|
|
325
417
|
continue;
|
|
@@ -333,6 +425,7 @@ export async function processBrainIngestQueueOnce(
|
|
|
333
425
|
row,
|
|
334
426
|
"Headless distillation agent did not mark this capture distilled or ignored.",
|
|
335
427
|
{ ...nextPayload, failedAt: nowIso() },
|
|
428
|
+
claimToken,
|
|
336
429
|
);
|
|
337
430
|
failed.push(row.id);
|
|
338
431
|
} else {
|
|
@@ -340,22 +433,163 @@ export async function processBrainIngestQueueOnce(
|
|
|
340
433
|
row,
|
|
341
434
|
"Headless distillation agent did not mark this capture distilled or ignored.",
|
|
342
435
|
{ ...nextPayload, lastHeadlessDistillationAt: nowIso() },
|
|
436
|
+
claimToken,
|
|
343
437
|
);
|
|
344
438
|
deferred.push(row.id);
|
|
345
439
|
}
|
|
346
440
|
continue;
|
|
347
441
|
}
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
442
|
+
if (row.operation === "search-unindex") {
|
|
443
|
+
if (!row.captureId) {
|
|
444
|
+
await markFailed(row, "Search unindex operation had no capture id.", {
|
|
445
|
+
...payload,
|
|
446
|
+
failedAt: now,
|
|
447
|
+
});
|
|
448
|
+
failed.push(row.id);
|
|
449
|
+
continue;
|
|
450
|
+
}
|
|
451
|
+
const claimToken = await claimForHeadlessRunner(row, payload);
|
|
452
|
+
if (!claimToken) continue;
|
|
453
|
+
try {
|
|
454
|
+
const { unindexBrainCapture } =
|
|
455
|
+
await import("../server/lib/search-index.js");
|
|
456
|
+
await unindexBrainCapture(row.captureId);
|
|
457
|
+
await markOperationDone(row, claimToken);
|
|
458
|
+
processed.push(row.id);
|
|
459
|
+
} catch (error) {
|
|
460
|
+
await markFailed(
|
|
461
|
+
row,
|
|
462
|
+
error instanceof Error ? error.message : String(error),
|
|
463
|
+
{ ...payload, failedAt: nowIso() },
|
|
464
|
+
claimToken,
|
|
465
|
+
);
|
|
466
|
+
failed.push(row.id);
|
|
467
|
+
}
|
|
468
|
+
continue;
|
|
469
|
+
}
|
|
470
|
+
if (row.operation === "slack-thread-refresh") {
|
|
471
|
+
const [source] = row.sourceId
|
|
472
|
+
? await db
|
|
473
|
+
.select()
|
|
474
|
+
.from(schema.brainSources)
|
|
475
|
+
.where(eq(schema.brainSources.id, row.sourceId))
|
|
476
|
+
.limit(1)
|
|
477
|
+
: [];
|
|
478
|
+
if (!source) {
|
|
479
|
+
await markFailed(row, "Slack refresh source was missing.", {
|
|
480
|
+
...payload,
|
|
481
|
+
failedAt: now,
|
|
482
|
+
});
|
|
483
|
+
failed.push(row.id);
|
|
484
|
+
continue;
|
|
485
|
+
}
|
|
486
|
+
const claimToken = await claimForHeadlessRunner(row, payload);
|
|
487
|
+
if (!claimToken) continue;
|
|
488
|
+
try {
|
|
489
|
+
const { refreshSlackThreadCapture } =
|
|
490
|
+
await import("../server/lib/connectors.js");
|
|
491
|
+
await runWithRequestContext(
|
|
492
|
+
{
|
|
493
|
+
userEmail: source.ownerEmail,
|
|
494
|
+
orgId: source.orgId ?? undefined,
|
|
495
|
+
},
|
|
496
|
+
() => refreshSlackThreadCapture(source, row.payloadJson),
|
|
497
|
+
);
|
|
498
|
+
await markOperationDone(row, claimToken);
|
|
499
|
+
processed.push(row.id);
|
|
500
|
+
} catch (error) {
|
|
501
|
+
await markFailed(
|
|
502
|
+
row,
|
|
503
|
+
error instanceof Error ? error.message : String(error),
|
|
504
|
+
{ ...payload, failedAt: nowIso() },
|
|
505
|
+
claimToken,
|
|
506
|
+
);
|
|
507
|
+
failed.push(row.id);
|
|
508
|
+
}
|
|
509
|
+
continue;
|
|
510
|
+
}
|
|
511
|
+
if (row.operation === "sync") {
|
|
512
|
+
const [source] = row.sourceId
|
|
513
|
+
? await db
|
|
514
|
+
.select()
|
|
515
|
+
.from(schema.brainSources)
|
|
516
|
+
.where(eq(schema.brainSources.id, row.sourceId))
|
|
517
|
+
.limit(1)
|
|
518
|
+
: [];
|
|
519
|
+
if (!source) {
|
|
520
|
+
await markFailed(row, "Source sync operation had no source.", {
|
|
521
|
+
...payload,
|
|
522
|
+
failedAt: now,
|
|
523
|
+
});
|
|
524
|
+
failed.push(row.id);
|
|
525
|
+
continue;
|
|
526
|
+
}
|
|
527
|
+
const claimToken = await claimForHeadlessRunner(row, payload);
|
|
528
|
+
if (!claimToken) continue;
|
|
529
|
+
try {
|
|
530
|
+
const { runConnectorSync } =
|
|
531
|
+
await import("../server/lib/connectors.js");
|
|
532
|
+
await runWithRequestContext(
|
|
533
|
+
{
|
|
534
|
+
userEmail: source.ownerEmail,
|
|
535
|
+
orgId: source.orgId ?? undefined,
|
|
536
|
+
},
|
|
537
|
+
() => runConnectorSync(source),
|
|
538
|
+
);
|
|
539
|
+
await markOperationDone(row, claimToken);
|
|
540
|
+
processed.push(row.id);
|
|
541
|
+
} catch (error) {
|
|
542
|
+
await markFailed(
|
|
543
|
+
row,
|
|
544
|
+
error instanceof Error ? error.message : String(error),
|
|
545
|
+
{ ...payload, failedAt: nowIso() },
|
|
546
|
+
claimToken,
|
|
547
|
+
);
|
|
548
|
+
failed.push(row.id);
|
|
549
|
+
}
|
|
550
|
+
continue;
|
|
551
|
+
}
|
|
552
|
+
const contextRows = await loadCaptureAndSource(row);
|
|
553
|
+
if (!contextRows) {
|
|
554
|
+
await markFailed(row, "Queue capture or source was missing.", {
|
|
354
555
|
...payload,
|
|
355
556
|
failedAt: now,
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
|
|
557
|
+
});
|
|
558
|
+
failed.push(row.id);
|
|
559
|
+
continue;
|
|
560
|
+
}
|
|
561
|
+
const claimToken = await claimForHeadlessRunner(row, payload);
|
|
562
|
+
if (!claimToken) continue;
|
|
563
|
+
try {
|
|
564
|
+
await runWithRequestContext(
|
|
565
|
+
{
|
|
566
|
+
userEmail: contextRows.source.ownerEmail,
|
|
567
|
+
orgId: contextRows.source.orgId ?? undefined,
|
|
568
|
+
},
|
|
569
|
+
() => runDeterministicOperation(row, contextRows),
|
|
570
|
+
);
|
|
571
|
+
await markOperationDone(row, claimToken);
|
|
572
|
+
processed.push(row.id);
|
|
573
|
+
} catch (error) {
|
|
574
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
575
|
+
if (row.attempts + 1 >= MAX_ATTEMPTS) {
|
|
576
|
+
await markFailed(
|
|
577
|
+
row,
|
|
578
|
+
message,
|
|
579
|
+
{ ...payload, failedAt: nowIso() },
|
|
580
|
+
claimToken,
|
|
581
|
+
);
|
|
582
|
+
failed.push(row.id);
|
|
583
|
+
} else {
|
|
584
|
+
await requeueDistillation(
|
|
585
|
+
row,
|
|
586
|
+
message,
|
|
587
|
+
{ ...payload, lastOperationErrorAt: nowIso() },
|
|
588
|
+
claimToken,
|
|
589
|
+
);
|
|
590
|
+
deferred.push(row.id);
|
|
591
|
+
}
|
|
592
|
+
}
|
|
359
593
|
}
|
|
360
594
|
|
|
361
595
|
return { processed, deferred, failed };
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
"demo:seed": "agent-native action seed-demo-data",
|
|
15
15
|
"demo:eval": "agent-native action run-demo-eval",
|
|
16
16
|
"retrieval:eval": "agent-native action run-retrieval-eval",
|
|
17
|
+
"privacy:eval": "vitest --run evals/privacy-leakage.test.ts --config vitest.config.ts",
|
|
17
18
|
"eval:ci": "sh -c 'set -e; db=\"./data/brain-evals-ci-$$.db\"; cleanup() { rm -f \"$db\" \"$db-shm\" \"$db-wal\"; }; trap cleanup EXIT; cleanup; DATABASE_URL=\"file:$db\" AGENT_USER_EMAIL=\"brain-evals@agent-native.test\" agent-native action run-demo-eval; DATABASE_URL=\"file:$db\" AGENT_USER_EMAIL=\"brain-evals@agent-native.test\" agent-native action run-retrieval-eval'",
|
|
18
19
|
"script": "agent-native script"
|
|
19
20
|
},
|
|
@@ -13,6 +13,8 @@ registerShareableResource({
|
|
|
13
13
|
displayName: "Brain Source",
|
|
14
14
|
titleColumn: "title",
|
|
15
15
|
getResourcePath: (source) => `/sources/${source.id}`,
|
|
16
|
+
allowPublic: false,
|
|
17
|
+
requireOrgMemberForUserShares: true,
|
|
16
18
|
getDb,
|
|
17
19
|
});
|
|
18
20
|
|
|
@@ -23,6 +25,8 @@ registerShareableResource({
|
|
|
23
25
|
displayName: "Brain Knowledge",
|
|
24
26
|
titleColumn: "title",
|
|
25
27
|
getResourcePath: (knowledge) => `/knowledge/${knowledge.id}`,
|
|
28
|
+
allowPublic: false,
|
|
29
|
+
requireOrgMemberForUserShares: true,
|
|
26
30
|
getDb,
|
|
27
31
|
});
|
|
28
32
|
|
|
@@ -33,5 +37,19 @@ registerShareableResource({
|
|
|
33
37
|
displayName: "Brain Proposal",
|
|
34
38
|
titleColumn: "title",
|
|
35
39
|
getResourcePath: (proposal) => `/proposals/${proposal.id}`,
|
|
40
|
+
allowPublic: false,
|
|
41
|
+
requireOrgMemberForUserShares: true,
|
|
42
|
+
getDb,
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
registerShareableResource({
|
|
46
|
+
type: "brain-project",
|
|
47
|
+
resourceTable: schema.brainProjects,
|
|
48
|
+
sharesTable: schema.brainProjectShares,
|
|
49
|
+
displayName: "Brain Project",
|
|
50
|
+
titleColumn: "title",
|
|
51
|
+
getResourcePath: (project) => `/search?projectId=${project.id}`,
|
|
52
|
+
allowPublic: false,
|
|
53
|
+
requireOrgMemberForUserShares: true,
|
|
36
54
|
getDb,
|
|
37
55
|
});
|