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.
- package/index.js +688 -175
- 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 =
|
|
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
|
|
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: "
|
|
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: "
|
|
20362
|
+
mocha: "catppuccin"
|
|
20297
20363
|
};
|
|
20298
|
-
DEFAULT_THEME_NAME = "
|
|
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
|
|
21568
|
-
const
|
|
21569
|
-
const
|
|
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:
|
|
21622
|
-
const
|
|
21610
|
+
radius: (() => {
|
|
21611
|
+
const boost = meta?.radiusBoost ?? 0;
|
|
21623
21612
|
const xs = compact2 ? "10px" : "12px";
|
|
21624
|
-
const sm =
|
|
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:
|
|
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
|
-
...
|
|
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
|
|
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
|
|
65993
|
-
import { fileURLToPath as
|
|
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
|
|
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>] [--
|
|
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>] [--
|
|
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))
|
|
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
|
-
|
|
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
|
-
|
|
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: ${
|
|
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
|
|
71706
|
-
|
|
71707
|
-
|
|
71708
|
-
|
|
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/
|
|
72005
|
+
// packages/cli/standaloneBundle.ts
|
|
71875
72006
|
init_processSpawn();
|
|
71876
|
-
import {
|
|
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
|
|
71880
|
-
|
|
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 =
|
|
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
|
|
71893
|
-
|
|
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 =
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
71964
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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.
|
|
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.
|
|
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 =
|
|
73381
|
-
var ROOT_DIR =
|
|
73382
|
-
var SCRIPT_DIR =
|
|
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 =
|
|
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:
|
|
73916
|
+
entrypointPath: fileURLToPath6(import.meta.url),
|
|
73404
73917
|
packageInfo
|
|
73405
73918
|
});
|
|
73406
73919
|
if (args.length === 0) {
|