@deployxai/dxc 0.1.5 → 0.1.7

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/dist/index.js CHANGED
@@ -1,9 +1,12 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire as __dxcCreateRequire } from "node:module"; const require = __dxcCreateRequire(import.meta.url);
3
+ import {
4
+ resolveUserPath
5
+ } from "./chunks/chunk-ZKJQWR2J.js";
3
6
  import {
4
7
  SourceCli,
5
8
  SourceCliError
6
- } from "./chunks/chunk-GCGIIKQJ.js";
9
+ } from "./chunks/chunk-NAL5UOUZ.js";
7
10
  import {
8
11
  CONTENT_ARTIFACT_KINDS,
9
12
  CONTENT_STAGE_INPUTS,
@@ -78,7 +81,7 @@ import {
78
81
  wechatRenderResultSchema,
79
82
  writePrivateBuffer,
80
83
  writePrivateJson
81
- } from "./chunks/chunk-JGUPNE36.js";
84
+ } from "./chunks/chunk-N4CMLINP.js";
82
85
 
83
86
  // node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/nodes/identity.js
84
87
  var require_identity = __commonJS({
@@ -157,17 +160,17 @@ var require_visit = __commonJS({
157
160
  visit.BREAK = BREAK;
158
161
  visit.SKIP = SKIP;
159
162
  visit.REMOVE = REMOVE;
160
- function visit_(key, node, visitor, path9) {
161
- const ctrl = callVisitor(key, node, visitor, path9);
163
+ function visit_(key, node, visitor, path8) {
164
+ const ctrl = callVisitor(key, node, visitor, path8);
162
165
  if (identity.isNode(ctrl) || identity.isPair(ctrl)) {
163
- replaceNode(key, path9, ctrl);
164
- return visit_(key, ctrl, visitor, path9);
166
+ replaceNode(key, path8, ctrl);
167
+ return visit_(key, ctrl, visitor, path8);
165
168
  }
166
169
  if (typeof ctrl !== "symbol") {
167
170
  if (identity.isCollection(node)) {
168
- path9 = Object.freeze(path9.concat(node));
171
+ path8 = Object.freeze(path8.concat(node));
169
172
  for (let i = 0; i < node.items.length; ++i) {
170
- const ci = visit_(i, node.items[i], visitor, path9);
173
+ const ci = visit_(i, node.items[i], visitor, path8);
171
174
  if (typeof ci === "number")
172
175
  i = ci - 1;
173
176
  else if (ci === BREAK)
@@ -178,13 +181,13 @@ var require_visit = __commonJS({
178
181
  }
179
182
  }
180
183
  } else if (identity.isPair(node)) {
181
- path9 = Object.freeze(path9.concat(node));
182
- const ck = visit_("key", node.key, visitor, path9);
184
+ path8 = Object.freeze(path8.concat(node));
185
+ const ck = visit_("key", node.key, visitor, path8);
183
186
  if (ck === BREAK)
184
187
  return BREAK;
185
188
  else if (ck === REMOVE)
186
189
  node.key = null;
187
- const cv = visit_("value", node.value, visitor, path9);
190
+ const cv = visit_("value", node.value, visitor, path8);
188
191
  if (cv === BREAK)
189
192
  return BREAK;
190
193
  else if (cv === REMOVE)
@@ -205,17 +208,17 @@ var require_visit = __commonJS({
205
208
  visitAsync.BREAK = BREAK;
206
209
  visitAsync.SKIP = SKIP;
207
210
  visitAsync.REMOVE = REMOVE;
208
- async function visitAsync_(key, node, visitor, path9) {
209
- const ctrl = await callVisitor(key, node, visitor, path9);
211
+ async function visitAsync_(key, node, visitor, path8) {
212
+ const ctrl = await callVisitor(key, node, visitor, path8);
210
213
  if (identity.isNode(ctrl) || identity.isPair(ctrl)) {
211
- replaceNode(key, path9, ctrl);
212
- return visitAsync_(key, ctrl, visitor, path9);
214
+ replaceNode(key, path8, ctrl);
215
+ return visitAsync_(key, ctrl, visitor, path8);
213
216
  }
214
217
  if (typeof ctrl !== "symbol") {
215
218
  if (identity.isCollection(node)) {
216
- path9 = Object.freeze(path9.concat(node));
219
+ path8 = Object.freeze(path8.concat(node));
217
220
  for (let i = 0; i < node.items.length; ++i) {
218
- const ci = await visitAsync_(i, node.items[i], visitor, path9);
221
+ const ci = await visitAsync_(i, node.items[i], visitor, path8);
219
222
  if (typeof ci === "number")
220
223
  i = ci - 1;
221
224
  else if (ci === BREAK)
@@ -226,13 +229,13 @@ var require_visit = __commonJS({
226
229
  }
227
230
  }
228
231
  } else if (identity.isPair(node)) {
229
- path9 = Object.freeze(path9.concat(node));
230
- const ck = await visitAsync_("key", node.key, visitor, path9);
232
+ path8 = Object.freeze(path8.concat(node));
233
+ const ck = await visitAsync_("key", node.key, visitor, path8);
231
234
  if (ck === BREAK)
232
235
  return BREAK;
233
236
  else if (ck === REMOVE)
234
237
  node.key = null;
235
- const cv = await visitAsync_("value", node.value, visitor, path9);
238
+ const cv = await visitAsync_("value", node.value, visitor, path8);
236
239
  if (cv === BREAK)
237
240
  return BREAK;
238
241
  else if (cv === REMOVE)
@@ -259,23 +262,23 @@ var require_visit = __commonJS({
259
262
  }
260
263
  return visitor;
261
264
  }
262
- function callVisitor(key, node, visitor, path9) {
265
+ function callVisitor(key, node, visitor, path8) {
263
266
  if (typeof visitor === "function")
264
- return visitor(key, node, path9);
267
+ return visitor(key, node, path8);
265
268
  if (identity.isMap(node))
266
- return visitor.Map?.(key, node, path9);
269
+ return visitor.Map?.(key, node, path8);
267
270
  if (identity.isSeq(node))
268
- return visitor.Seq?.(key, node, path9);
271
+ return visitor.Seq?.(key, node, path8);
269
272
  if (identity.isPair(node))
270
- return visitor.Pair?.(key, node, path9);
273
+ return visitor.Pair?.(key, node, path8);
271
274
  if (identity.isScalar(node))
272
- return visitor.Scalar?.(key, node, path9);
275
+ return visitor.Scalar?.(key, node, path8);
273
276
  if (identity.isAlias(node))
274
- return visitor.Alias?.(key, node, path9);
277
+ return visitor.Alias?.(key, node, path8);
275
278
  return void 0;
276
279
  }
277
- function replaceNode(key, path9, node) {
278
- const parent = path9[path9.length - 1];
280
+ function replaceNode(key, path8, node) {
281
+ const parent = path8[path8.length - 1];
279
282
  if (identity.isCollection(parent)) {
280
283
  parent.items[key] = node;
281
284
  } else if (identity.isPair(parent)) {
@@ -885,10 +888,10 @@ var require_Collection = __commonJS({
885
888
  var createNode = require_createNode();
886
889
  var identity = require_identity();
887
890
  var Node2 = require_Node();
888
- function collectionFromPath(schema, path9, value) {
891
+ function collectionFromPath(schema, path8, value) {
889
892
  let v2 = value;
890
- for (let i = path9.length - 1; i >= 0; --i) {
891
- const k = path9[i];
893
+ for (let i = path8.length - 1; i >= 0; --i) {
894
+ const k = path8[i];
892
895
  if (typeof k === "number" && Number.isInteger(k) && k >= 0) {
893
896
  const a = [];
894
897
  a[k] = v2;
@@ -907,7 +910,7 @@ var require_Collection = __commonJS({
907
910
  sourceObjects: /* @__PURE__ */ new Map()
908
911
  });
909
912
  }
910
- var isEmptyPath = (path9) => path9 == null || typeof path9 === "object" && !!path9[Symbol.iterator]().next().done;
913
+ var isEmptyPath = (path8) => path8 == null || typeof path8 === "object" && !!path8[Symbol.iterator]().next().done;
911
914
  var Collection = class extends Node2.NodeBase {
912
915
  constructor(type, schema) {
913
916
  super(type);
@@ -937,11 +940,11 @@ var require_Collection = __commonJS({
937
940
  * be a Pair instance or a `{ key, value }` object, which may not have a key
938
941
  * that already exists in the map.
939
942
  */
940
- addIn(path9, value) {
941
- if (isEmptyPath(path9))
943
+ addIn(path8, value) {
944
+ if (isEmptyPath(path8))
942
945
  this.add(value);
943
946
  else {
944
- const [key, ...rest] = path9;
947
+ const [key, ...rest] = path8;
945
948
  const node = this.get(key, true);
946
949
  if (identity.isCollection(node))
947
950
  node.addIn(rest, value);
@@ -955,8 +958,8 @@ var require_Collection = __commonJS({
955
958
  * Removes a value from the collection.
956
959
  * @returns `true` if the item was found and removed.
957
960
  */
958
- deleteIn(path9) {
959
- const [key, ...rest] = path9;
961
+ deleteIn(path8) {
962
+ const [key, ...rest] = path8;
960
963
  if (rest.length === 0)
961
964
  return this.delete(key);
962
965
  const node = this.get(key, true);
@@ -970,8 +973,8 @@ var require_Collection = __commonJS({
970
973
  * scalar values from their surrounding node; to disable set `keepScalar` to
971
974
  * `true` (collections are always returned intact).
972
975
  */
973
- getIn(path9, keepScalar) {
974
- const [key, ...rest] = path9;
976
+ getIn(path8, keepScalar) {
977
+ const [key, ...rest] = path8;
975
978
  const node = this.get(key, true);
976
979
  if (rest.length === 0)
977
980
  return !keepScalar && identity.isScalar(node) ? node.value : node;
@@ -989,8 +992,8 @@ var require_Collection = __commonJS({
989
992
  /**
990
993
  * Checks if the collection includes a value with the key `key`.
991
994
  */
992
- hasIn(path9) {
993
- const [key, ...rest] = path9;
995
+ hasIn(path8) {
996
+ const [key, ...rest] = path8;
994
997
  if (rest.length === 0)
995
998
  return this.has(key);
996
999
  const node = this.get(key, true);
@@ -1000,8 +1003,8 @@ var require_Collection = __commonJS({
1000
1003
  * Sets a value in this collection. For `!!set`, `value` needs to be a
1001
1004
  * boolean to add/remove the item from the set.
1002
1005
  */
1003
- setIn(path9, value) {
1004
- const [key, ...rest] = path9;
1006
+ setIn(path8, value) {
1007
+ const [key, ...rest] = path8;
1005
1008
  if (rest.length === 0) {
1006
1009
  this.set(key, value);
1007
1010
  } else {
@@ -3516,9 +3519,9 @@ var require_Document = __commonJS({
3516
3519
  this.contents.add(value);
3517
3520
  }
3518
3521
  /** Adds a value to the document. */
3519
- addIn(path9, value) {
3522
+ addIn(path8, value) {
3520
3523
  if (assertCollection(this.contents))
3521
- this.contents.addIn(path9, value);
3524
+ this.contents.addIn(path8, value);
3522
3525
  }
3523
3526
  /**
3524
3527
  * Create a new `Alias` node, ensuring that the target `node` has the required anchor.
@@ -3593,14 +3596,14 @@ var require_Document = __commonJS({
3593
3596
  * Removes a value from the document.
3594
3597
  * @returns `true` if the item was found and removed.
3595
3598
  */
3596
- deleteIn(path9) {
3597
- if (Collection.isEmptyPath(path9)) {
3599
+ deleteIn(path8) {
3600
+ if (Collection.isEmptyPath(path8)) {
3598
3601
  if (this.contents == null)
3599
3602
  return false;
3600
3603
  this.contents = null;
3601
3604
  return true;
3602
3605
  }
3603
- return assertCollection(this.contents) ? this.contents.deleteIn(path9) : false;
3606
+ return assertCollection(this.contents) ? this.contents.deleteIn(path8) : false;
3604
3607
  }
3605
3608
  /**
3606
3609
  * Returns item at `key`, or `undefined` if not found. By default unwraps
@@ -3615,10 +3618,10 @@ var require_Document = __commonJS({
3615
3618
  * scalar values from their surrounding node; to disable set `keepScalar` to
3616
3619
  * `true` (collections are always returned intact).
3617
3620
  */
3618
- getIn(path9, keepScalar) {
3619
- if (Collection.isEmptyPath(path9))
3621
+ getIn(path8, keepScalar) {
3622
+ if (Collection.isEmptyPath(path8))
3620
3623
  return !keepScalar && identity.isScalar(this.contents) ? this.contents.value : this.contents;
3621
- return identity.isCollection(this.contents) ? this.contents.getIn(path9, keepScalar) : void 0;
3624
+ return identity.isCollection(this.contents) ? this.contents.getIn(path8, keepScalar) : void 0;
3622
3625
  }
3623
3626
  /**
3624
3627
  * Checks if the document includes a value with the key `key`.
@@ -3629,10 +3632,10 @@ var require_Document = __commonJS({
3629
3632
  /**
3630
3633
  * Checks if the document includes a value at `path`.
3631
3634
  */
3632
- hasIn(path9) {
3633
- if (Collection.isEmptyPath(path9))
3635
+ hasIn(path8) {
3636
+ if (Collection.isEmptyPath(path8))
3634
3637
  return this.contents !== void 0;
3635
- return identity.isCollection(this.contents) ? this.contents.hasIn(path9) : false;
3638
+ return identity.isCollection(this.contents) ? this.contents.hasIn(path8) : false;
3636
3639
  }
3637
3640
  /**
3638
3641
  * Sets a value in this document. For `!!set`, `value` needs to be a
@@ -3649,13 +3652,13 @@ var require_Document = __commonJS({
3649
3652
  * Sets a value in this document. For `!!set`, `value` needs to be a
3650
3653
  * boolean to add/remove the item from the set.
3651
3654
  */
3652
- setIn(path9, value) {
3653
- if (Collection.isEmptyPath(path9)) {
3655
+ setIn(path8, value) {
3656
+ if (Collection.isEmptyPath(path8)) {
3654
3657
  this.contents = value;
3655
3658
  } else if (this.contents == null) {
3656
- this.contents = Collection.collectionFromPath(this.schema, Array.from(path9), value);
3659
+ this.contents = Collection.collectionFromPath(this.schema, Array.from(path8), value);
3657
3660
  } else if (assertCollection(this.contents)) {
3658
- this.contents.setIn(path9, value);
3661
+ this.contents.setIn(path8, value);
3659
3662
  }
3660
3663
  }
3661
3664
  /**
@@ -5615,9 +5618,9 @@ var require_cst_visit = __commonJS({
5615
5618
  visit.BREAK = BREAK;
5616
5619
  visit.SKIP = SKIP;
5617
5620
  visit.REMOVE = REMOVE;
5618
- visit.itemAtPath = (cst, path9) => {
5621
+ visit.itemAtPath = (cst, path8) => {
5619
5622
  let item = cst;
5620
- for (const [field, index] of path9) {
5623
+ for (const [field, index] of path8) {
5621
5624
  const tok = item?.[field];
5622
5625
  if (tok && "items" in tok) {
5623
5626
  item = tok.items[index];
@@ -5626,23 +5629,23 @@ var require_cst_visit = __commonJS({
5626
5629
  }
5627
5630
  return item;
5628
5631
  };
5629
- visit.parentCollection = (cst, path9) => {
5630
- const parent = visit.itemAtPath(cst, path9.slice(0, -1));
5631
- const field = path9[path9.length - 1][0];
5632
+ visit.parentCollection = (cst, path8) => {
5633
+ const parent = visit.itemAtPath(cst, path8.slice(0, -1));
5634
+ const field = path8[path8.length - 1][0];
5632
5635
  const coll = parent?.[field];
5633
5636
  if (coll && "items" in coll)
5634
5637
  return coll;
5635
5638
  throw new Error("Parent collection not found");
5636
5639
  };
5637
- function _visit(path9, item, visitor) {
5638
- let ctrl = visitor(item, path9);
5640
+ function _visit(path8, item, visitor) {
5641
+ let ctrl = visitor(item, path8);
5639
5642
  if (typeof ctrl === "symbol")
5640
5643
  return ctrl;
5641
5644
  for (const field of ["key", "value"]) {
5642
5645
  const token = item[field];
5643
5646
  if (token && "items" in token) {
5644
5647
  for (let i = 0; i < token.items.length; ++i) {
5645
- const ci = _visit(Object.freeze(path9.concat([[field, i]])), token.items[i], visitor);
5648
+ const ci = _visit(Object.freeze(path8.concat([[field, i]])), token.items[i], visitor);
5646
5649
  if (typeof ci === "number")
5647
5650
  i = ci - 1;
5648
5651
  else if (ci === BREAK)
@@ -5653,10 +5656,10 @@ var require_cst_visit = __commonJS({
5653
5656
  }
5654
5657
  }
5655
5658
  if (typeof ctrl === "function" && field === "key")
5656
- ctrl = ctrl(item, path9);
5659
+ ctrl = ctrl(item, path8);
5657
5660
  }
5658
5661
  }
5659
- return typeof ctrl === "function" ? ctrl(item, path9) : ctrl;
5662
+ return typeof ctrl === "function" ? ctrl(item, path8) : ctrl;
5660
5663
  }
5661
5664
  exports.visit = visit;
5662
5665
  }
@@ -7288,7 +7291,7 @@ var require_public_api = __commonJS({
7288
7291
  return docs;
7289
7292
  return Object.assign([], { empty: true }, composer$1.streamInfo());
7290
7293
  }
7291
- function parseDocument2(source, options = {}) {
7294
+ function parseDocument3(source, options = {}) {
7292
7295
  const { lineCounter: lineCounter2, prettyErrors } = parseOptions(options);
7293
7296
  const parser$1 = new parser.Parser(lineCounter2?.addNewLine);
7294
7297
  const composer$1 = new composer.Composer(options);
@@ -7314,7 +7317,7 @@ var require_public_api = __commonJS({
7314
7317
  } else if (options === void 0 && reviver && typeof reviver === "object") {
7315
7318
  options = reviver;
7316
7319
  }
7317
- const doc = parseDocument2(src, options);
7320
+ const doc = parseDocument3(src, options);
7318
7321
  if (!doc)
7319
7322
  return null;
7320
7323
  doc.warnings.forEach((warning2) => log.warn(doc.options.logLevel, warning2));
@@ -7350,7 +7353,7 @@ var require_public_api = __commonJS({
7350
7353
  }
7351
7354
  exports.parse = parse;
7352
7355
  exports.parseAllDocuments = parseAllDocuments;
7353
- exports.parseDocument = parseDocument2;
7356
+ exports.parseDocument = parseDocument3;
7354
7357
  exports.stringify = stringify;
7355
7358
  }
7356
7359
  });
@@ -13023,27 +13026,27 @@ var require_util = __commonJS({
13023
13026
  };
13024
13027
  }
13025
13028
  var normalize = lruMemoize(function normalize2(aPath) {
13026
- var path9 = aPath;
13029
+ var path8 = aPath;
13027
13030
  var url = urlParse(aPath);
13028
13031
  if (url) {
13029
13032
  if (!url.path) {
13030
13033
  return aPath;
13031
13034
  }
13032
- path9 = url.path;
13035
+ path8 = url.path;
13033
13036
  }
13034
- var isAbsolute = exports.isAbsolute(path9);
13037
+ var isAbsolute = exports.isAbsolute(path8);
13035
13038
  var parts = [];
13036
13039
  var start = 0;
13037
13040
  var i = 0;
13038
13041
  while (true) {
13039
13042
  start = i;
13040
- i = path9.indexOf("/", start);
13043
+ i = path8.indexOf("/", start);
13041
13044
  if (i === -1) {
13042
- parts.push(path9.slice(start));
13045
+ parts.push(path8.slice(start));
13043
13046
  break;
13044
13047
  } else {
13045
- parts.push(path9.slice(start, i));
13046
- while (i < path9.length && path9[i] === "/") {
13048
+ parts.push(path8.slice(start, i));
13049
+ while (i < path8.length && path8[i] === "/") {
13047
13050
  i++;
13048
13051
  }
13049
13052
  }
@@ -13064,15 +13067,15 @@ var require_util = __commonJS({
13064
13067
  }
13065
13068
  }
13066
13069
  }
13067
- path9 = parts.join("/");
13068
- if (path9 === "") {
13069
- path9 = isAbsolute ? "/" : ".";
13070
+ path8 = parts.join("/");
13071
+ if (path8 === "") {
13072
+ path8 = isAbsolute ? "/" : ".";
13070
13073
  }
13071
13074
  if (url) {
13072
- url.path = path9;
13075
+ url.path = path8;
13073
13076
  return urlGenerate(url);
13074
13077
  }
13075
- return path9;
13078
+ return path8;
13076
13079
  });
13077
13080
  exports.normalize = normalize;
13078
13081
  function join(aRoot, aPath) {
@@ -14824,22 +14827,22 @@ var require_previous_map = __commonJS({
14824
14827
  this.annotation = this.getAnnotationURL(css.substring(start, end));
14825
14828
  }
14826
14829
  }
14827
- loadFile(path9, cssFile, trusted) {
14830
+ loadFile(path8, cssFile, trusted) {
14828
14831
  if (!trusted && !this.unsafeMap) {
14829
- if (!/\.map$/i.test(path9)) {
14832
+ if (!/\.map$/i.test(path8)) {
14830
14833
  return void 0;
14831
14834
  }
14832
14835
  if (cssFile) {
14833
- let relativePath = relative(dirname(cssFile), path9);
14836
+ let relativePath = relative(dirname(cssFile), path8);
14834
14837
  if (relativePath === ".." || relativePath.startsWith(".." + sep) || isAbsolute(relativePath)) {
14835
14838
  return void 0;
14836
14839
  }
14837
14840
  }
14838
14841
  }
14839
- this.root = dirname(path9);
14840
- if (existsSync(path9)) {
14841
- this.mapFile = path9;
14842
- return readFileSync(path9, "utf-8").toString().trim();
14842
+ this.root = dirname(path8);
14843
+ if (existsSync(path8)) {
14844
+ this.mapFile = path8;
14845
+ return readFileSync(path8, "utf-8").toString().trim();
14843
14846
  }
14844
14847
  }
14845
14848
  loadMap(file, prev) {
@@ -15611,9 +15614,9 @@ var require_map_generator = __commonJS({
15611
15614
  if (typeof this.mapOpts.annotation === "string") {
15612
15615
  from = dirname(resolve(from, this.mapOpts.annotation));
15613
15616
  }
15614
- let path9 = relative(from, file);
15615
- this.memoizedPaths.set(file, path9);
15616
- return path9;
15617
+ let path8 = relative(from, file);
15618
+ this.memoizedPaths.set(file, path8);
15619
+ return path8;
15617
15620
  }
15618
15621
  previous() {
15619
15622
  if (!this.previousMaps) {
@@ -15668,12 +15671,12 @@ var require_map_generator = __commonJS({
15668
15671
  return window.btoa(unescape(encodeURIComponent(str)));
15669
15672
  }
15670
15673
  }
15671
- toFileUrl(path9) {
15672
- let cached = this.memoizedFileURLs.get(path9);
15674
+ toFileUrl(path8) {
15675
+ let cached = this.memoizedFileURLs.get(path8);
15673
15676
  if (cached) return cached;
15674
15677
  if (pathToFileURL) {
15675
- let fileURL = pathToFileURL(path9).toString();
15676
- this.memoizedFileURLs.set(path9, fileURL);
15678
+ let fileURL = pathToFileURL(path8).toString();
15679
+ this.memoizedFileURLs.set(path8, fileURL);
15677
15680
  return fileURL;
15678
15681
  } else {
15679
15682
  throw new Error(
@@ -15681,14 +15684,14 @@ var require_map_generator = __commonJS({
15681
15684
  );
15682
15685
  }
15683
15686
  }
15684
- toUrl(path9) {
15685
- let cached = this.memoizedURLs.get(path9);
15687
+ toUrl(path8) {
15688
+ let cached = this.memoizedURLs.get(path8);
15686
15689
  if (cached) return cached;
15687
15690
  if (sep === "\\") {
15688
- path9 = path9.replace(/\\/g, "/");
15691
+ path8 = path8.replace(/\\/g, "/");
15689
15692
  }
15690
- let url = encodeURI(path9).replace(/[#?]/g, encodeURIComponent);
15691
- this.memoizedURLs.set(path9, url);
15693
+ let url = encodeURI(path8).replace(/[#?]/g, encodeURIComponent);
15694
+ this.memoizedURLs.set(path8, url);
15692
15695
  return url;
15693
15696
  }
15694
15697
  };
@@ -19069,8 +19072,8 @@ var require_req = __commonJS({
19069
19072
  if (req.originalUrl) {
19070
19073
  _req.url = req.originalUrl;
19071
19074
  } else {
19072
- const path9 = req.path;
19073
- _req.url = typeof path9 === "string" ? path9 : req.url ? req.url.path || req.url : void 0;
19075
+ const path8 = req.path;
19076
+ _req.url = typeof path8 === "string" ? path8 : req.url ? req.url.path || req.url : void 0;
19074
19077
  }
19075
19078
  if (req.query) {
19076
19079
  _req.query = req.query;
@@ -19235,14 +19238,14 @@ var require_redact = __commonJS({
19235
19238
  }
19236
19239
  return obj;
19237
19240
  }
19238
- function parsePath(path9) {
19241
+ function parsePath(path8) {
19239
19242
  const parts = [];
19240
19243
  let current = "";
19241
19244
  let inBrackets = false;
19242
19245
  let inQuotes = false;
19243
19246
  let quoteChar = "";
19244
- for (let i = 0; i < path9.length; i++) {
19245
- const char = path9[i];
19247
+ for (let i = 0; i < path8.length; i++) {
19248
+ const char = path8[i];
19246
19249
  if (!inBrackets && char === ".") {
19247
19250
  if (current) {
19248
19251
  parts.push(current);
@@ -19373,10 +19376,10 @@ var require_redact = __commonJS({
19373
19376
  return current;
19374
19377
  }
19375
19378
  function redactPaths(obj, paths, censor, remove = false) {
19376
- for (const path9 of paths) {
19377
- const parts = parsePath(path9);
19379
+ for (const path8 of paths) {
19380
+ const parts = parsePath(path8);
19378
19381
  if (parts.includes("*")) {
19379
- redactWildcardPath(obj, parts, censor, path9, remove);
19382
+ redactWildcardPath(obj, parts, censor, path8, remove);
19380
19383
  } else {
19381
19384
  if (remove) {
19382
19385
  removeKey(obj, parts);
@@ -19461,8 +19464,8 @@ var require_redact = __commonJS({
19461
19464
  }
19462
19465
  } else {
19463
19466
  if (afterWildcard.includes("*")) {
19464
- const wrappedCensor = typeof censor === "function" ? (value, path9) => {
19465
- const fullPath = [...pathArray.slice(0, pathLength), ...path9];
19467
+ const wrappedCensor = typeof censor === "function" ? (value, path8) => {
19468
+ const fullPath = [...pathArray.slice(0, pathLength), ...path8];
19466
19469
  return censor(value, fullPath);
19467
19470
  } : censor;
19468
19471
  redactWildcardPath(current, afterWildcard, wrappedCensor, originalPath, remove);
@@ -19497,8 +19500,8 @@ var require_redact = __commonJS({
19497
19500
  return null;
19498
19501
  }
19499
19502
  const pathStructure = /* @__PURE__ */ new Map();
19500
- for (const path9 of pathsToClone) {
19501
- const parts = parsePath(path9);
19503
+ for (const path8 of pathsToClone) {
19504
+ const parts = parsePath(path8);
19502
19505
  let current = pathStructure;
19503
19506
  for (let i = 0; i < parts.length; i++) {
19504
19507
  const part = parts[i];
@@ -19550,24 +19553,24 @@ var require_redact = __commonJS({
19550
19553
  }
19551
19554
  return cloneSelectively(obj, pathStructure);
19552
19555
  }
19553
- function validatePath(path9) {
19554
- if (typeof path9 !== "string") {
19556
+ function validatePath(path8) {
19557
+ if (typeof path8 !== "string") {
19555
19558
  throw new Error("Paths must be (non-empty) strings");
19556
19559
  }
19557
- if (path9 === "") {
19560
+ if (path8 === "") {
19558
19561
  throw new Error("Invalid redaction path ()");
19559
19562
  }
19560
- if (path9.includes("..")) {
19561
- throw new Error(`Invalid redaction path (${path9})`);
19563
+ if (path8.includes("..")) {
19564
+ throw new Error(`Invalid redaction path (${path8})`);
19562
19565
  }
19563
- if (path9.includes(",")) {
19564
- throw new Error(`Invalid redaction path (${path9})`);
19566
+ if (path8.includes(",")) {
19567
+ throw new Error(`Invalid redaction path (${path8})`);
19565
19568
  }
19566
19569
  let bracketCount = 0;
19567
19570
  let inQuotes = false;
19568
19571
  let quoteChar = "";
19569
- for (let i = 0; i < path9.length; i++) {
19570
- const char = path9[i];
19572
+ for (let i = 0; i < path8.length; i++) {
19573
+ const char = path8[i];
19571
19574
  if ((char === '"' || char === "'") && bracketCount > 0) {
19572
19575
  if (!inQuotes) {
19573
19576
  inQuotes = true;
@@ -19581,20 +19584,20 @@ var require_redact = __commonJS({
19581
19584
  } else if (char === "]" && !inQuotes) {
19582
19585
  bracketCount--;
19583
19586
  if (bracketCount < 0) {
19584
- throw new Error(`Invalid redaction path (${path9})`);
19587
+ throw new Error(`Invalid redaction path (${path8})`);
19585
19588
  }
19586
19589
  }
19587
19590
  }
19588
19591
  if (bracketCount !== 0) {
19589
- throw new Error(`Invalid redaction path (${path9})`);
19592
+ throw new Error(`Invalid redaction path (${path8})`);
19590
19593
  }
19591
19594
  }
19592
19595
  function validatePaths(paths) {
19593
19596
  if (!Array.isArray(paths)) {
19594
19597
  throw new TypeError("paths must be an array");
19595
19598
  }
19596
- for (const path9 of paths) {
19597
- validatePath(path9);
19599
+ for (const path8 of paths) {
19600
+ validatePath(path8);
19598
19601
  }
19599
19602
  }
19600
19603
  function slowRedact(options = {}) {
@@ -19762,8 +19765,8 @@ var require_redaction = __commonJS({
19762
19765
  if (shape[k] === null) {
19763
19766
  o[k] = (value) => topCensor(value, [k]);
19764
19767
  } else {
19765
- const wrappedCensor = typeof censor === "function" ? (value, path9) => {
19766
- return censor(value, [k, ...path9]);
19768
+ const wrappedCensor = typeof censor === "function" ? (value, path8) => {
19769
+ return censor(value, [k, ...path8]);
19767
19770
  } : censor;
19768
19771
  o[k] = Redact({
19769
19772
  paths: shape[k],
@@ -19984,7 +19987,7 @@ var require_sonic_boom = __commonJS({
19984
19987
  var fs2 = __require("fs");
19985
19988
  var EventEmitter2 = __require("events");
19986
19989
  var inherits = __require("util").inherits;
19987
- var path9 = __require("path");
19990
+ var path8 = __require("path");
19988
19991
  var sleep = require_atomic_sleep();
19989
19992
  var assert = __require("assert");
19990
19993
  var BUSY_WRITE_TIMEOUT = 100;
@@ -20038,7 +20041,7 @@ var require_sonic_boom = __commonJS({
20038
20041
  const mode = sonic.mode;
20039
20042
  if (sonic.sync) {
20040
20043
  try {
20041
- if (sonic.mkdir) fs2.mkdirSync(path9.dirname(file), { recursive: true });
20044
+ if (sonic.mkdir) fs2.mkdirSync(path8.dirname(file), { recursive: true });
20042
20045
  const fd = fs2.openSync(file, flags, mode);
20043
20046
  fileOpened(null, fd);
20044
20047
  } catch (err) {
@@ -20046,7 +20049,7 @@ var require_sonic_boom = __commonJS({
20046
20049
  throw err;
20047
20050
  }
20048
20051
  } else if (sonic.mkdir) {
20049
- fs2.mkdir(path9.dirname(file), { recursive: true }, (err) => {
20052
+ fs2.mkdir(path8.dirname(file), { recursive: true }, (err) => {
20050
20053
  if (err) return fileOpened(err);
20051
20054
  fs2.open(file, flags, mode, fileOpened);
20052
20055
  });
@@ -21378,15 +21381,15 @@ var require_transport = __commonJS({
21378
21381
  if (!unquoted) {
21379
21382
  return false;
21380
21383
  }
21381
- let path9 = unquoted;
21382
- if (path9.startsWith("file://")) {
21384
+ let path8 = unquoted;
21385
+ if (path8.startsWith("file://")) {
21383
21386
  try {
21384
- path9 = fileURLToPath2(path9);
21387
+ path8 = fileURLToPath2(path8);
21385
21388
  } catch {
21386
21389
  return false;
21387
21390
  }
21388
21391
  }
21389
- return isAbsolute(path9) && !existsSync(path9);
21392
+ return isAbsolute(path8) && !existsSync(path8);
21390
21393
  }
21391
21394
  function stripQuotes(value) {
21392
21395
  const first = value[0];
@@ -23288,12 +23291,11 @@ var require_pino = __commonJS({
23288
23291
 
23289
23292
  // apps/cli/src/program.ts
23290
23293
  import os3 from "node:os";
23291
- import path8 from "node:path";
23292
23294
 
23293
23295
  // apps/cli/package.json
23294
23296
  var package_default = {
23295
23297
  name: "@dxc/cli",
23296
- version: "0.1.5",
23298
+ version: "0.1.7",
23297
23299
  private: true,
23298
23300
  type: "module",
23299
23301
  bin: {
@@ -26432,9 +26434,9 @@ Expecting one of '${allowedValues.join("', '")}'`);
26432
26434
  * @param {string} [path]
26433
26435
  * @return {(string|null|Command)}
26434
26436
  */
26435
- executableDir(path9) {
26436
- if (path9 === void 0) return this._executableDir;
26437
- this._executableDir = path9;
26437
+ executableDir(path8) {
26438
+ if (path8 === void 0) return this._executableDir;
26439
+ this._executableDir = path8;
26438
26440
  return this;
26439
26441
  }
26440
26442
  /**
@@ -26737,7 +26739,7 @@ async function runDoctor(runtime) {
26737
26739
 
26738
26740
  // apps/cli/src/profile.ts
26739
26741
  import { randomUUID } from "node:crypto";
26740
- import { readFile, stat } from "node:fs/promises";
26742
+ import { lstat, readFile, rename, stat } from "node:fs/promises";
26741
26743
  import path2 from "node:path";
26742
26744
  var PROFILE_DISPLAY_PATH = "~/.dxc/content-profile.json";
26743
26745
  var MEMORY_DISPLAY_PATH = "~/.dxc/content-memory.json";
@@ -26745,12 +26747,16 @@ var USER_MEMORY_DISPLAY_PATH = "~/.dxc/USER.md";
26745
26747
  var PROFILE_MAXIMUM_BYTES = 64 * 1024;
26746
26748
  var MEMORY_MAXIMUM_BYTES = 128 * 1024;
26747
26749
  var ProfileCliError = class extends Error {
26748
- constructor(code, message) {
26750
+ constructor(code, message, hint, fields) {
26749
26751
  super(message);
26750
26752
  this.code = code;
26753
+ this.hint = hint;
26754
+ this.fields = fields;
26751
26755
  this.name = "ProfileCliError";
26752
26756
  }
26753
26757
  code;
26758
+ hint;
26759
+ fields;
26754
26760
  };
26755
26761
  var ContentMemoryCliError = class extends Error {
26756
26762
  constructor(code, message) {
@@ -26921,9 +26927,9 @@ async function refreshUserMemory(homeDirectory, user, now) {
26921
26927
  Buffer.from(renderUserMemory(user, memory.memories))
26922
26928
  );
26923
26929
  }
26924
- async function readProfileInput(currentDirectory, inputPath) {
26930
+ async function readProfileInput(currentDirectory, homeDirectory, inputPath) {
26925
26931
  try {
26926
- const target = path2.resolve(currentDirectory, inputPath);
26932
+ const target = resolveUserPath({ currentDirectory, homeDirectory, input: inputPath });
26927
26933
  const metadata = await stat(target);
26928
26934
  if (!metadata.isFile() || metadata.size > PROFILE_MAXIMUM_BYTES) {
26929
26935
  throw new ProfileCliError("DXC_PROFILE_INPUT_INVALID", "Profile input is invalid");
@@ -26937,7 +26943,45 @@ async function readProfileInput(currentDirectory, inputPath) {
26937
26943
  if (error instanceof ProfileCliError) {
26938
26944
  throw error;
26939
26945
  }
26940
- throw new ProfileCliError("DXC_PROFILE_INPUT_INVALID", "Profile input is invalid");
26946
+ throw new ProfileCliError(
26947
+ "DXC_PROFILE_INPUT_INVALID",
26948
+ "\u753B\u50CF\u8F93\u5165\u6587\u4EF6\u65E0\u6CD5\u8BFB\u53D6\u6216\u4E0D\u662F\u6709\u6548 JSON\u3002",
26949
+ "\u8BF7\u8BA9 DxC \u5DE5\u4F5C\u6D41\u91CD\u65B0\u751F\u6210\u753B\u50CF\u8F93\u5165\uFF1B\u65E0\u9700\u624B\u52A8\u4FEE\u6539\u8DEF\u5F84\u6216\u5E94\u7528\u6570\u636E\u6587\u4EF6\u3002"
26950
+ );
26951
+ }
26952
+ }
26953
+ function issueFields(issues) {
26954
+ return [
26955
+ ...new Set(
26956
+ issues.map((issue) => issue.path.map(String).join(".")).filter((field) => field.length > 0)
26957
+ )
26958
+ ];
26959
+ }
26960
+ async function readProfileForSave(target, timestamp) {
26961
+ try {
26962
+ return await readProfile(target);
26963
+ } catch (error) {
26964
+ if (!(error instanceof ProfileCliError) || error.code !== "DXC_PROFILE_INVALID") {
26965
+ throw error;
26966
+ }
26967
+ try {
26968
+ const metadata = await lstat(target);
26969
+ if (!metadata.isFile() || metadata.isSymbolicLink()) {
26970
+ throw error;
26971
+ }
26972
+ const suffix = timestamp.replaceAll(":", "-");
26973
+ await rename(target, `${target}.invalid-${suffix}.bak`);
26974
+ return void 0;
26975
+ } catch (recoveryError) {
26976
+ if (recoveryError === error) {
26977
+ throw error;
26978
+ }
26979
+ throw new ProfileCliError(
26980
+ "DXC_PROFILE_INVALID",
26981
+ "\u53D1\u73B0\u65E0\u6548\u7684\u65E7\u753B\u50CF\uFF0C\u4F46\u65E0\u6CD5\u5B89\u5168\u5907\u4EFD\u5E76\u6062\u590D\u3002",
26982
+ "\u8BF7\u8BA9 DxC \u5DE5\u4F5C\u6D41\u91CD\u8BD5\uFF1B\u4E0D\u8981\u624B\u52A8\u5220\u9664 ~/.dxc \u4E2D\u7684\u6587\u4EF6\u3002"
26983
+ );
26984
+ }
26941
26985
  }
26942
26986
  }
26943
26987
  var ProfileCli = class {
@@ -26953,14 +26997,20 @@ var ProfileCli = class {
26953
26997
  }
26954
26998
  async save(inputPath) {
26955
26999
  const input = contentProfileInputSchema.safeParse(
26956
- await readProfileInput(this.#currentDirectory, inputPath)
27000
+ await readProfileInput(this.#currentDirectory, this.#homeDirectory, inputPath)
26957
27001
  );
26958
27002
  if (!input.success) {
26959
- throw new ProfileCliError("DXC_PROFILE_INPUT_INVALID", "Profile input is invalid");
27003
+ const fields = issueFields(input.error.issues);
27004
+ throw new ProfileCliError(
27005
+ "DXC_PROFILE_INPUT_INVALID",
27006
+ fields.length === 0 ? "\u753B\u50CF\u8F93\u5165\u4E0D\u7B26\u5408\u5F53\u524D\u7248\u672C\u8981\u6C42\u3002" : `\u753B\u50CF\u8F93\u5165\u7F3A\u5C11\u6216\u5305\u542B\u65E0\u6548\u5B57\u6BB5\uFF1A${fields.join("\u3001")}\u3002`,
27007
+ "\u8BF7\u8BA9 DxC \u5DE5\u4F5C\u6D41\u8865\u9F50\u8FD9\u4E9B\u5B57\u6BB5\u540E\u81EA\u52A8\u91CD\u8BD5\uFF1B\u65E0\u9700\u624B\u5199 JSON\u3002",
27008
+ fields
27009
+ );
26960
27010
  }
26961
27011
  const target = profilePath(this.#homeDirectory);
26962
- const existing = await readProfile(target);
26963
27012
  const timestamp = this.#now().toISOString();
27013
+ const existing = await readProfileForSave(target, timestamp);
26964
27014
  const profile = contentProfileSchema.parse({
26965
27015
  ...input.data,
26966
27016
  createdAt: existing?.createdAt ?? timestamp,
@@ -26986,7 +27036,7 @@ var ProfileCli = class {
26986
27036
  }
26987
27037
  async update(inputPath) {
26988
27038
  const input = contentProfileUpdateInputSchema.safeParse(
26989
- await readProfileInput(this.#currentDirectory, inputPath)
27039
+ await readProfileInput(this.#currentDirectory, this.#homeDirectory, inputPath)
26990
27040
  );
26991
27041
  if (!input.success) {
26992
27042
  throw new ProfileCliError("DXC_PROFILE_INPUT_INVALID", "Profile update input is invalid");
@@ -27056,7 +27106,7 @@ var ContentMemoryCli = class {
27056
27106
  }
27057
27107
  async add(inputPath) {
27058
27108
  const input = contentMemoryInputSchema.safeParse(
27059
- await readProfileInput(this.#currentDirectory, inputPath)
27109
+ await readProfileInput(this.#currentDirectory, this.#homeDirectory, inputPath)
27060
27110
  );
27061
27111
  if (!input.success) {
27062
27112
  throw new ContentMemoryCliError(
@@ -27155,15 +27205,15 @@ var ContentMemoryCli = class {
27155
27205
  };
27156
27206
 
27157
27207
  // apps/cli/src/project.ts
27158
- import { createHash as createHash4, randomUUID as randomUUID2 } from "node:crypto";
27208
+ import { createHash as createHash4, randomUUID as randomUUID3 } from "node:crypto";
27159
27209
  import { createReadStream } from "node:fs";
27160
- import { lstat, mkdir, readFile as readFile2, rename, unlink, writeFile } from "node:fs/promises";
27210
+ import { lstat as lstat2, mkdir, readFile as readFile3, rename as rename3, unlink as unlink2, writeFile as writeFile2 } from "node:fs/promises";
27161
27211
  import path4 from "node:path";
27162
27212
 
27163
27213
  // apps/cli/src/stage-artifact.ts
27164
- import { createHash as createHash3 } from "node:crypto";
27214
+ import { createHash as createHash3, randomUUID as randomUUID2 } from "node:crypto";
27165
27215
  import { constants as fileConstants } from "node:fs";
27166
- import { open } from "node:fs/promises";
27216
+ import { open, readFile as readFile2, rename as rename2, unlink, writeFile } from "node:fs/promises";
27167
27217
  import path3 from "node:path";
27168
27218
 
27169
27219
  // packages/renderer-wechat/src/article.ts
@@ -28413,6 +28463,30 @@ var tn = x.lex;
28413
28463
  // packages/renderer-wechat/src/article.ts
28414
28464
  var import_yaml = __toESM(require_dist(), 1);
28415
28465
  import { z as z2 } from "zod";
28466
+
28467
+ // packages/renderer-wechat/src/asset-path.ts
28468
+ function normalizeLogicalAssetPath(value) {
28469
+ let normalized;
28470
+ try {
28471
+ normalized = decodeURIComponent(value.trim()).replaceAll("\\", "/");
28472
+ } catch {
28473
+ return void 0;
28474
+ }
28475
+ if (normalized.length === 0 || normalized.includes("\0") || normalized.startsWith("/") || normalized.startsWith("//") || normalized.includes("?") || normalized.includes("#") || /^[a-z][a-z0-9+.-]*:/iu.test(normalized)) {
28476
+ return void 0;
28477
+ }
28478
+ const segments = normalized.split("/");
28479
+ const portableSegments = segments[0] === "." ? segments.slice(1) : segments;
28480
+ if (portableSegments.length === 0 || portableSegments.some((segment) => segment.length === 0 || segment === "." || segment === "..")) {
28481
+ return void 0;
28482
+ }
28483
+ return portableSegments.join("/");
28484
+ }
28485
+ function isSafeLogicalAssetPath(value) {
28486
+ return normalizeLogicalAssetPath(value) !== void 0;
28487
+ }
28488
+
28489
+ // packages/renderer-wechat/src/article.ts
28416
28490
  var dxcArticleMetadataSchema = z2.object({
28417
28491
  artifactStatus: z2.enum(["complete", "awaiting-user", "blocked"]),
28418
28492
  contract: z2.literal("dxc-content-stage@1"),
@@ -28425,6 +28499,12 @@ var dxcArticleMetadataSchema = z2.object({
28425
28499
  }).strict()
28426
28500
  ),
28427
28501
  projectId: z2.uuid(),
28502
+ quoteSnapshots: z2.array(
28503
+ z2.object({
28504
+ contentSha256: z2.string().regex(/^[a-f0-9]{64}$/u),
28505
+ quoteId: z2.uuid()
28506
+ }).strict()
28507
+ ).max(50).default([]),
28428
28508
  skill: z2.string().regex(/^dxc-[a-z0-9]+(?:-[a-z0-9]+)*@\d+\.\d+\.\d+$/u),
28429
28509
  stage: z2.literal("article"),
28430
28510
  workflowId: z2.literal("dxc-article@1")
@@ -28463,7 +28543,7 @@ var ArticleDocumentValidationError = class extends Error {
28463
28543
  }
28464
28544
  };
28465
28545
  function issuePaths(error) {
28466
- return error.issues.map((issue) => issue.path.join(".")).filter((path9) => path9.length > 0);
28546
+ return error.issues.map((issue) => issue.path.join(".")).filter((path8) => path8.length > 0);
28467
28547
  }
28468
28548
  function plainTokenText(tokens) {
28469
28549
  return tokens.map((token) => {
@@ -28490,7 +28570,7 @@ function collectInlineImages(marked, tokens) {
28490
28570
  if (!isImageToken(token)) {
28491
28571
  return;
28492
28572
  }
28493
- const logicalPath = token.href.trim();
28573
+ const logicalPath = normalizeLogicalAssetPath(token.href) ?? token.href.trim();
28494
28574
  if (!seen.has(logicalPath)) {
28495
28575
  seen.add(logicalPath);
28496
28576
  paths.push(logicalPath);
@@ -28550,7 +28630,8 @@ function parseArticleDocument(source) {
28550
28630
  const tokens = marked.lexer(frontmatter.body);
28551
28631
  const title = frontmatter.value.title ?? firstHeadingTitle(tokens);
28552
28632
  const digest = frontmatter.value.digest ?? frontmatter.value.wechat_digest;
28553
- const coverImage = frontmatter.value.coverImage ?? frontmatter.value.wechat_cover_image;
28633
+ const rawCoverImage = frontmatter.value.coverImage ?? frontmatter.value.wechat_cover_image;
28634
+ const coverImage = rawCoverImage === void 0 ? void 0 : normalizeLogicalAssetPath(rawCoverImage) ?? rawCoverImage.trim();
28554
28635
  const commentsValue = frontmatter.value.commentsEnabled ?? frontmatter.value.wechat_comments ?? true;
28555
28636
  const result = articleBundleSchema.safeParse({
28556
28637
  schemaVersion: "1",
@@ -28995,20 +29076,6 @@ function isExternalHttpUrl(value) {
28995
29076
  return false;
28996
29077
  }
28997
29078
  }
28998
- function isSafeLogicalAssetPath(value) {
28999
- let path9;
29000
- try {
29001
- path9 = decodeURIComponent(value.trim()).replaceAll("\\", "/");
29002
- } catch {
29003
- return false;
29004
- }
29005
- if (path9.length === 0 || path9.includes("\0") || path9.startsWith("/") || path9.startsWith("//") || path9.includes("?") || path9.includes("#") || /^[a-z][a-z0-9+.-]*:/iu.test(path9)) {
29006
- return false;
29007
- }
29008
- const segments = path9.split("/");
29009
- const normalizedSegments = segments[0] === "." ? segments.slice(1) : segments;
29010
- return normalizedSegments.length > 0 && normalizedSegments.every((segment) => segment.length > 0 && segment !== "." && segment !== "..");
29011
- }
29012
29079
  function stripObsidianCalloutMarkers(markdown) {
29013
29080
  return markdown.replace(/^>\s*\[![^\]]+\][-+]?\s?[^\n]*$/gmu, ">");
29014
29081
  }
@@ -29066,10 +29133,11 @@ function createRenderer(styles) {
29066
29133
  return escapeHtml(text);
29067
29134
  },
29068
29135
  image({ href, text }) {
29069
- if (!isSafeLogicalAssetPath(href)) {
29136
+ const logicalPath = normalizeLogicalAssetPath(href);
29137
+ if (logicalPath === void 0) {
29070
29138
  return escapeHtml(text);
29071
29139
  }
29072
- return `<img style="${styles.image}" src="${escapeHtml(href)}" alt="${escapeHtml(text)}">`;
29140
+ return `<img style="${styles.image}" src="${escapeHtml(logicalPath)}" alt="${escapeHtml(text)}">`;
29073
29141
  },
29074
29142
  link({ tokens }) {
29075
29143
  return this.parser.parseInline(tokens);
@@ -29178,8 +29246,8 @@ function withoutManualReferences(tokens) {
29178
29246
  );
29179
29247
  return referenceIndex < 0 ? [...tokens] : tokens.slice(0, referenceIndex);
29180
29248
  }
29181
- function warning(code, message, path9) {
29182
- return path9 === void 0 ? { code, message } : { code, path: path9, message };
29249
+ function warning(code, message, path8) {
29250
+ return path8 === void 0 ? { code, message } : { code, path: path8, message };
29183
29251
  }
29184
29252
  function buildPreflight(article, html, observations) {
29185
29253
  const errors = [];
@@ -29345,6 +29413,288 @@ function parseFrontmatter2(source) {
29345
29413
  throw new StageArtifactValidationError(["YAML frontmatter"]);
29346
29414
  }
29347
29415
  }
29416
+ function recordValue(value) {
29417
+ return typeof value === "object" && value !== null && !Array.isArray(value) ? value : void 0;
29418
+ }
29419
+ function normalizedIsoDate(value, fallback) {
29420
+ if (typeof value !== "string") {
29421
+ return fallback;
29422
+ }
29423
+ const timestamp = new Date(value);
29424
+ return Number.isNaN(timestamp.valueOf()) ? fallback : timestamp.toISOString();
29425
+ }
29426
+ var CONTENT_ORIGINS = /* @__PURE__ */ new Set(["hotspot", "article", "keywords", "intent"]);
29427
+ function normalizedOrigin(value) {
29428
+ return typeof value === "string" && CONTENT_ORIGINS.has(value) ? value : void 0;
29429
+ }
29430
+ function comparableCharacters(value) {
29431
+ const characters = [];
29432
+ const indexes = [];
29433
+ for (const [index, character] of [...value].entries()) {
29434
+ if (/^[\p{L}\p{N}]$/u.test(character)) {
29435
+ characters.push(character.toLocaleLowerCase("zh-CN"));
29436
+ indexes.push(index);
29437
+ }
29438
+ }
29439
+ return { indexes, value: characters.join("") };
29440
+ }
29441
+ function exactArticleText(body, proposed) {
29442
+ if (body.includes(proposed)) {
29443
+ return proposed;
29444
+ }
29445
+ const article = comparableCharacters(body);
29446
+ const quote = comparableCharacters(proposed).value;
29447
+ if (quote.length === 0) {
29448
+ return void 0;
29449
+ }
29450
+ const start = article.value.indexOf(quote);
29451
+ if (start < 0 || article.value.indexOf(quote, start + 1) >= 0) {
29452
+ return void 0;
29453
+ }
29454
+ const first = article.indexes[start];
29455
+ const last = article.indexes[start + quote.length - 1];
29456
+ if (first === void 0 || last === void 0) {
29457
+ return void 0;
29458
+ }
29459
+ return [...body].slice(first, last + 1).join("").trim();
29460
+ }
29461
+ async function writeAtomically(target, bytes) {
29462
+ const temporary = `${target}.${randomUUID2()}.tmp`;
29463
+ try {
29464
+ await writeFile(temporary, bytes, { mode: 384 });
29465
+ await rename2(temporary, target);
29466
+ } catch (error) {
29467
+ await unlink(temporary).catch(() => void 0);
29468
+ throw error;
29469
+ }
29470
+ }
29471
+ async function bindDeliveryApprovalArtifact(options) {
29472
+ const source = (await readRegularFile(options.target, MAXIMUM_ARTIFACT_BYTES)).toString("utf8");
29473
+ const frontmatter = parseFrontmatter2(source);
29474
+ const value = recordValue(frontmatter.value);
29475
+ if (value === void 0) {
29476
+ throw new StageArtifactValidationError(["YAML frontmatter"]);
29477
+ }
29478
+ if (value["rootSnapshotId"] !== options.approval.rootSnapshotId || value["rootSnapshotHash"] !== options.approval.rootSnapshotHash) {
29479
+ throw new StageArtifactValidationError(["rootSnapshotId/rootSnapshotHash \u4E0E\u6279\u51C6\u8BF7\u6C42\u4E0D\u4E00\u81F4"]);
29480
+ }
29481
+ const intentState = options.intent === void 0 ? {} : options.intent.status === "SUCCEEDED" && options.intent.mediaId !== void 0 ? { intentId: options.intent.id, mediaId: options.intent.mediaId, state: "completed" } : options.intent.status === "FAILED" ? { intentId: options.intent.id, state: "failed" } : options.intent.progress.terminal ? { intentId: options.intent.id, state: "requires-attention" } : { intentId: options.intent.id, state: "processing" };
29482
+ const nextValue = {
29483
+ ...value,
29484
+ ...intentState,
29485
+ selectedSnapshotHash: options.approval.selectedSnapshotHash,
29486
+ selectedSnapshotId: options.approval.selectedSnapshotId,
29487
+ templateId: options.approval.templateId
29488
+ };
29489
+ const parsed = deliveryStageArtifactFrontmatterSchema.safeParse(nextValue);
29490
+ if (!parsed.success) {
29491
+ throw new StageArtifactValidationError(issuePaths2(parsed.error.issues));
29492
+ }
29493
+ await writeAtomically(
29494
+ options.target,
29495
+ `---
29496
+ ${(0, import_yaml2.stringify)(parsed.data, { lineWidth: 0 }).trimEnd()}
29497
+ ---
29498
+
29499
+ ${frontmatter.body}
29500
+ `
29501
+ );
29502
+ }
29503
+ async function normalizeGoldenLines(directory, body, logicalPath) {
29504
+ const target = insideProject(directory, logicalPath);
29505
+ let parsed;
29506
+ try {
29507
+ const bytes2 = await readFile2(target);
29508
+ if (bytes2.length === 0 || bytes2.length > 64 * 1024) {
29509
+ throw new StageArtifactValidationError([`${logicalPath} \u4E0D\u662F\u5408\u6CD5\u91D1\u53E5\u4EA4\u63A5\u6587\u4EF6`]);
29510
+ }
29511
+ parsed = JSON.parse(bytes2.toString("utf8"));
29512
+ } catch (error) {
29513
+ if (error.code === "ENOENT") {
29514
+ parsed = { lines: [], schemaVersion: "dxc-golden-lines@1" };
29515
+ } else if (error instanceof StageArtifactValidationError) {
29516
+ throw error;
29517
+ } else {
29518
+ throw new StageArtifactValidationError([`${logicalPath} \u4E0D\u662F\u5408\u6CD5\u91D1\u53E5\u4EA4\u63A5\u6587\u4EF6`]);
29519
+ }
29520
+ }
29521
+ const sidecar = goldenLinesSidecarSchema.safeParse(parsed);
29522
+ if (!sidecar.success) {
29523
+ throw new StageArtifactValidationError([`${logicalPath} \u4E0D\u662F\u5408\u6CD5\u91D1\u53E5\u4EA4\u63A5\u6587\u4EF6`]);
29524
+ }
29525
+ const normalized = {
29526
+ ...sidecar.data,
29527
+ lines: sidecar.data.lines.map((line) => ({
29528
+ ...line,
29529
+ text: exactArticleText(body, line.text) ?? line.text
29530
+ }))
29531
+ };
29532
+ const bytes = Buffer.from(`${JSON.stringify(normalized, void 0, 2)}
29533
+ `, "utf8");
29534
+ await writeAtomically(target, bytes);
29535
+ return sha256(bytes);
29536
+ }
29537
+ async function normalizeStageArtifact(options) {
29538
+ const artifactPath = options.manifest.artifacts[options.stage];
29539
+ const target = insideProject(options.directory, artifactPath);
29540
+ const source = (await readRegularFile(
29541
+ target,
29542
+ options.stage === "article" ? MAXIMUM_ARTICLE_BYTES : MAXIMUM_ARTIFACT_BYTES
29543
+ )).toString("utf8");
29544
+ const frontmatter = parseFrontmatter2(source);
29545
+ const value = recordValue(frontmatter.value);
29546
+ if (value === void 0) {
29547
+ throw new StageArtifactValidationError(["YAML frontmatter"]);
29548
+ }
29549
+ const previousDxc = recordValue(value["dxc"]) ?? {};
29550
+ const nextValue = { ...value };
29551
+ const rootQuoteSnapshots = nextValue["quoteSnapshots"];
29552
+ delete nextValue["quoteSnapshots"];
29553
+ nextValue["dxc"] = {
29554
+ artifactStatus: options.artifactStatus,
29555
+ contract: "dxc-content-stage@1",
29556
+ createdAt: normalizedIsoDate(previousDxc["createdAt"], options.createdAt),
29557
+ inputs: options.inputs.map((input) => ({
29558
+ kind: input.kind,
29559
+ path: input.path,
29560
+ ...input.sha256 === void 0 ? {} : { sha256: input.sha256 }
29561
+ })),
29562
+ projectId: options.manifest.projectId,
29563
+ ...options.stage === "article" ? {
29564
+ quoteSnapshots: previousDxc["quoteSnapshots"] ?? rootQuoteSnapshots ?? []
29565
+ } : {},
29566
+ skill: `${options.skill}@${options.skillVersion}`,
29567
+ stage: options.stage,
29568
+ workflowId: options.manifest.workflowId
29569
+ };
29570
+ if (options.stage === "research") {
29571
+ const origin = normalizedOrigin(nextValue["origin"]) ?? "intent";
29572
+ nextValue["origin"] = origin;
29573
+ nextValue["researchMode"] ??= origin === "hotspot" ? "viewpoint-scan" : "fact-only";
29574
+ const sources = Array.isArray(nextValue["sources"]) ? nextValue["sources"] : [];
29575
+ nextValue["sources"] = sources;
29576
+ nextValue["sourceCount"] = sources.length;
29577
+ if (origin !== "hotspot" && nextValue["researchMode"] === "fact-only") {
29578
+ nextValue["externalOpinionStatus"] ??= "not-applicable";
29579
+ nextValue["stanceCoverage"] ??= {
29580
+ oppose: "not-applicable",
29581
+ supplement: "not-applicable",
29582
+ support: "not-applicable"
29583
+ };
29584
+ nextValue["coverageNote"] ??= "\u672C\u6B21\u8F93\u5165\u4E0D\u5C5E\u4E8E\u70ED\u70B9\u89C2\u70B9\u626B\u63CF\uFF0C\u6309\u4E8B\u5B9E\u4E0E\u7528\u6237\u6750\u6599\u5B8C\u6210\u7814\u7A76\u3002";
29585
+ }
29586
+ }
29587
+ if (options.stage === "brief" && normalizedOrigin(nextValue["origin"]) === void 0) {
29588
+ let upstreamOrigin;
29589
+ try {
29590
+ const researchSource = (await readRegularFile(
29591
+ insideProject(options.directory, options.manifest.artifacts.research),
29592
+ MAXIMUM_ARTIFACT_BYTES
29593
+ )).toString("utf8");
29594
+ upstreamOrigin = normalizedOrigin(
29595
+ recordValue(parseFrontmatter2(researchSource).value)?.["origin"]
29596
+ );
29597
+ } catch {
29598
+ upstreamOrigin = void 0;
29599
+ }
29600
+ nextValue["origin"] = upstreamOrigin ?? "intent";
29601
+ }
29602
+ if (options.stage === "article") {
29603
+ const defaultGoldenLinesPath = artifactPath.replace(/\.md$/iu, ".golden-lines.json");
29604
+ const goldenLinesPath = typeof nextValue["goldenLinesPath"] === "string" && nextValue["goldenLinesPath"].trim().length > 0 ? nextValue["goldenLinesPath"].trim() : defaultGoldenLinesPath;
29605
+ nextValue["goldenLinesPath"] = goldenLinesPath;
29606
+ nextValue["goldenLinesSha256"] = await normalizeGoldenLines(
29607
+ options.directory,
29608
+ frontmatter.body,
29609
+ goldenLinesPath
29610
+ );
29611
+ }
29612
+ if (options.stage === "titles") {
29613
+ const articleInput = options.inputs.find((input) => input.kind === "article");
29614
+ if (articleInput?.sha256 !== void 0) {
29615
+ nextValue["articleSha256"] = articleInput.sha256;
29616
+ }
29617
+ }
29618
+ if (options.stage === "visual-plan") {
29619
+ nextValue["assetsDirectory"] ??= options.manifest.assetsDirectory;
29620
+ nextValue["inlineImagesSupported"] ??= true;
29621
+ nextValue["inlineAssets"] ??= [];
29622
+ if (typeof nextValue["coverAsset"] === "string") {
29623
+ nextValue["coverSha256"] = sha256(
29624
+ await readRegularFile(
29625
+ insideProject(options.directory, nextValue["coverAsset"]),
29626
+ MAXIMUM_COVER_BYTES
29627
+ )
29628
+ );
29629
+ }
29630
+ if (Array.isArray(nextValue["inlineAssets"])) {
29631
+ nextValue["inlineAssets"] = await Promise.all(
29632
+ nextValue["inlineAssets"].map(async (asset) => {
29633
+ const value2 = recordValue(asset);
29634
+ if (value2 === void 0 || typeof value2["path"] !== "string") {
29635
+ return asset;
29636
+ }
29637
+ return {
29638
+ ...value2,
29639
+ sha256: sha256(
29640
+ await readRegularFile(
29641
+ insideProject(options.directory, value2["path"]),
29642
+ MAXIMUM_INLINE_IMAGE_BYTES
29643
+ )
29644
+ )
29645
+ };
29646
+ })
29647
+ );
29648
+ }
29649
+ }
29650
+ if (options.stage === "quality-review") {
29651
+ const researchInput = options.inputs.find((input) => input.kind === "research");
29652
+ if (researchInput === void 0) {
29653
+ nextValue["researchCoverage"] = "not-applicable";
29654
+ } else {
29655
+ const researchSource = (await readRegularFile(
29656
+ insideProject(options.directory, options.manifest.artifacts.research),
29657
+ MAXIMUM_ARTIFACT_BYTES
29658
+ )).toString("utf8");
29659
+ const research = contentStageArtifactFrontmatterSchema("research").safeParse(
29660
+ parseFrontmatter2(researchSource).value
29661
+ );
29662
+ if (!research.success) {
29663
+ throw new StageArtifactValidationError(["research \u4E0D\u662F\u5F53\u524D\u7248\u672C\u7684\u5B8C\u6574\u7814\u7A76\u4EA7\u7269"]);
29664
+ }
29665
+ nextValue["researchCoverage"] = "externalOpinionStatus" in research.data && research.data.externalOpinionStatus === "user-skipped" ? "warning" : "pass";
29666
+ }
29667
+ }
29668
+ if (options.stage === "delivery") {
29669
+ const legacySnapshotId = nextValue["snapshotId"];
29670
+ const legacySnapshotHash = nextValue["snapshotHash"];
29671
+ nextValue["rootSnapshotId"] ??= legacySnapshotId;
29672
+ nextValue["rootSnapshotHash"] ??= legacySnapshotHash;
29673
+ nextValue["selectedSnapshotId"] ??= legacySnapshotId;
29674
+ nextValue["selectedSnapshotHash"] ??= legacySnapshotHash;
29675
+ nextValue["templateId"] ??= "wechat-minimal@1";
29676
+ delete nextValue["snapshotId"];
29677
+ delete nextValue["snapshotHash"];
29678
+ if (typeof nextValue["rootSnapshotId"] === "string") {
29679
+ nextValue["idempotencyKey"] ??= `dxc:${options.manifest.projectId}:${nextValue["rootSnapshotId"]}`;
29680
+ }
29681
+ if (typeof nextValue["previewExpiresAt"] === "string") {
29682
+ nextValue["previewExpiresAt"] = normalizedIsoDate(
29683
+ nextValue["previewExpiresAt"],
29684
+ nextValue["previewExpiresAt"]
29685
+ );
29686
+ }
29687
+ }
29688
+ const normalizedSource = `---
29689
+ ${(0, import_yaml2.stringify)(nextValue, { lineWidth: 0 }).trimEnd()}
29690
+ ---
29691
+
29692
+ ${frontmatter.body}
29693
+ `;
29694
+ if (normalizedSource !== source) {
29695
+ await writeAtomically(target, normalizedSource);
29696
+ }
29697
+ }
29348
29698
  async function validateGoldenLinesSidecar(directory, articleBody, logicalPath, expectedSha256) {
29349
29699
  const bytes = await readRegularFile(insideProject(directory, logicalPath), 64 * 1024);
29350
29700
  if (sha256(bytes) !== expectedSha256) {
@@ -29434,6 +29784,28 @@ async function validateStageArtifact(options) {
29434
29784
  if (options.checkpointStatus === "completed" && ("verdict" in review ? review.verdict : void 0) !== "pass") {
29435
29785
  issues.push("verdict \u5FC5\u987B\u4E3A pass");
29436
29786
  }
29787
+ const researchInput = options.inputs.find((input) => input.kind === "research");
29788
+ if (researchInput === void 0) {
29789
+ if (!("researchCoverage" in review) || review.researchCoverage !== "not-applicable") {
29790
+ issues.push("researchCoverage \u5FC5\u987B\u4E3A not-applicable");
29791
+ }
29792
+ } else {
29793
+ const researchSource = (await readRegularFile(
29794
+ insideProject(options.directory, options.manifest.artifacts.research),
29795
+ MAXIMUM_ARTIFACT_BYTES
29796
+ )).toString("utf8");
29797
+ const research = contentStageArtifactFrontmatterSchema("research").safeParse(
29798
+ parseFrontmatter2(researchSource).value
29799
+ );
29800
+ if (!research.success) {
29801
+ issues.push("research \u4E0D\u662F\u5F53\u524D\u7248\u672C\u7684\u5B8C\u6574\u7814\u7A76\u4EA7\u7269");
29802
+ } else {
29803
+ const expectedCoverage = "externalOpinionStatus" in research.data && research.data.externalOpinionStatus === "user-skipped" ? "warning" : "pass";
29804
+ if (!("researchCoverage" in review) || review.researchCoverage !== expectedCoverage) {
29805
+ issues.push(`researchCoverage \u5FC5\u987B\u4E3A ${expectedCoverage}`);
29806
+ }
29807
+ }
29808
+ }
29437
29809
  }
29438
29810
  if (issues.length > 0) {
29439
29811
  throw new StageArtifactValidationError([...new Set(issues)]);
@@ -29464,7 +29836,7 @@ async function validateStageArtifact(options) {
29464
29836
  }
29465
29837
  if (options.stage === "delivery") {
29466
29838
  return {
29467
- confirmationSnapshotHash: deliveryStageArtifactFrontmatterSchema.parse(frontmatter.value).snapshotHash,
29839
+ confirmationSnapshotHash: deliveryStageArtifactFrontmatterSchema.parse(frontmatter.value).selectedSnapshotHash,
29468
29840
  snapshotType: "render-snapshot"
29469
29841
  };
29470
29842
  }
@@ -29484,11 +29856,29 @@ async function validateStageArtifact(options) {
29484
29856
  snapshotType: "stage-artifact"
29485
29857
  };
29486
29858
  }
29859
+ const semanticFrontmatter = { ...parsed.data };
29860
+ delete semanticFrontmatter["dxc"];
29487
29861
  return {
29488
- confirmationSnapshotHash: articleConfirmationSnapshotHash ?? sha256(Buffer.from(source, "utf8")),
29862
+ confirmationSnapshotHash: articleConfirmationSnapshotHash ?? sha256(
29863
+ Buffer.from(
29864
+ JSON.stringify({ body: frontmatter.body, frontmatter: semanticFrontmatter }),
29865
+ "utf8"
29866
+ )
29867
+ ),
29489
29868
  snapshotType: "stage-artifact"
29490
29869
  };
29491
29870
  }
29871
+ async function stageArtifactRequiresUserConfirmation(options) {
29872
+ if (options.stage !== "research") {
29873
+ return false;
29874
+ }
29875
+ const source = (await readRegularFile(
29876
+ insideProject(options.directory, options.manifest.artifacts.research),
29877
+ MAXIMUM_ARTIFACT_BYTES
29878
+ )).toString("utf8");
29879
+ const value = recordValue(parseFrontmatter2(source).value);
29880
+ return normalizedOrigin(value?.["origin"]) === "hotspot" && value?.["researchMode"] === "fact-only" && value?.["externalOpinionStatus"] === "user-skipped";
29881
+ }
29492
29882
 
29493
29883
  // apps/cli/src/project.ts
29494
29884
  var MANIFEST_NAME = "dxc.project.json";
@@ -29525,8 +29915,12 @@ var ProjectCliError = class extends Error {
29525
29915
  }
29526
29916
  code;
29527
29917
  };
29528
- function projectDirectory(currentDirectory, input) {
29529
- return path4.resolve(currentDirectory, input ?? ".");
29918
+ function migrateCheckpointInputKinds(required, optional, existing) {
29919
+ const allowedOptionalInputs = new Set(optional);
29920
+ return [...required, ...existing.filter((inputStage) => allowedOptionalInputs.has(inputStage))];
29921
+ }
29922
+ function projectDirectory(currentDirectory, homeDirectory, input) {
29923
+ return resolveUserPath({ currentDirectory, homeDirectory, input: input ?? "." });
29530
29924
  }
29531
29925
  function insideProject2(directory, relativePath) {
29532
29926
  const target = path4.resolve(directory, relativePath);
@@ -29544,11 +29938,11 @@ function errorCode(error) {
29544
29938
  }
29545
29939
  async function readJsonFile(target, maximumBytes, missingCode) {
29546
29940
  try {
29547
- const metadata = await lstat(target);
29941
+ const metadata = await lstat2(target);
29548
29942
  if (!metadata.isFile() || metadata.isSymbolicLink() || metadata.size > maximumBytes) {
29549
29943
  throw new ProjectCliError("DXC_PROJECT_INVALID", "Project state file is invalid");
29550
29944
  }
29551
- return JSON.parse(await readFile2(target, "utf8"));
29945
+ return JSON.parse(await readFile3(target, "utf8"));
29552
29946
  } catch (error) {
29553
29947
  if (error instanceof ProjectCliError) {
29554
29948
  throw error;
@@ -29563,19 +29957,19 @@ async function readJsonFile(target, maximumBytes, missingCode) {
29563
29957
  }
29564
29958
  }
29565
29959
  async function writeJsonAtomically(target, value) {
29566
- const temporary = `${target}.${randomUUID2()}.tmp`;
29960
+ const temporary = `${target}.${randomUUID3()}.tmp`;
29567
29961
  try {
29568
- await writeFile(temporary, `${JSON.stringify(value, void 0, 2)}
29962
+ await writeFile2(temporary, `${JSON.stringify(value, void 0, 2)}
29569
29963
  `, {
29570
29964
  encoding: "utf8",
29571
29965
  flag: "wx",
29572
29966
  mode: 384
29573
29967
  });
29574
- await rename(temporary, target);
29968
+ await rename3(temporary, target);
29575
29969
  } catch {
29576
29970
  throw new ProjectCliError("DXC_PROJECT_IO_FAILED", "Unable to save project state");
29577
29971
  } finally {
29578
- await unlink(temporary).catch(() => void 0);
29972
+ await unlink2(temporary).catch(() => void 0);
29579
29973
  }
29580
29974
  }
29581
29975
  async function loadProjectIndex(target) {
@@ -29641,7 +30035,7 @@ async function inspectArtifact(directory, manifest, kind) {
29641
30035
  const relativePath = manifest.artifacts[kind];
29642
30036
  const target = insideProject2(directory, relativePath);
29643
30037
  try {
29644
- const metadata = await lstat(target);
30038
+ const metadata = await lstat2(target);
29645
30039
  if (!metadata.isFile() || metadata.isSymbolicLink()) {
29646
30040
  throw new ProjectCliError("DXC_PROJECT_INVALID", "Project artifact is invalid");
29647
30041
  }
@@ -29823,16 +30217,18 @@ async function findNearestProjectDirectory(start) {
29823
30217
  }
29824
30218
  var ProjectCli = class {
29825
30219
  #currentDirectory;
30220
+ #homeDirectory;
29826
30221
  #now;
29827
30222
  #profilePath;
29828
30223
  #projectIndexPath;
29829
30224
  #randomUUID;
29830
30225
  constructor(dependencies) {
29831
30226
  this.#currentDirectory = dependencies.currentDirectory;
30227
+ this.#homeDirectory = dependencies.homeDirectory;
29832
30228
  this.#now = dependencies.now ?? (() => /* @__PURE__ */ new Date());
29833
30229
  this.#projectIndexPath = path4.join(dependencies.homeDirectory, PROJECT_INDEX_RELATIVE_PATH);
29834
30230
  this.#profilePath = path4.join(dependencies.homeDirectory, ".dxc", "content-profile.json");
29835
- this.#randomUUID = dependencies.randomUUID ?? randomUUID2;
30231
+ this.#randomUUID = dependencies.randomUUID ?? randomUUID3;
29836
30232
  }
29837
30233
  async #confirmationPolicy() {
29838
30234
  try {
@@ -29856,6 +30252,56 @@ var ProjectCli = class {
29856
30252
  }
29857
30253
  return stage === "article" || stage === "titles";
29858
30254
  }
30255
+ async #skipArticleAdoptionPrerequisites(directory, manifest, timestamp, execution) {
30256
+ const pendingCheckpoints = [];
30257
+ for (const stage of ["research", "brief", "outline"]) {
30258
+ const existing = await loadCheckpoint(directory, manifest, stage);
30259
+ if (existing !== void 0) {
30260
+ if (existing.status !== "skipped") {
30261
+ throw new ProjectCliError(
30262
+ "DXC_PROJECT_STAGE_INVALID",
30263
+ "\u5DF2\u6709\u6B63\u6587\u63A5\u7BA1\u53EA\u5141\u8BB8\u7528\u4E8E\u5C1A\u672A\u5F00\u59CB\u7684\u65B0\u9879\u76EE\uFF1B\u5DF2\u6709\u7814\u7A76\u6216\u5927\u7EB2\u65F6\u8BF7\u65B0\u5EFA\u9879\u76EE\u6216\u4ECE\u5F53\u524D\u9636\u6BB5\u7EE7\u7EED\u3002"
30264
+ );
30265
+ }
30266
+ continue;
30267
+ }
30268
+ const artifact = await inspectArtifact(directory, manifest, stage);
30269
+ if (artifact.status !== "missing") {
30270
+ throw new ProjectCliError(
30271
+ "DXC_PROJECT_STAGE_INVALID",
30272
+ "\u5DF2\u6709\u6B63\u6587\u63A5\u7BA1\u4E0D\u80FD\u9759\u9ED8\u8986\u76D6\u5DF2\u7ECF\u5B58\u5728\u7684\u524D\u7F6E\u4EA7\u7269\u3002"
30273
+ );
30274
+ }
30275
+ const checkpoint = stepCheckpointSchema.parse({
30276
+ checkpointVersion: "3",
30277
+ completedAt: timestamp,
30278
+ confirmation: "not-required",
30279
+ confirmationBinding: null,
30280
+ execution,
30281
+ inputs: [],
30282
+ metadata: {
30283
+ summary: "\u7528\u6237\u63D0\u4F9B\u4E86\u53EF\u4FE1\u65E2\u6709\u6B63\u6587\uFF0C\u672C\u8DEF\u7EBF\u4E0D\u9700\u8981\u91CD\u65B0\u751F\u6210\u7814\u7A76\u3001Brief \u6216\u5927\u7EB2\u3002"
30284
+ },
30285
+ outputs: [artifactReference(artifact)],
30286
+ projectId: manifest.projectId,
30287
+ revision: 1,
30288
+ skill: ARTICLE_ADOPTION_SKILL,
30289
+ stage,
30290
+ startedAt: timestamp,
30291
+ status: "skipped",
30292
+ updatedAt: timestamp,
30293
+ waitingFor: null,
30294
+ workflowId: manifest.workflowId
30295
+ });
30296
+ pendingCheckpoints.push({ checkpoint, stage });
30297
+ }
30298
+ for (const { checkpoint, stage } of pendingCheckpoints) {
30299
+ await writeJsonAtomically(
30300
+ insideProject2(directory, checkpointRelativePath(manifest, stage)),
30301
+ checkpoint
30302
+ );
30303
+ }
30304
+ }
29859
30305
  async #rememberProject(directory, manifest, updatedAt) {
29860
30306
  const index = await loadProjectIndex(this.#projectIndexPath);
29861
30307
  const projects = [
@@ -29880,10 +30326,10 @@ var ProjectCli = class {
29880
30326
  }
29881
30327
  }
29882
30328
  async assertCanInitialize(directoryInput) {
29883
- const directory = projectDirectory(this.#currentDirectory, directoryInput);
30329
+ const directory = projectDirectory(this.#currentDirectory, this.#homeDirectory, directoryInput);
29884
30330
  const manifestTarget = path4.join(directory, MANIFEST_NAME);
29885
30331
  try {
29886
- await lstat(manifestTarget);
30332
+ await lstat2(manifestTarget);
29887
30333
  throw new ProjectCliError("DXC_PROJECT_EXISTS", "A DxC project already exists");
29888
30334
  } catch (error) {
29889
30335
  if (error instanceof ProjectCliError) {
@@ -29895,7 +30341,7 @@ var ProjectCli = class {
29895
30341
  }
29896
30342
  }
29897
30343
  async initialize(directoryInput, title, knowledgeArticleCount = 0) {
29898
- const directory = projectDirectory(this.#currentDirectory, directoryInput);
30344
+ const directory = projectDirectory(this.#currentDirectory, this.#homeDirectory, directoryInput);
29899
30345
  const manifestTarget = path4.join(directory, MANIFEST_NAME);
29900
30346
  try {
29901
30347
  await mkdir(directory, { recursive: true });
@@ -29965,7 +30411,7 @@ var ProjectCli = class {
29965
30411
  const summary = workflowSummary(checkpoints);
29966
30412
  let assetsDirectoryReady = false;
29967
30413
  try {
29968
- const metadata = await lstat(insideProject2(directory, manifest.assetsDirectory));
30414
+ const metadata = await lstat2(insideProject2(directory, manifest.assetsDirectory));
29969
30415
  assetsDirectoryReady = metadata.isDirectory() && !metadata.isSymbolicLink();
29970
30416
  } catch (error) {
29971
30417
  if (errorCode(error) !== "ENOENT") {
@@ -29988,7 +30434,7 @@ var ProjectCli = class {
29988
30434
  });
29989
30435
  }
29990
30436
  async status(directoryInput) {
29991
- const directory = projectDirectory(this.#currentDirectory, directoryInput);
30437
+ const directory = projectDirectory(this.#currentDirectory, this.#homeDirectory, directoryInput);
29992
30438
  const result = await this.#statusAtDirectory(directory);
29993
30439
  await this.#rememberProject(directory, result.data.manifest, this.#now().toISOString());
29994
30440
  return result;
@@ -30000,7 +30446,7 @@ var ProjectCli = class {
30000
30446
  }
30001
30447
  const index = await loadProjectIndex(this.#projectIndexPath);
30002
30448
  const currentProjectDirectory = await findNearestProjectDirectory(
30003
- projectDirectory(this.#currentDirectory, directoryInput)
30449
+ projectDirectory(this.#currentDirectory, this.#homeDirectory, directoryInput)
30004
30450
  );
30005
30451
  const candidates = [...index.projects];
30006
30452
  let currentCandidate;
@@ -30077,34 +30523,45 @@ var ProjectCli = class {
30077
30523
  throw new ProjectCliError("DXC_PROJECT_STAGE_INVALID", "Checkpoint options are invalid");
30078
30524
  }
30079
30525
  const expectedSkill = CONTENT_STAGE_SKILLS[stage.data];
30080
- const adoptsExistingArticle = stage.data === "article" && options.skill === ARTICLE_ADOPTION_SKILL.name && options.skillVersion === ARTICLE_ADOPTION_SKILL.version;
30081
- if (!adoptsExistingArticle && (options.skill !== expectedSkill.name || options.skillVersion !== expectedSkill.version)) {
30526
+ const effectiveSkill = options.skill ?? expectedSkill.name;
30527
+ const effectiveSkillVersion = options.skillVersion ?? expectedSkill.version;
30528
+ const adoptsExistingArticle = stage.data === "article" && effectiveSkill === ARTICLE_ADOPTION_SKILL.name && effectiveSkillVersion === ARTICLE_ADOPTION_SKILL.version;
30529
+ if (!adoptsExistingArticle && (effectiveSkill !== expectedSkill.name || effectiveSkillVersion !== expectedSkill.version)) {
30082
30530
  throw new ProjectCliError(
30083
30531
  "DXC_PROJECT_STAGE_INVALID",
30084
30532
  `\u9636\u6BB5 ${stage.data} \u5FC5\u987B\u7531 ${expectedSkill.name}@${expectedSkill.version} \u5199\u5165\u68C0\u67E5\u70B9\u3002`
30085
30533
  );
30086
30534
  }
30087
- const requiresUserConfirmation = await this.#requiresUserConfirmation(stage.data);
30088
- const confirmationRequired = status.data === "completed" && requiresUserConfirmation && options.confirmed !== true;
30089
- const effectiveStatus = confirmationRequired ? "awaiting-user" : status.data;
30090
- const waitingFor = confirmationRequired ? requestedWaitingFor ?? `\u8BF7\u786E\u8BA4 ${stage.data} \u9636\u6BB5\u5F53\u524D\u5FEB\u7167\uFF1B\u786E\u8BA4\u540E\u4F7F\u7528 --confirm \u5B8C\u6210\u8BE5\u9636\u6BB5\u3002` : requestedWaitingFor;
30091
- if (effectiveStatus === "failed" && options.errorCode === void 0) {
30092
- throw new ProjectCliError(
30093
- "DXC_PROJECT_STAGE_INVALID",
30094
- "Failed checkpoint needs an error code"
30095
- );
30096
- }
30097
- if (effectiveStatus === "awaiting-user" && (waitingFor === void 0 || waitingFor.length === 0) || effectiveStatus !== "awaiting-user" && waitingFor !== void 0) {
30535
+ const directory = projectDirectory(
30536
+ this.#currentDirectory,
30537
+ this.#homeDirectory,
30538
+ options.directory
30539
+ );
30540
+ const manifest = await loadManifest(directory);
30541
+ const existing = await loadCheckpoint(directory, manifest, stage.data);
30542
+ const timestamp = this.#now().toISOString();
30543
+ const currentStatus = await this.#statusAtDirectory(directory);
30544
+ const adoptionCanEnter = adoptsExistingArticle && (currentStatus.data.nextStage === "research" || currentStatus.data.nextStage === "article");
30545
+ if (!adoptionCanEnter && currentStatus.data.nextStage !== stage.data) {
30098
30546
  throw new ProjectCliError(
30099
30547
  "DXC_PROJECT_STAGE_INVALID",
30100
- "Awaiting checkpoint needs one waiting-for prompt"
30548
+ currentStatus.data.nextStage === null ? "\u5DE5\u4F5C\u6D41\u5DF2\u7ECF\u5B8C\u6210\uFF1B\u8BF7\u5148\u4FEE\u6539\u76EE\u6807\u9636\u6BB5\u4EA7\u7269\uFF0C\u4F7F\u8BE5\u9636\u6BB5\u8FDB\u5165 stale \u540E\u518D\u91CD\u505A\u3002" : `\u5F53\u524D\u5FC5\u987B\u5148\u5904\u7406 ${currentStatus.data.nextStage}\uFF0C\u4E0D\u80FD\u8D8A\u8FC7\u672A\u5B8C\u6210\u6216\u5DF2\u8FC7\u671F\u9636\u6BB5\u5199\u5165 ${stage.data}\u3002`
30101
30549
  );
30102
30550
  }
30103
- const directory = projectDirectory(this.#currentDirectory, options.directory);
30104
- const manifest = await loadManifest(directory);
30105
- const existing = await loadCheckpoint(directory, manifest, stage.data);
30106
- const timestamp = this.#now().toISOString();
30107
- const inputStageValues = options.inputStages ?? (existing?.checkpointVersion === "2" || existing?.checkpointVersion === "3" ? existing.inputs.map((input) => input.kind) : []);
30551
+ const researchCheckpoint = stage.data === "quality-review" ? await loadCheckpoint(directory, manifest, "research") : void 0;
30552
+ const stageInputs = adoptsExistingArticle ? { optional: [], required: [] } : stage.data === "quality-review" && researchCheckpoint?.status === "skipped" ? { optional: ["visual-plan"], required: ["article", "titles"] } : CONTENT_STAGE_INPUTS[stage.data];
30553
+ const inferredOptionalInputs = options.inputStages === void 0 && existing === void 0 && stage.data === "delivery" ? (await Promise.all(
30554
+ stageInputs.optional.map(async (inputStage) => ({
30555
+ inputStage,
30556
+ status: await inspectArtifact(directory, manifest, inputStage)
30557
+ }))
30558
+ )).filter((input) => input.status.status === "ready").map((input) => input.inputStage) : [];
30559
+ const migratedExistingInputs = existing?.checkpointVersion === "2" || existing?.checkpointVersion === "3" ? migrateCheckpointInputKinds(
30560
+ stageInputs.required,
30561
+ stageInputs.optional,
30562
+ existing.inputs.map((input) => input.kind)
30563
+ ) : [];
30564
+ const inputStageValues = options.inputStages !== void 0 ? [...stageInputs.required, ...options.inputStages] : existing?.checkpointVersion === "2" || existing?.checkpointVersion === "3" ? migratedExistingInputs : [...stageInputs.required, ...inferredOptionalInputs];
30108
30565
  const inputStages = inputStageValues.map(
30109
30566
  (inputStage) => contentArtifactKindSchema.safeParse(inputStage)
30110
30567
  );
@@ -30123,7 +30580,6 @@ var ProjectCli = class {
30123
30580
  ].sort(
30124
30581
  (left, right) => CONTENT_ARTIFACT_KINDS.indexOf(left) - CONTENT_ARTIFACT_KINDS.indexOf(right)
30125
30582
  );
30126
- const stageInputs = adoptsExistingArticle ? { optional: [], required: [] } : CONTENT_STAGE_INPUTS[stage.data];
30127
30583
  const missingRequiredInputs = stageInputs.required.filter(
30128
30584
  (inputStage) => !parsedInputStages.includes(inputStage)
30129
30585
  );
@@ -30163,8 +30619,64 @@ var ProjectCli = class {
30163
30619
  );
30164
30620
  }
30165
30621
  const inputs = inputArtifactStatuses.map(artifactReference);
30166
- const artifactStatus = await inspectArtifact(directory, manifest, stage.data);
30622
+ const requestedNeedsArtifact = status.data === "awaiting-user" || status.data === "completed";
30623
+ const artifactStatusBeforeNormalization = await inspectArtifact(
30624
+ directory,
30625
+ manifest,
30626
+ stage.data
30627
+ );
30628
+ let artifactRequiresConfirmation = false;
30629
+ if (requestedNeedsArtifact && artifactStatusBeforeNormalization.status === "ready") {
30630
+ try {
30631
+ artifactRequiresConfirmation = await stageArtifactRequiresUserConfirmation({
30632
+ directory,
30633
+ manifest,
30634
+ stage: stage.data
30635
+ });
30636
+ } catch (error) {
30637
+ if (error instanceof StageArtifactValidationError) {
30638
+ throw new ProjectCliError("DXC_PROJECT_STAGE_INVALID", error.message);
30639
+ }
30640
+ throw error;
30641
+ }
30642
+ }
30643
+ const requiresUserConfirmation = await this.#requiresUserConfirmation(stage.data) || artifactRequiresConfirmation;
30644
+ const confirmationRequired = status.data === "completed" && requiresUserConfirmation && options.confirmed !== true;
30645
+ const effectiveStatus = confirmationRequired ? "awaiting-user" : status.data;
30646
+ const waitingFor = confirmationRequired ? requestedWaitingFor ?? (artifactRequiresConfirmation ? "\u672C\u6B21\u70ED\u70B9\u7814\u7A76\u5C06\u8DF3\u8FC7\u5916\u90E8\u89C2\u70B9\u626B\u63CF\uFF0C\u53EA\u4FDD\u7559\u4E8B\u5B9E\u4E0E\u7528\u6237\u6750\u6599\u3002\u8BF7\u786E\u8BA4\u662F\u5426\u63A5\u53D7\u8FD9\u6761\u7814\u7A76\u8DEF\u7EBF\u3002" : `\u8BF7\u786E\u8BA4 ${stage.data} \u9636\u6BB5\u5F53\u524D\u5FEB\u7167\uFF1B\u786E\u8BA4\u540E\u4F7F\u7528 --confirm \u5B8C\u6210\u8BE5\u9636\u6BB5\u3002`) : requestedWaitingFor;
30647
+ if (effectiveStatus === "failed" && options.errorCode === void 0) {
30648
+ throw new ProjectCliError(
30649
+ "DXC_PROJECT_STAGE_INVALID",
30650
+ "Failed checkpoint needs an error code"
30651
+ );
30652
+ }
30653
+ if (effectiveStatus === "awaiting-user" && (waitingFor === void 0 || waitingFor.length === 0) || effectiveStatus !== "awaiting-user" && waitingFor !== void 0) {
30654
+ throw new ProjectCliError(
30655
+ "DXC_PROJECT_STAGE_INVALID",
30656
+ "Awaiting checkpoint needs one waiting-for prompt"
30657
+ );
30658
+ }
30167
30659
  const needsArtifact = effectiveStatus === "awaiting-user" || effectiveStatus === "completed";
30660
+ if (needsArtifact) {
30661
+ try {
30662
+ await normalizeStageArtifact({
30663
+ artifactStatus: effectiveStatus === "completed" ? "complete" : "awaiting-user",
30664
+ createdAt: timestamp,
30665
+ directory,
30666
+ inputs,
30667
+ manifest,
30668
+ skill: effectiveSkill,
30669
+ skillVersion: effectiveSkillVersion,
30670
+ stage: stage.data
30671
+ });
30672
+ } catch (error) {
30673
+ if (error instanceof StageArtifactValidationError) {
30674
+ throw new ProjectCliError("DXC_PROJECT_STAGE_INVALID", error.message);
30675
+ }
30676
+ throw error;
30677
+ }
30678
+ }
30679
+ const artifactStatus = await inspectArtifact(directory, manifest, stage.data);
30168
30680
  if (needsArtifact && artifactStatus.status !== "ready") {
30169
30681
  throw new ProjectCliError(
30170
30682
  "DXC_PROJECT_STAGE_INVALID",
@@ -30179,8 +30691,8 @@ var ProjectCli = class {
30179
30691
  directory,
30180
30692
  inputs,
30181
30693
  manifest,
30182
- skill: options.skill,
30183
- skillVersion: options.skillVersion,
30694
+ skill: effectiveSkill,
30695
+ skillVersion: effectiveSkillVersion,
30184
30696
  stage: stage.data
30185
30697
  });
30186
30698
  } catch (error) {
@@ -30207,13 +30719,15 @@ var ProjectCli = class {
30207
30719
  const confirmationRelevant = effectiveStatus === "awaiting-user" || effectiveStatus === "completed" && requiresUserConfirmation && options.confirmed;
30208
30720
  const previousBinding = existing?.checkpointVersion === "3" ? existing.confirmationBinding : null;
30209
30721
  const confirmationSnapshotType = artifactValidation?.snapshotType ?? "stage-artifact";
30210
- if (effectiveStatus === "completed" && requiresUserConfirmation && options.confirmed && (existing?.status !== "awaiting-user" || existing.confirmation !== "pending" || previousBinding?.status !== "pending" || previousBinding.snapshotHash !== confirmationSnapshotHash || previousBinding.snapshotType !== confirmationSnapshotType)) {
30722
+ const legacyPendingSnapshotMatches = options.confirmed && previousBinding?.snapshotType === "stage-artifact" && artifactStatusBeforeNormalization.status === "ready" && previousBinding.snapshotHash === artifactStatusBeforeNormalization.sha256;
30723
+ const previousSnapshotMatches = previousBinding?.snapshotHash === confirmationSnapshotHash || legacyPendingSnapshotMatches;
30724
+ if (effectiveStatus === "completed" && requiresUserConfirmation && options.confirmed && (existing?.status !== "awaiting-user" || existing.confirmation !== "pending" || previousBinding?.status !== "pending" || !previousSnapshotMatches || previousBinding.snapshotType !== confirmationSnapshotType)) {
30211
30725
  throw new ProjectCliError(
30212
30726
  "DXC_PROJECT_STAGE_INVALID",
30213
30727
  "\u5F53\u524D\u5185\u5BB9\u6216\u6E32\u67D3\u5FEB\u7167\u4E0D\u662F\u521A\u624D\u7B49\u5F85\u786E\u8BA4\u7684\u7248\u672C\uFF1B\u8BF7\u5148\u91CD\u65B0\u5C55\u793A\u5E76\u5199\u5165 awaiting-user \u68C0\u67E5\u70B9\uFF0C\u518D\u6839\u636E\u7528\u6237\u660E\u786E\u56DE\u7B54\u786E\u8BA4\u3002"
30214
30728
  );
30215
30729
  }
30216
- const requestedAt = previousBinding !== null && previousBinding.snapshotHash === confirmationSnapshotHash && previousBinding.snapshotType === confirmationSnapshotType ? previousBinding.requestedAt : timestamp;
30730
+ const requestedAt = previousBinding !== null && previousSnapshotMatches && previousBinding.snapshotType === confirmationSnapshotType ? previousBinding.requestedAt : timestamp;
30217
30731
  const confirmedBy = options.confirmedBy?.trim() || "local-interactive-user";
30218
30732
  const checkpointResult = stepCheckpointSchema.safeParse({
30219
30733
  ...needsArtifact && artifactStatus.status === "ready" ? {
@@ -30248,8 +30762,8 @@ var ProjectCli = class {
30248
30762
  projectId: manifest.projectId,
30249
30763
  revision: (existing?.revision ?? 0) + 1,
30250
30764
  skill: {
30251
- name: options.skill,
30252
- version: options.skillVersion
30765
+ name: effectiveSkill,
30766
+ version: effectiveSkillVersion
30253
30767
  },
30254
30768
  stage: stage.data,
30255
30769
  startedAt: status.data === "running" && existing !== void 0 && TERMINAL_CHECKPOINT_STATUSES.has(existing.status) ? timestamp : existing?.startedAt ?? timestamp,
@@ -30263,6 +30777,12 @@ var ProjectCli = class {
30263
30777
  }
30264
30778
  const checkpoint = checkpointResult.data;
30265
30779
  const relativePath = checkpointRelativePath(manifest, stage.data);
30780
+ if (adoptsExistingArticle) {
30781
+ await this.#skipArticleAdoptionPrerequisites(directory, manifest, timestamp, {
30782
+ dataTransit: dataTransit.data,
30783
+ location: executionLocation.data
30784
+ });
30785
+ }
30266
30786
  await this.#rememberProject(directory, manifest, timestamp);
30267
30787
  await writeJsonAtomically(insideProject2(directory, relativePath), checkpoint);
30268
30788
  return contentProjectCheckpointResultSchema.parse({
@@ -30282,7 +30802,7 @@ var ProjectCli = class {
30282
30802
  };
30283
30803
 
30284
30804
  // apps/cli/src/skills.ts
30285
- import { cp, lstat as lstat2, mkdir as mkdir2, mkdtemp, readdir, rename as rename2, rm } from "node:fs/promises";
30805
+ import { cp, lstat as lstat3, mkdir as mkdir2, mkdtemp, readdir, rename as rename4, rm } from "node:fs/promises";
30286
30806
  import os from "node:os";
30287
30807
  import path5 from "node:path";
30288
30808
  import { fileURLToPath } from "node:url";
@@ -30311,7 +30831,7 @@ var SkillInstallerError = class extends Error {
30311
30831
  };
30312
30832
  async function isDirectory(directory) {
30313
30833
  try {
30314
- return (await lstat2(directory)).isDirectory();
30834
+ return (await lstat3(directory)).isDirectory();
30315
30835
  } catch {
30316
30836
  return false;
30317
30837
  }
@@ -30335,7 +30855,7 @@ async function findBundledSkills() {
30335
30855
  async function assertRegularSkillTree(directory) {
30336
30856
  for (const entry of await readdir(directory, { withFileTypes: true })) {
30337
30857
  const entryPath = path5.join(directory, entry.name);
30338
- const entryStat = await lstat2(entryPath);
30858
+ const entryStat = await lstat3(entryPath);
30339
30859
  if (entryStat.isSymbolicLink()) {
30340
30860
  throw new SkillInstallerError(
30341
30861
  "DXC_SKILL_SOURCE_UNSAFE",
@@ -30358,23 +30878,31 @@ function defaultTargetDirectory(homeDirectory, target) {
30358
30878
  return path5.join(homeDirectory, target === "codex" ? ".codex" : ".workbuddy", "skills");
30359
30879
  }
30360
30880
  var SkillInstaller = class {
30361
- constructor(homeDirectory = os.homedir()) {
30881
+ constructor(homeDirectory = os.homedir(), currentDirectory = process.cwd(), remove = rm) {
30362
30882
  this.homeDirectory = homeDirectory;
30883
+ this.currentDirectory = currentDirectory;
30884
+ this.remove = remove;
30363
30885
  }
30364
30886
  homeDirectory;
30887
+ currentDirectory;
30888
+ remove;
30365
30889
  async install(options) {
30366
30890
  const sourceRoot = await findBundledSkills();
30367
- const targetRoot = path5.resolve(
30368
- options.directory ?? defaultTargetDirectory(this.homeDirectory, options.target)
30369
- );
30891
+ const targetRoot = resolveUserPath({
30892
+ currentDirectory: this.currentDirectory,
30893
+ homeDirectory: this.homeDirectory,
30894
+ input: options.directory ?? defaultTargetDirectory(this.homeDirectory, options.target)
30895
+ });
30370
30896
  await mkdir2(targetRoot, { mode: 448, recursive: true });
30371
30897
  const installed = [];
30372
30898
  const skipped = [];
30899
+ const cleanupWarnings = [];
30373
30900
  for (const skill of OFFICIAL_SKILLS) {
30374
30901
  const source = path5.join(sourceRoot, skill);
30375
30902
  const destination = path5.join(targetRoot, skill);
30376
30903
  await assertRegularSkillTree(source);
30377
- if (await isDirectory(destination)) {
30904
+ const destinationExists = await isDirectory(destination);
30905
+ if (destinationExists) {
30378
30906
  if (!options.force) {
30379
30907
  skipped.push(skill);
30380
30908
  continue;
@@ -30388,22 +30916,33 @@ var SkillInstaller = class {
30388
30916
  errorOnExist: true,
30389
30917
  recursive: true
30390
30918
  });
30391
- if (await isDirectory(destination)) {
30392
- await rename2(destination, backup);
30919
+ if (destinationExists) {
30920
+ await rename4(destination, backup);
30393
30921
  }
30394
- await rename2(stagedSkill, destination);
30395
- await rm(backup, { force: true, recursive: true });
30922
+ await rename4(stagedSkill, destination);
30396
30923
  installed.push(skill);
30924
+ if (destinationExists) {
30925
+ try {
30926
+ await this.remove(backup, { force: true, recursive: true });
30927
+ } catch {
30928
+ cleanupWarnings.push(`${skill}:backup`);
30929
+ }
30930
+ }
30397
30931
  } catch (error) {
30398
30932
  if (!await isDirectory(destination) && await isDirectory(backup)) {
30399
- await rename2(backup, destination);
30933
+ await rename4(backup, destination);
30400
30934
  }
30401
30935
  throw error;
30402
30936
  } finally {
30403
- await rm(stagingRoot, { force: true, recursive: true });
30937
+ try {
30938
+ await this.remove(stagingRoot, { force: true, recursive: true });
30939
+ } catch {
30940
+ cleanupWarnings.push(`${skill}:staging`);
30941
+ }
30404
30942
  }
30405
30943
  }
30406
30944
  return {
30945
+ cleanupWarnings,
30407
30946
  directory: targetRoot,
30408
30947
  installed,
30409
30948
  skipped,
@@ -30419,10 +30958,10 @@ import {
30419
30958
  createPrivateKey as createPrivateKey2,
30420
30959
  createPublicKey as createPublicKey2,
30421
30960
  randomBytes,
30422
- randomUUID as randomUUID3
30961
+ randomUUID as randomUUID4
30423
30962
  } from "node:crypto";
30424
30963
  import { constants as fileConstants3 } from "node:fs";
30425
- import { chmod, mkdir as mkdir3, open as open3, rename as rename3, rm as rm2, writeFile as writeFile2 } from "node:fs/promises";
30964
+ import { chmod, mkdir as mkdir3, open as open3, rename as rename5, rm as rm2, writeFile as writeFile3 } from "node:fs/promises";
30426
30965
  import os2 from "node:os";
30427
30966
  import path7 from "node:path";
30428
30967
 
@@ -30572,7 +31111,7 @@ var LOG_REDACTION_PATHS = Object.freeze([
30572
31111
  // apps/cli/src/publishing-assets.ts
30573
31112
  import { createHash as createHash6 } from "node:crypto";
30574
31113
  import { constants as fileConstants2 } from "node:fs";
30575
- import { lstat as lstat3, open as open2, readdir as readdir2, realpath } from "node:fs/promises";
31114
+ import { lstat as lstat4, open as open2, readdir as readdir2, realpath } from "node:fs/promises";
30576
31115
  import path6 from "node:path";
30577
31116
  var import_yaml3 = __toESM(require_dist(), 1);
30578
31117
 
@@ -30595,7 +31134,9 @@ var MAXIMUM_INLINE_IMAGE_BYTES2 = 1024 * 1024 - 1;
30595
31134
  var MAXIMUM_INLINE_IMAGES = 20;
30596
31135
  var SUPPORTED_IMAGE_EXTENSIONS = /* @__PURE__ */ new Set([".jpeg", ".jpg", ".png"]);
30597
31136
  var VISUAL_PLAN_MAXIMUM_BYTES = 128 * 1024;
31137
+ var ARTICLE_FRONTMATTER = /^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n|$)([\s\S]*)$/u;
30598
31138
  var VISUAL_PLAN_FRONTMATTER = /^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n|$)/u;
31139
+ var LOCAL_WORKFLOW_FRONTMATTER_KEYS = ["dxc", "goldenLinesPath", "goldenLinesSha256"];
30599
31140
  async function readPublishingInput(inputPath, maximumBytes) {
30600
31141
  const target = path6.resolve(inputPath);
30601
31142
  let handle;
@@ -30685,7 +31226,7 @@ async function collectedImages(directoryInput, articleDirectory) {
30685
31226
  const directory = path6.resolve(directoryInput);
30686
31227
  let entries;
30687
31228
  try {
30688
- const metadata = await lstat3(directory);
31229
+ const metadata = await lstat4(directory);
30689
31230
  if (!metadata.isDirectory() || metadata.isSymbolicLink()) {
30690
31231
  throw new WechatCliError(
30691
31232
  "DXC_PUBLISHING_ASSETS_DIRECTORY_INVALID",
@@ -30769,7 +31310,9 @@ function injectCollectedImages(source, images) {
30769
31310
  async function plannedInlineImages(visualPlanFile, availableByFileName) {
30770
31311
  let source;
30771
31312
  try {
30772
- source = (await readPublishingInput(visualPlanFile, VISUAL_PLAN_MAXIMUM_BYTES)).bytes.toString("utf8");
31313
+ source = (await readPublishingInput(visualPlanFile, VISUAL_PLAN_MAXIMUM_BYTES)).bytes.toString(
31314
+ "utf8"
31315
+ );
30773
31316
  } catch {
30774
31317
  throw new WechatCliError("DXC_PUBLISHING_VISUAL_PLAN_INVALID");
30775
31318
  }
@@ -30787,34 +31330,55 @@ async function plannedInlineImages(visualPlanFile, availableByFileName) {
30787
31330
  if (!parsed.success) {
30788
31331
  throw new WechatCliError("DXC_PUBLISHING_VISUAL_PLAN_INVALID");
30789
31332
  }
30790
- return Promise.all(parsed.data.inlineAssets.map(async (asset) => {
30791
- const absolutePath = availableByFileName.get(path6.posix.basename(asset.path));
30792
- if (absolutePath === void 0) {
30793
- throw new WechatCliError(
30794
- "DXC_PUBLISHING_VISUAL_PLAN_INVALID",
30795
- `\u89C6\u89C9\u8BA1\u5212\u58F0\u660E\u7684\u7D20\u6750 ${path6.posix.basename(asset.path)} \u4E0D\u5728\u6307\u5B9A\u7D20\u6750\u76EE\u5F55\u4E2D\u3002`
30796
- );
30797
- }
30798
- const input = await readPublishingInput(absolutePath, MAXIMUM_INLINE_IMAGE_BYTES2);
30799
- if (createHash6("sha256").update(input.bytes).digest("hex") !== asset.sha256) {
30800
- throw new WechatCliError(
30801
- "DXC_PUBLISHING_VISUAL_PLAN_INVALID",
30802
- `\u89C6\u89C9\u8BA1\u5212\u58F0\u660E\u7684\u7D20\u6750 ${path6.posix.basename(asset.path)} \u4E0E\u8BB0\u5F55\u7684\u54C8\u5E0C\u4E0D\u4E00\u81F4\u3002`
30803
- );
30804
- }
30805
- const digest = createHash6("sha256").update(absolutePath).digest("hex").slice(0, 12);
30806
- const fileName = safeFileName(path6.basename(absolutePath)) || `visual-${digest}.png`;
30807
- return {
30808
- absolutePath,
30809
- alt: asset.purpose,
30810
- logicalPath: `assets/dxc-visuals/${digest}-${fileName}`,
30811
- placementAnchor: asset.placementAnchor
30812
- };
30813
- }));
31333
+ return Promise.all(
31334
+ parsed.data.inlineAssets.map(async (asset) => {
31335
+ const absolutePath = availableByFileName.get(path6.posix.basename(asset.path));
31336
+ if (absolutePath === void 0) {
31337
+ throw new WechatCliError(
31338
+ "DXC_PUBLISHING_VISUAL_PLAN_INVALID",
31339
+ `\u89C6\u89C9\u8BA1\u5212\u58F0\u660E\u7684\u7D20\u6750 ${path6.posix.basename(asset.path)} \u4E0D\u5728\u6307\u5B9A\u7D20\u6750\u76EE\u5F55\u4E2D\u3002`
31340
+ );
31341
+ }
31342
+ const input = await readPublishingInput(absolutePath, MAXIMUM_INLINE_IMAGE_BYTES2);
31343
+ if (createHash6("sha256").update(input.bytes).digest("hex") !== asset.sha256) {
31344
+ throw new WechatCliError(
31345
+ "DXC_PUBLISHING_VISUAL_PLAN_INVALID",
31346
+ `\u89C6\u89C9\u8BA1\u5212\u58F0\u660E\u7684\u7D20\u6750 ${path6.posix.basename(asset.path)} \u4E0E\u8BB0\u5F55\u7684\u54C8\u5E0C\u4E0D\u4E00\u81F4\u3002`
31347
+ );
31348
+ }
31349
+ const digest = createHash6("sha256").update(absolutePath).digest("hex").slice(0, 12);
31350
+ const fileName = safeFileName(path6.basename(absolutePath)) || `visual-${digest}.png`;
31351
+ return {
31352
+ absolutePath,
31353
+ alt: asset.purpose,
31354
+ logicalPath: `assets/dxc-visuals/${digest}-${fileName}`,
31355
+ placementAnchor: asset.placementAnchor
31356
+ };
31357
+ })
31358
+ );
30814
31359
  }
30815
31360
  function logicalInlinePaths(bundle) {
30816
31361
  return bundle.assets.filter((asset) => asset.role === "inline").map((asset) => asset.logicalPath);
30817
31362
  }
31363
+ function publishingArticleSource(source) {
31364
+ const match = ARTICLE_FRONTMATTER.exec(source);
31365
+ const yamlSource = match?.[1];
31366
+ const body = match?.[2];
31367
+ if (yamlSource === void 0 || body === void 0) {
31368
+ throw new WechatCliError("DXC_PUBLISHING_ARTICLE_INVALID");
31369
+ }
31370
+ const document = (0, import_yaml3.parseDocument)(yamlSource, { uniqueKeys: true });
31371
+ if (document.errors.length > 0) {
31372
+ throw new WechatCliError("DXC_PUBLISHING_ARTICLE_INVALID");
31373
+ }
31374
+ for (const key of LOCAL_WORKFLOW_FRONTMATTER_KEYS) {
31375
+ document.delete(key);
31376
+ }
31377
+ return `---
31378
+ ${document.toString().trimEnd()}
31379
+ ---
31380
+ ${body}`;
31381
+ }
30818
31382
  async function preparePublishingDraft(input) {
30819
31383
  const articleInput = await readPublishingInput(input.articleFile, MAXIMUM_ARTICLE_BYTES2);
30820
31384
  const originalSource = articleInput.bytes.toString("utf8");
@@ -30862,11 +31426,17 @@ async function preparePublishingDraft(input) {
30862
31426
  };
30863
31427
  }).filter((asset) => !referenced.has(asset.logicalPath))
30864
31428
  ];
30865
- const finalSource = injectCollectedImages(originalSource, injected);
31429
+ const materializedSource = injectCollectedImages(originalSource, injected);
31430
+ let finalSource;
30866
31431
  let bundle;
30867
31432
  try {
31433
+ parseArticleDocument(materializedSource);
31434
+ finalSource = publishingArticleSource(materializedSource);
30868
31435
  bundle = parseArticleDocument(finalSource);
30869
- } catch {
31436
+ } catch (error) {
31437
+ if (error instanceof WechatCliError) {
31438
+ throw error;
31439
+ }
30870
31440
  throw new WechatCliError("DXC_PUBLISHING_ARTICLE_INVALID");
30871
31441
  }
30872
31442
  bundle = input.title === void 0 ? bundle : { ...bundle, title: input.title.trim() };
@@ -30939,6 +31509,28 @@ function writeAgentBrowserEvent(output, event) {
30939
31509
  `
30940
31510
  );
30941
31511
  }
31512
+ async function presentDraftPreview(output, openExternal, preview, browserMode) {
31513
+ if (browserMode === "agent") {
31514
+ writeAgentBrowserEvent(output, {
31515
+ expiresAt: preview.expiresAt,
31516
+ kind: "wechat-draft-preview",
31517
+ url: preview.url
31518
+ });
31519
+ output.writeStderr(
31520
+ "\u8BF7\u7531\u5F53\u524D Agent \u5728\u53F3\u4FA7\u5185\u7F6E\u6D4F\u89C8\u5668\u6253\u5F00\u9884\u89C8\uFF1B\u82E5\u5BBF\u4E3B\u4E0D\u652F\u6301\u53F3\u4FA7\u6D4F\u89C8\u5668\uFF0C\u4F7F\u7528\u540C\u4E00\u5FEB\u7167\u7684 --browser system \u56DE\u9000\u5230\u7CFB\u7EDF\u9ED8\u8BA4\u6D4F\u89C8\u5668\u3002\n"
31521
+ );
31522
+ return;
31523
+ }
31524
+ if (!await openExternal(preview.url)) {
31525
+ output.writeStderr(
31526
+ `\u6CA1\u6709\u81EA\u52A8\u6253\u5F00\u9884\u89C8\u9875\u9762\u3002\u8BF7\u70B9\u51FB\u4E0B\u9762\u7684\u4E34\u65F6\u94FE\u63A5\u67E5\u770B\u9884\u89C8\uFF1B\u67E5\u770B\u540E\u56DE\u5230\u8FD9\u91CC\u786E\u8BA4\u3002
31527
+ ${preview.url}
31528
+ `
31529
+ );
31530
+ return;
31531
+ }
31532
+ output.writeStderr("\u5DF2\u5728\u7CFB\u7EDF\u9ED8\u8BA4\u6D4F\u89C8\u5668\u6253\u5F00\u4E0D\u53EF\u53D8\u9884\u89C8\u3002\n");
31533
+ }
30942
31534
  function isLoopbackHostname(hostname) {
30943
31535
  if (hostname === "localhost" || hostname === "[::1]" || hostname === "::1") {
30944
31536
  return true;
@@ -30959,8 +31551,11 @@ function apiBaseUrl(input) {
30959
31551
  }
30960
31552
  return url.toString().replace(/\/+$/u, "");
30961
31553
  }
31554
+ function externalOpenCommand(url, platform = process.platform) {
31555
+ return platform === "darwin" ? { arguments_: [url], executable: "open" } : platform === "win32" ? { arguments_: [url], executable: "explorer.exe" } : { arguments_: [url], executable: "xdg-open" };
31556
+ }
30962
31557
  async function defaultOpenExternal(url) {
30963
- const command = process.platform === "darwin" ? { arguments_: [url], executable: "open" } : process.platform === "win32" ? { arguments_: ["/c", "start", "", url], executable: "cmd" } : { arguments_: [url], executable: "xdg-open" };
31558
+ const command = externalOpenCommand(url);
30964
31559
  return new Promise((resolve) => {
30965
31560
  const child = spawn(command.executable, command.arguments_, {
30966
31561
  detached: true,
@@ -30978,6 +31573,22 @@ function defaultSleep(milliseconds) {
30978
31573
  setTimeout(resolve, milliseconds);
30979
31574
  });
30980
31575
  }
31576
+ async function retryExpiredBrowserFlow(action, output) {
31577
+ try {
31578
+ return await action();
31579
+ } catch (error) {
31580
+ if (!(error instanceof WechatCliError) || ![
31581
+ "WECHAT_AUTHORIZATION_EXPIRED",
31582
+ "WECHAT_AUTHORIZATION_TIMEOUT",
31583
+ "WECHAT_LOGIN_EXPIRED",
31584
+ "WECHAT_LOGIN_TIMEOUT"
31585
+ ].includes(error.code)) {
31586
+ throw error;
31587
+ }
31588
+ output.writeStderr("\u626B\u7801\u9875\u9762\u5DF2\u66F4\u65B0\uFF0C\u8BF7\u4F7F\u7528\u521A\u521A\u6253\u5F00\u7684\u65B0\u9875\u9762\u7EE7\u7EED\u3002\n");
31589
+ return action();
31590
+ }
31591
+ }
30981
31592
  function sessionPath(stateDirectory) {
30982
31593
  return path7.join(stateDirectory, "wechat-session.json");
30983
31594
  }
@@ -31023,13 +31634,13 @@ async function saveSession(stateDirectory, session) {
31023
31634
  await chmod(stateDirectory, 448);
31024
31635
  const target = sessionPath(stateDirectory);
31025
31636
  const temporary = `${target}.${process.pid}.tmp`;
31026
- await writeFile2(temporary, `${JSON.stringify(session)}
31637
+ await writeFile3(temporary, `${JSON.stringify(session)}
31027
31638
  `, {
31028
31639
  encoding: "utf8",
31029
31640
  mode: 384
31030
31641
  });
31031
31642
  await chmod(temporary, 384);
31032
- await rename3(temporary, target);
31643
+ await rename5(temporary, target);
31033
31644
  await chmod(target, 384);
31034
31645
  }
31035
31646
  async function readSessionValue(stateDirectory) {
@@ -31147,7 +31758,7 @@ async function loadOrCreateDeviceIdentity(stateDirectory) {
31147
31758
  const keyPair = generateDeviceKeyPair();
31148
31759
  const identity = {
31149
31760
  deviceName: os2.hostname().trim().slice(0, 80) || "DxC \u8BBE\u5907",
31150
- installationId: randomUUID3(),
31761
+ installationId: randomUUID4(),
31151
31762
  privateKeyPem: keyPair.privateKeyPem,
31152
31763
  publicKeyFingerprint: keyPair.publicKeyFingerprint,
31153
31764
  publicKeyPem: keyPair.publicKeyPem
@@ -31156,13 +31767,13 @@ async function loadOrCreateDeviceIdentity(stateDirectory) {
31156
31767
  await chmod(stateDirectory, 448);
31157
31768
  const target = deviceIdentityPath(stateDirectory);
31158
31769
  const temporary = `${target}.${process.pid}.tmp`;
31159
- await writeFile2(temporary, `${JSON.stringify(identity)}
31770
+ await writeFile3(temporary, `${JSON.stringify(identity)}
31160
31771
  `, {
31161
31772
  encoding: "utf8",
31162
31773
  mode: 384
31163
31774
  });
31164
31775
  await chmod(temporary, 384);
31165
- await rename3(temporary, target);
31776
+ await rename5(temporary, target);
31166
31777
  await chmod(target, 384);
31167
31778
  return { created: true, identity };
31168
31779
  }
@@ -31194,6 +31805,22 @@ function secretHash(value) {
31194
31805
  function bytesHash(value) {
31195
31806
  return createHash7("sha256").update(value).digest("hex");
31196
31807
  }
31808
+ function assertCompleteInlineAssets(expected, actual) {
31809
+ const expectedRecords = expected.map((asset) => ({
31810
+ logicalPath: asset.logicalPath,
31811
+ mediaType: asset.mediaType,
31812
+ sha256: bytesHash(asset.bytes)
31813
+ })).sort((left, right) => left.logicalPath.localeCompare(right.logicalPath, "en"));
31814
+ const actualRecords = [...actual].sort(
31815
+ (left, right) => left.logicalPath.localeCompare(right.logicalPath, "en")
31816
+ );
31817
+ if (JSON.stringify(expectedRecords) !== JSON.stringify(actualRecords)) {
31818
+ throw new WechatCliError(
31819
+ "DXC_PUBLISHING_INLINE_ASSETS_MISMATCH",
31820
+ "\u6B63\u6587\u56FE\u7247\u672A\u5B8C\u6574\u8FDB\u5165\u4E0D\u53EF\u53D8\u5FEB\u7167\uFF1B\u5DF2\u505C\u6B62\u521B\u5EFA\u8349\u7A3F\uFF0C\u8BF7\u4FEE\u590D\u56FE\u7247\u8DEF\u5F84\u6216\u4E0A\u4F20\u7ED3\u679C\u540E\u91CD\u65B0\u9884\u89C8\u3002"
31821
+ );
31822
+ }
31823
+ }
31197
31824
  var WechatCli = class {
31198
31825
  #fetch;
31199
31826
  #openExternal;
@@ -31288,7 +31915,7 @@ var WechatCli = class {
31288
31915
  const pending = session.pendingRefresh ?? {
31289
31916
  nextDeviceRefreshToken: randomBytes(32).toString("base64url"),
31290
31917
  nextDeviceToken: randomBytes(32).toString("base64url"),
31291
- rotationId: randomUUID3()
31918
+ rotationId: randomUUID4()
31292
31919
  };
31293
31920
  const pendingSession = {
31294
31921
  apiBaseUrl: session.apiBaseUrl,
@@ -31346,18 +31973,23 @@ var WechatCli = class {
31346
31973
  }
31347
31974
  return session.deviceId;
31348
31975
  }
31349
- async accounts(output) {
31976
+ async accounts(output, json = false) {
31350
31977
  const session = await loadSession(this.#stateDirectory);
31351
31978
  const { response } = await this.#authenticatedFetch(
31352
31979
  session,
31353
31980
  `${session.apiBaseUrl}/api/v1/wechat/accounts`
31354
31981
  );
31355
31982
  const result = wechatAccountsResponseSchema.parse(await checkedJson(response));
31356
- for (const account of result.accounts) {
31357
- output.writeStdout(
31358
- `${account.id} ${account.displayName} ${account.draftCapability} ${account.permissions.join(",")}
31983
+ if (json) {
31984
+ output.writeStdout(`${JSON.stringify(result)}
31985
+ `);
31986
+ } else {
31987
+ for (const account of result.accounts) {
31988
+ output.writeStdout(
31989
+ `${account.id} ${account.displayName} ${account.draftCapability} ${account.permissions.join(",")}
31359
31990
  `
31360
- );
31991
+ );
31992
+ }
31361
31993
  }
31362
31994
  return result.accounts;
31363
31995
  }
@@ -31472,6 +32104,7 @@ var WechatCli = class {
31472
32104
  );
31473
32105
  session = articleResponse.session;
31474
32106
  const article = publishingArticleSchema.parse(await checkedJson(articleResponse.response));
32107
+ assertCompleteInlineAssets(prepared.inlineAssets, article.inlineAssets);
31475
32108
  const snapshotResponse = await this.#authenticatedFetch(
31476
32109
  session,
31477
32110
  `${session.apiBaseUrl}/api/v1/articles/${encodeURIComponent(article.id)}/render-snapshots`,
@@ -31485,6 +32118,7 @@ var WechatCli = class {
31485
32118
  const snapshot = publishingRenderSnapshotSchema.parse(
31486
32119
  await checkedJson(snapshotResponse.response)
31487
32120
  );
32121
+ assertCompleteInlineAssets(prepared.inlineAssets, snapshot.inlineAssets);
31488
32122
  if (!snapshot.preflight.ok) {
31489
32123
  output.writeStdout(`${JSON.stringify({ account, snapshot })}
31490
32124
  `);
@@ -31500,11 +32134,12 @@ var WechatCli = class {
31500
32134
  }
31501
32135
  );
31502
32136
  const preview = publishingPreviewLinkSchema.parse(await checkedJson(previewResponse.response));
32137
+ const browserMode = options.browserMode ?? "agent";
31503
32138
  const result = {
31504
32139
  account,
31505
32140
  presentation: {
31506
- instruction: "\u8BF7\u5728\u53F3\u4FA7\u5185\u7F6E\u6D4F\u89C8\u5668\u67E5\u770B\u9884\u89C8\uFF0C\u4E0D\u8981\u5728\u5BF9\u8BDD\u4E2D\u53D1\u9001\u9884\u89C8\u94FE\u63A5\u3002",
31507
- surface: "agent-side-panel"
32141
+ instruction: browserMode === "agent" ? "\u8BF7\u5728\u53F3\u4FA7\u5185\u7F6E\u6D4F\u89C8\u5668\u67E5\u770B\u9884\u89C8\uFF1B\u5BBF\u4E3B\u4E0D\u652F\u6301\u65F6\u56DE\u9000\u7CFB\u7EDF\u9ED8\u8BA4\u6D4F\u89C8\u5668\u3002" : "\u8BF7\u5728\u7CFB\u7EDF\u9ED8\u8BA4\u6D4F\u89C8\u5668\u67E5\u770B\u9884\u89C8\u3002",
32142
+ surface: browserMode === "agent" ? "agent-side-panel" : "system-browser"
31508
32143
  },
31509
32144
  preview,
31510
32145
  snapshot
@@ -31525,9 +32160,8 @@ var WechatCli = class {
31525
32160
  `\u5C01\u9762\uFF1A${coverDescription}\uFF1B\u6B63\u6587\u56FE\u7247\uFF1A${prepared.inlineAssets.length} \u5F20\uFF08\u5176\u4E2D\u4ECE\u6307\u5B9A\u7D20\u6750\u76EE\u5F55\u91C7\u96C6 ${prepared.collectedInlineCount} \u5F20\uFF09\u3002
31526
32161
  `
31527
32162
  );
31528
- output.writeStderr(
31529
- "\u9884\u89C8\u5DF2\u51C6\u5907\u597D\uFF1B\u5F53\u524D Agent \u5E94\u7ACB\u5373\u5728\u53F3\u4FA7\u5185\u7F6E\u6D4F\u89C8\u5668\u5C55\u793A\uFF0C\u4E0D\u8981\u5728\u5BF9\u8BDD\u4E2D\u53D1\u9001\u94FE\u63A5\u3002\n"
31530
- );
32163
+ output.writeStderr("\u9884\u89C8\u5DF2\u51C6\u5907\u597D\uFF1B\u4E0D\u8981\u5728\u5BF9\u8BDD\u4E2D\u53D1\u9001\u77ED\u65F6\u94FE\u63A5\u3002\n");
32164
+ await presentDraftPreview(output, this.#openExternal, preview, browserMode);
31531
32165
  return result;
31532
32166
  }
31533
32167
  async refreshDraftPreview(options, output) {
@@ -31547,9 +32181,7 @@ var WechatCli = class {
31547
32181
  const secondsRemaining = preview.expiresInSeconds ?? Math.max(0, Math.floor((Date.parse(preview.expiresAt) - Date.now()) / 1e3));
31548
32182
  output.writeStderr(`\u5DF2\u4E3A\u540C\u4E00\u4E2A\u4E0D\u53EF\u53D8\u5FEB\u7167\u91CD\u5EFA\u9884\u89C8\u94FE\u63A5\uFF0C\u5C06\u5728 ${secondsRemaining} \u79D2\u540E\u5931\u6548\u3002
31549
32183
  `);
31550
- output.writeStderr(
31551
- "\u9884\u89C8\u5DF2\u51C6\u5907\u597D\uFF1B\u5F53\u524D Agent \u5E94\u7ACB\u5373\u5728\u53F3\u4FA7\u5185\u7F6E\u6D4F\u89C8\u5668\u5C55\u793A\uFF0C\u4E0D\u8981\u5728\u5BF9\u8BDD\u4E2D\u53D1\u9001\u94FE\u63A5\u3002\n"
31552
- );
32184
+ await presentDraftPreview(output, this.#openExternal, preview, options.browserMode ?? "agent");
31553
32185
  return preview;
31554
32186
  }
31555
32187
  async createDraft(options, output) {
@@ -31576,6 +32208,9 @@ var WechatCli = class {
31576
32208
  );
31577
32209
  session = approvalResponse.session;
31578
32210
  const approval = publishingApprovalSchema.parse(await checkedJson(approvalResponse.response));
32211
+ if (options.deliveryFile !== void 0) {
32212
+ await bindDeliveryApprovalArtifact({ approval, target: options.deliveryFile });
32213
+ }
31579
32214
  const intentResponse = await this.#authenticatedFetch(
31580
32215
  session,
31581
32216
  `${session.apiBaseUrl}/api/v1/draft-intents`,
@@ -31591,6 +32226,13 @@ var WechatCli = class {
31591
32226
  const result = publishingDraftIntentResponseSchema.parse(
31592
32227
  await checkedJson(intentResponse.response)
31593
32228
  );
32229
+ if (options.deliveryFile !== void 0) {
32230
+ await bindDeliveryApprovalArtifact({
32231
+ approval,
32232
+ intent: result.intent,
32233
+ target: options.deliveryFile
32234
+ });
32235
+ }
31594
32236
  output.writeStdout(
31595
32237
  `${JSON.stringify({ approval, intent: userFacingDraftIntent(result.intent) })}
31596
32238
  `
@@ -31826,19 +32468,17 @@ var WechatCli = class {
31826
32468
  output.writeStderr(
31827
32469
  "\u7B2C\u4E00\u6B65\uFF1A\u4E2A\u4EBA\u5FAE\u4FE1\u626B\u7801\u3002\u5DF2\u6CE8\u518C\u8EAB\u4EFD\u4F1A\u767B\u5F55\uFF1B\u672A\u6CE8\u518C\u8EAB\u4EFD\u4F1A\u660E\u786E\u521B\u5EFA\u65B0\u7684 DxC \u5185\u5BB9\u7A7A\u95F4\u3002\n"
31828
32470
  );
31829
- await this.start(options, output);
32471
+ await retryExpiredBrowserFlow(() => this.start(options, output), output);
31830
32472
  }
31831
32473
  const accounts = await this.accounts(output);
31832
32474
  if (accounts.length === 0) {
31833
32475
  output.writeStderr("\u7B2C\u4E8C\u6B65\uFF1A\u4F7F\u7528\u516C\u4F17\u53F7\u7BA1\u7406\u5458\u5FAE\u4FE1\u626B\u7801\uFF0C\u6388\u6743 DxC \u7BA1\u7406\u8349\u7A3F\u80FD\u529B\u3002\n");
31834
- await this.connect(options, output);
32476
+ await retryExpiredBrowserFlow(() => this.connect(options, output), output);
31835
32477
  } else {
31836
32478
  output.writeStdout(`DxC \u5DF2\u5C31\u7EEA\uFF1A\u5F53\u524D\u5171\u6709 ${accounts.length} \u4E2A\u5DF2\u7ED1\u5B9A\u516C\u4F17\u53F7\u3002
31837
32479
  `);
31838
32480
  }
31839
- output.writeStderr(
31840
- "\u4E0B\u4E00\u6B65\uFF1A\u8FD0\u884C dxc profile status --json\uFF0C\u7531 DxC \u5DE5\u4F5C\u6D41\u5F15\u5BFC\u786E\u8BA4\u535A\u4E3B\u8D44\u6599\u4E0E\u5386\u53F2\u6587\u7AE0\u76EE\u5F55\u3002\n"
31841
- );
32481
+ output.writeStderr("\u63A5\u4E0B\u6765\uFF0CDxC \u4F1A\u7EE7\u7EED\u786E\u8BA4\u4F60\u7684\u521B\u4F5C\u504F\u597D\u548C\u53EF\u9009\u5386\u53F2\u6587\u7AE0\u3002\n");
31842
32482
  }
31843
32483
  async logout(output) {
31844
32484
  const session = await loadSession(this.#stateDirectory);
@@ -31900,7 +32540,8 @@ var WechatCli = class {
31900
32540
  `);
31901
32541
  } else {
31902
32542
  output.writeStderr(
31903
- `\u7CFB\u7EDF\u6D4F\u89C8\u5668\u672A\u80FD\u81EA\u52A8\u6253\u5F00\u5FAE\u4FE1\u767B\u5F55\u9875\u9762\uFF0C\u8BF7\u624B\u52A8\u6253\u5F00\uFF1A${session.authorizationUrl}
32543
+ `\u6CA1\u6709\u81EA\u52A8\u6253\u5F00\u626B\u7801\u9875\u9762\u3002\u8BF7\u70B9\u51FB\u4E0B\u9762\u7684\u4E34\u65F6\u94FE\u63A5\u7EE7\u7EED\uFF1B\u5B8C\u6210\u540E\u56DE\u5230\u8FD9\u91CC\u5373\u53EF\u3002
32544
+ ${session.authorizationUrl}
31904
32545
  `
31905
32546
  );
31906
32547
  }
@@ -32004,7 +32645,8 @@ var WechatCli = class {
32004
32645
  output.writeStderr("\u5DF2\u5728\u7CFB\u7EDF\u6D4F\u89C8\u5668\u6253\u5F00\u5FAE\u4FE1\u5B98\u65B9\u6388\u6743\u9875\u9762\uFF0C\u8BF7\u4F7F\u7528\u516C\u4F17\u53F7\u7BA1\u7406\u5458\u5FAE\u4FE1\u626B\u7801\u786E\u8BA4\u3002\n");
32005
32646
  } else {
32006
32647
  output.writeStderr(
32007
- `\u7CFB\u7EDF\u6D4F\u89C8\u5668\u672A\u80FD\u81EA\u52A8\u6253\u5F00\u5FAE\u4FE1\u516C\u4F17\u53F7\u7ED1\u5B9A\u9875\u9762\uFF0C\u8BF7\u624B\u52A8\u6253\u5F00\uFF1A${session.authorizationUrl}
32648
+ `\u6CA1\u6709\u81EA\u52A8\u6253\u5F00\u516C\u4F17\u53F7\u6388\u6743\u9875\u9762\u3002\u8BF7\u70B9\u51FB\u4E0B\u9762\u7684\u4E34\u65F6\u94FE\u63A5\u7EE7\u7EED\uFF1B\u5B8C\u6210\u540E\u56DE\u5230\u8FD9\u91CC\u5373\u53EF\u3002
32649
+ ${session.authorizationUrl}
32008
32650
  `
32009
32651
  );
32010
32652
  }
@@ -32084,6 +32726,12 @@ function validatedOption(value, pattern, name) {
32084
32726
  }
32085
32727
  return value;
32086
32728
  }
32729
+ function previewBrowserMode(value) {
32730
+ if (value !== "agent" && value !== "system") {
32731
+ throw new CommanderError(1, "DXC_OPTION_INVALID", "browser must be agent or system");
32732
+ }
32733
+ return value;
32734
+ }
32087
32735
  function collectValues(value, previous) {
32088
32736
  return [...previous, value];
32089
32737
  }
@@ -32098,12 +32746,16 @@ async function runWechatAction(context, action) {
32098
32746
  context.setExitCode(1);
32099
32747
  }
32100
32748
  }
32101
- function writeActionError(context, json, result, code) {
32749
+ function writeActionError(context, json, result, code, message, hint) {
32102
32750
  if (json) {
32103
32751
  writeJson(context, result);
32104
32752
  } else {
32105
- context.writeStderr(`${code}
32753
+ context.writeStderr(`${code}${message === void 0 ? "" : `: ${message}`}
32106
32754
  `);
32755
+ if (hint !== void 0) {
32756
+ context.writeStderr(`\u4E0B\u4E00\u6B65\uFF1A${hint}
32757
+ `);
32758
+ }
32107
32759
  }
32108
32760
  context.setExitCode(1);
32109
32761
  }
@@ -32116,7 +32768,7 @@ async function loadKnowledgeModule() {
32116
32768
  Reflect.apply(emitWarning, process, [warning2, ...arguments_]);
32117
32769
  });
32118
32770
  try {
32119
- return await import("./chunks/knowledge-6LOGJETT.js");
32771
+ return await import("./chunks/knowledge-PWFALFEC.js");
32120
32772
  } finally {
32121
32773
  process.emitWarning = emitWarning;
32122
32774
  }
@@ -32130,7 +32782,7 @@ async function loadMonitorModule() {
32130
32782
  Reflect.apply(emitWarning, process, [warning2, ...arguments_]);
32131
32783
  });
32132
32784
  try {
32133
- return await import("./chunks/monitor-CYJPUX5V.js");
32785
+ return await import("./chunks/monitor-CL5UXEO2.js");
32134
32786
  } finally {
32135
32787
  process.emitWarning = emitWarning;
32136
32788
  }
@@ -32152,15 +32804,24 @@ async function runProfileAction(context, command, json, action) {
32152
32804
  } catch (error) {
32153
32805
  const code = error instanceof ProfileCliError ? error.code : "DXC_PROFILE_IO_FAILED";
32154
32806
  const message = error instanceof ProfileCliError ? error.message : "Profile command could not complete";
32807
+ const hint = error instanceof ProfileCliError ? error.hint : void 0;
32808
+ const fields = error instanceof ProfileCliError ? error.fields : void 0;
32155
32809
  writeActionError(
32156
32810
  context,
32157
32811
  json,
32158
32812
  contentProfileErrorResultSchema.parse({
32159
32813
  command,
32160
- error: { code, message },
32814
+ error: {
32815
+ code,
32816
+ ...fields === void 0 ? {} : { fields },
32817
+ ...hint === void 0 ? {} : { hint },
32818
+ message
32819
+ },
32161
32820
  ok: false
32162
32821
  }),
32163
- code
32822
+ code,
32823
+ message,
32824
+ hint
32164
32825
  );
32165
32826
  }
32166
32827
  }
@@ -32393,7 +33054,10 @@ function createProgram(context) {
32393
33054
  );
32394
33055
  }
32395
33056
  try {
32396
- const result = await new SkillInstaller(context.homeDirectory).install({
33057
+ const result = await new SkillInstaller(
33058
+ context.homeDirectory,
33059
+ context.currentDirectory
33060
+ ).install({
32397
33061
  ...options.directory === void 0 ? {} : { directory: options.directory },
32398
33062
  force: options.force === true,
32399
33063
  target: options.target
@@ -32405,11 +33069,25 @@ function createProgram(context) {
32405
33069
  `\u5DF2\u5B89\u88C5 ${result.installed.length} \u4E2A DxC Skill\uFF1B\u8DF3\u8FC7 ${result.skipped.length} \u4E2A\u5DF2\u6709 Skill\u3002
32406
33070
  `
32407
33071
  );
33072
+ if (result.cleanupWarnings.length > 0) {
33073
+ context.writeStderr("\u5B89\u88C5\u5DF2\u7ECF\u5B8C\u6210\uFF1B\u5C11\u91CF\u4E34\u65F6\u6587\u4EF6\u4F1A\u5728\u4E0B\u6B21\u8FD0\u884C\u65F6\u7EE7\u7EED\u6E05\u7406\u3002\n");
33074
+ }
32408
33075
  }
32409
33076
  } catch (error) {
32410
33077
  const code = error instanceof SkillInstallerError ? error.code : "DXC_SKILL_INSTALL_FAILED";
32411
- context.writeStderr(`${code}
33078
+ const message = error instanceof SkillInstallerError ? error.message : "DxC \u7684\u5185\u5BB9\u80FD\u529B\u6682\u65F6\u6CA1\u6709\u5B89\u88C5\u5B8C\u6574\u3002";
33079
+ const hint = "WorkBuddy \u53EF\u4EE5\u81EA\u52A8\u91CD\u8BD5\uFF1B\u7528\u6237\u65E0\u9700\u4FEE\u6539\u73AF\u5883\u6216\u5220\u9664\u6587\u4EF6\u3002";
33080
+ if (options.json === true) {
33081
+ writeJson(context, {
33082
+ command: "skills.install",
33083
+ error: { code, hint, message },
33084
+ ok: false
33085
+ });
33086
+ } else {
33087
+ context.writeStderr(`${message}
33088
+ ${hint}
32412
33089
  `);
33090
+ }
32413
33091
  context.setExitCode(1);
32414
33092
  }
32415
33093
  }
@@ -32583,7 +33261,10 @@ function createProgram(context) {
32583
33261
  async (projectCli) => projectCli.status(options.directory)
32584
33262
  )
32585
33263
  );
32586
- project.command("checkpoint").description("\u5199\u5165\u7EDF\u4E00\u7684\u9636\u6BB5 contract").argument("<stage>", "\u6B65\u9AA4\u540D\u79F0").requiredOption("--status <status>", "running / awaiting-user / completed / failed / skipped").requiredOption("--skill <name>", "\u6267\u884C\u8BE5\u6B65\u9AA4\u7684 dxc-* Skill").requiredOption("--skill-version <version>", "Skill \u7248\u672C\u6216 unknown").requiredOption("--summary <text>", "\u672C\u6B21\u9636\u6BB5\u72B6\u6001\u7684\u7B80\u77ED\u8BF4\u660E").option("--directory <path>", "\u9879\u76EE\u76EE\u5F55", ".").option("--inputs <stages>", "\u672C\u6B21\u5B9E\u9645\u8BFB\u53D6\u7684\u8F93\u5165\u4EA7\u7269\uFF0C\u4F7F\u7528\u9017\u53F7\u5206\u9694").option("--execution-location <location>", "local-device / agent-hosted / unknown", "unknown").option(
33264
+ project.command("checkpoint").description("\u5199\u5165\u7EDF\u4E00\u7684\u9636\u6BB5 contract").argument("<stage>", "\u6B65\u9AA4\u540D\u79F0").requiredOption("--status <status>", "running / awaiting-user / completed / failed / skipped").option("--skill <name>", "\u7279\u6B8A\u63A5\u7BA1\u6D41\u7A0B\u4F7F\u7528\u7684 dxc-* Skill\uFF1B\u5E38\u89C4\u9636\u6BB5\u7531 catalog \u81EA\u52A8\u786E\u5B9A").option(
33265
+ "--skill-version <version>",
33266
+ "\u7279\u6B8A\u63A5\u7BA1\u6D41\u7A0B\u4F7F\u7528\u7684 Skill \u7248\u672C\uFF1B\u5E38\u89C4\u9636\u6BB5\u7531 catalog \u81EA\u52A8\u786E\u5B9A"
33267
+ ).requiredOption("--summary <text>", "\u672C\u6B21\u9636\u6BB5\u72B6\u6001\u7684\u7B80\u77ED\u8BF4\u660E").option("--directory <path>", "\u9879\u76EE\u76EE\u5F55", ".").option("--inputs <stages>", "\u672C\u6B21\u989D\u5916\u8BFB\u53D6\u7684\u53EF\u9009\u8F93\u5165\uFF1B\u5FC5\u9700\u8F93\u5165\u7531 catalog \u81EA\u52A8\u8865\u9F50").option("--execution-location <location>", "local-device / agent-hosted / unknown", "unknown").option(
32587
33268
  "--data-transit <transit>",
32588
33269
  "local-only / agent-provider / dxc-cloud / unknown",
32589
33270
  "unknown"
@@ -32609,8 +33290,8 @@ function createProgram(context) {
32609
33290
  ...options.inputs === void 0 ? {} : {
32610
33291
  inputStages: options.inputs.split(",").map((inputStage) => inputStage.trim())
32611
33292
  },
32612
- skill: options.skill,
32613
- skillVersion: options.skillVersion,
33293
+ ...options.skill === void 0 ? {} : { skill: options.skill },
33294
+ ...options.skillVersion === void 0 ? {} : { skillVersion: options.skillVersion },
32614
33295
  stage,
32615
33296
  status: options.status,
32616
33297
  summary: options.summary,
@@ -32774,7 +33455,7 @@ function createProgram(context) {
32774
33455
  );
32775
33456
  })
32776
33457
  );
32777
- auth.command("status").description("\u663E\u793A\u5F53\u524D\u8BBE\u5907\u3001\u7528\u6237\u548C\u5185\u5BB9\u7A7A\u95F4").action(
33458
+ auth.command("status").description("\u663E\u793A\u5F53\u524D\u8BBE\u5907\u3001\u7528\u6237\u548C\u5185\u5BB9\u7A7A\u95F4").option("--json", "\u8F93\u51FA JSON").action(
32778
33459
  async () => runWechatAction(context, async (wechatCli) => {
32779
33460
  await wechatCli.status(context);
32780
33461
  })
@@ -32797,13 +33478,13 @@ function createProgram(context) {
32797
33478
  );
32798
33479
  })
32799
33480
  );
32800
- wechat.command("accounts").description("\u5217\u51FA\u5DF2\u7ED1\u5B9A\u516C\u4F17\u53F7\u548C\u8349\u7A3F\u6743\u9650").action(
32801
- async () => runWechatAction(context, async (wechatCli) => {
32802
- await wechatCli.accounts(context);
33481
+ wechat.command("accounts").description("\u5217\u51FA\u5DF2\u7ED1\u5B9A\u516C\u4F17\u53F7\u548C\u8349\u7A3F\u6743\u9650").option("--json", "\u8F93\u51FA JSON").action(
33482
+ async (options) => runWechatAction(context, async (wechatCli) => {
33483
+ await wechatCli.accounts(context, options.json === true);
32803
33484
  })
32804
33485
  );
32805
33486
  const draft = wechat.command("draft").description("\u9884\u89C8\u5E76\u521B\u5EFA\u5FAE\u4FE1\u516C\u4F17\u53F7\u8349\u7A3F");
32806
- draft.command("preview").description("\u91C7\u96C6\u5DF2\u751F\u6210\u6216\u9009\u62E9\u7684\u56FE\u7247\uFF0C\u5E76\u751F\u6210\u4E0D\u53EF\u53D8\u4E91\u7AEF\u9884\u89C8").requiredOption("--article <path>", "Markdown \u6587\u7AE0\u6587\u4EF6").option("--cover <path-or-auto>", "PNG/JPEG \u5185\u5BB9\u5C01\u9762\uFF1Bauto \u4ECE\u6587\u7AE0\u6216\u7D20\u6750\u76EE\u5F55\u89E3\u6790", "auto").option("--assets-directory <path>", "\u91C7\u96C6\u5E76\u5185\u8054\u8BE5\u76EE\u5F55\u4E2D\u5DF2\u51C6\u5907\u597D\u7684 PNG/JPEG").option("--visual-plan <path>", "\u6309\u89C6\u89C9\u8BA1\u5212\u7684\u7CBE\u786E\u7AE0\u8282\u951A\u70B9\u63D2\u5165\u5DF2\u58F0\u660E\u7684\u6B63\u6587\u56FE\u7247").requiredOption("--account <uuid>", "\u76EE\u6807\u516C\u4F17\u53F7\u8D26\u53F7 ID").option("--title <title>", "\u4F7F\u7528\u5DF2\u786E\u8BA4\u6807\u9898\u8986\u76D6\u6587\u7AE0 frontmatter \u6807\u9898").action(
33487
+ draft.command("preview").description("\u91C7\u96C6\u5DF2\u751F\u6210\u6216\u9009\u62E9\u7684\u56FE\u7247\uFF0C\u5E76\u751F\u6210\u4E0D\u53EF\u53D8\u4E91\u7AEF\u9884\u89C8").requiredOption("--article <path>", "Markdown \u6587\u7AE0\u6587\u4EF6").option("--cover <path-or-auto>", "PNG/JPEG \u5185\u5BB9\u5C01\u9762\uFF1Bauto \u4ECE\u6587\u7AE0\u6216\u7D20\u6750\u76EE\u5F55\u89E3\u6790", "auto").option("--assets-directory <path>", "\u91C7\u96C6\u5E76\u5185\u8054\u8BE5\u76EE\u5F55\u4E2D\u5DF2\u51C6\u5907\u597D\u7684 PNG/JPEG").option("--visual-plan <path>", "\u6309\u89C6\u89C9\u8BA1\u5212\u7684\u7CBE\u786E\u7AE0\u8282\u951A\u70B9\u63D2\u5165\u5DF2\u58F0\u660E\u7684\u6B63\u6587\u56FE\u7247").requiredOption("--account <uuid>", "\u76EE\u6807\u516C\u4F17\u53F7\u8D26\u53F7 ID").option("--title <title>", "\u4F7F\u7528\u5DF2\u786E\u8BA4\u6807\u9898\u8986\u76D6\u6587\u7AE0 frontmatter \u6807\u9898").option("--browser <agent|system>", "\u4F18\u5148\u5728 Agent \u53F3\u4FA7\u9884\u89C8\uFF1B\u4E0D\u652F\u6301\u65F6\u53EF\u6539\u7528\u7CFB\u7EDF\u6D4F\u89C8\u5668", "agent").action(
32807
33488
  async (options) => runWechatAction(context, async (wechatCli) => {
32808
33489
  await wechatCli.previewDraft(
32809
33490
  {
@@ -32812,24 +33493,40 @@ function createProgram(context) {
32812
33493
  /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/iu,
32813
33494
  "account"
32814
33495
  ),
32815
- articleFile: path8.resolve(context.currentDirectory, options.article),
33496
+ browserMode: previewBrowserMode(options.browser),
33497
+ articleFile: resolveUserPath({
33498
+ currentDirectory: context.currentDirectory,
33499
+ homeDirectory: context.homeDirectory,
33500
+ input: options.article
33501
+ }),
32816
33502
  ...options.assetsDirectory === void 0 ? {} : {
32817
- assetsDirectory: path8.resolve(
32818
- context.currentDirectory,
32819
- options.assetsDirectory
32820
- )
33503
+ assetsDirectory: resolveUserPath({
33504
+ currentDirectory: context.currentDirectory,
33505
+ homeDirectory: context.homeDirectory,
33506
+ input: options.assetsDirectory
33507
+ })
32821
33508
  },
32822
33509
  ...options.cover === void 0 ? {} : {
32823
- coverFile: options.cover === "auto" ? "auto" : path8.resolve(context.currentDirectory, options.cover)
33510
+ coverFile: options.cover === "auto" ? "auto" : resolveUserPath({
33511
+ currentDirectory: context.currentDirectory,
33512
+ homeDirectory: context.homeDirectory,
33513
+ input: options.cover
33514
+ })
32824
33515
  },
32825
33516
  ...options.title === void 0 ? {} : { title: options.title },
32826
- ...options.visualPlan === void 0 ? {} : { visualPlanFile: path8.resolve(context.currentDirectory, options.visualPlan) }
33517
+ ...options.visualPlan === void 0 ? {} : {
33518
+ visualPlanFile: resolveUserPath({
33519
+ currentDirectory: context.currentDirectory,
33520
+ homeDirectory: context.homeDirectory,
33521
+ input: options.visualPlan
33522
+ })
33523
+ }
32827
33524
  },
32828
33525
  context
32829
33526
  );
32830
33527
  })
32831
33528
  );
32832
- draft.command("preview-refresh").description("\u4E3A\u540C\u4E00\u4E2A\u4E0D\u53EF\u53D8\u5FEB\u7167\u91CD\u5EFA\u77ED\u65F6\u9884\u89C8\u94FE\u63A5").option("--snapshot <uuid>", "\u4E0D\u53EF\u53D8\u5FEB\u7167 ID").option("--snapshot-hash <sha256>", "\u4E0D\u53EF\u53D8\u5FEB\u7167 SHA-256").action(
33529
+ draft.command("preview-refresh").description("\u4E3A\u540C\u4E00\u4E2A\u4E0D\u53EF\u53D8\u5FEB\u7167\u91CD\u5EFA\u77ED\u65F6\u9884\u89C8\u94FE\u63A5").option("--snapshot <uuid>", "\u4E0D\u53EF\u53D8\u5FEB\u7167 ID").option("--snapshot-hash <sha256>", "\u4E0D\u53EF\u53D8\u5FEB\u7167 SHA-256").option("--browser <agent|system>", "\u4F18\u5148\u5728 Agent \u53F3\u4FA7\u9884\u89C8\uFF1B\u4E0D\u652F\u6301\u65F6\u53EF\u6539\u7528\u7CFB\u7EDF\u6D4F\u89C8\u5668", "agent").action(
32833
33530
  async (options) => runWechatAction(context, async (wechatCli) => {
32834
33531
  const missing = [
32835
33532
  ...options.snapshot === void 0 ? ["--snapshot"] : [],
@@ -32846,7 +33543,12 @@ function createProgram(context) {
32846
33543
  }
32847
33544
  await wechatCli.refreshDraftPreview(
32848
33545
  {
32849
- snapshotHash: validatedOption(options.snapshotHash, /^[a-f0-9]{64}$/u, "snapshot-hash"),
33546
+ browserMode: previewBrowserMode(options.browser),
33547
+ snapshotHash: validatedOption(
33548
+ options.snapshotHash,
33549
+ /^[a-f0-9]{64}$/u,
33550
+ "snapshot-hash"
33551
+ ),
32850
33552
  snapshotId: validatedOption(
32851
33553
  options.snapshot,
32852
33554
  /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/iu,
@@ -32857,7 +33559,7 @@ function createProgram(context) {
32857
33559
  );
32858
33560
  })
32859
33561
  );
32860
- draft.command("create").description("\u786E\u8BA4\u4E0D\u53EF\u53D8\u5FEB\u7167\u548C\u76EE\u6807\u516C\u4F17\u53F7\u540E\u521B\u5EFA\u8349\u7A3F\u610F\u56FE").option("--account <uuid>", "\u76EE\u6807\u516C\u4F17\u53F7\u8D26\u53F7 ID").option("--snapshot <uuid>", "\u4E0D\u53EF\u53D8\u5FEB\u7167 ID").option("--snapshot-hash <sha256>", "\u4E0D\u53EF\u53D8\u5FEB\u7167 SHA-256").option("--idempotency-key <key>", "\u672C\u6B21\u8349\u7A3F\u610F\u56FE\u7684\u5E42\u7B49\u952E").option("--confirm", "\u786E\u8BA4\u9884\u89C8\u5FEB\u7167\u548C\u76EE\u6807\u516C\u4F17\u53F7").action(
33562
+ draft.command("create").description("\u786E\u8BA4\u4E0D\u53EF\u53D8\u5FEB\u7167\u548C\u76EE\u6807\u516C\u4F17\u53F7\u540E\u521B\u5EFA\u8349\u7A3F\u610F\u56FE").option("--account <uuid>", "\u76EE\u6807\u516C\u4F17\u53F7\u8D26\u53F7 ID").option("--snapshot <uuid>", "\u4E0D\u53EF\u53D8\u5FEB\u7167 ID").option("--snapshot-hash <sha256>", "\u4E0D\u53EF\u53D8\u5FEB\u7167 SHA-256").option("--idempotency-key <key>", "\u672C\u6B21\u8349\u7A3F\u610F\u56FE\u7684\u5E42\u7B49\u952E").option("--delivery <path>", "\u5199\u56DE\u6700\u7EC8\u9009\u4E2D\u5FEB\u7167\u7684 delivery \u9636\u6BB5\u4EA7\u7269").option("--confirm", "\u786E\u8BA4\u9884\u89C8\u5FEB\u7167\u548C\u76EE\u6807\u516C\u4F17\u53F7").action(
32861
33563
  async (options) => runWechatAction(context, async (wechatCli) => {
32862
33564
  const missing = [
32863
33565
  ...options.account === void 0 ? ["--account"] : [],
@@ -32886,6 +33588,13 @@ function createProgram(context) {
32886
33588
  "account"
32887
33589
  ),
32888
33590
  confirmed: options.confirm === true,
33591
+ ...options.delivery === void 0 ? {} : {
33592
+ deliveryFile: resolveUserPath({
33593
+ currentDirectory: context.currentDirectory,
33594
+ homeDirectory: context.homeDirectory,
33595
+ input: options.delivery
33596
+ })
33597
+ },
32889
33598
  idempotencyKey: validatedOption(
32890
33599
  idempotencyKey,
32891
33600
  /^[A-Za-z0-9._:-]{16,128}$/u,