@vendian/cli 0.0.43 → 0.0.44

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
@@ -46,7 +46,7 @@ Agent authoring commands are also forwarded to the managed Python SDK CLI.
46
46
  `vendian init` writes the current SDK-owned authoring docs into `.vendian-docs/`,
47
47
  and `vendian create` scaffolds agents from the SDK templates. Updating the
48
48
  managed runtime refreshes these docs and templates with the Python SDK. The CLI
49
- remembers workspaces initialized with `vendian init` and refreshes their
49
+ remembers folders initialized with `vendian init` and refreshes their
50
50
  `.vendian-docs/` automatically after `vendian update` or a managed auto-update.
51
51
 
52
52
  ## Local Data
package/cli-wrapper.mjs CHANGED
@@ -863,26 +863,27 @@ function initOutputDir(args = []) {
863
863
  }
864
864
  return ".";
865
865
  }
866
- function resolveWorkspacePath(outputDir, { cwd = process.cwd(), platform = process.platform } = {}) {
866
+ function resolveDocsPath(outputDir, { cwd = process.cwd(), platform = process.platform } = {}) {
867
867
  const api = pathApi2(platform);
868
868
  const raw = outputDir || ".";
869
869
  return api.isAbsolute(raw) ? api.normalize(raw) : api.resolve(cwd, raw);
870
870
  }
871
- function recordAgentDocsWorkspace(outputDir, {
871
+ function recordAgentDocsDir(outputDir, {
872
872
  env = process.env,
873
873
  platform = process.platform,
874
874
  cwd = process.cwd(),
875
875
  now = /* @__PURE__ */ new Date()
876
876
  } = {}) {
877
- const workspacePath = resolveWorkspacePath(outputDir, { cwd, platform });
877
+ const docsPath = resolveDocsPath(outputDir, { cwd, platform });
878
878
  const config = loadConfig(env, platform);
879
- const existing = Array.isArray(config[DOC_WORKSPACES_KEY]) ? config[DOC_WORKSPACES_KEY] : [];
880
- const workspaces = [workspacePath, ...existing.filter((entry) => entry !== workspacePath)];
879
+ const existing = agentDocsDirs(config);
880
+ const dirs = [docsPath, ...existing.filter((entry) => entry !== docsPath)];
881
881
  const next = {
882
882
  ...config,
883
- [DOC_WORKSPACES_KEY]: workspaces,
883
+ [DOC_DIRS_KEY]: dirs,
884
884
  lastAgentDocsInitAt: now.toISOString()
885
885
  };
886
+ delete next[LEGACY_DOC_DIRS_KEY];
886
887
  saveConfig(next, env, platform);
887
888
  return next;
888
889
  }
@@ -890,10 +891,10 @@ function recordForwardedDocsCommand(args, code, options = {}) {
890
891
  if (code !== 0 || !commandWritesAgentDocs(args)) {
891
892
  return false;
892
893
  }
893
- recordAgentDocsWorkspace(initOutputDir(args), options);
894
+ recordAgentDocsDir(initOutputDir(args), options);
894
895
  return true;
895
896
  }
896
- function refreshAgentDocsWorkspaces({
897
+ function refreshAgentDocsDirs({
897
898
  config,
898
899
  venvPath,
899
900
  env = process.env,
@@ -902,41 +903,52 @@ function refreshAgentDocsWorkspaces({
902
903
  now = /* @__PURE__ */ new Date()
903
904
  } = {}) {
904
905
  const currentConfig = config || loadConfig(env, platform);
905
- const workspaces = Array.isArray(currentConfig[DOC_WORKSPACES_KEY]) ? [...new Set(currentConfig[DOC_WORKSPACES_KEY].filter((entry) => typeof entry === "string" && entry.trim()))] : [];
906
- if (workspaces.length === 0) {
906
+ const dirs = agentDocsDirs(currentConfig);
907
+ if (dirs.length === 0) {
907
908
  saveConfig(currentConfig, env, platform);
908
909
  return { config: currentConfig, refreshed: 0, failed: 0 };
909
910
  }
910
911
  const vendianPath = venvVendian(venvPath, platform);
911
912
  let refreshed = 0;
912
913
  let failed = 0;
913
- for (const workspace of workspaces) {
914
- if (!fs7.existsSync(workspace)) {
914
+ for (const dir of dirs) {
915
+ if (!fs7.existsSync(dir)) {
915
916
  continue;
916
917
  }
917
- const status = run2(vendianPath, ["init", "--output-dir", workspace, "--yes"]);
918
+ const status = run2(vendianPath, ["init", "--output-dir", dir, "--yes"]);
918
919
  if (status === 0) {
919
920
  refreshed += 1;
920
921
  } else {
921
922
  failed += 1;
922
- console.error(`[vendian] Could not refresh SDK docs in ${workspace}`);
923
+ console.error(`[vendian] Could not refresh SDK docs in ${dir}`);
923
924
  }
924
925
  }
925
926
  const next = {
926
927
  ...currentConfig,
927
- [DOC_WORKSPACES_KEY]: workspaces,
928
+ [DOC_DIRS_KEY]: dirs,
928
929
  lastAgentDocsRefreshAt: now.toISOString()
929
930
  };
931
+ delete next[LEGACY_DOC_DIRS_KEY];
930
932
  saveConfig(next, env, platform);
931
933
  return { config: next, refreshed, failed };
932
934
  }
933
- var DOC_WORKSPACES_KEY;
935
+ function agentDocsDirs(config = {}) {
936
+ return [.../* @__PURE__ */ new Set([
937
+ ...stringList(config[DOC_DIRS_KEY]),
938
+ ...stringList(config[LEGACY_DOC_DIRS_KEY])
939
+ ])];
940
+ }
941
+ function stringList(value) {
942
+ return Array.isArray(value) ? value.filter((entry) => typeof entry === "string" && entry.trim()) : [];
943
+ }
944
+ var DOC_DIRS_KEY, LEGACY_DOC_DIRS_KEY;
934
945
  var init_docs = __esm({
935
946
  "src/docs.js"() {
936
947
  init_config();
937
948
  init_paths();
938
949
  init_process();
939
- DOC_WORKSPACES_KEY = "agentDocWorkspaces";
950
+ DOC_DIRS_KEY = "agentDocDirs";
951
+ LEGACY_DOC_DIRS_KEY = ["agentDoc", "Work", "spaces"].join("");
940
952
  }
941
953
  });
942
954
 
@@ -1011,7 +1023,7 @@ async function setup({
1011
1023
  saveConfig(next, env, platform);
1012
1024
  installVendianPackages({ pythonPath, venvPath, config: next, env, platform });
1013
1025
  const updated = { ...next, lastManagedUpdateAt: (/* @__PURE__ */ new Date()).toISOString() };
1014
- refreshAgentDocsWorkspaces({ config: updated, venvPath, env, platform });
1026
+ refreshAgentDocsDirs({ config: updated, venvPath, env, platform });
1015
1027
  if (!verifyVendianImports(pythonPath)) {
1016
1028
  throw new Error("Vendian packages installed, but import verification failed.");
1017
1029
  }
@@ -1196,8 +1208,8 @@ function findAgentDirectoryCandidates({
1196
1208
  ]);
1197
1209
  for (const root of roots) {
1198
1210
  for (const manifest of findManifestFiles(root, { maxDepth, maxDirs, limit: 250 })) {
1199
- const workspace = nearestAgentsAncestor(manifest, root);
1200
- addCandidate(workspace || path4.dirname(manifest));
1211
+ const agentsGroup = nearestAgentsAncestor(manifest, root);
1212
+ addCandidate(agentsGroup || path4.dirname(manifest));
1201
1213
  if (candidates.length >= limit) {
1202
1214
  return candidates.slice(0, limit);
1203
1215
  }
@@ -1459,7 +1471,7 @@ function maybeAutoUpdateManagedEnv({
1459
1471
  load = loadConfig,
1460
1472
  save = saveConfig,
1461
1473
  installPackages = installVendianPackages,
1462
- refreshDocs = refreshAgentDocsWorkspaces,
1474
+ refreshDocs = refreshAgentDocsDirs,
1463
1475
  now = Date.now(),
1464
1476
  onProgress = null
1465
1477
  } = {}) {
@@ -1509,60 +1521,8 @@ function reportProgress(onProgress, message) {
1509
1521
  init_process();
1510
1522
  init_paths();
1511
1523
 
1512
- // src/workspaces.js
1513
- init_process();
1514
- async function listCloudWorkspaces({
1515
- env = process.env,
1516
- platform = process.platform,
1517
- prepareInvocation = preparePythonVendianInvocation,
1518
- run: run2 = runCapture,
1519
- onProgress = null,
1520
- timeoutMs = 2e4
1521
- } = {}) {
1522
- const progress = typeof onProgress === "function" ? onProgress : () => {
1523
- };
1524
- progress("Checking managed Python runtime");
1525
- const invocation = await prepareInvocation(["cloud", "collections", "list", "--json"], {
1526
- env,
1527
- platform,
1528
- onProgress: progress,
1529
- skipAutoUpdate: true
1530
- });
1531
- progress("Loading workspaces from Vendian");
1532
- const result = run2(invocation.command, invocation.args, { env: invocation.env, timeout: timeoutMs });
1533
- if (!result.ok) {
1534
- return {
1535
- ok: false,
1536
- workspaces: [],
1537
- error: (result.stderr || result.stdout || `workspace list exited with code ${result.status}`).trim()
1538
- };
1539
- }
1540
- try {
1541
- return { ok: true, workspaces: normalizeWorkspaceList(JSON.parse(result.stdout)), error: "" };
1542
- } catch (error) {
1543
- const message = error && typeof error.message === "string" ? error.message : String(error);
1544
- return { ok: false, workspaces: [], error: `Could not parse workspace list: ${message}` };
1545
- }
1546
- }
1547
- function normalizeWorkspaceList(payload) {
1548
- const data = payload && typeof payload === "object" && "data" in payload ? payload.data : payload;
1549
- const raw = Array.isArray(data) ? data : data && typeof data === "object" && Array.isArray(data.data) ? data.data : data && typeof data === "object" && Array.isArray(data.collections) ? data.collections : [];
1550
- return raw.filter((item) => item && typeof item === "object").map((item) => ({
1551
- id: stringValue(item.id),
1552
- name: stringValue(item.name || item.slug || item.id || "Unnamed workspace"),
1553
- slug: stringValue(item.slug)
1554
- })).filter((item) => item.id);
1555
- }
1556
- function workspaceLabel(workspace) {
1557
- const name = workspace?.name || workspace?.slug || workspace?.id || "Unnamed workspace";
1558
- const slug = workspace?.slug && workspace.slug !== name ? ` (${workspace.slug})` : "";
1559
- return `${name}${slug}`;
1560
- }
1561
- function stringValue(value) {
1562
- return value == null ? "" : String(value).trim();
1563
- }
1564
-
1565
1524
  // src/serve-events.js
1525
+ var LEGACY_COLLECTION_RESOLVED_EVENT = ["work", "space_resolved"].join("");
1566
1526
  function initialServeState() {
1567
1527
  return {
1568
1528
  connected: false,
@@ -1616,15 +1576,15 @@ function applyServeEvent(state, event) {
1616
1576
  ...state,
1617
1577
  logs: appendLog(state.logs, event)
1618
1578
  };
1619
- if (event.type === "workspace_resolved") {
1620
- return { ...next, collectionId: stringValue2(event.collectionId), activity: "Workspace resolved" };
1579
+ if (event.type === "collection_resolved" || event.type === LEGACY_COLLECTION_RESOLVED_EVENT) {
1580
+ return { ...next, collectionId: stringValue(event.collectionId), activity: "Collection resolved" };
1621
1581
  }
1622
1582
  if (event.type === "daemon_registered") {
1623
1583
  return {
1624
1584
  ...next,
1625
1585
  connected: true,
1626
- daemonId: stringValue2(event.daemonId),
1627
- cliSessionId: stringValue2(event.cliSessionId),
1586
+ daemonId: stringValue(event.daemonId),
1587
+ cliSessionId: stringValue(event.cliSessionId),
1628
1588
  activity: "Daemon registered"
1629
1589
  };
1630
1590
  }
@@ -1644,7 +1604,7 @@ function applyServeEvent(state, event) {
1644
1604
  };
1645
1605
  }
1646
1606
  if (event.type === "daemon_wake_received") {
1647
- const sourceType = stringValue2(event.sourceEventType || "backend wake");
1607
+ const sourceType = stringValue(event.sourceEventType || "backend wake");
1648
1608
  return {
1649
1609
  ...next,
1650
1610
  activity: `Wake received: ${sourceType}`
@@ -1659,17 +1619,17 @@ function applyServeEvent(state, event) {
1659
1619
  if (event.type === "dispatch_job_received") {
1660
1620
  return {
1661
1621
  ...next,
1662
- activity: `Dispatch received for run ${stringValue2(event.runId || event.sessionId || "unknown")}`
1622
+ activity: `Dispatch received for run ${stringValue(event.runId || event.sessionId || "unknown")}`
1663
1623
  };
1664
1624
  }
1665
1625
  if (event.type === "dispatch_job_acked") {
1666
1626
  return {
1667
1627
  ...next,
1668
- activity: `Dispatch acknowledged for run ${stringValue2(event.runId || event.sessionId || "unknown")}`
1628
+ activity: `Dispatch acknowledged for run ${stringValue(event.runId || event.sessionId || "unknown")}`
1669
1629
  };
1670
1630
  }
1671
1631
  if (event.type === "daemon_stderr") {
1672
- const message = stringValue2(event.message || event.stderr || "Daemon wrote to stderr");
1632
+ const message = stringValue(event.message || event.stderr || "Daemon wrote to stderr");
1673
1633
  return {
1674
1634
  ...next,
1675
1635
  activity: `Daemon stderr: ${message}`,
@@ -1714,14 +1674,14 @@ function applyServeEvent(state, event) {
1714
1674
  if (event.type === "agent_prepare_progress") {
1715
1675
  const relativePath = agentLabel(event);
1716
1676
  const timestamp = event.timestamp || (/* @__PURE__ */ new Date()).toISOString();
1717
- const message = stringValue2(event.message || event.stage || "Preparing agent");
1677
+ const message = stringValue(event.message || event.stage || "Preparing agent");
1718
1678
  return {
1719
1679
  ...next,
1720
1680
  agentLogs: appendAgentLog(state.agentLogs, event),
1721
1681
  agentRunState: setAgentRunState(state.agentRunState, relativePath, {
1722
1682
  status: "preparing",
1723
1683
  lastEventAt: timestamp,
1724
- progressStage: stringValue2(event.stage),
1684
+ progressStage: stringValue(event.stage),
1725
1685
  progressMessage: message
1726
1686
  }),
1727
1687
  activity: `${relativePath}: ${message}`
@@ -1733,11 +1693,11 @@ function applyServeEvent(state, event) {
1733
1693
  const runState = isError ? setAgentRunState(state.agentRunState, agentLabel(event), {
1734
1694
  status: "error",
1735
1695
  lastEventAt: event.timestamp || (/* @__PURE__ */ new Date()).toISOString(),
1736
- errorMessage: stringValue2(event.error || event.errorMessage || "Agent setup failed")
1696
+ errorMessage: stringValue(event.error || event.errorMessage || "Agent setup failed")
1737
1697
  }) : isDisabled ? setAgentRunState(state.agentRunState, agentLabel(event), {
1738
1698
  status: "disabled",
1739
1699
  lastEventAt: event.timestamp || (/* @__PURE__ */ new Date()).toISOString(),
1740
- disabledReason: stringValue2(event.disabledReason || event.warning || "System dependency not met"),
1700
+ disabledReason: stringValue(event.disabledReason || event.warning || "System dependency not met"),
1741
1701
  resolutionHints: Array.isArray(event.resolutionHints) ? event.resolutionHints : []
1742
1702
  }) : setAgentRunState(state.agentRunState, agentLabel(event), {
1743
1703
  status: "ready",
@@ -1773,8 +1733,8 @@ function applyServeEvent(state, event) {
1773
1733
  agentLogs: appendAgentLog(state.agentLogs, event),
1774
1734
  agentRunState: setAgentRunState(state.agentRunState, relativePath, {
1775
1735
  status: "running",
1776
- runId: stringValue2(event.runId || event.deployRequestId),
1777
- jobType: stringValue2(event.jobType || "run"),
1736
+ runId: stringValue(event.runId || event.deployRequestId),
1737
+ jobType: stringValue(event.jobType || "run"),
1778
1738
  startedAt: timestamp,
1779
1739
  completedAt: null,
1780
1740
  lastEventAt: timestamp,
@@ -1788,7 +1748,7 @@ function applyServeEvent(state, event) {
1788
1748
  const relativePath = agentLabel(event);
1789
1749
  const timestamp = event.timestamp || (/* @__PURE__ */ new Date()).toISOString();
1790
1750
  const success = event.success !== false;
1791
- const runId = stringValue2(event.runId || event.deployRequestId);
1751
+ const runId = stringValue(event.runId || event.deployRequestId);
1792
1752
  const previous = (state.agentRunState || {})[relativePath];
1793
1753
  const effectiveSuccess = success && !(previous?.status === "error" && previous?.runId === runId);
1794
1754
  return {
@@ -1797,10 +1757,10 @@ function applyServeEvent(state, event) {
1797
1757
  agentRunState: setAgentRunState(state.agentRunState, relativePath, {
1798
1758
  status: effectiveSuccess ? "completed" : "error",
1799
1759
  runId,
1800
- jobType: stringValue2(event.jobType || "run"),
1760
+ jobType: stringValue(event.jobType || "run"),
1801
1761
  completedAt: timestamp,
1802
1762
  lastEventAt: timestamp,
1803
- errorMessage: effectiveSuccess ? null : previous?.errorMessage || stringValue2(event.error || "Job failed")
1763
+ errorMessage: effectiveSuccess ? null : previous?.errorMessage || stringValue(event.error || "Job failed")
1804
1764
  }),
1805
1765
  jobsRun: state.jobsRun + 1,
1806
1766
  currentJob: null,
@@ -1808,13 +1768,13 @@ function applyServeEvent(state, event) {
1808
1768
  };
1809
1769
  }
1810
1770
  if (event.type === "backend_connection_lost") {
1811
- return { ...next, connected: false, activity: `Connection lost during ${stringValue2(event.activity)}`, retry: event };
1771
+ return { ...next, connected: false, activity: `Connection lost during ${stringValue(event.activity)}`, retry: event };
1812
1772
  }
1813
1773
  if (event.type === "backend_connection_restored") {
1814
1774
  return { ...next, connected: true, activity: "Backend connection restored", retry: null };
1815
1775
  }
1816
1776
  if (event.type === "retry_scheduled") {
1817
- return { ...next, retry: event, activity: `Retrying ${stringValue2(event.activity)} in ${formatSeconds(event.delaySeconds)}` };
1777
+ return { ...next, retry: event, activity: `Retrying ${stringValue(event.activity)} in ${formatSeconds(event.delaySeconds)}` };
1818
1778
  }
1819
1779
  if (event.type === "error") {
1820
1780
  const relativePath = event.relativePath || event.path ? agentLabel(event) : "";
@@ -1825,11 +1785,11 @@ function applyServeEvent(state, event) {
1825
1785
  agentLogs: hasAgentScope ? appendAgentLog(state.agentLogs, event) : state.agentLogs,
1826
1786
  agentRunState: hasAgentScope ? setAgentRunState(state.agentRunState, relativePath, {
1827
1787
  status: "error",
1828
- runId: stringValue2(event.runId || event.deployRequestId),
1829
- jobType: stringValue2(event.jobType || "run"),
1788
+ runId: stringValue(event.runId || event.deployRequestId),
1789
+ jobType: stringValue(event.jobType || "run"),
1830
1790
  completedAt: timestamp,
1831
1791
  lastEventAt: timestamp,
1832
- errorMessage: stringValue2(event.error || event.code || "Unknown error")
1792
+ errorMessage: stringValue(event.error || event.code || "Unknown error")
1833
1793
  }) : state.agentRunState,
1834
1794
  activity: "Error",
1835
1795
  errors: appendError(state.errors, jobLabel(event), event.error || event.code || "Unknown error")
@@ -1847,8 +1807,8 @@ function applyServeEvent(state, event) {
1847
1807
  }
1848
1808
  if (event.type === "process_exit" || event.type === "daemon_exit") {
1849
1809
  const timestamp = event.timestamp || (/* @__PURE__ */ new Date()).toISOString();
1850
- const message = stringValue2(event.message || processExitMessage(event));
1851
- const relativePath = stringValue2(event.relativePath || "");
1810
+ const message = stringValue(event.message || processExitMessage(event));
1811
+ const relativePath = stringValue(event.relativePath || "");
1852
1812
  const runState = failRunningAgents(state.agentRunState, message, timestamp, relativePath);
1853
1813
  return {
1854
1814
  ...next,
@@ -1903,7 +1863,7 @@ function mergeAgentLogRecords(agentLogs, records = []) {
1903
1863
  let next = agentLogs || {};
1904
1864
  for (const record of records) {
1905
1865
  if (!record || typeof record !== "object") continue;
1906
- const relativePath = stringValue2(record.relativePath || ".");
1866
+ const relativePath = stringValue(record.relativePath || ".");
1907
1867
  const entry = record.entry && typeof record.entry === "object" ? record.entry : record;
1908
1868
  const existing = next[relativePath] || [];
1909
1869
  next = {
@@ -1918,13 +1878,13 @@ function agentRunStateFromLogs(agentLogs, { includeRunning = true } = {}) {
1918
1878
  for (const [relativePath, entries] of Object.entries(agentLogs || {})) {
1919
1879
  for (const entry of entries || []) {
1920
1880
  const timestamp = entry.timestamp || (/* @__PURE__ */ new Date()).toISOString();
1921
- const runId = stringValue2(entry.runId);
1881
+ const runId = stringValue(entry.runId);
1922
1882
  const current = next[relativePath] || {};
1923
1883
  if (entry.eventType === "job_started") {
1924
1884
  next = setAgentRunState(next, relativePath, {
1925
1885
  status: includeRunning ? "running" : current.status,
1926
1886
  runId,
1927
- jobType: entry.jobType ? stringValue2(entry.jobType) : current.jobType,
1887
+ jobType: entry.jobType ? stringValue(entry.jobType) : current.jobType,
1928
1888
  startedAt: timestamp,
1929
1889
  lastEventAt: timestamp
1930
1890
  });
@@ -1935,10 +1895,10 @@ function agentRunStateFromLogs(agentLogs, { includeRunning = true } = {}) {
1935
1895
  next = setAgentRunState(next, relativePath, {
1936
1896
  status: failed ? "error" : "completed",
1937
1897
  runId,
1938
- jobType: entry.jobType ? stringValue2(entry.jobType) : current.jobType,
1898
+ jobType: entry.jobType ? stringValue(entry.jobType) : current.jobType,
1939
1899
  completedAt: timestamp,
1940
1900
  lastEventAt: timestamp,
1941
- errorMessage: failed ? formatErrorMessage(entry.error) || current.errorMessage || stringValue2(entry.message || "Job failed") : null
1901
+ errorMessage: failed ? formatErrorMessage(entry.error) || current.errorMessage || stringValue(entry.message || "Job failed") : null
1942
1902
  });
1943
1903
  continue;
1944
1904
  }
@@ -1946,10 +1906,10 @@ function agentRunStateFromLogs(agentLogs, { includeRunning = true } = {}) {
1946
1906
  next = setAgentRunState(next, relativePath, {
1947
1907
  status: "error",
1948
1908
  runId,
1949
- jobType: entry.jobType ? stringValue2(entry.jobType) : current.jobType,
1909
+ jobType: entry.jobType ? stringValue(entry.jobType) : current.jobType,
1950
1910
  completedAt: timestamp,
1951
1911
  lastEventAt: timestamp,
1952
- errorMessage: formatErrorMessage(entry.error) || stringValue2(entry.message || "Job failed")
1912
+ errorMessage: formatErrorMessage(entry.error) || stringValue(entry.message || "Job failed")
1953
1913
  });
1954
1914
  continue;
1955
1915
  }
@@ -1967,34 +1927,34 @@ function serveEventAgentLogEntry(event) {
1967
1927
  if (!event || typeof event !== "object") {
1968
1928
  return null;
1969
1929
  }
1970
- const type = stringValue2(event.type);
1971
- const relativePath = stringValue2(event.relativePath || event.path || ".");
1930
+ const type = stringValue(event.type);
1931
+ const relativePath = stringValue(event.relativePath || event.path || ".");
1972
1932
  const timestamp = event.timestamp || (/* @__PURE__ */ new Date()).toISOString();
1973
1933
  if (type === "run_log") {
1974
1934
  return {
1975
1935
  relativePath,
1976
1936
  entry: {
1977
1937
  timestamp,
1978
- runId: stringValue2(event.runId),
1979
- eventType: stringValue2(event.eventType || "log"),
1980
- level: stringValue2(event.level || "info"),
1981
- message: stringValue2(event.message),
1982
- stepId: event.stepId ? stringValue2(event.stepId) : null,
1938
+ runId: stringValue(event.runId),
1939
+ eventType: stringValue(event.eventType || "log"),
1940
+ level: stringValue(event.level || "info"),
1941
+ message: stringValue(event.message),
1942
+ stepId: event.stepId ? stringValue(event.stepId) : null,
1983
1943
  current: event.current ?? null,
1984
1944
  total: event.total ?? null,
1985
1945
  success: event.success ?? null,
1986
1946
  error: event.error ?? null,
1987
- jobType: event.jobType ? stringValue2(event.jobType) : null
1947
+ jobType: event.jobType ? stringValue(event.jobType) : null
1988
1948
  }
1989
1949
  };
1990
1950
  }
1991
1951
  if (type === "job_started") {
1992
- const jobType = stringValue2(event.jobType || "run");
1952
+ const jobType = stringValue(event.jobType || "run");
1993
1953
  return {
1994
1954
  relativePath,
1995
1955
  entry: {
1996
1956
  timestamp,
1997
- runId: stringValue2(event.runId || event.deployRequestId),
1957
+ runId: stringValue(event.runId || event.deployRequestId),
1998
1958
  eventType: "job_started",
1999
1959
  level: "info",
2000
1960
  message: `Started ${jobType}`,
@@ -2009,15 +1969,15 @@ function serveEventAgentLogEntry(event) {
2009
1969
  }
2010
1970
  if (type === "job_completed") {
2011
1971
  const success = event.success !== false;
2012
- const jobType = stringValue2(event.jobType || "run");
1972
+ const jobType = stringValue(event.jobType || "run");
2013
1973
  return {
2014
1974
  relativePath,
2015
1975
  entry: {
2016
1976
  timestamp,
2017
- runId: stringValue2(event.runId || event.deployRequestId),
1977
+ runId: stringValue(event.runId || event.deployRequestId),
2018
1978
  eventType: "job_completed",
2019
1979
  level: success ? "info" : "error",
2020
- message: success ? "Completed successfully" : stringValue2(event.error || "Failed"),
1980
+ message: success ? "Completed successfully" : stringValue(event.error || "Failed"),
2021
1981
  stepId: null,
2022
1982
  current: null,
2023
1983
  total: null,
@@ -2032,16 +1992,16 @@ function serveEventAgentLogEntry(event) {
2032
1992
  relativePath,
2033
1993
  entry: {
2034
1994
  timestamp,
2035
- runId: stringValue2(event.runId || event.deployRequestId),
1995
+ runId: stringValue(event.runId || event.deployRequestId),
2036
1996
  eventType: "error",
2037
1997
  level: "error",
2038
- message: stringValue2(event.error || event.code || "Unknown error"),
1998
+ message: stringValue(event.error || event.code || "Unknown error"),
2039
1999
  stepId: null,
2040
2000
  current: null,
2041
2001
  total: null,
2042
2002
  success: false,
2043
2003
  error: event.error ?? event.code ?? null,
2044
- jobType: event.jobType ? stringValue2(event.jobType) : null
2004
+ jobType: event.jobType ? stringValue(event.jobType) : null
2045
2005
  }
2046
2006
  };
2047
2007
  }
@@ -2055,7 +2015,7 @@ function serveEventAgentLogEntry(event) {
2055
2015
  eventType: type,
2056
2016
  level: event.status === "error" ? "error" : "info",
2057
2017
  message: agentPrepareLogMessage(event),
2058
- stepId: stringValue2(event.stage || type),
2018
+ stepId: stringValue(event.stage || type),
2059
2019
  current: null,
2060
2020
  total: null,
2061
2021
  success,
@@ -2065,12 +2025,12 @@ function serveEventAgentLogEntry(event) {
2065
2025
  };
2066
2026
  }
2067
2027
  if (type === "process_exit" || type === "daemon_exit") {
2068
- const message = stringValue2(event.message || processExitMessage(event));
2028
+ const message = stringValue(event.message || processExitMessage(event));
2069
2029
  return {
2070
2030
  relativePath,
2071
2031
  entry: {
2072
2032
  timestamp,
2073
- runId: stringValue2(event.runId || event.sessionId || "daemon"),
2033
+ runId: stringValue(event.runId || event.sessionId || "daemon"),
2074
2034
  eventType: type,
2075
2035
  level: "error",
2076
2036
  message,
@@ -2084,16 +2044,16 @@ function serveEventAgentLogEntry(event) {
2084
2044
  signal: event.signal ?? null,
2085
2045
  stderrTail: event.stderrTail ?? null
2086
2046
  },
2087
- jobType: event.jobType ? stringValue2(event.jobType) : null
2047
+ jobType: event.jobType ? stringValue(event.jobType) : null
2088
2048
  }
2089
2049
  };
2090
2050
  }
2091
2051
  return null;
2092
2052
  }
2093
2053
  function agentRuntimeStatus(agent, agentRunState = {}) {
2094
- const path10 = stringValue2(agent?.relativePath || ".");
2054
+ const path10 = stringValue(agent?.relativePath || ".");
2095
2055
  const run2 = (agentRunState || {})[path10];
2096
- const inventoryStatus = stringValue2(agent?.status);
2056
+ const inventoryStatus = stringValue(agent?.status);
2097
2057
  if (run2?.status === "running") {
2098
2058
  return { status: "running", label: "running", run: run2 };
2099
2059
  }
@@ -2121,28 +2081,29 @@ function agentRuntimeStatus(agent, agentRunState = {}) {
2121
2081
  return { status: inventoryStatus || "unknown", label: inventoryStatus || "unknown", run: run2 };
2122
2082
  }
2123
2083
  function appendError(errors, scope, message) {
2124
- return [...errors, { scope, message: stringValue2(message) }].slice(-20);
2084
+ return [...errors, { scope, message: stringValue(message) }].slice(-20);
2125
2085
  }
2126
2086
  function serveDebugEntry(event) {
2127
2087
  if (!event || typeof event !== "object") return null;
2128
- const type = stringValue2(event.type);
2088
+ const type = stringValue(event.type);
2129
2089
  const timestamp = event.timestamp || event.occurredAt || (/* @__PURE__ */ new Date()).toISOString();
2130
2090
  const base = { timestamp, eventType: type, level: debugLevel(event) };
2131
2091
  switch (type) {
2132
- case "workspace_resolved":
2133
- return { ...base, message: `workspace resolved collection=${stringValue2(event.collectionId || "unknown")}` };
2092
+ case "collection_resolved":
2093
+ case LEGACY_COLLECTION_RESOLVED_EVENT:
2094
+ return { ...base, message: `collection resolved id=${stringValue(event.collectionId || "unknown")}` };
2134
2095
  case "daemon_registered":
2135
2096
  return { ...base, message: `daemon registered daemon=${shortId(event.daemonId)} cli=${shortId(event.cliSessionId)}` };
2136
2097
  case "daemon_event_stream_connected":
2137
2098
  return { ...base, message: `daemon event stream connected daemon=${shortId(event.daemonId)}` };
2138
2099
  case "daemon_event_stream_lost":
2139
- return { ...base, level: "warn", message: `daemon event stream lost retry=${formatSeconds(event.retryInSeconds)} error=${stringValue2(event.error || "unknown")}` };
2100
+ return { ...base, level: "warn", message: `daemon event stream lost retry=${formatSeconds(event.retryInSeconds)} error=${stringValue(event.error || "unknown")}` };
2140
2101
  case "daemon_wake_received":
2141
2102
  return {
2142
2103
  ...base,
2143
2104
  message: [
2144
- `wake received source=${stringValue2(event.sourceEventType || "backend")}`,
2145
- event.eventType ? `event=${stringValue2(event.eventType)}` : "",
2105
+ `wake received source=${stringValue(event.sourceEventType || "backend")}`,
2106
+ event.eventType ? `event=${stringValue(event.eventType)}` : "",
2146
2107
  event.sessionId ? `session=${shortId(event.sessionId)}` : "",
2147
2108
  event.runId ? `run=${shortId(event.runId)}` : "",
2148
2109
  event.localAgentRowId ? `agentRow=${shortId(event.localAgentRowId)}` : ""
@@ -2165,7 +2126,7 @@ function serveDebugEntry(event) {
2165
2126
  message: `dispatch acked delivery=${shortId(event.deliveryId)} run=${shortId(event.runId || event.sessionId)} attempt=${shortId(event.attemptId)}`
2166
2127
  };
2167
2128
  case "job_started":
2168
- return { ...base, message: `job started type=${stringValue2(event.jobType || "run")} run=${shortId(event.runId || event.sessionId || event.deployRequestId || event.testRunId)}` };
2129
+ return { ...base, message: `job started type=${stringValue(event.jobType || "run")} run=${shortId(event.runId || event.sessionId || event.deployRequestId || event.testRunId)}` };
2169
2130
  case "job_completed":
2170
2131
  return {
2171
2132
  ...base,
@@ -2173,18 +2134,18 @@ function serveDebugEntry(event) {
2173
2134
  message: `job completed success=${event.success !== false} run=${shortId(event.runId || event.sessionId || event.deployRequestId || event.testRunId)}${event.error ? ` error=${formatErrorMessage(event.error)}` : ""}`
2174
2135
  };
2175
2136
  case "backend_connection_lost":
2176
- return { ...base, level: "warn", message: `backend connection lost activity=${stringValue2(event.activity)} error=${stringValue2(event.error)}` };
2137
+ return { ...base, level: "warn", message: `backend connection lost activity=${stringValue(event.activity)} error=${stringValue(event.error)}` };
2177
2138
  case "backend_connection_restored":
2178
- return { ...base, message: `backend connection restored activity=${stringValue2(event.activity)}` };
2139
+ return { ...base, message: `backend connection restored activity=${stringValue(event.activity)}` };
2179
2140
  case "retry_scheduled":
2180
- return { ...base, level: "warn", message: `retry scheduled activity=${stringValue2(event.activity)} delay=${formatSeconds(event.delaySeconds)}` };
2141
+ return { ...base, level: "warn", message: `retry scheduled activity=${stringValue(event.activity)} delay=${formatSeconds(event.delaySeconds)}` };
2181
2142
  case "daemon_stderr":
2182
- return { ...base, level: looksLikeError(event.message || event.stderr) ? "error" : "warn", message: `stderr ${stringValue2(event.message || event.stderr)}` };
2143
+ return { ...base, level: looksLikeError(event.message || event.stderr) ? "error" : "warn", message: `stderr ${stringValue(event.message || event.stderr)}` };
2183
2144
  case "error":
2184
- return { ...base, level: "error", message: `error scope=${stringValue2(event.relativePath || event.path || "daemon")} ${stringValue2(event.error || event.code || "unknown")}` };
2145
+ return { ...base, level: "error", message: `error scope=${stringValue(event.relativePath || event.path || "daemon")} ${stringValue(event.error || event.code || "unknown")}` };
2185
2146
  case "process_exit":
2186
2147
  case "daemon_exit":
2187
- return { ...base, level: "error", message: stringValue2(event.message || processExitMessage(event)) };
2148
+ return { ...base, level: "error", message: stringValue(event.message || processExitMessage(event)) };
2188
2149
  case "stopped":
2189
2150
  return { ...base, message: `stopped jobsRun=${Number(event.jobsRun ?? 0)}` };
2190
2151
  default:
@@ -2192,7 +2153,7 @@ function serveDebugEntry(event) {
2192
2153
  }
2193
2154
  }
2194
2155
  function debugLevel(event) {
2195
- if (event?.level) return stringValue2(event.level);
2156
+ if (event?.level) return stringValue(event.level);
2196
2157
  if (event?.type === "error" || event?.type === "process_exit" || event?.type === "daemon_exit") return "error";
2197
2158
  return "info";
2198
2159
  }
@@ -2200,14 +2161,14 @@ function boolText(value) {
2200
2161
  return value ? "yes" : "no";
2201
2162
  }
2202
2163
  function shortId(value) {
2203
- const text = stringValue2(value);
2164
+ const text = stringValue(value);
2204
2165
  return text ? text.slice(0, 8) : "unknown";
2205
2166
  }
2206
2167
  function looksLikeError(value) {
2207
- return /(error|exception|traceback|failed|fatal|denied|unauthorized|timeout)/i.test(stringValue2(value));
2168
+ return /(error|exception|traceback|failed|fatal|denied|unauthorized|timeout)/i.test(stringValue(value));
2208
2169
  }
2209
2170
  function setAgentRunState(agentRunState, relativePath, patch) {
2210
- const key = stringValue2(relativePath || ".");
2171
+ const key = stringValue(relativePath || ".");
2211
2172
  return {
2212
2173
  ...agentRunState || {},
2213
2174
  [key]: {
@@ -2259,19 +2220,19 @@ function appendProcessExitAgentLogs(agentLogs, event, agentRunState, relativePat
2259
2220
  function reconcileInventoryRunState(agentRunState, agents, timestamp) {
2260
2221
  let next = agentRunState || {};
2261
2222
  for (const agent of agents || []) {
2262
- const path10 = stringValue2(agent?.relativePath || ".");
2223
+ const path10 = stringValue(agent?.relativePath || ".");
2263
2224
  const current = next[path10];
2264
2225
  if (agent?.status === "error") {
2265
2226
  next = setAgentRunState(next, path10, {
2266
2227
  status: "error",
2267
2228
  lastEventAt: timestamp || (/* @__PURE__ */ new Date()).toISOString(),
2268
- errorMessage: stringValue2(agent.errorMessage || agent.error || "Agent setup failed")
2229
+ errorMessage: stringValue(agent.errorMessage || agent.error || "Agent setup failed")
2269
2230
  });
2270
2231
  } else if (agent?.status === "disabled") {
2271
2232
  next = setAgentRunState(next, path10, {
2272
2233
  status: "disabled",
2273
2234
  lastEventAt: timestamp || (/* @__PURE__ */ new Date()).toISOString(),
2274
- disabledReason: stringValue2(agent.disabledReason || "System dependency not met locally"),
2235
+ disabledReason: stringValue(agent.disabledReason || "System dependency not met locally"),
2275
2236
  resolutionHints: Array.isArray(agent.resolutionHints) ? agent.resolutionHints : []
2276
2237
  });
2277
2238
  } else if (agent?.status === "online" && ["preparing", "error", "disabled"].includes(current?.status) && !current?.runId) {
@@ -2291,22 +2252,22 @@ function reconcileInventoryRunState(agentRunState, agents, timestamp) {
2291
2252
  function normalizeStoredAgentLogEntry(entry) {
2292
2253
  return {
2293
2254
  timestamp: entry.timestamp || (/* @__PURE__ */ new Date()).toISOString(),
2294
- runId: stringValue2(entry.runId),
2295
- eventType: stringValue2(entry.eventType || "log"),
2296
- level: stringValue2(entry.level || "info"),
2297
- message: stringValue2(entry.message),
2298
- stepId: entry.stepId ? stringValue2(entry.stepId) : null,
2255
+ runId: stringValue(entry.runId),
2256
+ eventType: stringValue(entry.eventType || "log"),
2257
+ level: stringValue(entry.level || "info"),
2258
+ message: stringValue(entry.message),
2259
+ stepId: entry.stepId ? stringValue(entry.stepId) : null,
2299
2260
  current: entry.current ?? null,
2300
2261
  total: entry.total ?? null,
2301
2262
  success: entry.success ?? null,
2302
2263
  error: entry.error ?? null,
2303
- jobType: entry.jobType ? stringValue2(entry.jobType) : null
2264
+ jobType: entry.jobType ? stringValue(entry.jobType) : null
2304
2265
  };
2305
2266
  }
2306
2267
  function formatErrorMessage(error) {
2307
2268
  if (!error) return null;
2308
- if (typeof error === "object") return stringValue2(error.message || "error");
2309
- return stringValue2(error);
2269
+ if (typeof error === "object") return stringValue(error.message || "error");
2270
+ return stringValue(error);
2310
2271
  }
2311
2272
  function findNewAgents(previous, next) {
2312
2273
  const seen = new Set(previous.map(agentKey).filter(Boolean));
@@ -2319,15 +2280,15 @@ function agentKey(agent) {
2319
2280
  if (!agent || typeof agent !== "object") {
2320
2281
  return "";
2321
2282
  }
2322
- return stringValue2(agent.localAgentId || agent.relativePath || agent.path || agent.manifestName || agent.id);
2283
+ return stringValue(agent.localAgentId || agent.relativePath || agent.path || agent.manifestName || agent.id);
2323
2284
  }
2324
2285
  function agentLabel(event) {
2325
- return stringValue2(event.relativePath || event.path || ".");
2286
+ return stringValue(event.relativePath || event.path || ".");
2326
2287
  }
2327
2288
  function jobLabel(event) {
2328
- return stringValue2(event.runId || event.deployRequestId || event.relativePath || event.jobType || "job");
2289
+ return stringValue(event.runId || event.deployRequestId || event.relativePath || event.jobType || "job");
2329
2290
  }
2330
- function stringValue2(value) {
2291
+ function stringValue(value) {
2331
2292
  return value == null ? "" : String(value);
2332
2293
  }
2333
2294
  function processExitMessage(event) {
@@ -2344,11 +2305,11 @@ function agentPrepareLogMessage(event) {
2344
2305
  return "Preparing agent";
2345
2306
  }
2346
2307
  if (event.type === "agent_prepare_completed") {
2347
- if (event.status === "error") return stringValue2(event.error || event.errorMessage || "Agent setup failed");
2348
- if (event.status === "disabled") return stringValue2(event.warning || event.disabledReason || "Agent disabled locally");
2308
+ if (event.status === "error") return stringValue(event.error || event.errorMessage || "Agent setup failed");
2309
+ if (event.status === "disabled") return stringValue(event.warning || event.disabledReason || "Agent disabled locally");
2349
2310
  return "Agent ready";
2350
2311
  }
2351
- return stringValue2(event.message || event.stage || "Preparing agent");
2312
+ return stringValue(event.message || event.stage || "Preparing agent");
2352
2313
  }
2353
2314
  function textTail(value, limit = 800) {
2354
2315
  const text = String(value || "").trim().replace(/\s+/g, " ");
@@ -2500,7 +2461,7 @@ function buildLocalServeEventStreamArgs({ agentsDir: agentsDir2 = "./agents", co
2500
2461
  }
2501
2462
 
2502
2463
  // src/version.js
2503
- var CLI_VERSION = true ? "0.0.43" : process.env.npm_package_version || "0.0.0-dev";
2464
+ var CLI_VERSION = true ? "0.0.44" : process.env.npm_package_version || "0.0.0-dev";
2504
2465
 
2505
2466
  // src/dev-server.js
2506
2467
  var __dirname = path8.dirname(fileURLToPath(import.meta.url));
@@ -2621,8 +2582,6 @@ async function handleApi(req, res, pathname, parsed) {
2621
2582
  return apiServeState(req, res);
2622
2583
  case "/api/auth":
2623
2584
  return apiAuth(req, res);
2624
- case "/api/workspaces":
2625
- return await apiWorkspaces(req, res);
2626
2585
  default:
2627
2586
  return jsonResponse(res, { error: "not found" }, 404);
2628
2587
  }
@@ -2785,10 +2744,6 @@ function apiAuth(req, res) {
2785
2744
  backends
2786
2745
  });
2787
2746
  }
2788
- async function apiWorkspaces(req, res) {
2789
- const result = await listCloudWorkspaces({ timeoutMs: 15e3 });
2790
- jsonResponse(res, result);
2791
- }
2792
2747
  async function apiAuthSwitch(req, res, body) {
2793
2748
  const backend = body.backend;
2794
2749
  if (!backend || !BACKEND_TARGETS[backend]) {
@@ -2876,9 +2831,6 @@ async function apiValidate(req, res, body) {
2876
2831
  function resolveServeStartTarget(body = {}, current = {}) {
2877
2832
  const targetDir = body.agentsDir || current.agentsDir || "";
2878
2833
  const targetCollection = body.collectionId || current.collectionId || "";
2879
- if (!targetCollection) {
2880
- return { ok: false, error: "Choose a workspace before starting local serve." };
2881
- }
2882
2834
  return { ok: true, agentsDir: targetDir, collectionId: targetCollection };
2883
2835
  }
2884
2836
  function devServerStateAfterServeStart(current = {}, target = {}) {
@@ -3164,6 +3116,59 @@ init_paths();
3164
3116
  init_setup();
3165
3117
  init_process();
3166
3118
 
3119
+ // src/collections.js
3120
+ init_process();
3121
+ async function listCloudCollections({
3122
+ env = process.env,
3123
+ platform = process.platform,
3124
+ prepareInvocation = preparePythonVendianInvocation,
3125
+ run: run2 = runCapture,
3126
+ onProgress = null,
3127
+ timeoutMs = 2e4
3128
+ } = {}) {
3129
+ const progress = typeof onProgress === "function" ? onProgress : () => {
3130
+ };
3131
+ progress("Checking managed Python runtime");
3132
+ const invocation = await prepareInvocation(["cloud", "collections", "list", "--json"], {
3133
+ env,
3134
+ platform,
3135
+ onProgress: progress,
3136
+ skipAutoUpdate: true
3137
+ });
3138
+ progress("Loading collections from Vendian");
3139
+ const result = run2(invocation.command, invocation.args, { env: invocation.env, timeout: timeoutMs });
3140
+ if (!result.ok) {
3141
+ return {
3142
+ ok: false,
3143
+ collections: [],
3144
+ error: (result.stderr || result.stdout || `collection list exited with code ${result.status}`).trim()
3145
+ };
3146
+ }
3147
+ try {
3148
+ return { ok: true, collections: normalizeCollectionList(JSON.parse(result.stdout)), error: "" };
3149
+ } catch (error) {
3150
+ const message = error && typeof error.message === "string" ? error.message : String(error);
3151
+ return { ok: false, collections: [], error: `Could not parse collection list: ${message}` };
3152
+ }
3153
+ }
3154
+ function normalizeCollectionList(payload) {
3155
+ const data = payload && typeof payload === "object" && "data" in payload ? payload.data : payload;
3156
+ const raw = Array.isArray(data) ? data : data && typeof data === "object" && Array.isArray(data.data) ? data.data : data && typeof data === "object" && Array.isArray(data.collections) ? data.collections : [];
3157
+ return raw.filter((item) => item && typeof item === "object").map((item) => ({
3158
+ id: stringValue2(item.id),
3159
+ name: stringValue2(item.name || item.slug || item.id || "Unnamed collection"),
3160
+ slug: stringValue2(item.slug)
3161
+ })).filter((item) => item.id);
3162
+ }
3163
+ function collectionLabel(collection) {
3164
+ const name = collection?.name || collection?.slug || collection?.id || "Unnamed collection";
3165
+ const slug = collection?.slug && collection.slug !== name ? ` (${collection.slug})` : "";
3166
+ return `${name}${slug}`;
3167
+ }
3168
+ function stringValue2(value) {
3169
+ return value == null ? "" : String(value).trim();
3170
+ }
3171
+
3167
3172
  // src/ui/figures.js
3168
3173
  var supportsUnicode = process.platform !== "win32" || Boolean(
3169
3174
  process.env.WT_SESSION || // Windows Terminal
@@ -3463,7 +3468,7 @@ async function connectCustomUrl({ env, platform }) {
3463
3468
  var COMMAND_GROUPS = [
3464
3469
  { section: "Getting started", commands: [
3465
3470
  { cmd: "vendian login", desc: "Sign in and set up your computer" },
3466
- { cmd: "vendian init --output-dir ./agents", desc: "Set up a docs workspace" }
3471
+ { cmd: "vendian init --output-dir ./agents", desc: "Set up SDK docs" }
3467
3472
  ] },
3468
3473
  { section: "Building agents", commands: [
3469
3474
  { cmd: 'vendian create "My Agent" --output-dir .', desc: "Create a new agent" },
@@ -3587,13 +3592,13 @@ async function pickSingleAgentToRun({ env, platform, candidates }) {
3587
3592
  if (idx === null || idx === -1) return null;
3588
3593
  return agents[idx];
3589
3594
  }
3590
- async function chooseCloudWorkspace({ env, platform, loadingTitle, pickerTitle } = {}) {
3595
+ async function chooseCloudCollection({ env, platform, loadingTitle, pickerTitle } = {}) {
3591
3596
  print("");
3592
- process.stdout.write(` ${col.gray(loadingTitle || "Loading workspaces...")}
3597
+ process.stdout.write(` ${col.gray(loadingTitle || "Loading collections...")}
3593
3598
  `);
3594
- let wsResult;
3599
+ let result;
3595
3600
  try {
3596
- wsResult = await listCloudWorkspaces({
3601
+ result = await listCloudCollections({
3597
3602
  env,
3598
3603
  platform,
3599
3604
  onProgress: (msg) => {
@@ -3609,28 +3614,28 @@ async function chooseCloudWorkspace({ env, platform, loadingTitle, pickerTitle }
3609
3614
  await pressEnterToContinue({ grabActive: false });
3610
3615
  return null;
3611
3616
  }
3612
- if (!wsResult.ok) {
3617
+ if (!result.ok) {
3613
3618
  print(col.red(`
3614
- ${fig.cross} ${wsResult.error}`));
3619
+ ${fig.cross} ${result.error}`));
3615
3620
  await pressEnterToContinue({ grabActive: false });
3616
3621
  return null;
3617
3622
  }
3618
- if (wsResult.workspaces.length === 0) return null;
3619
- if (wsResult.workspaces.length === 1) {
3620
- const ws2 = wsResult.workspaces[0];
3621
- return { id: ws2.id || "", label: workspaceLabel(ws2) };
3623
+ if (result.collections.length === 0) return null;
3624
+ if (result.collections.length === 1) {
3625
+ const collection2 = result.collections[0];
3626
+ return { id: collection2.id || "", label: collectionLabel(collection2) };
3622
3627
  }
3623
3628
  clearScreen();
3624
3629
  print("");
3625
3630
  printHeader({ env, platform });
3626
3631
  print("");
3627
- print(col.bold(` ${pickerTitle || "Choose a workspace:"}`));
3632
+ print(col.bold(` ${pickerTitle || "Choose a collection:"}`));
3628
3633
  print("");
3629
- const items = wsResult.workspaces.map((ws2) => workspaceLabel(ws2));
3634
+ const items = result.collections.map((collection2) => collectionLabel(collection2));
3630
3635
  const idx = await pickMenu(items, { allowBack: true });
3631
3636
  if (idx === null || idx === -1) return null;
3632
- const ws = wsResult.workspaces[idx];
3633
- return { id: ws.id || "", label: workspaceLabel(ws) };
3637
+ const collection = result.collections[idx];
3638
+ return { id: collection.id || "", label: collectionLabel(collection) };
3634
3639
  }
3635
3640
  async function showCreate({ env, platform }) {
3636
3641
  clearScreen();
@@ -3651,19 +3656,19 @@ async function showRun({ env, platform }) {
3651
3656
  const candidates = findAgentDirectoryCandidates();
3652
3657
  const picked = await pickSingleAgentToRun({ env, platform, candidates });
3653
3658
  if (!picked) return "home";
3654
- const workspace = await chooseCloudWorkspace({
3659
+ const collection = await chooseCloudCollection({
3655
3660
  env,
3656
3661
  platform,
3657
3662
  loadingTitle: "Getting ready to run this agent...",
3658
- pickerTitle: "Which project should own this run?"
3663
+ pickerTitle: "Which collection should own this run?"
3659
3664
  });
3660
- if (!workspace) return "home";
3665
+ if (!collection) return "home";
3661
3666
  const inputJson = await ask("Input JSON", "{}");
3662
3667
  await withOutputMode(
3663
3668
  `Running ${picked.displayName}`,
3664
3669
  () => forwardToPythonVendian(buildLocalRunArgs({
3665
3670
  agentPath: picked.path,
3666
- collectionId: workspace.id,
3671
+ collectionId: collection.id,
3667
3672
  inputJson: inputJson || "{}"
3668
3673
  }), { env, platform })
3669
3674
  );
@@ -3674,16 +3679,15 @@ async function showServe({ env, platform }) {
3674
3679
  const picked = await pickAgentsToRun({ env, platform, candidates });
3675
3680
  if (!picked) return "home";
3676
3681
  const { agentsDir: agentsDir2 } = picked;
3677
- const workspace = await chooseCloudWorkspace({
3682
+ return await runServeDashboard({
3678
3683
  env,
3679
3684
  platform,
3680
- loadingTitle: "Getting ready to run your agents...",
3681
- pickerTitle: "Which project do you want to run?"
3685
+ agentsDir: agentsDir2,
3686
+ collectionId: "",
3687
+ collectionLabel: "Admin Local Lab"
3682
3688
  });
3683
- if (!workspace) return "home";
3684
- return await runServeDashboard({ env, platform, agentsDir: agentsDir2, collectionId: workspace.id, wsLabel: workspace.label });
3685
3689
  }
3686
- async function runServeDashboard({ env, platform, agentsDir: agentsDir2, collectionId: collectionId2, wsLabel = "" }) {
3690
+ async function runServeDashboard({ env, platform, agentsDir: agentsDir2, collectionId: collectionId2, collectionLabel: collectionLabel2 = "" }) {
3687
3691
  let state = initialServeState();
3688
3692
  let child = null;
3689
3693
  let ctrlCArmed = false;
@@ -3703,7 +3707,7 @@ async function runServeDashboard({ env, platform, agentsDir: agentsDir2, collect
3703
3707
  print(col.gray("\u2550".repeat(W)));
3704
3708
  print(` ${col.cyan(col.bold("\u2191 VENDIAN"))} ${col.bold("Serving agents")}`);
3705
3709
  print(` ${col.gray("Dir:")} ${agentsDir2}`);
3706
- print(` ${col.gray("Workspace:")} ${wsLabel || collectionId2 || "\u2014"}`);
3710
+ print(` ${col.gray("Scope:")} ${collectionLabel2 || collectionId2 || "Admin Local Lab"}`);
3707
3711
  print(col.gray(hr(W)));
3708
3712
  print(col.gray(" S stop gracefully | ^c ^c exit"));
3709
3713
  print(col.gray(hr(W)));
@@ -4162,7 +4166,7 @@ function helpText() {
4162
4166
  " vendian login Sign in and prepare the local runtime",
4163
4167
  " vendian doctor Check local bootstrap health",
4164
4168
  " vendian update Update the managed runtime",
4165
- " vendian init Write SDK agent docs into a workspace",
4169
+ " vendian init Write SDK agent docs into a folder",
4166
4170
  ' vendian create "My Agent" Scaffold a new agent from templates',
4167
4171
  " vendian dev Open the dev UI (alias for bare vendian)",
4168
4172
  " vendian <command> Run a managed Python SDK/cloud command",
@@ -152,22 +152,10 @@ body { font-family: var(--font); background: var(--bg-page); color: var(--text);
152
152
  .serve-section-title { font-size: 11px; font-weight: 700; color: var(--text-dim); text-transform: uppercase; letter-spacing: 0.5px; }
153
153
  .serve-section-desc { font-size: 12.5px; color: var(--text-secondary); margin-top: 3px; }
154
154
  .serve-section-meta { font-size: 11.5px; color: var(--text-dim); white-space: nowrap; padding-top: 1px; }
155
- #workspace-picker { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: 10px; margin-bottom: 6px; }
156
155
  .serve-select-bar { display: flex; align-items: center; gap: 9px; padding: 10px 14px; border-radius: 8px; background: var(--bg-card); border: 1px solid var(--border); box-shadow: var(--shadow); margin-bottom: 14px; font-size: 13px; font-weight: 600; cursor: pointer; user-select: none; }
157
156
  .serve-select-bar:hover { background: var(--bg-hover); }
158
157
  .serve-select-bar input { width: 16px; height: 16px; accent-color: var(--accent-solid); cursor: pointer; }
159
158
  .serve-select-bar .count { margin-left: auto; font-weight: 400; color: var(--text-dim); font-size: 12px; }
160
- .workspace-card { background: var(--bg-card); border: 1px solid var(--border); border-radius: var(--radius-lg); padding: 14px 16px; text-align: left; cursor: pointer; transition: all var(--transition); box-shadow: var(--shadow); font: inherit; color: inherit; }
161
- .workspace-card:hover { border-color: var(--border-hover); transform: translateY(-1px); box-shadow: var(--shadow-lg); }
162
- .workspace-card.selected { border-color: var(--accent); background: var(--accent-bg); }
163
- .workspace-card-title-row { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; }
164
- .workspace-card-title { font-size: 13.5px; font-weight: 650; color: var(--text); }
165
- .workspace-card-slug { font-size: 11px; color: var(--text-dim); margin-top: 2px; }
166
- .workspace-card-id { font-size: 11px; font-family: var(--mono); color: var(--text-dim); margin-top: 10px; overflow: hidden; text-overflow: ellipsis; }
167
- .workspace-card-badge { font-size: 10px; font-weight: 700; padding: 3px 8px; border-radius: 4px; border: 1px solid var(--border); color: var(--text-dim); background: var(--bg-elevated); white-space: nowrap; }
168
- .workspace-card.selected .workspace-card-badge { color: var(--accent); border-color: var(--accent-border); background: white; }
169
- .workspace-empty { padding: 14px 16px; border-radius: var(--radius); background: var(--bg-card); border: 1px dashed var(--border); color: var(--text-secondary); font-size: 12.5px; }
170
- .workspace-empty.workspace-error { color: var(--red); border-color: var(--red-border); background: var(--red-bg); }
171
159
  .serve-folder { margin-bottom: 20px; }
172
160
  .serve-folder-title { display: flex; align-items: center; gap: 6px; margin-bottom: 8px; font-size: 10.5px; font-weight: 700; color: var(--text-dim); text-transform: uppercase; letter-spacing: 0.5px; }
173
161
  .serve-folder-title svg { width: 12px; height: 12px; opacity: 0.5; }
package/dev-ui/index.html CHANGED
@@ -23,7 +23,7 @@
23
23
 
24
24
  <div class="layout">
25
25
  <aside class="sidebar">
26
- <div class="nav-label">Workspace</div>
26
+ <div class="nav-label">Agents</div>
27
27
  <div class="nav-item active" data-page="agents">
28
28
  <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="3" y="3" width="7" height="7" rx="2"/><rect x="14" y="3" width="7" height="7" rx="2"/><rect x="3" y="14" width="7" height="7" rx="2"/><rect x="14" y="14" width="7" height="7" rx="2"/></svg>
29
29
  <span>Agents</span>
@@ -95,18 +95,9 @@
95
95
 
96
96
  <div id="serve-picker-section">
97
97
  <div class="serve-section-head">
98
- <div>
99
- <div class="serve-section-title">Workspace</div>
100
- <div class="serve-section-desc">Choose the Vendian workspace that should own this daemon and its local runs.</div>
101
- </div>
102
- <div class="serve-section-meta" id="workspace-summary">Loading workspaces…</div>
103
- </div>
104
- <div id="workspace-picker"></div>
105
-
106
- <div class="serve-section-head" style="margin-top:20px">
107
98
  <div>
108
99
  <div class="serve-section-title">Agents</div>
109
- <div class="serve-section-desc">Pick which local agents this serve session should expose.</div>
100
+ <div class="serve-section-desc">Pick which local agents this Local Lab session should expose.</div>
110
101
  </div>
111
102
  </div>
112
103
  <div class="serve-select-bar" id="serve-select-bar">
package/dev-ui/js/app.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { state, api } from './state.js';
2
2
  import { renderAgents } from './agents.js';
3
3
  import { populateValidateGrid, runValidateAll, triggerValidateAgent } from './validate.js';
4
- import { populateServePicker, toggleAll, startServe, stopServe, setServing, clearLogs, loadWorkspaces } from './serve.js';
4
+ import { populateServePicker, toggleAll, startServe, stopServe, setServing, clearLogs } from './serve.js';
5
5
  import { loadAuth } from './settings.js';
6
6
 
7
7
  // ─── Navigation ───
@@ -20,10 +20,6 @@ window.addEventListener('navigate', (e) => {
20
20
  if (page === 'validate' && path) triggerValidateAgent(path);
21
21
  });
22
22
 
23
- window.addEventListener('auth-changed', () => {
24
- loadWorkspaces();
25
- });
26
-
27
23
  // ─── Load agents ───
28
24
  async function loadAgents() {
29
25
  try {
@@ -96,8 +92,6 @@ document.getElementById('serve-select-bar').addEventListener('click', (e) => {
96
92
  // ─── Init ───
97
93
  loadAgents();
98
94
  loadAuth();
99
- loadWorkspaces();
100
95
  checkStatus();
101
96
  setInterval(checkStatus, 4000);
102
97
  setInterval(loadAgents, 8000);
103
- setInterval(loadWorkspaces, 15000);
@@ -1,80 +1,5 @@
1
1
  import { state, api, esc, groupByFolder, formatTime } from './state.js';
2
2
 
3
- export async function loadWorkspaces() {
4
- state.workspacesLoading = true;
5
- state.workspacesError = '';
6
- renderWorkspacePicker();
7
- try {
8
- const result = await api('/workspaces');
9
- state.workspaces = Array.isArray(result.workspaces) ? result.workspaces : [];
10
- const hasSelected = state.workspaces.some((workspace) => workspace.id === state.selectedWorkspaceId);
11
- if (!hasSelected) {
12
- state.selectedWorkspaceId = state.workspaces[0]?.id || '';
13
- }
14
- if (!result.ok) {
15
- state.workspacesError = result.error || 'Could not load workspaces.';
16
- }
17
- } catch (error) {
18
- state.workspaces = [];
19
- state.selectedWorkspaceId = '';
20
- state.workspacesError = error?.message || 'Could not load workspaces.';
21
- } finally {
22
- state.workspacesLoading = false;
23
- renderWorkspacePicker();
24
- }
25
- }
26
-
27
- export function renderWorkspacePicker() {
28
- const container = document.getElementById('workspace-picker');
29
- const summary = document.getElementById('workspace-summary');
30
- if (!container || !summary) return;
31
-
32
- if (state.workspacesLoading) {
33
- summary.textContent = 'Loading workspaces…';
34
- container.innerHTML = '<div class="workspace-empty">Loading workspaces from Vendian…</div>';
35
- return;
36
- }
37
-
38
- if (state.workspacesError) {
39
- summary.textContent = 'Workspace required';
40
- container.innerHTML = `<div class="workspace-empty workspace-error">${esc(state.workspacesError)}</div>`;
41
- return;
42
- }
43
-
44
- if (!state.workspaces.length) {
45
- summary.textContent = 'No workspace available';
46
- container.innerHTML = '<div class="workspace-empty">Sign in to a Vendian environment to load workspaces.</div>';
47
- return;
48
- }
49
-
50
- const selected = state.workspaces.find((workspace) => workspace.id === state.selectedWorkspaceId) || state.workspaces[0];
51
- if (selected && state.selectedWorkspaceId !== selected.id) {
52
- state.selectedWorkspaceId = selected.id || '';
53
- }
54
- summary.textContent = `${state.workspaces.length} workspace${state.workspaces.length === 1 ? '' : 's'}`;
55
- container.innerHTML = state.workspaces.map((workspace) => {
56
- const selectedClass = workspace.id === state.selectedWorkspaceId ? ' selected' : '';
57
- const slug = workspace.slug && workspace.slug !== workspace.name ? `<div class="workspace-card-slug">${esc(workspace.slug)}</div>` : '';
58
- return `<button type="button" class="workspace-card${selectedClass}" data-workspace-id="${esc(workspace.id)}">
59
- <div class="workspace-card-title-row">
60
- <div>
61
- <div class="workspace-card-title">${esc(workspace.name || workspace.id)}</div>
62
- ${slug}
63
- </div>
64
- <div class="workspace-card-badge">${workspace.id === state.selectedWorkspaceId ? 'Selected' : 'Choose'}</div>
65
- </div>
66
- <div class="workspace-card-id">${esc(workspace.id)}</div>
67
- </button>`;
68
- }).join('');
69
-
70
- container.querySelectorAll('[data-workspace-id]').forEach((button) => {
71
- button.addEventListener('click', () => {
72
- state.selectedWorkspaceId = button.dataset.workspaceId || '';
73
- renderWorkspacePicker();
74
- });
75
- });
76
- }
77
-
78
3
  // ─── Picker ───
79
4
  let userSelections = null; // null = all selected (default), Set = explicit selections
80
5
 
@@ -160,9 +85,8 @@ export function getSelectedPaths() {
160
85
  // ─── Controls ───
161
86
  export async function startServe() {
162
87
  const selected = getSelectedPaths();
163
- if (!state.selectedWorkspaceId) { alert('Choose a workspace before starting local serve.'); return; }
164
88
  if (!selected.length) { alert('Select at least one agent.'); return; }
165
- const body = { collectionId: state.selectedWorkspaceId };
89
+ const body = {};
166
90
  if (selected.length < state.agents.length) {
167
91
  body.agentsDir = commonParent(selected);
168
92
  }
@@ -2,10 +2,6 @@
2
2
  export const state = {
3
3
  agents: [],
4
4
  authData: {},
5
- workspaces: [],
6
- selectedWorkspaceId: '',
7
- workspacesLoading: false,
8
- workspacesError: '',
9
5
  logOffset: 0,
10
6
  pollTimer: null,
11
7
  isServing: false,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vendian/cli",
3
- "version": "0.0.43",
3
+ "version": "0.0.44",
4
4
  "description": "Public Vendian CLI bootstrapper and launcher",
5
5
  "license": "UNLICENSED",
6
6
  "private": false,