@xiaohhhh1/canvas-agent 0.4.13 → 0.4.14

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.
@@ -117,6 +117,7 @@ export function startHttpServer() {
117
117
  app.get("/agent/workflow/downloads", (_req, res) => res.json({ ok: true, ...workflows.downloadState() }));
118
118
  app.post("/agent/workflow/downloads/select-directory", (_req, res) => res.json({ ok: true, selection: workflows.startDownloadDirectorySelection() }));
119
119
  app.get("/agent/workflow/downloads/select-directory/:selectionId", route(async (req, res) => res.json({ ok: true, selection: workflows.downloadDirectorySelection(routeParam(req.params.selectionId)), ...workflows.downloadState() })));
120
+ app.post("/agent/workflow/downloads/set-directory", route(async (req, res) => res.json({ ok: true, ...await workflows.setDownloadDirectory(req.body?.directory) })));
120
121
  app.post("/agent/workflow/downloads/clear-directory", (_req, res) => res.json({ ok: true, ...workflows.clearDownloadDirectory() }));
121
122
  app.post("/agent/workflow/downloads/subscriptions", route(async (req, res) => res.json({ ok: true, subscription: workflows.subscribeDownload(req.body || {}) })));
122
123
  app.post("/agent/workflow/downloads/:batchId/sync", route(async (req, res) => res.json({ ok: true, subscription: await workflows.syncDownload(routeParam(req.params.batchId)) })));
@@ -149,6 +149,19 @@ export declare class WorkflowManager {
149
149
  updatedAt: string;
150
150
  }[];
151
151
  }>;
152
+ setDownloadDirectory(directoryValue: unknown): Promise<{
153
+ configured: boolean;
154
+ directoryName: string | undefined;
155
+ subscriptions: {
156
+ batchId: string;
157
+ status: DownloadStatus;
158
+ downloaded: number;
159
+ market: string | undefined;
160
+ message: string | undefined;
161
+ expiresAt: string | undefined;
162
+ updatedAt: string;
163
+ }[];
164
+ }>;
152
165
  private scheduleScript;
153
166
  /** 同一台电脑串行处理脚本交接,避免多个大批次争用一个 Codex app-server。 */
154
167
  private pumpScriptQueue;
@@ -153,6 +153,20 @@ export class WorkflowManager {
153
153
  await this.syncDownloads(batchId);
154
154
  return batchId ? publicDownload(this.downloadRecord(batchId)) : this.downloadState();
155
155
  }
156
+ async setDownloadDirectory(directoryValue) {
157
+ const selected = String(directoryValue || "").trim();
158
+ if (!selected || !path.isAbsolute(selected))
159
+ throw new Error("请输入本机文件夹的完整路径");
160
+ const resolved = path.resolve(selected);
161
+ await mkdir(resolved, { recursive: true });
162
+ const info = await stat(resolved);
163
+ if (!info.isDirectory())
164
+ throw new Error("选择的路径不是文件夹");
165
+ this.state.downloadDirectory = resolved;
166
+ this.save();
167
+ void this.syncDownloads();
168
+ return this.downloadState();
169
+ }
156
170
  scheduleScript(_id) {
157
171
  queueMicrotask(() => void this.pumpScriptQueue());
158
172
  }
@@ -182,15 +196,8 @@ export class WorkflowManager {
182
196
  this.directorySelection = { id, status: "cancelled" };
183
197
  return;
184
198
  }
185
- const resolved = path.resolve(selected);
186
- await mkdir(resolved, { recursive: true });
187
- const info = await stat(resolved);
188
- if (!info.isDirectory())
189
- throw new Error("选择的路径不是文件夹");
190
- this.state.downloadDirectory = resolved;
191
- this.save();
192
- this.directorySelection = { id, status: "selected", directoryName: path.basename(resolved) };
193
- void this.syncDownloads();
199
+ const state = await this.setDownloadDirectory(selected);
200
+ this.directorySelection = { id, status: "selected", directoryName: state.directoryName };
194
201
  }
195
202
  catch (error) {
196
203
  this.directorySelection = { id, status: "error", error: error instanceof Error ? error.message : "无法选择本机文件夹" };
@@ -500,15 +507,15 @@ async function isExistingFile(filePath, expectedBytes, expectedSha256 = "") {
500
507
  function selectNativeDirectory() {
501
508
  if (process.platform === "win32") {
502
509
  const script = "$ErrorActionPreference='Stop'; Add-Type -AssemblyName System.Windows.Forms; $d=New-Object System.Windows.Forms.FolderBrowserDialog; $d.Description='选择抖音小辉跨境工具的本机视频保存位置'; $d.ShowNewFolderButton=$true; if($d.ShowDialog() -eq [System.Windows.Forms.DialogResult]::OK){[Console]::OutputEncoding=[Text.Encoding]::UTF8; Write-Output $d.SelectedPath}";
503
- return commandOutput(windowsPowerShellExecutable(), ["-NoProfile", "-STA", "-Command", script]);
510
+ return commandOutput(windowsPowerShellExecutable(), ["-NoProfile", "-STA", "-Command", script], { windowsHide: false });
504
511
  }
505
512
  if (process.platform === "darwin")
506
513
  return commandOutput("osascript", ["-e", "POSIX path of (choose folder with prompt \"选择视频保存位置\")"]);
507
514
  return commandOutput("zenity", ["--file-selection", "--directory", "--title=选择视频保存位置"]);
508
515
  }
509
- function commandOutput(command, args) {
516
+ function commandOutput(command, args, options = {}) {
510
517
  return new Promise((resolve, reject) => {
511
- const child = spawn(command, args, { windowsHide: true, stdio: ["ignore", "pipe", "pipe"] });
518
+ const child = spawn(command, args, { windowsHide: options.windowsHide ?? true, stdio: ["ignore", "pipe", "pipe"] });
512
519
  let stdout = "";
513
520
  let stderr = "";
514
521
  child.stdout.on("data", (chunk) => { stdout += chunk.toString(); });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xiaohhhh1/canvas-agent",
3
- "version": "0.4.13",
3
+ "version": "0.4.14",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",