@agent-native/core 0.111.3 → 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.
Files changed (109) hide show
  1. package/corpus/README.md +2 -2
  2. package/corpus/core/CHANGELOG.md +18 -0
  3. package/corpus/core/package.json +3 -1
  4. package/corpus/core/src/cli/code-agent-executor.ts +17 -5
  5. package/corpus/core/src/cli/code-agent-runs.ts +43 -2
  6. package/corpus/core/src/cli/migration-codemod.ts +59 -9
  7. package/corpus/core/src/cli/multi-frontier-runs.ts +841 -0
  8. package/corpus/core/src/coding-tools/index.ts +27 -8
  9. package/corpus/core/src/embeddings/index.ts +233 -0
  10. package/corpus/core/src/index.ts +2 -0
  11. package/corpus/core/src/search/index.ts +413 -0
  12. package/corpus/templates/brain/.agents/skills/brain/RUNBOOK.md +48 -5
  13. package/corpus/templates/brain/.agents/skills/brain/SKILL.md +46 -14
  14. package/corpus/templates/brain/README.md +34 -3
  15. package/corpus/templates/brain/actions/approve-proposal.ts +2 -0
  16. package/corpus/templates/brain/actions/claim-distillation.ts +24 -27
  17. package/corpus/templates/brain/actions/create-source.ts +1 -1
  18. package/corpus/templates/brain/actions/get-knowledge.ts +6 -2
  19. package/corpus/templates/brain/actions/get-pilot-report.ts +44 -8
  20. package/corpus/templates/brain/actions/import-capture.ts +21 -9
  21. package/corpus/templates/brain/actions/import-transcript.ts +42 -14
  22. package/corpus/templates/brain/actions/list-captures.ts +10 -1
  23. package/corpus/templates/brain/actions/list-distillation-queue.ts +39 -14
  24. package/corpus/templates/brain/actions/list-projects.ts +51 -0
  25. package/corpus/templates/brain/actions/list-proposals.ts +80 -4
  26. package/corpus/templates/brain/actions/list-sources.ts +17 -3
  27. package/corpus/templates/brain/actions/manage-project.ts +118 -0
  28. package/corpus/templates/brain/actions/mark-capture-distilled.ts +68 -20
  29. package/corpus/templates/brain/actions/navigate.ts +1 -0
  30. package/corpus/templates/brain/actions/reject-proposal.ts +6 -1
  31. package/corpus/templates/brain/actions/resanitize-captures.ts +159 -33
  32. package/corpus/templates/brain/actions/review-proposal.ts +2 -0
  33. package/corpus/templates/brain/actions/search-everything.ts +10 -1
  34. package/corpus/templates/brain/actions/search-knowledge.ts +1 -1
  35. package/corpus/templates/brain/actions/set-settings.ts +36 -1
  36. package/corpus/templates/brain/actions/update-proposal.ts +2 -0
  37. package/corpus/templates/brain/app/hooks/use-distillation-bridge.ts +18 -9
  38. package/corpus/templates/brain/app/hooks/use-navigation-state.ts +3 -0
  39. package/corpus/templates/brain/app/i18n-data.ts +731 -2
  40. package/corpus/templates/brain/app/lib/brain.ts +33 -1
  41. package/corpus/templates/brain/app/routes/ops.tsx +47 -0
  42. package/corpus/templates/brain/app/routes/review.tsx +41 -2
  43. package/corpus/templates/brain/app/routes/search.tsx +33 -2
  44. package/corpus/templates/brain/app/routes/settings.tsx +158 -0
  45. package/corpus/templates/brain/app/routes/sources.tsx +31 -0
  46. package/corpus/templates/brain/changelog/2026-07-19-added-private-source-safe-semantic-search.md +6 -0
  47. package/corpus/templates/brain/jobs/process-ingest-queue.ts +270 -36
  48. package/corpus/templates/brain/package.json +1 -0
  49. package/corpus/templates/brain/server/db/index.ts +18 -0
  50. package/corpus/templates/brain/server/db/schema.ts +197 -1
  51. package/corpus/templates/brain/server/jobs/distillation-queue.ts +12 -5
  52. package/corpus/templates/brain/server/lib/audiences.ts +708 -0
  53. package/corpus/templates/brain/server/lib/brain-health.ts +251 -38
  54. package/corpus/templates/brain/server/lib/brain.ts +877 -50
  55. package/corpus/templates/brain/server/lib/capture-sanitization.ts +217 -53
  56. package/corpus/templates/brain/server/lib/connectors.ts +556 -70
  57. package/corpus/templates/brain/server/lib/demo.ts +17 -4
  58. package/corpus/templates/brain/server/lib/hybrid-search.ts +363 -0
  59. package/corpus/templates/brain/server/lib/ingest-queue.ts +104 -0
  60. package/corpus/templates/brain/server/lib/privacy-readiness.ts +24 -0
  61. package/corpus/templates/brain/server/lib/search-index-contracts.ts +72 -0
  62. package/corpus/templates/brain/server/lib/search-index.ts +714 -0
  63. package/corpus/templates/brain/server/lib/search.ts +120 -4
  64. package/corpus/templates/brain/server/lib/sensitivity-policy.ts +174 -0
  65. package/corpus/templates/brain/server/lib/slack-events.ts +281 -0
  66. package/corpus/templates/brain/server/onboarding.ts +29 -0
  67. package/corpus/templates/brain/server/plugins/db.ts +204 -0
  68. package/corpus/templates/brain/server/register-secrets.ts +46 -0
  69. package/corpus/templates/brain/server/routes/api/_agent-native/brain/ingest.post.ts +36 -16
  70. package/corpus/templates/brain/server/routes/api/_agent-native/brain/slack-events.post.ts +28 -0
  71. package/corpus/templates/brain/shared/types.ts +10 -0
  72. package/dist/cli/code-agent-executor.d.ts +8 -9
  73. package/dist/cli/code-agent-executor.d.ts.map +1 -1
  74. package/dist/cli/code-agent-executor.js +9 -3
  75. package/dist/cli/code-agent-executor.js.map +1 -1
  76. package/dist/cli/code-agent-runs.d.ts +5 -0
  77. package/dist/cli/code-agent-runs.d.ts.map +1 -1
  78. package/dist/cli/code-agent-runs.js +33 -2
  79. package/dist/cli/code-agent-runs.js.map +1 -1
  80. package/dist/cli/migration-codemod.d.ts.map +1 -1
  81. package/dist/cli/migration-codemod.js +48 -10
  82. package/dist/cli/migration-codemod.js.map +1 -1
  83. package/dist/cli/multi-frontier-runs.d.ts +131 -0
  84. package/dist/cli/multi-frontier-runs.d.ts.map +1 -0
  85. package/dist/cli/multi-frontier-runs.js +529 -0
  86. package/dist/cli/multi-frontier-runs.js.map +1 -0
  87. package/dist/coding-tools/index.d.ts +1 -0
  88. package/dist/coding-tools/index.d.ts.map +1 -1
  89. package/dist/coding-tools/index.js +25 -7
  90. package/dist/coding-tools/index.js.map +1 -1
  91. package/dist/collab/awareness.d.ts +2 -2
  92. package/dist/collab/awareness.d.ts.map +1 -1
  93. package/dist/embeddings/index.d.ts +24 -0
  94. package/dist/embeddings/index.d.ts.map +1 -0
  95. package/dist/embeddings/index.js +172 -0
  96. package/dist/embeddings/index.js.map +1 -0
  97. package/dist/index.d.ts +2 -0
  98. package/dist/index.d.ts.map +1 -1
  99. package/dist/index.js +2 -0
  100. package/dist/index.js.map +1 -1
  101. package/dist/notifications/routes.d.ts +3 -3
  102. package/dist/progress/routes.d.ts +1 -1
  103. package/dist/resources/handlers.d.ts +1 -1
  104. package/dist/search/index.d.ts +88 -0
  105. package/dist/search/index.d.ts.map +1 -0
  106. package/dist/search/index.js +267 -0
  107. package/dist/search/index.js.map +1 -0
  108. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  109. 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
- async function markFailed(row: QueueRow, message: string, payload: object) {
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(eq(schema.brainIngestQueue.id, row.id));
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(eq(schema.brainIngestQueue.id, row.id));
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
- await getDb()
128
- .update(schema.brainIngestQueue)
129
- .set({
130
- status: "processing",
131
- attempts: row.attempts + 1,
132
- payloadJson: stableJson(payload),
133
- error: null,
134
- runAfter: null,
135
- updatedAt: now,
136
- })
137
- .where(eq(schema.brainIngestQueue.id, row.id));
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
- "4. Call mark-capture-distilled when finished, or mark ignored if excluded.",
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: row,
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(row, message, {
314
- ...nextPayload,
315
- failedAt: nowIso(),
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(row, message, {
320
- ...nextPayload,
321
- lastHeadlessDistillationErrorAt: nowIso(),
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
- await claimForHeadlessRunner(row, payload);
350
- await markFailed(
351
- row,
352
- `Unsupported ingest queue operation: ${row.operation}`,
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
- failed.push(row.id);
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
  });