@feltdb/core 0.13.0 → 0.15.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 (92) hide show
  1. package/dist/agent-runtime.d.ts +64 -2
  2. package/dist/agent-runtime.d.ts.map +1 -1
  3. package/dist/agent-runtime.js +121 -11
  4. package/dist/agent-state.d.ts +48 -0
  5. package/dist/agent-state.d.ts.map +1 -1
  6. package/dist/agent-state.js +174 -12
  7. package/dist/agent.d.ts +10 -1
  8. package/dist/agent.d.ts.map +1 -1
  9. package/dist/agent.js +10 -1
  10. package/dist/build-identity.json +4 -4
  11. package/dist/cli/commands.js +27 -6
  12. package/dist/collection.d.ts +3 -1
  13. package/dist/collection.d.ts.map +1 -1
  14. package/dist/collection.js +30 -8
  15. package/dist/create/build-identity.json +4 -4
  16. package/dist/create/cli.js +1 -1
  17. package/dist/create/create.js +4 -6
  18. package/dist/create/package-versions.js +1 -1
  19. package/dist/create/server-source/Cargo.lock +6 -6
  20. package/dist/create/server-source/Cargo.toml +1 -1
  21. package/dist/create/server-source/crates/feltdb/src/lib.rs +126 -35
  22. package/dist/create/server-source/crates/feltdb/src/state_contract.rs +162 -53
  23. package/dist/create/server-source/crates/feltdb/src/worker_mesh.rs +137 -1
  24. package/dist/create/server-source/crates/feltdb/src/workload.rs +1427 -91
  25. package/dist/create/server-source/crates/feltdb-client/Cargo.toml +1 -1
  26. package/dist/create/server-source/crates/feltdb-server/Cargo.toml +1 -1
  27. package/dist/create/server-source/crates/feltdb-server/README.md +6 -1
  28. package/dist/create/server-source/crates/feltdb-server/src/app_state.rs +9 -1
  29. package/dist/create/server-source/crates/feltdb-server/src/auth.rs +85 -25
  30. package/dist/create/server-source/crates/feltdb-server/src/backup.rs +4 -0
  31. package/dist/create/server-source/crates/feltdb-server/src/console_accounts.rs +1009 -0
  32. package/dist/create/server-source/crates/feltdb-server/src/control_authorization.rs +441 -0
  33. package/dist/create/server-source/crates/feltdb-server/src/identity.rs +68 -6
  34. package/dist/create/server-source/crates/feltdb-server/src/key_management.rs +355 -23
  35. package/dist/create/server-source/crates/feltdb-server/src/lib.rs +3 -0
  36. package/dist/create/server-source/crates/feltdb-server/src/main.rs +879 -84
  37. package/dist/create/server-source/crates/feltdb-server/src/redaction.rs +208 -0
  38. package/dist/create/server-source/crates/feltdb-server/src/tenancy.rs +198 -19
  39. package/dist/create/server-source/crates/feltdb-server/tests/transaction_precondition_contract.rs +403 -0
  40. package/dist/db.d.ts +64 -9
  41. package/dist/db.d.ts.map +1 -1
  42. package/dist/db.js +153 -27
  43. package/dist/deployment.d.ts +19 -0
  44. package/dist/deployment.d.ts.map +1 -1
  45. package/dist/deployment.js +38 -2
  46. package/dist/embedded-query.d.ts.map +1 -1
  47. package/dist/embedded-query.js +5 -4
  48. package/dist/embedded-transaction.d.ts +8 -4
  49. package/dist/embedded-transaction.d.ts.map +1 -1
  50. package/dist/embedded-transaction.js +55 -19
  51. package/dist/error-codes.d.ts +31 -2
  52. package/dist/error-codes.d.ts.map +1 -1
  53. package/dist/error-codes.js +41 -2
  54. package/dist/feltdb.d.ts +7 -0
  55. package/dist/feltdb.d.ts.map +1 -1
  56. package/dist/file-db.d.ts +27 -0
  57. package/dist/file-db.d.ts.map +1 -1
  58. package/dist/file-db.js +145 -7
  59. package/dist/http-client.d.ts +11 -3
  60. package/dist/http-client.d.ts.map +1 -1
  61. package/dist/http-client.js +27 -14
  62. package/dist/http-db.d.ts +27 -1
  63. package/dist/http-db.d.ts.map +1 -1
  64. package/dist/http-db.js +252 -54
  65. package/dist/index.js +1 -1
  66. package/dist/local-state-lock.d.ts +34 -0
  67. package/dist/local-state-lock.d.ts.map +1 -0
  68. package/dist/local-state-lock.js +225 -0
  69. package/dist/reactive-graph.d.ts +0 -3
  70. package/dist/reactive-graph.d.ts.map +1 -1
  71. package/dist/reactive-graph.js +11 -1
  72. package/dist/runtime-registry.d.ts +7 -2
  73. package/dist/runtime-registry.d.ts.map +1 -1
  74. package/dist/runtime-registry.js +2 -2
  75. package/dist/studio/components/index.js +1 -1
  76. package/dist/studio/{components-BSGmHfif.js → components-CJmzntBi.js} +2 -1
  77. package/dist/studio/index.js +1 -1
  78. package/dist/studio-app/assets/{feltdb_wasm-3hDngl1h.js → feltdb_wasm-BjM1ylL3.js} +1 -1
  79. package/dist/studio-app/assets/feltdb_wasm_bg-TseJn2Ax.wasm +0 -0
  80. package/dist/studio-app/assets/index-1wd0uKua.js +30 -0
  81. package/dist/studio-app/index.html +1 -1
  82. package/dist/transaction.d.ts +27 -11
  83. package/dist/transaction.d.ts.map +1 -1
  84. package/dist/transaction.js +20 -14
  85. package/dist/wasm/feltdb_wasm_bg.wasm +0 -0
  86. package/dist/wasm/package.json +1 -1
  87. package/dist/workload.d.ts +31 -3
  88. package/dist/workload.d.ts.map +1 -1
  89. package/dist/workload.js +28 -3
  90. package/package.json +1 -1
  91. package/dist/studio-app/assets/feltdb_wasm_bg-CFQT4gCy.wasm +0 -0
  92. package/dist/studio-app/assets/index-Dql1hS5m.js +0 -30
@@ -32,6 +32,13 @@ export const FELTDB_AGENT_CHECKPOINT_COLLECTION = '_feltdb.AgentCheckpoint';
32
32
  export const FELTDB_AGENT_MEMORY_COLLECTION = '_feltdb.AgentMemory';
33
33
  export const FELTDB_AGENT_HANDOFF_COLLECTION = '_feltdb.AgentHandoff';
34
34
  export const AGENT_CONTEXT_FORMAT = 'feltdb.agent-context@1';
35
+ /**
36
+ * Index keys written beside every task head so `listTasks` can filter by
37
+ * project with an equality prefix. Derived from `scope.project` and `status`
38
+ * on every task write; never returned as part of an `AgentTask`.
39
+ */
40
+ const TASK_PROJECT_FIELD = 'list_project';
41
+ const TASK_STATUS_PROJECT_FIELD = 'list_status_project';
35
42
  /** Compound indexes every agent-state query is planned against. */
36
43
  export const AGENT_STATE_INDEXES = [
37
44
  {
@@ -54,9 +61,73 @@ export const AGENT_STATE_INDEXES = [
54
61
  persistent: true,
55
62
  },
56
63
  },
64
+ // listTasks: one index per filter shape, each led by a distinct field, so
65
+ // every shape has exactly one compatible plan and none is a residual filter.
66
+ {
67
+ collection: FELTDB_AGENT_TASK_COLLECTION,
68
+ index: {
69
+ name: 'agent_tasks_by_updated',
70
+ type: 'compound',
71
+ fields: ['updated_at', 'id'],
72
+ directions: ['desc', 'asc'],
73
+ persistent: true,
74
+ },
75
+ },
76
+ {
77
+ collection: FELTDB_AGENT_TASK_COLLECTION,
78
+ index: {
79
+ name: 'agent_tasks_by_status_updated',
80
+ type: 'compound',
81
+ fields: ['status', 'updated_at', 'id'],
82
+ directions: ['asc', 'desc', 'asc'],
83
+ persistent: true,
84
+ },
85
+ },
86
+ {
87
+ collection: FELTDB_AGENT_TASK_COLLECTION,
88
+ index: {
89
+ name: 'agent_tasks_by_project_updated',
90
+ type: 'compound',
91
+ fields: [TASK_PROJECT_FIELD, 'updated_at', 'id'],
92
+ directions: ['asc', 'desc', 'asc'],
93
+ persistent: true,
94
+ },
95
+ },
96
+ {
97
+ collection: FELTDB_AGENT_TASK_COLLECTION,
98
+ index: {
99
+ name: 'agent_tasks_by_status_project_updated',
100
+ type: 'compound',
101
+ fields: [TASK_STATUS_PROJECT_FIELD, 'updated_at', 'id'],
102
+ directions: ['asc', 'desc', 'asc'],
103
+ persistent: true,
104
+ },
105
+ },
106
+ // listHandoffs
107
+ {
108
+ collection: FELTDB_AGENT_HANDOFF_COLLECTION,
109
+ index: {
110
+ name: 'agent_handoffs_by_created',
111
+ type: 'compound',
112
+ fields: ['created_at', 'id'],
113
+ directions: ['desc', 'asc'],
114
+ persistent: true,
115
+ },
116
+ },
117
+ {
118
+ collection: FELTDB_AGENT_HANDOFF_COLLECTION,
119
+ index: {
120
+ name: 'agent_handoffs_by_status_created',
121
+ type: 'compound',
122
+ fields: ['status', 'created_at', 'id'],
123
+ directions: ['asc', 'desc', 'asc'],
124
+ persistent: true,
125
+ },
126
+ },
57
127
  ];
58
128
  const TASK_STATUSES = ['ready', 'running', 'blocked', 'completed', 'cancelled'];
59
129
  const TERMINAL = ['completed', 'cancelled'];
130
+ const HANDOFF_STATUSES = ['open', 'claimed', 'accepted'];
60
131
  /** Every refusal. A refused write committed nothing. */
61
132
  export class AgentStateError extends Error {
62
133
  code;
@@ -150,6 +221,26 @@ function strip(row) {
150
221
  const { id: _id, __version, ...rest } = row;
151
222
  return { ...rest, revision: typeof __version === 'number' ? __version : 1 };
152
223
  }
224
+ /** A task row without its derived index keys. */
225
+ function toTask(row) {
226
+ const { [TASK_PROJECT_FIELD]: _project, [TASK_STATUS_PROJECT_FIELD]: _statusProject, ...task } = strip(row);
227
+ return task;
228
+ }
229
+ /** A task head as written: the task plus the index keys `listTasks` filters on. */
230
+ function taskHead(task) {
231
+ const project = task.scope?.project;
232
+ return {
233
+ ...task,
234
+ ...(project === undefined ? {} : {
235
+ [TASK_PROJECT_FIELD]: project,
236
+ [TASK_STATUS_PROJECT_FIELD]: statusProjectKey(task.status, project),
237
+ }),
238
+ };
239
+ }
240
+ function statusProjectKey(status, project) {
241
+ // A status never contains '|', so the first '|' separates the two.
242
+ return `${status}|${project}`;
243
+ }
153
244
  function version(row) {
154
245
  return typeof row.__version === 'number' ? row.__version : 1;
155
246
  }
@@ -270,7 +361,7 @@ export class AgentStateStore {
270
361
  };
271
362
  try {
272
363
  await this.db.transaction(tx => {
273
- tx.collection(FELTDB_AGENT_TASK_COLLECTION).set(taskId, task, { requireAbsent: true });
364
+ tx.collection(FELTDB_AGENT_TASK_COLLECTION).set(taskId, taskHead(task), { requireAbsent: true });
274
365
  tx.collection(FELTDB_AGENT_CHECKPOINT_COLLECTION).set(checkpoint.checkpoint_id, checkpoint, { requireAbsent: true });
275
366
  });
276
367
  }
@@ -286,7 +377,7 @@ export class AgentStateStore {
286
377
  const row = await this.taskRow(identifier(taskId, 'taskId'));
287
378
  if (!row)
288
379
  return null;
289
- const task = strip(row);
380
+ const task = toTask(row);
290
381
  const checkpoint = await this.getCheckpoint(task.task_id, task.checkpoint_version);
291
382
  if (!checkpoint) {
292
383
  throw fail('NOT_FOUND', `task ${taskId} names checkpoint ${task.checkpoint_version}, which is not committed`);
@@ -300,6 +391,30 @@ export class AgentStateStore {
300
391
  const { revision: _revision, ...checkpoint } = strip(row);
301
392
  return checkpoint;
302
393
  }
394
+ /**
395
+ * One bounded page of tasks, most recently updated first (ties by task id),
396
+ * optionally narrowed to a status and/or a project.
397
+ *
398
+ * Every filter shape is answered by one declared compound index with an
399
+ * equality prefix; nothing reads the whole collection. Continue with
400
+ * `cursor: page.nextCursor` and the same filters.
401
+ */
402
+ async listTasks(input = {}) {
403
+ if (input.status !== undefined && !TASK_STATUSES.includes(input.status)) {
404
+ throw fail('INVALID_REQUEST', `status must be one of ${TASK_STATUSES.join(', ')}`);
405
+ }
406
+ const project = input.project === undefined ? undefined : name(input.project, 'project');
407
+ const where = project === undefined
408
+ ? (input.status === undefined ? [] : [{ field: 'status', eq: input.status }])
409
+ : input.status === undefined
410
+ ? [{ field: TASK_PROJECT_FIELD, eq: project }]
411
+ : [{ field: TASK_STATUS_PROJECT_FIELD, eq: statusProjectKey(input.status, project) }];
412
+ const page = await this.page(FELTDB_AGENT_TASK_COLLECTION, where, 'updated_at', input.limit, input.cursor);
413
+ return {
414
+ tasks: page.records.map(toTask),
415
+ ...(page.nextCursor ? { nextCursor: page.nextCursor } : {}),
416
+ };
417
+ }
303
418
  /**
304
419
  * Commit checkpoint N+1 atomically with the task head.
305
420
  *
@@ -323,7 +438,7 @@ export class AgentStateStore {
323
438
  throw fail('INVALID_REQUEST', `evidence must be an array of at most ${LIST_LIMIT} references`);
324
439
  }
325
440
  const row = await this.requireTask(id);
326
- const task = strip(row);
441
+ const task = toTask(row);
327
442
  if (input.expectedVersion !== undefined && input.expectedVersion !== task.checkpoint_version) {
328
443
  throw fail('VERSION_CONFLICT', `task ${id} is at checkpoint ${task.checkpoint_version}, not ${input.expectedVersion}`, {
329
444
  expected: input.expectedVersion, current: task.checkpoint_version,
@@ -369,7 +484,7 @@ export class AgentStateStore {
369
484
  };
370
485
  try {
371
486
  await this.db.transaction(tx => {
372
- tx.collection(FELTDB_AGENT_TASK_COLLECTION).set(id, head, { ifVersion: version(row) });
487
+ tx.collection(FELTDB_AGENT_TASK_COLLECTION).set(id, taskHead(head), { ifVersion: version(row) });
373
488
  tx.collection(FELTDB_AGENT_CHECKPOINT_COLLECTION).set(next.checkpoint_id, next, { requireAbsent: true });
374
489
  for (const entry of cited) {
375
490
  if (entry.evidence.kind === 'record') {
@@ -400,7 +515,7 @@ export class AgentStateStore {
400
515
  */
401
516
  async resume(taskId, input) {
402
517
  const row = await this.requireTask(identifier(taskId, 'taskId'));
403
- this.assertOwner(strip(row), name(input.actor, 'actor'));
518
+ this.assertOwner(toTask(row), name(input.actor, 'actor'));
404
519
  return this.assembleContext(taskId, input);
405
520
  }
406
521
  // --------------------------------------------------------------- memory
@@ -414,7 +529,7 @@ export class AgentStateStore {
414
529
  const scopeKey = memoryScopeKey(scope);
415
530
  if (taskId || scope.kind === 'task') {
416
531
  const owningTask = taskId ?? scope.taskId;
417
- const task = strip(await this.requireTask(owningTask));
532
+ const task = toTask(await this.requireTask(owningTask));
418
533
  if (scope.kind === 'task' && scope.taskId !== task.task_id) {
419
534
  throw fail('INVALID_REQUEST', `memory for task ${task.task_id} cannot be written to task scope ${scope.taskId}`);
420
535
  }
@@ -481,7 +596,7 @@ export class AgentStateStore {
481
596
  * its workspace. A memory scoped to another task is never returned.
482
597
  */
483
598
  async recallForTask(taskId, input = {}) {
484
- const task = strip(await this.requireTask(identifier(taskId, 'taskId')));
599
+ const task = toTask(await this.requireTask(identifier(taskId, 'taskId')));
485
600
  const limit = boundedLimit(input.limit, 20, 100);
486
601
  const scopes = [
487
602
  { kind: 'task', taskId: task.task_id },
@@ -572,7 +687,7 @@ export class AgentStateStore {
572
687
  const actor = name(input.actor, 'actor');
573
688
  const to = input.to === undefined ? undefined : name(input.to, 'to');
574
689
  const row = await this.requireTask(id);
575
- const task = strip(row);
690
+ const task = toTask(row);
576
691
  this.assertOwner(task, actor);
577
692
  if (TERMINAL.includes(task.status))
578
693
  throw fail('INVALID_TRANSITION', `task ${id} is ${task.status}; it cannot be handed off`);
@@ -633,12 +748,34 @@ export class AgentStateStore {
633
748
  }
634
749
  return resolveHandoff({ ...record, revision: 1 }, task, checkpoint);
635
750
  }
751
+ /**
752
+ * One bounded page of handoff records, newest first (ties by handoff id).
753
+ * `open: true` lists the handoffs nobody has claimed yet. Indexed; never a
754
+ * collection scan.
755
+ */
756
+ async listHandoffs(input = {}) {
757
+ if (input.open === false) {
758
+ throw fail('INVALID_REQUEST', "open: false is ambiguous; pass status: 'claimed' or 'accepted'");
759
+ }
760
+ if (input.status !== undefined && !HANDOFF_STATUSES.includes(input.status)) {
761
+ throw fail('INVALID_REQUEST', `status must be one of ${HANDOFF_STATUSES.join(', ')}`);
762
+ }
763
+ if (input.open && input.status !== undefined && input.status !== 'open') {
764
+ throw fail('INVALID_REQUEST', `open: true contradicts status: '${input.status}'`);
765
+ }
766
+ const status = input.open ? 'open' : input.status;
767
+ const page = await this.page(FELTDB_AGENT_HANDOFF_COLLECTION, status === undefined ? [] : [{ field: 'status', eq: status }], 'created_at', input.limit, input.cursor);
768
+ return {
769
+ handoffs: page.records.map(row => strip(row)),
770
+ ...(page.nextCursor ? { nextCursor: page.nextCursor } : {}),
771
+ };
772
+ }
636
773
  async getHandoff(handoffId) {
637
774
  const row = await this.db.collection(FELTDB_AGENT_HANDOFF_COLLECTION).get(identifier(handoffId, 'handoffId', 128));
638
775
  if (!row)
639
776
  return null;
640
777
  const record = strip(row);
641
- const task = strip(await this.requireTask(record.task_id));
778
+ const task = toTask(await this.requireTask(record.task_id));
642
779
  const checkpoint = await this.getCheckpoint(record.task_id, record.checkpoint_version);
643
780
  if (!checkpoint)
644
781
  throw fail('NOT_FOUND', `handoff ${handoffId} references checkpoint ${record.checkpoint_version}, which is not committed`);
@@ -664,7 +801,7 @@ export class AgentStateStore {
664
801
  const first = await handoffs.get(id);
665
802
  if (!first)
666
803
  throw fail('NOT_FOUND', `handoff ${id} does not exist`);
667
- const task = strip(await this.requireTask(strip(first).task_id));
804
+ const task = toTask(await this.requireTask(strip(first).task_id));
668
805
  // Decide on a handoff read taken after the task read. A claim commits both
669
806
  // records together, so this pair can never show a claimed task beside an
670
807
  // open handoff, which would misreport a lost race as a stale handoff.
@@ -710,7 +847,7 @@ export class AgentStateStore {
710
847
  try {
711
848
  await this.db.transaction(tx => {
712
849
  tx.collection(FELTDB_AGENT_HANDOFF_COLLECTION).set(id, claimed, { ifVersion: handoff.revision });
713
- tx.collection(FELTDB_AGENT_TASK_COLLECTION).set(task.task_id, head, { ifVersion: task.revision });
850
+ tx.collection(FELTDB_AGENT_TASK_COLLECTION).set(task.task_id, taskHead(head), { ifVersion: task.revision });
714
851
  });
715
852
  }
716
853
  catch (error) {
@@ -760,7 +897,7 @@ export class AgentStateStore {
760
897
  }
761
898
  throw error;
762
899
  }
763
- const task = strip(await this.requireTask(handoff.task_id));
900
+ const task = toTask(await this.requireTask(handoff.task_id));
764
901
  return this.resolveRecord({ ...accepted, revision: handoff.revision + 1 }, task);
765
902
  }
766
903
  // -------------------------------------------------------------- context
@@ -894,6 +1031,31 @@ export class AgentStateStore {
894
1031
  return bundle;
895
1032
  }
896
1033
  // ------------------------------------------------------------- internal
1034
+ async page(collection, where, newestFirst, limit, cursor) {
1035
+ if (cursor !== undefined && (typeof cursor !== 'string' || !cursor)) {
1036
+ throw fail('INVALID_REQUEST', 'cursor must be the nextCursor of a previous page');
1037
+ }
1038
+ let page;
1039
+ try {
1040
+ page = await this.db.query({
1041
+ collection,
1042
+ ...(where.length ? { where } : {}),
1043
+ orderBy: [{ field: newestFirst, direction: 'desc' }],
1044
+ limit: boundedLimit(limit, 50, 1_000),
1045
+ ...(cursor ? { cursor } : {}),
1046
+ });
1047
+ }
1048
+ catch (error) {
1049
+ if (/INVALID_CURSOR/.test(error instanceof Error ? error.message : String(error))) {
1050
+ throw fail('INVALID_REQUEST', 'cursor does not belong to this query; pass the nextCursor of a page with the same filters');
1051
+ }
1052
+ throw error;
1053
+ }
1054
+ return {
1055
+ records: page.records,
1056
+ ...(page.nextCursor && !page.exhausted ? { nextCursor: page.nextCursor } : {}),
1057
+ };
1058
+ }
897
1059
  async taskRow(taskId) {
898
1060
  return this.db.collection(FELTDB_AGENT_TASK_COLLECTION).get(taskId);
899
1061
  }
package/dist/agent.d.ts CHANGED
@@ -19,7 +19,11 @@ export interface AgentRef {
19
19
  toString(): string;
20
20
  }
21
21
  /**
22
- * Lifecycle states for agent execution
22
+ * Lifecycle states for agent execution.
23
+ *
24
+ * `Completed`, `Failed` and `Cancelled` are terminal. `Cancelled` is reachable
25
+ * from every non-terminal state, through `AgentRuntime.cancel` or
26
+ * `transition(execution, Cancelled)`.
23
27
  */
24
28
  export declare enum AgentExecutionStatus {
25
29
  Created = "Created",
@@ -113,6 +117,10 @@ export interface AgentExecution {
113
117
  completedMs?: number;
114
118
  /** Optional error message if execution failed */
115
119
  error?: string;
120
+ /** The agent-state task this execution works on, when it was created for one. */
121
+ taskId?: string;
122
+ /** Why the execution was cancelled (status `Cancelled`). */
123
+ cancelReason?: string;
116
124
  /** Metadata about the execution */
117
125
  metadata?: Record<string, any>;
118
126
  }
@@ -120,6 +128,7 @@ export interface AgentExecution {
120
128
  * Parse an agent reference from its canonical form
121
129
  * @example parseAgentRef("flow://agent/researcher@1")
122
130
  */
131
+ export declare const AGENT_EXECUTION_TERMINAL_STATUSES: readonly AgentExecutionStatus[];
123
132
  export declare function parseAgentRef(ref: string): AgentRef;
124
133
  /**
125
134
  * Create an agent reference
@@ -1 +1 @@
1
- {"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../src/agent.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../src/agent.ts"],"names":[],"mappings":"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"}
package/dist/agent.js CHANGED
@@ -6,7 +6,11 @@
6
6
  * of the same causal graph.
7
7
  */
8
8
  /**
9
- * Lifecycle states for agent execution
9
+ * Lifecycle states for agent execution.
10
+ *
11
+ * `Completed`, `Failed` and `Cancelled` are terminal. `Cancelled` is reachable
12
+ * from every non-terminal state, through `AgentRuntime.cancel` or
13
+ * `transition(execution, Cancelled)`.
10
14
  */
11
15
  export var AgentExecutionStatus;
12
16
  (function (AgentExecutionStatus) {
@@ -25,6 +29,11 @@ export var AgentExecutionStatus;
25
29
  * Parse an agent reference from its canonical form
26
30
  * @example parseAgentRef("flow://agent/researcher@1")
27
31
  */
32
+ export const AGENT_EXECUTION_TERMINAL_STATUSES = [
33
+ AgentExecutionStatus.Completed,
34
+ AgentExecutionStatus.Failed,
35
+ AgentExecutionStatus.Cancelled,
36
+ ];
28
37
  export function parseAgentRef(ref) {
29
38
  const match = ref.match(/^flow:\/\/agent\/([^@]+)@(\d+)$/);
30
39
  if (!match) {
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "schema": "feltdb.build-identity.v2",
3
3
  "package": "@feltdb/core",
4
- "version": "0.13.0",
4
+ "version": "0.15.0",
5
5
  "git": {
6
- "sha1": "b67312f73ea647ffea6f87337303c170d40d541d",
6
+ "sha1": "5ad54972a9e31a5459cadbb471428111624ec9c6",
7
7
  "dirty": false
8
8
  },
9
9
  "path_in_vcs": "packages/core",
10
- "source_digest": "sha256:7435af3423598673fcce76eb77444ee1e160f39f3fd83a0a788517e315bd3444",
10
+ "source_digest": "sha256:01efc5737aae1fef37c976e5841df3bb9b615d034f31d27b038f7fd4ca202428",
11
11
  "inputs": [
12
12
  "Cargo.lock",
13
13
  "Cargo.toml",
@@ -20,7 +20,7 @@
20
20
  "tools/cli",
21
21
  "tools/create-feltdb"
22
22
  ],
23
- "files": 776,
23
+ "files": 789,
24
24
  "build": {
25
25
  "command": "npm run build",
26
26
  "node": "v24.9.0"
@@ -40,6 +40,27 @@ function loadProjectEnvironment(file = path.resolve('.env.local')) {
40
40
  if (!(key in process.env))
41
41
  process.env[key] = value;
42
42
  }
43
+ warnBrowserExposedCredentials();
44
+ }
45
+ /**
46
+ * Credentials under a `VITE_` name are inlined into the application's browser
47
+ * bundle by Vite, so they are no longer read as credentials anywhere. Say so,
48
+ * rather than silently dropping authentication a project used to have.
49
+ */
50
+ function warnBrowserExposedCredentials() {
51
+ for (const name of Object.keys(process.env)) {
52
+ if (/^VITE_[A-Z0-9_]*(?:TOKEN|API_KEY|SECRET)$/.test(name) && process.env[name]) {
53
+ console.warn(`⚠ ${name} is ignored: VITE_* variables are inlined into browser bundles. Move the credential to FELTDB_TOKEN (server-side only).`);
54
+ }
55
+ }
56
+ }
57
+ /**
58
+ * The local `feltdb dev` Studio is an operator console on localhost. It
59
+ * receives the developer's server-side key at runtime (no-store), never from a
60
+ * bundled VITE_* value.
61
+ */
62
+ function studioOperatorToken() {
63
+ return process.env.FELTDB_TOKEN || '';
43
64
  }
44
65
  async function availablePort(preferred, host = '127.0.0.1') {
45
66
  for (let port = preferred; port < preferred + 100; port += 1) {
@@ -831,8 +852,8 @@ async function handleConnect(args) {
831
852
  let health;
832
853
  try {
833
854
  const response = await fetch(`${url}/health`, {
834
- headers: process.env.FELTDB_TOKEN || process.env.VITE_FELTDB_API_KEY
835
- ? { Authorization: `Bearer ${process.env.FELTDB_TOKEN || process.env.VITE_FELTDB_API_KEY}` }
855
+ headers: process.env.FELTDB_TOKEN
856
+ ? { Authorization: `Bearer ${process.env.FELTDB_TOKEN}` }
836
857
  : {},
837
858
  signal: controller.signal,
838
859
  });
@@ -855,14 +876,14 @@ async function handleConnect(args) {
855
876
  fs.writeFileSync(connFile, JSON.stringify({
856
877
  url,
857
878
  connected: new Date().toISOString(),
858
- authenticated: Boolean(process.env.FELTDB_TOKEN || process.env.VITE_FELTDB_API_KEY),
879
+ authenticated: Boolean(process.env.FELTDB_TOKEN),
859
880
  namespace: managed.namespace || project.namespace || 'default',
860
881
  runtime: project.runtime || 'self-hosted',
861
882
  }, null, 2));
862
883
  console.log('✅ Connected to FeltDB\n');
863
884
  console.log('Endpoint: ' + url);
864
885
  console.log(`Namespace: ${managed.namespace || project.namespace || 'default'}`);
865
- console.log(`Authenticated: ${process.env.FELTDB_TOKEN || process.env.VITE_FELTDB_API_KEY ? 'yes' : 'no'}`);
886
+ console.log(`Authenticated: ${process.env.FELTDB_TOKEN ? 'yes' : 'no'}`);
866
887
  console.log(`Runtime: ${project.runtime || 'self-hosted'}`);
867
888
  console.log(`Health: ${health.status || 'healthy'}\n`);
868
889
  console.log('Use: feltdb status (to check connection)\n');
@@ -1894,7 +1915,7 @@ async function handleStudio(args, onReady) {
1894
1915
  environment: managedProject.environment || 'production',
1895
1916
  publishEndpoint: '/_feltdb/publish',
1896
1917
  } : undefined;
1897
- response.end(JSON.stringify({ token: connectUrl ? process.env.VITE_FELTDB_API_KEY || '' : '', managedPublish, session, studioQuery, sourceSync: { enabled: true, webllmEnabled, previewOnly, token: studioMutationToken, aiModel: publicAiModelConfiguration() } }));
1918
+ response.end(JSON.stringify({ token: connectUrl ? studioOperatorToken() : '', managedPublish, session, studioQuery, sourceSync: { enabled: true, webllmEnabled, previewOnly, token: studioMutationToken, aiModel: publicAiModelConfiguration() } }));
1898
1919
  return;
1899
1920
  }
1900
1921
  if (pathname === '/_feltdb/contract') {
@@ -1913,7 +1934,7 @@ async function handleStudio(args, onReady) {
1913
1934
  endpoint.searchParams.set('application_id', applicationId);
1914
1935
  endpoint.searchParams.set('environment', managedProject.environment || lastPublished?.environment || 'production');
1915
1936
  const headers = {};
1916
- const credential = process.env.FELTDB_MANAGED_CONTROL_API_KEY || process.env.VITE_FELTDB_API_KEY;
1937
+ const credential = process.env.FELTDB_MANAGED_CONTROL_API_KEY || process.env.FELTDB_TOKEN;
1917
1938
  if (credential)
1918
1939
  headers.authorization = `Bearer ${credential}`;
1919
1940
  const discovered = await fetch(endpoint, { headers });
@@ -359,7 +359,9 @@ export declare class Collection<T> {
359
359
  /**
360
360
  * Refresh data from the database and notify subscribers.
361
361
  */
362
- refresh(): Promise<void>;
362
+ refresh(options?: {
363
+ strict?: boolean;
364
+ }): Promise<void>;
363
365
  }
364
366
  /**
365
367
  * Relationship helper for loading related data.
@@ -1 +1 @@
1
- {"version":3,"file":"collection.d.ts","sourceRoot":"","sources":["../src/collection.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"collection.d.ts","sourceRoot":"","sources":["../src/collection.ts"],"names":[],"mappings":"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"}
@@ -129,7 +129,9 @@ export class Collection {
129
129
  * Returns cached results (live-updated).
130
130
  */
131
131
  async all() {
132
- await this.refresh();
132
+ // A read the authority refused, or could not answer, is raised typed --
133
+ // never answered from whatever this handle last cached.
134
+ await this.refresh({ strict: true });
133
135
  return [...this.cache];
134
136
  }
135
137
  /** List records through the canonical application collection API. */
@@ -375,7 +377,7 @@ export class Collection {
375
377
  const key = `${this.name}:${id}`;
376
378
  const result = await this.db.get(key);
377
379
  if (!result.success) {
378
- throw new Error(result.error || `Failed to read record ${id}`);
380
+ throw runtimeFailure(result, result.error || `Failed to read record ${id}`);
379
381
  }
380
382
  if (result.data) {
381
383
  return JSON.parse(result.data);
@@ -421,7 +423,7 @@ export class Collection {
421
423
  const stored = { ...data, id: recordId, __version: 1 };
422
424
  const result = await this.db.insert(key, JSON.stringify(stored));
423
425
  if (!result.success) {
424
- throw new Error(`Insert failed: ${result.error}`);
426
+ throw runtimeFailure(result, `Insert failed: ${result.error}`);
425
427
  }
426
428
  await this.publish('insert', key, String(recordId), null, stored);
427
429
  return String(recordId);
@@ -614,9 +616,11 @@ export class Collection {
614
616
  const result = await this.db.delete(key);
615
617
  if (!result.success) {
616
618
  const message = `Delete failed: ${result.error}`;
617
- throw /not found/i.test(String(result.error))
618
- ? new FeltDBServiceError(message, FeltDBErrorCode.NOT_FOUND)
619
- : new Error(message);
619
+ throw result.cause
620
+ ? runtimeFailure(result, message)
621
+ : /not found/i.test(String(result.error))
622
+ ? new FeltDBServiceError(message, FeltDBErrorCode.NOT_FOUND)
623
+ : new Error(message);
620
624
  }
621
625
  // Update indexes - find and remove the deleted record
622
626
  const deleted = await this.get(id);
@@ -686,7 +690,7 @@ export class Collection {
686
690
  throw error;
687
691
  const existing = await this.db.get(key);
688
692
  if (!existing.success) {
689
- throw new Error(existing.error || `could not read the record that won ${key}`);
693
+ throw runtimeFailure(existing, existing.error || `could not read the record that won ${key}`);
690
694
  }
691
695
  if (!existing.data) {
692
696
  throw new Error(`${key} was created and then removed while resolving a conditional create`);
@@ -914,7 +918,7 @@ export class Collection {
914
918
  /**
915
919
  * Refresh data from the database and notify subscribers.
916
920
  */
917
- async refresh() {
921
+ async refresh(options = {}) {
918
922
  try {
919
923
  // The revision is read *before* the query, so it can only ever be older
920
924
  // than the data it ends up labelling. The reverse ordering would let a
@@ -980,14 +984,32 @@ export class Collection {
980
984
  }
981
985
  }
982
986
  else if (!result.success) {
987
+ if (options.strict)
988
+ throw runtimeFailure(result, result.error || `Failed to read ${this.name}`);
983
989
  console.error('Query failed:', result.error);
984
990
  }
985
991
  }
986
992
  catch (err) {
993
+ if (options.strict)
994
+ throw err;
987
995
  console.error('Refresh error:', err);
988
996
  }
989
997
  }
990
998
  }
999
+ /**
1000
+ * The error a failed runtime result is raised as. A remote runtime attaches
1001
+ * the authority's typed refusal (`cause`): its stable code, status, request id
1002
+ * and body travel on, so an unauthenticated, cross-application or interrupted
1003
+ * operation is never a bare `Error` with the code only in its message.
1004
+ */
1005
+ function runtimeFailure(result, message) {
1006
+ const cause = result.cause;
1007
+ if (!(cause instanceof FeltDBServiceError))
1008
+ return new Error(message);
1009
+ const error = new FeltDBServiceError(message, cause.code, cause.requestId, cause.status, cause.body);
1010
+ error.cause = cause;
1011
+ return error;
1012
+ }
991
1013
  /**
992
1014
  * Relationship helper for loading related data.
993
1015
  */
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "schema": "feltdb.build-identity.v2",
3
3
  "package": "create-feltdb",
4
- "version": "0.13.0",
4
+ "version": "0.15.0",
5
5
  "git": {
6
- "sha1": "b67312f73ea647ffea6f87337303c170d40d541d",
6
+ "sha1": "5ad54972a9e31a5459cadbb471428111624ec9c6",
7
7
  "dirty": false
8
8
  },
9
9
  "path_in_vcs": "tools/create-feltdb",
10
- "source_digest": "sha256:7435af3423598673fcce76eb77444ee1e160f39f3fd83a0a788517e315bd3444",
10
+ "source_digest": "sha256:01efc5737aae1fef37c976e5841df3bb9b615d034f31d27b038f7fd4ca202428",
11
11
  "inputs": [
12
12
  "Cargo.lock",
13
13
  "Cargo.toml",
@@ -20,7 +20,7 @@
20
20
  "tools/cli",
21
21
  "tools/create-feltdb"
22
22
  ],
23
- "files": 776,
23
+ "files": 789,
24
24
  "build": {
25
25
  "command": "npm run build",
26
26
  "node": "v24.9.0"
@@ -226,7 +226,7 @@ Deployment Target (Explicit):
226
226
 
227
227
  --managed Managed FeltDB runtime
228
228
  Best for: Production without operating servers
229
- Requires VITE_FELTDB_URL and VITE_FELTDB_API_KEY
229
+ Requires VITE_FELTDB_URL; server-side FELTDB_TOKEN only
230
230
 
231
231
  Options:
232
232
  --browser Explicit: Browser runtime with IndexedDB