maoda-commander-tt 0.0.45 → 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
  }
@@ -3513,19 +3530,26 @@ var XyqSession = class {
3513
3530
  const normalizedInput = normalizedInputResult.value;
3514
3531
  const threadId = randomUUID3();
3515
3532
  const clientRunId = `canvas_run_${randomUUID3()}`;
3533
+ const messageId = randomUUID3();
3516
3534
  const requestId = randomUUID3();
3517
3535
  const submittedAt = this._now();
3536
+ const runExtra = buildVideoPartRunExtra(clientRunId, messageId);
3518
3537
  const body = buildSubmitVideoPartBody({
3519
3538
  ...normalizedInput,
3520
3539
  threadId,
3521
3540
  clientRunId,
3541
+ messageId,
3522
3542
  requestId,
3523
3543
  submittedAt,
3524
- context: this.context
3544
+ context: this.context,
3545
+ runExtra
3525
3546
  });
3547
+ const submitUrl = new URL(`${XYQ_ORIGIN}/api/biz/v1/agent/submit_run`);
3548
+ const { generate_id: _generateId, ...queryBabiParam } = runExtra.babi_param;
3549
+ submitUrl.searchParams.set("babi_param", JSON.stringify(queryBabiParam));
3526
3550
  const responseResult = await requestXyqJson(
3527
3551
  this._fetcher,
3528
- `${XYQ_ORIGIN}/api/biz/v1/agent/submit_run`,
3552
+ submitUrl.toString(),
3529
3553
  {
3530
3554
  method: "POST",
3531
3555
  headers: {
@@ -3958,27 +3982,32 @@ function normalizeVideoAssetReferences(assets, label) {
3958
3982
  }
3959
3983
  return ok19(normalized);
3960
3984
  }
3961
- function buildSubmitVideoPartBody(input) {
3962
- const babiParam = {
3985
+ function buildVideoPartRunExtra(clientRunId, messageId) {
3986
+ return {
3963
3987
  babi_param: {
3964
- generate_id: input.clientRunId,
3965
- section_id: input.clientRunId,
3988
+ generate_id: clientRunId,
3989
+ user_message_id: messageId,
3990
+ section_id: clientRunId,
3966
3991
  scene_lv1: "ai_agent",
3967
3992
  scene_lv2: "front_tool",
3968
- tool_id: "pippit_novel_video_part_agent",
3993
+ tool_id: "novel_canvas",
3969
3994
  tab_name: "canvas",
3970
- edit_type: "video_part",
3995
+ edit_type: "novel",
3971
3996
  enter_from: "web"
3972
3997
  },
3973
3998
  client_extra: {
3974
- edit_type: "video_part",
3999
+ edit_type: "novel",
4000
+ canvas_type: "novel",
3975
4001
  position: "canvas",
3976
4002
  entrance_from: "web",
3977
4003
  tab_name: "canvas",
3978
4004
  target: "video",
3979
- run_source: "video_part"
4005
+ run_source: "video_part",
4006
+ placement_name: "canvas"
3980
4007
  }
3981
4008
  };
4009
+ }
4010
+ function buildSubmitVideoPartBody(input) {
3982
4011
  const contentDataParam = {
3983
4012
  prompt: input.prompt,
3984
4013
  images: input.images,
@@ -4008,7 +4037,7 @@ function buildSubmitVideoPartBody(input) {
4008
4037
  thread_id: input.threadId,
4009
4038
  run_id: input.clientRunId,
4010
4039
  created_at: input.submittedAt,
4011
- message_id: ""
4040
+ message_id: input.messageId
4012
4041
  },
4013
4042
  user_info: {
4014
4043
  consumer_uid: input.context.uid,
@@ -4018,7 +4047,7 @@ function buildSubmitVideoPartBody(input) {
4018
4047
  },
4019
4048
  agent_name: "pippit_novel_video_part_agent",
4020
4049
  entrance_from: "web",
4021
- run_extra: JSON.stringify(babiParam),
4050
+ run_extra: JSON.stringify(input.runExtra),
4022
4051
  request_id: input.requestId
4023
4052
  };
4024
4053
  }
@@ -4856,7 +4885,7 @@ function describeUnsuccessfulTerminalState(state) {
4856
4885
  // src/commands/ai/ai-image-command-v2.ts
4857
4886
  import { spawn as spawn3 } from "node:child_process";
4858
4887
  import * as fs10 from "node:fs/promises";
4859
- import { homedir as homedir9 } from "node:os";
4888
+ import { homedir as homedir10 } from "node:os";
4860
4889
  import * as path11 from "node:path";
4861
4890
  import { err as err10, ok as ok21 } from "rockbed/error";
4862
4891
 
@@ -4914,17 +4943,17 @@ var generateUuid = (() => {
4914
4943
  // src/commands/ai/ai-image-command-v2.ts
4915
4944
  var GENERATED_IMAGES_SUBDIR = "generated_imgs";
4916
4945
  var GENERATED_IMAGES_DIR = path11.join(
4917
- homedir9(),
4946
+ homedir10(),
4918
4947
  ".codex",
4919
4948
  GENERATED_IMAGES_SUBDIR
4920
4949
  );
4921
4950
  var GENERATED_IMAGES_PROMPT_DIR = `~/.codex/${GENERATED_IMAGES_SUBDIR}`;
4922
4951
  var LEGACY_GENERATED_IMAGES_DIR = path11.join(
4923
- homedir9(),
4952
+ homedir10(),
4924
4953
  ".codex",
4925
4954
  "generated_images"
4926
4955
  );
4927
- var CODEX_EMPTY_WORKDIR = path11.join(homedir9(), ".codex-empty");
4956
+ var CODEX_EMPTY_WORKDIR = path11.join(homedir10(), ".codex-empty");
4928
4957
  var AiImageCommandV2 = class extends AiBaseCommand {
4929
4958
  _meta() {
4930
4959
  return {
@@ -6609,8 +6638,8 @@ async function readConfigValue2(settingsReader, key) {
6609
6638
 
6610
6639
  // src/commands/tool/tool-random-files-command.ts
6611
6640
  import { readdir as readdir2, stat as stat3 } from "node:fs/promises";
6612
- import { homedir as homedir10 } from "node:os";
6613
- 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";
6614
6643
  var DEFAULT_COUNT = 1;
6615
6644
  var DEFAULT_SUFFIXES = ["png", "jpeg", "jpg"];
6616
6645
  var DEFAULT_DEPTH = 3;
@@ -6789,7 +6818,7 @@ async function collectMatchingFiles(options) {
6789
6818
  const entries = await safeReadDir(options.folder);
6790
6819
  const files = [];
6791
6820
  for (const entry of entries) {
6792
- const entryPath = join13(options.folder, entry.name);
6821
+ const entryPath = join14(options.folder, entry.name);
6793
6822
  if (entry.isFile()) {
6794
6823
  if (hasAllowedSuffix(entry.name, options.suffixes)) {
6795
6824
  files.push(entryPath);
@@ -6841,10 +6870,10 @@ async function safeStat(path13) {
6841
6870
  }
6842
6871
  function expandHomeDir(path13) {
6843
6872
  if (path13 === "~") {
6844
- return homedir10();
6873
+ return homedir11();
6845
6874
  }
6846
6875
  if (path13.startsWith("~/")) {
6847
- return join13(homedir10(), path13.slice(2));
6876
+ return join14(homedir11(), path13.slice(2));
6848
6877
  }
6849
6878
  return resolve8(path13);
6850
6879
  }