@thinkingai/ae-cli 1.0.27 → 1.0.30

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 (90) hide show
  1. package/README.md +1 -16
  2. package/README.zh.md +1 -16
  3. package/dist/auth-H3GJD55A.js +457 -0
  4. package/dist/{auth-TXFJHPXU.js → auth-U25QJU5D.js} +3 -3
  5. package/dist/{chunk-B4UL2VIJ.js → chunk-CLJF7MQA.js} +1 -1
  6. package/dist/{chunk-6T7245YE.js → chunk-EGEIXA2Z.js} +90 -18
  7. package/dist/{chunk-2NGWYMLB.js → chunk-GLNZSDKO.js} +88 -50
  8. package/dist/chunk-GSJGPNKK.js +49 -0
  9. package/dist/{chunk-VT6VC4PA.js → chunk-I42JGQ2J.js} +26 -11
  10. package/dist/chunk-JM34JPCO.js +239 -0
  11. package/dist/chunk-NOO24N7W.js +11 -0
  12. package/dist/chunk-SF3KTPIC.js +98 -0
  13. package/dist/chunk-SRJIAOBN.js +244 -0
  14. package/dist/chunk-U6TKB3IV.js +171 -0
  15. package/dist/{chunk-TG64AQV4.js → chunk-VJFUB3H3.js} +99 -56
  16. package/dist/{client-IU2E5IOL.js → client-IN42F223.js} +4 -4
  17. package/dist/config-64G36TJL.js +130 -0
  18. package/dist/index.js +52 -25
  19. package/dist/{model-CC7U5XOJ.js → model-VZCYNIOG.js} +11 -10
  20. package/dist/{raw-TUHZQ4UB.js → raw-WJIWC6YP.js} +13 -7
  21. package/dist/{sync-EVEDS7YE.js → sync-NVASAISS.js} +146 -47
  22. package/dist/{te-agent-FLTDYV3L.js → te-agent-YV4DXEXK.js} +24 -23
  23. package/dist/{te-analysis-CMXADIJM.js → te-analysis-CB3DA5I5.js} +61 -13
  24. package/dist/{te-audience-LPZFFSXM.js → te-audience-W7SCQFC7.js} +7 -5
  25. package/dist/{te-common-BXQFKTB3.js → te-common-FBXVWBSI.js} +21 -9
  26. package/dist/{te-community-K5S3VOZY.js → te-community-LNVDZSGW.js} +6 -4
  27. package/dist/{te-dataops-567IMCQG.js → te-dataops-IPCSSWYH.js} +29 -27
  28. package/dist/{te-engage-TBUTGW5F.js → te-engage-KARARMIR.js} +6 -4
  29. package/dist/{te-kb-XHVBWP5E.js → te-kb-2Z2CARN3.js} +7 -5
  30. package/dist/{te-meta-NQ4U3VJW.js → te-meta-PDKLMWXN.js} +6 -4
  31. package/dist/{te-team-556APRIU.js → te-team-SW5B7DHO.js} +17 -12
  32. package/package.json +6 -2
  33. package/skills/ae-agent/SKILL.md +2 -1
  34. package/skills/ae-analysis/SKILL.md +1 -1
  35. package/skills/ae-analysis/references/list_clusters.md +4 -2
  36. package/skills/ae-analysis-global/SKILL.md +51 -0
  37. package/skills/ae-analysis-global/references/list_query_clusters.md +67 -0
  38. package/skills/ae-community/SKILL.md +2 -3
  39. package/skills/ae-dataops/SKILL.md +1 -2
  40. package/skills/ae-engage/SKILL.md +1 -0
  41. package/skills/ae-engage/references/add-approver.md +0 -1
  42. package/skills/ae-engage/references/add-channel.md +0 -1
  43. package/skills/ae-engage/references/approver-list.md +0 -1
  44. package/skills/ae-engage/references/cancel-query-by-request-id.md +0 -1
  45. package/skills/ae-engage/references/channel-detail.md +0 -1
  46. package/skills/ae-engage/references/channel-list.md +0 -1
  47. package/skills/ae-engage/references/config-channel-detail.md +0 -1
  48. package/skills/ae-engage/references/config-channel-list.md +0 -1
  49. package/skills/ae-engage/references/config-item-analysis-report.md +0 -1
  50. package/skills/ae-engage/references/config-item-detail.md +0 -1
  51. package/skills/ae-engage/references/config-item-list.md +0 -1
  52. package/skills/ae-engage/references/config-item-strategy-comparison.md +0 -1
  53. package/skills/ae-engage/references/config-item-trigger-report.md +0 -1
  54. package/skills/ae-engage/references/copy-config-template.md +0 -1
  55. package/skills/ae-engage/references/delete-channel.md +0 -1
  56. package/skills/ae-engage/references/delete-config-channel.md +0 -1
  57. package/skills/ae-engage/references/delete-config-item.md +0 -1
  58. package/skills/ae-engage/references/delete-flow.md +0 -1
  59. package/skills/ae-engage/references/flow-ab-split-node-report.md +0 -1
  60. package/skills/ae-engage/references/flow-detail.md +0 -1
  61. package/skills/ae-engage/references/flow-list.md +0 -1
  62. package/skills/ae-engage/references/flow-node-config-schema.md +0 -1
  63. package/skills/ae-engage/references/flow-node-detail-report.md +0 -1
  64. package/skills/ae-engage/references/flow-node-overview-report.md +0 -1
  65. package/skills/ae-engage/references/flow-process-report.md +0 -1
  66. package/skills/ae-engage/references/manage-flow.md +0 -1
  67. package/skills/ae-engage/references/manage-strategy.md +0 -1
  68. package/skills/ae-engage/references/manage-task.md +0 -1
  69. package/skills/ae-engage/references/modify-flow-base-info.md +0 -1
  70. package/skills/ae-engage/references/strategy-detail.md +0 -1
  71. package/skills/ae-engage/references/strategy-list.md +0 -1
  72. package/skills/ae-engage/references/task-data-detail.md +0 -1
  73. package/skills/ae-engage/references/task-data-overview.md +0 -1
  74. package/skills/ae-engage/references/task-detail.md +0 -1
  75. package/skills/ae-engage/references/task-experiment-report.md +0 -1
  76. package/skills/ae-engage/references/task-list.md +0 -1
  77. package/skills/ae-engage/references/task-metric-detail.md +0 -1
  78. package/skills/ae-engage/references/task-stats.md +0 -1
  79. package/skills/ae-engage/references/update-channel-status.md +0 -1
  80. package/skills/ae-engage/references/update-config-channel-status.md +0 -1
  81. package/skills/ae-engage/references/validate-flow-node-config.md +0 -1
  82. package/skills/ae-engage/references/whitelist-list.md +0 -1
  83. package/skills/ae-kb/SKILL.md +1 -0
  84. package/skills/ae-team/SKILL.md +1 -1
  85. package/dist/auth-W2JZ3DKA.js +0 -170
  86. package/dist/chunk-BI5ZVD6T.js +0 -186
  87. package/dist/chunk-MNHE6SSI.js +0 -79
  88. package/dist/chunk-MWWYGZ76.js +0 -130
  89. package/dist/chunk-SRRUNQIM.js +0 -312
  90. package/dist/config-WH3R3IRY.js +0 -258
@@ -1,6 +1,8 @@
1
1
  import {
2
2
  MultiselectCancelled,
3
3
  SKILL_MANIFEST_FILE,
4
+ assertValidMcpName,
5
+ assertValidSkillSlug,
4
6
  describeSource,
5
7
  getCurrentWorkspace,
6
8
  promptMultiselect,
@@ -8,19 +10,20 @@ import {
8
10
  readSkillManifestEntries,
9
11
  scanMcps,
10
12
  scanSkills,
13
+ splitPushableMcps,
11
14
  writeSkillManifestEntries
12
- } from "./chunk-6T7245YE.js";
15
+ } from "./chunk-EGEIXA2Z.js";
13
16
  import {
14
17
  TeAgentApiError,
15
18
  TeAgentCredentialsError,
16
19
  getSandboxSyncPullCandidates,
17
20
  postSandboxSyncPull,
18
21
  postToMainApp
19
- } from "./chunk-TG64AQV4.js";
22
+ } from "./chunk-VJFUB3H3.js";
20
23
  import {
21
24
  printError
22
- } from "./chunk-B4UL2VIJ.js";
23
- import "./chunk-MNHE6SSI.js";
25
+ } from "./chunk-CLJF7MQA.js";
26
+ import "./chunk-SRJIAOBN.js";
24
27
 
25
28
  // src/commands/sync/index.ts
26
29
  import Table from "cli-table3";
@@ -30,19 +33,57 @@ import {
30
33
  cpSync,
31
34
  existsSync,
32
35
  mkdirSync,
36
+ readFileSync,
33
37
  realpathSync,
34
38
  rmSync,
35
- statSync
39
+ statSync,
40
+ writeFileSync
36
41
  } from "fs";
37
42
  import path from "path";
38
- var SKILL_SLUG_RE = /^[a-z0-9-]+$/;
39
- function updateSkillManifestForSource(sourceDir, slug) {
40
- if (!SKILL_SLUG_RE.test(slug)) {
41
- throw new Error(`\u975E\u6CD5 Skill slug: ${slug}`);
43
+ var MCP_MANIFEST_FILE = ".mcp-manifest.json";
44
+ function isMcpScope(value) {
45
+ return value === "personal" || value === "company" || value === "system";
46
+ }
47
+ function uniqueMcpEntries(entries) {
48
+ const seen = /* @__PURE__ */ new Set();
49
+ const out = [];
50
+ for (const entry of entries) {
51
+ if (seen.has(entry.name)) continue;
52
+ seen.add(entry.name);
53
+ out.push(entry);
42
54
  }
55
+ return out;
56
+ }
57
+ function readMcpManifestEntries(manifestPath) {
58
+ if (!existsSync(manifestPath)) return [];
59
+ let parsed;
60
+ try {
61
+ parsed = JSON.parse(readFileSync(manifestPath, "utf8"));
62
+ } catch {
63
+ return [];
64
+ }
65
+ if (!Array.isArray(parsed)) return [];
66
+ const entries = [];
67
+ for (const item of parsed) {
68
+ if (!item || typeof item !== "object") continue;
69
+ const entry = item;
70
+ if (typeof entry.name !== "string" || !isMcpScope(entry.scope)) continue;
71
+ entries.push({ name: entry.name, scope: entry.scope });
72
+ }
73
+ return uniqueMcpEntries(entries);
74
+ }
75
+ function writeMcpManifestEntries(manifestPath, entries) {
76
+ writeFileSync(
77
+ manifestPath,
78
+ JSON.stringify(uniqueMcpEntries(entries), null, 2) + "\n",
79
+ "utf8"
80
+ );
81
+ }
82
+ function updateSkillManifestForSource(sourceDir, slug) {
83
+ assertValidSkillSlug(slug);
43
84
  const sourceAbs = path.resolve(sourceDir);
44
85
  if (!statSync(sourceAbs).isDirectory()) {
45
- throw new Error(`Skill \u6E90\u8DEF\u5F84\u4E0D\u662F\u76EE\u5F55: ${sourceDir}`);
86
+ throw new Error(`Skill source path is not a directory: ${sourceDir}`);
46
87
  }
47
88
  const manifestPath = path.join(path.dirname(sourceAbs), SKILL_MANIFEST_FILE);
48
89
  const manifest = readSkillManifestEntries(manifestPath);
@@ -60,16 +101,36 @@ function updateSkillManifestForSource(sourceDir, slug) {
60
101
  writeSkillManifestEntries(manifestPath, nextManifest);
61
102
  return { manifestPath, changed: true };
62
103
  }
63
- function copySkillPackageToTarget(args) {
64
- if (!SKILL_SLUG_RE.test(args.slug)) {
65
- throw new Error(`\u975E\u6CD5 Skill slug: ${args.slug}`);
104
+ function updateMcpManifestForProjectSource(workspaceDir, name) {
105
+ assertValidMcpName(name);
106
+ const workspaceAbs = path.resolve(workspaceDir);
107
+ if (!statSync(workspaceAbs).isDirectory()) {
108
+ throw new Error(`MCP workspace path is not a directory: ${workspaceDir}`);
109
+ }
110
+ const manifestPath = path.join(workspaceAbs, MCP_MANIFEST_FILE);
111
+ const manifest = readMcpManifestEntries(manifestPath);
112
+ const nextEntry = { name, scope: "personal" };
113
+ const existingIndex = manifest.findIndex((entry) => entry.name === name);
114
+ if (existingIndex >= 0 && manifest[existingIndex].scope === nextEntry.scope) {
115
+ return { manifestPath, changed: false };
116
+ }
117
+ const nextManifest = manifest.slice();
118
+ if (existingIndex >= 0) {
119
+ nextManifest[existingIndex] = nextEntry;
120
+ } else {
121
+ nextManifest.push(nextEntry);
66
122
  }
123
+ writeMcpManifestEntries(manifestPath, nextManifest);
124
+ return { manifestPath, changed: true };
125
+ }
126
+ function copySkillPackageToTarget(args) {
127
+ assertValidSkillSlug(args.slug);
67
128
  if (!path.isAbsolute(args.targetRoot)) {
68
- throw new Error(`skillTargetRoot \u5FC5\u987B\u662F\u7EDD\u5BF9\u8DEF\u5F84: ${args.targetRoot}`);
129
+ throw new Error(`skillTargetRoot must be an absolute path: ${args.targetRoot}`);
69
130
  }
70
131
  const sourceReal = realpathSync(args.sourceDir);
71
132
  if (!statSync(sourceReal).isDirectory()) {
72
- throw new Error(`Skill \u6E90\u8DEF\u5F84\u4E0D\u662F\u76EE\u5F55: ${args.sourceDir}`);
133
+ throw new Error(`Skill source path is not a directory: ${args.sourceDir}`);
73
134
  }
74
135
  const targetDir = path.join(args.targetRoot, args.slug);
75
136
  const targetAbs = path.resolve(targetDir);
@@ -101,6 +162,13 @@ function redactEnv(env) {
101
162
  }
102
163
  return out;
103
164
  }
165
+ var SOURCE_ORDER = {
166
+ global: 0,
167
+ workspace: 1,
168
+ project: 0,
169
+ local: 1,
170
+ user: 2
171
+ };
104
172
  function skillToItem(s) {
105
173
  return {
106
174
  kind: "skill",
@@ -122,6 +190,7 @@ function mcpToItem(m, includeSecrets) {
122
190
  scope: "personal",
123
191
  source: m.source,
124
192
  workspacePath: m.workspacePath,
193
+ workspaceDir: m.workspaceDir,
125
194
  event: "upsert",
126
195
  transport: m.transport,
127
196
  url: m.url,
@@ -134,11 +203,11 @@ function mcpToItem(m, includeSecrets) {
134
203
  async function selectSkills() {
135
204
  const all = scanSkills();
136
205
  if (all.length === 0) {
137
- process.stderr.write("\u672A\u627E\u5230\u4EFB\u4F55 Skill\uFF08\u626B\u63CF\u4E86\u5F53\u524D\u5DE5\u4F5C\u7A7A\u95F4 .claude/skills\uFF09\n");
206
+ process.stderr.write("No Skills found (scanned current workspace .claude/skills)\n");
138
207
  return [];
139
208
  }
140
209
  all.sort((a, b) => {
141
- if (a.source !== b.source) return a.source === "global" ? -1 : 1;
210
+ if (a.source !== b.source) return SOURCE_ORDER[a.source] - SOURCE_ORDER[b.source];
142
211
  return a.slug.localeCompare(b.slug);
143
212
  });
144
213
  const items = all.map((s) => ({
@@ -147,26 +216,36 @@ async function selectSkills() {
147
216
  group: describeSource(s),
148
217
  hint: s.isSymlink ? "(symlink)" : void 0
149
218
  }));
150
- const picked = await promptMultiselect({ title: "\u9009\u62E9\u8981\u63A8\u9001\u5230\u4E3B\u5E94\u7528\u7684 Skill", items });
219
+ const picked = await promptMultiselect({ title: "Select Skills to push to the main app", items });
151
220
  return picked.map(skillToItem);
152
221
  }
153
222
  async function selectMcps(includeSecrets) {
154
223
  const all = scanMcps();
155
224
  if (all.length === 0) {
156
- process.stderr.write("\u672A\u627E\u5230\u4EFB\u4F55 MCP\uFF08\u626B\u63CF\u4E86\u5F53\u524D\u5DE5\u4F5C\u7A7A\u95F4 .mcp.json / .claude/.claude.json \u4E0E\u5168\u5C40 ~/.claude.json\uFF09\n");
225
+ process.stderr.write("No MCPs found (scanned current workspace .mcp.json / .claude/.claude.json and global ~/.claude.json)\n");
157
226
  return [];
158
227
  }
159
- all.sort((a, b) => {
160
- if (a.source !== b.source) return a.source === "global" ? -1 : 1;
228
+ const { supported, unsupportedStdio } = splitPushableMcps(all);
229
+ if (unsupportedStdio.length > 0) {
230
+ const names = unsupportedStdio.map((m) => m.slug).sort().join(", ");
231
+ process.stderr.write(`ae-cli sync push only supports http/sse MCPs; skipped stdio MCPs: ${names}
232
+ `);
233
+ }
234
+ if (supported.length === 0) {
235
+ process.stderr.write("No syncable MCPs found. ae-cli sync push only supports http/sse.\n");
236
+ return [];
237
+ }
238
+ supported.sort((a, b) => {
239
+ if (a.source !== b.source) return SOURCE_ORDER[a.source] - SOURCE_ORDER[b.source];
161
240
  return a.slug.localeCompare(b.slug);
162
241
  });
163
- const items = all.map((m) => ({
242
+ const items = supported.map((m) => ({
164
243
  value: m,
165
244
  label: m.slug,
166
245
  group: describeSource(m),
167
- hint: m.hasSecrets && !includeSecrets ? "(env \u5DF2\u8131\u654F)" : void 0
246
+ hint: m.hasSecrets && !includeSecrets ? "(env redacted)" : void 0
168
247
  }));
169
- const picked = await promptMultiselect({ title: "\u9009\u62E9\u8981\u63A8\u9001\u5230\u4E3B\u5E94\u7528\u7684 MCP", items });
248
+ const picked = await promptMultiselect({ title: "Select MCPs to push to the main app", items });
170
249
  return picked.map((m) => mcpToItem(m, includeSecrets));
171
250
  }
172
251
  function renderResults(results) {
@@ -178,7 +257,7 @@ function renderResults(results) {
178
257
  const failed = results.filter((r) => r.status === "failed").length;
179
258
  if (failed > 0) {
180
259
  process.stderr.write(`
181
- \u2717 \u6709 ${failed} \u9879\u5931\u8D25
260
+ \u2717 ${failed} item(s) failed
182
261
  `);
183
262
  }
184
263
  }
@@ -193,7 +272,7 @@ async function selectPullResources(args) {
193
272
  return scopeDiff !== 0 ? scopeDiff : a.name.localeCompare(b.name);
194
273
  });
195
274
  if (all.length === 0) {
196
- process.stderr.write(`${args.title} \u65E0\u53EF\u540C\u6B65\u5019\u9009
275
+ process.stderr.write(`${args.title}: no candidates available to sync
197
276
  `);
198
277
  return [];
199
278
  }
@@ -210,7 +289,7 @@ function toHttpItems(items) {
210
289
  const { kind: _kind2, dirPath: _dirPath, ...rest2 } = item;
211
290
  return rest2;
212
291
  }
213
- const { kind: _kind, ...rest } = item;
292
+ const { kind: _kind, workspaceDir: _workspaceDir, ...rest } = item;
214
293
  return rest;
215
294
  });
216
295
  }
@@ -245,7 +324,7 @@ function copySyncedSkillPackages(skillItems, resp) {
245
324
  if (!item) continue;
246
325
  if (!resp.skillTargetRoot) {
247
326
  result.status = "failed";
248
- result.message = "\u4E3B\u5E94\u7528\u54CD\u5E94\u7F3A\u5C11 skillTargetRoot\uFF0C\u65E0\u6CD5\u590D\u5236 Skill package";
327
+ result.message = "Main app response is missing skillTargetRoot; cannot copy Skill package";
249
328
  continue;
250
329
  }
251
330
  try {
@@ -256,34 +335,54 @@ function copySyncedSkillPackages(skillItems, resp) {
256
335
  });
257
336
  updateSkillManifestForSource(item.dirPath, item.slug);
258
337
  if (copied.skipped) {
259
- result.message = "\u6E90\u76EE\u5F55\u5DF2\u662F\u76EE\u6807\u76EE\u5F55\uFF0C\u8DF3\u8FC7\u672C\u5730\u590D\u5236";
338
+ result.message = "Source directory is already the target directory; local copy skipped";
260
339
  }
261
340
  } catch (err) {
262
341
  result.status = "failed";
263
- result.message = `\u672C\u5730\u590D\u5236\u5931\u8D25\uFF1A${err?.message ?? String(err)}`;
342
+ result.message = `Local copy failed: ${err?.message ?? String(err)}`;
343
+ }
344
+ }
345
+ }
346
+ function updateSyncedProjectMcpManifest(mcpItems, resp) {
347
+ if (mcpItems.length === 0) return;
348
+ const bySlug = new Map(mcpItems.map((item) => [item.slug, item]));
349
+ for (const result of resp.results) {
350
+ if (result.kind !== "mcp" || result.status !== "synced") continue;
351
+ const item = bySlug.get(result.slug);
352
+ if (!item || item.source !== "project") continue;
353
+ if (!item.workspaceDir) {
354
+ result.status = "failed";
355
+ result.message = "Main app synced the MCP, but local MCP manifest update failed: missing workspaceDir";
356
+ continue;
357
+ }
358
+ try {
359
+ updateMcpManifestForProjectSource(item.workspaceDir, item.slug);
360
+ } catch (err) {
361
+ result.status = "failed";
362
+ result.message = `Main app synced the MCP, but local MCP manifest update failed: ${err?.message ?? String(err)}`;
264
363
  }
265
364
  }
266
365
  }
267
366
  async function selectDirection(optsDirection) {
268
367
  if (optsDirection === "push" || optsDirection === "pull") return optsDirection;
269
368
  if (optsDirection) {
270
- throw new Error("--direction \u4EC5\u652F\u6301 push \u6216 pull");
369
+ throw new Error("--direction must be push or pull");
271
370
  }
272
371
  return promptSingleSelect({
273
- title: "\u540C\u6B65\u65B9\u5411\uFF1F",
372
+ title: "Sync direction?",
274
373
  items: [
275
- { value: "push", label: "\u5DE5\u4F5C\u7A7A\u95F4 -> \u4E3B\u5E94\u7528" },
276
- { value: "pull", label: "\u4E3B\u5E94\u7528 -> \u5DE5\u4F5C\u7A7A\u95F4" }
374
+ { value: "push", label: "Workspace -> Main app" },
375
+ { value: "pull", label: "Main app -> Workspace" }
277
376
  ]
278
377
  });
279
378
  }
280
379
  async function selectKind(optsKind) {
281
380
  if (optsKind === "skill" || optsKind === "mcp" || optsKind === "both") return optsKind;
282
381
  if (optsKind) {
283
- throw new Error("--kind \u4EC5\u652F\u6301 skill\u3001mcp \u6216 both");
382
+ throw new Error("--kind must be skill, mcp, or both");
284
383
  }
285
384
  return promptSingleSelect({
286
- title: "\u540C\u6B65\u54EA\u7C7B\u8D44\u6E90\uFF1F",
385
+ title: "Which resource type to sync?",
287
386
  items: [
288
387
  { value: "skill", label: "Skills" },
289
388
  { value: "mcp", label: "MCPs" },
@@ -295,10 +394,10 @@ async function runPush(kind, includeSecrets) {
295
394
  const skillItems = kind !== "mcp" ? await selectSkills() : [];
296
395
  const mcpItems = kind !== "skill" ? await selectMcps(includeSecrets) : [];
297
396
  if (skillItems.length === 0 && mcpItems.length === 0) {
298
- process.stderr.write("\u672A\u9009\u62E9\u4EFB\u4F55\u9879\uFF0C\u5DF2\u9000\u51FA\n");
397
+ process.stderr.write("Nothing selected, exiting\n");
299
398
  return;
300
399
  }
301
- process.stderr.write(`\u63A8\u9001 ${skillItems.length} \u4E2A Skill / ${mcpItems.length} \u4E2A MCP ...
400
+ process.stderr.write(`Pushing ${skillItems.length} Skill(s) / ${mcpItems.length} MCP(s) ...
302
401
  `);
303
402
  const allResults = [];
304
403
  if (skillItems.length > 0) {
@@ -308,6 +407,7 @@ async function runPush(kind, includeSecrets) {
308
407
  }
309
408
  if (mcpItems.length > 0) {
310
409
  const mcpResp = await pushItems("mcp", mcpItems);
410
+ updateSyncedProjectMcpManifest(mcpItems, mcpResp);
311
411
  allResults.push(...mcpResp.results);
312
412
  }
313
413
  renderResults(allResults);
@@ -323,32 +423,31 @@ function pullResultRows(resp) {
323
423
  async function runPull(kind) {
324
424
  const workspace = getCurrentWorkspace();
325
425
  if (!workspace) {
326
- throw new Error("\u672A\u8BC6\u522B\u5F53\u524D\u5DE5\u4F5C\u7A7A\u95F4\uFF0C\u8BF7\u5728 /home/ta/workspaces/<workspace> \u4E0B\u6267\u884C");
426
+ throw new Error("Current workspace not recognized; please run from within /home/ta/workspaces/<workspace>");
327
427
  }
328
428
  const candidates = await getSandboxSyncPullCandidates({
329
429
  workspacePath: workspace.name,
330
430
  kind
331
431
  });
332
432
  const skillItems = kind !== "mcp" ? await selectPullResources({
333
- title: "\u9009\u62E9\u8981\u540C\u6B65\u5230\u5DE5\u4F5C\u7A7A\u95F4\u7684 Skill",
334
- candidates: candidates.skills ?? []
433
+ title: "Select Skills to sync to workspace",
434
+ candidates: (candidates.skills ?? []).filter((candidate) => candidate.scope !== "system")
335
435
  }) : [];
336
436
  const mcpItems = kind !== "skill" ? await selectPullResources({
337
- title: "\u9009\u62E9\u8981\u540C\u6B65\u5230\u5DE5\u4F5C\u7A7A\u95F4\u7684 MCP",
437
+ title: "Select MCPs to sync to workspace",
338
438
  candidates: candidates.mcp ?? []
339
439
  }) : [];
340
440
  if (skillItems.length === 0 && mcpItems.length === 0) {
341
- process.stderr.write("\u672A\u9009\u62E9\u4EFB\u4F55\u9879\uFF0C\u5DF2\u9000\u51FA\n");
441
+ process.stderr.write("Nothing selected, exiting\n");
342
442
  return;
343
443
  }
344
- process.stderr.write(`\u540C\u6B65\u5230\u5DE5\u4F5C\u7A7A\u95F4 ${skillItems.length} \u4E2A Skill / ${mcpItems.length} \u4E2A MCP ...
444
+ process.stderr.write(`Syncing to workspace: ${skillItems.length} Skill(s) / ${mcpItems.length} MCP(s) ...
345
445
  `);
346
446
  const resp = await postSandboxSyncPull({
347
447
  workspacePath: workspace.name,
348
448
  kind,
349
449
  skills: skillItems.map((item) => item.id),
350
- mcp: mcpItems.map((item) => item.id),
351
- ifUnmodifiedSince: candidates.mtime
450
+ mcp: mcpItems.map((item) => item.id)
352
451
  });
353
452
  renderResults(pullResultRows(resp));
354
453
  }
@@ -361,7 +460,7 @@ function registerSync(program) {
361
460
  else await runPull(kind);
362
461
  } catch (err) {
363
462
  if (err instanceof MultiselectCancelled) {
364
- process.stderr.write("\u5DF2\u53D6\u6D88\n");
463
+ process.stderr.write("Cancelled\n");
365
464
  return;
366
465
  }
367
466
  if (err instanceof TeAgentCredentialsError) {
@@ -4,7 +4,8 @@ import {
4
4
  patchToMainApp,
5
5
  postToMainApp,
6
6
  uploadToMainApp
7
- } from "./chunk-TG64AQV4.js";
7
+ } from "./chunk-VJFUB3H3.js";
8
+ import "./chunk-SRJIAOBN.js";
8
9
 
9
10
  // src/commands/te-agent/models.ts
10
11
  var BASE_PATH = "/api/sandbox/agent/models";
@@ -19,7 +20,7 @@ var listModels = {
19
20
  validate: (ctx) => {
20
21
  const scope = ctx.str("scope");
21
22
  if (scope && !["personal", "company", "system"].includes(scope)) {
22
- throw new Error("--scope \u5FC5\u987B\u662F personal\u3001company \u6216 system");
23
+ throw new Error("--scope must be personal, company, or system");
23
24
  }
24
25
  },
25
26
  dryRun: (ctx) => {
@@ -52,7 +53,7 @@ var addModel = {
52
53
  try {
53
54
  new URL(baseUrl);
54
55
  } catch {
55
- throw new Error("--base-url \u5FC5\u987B\u662F\u6709\u6548 URL");
56
+ throw new Error("--base-url must be a valid URL");
56
57
  }
57
58
  },
58
59
  dryRun: (ctx) => ({
@@ -131,7 +132,7 @@ var listMcps = {
131
132
  validate: (ctx) => {
132
133
  const scope = ctx.str("scope");
133
134
  if (scope && !["personal", "company", "system"].includes(scope)) {
134
- throw new Error("--scope \u5FC5\u987B\u662F personal\u3001company \u6216 system");
135
+ throw new Error("--scope must be personal, company, or system");
135
136
  }
136
137
  },
137
138
  dryRun: (ctx) => {
@@ -161,22 +162,22 @@ var addMcp = {
161
162
  validate: (ctx) => {
162
163
  const name = ctx.str("name");
163
164
  if (!/^[a-zA-Z][a-zA-Z0-9_-]*$/.test(name)) {
164
- throw new Error("--name \u5FC5\u987B\u4EE5\u5B57\u6BCD\u5F00\u5934\uFF0C\u4EC5\u5305\u542B\u5B57\u6BCD\u3001\u6570\u5B57\u3001_\u3001-");
165
+ throw new Error("--name must start with a letter and contain only letters, digits, _, or -");
165
166
  }
166
167
  if (name.length < 2 || name.length > 64) {
167
- throw new Error("--name \u957F\u5EA6\u5FC5\u987B\u5728 2-64 \u4E4B\u95F4");
168
+ throw new Error("--name length must be between 2 and 64");
168
169
  }
169
170
  try {
170
171
  new URL(ctx.str("url"));
171
172
  } catch {
172
- throw new Error("--url \u5FC5\u987B\u662F\u6709\u6548 URL");
173
+ throw new Error("--url must be a valid URL");
173
174
  }
174
175
  if (!/^https?:\/\//i.test(ctx.str("url"))) {
175
- throw new Error("--url \u4EC5\u652F\u6301 http:// \u6216 https:// \u534F\u8BAE");
176
+ throw new Error("--url only supports http:// or https:// protocols");
176
177
  }
177
178
  const transport = ctx.str("transport");
178
179
  if (transport && !["sse", "http"].includes(transport)) {
179
- throw new Error("--transport \u5FC5\u987B\u662F sse \u6216 http");
180
+ throw new Error("--transport must be sse or http");
180
181
  }
181
182
  },
182
183
  dryRun: (ctx) => ({
@@ -249,7 +250,7 @@ async function resolveInstructions(raw) {
249
250
  chunks.push(chunk);
250
251
  }
251
252
  const text = Buffer.concat(chunks).toString("utf8").trim();
252
- if (!text) throw new Error("stdin \u4E3A\u7A7A\uFF0C\u65E0\u6CD5\u8BFB\u53D6 instructions");
253
+ if (!text) throw new Error("stdin is empty; cannot read instructions");
253
254
  return text;
254
255
  }
255
256
  return raw;
@@ -265,7 +266,7 @@ var listSkills = {
265
266
  validate: (ctx) => {
266
267
  const scope = ctx.str("scope");
267
268
  if (scope && !["personal", "company", "system"].includes(scope)) {
268
- throw new Error("--scope \u5FC5\u987B\u662F personal\u3001company \u6216 system");
269
+ throw new Error("--scope must be personal, company, or system");
269
270
  }
270
271
  },
271
272
  dryRun: (ctx) => {
@@ -293,7 +294,7 @@ var addSkill = {
293
294
  validate: (ctx) => {
294
295
  const name = ctx.str("name");
295
296
  if (name.length < 1 || name.length > 80) {
296
- throw new Error("--name \u957F\u5EA6\u5FC5\u987B\u5728 1-80 \u4E4B\u95F4");
297
+ throw new Error("--name length must be between 1 and 80");
297
298
  }
298
299
  },
299
300
  dryRun: (ctx) => ({
@@ -388,21 +389,21 @@ function resolveFilePaths(ctx) {
388
389
  const file = ctx.str("file");
389
390
  const files = ctx.str("files");
390
391
  if (file && files) {
391
- throw new Error("--file \u548C --files \u4E0D\u80FD\u540C\u65F6\u4F7F\u7528");
392
+ throw new Error("--file and --files cannot be used together");
392
393
  }
393
394
  if (!file && !files) {
394
- throw new Error("\u5FC5\u987B\u6307\u5B9A --file \u6216 --files");
395
+ throw new Error("Either --file or --files must be specified");
395
396
  }
396
397
  if (file) return [file];
397
398
  try {
398
399
  const parsed = JSON.parse(files);
399
- if (!Array.isArray(parsed)) throw new Error("--files \u5FC5\u987B\u662F JSON \u6570\u7EC4");
400
+ if (!Array.isArray(parsed)) throw new Error("--files must be a JSON array");
400
401
  return parsed.map((p) => {
401
- if (typeof p !== "string") throw new Error("--files \u6570\u7EC4\u5143\u7D20\u5FC5\u987B\u662F\u5B57\u7B26\u4E32");
402
+ if (typeof p !== "string") throw new Error("--files array elements must be strings");
402
403
  return p;
403
404
  });
404
405
  } catch (err) {
405
- if (err instanceof SyntaxError) throw new Error("--files \u5FC5\u987B\u662F\u6709\u6548 JSON \u6570\u7EC4");
406
+ if (err instanceof SyntaxError) throw new Error("--files must be a valid JSON array");
406
407
  throw err;
407
408
  }
408
409
  }
@@ -411,7 +412,7 @@ async function uploadFiles(filePaths) {
411
412
  for (const filePath of filePaths) {
412
413
  const resolved = resolve(filePath);
413
414
  if (!existsSync(resolved)) {
414
- throw new Error(`\u6587\u4EF6\u4E0D\u5B58\u5728\uFF1A${resolved}`);
415
+ throw new Error(`File not found: ${resolved}`);
415
416
  }
416
417
  const buffer = readFileSync(resolved);
417
418
  const mimeType = guessMimeType(resolved);
@@ -434,7 +435,7 @@ var listAttachments = {
434
435
  validate: (ctx) => {
435
436
  const type = ctx.str("type");
436
437
  if (type && !["image", "document"].includes(type)) {
437
- throw new Error("--type \u5FC5\u987B\u662F image \u6216 document");
438
+ throw new Error("--type must be image or document");
438
439
  }
439
440
  },
440
441
  dryRun: (ctx) => {
@@ -496,22 +497,22 @@ var delAttachment = {
496
497
 
497
498
  // src/commands/te-agent/index.ts
498
499
  var commands = [
499
- // 模型管理
500
+ // Model management
500
501
  listModels,
501
502
  addModel,
502
503
  delModel,
503
504
  toggleModel,
504
- // MCP 服务管理
505
+ // MCP server management
505
506
  listMcps,
506
507
  addMcp,
507
508
  delMcp,
508
509
  toggleMcp,
509
- // Skill 管理
510
+ // Skill management
510
511
  listSkills,
511
512
  addSkill,
512
513
  delSkill,
513
514
  toggleSkill,
514
- // 附件库管理
515
+ // Attachment library management
515
516
  listAttachments,
516
517
  addAttachment,
517
518
  delAttachment