@taloswork/ose-shared 0.1.16 → 0.1.17

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@taloswork/ose-shared",
3
- "version": "0.1.16",
3
+ "version": "0.1.17",
4
4
  "description": "Talos cross-OSE shared library — skills + MCP servers auto-loaded into every OSE (P93 2026-07-27).",
5
5
  "type": "module",
6
6
  "files": [
@@ -10,6 +10,6 @@
10
10
  "publishConfig": {
11
11
  "access": "public"
12
12
  },
13
- "_talosPublishHash": "sha256-DEbZ3scJtwwOPm_sj7A7Wh-1-nZGQYK8ZMFeJfxy1i4",
14
- "_talosPublishedAt": "2026-10-16T08:11:55.057Z"
13
+ "_talosPublishHash": "sha256-GSLGl3lk5au4tYXTSTJ6FHkR8NCBTSWGm7wBjC2NOm0",
14
+ "_talosPublishedAt": "2026-10-22T14:08:12.224Z"
15
15
  }
@@ -9,6 +9,13 @@ license: Proprietary. LICENSE.txt has complete terms
9
9
  Local-first, progressive disclosure: read the extracted text first, render pages only
10
10
  when the content is genuinely visual, and write files only through this skill's scripts.
11
11
 
12
+ ## Where files go
13
+
14
+ Write the finished file into the working directory itself, named as the user would
15
+ (never `out.pptx`); present_file shows it but does not put it there. Everything else
16
+ (specs, scripts, `plan.json`, `deck.html`, previews) goes in a per-task folder under
17
+ `$TALOS_SCRATCH_DIR` (none → the working directory); `cd` there in the same command.
18
+
12
19
  ## Route (read only what you need)
13
20
 
14
21
  **Attachments arrive as file pointers** — a `<document … delivery="file">` block gives
@@ -40,22 +47,21 @@ document's content; never guess from the filename. Then:
40
47
 
41
48
  ## Decks
42
49
 
43
- **CLARIFY FIRST — HARD GATE (applies to EVERY deck).** Before authoring, collect three
44
- brief fields: **(1) content source** (提供材料 / 联网调研 / 自由创作); **(2) scenario**
45
- (pitch / 内审 / 销售 / 讲座 / 发布会 / 培训 / 大会 — sets tone, density, required sections);
46
- **(3) slide count.** Ask only for fields the user did not already supply, in **ONE
47
- AskUserQuestion call with at most THREE questions**, and wait for the answers. If all
48
- three are already known, do not ask them again.
50
+ **BRIEF — INFER IT, DO NOT ASK.** Source: material given → 提供材料; current facts or
51
+ figures (market, company, policy, news) → 联网调研; else 自由创作. Scenario from the
52
+ audience or purpose (新人培训 → 培训); slide count as stated, else the scenario default.
53
+ Never ask them on their own: an uninferable scenario rides as a
54
+ second question in the style picker call. The outline gate names all three for correction.
49
55
 
50
- **STYLE PICKER — ONE RESULT PER IMAGE, SCENARIO-RANKED.** After the scenario is
51
- known, run `node <skill>/bin/deck-styles.cjs --scenario "<the confirmed scenario>"`: it
56
+ **STYLE PICKER — ONE RESULT PER IMAGE, SCENARIO-RANKED.** Run
57
+ `node <skill>/bin/deck-styles.cjs --scenario "<the inferred scenario>"`: it
52
58
  reads the current `catalog.json` from disk immediately and ranks the entries (a
53
59
  scenario-matching pack first, at least six cards). Never rank from memory, reuse a listing
54
60
  from earlier context or scan `packs/`. If it exits non-zero, stop and report that exact
55
61
  error instead of presenting stale options.
56
62
 
57
63
  Unless the user already named an entry id/name, supplied a template file, or explicitly
58
- said **"无需展示模板,直接替我选定风格"**, send one single-question image-card picker whose
64
+ said **"无需展示模板,直接替我选定风格"**, send one image-card picker question (the style question comes first) whose
59
65
  `options` are deck-styles' `options` **as printed** — never rewrite, reorder or add a card.
60
66
 
61
67
  **"按场景推荐/你推荐" means rank the cards and still ask.** It does NOT waive the
@@ -75,9 +81,8 @@ The selected `entry.id` is the stable
75
81
  renders V1 (no `themeVersion`, never `--theme-v2`); every other new deck uses Theme V2 —
76
82
  read **theme-system.md** before authoring.
77
83
 
78
- **Keep both calls LEAN:** bare label strings for the content/scenario/count questions,
79
- one short sentence per stem, no chat preamble beyond one line. If the user answers with
80
- a correction or question, handle it and re-ask.
84
+ **Keep the call LEAN:** one short sentence per stem, one line of preamble at most. A
85
+ correction or question in the answer: handle it, re-ask.
81
86
 
82
87
  **Automatic choice, only when explicitly authorized:** rank by a remembered preference,
83
88
  an exact user-named style, scenario match, a matching pack before a matching skin, then
@@ -96,7 +101,7 @@ uploaded deck". Never write inside the skill directory.
96
101
  if so, read **generated-visuals.md**. In short:
97
102
  **plan before you fill** — `bin/deck-plan.cjs plan.json spec.json` picks layouts by
98
103
  MEASURED capacity and drafts the spec, `deck-build` fills it, charts are drawn from data
99
- (never hand-write chart SVG), and `bin/html2pptx.cjs deck.html out.pptx --style <id>`
104
+ (never hand-write chart SVG), and `bin/html2pptx.cjs deck.html <deliverable>.pptx --style <id>`
100
105
  (+ `--theme-v2` unless the entry is classic-v1) renders it. `doc-gen` and doc-run
101
106
  PptxGenJS make no decks; html2pptx needs a browser — without one, say so and stop, never
102
107
  fall back to a lesser deck.
@@ -10631,7 +10631,8 @@ function normalizeScatter(spec, warnings, errors) {
10631
10631
  let bad = 0;
10632
10632
  const points = [];
10633
10633
  for (const p of rows) {
10634
- const [x, y, lab] = Array.isArray(p) ? [p[0], p[1], p[2]] : p && typeof p === "object" ? [p.x, p.y, p.label] : [NaN, NaN, ""];
10634
+ const point = p && typeof p === "object" && !Array.isArray(p) ? p : void 0;
10635
+ const [x, y, lab] = Array.isArray(p) ? [p[0], p[1], p[2]] : point ? [point.x, point.y, point.label] : [NaN, NaN, ""];
10635
10636
  const nx = toNum(x);
10636
10637
  const ny = toNum(y);
10637
10638
  if (!Number.isFinite(nx) || !Number.isFinite(ny)) {
@@ -646,7 +646,8 @@ function normalizeScatter(spec, warnings, errors) {
646
646
  let bad = 0;
647
647
  const points = [];
648
648
  for (const p of rows) {
649
- const [x, y, lab] = Array.isArray(p) ? [p[0], p[1], p[2]] : p && typeof p === "object" ? [p.x, p.y, p.label] : [NaN, NaN, ""];
649
+ const point = p && typeof p === "object" && !Array.isArray(p) ? p : void 0;
650
+ const [x, y, lab] = Array.isArray(p) ? [p[0], p[1], p[2]] : point ? [point.x, point.y, point.label] : [NaN, NaN, ""];
650
651
  const nx = toNum(x);
651
652
  const ny = toNum(y);
652
653
  if (!Number.isFinite(nx) || !Number.isFinite(ny)) {
@@ -315,7 +315,7 @@ var require_BufferList = __commonJS({
315
315
  this.head = this.tail = null;
316
316
  this.length = 0;
317
317
  };
318
- BufferList.prototype.join = function join5(s) {
318
+ BufferList.prototype.join = function join6(s) {
319
319
  if (this.length === 0) return "";
320
320
  var p = this.head;
321
321
  var ret = "" + p.data;
@@ -2347,8 +2347,8 @@ var require_lib2 = __commonJS({
2347
2347
  return this;
2348
2348
  }
2349
2349
  var p = this.constructor;
2350
- return this.then(resolve2, reject2);
2351
- function resolve2(value) {
2350
+ return this.then(resolve3, reject2);
2351
+ function resolve3(value) {
2352
2352
  function yes() {
2353
2353
  return value;
2354
2354
  }
@@ -2501,8 +2501,8 @@ var require_lib2 = __commonJS({
2501
2501
  }
2502
2502
  return out;
2503
2503
  }
2504
- Promise2.resolve = resolve;
2505
- function resolve(value) {
2504
+ Promise2.resolve = resolve2;
2505
+ function resolve2(value) {
2506
2506
  if (value instanceof this) {
2507
2507
  return value;
2508
2508
  }
@@ -3033,10 +3033,10 @@ var require_utils = __commonJS({
3033
3033
  var promise = external.Promise.resolve(inputData).then(function(data) {
3034
3034
  var isBlob = support.blob && (data instanceof Blob || ["[object File]", "[object Blob]"].indexOf(Object.prototype.toString.call(data)) !== -1);
3035
3035
  if (isBlob && typeof FileReader !== "undefined") {
3036
- return new external.Promise(function(resolve, reject) {
3036
+ return new external.Promise(function(resolve2, reject) {
3037
3037
  var reader = new FileReader();
3038
3038
  reader.onload = function(e) {
3039
- resolve(e.target.result);
3039
+ resolve2(e.target.result);
3040
3040
  };
3041
3041
  reader.onerror = function(e) {
3042
3042
  reject(e.target.error);
@@ -3591,7 +3591,7 @@ var require_StreamHelper = __commonJS({
3591
3591
  }
3592
3592
  }
3593
3593
  function accumulate(helper, updateCallback) {
3594
- return new external.Promise(function(resolve, reject) {
3594
+ return new external.Promise(function(resolve2, reject) {
3595
3595
  var dataArray = [];
3596
3596
  var chunkType = helper._internalType, resultType = helper._outputType, mimeType = helper._mimeType;
3597
3597
  helper.on("data", function(data, meta) {
@@ -3605,7 +3605,7 @@ var require_StreamHelper = __commonJS({
3605
3605
  }).on("end", function() {
3606
3606
  try {
3607
3607
  var result = transformZipOutput(resultType, concat(chunkType, dataArray), mimeType);
3608
- resolve(result);
3608
+ resolve2(result);
3609
3609
  } catch (e) {
3610
3610
  reject(e);
3611
3611
  }
@@ -9718,7 +9718,7 @@ var require_load = __commonJS({
9718
9718
  var Crc32Probe = require_Crc32Probe();
9719
9719
  var nodejsUtils = require_nodejsUtils();
9720
9720
  function checkEntryCRC32(zipEntry) {
9721
- return new external.Promise(function(resolve, reject) {
9721
+ return new external.Promise(function(resolve2, reject) {
9722
9722
  var worker = zipEntry.decompressed.getContentWorker().pipe(new Crc32Probe());
9723
9723
  worker.on("error", function(e) {
9724
9724
  reject(e);
@@ -9726,7 +9726,7 @@ var require_load = __commonJS({
9726
9726
  if (worker.streamInfo.crc32 !== zipEntry.decompressed.crc32) {
9727
9727
  reject(new Error("Corrupted zip : CRC32 mismatch"));
9728
9728
  } else {
9729
- resolve();
9729
+ resolve2();
9730
9730
  }
9731
9731
  }).resume();
9732
9732
  });
@@ -9881,9 +9881,15 @@ function textTableHint(text) {
9881
9881
  const gaps = (text.match(/ {2,}|\t/g) || []).length;
9882
9882
  return gaps >= 6;
9883
9883
  }
9884
+ function openPdf(mupdf, bytes) {
9885
+ const doc = mupdf.Document.openDocument(bytes, "application/pdf").asPDF();
9886
+ if (!doc)
9887
+ throw new Error("not a PDF document");
9888
+ return doc;
9889
+ }
9884
9890
  async function openDoc(bytes) {
9885
9891
  const mupdf = await loadMupdf();
9886
- const doc = mupdf.Document.openDocument(bytes, "application/pdf");
9892
+ const doc = openPdf(mupdf, bytes);
9887
9893
  if (doc.needsPassword())
9888
9894
  throw new PdfEncryptedError();
9889
9895
  if (doc.countPages() === 0) {
@@ -9990,17 +9996,15 @@ function isDelimiter(ch) {
9990
9996
  }
9991
9997
  function pageContentStream(page) {
9992
9998
  try {
9993
- const obj = page.getObject?.();
9994
- const contents = obj?.get?.("Contents");
9995
- if (!contents)
9999
+ const contents = page.getObject().get("Contents");
10000
+ if (contents.isNull())
9996
10001
  return "";
9997
- const streams = contents.isArray?.() && contents.get ? Array.from({ length: contents.length ?? 0 }, (_, i) => contents.get(i)) : [contents];
10002
+ const streams = contents.isArray() ? Array.from({ length: contents.length }, (_, i) => contents.get(i)) : [contents];
9998
10003
  let out = "";
9999
10004
  for (const stream of streams) {
10000
- const buf = stream?.readStream?.();
10001
- const bytes = buf?.asUint8Array?.();
10002
- if (bytes)
10003
- out += Buffer.from(bytes).toString("latin1");
10005
+ if (!stream.isStream())
10006
+ continue;
10007
+ out += Buffer.from(stream.readStream().asUint8Array()).toString("latin1");
10004
10008
  }
10005
10009
  return out;
10006
10010
  } catch {
@@ -10197,12 +10201,11 @@ async function encryptPdf(bytes, userPassword, ownerPassword) {
10197
10201
  }
10198
10202
  async function pdfNeedsPassword(bytes) {
10199
10203
  const mupdf = await loadMupdf();
10200
- const doc = mupdf.Document.openDocument(bytes, "application/pdf");
10201
- return doc.needsPassword();
10204
+ return openPdf(mupdf, bytes).needsPassword();
10202
10205
  }
10203
10206
  async function decryptPdf(bytes, password) {
10204
10207
  const mupdf = await loadMupdf();
10205
- const doc = mupdf.Document.openDocument(bytes, "application/pdf");
10208
+ const doc = openPdf(mupdf, bytes);
10206
10209
  if (doc.needsPassword()) {
10207
10210
  if (doc.authenticatePassword(password) === 0)
10208
10211
  throw new Error("wrong password");
@@ -10284,11 +10287,11 @@ function __metadata(metadataKey, metadataValue) {
10284
10287
  }
10285
10288
  function __awaiter(thisArg, _arguments, P, generator) {
10286
10289
  function adopt(value) {
10287
- return value instanceof P ? value : new P(function(resolve) {
10288
- resolve(value);
10290
+ return value instanceof P ? value : new P(function(resolve2) {
10291
+ resolve2(value);
10289
10292
  });
10290
10293
  }
10291
- return new (P || (P = Promise))(function(resolve, reject) {
10294
+ return new (P || (P = Promise))(function(resolve2, reject) {
10292
10295
  function fulfilled(value) {
10293
10296
  try {
10294
10297
  step(generator.next(value));
@@ -10304,7 +10307,7 @@ function __awaiter(thisArg, _arguments, P, generator) {
10304
10307
  }
10305
10308
  }
10306
10309
  function step(result) {
10307
- result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected);
10310
+ result.done ? resolve2(result.value) : adopt(result.value).then(fulfilled, rejected);
10308
10311
  }
10309
10312
  step((generator = generator.apply(thisArg, _arguments || [])).next());
10310
10313
  });
@@ -10482,14 +10485,14 @@ function __asyncValues(o) {
10482
10485
  }, i);
10483
10486
  function verb(n) {
10484
10487
  i[n] = o[n] && function(v) {
10485
- return new Promise(function(resolve, reject) {
10486
- v = o[n](v), settle(resolve, reject, v.done, v.value);
10488
+ return new Promise(function(resolve2, reject) {
10489
+ v = o[n](v), settle(resolve2, reject, v.done, v.value);
10487
10490
  });
10488
10491
  };
10489
10492
  }
10490
- function settle(resolve, reject, d, v) {
10493
+ function settle(resolve2, reject, d, v) {
10491
10494
  Promise.resolve(v).then(function(v2) {
10492
- resolve({ value: v2, done: d });
10495
+ resolve2({ value: v2, done: d });
10493
10496
  }, reject);
10494
10497
  }
10495
10498
  }
@@ -10908,9 +10911,9 @@ var require_async = __commonJS({
10908
10911
  Object.defineProperty(exports2, "__esModule", { value: true });
10909
10912
  exports2.waitForTick = void 0;
10910
10913
  exports2.waitForTick = function() {
10911
- return new Promise(function(resolve) {
10914
+ return new Promise(function(resolve2) {
10912
10915
  setTimeout(function() {
10913
- return resolve();
10916
+ return resolve2();
10914
10917
  }, 0);
10915
10918
  });
10916
10919
  };
@@ -15430,12 +15433,12 @@ var require_CustomFontSubsetEmbedder = __commonJS({
15430
15433
  };
15431
15434
  CustomFontSubsetEmbedder2.prototype.serializeFont = function() {
15432
15435
  var _this = this;
15433
- return new Promise(function(resolve, reject) {
15436
+ return new Promise(function(resolve2, reject) {
15434
15437
  var parts = [];
15435
15438
  _this.subset.encodeStream().on("data", function(bytes) {
15436
15439
  return parts.push(bytes);
15437
15440
  }).on("end", function() {
15438
- return resolve(utils_1.mergeUint8Arrays(parts));
15441
+ return resolve2(utils_1.mergeUint8Arrays(parts));
15439
15442
  }).on("error", function(err) {
15440
15443
  return reject(err);
15441
15444
  });
@@ -27984,7 +27987,7 @@ var require_cjs = __commonJS({
27984
27987
  // apps/admin/data/skills.lib/document/bin-src/deck-qa.mjs
27985
27988
  var import_node_child_process = require("node:child_process");
27986
27989
  var import_promises2 = require("node:fs/promises");
27987
- var import_node_path4 = require("node:path");
27990
+ var import_node_path5 = require("node:path");
27988
27991
  var import_node_util = require("node:util");
27989
27992
 
27990
27993
  // packages/core/dist/document/doc-design-lint.js
@@ -29310,6 +29313,17 @@ async function checkPptx(bytes, options = {}) {
29310
29313
  return report;
29311
29314
  }
29312
29315
 
29316
+ // apps/admin/data/skills.lib/document/bin-src/lib/derived-path.mjs
29317
+ var import_node_path4 = require("node:path");
29318
+ var SCRATCH_ENV = "TALOS_SCRATCH_DIR";
29319
+ function derivedDir(source, env = process.env) {
29320
+ const scratch = env[SCRATCH_ENV];
29321
+ return scratch ? (0, import_node_path4.join)(scratch, "derived") : (0, import_node_path4.dirname)((0, import_node_path4.resolve)(source));
29322
+ }
29323
+ function derivedPath(source, name, env = process.env) {
29324
+ return (0, import_node_path4.join)(derivedDir(source, env), name);
29325
+ }
29326
+
29313
29327
  // apps/admin/data/skills.lib/document/bin-src/deck-qa.mjs
29314
29328
  function die(msg, code = 1) {
29315
29329
  process.stderr.write(`deck-qa: ${msg}
@@ -29334,7 +29348,7 @@ function printLint(result) {
29334
29348
  `);
29335
29349
  }
29336
29350
  async function officeRender(deck, pdf, cacheDir) {
29337
- const bin = (0, import_node_path4.join)((0, import_node_path4.dirname)(process.argv[1]), "doc-convert.cjs");
29351
+ const bin = (0, import_node_path5.join)((0, import_node_path5.dirname)(process.argv[1]), "doc-convert.cjs");
29338
29352
  try {
29339
29353
  const { stdout } = await (0, import_node_util.promisify)(import_node_child_process.execFile)(process.execPath, [bin, deck, pdf, "--cache-dir", cacheDir, "--require-office"], {
29340
29354
  maxBuffer: 8 * 1024 * 1024
@@ -29352,8 +29366,9 @@ async function finalSignOff(file, bytes, cacheDir, requireOffice) {
29352
29366
  process.stdout.write(JSON.stringify({ ok: false, valid: check.valid, errors: check.errors, strict: check.strict }) + "\n");
29353
29367
  die(check.valid ? "strict XSD validation failed \u2014 the deck is not standard OOXML; fix it before delivering" : "the deck is structurally invalid \u2014 do not deliver it");
29354
29368
  }
29355
- const stem = (0, import_node_path4.basename)(file).replace(/\.pptx$/i, "");
29356
- const office = await officeRender(file, (0, import_node_path4.join)((0, import_node_path4.dirname)(file), `${stem}.office.pdf`), cacheDir);
29369
+ const stem = (0, import_node_path5.basename)(file).replace(/\.pptx$/i, "");
29370
+ await (0, import_promises2.mkdir)(derivedDir(file), { recursive: true });
29371
+ const office = await officeRender(file, derivedPath(file, `${stem}.office.pdf`), cacheDir);
29357
29372
  let findings = check.qa.findings;
29358
29373
  let review = [];
29359
29374
  let charts = [];
@@ -29366,7 +29381,7 @@ async function finalSignOff(file, bytes, cacheDir, requireOffice) {
29366
29381
  office.type3Fonts = rendered.type3Fonts;
29367
29382
  if (review.length) {
29368
29383
  for (const r of await renderPdfPages(new Uint8Array(pdfBytes), review, 1)) {
29369
- const path = (0, import_node_path4.join)((0, import_node_path4.dirname)(office.pdf), `${stem}.office_p${r.page}.png`);
29384
+ const path = (0, import_node_path5.join)((0, import_node_path5.dirname)(office.pdf), `${stem}.office_p${r.page}.png`);
29370
29385
  await (0, import_promises2.writeFile)(path, Buffer.from(r.png));
29371
29386
  previews.push({ slide: r.page, path });
29372
29387
  }
@@ -29398,7 +29413,7 @@ async function main() {
29398
29413
  const rendered = flagValue(args, "--rendered");
29399
29414
  const valued = /* @__PURE__ */ new Set(["--rendered", "--cache-dir"]);
29400
29415
  const file = args.find((a, i) => !a.startsWith("--") && !valued.has(args[i - 1]));
29401
- const cacheDir = flagValue(args, "--cache-dir") ?? (process.env.TALOS_OFFICE_CACHE_DIR || void 0) ?? (file ? (0, import_node_path4.join)((0, import_node_path4.dirname)(file), ".office-cache") : void 0);
29416
+ const cacheDir = flagValue(args, "--cache-dir") ?? (process.env.TALOS_OFFICE_CACHE_DIR || void 0) ?? (file ? derivedPath(file, ".office-cache") : void 0);
29402
29417
  const requireOffice = args.includes("--require-office");
29403
29418
  const usage = "usage: deck-qa <file.pptx> [--json] [--rendered <office.pdf> | --final [--cache-dir <dir>] [--require-office]]";
29404
29419
  if (!file) die(usage, 64);