@assethub/cli 0.1.18 → 0.1.19

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.
@@ -0,0 +1,30 @@
1
+ import type { CanvasExecution, ExecutionContext } from '@assethub/api-client';
2
+ import { executeRecorded, resumeRecorded } from './execution.js';
3
+ type Session = Parameters<typeof executeRecorded>[0];
4
+ type NodeMeshBatch = {
5
+ operationId: string;
6
+ nodeId: string;
7
+ canvasId: number;
8
+ baseUrl: string;
9
+ ownerId: string;
10
+ body: Record<string, unknown>;
11
+ children: Array<{
12
+ nodeId: string;
13
+ operationId: string;
14
+ }>;
15
+ skipped: Array<{
16
+ nodeId: string;
17
+ meshStatus?: string;
18
+ }>;
19
+ agent?: ExecutionContext['agent'];
20
+ parentRunId?: string;
21
+ };
22
+ export type NodeMeshBatchResult = Pick<NodeMeshBatch, 'operationId' | 'nodeId' | 'skipped'> & {
23
+ executions: CanvasExecution[];
24
+ };
25
+ export declare const executeNodeMeshBatch: (session: Session, input: Omit<NodeMeshBatch, "baseUrl" | "ownerId" | "canvasId" | "children"> & {
26
+ children: string[];
27
+ }) => Promise<NodeMeshBatchResult>;
28
+ export declare const resumeNodeMeshBatch: (options: Parameters<typeof resumeRecorded>[0]) => Promise<NodeMeshBatchResult | undefined>;
29
+ export {};
30
+ //# sourceMappingURL=nodeMeshBatch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nodeMeshBatch.d.ts","sourceRoot":"","sources":["../src/nodeMeshBatch.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,eAAe,EACf,gBAAgB,EAEjB,MAAM,sBAAsB,CAAA;AAE7B,OAAO,EAIL,eAAe,EAEf,cAAc,EAEf,MAAM,gBAAgB,CAAA;AAEvB,KAAK,OAAO,GAAG,UAAU,CAAC,OAAO,eAAe,CAAC,CAAC,CAAC,CAAC,CAAA;AACpD,KAAK,aAAa,GAAG;IACnB,WAAW,EAAE,MAAM,CAAA;IACnB,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,MAAM,CAAA;IAChB,OAAO,EAAE,MAAM,CAAA;IACf,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC7B,QAAQ,EAAE,KAAK,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAC,CAAC,CAAA;IACtD,OAAO,EAAE,KAAK,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAC,CAAC,CAAA;IACrD,KAAK,CAAC,EAAE,gBAAgB,CAAC,OAAO,CAAC,CAAA;IACjC,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB,CAAA;AACD,MAAM,MAAM,mBAAmB,GAAG,IAAI,CACpC,aAAa,EACb,aAAa,GAAG,QAAQ,GAAG,SAAS,CACrC,GAAG;IAAC,UAAU,EAAE,eAAe,EAAE,CAAA;CAAC,CAAA;AAwDnC,eAAO,MAAM,oBAAoB,GAC/B,SAAS,OAAO,EAChB,OAAO,IAAI,CACT,aAAa,EACb,SAAS,GAAG,SAAS,GAAG,UAAU,GAAG,UAAU,CAChD,GAAG;IAAC,QAAQ,EAAE,MAAM,EAAE,CAAA;CAAC,KACvB,OAAO,CAAC,mBAAmB,CAsC7B,CAAA;AAED,eAAO,MAAM,mBAAmB,GAC9B,SAAS,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC,CAAC,CAAC,KAC5C,OAAO,CAAC,mBAAmB,GAAG,SAAS,CA0DzC,CAAA"}
@@ -0,0 +1,122 @@
1
+ import { join } from 'node:path';
2
+ import { readState, writeState } from './canvas.js';
3
+ import { activeExecution, childOperationId, CliExecutionError, executeRecorded, openExecutionSession, resumeRecorded, hasRecordedOperation, } from './execution.js';
4
+ const uuid = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
5
+ const batchPath = (stateDir, id) => {
6
+ if (!uuid.test(id))
7
+ throw new Error('Operation ID must be a UUID');
8
+ return join(stateDir, 'node-batches', `${id}.json`);
9
+ };
10
+ const submitBatch = async (session, batch) => {
11
+ activeExecution.batchOperationId = batch.operationId;
12
+ const executions = [];
13
+ for (const child of batch.children) {
14
+ try {
15
+ const result = (await hasRecordedOperation(session.stateDir, child.operationId))
16
+ ? await resumeRecorded({
17
+ ...session,
18
+ operationId: child.operationId,
19
+ expectedCanvasId: batch.canvasId,
20
+ expectedCanvasNodeId: child.nodeId,
21
+ expectedOperation: 'mesh.generate',
22
+ expectedBody: batch.body,
23
+ })
24
+ : await executeRecorded(session, 'mesh.generate', batch.body, {
25
+ operationId: child.operationId,
26
+ canvasNode: { nodeId: child.nodeId },
27
+ agent: batch.agent,
28
+ parentRunId: batch.parentRunId,
29
+ });
30
+ executions.push(result.execution);
31
+ }
32
+ catch (error) {
33
+ throw new CliExecutionError(`Node ${child.nodeId} failed (${child.operationId}). Resume batch ${batch.operationId}: ${error instanceof Error ? error.message : String(error)}`, error instanceof CliExecutionError ? error.exitCode : 1, batch.operationId);
34
+ }
35
+ }
36
+ return {
37
+ operationId: batch.operationId,
38
+ nodeId: batch.nodeId,
39
+ executions,
40
+ skipped: batch.skipped,
41
+ };
42
+ };
43
+ export const executeNodeMeshBatch = async (session, input) => {
44
+ const batch = JSON.parse(JSON.stringify({
45
+ ...input,
46
+ baseUrl: session.baseUrl,
47
+ ownerId: session.ownerId,
48
+ canvasId: session.canvas.id,
49
+ children: input.children.map(nodeId => ({
50
+ nodeId,
51
+ operationId: childOperationId(input.operationId, nodeId),
52
+ })),
53
+ }));
54
+ const path = batchPath(session.stateDir, batch.operationId);
55
+ // Pin the entire target set before any paid dispatch. Per-child receipts retain
56
+ // resolved server inputs; a retry never discovers a changed split again.
57
+ try {
58
+ await writeState(path, batch, { exclusive: true });
59
+ }
60
+ catch (error) {
61
+ if (!error ||
62
+ typeof error !== 'object' ||
63
+ !('code' in error) ||
64
+ error.code !== 'EEXIST')
65
+ throw error;
66
+ const existing = await resumeNodeMeshBatch({
67
+ ...session,
68
+ operationId: input.operationId,
69
+ expectedCanvasId: session.canvas.id,
70
+ expectedCanvasNodeId: input.nodeId,
71
+ expectedOperation: 'mesh.generate',
72
+ expectedBody: input.body,
73
+ });
74
+ if (!existing)
75
+ throw new Error('Saved node batch not found');
76
+ return existing;
77
+ }
78
+ return submitBatch(session, batch);
79
+ };
80
+ export const resumeNodeMeshBatch = async (options) => {
81
+ const batch = (await readState(batchPath(options.stateDir, options.operationId)));
82
+ if (batch === undefined)
83
+ return undefined;
84
+ if (options.expectedOperation !== undefined &&
85
+ options.expectedOperation !== 'mesh.generate')
86
+ throw new Error('Saved operation has a different operation type');
87
+ if (!batch ||
88
+ batch.operationId !== options.operationId ||
89
+ typeof batch.nodeId !== 'string' ||
90
+ !Number.isSafeInteger(batch.canvasId) ||
91
+ typeof batch.baseUrl !== 'string' ||
92
+ typeof batch.ownerId !== 'string' ||
93
+ !batch.body ||
94
+ typeof batch.body !== 'object' ||
95
+ Array.isArray(batch.body) ||
96
+ !Array.isArray(batch.children) ||
97
+ !batch.children.every(child => child &&
98
+ typeof child.nodeId === 'string' &&
99
+ uuid.test(child.operationId)) ||
100
+ !Array.isArray(batch.skipped))
101
+ throw new Error('Invalid saved node batch');
102
+ if (batch.baseUrl !== options.client.baseUrl)
103
+ throw new Error('Saved operation belongs to a different API origin');
104
+ if (options.expectedCanvasId !== undefined &&
105
+ options.expectedCanvasId !== batch.canvasId)
106
+ throw new Error('Saved operation belongs to a different canvas');
107
+ if (options.expectedCanvasNodeId !== undefined &&
108
+ options.expectedCanvasNodeId !== batch.nodeId)
109
+ throw new Error('Saved operation belongs to a different canvas node');
110
+ if (options.expectedBody !== undefined &&
111
+ JSON.stringify(options.expectedBody) !== JSON.stringify(batch.body))
112
+ throw new Error('Operation ID already belongs to different inputs; use runs resume or a new operation ID');
113
+ const session = await openExecutionSession({
114
+ ...options,
115
+ canvasId: batch.canvasId,
116
+ operation: 'mesh.generate',
117
+ create: false,
118
+ });
119
+ if (session.ownerId !== batch.ownerId)
120
+ throw new Error('Saved operation belongs to a different organization');
121
+ return submitBatch(session, batch);
122
+ };
@@ -35,9 +35,10 @@ export type UploadRunInput = {
35
35
  plan: RunUploadPlan;
36
36
  baseUrl: string;
37
37
  apiKey: string;
38
+ workspaceId?: string;
38
39
  fetchImpl?: typeof fetch;
39
40
  skipRegister?: boolean;
40
41
  onProgress?: (event: RunUploadProgressEvent) => void;
41
42
  };
42
- export declare const uploadRun: ({ plan, baseUrl, apiKey, fetchImpl, skipRegister, onProgress, }: UploadRunInput) => Promise<RunUploadResult>;
43
+ export declare const uploadRun: ({ plan, baseUrl, apiKey, workspaceId, fetchImpl, skipRegister, onProgress, }: UploadRunInput) => Promise<RunUploadResult>;
43
44
  //# sourceMappingURL=uploadRun.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"uploadRun.d.ts","sourceRoot":"","sources":["../../src/runsUpload/uploadRun.ts"],"names":[],"mappings":"AAwBA,OAAO,EAAc,KAAK,WAAW,EAAE,KAAK,aAAa,EAAC,MAAM,qBAAqB,CAAA;AAGrF,MAAM,MAAM,sBAAsB,GAC9B;IAAC,IAAI,EAAE,UAAU,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAC,GACnC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,WAAW,CAAC;IAAC,MAAM,EAAE,UAAU,GAAG,SAAS,CAAA;CAAC,GAC/F;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAC,CAAA;AAEhD,MAAM,MAAM,eAAe,GAAG;IAC5B,OAAO,EAAE,MAAM,CAAA;IACf,QAAQ,EAAE,MAAM,CAAA;IAChB,GAAG,EAAE,MAAM,CAAA;IACX,SAAS,EAAE,MAAM,CAAA;IACjB,UAAU,EAAE,OAAO,CAAA;IACnB,aAAa,EAAE,MAAM,CAAA;IACrB,YAAY,EAAE,MAAM,CAAA;IACpB,aAAa,EAAE,MAAM,CAAA;IACrB;;;;;OAKG;IACH,MAAM,EAAE,WAAW,GAAG,WAAW,GAAG,OAAO,CAAA;IAC3C,IAAI,EAAE,OAAO,CAAA;CACd,CAAA;AAED,MAAM,MAAM,cAAc,GAAG;IAC3B,IAAI,EAAE,aAAa,CAAA;IACnB,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,MAAM,CAAA;IACd,SAAS,CAAC,EAAE,OAAO,KAAK,CAAA;IACxB,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,sBAAsB,KAAK,IAAI,CAAA;CACrD,CAAA;AAED,eAAO,MAAM,SAAS,GAAU,iEAO7B,cAAc,KAAG,OAAO,CAAC,eAAe,CA0F1C,CAAA"}
1
+ {"version":3,"file":"uploadRun.d.ts","sourceRoot":"","sources":["../../src/runsUpload/uploadRun.ts"],"names":[],"mappings":"AAwBA,OAAO,EAAc,KAAK,WAAW,EAAE,KAAK,aAAa,EAAC,MAAM,qBAAqB,CAAA;AAGrF,MAAM,MAAM,sBAAsB,GAC9B;IAAC,IAAI,EAAE,UAAU,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAC,GACnC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,WAAW,CAAC;IAAC,MAAM,EAAE,UAAU,GAAG,SAAS,CAAA;CAAC,GAC/F;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAC,CAAA;AAEhD,MAAM,MAAM,eAAe,GAAG;IAC5B,OAAO,EAAE,MAAM,CAAA;IACf,QAAQ,EAAE,MAAM,CAAA;IAChB,GAAG,EAAE,MAAM,CAAA;IACX,SAAS,EAAE,MAAM,CAAA;IACjB,UAAU,EAAE,OAAO,CAAA;IACnB,aAAa,EAAE,MAAM,CAAA;IACrB,YAAY,EAAE,MAAM,CAAA;IACpB,aAAa,EAAE,MAAM,CAAA;IACrB;;;;;OAKG;IACH,MAAM,EAAE,WAAW,GAAG,WAAW,GAAG,OAAO,CAAA;IAC3C,IAAI,EAAE,OAAO,CAAA;CACd,CAAA;AAED,MAAM,MAAM,cAAc,GAAG;IAC3B,IAAI,EAAE,aAAa,CAAA;IACnB,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,MAAM,CAAA;IACd,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,SAAS,CAAC,EAAE,OAAO,KAAK,CAAA;IACxB,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,sBAAsB,KAAK,IAAI,CAAA;CACrD,CAAA;AAED,eAAO,MAAM,SAAS,GAAU,8EAQ7B,cAAc,KAAG,OAAO,CAAC,eAAe,CA0F1C,CAAA"}
@@ -17,10 +17,10 @@ import { readFile } from 'node:fs/promises';
17
17
  import { createHash } from 'node:crypto';
18
18
  import { CONTROL_ERROR_CODES, CONTROL_NOT_ENTITLED_STATUS, controlRunUploadUrls, } from './controlEndpoints.js';
19
19
  import { RunUploadError } from './runUploadError.js';
20
- export const uploadRun = async ({ plan, baseUrl, apiKey, fetchImpl = globalThis.fetch.bind(globalThis), skipRegister = false, onProgress = () => { }, }) => {
20
+ export const uploadRun = async ({ plan, baseUrl, apiKey, workspaceId, fetchImpl = globalThis.fetch.bind(globalThis), skipRegister = false, onProgress = () => { }, }) => {
21
21
  const urls = controlRunUploadUrls(baseUrl);
22
22
  // Built once, never logged, never placed in a URL or a query string.
23
- const authHeaders = { authorization: `Bearer ${apiKey}` };
23
+ const authHeaders = { authorization: `Bearer ${apiKey}`, ...(workspaceId ? { 'X-AssetHub-Workspace': workspaceId } : {}) };
24
24
  let registered = false;
25
25
  if (!skipRegister) {
26
26
  onProgress({ kind: 'register', graphId: plan.graphId });
package/dist/setup.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import type { Tool } from '@modelcontextprotocol/sdk/types.js';
2
2
  export declare const cliVersion: () => Promise<string>;
3
- export declare const mcpConfig: (client: string, baseUrl: string, account?: boolean) => string;
3
+ export declare const mcpConfig: (client: string, baseUrl: string, account?: boolean, workspaceId?: string) => string;
4
4
  type Check = {
5
5
  name: 'api' | 'mcp' | 'configuration';
6
6
  status: 'pass' | 'fail';
@@ -17,6 +17,7 @@ type Auth = {
17
17
  baseUrl: string;
18
18
  profile: string;
19
19
  source: string;
20
+ workspaceId?: string;
20
21
  workspaceMfaToken?: string;
21
22
  };
22
23
  export declare const diagnose: ({ resolveAuth, includeMcp, timeoutMs, includeTools, account, }: {
@@ -1 +1 @@
1
- {"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../src/setup.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAC,IAAI,EAAC,MAAM,oCAAoC,CAAA;AAE5D,eAAO,MAAM,UAAU,QAAa,OAAO,CAAC,MAAM,CAKvC,CAAA;AAmBX,eAAO,MAAM,SAAS,GAAI,QAAQ,MAAM,EAAE,SAAS,MAAM,EAAE,iBAAe,KAAG,MAsB5E,CAAA;AAED,KAAK,KAAK,GAAG;IACX,IAAI,EAAE,KAAK,GAAG,KAAK,GAAG,eAAe,CAAA;IACrC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAA;IACvB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,KAAK,CAAC,EAAE,IAAI,EAAE,CAAA;CACf,CAAA;AAED,KAAK,IAAI,GAAG;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,iBAAiB,CAAC,EAAE,MAAM,CAAA;CAAC,CAAA;AA2D1G,eAAO,MAAM,QAAQ,GAAU,gEAM5B;IACD,WAAW,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;IAChC,UAAU,EAAE,OAAO,CAAA;IACnB,SAAS,EAAE,MAAM,CAAA;IACjB,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB;;;;;;;;;;;;;;;;;;;;;;EAiHA,CAAA"}
1
+ {"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../src/setup.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAC,IAAI,EAAC,MAAM,oCAAoC,CAAA;AAE5D,eAAO,MAAM,UAAU,QAAa,OAAO,CAAC,MAAM,CAKvC,CAAA;AAmBX,eAAO,MAAM,SAAS,GAAI,QAAQ,MAAM,EAAE,SAAS,MAAM,EAAE,iBAAe,EAAE,cAAc,MAAM,KAAG,MAsBlG,CAAA;AAED,KAAK,KAAK,GAAG;IACX,IAAI,EAAE,KAAK,GAAG,KAAK,GAAG,eAAe,CAAA;IACrC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAA;IACvB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,KAAK,CAAC,EAAE,IAAI,EAAE,CAAA;CACf,CAAA;AAED,KAAK,IAAI,GAAG;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAAC,iBAAiB,CAAC,EAAE,MAAM,CAAA;CAAC,CAAA;AA2DhI,eAAO,MAAM,QAAQ,GAAU,gEAM5B;IACD,WAAW,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;IAChC,UAAU,EAAE,OAAO,CAAA;IACnB,SAAS,EAAE,MAAM,CAAA;IACjB,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB;;;;;;;;;;;;;;;;;;;;;;EAkHA,CAAA"}
package/dist/setup.js CHANGED
@@ -11,7 +11,7 @@ const validatedBaseUrl = (baseUrl) => {
11
11
  throw new Error('Use HTTPS for remote servers; HTTP is supported only on localhost.');
12
12
  return url.href.replace(/\/+$/, '');
13
13
  };
14
- export const mcpConfig = (client, baseUrl, account = false) => {
14
+ export const mcpConfig = (client, baseUrl, account = false, workspaceId) => {
15
15
  const url = `${validatedBaseUrl(baseUrl)}${account ? '/api/workspaces/mcp' : '/api/mcp'}`;
16
16
  const name = account ? 'assethub-workspaces' : 'assethub';
17
17
  const token = account ? 'ASSETHUB_ACCESS_TOKEN' : 'ASSETHUB_API_KEY';
@@ -20,12 +20,12 @@ export const mcpConfig = (client, baseUrl, account = false) => {
20
20
  mcpServers: {
21
21
  [name]: {
22
22
  url,
23
- headers: { Authorization: `Bearer \${env:${token}}`, ...(account ? { Cookie: '${env:ASSETHUB_WORKSPACE_MFA_COOKIE}' } : {}) },
23
+ headers: { Authorization: `Bearer \${env:${token}}`, ...(!account && workspaceId ? { 'X-AssetHub-Workspace': workspaceId } : {}), ...(account ? { Cookie: '${env:ASSETHUB_WORKSPACE_MFA_COOKIE}' } : {}) },
24
24
  },
25
25
  },
26
26
  }, null, 2) + '\n');
27
27
  if (client === 'codex')
28
- return `[mcp_servers.${name}]\nurl = ${JSON.stringify(url)}\nbearer_token_env_var = "${token}"\n${account ? 'env_http_headers = { Cookie = "ASSETHUB_WORKSPACE_MFA_COOKIE" }\n' : ''}`;
28
+ return `[mcp_servers.${name}]\nurl = ${JSON.stringify(url)}\nbearer_token_env_var = "${token}"\n${account ? 'env_http_headers = { Cookie = "ASSETHUB_WORKSPACE_MFA_COOKIE" }\n' : workspaceId ? `http_headers = { "X-AssetHub-Workspace" = ${JSON.stringify(workspaceId)} }\n` : ''}`;
29
29
  throw new Error('Use mcp config --client cursor|codex');
30
30
  };
31
31
  const failedCheck = (name, status, timedOut, account = false) => {
@@ -119,6 +119,7 @@ export const diagnose = async ({ resolveAuth, includeMcp, timeoutMs, includeTool
119
119
  const capabilities = await createAssetHubClient({
120
120
  apiKey: auth.apiKey,
121
121
  baseUrl: auth.baseUrl,
122
+ workspaceId: auth.workspaceId,
122
123
  fetch: boundedFetch,
123
124
  }).v2.getCapabilities();
124
125
  if (typeof capabilities.ownerId !== 'string' || !capabilities.ownerId)
@@ -141,7 +142,7 @@ export const diagnose = async ({ resolveAuth, includeMcp, timeoutMs, includeTool
141
142
  try {
142
143
  await client.connect(new StreamableHTTPClientTransport(new URL(`${auth.baseUrl}${account ? '/api/workspaces/mcp' : '/api/mcp'}`), {
143
144
  fetch: boundedFetch,
144
- requestInit: { headers: { Authorization: `Bearer ${auth.apiKey}`, ...(account && auth.workspaceMfaToken ? { Cookie: `ah_workspace_mfa=${encodeURIComponent(auth.workspaceMfaToken)}` } : {}) } },
145
+ requestInit: { headers: { Authorization: `Bearer ${auth.apiKey}`, ...(!account && auth.workspaceId ? { 'X-AssetHub-Workspace': auth.workspaceId } : {}), ...(account && auth.workspaceMfaToken ? { Cookie: `ah_workspace_mfa=${encodeURIComponent(auth.workspaceMfaToken)}` } : {}) } },
145
146
  }), { signal, timeout: timeoutMs });
146
147
  let toolCount = 0;
147
148
  const tools = [];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@assethub/cli",
3
- "version": "0.1.18",
3
+ "version": "0.1.19",
4
4
  "description": "Command line interface for AssetHub.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -30,7 +30,7 @@
30
30
  "access": "public"
31
31
  },
32
32
  "dependencies": {
33
- "@assethub/api-client": "^0.1.9",
33
+ "@assethub/api-client": "^0.1.10",
34
34
  "@modelcontextprotocol/sdk": "^1.30.0"
35
35
  },
36
36
  "repository": {