nolo-cli 0.201.0-alpha.2 → 0.202.0-alpha.2

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 (124) hide show
  1. package/{_executeModel-BNYZLAN6.js → _executeModel-IPRTPSW7.js} +34 -33
  2. package/{agentDeleteCommand-4V4YSAXS.js → agentDeleteCommand-6HFA37FH.js} +49 -47
  3. package/{agentEmailCommands-EYIQEH6Z.js → agentEmailCommands-TDBNVIAT.js} +51 -49
  4. package/{agentListCommands-2KGUT7UB.js → agentListCommands-YSQSDQM3.js} +81 -45
  5. package/{agentMachineCommands-WUN47ILO.js → agentMachineCommands-5W23BLFR.js} +28 -26
  6. package/{agentProviderCommands-T6E3JCR6.js → agentProviderCommands-5ALOQLE5.js} +2 -2
  7. package/{agentRecordCommands-XL2CON36.js → agentRecordCommands-SRIMZZFK.js} +47 -45
  8. package/{agentRunCommand-R237ZGMQ.js → agentRunCommand-BLYHIN6S.js} +49 -47
  9. package/{agentRunControl-6HHESKDB.js → agentRunControl-ABDUPJLX.js} +10 -5
  10. package/{agentRuntimeLocal-XLLWFAVI.js → agentRuntimeLocal-FE66EBRC.js} +24 -22
  11. package/{agentSlice-Z5NKGMB7.js → agentSlice-BFDKYW6H.js} +4 -3
  12. package/{appDeleteCommands-IPF2VI3W.js → appDeleteCommands-BEVZGCAG.js} +29 -27
  13. package/{appDeployCommands-IBQ7GUXO.js → appDeployCommands-E7TFCHSP.js} +29 -27
  14. package/{appDeployStatusCommands-6ESVU6XE.js → appDeployStatusCommands-MYY5Z5G3.js} +29 -27
  15. package/{appGetCommands-VTSYTM4V.js → appGetCommands-HNED5JUU.js} +29 -27
  16. package/{appListCommands-VCP5TUX7.js → appListCommands-MSBFWPIY.js} +29 -27
  17. package/{authCommand-RV5MQDWN.js → authCommand-W34UWJGR.js} +14 -13
  18. package/{builtinSkillRegistry-7RAJP7FD.js → builtinSkillRegistry-NJVHQIKY.js} +1 -1
  19. package/{chromeOpsCommands-BA6CS4DI.js → chromeOpsCommands-USKE4B4K.js} +15 -4
  20. package/{chunk-RE3B2OCC.js → chunk-266E37EL.js} +69 -14
  21. package/chunk-2BMURXSB.js +1863 -0
  22. package/{chunk-NABJEYPJ.js → chunk-2Q3LOAFE.js} +38 -3
  23. package/{chunk-EOLPKHSB.js → chunk-326HCB6L.js} +28 -24
  24. package/{chunk-4CEAZRZ4.js → chunk-33W4IFUU.js} +1 -1
  25. package/{chunk-V3MGT3RF.js → chunk-3CWF2EUZ.js} +8 -8
  26. package/{chunk-G6OOUQWJ.js → chunk-4KB6WQUL.js} +2 -0
  27. package/{chunk-DYQXB46J.js → chunk-4KPB3KWX.js} +2 -2
  28. package/{chunk-WAZ6BTSC.js → chunk-5E4FSR4J.js} +1 -1
  29. package/{chunk-PVD7CRYV.js → chunk-6I7ZP7KJ.js} +3 -3
  30. package/chunk-6UBGXX2W.js +12 -0
  31. package/{chunk-ZBCBFOWC.js → chunk-A2ZMIRLN.js} +2 -2
  32. package/{chunk-Z646E5YH.js → chunk-ASG7VWPK.js} +3 -3
  33. package/{chunk-QWVGFBOQ.js → chunk-BLFZULEQ.js} +3 -3
  34. package/{chunk-RRHJJUA3.js → chunk-BRZTSZBG.js} +174 -100
  35. package/{chunk-JIFYXQRD.js → chunk-BTYQAODF.js} +26 -8
  36. package/{chunk-KORCRPLO.js → chunk-C7PKPHK6.js} +334 -12
  37. package/{chunk-6WZQGT5X.js → chunk-CJ37ZMCQ.js} +6 -2
  38. package/{chunk-VHGD6FHV.js → chunk-CKAHAVMK.js} +40 -10
  39. package/{chunk-UNOILAZP.js → chunk-CLTGWJVT.js} +76 -4
  40. package/{chunk-Q6RMLYSA.js → chunk-CMLBKYEI.js} +4 -2
  41. package/{chunk-NVOYW6H4.js → chunk-CQHMBWZH.js} +12 -8
  42. package/{chunk-7KWPNGVJ.js → chunk-CTZ4O3XD.js} +1 -1
  43. package/{chunk-OHRDHS4N.js → chunk-CVCRAO6Q.js} +9 -4
  44. package/{chunk-26CRLZFD.js → chunk-D57YYGMD.js} +2 -2
  45. package/{chunk-TEC5UHQK.js → chunk-DHJXDGC3.js} +2 -2
  46. package/{chunk-QYOB7RVA.js → chunk-DKZJJ2NQ.js} +3 -2
  47. package/{chunk-4YX7VQOC.js → chunk-E2FC5RMU.js} +17 -14
  48. package/{chunk-EH4MNUMF.js → chunk-ETTDZBK5.js} +4 -4
  49. package/{chunk-ZWQUWF6W.js → chunk-G7Y4GXTY.js} +8 -14
  50. package/{chunk-5KTQVMCX.js → chunk-GOO6G4PY.js} +85 -0
  51. package/{chunk-FMOZ57LN.js → chunk-H7HWWNJB.js} +1 -1
  52. package/{chunk-SW5AAI5D.js → chunk-HKMPGHFZ.js} +5 -5
  53. package/{chunk-H44LQSZ2.js → chunk-HKWGI3TM.js} +178 -311
  54. package/{chunk-BBGYSMUE.js → chunk-JH7KMNGT.js} +143 -19
  55. package/{chunk-YXMZHGNA.js → chunk-KDUYNEJ5.js} +33 -16
  56. package/{chunk-FEKMTBKJ.js → chunk-LAYFVGS4.js} +192 -55
  57. package/{chunk-O5V7QQAF.js → chunk-LEX6DEH4.js} +114 -2
  58. package/{chunk-BTBT2566.js → chunk-MNUOMXJH.js} +412 -9
  59. package/{chunk-N7E3LQ4A.js → chunk-MZXWSY4E.js} +1 -1
  60. package/{chunk-ZQ3EAOY3.js → chunk-NTLJGRAT.js} +1 -1
  61. package/{chunk-BUXH3H5M.js → chunk-OIB4GARE.js} +3743 -4848
  62. package/{chunk-WFUIXNKC.js → chunk-P4YLK2OD.js} +3 -3
  63. package/chunk-PRJ473FK.js +63 -0
  64. package/{chunk-2SHLT6JB.js → chunk-Q7GNBUT4.js} +2 -2
  65. package/{chunk-C2UXCAMB.js → chunk-RIKSN62L.js} +3 -3
  66. package/{chunk-GTP6VNWH.js → chunk-RQ22OZD7.js} +3 -3
  67. package/{chunk-H7NIQGTU.js → chunk-RS66RJLA.js} +2 -2
  68. package/{chunk-GC64WGMD.js → chunk-SM3NSZJV.js} +16 -5
  69. package/{chunk-QKDMI22S.js → chunk-SSK4WNJA.js} +1 -1
  70. package/{chunk-6MAFLMAO.js → chunk-SUBNV2JH.js} +3 -3
  71. package/{chunk-HLAL63BZ.js → chunk-T43B7LB2.js} +1 -1
  72. package/{chunk-HTLIKE5U.js → chunk-TWVVTUNG.js} +2 -2
  73. package/{chunk-X3RWBJDQ.js → chunk-U7HTU2S7.js} +1 -1
  74. package/{chunk-76YUTLOT.js → chunk-UIOEHFF6.js} +1 -1
  75. package/{chunk-IIX6VWLW.js → chunk-VCFU3BO5.js} +224 -38
  76. package/{chunk-QU3TLYBR.js → chunk-VEUSD6OF.js} +35 -11
  77. package/{chunk-4YMD7B4Y.js → chunk-WPOKOKZA.js} +2 -2
  78. package/{chunk-A5VR65AE.js → chunk-WPQGLJHU.js} +4 -4
  79. package/{chunk-K6TZSON4.js → chunk-WTKYP6QO.js} +19 -5
  80. package/{chunk-ZSO5B6SW.js → chunk-Y2WUYX4I.js} +9 -0
  81. package/{chunk-A3SXTJDE.js → chunk-YAGFPXOX.js} +14 -14
  82. package/{chunk-TVGX5QIN.js → chunk-YUA6OAH5.js} +2 -2
  83. package/{chunk-NYE2INIO.js → chunk-YV2RSLM4.js} +13 -13
  84. package/{chunk-MJWUBTK7.js → chunk-YZGNKHUM.js} +2 -2
  85. package/{commandRegistry-YFXWA5SF.js → commandRegistry-ZU3RX7A2.js} +87 -67
  86. package/{contentThunks-2BV7CFUP.js → contentThunks-I4IHSDTM.js} +14 -13
  87. package/{cooldownCommands-KRILPXOZ.js → cooldownCommands-5SJ74DNP.js} +1 -1
  88. package/{createAgentAutomationAction-T6CGXCSO.js → createAgentAutomationAction-WQCH5HR2.js} +14 -13
  89. package/{createDialogAction-X27IA3G2.js → createDialogAction-CKMZK5JQ.js} +15 -14
  90. package/{createPageAction-EHDHNW5P.js → createPageAction-QAZHQGY7.js} +14 -13
  91. package/{dialogCommands-XZXH3HSQ.js → dialogCommands-NEQ6NW5H.js} +30 -28
  92. package/{dialogSlice-AZNPVOCU.js → dialogSlice-GEGACCH2.js} +13 -12
  93. package/{docCreateCommands-Z64V5BFZ.js → docCreateCommands-EXV267FP.js} +28 -26
  94. package/{docDeleteCommands-7UFHIM4C.js → docDeleteCommands-TSBILA2Z.js} +29 -27
  95. package/{docReadCommands-NLU7Y67R.js → docReadCommands-AKVYHITD.js} +28 -26
  96. package/{docStore-M37Q6JFO.js → docStore-B4EFT53J.js} +1 -1
  97. package/{docUpdateCommands-S2KGBEG3.js → docUpdateCommands-G6GULDGZ.js} +28 -26
  98. package/{fetchMessages-HWBVATSE.js → fetchMessages-YY4SATNR.js} +1 -1
  99. package/{getPricing-E2PLNWCR.js → getPricing-3PQY3TGI.js} +3 -3
  100. package/{handleSendMessageAction-KUJQZ6B6.js → handleSendMessageAction-4BACQWOG.js} +70 -29
  101. package/index.js +7 -7
  102. package/{lib-4YTWAGY7.js → lib-5KKIBFIT.js} +439 -272
  103. package/{localDialogRead-CT5HGDMC.js → localDialogRead-FUXGZ57B.js} +1 -1
  104. package/{localRuntimeAdapter-5BNHO6JZ.js → localRuntimeAdapter-MTDULOUZ.js} +45 -43
  105. package/{machineCommands-2KDROAVV.js → machineCommands-OGHHBRV3.js} +48 -46
  106. package/{machineWsRunDispatch-4NP5M574.js → machineWsRunDispatch-R6DNC3H7.js} +46 -44
  107. package/{models-UUNO6DOL.js → models-PJBE6JDV.js} +2 -2
  108. package/{oauthTokenStore-PADKLNOC.js → oauthTokenStore-OEERZFUC.js} +2 -1
  109. package/package.json +1 -1
  110. package/{providerPresetApply-JGNMO2KX.js → providerPresetApply-HBBUUVJD.js} +6 -6
  111. package/{providerRegistry-33J3ZYFJ.js → providerRegistry-5LK2NXYE.js} +6 -6
  112. package/{readlineWorkspace-MKUSR6HA.js → readlineWorkspace-NC2O4DQP.js} +290 -121
  113. package/{runAgentClientLoop-J32KRVN7.js → runAgentClientLoop-QKV66PX5.js} +31 -30
  114. package/{runtimeDoctorCommands-NYBOTA6D.js → runtimeDoctorCommands-3VFVTGPI.js} +8 -7
  115. package/{secretCommands-N6CMCJDZ.js → secretCommands-MKU25CDP.js} +311 -3
  116. package/{settingThunks-YRYNPWJM.js → settingThunks-4WU7YE62.js} +2 -2
  117. package/{skillDiscovery-F3TMVQOJ.js → skillDiscovery-BKLWW2EZ.js} +2 -2
  118. package/{spaceCommands-VV4K7TGI.js → spaceCommands-J7BRTTM3.js} +27 -25
  119. package/{streamAgentChatTurn-S2Q7STXS.js → streamAgentChatTurn-GM3UNSLS.js} +46 -43
  120. package/{tools-KOIPW4ZA.js → tools-UJLEQBKI.js} +25 -24
  121. package/{tuiSummaryLlmCaller-FSOADMXK.js → tuiSummaryLlmCaller-73QO3HAD.js} +12 -12
  122. package/{updateCommands-KE6LP3QX.js → updateCommands-RVDAFHBT.js} +3 -3
  123. package/{updateDialogTitleAction-ILS5OIXF.js → updateDialogTitleAction-24QO27NT.js} +14 -13
  124. package/{windowsSelfUpdate-26TSFXEZ.js → windowsSelfUpdate-N2VH2OBW.js} +2 -2
@@ -3,13 +3,14 @@ import {
3
3
  } from "./chunk-PSCNXBYA.js";
4
4
  import {
5
5
  MODEL_LOOKUP_MAP
6
- } from "./chunk-GC64WGMD.js";
6
+ } from "./chunk-SM3NSZJV.js";
7
7
  import {
8
8
  ALL_MODELS
9
- } from "./chunk-HLAL63BZ.js";
9
+ } from "./chunk-T43B7LB2.js";
10
10
  import {
11
- isPlatformManagedProvider
12
- } from "./chunk-5KTQVMCX.js";
11
+ isPlatformManagedProvider,
12
+ resolvePlatformEffectiveModel
13
+ } from "./chunk-GOO6G4PY.js";
13
14
 
14
15
  // packages/core/chat/messageContentSerialize.ts
15
16
  var serializeMessageContent = (content, imagePlaceholder = "[\u56FE\u7247]") => {
@@ -771,8 +772,12 @@ var QWEN_3_6_CONTEXT_WINDOW = 262144;
771
772
  var GLM_5_2_CONTEXT_WINDOW = 1e6;
772
773
  var GPT_6_1_SOL_CONTEXT_WINDOW = 5e5;
773
774
  var GPT_6_1_SOL_PATTERN = /(^|\/)gpt-6\.1[- ]sol(?![a-z])/;
775
+ var GPT_6_1_PINNED_PATTERN = /(^|\/)gpt-6\.1[- ](sol|terra)(?![a-z0-9])/;
776
+ var GPT_272K_PINNED_PATTERN = /(^|\/)(gpt-6[- ](astra|luna|sol)|gpt-5\.6[- ](sol|terra|luna))(?![a-z0-9])/;
777
+ var GPT_272K_CONTEXT_WINDOW = 272e3;
774
778
  function channelPinnedContextWindow(normalizedName) {
775
- if (GPT_6_1_SOL_PATTERN.test(normalizedName)) return GPT_6_1_SOL_CONTEXT_WINDOW;
779
+ if (GPT_6_1_PINNED_PATTERN.test(normalizedName)) return GPT_6_1_SOL_CONTEXT_WINDOW;
780
+ if (GPT_272K_PINNED_PATTERN.test(normalizedName)) return GPT_272K_CONTEXT_WINDOW;
776
781
  return void 0;
777
782
  }
778
783
  var ANTIGRAVITY_EFFORT_SUFFIXES = [
@@ -844,6 +849,8 @@ function fuzzyContextWindow(normalizedName) {
844
849
  if (normalizedName.includes("glm-5.2") || normalizedName.includes("glm5.2")) return GLM_5_2_CONTEXT_WINDOW;
845
850
  if (normalizedName.includes("deepseek")) return 1e6;
846
851
  if (GPT_6_1_SOL_PATTERN.test(normalizedName)) return GPT_6_1_SOL_CONTEXT_WINDOW;
852
+ const channelPinned = channelPinnedContextWindow(normalizedName);
853
+ if (channelPinned !== void 0) return channelPinned;
847
854
  if (normalizedName.includes("gpt-5") || normalizedName.includes("gpt-4.1")) return 1047576;
848
855
  if (normalizedName.startsWith("cursor-grok-4.5")) return 1e6;
849
856
  if (normalizedName.includes("claude-4.6")) return 1e6;
@@ -916,15 +923,26 @@ var findModelContextWindow = (modelName, provider) => {
916
923
  for (const candidate of candidates) {
917
924
  const model = map.get(candidate);
918
925
  if (model?.contextWindow) {
919
- if (!onPlatformChannel && isPlatformManagedProvider(model.provider, model.name) && channelPinnedContextWindow(model.name.toLowerCase()) !== void 0) {
926
+ if (!onPlatformChannel && (channelPinnedContextWindow(model.name.toLowerCase()) !== void 0 || channelPinnedContextWindow(candidate.toLowerCase()) !== void 0)) {
920
927
  continue;
921
928
  }
922
929
  return typeof model.contextWindow === "number" ? model.contextWindow : void 0;
923
930
  }
924
931
  }
932
+ if (onPlatformChannel) {
933
+ const effective = resolvePlatformEffectiveModel(normalizedName);
934
+ if (effective && effective !== normalizedName) {
935
+ const aliased = map.get(effective);
936
+ if (aliased?.contextWindow) {
937
+ return typeof aliased.contextWindow === "number" ? aliased.contextWindow : void 0;
938
+ }
939
+ }
940
+ }
925
941
  if (!onPlatformChannel) {
926
- const pinned = channelPinnedContextWindow(normalizedName);
927
- if (pinned !== void 0) return pinned;
942
+ for (const candidate of candidates) {
943
+ const pinned = channelPinnedContextWindow(candidate.toLowerCase());
944
+ if (pinned !== void 0) return pinned;
945
+ }
928
946
  }
929
947
  return fuzzyContextWindow(normalizedName);
930
948
  };
@@ -1,18 +1,37 @@
1
1
  import {
2
2
  DEFAULT_AUTO_APPROVED_SELF_UPDATE_FIELDS,
3
3
  DEFAULT_USER_PREFERENCE_PROFILE,
4
+ isAgentSkillDisabled,
4
5
  normalizeAgentUpdateFieldList,
5
6
  normalizePolicyLevelSetting,
6
7
  normalizeSystemBuiltinSkills,
7
8
  normalizeTonePresetSetting,
8
9
  resolveUserEnabledSkills
9
- } from "./chunk-QYOB7RVA.js";
10
+ } from "./chunk-DKZJJ2NQ.js";
11
+ import {
12
+ isSkillSummaryMarker
13
+ } from "./chunk-VF4K2QE6.js";
14
+ import {
15
+ setDialogExtraReferencesAction
16
+ } from "./chunk-RXUKDHS5.js";
10
17
  import {
11
18
  fetchAndCacheTableRows
12
- } from "./chunk-QKDMI22S.js";
19
+ } from "./chunk-SSK4WNJA.js";
20
+ import {
21
+ createSpaceKey
22
+ } from "./chunk-UAD2WT54.js";
23
+ import {
24
+ getActiveDialogKey
25
+ } from "./chunk-OWYYDMGJ.js";
13
26
  import {
14
27
  require_react
15
28
  } from "./chunk-YDH3FDFQ.js";
29
+ import {
30
+ selectById
31
+ } from "./chunk-OHYCQKPW.js";
32
+ import {
33
+ selectRuntimeSnapshot
34
+ } from "./chunk-32GANJHJ.js";
16
35
  import {
17
36
  createAsyncThunk,
18
37
  createSelector
@@ -20,12 +39,31 @@ import {
20
39
  import {
21
40
  selectIdentityUserId
22
41
  } from "./chunk-PXYBUFDB.js";
42
+ import {
43
+ listBuiltinSkills,
44
+ resolveBuiltinSkillByName
45
+ } from "./chunk-LEX6DEH4.js";
23
46
  import {
24
47
  DEFAULT_SYSTEM_AGENT_CAPABILITIES
25
48
  } from "./chunk-6OEPWZV7.js";
49
+ import {
50
+ parseSkillDocProtocol
51
+ } from "./chunk-AETZ7AD6.js";
26
52
  import {
27
53
  toErrorMessage
28
54
  } from "./chunk-HNMXYYJR.js";
55
+ import {
56
+ isRecord
57
+ } from "./chunk-KUG52IAP.js";
58
+ import {
59
+ normalizeServerOrigin
60
+ } from "./chunk-CF7PE763.js";
61
+ import {
62
+ asTrimmedNonEmptyStringArray
63
+ } from "./chunk-I42VC5KR.js";
64
+ import {
65
+ asTrimmedString
66
+ } from "./chunk-3EUW3WEO.js";
29
67
  import {
30
68
  asOptionalTrimmedString
31
69
  } from "./chunk-G3SUCT4W.js";
@@ -153,6 +191,288 @@ var selectSystemBuiltinSkills = createSelector(
153
191
  )
154
192
  );
155
193
 
194
+ // packages/ai/tools/loadSkillTool.ts
195
+ var loadSkillFunctionSchema = {
196
+ name: "loadSkill",
197
+ description: [
198
+ "\u6309\u540D\u79F0\u6216\u7CBE\u786E\u5F15\u7528\u52A0\u8F7D\u4E00\u4E2A skill \u6587\u6863\uFF0C\u8FD4\u56DE\u5176\u5B8C\u6574\u6307\u4EE4\u6B63\u6587\u3002",
199
+ "name \u4F7F\u7528 skill \u4FDD\u5B58\u65F6\u5199\u5165 skill-config \u7684 name\uFF08\u4E5F\u63A5\u53D7 skillId\uFF09\u3002",
200
+ "\u7CBE\u786E\u5F15\u7528\u4E0D\u4F20 name\uFF1Asource=space + dbKey\uFF0Csource=builtin + slug\uFF0C\u6216 source=project + projectBinding + relativePath\uFF1B\u5404\u7EC4\u5B57\u6BB5\u4E92\u65A5\uFF0C\u4E0D\u6DF7\u7528\u3002",
201
+ "\u6267\u884C\u5668\u652F\u6301\u8303\u56F4\uFF1A\u670D\u52A1\u7AEF\u652F\u6301 space/builtin\uFF0C\u672C\u5730 CLI/desktop \u652F\u6301 builtin/project\uFF1BWeb \u5BA2\u6237\u7AEF\u652F\u6301 name \u4E0E space/builtin \u7CBE\u786E\u5F15\u7528\uFF0C\u4E0D\u652F\u6301 project\u3002",
202
+ "\u627E\u4E0D\u5230\u5BF9\u5E94 skill \u65F6\u8FD4\u56DE\u5F53\u524D\u53EF\u7528\u7684 skill \u540D\u79F0\u5217\u8868\uFF08\u4E0D\u62A5\u9519\uFF09\uFF1B\u7CBE\u786E\u5F15\u7528\u4E0D\u56DE\u9000\u5230\u540C\u540D skill\u3002",
203
+ '\u7CFB\u7EDF\u5185\u7F6E\u5199\u4EE3\u7801\u6280\u80FD\uFF1A\u5BF9\u8BDD\u8F6C\u5411\u5199\u4EE3\u7801\u65F6\u7528 loadSkill("coding") \u8F7D\u5165\u5199\u4EE3\u7801\u80FD\u529B\u4E0E\u4EE3\u7801\u5BA1\u67E5\u7EAA\u5F8B\uFF08\u542B review \u89D2\u8272\u5207\u5272\uFF09\u3002',
204
+ "\u7CFB\u7EDF\u5185\u7F6E\u4E13\u804C\u6280\u80FD\uFF1Afeedback\uFF08\u53CD\u9988\u6536\u96C6\uFF09/ agent-creator\uFF08\u521B\u5EFA Agent\uFF09/ app-builder\uFF08\u5E94\u7528\u6784\u5EFA\uFF09\uFF0C\u540C\u6837\u53EF\u76F4\u63A5 loadSkill \u8F7D\u5165\u3002"
205
+ ].join("\n"),
206
+ parameters: {
207
+ type: "object",
208
+ properties: {
209
+ name: {
210
+ type: "string",
211
+ description: "\u65E7\u7248 skill \u540D\u79F0\uFF1B\u4E0D\u4E0E\u7CBE\u786E\u5F15\u7528\u5B57\u6BB5\u6DF7\u7528\u3002"
212
+ },
213
+ source: {
214
+ type: "string",
215
+ enum: ["space", "builtin", "project"],
216
+ description: "\u7CBE\u786E\u6765\u6E90\uFF1Aspace \u9700 dbKey\uFF0Cbuiltin \u9700 slug\uFF0Cproject \u9700 projectBinding \u4E0E relativePath\uFF1B\u4E0D\u4F20 name\u3002Web \u5BA2\u6237\u7AEF\u652F\u6301 space/builtin\uFF0C\u4E0D\u652F\u6301 project\u3002"
217
+ },
218
+ dbKey: {
219
+ type: "string",
220
+ description: "\u7CBE\u786E skill \u6587\u6863 dbKey\uFF0C\u4EC5\u7528\u4E8E source=space\uFF1B\u5FC5\u987B\u5728\u5F53\u524D\u7528\u6237 membership \u53EF\u89C1\u7684 Space Skill \u7D22\u5F15\u4E2D\uFF08\u670D\u52A1\u7AEF\u6216 Web \u5BA2\u6237\u7AEF\u6267\u884C\uFF09\u3002"
221
+ },
222
+ slug: {
223
+ type: "string",
224
+ description: "\u7CBE\u786E\u5185\u7F6E skill slug\uFF0C\u4EC5\u7528\u4E8E source=builtin\u3002"
225
+ },
226
+ projectBinding: {
227
+ type: "string",
228
+ description: "\u4E0E\u6267\u884C\u5668\u6388\u6743 cwd \u5339\u914D\u7684\u9879\u76EE\u6839\u76EE\u5F55\u7EDD\u5BF9\u8DEF\u5F84\uFF0C\u4EC5\u7528\u4E8E source=project\uFF08\u672C\u5730\u6267\u884C\uFF09\u3002"
229
+ },
230
+ relativePath: {
231
+ type: "string",
232
+ description: "\u9879\u76EE .agents/skills/ \u5185 SKILL.md \u7684\u9879\u76EE\u76F8\u5BF9\u8DEF\u5F84\uFF0C\u4EC5\u7528\u4E8E source=project\uFF08\u672C\u5730\u6267\u884C\uFF09\u3002"
233
+ }
234
+ }
235
+ }
236
+ };
237
+ var getRuntime = (thunkApi) => {
238
+ const state = thunkApi?.getState?.();
239
+ return state ? selectRuntimeSnapshot(state) : null;
240
+ };
241
+ var authHeaders = (token) => token ? { Authorization: `Bearer ${token}` } : {};
242
+ async function readRemoteRecord(args) {
243
+ const serverBase = normalizeServerOrigin(args.serverBase);
244
+ if (!serverBase || !args.token) return null;
245
+ const response = await fetch(
246
+ `${serverBase}/api/v1/db/read/${encodeURIComponent(args.dbKey)}?includeDeleted=true`,
247
+ { headers: authHeaders(args.token) }
248
+ );
249
+ if (!response.ok) return null;
250
+ const payload = await response.json().catch(() => null);
251
+ return payload?.data ?? payload;
252
+ }
253
+ function resolveWebSkill(candidates, requestedName) {
254
+ const candidate = matchSkillCandidate(candidates, requestedName);
255
+ if (candidate) return { kind: "space", candidate };
256
+ const entry = resolveBuiltinSkillByName(requestedName);
257
+ return entry ? { kind: "builtin", entry } : null;
258
+ }
259
+ function listWebSkillNames(candidates) {
260
+ return Array.from(
261
+ /* @__PURE__ */ new Set([
262
+ ...candidates.map((candidate) => candidate.name),
263
+ ...listBuiltinSkills().flatMap((skill) => [skill.slug, skill.title])
264
+ ])
265
+ );
266
+ }
267
+ function matchSkillCandidate(candidates, requestedName) {
268
+ return candidates.find(
269
+ (candidate) => candidate.name === requestedName || candidate.skillId === requestedName
270
+ );
271
+ }
272
+ function collectSkillCandidatesFromSpace(space) {
273
+ if (!space?.contents || typeof space.contents !== "object") return [];
274
+ const candidates = [];
275
+ for (const [entryKey, value] of Object.entries(space.contents)) {
276
+ if (!isRecord(value)) continue;
277
+ const skillSummary = value.skillSummary;
278
+ if (!isSkillSummaryMarker(skillSummary)) continue;
279
+ const name = asTrimmedString(skillSummary.name);
280
+ if (!name) continue;
281
+ candidates.push({
282
+ dbKey: entryKey,
283
+ name,
284
+ skillId: asOptionalTrimmedString(skillSummary.skillId) ?? void 0
285
+ });
286
+ }
287
+ return candidates;
288
+ }
289
+ function extractSkillBody(page) {
290
+ return parseSkillDocProtocol(page?.content ?? "").content;
291
+ }
292
+ async function listSkillCandidates(thunkApi) {
293
+ const runtime = getRuntime(thunkApi);
294
+ const serverBase = runtime?.currentServer;
295
+ const token = runtime?.currentToken;
296
+ const userId = runtime?.currentUserId;
297
+ if (!serverBase || !token || !userId) return [];
298
+ const membershipsResponse = await fetch(
299
+ `${normalizeServerOrigin(serverBase)}/rpc/getUserSpaceMemberships`,
300
+ {
301
+ method: "POST",
302
+ headers: {
303
+ "Content-Type": "application/json",
304
+ ...authHeaders(token)
305
+ },
306
+ body: JSON.stringify({ userId })
307
+ }
308
+ ).catch(() => null);
309
+ if (!membershipsResponse?.ok) return [];
310
+ const memberships = await membershipsResponse.json().catch(() => []);
311
+ if (!Array.isArray(memberships)) return [];
312
+ const candidates = [];
313
+ for (const membership of memberships) {
314
+ const spaceId = asTrimmedString(membership?.spaceId);
315
+ if (!spaceId) continue;
316
+ const space = await readRemoteRecord({
317
+ serverBase,
318
+ token,
319
+ dbKey: createSpaceKey.space(spaceId)
320
+ });
321
+ if (!space) continue;
322
+ candidates.push(...collectSkillCandidatesFromSpace(space));
323
+ }
324
+ return candidates;
325
+ }
326
+ var resolveCurrentAgentKeyForSkillGate = (thunkApi) => {
327
+ try {
328
+ const state = thunkApi?.getState?.();
329
+ if (!state) return null;
330
+ const currentDialogKey = getActiveDialogKey();
331
+ if (!currentDialogKey) return null;
332
+ const dialogConfig = selectById(
333
+ state,
334
+ currentDialogKey
335
+ );
336
+ return asTrimmedNonEmptyStringArray(dialogConfig?.cybots)[0] ?? null;
337
+ } catch {
338
+ return null;
339
+ }
340
+ };
341
+ var readCurrentAgentSkillSource = async (thunkApi) => {
342
+ const agentKey = resolveCurrentAgentKeyForSkillGate(thunkApi);
343
+ if (!agentKey) return null;
344
+ const db = thunkApi?.extra?.db;
345
+ if (!db) return null;
346
+ try {
347
+ const agent = await db.get(agentKey);
348
+ if (!agent || typeof agent !== "object") return null;
349
+ return agent;
350
+ } catch {
351
+ return null;
352
+ }
353
+ };
354
+ async function loadSkillFunc(args, thunkApi, context) {
355
+ const hasArg = (key) => Object.prototype.hasOwnProperty.call(args ?? {}, key);
356
+ const exact = ["source", "dbKey", "slug", "projectBinding", "relativePath"].some(hasArg);
357
+ const source = args?.source;
358
+ if (exact) {
359
+ const validSpace = source === "space" && typeof args.dbKey === "string" && !!args.dbKey.trim() && !hasArg("slug") && !hasArg("projectBinding") && !hasArg("relativePath");
360
+ const validBuiltin = source === "builtin" && typeof args.slug === "string" && !!args.slug.trim() && !hasArg("dbKey") && !hasArg("projectBinding") && !hasArg("relativePath");
361
+ if (hasArg("name") || !validSpace && !validBuiltin) {
362
+ throw new Error(source === "project" ? "loadSkill: source=project is not supported by the Web client." : "loadSkill: use name, source=space + dbKey, or source=builtin + slug exclusively.");
363
+ }
364
+ }
365
+ let requestedName = asTrimmedString(exact ? source === "space" ? args.dbKey : args.slug : args?.name);
366
+ if (!requestedName) throw new Error("loadSkill \u9700\u8981\u63D0\u4F9B name\u3002");
367
+ const candidates = await listSkillCandidates(thunkApi);
368
+ let resolution;
369
+ if (!exact) {
370
+ resolution = resolveWebSkill(candidates, requestedName);
371
+ } else if (source === "space") {
372
+ const candidate = candidates.find((entry) => entry.dbKey === requestedName);
373
+ resolution = candidate ? { kind: "space", candidate } : null;
374
+ } else {
375
+ const entry = listBuiltinSkills().find((entry2) => entry2.slug === requestedName);
376
+ resolution = entry ? { kind: "builtin", entry } : null;
377
+ }
378
+ const matched = resolution?.kind === "space" ? resolution.candidate : void 0;
379
+ if (exact && matched) requestedName = matched.name;
380
+ const builtinEntry = resolution?.kind === "builtin" ? resolution.entry : null;
381
+ const resolvedSlug = builtinEntry?.slug ?? matched?.skillId ?? null;
382
+ if (resolvedSlug) {
383
+ const agentSkillSource = await readCurrentAgentSkillSource(thunkApi);
384
+ if (agentSkillSource && isAgentSkillDisabled(agentSkillSource, resolvedSlug)) {
385
+ return {
386
+ rawData: {
387
+ success: false,
388
+ name: requestedName,
389
+ slug: resolvedSlug,
390
+ disabled: true
391
+ },
392
+ displayData: `Skill "${requestedName}" \u5DF2\u88AB\u7981\u7528\uFF1A\u8BE5\u80FD\u529B\u5728\u6B64 agent \u4E0A\u4E0D\u53EF\u7528\uFF0C\u65E0\u6CD5\u52A0\u8F7D\u3002`
393
+ };
394
+ }
395
+ }
396
+ if (builtinEntry) {
397
+ const body2 = builtinEntry.content;
398
+ const dbKey = builtinEntry.slug;
399
+ if (context?.skipSkillReferencePersist !== true) {
400
+ await persistLoadedSkillReference(thunkApi, dbKey, requestedName);
401
+ }
402
+ return {
403
+ rawData: {
404
+ success: true,
405
+ name: requestedName,
406
+ dbKey,
407
+ body: body2
408
+ },
409
+ displayData: `Skill "${requestedName}" loaded inline. Follow its instructions.
410
+
411
+ ${body2}`
412
+ };
413
+ }
414
+ if (!matched) {
415
+ const availableNames = listWebSkillNames(candidates);
416
+ const availableText = availableNames.length ? availableNames.join(", ") : "(none)";
417
+ return {
418
+ rawData: {
419
+ success: false,
420
+ name: requestedName,
421
+ availableSkills: availableNames
422
+ },
423
+ displayData: `Skill "${requestedName}" not found. Available skills: ${availableText}`
424
+ };
425
+ }
426
+ const runtime = getRuntime(thunkApi);
427
+ const page = await readRemoteRecord({
428
+ serverBase: runtime?.currentServer,
429
+ token: runtime?.currentToken,
430
+ dbKey: matched.dbKey
431
+ });
432
+ if (exact && !page) {
433
+ return {
434
+ rawData: { success: false, name: requestedName, dbKey: matched.dbKey },
435
+ displayData: `Skill "${requestedName}" could not be read.`
436
+ };
437
+ }
438
+ const body = extractSkillBody(page);
439
+ if (context?.skipSkillReferencePersist !== true) {
440
+ await persistLoadedSkillReference(thunkApi, matched.dbKey, requestedName);
441
+ }
442
+ return {
443
+ rawData: {
444
+ success: true,
445
+ name: requestedName,
446
+ dbKey: matched.dbKey,
447
+ body
448
+ },
449
+ displayData: `Skill "${requestedName}" loaded inline. Follow its instructions.
450
+
451
+ ${body}`
452
+ };
453
+ }
454
+ async function persistLoadedSkillReference(thunkApi, dbKey, name) {
455
+ try {
456
+ const state = thunkApi?.getState?.();
457
+ const currentDialogKey = getActiveDialogKey();
458
+ if (!state || !currentDialogKey) return;
459
+ const dialogConfig = selectById(
460
+ state,
461
+ currentDialogKey
462
+ );
463
+ const existing = dialogConfig?.extraReferences ?? [];
464
+ const alreadyMounted = existing.some((ref) => ref.dbKey === dbKey);
465
+ if (alreadyMounted) return;
466
+ const newRef = {
467
+ dbKey,
468
+ title: name,
469
+ type: "instruction"
470
+ };
471
+ await setDialogExtraReferencesAction([...existing, newRef], thunkApi);
472
+ } catch {
473
+ }
474
+ }
475
+
156
476
  // packages/ai/tools/uiCardSchema.ts
157
477
  var UI_CARD_VERSION = 1;
158
478
  var MAX_BLOCKS = 32;
@@ -162,7 +482,7 @@ var UI_CARD_ENVELOPE_MAX_BYTES = UI_CARD_MAX_BYTES + 4096;
162
482
  var MAX_COLLECTION_ITEMS = 500;
163
483
  var MAX_JSON_DEPTH = 12;
164
484
  var MAX_JSON_NODES = 2e3;
165
- function isRecord(value) {
485
+ function isRecord2(value) {
166
486
  return value !== null && typeof value === "object" && !Array.isArray(value);
167
487
  }
168
488
  function hasOnlyKeys(value, allowed) {
@@ -181,7 +501,7 @@ function isJsonValue(value, depth, budget) {
181
501
  if (typeof value === "string") return isText(value);
182
502
  if (typeof value === "number") return Number.isFinite(value);
183
503
  if (Array.isArray(value)) return value.every((item) => isJsonValue(item, depth + 1, budget));
184
- if (!isRecord(value)) return false;
504
+ if (!isRecord2(value)) return false;
185
505
  for (const [key, item] of Object.entries(value)) {
186
506
  if (["$ref", "$expr", "expression", "script"].includes(key)) return false;
187
507
  if (!isText(key) || !isJsonValue(item, depth + 1, budget)) return false;
@@ -189,7 +509,7 @@ function isJsonValue(value, depth, budget) {
189
509
  return true;
190
510
  }
191
511
  function isChoiceQuestion(value) {
192
- if (!isRecord(value) || !hasOnlyKeys(value, ["id", "header", "question", "choices", "multiSelect", "allowOther", "required"])) return false;
512
+ if (!isRecord2(value) || !hasOnlyKeys(value, ["id", "header", "question", "choices", "multiSelect", "allowOther", "required"])) return false;
193
513
  if (!isText(value.id) || !value.id.trim() || !isText(value.question) || !value.question.trim()) return false;
194
514
  if (value.header !== void 0 && !isText(value.header)) return false;
195
515
  for (const flag of ["multiSelect", "allowOther", "required"]) {
@@ -198,7 +518,7 @@ function isChoiceQuestion(value) {
198
518
  if (!Array.isArray(value.choices) || value.choices.length === 0 || value.choices.length > MAX_COLLECTION_ITEMS) return false;
199
519
  const ids = /* @__PURE__ */ new Set();
200
520
  for (const option of value.choices) {
201
- if (!isRecord(option) || !hasOnlyKeys(option, ["id", "label", "detail", "recommended", "userMessage"])) return false;
521
+ if (!isRecord2(option) || !hasOnlyKeys(option, ["id", "label", "detail", "recommended", "userMessage"])) return false;
202
522
  if (!isText(option.label) || !option.label.trim()) return false;
203
523
  if (option.id !== void 0) {
204
524
  if (!isText(option.id) || !option.id.trim() || ids.has(option.id)) return false;
@@ -221,7 +541,7 @@ function isAppUrl(value) {
221
541
  }
222
542
  }
223
543
  function isBlock(value) {
224
- if (!isRecord(value) || typeof value.type !== "string") return false;
544
+ if (!isRecord2(value) || typeof value.type !== "string") return false;
225
545
  switch (value.type) {
226
546
  case "text":
227
547
  return hasOnlyKeys(value, ["type", "text"]) && isText(value.text);
@@ -237,11 +557,11 @@ function isBlock(value) {
237
557
  case "choice":
238
558
  return hasOnlyKeys(value, ["type", "question"]) && isChoiceQuestion(value.question);
239
559
  case "action": {
240
- if (!isRecord(value.action) || typeof value.action.type !== "string") return false;
560
+ if (!isRecord2(value.action) || typeof value.action.type !== "string") return false;
241
561
  if (value.action.type === "submit") {
242
562
  if (!hasOnlyKeys(value, ["type", "action"]) || !hasOnlyKeys(value.action, ["type", "payload"])) return false;
243
563
  if (value.action.payload === void 0) return true;
244
- return isRecord(value.action.payload) && isJsonValue(value.action.payload, 0, { nodes: 0 });
564
+ return isRecord2(value.action.payload) && isJsonValue(value.action.payload, 0, { nodes: 0 });
245
565
  }
246
566
  if (value.action.type === "openApp") {
247
567
  return hasOnlyKeys(value, ["type", "action"]) && hasOnlyKeys(value.action, ["type", "appId", "url"]) && isText(value.action.appId) && !!value.action.appId.trim() && (value.action.url === void 0 || isText(value.action.url) && isAppUrl(value.action.url));
@@ -253,7 +573,7 @@ function isBlock(value) {
253
573
  }
254
574
  }
255
575
  function parseUiCard(input) {
256
- if (!isRecord(input) || !hasOnlyKeys(input, ["id", "version", "source", "blocks"])) return { ok: false, error: "invalid card shape" };
576
+ if (!isRecord2(input) || !hasOnlyKeys(input, ["id", "version", "source", "blocks"])) return { ok: false, error: "invalid card shape" };
257
577
  if (typeof input.id !== "string" || !/^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/.test(input.id)) return { ok: false, error: "invalid card id" };
258
578
  if (input.version !== UI_CARD_VERSION || input.source !== "tool") return { ok: false, error: "unsupported card version or source" };
259
579
  if (!Array.isArray(input.blocks) || input.blocks.length > MAX_BLOCKS || !input.blocks.every(isBlock)) return { ok: false, error: "invalid blocks" };
@@ -463,7 +783,7 @@ var executeToolRun = createAsyncThunk(
463
783
  if (!executionInput) {
464
784
  throw new Error(`ToolRun ${id} has no input to execute with.`);
465
785
  }
466
- const { findToolExecutor } = await import("./tools-KOIPW4ZA.js");
786
+ const { findToolExecutor } = await import("./tools-UJLEQBKI.js");
467
787
  const { executor } = findToolExecutor(run.toolName);
468
788
  toolRunStarted({
469
789
  id: run.id,
@@ -532,5 +852,7 @@ export {
532
852
  toolRunSucceeded,
533
853
  toolRunUpdated,
534
854
  toolRunFailed,
535
- getAllToolRuns
855
+ getAllToolRuns,
856
+ loadSkillFunctionSchema,
857
+ loadSkillFunc
536
858
  };
@@ -3,7 +3,7 @@ import {
3
3
  classifyAgentApiKeyRef,
4
4
  formatUnsupportedAgentApiKeyRefMessage,
5
5
  shouldReadAgentKeyRemotely
6
- } from "./chunk-X3RWBJDQ.js";
6
+ } from "./chunk-U7HTU2S7.js";
7
7
  import {
8
8
  resolveCliAgentKeyInput
9
9
  } from "./chunk-NBTY7YJF.js";
@@ -558,7 +558,7 @@ async function buildCreatedAgentRecord(args) {
558
558
  const resolvedAgentInput = resolveCliAgentKeyInput(args.parsed.agentInput);
559
559
  const agentKey = resolvedAgentInput.startsWith("agent-") ? resolvedAgentInput : createAgentKey.private(userId || "local", resolvedAgentInput);
560
560
  if (args.parsed.presetId) {
561
- const { resolveProviderPresetFields } = await import("./providerPresetApply-JGNMO2KX.js");
561
+ const { resolveProviderPresetFields } = await import("./providerPresetApply-HBBUUVJD.js");
562
562
  const fields = resolveProviderPresetFields(args.parsed.presetId);
563
563
  if (fields.kind === "manual") {
564
564
  throw new Error(
@@ -614,6 +614,9 @@ async function buildCreatedAgentRecord(args) {
614
614
  }
615
615
  args.parsed.updates.prompt = promptBody;
616
616
  }
617
+ if (args.parsed.updates.customProviderUrl && !args.parsed.updates.apiSource) {
618
+ args.parsed.updates.apiSource = "custom";
619
+ }
617
620
  const nextRecord = {
618
621
  ...args.parsed.updates,
619
622
  dbKey: agentKey,
@@ -686,6 +689,7 @@ async function buildUpdatedAgentRecord(args) {
686
689
  const nextRecord = {
687
690
  ...currentRecord,
688
691
  ...args.parsed.updates,
692
+ ...args.parsed.updates.customProviderUrl && !args.parsed.updates.apiSource ? { apiSource: "custom" } : {},
689
693
  updatedAt: Date.now()
690
694
  };
691
695
  return {
@@ -1,15 +1,17 @@
1
1
  // packages/cli/tui/ciStatus.ts
2
2
  import { execFile } from "node:child_process";
3
- var DEFAULT_SSH_HOST = "alpha-raw";
3
+ var DEFAULT_SSH_HOST = "nolotus@136.67.147.177";
4
4
  var DEFAULT_CI_PORT = "3900";
5
5
  function resolveSshTarget() {
6
- const alias = process.env.NOLO_ALPHA_SSH_CONFIG_HOST?.trim();
7
- if (alias) return alias;
8
- const raw = process.env.NOLO_ALPHA_RAW_HOST?.trim();
6
+ const override = process.env.NOLO_CI_SSH_HOST?.trim();
7
+ if (override) return override;
8
+ const raw = process.env.NOLO_CI_RAW_HOST?.trim() ?? process.env.NOLO_ALPHA_RAW_HOST?.trim();
9
9
  if (raw) {
10
- const user = process.env.NOLO_ALPHA_SSH_USER?.trim() || "root";
10
+ const user = process.env.NOLO_CI_SSH_USER?.trim() ?? process.env.NOLO_ALPHA_SSH_USER?.trim() ?? "nolotus";
11
11
  return `${user}@${raw}`;
12
12
  }
13
+ const legacyAlias = process.env.NOLO_ALPHA_SSH_CONFIG_HOST?.trim();
14
+ if (legacyAlias) return legacyAlias;
13
15
  return DEFAULT_SSH_HOST;
14
16
  }
15
17
  function asRecord(value) {
@@ -62,13 +64,19 @@ function parseCiStatusPayload(raw) {
62
64
  const single = toCiJob(parsed);
63
65
  return single ? [single] : void 0;
64
66
  }
65
- function buildRemoteCommand(limit) {
67
+ function resolveCiPort() {
66
68
  const rawPort = process.env.NOLO_CI_PORT?.trim() ?? "";
67
- const port = /^\d{1,5}$/.test(rawPort) && Number(rawPort) > 0 && Number(rawPort) <= 65535 ? rawPort : DEFAULT_CI_PORT;
69
+ return /^\d{1,5}$/.test(rawPort) && Number(rawPort) > 0 && Number(rawPort) <= 65535 ? rawPort : DEFAULT_CI_PORT;
70
+ }
71
+ function buildRemoteCommand(limit) {
72
+ const port = resolveCiPort();
68
73
  const safeLimit = Math.max(1, Math.min(20, Math.trunc(limit) || 5));
69
74
  return `curl -s -m 3 "http://127.0.0.1:${port}/status?limit=${safeLimit}"`;
70
75
  }
71
76
  function fetchCiStatus(limit = 5, timeoutMs = 4e3) {
77
+ return fetchCiPayload(buildRemoteCommand(limit), parseCiStatusPayload, timeoutMs);
78
+ }
79
+ function fetchCiPayload(command, parse, timeoutMs) {
72
80
  return new Promise((resolve) => {
73
81
  let settled = false;
74
82
  let guard;
@@ -83,14 +91,18 @@ function fetchCiStatus(limit = 5, timeoutMs = 4e3) {
83
91
  try {
84
92
  execFile(
85
93
  "ssh",
86
- ["-o", "BatchMode=yes", "-o", `ConnectTimeout=3`, resolveSshTarget(), buildRemoteCommand(limit)],
94
+ ["-o", "BatchMode=yes", "-o", `ConnectTimeout=3`, resolveSshTarget(), command],
87
95
  { timeout: timeoutMs, encoding: "utf8", maxBuffer: 1024 * 1024 },
88
96
  (error, stdout) => {
89
97
  if (error) {
90
98
  finish(void 0);
91
99
  return;
92
100
  }
93
- finish(parseCiStatusPayload(stdout ?? ""));
101
+ try {
102
+ finish(parse(stdout ?? ""));
103
+ } catch {
104
+ finish(void 0);
105
+ }
94
106
  }
95
107
  );
96
108
  } catch {
@@ -109,8 +121,26 @@ function summarizeLatest(jobs) {
109
121
  }
110
122
  return `ci:${sha} ${latest.status}`;
111
123
  }
124
+ function buildCancelCommand(jobId) {
125
+ const port = resolveCiPort();
126
+ const body = JSON.stringify({ jobId }).replace(/'/g, "'\\''");
127
+ const endpoint = `http://127.0.0.1:${port}/cancel`;
128
+ const tokenRef = `$(grep -m1 '^NOLO_CI_ADMIN_TOKEN=' "$HOME/.config/nolo-ci.env" 2>/dev/null | cut -d= -f2-)`;
129
+ return `curl -s -m 110 -H "Authorization: Bearer ${tokenRef}" -H 'Content-Type: application/json' -X POST --data '${body}' "${endpoint}"`;
130
+ }
131
+ function fetchCiCancel(jobId, timeoutMs = 12e4) {
132
+ return fetchCiPayload(
133
+ buildCancelCommand(jobId),
134
+ (stdout) => {
135
+ const response = JSON.parse(stdout);
136
+ return response?.ok === true && response?.cancelled === true && response?.jobId === jobId ? true : false;
137
+ },
138
+ timeoutMs
139
+ );
140
+ }
112
141
 
113
142
  export {
114
143
  fetchCiStatus,
115
- summarizeLatest
144
+ summarizeLatest,
145
+ fetchCiCancel
116
146
  };