@vellumai/cli 0.6.0 → 0.6.1

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vellumai/cli",
3
- "version": "0.6.0",
3
+ "version": "0.6.1",
4
4
  "description": "CLI tools for vellum-assistant",
5
5
  "type": "module",
6
6
  "exports": {
@@ -64,7 +64,6 @@ mock.module("../lib/guardian-token.js", () => ({
64
64
  }));
65
65
 
66
66
  const readPlatformTokenMock = mock((): string | null => "platform-token");
67
- const fetchOrganizationIdMock = mock(async () => "org-123");
68
67
  const getPlatformUrlMock = mock(() => "https://platform.vellum.ai");
69
68
  const hatchAssistantMock = mock(async () => ({
70
69
  id: "platform-new-id",
@@ -142,7 +141,6 @@ const platformImportBundleFromGcsMock = mock(async () => ({
142
141
 
143
142
  mock.module("../lib/platform-client.js", () => ({
144
143
  readPlatformToken: readPlatformTokenMock,
145
- fetchOrganizationId: fetchOrganizationIdMock,
146
144
  getPlatformUrl: getPlatformUrlMock,
147
145
  hatchAssistant: hatchAssistantMock,
148
146
  platformInitiateExport: platformInitiateExportMock,
@@ -240,8 +238,6 @@ beforeEach(() => {
240
238
 
241
239
  readPlatformTokenMock.mockReset();
242
240
  readPlatformTokenMock.mockReturnValue("platform-token");
243
- fetchOrganizationIdMock.mockReset();
244
- fetchOrganizationIdMock.mockResolvedValue("org-123");
245
241
  getPlatformUrlMock.mockReset();
246
242
  getPlatformUrlMock.mockReturnValue("https://platform.vellum.ai");
247
243
  hatchAssistantMock.mockReset();
@@ -757,10 +753,7 @@ describe("resolveOrHatchTarget", () => {
757
753
  findAssistantByNameMock.mockReturnValue(null);
758
754
 
759
755
  const result = await resolveOrHatchTarget("platform", "nonexistent");
760
- expect(hatchAssistantMock).toHaveBeenCalledWith(
761
- "platform-token",
762
- "org-123",
763
- );
756
+ expect(hatchAssistantMock).toHaveBeenCalledWith("platform-token");
764
757
  expect(saveAssistantEntryMock).toHaveBeenCalledWith(
765
758
  expect.objectContaining({
766
759
  assistantId: "platform-new-id",
@@ -1099,7 +1092,6 @@ describe("signed-URL upload flow", () => {
1099
1092
  expect(platformImportBundleFromGcsMock).toHaveBeenCalledWith(
1100
1093
  "bundle-key-123",
1101
1094
  "platform-token",
1102
- "org-123",
1103
1095
  "https://platform.vellum.ai",
1104
1096
  );
1105
1097
  // Inline import should NOT be called
@@ -1145,7 +1137,6 @@ describe("signed-URL upload flow", () => {
1145
1137
  expect(platformImportPreflightFromGcsMock).toHaveBeenCalledWith(
1146
1138
  "bundle-key-123",
1147
1139
  "platform-token",
1148
- "org-123",
1149
1140
  "https://platform.vellum.ai",
1150
1141
  );
1151
1142
  // Inline preflight should NOT be called
@@ -1284,7 +1275,7 @@ describe("signed-URL upload flow", () => {
1284
1275
  // ---------------------------------------------------------------------------
1285
1276
 
1286
1277
  describe("platform teleport org ID and reordered flow", () => {
1287
- test("hatchAssistant is called with the org ID from fetchOrganizationId", async () => {
1278
+ test("hatchAssistant is called without orgId (authHeaders fetches it internally)", async () => {
1288
1279
  setArgv("--from", "my-local", "--platform");
1289
1280
 
1290
1281
  const localEntry = makeEntry("my-local", { cloud: "local" });
@@ -1294,21 +1285,14 @@ describe("platform teleport org ID and reordered flow", () => {
1294
1285
  return null;
1295
1286
  });
1296
1287
 
1297
- fetchOrganizationIdMock.mockResolvedValue("test-org-456");
1298
-
1299
1288
  const originalFetch = globalThis.fetch;
1300
1289
  globalThis.fetch = createFetchMock() as unknown as typeof globalThis.fetch;
1301
1290
 
1302
1291
  try {
1303
1292
  await teleport();
1304
1293
 
1305
- // fetchOrganizationId should have been called
1306
- expect(fetchOrganizationIdMock).toHaveBeenCalled();
1307
- // hatchAssistant must be called with (token, orgId)
1308
- expect(hatchAssistantMock).toHaveBeenCalledWith(
1309
- "platform-token",
1310
- "test-org-456",
1311
- );
1294
+ // hatchAssistant should be called with just the token (orgId is resolved internally by authHeaders)
1295
+ expect(hatchAssistantMock).toHaveBeenCalledWith("platform-token");
1312
1296
  } finally {
1313
1297
  globalThis.fetch = originalFetch;
1314
1298
  }
@@ -1432,7 +1416,6 @@ describe("platform teleport org ID and reordered flow", () => {
1432
1416
  "pre-uploaded-key-789",
1433
1417
  "platform-token",
1434
1418
  expect.any(String),
1435
- expect.any(String),
1436
1419
  );
1437
1420
  // Inline import should NOT be used since signed upload succeeded
1438
1421
  expect(platformImportBundleMock).not.toHaveBeenCalled();
@@ -0,0 +1,206 @@
1
+ import { describe, expect, test } from "bun:test";
2
+
3
+ import {
4
+ parseVersion,
5
+ compareVersions,
6
+ isVersionCompatible,
7
+ } from "../lib/version-compat.js";
8
+
9
+ describe("parseVersion", () => {
10
+ test("parses basic semver", () => {
11
+ expect(parseVersion("1.2.3")).toEqual({
12
+ major: 1,
13
+ minor: 2,
14
+ patch: 3,
15
+ pre: null,
16
+ });
17
+ });
18
+
19
+ test("strips v prefix", () => {
20
+ expect(parseVersion("v1.2.3")).toEqual({
21
+ major: 1,
22
+ minor: 2,
23
+ patch: 3,
24
+ pre: null,
25
+ });
26
+ });
27
+
28
+ test("strips V prefix", () => {
29
+ expect(parseVersion("V1.2.3")).toEqual({
30
+ major: 1,
31
+ minor: 2,
32
+ patch: 3,
33
+ pre: null,
34
+ });
35
+ });
36
+
37
+ test("defaults missing patch to 0", () => {
38
+ expect(parseVersion("1.2")).toEqual({
39
+ major: 1,
40
+ minor: 2,
41
+ patch: 0,
42
+ pre: null,
43
+ });
44
+ });
45
+
46
+ test("captures pre-release suffix", () => {
47
+ expect(parseVersion("0.6.0-staging.5")).toEqual({
48
+ major: 0,
49
+ minor: 6,
50
+ patch: 0,
51
+ pre: "staging.5",
52
+ });
53
+ });
54
+
55
+ test("captures pre-release with v prefix", () => {
56
+ expect(parseVersion("v0.6.0-staging.1")).toEqual({
57
+ major: 0,
58
+ minor: 6,
59
+ patch: 0,
60
+ pre: "staging.1",
61
+ });
62
+ });
63
+
64
+ test("captures hyphenated pre-release suffix", () => {
65
+ expect(parseVersion("1.0.0-pre-release-1")).toEqual({
66
+ major: 1,
67
+ minor: 0,
68
+ patch: 0,
69
+ pre: "pre-release-1",
70
+ });
71
+ });
72
+
73
+ test("returns null for single segment", () => {
74
+ expect(parseVersion("1")).toBeNull();
75
+ });
76
+
77
+ test("returns null for non-numeric segments", () => {
78
+ expect(parseVersion("abc.def")).toBeNull();
79
+ });
80
+
81
+ test("returns null for empty string", () => {
82
+ expect(parseVersion("")).toBeNull();
83
+ });
84
+ });
85
+
86
+ describe("compareVersions", () => {
87
+ // ── Basic numeric comparison ──────────────────────────────────────
88
+ test("equal versions return 0", () => {
89
+ expect(compareVersions("1.2.3", "1.2.3")).toBe(0);
90
+ });
91
+
92
+ test("higher major returns positive", () => {
93
+ expect(compareVersions("2.0.0", "1.0.0")).toBeGreaterThan(0);
94
+ });
95
+
96
+ test("lower major returns negative", () => {
97
+ expect(compareVersions("1.0.0", "2.0.0")).toBeLessThan(0);
98
+ });
99
+
100
+ test("higher minor returns positive", () => {
101
+ expect(compareVersions("1.3.0", "1.2.0")).toBeGreaterThan(0);
102
+ });
103
+
104
+ test("higher patch returns positive", () => {
105
+ expect(compareVersions("1.2.4", "1.2.3")).toBeGreaterThan(0);
106
+ });
107
+
108
+ // ── v prefix handling ─────────────────────────────────────────────
109
+ test("strips v prefix for comparison", () => {
110
+ expect(compareVersions("v1.2.3", "1.2.3")).toBe(0);
111
+ });
112
+
113
+ // ── Pre-release vs release ────────────────────────────────────────
114
+ test("pre-release sorts lower than release", () => {
115
+ expect(compareVersions("0.6.0-staging.1", "0.6.0")).toBeLessThan(0);
116
+ });
117
+
118
+ test("release sorts higher than pre-release", () => {
119
+ expect(compareVersions("0.6.0", "0.6.0-staging.1")).toBeGreaterThan(0);
120
+ });
121
+
122
+ // ── Pre-release numeric comparison ────────────────────────────────
123
+ test("staging.1 < staging.2", () => {
124
+ expect(compareVersions("0.6.0-staging.1", "0.6.0-staging.2")).toBeLessThan(
125
+ 0,
126
+ );
127
+ });
128
+
129
+ test("staging.10 > staging.2 (numeric, not lexical)", () => {
130
+ expect(
131
+ compareVersions("0.6.0-staging.10", "0.6.0-staging.2"),
132
+ ).toBeGreaterThan(0);
133
+ });
134
+
135
+ // ── Pre-release lexical comparison ────────────────────────────────
136
+ test("alpha < beta (lexical)", () => {
137
+ expect(compareVersions("1.0.0-alpha", "1.0.0-beta")).toBeLessThan(0);
138
+ });
139
+
140
+ // ── Mixed numeric vs non-numeric per §11.4.4 ─────────────────────
141
+ test("numeric identifier sorts lower than non-numeric", () => {
142
+ expect(compareVersions("1.0.0-1", "1.0.0-alpha")).toBeLessThan(0);
143
+ });
144
+
145
+ // ── Fewer pre-release identifiers sorts earlier ───────────────────
146
+ test("fewer pre-release identifiers sorts earlier", () => {
147
+ expect(compareVersions("1.0.0-alpha", "1.0.0-alpha.1")).toBeLessThan(0);
148
+ });
149
+
150
+ // ── Returns null for unparseable input ────────────────────────────
151
+ test("returns null if first version is unparseable", () => {
152
+ expect(compareVersions("bad", "1.0.0")).toBeNull();
153
+ });
154
+
155
+ test("returns null if second version is unparseable", () => {
156
+ expect(compareVersions("1.0.0", "bad")).toBeNull();
157
+ });
158
+
159
+ // ── Different major.minor.patch trumps pre-release ────────────────
160
+ test("higher patch wins regardless of pre-release", () => {
161
+ expect(compareVersions("0.6.1", "0.6.0-staging.99")).toBeGreaterThan(0);
162
+ });
163
+
164
+ // ── Sort integration ──────────────────────────────────────────────
165
+ test("Array.sort produces correct semver order", () => {
166
+ const versions = [
167
+ "0.6.0",
168
+ "0.6.0-staging.2",
169
+ "0.5.9",
170
+ "0.6.0-staging.10",
171
+ "v0.6.0-staging.1",
172
+ "0.6.1",
173
+ ];
174
+ const sorted = [...versions].sort((a, b) => compareVersions(a, b) ?? 0);
175
+ expect(sorted).toEqual([
176
+ "0.5.9",
177
+ "v0.6.0-staging.1",
178
+ "0.6.0-staging.2",
179
+ "0.6.0-staging.10",
180
+ "0.6.0",
181
+ "0.6.1",
182
+ ]);
183
+ });
184
+ });
185
+
186
+ describe("isVersionCompatible", () => {
187
+ test("same major.minor are compatible", () => {
188
+ expect(isVersionCompatible("1.2.3", "1.2.5")).toBe(true);
189
+ });
190
+
191
+ test("different minor are incompatible", () => {
192
+ expect(isVersionCompatible("1.2.3", "1.3.0")).toBe(false);
193
+ });
194
+
195
+ test("different major are incompatible", () => {
196
+ expect(isVersionCompatible("1.2.3", "2.2.3")).toBe(false);
197
+ });
198
+
199
+ test("pre-release on same major.minor is compatible", () => {
200
+ expect(isVersionCompatible("0.6.0-staging.5", "0.6.0")).toBe(true);
201
+ });
202
+
203
+ test("returns false for unparseable input", () => {
204
+ expect(isVersionCompatible("bad", "1.0.0")).toBe(false);
205
+ });
206
+ });
@@ -6,7 +6,6 @@ import { getBackupsDir, formatSize } from "../lib/backup-ops.js";
6
6
  import { loadGuardianToken, leaseGuardianToken } from "../lib/guardian-token";
7
7
  import {
8
8
  readPlatformToken,
9
- fetchOrganizationId,
10
9
  platformInitiateExport,
11
10
  platformPollExportStatus,
12
11
  platformDownloadExport,
@@ -196,24 +195,11 @@ async function backupPlatform(
196
195
  process.exit(1);
197
196
  }
198
197
 
199
- let orgId: string;
200
- try {
201
- orgId = await fetchOrganizationId(token, runtimeUrl);
202
- } catch (err) {
203
- const msg = err instanceof Error ? err.message : String(err);
204
- if (msg.includes("401") || msg.includes("403")) {
205
- console.error("Authentication failed. Run 'vellum login' to refresh.");
206
- process.exit(1);
207
- }
208
- throw err;
209
- }
210
-
211
198
  // Step 2 — Initiate export job
212
199
  let jobId: string;
213
200
  try {
214
201
  const result = await platformInitiateExport(
215
202
  token,
216
- orgId,
217
203
  "CLI backup",
218
204
  runtimeUrl,
219
205
  );
@@ -244,7 +230,7 @@ async function backupPlatform(
244
230
  while (Date.now() < deadline) {
245
231
  let status: { status: string; downloadUrl?: string; error?: string };
246
232
  try {
247
- status = await platformPollExportStatus(jobId, token, orgId, runtimeUrl);
233
+ status = await platformPollExportStatus(jobId, token, runtimeUrl);
248
234
  } catch (err) {
249
235
  const msg = err instanceof Error ? err.message : String(err);
250
236
  // Let non-transient errors (e.g. 404 "job not found") propagate immediately
@@ -0,0 +1,146 @@
1
+ /**
2
+ * `vellum events [assistant]`
3
+ *
4
+ * Subscribe to assistant events via the SSE endpoint and stream them
5
+ * to stdout. By default, events are rendered as human-readable
6
+ * markdown. Pass `--json` to emit one JSON object per event,
7
+ * separated by newlines.
8
+ */
9
+
10
+ import { extractFlag } from "../lib/arg-utils.js";
11
+ import { AssistantClient } from "../lib/assistant-client.js";
12
+
13
+ function printUsage(): void {
14
+ console.log(`vellum events - Stream events from a running assistant
15
+
16
+ USAGE:
17
+ vellum events [assistant] [options]
18
+
19
+ ARGUMENTS:
20
+ [assistant] Instance name (default: active assistant)
21
+
22
+ OPTIONS:
23
+ --conversation-key <key> Scope to a single conversation
24
+ --json Output raw JSON events (one per line)
25
+ -h, --help Show this help message
26
+
27
+ EXAMPLES:
28
+ vellum events
29
+ vellum events my-assistant
30
+ vellum events --json
31
+ vellum events --conversation-key my-thread
32
+ `);
33
+ }
34
+
35
+ interface AssistantEvent {
36
+ id: string;
37
+ assistantId: string;
38
+ conversationId?: string;
39
+ emittedAt: string;
40
+ message: {
41
+ type: string;
42
+ text?: string;
43
+ thinking?: string;
44
+ toolName?: string;
45
+ input?: Record<string, unknown>;
46
+ result?: string;
47
+ isError?: boolean;
48
+ content?: string;
49
+ message?: string;
50
+ chunk?: string;
51
+ conversationId?: string;
52
+ [key: string]: unknown;
53
+ };
54
+ }
55
+
56
+ /** Render an event as human-readable markdown to stdout. */
57
+ function renderMarkdown(event: AssistantEvent): void {
58
+ const msg = event.message;
59
+ switch (msg.type) {
60
+ case "assistant_text_delta":
61
+ process.stdout.write(msg.text ?? "");
62
+ break;
63
+ case "assistant_thinking_delta":
64
+ process.stdout.write(msg.thinking ?? "");
65
+ break;
66
+ case "tool_use_start":
67
+ console.log(`\n> **Tool call:** \`${msg.toolName}\``);
68
+ if (msg.input && Object.keys(msg.input).length > 0) {
69
+ console.log("```json");
70
+ console.log(JSON.stringify(msg.input, null, 2));
71
+ console.log("```");
72
+ }
73
+ break;
74
+ case "tool_input_delta":
75
+ process.stdout.write(msg.content ?? "");
76
+ break;
77
+ case "tool_result":
78
+ if (msg.isError) {
79
+ console.log(`\n> **Tool error** (\`${msg.toolName}\`): ${msg.result}`);
80
+ } else {
81
+ console.log(`\n> **Tool result** (\`${msg.toolName}\`): ${msg.result}`);
82
+ }
83
+ break;
84
+ case "tool_output_chunk":
85
+ process.stdout.write(msg.chunk ?? "");
86
+ break;
87
+ case "message_complete":
88
+ console.log("\n");
89
+ break;
90
+ case "error":
91
+ console.error(`\n**Error:** ${msg.message}`);
92
+ break;
93
+ case "user_message_echo":
94
+ console.log(`\n**You:** ${msg.text}`);
95
+ break;
96
+ default:
97
+ // Silently skip events that don't have a markdown representation
98
+ // (e.g. heartbeat comments, activity states, etc.)
99
+ break;
100
+ }
101
+ }
102
+
103
+ export async function events(): Promise<void> {
104
+ const rawArgs = process.argv.slice(3);
105
+
106
+ if (rawArgs.includes("--help") || rawArgs.includes("-h")) {
107
+ printUsage();
108
+ return;
109
+ }
110
+
111
+ const jsonOutput = rawArgs.includes("--json");
112
+ let args = rawArgs.filter((a) => a !== "--json");
113
+
114
+ const [conversationKey, filteredArgs] = extractFlag(
115
+ args,
116
+ "--conversation-key",
117
+ );
118
+ args = filteredArgs;
119
+
120
+ const assistantId = args[0];
121
+
122
+ const client = new AssistantClient({ assistantId });
123
+
124
+ // Use an explicit AbortController so we can clean up on SIGINT
125
+ const controller = new AbortController();
126
+ process.on("SIGINT", () => {
127
+ controller.abort();
128
+ process.exit(0);
129
+ });
130
+
131
+ const query: Record<string, string> = {};
132
+ if (conversationKey) {
133
+ query.conversationKey = conversationKey;
134
+ }
135
+
136
+ for await (const event of client.stream<AssistantEvent>("/events", {
137
+ signal: controller.signal,
138
+ query,
139
+ })) {
140
+ if (jsonOutput) {
141
+ console.log(JSON.stringify(event));
142
+ } else {
143
+ renderMarkdown(event);
144
+ }
145
+ }
146
+ }
@@ -21,7 +21,6 @@ import { hatchGcp } from "../lib/gcp";
21
21
  import type { PollResult, WatchHatchingResult } from "../lib/gcp";
22
22
  import { hatchLocal } from "../lib/hatch-local";
23
23
  import {
24
- fetchOrganizationId,
25
24
  getPlatformUrl,
26
25
  hatchAssistant,
27
26
  readPlatformToken,
@@ -594,19 +593,7 @@ async function hatchVellumPlatform(): Promise<void> {
594
593
  console.log(" Hatching assistant on Vellum platform...");
595
594
  console.log("");
596
595
 
597
- let orgId: string;
598
- try {
599
- orgId = await fetchOrganizationId(token);
600
- } catch (err) {
601
- const msg = err instanceof Error ? err.message : String(err);
602
- if (msg.includes("401") || msg.includes("403")) {
603
- console.error("Authentication failed. Run 'vellum login' to refresh.");
604
- process.exit(1);
605
- }
606
- throw err;
607
- }
608
-
609
- const result = await hatchAssistant(token, orgId);
596
+ const result = await hatchAssistant(token);
610
597
 
611
598
  const platformUrl = getPlatformUrl();
612
599
 
@@ -0,0 +1,105 @@
1
+ /**
2
+ * `vellum message <assistant> <message>`
3
+ *
4
+ * Send a message to a running assistant via its runtime HTTP API and
5
+ * print the result. This is a fire-and-send command — it does NOT
6
+ * subscribe to SSE events (use `vellum events` for that).
7
+ */
8
+
9
+ import { extractFlag } from "../lib/arg-utils.js";
10
+ import { AssistantClient } from "../lib/assistant-client.js";
11
+
12
+ function printUsage(): void {
13
+ console.log(`vellum message - Send a message to a running assistant
14
+
15
+ USAGE:
16
+ vellum message [assistant] <message>
17
+
18
+ ARGUMENTS:
19
+ [assistant] Instance name (default: active assistant)
20
+ <message> Message content to send
21
+
22
+ OPTIONS:
23
+ --conversation-key <key> Conversation key (default: stable key per channel/interface)
24
+ --json Output raw JSON response
25
+
26
+ EXAMPLES:
27
+ vellum message "hello"
28
+ vellum message my-assistant "ping"
29
+ vellum message --conversation-key my-thread "hello"
30
+ vellum message --json "hello"
31
+ `);
32
+ }
33
+
34
+ export async function message(): Promise<void> {
35
+ const rawArgs = process.argv.slice(3);
36
+
37
+ if (rawArgs.includes("--help") || rawArgs.includes("-h")) {
38
+ printUsage();
39
+ return;
40
+ }
41
+
42
+ const jsonOutput = rawArgs.includes("--json");
43
+ let args = rawArgs.filter((a) => a !== "--json");
44
+
45
+ const [conversationKey, filteredArgs] = extractFlag(
46
+ args,
47
+ "--conversation-key",
48
+ );
49
+ args = filteredArgs;
50
+
51
+ let assistantId: string | undefined;
52
+ let messageContent: string | undefined;
53
+
54
+ if (args.length >= 2) {
55
+ // vellum message <assistant> <message>
56
+ assistantId = args[0];
57
+ messageContent = args[1];
58
+ } else if (args.length === 1) {
59
+ // vellum message <message> (uses active/latest assistant)
60
+ messageContent = args[0];
61
+ }
62
+
63
+ if (!messageContent) {
64
+ console.error("Error: message content is required.");
65
+ console.error("");
66
+ printUsage();
67
+ process.exit(1);
68
+ }
69
+
70
+ const client = new AssistantClient({ assistantId });
71
+
72
+ const payload: Record<string, string> = {
73
+ content: messageContent,
74
+ sourceChannel: "vellum",
75
+ interface: "cli",
76
+ };
77
+ if (conversationKey) {
78
+ payload.conversationKey = conversationKey;
79
+ }
80
+
81
+ const response = await client.post("/messages/", payload);
82
+
83
+ if (!response.ok) {
84
+ const body = await response.text().catch(() => "");
85
+ console.error(
86
+ `Error: HTTP ${response.status}: ${body || response.statusText}`,
87
+ );
88
+ process.exit(1);
89
+ }
90
+
91
+ const result = (await response.json()) as {
92
+ accepted: boolean;
93
+ messageId: string;
94
+ };
95
+
96
+ if (jsonOutput) {
97
+ console.log(JSON.stringify(result, null, 2));
98
+ } else {
99
+ if (result.accepted) {
100
+ console.log(`Message accepted (id: ${result.messageId})`);
101
+ } else {
102
+ console.log(`Message rejected (id: ${result.messageId})`);
103
+ }
104
+ }
105
+ }
@@ -8,7 +8,6 @@ import {
8
8
  } from "../lib/guardian-token.js";
9
9
  import {
10
10
  readPlatformToken,
11
- fetchOrganizationId,
12
11
  rollbackPlatformAssistant,
13
12
  platformImportPreflight,
14
13
  platformImportBundle,
@@ -177,18 +176,6 @@ async function restorePlatform(
177
176
  process.exit(1);
178
177
  }
179
178
 
180
- let orgId: string;
181
- try {
182
- orgId = await fetchOrganizationId(token, entry.runtimeUrl);
183
- } catch (err) {
184
- const msg = err instanceof Error ? err.message : String(err);
185
- if (msg.includes("401") || msg.includes("403")) {
186
- console.error("Authentication failed. Run 'vellum login' to refresh.");
187
- process.exit(1);
188
- }
189
- throw err;
190
- }
191
-
192
179
  // Step 2 — Dry-run path
193
180
  if (opts.dryRun) {
194
181
  if (opts.version) {
@@ -205,7 +192,6 @@ async function restorePlatform(
205
192
  preflightResult = await platformImportPreflight(
206
193
  new Uint8Array(bundleData),
207
194
  token,
208
- orgId,
209
195
  entry.runtimeUrl,
210
196
  );
211
197
  } catch (err) {
@@ -316,12 +302,7 @@ async function restorePlatform(
316
302
  );
317
303
 
318
304
  try {
319
- await rollbackPlatformAssistant(
320
- token,
321
- orgId,
322
- opts.version,
323
- entry.runtimeUrl,
324
- );
305
+ await rollbackPlatformAssistant(token, opts.version, entry.runtimeUrl);
325
306
  } catch (err) {
326
307
  const msg = err instanceof Error ? err.message : String(err);
327
308
  if (msg.includes("401") || msg.includes("403")) {
@@ -345,7 +326,6 @@ async function restorePlatform(
345
326
  importResult = await platformImportBundle(
346
327
  new Uint8Array(bundleData),
347
328
  token,
348
- orgId,
349
329
  entry.runtimeUrl,
350
330
  );
351
331
  } catch (err) {