@vellumai/assistant 0.12.2-staging.4 → 0.12.2-staging.6

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 (57) hide show
  1. package/Dockerfile +7 -7
  2. package/openapi.yaml +151 -53
  3. package/package.json +5 -4
  4. package/scripts/bundled-plugin-packages.ts +154 -0
  5. package/scripts/generate-bundled-plugin-packages.ts +29 -0
  6. package/scripts/test.ts +15 -13
  7. package/src/__tests__/managed-store.test.ts +121 -0
  8. package/src/__tests__/scaffold-managed-skill-tool.test.ts +88 -0
  9. package/src/calls/__tests__/voice-control-protocol.test.ts +24 -2
  10. package/src/calls/__tests__/voice-session-bridge.test.ts +22 -2
  11. package/src/calls/voice-control-protocol.ts +13 -4
  12. package/src/calls/voice-session-bridge.ts +27 -6
  13. package/src/cli/commands/__tests__/plugins.test.ts +66 -0
  14. package/src/cli/commands/plugins.ts +50 -18
  15. package/src/cli/lib/__tests__/install-from-github.test.ts +67 -0
  16. package/src/cli/lib/__tests__/local-plugin-upgrade.test.ts +169 -0
  17. package/src/cli/lib/__tests__/plugin-catalog-cache.test.ts +57 -0
  18. package/src/cli/lib/__tests__/plugin-catalog-platform.test.ts +14 -0
  19. package/src/cli/lib/__tests__/plugin-catalog-resolve.test.ts +27 -1
  20. package/src/cli/lib/__tests__/plugin-details.test.ts +9 -2
  21. package/src/cli/lib/__tests__/plugin-marketplace.test.ts +20 -0
  22. package/src/cli/lib/__tests__/plugins-install-offline.test.ts +43 -0
  23. package/src/cli/lib/__tests__/search-plugins.test.ts +31 -0
  24. package/src/cli/lib/bundled-plugin-packages.json +4 -0
  25. package/src/cli/lib/bundled-plugin-packages.ts +87 -0
  26. package/src/cli/lib/diff-plugin.ts +1 -1
  27. package/src/cli/lib/inspect-plugin.ts +80 -12
  28. package/src/cli/lib/install-from-github.ts +133 -76
  29. package/src/cli/lib/plugin-catalog-cache.ts +22 -3
  30. package/src/cli/lib/plugin-catalog-local.ts +13 -3
  31. package/src/cli/lib/plugin-catalog-platform.ts +6 -1
  32. package/src/cli/lib/plugin-catalog-resolve.ts +20 -0
  33. package/src/cli/lib/plugin-details.ts +12 -0
  34. package/src/cli/lib/plugin-marketplace.ts +121 -21
  35. package/src/cli/lib/plugin-pin-history.ts +5 -2
  36. package/src/cli/lib/search-plugins.ts +58 -16
  37. package/src/cli/lib/upgrade-plugin.ts +48 -3
  38. package/src/config/bundled-skills/skill-management/SKILL.md +1 -1
  39. package/src/config/bundled-skills/skill-management/TOOLS.json +7 -7
  40. package/src/daemon/conversation-tool-setup.ts +4 -22
  41. package/src/live-voice/__tests__/live-voice-look-follow-up.test.ts +374 -0
  42. package/src/live-voice/__tests__/live-voice-vad.test.ts +658 -3
  43. package/src/live-voice/__tests__/protocol.test.ts +48 -0
  44. package/src/live-voice/__tests__/session-controls.test.ts +43 -0
  45. package/src/live-voice/live-voice-session.ts +784 -64
  46. package/src/live-voice/protocol.ts +20 -0
  47. package/src/live-voice/session-controls.ts +61 -3
  48. package/src/monitoring/plugin-auto-update.ts +6 -0
  49. package/src/plugins/defaults/memory/__tests__/memory-retrospective-prompt.test.ts +15 -0
  50. package/src/plugins/defaults/memory/memory-retrospective-prompt.ts +1 -1
  51. package/src/runtime/routes/__tests__/plugins-routes.test.ts +102 -0
  52. package/src/runtime/routes/plugins-routes.ts +69 -49
  53. package/src/skills/managed-store.ts +153 -31
  54. package/src/tools/skills/find-similar-skills.test.ts +214 -2
  55. package/src/tools/skills/find-similar-skills.ts +62 -9
  56. package/src/tools/skills/resolve-execute-invocation.ts +24 -0
  57. package/src/tools/skills/scaffold-managed.ts +16 -13
@@ -800,6 +800,54 @@ describe("parseLiveVoiceClientTextFrame", () => {
800
800
  });
801
801
  });
802
802
 
803
+ test("parses the lookFrames capability on the start frame", () => {
804
+ const result = validateLiveVoiceClientFrame({
805
+ type: "start",
806
+ lookFrames: true,
807
+ audio: { mimeType: "audio/pcm", sampleRate: 24000, channels: 1 },
808
+ });
809
+
810
+ expect(result.ok).toBe(true);
811
+ if (!result.ok) {
812
+ return;
813
+ }
814
+ expect(result.frame).toMatchObject({ type: "start", lookFrames: true });
815
+ });
816
+
817
+ test("omits lookFrames from the start frame when false", () => {
818
+ // False and absent mean the same thing: no look frame is coming, so the
819
+ // session must not wait for one.
820
+ const result = validateLiveVoiceClientFrame({
821
+ type: "start",
822
+ lookFrames: false,
823
+ audio: { mimeType: "audio/pcm", sampleRate: 24000, channels: 1 },
824
+ });
825
+
826
+ expect(result.ok).toBe(true);
827
+ if (!result.ok) {
828
+ return;
829
+ }
830
+ expect("lookFrames" in result.frame).toBe(false);
831
+ });
832
+
833
+ test("returns a typed protocol error for a non-boolean lookFrames", () => {
834
+ const result = validateLiveVoiceClientFrame({
835
+ type: "start",
836
+ lookFrames: 1,
837
+ audio: { mimeType: "audio/pcm", sampleRate: 24000, channels: 1 },
838
+ });
839
+
840
+ expect(result.ok).toBe(false);
841
+ if (result.ok) {
842
+ return;
843
+ }
844
+ expect(result.error).toMatchObject({
845
+ code: "invalid_field",
846
+ field: "lookFrames",
847
+ frameType: "start",
848
+ });
849
+ });
850
+
803
851
  test("returns typed protocol errors for missing audio configuration fields", () => {
804
852
  const result = validateLiveVoiceClientFrame({
805
853
  type: "start",
@@ -53,6 +53,12 @@ describe("requestedSessionControl", () => {
53
53
  });
54
54
  });
55
55
 
56
+ test("task stop needs no client declaration", () => {
57
+ expect(requestedSessionControl("Okay. [TASK:STOP]", [])).toEqual({
58
+ action: "task_stop",
59
+ });
60
+ });
61
+
56
62
  test("a client control needs the client's declaration", () => {
57
63
  expect(requestedSessionControl("Bye. [END_CALL]", [])).toBeNull();
58
64
  expect(requestedSessionControl("Bye. [END_CALL]", ["end"])).toEqual({
@@ -68,9 +74,21 @@ describe("sessionControlTeaching", () => {
68
74
  expect(teaching).toContain("[UPDATES:FEWER]");
69
75
  expect(teaching).toContain("[MUTE]");
70
76
  expect(teaching).not.toContain("[END_CALL]");
77
+ expect(teaching).not.toContain("[TASK:STOP]");
71
78
  expect(teaching).toContain("Never emit any other bracketed marker.");
72
79
  });
73
80
 
81
+ test("teaches task stop only while an unfinished task is pending", () => {
82
+ const teaching = sessionControlTeaching(
83
+ [],
84
+ {},
85
+ { unfinishedTaskPending: true },
86
+ );
87
+
88
+ expect(teaching).toContain("[TASK:STOP]");
89
+ expect(teaching).toContain("not when they interrupt with a question");
90
+ });
91
+
74
92
  test("a device that can show both asks which one a bare look means", () => {
75
93
  const teaching = sessionControlTeaching(["look_screen", "look_camera"], {});
76
94
 
@@ -105,6 +123,31 @@ describe("sessionControlTeaching", () => {
105
123
  );
106
124
  });
107
125
 
126
+ // A client that sends a fresh frame for every look lets the session answer
127
+ // it, so the reply asking for the look only acknowledges, and asking again is
128
+ // how a share already running gets looked at as it is now.
129
+ test("a client that sends look frames is taught the look is answered for it", () => {
130
+ const teaching = sessionControlTeaching(
131
+ ["look_screen", "look_camera"],
132
+ {},
133
+ { lookFrames: true },
134
+ );
135
+
136
+ expect(teaching).toContain("[LOOK:SCREEN]");
137
+ expect(teaching).toContain(
138
+ "Use it even when their screen is already shared with you",
139
+ );
140
+ expect(teaching).toContain("Use it even when the camera is already on");
141
+ expect(teaching).not.toContain("take it from their next words");
142
+ });
143
+
144
+ test("a client that sends no look frames keeps the next-words look", () => {
145
+ const teaching = sessionControlTeaching(["look_screen"], {});
146
+
147
+ expect(teaching).toContain("take it from their next words");
148
+ expect(teaching).not.toContain("Use it even when");
149
+ });
150
+
108
151
  test("the front-door leg keeps its verdict tokens", () => {
109
152
  expect(sessionControlTeaching(["end"], { frontDoor: true })).not.toContain(
110
153
  "Never emit any other bracketed marker.",