@vellumai/assistant 0.10.7-dev.202607101836.11f2eba → 0.10.7-dev.202607102035.64f07ea

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 (44) hide show
  1. package/openapi.yaml +0 -264
  2. package/package.json +1 -1
  3. package/src/__tests__/conversation-history-web-search.test.ts +0 -4
  4. package/src/__tests__/helpers/set-config.ts +40 -0
  5. package/src/__tests__/llm-request-log-disabled-writes.test.ts +11 -23
  6. package/src/__tests__/plugin-import-boundary-guard.test.ts +0 -1
  7. package/src/__tests__/tool-execution-abort-cleanup.test.ts +5 -26
  8. package/src/cli/AGENTS.md +3 -2
  9. package/src/cli/commands/avatar.help.ts +236 -0
  10. package/src/cli/commands/avatar.ts +66 -250
  11. package/src/cli/commands/backup.help.ts +190 -0
  12. package/src/cli/commands/backup.ts +109 -276
  13. package/src/cli/commands/bash.help.ts +45 -0
  14. package/src/cli/commands/bash.ts +55 -75
  15. package/src/cli/commands/browser.help.ts +196 -0
  16. package/src/cli/commands/browser.ts +222 -343
  17. package/src/cli/index.help.ts +8 -0
  18. package/src/cli/lib/cli-command-help.ts +47 -8
  19. package/src/config/feature-flag-registry.json +0 -8
  20. package/src/persistence/__tests__/message-content-file.test.ts +51 -3
  21. package/src/persistence/llm-request-log-sink-clickhouse.ts +2 -8
  22. package/src/persistence/llm-request-log-store.ts +2 -8
  23. package/src/persistence/message-content-file.ts +68 -6
  24. package/src/persistence/migrations/326-move-injection-events-to-memory-db.ts +104 -0
  25. package/src/persistence/schema/memory-injection.ts +3 -1
  26. package/src/persistence/steps.ts +2 -0
  27. package/src/plugins/defaults/memory/__tests__/db-memory-attach.test.ts +22 -18
  28. package/src/plugins/defaults/memory/__tests__/memory-retrospective-skill-card.test.ts +2 -29
  29. package/src/plugins/defaults/memory/__tests__/table-relocation.test.ts +49 -0
  30. package/src/plugins/defaults/memory/memory-retrospective-job.ts +8 -19
  31. package/src/plugins/defaults/memory/memory-retrospective-skill-card.ts +0 -7
  32. package/src/plugins/defaults/memory/routes/__tests__/memory-v2-simulate-route.test.ts +1 -6
  33. package/src/plugins/defaults/memory/routes/memory-v2-routes.ts +3 -8
  34. package/src/plugins/defaults/memory/v2/__tests__/injection-events.test.ts +60 -62
  35. package/src/plugins/defaults/memory/v2/__tests__/router.test.ts +7 -20
  36. package/src/plugins/defaults/memory/v2/cli-command-content.ts +37 -11
  37. package/src/plugins/defaults/memory/v2/harness/router-retriever.ts +1 -8
  38. package/src/plugins/defaults/memory/v2/injection-events.ts +33 -14
  39. package/src/plugins/defaults/memory/v2/injection.ts +1 -2
  40. package/src/plugins/defaults/memory/v2/router.ts +4 -14
  41. package/src/runtime/routes/index.ts +0 -2
  42. package/src/tools/registry.ts +1 -2
  43. package/src/runtime/routes/work-items-routes.test.ts +0 -68
  44. package/src/runtime/routes/work-items-routes.ts +0 -914
package/openapi.yaml CHANGED
@@ -30607,270 +30607,6 @@ paths:
30607
30607
  - path
30608
30608
  - mode
30609
30609
  additionalProperties: false
30610
- /v1/work-items:
30611
- get:
30612
- operationId: workitems_get
30613
- summary: List work items
30614
- description: Return work items, optionally filtered by status.
30615
- tags:
30616
- - work-items
30617
- parameters:
30618
- - name: status
30619
- in: query
30620
- required: false
30621
- schema:
30622
- type: string
30623
- enum:
30624
- - pending
30625
- - running
30626
- - awaiting_review
30627
- - done
30628
- - failed
30629
- - cancelled
30630
- - archived
30631
- description: Filter by work item status
30632
- responses:
30633
- "200":
30634
- description: Successful response
30635
- content:
30636
- application/json:
30637
- schema:
30638
- type: object
30639
- properties:
30640
- items:
30641
- type: array
30642
- items: {}
30643
- required:
30644
- - items
30645
- additionalProperties: false
30646
- /v1/work-items/{id}:
30647
- delete:
30648
- operationId: workitems_by_id_delete
30649
- summary: Delete a work item
30650
- description: Permanently remove a work item.
30651
- tags:
30652
- - work-items
30653
- parameters:
30654
- - name: id
30655
- in: path
30656
- required: true
30657
- schema:
30658
- type: string
30659
- responses:
30660
- "200":
30661
- description: Successful response
30662
- get:
30663
- operationId: workitems_by_id_get
30664
- summary: Get a work item
30665
- description: Return a single work item by ID.
30666
- tags:
30667
- - work-items
30668
- parameters:
30669
- - name: id
30670
- in: path
30671
- required: true
30672
- schema:
30673
- type: string
30674
- responses:
30675
- "200":
30676
- description: Successful response
30677
- patch:
30678
- operationId: workitems_by_id_patch
30679
- summary: Update a work item
30680
- description: Partially update a work item's title, notes, status, or priority.
30681
- tags:
30682
- - work-items
30683
- parameters:
30684
- - name: id
30685
- in: path
30686
- required: true
30687
- schema:
30688
- type: string
30689
- requestBody:
30690
- required: true
30691
- content:
30692
- application/json:
30693
- schema:
30694
- type: object
30695
- properties:
30696
- title:
30697
- type: string
30698
- notes:
30699
- type: string
30700
- status:
30701
- type: string
30702
- priorityTier:
30703
- type: integer
30704
- minimum: -9007199254740991
30705
- maximum: 9007199254740991
30706
- sortIndex:
30707
- type: integer
30708
- minimum: -9007199254740991
30709
- maximum: 9007199254740991
30710
- required:
30711
- - title
30712
- - notes
30713
- - status
30714
- - priorityTier
30715
- - sortIndex
30716
- responses:
30717
- "200":
30718
- description: Successful response
30719
- /v1/work-items/{id}/approve-permissions:
30720
- post:
30721
- operationId: workitems_by_id_approvepermissions_post
30722
- summary: Approve tool permissions
30723
- description: Pre-approve a set of tools for a work item before it runs.
30724
- tags:
30725
- - work-items
30726
- parameters:
30727
- - name: id
30728
- in: path
30729
- required: true
30730
- schema:
30731
- type: string
30732
- requestBody:
30733
- required: true
30734
- content:
30735
- application/json:
30736
- schema:
30737
- type: object
30738
- properties:
30739
- approvedTools:
30740
- type: array
30741
- items: {}
30742
- description: Array of tool names to approve
30743
- required:
30744
- - approvedTools
30745
- responses:
30746
- "200":
30747
- description: Successful response
30748
- /v1/work-items/{id}/cancel:
30749
- post:
30750
- operationId: workitems_by_id_cancel_post
30751
- summary: Cancel a running work item
30752
- description: Abort a running work item and set its status to cancelled.
30753
- tags:
30754
- - work-items
30755
- parameters:
30756
- - name: id
30757
- in: path
30758
- required: true
30759
- schema:
30760
- type: string
30761
- responses:
30762
- "200":
30763
- description: Successful response
30764
- "404":
30765
- description: Work item not found
30766
- "409":
30767
- description: Work item is not running
30768
- /v1/work-items/{id}/complete:
30769
- post:
30770
- operationId: workitems_by_id_complete_post
30771
- summary: Complete a work item
30772
- description: Transition a work item from awaiting_review to done.
30773
- tags:
30774
- - work-items
30775
- parameters:
30776
- - name: id
30777
- in: path
30778
- required: true
30779
- schema:
30780
- type: string
30781
- responses:
30782
- "200":
30783
- description: Successful response
30784
- /v1/work-items/{id}/output:
30785
- get:
30786
- operationId: workitems_by_id_output_get
30787
- summary: Get work item output
30788
- description: Return the final output of a completed work item run.
30789
- tags:
30790
- - work-items
30791
- parameters:
30792
- - name: id
30793
- in: path
30794
- required: true
30795
- schema:
30796
- type: string
30797
- responses:
30798
- "200":
30799
- description: Successful response
30800
- content:
30801
- application/json:
30802
- schema:
30803
- type: object
30804
- properties:
30805
- id:
30806
- type: string
30807
- success:
30808
- type: boolean
30809
- output:
30810
- type: object
30811
- properties: {}
30812
- additionalProperties: {}
30813
- required:
30814
- - id
30815
- - success
30816
- - output
30817
- additionalProperties: false
30818
- /v1/work-items/{id}/preflight:
30819
- post:
30820
- operationId: workitems_by_id_preflight_post
30821
- summary: Preflight check
30822
- description: Check tool permissions needed before running a work item.
30823
- tags:
30824
- - work-items
30825
- parameters:
30826
- - name: id
30827
- in: path
30828
- required: true
30829
- schema:
30830
- type: string
30831
- responses:
30832
- "200":
30833
- description: Successful response
30834
- content:
30835
- application/json:
30836
- schema:
30837
- type: object
30838
- properties:
30839
- id:
30840
- type: string
30841
- success:
30842
- type: boolean
30843
- permissions:
30844
- type: object
30845
- properties: {}
30846
- additionalProperties: {}
30847
- required:
30848
- - id
30849
- - success
30850
- - permissions
30851
- additionalProperties: false
30852
- /v1/work-items/{id}/run:
30853
- post:
30854
- operationId: workitems_by_id_run_post
30855
- summary: Run a work item
30856
- description: Execute the task associated with a work item. Returns immediately; execution happens in the background.
30857
- tags:
30858
- - work-items
30859
- parameters:
30860
- - name: id
30861
- in: path
30862
- required: true
30863
- schema:
30864
- type: string
30865
- responses:
30866
- "200":
30867
- description: Successful response
30868
- "403":
30869
- description: Required tool permissions not approved
30870
- "404":
30871
- description: Work item or associated task not found
30872
- "409":
30873
- description: Work item is already running or not runnable
30874
30610
  /v1/workflows:
30875
30611
  get:
30876
30612
  operationId: workflows_get
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vellumai/assistant",
3
- "version": "0.10.7-dev.202607101836.11f2eba",
3
+ "version": "0.10.7-dev.202607102035.64f07ea",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "exports": {
@@ -703,10 +703,6 @@ describe("web_search_tool_result structural guard", () => {
703
703
  // web_search_tool_result is not emitted through the subagent event path.
704
704
  "runtime/routes/subagents-routes.ts",
705
705
 
706
- // Extracts tool results from persisted message content for work-item
707
- // display. web_search_tool_result blocks are not relevant here.
708
- "runtime/routes/work-items-routes.ts",
709
-
710
706
  // Media token counting iterates tool_result.contentBlocks for nested
711
707
  // image/file blocks. web_search_tool_result has opaque content with no
712
708
  // contentBlocks property, so it cannot contain nested media.
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Shared test helper: seed workspace config for real instead of mocking
3
+ * `config/loader`.
4
+ *
5
+ * Writes a top-level key into `$VELLUM_WORKSPACE_DIR/config.json`
6
+ * (read-modify-write, so seeding several keys composes) and bumps the file
7
+ * mtime monotonically so the loader's file-signature cache re-reads on the
8
+ * next `getConfig()`/`getConfigReadOnly()`. The production loader
9
+ * schema-merges the partial file over defaults — the same path a user's
10
+ * config.json takes.
11
+ *
12
+ * Node stdlib only, per the test-machinery isolation rules.
13
+ */
14
+ import { existsSync, readFileSync, utimesSync, writeFileSync } from "node:fs";
15
+ import { join } from "node:path";
16
+
17
+ let mtimeSeq = 0;
18
+
19
+ export function setConfig(key: string, value: unknown): void {
20
+ const path = join(process.env.VELLUM_WORKSPACE_DIR!, "config.json");
21
+ let config: Record<string, unknown> = {};
22
+ if (existsSync(path)) {
23
+ try {
24
+ const parsed = JSON.parse(readFileSync(path, "utf8")) as unknown;
25
+ if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
26
+ config = parsed as Record<string, unknown>;
27
+ }
28
+ } catch {
29
+ // Unparseable prior seed — start fresh; the loader treats a corrupt
30
+ // file as defaults anyway.
31
+ }
32
+ }
33
+ config[key] = value;
34
+ writeFileSync(path, JSON.stringify(config));
35
+ // Force a distinct mtime per write so the loader's size+mtime+ctime
36
+ // signature can never read two consecutive seeds as identical.
37
+ mtimeSeq += 1;
38
+ const stamp = new Date(Date.now() + mtimeSeq);
39
+ utimesSync(path, stamp, stamp);
40
+ }
@@ -5,24 +5,7 @@
5
5
  * prompt/completion payload lands on disk — and return `null`. The read-side
6
6
  * 4xx is exercised separately at the route layer.
7
7
  */
8
- import { afterAll, beforeEach, describe, expect, mock, test } from "bun:test";
9
-
10
- // Mutable so each test toggles the flag the store reads via `getConfigReadOnly`.
11
- let enabled = true;
12
- mock.module("../config/loader.js", () => ({
13
- getConfig: () => ({
14
- llmRequestLogs: { readSource: "local", enabled },
15
- }),
16
- getConfigReadOnly: () => ({
17
- llmRequestLogs: { readSource: "local", enabled },
18
- }),
19
- }));
20
-
21
- // `mock.module()` persists process-wide; reset so other files don't inherit a
22
- // stale value.
23
- afterAll(() => {
24
- enabled = true;
25
- });
8
+ import { beforeEach, describe, expect, test } from "bun:test";
26
9
 
27
10
  import { getLogsDb } from "../persistence/db-connection.js";
28
11
  import { initializeDb } from "../persistence/db-init.js";
@@ -33,6 +16,11 @@ import {
33
16
  recordSyntheticAgentErrorMessageLog,
34
17
  } from "../persistence/llm-request-log-store.js";
35
18
  import { llmRequestLogs } from "../persistence/schema/index.js";
19
+ import { setConfig } from "./helpers/set-config.js";
20
+
21
+ function setLlmRequestLogging(enabled: boolean): void {
22
+ setConfig("llmRequestLogs", { readSource: "local", enabled });
23
+ }
36
24
 
37
25
  await initializeDb();
38
26
 
@@ -43,7 +31,7 @@ function resetLogs(): void {
43
31
  describe("llmRequestLogs.enabled write gate", () => {
44
32
  beforeEach(() => {
45
33
  resetLogs();
46
- enabled = true;
34
+ setLlmRequestLogging(true);
47
35
  });
48
36
 
49
37
  test("recordRequestLog writes normally when logging is enabled", () => {
@@ -53,14 +41,14 @@ describe("llmRequestLogs.enabled write gate", () => {
53
41
  });
54
42
 
55
43
  test("recordRequestLog skips the write when logging is disabled", () => {
56
- enabled = false;
44
+ setLlmRequestLogging(false);
57
45
  const id = recordRequestLog("conv-1", '{"req":1}', '{"res":1}');
58
46
  expect(id).toBeNull();
59
47
  expect(getRequestLogsByConversationId("conv-1")).toEqual([]);
60
48
  });
61
49
 
62
50
  test("recordSyntheticAgentErrorMessageLog skips the write when disabled", () => {
63
- enabled = false;
51
+ setLlmRequestLogging(false);
64
52
  const id = recordSyntheticAgentErrorMessageLog({
65
53
  conversationId: "conv-2",
66
54
  messageId: "msg-2",
@@ -74,9 +62,9 @@ describe("llmRequestLogs.enabled write gate", () => {
74
62
  });
75
63
 
76
64
  test("re-enabling logging restores writes", () => {
77
- enabled = false;
65
+ setLlmRequestLogging(false);
78
66
  expect(recordRequestLog("conv-3", '{"req":1}', '{"res":1}')).toBeNull();
79
- enabled = true;
67
+ setLlmRequestLogging(true);
80
68
  const id = recordRequestLog("conv-3", '{"req":2}', '{"res":2}');
81
69
  expect(id).not.toBeNull();
82
70
  expect(getRequestLogsByConversationId("conv-3")).toHaveLength(1);
@@ -137,7 +137,6 @@ const BASELINE: Record<string, readonly string[]> = {
137
137
  "../../../../telemetry/watchdog-events-store.js",
138
138
  "../../../../tools/skills/delete-managed.js",
139
139
  "../../../channels/types.js",
140
- "../../../config/assistant-feature-flags.js",
141
140
  "../../../config/loader.js",
142
141
  "../../../config/memory-v3-gate.js",
143
142
  "../../../config/schema.js",
@@ -16,32 +16,11 @@ import { join } from "node:path";
16
16
  import { afterEach, beforeEach, describe, expect, mock, test } from "bun:test";
17
17
 
18
18
  // ── Shared mock setup ────────────────────────────────────────────────────────
19
- // Config mock must be declared before importing tool modules so that the
20
- // mock.module calls are hoisted above the dynamic imports.
21
-
22
- mock.module("../config/loader.js", () => ({
23
- getConfig: () => ({
24
- ui: {},
25
-
26
- provider: "anthropic",
27
- model: "test",
28
- maxTokens: 4096,
29
- dataDir: "/tmp",
30
- timeouts: {
31
- shellDefaultTimeoutSec: 120,
32
- shellMaxTimeoutSec: 600,
33
- permissionTimeoutSec: 300,
34
- },
35
- rateLimit: { maxRequestsPerMinute: 0 },
36
- secretDetection: {
37
- enabled: false,
38
- },
39
- }),
40
- loadConfig: () => ({}),
41
- invalidateConfigCache: () => {},
42
- loadRawConfig: () => ({}),
43
- saveRawConfig: () => {},
44
- }));
19
+ // The real config loader serves these tests: it reads from the per-test temp
20
+ // workspace and returns schema defaults (the timeout values the shell tool
21
+ // needs are the documented defaults). Mocking `config/loader` here would force
22
+ // the mock to mirror the loader's full export surface — modules under test
23
+ // import it by name, and a partial mock fails to link.
45
24
 
46
25
  // shell.ts uses the script proxy — stub it to avoid network side-effects.
47
26
  mock.module("../tools/network/script-proxy/index.js", () => ({
package/src/cli/AGENTS.md CHANGED
@@ -123,9 +123,10 @@ registerFooCommand(program);
123
123
  _synchronously_ at command registration (so it can't be a lazy
124
124
  `import()`) may stay hoisted behind a scoped
125
125
  `// eslint-disable-next-line cli/no-daemon-internals` with a comment
126
- explaining why. The only current case is `browser/operation-meta` in
126
+ explaining why. The only current case is `browser/operation-meta`, in
127
127
  `commands/browser.ts` (it drives synchronous subcommand generation and
128
- deliberately pulls no Playwright graph).
128
+ deliberately pulls no Playwright graph) and `commands/browser.help.ts`
129
+ (which derives the declarative help from the same contract).
129
130
 
130
131
  2. **Lazy-import daemon functionality inside the action.** Running daemon
131
132
  logic in-process is encouraged where it avoids an IPC round-trip (which