maoda-commander-tt 0.0.21 → 0.0.23

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/main.js CHANGED
@@ -1799,6 +1799,154 @@ var PippitAssetGetCommand = class extends BaseCommand {
1799
1799
  }
1800
1800
  };
1801
1801
 
1802
+ // src/commands/pippit/modules/douyin-video/errors.ts
1803
+ var BASE6 = 15e3;
1804
+ var DouyinVideoError = ((DouyinVideoError2) => {
1805
+ DouyinVideoError2[DouyinVideoError2["MissingUserInput"] = BASE6 + 1] = "MissingUserInput";
1806
+ DouyinVideoError2[DouyinVideoError2["MissingWebToken"] = BASE6 + 2] = "MissingWebToken";
1807
+ DouyinVideoError2[DouyinVideoError2["NetworkRequestFailed"] = BASE6 + 3] = "NetworkRequestFailed";
1808
+ DouyinVideoError2[DouyinVideoError2["ResponseParseFailed"] = BASE6 + 4] = "ResponseParseFailed";
1809
+ DouyinVideoError2[DouyinVideoError2["RequestFailed"] = BASE6 + 5] = "RequestFailed";
1810
+ return DouyinVideoError2;
1811
+ })(DouyinVideoError || {});
1812
+ var missingUserInputError = lvErrorConst(
1813
+ DouyinVideoError.MissingUserInput,
1814
+ "\u7F3A\u5C11\u6296\u97F3\u94FE\u63A5\u53C2\u6570\u3002"
1815
+ );
1816
+ var missingWebTokenError2 = lvErrorConst(
1817
+ DouyinVideoError.MissingWebToken,
1818
+ "\u7F3A\u5C11\u53EF\u7528\u7684 sessionid_pippitcn_web token\uFF0C\u8BF7\u5148\u4F7F\u7528 `tt pippit web-token --region=cn <token>` \u914D\u7F6E token\u3002"
1819
+ );
1820
+ var networkRequestFailedError6 = lvErrorConst(
1821
+ DouyinVideoError.NetworkRequestFailed,
1822
+ "\u8BF7\u6C42\u6296\u97F3\u89C6\u9891\u89E3\u6790\u63A5\u53E3\u5931\u8D25\uFF0C\u8BF7\u68C0\u67E5\u7F51\u7EDC\u548C\u767B\u5F55\u6001\u3002"
1823
+ );
1824
+ var responseParseFailedError5 = lvErrorConst(
1825
+ DouyinVideoError.ResponseParseFailed,
1826
+ "\u89E3\u6790\u6296\u97F3\u89C6\u9891\u89E3\u6790\u63A5\u53E3\u54CD\u5E94\u5931\u8D25\u3002"
1827
+ );
1828
+ var requestFailedError2 = lvErrorConst(
1829
+ DouyinVideoError.RequestFailed,
1830
+ "\u83B7\u53D6\u6296\u97F3\u89C6\u9891\u5730\u5740\u5931\u8D25\u3002"
1831
+ );
1832
+
1833
+ // src/commands/pippit/modules/douyin-video/cn-douyin-video.ts
1834
+ var PARSE_URL = "https://xyq.jianying.com/api/biz/v1/parse/check_input_valid";
1835
+ function normalizeToken4(token) {
1836
+ const trimmed = token.trim();
1837
+ const prefix = "sessionid_pippitcn_web=";
1838
+ if (trimmed.startsWith(prefix)) {
1839
+ return trimmed.slice(prefix.length).trim();
1840
+ }
1841
+ return trimmed;
1842
+ }
1843
+ function createCookieHeader3(token) {
1844
+ return `sessionid_pippitcn_web=${normalizeToken4(token)}`;
1845
+ }
1846
+ function readRecord(value) {
1847
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
1848
+ return void 0;
1849
+ }
1850
+ return value;
1851
+ }
1852
+ function parseVideoUrl(data) {
1853
+ const dataRecord = readRecord(data);
1854
+ const videoInfoRecord = readRecord(dataRecord?.video_info);
1855
+ const videoUrl = videoInfoRecord?.video_url;
1856
+ if (typeof videoUrl !== "string") {
1857
+ return void 0;
1858
+ }
1859
+ const trimmed = videoUrl.trim();
1860
+ return trimmed.length > 0 ? trimmed : void 0;
1861
+ }
1862
+ function parseErrorCode2(ret) {
1863
+ const parsed = typeof ret === "number" ? ret : typeof ret === "string" ? Number.parseInt(ret, 10) : Number.NaN;
1864
+ return Number.isFinite(parsed) ? parsed : DouyinVideoError.RequestFailed;
1865
+ }
1866
+ async function fetchDouyinVideoCn(options) {
1867
+ const webContextResult = await readWebContext("cn" /* CN */);
1868
+ if (!webContextResult.ok) {
1869
+ return webContextResult;
1870
+ }
1871
+ const tokenResult = await readWebToken("cn" /* CN */);
1872
+ if (!tokenResult.ok) {
1873
+ return tokenResult;
1874
+ }
1875
+ const token = tokenResult.value?.trim();
1876
+ if (!token) {
1877
+ return missingWebTokenError2();
1878
+ }
1879
+ const responseResult = await requestJson(
1880
+ PARSE_URL,
1881
+ {
1882
+ method: "POST",
1883
+ headers: {
1884
+ accept: "application/json, text/plain, */*",
1885
+ "content-type": "application/json",
1886
+ cookie: createCookieHeader3(token),
1887
+ Referer: "https://xyq.jianying.com/"
1888
+ },
1889
+ body: JSON.stringify({
1890
+ uid: webContextResult.value.uid,
1891
+ user_input: options.userInput
1892
+ })
1893
+ },
1894
+ {
1895
+ networkRequestFailed: (message) => networkRequestFailedError6(message),
1896
+ responseParseFailed: (message) => responseParseFailedError5(message)
1897
+ }
1898
+ );
1899
+ if (!responseResult.ok) {
1900
+ return responseResult;
1901
+ }
1902
+ const response = responseResult.value;
1903
+ const videoUrl = parseVideoUrl(response.data);
1904
+ if (videoUrl) {
1905
+ return makeOkWith({ video_url: videoUrl });
1906
+ }
1907
+ if (response.ret !== void 0 && String(response.ret) !== "0") {
1908
+ return makeError(
1909
+ parseErrorCode2(response.ret),
1910
+ response.errmsg?.trim() || "\u6296\u97F3\u89C6\u9891\u89E3\u6790\u63A5\u53E3\u8FD4\u56DE\u9519\u8BEF\u3002"
1911
+ );
1912
+ }
1913
+ return requestFailedError2("\u63A5\u53E3\u672A\u8FD4\u56DE data.video_info.video_url\u3002");
1914
+ }
1915
+
1916
+ // src/commands/pippit/modules/douyin-video/douyin-video.ts
1917
+ async function fetchDouyinVideo(options) {
1918
+ return fetchDouyinVideoCn(options);
1919
+ }
1920
+
1921
+ // src/commands/pippit/pippit-douyin-video-command.ts
1922
+ var PippitDouyinVideoCommand = class extends BaseCommand {
1923
+ _meta() {
1924
+ return {
1925
+ name: "douyin-video",
1926
+ description: "\u901A\u8FC7\u6296\u97F3\u94FE\u63A5\u83B7\u53D6\u89C6\u9891\u5730\u5740"
1927
+ };
1928
+ }
1929
+ _configureArguments(cmd) {
1930
+ cmd.argument("<user_input...>", "\u8981\u89E3\u6790\u7684\u6296\u97F3\u94FE\u63A5\u6216\u5B8C\u6574\u5206\u4EAB\u6587\u6848");
1931
+ }
1932
+ async _execute(ctx) {
1933
+ const userInputParts = ctx.args[0] ?? [];
1934
+ const userInput = userInputParts.join(" ").trim();
1935
+ if (!userInput) {
1936
+ const error = missingUserInputError();
1937
+ this._outputJsonError(error.code, error.msg);
1938
+ return this._makeOk();
1939
+ }
1940
+ const result = await fetchDouyinVideo({ userInput });
1941
+ if (!result.ok) {
1942
+ this._outputJsonError(result.code, result.msg);
1943
+ return this._makeOk();
1944
+ }
1945
+ this._outputJsonOk(result.value);
1946
+ return this._makeOk();
1947
+ }
1948
+ };
1949
+
1802
1950
  // src/commands/pippit/pippit-command.ts
1803
1951
  var PippitCommand = class extends BaseSubcommandHost {
1804
1952
  _meta() {
@@ -1816,6 +1964,7 @@ var PippitCommand = class extends BaseSubcommandHost {
1816
1964
  this._addSubcommand(new PippitAssetUploadCommand());
1817
1965
  this._addSubcommand(new PippitWebTokenCommand());
1818
1966
  this._addSubcommand(new PippitAssetGetCommand());
1967
+ this._addSubcommand(new PippitDouyinVideoCommand());
1819
1968
  }
1820
1969
  };
1821
1970
 
@@ -2078,9 +2227,9 @@ var ShortcutBaseCommand = class extends BaseCommand {
2078
2227
  stdio: "inherit",
2079
2228
  shell: true
2080
2229
  });
2081
- return new Promise((resolve8) => {
2230
+ return new Promise((resolve9) => {
2082
2231
  child.on("error", (error) => {
2083
- resolve8(
2232
+ resolve9(
2084
2233
  this._makeError(
2085
2234
  1,
2086
2235
  `\u6267\u884C ${cmdLine} \u5931\u8D25: ${error.message}`
@@ -2089,11 +2238,11 @@ var ShortcutBaseCommand = class extends BaseCommand {
2089
2238
  });
2090
2239
  child.on("close", (code, signal) => {
2091
2240
  if (code === 0) {
2092
- resolve8(this._makeOk());
2241
+ resolve9(this._makeOk());
2093
2242
  return;
2094
2243
  }
2095
2244
  const signalText = signal ? `, signal: ${signal}` : "";
2096
- resolve8(
2245
+ resolve9(
2097
2246
  this._makeError(
2098
2247
  code ?? 1,
2099
2248
  `\u6267\u884C ${cmdLine} \u5931\u8D25${signalText}`
@@ -2188,9 +2337,9 @@ var AiBaseCommand = class extends BaseCommand {
2188
2337
  cwd: process.cwd(),
2189
2338
  stdio: "inherit"
2190
2339
  });
2191
- return new Promise((resolve8) => {
2340
+ return new Promise((resolve9) => {
2192
2341
  child.on("error", (error) => {
2193
- resolve8(
2342
+ resolve9(
2194
2343
  this._makeError(
2195
2344
  1,
2196
2345
  `\u6267\u884C ${command} ${args.join(" ")} \u5931\u8D25: ${error.message}`
@@ -2199,11 +2348,11 @@ var AiBaseCommand = class extends BaseCommand {
2199
2348
  });
2200
2349
  child.on("close", (code, signal) => {
2201
2350
  if (code === 0) {
2202
- resolve8(this._makeOk());
2351
+ resolve9(this._makeOk());
2203
2352
  return;
2204
2353
  }
2205
2354
  const signalText = signal ? `, signal: ${signal}` : "";
2206
- resolve8(
2355
+ resolve9(
2207
2356
  this._makeError(
2208
2357
  code ?? 1,
2209
2358
  `\u6267\u884C ${command} ${args.join(" ")} \u5931\u8D25${signalText}`
@@ -2523,9 +2672,9 @@ var AiImageCommandV2 = class extends AiBaseCommand {
2523
2672
  cwd: process.cwd(),
2524
2673
  stdio: "ignore"
2525
2674
  });
2526
- return new Promise((resolve8) => {
2675
+ return new Promise((resolve9) => {
2527
2676
  child.on("error", (error) => {
2528
- resolve8(
2677
+ resolve9(
2529
2678
  this._makeError(
2530
2679
  1,
2531
2680
  `\u6267\u884C codex ${args.join(" ")} \u5931\u8D25: ${error.message}`
@@ -2534,11 +2683,11 @@ var AiImageCommandV2 = class extends AiBaseCommand {
2534
2683
  });
2535
2684
  child.on("close", (code, signal) => {
2536
2685
  if (code === 0) {
2537
- resolve8(this._makeOk());
2686
+ resolve9(this._makeOk());
2538
2687
  return;
2539
2688
  }
2540
2689
  const signalText = signal ? `, signal: ${signal}` : "";
2541
- resolve8(
2690
+ resolve9(
2542
2691
  this._makeError(
2543
2692
  code ?? 1,
2544
2693
  `\u6267\u884C codex ${args.join(" ")} \u5931\u8D25${signalText}`
@@ -2692,7 +2841,7 @@ var generateUuid = (() => {
2692
2841
 
2693
2842
  // src/commands/pippit/modules/submit-direct/submit-direct-cn.ts
2694
2843
  var SUBMIT_DIRECT_URL = "https://xyq.jianying.com/api/biz/v1/agent/submit_run";
2695
- function normalizeToken4(token) {
2844
+ function normalizeToken5(token) {
2696
2845
  const trimmed = token.trim();
2697
2846
  const prefix = "sessionid_pippitcn_web=";
2698
2847
  if (trimmed.startsWith(prefix)) {
@@ -2700,10 +2849,10 @@ function normalizeToken4(token) {
2700
2849
  }
2701
2850
  return trimmed;
2702
2851
  }
2703
- function createCookieHeader3(token) {
2704
- return `sessionid_pippitcn_web=${normalizeToken4(token)}`;
2852
+ function createCookieHeader4(token) {
2853
+ return `sessionid_pippitcn_web=${normalizeToken5(token)}`;
2705
2854
  }
2706
- function parseErrorCode2(ret) {
2855
+ function parseErrorCode3(ret) {
2707
2856
  const parsed = typeof ret === "number" ? ret : typeof ret === "string" ? Number.parseInt(ret, 10) : Number.NaN;
2708
2857
  return Number.isFinite(parsed) ? parsed : 1;
2709
2858
  }
@@ -2789,7 +2938,7 @@ async function submitDirectCn(options) {
2789
2938
  headers: {
2790
2939
  accept: "application/json, text/plain, */*",
2791
2940
  "content-type": "application/json",
2792
- cookie: createCookieHeader3(token),
2941
+ cookie: createCookieHeader4(token),
2793
2942
  Referer: "https://xyq.jianying.com/"
2794
2943
  },
2795
2944
  body: JSON.stringify({
@@ -2812,7 +2961,7 @@ async function submitDirectCn(options) {
2812
2961
  console.log("=====response", response);
2813
2962
  if (String(response.ret) !== "0") {
2814
2963
  return makeError(
2815
- parseErrorCode2(response.ret),
2964
+ parseErrorCode3(response.ret),
2816
2965
  response.errmsg?.trim() || "\u76F4\u63A5\u63D0\u4EA4\u5931\u8D25\u3002"
2817
2966
  );
2818
2967
  }
@@ -3430,7 +3579,7 @@ function extractErrorText(payload) {
3430
3579
  return void 0;
3431
3580
  }
3432
3581
  function delay(ms) {
3433
- return new Promise((resolve8) => setTimeout(resolve8, ms));
3582
+ return new Promise((resolve9) => setTimeout(resolve9, ms));
3434
3583
  }
3435
3584
  async function appendPollingUrl(pollingUrl, generationId) {
3436
3585
  const locationResult = await resolveConfigLocation();
@@ -3631,7 +3780,7 @@ var AiQueryTaskCommand = class extends AiBaseCommand {
3631
3780
  PPE_ENV,
3632
3781
  "--json"
3633
3782
  ];
3634
- return new Promise((resolve8) => {
3783
+ return new Promise((resolve9) => {
3635
3784
  const child = spawn4(BIN, args, { cwd: process.cwd() });
3636
3785
  let stdout = "";
3637
3786
  let stderr = "";
@@ -3642,7 +3791,7 @@ var AiQueryTaskCommand = class extends AiBaseCommand {
3642
3791
  stderr += chunk.toString();
3643
3792
  });
3644
3793
  child.on("error", (error) => {
3645
- resolve8(
3794
+ resolve9(
3646
3795
  makeError(
3647
3796
  1,
3648
3797
  `\u6267\u884C ${BIN} ${args.join(" ")} \u5931\u8D25: ${error.message}`
@@ -3651,13 +3800,13 @@ var AiQueryTaskCommand = class extends AiBaseCommand {
3651
3800
  });
3652
3801
  child.on("close", (code, signal) => {
3653
3802
  if (code === 0) {
3654
- resolve8(makeOkWith({ stdout, stderr }));
3803
+ resolve9(makeOkWith({ stdout, stderr }));
3655
3804
  return;
3656
3805
  }
3657
3806
  const signalText = signal ? `, signal: ${signal}` : "";
3658
3807
  const stderrText = stderr.trim() ? `
3659
3808
  ${stderr.trim()}` : "";
3660
- resolve8(
3809
+ resolve9(
3661
3810
  makeError(
3662
3811
  code ?? 1,
3663
3812
  `\u6267\u884C ${BIN} ${args.join(" ")} \u5931\u8D25${signalText}${stderrText}`
@@ -3697,7 +3846,7 @@ function tryParseJson(text) {
3697
3846
  }
3698
3847
  }
3699
3848
  function delay2(ms) {
3700
- return new Promise((resolve8) => setTimeout(resolve8, ms));
3849
+ return new Promise((resolve9) => setTimeout(resolve9, ms));
3701
3850
  }
3702
3851
 
3703
3852
  // src/commands/ai/ai-command.ts
@@ -3720,6 +3869,246 @@ var AiCommand = class extends BaseSubcommandHost {
3720
3869
  }
3721
3870
  };
3722
3871
 
3872
+ // src/commands/tool/tool-canvas-command.ts
3873
+ import { readdir as readdir2, readFile as readFile4, stat as stat4 } from "fs/promises";
3874
+ import { homedir as homedir8 } from "os";
3875
+ import { join as join12, resolve as resolve8 } from "path";
3876
+ var MINIMAX_DIR_LIST = ["~/Movies/Hub/Projects/"];
3877
+ var CANVAS_JSON_RELATIVE_PATH = join12(".hilo", "canvas.json");
3878
+ var EMPTY_NODE_ID_PREFIX = "empty";
3879
+ var MARKER_PREFIX = "==";
3880
+ var ToolCanvasCommand = class extends BaseCommand {
3881
+ _meta() {
3882
+ return {
3883
+ name: "canvas",
3884
+ description: "\u67E5\u627E Minimax canvas \u7A7A\u8349\u7A3F\u8282\u70B9"
3885
+ };
3886
+ }
3887
+ _configureArguments(cmd) {
3888
+ cmd.argument("[keyword]", "\u53EF\u9009\uFF1A\u8FC7\u6EE4 prompt \u4E2D\u7684 == \u540E\u7F00");
3889
+ }
3890
+ async _execute(ctx) {
3891
+ const keyword = String(ctx.args[0] ?? "").trim();
3892
+ const result = await findLatestCanvasDraft(keyword);
3893
+ if (!result) {
3894
+ const marker = keyword ? `${MARKER_PREFIX}${keyword}` : MARKER_PREFIX;
3895
+ return this._makeError(1, `\u672A\u627E\u5230\u5305\u542B ${marker} \u7684\u7A7A\u8349\u7A3F node`);
3896
+ }
3897
+ this._outputJson({
3898
+ basePath: result.basePath,
3899
+ type: result.type,
3900
+ prompt: result.prompt
3901
+ });
3902
+ return this._makeOk();
3903
+ }
3904
+ _outputJson(data) {
3905
+ this._output(JSON.stringify(data, null, 2));
3906
+ }
3907
+ };
3908
+ async function findLatestCanvasDraft(keyword) {
3909
+ const markerRegExp = createMarkerRegExp(keyword);
3910
+ const matches = [];
3911
+ for (const rawDir of MINIMAX_DIR_LIST) {
3912
+ const rootDir = expandHomeDir(rawDir);
3913
+ const rootStat = await safeStat(rootDir);
3914
+ if (!rootStat?.isDirectory()) {
3915
+ continue;
3916
+ }
3917
+ const projectEntries = await readdir2(rootDir, { withFileTypes: true });
3918
+ for (const projectEntry of projectEntries) {
3919
+ if (!projectEntry.isDirectory()) {
3920
+ continue;
3921
+ }
3922
+ const projectDir = resolve8(rootDir, projectEntry.name);
3923
+ const canvasPath = join12(projectDir, CANVAS_JSON_RELATIVE_PATH);
3924
+ const canvasStat = await safeStat(canvasPath);
3925
+ if (!canvasStat?.isFile()) {
3926
+ continue;
3927
+ }
3928
+ const projectMatches = await collectMatchesFromCanvas({
3929
+ projectDir,
3930
+ canvasPath,
3931
+ canvasStat,
3932
+ markerRegExp
3933
+ });
3934
+ matches.push(...projectMatches);
3935
+ }
3936
+ }
3937
+ matches.sort(compareCanvasMatches);
3938
+ return matches[0];
3939
+ }
3940
+ async function collectMatchesFromCanvas(options) {
3941
+ const { projectDir, canvasPath, canvasStat, markerRegExp } = options;
3942
+ const canvasJson = await readJsonFile(canvasPath);
3943
+ const canvas = asRecord(canvasJson);
3944
+ const nodes = Array.isArray(canvas?.nodes) ? canvas.nodes : [];
3945
+ const matches = [];
3946
+ nodes.forEach((node, nodeIndex) => {
3947
+ const payload = getDraftPayload(node);
3948
+ if (!payload || !markerRegExp.test(payload.prompt)) {
3949
+ return;
3950
+ }
3951
+ const promptParts = parsePromptJson(payload.promptJson);
3952
+ if (!promptParts) {
3953
+ return;
3954
+ }
3955
+ const prompt = stringifyPromptParts(promptParts);
3956
+ matches.push({
3957
+ basePath: projectDir,
3958
+ type: payload.type,
3959
+ prompt: removeMarkerLine(prompt, markerRegExp),
3960
+ canvasPath,
3961
+ updatedAtMs: canvasStat.mtimeMs,
3962
+ nodeIndex
3963
+ });
3964
+ });
3965
+ return matches;
3966
+ }
3967
+ function createMarkerRegExp(keyword) {
3968
+ const marker = `${MARKER_PREFIX}${keyword}`;
3969
+ return new RegExp(escapeRegExp(marker));
3970
+ }
3971
+ function removeMarkerLine(prompt, markerRegExp) {
3972
+ return prompt.split(/\r?\n/).filter((line) => !markerRegExp.test(line)).join("\n");
3973
+ }
3974
+ function escapeRegExp(value) {
3975
+ return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
3976
+ }
3977
+ function getDraftPayload(node) {
3978
+ const nodeRecord = asRecord(node);
3979
+ if (!nodeRecord) {
3980
+ return void 0;
3981
+ }
3982
+ const type = nodeRecord.type;
3983
+ if (type !== "image" && type !== "video") {
3984
+ return void 0;
3985
+ }
3986
+ const id = nodeRecord.id;
3987
+ if (typeof id !== "string" || !id.startsWith(EMPTY_NODE_ID_PREFIX)) {
3988
+ return void 0;
3989
+ }
3990
+ const data = asRecord(nodeRecord.data);
3991
+ const popoverDraft = asRecord(data?.popoverDraft);
3992
+ if (!popoverDraft) {
3993
+ return void 0;
3994
+ }
3995
+ const payload = asRecord(
3996
+ type === "image" ? popoverDraft.i2i : popoverDraft.i2v
3997
+ );
3998
+ if (!payload) {
3999
+ return void 0;
4000
+ }
4001
+ const prompt = payload.prompt;
4002
+ if (typeof prompt !== "string") {
4003
+ return void 0;
4004
+ }
4005
+ return {
4006
+ type,
4007
+ prompt,
4008
+ promptJson: payload.promptJson
4009
+ };
4010
+ }
4011
+ function parsePromptJson(value) {
4012
+ const parsed = parsePromptJsonValue(value);
4013
+ if (Array.isArray(parsed)) {
4014
+ return parsed;
4015
+ }
4016
+ const parsedRecord = asRecord(parsed);
4017
+ const content = parsedRecord?.content;
4018
+ return Array.isArray(content) ? content : void 0;
4019
+ }
4020
+ function parsePromptJsonValue(value) {
4021
+ if (typeof value !== "string") {
4022
+ return value;
4023
+ }
4024
+ try {
4025
+ return JSON.parse(value);
4026
+ } catch {
4027
+ return void 0;
4028
+ }
4029
+ }
4030
+ function stringifyPromptParts(parts) {
4031
+ return parts.map((part) => stringifyPromptPart(part)).join("");
4032
+ }
4033
+ function stringifyPromptPart(part) {
4034
+ const partRecord = asRecord(part);
4035
+ if (!partRecord) {
4036
+ return "";
4037
+ }
4038
+ const type = partRecord.type;
4039
+ if (type === "text") {
4040
+ const text = partRecord.text;
4041
+ return typeof text === "string" ? text : "";
4042
+ }
4043
+ if (type === "hardBreak") {
4044
+ return "\n";
4045
+ }
4046
+ if (type === "canvasFileRef") {
4047
+ const attrs = asRecord(partRecord.attrs);
4048
+ const filename = attrs?.filename;
4049
+ return typeof filename === "string" ? ` ${filename} ` : "";
4050
+ }
4051
+ const content = partRecord.content;
4052
+ if (Array.isArray(content)) {
4053
+ return stringifyPromptParts(content);
4054
+ }
4055
+ return "";
4056
+ }
4057
+ async function readJsonFile(filePath) {
4058
+ try {
4059
+ const content = await readFile4(filePath, "utf8");
4060
+ return JSON.parse(content);
4061
+ } catch {
4062
+ return void 0;
4063
+ }
4064
+ }
4065
+ async function safeStat(path10) {
4066
+ try {
4067
+ return await stat4(path10);
4068
+ } catch {
4069
+ return void 0;
4070
+ }
4071
+ }
4072
+ function expandHomeDir(path10) {
4073
+ if (path10 === "~") {
4074
+ return homedir8();
4075
+ }
4076
+ if (path10.startsWith("~/")) {
4077
+ return join12(homedir8(), path10.slice(2));
4078
+ }
4079
+ return resolve8(path10);
4080
+ }
4081
+ function asRecord(value) {
4082
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
4083
+ return void 0;
4084
+ }
4085
+ return value;
4086
+ }
4087
+ function compareCanvasMatches(a, b) {
4088
+ const updatedAtDiff = b.updatedAtMs - a.updatedAtMs;
4089
+ if (updatedAtDiff !== 0) {
4090
+ return updatedAtDiff;
4091
+ }
4092
+ const canvasPathDiff = a.canvasPath.localeCompare(b.canvasPath);
4093
+ if (canvasPathDiff !== 0) {
4094
+ return canvasPathDiff;
4095
+ }
4096
+ return a.nodeIndex - b.nodeIndex;
4097
+ }
4098
+
4099
+ // src/commands/tool/tool-command.ts
4100
+ var ToolCommand = class extends BaseSubcommandHost {
4101
+ _meta() {
4102
+ return {
4103
+ name: "tool",
4104
+ description: "\u5E38\u7528\u5DE5\u5177\u547D\u4EE4"
4105
+ };
4106
+ }
4107
+ _registerSubcommands() {
4108
+ this._addSubcommand(new ToolCanvasCommand());
4109
+ }
4110
+ };
4111
+
3723
4112
  // src/main.ts
3724
4113
  var require2 = createRequire(import.meta.url);
3725
4114
  var pkg = require2("../package.json");
@@ -3735,6 +4124,7 @@ async function bootstrap() {
3735
4124
  app.registerCommand(new GitCommand(), { hidden: true });
3736
4125
  app.registerCommand(new ShortcutCommand(), { hidden: true });
3737
4126
  app.registerCommand(new AiCommand(), { hidden: true });
4127
+ app.registerCommand(new ToolCommand(), { hidden: true });
3738
4128
  const result = await app.run();
3739
4129
  if (!result.ok) {
3740
4130
  process.stderr.write(`Fatal: ${result.msg}