maoda-commander-tt 0.0.46 → 0.0.47

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/README.md CHANGED
@@ -58,6 +58,92 @@ pnpm build
58
58
  pnpm start -- --help
59
59
  ```
60
60
 
61
+ ## 发布到 npm
62
+
63
+ 发布采用 GitHub Actions + npm Trusted Publishing(OIDC)。本地 `pnpm pub` 负责
64
+ 检查、递增 patch 版本、提交版本和推送 `tt-v<版本>` 标签;GitHub Actions 在
65
+ `template-commander/` 中重新安装依赖、测试、构建,再发布 `maoda-commander-tt`。
66
+
67
+ ### 首次配置
68
+
69
+ 1. 将本次改造提交到 `main` 并推送到 `imaoda/local-multi-repo`,确保仓库根目录的
70
+ `.github/workflows/publish-tt.yml` 已在 GitHub 上,且仓库已启用 Actions。
71
+ 2. 登录 [npm 包设置](https://www.npmjs.com/package/maoda-commander-tt/access),
72
+ 在 Trusted publishing 中添加 GitHub Actions,填写:
73
+
74
+ | 字段 | 值 |
75
+ |---|---|
76
+ | Organization or user | `imaoda` |
77
+ | Repository | `local-multi-repo` |
78
+ | Workflow filename | `publish-tt.yml` |
79
+ | Environment name | 留空 |
80
+ | Allowed actions | 允许直接执行 `npm publish` |
81
+
82
+ Workflow filename 只填文件名。只允许 `npm stage publish` 时,发布仍需人工批准。
83
+ 保存信任配置时需完成一次 npm 账号验证,后续工作流发布使用 OIDC,无需配置
84
+ `NPM_TOKEN` 或逐次登录 npm。
85
+ 3. 按下面的日常流程发布,在 GitHub Actions 中确认第一次发布成功。
86
+
87
+ 网页保存异常时,也可以使用官方 CLI 配置同一个信任关系(终端登录及配置时
88
+ 按 npm 提示完成账号验证):
89
+
90
+ ```bash
91
+ npm exec --yes --package=npm@11.16.0 -- npm login --registry=https://registry.npmjs.org
92
+ npm exec --yes --package=npm@11.16.0 -- npm trust github maoda-commander-tt \
93
+ --repo imaoda/local-multi-repo --file publish-tt.yml --allow-publish --yes \
94
+ --registry=https://registry.npmjs.org
95
+ ```
96
+
97
+ 工作流使用 GitHub 托管的 runner、Node.js 24、npm 11.16.0 和 pnpm 11.1.2,
98
+ 并固定第三方 Action 的提交 SHA。当前 GitHub 仓库为私有仓库,因此不会生成
99
+ npm provenance;这不影响 OIDC 发布。
100
+
101
+ ### 日常发布
102
+
103
+ 由 agent 代办时,直接说“发布 tt”即可;agent 按
104
+ [发布 harness](AGENTS.md) 执行检查、发布、等待 npm 目标版本可用,并在本机
105
+ 全局安装该精确版本、验证 `tt --version`。无需用户自行执行下面的命令。
106
+
107
+ 先提交代码,确保整个 Git 仓库没有未提交或未跟踪的文件,并切换到 `main`。
108
+ 本地 `main` 可以有尚未推送的提交,但不能落后于远端或与远端分叉。
109
+
110
+ ```bash
111
+ cd ~/work/local-multi-repo/template-commander
112
+ pnpm pub
113
+ ```
114
+
115
+ 命令会运行源码测试、发布脚本测试、构建和 CLI 帮助检查,然后只修改本包的
116
+ `package.json` 版本、创建发布提交和带注释的 `tt-v<版本>` 标签,原子推送
117
+ `main` 与这个标签。其他包的标签不会随之推送。CI 会校验标签与包版本一致;
118
+ 普通代码推送不会触发 npm 发布。
119
+
120
+ 推送成功表示已触发 CI,最终结果以
121
+ [Publish tt 工作流](https://github.com/imaoda/local-multi-repo/actions/workflows/publish-tt.yml)
122
+ 为准。等待本次发布结束再发布下一版;GitHub 的并发队列可能替换尚未开始的
123
+ 发布任务。发布后,在需要更新本机全局 `tt` 的电脑上运行 `pnpm upd`。
124
+
125
+ ### 失败后继续
126
+
127
+ - 本地检查失败:先修复并提交,再运行 `pnpm pub`;检查失败不会递增版本。
128
+ - 推送失败但发布提交和标签已生成:按终端提示修复网络或权限,在原发布提交上
129
+ 运行 `pnpm pub --retry`,重推同一版本,避免再次递增。
130
+ - 推送成功但 CI 失败:若只是 npm 信任配置错误,修正后在 Actions 中重跑失败的
131
+ 工作流;若需修改代码,提交修复后通过 `pnpm pub` 发布新版本。
132
+
133
+ 不要在 CI 中运行 `pnpm pub`:它负责本地版本提交和推送,CI 的最终发布步骤是
134
+ `npm publish`。已发布的版本不能重复发布。
135
+
136
+ 参见 [npm Trusted Publishing 文档](https://docs.npmjs.com/trusted-publishers/)。
137
+
138
+ ## Shell 快捷方式
139
+
140
+ ```bash
141
+ # 在 ~/work/web-proxy 中先执行 w2 start,成功后执行 pnpm gateway
142
+ tt sc w2
143
+ ```
144
+
145
+ 命令日志直接输出到当前终端,gateway 在前台运行。
146
+
61
147
  ## AI 音频生成
62
148
 
63
149
  `ai audio` 接受一段自然语言提示词并等待 XYQ 返回 MP3。参考音频可选;提供时,
@@ -187,6 +273,10 @@ return missingNameError();
187
273
  | `pnpm build` | TypeScript 编译 |
188
274
  | `pnpm start` | 运行编译后产物 |
189
275
  | `pnpm clean` | 清理 dist 目录 |
276
+ | `pnpm test:release` | 在临时 Git 仓库中验证发布脚本 |
277
+ | `pnpm pub` | 检查、升 patch 版本并推送 tt 标签,触发 CI 发布 |
278
+ | `pnpm pub --retry` | 重推当前发布提交和标签,不递增版本 |
279
+ | `pnpm upd` | 将本机全局 tt 更新到 npm 上的最新版本 |
190
280
 
191
281
  ## 技术栈
192
282
 
package/dist/main.js CHANGED
@@ -2335,6 +2335,22 @@ var ShortcutEmoPippitCommand = class extends ShortcutBaseCommand {
2335
2335
  }
2336
2336
  };
2337
2337
 
2338
+ // src/commands/shortcut/shortcut-w2-command.ts
2339
+ import { homedir as homedir5 } from "node:os";
2340
+ import { join as join7 } from "node:path";
2341
+ var ShortcutW2Command = class extends ShortcutBaseCommand {
2342
+ _meta() {
2343
+ return {
2344
+ name: "w2",
2345
+ description: "\u542F\u52A8 web-proxy \u7684 whistle \u548C gateway"
2346
+ };
2347
+ }
2348
+ async _execute(_ctx) {
2349
+ const cwd = join7(homedir5(), "work", "web-proxy");
2350
+ return this._runCommandLine("w2 start && pnpm gateway", cwd);
2351
+ }
2352
+ };
2353
+
2338
2354
  // src/commands/shortcut/shortcut-command.ts
2339
2355
  var ShortcutCommand = class extends BaseSubcommandHost {
2340
2356
  _meta() {
@@ -2348,6 +2364,7 @@ var ShortcutCommand = class extends BaseSubcommandHost {
2348
2364
  this._addSubcommand(new ShortcutEmoLynxCommand());
2349
2365
  this._addSubcommand(new ShortcutEmoPippitCommand());
2350
2366
  this._addSubcommand(new ShortcutEmoPippitCnCommand());
2367
+ this._addSubcommand(new ShortcutW2Command());
2351
2368
  }
2352
2369
  };
2353
2370
 
@@ -2471,21 +2488,21 @@ var AiWebSearchCommand = class extends AiBaseCommand {
2471
2488
  };
2472
2489
 
2473
2490
  // src/commands/ai/ai-run-command.ts
2474
- import { homedir as homedir6 } from "node:os";
2475
- import { join as join8 } from "node:path";
2491
+ import { homedir as homedir7 } from "node:os";
2492
+ import { join as join9 } from "node:path";
2476
2493
  import { ok as ok15 } from "rockbed/error";
2477
2494
 
2478
2495
  // src/commands/ai/ai-context-path.ts
2479
2496
  import { existsSync as existsSync2 } from "node:fs";
2480
- import { homedir as homedir5 } from "node:os";
2481
- import { join as join7 } from "node:path";
2497
+ import { homedir as homedir6 } from "node:os";
2498
+ import { join as join8 } from "node:path";
2482
2499
  import { err as err7, ok as ok14 } from "rockbed/error";
2483
2500
  function getCurrentCloudRootPath() {
2484
2501
  if (process.platform !== "darwin") {
2485
2502
  return err7(1, "`--my` \u4EC5\u652F\u6301\u5728 macOS \u4E0A\u4F7F\u7528");
2486
2503
  }
2487
- const cloudRootPath = join7(
2488
- homedir5(),
2504
+ const cloudRootPath = join8(
2505
+ homedir6(),
2489
2506
  "Library",
2490
2507
  "Mobile Documents",
2491
2508
  "com~apple~CloudDocs"
@@ -2513,7 +2530,7 @@ var AI_RUN_CONTEXT_ALIASES = [
2513
2530
  return cloudRoot;
2514
2531
  }
2515
2532
  return ensureDirectoryExists(
2516
- join8(cloudRoot.value, "icloud-hub", "local-knowlege-base")
2533
+ join9(cloudRoot.value, "icloud-hub", "local-knowlege-base")
2517
2534
  );
2518
2535
  }
2519
2536
  },
@@ -2522,7 +2539,7 @@ var AI_RUN_CONTEXT_ALIASES = [
2522
2539
  optionDescription: "\u53C2\u8003 ~/work/smart-agent/dymamic-skills \u5B66\u4E60 skill",
2523
2540
  resolveReferenceDir: () => {
2524
2541
  return ensureDirectoryExists(
2525
- join8(homedir6(), "work", "smart-agent", "dynamic-skills")
2542
+ join9(homedir7(), "work", "smart-agent", "dynamic-skills")
2526
2543
  );
2527
2544
  }
2528
2545
  }
@@ -4868,7 +4885,7 @@ function describeUnsuccessfulTerminalState(state) {
4868
4885
  // src/commands/ai/ai-image-command-v2.ts
4869
4886
  import { spawn as spawn3 } from "node:child_process";
4870
4887
  import * as fs10 from "node:fs/promises";
4871
- import { homedir as homedir9 } from "node:os";
4888
+ import { homedir as homedir10 } from "node:os";
4872
4889
  import * as path11 from "node:path";
4873
4890
  import { err as err10, ok as ok21 } from "rockbed/error";
4874
4891
 
@@ -4926,17 +4943,17 @@ var generateUuid = (() => {
4926
4943
  // src/commands/ai/ai-image-command-v2.ts
4927
4944
  var GENERATED_IMAGES_SUBDIR = "generated_imgs";
4928
4945
  var GENERATED_IMAGES_DIR = path11.join(
4929
- homedir9(),
4946
+ homedir10(),
4930
4947
  ".codex",
4931
4948
  GENERATED_IMAGES_SUBDIR
4932
4949
  );
4933
4950
  var GENERATED_IMAGES_PROMPT_DIR = `~/.codex/${GENERATED_IMAGES_SUBDIR}`;
4934
4951
  var LEGACY_GENERATED_IMAGES_DIR = path11.join(
4935
- homedir9(),
4952
+ homedir10(),
4936
4953
  ".codex",
4937
4954
  "generated_images"
4938
4955
  );
4939
- var CODEX_EMPTY_WORKDIR = path11.join(homedir9(), ".codex-empty");
4956
+ var CODEX_EMPTY_WORKDIR = path11.join(homedir10(), ".codex-empty");
4940
4957
  var AiImageCommandV2 = class extends AiBaseCommand {
4941
4958
  _meta() {
4942
4959
  return {
@@ -6621,8 +6638,8 @@ async function readConfigValue2(settingsReader, key) {
6621
6638
 
6622
6639
  // src/commands/tool/tool-random-files-command.ts
6623
6640
  import { readdir as readdir2, stat as stat3 } from "node:fs/promises";
6624
- import { homedir as homedir10 } from "node:os";
6625
- import { extname as extname4, join as join13, resolve as resolve8 } from "node:path";
6641
+ import { homedir as homedir11 } from "node:os";
6642
+ import { extname as extname4, join as join14, resolve as resolve8 } from "node:path";
6626
6643
  var DEFAULT_COUNT = 1;
6627
6644
  var DEFAULT_SUFFIXES = ["png", "jpeg", "jpg"];
6628
6645
  var DEFAULT_DEPTH = 3;
@@ -6801,7 +6818,7 @@ async function collectMatchingFiles(options) {
6801
6818
  const entries = await safeReadDir(options.folder);
6802
6819
  const files = [];
6803
6820
  for (const entry of entries) {
6804
- const entryPath = join13(options.folder, entry.name);
6821
+ const entryPath = join14(options.folder, entry.name);
6805
6822
  if (entry.isFile()) {
6806
6823
  if (hasAllowedSuffix(entry.name, options.suffixes)) {
6807
6824
  files.push(entryPath);
@@ -6853,10 +6870,10 @@ async function safeStat(path13) {
6853
6870
  }
6854
6871
  function expandHomeDir(path13) {
6855
6872
  if (path13 === "~") {
6856
- return homedir10();
6873
+ return homedir11();
6857
6874
  }
6858
6875
  if (path13.startsWith("~/")) {
6859
- return join13(homedir10(), path13.slice(2));
6876
+ return join14(homedir11(), path13.slice(2));
6860
6877
  }
6861
6878
  return resolve8(path13);
6862
6879
  }