@vellumai/assistant 0.8.10-dev.202606110544.2aed335 → 0.8.10-dev.202606110941.6cb149d

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 (63) hide show
  1. package/openapi.yaml +109 -70
  2. package/package.json +1 -1
  3. package/src/__tests__/background-workers-disk-pressure.test.ts +0 -2
  4. package/src/__tests__/db-schedule-syntax-migration.test.ts +80 -0
  5. package/src/__tests__/identity-routes.test.ts +1 -0
  6. package/src/__tests__/intent-routing.test.ts +7 -0
  7. package/src/__tests__/require-fresh-approval.test.ts +3 -0
  8. package/src/__tests__/schedule-routes.test.ts +116 -1
  9. package/src/__tests__/schedule-store.test.ts +28 -0
  10. package/src/__tests__/schedule-tools.test.ts +94 -1
  11. package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +1 -0
  12. package/src/cli/commands/__tests__/schedules.test.ts +62 -4
  13. package/src/cli/commands/schedules.ts +27 -4
  14. package/src/config/bundled-skills/schedule/TOOLS.json +11 -3
  15. package/src/config/feature-flag-registry.json +1 -1
  16. package/src/config/schemas/__tests__/memory-v2.test.ts +0 -1
  17. package/src/config/schemas/memory-v2.ts +0 -8
  18. package/src/daemon/__tests__/conversation-tool-setup-exclude.test.ts +18 -0
  19. package/src/daemon/conversation-tool-setup.ts +7 -0
  20. package/src/daemon/message-types/schedules.ts +1 -0
  21. package/src/memory/__tests__/conversation-queries.test.ts +176 -0
  22. package/src/memory/__tests__/jobs-worker-v2-schedule.test.ts +20 -32
  23. package/src/memory/conversation-crud.ts +43 -1
  24. package/src/memory/conversation-queries.ts +64 -7
  25. package/src/memory/db-init.ts +4 -0
  26. package/src/memory/embedding-backend.ts +1 -1
  27. package/src/memory/graph/__tests__/handle-remember-v2.test.ts +19 -0
  28. package/src/memory/graph/conversation-graph-memory.ts +1 -1
  29. package/src/memory/graph/tool-handlers.ts +3 -0
  30. package/src/memory/jobs-store.ts +0 -28
  31. package/src/memory/jobs-worker.ts +10 -22
  32. package/src/memory/migrations/270-schedule-description.ts +36 -0
  33. package/src/memory/migrations/280-conversations-surfaced-at.test.ts +88 -0
  34. package/src/memory/migrations/280-conversations-surfaced-at.ts +24 -0
  35. package/src/memory/migrations/index.ts +5 -0
  36. package/src/memory/migrations/registry.ts +8 -0
  37. package/src/memory/schema/conversations.ts +8 -0
  38. package/src/memory/schema/infrastructure.ts +1 -0
  39. package/src/memory/v2/__tests__/consolidation-job.test.ts +33 -5
  40. package/src/memory/v2/consolidation-job.ts +8 -2
  41. package/src/memory/v2/static-context.ts +1 -1
  42. package/src/permissions/checker.test.ts +83 -1
  43. package/src/permissions/checker.ts +25 -2
  44. package/src/permissions/gateway-threshold-reader.test.ts +182 -0
  45. package/src/permissions/gateway-threshold-reader.ts +80 -0
  46. package/src/plugins/defaults/memory-v3-shadow/__tests__/injection.test.ts +14 -0
  47. package/src/plugins/defaults/memory-v3-shadow/__tests__/shadow-plugin.test.ts +15 -0
  48. package/src/plugins/defaults/memory-v3-shadow/injector.ts +2 -0
  49. package/src/plugins/defaults/memory-v3-shadow/shadow-plugin.ts +4 -1
  50. package/src/runtime/routes/__tests__/consolidation-routes.test.ts +12 -50
  51. package/src/runtime/routes/__tests__/conversation-surface-routes.test.ts +322 -0
  52. package/src/runtime/routes/consolidation-routes.ts +6 -82
  53. package/src/runtime/routes/conversation-list-routes.ts +6 -0
  54. package/src/runtime/routes/conversation-management-routes.ts +71 -0
  55. package/src/runtime/routes/identity-routes.ts +8 -0
  56. package/src/runtime/routes/schedule-routes.ts +43 -5
  57. package/src/runtime/services/__tests__/conversation-serializer.test.ts +140 -0
  58. package/src/runtime/services/conversation-serializer.ts +38 -1
  59. package/src/schedule/schedule-store.ts +19 -0
  60. package/src/tasks/task-scheduler.ts +1 -0
  61. package/src/tools/schedule/create.ts +16 -0
  62. package/src/tools/schedule/list.ts +12 -4
  63. package/src/tools/schedule/update.ts +12 -0
package/openapi.yaml CHANGED
@@ -4539,55 +4539,6 @@ paths:
4539
4539
  - lastRunAt
4540
4540
  - success
4541
4541
  additionalProperties: false
4542
- put:
4543
- operationId: consolidation_config_put
4544
- summary: Update consolidation config
4545
- description: Update the memory v2 consolidation schedule configuration.
4546
- tags:
4547
- - consolidation
4548
- responses:
4549
- "200":
4550
- description: Successful response
4551
- content:
4552
- application/json:
4553
- schema:
4554
- type: object
4555
- properties:
4556
- available:
4557
- type: boolean
4558
- enabled:
4559
- type: boolean
4560
- intervalMs:
4561
- type: number
4562
- nextRunAt:
4563
- anyOf:
4564
- - type: number
4565
- - type: "null"
4566
- lastRunAt:
4567
- anyOf:
4568
- - type: number
4569
- - type: "null"
4570
- success:
4571
- type: boolean
4572
- required:
4573
- - available
4574
- - enabled
4575
- - intervalMs
4576
- - nextRunAt
4577
- - lastRunAt
4578
- - success
4579
- additionalProperties: false
4580
- requestBody:
4581
- required: true
4582
- content:
4583
- application/json:
4584
- schema:
4585
- type: object
4586
- properties:
4587
- enabled:
4588
- description: Enable or disable automatic consolidation
4589
- type: boolean
4590
- additionalProperties: false
4591
4542
  /v1/consolidation/run-now:
4592
4543
  post:
4593
4544
  operationId: consolidation_runnow_post
@@ -6020,6 +5971,8 @@ paths:
6020
5971
  additionalProperties: false
6021
5972
  archivedAt:
6022
5973
  type: number
5974
+ surfacedAt:
5975
+ type: number
6023
5976
  inferenceProfile:
6024
5977
  type: string
6025
5978
  isProcessing:
@@ -6381,6 +6334,8 @@ paths:
6381
6334
  additionalProperties: false
6382
6335
  archivedAt:
6383
6336
  type: number
6337
+ surfacedAt:
6338
+ type: number
6384
6339
  inferenceProfile:
6385
6340
  type: string
6386
6341
  isProcessing:
@@ -6579,6 +6534,8 @@ paths:
6579
6534
  additionalProperties: false
6580
6535
  archivedAt:
6581
6536
  type: number
6537
+ surfacedAt:
6538
+ type: number
6582
6539
  inferenceProfile:
6583
6540
  type: string
6584
6541
  isProcessing:
@@ -6987,6 +6944,56 @@ paths:
6987
6944
  required: true
6988
6945
  schema:
6989
6946
  type: string
6947
+ /v1/conversations/{id}/surface:
6948
+ post:
6949
+ operationId: conversations_by_id_surface_post
6950
+ summary: Surface a conversation into Recents
6951
+ description:
6952
+ Explicitly promote a background or scheduled conversation into the default conversation listing (the
6953
+ Recents sidebar grouping), or demote it with surfaced=false. Conversations are never surfaced automatically.
6954
+ tags:
6955
+ - conversations
6956
+ responses:
6957
+ "200":
6958
+ description: Successful response
6959
+ content:
6960
+ application/json:
6961
+ schema:
6962
+ type: object
6963
+ properties:
6964
+ ok:
6965
+ type: boolean
6966
+ conversationId:
6967
+ type: string
6968
+ surfacedAt:
6969
+ anyOf:
6970
+ - type: number
6971
+ - type: "null"
6972
+ description: Epoch-ms timestamp of the promotion, or null when cleared.
6973
+ required:
6974
+ - ok
6975
+ - conversationId
6976
+ - surfacedAt
6977
+ additionalProperties: false
6978
+ parameters:
6979
+ - name: id
6980
+ in: path
6981
+ required: true
6982
+ schema:
6983
+ type: string
6984
+ requestBody:
6985
+ required: true
6986
+ content:
6987
+ application/json:
6988
+ schema:
6989
+ type: object
6990
+ properties:
6991
+ surfaced:
6992
+ type: boolean
6993
+ description: true to surface the conversation into Recents, false to clear the promotion.
6994
+ required:
6995
+ - surfaced
6996
+ additionalProperties: false
6990
6997
  /v1/conversations/{id}/unarchive:
6991
6998
  post:
6992
6999
  operationId: conversations_by_id_unarchive_post
@@ -7542,6 +7549,8 @@ paths:
7542
7549
  additionalProperties: false
7543
7550
  archivedAt:
7544
7551
  type: number
7552
+ surfacedAt:
7553
+ type: number
7545
7554
  inferenceProfile:
7546
7555
  type: string
7547
7556
  isProcessing:
@@ -11182,6 +11191,14 @@ paths:
11182
11191
  required:
11183
11192
  - connected
11184
11193
  additionalProperties: false
11194
+ capabilities:
11195
+ type: object
11196
+ properties:
11197
+ memoryOptOut:
11198
+ type: boolean
11199
+ required:
11200
+ - memoryOptOut
11201
+ additionalProperties: false
11185
11202
  profiler:
11186
11203
  type: object
11187
11204
  properties:
@@ -11266,6 +11283,7 @@ paths:
11266
11283
  - cpu
11267
11284
  - migrations
11268
11285
  - ces
11286
+ - capabilities
11269
11287
  additionalProperties: false
11270
11288
  /v1/healthz:
11271
11289
  get:
@@ -11350,6 +11368,14 @@ paths:
11350
11368
  required:
11351
11369
  - connected
11352
11370
  additionalProperties: false
11371
+ capabilities:
11372
+ type: object
11373
+ properties:
11374
+ memoryOptOut:
11375
+ type: boolean
11376
+ required:
11377
+ - memoryOptOut
11378
+ additionalProperties: false
11353
11379
  profiler:
11354
11380
  type: object
11355
11381
  properties:
@@ -11434,6 +11460,7 @@ paths:
11434
11460
  - cpu
11435
11461
  - migrations
11436
11462
  - ces
11463
+ - capabilities
11437
11464
  additionalProperties: false
11438
11465
  /v1/heartbeat/checklist:
11439
11466
  get:
@@ -20298,9 +20325,9 @@ paths:
20298
20325
  - type: number
20299
20326
  - type: "null"
20300
20327
  description:
20301
- anyOf:
20302
- - type: string
20303
- - type: "null"
20328
+ type: string
20329
+ cadenceDescription:
20330
+ type: string
20304
20331
  mode:
20305
20332
  type: string
20306
20333
  enum:
@@ -20350,6 +20377,7 @@ paths:
20350
20377
  - createdFromConversationExists
20351
20378
  - createdFromConversationArchivedAt
20352
20379
  - description
20380
+ - cadenceDescription
20353
20381
  - mode
20354
20382
  - status
20355
20383
  - routingIntent
@@ -20447,9 +20475,9 @@ paths:
20447
20475
  - type: number
20448
20476
  - type: "null"
20449
20477
  description:
20450
- anyOf:
20451
- - type: string
20452
- - type: "null"
20478
+ type: string
20479
+ cadenceDescription:
20480
+ type: string
20453
20481
  mode:
20454
20482
  type: string
20455
20483
  enum:
@@ -20499,6 +20527,7 @@ paths:
20499
20527
  - createdFromConversationExists
20500
20528
  - createdFromConversationArchivedAt
20501
20529
  - description
20530
+ - cadenceDescription
20502
20531
  - mode
20503
20532
  - status
20504
20533
  - routingIntent
@@ -20520,6 +20549,9 @@ paths:
20520
20549
  name:
20521
20550
  type: string
20522
20551
  description: Display name
20552
+ description:
20553
+ type: string
20554
+ description: Authored schedule description. Defaults to the schedule name when omitted for backward compatibility.
20523
20555
  expression:
20524
20556
  type: string
20525
20557
  description: Cron or RRULE expression
@@ -20622,9 +20654,9 @@ paths:
20622
20654
  - type: number
20623
20655
  - type: "null"
20624
20656
  description:
20625
- anyOf:
20626
- - type: string
20627
- - type: "null"
20657
+ type: string
20658
+ cadenceDescription:
20659
+ type: string
20628
20660
  mode:
20629
20661
  type: string
20630
20662
  enum:
@@ -20674,6 +20706,7 @@ paths:
20674
20706
  - createdFromConversationExists
20675
20707
  - createdFromConversationArchivedAt
20676
20708
  - description
20709
+ - cadenceDescription
20677
20710
  - mode
20678
20711
  - status
20679
20712
  - routingIntent
@@ -20770,9 +20803,9 @@ paths:
20770
20803
  - type: number
20771
20804
  - type: "null"
20772
20805
  description:
20773
- anyOf:
20774
- - type: string
20775
- - type: "null"
20806
+ type: string
20807
+ cadenceDescription:
20808
+ type: string
20776
20809
  mode:
20777
20810
  type: string
20778
20811
  enum:
@@ -20822,6 +20855,7 @@ paths:
20822
20855
  - createdFromConversationExists
20823
20856
  - createdFromConversationArchivedAt
20824
20857
  - description
20858
+ - cadenceDescription
20825
20859
  - mode
20826
20860
  - status
20827
20861
  - routingIntent
@@ -20848,6 +20882,8 @@ paths:
20848
20882
  properties:
20849
20883
  name:
20850
20884
  type: string
20885
+ description:
20886
+ type: string
20851
20887
  expression:
20852
20888
  type: string
20853
20889
  timezone:
@@ -20961,9 +20997,9 @@ paths:
20961
20997
  - type: number
20962
20998
  - type: "null"
20963
20999
  description:
20964
- anyOf:
20965
- - type: string
20966
- - type: "null"
21000
+ type: string
21001
+ cadenceDescription:
21002
+ type: string
20967
21003
  mode:
20968
21004
  type: string
20969
21005
  enum:
@@ -21013,6 +21049,7 @@ paths:
21013
21049
  - createdFromConversationExists
21014
21050
  - createdFromConversationArchivedAt
21015
21051
  - description
21052
+ - cadenceDescription
21016
21053
  - mode
21017
21054
  - status
21018
21055
  - routingIntent
@@ -21110,9 +21147,9 @@ paths:
21110
21147
  - type: number
21111
21148
  - type: "null"
21112
21149
  description:
21113
- anyOf:
21114
- - type: string
21115
- - type: "null"
21150
+ type: string
21151
+ cadenceDescription:
21152
+ type: string
21116
21153
  mode:
21117
21154
  type: string
21118
21155
  enum:
@@ -21162,6 +21199,7 @@ paths:
21162
21199
  - createdFromConversationExists
21163
21200
  - createdFromConversationArchivedAt
21164
21201
  - description
21202
+ - cadenceDescription
21165
21203
  - mode
21166
21204
  - status
21167
21205
  - routingIntent
@@ -21348,9 +21386,9 @@ paths:
21348
21386
  - type: number
21349
21387
  - type: "null"
21350
21388
  description:
21351
- anyOf:
21352
- - type: string
21353
- - type: "null"
21389
+ type: string
21390
+ cadenceDescription:
21391
+ type: string
21354
21392
  mode:
21355
21393
  type: string
21356
21394
  enum:
@@ -21400,6 +21438,7 @@ paths:
21400
21438
  - createdFromConversationExists
21401
21439
  - createdFromConversationArchivedAt
21402
21440
  - description
21441
+ - cadenceDescription
21403
21442
  - mode
21404
21443
  - status
21405
21444
  - routingIntent
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vellumai/assistant",
3
- "version": "0.8.10-dev.202606110544.2aed335",
3
+ "version": "0.8.10-dev.202606110941.6cb149d",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "exports": {
@@ -167,7 +167,6 @@ const mockFailStalledJobs = mock(() => 0);
167
167
  const mockClaimMemoryJobs = mock(() => []);
168
168
  mock.module("../memory/jobs-store.js", () => ({
169
169
  claimMemoryJobs: mockClaimMemoryJobs,
170
- cancelPendingAutomaticConsolidationJobs: mock(() => 0),
171
170
  completeMemoryJob: mock(() => {}),
172
171
  deferMemoryJob: mock(() => "deferred"),
173
172
  EMBED_JOB_TYPES: [],
@@ -179,7 +178,6 @@ mock.module("../memory/jobs-store.js", () => ({
179
178
  failStalledJobs: mockFailStalledJobs,
180
179
  getMemoryJobCounts: mock(() => ({})),
181
180
  hasActiveJobOfType: mock(() => false),
182
- isAutomaticConsolidationJob: mock(() => true),
183
181
  isMemoryEnabled: () => true,
184
182
  MEMORY_V2_CONSOLIDATION_JOB_TRIGGERS: {
185
183
  automatic: "automatic",
@@ -4,6 +4,7 @@ import { describe, expect, test } from "bun:test";
4
4
  import { eq } from "drizzle-orm";
5
5
  import { drizzle } from "drizzle-orm/bun-sqlite";
6
6
 
7
+ import { migrateScheduleDescription } from "../memory/migrations/270-schedule-description.js";
7
8
  import { migrateScheduleSourceConversation } from "../memory/migrations/270-schedule-source-conversation.js";
8
9
  import * as schema from "../memory/schema.js";
9
10
  import { scheduleJobs } from "../memory/schema.js";
@@ -50,6 +51,7 @@ describe("schedule_syntax column migration", () => {
50
51
  script TEXT,
51
52
  wake_conversation_id TEXT,
52
53
  timeout_ms INTEGER,
54
+ description TEXT NOT NULL DEFAULT '',
53
55
  created_at INTEGER NOT NULL,
54
56
  updated_at INTEGER NOT NULL
55
57
  )
@@ -137,6 +139,7 @@ describe("schedule_syntax column migration", () => {
137
139
  /* already exists */
138
140
  }
139
141
  migrateScheduleSourceConversation(db);
142
+ migrateScheduleDescription(db);
140
143
 
141
144
  const row = db
142
145
  .select()
@@ -202,6 +205,8 @@ describe("schedule_syntax column migration", () => {
202
205
  }
203
206
  migrateScheduleSourceConversation(db);
204
207
  migrateScheduleSourceConversation(db);
208
+ migrateScheduleDescription(db);
209
+ migrateScheduleDescription(db);
205
210
 
206
211
  const now = Date.now();
207
212
  raw.exec(
@@ -214,4 +219,79 @@ describe("schedule_syntax column migration", () => {
214
219
  .get();
215
220
  expect(row!.scheduleSyntax).toBe("cron");
216
221
  });
222
+
223
+ test("schedule description migration backfills non-defer rows once", () => {
224
+ const db = createTestDb();
225
+ const raw = getRawSqlite(db);
226
+
227
+ raw.exec(/*sql*/ `
228
+ CREATE TABLE IF NOT EXISTS cron_jobs (
229
+ id TEXT PRIMARY KEY,
230
+ name TEXT NOT NULL,
231
+ enabled INTEGER NOT NULL DEFAULT 1,
232
+ cron_expression TEXT,
233
+ schedule_syntax TEXT NOT NULL DEFAULT 'cron',
234
+ timezone TEXT,
235
+ message TEXT NOT NULL,
236
+ next_run_at INTEGER NOT NULL,
237
+ retry_count INTEGER NOT NULL DEFAULT 0,
238
+ created_by TEXT NOT NULL,
239
+ created_at INTEGER NOT NULL,
240
+ updated_at INTEGER NOT NULL
241
+ )
242
+ `);
243
+
244
+ const now = Date.now();
245
+ raw
246
+ .query(
247
+ `INSERT INTO cron_jobs (id, name, cron_expression, message, next_run_at, created_by, created_at, updated_at)
248
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,
249
+ )
250
+ .run(
251
+ "legacy-schedule",
252
+ "Legacy report",
253
+ "0 9 * * *",
254
+ "compile report",
255
+ now + 60_000,
256
+ "agent",
257
+ now,
258
+ now,
259
+ );
260
+ raw
261
+ .query(
262
+ `INSERT INTO cron_jobs (id, name, cron_expression, message, next_run_at, created_by, created_at, updated_at)
263
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,
264
+ )
265
+ .run(
266
+ "legacy-defer",
267
+ "Deferred wake",
268
+ null,
269
+ "resume later",
270
+ now + 60_000,
271
+ "defer",
272
+ now,
273
+ now,
274
+ );
275
+
276
+ migrateScheduleDescription(db);
277
+
278
+ const rows = raw
279
+ .query("SELECT id, description FROM cron_jobs ORDER BY id")
280
+ .all() as Array<{ id: string; description: string }>;
281
+ expect(rows).toEqual([
282
+ { id: "legacy-defer", description: "" },
283
+ { id: "legacy-schedule", description: "Legacy report" },
284
+ ]);
285
+
286
+ raw
287
+ .query("UPDATE cron_jobs SET description = ? WHERE id = ?")
288
+ .run("", "legacy-schedule");
289
+
290
+ migrateScheduleDescription(db);
291
+
292
+ const description = raw
293
+ .query("SELECT description FROM cron_jobs WHERE id = ?")
294
+ .get("legacy-schedule") as { description: string };
295
+ expect(description.description).toBe("");
296
+ });
217
297
  });
@@ -237,6 +237,7 @@ describe("identity routes — health endpoint", () => {
237
237
  expect(body.memory).toBeDefined();
238
238
  expect(body.cpu).toBeDefined();
239
239
  expect(body.migrations).toBeDefined();
240
+ expect(body.capabilities).toEqual({ memoryOptOut: true });
240
241
 
241
242
  // Profiler should either be absent or show enabled: false
242
243
  if ("profiler" in body) {
@@ -83,6 +83,13 @@ describe("schedule_create tool description", () => {
83
83
  expect(scheduleCreateDef.description).toContain("cron");
84
84
  });
85
85
 
86
+ test("requires an authored description", () => {
87
+ expect(scheduleCreateDef.input_schema.required).toContain("description");
88
+ expect(
89
+ scheduleCreateDef.input_schema.properties.description.description,
90
+ ).toContain("what it does and why");
91
+ });
92
+
86
93
  test('warns against using for "add to my tasks" requests', () => {
87
94
  expect(scheduleCreateDef.description).toContain(
88
95
  'Do NOT use this for "add to my tasks"',
@@ -125,6 +125,9 @@ mock.module("../tools/registry.js", () => ({
125
125
 
126
126
  mock.module("../permissions/gateway-threshold-reader.js", () => ({
127
127
  getAutoApproveThreshold: async () => "medium",
128
+ // Refresh failure ("null") keeps the original decision — these tests
129
+ // exercise the cached-threshold paths only.
130
+ refreshAutoApproveThreshold: async () => null,
128
131
  _clearGlobalCacheForTesting: () => {},
129
132
  }));
130
133