nolo-cli 0.34.0-alpha.3 → 0.35.0-alpha.1

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 (61) hide show
  1. package/{_executeModel-TMUXL7J5.js → _executeModel-RV52PPE3.js} +14 -13
  2. package/{agentDeleteCommand-KA2IQAPG.js → agentDeleteCommand-FBBW3IIM.js} +2 -2
  3. package/{agentEmailCommands-UIYBGCZW.js → agentEmailCommands-7F4PCABZ.js} +14 -13
  4. package/{agentListCommands-L6JNUOLH.js → agentListCommands-ZQXPSB6U.js} +2 -2
  5. package/{agentMachineCommands-5CQW5NZR.js → agentMachineCommands-E3NB67GM.js} +3 -3
  6. package/{agentRecordCommands-VUDJQIZH.js → agentRecordCommands-7PXWHCQM.js} +14 -13
  7. package/{agentRunCommand-EJWYF3BL.js → agentRunCommand-Z4654ONK.js} +15 -14
  8. package/{agentRuntimeLocal-XXBMDMBU.js → agentRuntimeLocal-OBKWKEKW.js} +2 -2
  9. package/{agentSlice-HTIEYKIU.js → agentSlice-B2IMSPH5.js} +1 -1
  10. package/{appDeleteCommands-OUBL6VHB.js → appDeleteCommands-72BE7DSA.js} +2 -2
  11. package/{appDeployCommands-BZSS2MX4.js → appDeployCommands-XJBLKCYO.js} +2 -2
  12. package/{appDeployStatusCommands-P2ZQOY5X.js → appDeployStatusCommands-EC4HWCBQ.js} +2 -2
  13. package/{appGetCommands-WCFWQZZM.js → appGetCommands-62BAATPL.js} +2 -2
  14. package/{appListCommands-FVJ3QNL7.js → appListCommands-5EZCONM7.js} +2 -2
  15. package/{chatQueueReduxAdapter-ZP2ZS63U.js → chatQueueReduxAdapter-SSF3DNBX.js} +2 -2
  16. package/{chunk-P2I7ELDC.js → chunk-2KO5QQFV.js} +1 -1
  17. package/{chunk-TLBZMLLJ.js → chunk-55C3UZSC.js} +3 -3
  18. package/{chunk-5GQ6XCJY.js → chunk-5Q4DXT47.js} +11 -11
  19. package/{chunk-6HIGYUBQ.js → chunk-6XIE5ZGI.js} +1 -1
  20. package/{chunk-PILJX4DH.js → chunk-7KY6U7MW.js} +8 -8
  21. package/chunk-AETZ7AD6.js +274 -0
  22. package/{chunk-I7VDDN45.js → chunk-EFN2AFWF.js} +233 -4
  23. package/{chunk-Z7COG62J.js → chunk-INXNBCEY.js} +2 -2
  24. package/{chunk-EY7V7REW.js → chunk-KHCLMKZZ.js} +6 -280
  25. package/{chunk-XMFDQYWA.js → chunk-KPJYUEPE.js} +1 -1
  26. package/{chunk-WBZE7C6S.js → chunk-LFOILL6R.js} +1 -1
  27. package/{chunk-QI3CHZUT.js → chunk-OCJNJUR4.js} +2 -2
  28. package/chunk-OFZPJ3NT.js +114 -0
  29. package/{chunk-ILZY5B4U.js → chunk-OGPQ3AMC.js} +11 -11
  30. package/{chunk-Y5W623XU.js → chunk-P62APAXL.js} +3 -3
  31. package/{chunk-AA2YUJNV.js → chunk-P66M7LSQ.js} +4 -0
  32. package/{chunk-AE5GVFMG.js → chunk-RUVWTAK7.js} +4 -4
  33. package/{chunk-FT4XBCK4.js → chunk-SDAPQUSO.js} +7 -7
  34. package/{chunk-5LDKQUOT.js → chunk-Z7D7MBWR.js} +1 -1
  35. package/{chunk-RKRXAL3V.js → chunk-ZOEE4OVX.js} +5 -5
  36. package/{chunk-IEEEWIVO.js → chunk-ZZDWMZFU.js} +3 -3
  37. package/{codingSkills-6F4EQFCM.js → codingSkills-H6N5EKSX.js} +3 -2
  38. package/{createAgentAutomationAction-TGUXUZCY.js → createAgentAutomationAction-IDIY6K45.js} +3 -3
  39. package/{createDialogAction-FD5AEOUF.js → createDialogAction-5LB4YBPS.js} +6 -5
  40. package/{createPageAction-NPC3LYNK.js → createPageAction-TJWVDPZD.js} +5 -4
  41. package/{dialogCommands-ZF2RSNCG.js → dialogCommands-44NGBPJJ.js} +2 -2
  42. package/{dialogSlice-6BINHWQT.js → dialogSlice-62JC4ZMX.js} +2 -2
  43. package/{docCreateCommands-4VQ5MOHP.js → docCreateCommands-IOGYJ7F7.js} +5 -4
  44. package/{docDeleteCommands-M7WLNVPB.js → docDeleteCommands-RO4BZWFP.js} +5 -4
  45. package/{docReadCommands-6LU6P2WT.js → docReadCommands-F2KNOJFW.js} +5 -4
  46. package/{docStore-SIUFLABN.js → docStore-ZRNKZZXU.js} +4 -4
  47. package/{docUpdateCommands-S2LX4ENL.js → docUpdateCommands-2VG4AYOC.js} +5 -4
  48. package/{handleSendMessageAction-QVG5YNZY.js → handleSendMessageAction-YB64A32O.js} +2 -2
  49. package/index.js +40 -40
  50. package/{machineCommands-OSEBN7BZ.js → machineCommands-6WPICTON.js} +14 -13
  51. package/{machineWsRunDispatch-NTJQCIIF.js → machineWsRunDispatch-4OGEZTYG.js} +14 -13
  52. package/package.json +1 -1
  53. package/{readlineWorkspace-JPME5S7A.js → readlineWorkspace-BZAZ5YXM.js} +15 -14
  54. package/{runAgentClientLoop-SOKEXCUF.js → runAgentClientLoop-SOZS3YTQ.js} +11 -10
  55. package/{skillDiscovery-GPUDHDTZ.js → skillDiscovery-COX56OBO.js} +2 -1
  56. package/{spaceCommands-Z5JLMFFJ.js → spaceCommands-WEASK3IV.js} +2 -2
  57. package/{spaceSlice-Z3BGCLGX.js → spaceSlice-2QNUKRN6.js} +3 -3
  58. package/{streamAgentChatTurn-INF5RGK4.js → streamAgentChatTurn-BYI7UXAA.js} +13 -12
  59. package/{tools-ZELMSJZ3.js → tools-E6FEUNZY.js} +9 -8
  60. package/{updateDialogTitleAction-EDUCIB7G.js → updateDialogTitleAction-2A3BEXSP.js} +3 -3
  61. package/chunk-2BWU4ORW.js +0 -2574
@@ -13,7 +13,7 @@ import {
13
13
  } from "./chunk-AGGIDPCZ.js";
14
14
  import {
15
15
  runLlm
16
- } from "./chunk-TLBZMLLJ.js";
16
+ } from "./chunk-55C3UZSC.js";
17
17
  import {
18
18
  cleanupCliSessionForDialog
19
19
  } from "./chunk-MGIHZ5CJ.js";
@@ -3519,7 +3519,7 @@ var messageSlice = createSliceWithThunks({
3519
3519
  runtimeOptions: args.runtimeOptions
3520
3520
  });
3521
3521
  if (agentKeyToUse) {
3522
- const { streamAgentChatTurn } = await import("./agentSlice-HTIEYKIU.js");
3522
+ const { streamAgentChatTurn } = await import("./agentSlice-B2IMSPH5.js");
3523
3523
  await dispatch(
3524
3524
  streamAgentChatTurn({
3525
3525
  agentKey: agentKeyToUse,
@@ -4742,7 +4742,7 @@ var deleteDialogThunk = async (payload, thunkApi) => {
4742
4742
  }
4743
4743
  if (isCurrentDialog) {
4744
4744
  await thunkApi.dispatch(resetMsgs());
4745
- const { clearPendingAttachments: clearPendingAttachments2 } = await import("./dialogSlice-6BINHWQT.js");
4745
+ const { clearPendingAttachments: clearPendingAttachments2 } = await import("./dialogSlice-62JC4ZMX.js");
4746
4746
  dispatch(clearPendingAttachments2());
4747
4747
  }
4748
4748
  return { dialogKey, isCurrentDialog, attachmentPlan };
@@ -4750,15 +4750,15 @@ var deleteDialogThunk = async (payload, thunkApi) => {
4750
4750
 
4751
4751
  // packages/chat/dialog/dialogSlice.ts
4752
4752
  var runCreateDialogAction = async (args, thunkApi) => {
4753
- const { createDialogAction } = await import("./createDialogAction-FD5AEOUF.js");
4753
+ const { createDialogAction } = await import("./createDialogAction-5LB4YBPS.js");
4754
4754
  return createDialogAction(args, thunkApi);
4755
4755
  };
4756
4756
  var runCreateAgentAutomationAction = async (args, thunkApi) => {
4757
- const { createAgentAutomationAction } = await import("./createAgentAutomationAction-TGUXUZCY.js");
4757
+ const { createAgentAutomationAction } = await import("./createAgentAutomationAction-IDIY6K45.js");
4758
4758
  return createAgentAutomationAction(args, thunkApi);
4759
4759
  };
4760
4760
  var runUpdateDialogTitleAction = async (args, thunkApi) => {
4761
- const { updateDialogTitleAction } = await import("./updateDialogTitleAction-EDUCIB7G.js");
4761
+ const { updateDialogTitleAction } = await import("./updateDialogTitleAction-2A3BEXSP.js");
4762
4762
  return updateDialogTitleAction(args, thunkApi);
4763
4763
  };
4764
4764
  var runAddDialogAgentAction = async (args, thunkApi) => {
@@ -4782,7 +4782,7 @@ var runSetDialogExtraReferencesAction = async (args, thunkApi) => {
4782
4782
  return setDialogExtraReferencesAction(args, thunkApi);
4783
4783
  };
4784
4784
  var runHandleSendMessageAction = async (args, thunkApi) => {
4785
- const { handleSendMessageAction } = await import("./handleSendMessageAction-QVG5YNZY.js");
4785
+ const { handleSendMessageAction } = await import("./handleSendMessageAction-YB64A32O.js");
4786
4786
  return handleSendMessageAction(args, thunkApi);
4787
4787
  };
4788
4788
  function clearDialogState() {
@@ -4795,7 +4795,7 @@ var createPageAndAddReference = createAsyncThunk(
4795
4795
  async (payload, { dispatch, getState, rejectWithValue }) => {
4796
4796
  const { slateData, jsonData, title, type, fileId, groupId, dialogKey } = payload;
4797
4797
  try {
4798
- const { createDocState } = await import("./docStore-SIUFLABN.js");
4798
+ const { createDocState } = await import("./docStore-ZRNKZZXU.js");
4799
4799
  const pageKey = await createDocState(
4800
4800
  { slateData, title },
4801
4801
  { dispatch, getState }
@@ -0,0 +1,274 @@
1
+ import {
2
+ dump,
3
+ load
4
+ } from "./chunk-KHCLMKZZ.js";
5
+ import {
6
+ asTrimmedNonEmptyStringArray
7
+ } from "./chunk-I42VC5KR.js";
8
+ import {
9
+ asOptionalTrimmedString
10
+ } from "./chunk-G3SUCT4W.js";
11
+
12
+ // packages/ai/skills/skillDocProtocol.ts
13
+ var SKILL_DOC_ENUMS = {
14
+ triggerMode: ["explicit", "required", "recommended"],
15
+ // budgetTier 只服务 WorkflowReferenceConfig;skill 侧已移除(零读点)。
16
+ budgetTier: ["low", "medium", "high"],
17
+ modality: ["text", "image", "video", "audio", "3d"],
18
+ docKind: ["knowledge", "instruction", "skill"]
19
+ };
20
+ var SKILL_CONFIG_BLOCK = "skill-config";
21
+ var EVAL_CONFIG_BLOCK = "eval-config";
22
+ var WORKFLOW_CONFIG_BLOCK = "workflow-config";
23
+ var normalizeStringArray = (value) => {
24
+ if (!Array.isArray(value)) return void 0;
25
+ const items = [...new Set(asTrimmedNonEmptyStringArray(value))];
26
+ return items.length > 0 ? items : void 0;
27
+ };
28
+ var normalizeSkillEnumValue = (key, value) => typeof value === "string" && SKILL_DOC_ENUMS[key].includes(value) ? value : void 0;
29
+ var normalizeSkillModalities = (value) => {
30
+ const raw = normalizeStringArray(value);
31
+ if (!raw) return void 0;
32
+ const filtered = raw.flatMap((item) => {
33
+ const modality = normalizeSkillEnumValue("modality", item);
34
+ return modality ? [modality] : [];
35
+ });
36
+ return filtered.length > 0 ? Array.from(new Set(filtered)) : void 0;
37
+ };
38
+ var normalizeSkillConfig = (value, fallbackTools) => {
39
+ if (!value || typeof value !== "object") return void 0;
40
+ const record = value;
41
+ const name = asOptionalTrimmedString(record.name) ?? "";
42
+ const description = asOptionalTrimmedString(record.description) ?? "";
43
+ if (!name || !description) return void 0;
44
+ const triggerMode = normalizeSkillEnumValue("triggerMode", record.triggerMode);
45
+ const modalities = normalizeSkillModalities(record.modalities);
46
+ const toolNames = normalizeStringArray(record.toolNames) ?? normalizeStringArray(fallbackTools) ?? void 0;
47
+ return {
48
+ version: "0.1",
49
+ kind: "skill",
50
+ id: asOptionalTrimmedString(record.id),
51
+ name,
52
+ description,
53
+ triggerMode,
54
+ toolNames,
55
+ modalities,
56
+ requiredSkills: normalizeStringArray(record.requiredSkills),
57
+ recommendedSkills: normalizeStringArray(record.recommendedSkills),
58
+ promptPatch: asOptionalTrimmedString(record.promptPatch)
59
+ };
60
+ };
61
+ var normalizeEvalConfig = (value) => {
62
+ if (!value || typeof value !== "object") return void 0;
63
+ const record = value;
64
+ if (!Array.isArray(record.cases)) return void 0;
65
+ const cases = [];
66
+ for (const item of record.cases) {
67
+ if (!item || typeof item !== "object") continue;
68
+ const testCase = item;
69
+ const input = asOptionalTrimmedString(testCase.input) ?? "";
70
+ if (!input) continue;
71
+ cases.push({
72
+ input,
73
+ expectedTools: normalizeStringArray(testCase.expectedTools),
74
+ expectedSignals: normalizeStringArray(testCase.expectedSignals),
75
+ forbiddenSignals: normalizeStringArray(testCase.forbiddenSignals)
76
+ });
77
+ }
78
+ return cases.length > 0 ? {
79
+ version: "0.1",
80
+ cases
81
+ } : void 0;
82
+ };
83
+ var normalizeWorkflowConfig = (value) => {
84
+ if (!value || typeof value !== "object") return void 0;
85
+ const record = value;
86
+ const name = asOptionalTrimmedString(record.name) ?? "";
87
+ const description = asOptionalTrimmedString(record.description) ?? "";
88
+ if (!name || !description) return void 0;
89
+ const budgetTier = normalizeSkillEnumValue("budgetTier", record.budgetTier);
90
+ return {
91
+ version: "0.1",
92
+ kind: "workflow",
93
+ id: asOptionalTrimmedString(record.id),
94
+ name,
95
+ description,
96
+ defaultAgent: asOptionalTrimmedString(record.defaultAgent),
97
+ inputs: normalizeStringArray(record.inputs),
98
+ recommendedTools: normalizeStringArray(record.recommendedTools),
99
+ requiredTools: normalizeStringArray(record.requiredTools),
100
+ requiredOutputs: normalizeStringArray(record.requiredOutputs),
101
+ gates: normalizeStringArray(record.gates),
102
+ budgetTier,
103
+ contextStrategy: asOptionalTrimmedString(record.contextStrategy),
104
+ failureProtocol: asOptionalTrimmedString(record.failureProtocol)
105
+ };
106
+ };
107
+ var normalizePageSkillMetadata = (value, fallbackTools) => {
108
+ if (!value || typeof value !== "object") return void 0;
109
+ const record = value;
110
+ const kind = normalizeSkillEnumValue("docKind", record.kind);
111
+ const meta = {
112
+ kind,
113
+ requiredSkills: normalizeStringArray(record.requiredSkills),
114
+ recommendedSkills: normalizeStringArray(record.recommendedSkills),
115
+ skillConfig: normalizeSkillConfig(record.skillConfig, fallbackTools),
116
+ evalConfig: normalizeEvalConfig(record.evalConfig),
117
+ workflowConfig: normalizeWorkflowConfig(record.workflowConfig)
118
+ };
119
+ if (meta.skillConfig && !meta.kind) {
120
+ meta.kind = "skill";
121
+ }
122
+ if (meta.workflowConfig && !meta.kind) {
123
+ meta.kind = "instruction";
124
+ }
125
+ return meta.kind || meta.requiredSkills || meta.recommendedSkills || meta.skillConfig || meta.evalConfig || meta.workflowConfig ? meta : void 0;
126
+ };
127
+ var extractCommentBlock = (markdown, blockName) => {
128
+ if (!markdown) return void 0;
129
+ const matcher = new RegExp(
130
+ `<!--\\s*${blockName}\\s*\\n([\\s\\S]*?)-->`,
131
+ "i"
132
+ );
133
+ const match = markdown.match(matcher);
134
+ return asOptionalTrimmedString(match?.[1]);
135
+ };
136
+ var removeCommentBlock = (markdown, blockName) => markdown.replace(
137
+ new RegExp(`\\n?<!--\\s*${blockName}\\s*\\n[\\s\\S]*?-->\\s*`, "gi"),
138
+ "\n\n"
139
+ );
140
+ var parseYamlObject = (raw) => {
141
+ if (!raw) return void 0;
142
+ try {
143
+ const parsed = load(raw);
144
+ return parsed && typeof parsed === "object" ? parsed : void 0;
145
+ } catch {
146
+ return void 0;
147
+ }
148
+ };
149
+ var parseSkillDocProtocol = (markdown, existingMeta, fallbackTools) => {
150
+ const source = typeof markdown === "string" ? markdown : "";
151
+ const skillBlock = parseYamlObject(extractCommentBlock(source, SKILL_CONFIG_BLOCK));
152
+ const evalBlock = parseYamlObject(extractCommentBlock(source, EVAL_CONFIG_BLOCK));
153
+ const workflowBlock = parseYamlObject(extractCommentBlock(source, WORKFLOW_CONFIG_BLOCK));
154
+ const cleanedContent = removeCommentBlock(
155
+ removeCommentBlock(
156
+ removeCommentBlock(source, SKILL_CONFIG_BLOCK),
157
+ EVAL_CONFIG_BLOCK
158
+ ),
159
+ WORKFLOW_CONFIG_BLOCK
160
+ ).replace(/\n{3,}/g, "\n\n").trim();
161
+ const parsedMeta = normalizePageSkillMetadata(
162
+ {
163
+ ...existingMeta ?? {},
164
+ ...skillBlock ? {
165
+ kind: existingMeta?.kind === "skill" || skillBlock.kind === "skill" ? "skill" : existingMeta?.kind,
166
+ requiredSkills: skillBlock.requiredSkills ?? existingMeta?.requiredSkills,
167
+ recommendedSkills: skillBlock.recommendedSkills ?? existingMeta?.recommendedSkills,
168
+ skillConfig: skillBlock
169
+ } : {},
170
+ ...evalBlock ? { evalConfig: evalBlock } : {},
171
+ ...workflowBlock ? { workflowConfig: workflowBlock } : {}
172
+ },
173
+ fallbackTools
174
+ );
175
+ return {
176
+ content: cleanedContent,
177
+ meta: parsedMeta
178
+ };
179
+ };
180
+ var resolvePageSkillMetadata = (page) => {
181
+ if (!page) return void 0;
182
+ const existingMeta = normalizePageSkillMetadata(page.meta, page.tools);
183
+ return parseSkillDocProtocol(page.content ?? "", existingMeta, page.tools).meta;
184
+ };
185
+ var yamlBlock = (value) => dump(value, { lineWidth: 120, noRefs: true }).trim();
186
+ var buildSkillConfigComment = (config) => {
187
+ const payload = {
188
+ version: config.version,
189
+ kind: config.kind,
190
+ ...config.id ? { id: config.id } : {},
191
+ name: config.name,
192
+ description: config.description,
193
+ ...config.triggerMode ? { triggerMode: config.triggerMode } : {},
194
+ ...config.requiredSkills?.length ? { requiredSkills: config.requiredSkills } : {},
195
+ ...config.recommendedSkills?.length ? { recommendedSkills: config.recommendedSkills } : {},
196
+ ...config.toolNames?.length ? { toolNames: config.toolNames } : {},
197
+ ...config.modalities?.length ? { modalities: config.modalities } : {},
198
+ ...config.promptPatch ? { promptPatch: config.promptPatch } : {}
199
+ };
200
+ return `<!-- ${SKILL_CONFIG_BLOCK}
201
+ ${yamlBlock(payload)}
202
+ -->`;
203
+ };
204
+ var buildEvalConfigComment = (config) => `<!-- ${EVAL_CONFIG_BLOCK}
205
+ ${yamlBlock({
206
+ version: config.version,
207
+ cases: config.cases
208
+ })}
209
+ -->`;
210
+ var buildWorkflowConfigComment = (config) => `<!-- ${WORKFLOW_CONFIG_BLOCK}
211
+ ${yamlBlock({
212
+ version: config.version,
213
+ kind: config.kind,
214
+ ...config.id ? { id: config.id } : {},
215
+ name: config.name,
216
+ description: config.description,
217
+ ...config.defaultAgent ? { defaultAgent: config.defaultAgent } : {},
218
+ ...config.inputs?.length ? { inputs: config.inputs } : {},
219
+ ...config.recommendedTools?.length ? { recommendedTools: config.recommendedTools } : {},
220
+ ...config.requiredTools?.length ? { requiredTools: config.requiredTools } : {},
221
+ ...config.requiredOutputs?.length ? { requiredOutputs: config.requiredOutputs } : {},
222
+ ...config.gates?.length ? { gates: config.gates } : {},
223
+ ...config.budgetTier ? { budgetTier: config.budgetTier } : {},
224
+ ...config.contextStrategy ? { contextStrategy: config.contextStrategy } : {},
225
+ ...config.failureProtocol ? { failureProtocol: config.failureProtocol } : {}
226
+ })}
227
+ -->`;
228
+ var buildSkillDocMarkdown = (options) => {
229
+ const sections = [
230
+ asOptionalTrimmedString(options.body) ?? "",
231
+ buildSkillConfigComment(options.skillConfig),
232
+ options.evalConfig ? buildEvalConfigComment(options.evalConfig) : "",
233
+ options.workflowConfig ? buildWorkflowConfigComment(options.workflowConfig) : ""
234
+ ].filter(Boolean);
235
+ return sections.join("\n\n").trim();
236
+ };
237
+ var extractFrontmatter = (markdown) => {
238
+ const match = markdown.match(/^\s*---\s*\n([\s\S]*?)\n\s*---\s*\n?/);
239
+ if (!match) return { body: markdown.trim() };
240
+ const frontmatter = parseYamlObject(match[1]);
241
+ const body = markdown.slice(match[0].length).trim();
242
+ return { frontmatter, body };
243
+ };
244
+ var normalizeAllowedTools = (value) => {
245
+ if (Array.isArray(value)) {
246
+ return normalizeStringArray(value) ?? [];
247
+ }
248
+ if (typeof value === "string") {
249
+ return value.split(/\s+/).map((item) => item.trim()).filter(Boolean);
250
+ }
251
+ return [];
252
+ };
253
+ var parseExternalSkillMarkdown = (markdown) => {
254
+ const { frontmatter, body } = extractFrontmatter(markdown);
255
+ return {
256
+ name: asOptionalTrimmedString(frontmatter?.name),
257
+ description: asOptionalTrimmedString(frontmatter?.description),
258
+ compatibility: asOptionalTrimmedString(frontmatter?.compatibility),
259
+ allowedTools: normalizeAllowedTools(frontmatter?.["allowed-tools"]),
260
+ metadata: frontmatter?.metadata && typeof frontmatter.metadata === "object" ? Object.fromEntries(
261
+ Object.entries(frontmatter.metadata).filter(([, value]) => typeof value === "string").map(([key, value]) => [key, String(value)])
262
+ ) : void 0,
263
+ body
264
+ };
265
+ };
266
+
267
+ export {
268
+ normalizeStringArray,
269
+ normalizeSkillModalities,
270
+ parseSkillDocProtocol,
271
+ resolvePageSkillMetadata,
272
+ buildSkillDocMarkdown,
273
+ parseExternalSkillMarkdown
274
+ };
@@ -27,7 +27,7 @@ import {
27
27
  hasAssistantVisibleOutput,
28
28
  resolveEmptyAssistantFallbackMessage,
29
29
  resolveEmptyAssistantOutcome
30
- } from "./chunk-AA2YUJNV.js";
30
+ } from "./chunk-P66M7LSQ.js";
31
31
  import {
32
32
  createThinkParserState,
33
33
  createToolCallAccumulator,
@@ -722,6 +722,191 @@ async function maybeAutoCompactLocalHistory(args) {
722
722
  }
723
723
  }
724
724
 
725
+ // packages/agent-runtime/progressGuard.ts
726
+ var DEFAULT_MAX_CONSECUTIVE_IDENTICAL_ROUNDS = 5;
727
+ var DEFAULT_MAX_CONSECUTIVE_STAGNANT_TOOL_ROUNDS = 8;
728
+ function sortJsonKeys(obj) {
729
+ if (obj === null || typeof obj !== "object") return obj;
730
+ if (Array.isArray(obj)) return obj.map(sortJsonKeys);
731
+ const sorted = {};
732
+ for (const key of Object.keys(obj).sort()) {
733
+ sorted[key] = sortJsonKeys(obj[key]);
734
+ }
735
+ return sorted;
736
+ }
737
+ function normalizeToolArguments(rawArgs) {
738
+ if (typeof rawArgs !== "string") {
739
+ try {
740
+ return JSON.stringify(sortJsonKeys(rawArgs ?? ""));
741
+ } catch {
742
+ return String(rawArgs ?? "");
743
+ }
744
+ }
745
+ const trimmed = rawArgs.trim();
746
+ if (!trimmed) return "";
747
+ try {
748
+ const parsed = JSON.parse(trimmed);
749
+ return JSON.stringify(sortJsonKeys(parsed));
750
+ } catch {
751
+ return trimmed;
752
+ }
753
+ }
754
+ function extractNormalizedContentText(content) {
755
+ if (typeof content === "string") return content.trim();
756
+ if (!Array.isArray(content)) return "";
757
+ return content.map((part) => {
758
+ if (part?.type === "text") return String(part.text ?? "").trim();
759
+ if (part?.type === "image_url") return `[img:${part.image_url?.url ?? ""}]`;
760
+ return "";
761
+ }).filter(Boolean).join("\n");
762
+ }
763
+ function buildToolCallsSignature(toolCalls) {
764
+ if (!toolCalls || toolCalls.length === 0) return "";
765
+ return toolCalls.map(
766
+ (tc) => `${tc.function?.name ?? ""}:${normalizeToolArguments(tc.function?.arguments)}`
767
+ ).join(";;");
768
+ }
769
+ function buildAssistantActionFingerprint(result) {
770
+ const content = extractNormalizedContentText(result.content);
771
+ const reasoning = typeof result.reasoning_content === "string" ? result.reasoning_content.trim() : "";
772
+ let toolCallsSig = buildToolCallsSignature(result.tool_calls);
773
+ let hasToolCalls = Array.isArray(result.tool_calls) && result.tool_calls.length > 0;
774
+ if (!toolCallsSig && Array.isArray(result.output) && result.output.length > 0) {
775
+ const blocksToolCalls = result.output.filter(
776
+ (b) => b.type === "toolCall"
777
+ ).map((b) => b.toolCall);
778
+ if (blocksToolCalls.length > 0) {
779
+ toolCallsSig = buildToolCallsSignature(blocksToolCalls);
780
+ hasToolCalls = true;
781
+ }
782
+ }
783
+ const hasNonEmptyText = content.length > 0 || reasoning.length > 0;
784
+ const fingerprint = `${content}##${reasoning}##${toolCallsSig}`;
785
+ return {
786
+ fingerprint,
787
+ hasNonEmptyText,
788
+ hasToolCalls,
789
+ toolCallsSignature: toolCallsSig
790
+ };
791
+ }
792
+ function buildToolResultsSignature(toolExecutions) {
793
+ if (toolExecutions.length === 0) return "";
794
+ return toolExecutions.map((exec) => {
795
+ const contentStr = typeof exec.content === "string" ? exec.content.trim() : "";
796
+ const metaStr = exec.metadata ? JSON.stringify(sortJsonKeys(exec.metadata)) : "";
797
+ return `${exec.toolName}:${contentStr}:${metaStr}`;
798
+ }).join(";;");
799
+ }
800
+ function resolveProgressGuardConfig(options, env = typeof process !== "undefined" ? process.env : {}) {
801
+ const envDisabled = env.NOLO_LOOP_PROGRESS_GUARD_DISABLED === "true" || env.NOLO_LOOP_PROGRESS_GUARD_DISABLED === "1";
802
+ const disabled = options?.disabled ?? envDisabled ?? false;
803
+ const parsePositiveInt = (val, fallback) => {
804
+ if (typeof val === "number" && Number.isFinite(val) && val >= 1) {
805
+ return Math.floor(val);
806
+ }
807
+ if (typeof val === "string") {
808
+ const parsed = parseInt(val, 10);
809
+ if (Number.isFinite(parsed) && parsed >= 1) {
810
+ return parsed;
811
+ }
812
+ }
813
+ return fallback;
814
+ };
815
+ const maxConsecutiveIdenticalRounds = parsePositiveInt(
816
+ options?.maxConsecutiveIdenticalRounds ?? env.NOLO_LOOP_MAX_IDENTICAL_ROUNDS,
817
+ DEFAULT_MAX_CONSECUTIVE_IDENTICAL_ROUNDS
818
+ );
819
+ const maxConsecutiveStagnantToolRounds = parsePositiveInt(
820
+ options?.maxConsecutiveStagnantToolRounds ?? env.NOLO_LOOP_MAX_STAGNANT_TOOL_ROUNDS,
821
+ DEFAULT_MAX_CONSECUTIVE_STAGNANT_TOOL_ROUNDS
822
+ );
823
+ return {
824
+ disabled,
825
+ maxConsecutiveIdenticalRounds,
826
+ maxConsecutiveStagnantToolRounds
827
+ };
828
+ }
829
+ var LocalLoopProgressGuard = class {
830
+ config;
831
+ lastAssistantFingerprint = null;
832
+ lastAssistantHasNonEmptyText = false;
833
+ consecutiveIdenticalCount = 0;
834
+ lastToolCallsSignature = null;
835
+ lastToolResultsSignature = null;
836
+ consecutiveStagnantToolCount = 0;
837
+ constructor(config, env) {
838
+ this.config = resolveProgressGuardConfig(config, env);
839
+ }
840
+ /**
841
+ * 在 LLM 返回 assistant 响应后调用。
842
+ * 仅在纯文本/无工具调用且实质文本相同达到阈值时直接熔断;
843
+ * 若存在工具调用,则不在此处熔断,留待工具执行后结合工具结果综合判定。
844
+ */
845
+ observeAssistantResponse(result) {
846
+ if (this.config.disabled) return { action: "continue" };
847
+ const { fingerprint, hasNonEmptyText, hasToolCalls } = buildAssistantActionFingerprint(result);
848
+ if (this.lastAssistantFingerprint !== null && this.lastAssistantFingerprint === fingerprint) {
849
+ this.consecutiveIdenticalCount += 1;
850
+ if (!hasToolCalls && hasNonEmptyText && this.consecutiveIdenticalCount >= this.config.maxConsecutiveIdenticalRounds) {
851
+ return {
852
+ action: "stall",
853
+ reason: "repetition_loop",
854
+ detail: `Consecutive identical text-only assistant response for ${this.consecutiveIdenticalCount} rounds.`,
855
+ consecutiveRounds: this.consecutiveIdenticalCount
856
+ };
857
+ }
858
+ } else {
859
+ this.lastAssistantFingerprint = fingerprint;
860
+ this.lastAssistantHasNonEmptyText = hasNonEmptyText;
861
+ this.consecutiveIdenticalCount = 1;
862
+ }
863
+ return { action: "continue" };
864
+ }
865
+ /**
866
+ * 在本轮所有工具执行完毕后调用,检查是否陷入停滞死循环。
867
+ * 只有当工具返回内容与元数据完全无变化时才计入无进展 streak;
868
+ * 一旦工具结果发生变化(如合法轮询状态推进),立即重置 identical streak,确保绝不误杀正常长任务。
869
+ */
870
+ observeToolExecution(toolCalls, toolResults) {
871
+ if (this.config.disabled) return { action: "continue" };
872
+ if (!toolCalls || toolCalls.length === 0) return { action: "continue" };
873
+ const toolCallsSig = buildToolCallsSignature(toolCalls);
874
+ const toolResultsSig = buildToolResultsSignature(toolResults);
875
+ const toolCallsUnchanged = this.lastToolCallsSignature !== null && this.lastToolCallsSignature === toolCallsSig;
876
+ const toolResultsUnchanged = this.lastToolResultsSignature !== null && this.lastToolResultsSignature === toolResultsSig;
877
+ if (toolCallsUnchanged && toolResultsUnchanged) {
878
+ this.consecutiveStagnantToolCount += 1;
879
+ if (this.consecutiveIdenticalCount >= this.config.maxConsecutiveIdenticalRounds) {
880
+ return {
881
+ action: "stall",
882
+ reason: "repetition_loop",
883
+ detail: `Consecutive identical assistant response with unchanged tool results for ${this.consecutiveIdenticalCount} rounds.`,
884
+ consecutiveRounds: this.consecutiveIdenticalCount
885
+ };
886
+ }
887
+ if (this.consecutiveStagnantToolCount >= this.config.maxConsecutiveStagnantToolRounds) {
888
+ return {
889
+ action: "stall",
890
+ reason: "stagnant_tool_calls",
891
+ detail: `Consecutive stagnant tool calls with unchanged results for ${this.consecutiveStagnantToolCount} rounds.`,
892
+ consecutiveRounds: this.consecutiveStagnantToolCount
893
+ };
894
+ }
895
+ } else {
896
+ this.lastToolCallsSignature = toolCallsSig;
897
+ this.lastToolResultsSignature = toolResultsSig;
898
+ this.consecutiveStagnantToolCount = 1;
899
+ if (!toolResultsUnchanged) {
900
+ this.consecutiveIdenticalCount = 1;
901
+ }
902
+ }
903
+ return { action: "continue" };
904
+ }
905
+ };
906
+ function createLocalLoopProgressGuard(config, env) {
907
+ return new LocalLoopProgressGuard(config, env);
908
+ }
909
+
725
910
  // packages/agent-runtime/localLoop.ts
726
911
  var LOCAL_AGENT_CONFIG_MISSING_CODE = "LOCAL_AGENT_CONFIG_MISSING";
727
912
  function formatToolExecutionError(args) {
@@ -1490,6 +1675,7 @@ async function runLocalAgentTurn(input) {
1490
1675
  let reasoningEmptyRepairCount = 0;
1491
1676
  let skipFinalAppend = false;
1492
1677
  let partialContent = "";
1678
+ const progressGuard = createLocalLoopProgressGuard(input.progressGuardConfig);
1493
1679
  try {
1494
1680
  const provider = await resolveProviderOnce();
1495
1681
  while (true) {
@@ -1549,6 +1735,23 @@ async function runLocalAgentTurn(input) {
1549
1735
  ...result.provider || agentConfig.provider ? { provider: result.provider || agentConfig.provider } : {}
1550
1736
  });
1551
1737
  }
1738
+ const assistantGuardVerdict = progressGuard.observeAssistantResponse(result);
1739
+ if (assistantGuardVerdict.action === "stall") {
1740
+ emitLoopEvent(input, {
1741
+ kind: "loop-stalled",
1742
+ round,
1743
+ reason: assistantGuardVerdict.reason,
1744
+ detail: assistantGuardVerdict.detail,
1745
+ consecutiveRounds: assistantGuardVerdict.consecutiveRounds,
1746
+ atMs: Date.now()
1747
+ });
1748
+ result = {
1749
+ ...result,
1750
+ content: resolveEmptyAssistantFallbackMessage(assistantGuardVerdict.reason),
1751
+ emptyAssistantFallbackReason: assistantGuardVerdict.reason
1752
+ };
1753
+ break;
1754
+ }
1552
1755
  const toolCalls = result.tool_calls ?? [];
1553
1756
  const rawToolCallsCount = (result.tool_calls?.length ?? 0) || (Array.isArray(result.raw_tool_calls) ? result.raw_tool_calls.length : 0);
1554
1757
  if (toolCalls.length === 0 && rawToolCallsCount === 0) {
@@ -1618,6 +1821,7 @@ ${reasoningTailLog}
1618
1821
  ...result.reasoning_content ? { reasoning_content: result.reasoning_content } : {},
1619
1822
  tool_calls: toolCalls
1620
1823
  });
1824
+ const executedToolResults = [];
1621
1825
  for (const toolCall of toolCalls) {
1622
1826
  throwIfAborted(input);
1623
1827
  const toolName = toolCall.function.name;
@@ -1730,6 +1934,11 @@ ${reasoningTailLog}
1730
1934
  }
1731
1935
  };
1732
1936
  }
1937
+ executedToolResults.push({
1938
+ toolName,
1939
+ content: toolResult.content,
1940
+ metadata: toolResult.metadata
1941
+ });
1733
1942
  messages.push({
1734
1943
  role: "tool",
1735
1944
  content: formatToolMessageContent({
@@ -1742,6 +1951,26 @@ ${reasoningTailLog}
1742
1951
  ...toolResult.metadata ? { tool_result_metadata: toolResult.metadata } : {}
1743
1952
  });
1744
1953
  }
1954
+ const toolExecutionGuardVerdict = progressGuard.observeToolExecution(
1955
+ toolCalls,
1956
+ executedToolResults
1957
+ );
1958
+ if (toolExecutionGuardVerdict.action === "stall") {
1959
+ emitLoopEvent(input, {
1960
+ kind: "loop-stalled",
1961
+ round,
1962
+ reason: toolExecutionGuardVerdict.reason,
1963
+ detail: toolExecutionGuardVerdict.detail,
1964
+ consecutiveRounds: toolExecutionGuardVerdict.consecutiveRounds,
1965
+ atMs: Date.now()
1966
+ });
1967
+ result = {
1968
+ ...result,
1969
+ content: resolveEmptyAssistantFallbackMessage(toolExecutionGuardVerdict.reason),
1970
+ emptyAssistantFallbackReason: toolExecutionGuardVerdict.reason
1971
+ };
1972
+ break;
1973
+ }
1745
1974
  round += 1;
1746
1975
  }
1747
1976
  } catch (error) {
@@ -5903,10 +6132,10 @@ function buildLoadSkillExecutor(args) {
5903
6132
  metadata: { loadSkill: true, resolved: false }
5904
6133
  };
5905
6134
  }
5906
- const { resolveSkillByName } = await import("./skillDiscovery-GPUDHDTZ.js");
6135
+ const { resolveSkillByName } = await import("./skillDiscovery-COX56OBO.js");
5907
6136
  const resolved = resolveSkillByName(args.cwd, name);
5908
6137
  if (!resolved) {
5909
- const { resolveCodingBuiltinSlug, buildCodingSkillContentBySlug } = await import("./codingSkills-6F4EQFCM.js");
6138
+ const { resolveCodingBuiltinSlug, buildCodingSkillContentBySlug } = await import("./codingSkills-H6N5EKSX.js");
5910
6139
  const builtinSlug = resolveCodingBuiltinSlug(name);
5911
6140
  if (builtinSlug) {
5912
6141
  const body = buildCodingSkillContentBySlug(builtinSlug);
@@ -5941,7 +6170,7 @@ ${body}`,
5941
6170
  };
5942
6171
  }
5943
6172
  async function formatUnknownSkillMessage(cwd, requestedName) {
5944
- const { discoverSkills } = await import("./skillDiscovery-GPUDHDTZ.js");
6173
+ const { discoverSkills } = await import("./skillDiscovery-COX56OBO.js");
5945
6174
  let available = [];
5946
6175
  try {
5947
6176
  available = discoverSkills(cwd).map((s) => s.name);
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  updateContentTitle
3
- } from "./chunk-QI3CHZUT.js";
3
+ } from "./chunk-OCJNJUR4.js";
4
4
  import {
5
5
  require_date_fns
6
6
  } from "./chunk-M76ECQRD.js";
@@ -367,7 +367,7 @@ async function saveDocState(arg, { dispatch, getState }) {
367
367
  }
368
368
  }
369
369
  async function createDocState(args, thunkApi) {
370
- const { createPageAction } = await import("./createPageAction-NPC3LYNK.js");
370
+ const { createPageAction } = await import("./createPageAction-TJWVDPZD.js");
371
371
  return createPageAction(args, thunkApi);
372
372
  }
373
373
  function subscribe(listener) {