nolo-cli 0.34.0-alpha.3 → 0.36.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 (66) hide show
  1. package/{_executeModel-TMUXL7J5.js → _executeModel-2S6HNTBF.js} +15 -14
  2. package/{agentDeleteCommand-KA2IQAPG.js → agentDeleteCommand-EJ6RRIGV.js} +3 -3
  3. package/{agentEmailCommands-UIYBGCZW.js → agentEmailCommands-44XJPIUG.js} +15 -14
  4. package/{agentListCommands-L6JNUOLH.js → agentListCommands-HSWVSDLI.js} +3 -3
  5. package/{agentMachineCommands-5CQW5NZR.js → agentMachineCommands-VMWDSASB.js} +4 -4
  6. package/{agentRecordCommands-VUDJQIZH.js → agentRecordCommands-NLRF3ZCV.js} +15 -14
  7. package/{agentRunCommand-EJWYF3BL.js → agentRunCommand-RUCLOMIL.js} +16 -15
  8. package/{agentRuntimeLocal-XXBMDMBU.js → agentRuntimeLocal-GTNYV7LH.js} +3 -3
  9. package/{agentSlice-HTIEYKIU.js → agentSlice-LAILHBMM.js} +1 -1
  10. package/{appDeleteCommands-OUBL6VHB.js → appDeleteCommands-YDXSR75I.js} +3 -3
  11. package/{appDeployCommands-BZSS2MX4.js → appDeployCommands-4X5SN3EF.js} +3 -3
  12. package/{appDeployStatusCommands-P2ZQOY5X.js → appDeployStatusCommands-TK3JKBHH.js} +3 -3
  13. package/{appGetCommands-WCFWQZZM.js → appGetCommands-ZKQHHJYB.js} +3 -3
  14. package/{appListCommands-FVJ3QNL7.js → appListCommands-JRDOEEGV.js} +3 -3
  15. package/{chatQueueReduxAdapter-ZP2ZS63U.js → chatQueueReduxAdapter-DQWFZYNL.js} +2 -2
  16. package/{chunk-P2I7ELDC.js → chunk-2KO5QQFV.js} +1 -1
  17. package/{chunk-6HIGYUBQ.js → chunk-6XIE5ZGI.js} +1 -1
  18. package/{chunk-RKRXAL3V.js → chunk-7MWPUOKI.js} +5 -5
  19. package/chunk-AETZ7AD6.js +274 -0
  20. package/{chunk-IEEEWIVO.js → chunk-ANM6AIWX.js} +3 -3
  21. package/{chunk-PILJX4DH.js → chunk-ARFXKWJH.js} +8 -8
  22. package/{chunk-TLBZMLLJ.js → chunk-CVXDBLYH.js} +3 -3
  23. package/{chunk-QI3CHZUT.js → chunk-D72M3G32.js} +2 -2
  24. package/{chunk-XMFDQYWA.js → chunk-EJAL5LSG.js} +1 -1
  25. package/{chunk-AE5GVFMG.js → chunk-FXZBSLFK.js} +5 -5
  26. package/{chunk-WBZE7C6S.js → chunk-HRSIJO5A.js} +1 -1
  27. package/{chunk-5GQ6XCJY.js → chunk-JK7UM3LT.js} +11 -11
  28. package/{chunk-EY7V7REW.js → chunk-KHCLMKZZ.js} +6 -280
  29. package/{chunk-Z7COG62J.js → chunk-KR74XLMV.js} +2 -2
  30. package/{chunk-I7VDDN45.js → chunk-LBZHTQTD.js} +397 -14
  31. package/{chunk-ILZY5B4U.js → chunk-MUG4FG5J.js} +11 -11
  32. package/{chunk-Y5W623XU.js → chunk-NT3QRCVS.js} +3 -3
  33. package/chunk-OFZPJ3NT.js +114 -0
  34. package/{chunk-AA2YUJNV.js → chunk-P66M7LSQ.js} +4 -0
  35. package/{chunk-5LDKQUOT.js → chunk-QIMPDPEE.js} +1 -1
  36. package/{chunk-M3JQWYBC.js → chunk-T2BZICLK.js} +3 -1
  37. package/chunk-T5HJEUQN.js +956 -0
  38. package/{chunk-FT4XBCK4.js → chunk-YNAGAUJT.js} +7 -7
  39. package/{clipboardy-PRUHGPGC.js → clipboardy-BX4NMYHE.js} +7 -5
  40. package/{codingSkills-6F4EQFCM.js → codingSkills-H6N5EKSX.js} +3 -2
  41. package/{createAgentAutomationAction-TGUXUZCY.js → createAgentAutomationAction-767ZITQJ.js} +3 -3
  42. package/{createDialogAction-FD5AEOUF.js → createDialogAction-H75NDXYH.js} +6 -5
  43. package/{createPageAction-NPC3LYNK.js → createPageAction-KYJYZPLC.js} +5 -4
  44. package/{dialogCommands-ZF2RSNCG.js → dialogCommands-VYH2BY5H.js} +3 -3
  45. package/{dialogSlice-6BINHWQT.js → dialogSlice-YJV3AVFM.js} +2 -2
  46. package/{docCreateCommands-4VQ5MOHP.js → docCreateCommands-JS7A3OHQ.js} +6 -5
  47. package/{docDeleteCommands-M7WLNVPB.js → docDeleteCommands-HG5HNKZR.js} +6 -5
  48. package/{docReadCommands-6LU6P2WT.js → docReadCommands-BH4WN6HH.js} +6 -5
  49. package/{docStore-SIUFLABN.js → docStore-JOODSWDW.js} +4 -4
  50. package/{docUpdateCommands-S2LX4ENL.js → docUpdateCommands-TAXC7LHJ.js} +6 -5
  51. package/{handleSendMessageAction-QVG5YNZY.js → handleSendMessageAction-DGL6H4E4.js} +2 -2
  52. package/index.js +59 -46
  53. package/{machineCommands-OSEBN7BZ.js → machineCommands-4J5NN3JH.js} +15 -14
  54. package/{machineWsRunDispatch-NTJQCIIF.js → machineWsRunDispatch-KBPZKHM2.js} +15 -14
  55. package/package.json +1 -1
  56. package/{readlineWorkspace-JPME5S7A.js → readlineWorkspace-EP2W65SI.js} +35 -27
  57. package/{runAgentClientLoop-SOKEXCUF.js → runAgentClientLoop-B3TTKXIX.js} +12 -11
  58. package/{skillDiscovery-GPUDHDTZ.js → skillDiscovery-COX56OBO.js} +2 -1
  59. package/{spaceCommands-Z5JLMFFJ.js → spaceCommands-Y33JLAKF.js} +3 -3
  60. package/{spaceSlice-Z3BGCLGX.js → spaceSlice-ZKUZSVYD.js} +3 -3
  61. package/{streamAgentChatTurn-INF5RGK4.js → streamAgentChatTurn-PLTB7RMV.js} +14 -13
  62. package/{tools-ZELMSJZ3.js → tools-KQXDW66A.js} +9 -8
  63. package/{updateCommands-MNDUIKN7.js → updateCommands-IYKLF3JX.js} +3 -1
  64. package/{updateDialogTitleAction-EDUCIB7G.js → updateDialogTitleAction-OTYEQJAK.js} +3 -3
  65. package/chunk-2BWU4ORW.js +0 -2574
  66. package/chunk-VFVCYIRQ.js +0 -407
@@ -0,0 +1,114 @@
1
+ import {
2
+ load
3
+ } from "./chunk-KHCLMKZZ.js";
4
+ import {
5
+ buildSkillDiscoveryLayer
6
+ } from "./chunk-3AOLVADY.js";
7
+
8
+ // packages/agent-runtime/skillDiscovery.ts
9
+ import { existsSync, readFileSync, readdirSync, statSync } from "node:fs";
10
+ import { join } from "node:path";
11
+ var SKILL_SCAN_DIRS = [".agents/skills"];
12
+ var MAX_DISCOVERED_SKILLS = 50;
13
+ var MAX_DISCOVERY_DESC_BUDGET = 4e3;
14
+ var MIN_DESC_LENGTH = 80;
15
+ function parseSkillFrontmatter(filePath) {
16
+ try {
17
+ const content = readFileSync(filePath, "utf8").slice(0, 2048);
18
+ const fmMatch = content.match(/^---\n([\s\S]*?)\n---/);
19
+ if (!fmMatch) return {};
20
+ const fm = (() => {
21
+ try {
22
+ return load(fmMatch[1]);
23
+ } catch (err) {
24
+ console.warn(
25
+ `[skillDiscovery] failed to parse frontmatter: ${filePath}: ${err.message}`
26
+ );
27
+ throw err;
28
+ }
29
+ })();
30
+ if (!fm || typeof fm !== "object") return {};
31
+ const name = typeof fm.name === "string" ? fm.name : void 0;
32
+ const rawDesc = fm.description;
33
+ const description = typeof rawDesc === "string" ? rawDesc : rawDesc == null ? void 0 : String(rawDesc);
34
+ const sanitizeName = (s) => s?.trim().replace(/^["']|["']$/g, "").replace(/[\n\r]+/g, " ").slice(0, 200);
35
+ const sanitizeDesc = (s) => s?.trim().replace(/^["']|["']$/g, "").replace(/[\n\r]+/g, " ").slice(0, 200);
36
+ return { name: sanitizeName(name), description: sanitizeDesc(description) };
37
+ } catch {
38
+ return {};
39
+ }
40
+ }
41
+ function discoverSkills(cwd) {
42
+ const skills = [];
43
+ for (const dir of SKILL_SCAN_DIRS) {
44
+ if (skills.length >= MAX_DISCOVERED_SKILLS) break;
45
+ const absDir = join(cwd, dir);
46
+ if (!existsSync(absDir) || !statSync(absDir).isDirectory()) continue;
47
+ try {
48
+ for (const entry of readdirSync(absDir)) {
49
+ if (skills.length >= MAX_DISCOVERED_SKILLS) break;
50
+ const skillMdPath = join(absDir, entry, "SKILL.md");
51
+ if (existsSync(skillMdPath)) {
52
+ const { name, description } = parseSkillFrontmatter(skillMdPath);
53
+ skills.push({ name: name ?? entry, description: description ?? "", relativePath: join(dir, entry, "SKILL.md") });
54
+ continue;
55
+ }
56
+ }
57
+ } catch {
58
+ }
59
+ }
60
+ const totalDescLen = skills.reduce((sum, s) => sum + s.description.length, 0);
61
+ if (totalDescLen > MAX_DISCOVERY_DESC_BUDGET && skills.length > 0) {
62
+ const scale = MAX_DISCOVERY_DESC_BUDGET / totalDescLen;
63
+ for (const s of skills) {
64
+ const targetLen = Math.max(MIN_DESC_LENGTH, Math.floor(s.description.length * scale));
65
+ if (s.description.length > targetLen) {
66
+ s.description = s.description.slice(0, targetLen).trimEnd();
67
+ }
68
+ }
69
+ }
70
+ return skills;
71
+ }
72
+ function resolveSkillByName(cwd, name) {
73
+ const trimmed = name.trim();
74
+ if (!trimmed || trimmed.includes("/") || trimmed.includes("\\") || trimmed.includes("..")) {
75
+ return null;
76
+ }
77
+ const agentsDir = join(cwd, ".agents", "skills", trimmed);
78
+ const agentsSkillMd = join(agentsDir, "SKILL.md");
79
+ if (existsSync(agentsSkillMd)) return agentsSkillMd;
80
+ const agentsParent = join(cwd, ".agents", "skills");
81
+ if (existsSync(agentsParent) && statSync(agentsParent).isDirectory()) {
82
+ try {
83
+ for (const entry of readdirSync(agentsParent)) {
84
+ const candidate = join(agentsParent, entry, "SKILL.md");
85
+ if (!existsSync(candidate)) continue;
86
+ try {
87
+ const { name: fmName } = parseSkillFrontmatter(candidate);
88
+ if (fmName && fmName === trimmed) return candidate;
89
+ } catch {
90
+ }
91
+ }
92
+ } catch {
93
+ }
94
+ }
95
+ return null;
96
+ }
97
+ function buildSkillDiscoveryContextLayer(cwd) {
98
+ try {
99
+ return buildSkillDiscoveryLayer(discoverSkills(cwd), cwd);
100
+ } catch {
101
+ return null;
102
+ }
103
+ }
104
+ function buildSkillDiscoveryContextBlock(cwd) {
105
+ return buildSkillDiscoveryContextLayer(cwd)?.content ?? null;
106
+ }
107
+
108
+ export {
109
+ parseSkillFrontmatter,
110
+ discoverSkills,
111
+ resolveSkillByName,
112
+ buildSkillDiscoveryContextLayer,
113
+ buildSkillDiscoveryContextBlock
114
+ };
@@ -3,6 +3,8 @@ var EMPTY_ASSISTANT_REPAIR_PROMPT = "\u8BF7\u7ED9\u51FA\u660E\u786E\u7684\u6587\
3
3
  var EMPTY_ASSISTANT_FALLBACK_MESSAGE = "\u6A21\u578B\u8FDE\u7EED\u8FD4\u56DE\u7A7A\u6D88\u606F\uFF0C\u5F53\u524D\u4EFB\u52A1\u672A\u5B8C\u6210\u3002\u8BF7\u91CD\u8BD5\u5F53\u524D\u6B65\u9AA4\uFF0C\u6216\u7ED9\u51FA\u66F4\u5177\u4F53\u7684\u4FEE\u6539\u8303\u56F4\u3002";
4
4
  var LENGTH_TRUNCATED_FALLBACK_MESSAGE = "\u8F93\u51FA\u8FBE\u5230\u957F\u5EA6\u4E0A\u9650\u88AB\u622A\u65AD\uFF0C\u5EFA\u8BAE\u7F29\u77ED\u4EFB\u52A1\u6216\u63D0\u9AD8\u8F93\u51FA\u4E0A\u9650\u3002";
5
5
  var STREAM_TRUNCATED_FALLBACK_MESSAGE = "\u4E0A\u6E38\u54CD\u5E94\u6D41\u5728\u6536\u5C3E\u524D\u88AB\u4E2D\u65AD\uFF08\u672A\u6536\u5230\u7ED3\u675F\u6807\u8BB0\uFF09\uFF0C\u672C\u8F6E\u8F93\u51FA\u4E0D\u5B8C\u6574\u3002\u8BF7\u91CD\u8BD5\u5F53\u524D\u6B65\u9AA4\u3002";
6
+ var REPETITION_LOOP_FALLBACK_MESSAGE = "\u68C0\u6D4B\u5230\u6A21\u578B\u9677\u5165\u91CD\u590D\u8F93\u51FA\u6B7B\u5FAA\u73AF\uFF0C\u5DF2\u81EA\u52A8\u7194\u65AD\u7EC8\u6B62\u5F53\u524D\u4EFB\u52A1\u3002";
7
+ var STAGNANT_TOOL_CALLS_FALLBACK_MESSAGE = "\u68C0\u6D4B\u5230\u8FDE\u7EED\u591A\u6B21\u76F8\u540C\u5DE5\u5177\u8C03\u7528\u4E14\u65E0\u5B9E\u8D28\u8FDB\u5C55\uFF0C\u5DF2\u81EA\u52A8\u7194\u65AD\u7EC8\u6B62\u5F53\u524D\u4EFB\u52A1\u3002";
6
8
  var MAX_REASONING_ONLY_REPAIRS = 2;
7
9
  function resolveEmptyAssistantOutcome(args) {
8
10
  if (args.hasToolCalls || args.hasVisibleOutput) return { kind: "ok" };
@@ -20,6 +22,8 @@ function resolveEmptyAssistantOutcome(args) {
20
22
  function resolveEmptyAssistantFallbackMessage(reason) {
21
23
  if (reason === "length_truncated") return LENGTH_TRUNCATED_FALLBACK_MESSAGE;
22
24
  if (reason === "stream_truncated") return STREAM_TRUNCATED_FALLBACK_MESSAGE;
25
+ if (reason === "repetition_loop") return REPETITION_LOOP_FALLBACK_MESSAGE;
26
+ if (reason === "stagnant_tool_calls") return STAGNANT_TOOL_CALLS_FALLBACK_MESSAGE;
23
27
  return EMPTY_ASSISTANT_FALLBACK_MESSAGE;
24
28
  }
25
29
  function hasAssistantVisibleOutput(content) {
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  clearCliLocalRuntimePreparedAgentCache
3
- } from "./chunk-RKRXAL3V.js";
3
+ } from "./chunk-7MWPUOKI.js";
4
4
  import {
5
5
  getReadableCliDb
6
6
  } from "./chunk-UNHKVD2N.js";
@@ -151,7 +151,9 @@ var MENU_USAGE_INSTRUCTIONS = `--- \u4EA4\u4E92\u8BF4\u660E ---
151
151
  \u6240\u6709\u7528\u6237\u8F93\u5165\u5747\u4E3A\u7EAF\u6587\u672C\u6D88\u606F\uFF0C\u76F4\u63A5\u7406\u89E3\u5373\u53EF\uFF0C\u4E0D\u8981\u5728\u56DE\u590D\u4E2D\u63D0\u53CA\u6309\u94AE\u3001\u83DC\u5355\u3001\u754C\u9762\u7B49 UI \u5143\u7D20\u3002
152
152
 
153
153
  ## \u4F55\u65F6\u8C03\u7528 ask_user
154
- \u9ED8\u8BA4\u76F4\u63A5\u884C\u52A8\uFF1A\u80FD\u57FA\u4E8E\u73B0\u6709\u4E0A\u4E0B\u6587\u7ED9\u51FA\u9AD8\u8D28\u91CF\u7B54\u6848\u65F6\u5C31\u76F4\u63A5\u505A\uFF0C\u4E0D\u8981\u4E3A\u4E86\u95EE\u800C\u95EE\uFF1B\u7528\u6237\u76EE\u6807\u5DF2\u5177\u4F53\u6E05\u6670\u65F6\uFF0C\u5373\u4FBF\u5F62\u5F0F\u4E0A\u6EE1\u8DB3\u4E0B\u5217\u6761\u4EF6\u4E5F\u4F18\u5148\u76F4\u63A5\u56DE\u7B54\uFF0C\u4E0D\u5F3A\u884C\u5F39\u83DC\u5355\u3002\u4EC5\u4E09\u79CD\u60C5\u51B5\u8C03\u7528\uFF1A1\uFF09\u9700\u6C42\u5BBD\u6CDB\u6216\u6A21\u7CCA\uFF0C\u7ED9\u51FA 2\uFF5E5 \u4E2A\u4E92\u65A5\u4E14\u90FD\u5408\u7406\u7684\u65B9\u5411\u8BA9\u7528\u6237\u5148\u9009\uFF1B2\uFF09\u8BA1\u5212\u5230\u8FBE\u771F\u6B63\u7684\u5206\u652F\u8282\u70B9\u2014\u2014\u4E0D\u540C\u9009\u62E9\u4F1A\u663E\u8457\u6539\u53D8\u6210\u672C\u3001\u9690\u79C1\u6216\u7ED3\u679C\u8D70\u5411\uFF0C\u4E14\u65E0\u6CD5\u4ECE\u4E0A\u4E0B\u6587\u63A8\u65AD\u7528\u6237\u504F\u597D\uFF1B3\uFF09\u65B0\u4F1A\u8BDD\u5F00\u5934\u9700\u8981\u6309\u7528\u6237\u753B\u50CF\u505A\u529F\u80FD\u5BFC\u822A\u6216\u5F15\u5BFC\u3002
154
+ \u9ED8\u8BA4\u76F4\u63A5\u884C\u52A8\uFF1A\u80FD\u57FA\u4E8E\u73B0\u6709\u4E0A\u4E0B\u6587\u7ED9\u51FA\u9AD8\u8D28\u91CF\u7B54\u6848\u65F6\u5C31\u76F4\u63A5\u505A\uFF0C\u4E0D\u8981\u4E3A\u4E86\u95EE\u800C\u95EE\u3002\u5224\u636E\u662F**\u7528\u6237\u662F\u5426\u9700\u8981\u4E3A\u8FD9\u4E2A\u9009\u62E9\u627F\u62C5\u540E\u679C**\uFF08\u82B1\u94B1\u3001\u6CC4\u9732\u6570\u636E\u3001\u52A8\u7EBF\u4E0A\u3001\u4E0D\u53EF\u56DE\u6EDA\uFF1B\u6216\u8BE5\u9009\u62E9\u7EAF\u5C5E\u4E2A\u4EBA\u53E3\u5473\u3001\u65E0\u4ECE\u63A8\u65AD\uFF09\uFF0C\u800C\u4E0D\u662F"\u8FD9\u4E2A\u9009\u62E9\u4F1A\u4E0D\u4F1A\u5F71\u54CD\u540E\u7EED\u8D70\u5411"\u3002\u4EC5\u4E09\u79CD\u60C5\u51B5\u8C03\u7528\uFF1A1\uFF09\u9700\u6C42\u5BBD\u6CDB\u6216\u6A21\u7CCA\uFF0C\u7ED9\u51FA 2\uFF5E5 \u4E2A\u4E92\u65A5\u4E14\u90FD\u5408\u7406\u7684\u65B9\u5411\u8BA9\u7528\u6237\u5148\u9009\uFF1B2\uFF09\u5206\u53C9\u7684\u540E\u679C\u7531\u7528\u6237\u627F\u62C5\u4E14\u65E0\u6CD5\u4ECE\u4E0A\u4E0B\u6587\u63A8\u65AD\u5176\u504F\u597D\uFF1B3\uFF09\u65B0\u4F1A\u8BDD\u5F00\u5934\u9700\u8981\u6309\u7528\u6237\u753B\u50CF\u505A\u529F\u80FD\u5BFC\u822A\u6216\u5F15\u5BFC\u3002
155
+
156
+ \u4E0D\u8981\u95EE\u7684\uFF08\u5C5E\u4E8E\u4F60\u7684\u804C\u8D23\uFF0C\u95EE\u51FA\u6765\u662F\u628A\u672C\u8BE5\u4F60\u505A\u7684\u5224\u65AD\u63A8\u7ED9\u7528\u6237\uFF09\uFF1A\u5148\u505A\u54EA\u4E2A\u4EFB\u52A1\u3001\u6309\u4EC0\u4E48\u987A\u5E8F\u63A8\u8FDB\u3001\u8981\u4E0D\u8981\u987A\u624B\u4FEE\u67D0\u5904\u3001\u65E5\u5E38\u5B9E\u73B0\u7EC6\u8282\u7528\u54EA\u79CD\u5199\u6CD5\u3001\u8981\u4E0D\u8981\u518D\u68C0\u67E5\u4E00\u904D\u3002\u8FD9\u4E9B\u81EA\u5DF1\u5B9A\uFF0C\u505A\u5B8C\u5728\u56DE\u590D\u91CC\u8BF4\u660E\u7406\u7531\u5373\u53EF\u3002\u6CE8\u610F\u533A\u5206\uFF1A\u67B6\u6784\u9009\u578B\u3001\u6280\u672F\u6808\u3001\u6570\u636E\u5B58\u50A8\u65B9\u6848\u7B49\u957F\u671F\u4E14\u96BE\u56DE\u6EDA\u7684\u6280\u672F\u51B3\u7B56\u4E0D\u5728\u6B64\u5217\u2014\u2014\u5B83\u4EEC\u7684\u540E\u679C\u7531\u7528\u6237\u627F\u62C5\uFF0C\u6309\u4E0A\u8FF0\u7B2C 2 \u6761\u8BE5\u95EE\u5C31\u95EE\u3002\u7528\u6237\u76EE\u6807\u5DF2\u5177\u4F53\u6E05\u6670\u65F6\uFF0C\u5373\u4FBF\u5F62\u5F0F\u4E0A\u6EE1\u8DB3\u524D\u8FF0\u4E09\u79CD\u60C5\u51B5\u4E5F\u4F18\u5148\u76F4\u63A5\u56DE\u7B54\uFF0C\u4E0D\u5F3A\u884C\u5F39\u83DC\u5355\uFF1B\u5C31\u540C\u4E00\u4EF6\u4E8B\u7B2C\u4E8C\u6B21\u5F39\u83DC\u5355\u524D\uFF0C\u5148\u81EA\u68C0\u5224\u636E\u662F\u4E0D\u662F\u7528\u9519\u4E86\u3002
155
157
 
156
158
  ## \u8C03\u7528\u89C4\u8303
157
159
  - \u5148\u5728\u666E\u901A\u56DE\u590D\u6587\u672C\u91CC\u5199\u6E05\u80CC\u666F\u3001\u7406\u7531\u4E0E\u6743\u8861\u518D\u8C03\u7528\u5DE5\u5177\uFF1B\u65E0\u660E\u786E\u63A8\u8350\u9879\u65F6\uFF0C\u5FC5\u987B\u9010\u4E2A\u7B80\u8FF0\u9009\u9879\u4F18\u7F3A\u70B9\u5E2E\u52A9\u6743\u8861\uFF1B