@petercjl/tuda 0.1.0 → 0.1.1

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/capabilities.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
3
  "name": "@petercjl/tuda",
4
- "version": "0.1.0",
4
+ "version": "0.1.1",
5
5
  "kind": "cli-skill",
6
6
  "skills": [
7
7
  "using-tuda"
@@ -438,6 +438,15 @@
438
438
  "activation": "next-connection",
439
439
  "compatibility": "same-minor-for-0.x-same-major-for-1.x",
440
440
  "failure": "keep-active"
441
+ },
442
+ "sharedDesktopSession": {
443
+ "contract": 1,
444
+ "authScope": "connection",
445
+ "preservesDesktopSession": true,
446
+ "transport": "private-file-pkce-with-connection-secret",
447
+ "sessionPersistence": "memory-only",
448
+ "space": "enterprise",
449
+ "source": "codex-own"
441
450
  }
442
451
  }
443
452
  }
@@ -17039,6 +17039,7 @@ var StdioServerTransport = class {
17039
17039
  };
17040
17040
 
17041
17041
  // src/board-plugin.ts
17042
+ import { randomBytes, createHash as createHash2 } from "node:crypto";
17042
17043
  import { readFile as readFile3, stat } from "node:fs/promises";
17043
17044
  import path4 from "node:path";
17044
17045
 
@@ -17361,6 +17362,8 @@ var userData = process.env.TUDA_USER_DATA_PATH || defaultUserDataPath();
17361
17362
  var fixedSpace = process.env.TUDA_SPACE || process.env.TUDA_PLUGIN_SPACE;
17362
17363
  if (fixedSpace && !["personal", "enterprise"].includes(fixedSpace)) throw new Error("INVALID_SPACE");
17363
17364
  var authenticatedInstance;
17365
+ var authenticatedGrant;
17366
+ var connectionSecret = process.env.TUDA_AUTH_HANDOFF_FILE ? randomBytes(32).toString("hex") : void 0;
17364
17367
  async function local(route, payload) {
17365
17368
  let info;
17366
17369
  try {
@@ -17371,33 +17374,36 @@ async function local(route, payload) {
17371
17374
  if (!Number.isInteger(info.port) || info.port < 1 || info.port > 65535 || typeof info.token !== "string" || !/^[A-Za-z0-9_-]{20,100}$/.test(info.token)) throw new Error("INVALID_LOCAL_BRIDGE");
17372
17375
  const response = await fetch(`http://127.0.0.1:${info.port}${route}`, {
17373
17376
  method: "POST",
17374
- headers: { authorization: `Bearer ${info.token}`, "content-type": "application/json" },
17377
+ headers: { authorization: `Bearer ${info.token}`, "content-type": "application/json", ...connectionSecret ? { "x-tuda-plugin-session": connectionSecret } : {} },
17375
17378
  body: JSON.stringify(payload),
17376
17379
  signal: AbortSignal.timeout(6e4)
17377
17380
  });
17378
17381
  const result = await response.json();
17379
- if (!response.ok) throw new Error(route === "/board-plugin/auth" ? "AUTH_HANDOFF_FAILED" : result.error || "BOARD_PLUGIN_FAILED");
17382
+ if (!response.ok) throw new Error(result.error || (route === "/board-plugin/auth" ? "AUTH_HANDOFF_FAILED" : "BOARD_PLUGIN_FAILED"));
17380
17383
  return result.result;
17381
17384
  }
17382
17385
  async function ready() {
17383
17386
  await connect({ userDataPath: userData, appRoot: process.env.TUDA_APP_PATH, noLaunch: process.env.TUDA_NO_LAUNCH === "1", startupTimeoutMs: Number(process.env.TUDA_STARTUP_TIMEOUT_MS ?? 12e4) });
17384
17387
  const instanceId = await desktopInstance(userData);
17385
- if (authenticatedInstance !== instanceId && process.env.TUDA_AUTH_HANDOFF_FILE) {
17388
+ if (process.env.TUDA_AUTH_HANDOFF_FILE) {
17386
17389
  const file = process.env.TUDA_AUTH_HANDOFF_FILE;
17387
17390
  if (!path4.isAbsolute(file)) throw new Error("UNSAFE_AUTH_HANDOFF_FILE");
17388
17391
  const info = await stat(file).catch(() => {
17389
17392
  throw new Error("AUTH_HANDOFF_REQUIRED");
17390
17393
  });
17391
17394
  if (!path4.isAbsolute(file) || !info.isFile() || info.size > 16384 || process.platform !== "win32" && (info.mode & 63) !== 0) throw new Error("UNSAFE_AUTH_HANDOFF_FILE");
17395
+ const bytes = await readFile3(file, "utf8"), digest = createHash2("sha256").update(bytes).digest("hex");
17396
+ if (authenticatedInstance === instanceId && authenticatedGrant === digest) return;
17392
17397
  let grant;
17393
17398
  try {
17394
- grant = JSON.parse(await readFile3(file, "utf8"));
17399
+ grant = JSON.parse(bytes);
17395
17400
  } catch {
17396
17401
  throw new Error("INVALID_AUTH_HANDOFF_FILE");
17397
17402
  }
17398
17403
  if (!grant || typeof grant !== "object" || grant.instanceId !== instanceId) throw new Error("AUTH_HANDOFF_STALE_INSTANCE");
17399
17404
  await local("/board-plugin/auth", grant);
17400
17405
  authenticatedInstance = instanceId;
17406
+ authenticatedGrant = digest;
17401
17407
  }
17402
17408
  }
17403
17409
  async function importLocalFiles(args) {
package/dist/main.js CHANGED
@@ -551,7 +551,7 @@ async function desktopInstance(userDataPath) {
551
551
  async function prepareDesktop(options) {
552
552
  const call = await connect(options);
553
553
  const state = await call("status");
554
- return { ready: true, instanceId: await desktopInstance(options.userDataPath), protocolVersion: state.protocolVersion };
554
+ return { ready: true, instanceId: await desktopInstance(options.userDataPath), protocolVersion: state.protocolVersion, desktopVersion: state.desktopVersion, boardPlugin: state.boardPlugin };
555
555
  }
556
556
  async function connect(options) {
557
557
  const startupTimeoutMs = options.startupTimeoutMs ?? Number(process.env.TUDA_STARTUP_TIMEOUT_MS ?? 3e4);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@petercjl/tuda",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "CLI for Tuda: images, videos, and creative workflows on one canvas. Generate, edit, organize, and export with your configured models.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -2,7 +2,7 @@
2
2
  name: using-tuda
3
3
  description: Use Tuda for image and video creation, editing, boards and assets only when the user explicitly invokes /using-tuda or $using-tuda. Do not select this skill automatically.
4
4
  metadata:
5
- version: "0.1.0"
5
+ version: "0.1.1"
6
6
  ---
7
7
 
8
8
  # Using Tuda