nolo-cli 0.1.46 → 0.1.47

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/index.js +688 -175
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -1443,6 +1443,15 @@ var init_agentAliases = __esm({
1443
1443
  nolo: NOLO_DEFAULT_AGENT_KEY,
1444
1444
  default: NOLO_DEFAULT_AGENT_KEY,
1445
1445
  "default-nolo": NOLO_DEFAULT_AGENT_KEY,
1446
+ // Product implementation & coordination aliases
1447
+ "frontend-implementer": NOLO_FRONTEND_AGENT_KEY,
1448
+ "frontend-agent": NOLO_FRONTEND_AGENT_KEY,
1449
+ frontend: NOLO_FRONTEND_AGENT_KEY,
1450
+ "frontend agent": NOLO_FRONTEND_AGENT_KEY,
1451
+ "\u524D\u7AEFagent": NOLO_FRONTEND_AGENT_KEY,
1452
+ "\u524D\u7AEF agent": NOLO_FRONTEND_AGENT_KEY,
1453
+ "project-manager": NOLO_PROJECT_MANAGER_AGENT_KEY,
1454
+ pm: NOLO_PROJECT_MANAGER_AGENT_KEY,
1446
1455
  // Explicit local CLI agents. These are ordinary private agent records that
1447
1456
  // run through the current computer local runtime when unbound.
1448
1457
  "local-codex": LOCAL_CODEX_AGENT_KEY,
@@ -19818,7 +19827,7 @@ var init_userPreferenceRegister = __esm({
19818
19827
  });
19819
19828
 
19820
19829
  // packages/app/theme/colors.ts
19821
- var semantic, mkLight, mkDark, neutral, ocean, iris, forest, trail, wave, rose, ember, blue, purple, green, graphite, mocha, pink, red, orange, yellow;
19830
+ var semantic, mkLight, mkDark, neutral, ocean, iris, forest, trail, wave, rose, ember, catppuccin, blue, purple, green, graphite, mocha, pink, red, orange, yellow;
19822
19831
  var init_colors = __esm({
19823
19832
  "packages/app/theme/colors.ts"() {
19824
19833
  "use strict";
@@ -19847,7 +19856,8 @@ var init_colors = __esm({
19847
19856
  codeBackground: bg3,
19848
19857
  shadowLight: `rgba(0,0,0,0.04)`,
19849
19858
  shadowMedium: `rgba(0,0,0,0.08)`,
19850
- shadowHeavy: `rgba(0,0,0,0.14)`
19859
+ shadowHeavy: `rgba(0,0,0,0.14)`,
19860
+ textOnPrimary: "#FFFFFF"
19851
19861
  });
19852
19862
  mkDark = (bg, bg2, bg3, textPrimary, textSec, textTer, border, borderL, shadowBase = "0,0,0") => ({
19853
19863
  background: bg,
@@ -19870,7 +19880,8 @@ var init_colors = __esm({
19870
19880
  codeBackground: bg2,
19871
19881
  shadowLight: `rgba(${shadowBase},0.18)`,
19872
19882
  shadowMedium: `rgba(${shadowBase},0.30)`,
19873
- shadowHeavy: `rgba(${shadowBase},0.44)`
19883
+ shadowHeavy: `rgba(${shadowBase},0.44)`,
19884
+ textOnPrimary: "#FFFFFF"
19874
19885
  });
19875
19886
  neutral = {
19876
19887
  light: {
@@ -19881,7 +19892,8 @@ var init_colors = __esm({
19881
19892
  primaryGhost: "rgba(113,113,122,0.08)",
19882
19893
  primaryHover: "rgba(113,113,122,0.10)",
19883
19894
  borderAccent: "#D4D4D8",
19884
- ...semantic.light
19895
+ ...semantic.light,
19896
+ ...mkLight("#FFFFFF", "#F4F4F5", "#E4E4E7", "#18181B", "#52525B", "#71717A", "#E4E4E7", "#F4F4F5")
19885
19897
  },
19886
19898
  dark: {
19887
19899
  primary: "#A1A1AA",
@@ -19891,7 +19903,9 @@ var init_colors = __esm({
19891
19903
  primaryGhost: "rgba(161,161,170,0.10)",
19892
19904
  primaryHover: "rgba(161,161,170,0.12)",
19893
19905
  borderAccent: "#52525B",
19894
- ...semantic.dark
19906
+ ...semantic.dark,
19907
+ ...mkDark("#18181B", "#27272A", "#3F3F46", "#FAFAFA", "#D4D4D8", "#A1A1AA", "#3F3F46", "#27272A", "24,24,27"),
19908
+ textOnPrimary: "#18181B"
19895
19909
  }
19896
19910
  };
19897
19911
  ocean = {
@@ -19916,7 +19930,8 @@ var init_colors = __esm({
19916
19930
  borderAccent: "#1F6FEB",
19917
19931
  ...semantic.dark,
19918
19932
  ...mkDark("#0D1117", "#161B22", "#21262D", "#E6EDF3", "#8B949E", "#6E7681", "#30363D", "#161B22", "13,17,23"),
19919
- textHeading: "#E6EDF3"
19933
+ textHeading: "#E6EDF3",
19934
+ textOnPrimary: "#0D1117"
19920
19935
  }
19921
19936
  };
19922
19937
  iris = {
@@ -19941,7 +19956,8 @@ var init_colors = __esm({
19941
19956
  borderAccent: "#4A55C0",
19942
19957
  ...semantic.dark,
19943
19958
  ...mkDark("#0F0E17", "#16141F", "#1E1B2E", "#E8E5F7", "#A8A4C8", "#7B7698", "#272435", "#16141F", "15,14,23"),
19944
- textHeading: "#E8E5F7"
19959
+ textHeading: "#E8E5F7",
19960
+ textOnPrimary: "#0F0E17"
19945
19961
  }
19946
19962
  };
19947
19963
  forest = {
@@ -19967,10 +19983,12 @@ var init_colors = __esm({
19967
19983
  ...semantic.dark,
19968
19984
  ...mkDark("#0C1209", "#121A0E", "#1A2416", "#E4F0E2", "#87A882", "#5E7A5A", "#1A2416", "#121A0E", "12,18,9"),
19969
19985
  success: "#4ADE80",
19970
- textHeading: "#C8EEC4"
19986
+ textHeading: "#C8EEC4",
19987
+ textOnPrimary: "#0C1209"
19971
19988
  }
19972
19989
  };
19973
19990
  trail = {
19991
+ meta: { radiusBoost: 1, motionEase: "cubic-bezier(0.22, 1, 0.36, 1)" },
19974
19992
  light: {
19975
19993
  primary: "#2E7DB5",
19976
19994
  primaryLight: "#6BB5E0",
@@ -20007,7 +20025,8 @@ var init_colors = __esm({
20007
20025
  shadowLight: "rgba(28, 36, 48, 0.05)",
20008
20026
  shadowMedium: "rgba(28, 36, 48, 0.09)",
20009
20027
  shadowHeavy: "rgba(28, 36, 48, 0.14)",
20010
- textHeading: "#1C2430"
20028
+ textHeading: "#1C2430",
20029
+ textOnPrimary: "#FFFFFF"
20011
20030
  },
20012
20031
  dark: {
20013
20032
  primary: "#5BA3D9",
@@ -20045,7 +20064,8 @@ var init_colors = __esm({
20045
20064
  shadowLight: "rgba(4, 8, 12, 0.22)",
20046
20065
  shadowMedium: "rgba(4, 8, 12, 0.34)",
20047
20066
  shadowHeavy: "rgba(4, 8, 12, 0.46)",
20048
- textHeading: "#E8F4FC"
20067
+ textHeading: "#E8F4FC",
20068
+ textOnPrimary: "#0B1218"
20049
20069
  }
20050
20070
  };
20051
20071
  wave = {
@@ -20082,7 +20102,8 @@ var init_colors = __esm({
20082
20102
  codeBackground: "#ECEAE3",
20083
20103
  shadowLight: "rgba(26, 26, 34, 0.05)",
20084
20104
  shadowMedium: "rgba(26, 26, 34, 0.09)",
20085
- shadowHeavy: "rgba(26, 26, 34, 0.14)"
20105
+ shadowHeavy: "rgba(26, 26, 34, 0.14)",
20106
+ textOnPrimary: "#FFFFFF"
20086
20107
  },
20087
20108
  dark: {
20088
20109
  // Kanagawa Wave — crystalBlue accent(#7E9CD8 是函数名颜色,最标志性的 Kanagawa 蓝)
@@ -20129,8 +20150,9 @@ var init_colors = __esm({
20129
20150
  shadowLight: "rgba(13, 12, 12, 0.18)",
20130
20151
  shadowMedium: "rgba(13, 12, 12, 0.28)",
20131
20152
  shadowHeavy: "rgba(13, 12, 12, 0.38)",
20132
- textHeading: "#DCD7BA"
20153
+ textHeading: "#DCD7BA",
20133
20154
  // fujiWhite — 暖色标题
20155
+ textOnPrimary: "#1F1F28"
20134
20156
  }
20135
20157
  };
20136
20158
  rose = {
@@ -20166,7 +20188,8 @@ var init_colors = __esm({
20166
20188
  codeBackground: "#F2E9E1",
20167
20189
  shadowLight: "rgba(87, 82, 121, 0.05)",
20168
20190
  shadowMedium: "rgba(87, 82, 121, 0.09)",
20169
- shadowHeavy: "rgba(87, 82, 121, 0.14)"
20191
+ shadowHeavy: "rgba(87, 82, 121, 0.14)",
20192
+ textOnPrimary: "#FFFFFF"
20170
20193
  },
20171
20194
  dark: {
20172
20195
  // Rosé Pine main
@@ -20201,7 +20224,8 @@ var init_colors = __esm({
20201
20224
  shadowLight: "rgba(12, 10, 20, 0.20)",
20202
20225
  shadowMedium: "rgba(12, 10, 20, 0.30)",
20203
20226
  shadowHeavy: "rgba(12, 10, 20, 0.44)",
20204
- textHeading: "#E0DEF4"
20227
+ textHeading: "#E0DEF4",
20228
+ textOnPrimary: "#191724"
20205
20229
  }
20206
20230
  };
20207
20231
  ember = {
@@ -20226,14 +20250,54 @@ var init_colors = __esm({
20226
20250
  borderAccent: "#92400E",
20227
20251
  ...semantic.dark,
20228
20252
  ...mkDark("#1A1207", "#221809", "#2E220C", "#F0E2C0", "#C4A056", "#8A7040", "#3A2A10", "#221809", "26,18,7"),
20229
- textHeading: "#FCD34D"
20253
+ textHeading: "#FCD34D",
20254
+ textOnPrimary: "#1A1207"
20255
+ }
20256
+ };
20257
+ catppuccin = {
20258
+ light: {
20259
+ // Catppuccin Latte
20260
+ primary: "#1e66f5",
20261
+ // Blue
20262
+ primaryLight: "#89b4fa",
20263
+ // Blue Light
20264
+ primaryDark: "#4c4f69",
20265
+ // Text
20266
+ primaryGradient: "linear-gradient(135deg, #1e66f5, #89b4fa)",
20267
+ primaryGhost: "rgba(30, 102, 245, 0.08)",
20268
+ primaryHover: "rgba(30, 102, 245, 0.10)",
20269
+ borderAccent: "#ccd0da",
20270
+ success: "#40a02b",
20271
+ warning: "#df8e1d",
20272
+ info: "#1e66f5",
20273
+ error: "#d20f39",
20274
+ ...mkLight("#eff1f5", "#e6e9ef", "#dce0e8", "#4c4f69", "#5c5f77", "#6c6f85", "#ccd0da", "#e6e9ef")
20275
+ },
20276
+ dark: {
20277
+ // Catppuccin Mocha
20278
+ primary: "#89b4fa",
20279
+ // Blue
20280
+ primaryLight: "#b4befe",
20281
+ // Lavender
20282
+ primaryDark: "#1e66f5",
20283
+ primaryGradient: "linear-gradient(135deg, #89b4fa, #b4befe)",
20284
+ primaryGhost: "rgba(137, 180, 250, 0.10)",
20285
+ primaryHover: "rgba(137, 180, 250, 0.14)",
20286
+ borderAccent: "#313244",
20287
+ success: "#a6e3a1",
20288
+ warning: "#f9e2af",
20289
+ info: "#89b4fa",
20290
+ error: "#f38ba8",
20291
+ ...mkDark("#1e1e2e", "#181825", "#11111b", "#cdd6f4", "#bac2de", "#a6adc8", "#313244", "#181825", "30,30,46"),
20292
+ textHeading: "#f5e0dc",
20293
+ textOnPrimary: "#11111b"
20230
20294
  }
20231
20295
  };
20232
20296
  blue = ocean;
20233
20297
  purple = iris;
20234
20298
  green = forest;
20235
20299
  graphite = neutral;
20236
- mocha = rose;
20300
+ mocha = catppuccin;
20237
20301
  pink = rose;
20238
20302
  red = ember;
20239
20303
  orange = ember;
@@ -20242,7 +20306,7 @@ var init_colors = __esm({
20242
20306
  });
20243
20307
 
20244
20308
  // packages/app/theme/theme.config.ts
20245
- var SPACE, THEME_COLORS, THEME_NAME_ALIASES, DEFAULT_THEME_NAME, BASE_COLORS, MODE_COLORS;
20309
+ var SPACE, THEME_COLORS, THEME_NAME_ALIASES, DEFAULT_THEME_NAME;
20246
20310
  var init_theme_config = __esm({
20247
20311
  "packages/app/theme/theme.config.ts"() {
20248
20312
  "use strict";
@@ -20273,6 +20337,7 @@ var init_theme_config = __esm({
20273
20337
  wave,
20274
20338
  rose,
20275
20339
  ember,
20340
+ catppuccin,
20276
20341
  // alias — DB 中可能存了旧 key,映射到最近似的新主题
20277
20342
  blue,
20278
20343
  purple,
@@ -20285,7 +20350,8 @@ var init_theme_config = __esm({
20285
20350
  mocha
20286
20351
  };
20287
20352
  THEME_NAME_ALIASES = {
20288
- blue: "ocean",
20353
+ blue: "catppuccin",
20354
+ ocean: "catppuccin",
20289
20355
  purple: "iris",
20290
20356
  green: "forest",
20291
20357
  orange: "ember",
@@ -20293,86 +20359,9 @@ var init_theme_config = __esm({
20293
20359
  graphite: "neutral",
20294
20360
  pink: "rose",
20295
20361
  red: "ember",
20296
- mocha: "rose"
20362
+ mocha: "catppuccin"
20297
20363
  };
20298
- DEFAULT_THEME_NAME = "ocean";
20299
- BASE_COLORS = {
20300
- light: {
20301
- background: "#FFFFFF",
20302
- backgroundSecondary: "#F4F4F5",
20303
- // zinc-100
20304
- backgroundTertiary: "#E4E4E7",
20305
- // zinc-200
20306
- backgroundGhost: "rgba(255, 255, 255, 0.94)",
20307
- backgroundHover: "#D4D4D8",
20308
- // zinc-300
20309
- backgroundSelected: "#A1A1AA",
20310
- // zinc-400
20311
- text: "#18181B",
20312
- // zinc-900
20313
- textSecondary: "#52525B",
20314
- // zinc-600
20315
- textTertiary: "#71717A",
20316
- // zinc-500
20317
- textQuaternary: "#A1A1AA",
20318
- // zinc-400
20319
- textLight: "#D4D4D8",
20320
- // zinc-300
20321
- placeholder: "#A1A1AA",
20322
- // zinc-400
20323
- border: "#E4E4E7",
20324
- // zinc-200
20325
- borderHover: "#A1A1AA",
20326
- // zinc-400
20327
- borderLight: "#F4F4F5",
20328
- // zinc-100
20329
- error: "#DC2626",
20330
- shadowLight: "rgba(0, 0, 0, 0.04)",
20331
- shadowMedium: "rgba(0, 0, 0, 0.08)",
20332
- shadowHeavy: "rgba(0, 0, 0, 0.14)",
20333
- messageBackground: "#FFFFFF",
20334
- codeBackground: "#F4F4F5"
20335
- },
20336
- dark: {
20337
- background: "#18181B",
20338
- // zinc-900
20339
- backgroundSecondary: "#27272A",
20340
- // zinc-800
20341
- backgroundTertiary: "#3F3F46",
20342
- // zinc-700
20343
- backgroundGhost: "rgba(24, 24, 27, 0.94)",
20344
- backgroundHover: "#52525B",
20345
- // zinc-600
20346
- backgroundSelected: "#3F3F46",
20347
- // zinc-700
20348
- text: "#FAFAFA",
20349
- // zinc-50
20350
- textSecondary: "#D4D4D8",
20351
- // zinc-300
20352
- textTertiary: "#A1A1AA",
20353
- // zinc-400
20354
- textQuaternary: "#71717A",
20355
- // zinc-500
20356
- textLight: "#52525B",
20357
- // zinc-600
20358
- placeholder: "#71717A",
20359
- // zinc-500
20360
- border: "#3F3F46",
20361
- // zinc-700
20362
- borderHover: "#71717A",
20363
- // zinc-500
20364
- borderLight: "#27272A",
20365
- // zinc-800
20366
- error: "#F87171",
20367
- shadowLight: "rgba(0, 0, 0, 0.16)",
20368
- shadowMedium: "rgba(0, 0, 0, 0.28)",
20369
- shadowHeavy: "rgba(0, 0, 0, 0.40)",
20370
- messageBackground: "#27272A",
20371
- codeBackground: "#09090B"
20372
- // zinc-950
20373
- }
20374
- };
20375
- MODE_COLORS = BASE_COLORS;
20364
+ DEFAULT_THEME_NAME = "catppuccin";
20376
20365
  }
20377
20366
  });
20378
20367
 
@@ -21564,9 +21553,9 @@ var init_settingSlice = __esm({
21564
21553
  const mode = isDark ? "dark" : "light";
21565
21554
  const validThemeName = THEME_COLORS[themeName] ? themeName : DEFAULT_THEME_NAME;
21566
21555
  const validFontPreset = normalizeFontPreset(fontPreset) ?? DEFAULT_FONT_PRESET;
21567
- const baseColors = MODE_COLORS[mode];
21568
- const themeColors = THEME_COLORS[validThemeName][mode];
21569
- const c = { ...baseColors, ...themeColors };
21556
+ const themeData = THEME_COLORS[validThemeName];
21557
+ const c = themeData[mode];
21558
+ const meta = themeData.meta;
21570
21559
  const compact2 = density === "compact";
21571
21560
  return {
21572
21561
  sidebarWidth: `${sidebarWidth}px`,
@@ -21618,14 +21607,14 @@ var init_settingSlice = __esm({
21618
21607
  },
21619
21608
  // Border radius scale — xs/sm/md map to control/surface/overlay tiers.
21620
21609
  // lg/xl remain as aliases for gradual migration of legacy CSS.
21621
- radius: /* @__PURE__ */ (() => {
21622
- const trail2 = validThemeName === "trail";
21610
+ radius: (() => {
21611
+ const boost = meta?.radiusBoost ?? 0;
21623
21612
  const xs = compact2 ? "10px" : "12px";
21624
- const sm = trail2 ? compact2 ? "15px" : "17px" : compact2 ? "14px" : "16px";
21613
+ const sm = compact2 ? `${14 + boost}px` : `${16 + boost}px`;
21625
21614
  const md = compact2 ? "20px" : "24px";
21626
21615
  return { xs, sm, md, lg: sm, xl: md };
21627
21616
  })(),
21628
- motionEase: validThemeName === "trail" ? "cubic-bezier(0.22, 1, 0.36, 1)" : "cubic-bezier(0.33, 0, 0.2, 1)",
21617
+ motionEase: meta?.motionEase ?? "cubic-bezier(0.33, 0, 0.2, 1)",
21629
21618
  motionEaseTide: "cubic-bezier(0.22, 1, 0.36, 1)",
21630
21619
  motionEaseBreath: "cubic-bezier(0.4, 0, 0.6, 1)",
21631
21620
  motionDuration: "0.32s",
@@ -22130,7 +22119,7 @@ var init_addContentAction = __esm({
22130
22119
  contentKey,
22131
22120
  fileCategory,
22132
22121
  mimeType,
22133
- fileSize,
22122
+ fileSize: fileSize2,
22134
22123
  originalName,
22135
22124
  categoryId: rawCategoryId,
22136
22125
  pinned = false,
@@ -22168,7 +22157,7 @@ var init_addContentAction = __esm({
22168
22157
  contentKey,
22169
22158
  ...fileCategory !== void 0 ? { fileCategory } : {},
22170
22159
  ...mimeType !== void 0 ? { mimeType } : {},
22171
- ...fileSize !== void 0 ? { fileSize } : {},
22160
+ ...fileSize2 !== void 0 ? { fileSize: fileSize2 } : {},
22172
22161
  ...originalName !== void 0 ? { originalName } : {},
22173
22162
  ...categoryIdForStorage !== void 0 && {
22174
22163
  categoryId: categoryIdForStorage
@@ -43545,7 +43534,7 @@ function appendCliCapabilityWarnings(content, warnings) {
43545
43534
  ${warnings.map((warning) => `- ${warning}`).join("\n")}`;
43546
43535
  return `${content}${warningBlock}`;
43547
43536
  }
43548
- var buildParallelMessageMetadata, filterMessagesForParallelBranch, buildDesktopRuntimeToolMessagesForUi, extractDesktopRuntimeToolCallsForUi, shouldUseDesktopLocalRuntime, resolveWebAgentRuntimeToolSurface, formatMachineAgentRunError, normalizeThreadMetadataPatch, patchDialogThreadMetadata, patchDialogActiveAgent, QUICK_CHAT_AGENT_CONFIG_READ_TIMEOUT_MS, QUICK_CHAT_DYNAMIC_CONTEXT_TIMEOUT_MS, EMPTY_DYNAMIC_CONTEXTS, logQuickChatPerfStage4, readAgentConfigForTurn, buildDynamicContextsForTurn, finalizeQuickChatAgentTurnFailure, normalizeAgentRunUserInput, isSimpleTextInput, canUseQuickChatEmptyDynamicContexts, QUICK_CHAT_DIRECT_ANSWER_PATTERN, QUICK_CHAT_TOOL_INTENT_PATTERN, shouldDisableQuickChatToolsForDirectAnswer, classifyQuickChatAccessError, isUsableAgentConfig, extractAgentRunUserText, hasAgentRunUserInputContent, setLoopStopReason2, streamAgentChatTurnHandler;
43537
+ var buildParallelMessageMetadata, filterMessagesForParallelBranch, buildDesktopRuntimeToolMessagesForUi, extractDesktopRuntimeToolCallsForUi, shouldUseDesktopLocalRuntime, readCurrentDesktopMachineId, resolveRemoteBoundMachineId, resolveWebAgentRuntimeToolSurface, formatMachineAgentRunError, normalizeThreadMetadataPatch, patchDialogThreadMetadata, patchDialogActiveAgent, QUICK_CHAT_AGENT_CONFIG_READ_TIMEOUT_MS, QUICK_CHAT_DYNAMIC_CONTEXT_TIMEOUT_MS, EMPTY_DYNAMIC_CONTEXTS, logQuickChatPerfStage4, readAgentConfigForTurn, buildDynamicContextsForTurn, finalizeQuickChatAgentTurnFailure, normalizeAgentRunUserInput, isSimpleTextInput, canUseQuickChatEmptyDynamicContexts, QUICK_CHAT_DIRECT_ANSWER_PATTERN, QUICK_CHAT_TOOL_INTENT_PATTERN, shouldDisableQuickChatToolsForDirectAnswer, classifyQuickChatAccessError, isUsableAgentConfig, extractAgentRunUserText, hasAgentRunUserInputContent, setLoopStopReason2, streamAgentChatTurnHandler;
43549
43538
  var init_streamAgentChatTurn = __esm({
43550
43539
  "packages/ai/agent/streamAgentChatTurn.ts"() {
43551
43540
  "use strict";
@@ -43675,6 +43664,18 @@ var init_streamAgentChatTurn = __esm({
43675
43664
  if (!getIsDesktopApp()) return false;
43676
43665
  return agentConfig?.apiSource !== "cli";
43677
43666
  };
43667
+ readCurrentDesktopMachineId = () => {
43668
+ const fromProcess = typeof process !== "undefined" ? (process.env?.NOLO_CURRENT_MACHINE_ID || process.env?.NOLO_MACHINE_ID || "").trim() : "";
43669
+ if (fromProcess) return fromProcess;
43670
+ const w = typeof globalThis !== "undefined" && globalThis.window ? globalThis.window : null;
43671
+ const fromWindow = typeof w?.__NOLO_CURRENT_MACHINE_ID__ === "string" ? w.__NOLO_CURRENT_MACHINE_ID__.trim() : typeof w?.__NOLO_MACHINE_ID__ === "string" ? w.__NOLO_MACHINE_ID__.trim() : "";
43672
+ return fromWindow;
43673
+ };
43674
+ resolveRemoteBoundMachineId = (machineId) => {
43675
+ if (!machineId || !getIsDesktopApp()) return machineId;
43676
+ const currentMachineId = readCurrentDesktopMachineId();
43677
+ return currentMachineId && currentMachineId === machineId ? "" : machineId;
43678
+ };
43678
43679
  resolveWebAgentRuntimeToolSurface = (agentConfig, state) => {
43679
43680
  const toolSurface = resolveRuntimeToolSurfaceForAgent({
43680
43681
  explicitToolNames: Array.isArray(agentConfig.tools) ? agentConfig.tools : [],
@@ -43999,7 +44000,8 @@ var init_streamAgentChatTurn = __esm({
43999
44000
  apiSource: agentConfig.apiSource,
44000
44001
  source: cachedAgentConfig === rawAgentConfig ? "cache" : "read"
44001
44002
  });
44002
- const boundMachineId = typeof agentConfig.runtimeBinding?.machineId === "string" ? agentConfig.runtimeBinding.machineId.trim() : "";
44003
+ const configuredBoundMachineId = typeof agentConfig.runtimeBinding?.machineId === "string" ? agentConfig.runtimeBinding.machineId.trim() : "";
44004
+ const boundMachineId = resolveRemoteBoundMachineId(configuredBoundMachineId);
44003
44005
  if (agentConfig.apiSource === "cli" || boundMachineId && !getIsDesktopApp()) {
44004
44006
  console.info("[streamAgentChatTurn] Triggered CLI/machine route. apiSource:", agentConfig.apiSource, "boundMachineId:", boundMachineId, "agentKey:", agentKey);
44005
44007
  const currentState = getState();
@@ -64419,6 +64421,9 @@ function createCliLocalRuntimeAdapter(deps) {
64419
64421
  raw: result.raw
64420
64422
  };
64421
64423
  } catch (error) {
64424
+ if (error instanceof CliProviderQuotaError) {
64425
+ throw error;
64426
+ }
64422
64427
  const message = error instanceof Error ? error.message : String(error);
64423
64428
  throw new Error(
64424
64429
  `Local CLI provider "${provider}" is unavailable or failed: ${message}`
@@ -65989,8 +65994,8 @@ var init_localDialogRead = __esm({
65989
65994
  });
65990
65995
 
65991
65996
  // packages/cli/index.ts
65992
- import { dirname as dirname8, join as join12 } from "node:path";
65993
- import { fileURLToPath as fileURLToPath5 } from "node:url";
65997
+ import { dirname as dirname9, join as join13 } from "node:path";
65998
+ import { fileURLToPath as fileURLToPath6 } from "node:url";
65994
65999
 
65995
66000
  // packages/cli/cliCommandDispatch.ts
65996
66001
  import { fileURLToPath } from "node:url";
@@ -66155,17 +66160,6 @@ function parseIsoTimestampOption(raw, flag) {
66155
66160
  }
66156
66161
  return new Date(time).toISOString();
66157
66162
  }
66158
- function buildUsageProbeConfig(kind) {
66159
- if (!kind) return void 0;
66160
- if (kind !== "qoder-local-quota-log") {
66161
- throw new Error("--usage-probe currently supports qoder-local-quota-log.");
66162
- }
66163
- return {
66164
- kind,
66165
- command: "nolo agent usage qoder",
66166
- capability: "qoder-usage"
66167
- };
66168
- }
66169
66163
  async function curlFetch(url, init) {
66170
66164
  const method = init?.method ?? "GET";
66171
66165
  const headers = new Headers(init?.headers ?? {});
@@ -66422,7 +66416,6 @@ function parseAgentUpdateArgs(args2) {
66422
66416
  "--max-concurrent"
66423
66417
  );
66424
66418
  const expiresAt = parseIsoTimestampOption(readOption2(args2, "--expires-at"), "--expires-at");
66425
- const usageProbe = buildUsageProbeConfig(readOption2(args2, "--usage-probe"));
66426
66419
  const handle = readOption2(args2, "--handle")?.trim();
66427
66420
  const promptSources = [prompt, promptFile, promptDoc].filter(Boolean);
66428
66421
  if (promptSources.length > 1) {
@@ -66439,11 +66432,8 @@ function parseAgentUpdateArgs(args2) {
66439
66432
  if (customProviderUrl) updates.customProviderUrl = customProviderUrl;
66440
66433
  if (apiKey) updates.apiKey = apiKey;
66441
66434
  if (maxConcurrent != null) updates.admission = { maxConcurrent };
66442
- if (expiresAt || usageProbe) {
66443
- updates.scheduling = {
66444
- ...expiresAt ? { expiresAt } : {},
66445
- ...usageProbe ? { usageProbe } : {}
66446
- };
66435
+ if (expiresAt) {
66436
+ updates.scheduling = { expiresAt };
66447
66437
  }
66448
66438
  if (handle) updates.handle = handle;
66449
66439
  for (const entry of readRepeatedOption(args2, "--field")) {
@@ -67582,7 +67572,7 @@ async function runAgentUpdateCommand(args2, deps = {}) {
67582
67572
  }
67583
67573
  if (!parsed) {
67584
67574
  output2.write(
67585
- "Usage: nolo agent update <agent> [--model <id>] [--cli-provider <provider>] [--api-source <source>] [--max-concurrent <n>] [--expires-at <iso>] [--usage-probe qoder-local-quota-log] [--prompt <text> | --prompt-file <path> | --prompt-doc <pageKey>] [--tools <json>] [--copy-provider-from <agent>] [--field key=value]\n".replace("[--field key=value]", "[--handle <name>] [--field key=value]")
67575
+ "Usage: nolo agent update <agent> [--model <id>] [--cli-provider <provider>] [--api-source <source>] [--max-concurrent <n>] [--expires-at <iso>] [--prompt <text> | --prompt-file <path> | --prompt-doc <pageKey>] [--tools <json>] [--copy-provider-from <agent>] [--field key=value]\n".replace("[--field key=value]", "[--handle <name>] [--field key=value]")
67586
67576
  );
67587
67577
  return args2[0] ? 0 : 1;
67588
67578
  }
@@ -67654,7 +67644,7 @@ async function runAgentCreateCommand(args2, deps = {}) {
67654
67644
  }
67655
67645
  if (!parsed) {
67656
67646
  output2.write(
67657
- "Usage: nolo agent create <agent> [--model <id>] [--cli-provider <provider>] [--api-source <source>] [--max-concurrent <n>] [--expires-at <iso>] [--usage-probe qoder-local-quota-log] [--prompt <text> | --prompt-file <path> | --prompt-doc <pageKey>] [--tools <json>] [--copy-provider-from <agent>] [--name <name>] [--custom-provider-url <url>] [--provider-api-key <key>] [--field key=value]\n".replace("[--field key=value]", "[--handle <name>] [--field key=value]")
67647
+ "Usage: nolo agent create <agent> [--model <id>] [--cli-provider <provider>] [--api-source <source>] [--max-concurrent <n>] [--expires-at <iso>] [--prompt <text> | --prompt-file <path> | --prompt-doc <pageKey>] [--tools <json>] [--copy-provider-from <agent>] [--name <name>] [--custom-provider-url <url>] [--provider-api-key <key>] [--field key=value]\n".replace("[--field key=value]", "[--handle <name>] [--field key=value]")
67658
67648
  );
67659
67649
  return args2[0] ? 0 : 1;
67660
67650
  }
@@ -67858,6 +67848,23 @@ function isCliProviderAgentConfig(agentConfig) {
67858
67848
  const provider = typeof agentConfig?.provider === "string" ? agentConfig.provider.trim() : "";
67859
67849
  return Boolean(cliProvider) || provider === "agy" || provider === "codex" || provider === "claude";
67860
67850
  }
67851
+ function resolveBoundMachineId(agentConfig) {
67852
+ return agentConfig?.runtimeBinding && typeof agentConfig.runtimeBinding === "object" ? String(agentConfig.runtimeBinding.machineId ?? "").trim() : "";
67853
+ }
67854
+ async function detectCurrentMachineId(env) {
67855
+ const fromEnv = (env.NOLO_CURRENT_MACHINE_ID || env.NOLO_MACHINE_ID || "").trim();
67856
+ if (fromEnv) return fromEnv;
67857
+ try {
67858
+ const { detectMachineInfo: detectMachineInfo2 } = await Promise.resolve().then(() => (init_machineInfo(), machineInfo_exports));
67859
+ const machine = await detectMachineInfo2({ probeLaunchable: true });
67860
+ return typeof machine?.machineId === "string" && machine.machineId.trim() ? machine.machineId.trim() : void 0;
67861
+ } catch {
67862
+ return void 0;
67863
+ }
67864
+ }
67865
+ async function resolveCurrentMachineId(options) {
67866
+ return options.currentMachineIdResolver ? options.currentMachineIdResolver(options.env) : detectCurrentMachineId(options.env);
67867
+ }
67861
67868
  function resolveAuthToken5(env) {
67862
67869
  return env.AUTH_TOKEN || env.AUTH || env.BENCHMARK_AUTH_TOKEN || "";
67863
67870
  }
@@ -67902,7 +67909,16 @@ async function shouldSkipAutoLocalForServerPlatformTools(options) {
67902
67909
  }
67903
67910
  return false;
67904
67911
  }
67905
- if (isCliProviderAgentConfig(agentConfig)) return false;
67912
+ if (isCliProviderAgentConfig(agentConfig)) {
67913
+ const boundMachineId = resolveBoundMachineId(agentConfig);
67914
+ if (!boundMachineId) return false;
67915
+ const currentMachineId = (await resolveCurrentMachineId(options))?.trim() || "";
67916
+ if (currentMachineId && currentMachineId === boundMachineId) return false;
67917
+ options.output.write(
67918
+ `[nolo] auto runtime: skipping local runtime because ${options.agentKey} is bound to ${boundMachineId}` + (currentMachineId ? ` and this machine is ${currentMachineId}.` : ".") + " Use --local explicitly to force the current machine.\n"
67919
+ );
67920
+ return true;
67921
+ }
67906
67922
  if (knownServerPlatformAgent) {
67907
67923
  options.output.write(
67908
67924
  `[nolo] auto runtime: skipping local runtime because ${options.agentKey} is a known platform agent. Use --local explicitly to force local workspace tools.
@@ -68023,6 +68039,9 @@ function shouldAttemptAutoLocal(options) {
68023
68039
  if (options.env.NOLO_DISABLE_CLI_WORKSPACE_TOOLS !== "1" && isBuiltinNoloAgentRef(options.agentKey) && resolveAuthToken5(options.env)) {
68024
68040
  return true;
68025
68041
  }
68042
+ if (options.env.NOLO_DISABLE_CLI_WORKSPACE_TOOLS !== "1" && resolveAuthToken5(options.env) && !isKnownServerPlatformAgent(options)) {
68043
+ return true;
68044
+ }
68026
68045
  return Boolean(
68027
68046
  options.env.NOLO_LOCAL_OPENAI_API_KEY || options.env.OPENAI_API_KEY || options.env.NOLO_LOCAL_OPENAI_BASE_URL || options.env.OPENAI_BASE_URL || options.env.NOLO_LOCAL_AGENT_KEY
68028
68047
  );
@@ -71467,7 +71486,6 @@ function getSpaceInternalCommandEntries() {
71467
71486
  // packages/cli/authCommands.ts
71468
71487
  import { createInterface } from "node:readline/promises";
71469
71488
  import { stdin as input, stdout as output } from "node:process";
71470
- import { rmSync as rmSync2 } from "node:fs";
71471
71489
  import { spawn as spawn5 } from "node:child_process";
71472
71490
 
71473
71491
  // packages/cli/client/profileConfig.ts
@@ -71502,16 +71520,31 @@ function loadProfileConfig(path7 = getDefaultProfileConfigPath()) {
71502
71520
  }
71503
71521
  return parsed;
71504
71522
  }
71523
+ function clearProfileAuthToken(path7 = getDefaultProfileConfigPath()) {
71524
+ const config = loadProfileConfig(path7);
71525
+ if (!config) return false;
71526
+ const profile = config.profiles[config.currentProfile];
71527
+ if (!profile?.authToken?.trim()) return false;
71528
+ delete profile.authToken;
71529
+ mkdirSync5(dirname6(path7), { recursive: true });
71530
+ writeFileSync4(path7, `${JSON.stringify(config, null, 2)}
71531
+ `, "utf8");
71532
+ return true;
71533
+ }
71505
71534
  function saveDefaultProfile(path7, profile) {
71535
+ const existing = loadProfileConfig(path7);
71536
+ const mergedDefault = {
71537
+ ...existing?.profiles?.default ?? {},
71538
+ serverUrl: normalizeProfileServerUrl(profile.serverUrl),
71539
+ authToken: profile.authToken.trim()
71540
+ };
71506
71541
  const config = {
71507
71542
  currentProfile: "default",
71508
71543
  profiles: {
71509
- default: profile
71544
+ ...existing?.profiles ?? {},
71545
+ default: mergedDefault
71510
71546
  }
71511
71547
  };
71512
- config.profiles.default.serverUrl = normalizeProfileServerUrl(
71513
- config.profiles.default.serverUrl
71514
- );
71515
71548
  mkdirSync5(dirname6(path7), { recursive: true });
71516
71549
  writeFileSync4(path7, `${JSON.stringify(config, null, 2)}
71517
71550
  `, "utf8");
@@ -71524,7 +71557,7 @@ function buildEnvFromProfile(config) {
71524
71557
  return {
71525
71558
  NOLO_PROFILE: config.currentProfile,
71526
71559
  NOLO_SERVER: profile.serverUrl,
71527
- AUTH_TOKEN: profile.authToken,
71560
+ ...profile.authToken?.trim() ? { AUTH_TOKEN: profile.authToken.trim() } : {},
71528
71561
  ...profile.agentKey ? { NOLO_AGENT: profile.agentKey } : {},
71529
71562
  ...profile.agentName ? { NOLO_AGENT_NAME: profile.agentName } : {}
71530
71563
  };
@@ -71547,7 +71580,51 @@ function getCurrentProfile(config) {
71547
71580
  }
71548
71581
 
71549
71582
  // packages/cli/authCommands.ts
71583
+ init_cliEnvHelpers();
71550
71584
  init_defaultServer();
71585
+ var LOGIN_HELP_TEXT = `Log in to Nolo and save a local profile.
71586
+
71587
+ Usage:
71588
+ nolo login [--server <url>] [--no-browser] [--token <jwt>] [--manual]
71589
+
71590
+ Options:
71591
+ --server <url> Nolo server URL (default: ${DEFAULT_NOLO_SERVER_URL})
71592
+ --no-browser Print the authorization URL instead of opening a browser
71593
+ --token <jwt> Save a token directly without browser authorization
71594
+ --manual Prompt to paste a token interactively
71595
+
71596
+ By default, opens the Nolo website and polls until authorization completes.
71597
+ In SSH sessions, use --no-browser and open the printed URL on a machine with a browser
71598
+ where you are already logged into Nolo.
71599
+ `;
71600
+ var LOGOUT_HELP_TEXT = `Log out of Nolo by clearing the saved auth token.
71601
+
71602
+ Usage:
71603
+ nolo logout
71604
+
71605
+ Keeps other profile settings such as server URL and default agent preferences.
71606
+ Does not unset AUTH_TOKEN or other auth-related environment variables.
71607
+ `;
71608
+ var WHOAMI_HELP_TEXT = `Show the current login state.
71609
+
71610
+ Usage:
71611
+ nolo whoami
71612
+ `;
71613
+ function wantsHelp(args2) {
71614
+ return args2.includes("--help") || args2.includes("-h");
71615
+ }
71616
+ function formatDuration(ms) {
71617
+ const totalSec = Math.max(0, Math.ceil(ms / 1e3));
71618
+ const minutes = Math.floor(totalSec / 60);
71619
+ const seconds = totalSec % 60;
71620
+ if (minutes > 0) return `${minutes}m ${seconds}s`;
71621
+ return `${seconds}s`;
71622
+ }
71623
+ function formatTokenPreview(token) {
71624
+ const trimmed = token.trim();
71625
+ if (!trimmed) return "";
71626
+ return `${trimmed.slice(0, 8)}...`;
71627
+ }
71551
71628
  function getArg(args2, flag) {
71552
71629
  const index = args2.indexOf(flag);
71553
71630
  return index >= 0 ? args2[index + 1] : void 0;
@@ -71609,6 +71686,11 @@ async function runWebLogin(args2) {
71609
71686
  const intervalMs = Math.max(1, Number(start.interval) || 2) * 1e3;
71610
71687
  const timeoutMs = Math.max(1, Number(start.expiresIn) || 600) * 1e3;
71611
71688
  const deadline = args2.now() + timeoutMs;
71689
+ const statusLogIntervalMs = 15e3;
71690
+ let lastStatusLogAt = 0;
71691
+ args2.output.log(
71692
+ `[nolo] Waiting for browser authorization (${formatDuration(timeoutMs)} remaining)...`
71693
+ );
71612
71694
  while (args2.now() <= deadline) {
71613
71695
  const pollResponse = await postJson(
71614
71696
  args2.fetchImpl,
@@ -71617,6 +71699,16 @@ async function runWebLogin(args2) {
71617
71699
  );
71618
71700
  const poll = await pollResponse.json().catch(() => ({}));
71619
71701
  if (pollResponse.status === 202) {
71702
+ const currentTime = args2.now();
71703
+ if (lastStatusLogAt > 0 && currentTime - lastStatusLogAt >= statusLogIntervalMs) {
71704
+ const remainingMs = Math.max(0, deadline - currentTime);
71705
+ args2.output.log(
71706
+ `[nolo] Still waiting... (${formatDuration(remainingMs)} remaining)`
71707
+ );
71708
+ lastStatusLogAt = currentTime;
71709
+ } else if (lastStatusLogAt === 0) {
71710
+ lastStatusLogAt = currentTime;
71711
+ }
71620
71712
  await args2.sleep(intervalMs);
71621
71713
  continue;
71622
71714
  }
@@ -71639,12 +71731,16 @@ async function runWebLogin(args2) {
71639
71731
  return 1;
71640
71732
  }
71641
71733
  async function runLoginCommand(args2, deps = {}) {
71734
+ const outputTarget = deps.output ?? console;
71735
+ const errorTarget = deps.error ?? console;
71736
+ if (wantsHelp(args2)) {
71737
+ outputTarget.log(LOGIN_HELP_TEXT);
71738
+ return 0;
71739
+ }
71642
71740
  const configPath = deps.configPath ?? getDefaultProfileConfigPath();
71643
71741
  const serverArg = getArg(args2, "--server");
71644
71742
  const tokenArg = getArg(args2, "--token");
71645
71743
  const noBrowser = args2.includes("--no-browser");
71646
- const outputTarget = deps.output ?? console;
71647
- const errorTarget = deps.error ?? console;
71648
71744
  const serverUrl = (serverArg || DEFAULT_NOLO_SERVER_URL).replace(/\/+$/, "");
71649
71745
  if (tokenArg) {
71650
71746
  return saveTokenLogin({
@@ -71684,33 +71780,68 @@ async function runLoginCommand(args2, deps = {}) {
71684
71780
  });
71685
71781
  }
71686
71782
  function runWhoamiCommand(deps = {}) {
71687
- const env = deps.env ?? process.env;
71688
71783
  const output2 = deps.output ?? console;
71784
+ if (wantsHelp(deps.args ?? [])) {
71785
+ output2.log(WHOAMI_HELP_TEXT);
71786
+ return 0;
71787
+ }
71788
+ const env = deps.env ?? process.env;
71689
71789
  const config = loadProfileConfig(deps.configPath);
71690
71790
  const profile = getCurrentProfile(config);
71691
- if (!config || !profile) {
71791
+ const profileToken = profile?.authToken?.trim() ?? "";
71792
+ const envToken = resolveAuthTokenFromEnv(env);
71793
+ if (!profileToken && !envToken) {
71692
71794
  output2.log("Not logged in. Run: nolo login");
71693
71795
  return 1;
71694
71796
  }
71695
71797
  const runtimeEnv2 = buildCliRuntimeEnv(env, config);
71696
- const effectiveServer = runtimeEnv2.NOLO_SERVER ?? profile.serverUrl;
71697
71798
  const explicitServer = env.NOLO_SERVER || env.NOLO_SERVER_URL || env.BASE_URL;
71799
+ if (!profileToken && envToken) {
71800
+ output2.log("profile: not logged in (no saved token)");
71801
+ if (profile?.serverUrl) {
71802
+ output2.log(`profile server: ${profile.serverUrl}`);
71803
+ }
71804
+ output2.log(`effective server: ${runtimeEnv2.NOLO_SERVER ?? resolveServerUrlFallback(profile)}`);
71805
+ output2.log(`server source: ${explicitServer ? "env" : profile?.serverUrl ? "profile" : "default"}`);
71806
+ output2.log(`env token: ${formatTokenPreview(envToken)} (source: environment)`);
71807
+ return 0;
71808
+ }
71809
+ const effectiveServer = runtimeEnv2.NOLO_SERVER ?? profile.serverUrl;
71698
71810
  output2.log(`profile: ${config.currentProfile}`);
71699
71811
  output2.log(`profile server: ${profile.serverUrl}`);
71700
71812
  output2.log(`effective server: ${effectiveServer}`);
71701
71813
  output2.log(`server source: ${explicitServer ? "env" : "profile"}`);
71702
- output2.log(`token: ${profile.authToken.slice(0, 8)}...`);
71814
+ output2.log(`token: ${formatTokenPreview(profileToken)} (source: profile)`);
71815
+ if (envToken && envToken !== profileToken) {
71816
+ output2.log(`env token: ${formatTokenPreview(envToken)} (source: environment, unused while profile token is set)`);
71817
+ }
71703
71818
  return 0;
71704
71819
  }
71705
- function runLogoutCommand() {
71706
- const configPath = getDefaultProfileConfigPath();
71707
- rmSync2(configPath, { force: true });
71708
- console.log("Logged out.");
71820
+ function resolveServerUrlFallback(profile) {
71821
+ return profile?.serverUrl ?? DEFAULT_NOLO_SERVER_URL;
71822
+ }
71823
+ function runLogoutCommand(deps = {}) {
71824
+ const output2 = deps.output ?? console;
71825
+ if (wantsHelp(deps.args ?? [])) {
71826
+ output2.log(LOGOUT_HELP_TEXT);
71827
+ return 0;
71828
+ }
71829
+ const env = deps.env ?? process.env;
71830
+ const configPath = deps.configPath ?? getDefaultProfileConfigPath();
71831
+ if (!clearProfileAuthToken(configPath)) {
71832
+ output2.log("Not logged in.");
71833
+ return 0;
71834
+ }
71835
+ output2.log("Logged out.");
71836
+ if (resolveAuthTokenFromEnv(env)) {
71837
+ output2.log(
71838
+ "Note: AUTH_TOKEN in the environment is unchanged and may still authenticate commands."
71839
+ );
71840
+ }
71709
71841
  return 0;
71710
71842
  }
71711
71843
 
71712
71844
  // packages/cli/systemInternalCommandEntries.ts
71713
- init_defaultServer();
71714
71845
  init_machineCommands();
71715
71846
 
71716
71847
  // packages/cli/runtimeDoctorCommands.ts
@@ -71871,15 +72002,352 @@ async function runDoctorRuntimeCommand(args2, deps = {}) {
71871
72002
  return decision.runnable ? 0 : 1;
71872
72003
  }
71873
72004
 
71874
- // packages/cli/updateCommands.ts
72005
+ // packages/cli/standaloneBundle.ts
71875
72006
  init_processSpawn();
71876
- import { readFileSync as readFileSync8 } from "node:fs";
72007
+ import { createHash as createHash3 } from "node:crypto";
72008
+ import {
72009
+ cpSync,
72010
+ existsSync as existsSync9,
72011
+ mkdirSync as mkdirSync6,
72012
+ readFileSync as readFileSync8,
72013
+ readdirSync as readdirSync3,
72014
+ renameSync,
72015
+ rmSync as rmSync2,
72016
+ statSync as statSync2,
72017
+ writeFileSync as writeFileSync5
72018
+ } from "node:fs";
72019
+ import { tmpdir as tmpdir2 } from "node:os";
71877
72020
  import { dirname as dirname7, join as join10 } from "node:path";
71878
72021
  import { fileURLToPath as fileURLToPath4 } from "node:url";
71879
- var CLI_DIR2 = dirname7(fileURLToPath4(import.meta.url));
71880
- var PACKAGE_JSON_PATH = join10(CLI_DIR2, "package.json");
72022
+ var CLI_DOWNLOADS_SUBPATH = "cli";
72023
+ function getCliInstallChannel(serverUrl) {
72024
+ const normalized = typeof serverUrl === "string" ? serverUrl.trim().replace(/\/+$/, "") : "";
72025
+ if (!normalized) {
72026
+ return "latest";
72027
+ }
72028
+ try {
72029
+ const hostname2 = new URL(normalized).hostname.toLowerCase();
72030
+ if (hostname2 === "us.nolo.chat" || hostname2.endsWith(".us.nolo.chat")) {
72031
+ return "alpha";
72032
+ }
72033
+ } catch {
72034
+ if (/us\.nolo\.chat/i.test(normalized)) {
72035
+ return "alpha";
72036
+ }
72037
+ }
72038
+ return "latest";
72039
+ }
72040
+ function resolveBundleUpdateChannel(args2) {
72041
+ const fromServer = getCliInstallChannel(args2.serverUrl);
72042
+ const fromInstall = args2.install.manifest.channel;
72043
+ if (fromInstall && fromInstall !== fromServer) {
72044
+ args2.output?.write(
72045
+ `[nolo] Warning: server channel (${fromServer}) differs from installed bundle channel (${fromInstall}); using installed channel.
72046
+ `
72047
+ );
72048
+ return fromInstall;
72049
+ }
72050
+ return fromServer;
72051
+ }
72052
+ function resolveCliBundlePlatform() {
72053
+ const { platform: platform2, arch: arch2 } = process;
72054
+ if (platform2 === "linux" && (arch2 === "x64" || arch2 === "amd64")) {
72055
+ return "linux-x64";
72056
+ }
72057
+ if (platform2 === "darwin" && arch2 === "arm64") {
72058
+ return "darwin-arm64";
72059
+ }
72060
+ if (platform2 === "darwin" && (arch2 === "x64" || arch2 === "amd64")) {
72061
+ return "darwin-x64";
72062
+ }
72063
+ if (platform2 === "win32" && (arch2 === "x64" || arch2 === "amd64")) {
72064
+ return "win-x64";
72065
+ }
72066
+ return null;
72067
+ }
72068
+ function detectStandaloneBundleInstall(entrypointPath) {
72069
+ const cliDir = entrypointPath ? entrypointPath.startsWith("file:") ? dirname7(fileURLToPath4(entrypointPath)) : dirname7(entrypointPath) : dirname7(fileURLToPath4(import.meta.url));
72070
+ const bundleRoot = join10(cliDir, "..", "..");
72071
+ const manifestPath = join10(bundleRoot, "manifest.json");
72072
+ if (!existsSync9(manifestPath)) {
72073
+ return null;
72074
+ }
72075
+ try {
72076
+ const manifest = JSON.parse(
72077
+ readFileSync8(manifestPath, "utf8")
72078
+ );
72079
+ if (manifest?.name !== "nolo-cli" || manifest?.schemaVersion !== 1) {
72080
+ return null;
72081
+ }
72082
+ const entrypoint = join10(cliDir, "index.js");
72083
+ if (!existsSync9(entrypoint)) {
72084
+ return null;
72085
+ }
72086
+ return { bundleRoot, cliDir, manifest };
72087
+ } catch {
72088
+ return null;
72089
+ }
72090
+ }
72091
+ function buildBundleManifestUrl(args2) {
72092
+ const origin = args2.serverUrl.trim().replace(/\/+$/, "");
72093
+ return `${origin}/public/downloads/${CLI_DOWNLOADS_SUBPATH}/nolo-cli-${args2.channel}-${args2.platform}-manifest.json`;
72094
+ }
72095
+ function buildNpmSelfUpdateCommand(channel = "latest") {
72096
+ return ["npm", "install", "-g", `nolo-cli@${channel}`, "--force"];
72097
+ }
72098
+ function validatePublishedBundleManifest(args2) {
72099
+ if (args2.published.schemaVersion !== 1) {
72100
+ throw new Error(
72101
+ `Unsupported standalone bundle manifest schema: ${args2.published.schemaVersion}`
72102
+ );
72103
+ }
72104
+ if (args2.published.channel !== args2.expectedChannel) {
72105
+ throw new Error(
72106
+ `Standalone bundle manifest channel mismatch (expected ${args2.expectedChannel}, got ${args2.published.channel})`
72107
+ );
72108
+ }
72109
+ if (args2.published.platform !== args2.expectedPlatform) {
72110
+ throw new Error(
72111
+ `Standalone bundle manifest platform mismatch (expected ${args2.expectedPlatform}, got ${args2.published.platform})`
72112
+ );
72113
+ }
72114
+ if (!args2.published.fileName || !args2.published.url || !args2.published.sha256) {
72115
+ throw new Error("Standalone bundle manifest is missing required fields");
72116
+ }
72117
+ }
72118
+ async function runCommand(command2, spawn6 = resolveDefaultSpawn(), env = process.env) {
72119
+ const proc = spawn6({
72120
+ cmd: command2,
72121
+ stdin: "ignore",
72122
+ stdout: "inherit",
72123
+ stderr: "inherit",
72124
+ env
72125
+ });
72126
+ return proc.exited;
72127
+ }
72128
+ function hashFile(path7) {
72129
+ const hash = createHash3("sha256");
72130
+ hash.update(readFileSync8(path7));
72131
+ return hash.digest("hex");
72132
+ }
72133
+ function fileSize(path7) {
72134
+ return statSync2(path7).size;
72135
+ }
72136
+ async function downloadFile(url, destinationPath) {
72137
+ const response = await fetch(url);
72138
+ if (!response.ok) {
72139
+ throw new Error(`Download failed (${response.status}): ${url}`);
72140
+ }
72141
+ const bytes = await response.arrayBuffer();
72142
+ mkdirSync6(dirname7(destinationPath), { recursive: true });
72143
+ writeFileSync5(destinationPath, Buffer.from(bytes));
72144
+ }
72145
+ function assertCliDir(cliDir) {
72146
+ const entrypoint = join10(cliDir, "index.js");
72147
+ if (!existsSync9(entrypoint)) {
72148
+ throw new Error(`Standalone CLI layout is invalid: missing ${entrypoint}`);
72149
+ }
72150
+ }
72151
+ async function extractArchive(args2) {
72152
+ mkdirSync6(args2.destDir, { recursive: true });
72153
+ const spawn6 = args2.spawn ?? resolveDefaultSpawn();
72154
+ const env = args2.env ?? process.env;
72155
+ if (args2.archivePath.endsWith(".zip")) {
72156
+ if (process.platform === "win32") {
72157
+ const command2 = [
72158
+ "powershell",
72159
+ "-NoProfile",
72160
+ "-Command",
72161
+ `Expand-Archive -Path '${args2.archivePath.replace(/'/g, "''")}' -DestinationPath '${args2.destDir.replace(/'/g, "''")}' -Force`
72162
+ ];
72163
+ return runCommand(command2, spawn6, env);
72164
+ }
72165
+ return runCommand(["unzip", "-qo", args2.archivePath, "-d", args2.destDir], spawn6, env);
72166
+ }
72167
+ return runCommand(["tar", "--zstd", "-xf", args2.archivePath, "-C", args2.destDir], spawn6, env);
72168
+ }
72169
+ function findExtractedBundleRoot(extractDir) {
72170
+ const matches = readdirSync3(extractDir, { withFileTypes: true }).filter((entry) => entry.isDirectory() && entry.name.startsWith("nolo-cli-")).map((entry) => join10(extractDir, entry.name));
72171
+ if (matches.length === 1) {
72172
+ return matches[0];
72173
+ }
72174
+ throw new Error(
72175
+ `Could not locate extracted standalone CLI bundle under ${extractDir}`
72176
+ );
72177
+ }
72178
+ function atomicReplaceDirectory(args2) {
72179
+ assertCliDir(args2.sourceDir);
72180
+ const parent = dirname7(args2.targetDir);
72181
+ mkdirSync6(parent, { recursive: true });
72182
+ const stagingDir = `${args2.targetDir}.staging-${process.pid}`;
72183
+ const backupDir = `${args2.targetDir}.backup-${process.pid}`;
72184
+ rmSync2(stagingDir, { recursive: true, force: true });
72185
+ cpSync(args2.sourceDir, stagingDir, { recursive: true });
72186
+ assertCliDir(stagingDir);
72187
+ if (existsSync9(args2.targetDir)) {
72188
+ rmSync2(backupDir, { recursive: true, force: true });
72189
+ renameSync(args2.targetDir, backupDir);
72190
+ }
72191
+ try {
72192
+ renameSync(stagingDir, args2.targetDir);
72193
+ } catch (error) {
72194
+ if (existsSync9(backupDir) && !existsSync9(args2.targetDir)) {
72195
+ renameSync(backupDir, args2.targetDir);
72196
+ }
72197
+ throw error;
72198
+ }
72199
+ rmSync2(backupDir, { recursive: true, force: true });
72200
+ rmSync2(stagingDir, { recursive: true, force: true });
72201
+ }
72202
+ function replaceFileWithFallback(args2) {
72203
+ if (!existsSync9(args2.sourcePath)) {
72204
+ return;
72205
+ }
72206
+ mkdirSync6(dirname7(args2.targetPath), { recursive: true });
72207
+ const pendingPath = `${args2.targetPath}.pending-${process.pid}`;
72208
+ cpSync(args2.sourcePath, pendingPath);
72209
+ try {
72210
+ rmSync2(args2.targetPath, { force: true });
72211
+ renameSync(pendingPath, args2.targetPath);
72212
+ } catch (error) {
72213
+ rmSync2(pendingPath, { force: true });
72214
+ args2.output?.write(
72215
+ `[nolo] Warning: could not replace ${args2.targetPath} (${error instanceof Error ? error.message : String(error)}). Restart all nolo processes and run nolo update again.
72216
+ `
72217
+ );
72218
+ }
72219
+ }
72220
+ function replaceStandaloneBundleContents(args2) {
72221
+ const nextCliDir = join10(args2.nextRoot, "lib", "nolo-cli");
72222
+ const currentCliDir = join10(args2.currentRoot, "lib", "nolo-cli");
72223
+ if (!existsSync9(nextCliDir)) {
72224
+ throw new Error(`Downloaded bundle is missing ${nextCliDir}`);
72225
+ }
72226
+ atomicReplaceDirectory({
72227
+ targetDir: currentCliDir,
72228
+ sourceDir: nextCliDir
72229
+ });
72230
+ for (const relativePath of ["VERSION", "manifest.json"]) {
72231
+ const source = join10(args2.nextRoot, relativePath);
72232
+ if (existsSync9(source)) {
72233
+ replaceFileWithFallback({
72234
+ sourcePath: source,
72235
+ targetPath: join10(args2.currentRoot, relativePath),
72236
+ output: args2.output
72237
+ });
72238
+ }
72239
+ }
72240
+ const bunName = process.platform === "win32" ? "bun.exe" : "bun";
72241
+ replaceFileWithFallback({
72242
+ sourcePath: join10(args2.nextRoot, "bin", bunName),
72243
+ targetPath: join10(args2.currentRoot, "bin", bunName),
72244
+ output: args2.output
72245
+ });
72246
+ const launcherName = process.platform === "win32" ? "nolo.cmd" : "nolo";
72247
+ replaceFileWithFallback({
72248
+ sourcePath: join10(args2.nextRoot, "bin", launcherName),
72249
+ targetPath: join10(args2.currentRoot, "bin", launcherName),
72250
+ output: args2.output
72251
+ });
72252
+ }
72253
+ async function runStandaloneBundleUpdate(args2) {
72254
+ const output2 = args2.output ?? process.stdout;
72255
+ const env = args2.env ?? process.env;
72256
+ const platform2 = resolveCliBundlePlatform() ?? args2.install.manifest.platform ?? null;
72257
+ if (!platform2) {
72258
+ throw new Error(
72259
+ `Standalone CLI self-update is not supported on ${process.platform}/${process.arch}`
72260
+ );
72261
+ }
72262
+ const channel = resolveBundleUpdateChannel({
72263
+ install: args2.install,
72264
+ serverUrl: args2.serverUrl,
72265
+ output: output2
72266
+ });
72267
+ const manifestUrl = buildBundleManifestUrl({
72268
+ serverUrl: args2.serverUrl,
72269
+ channel,
72270
+ platform: platform2
72271
+ });
72272
+ output2.write(`Checking standalone bundle update: ${manifestUrl}
72273
+ `);
72274
+ const response = await fetch(manifestUrl, { cache: "no-store" });
72275
+ if (!response.ok) {
72276
+ throw new Error(
72277
+ `Standalone bundle manifest not found (${response.status}). Publish the CLI bundle for ${channel}/${platform2} first.`
72278
+ );
72279
+ }
72280
+ const published = await response.json();
72281
+ validatePublishedBundleManifest({
72282
+ published,
72283
+ expectedChannel: channel,
72284
+ expectedPlatform: platform2
72285
+ });
72286
+ const currentVersion = args2.install.manifest.version;
72287
+ if (published.version === currentVersion) {
72288
+ output2.write(`Already on latest standalone bundle (${currentVersion}).
72289
+ `);
72290
+ return 0;
72291
+ }
72292
+ const workDir = join10(tmpdir2(), `nolo-cli-update-${process.pid}`);
72293
+ rmSync2(workDir, { recursive: true, force: true });
72294
+ mkdirSync6(workDir, { recursive: true });
72295
+ try {
72296
+ const archivePath = join10(workDir, published.fileName);
72297
+ output2.write(
72298
+ `Updating standalone bundle ${currentVersion} -> ${published.version}
72299
+ `
72300
+ );
72301
+ output2.write(`Downloading ${published.url}
72302
+ `);
72303
+ await downloadFile(published.url, archivePath);
72304
+ const actualSize = fileSize(archivePath);
72305
+ if (actualSize !== published.size) {
72306
+ throw new Error(
72307
+ `Downloaded bundle size mismatch (expected ${published.size} bytes, got ${actualSize} bytes)`
72308
+ );
72309
+ }
72310
+ const actualSha256 = hashFile(archivePath);
72311
+ if (actualSha256 !== published.sha256) {
72312
+ throw new Error(
72313
+ `Downloaded bundle checksum mismatch (expected ${published.sha256}, got ${actualSha256})`
72314
+ );
72315
+ }
72316
+ const extractDir = join10(workDir, "extracted");
72317
+ const exitCode2 = await extractArchive({
72318
+ archivePath,
72319
+ destDir: extractDir,
72320
+ spawn: args2.spawn,
72321
+ env
72322
+ });
72323
+ if (exitCode2 !== 0) {
72324
+ throw new Error("Failed to extract standalone bundle archive");
72325
+ }
72326
+ const nextRoot = findExtractedBundleRoot(extractDir);
72327
+ replaceStandaloneBundleContents({
72328
+ currentRoot: args2.install.bundleRoot,
72329
+ nextRoot,
72330
+ output: output2
72331
+ });
72332
+ output2.write(`Standalone bundle updated to ${published.version}.
72333
+ `);
72334
+ output2.write("Restart open nolo sessions to use the new version.\n");
72335
+ return 0;
72336
+ } finally {
72337
+ rmSync2(workDir, { recursive: true, force: true });
72338
+ }
72339
+ }
72340
+
72341
+ // packages/cli/updateCommands.ts
72342
+ init_defaultServer();
72343
+ import { readFileSync as readFileSync9 } from "node:fs";
72344
+ import { dirname as dirname8, join as join11 } from "node:path";
72345
+ import { fileURLToPath as fileURLToPath5 } from "node:url";
72346
+ init_processSpawn();
72347
+ var CLI_DIR2 = dirname8(fileURLToPath5(import.meta.url));
72348
+ var PACKAGE_JSON_PATH = join11(CLI_DIR2, "package.json");
71881
72349
  function readPackageInfo() {
71882
- const raw = readFileSync8(PACKAGE_JSON_PATH, "utf8");
72350
+ const raw = readFileSync9(PACKAGE_JSON_PATH, "utf8");
71883
72351
  const parsed = JSON.parse(raw);
71884
72352
  return {
71885
72353
  name: parsed.name || "nolo-cli",
@@ -71889,28 +72357,42 @@ function readPackageInfo() {
71889
72357
  function buildCliVersionText(info) {
71890
72358
  return `${info.name} ${info.version}`;
71891
72359
  }
71892
- function buildSelfUpdateCommand() {
71893
- return ["npm", "install", "-g", "nolo-cli@latest", "--force"];
72360
+ function resolveSelfUpdateServerUrl(env = process.env, override) {
72361
+ if (override?.trim()) {
72362
+ return override.trim().replace(/\/+$/, "");
72363
+ }
72364
+ const fromEnv = env.NOLO_SERVER || env.BASE_URL;
72365
+ if (typeof fromEnv === "string" && fromEnv.trim()) {
72366
+ return fromEnv.trim().replace(/\/+$/, "");
72367
+ }
72368
+ const profile = loadProfileConfig();
72369
+ const profileUrl = profile?.profiles?.[profile.currentProfile]?.serverUrl;
72370
+ if (profileUrl?.trim()) {
72371
+ return profileUrl.trim().replace(/\/+$/, "");
72372
+ }
72373
+ return DEFAULT_NOLO_SERVER_URL;
71894
72374
  }
71895
72375
  function buildCliDoctorText(info) {
71896
- const updateCommand = buildSelfUpdateCommand().join(" ");
72376
+ const updateCommand = info.installKind === "standalone-bundle" ? "nolo update" : buildNpmSelfUpdateCommand(info.updateChannel).join(" ");
71897
72377
  return [
71898
72378
  "Nolo CLI doctor",
71899
72379
  "---------------",
71900
72380
  `version ${info.packageName} ${info.version}`,
72381
+ `install ${info.installKind}`,
72382
+ `channel ${info.updateChannel}`,
71901
72383
  `entry ${info.entrypoint}`,
71902
72384
  `server ${info.serverUrl}`,
71903
72385
  `profile ${info.profileName}`,
71904
72386
  `update nolo update`,
71905
72387
  "",
71906
72388
  "If direct `nolo` differs from repo-local `bun ./packages/cli/index.ts`,",
71907
- "the global npm install is older than this checkout.",
72389
+ "the global install is older than this checkout.",
71908
72390
  "",
71909
72391
  `Manual update: ${updateCommand}`
71910
72392
  ].join("\n");
71911
72393
  }
71912
72394
  function isRunSelfUpdateOptions(value) {
71913
- return typeof value === "object" && value !== null && ("output" in value || "spawn" in value);
72395
+ return typeof value === "object" && value !== null && ("output" in value || "spawn" in value || "entrypointPath" in value || "serverUrl" in value || "env" in value);
71914
72396
  }
71915
72397
  async function forwardSpawnOutput(stream, output2) {
71916
72398
  if (!stream) {
@@ -71933,7 +72415,20 @@ async function runSelfUpdate(outputOrOptions) {
71933
72415
  const options = outputOrOptions === void 0 ? {} : isRunSelfUpdateOptions(outputOrOptions) ? outputOrOptions : { output: outputOrOptions };
71934
72416
  const output2 = options.output ?? process.stdout;
71935
72417
  const spawn6 = options.spawn ?? resolveDefaultSpawn();
71936
- const command2 = buildSelfUpdateCommand();
72418
+ const env = options.env ?? process.env;
72419
+ const serverUrl = resolveSelfUpdateServerUrl(env, options.serverUrl);
72420
+ const entrypointPath = options.entrypointPath ?? join11(CLI_DIR2, "index.js");
72421
+ const bundleInstall = detectStandaloneBundleInstall(entrypointPath);
72422
+ if (bundleInstall) {
72423
+ return runStandaloneBundleUpdate({
72424
+ install: bundleInstall,
72425
+ serverUrl,
72426
+ output: output2,
72427
+ spawn: spawn6,
72428
+ env
72429
+ });
72430
+ }
72431
+ const command2 = buildNpmSelfUpdateCommand(getCliInstallChannel(serverUrl));
71937
72432
  output2.write(`Updating nolo with: ${command2.join(" ")}
71938
72433
  `);
71939
72434
  const useCustomSink = options.output !== void 0;
@@ -71942,7 +72437,7 @@ async function runSelfUpdate(outputOrOptions) {
71942
72437
  stdin: "inherit",
71943
72438
  stdout: useCustomSink ? "pipe" : "inherit",
71944
72439
  stderr: useCustomSink ? "pipe" : "inherit",
71945
- env: process.env
72440
+ env
71946
72441
  });
71947
72442
  if (!useCustomSink) {
71948
72443
  return await proc.exited;
@@ -71960,24 +72455,43 @@ function getSystemInternalCommandEntries(renderHelpText2) {
71960
72455
  return [
71961
72456
  createEnvCommand(["doctor", "runtime"], "Diagnose local-first agent runtime selection", runDoctorRuntimeCommand),
71962
72457
  createArgsCommand(["login"], "Log in to Nolo", (args2) => Promise.resolve(runLoginCommand(args2))),
71963
- createArgsCommand(["logout"], "Log out of Nolo", async () => runLogoutCommand()),
71964
- createArgsCommand(["whoami"], "Show the current login state", async () => runWhoamiCommand()),
72458
+ createContextCommand(
72459
+ ["logout"],
72460
+ "Log out of Nolo",
72461
+ async (args2, ctx) => runLogoutCommand({ args: args2, env: ctx.env })
72462
+ ),
72463
+ createContextCommand(
72464
+ ["whoami"],
72465
+ "Show the current login state",
72466
+ async (args2, ctx) => runWhoamiCommand({ args: args2, env: ctx.env })
72467
+ ),
71965
72468
  createEntrypointEnvCommand(["connect"], "Send machine heartbeats or hold a connector websocket", runMachineConnectCommand),
71966
72469
  createDaemonShortcutCommand(["daemon"], "Run the connector daemon shortcut", runMachineConnectCommand),
71967
72470
  createEnvCommand(["machine", "status"], "List machines registered to the current profile", runMachineStatusCommand),
71968
72471
  createContextCommand(["doctor"], "Show CLI doctor information", async (_args, ctx) => {
72472
+ const serverUrl = resolveSelfUpdateServerUrl(ctx.env);
71969
72473
  console.log(
71970
72474
  buildCliDoctorText({
71971
72475
  packageName: ctx.packageInfo.name,
71972
72476
  version: ctx.packageInfo.version,
71973
72477
  entrypoint: ctx.entrypointPath,
71974
- serverUrl: ctx.env.NOLO_SERVER || ctx.env.BASE_URL || DEFAULT_NOLO_SERVER_URL,
71975
- profileName: ctx.env.NOLO_PROFILE || "local"
72478
+ serverUrl,
72479
+ profileName: ctx.env.NOLO_PROFILE || "local",
72480
+ installKind: detectStandaloneBundleInstall(ctx.entrypointPath) ? "standalone-bundle" : "npm-global",
72481
+ updateChannel: getCliInstallChannel(serverUrl)
71976
72482
  })
71977
72483
  );
71978
72484
  return 0;
71979
72485
  }),
71980
- createArgsCommand(["update"], "Update the CLI", async () => runSelfUpdate()),
72486
+ createContextCommand(
72487
+ ["update"],
72488
+ "Update the CLI",
72489
+ async (_args, ctx) => runSelfUpdate({
72490
+ entrypointPath: ctx.entrypointPath,
72491
+ serverUrl: resolveSelfUpdateServerUrl(ctx.env),
72492
+ env: ctx.env
72493
+ })
72494
+ ),
71981
72495
  createContextCommand(["version"], "Show CLI version", async (_args, ctx) => {
71982
72496
  console.log(buildCliVersionText(ctx.packageInfo));
71983
72497
  return 0;
@@ -72559,7 +73073,6 @@ function renderHelpText() {
72559
73073
  " nolo space list --json",
72560
73074
  " nolo agent pull agent-pub-01APPBUILDER00000001YAII3I",
72561
73075
  " nolo agent read agent-pub-01APPBUILDER00000001YAII3I",
72562
- " nolo agent usage qoder",
72563
73076
  ' nolo agent run frontend-implementer --msg "polish notifications"',
72564
73077
  " nolo agent bind-current agent-user-1-agent-1",
72565
73078
  " nolo agent runtime-doctor agent-user-1-agent-1",
@@ -72654,7 +73167,7 @@ function resolveTuiLaunchMode(args2) {
72654
73167
  // packages/cli/tui/readlineWorkspace.ts
72655
73168
  import { createInterface as createInterface2 } from "node:readline";
72656
73169
  import { stdin as defaultInput, stdout as defaultOutput } from "node:process";
72657
- import { join as join11 } from "node:path";
73170
+ import { join as join12 } from "node:path";
72658
73171
 
72659
73172
  // packages/cli/client/compactDialog.ts
72660
73173
  import { ulid as ulid11 } from "ulid";
@@ -72885,7 +73398,7 @@ function renderTuiHelp() {
72885
73398
  " /customize Describe how you want to tune nolo",
72886
73399
  " /login Show login/profile hint",
72887
73400
  " /profile Show active profile",
72888
- " /update Update the global nolo install",
73401
+ " /update Update the nolo CLI install",
72889
73402
  " /version Show version/update hint",
72890
73403
  " /exit Leave the workspace",
72891
73404
  "",
@@ -73257,7 +73770,7 @@ async function pipeReadableToOutput(stream, output2) {
73257
73770
  }
73258
73771
  function resolveDefaultCliEntrypoint(scriptDir) {
73259
73772
  if (process.argv[1]) return process.argv[1];
73260
- return join11(scriptDir, "..", "packages", "cli", "index.ts");
73773
+ return join12(scriptDir, "..", "packages", "cli", "index.ts");
73261
73774
  }
73262
73775
  async function runCliCommandInChildProcess(args2, context) {
73263
73776
  const proc = spawnProcess({
@@ -73321,12 +73834,12 @@ async function startTuiWorkspace(options) {
73321
73834
  if (exitCode2 === 0) {
73322
73835
  output2.write("Update finished. Restart nolo to use the new version.\n");
73323
73836
  } else {
73324
- output2.write("Update failed. Fix the npm error above, then run /update again or use nolo update.\n");
73837
+ output2.write("Update failed. Check the error above, then run /update again or use nolo update.\n");
73325
73838
  }
73326
73839
  } catch (error) {
73327
73840
  output2.write(`${error instanceof Error ? error.message : String(error)}
73328
73841
  `);
73329
- output2.write("Update failed. Fix the npm error above, then run /update again or use nolo update.\n");
73842
+ output2.write("Update failed. Check the error above, then run /update again or use nolo update.\n");
73330
73843
  }
73331
73844
  }
73332
73845
  if (result.action?.type === "cli-command") {
@@ -73377,12 +73890,12 @@ ${renderStatusLine(state)}
73377
73890
  }
73378
73891
 
73379
73892
  // packages/cli/index.ts
73380
- var CLI_DIR3 = dirname8(fileURLToPath5(import.meta.url));
73381
- var ROOT_DIR = join12(CLI_DIR3, "..", "..");
73382
- var SCRIPT_DIR = join12(ROOT_DIR, "scripts");
73893
+ var CLI_DIR3 = dirname9(fileURLToPath6(import.meta.url));
73894
+ var ROOT_DIR = join13(CLI_DIR3, "..", "..");
73895
+ var SCRIPT_DIR = join13(ROOT_DIR, "scripts");
73383
73896
  var packageInfo = readPackageInfo();
73384
73897
  async function runScript(script, forwardedArgs, env) {
73385
- const scriptPath = join12(SCRIPT_DIR, script);
73898
+ const scriptPath = join13(SCRIPT_DIR, script);
73386
73899
  const proc = spawnProcess({
73387
73900
  cmd: [process.execPath, scriptPath, ...forwardedArgs],
73388
73901
  stdin: "inherit",
@@ -73400,7 +73913,7 @@ var runtimeEnv = {
73400
73913
  var runtimeContext = createCliRuntimeContext({
73401
73914
  env: runtimeEnv,
73402
73915
  scriptDir: SCRIPT_DIR,
73403
- entrypointPath: fileURLToPath5(import.meta.url),
73916
+ entrypointPath: fileURLToPath6(import.meta.url),
73404
73917
  packageInfo
73405
73918
  });
73406
73919
  if (args.length === 0) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nolo-cli",
3
- "version": "0.1.46",
3
+ "version": "0.1.47",
4
4
  "type": "module",
5
5
  "description": "Agent-first terminal workspace for Nolo",
6
6
  "bin": {