@assethub/cli 0.1.19 → 0.1.21

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/README.md CHANGED
@@ -4,7 +4,7 @@ Command line interface for AssetHub.
4
4
 
5
5
  ## Personal API keys
6
6
 
7
- Log in once with a personal key (`ah_pat_`), then select its workspace:
7
+ Log in once with a personal key, then select its workspace:
8
8
 
9
9
  ```sh
10
10
  assethub auth login --api-key-stdin --profile personal
@@ -19,6 +19,13 @@ Login verifies account identity through workspace discovery, including when
19
19
  in the same profile with the same key. It does not issue keys or change browser
20
20
  sessions. Pass `--cursor <nextCursor>` for another workspace list page.
21
21
 
22
+ CLI 0.1.21 also discovers existing `sk_` keys enabled for personal access by the
23
+ server. Run `workspace list --profile <saved-profile>` to discover a saved key
24
+ without logging in again. Verified personal identity is saved in that profile;
25
+ workspace selection keeps its original key. The `assethub-UUID` format is not
26
+ eligible for this discovery. Unregistered workspace keys retain the existing
27
+ user-token flow; rejected personal keys never fall back to another identity.
28
+
22
29
  `--workspace` overrides the saved selection for one command, including diagnostics,
23
30
  MCP discovery, history, and run recovery. Recovery still rejects an operation saved
24
31
  in another workspace. Personal profiles take precedence over environment API
@@ -201,17 +208,21 @@ Existing parts commands use the same canvas and durable operation storage:
201
208
  assethub parts split --source-id "$IMAGE_ASSET_ID" --canvas "$CANVAS_ID" --part-extractor V1.5 --wait
202
209
  # Select only the parts to execute; --all-ready selects all ready tasks.
203
210
  assethub parts split --source-id "$IMAGE_ASSET_ID" --canvas "$CANVAS_ID" --part-extractor V1.5 --all-ready --wait
204
- # Internal V3.6.1, V3.6.3 and V3.6.4 run the complete graph split through one analyze receipt.
211
+ # Internal graph versions run the complete split through one analyze receipt.
205
212
  assethub production agents
206
213
  assethub parts split --source-id "$IMAGE_ASSET_ID" --canvas "$CANVAS_ID" --part-extractor V3.6.1 --all-ready --wait
214
+ # CLI 0.1.20+: existing Internal V3.6.5 and Pluffy models; check server availability first.
215
+ assethub parts split --source-id "$IMAGE_ASSET_ID" --canvas "$CANVAS_ID" --part-extractor V3.6.5 --all-ready --wait
216
+ assethub production analyze --source-id "$IMAGE_ASSET_ID" --canvas "$CANVAS_ID" --part-extractor pluffy --wait
207
217
  assethub production automation --canvas "$CANVAS_ID" --input-json @batch.json --wait
208
218
  ```
209
219
 
210
220
  `parts split` keeps separate analysis and selected-part execution phases. Each phase
211
221
  has its own saved operation ID, with the execution linked to the analysis run.
212
- For Internal `V3.6.1` (`V3.6.1 Primary Images First`) and `V3.6.3`
213
- (`V3.6.3 Fast Analysis`, CLI 0.1.16+), and `V3.6.4`
214
- (`V3.6.4 Fast Analysis`, CLI 0.1.17+), analysis runs the complete
222
+ For Internal `V3.6.1` (`V3.6.1 Primary Images First`), `V3.6.3`
223
+ (`V3.6.3 Fast Analysis`, CLI 0.1.16+), `V3.6.4`
224
+ (`V3.6.4 Fast Analysis`, CLI 0.1.17+), `V3.6.5 Primary Images` and
225
+ `Chibi Character (Pluffy) v3.1` (both CLI 0.1.20+), analysis runs the complete
215
226
  Artifact Graph split. `--all-ready` waits for that one receipt and does not start a
216
227
  second production execution. Resume an interrupted graph split with
217
228
  `runs resume <operation-id>`; `--task-id`, `--mission-id`,
@@ -483,9 +494,12 @@ Image generation uses the `v2` endpoint with mandatory canvas history.
483
494
  Part extraction uses the same names shown in the AssetHub product: `V1.5`,
484
495
  `V2.0 alpha`, `V2.1 alpha`, and the Internal-only aliases `V3.6.1`
485
496
  (`V3.6.1 Primary Images First`), `V3.6.3` (`V3.6.3 Fast Analysis`),
486
- and `V3.6.4` (`V3.6.4 Fast Analysis`).
497
+ `V3.6.4` (`V3.6.4 Fast Analysis`), `V3.6.5` (`V3.6.5 Primary Images`),
498
+ and `pluffy` (`Chibi Character (Pluffy) v3.1`). CLI 0.1.20 adds the latter two;
499
+ `3.6.5`, `pluffy v3.1`, and `pluffy 3.1` are also accepted aliases.
487
500
  Run `production agents` to check availability and `supportedOnGraphEndpoint`
488
- before selecting a graph version. These aliases do not change the default.
501
+ before selecting a graph version. These aliases do not change the V1.5 default
502
+ or grant access to Internal models; the server still authorizes the account.
489
503
  Retired names are no longer accepted by the CLI.
490
504
  Internal agent IDs are intentionally not part of the CLI interface.
491
505
 
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AA4BA,OAAO,EAIL,KAAK,wBAAwB,EAO7B,KAAK,YAAY,EAEjB,KAAK,UAAU,EAgBhB,MAAM,sBAAsB,CAAA;AAc7B,OAAO,EAAC,kBAAkB,EAAc,MAAM,gCAAgC,CAAA;AAI9E,KAAK,KAAK,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,GAAG,MAAM,EAAE,CAAC,CAAA;AA6IxD,eAAO,MAAM,KAAK,s3aAkIjB,CAAA;AA8pFD;;;;;;GAMG;AACH,eAAO,MAAM,6BAA6B,GACxC,OAAO,KAAK,KACX,wBA0BF,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,qBAAqB,GAChC,OAAO,KAAK,KACX,IAAI,CAAC,UAAU,EAAE,QAAQ,CAM1B,CAAA;AA6fF;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,uBAAuB,GAClC,MAAM,SAAS,MAAM,EAAE,KACtB,YAAY,EAuGd,CAAA;AAgsCD,MAAM,MAAM,cAAc,GAAG;IAC3B,UAAU,EAAE,MAAM,CAAA;IAClB,OAAO,EAAE,MAAM,GAAG,SAAS,CAAA;IAC3B,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAA;IAC5B,GAAG,EAAE,MAAM,GAAG,SAAS,CAAA;IACvB,WAAW,EAAE,MAAM,CAAA;IACnB,IAAI,EAAE,MAAM,EAAE,CAAA;IACd,MAAM,EAAE,OAAO,CAAA;IACf,YAAY,EAAE,OAAO,CAAA;CACtB,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,GAC9B,YAAY,MAAM,GAAG,SAAS,EAC9B,aAAa,MAAM,EAAE,EACrB,OAAO,KAAK,KACX,cAoBF,CAAA;AAED,KAAK,iBAAiB,GAAG,IAAI,CAC3B,OAAO,CAAC,UAAU,CAAC,OAAO,kBAAkB,CAAC,CAAC,EAC5C,SAAS,GACT,UAAU,GACV,KAAK,GACL,WAAW,GACX,QAAQ,GACR,OAAO,GACP,OAAO,GACP,UAAU,CACb,CAAA;AAED,eAAO,MAAM,iBAAiB,GAC5B,WAAW,MAAM,EACjB,MAAM,iBAAiB;;;;;;;;;;;;;;CAUvB,CAAA;AAEF,eAAO,MAAM,sBAAsB,GACjC,SAAS,UAAU,CAAC,OAAO,iBAAiB,CAAC,EAC7C,MAAM,iBAAiB,EACvB,SAAS,MAAM;;;;;;;;;;;;;;;;;;;;;;;CAYf,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AA4BA,OAAO,EAIL,KAAK,wBAAwB,EAO7B,KAAK,YAAY,EAEjB,KAAK,UAAU,EAgBhB,MAAM,sBAAsB,CAAA;AAc7B,OAAO,EAAC,kBAAkB,EAAc,MAAM,gCAAgC,CAAA;AAI9E,KAAK,KAAK,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,GAAG,MAAM,EAAE,CAAC,CAAA;AA2JxD,eAAO,MAAM,KAAK,s3aAkIjB,CAAA;AA4sFD;;;;;;GAMG;AACH,eAAO,MAAM,6BAA6B,GACxC,OAAO,KAAK,KACX,wBA0BF,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,qBAAqB,GAChC,OAAO,KAAK,KACX,IAAI,CAAC,UAAU,EAAE,QAAQ,CAM1B,CAAA;AA6fF;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,uBAAuB,GAClC,MAAM,SAAS,MAAM,EAAE,KACtB,YAAY,EAuGd,CAAA;AAgsCD,MAAM,MAAM,cAAc,GAAG;IAC3B,UAAU,EAAE,MAAM,CAAA;IAClB,OAAO,EAAE,MAAM,GAAG,SAAS,CAAA;IAC3B,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAA;IAC5B,GAAG,EAAE,MAAM,GAAG,SAAS,CAAA;IACvB,WAAW,EAAE,MAAM,CAAA;IACnB,IAAI,EAAE,MAAM,EAAE,CAAA;IACd,MAAM,EAAE,OAAO,CAAA;IACf,YAAY,EAAE,OAAO,CAAA;CACtB,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,GAC9B,YAAY,MAAM,GAAG,SAAS,EAC9B,aAAa,MAAM,EAAE,EACrB,OAAO,KAAK,KACX,cAoBF,CAAA;AAED,KAAK,iBAAiB,GAAG,IAAI,CAC3B,OAAO,CAAC,UAAU,CAAC,OAAO,kBAAkB,CAAC,CAAC,EAC5C,SAAS,GACT,UAAU,GACV,KAAK,GACL,WAAW,GACX,QAAQ,GACR,OAAO,GACP,OAAO,GACP,UAAU,CACb,CAAA;AAED,eAAO,MAAM,iBAAiB,GAC5B,WAAW,MAAM,EACjB,MAAM,iBAAiB;;;;;;;;;;;;;;CAUvB,CAAA;AAEF,eAAO,MAAM,sBAAsB,GACjC,SAAS,UAAU,CAAC,OAAO,iBAAiB,CAAC,EAC7C,MAAM,iBAAiB,EACvB,SAAS,MAAM;;;;;;;;;;;;;;;;;;;;;;;CAYf,CAAA"}
package/dist/index.js CHANGED
@@ -34,6 +34,8 @@ const artifactGraphPartExtractorApiValues = new Set([
34
34
  'ah_agent_graph_v3_6_1',
35
35
  'ah_agent_graph_v3_6_3',
36
36
  'ah_agent_graph_v3_6_4',
37
+ 'ah_agent_graph_v3_6_5',
38
+ 'ah_agent_graph_pluffy_v3_1',
37
39
  ]);
38
40
  const partExtractorOptions = [
39
41
  {
@@ -66,6 +68,16 @@ const partExtractorOptions = [
66
68
  apiValue: 'ah_agent_graph_v3_6_4',
67
69
  aliases: ['v3.6.4', '3.6.4'],
68
70
  },
71
+ {
72
+ publicName: 'V3.6.5 Primary Images',
73
+ apiValue: 'ah_agent_graph_v3_6_5',
74
+ aliases: ['v3.6.5', '3.6.5'],
75
+ },
76
+ {
77
+ publicName: 'Chibi Character (Pluffy) v3.1',
78
+ apiValue: 'ah_agent_graph_pluffy_v3_1',
79
+ aliases: ['pluffy', 'pluffy v3.1', 'pluffy 3.1'],
80
+ },
69
81
  ];
70
82
  const partExtractorPublicNames = partExtractorOptions
71
83
  .map(option => option.publicName)
@@ -432,6 +444,39 @@ const readStdinBlob = async (type) => await new Promise((resolve, reject) => {
432
444
  });
433
445
  stdin.on('error', reject);
434
446
  });
447
+ const isPersonalProfile = (profile) => profile?.authentication === 'personal' || Boolean(profile?.apiKey?.startsWith('ah_pat_'));
448
+ const personalProfileAuthentication = (apiKey, baseUrl, profile) => profile?.apiKey === apiKey && new URL(profile.baseUrl).origin === new URL(baseUrl).origin
449
+ ? profile.authentication : undefined;
450
+ const canDiscoverPersonalKey = (key) => Boolean(key && (key.startsWith('ah_pat_') || /^sk_[a-f0-9]{64}$/i.test(key)));
451
+ const preferredApiKey = (flags, stored) => getFlag(flags, 'api-key') ??
452
+ (hasFlag(flags, 'profile') || stored?.workspaceId || isPersonalProfile(stored)
453
+ ? stored?.apiKey
454
+ : env.ASSETHUB_API_KEY?.trim() || stored?.apiKey);
455
+ const personalAccount = async (auth) => {
456
+ const knownPersonal = isPersonalProfile(auth);
457
+ if (!knownPersonal && !canDiscoverPersonalKey(auth.apiKey))
458
+ return undefined;
459
+ try {
460
+ const account = await createWorkspaceClient({ accessToken: auth.apiKey, baseUrl: auth.baseUrl, workspaceId: auth.workspaceId }).list();
461
+ if (account.authentication !== 'personal')
462
+ throw new Error('Workspace API did not verify personal authentication');
463
+ return account;
464
+ }
465
+ catch (error) {
466
+ if (!knownPersonal && error instanceof WorkspaceClientError && error.status === 401 && error.code === 'PERSONAL_KEY_NOT_REGISTERED')
467
+ return undefined;
468
+ throw error;
469
+ }
470
+ };
471
+ const rememberPersonalProfile = async (auth, configPath, config, userId) => {
472
+ if (auth.source !== 'profile')
473
+ return;
474
+ config.profiles = { ...config.profiles, [auth.profile]: {
475
+ apiKey: auth.apiKey, authentication: 'personal', userId,
476
+ workspaceId: config.profiles?.[auth.profile]?.workspaceId, baseUrl: auth.baseUrl, updatedAt: new Date().toISOString(),
477
+ } };
478
+ await writeAuthConfig(configPath, config);
479
+ };
435
480
  const resolveAuth = async (flags) => {
436
481
  const explicitProfile = hasFlag(flags, 'profile') ? requireFlag(flags, 'profile') : undefined;
437
482
  const overrideKey = hasFlag(flags, 'api-key') ? requireFlag(flags, 'api-key') : undefined;
@@ -440,7 +485,7 @@ const resolveAuth = async (flags) => {
440
485
  : undefined;
441
486
  const profile = explicitProfile ?? config?.defaultProfile ?? defaultProfileName;
442
487
  const storedProfile = config?.profiles?.[profile];
443
- const selected = Boolean(explicitProfile || storedProfile?.workspaceId || storedProfile?.apiKey?.startsWith('ah_pat_'));
488
+ const selected = Boolean(explicitProfile || storedProfile?.workspaceId || isPersonalProfile(storedProfile));
444
489
  if (selected && (!storedProfile || (!storedProfile.apiKey && !overrideKey)))
445
490
  throw new Error('Selected profile has no workspace API key. Use workspace use <id> or auth login --api-key-stdin --profile <name>.');
446
491
  const baseUrl = getFlag(flags, 'base-url') ??
@@ -450,15 +495,18 @@ const resolveAuth = async (flags) => {
450
495
  if (overrideKey)
451
496
  return { apiKey: overrideKey, baseUrl, profile, source: 'flag', workspaceId: getFlag(flags, 'workspace') };
452
497
  if (selected && storedProfile?.apiKey) {
453
- if ((storedProfile.workspaceId || storedProfile.apiKey.startsWith('ah_pat_')) &&
498
+ if ((storedProfile.workspaceId || isPersonalProfile(storedProfile) || canDiscoverPersonalKey(storedProfile.apiKey)) &&
454
499
  new URL(baseUrl).origin !== new URL(storedProfile.baseUrl).origin)
455
500
  throw new Error('Selected workspace belongs to another API origin; select a workspace for this origin or supply an explicit API key');
456
- return { apiKey: storedProfile.apiKey, baseUrl, profile, source: 'profile', workspaceId: getFlag(flags, 'workspace') ?? storedProfile.workspaceId };
501
+ return { apiKey: storedProfile.apiKey, authentication: storedProfile.authentication, baseUrl, profile, source: 'profile', workspaceId: getFlag(flags, 'workspace') ?? storedProfile.workspaceId };
457
502
  }
458
503
  if (env.ASSETHUB_API_KEY?.trim())
459
504
  return { apiKey: env.ASSETHUB_API_KEY, baseUrl, profile, source: 'env', workspaceId: getFlag(flags, 'workspace') };
460
- if (storedProfile?.apiKey)
505
+ if (storedProfile?.apiKey) {
506
+ if (canDiscoverPersonalKey(storedProfile.apiKey) && new URL(baseUrl).origin !== new URL(storedProfile.baseUrl).origin)
507
+ throw new Error('Saved API key belongs to another API origin; supply an explicit API key for this origin');
461
508
  return { apiKey: storedProfile.apiKey, baseUrl, profile, source: 'profile', workspaceId: getFlag(flags, 'workspace') ?? storedProfile.workspaceId };
509
+ }
462
510
  throw new Error('Missing workspace API key. Use "workspace use <id>" after user login, "auth login --api-key-stdin", or ASSETHUB_API_KEY.');
463
511
  };
464
512
  const createContext = async (flags, args) => {
@@ -1256,18 +1304,22 @@ const workspaceAuth = async (flags, allowPersonal = false) => {
1256
1304
  const explicitProfile = hasFlag(flags, 'profile') ? requireFlag(flags, 'profile') : undefined;
1257
1305
  const profile = explicitProfile ?? config.defaultProfile ?? defaultProfileName;
1258
1306
  const stored = config.profiles?.[profile];
1259
- const preferredKey = getFlag(flags, 'api-key') ??
1260
- (explicitProfile || stored?.workspaceId || stored?.apiKey?.startsWith('ah_pat_')
1261
- ? stored?.apiKey
1262
- : env.ASSETHUB_API_KEY?.trim() || stored?.apiKey);
1263
- if (allowPersonal && preferredKey?.startsWith('ah_pat_')) {
1307
+ const preferredKey = preferredApiKey(flags, stored);
1308
+ if (allowPersonal && (canDiscoverPersonalKey(preferredKey) || (preferredKey === stored?.apiKey && isPersonalProfile(stored)))) {
1264
1309
  const auth = await resolveAuth(flags);
1265
- return {
1266
- configPath, config, profile, accessToken: auth.apiKey,
1267
- workspaceMfaToken: undefined, baseUrl: auth.baseUrl,
1268
- selectedWorkspaceId: auth.workspaceId, personal: true,
1269
- client: createWorkspaceClient({ accessToken: auth.apiKey, baseUrl: auth.baseUrl, workspaceId: auth.workspaceId }),
1270
- };
1310
+ auth.authentication = personalProfileAuthentication(auth.apiKey, auth.baseUrl, stored);
1311
+ const knownPersonal = isPersonalProfile(auth);
1312
+ const account = knownPersonal ? undefined : await personalAccount(auth);
1313
+ if (knownPersonal || account) {
1314
+ if (account)
1315
+ await rememberPersonalProfile(auth, configPath, config, account.userId);
1316
+ return {
1317
+ configPath, config, profile, accessToken: auth.apiKey,
1318
+ workspaceMfaToken: undefined, baseUrl: auth.baseUrl,
1319
+ selectedWorkspaceId: auth.workspaceId, personal: true,
1320
+ client: createWorkspaceClient({ accessToken: auth.apiKey, baseUrl: auth.baseUrl, workspaceId: auth.workspaceId }),
1321
+ };
1322
+ }
1271
1323
  }
1272
1324
  const environmentToken = explicitProfile ? undefined : env.ASSETHUB_ACCESS_TOKEN?.trim();
1273
1325
  const accessToken = environmentToken || stored?.accessToken;
@@ -1380,6 +1432,7 @@ const commandWorkspace = async (subcommand, positionals, flags) => {
1380
1432
  throw new Error('Workspace API did not verify personal authentication');
1381
1433
  profiles[auth.profile] = {
1382
1434
  apiKey: auth.accessToken,
1435
+ authentication: 'personal',
1383
1436
  userId: account.userId,
1384
1437
  workspaceId,
1385
1438
  baseUrl: auth.baseUrl,
@@ -1392,7 +1445,7 @@ const commandWorkspace = async (subcommand, positionals, flags) => {
1392
1445
  const cached = Object.entries(profiles).find(([, entry]) => entry.userId === account.userId &&
1393
1446
  entry.workspaceId === workspaceId &&
1394
1447
  new URL(entry.baseUrl).origin === new URL(auth.baseUrl).origin &&
1395
- entry.apiKey && !entry.apiKey.startsWith('ah_pat_'));
1448
+ entry.apiKey && !isPersonalProfile(entry));
1396
1449
  let apiKey;
1397
1450
  for (const candidate of new Set([cached?.[1].apiKey, suppliedKey])) {
1398
1451
  if (!candidate)
@@ -1495,22 +1548,19 @@ const commandAuth = async (subcommand, flags) => {
1495
1548
  throw new Error('API key is empty. Pass --api-key, use --api-key-stdin, or set ASSETHUB_API_KEY.');
1496
1549
  }
1497
1550
  const baseUrl = getFlag(flags, 'base-url') ?? env.ASSETHUB_API_BASE_URL ?? defaultBaseUrl;
1498
- const personal = apiKey.startsWith('ah_pat_');
1499
- const account = personal
1500
- ? await createWorkspaceClient({ accessToken: apiKey, baseUrl }).list()
1501
- : undefined;
1502
- if (personal && account?.authentication !== 'personal')
1503
- throw new Error('Workspace API did not verify personal authentication');
1551
+ const config = await readAuthConfig(configPath);
1552
+ const authentication = personalProfileAuthentication(apiKey, baseUrl, config.profiles?.[profile]);
1553
+ const account = await personalAccount({ apiKey, baseUrl, authentication });
1554
+ const personal = account !== undefined;
1504
1555
  if (!personal && !hasFlag(flags, 'skip-verify')) {
1505
1556
  const client = createAssetHubClient({ apiKey, baseUrl });
1506
1557
  await client.v2.listModels();
1507
1558
  }
1508
- const config = await readAuthConfig(configPath);
1509
1559
  const profiles = config.profiles ?? {};
1510
1560
  profiles[profile] = {
1511
1561
  apiKey,
1512
1562
  baseUrl,
1513
- ...(account ? { userId: account.userId } : {}),
1563
+ ...(account ? { authentication: 'personal', userId: account.userId } : {}),
1514
1564
  updatedAt: new Date().toISOString(),
1515
1565
  };
1516
1566
  await writeAuthConfig(configPath, {
@@ -1531,9 +1581,22 @@ const commandAuth = async (subcommand, flags) => {
1531
1581
  if (subcommand === 'status') {
1532
1582
  const config = await readAuthConfig(configPath);
1533
1583
  const current = config.profiles?.[getFlag(flags, 'profile') ?? config.defaultProfile ?? profile];
1584
+ let apiAuth;
1585
+ const preferredKey = preferredApiKey(flags, current);
1586
+ if (canDiscoverPersonalKey(preferredKey) || (preferredKey === current?.apiKey && isPersonalProfile(current))) {
1587
+ apiAuth = await resolveAuth(flags);
1588
+ apiAuth.authentication = personalProfileAuthentication(apiAuth.apiKey, apiAuth.baseUrl, current);
1589
+ const account = await personalAccount(apiAuth);
1590
+ if (account) {
1591
+ if (apiAuth.workspaceId)
1592
+ await createAssetHubClient(apiAuth).v2.getCapabilities();
1593
+ await rememberPersonalProfile(apiAuth, configPath, config, account.userId);
1594
+ print({ authenticated: true, authentication: 'personal', userId: account.userId, workspaceId: apiAuth.workspaceId,
1595
+ profile: apiAuth.profile, source: apiAuth.source, baseUrl: apiAuth.baseUrl });
1596
+ return;
1597
+ }
1598
+ }
1534
1599
  if (!hasFlag(flags, 'api-key') &&
1535
- !current?.apiKey?.startsWith('ah_pat_') &&
1536
- (hasFlag(flags, 'profile') || !env.ASSETHUB_API_KEY?.startsWith('ah_pat_')) &&
1537
1600
  ((!hasFlag(flags, 'profile') && env.ASSETHUB_ACCESS_TOKEN?.trim()) ||
1538
1601
  (current?.accessToken && !current.apiKey))) {
1539
1602
  const auth = await workspaceAuth(flags);
@@ -1548,22 +1611,12 @@ const commandAuth = async (subcommand, flags) => {
1548
1611
  });
1549
1612
  return;
1550
1613
  }
1551
- const auth = await resolveAuth(flags);
1614
+ const auth = apiAuth ?? await resolveAuth(flags);
1552
1615
  const client = createAssetHubClient({
1553
1616
  apiKey: auth.apiKey,
1554
1617
  baseUrl: auth.baseUrl,
1555
1618
  workspaceId: auth.workspaceId,
1556
1619
  });
1557
- if (auth.apiKey.startsWith('ah_pat_')) {
1558
- const account = await createWorkspaceClient({ accessToken: auth.apiKey, baseUrl: auth.baseUrl, workspaceId: auth.workspaceId }).list();
1559
- if (account.authentication !== 'personal')
1560
- throw new Error('Workspace API did not verify personal authentication');
1561
- if (auth.workspaceId)
1562
- await client.v2.getCapabilities();
1563
- print({ authenticated: true, authentication: 'personal', userId: account.userId, workspaceId: auth.workspaceId,
1564
- profile: auth.profile, source: auth.source, baseUrl: auth.baseUrl });
1565
- return;
1566
- }
1567
1620
  const models = await client.v2.listModels();
1568
1621
  print({
1569
1622
  authenticated: true,
@@ -3798,7 +3851,7 @@ const run = async () => {
3798
3851
  const stored = config.profiles?.[explicitProfile ?? config.defaultProfile ?? defaultProfileName];
3799
3852
  if (explicitProfile && !stored)
3800
3853
  throw new Error('Selected profile does not exist');
3801
- const selected = explicitProfile || stored?.workspaceId || stored?.apiKey?.startsWith('ah_pat_');
3854
+ const selected = explicitProfile || stored?.workspaceId || isPersonalProfile(stored);
3802
3855
  const baseUrl = getFlag(parsed.flags, 'base-url') ??
3803
3856
  (selected ? stored?.baseUrl : env.ASSETHUB_API_BASE_URL ?? stored?.baseUrl) ?? defaultBaseUrl;
3804
3857
  const workspaceId = getFlag(parsed.flags, 'workspace') ??
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@assethub/cli",
3
- "version": "0.1.19",
3
+ "version": "0.1.21",
4
4
  "description": "Command line interface for AssetHub.",
5
5
  "type": "module",
6
6
  "bin": {