vscode-behavior3 2.2.0 → 2.3.3

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/extension.js CHANGED
@@ -215264,10 +215264,7 @@ function customAlphabet(alphabet, size = 21) {
215264
215264
 
215265
215265
  // webview/shared/stable-id.ts
215266
215266
  var UUID_ALPHABET = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
215267
- var generateUuid = customAlphabet(
215268
- UUID_ALPHABET,
215269
- 10
215270
- );
215267
+ var generateUuid = customAlphabet(UUID_ALPHABET, 10);
215271
215268
  var hashString = (value) => {
215272
215269
  let hash = 2166136261;
215273
215270
  for (let index = 0; index < value.length; index += 1) {
@@ -215281,7 +215278,7 @@ var generateDeterministicUuid = (seed) => {
215281
215278
  let result = "";
215282
215279
  for (let index = 0; index < 10; index += 1) {
215283
215280
  state = Math.imul(state ^ state >>> 16, 2246822519) >>> 0;
215284
- state ^= hashString(`${seed}:${index}`);
215281
+ state = (state ^ hashString(`${seed}:${index}`)) >>> 0;
215285
215282
  result += UUID_ALPHABET[state % UUID_ALPHABET.length];
215286
215283
  }
215287
215284
  return result;
@@ -215375,6 +215372,12 @@ var asRequiredString = (value, label) => {
215375
215372
  }
215376
215373
  return value;
215377
215374
  };
215375
+ var normalizeTreeVersion = (value) => {
215376
+ if (value === void 0) {
215377
+ return DOCUMENT_VERSION;
215378
+ }
215379
+ return asRequiredString(value, "tree file version");
215380
+ };
215378
215381
  var asStringArray = (value, label) => {
215379
215382
  if (value === void 0) {
215380
215383
  return [];
@@ -215693,7 +215696,7 @@ var normalizeTreeData = (value, opts) => {
215693
215696
  const variablesValue = record.variables;
215694
215697
  const variablesRecord = variablesValue === void 0 ? void 0 : expectPlainRecord(variablesValue, "tree file variables");
215695
215698
  return {
215696
- version: asRequiredString(record.version, "tree file version"),
215699
+ version: normalizeTreeVersion(record.version),
215697
215700
  name: asRequiredString(record.name, "tree file name"),
215698
215701
  prefix: asOptionalString(record.prefix) ?? "",
215699
215702
  desc: asOptionalString(record.desc),
@@ -215948,10 +215951,10 @@ var applyMainTreeDisplayIds = (root, idsByStableId) => {
215948
215951
  }
215949
215952
  });
215950
215953
  };
215951
- var hasMissingStableIds = (content) => {
215954
+ var needsLegacyTreeWriteback = (content) => {
215952
215955
  try {
215953
215956
  const parsed = JSON.parse(content);
215954
- return subtreeNeedsMissingIds(parsed.root) || parsed.$override !== void 0 || parsed.import !== void 0 || parsed.vars !== void 0;
215957
+ return parsed.version === void 0 || subtreeNeedsMissingIds(parsed.root) || parsed.$override !== void 0 || parsed.import !== void 0 || parsed.vars !== void 0;
215955
215958
  } catch {
215956
215959
  return false;
215957
215960
  }
@@ -215974,7 +215977,7 @@ var loadSubtreeSourceCache = async (params) => {
215974
215977
  return;
215975
215978
  }
215976
215979
  try {
215977
- const needsWriteback = hasMissingStableIds(content);
215980
+ const needsWriteback = needsLegacyTreeWriteback(content);
215978
215981
  const tree = parsePersistedTreeContent(content, normalizedPath);
215979
215982
  cache[normalizedPath] = tree;
215980
215983
  await params.onTreeLoaded?.({
@@ -216464,14 +216467,15 @@ var readWorkspaceSettings = (path14) => {
216464
216467
  const content = getFs().readFileSync(path14, "utf-8");
216465
216468
  return parseWorkspaceModelContent(content).settings;
216466
216469
  };
216467
- var hasBatchHookMethod = (obj) => {
216470
+ var hasBuildHookMethod = (obj) => {
216468
216471
  if (!obj || typeof obj !== "object") {
216469
216472
  return false;
216470
216473
  }
216471
216474
  const candidate = obj;
216472
- return typeof candidate.shouldUpgradeTree === "function" || typeof candidate.onProcessTree === "function" || typeof candidate.onProcessNode === "function" || typeof candidate.onWriteFile === "function" || typeof candidate.onComplete === "function";
216475
+ return typeof candidate.onProcessTree === "function" || typeof candidate.onProcessNode === "function" || typeof candidate.onWriteFile === "function" || typeof candidate.onComplete === "function";
216473
216476
  };
216474
216477
  var BUILD_HOOK_MARKER = "__behavior3BuildHook";
216478
+ var BATCH_HOOK_MARKER = "__behavior3BatchHook";
216475
216479
  var CHECK_HOOK_MARKER = "__behavior3CheckHook";
216476
216480
  var CHECK_HOOK_NAME = "__behavior3CheckName";
216477
216481
  var markBuildHook = (ctor) => {
@@ -216481,6 +216485,13 @@ var markBuildHook = (ctor) => {
216481
216485
  });
216482
216486
  return ctor;
216483
216487
  };
216488
+ var markBatchHook = (ctor) => {
216489
+ Object.defineProperty(ctor, BATCH_HOOK_MARKER, {
216490
+ value: true,
216491
+ configurable: false
216492
+ });
216493
+ return ctor;
216494
+ };
216484
216495
  var markCheckCtor = (ctor, explicitName) => {
216485
216496
  const name = explicitName?.trim() || ctor.name;
216486
216497
  Object.defineProperty(ctor, CHECK_HOOK_MARKER, {
@@ -216499,28 +216510,51 @@ var markCheckHook = (nameOrCtor, _context) => {
216499
216510
  }
216500
216511
  return (ctor) => markCheckCtor(ctor, nameOrCtor);
216501
216512
  };
216502
- var isDecoratedHookCtor = (value) => typeof value === "function" && value[BUILD_HOOK_MARKER] === true;
216513
+ var isDecoratedBuildHookCtor = (value) => typeof value === "function" && value[BUILD_HOOK_MARKER] === true;
216514
+ var isDecoratedBatchHookCtor = (value) => typeof value === "function" && value[BATCH_HOOK_MARKER] === true;
216503
216515
  var isDecoratedCheckCtor = (value) => typeof value === "function" && value[CHECK_HOOK_MARKER] === true;
216504
- var findDecoratedHookCtor = (moduleRecord) => {
216505
- const decorated = Array.from(new Set(Object.values(moduleRecord))).filter(isDecoratedHookCtor);
216516
+ var findDecoratedBuildHookCtor = (moduleRecord) => {
216517
+ const decorated = Array.from(new Set(Object.values(moduleRecord))).filter(
216518
+ isDecoratedBuildHookCtor
216519
+ );
216506
216520
  if (decorated.length > 1) {
216507
216521
  logger.error("build script must decorate exactly one exported class with @behavior3.build");
216508
216522
  return void 0;
216509
216523
  }
216510
216524
  return decorated[0];
216511
216525
  };
216526
+ var findDecoratedBatchHookCtor = (moduleRecord) => {
216527
+ const decorated = Array.from(new Set(Object.values(moduleRecord))).filter(
216528
+ isDecoratedBatchHookCtor
216529
+ );
216530
+ if (decorated.length > 1) {
216531
+ logger.error("batch script must decorate exactly one exported class with @behavior3.batch");
216532
+ return void 0;
216533
+ }
216534
+ if (decorated.length === 1) {
216535
+ return decorated[0];
216536
+ }
216537
+ const legacyDecorated = Array.from(new Set(Object.values(moduleRecord))).filter(
216538
+ isDecoratedBuildHookCtor
216539
+ );
216540
+ if (legacyDecorated.length > 1) {
216541
+ logger.error("batch script must decorate exactly one exported class with @behavior3.batch");
216542
+ return void 0;
216543
+ }
216544
+ return legacyDecorated[0];
216545
+ };
216512
216546
  var findDecoratedCheckCtors = (moduleRecord) => Array.from(new Set(Object.values(moduleRecord))).filter(isDecoratedCheckCtor);
216513
- var createBatchHooks = (moduleExports, env2, reportMissing = true) => {
216547
+ var createBuildHooks = (moduleExports, env2, reportMissing = true) => {
216514
216548
  if (!moduleExports || typeof moduleExports !== "object") {
216515
216549
  return void 0;
216516
216550
  }
216517
216551
  const moduleRecord = moduleExports;
216518
- const defaultExport = isDecoratedCheckCtor(moduleRecord.default) ? void 0 : moduleRecord.default;
216519
- const ctor = moduleRecord.Hook ?? findDecoratedHookCtor(moduleRecord) ?? defaultExport;
216552
+ const defaultExport = isDecoratedCheckCtor(moduleRecord.default) || isDecoratedBatchHookCtor(moduleRecord.default) ? void 0 : moduleRecord.default;
216553
+ const ctor = moduleRecord.BuildHook ?? moduleRecord.Hook ?? findDecoratedBuildHookCtor(moduleRecord) ?? defaultExport;
216520
216554
  if (typeof ctor === "function") {
216521
216555
  try {
216522
216556
  const instance = new ctor(env2);
216523
- if (hasBatchHookMethod(instance)) {
216557
+ if (hasBuildHookMethod(instance)) {
216524
216558
  return instance;
216525
216559
  }
216526
216560
  logger.error("build hook class instance has no supported hook methods");
@@ -216530,7 +216564,32 @@ var createBatchHooks = (moduleExports, env2, reportMissing = true) => {
216530
216564
  }
216531
216565
  if (reportMissing) {
216532
216566
  logger.error(
216533
- "build script must export a Hook class, default class, or one @behavior3.build-decorated class"
216567
+ "build script must export a BuildHook class, Hook class, default class, or one @behavior3.build-decorated class"
216568
+ );
216569
+ }
216570
+ return void 0;
216571
+ };
216572
+ var createBatchHooks = (moduleExports, env2, reportMissing = true) => {
216573
+ if (!moduleExports || typeof moduleExports !== "object") {
216574
+ return void 0;
216575
+ }
216576
+ const moduleRecord = moduleExports;
216577
+ const defaultExport = isDecoratedCheckCtor(moduleRecord.default) || isDecoratedBuildHookCtor(moduleRecord.default) || isDecoratedBatchHookCtor(moduleRecord.default) ? void 0 : moduleRecord.default;
216578
+ const ctor = moduleRecord.BatchHook ?? findDecoratedBatchHookCtor(moduleRecord) ?? moduleRecord.Hook ?? defaultExport;
216579
+ if (typeof ctor === "function") {
216580
+ try {
216581
+ const instance = new ctor(env2);
216582
+ if (hasBuildHookMethod(instance) || typeof instance.shouldUpgradeTree === "function") {
216583
+ return instance;
216584
+ }
216585
+ logger.error("batch hook class instance has no supported hook methods");
216586
+ } catch (error) {
216587
+ logger.error("failed to instantiate batch hook class", error);
216588
+ }
216589
+ }
216590
+ if (reportMissing) {
216591
+ logger.error(
216592
+ "batch script must export a BatchHook class, default class, or one @behavior3.batch-decorated class"
216534
216593
  );
216535
216594
  }
216536
216595
  return void 0;
@@ -216579,13 +216638,13 @@ var createBuildScriptRuntime = (moduleExports, env2) => {
216579
216638
  };
216580
216639
  }
216581
216640
  const moduleRecord = moduleExports;
216582
- const hasBuildHookCandidate = typeof moduleRecord.Hook === "function" || Object.values(moduleRecord).some(isDecoratedHookCtor) || typeof moduleRecord.default === "function" && !isDecoratedCheckCtor(moduleRecord.default);
216583
- const buildScript = createBatchHooks(moduleExports, env2, false);
216641
+ const hasBuildHookCandidate = typeof moduleRecord.BuildHook === "function" || typeof moduleRecord.Hook === "function" || Object.values(moduleRecord).some(isDecoratedBuildHookCtor) || typeof moduleRecord.default === "function" && !isDecoratedCheckCtor(moduleRecord.default) && !isDecoratedBatchHookCtor(moduleRecord.default);
216642
+ const buildScript = createBuildHooks(moduleExports, env2, false);
216584
216643
  const checkerResult = createNodeArgCheckers(moduleExports, env2);
216585
216644
  const hasEntries = Boolean(buildScript) || checkerResult.hasCheckers;
216586
216645
  if (!hasEntries) {
216587
216646
  logger.error(
216588
- "build script must export a Hook class, default build class, @behavior3.build class, or @behavior3.check class"
216647
+ "build script must export a BuildHook class, Hook class, default build class, @behavior3.build class, or @behavior3.check class"
216589
216648
  );
216590
216649
  }
216591
216650
  return {
@@ -217006,6 +217065,7 @@ var applyBehavior3DecoratorGlobal = () => {
217006
217065
  runtimeGlobal.behavior3 = {
217007
217066
  ...decoratorGlobalState.previousBehavior3 && typeof decoratorGlobalState.previousBehavior3 === "object" ? decoratorGlobalState.previousBehavior3 : {},
217008
217067
  build: markBuildHook,
217068
+ batch: markBatchHook,
217009
217069
  check: markCheckHook
217010
217070
  };
217011
217071
  };
@@ -217026,7 +217086,7 @@ var restoreBehavior3DecoratorGlobal = () => {
217026
217086
  decoratorGlobalState.hadBehavior3 = false;
217027
217087
  decoratorGlobalState.previousBehavior3 = void 0;
217028
217088
  };
217029
- var withBehavior3BuildDecoratorGlobal = async (loader) => {
217089
+ var withBehavior3ScriptDecoratorGlobal = async (loader) => {
217030
217090
  applyBehavior3DecoratorGlobal();
217031
217091
  try {
217032
217092
  return await loader();
@@ -217165,7 +217225,7 @@ var loadRuntimeModule = async (modulePath, options) => {
217165
217225
  }
217166
217226
  }
217167
217227
  if (getRuntimeProcess()?.type === "renderer") {
217168
- return await withBehavior3BuildDecoratorGlobal(
217228
+ return await withBehavior3ScriptDecoratorGlobal(
217169
217229
  () => import(
217170
217230
  /* @vite-ignore */
217171
217231
  `${modulePath}?t=${Date.now()}`
@@ -217193,7 +217253,7 @@ var loadRuntimeModule = async (modulePath, options) => {
217193
217253
  return null;
217194
217254
  }
217195
217255
  const normalizedModulePath = b3path_default.posixPath(tempModulePath);
217196
- const result = await withBehavior3BuildDecoratorGlobal(
217256
+ const result = await withBehavior3ScriptDecoratorGlobal(
217197
217257
  () => import(
217198
217258
  /* @vite-ignore */
217199
217259
  `file:///${normalizedModulePath}?t=${Date.now()}`
@@ -217507,6 +217567,14 @@ var validateExpressionEntries = (entries, usingVars, checkExpr) => {
217507
217567
  return null;
217508
217568
  };
217509
217569
  var getArgLabel = (arg) => arg.desc || arg.name;
217570
+ var findNodeArgOneofInputIndex = (arg, inputDefs) => {
217571
+ if (!arg.oneof || !inputDefs?.length) {
217572
+ return -1;
217573
+ }
217574
+ return inputDefs.findIndex(
217575
+ (input, index) => parseSlotDefinition(input, inputDefs, index).label === arg.oneof
217576
+ );
217577
+ };
217510
217578
  var isRequiredNodeArgValueMissing = (arg, value) => {
217511
217579
  if (isNodeArgOptional(arg)) {
217512
217580
  return false;
@@ -217621,6 +217689,28 @@ var validateNodeArgValue = (params) => {
217621
217689
  }
217622
217690
  return validateNodeArgScalarValue(arg, value, args, validateOptions);
217623
217691
  };
217692
+ var validateNodeArgOneof = (params) => {
217693
+ const { arg, argValue, inputValues, inputDefs } = params;
217694
+ if (!arg.oneof) {
217695
+ return null;
217696
+ }
217697
+ const relatedInputIndex = findNodeArgOneofInputIndex(arg, inputDefs);
217698
+ if (relatedInputIndex < 0) {
217699
+ return {
217700
+ code: "missing-oneof-input",
217701
+ argName: arg.name,
217702
+ inputLabel: arg.oneof
217703
+ };
217704
+ }
217705
+ if (checkOneof(arg, argValue, inputValues?.[relatedInputIndex])) {
217706
+ return null;
217707
+ }
217708
+ return {
217709
+ code: "oneof-conflict",
217710
+ argName: arg.name,
217711
+ inputLabel: arg.oneof
217712
+ };
217713
+ };
217624
217714
 
217625
217715
  // webview/shared/b3build-context.ts
217626
217716
  var unknownNodeDef = {
@@ -217704,6 +217794,10 @@ var formatBuildDiagnostic = (diagnostic) => {
217704
217794
  return `intput field '${diagnostic.label}' is required`;
217705
217795
  case "required-output":
217706
217796
  return `output field '${diagnostic.label}' is required`;
217797
+ case "missing-oneof-input":
217798
+ return `missing oneof input slot '${diagnostic.inputLabel}' for arg '${diagnostic.argName}'`;
217799
+ case "oneof-conflict":
217800
+ return `only one of arg '${diagnostic.argName}' and input '${diagnostic.inputLabel}' can be set`;
217707
217801
  case "invalid-arg-value": {
217708
217802
  const value = JSON.stringify(diagnostic.value);
217709
217803
  switch (diagnostic.expected) {
@@ -217744,14 +217838,15 @@ var checkNodeArg = (data, conf, i, printer) => {
217744
217838
  const diagnostics = validateNodeArgValue({ arg, value, args: data.args ?? {} });
217745
217839
  let hasError = diagnostics.length > 0;
217746
217840
  diagnostics.forEach((diagnostic) => error(formatBuildDiagnostic(diagnostic)));
217747
- if (arg.oneof !== void 0) {
217748
- const idx = conf.input?.findIndex((v) => v.startsWith(arg.oneof)) ?? -1;
217749
- if (!checkOneof(arg, data.args?.[arg.name], data.input?.[idx])) {
217750
- error(
217751
- `only one is allowed for between argument '${arg.name}' and input '${data.input?.[idx]}'`
217752
- );
217753
- hasError = true;
217754
- }
217841
+ const oneofDiagnostic = validateNodeArgOneof({
217842
+ arg,
217843
+ argValue: value,
217844
+ inputValues: data.input,
217845
+ inputDefs: conf.input
217846
+ });
217847
+ if (oneofDiagnostic) {
217848
+ error(formatBuildDiagnostic(oneofDiagnostic));
217849
+ hasError = true;
217755
217850
  }
217756
217851
  return !hasError;
217757
217852
  };
@@ -218524,15 +218619,14 @@ async function runBatchProcess(context, resourceUri) {
218524
218619
  await runBatchProcessWithScript(context, workspaceFile, settingPath, projectRoot, picked[0].fsPath);
218525
218620
  }
218526
218621
  async function runBatchProcessScript(context, resourceUri) {
218527
- const scriptUri = resourceUri?.scheme === "file" ? resourceUri : getActiveFileUri();
218622
+ const resourceIsFile = resourceUri?.scheme === "file";
218623
+ const resourcePath = resourceIsFile ? resourceUri.fsPath : void 0;
218624
+ const explicitScriptUri = resourcePath && isSupportedBatchScriptPath(resourcePath) ? resourceUri : void 0;
218625
+ const activeFileUri = getActiveFileUri();
218626
+ const activeScriptUri = activeFileUri && isSupportedBatchScriptPath(activeFileUri.fsPath) ? activeFileUri : void 0;
218627
+ const scriptUri = explicitScriptUri ?? (!resourceUri ? activeScriptUri : void 0);
218528
218628
  if (!scriptUri) {
218529
- void vscode2.window.showErrorMessage("Select a batch script file first.");
218530
- return;
218531
- }
218532
- if (!isSupportedBatchScriptPath(scriptUri.fsPath)) {
218533
- void vscode2.window.showErrorMessage(
218534
- "Batch script must be a .ts, .mts, .js, or .mjs file."
218535
- );
218629
+ await runBatchProcess(context, resourceUri);
218536
218630
  return;
218537
218631
  }
218538
218632
  const folder = vscode2.workspace.getWorkspaceFolder(scriptUri) ?? vscode2.workspace.workspaceFolders?.[0];
@@ -219928,6 +220022,15 @@ function buildInitMessage(params) {
219928
220022
  };
219929
220023
  }
219930
220024
 
220025
+ // webview/shared/node-overrides.ts
220026
+ var hasOwn = (value, key) => Object.prototype.hasOwnProperty.call(value, key);
220027
+ var getNodeArgOverrideCompareValue = (args, arg) => {
220028
+ if (args && hasOwn(args, arg.name)) {
220029
+ return args[arg.name];
220030
+ }
220031
+ return arg.default;
220032
+ };
220033
+
219931
220034
  // media/locales/en.json
219932
220035
  var en_default = {
219933
220036
  about: "About Behavior3",
@@ -220095,6 +220198,11 @@ var en_default = {
220095
220198
  "editor.newerVersionEditDenied": "This file is created by a newer version of Behavior3({{version}}). Please upgrade to the latest version.",
220096
220199
  "inspector.noActiveDocument": "Open a Behavior3 editor to inspect and edit the active tree.",
220097
220200
  "inspector.embeddedModeNotice": "Inspector is configured to appear inside the Behavior3 editor.",
220201
+ "inspector.embeddedToolbar.build": "Build Behavior Tree",
220202
+ "inspector.embeddedToolbar.toggleEditorMode": "Toggle Editor Mode",
220203
+ "inspector.embeddedToolbar.toggleInspectorNodeJson": "Toggle Raw Node JSON",
220204
+ "inspector.embeddedToolbar.createProject": "Create Project",
220205
+ "inspector.embeddedToolbar.createTree": "Create Behavior Tree",
220098
220206
  "mutation.invalidJsonPath": "Invalid JSON path: {{path}}",
220099
220207
  "mutation.missingSelectedNode": "No selected node is available for this mutation.",
220100
220208
  "mutation.selectedNodeMismatch": "The selected node changed before the mutation was applied.",
@@ -220298,6 +220406,11 @@ var zh_default = {
220298
220406
  "editor.newerVersionEditDenied": "\u6B64\u6587\u4EF6\u7531\u65B0\u7248\u672C Behavior3({{version}}) \u521B\u5EFA\uFF0C\u8BF7\u5347\u7EA7\u5230\u6700\u65B0\u7248\u672C\u540E\u518D\u7F16\u8F91\u3002",
220299
220407
  "inspector.noActiveDocument": "\u6253\u5F00\u4E00\u4E2A Behavior3 \u7F16\u8F91\u5668\u540E\uFF0C\u8FD9\u91CC\u4F1A\u663E\u793A\u5F53\u524D\u884C\u4E3A\u6811\u7684 Inspector\uFF0C\u5E76\u652F\u6301\u76F4\u63A5\u7F16\u8F91\u3002",
220300
220408
  "inspector.embeddedModeNotice": "Inspector \u5F53\u524D\u914D\u7F6E\u4E3A\u5728 Behavior3 \u7F16\u8F91\u5668\u5185\u90E8\u663E\u793A\u3002",
220409
+ "inspector.embeddedToolbar.build": "\u6784\u5EFA\u884C\u4E3A\u6811",
220410
+ "inspector.embeddedToolbar.toggleEditorMode": "\u5207\u6362\u7F16\u8F91\u5668\u6A21\u5F0F",
220411
+ "inspector.embeddedToolbar.toggleInspectorNodeJson": "\u5207\u6362\u539F\u59CB\u8282\u70B9 JSON",
220412
+ "inspector.embeddedToolbar.createProject": "\u65B0\u5EFA\u9879\u76EE",
220413
+ "inspector.embeddedToolbar.createTree": "\u65B0\u5EFA\u884C\u4E3A\u6811",
220301
220414
  "mutation.invalidJsonPath": "\u65E0\u6548\u7684 JSON \u8DEF\u5F84: {{path}}",
220302
220415
  "mutation.missingSelectedNode": "\u5F53\u524D\u6CA1\u6709\u53EF\u7528\u4E8E\u63D0\u4EA4\u6B64\u4FEE\u6539\u7684\u9009\u4E2D\u8282\u70B9\u3002",
220303
220416
  "mutation.selectedNodeMismatch": "\u5F53\u524D\u9009\u4E2D\u8282\u70B9\u5DF2\u53D8\u5316\uFF0C\u8BF7\u91CD\u8BD5\u3002",
@@ -220448,8 +220561,8 @@ var computeNodeOverride = (original, edited, def) => {
220448
220561
  if (def?.args?.length) {
220449
220562
  const diffArgs = {};
220450
220563
  for (const arg of def.args) {
220451
- const originalValue = original.args?.[arg.name];
220452
- const editedValue = edited.args?.[arg.name];
220564
+ const originalValue = getNodeArgOverrideCompareValue(original.args, arg);
220565
+ const editedValue = getNodeArgOverrideCompareValue(edited.args, arg);
220453
220566
  if (!isJsonEqual(originalValue, editedValue)) {
220454
220567
  diffArgs[arg.name] = editedValue;
220455
220568
  }
@@ -221243,6 +221356,9 @@ function createSessionDispatcher({
221243
221356
  buildScriptDebug: msg.buildScriptDebug
221244
221357
  }).then(void 0, logAsyncRuntimeError("command:behavior3.build"));
221245
221358
  return;
221359
+ case "runInspectorCommand":
221360
+ void vscode14.commands.executeCommand(msg.command).then(void 0, logAsyncRuntimeError(`command:${msg.command}`));
221361
+ return;
221246
221362
  case "validateNodeChecks":
221247
221363
  await handleValidateNodeChecksMessage(msg, reply);
221248
221364
  return;
@@ -222954,11 +223070,154 @@ function createLogOutputChannelLogger(out) {
222954
223070
  };
222955
223071
  }
222956
223072
 
223073
+ // src/script-scaffold.ts
223074
+ var SCRIPT_FILE_EXTENSION_RE = /\.(ts|mts|js|mjs)$/i;
223075
+ var INVALID_FILE_NAME_RE = /[\/\\:*?"<>|]/;
223076
+ var DEFAULT_BASE_NAMES = {
223077
+ build: "build",
223078
+ batch: "batch",
223079
+ checker: "checker"
223080
+ };
223081
+ function getScriptScaffoldDefaultBaseName(kind) {
223082
+ return DEFAULT_BASE_NAMES[kind];
223083
+ }
223084
+ function normalizeScriptScaffoldBaseName(value) {
223085
+ return value.trim();
223086
+ }
223087
+ function validateScriptScaffoldBaseName(value) {
223088
+ const normalized = normalizeScriptScaffoldBaseName(value);
223089
+ if (!normalized) {
223090
+ return "Name cannot be empty";
223091
+ }
223092
+ if (INVALID_FILE_NAME_RE.test(normalized)) {
223093
+ return "Name contains invalid characters";
223094
+ }
223095
+ if (SCRIPT_FILE_EXTENSION_RE.test(normalized)) {
223096
+ return "Enter the name without an extension";
223097
+ }
223098
+ return null;
223099
+ }
223100
+ function createScriptScaffoldFileName(baseName) {
223101
+ return `${normalizeScriptScaffoldBaseName(baseName)}.ts`;
223102
+ }
223103
+ function createScriptScaffoldContent(kind, baseName) {
223104
+ switch (kind) {
223105
+ case "build":
223106
+ return createBuildScriptContent(baseName);
223107
+ case "batch":
223108
+ return createBatchScriptContent(baseName);
223109
+ case "checker":
223110
+ return createCheckerScriptContent(baseName);
223111
+ }
223112
+ }
223113
+ function createBuildScriptContent(baseName) {
223114
+ const className = ensureSuffix(toPascalIdentifier(baseName), "Script");
223115
+ return [
223116
+ 'import type { BuildEnv, BuildScript, NodeData, TreeData } from "vscode-behavior3/build";',
223117
+ "",
223118
+ "@behavior3.build",
223119
+ `export class ${className} implements BuildScript {`,
223120
+ " constructor(private readonly env: BuildEnv) {}",
223121
+ "",
223122
+ " onProcessTree(tree: TreeData, _path: string, _errors: string[]) {",
223123
+ " return tree;",
223124
+ " }",
223125
+ "",
223126
+ " onProcessNode(node: NodeData, _errors: string[]) {",
223127
+ " return node;",
223128
+ " }",
223129
+ "",
223130
+ ' onComplete(status: "success" | "failure") {',
223131
+ " this.env.logger.info(`build ${status}`);",
223132
+ " }",
223133
+ "}",
223134
+ ""
223135
+ ].join("\n");
223136
+ }
223137
+ function createBatchScriptContent(baseName) {
223138
+ const className = ensureSuffix(toPascalIdentifier(baseName), "Script");
223139
+ return [
223140
+ 'import type { BatchScript, BuildEnv, NodeData, TreeData } from "vscode-behavior3/build";',
223141
+ "",
223142
+ "@behavior3.batch",
223143
+ `export class ${className} implements BatchScript {`,
223144
+ " constructor(private readonly env: BuildEnv) {}",
223145
+ "",
223146
+ " shouldUpgradeTree(_path: string, _tree: TreeData) {",
223147
+ " return false;",
223148
+ " }",
223149
+ "",
223150
+ " onProcessTree(tree: TreeData, _path: string, _errors: string[]) {",
223151
+ " return tree;",
223152
+ " }",
223153
+ "",
223154
+ " onProcessNode(node: NodeData, _errors: string[]) {",
223155
+ " return node;",
223156
+ " }",
223157
+ "",
223158
+ ' onComplete(status: "success" | "failure") {',
223159
+ " this.env.logger.info(`batch ${status}`);",
223160
+ " }",
223161
+ "}",
223162
+ ""
223163
+ ].join("\n");
223164
+ }
223165
+ function createCheckerScriptContent(baseName) {
223166
+ const className = ensureSuffix(toPascalIdentifier(baseName), "Checker");
223167
+ const checkerName = toCheckerRegistrationName(baseName);
223168
+ return [
223169
+ 'import type { NodeArgCheckContext } from "vscode-behavior3/build";',
223170
+ "",
223171
+ `@behavior3.check("${checkerName}")`,
223172
+ `export class ${className} {`,
223173
+ " validate(value: unknown, ctx: NodeArgCheckContext) {",
223174
+ ' if (value === undefined || value === null || value === "") {',
223175
+ " return;",
223176
+ " }",
223177
+ ' if (typeof value !== "number") {',
223178
+ " return `${ctx.argName} must be a number`;",
223179
+ " }",
223180
+ " if (value <= 0) {",
223181
+ " return `${ctx.argName} must be greater than 0`;",
223182
+ " }",
223183
+ " }",
223184
+ "}",
223185
+ ""
223186
+ ].join("\n");
223187
+ }
223188
+ function toPascalIdentifier(value) {
223189
+ const source = normalizeScriptScaffoldBaseName(value).replace(SCRIPT_FILE_EXTENSION_RE, "");
223190
+ const tokens = source.match(/[A-Za-z0-9]+/g) ?? [];
223191
+ const joined = tokens.map((token) => token.charAt(0).toUpperCase() + token.slice(1)).join("");
223192
+ if (!joined) {
223193
+ return "Generated";
223194
+ }
223195
+ if (/^[A-Za-z_$]/.test(joined)) {
223196
+ return joined;
223197
+ }
223198
+ return `Generated${joined}`;
223199
+ }
223200
+ function ensureSuffix(value, suffix) {
223201
+ return value.toLowerCase().endsWith(suffix.toLowerCase()) ? value : `${value}${suffix}`;
223202
+ }
223203
+ function toCheckerRegistrationName(value) {
223204
+ const normalized = normalizeScriptScaffoldBaseName(value).replace(SCRIPT_FILE_EXTENSION_RE, "").toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
223205
+ return normalized || "checker";
223206
+ }
223207
+
222957
223208
  // src/extension.ts
222958
223209
  var getVSCodeTheme2 = () => {
222959
223210
  const kind = vscode23.window.activeColorTheme.kind;
222960
223211
  return kind === vscode23.ColorThemeKind.Light || kind === vscode23.ColorThemeKind.HighContrastLight ? "light" : "dark";
222961
223212
  };
223213
+ var getActiveBehaviorTreeEditorUri = () => {
223214
+ const tab = vscode23.window.tabGroups.activeTabGroup.activeTab;
223215
+ const input = tab?.input;
223216
+ if (!(input instanceof vscode23.TabInputCustom) || input.viewType !== TreeEditorProvider.viewType) {
223217
+ return null;
223218
+ }
223219
+ return input.uri;
223220
+ };
222962
223221
  function activate(context) {
222963
223222
  const config = vscode23.workspace.getConfiguration("behavior3");
222964
223223
  const inspectorMode = config.get("inspectorMode", "sidebar");
@@ -223006,27 +223265,35 @@ function activate(context) {
223006
223265
  inspectorCoordinator.setActiveDocument(documentUri);
223007
223266
  };
223008
223267
  syncActiveInspectorDocument();
223009
- context.subscriptions.push(vscode23.window.tabGroups.onDidChangeTabs(() => {
223010
- syncActiveInspectorDocument();
223011
- }));
223012
- context.subscriptions.push(vscode23.window.tabGroups.onDidChangeTabGroups(() => {
223013
- syncActiveInspectorDocument();
223014
- }));
223015
- context.subscriptions.push(vscode23.window.onDidChangeActiveColorTheme(() => {
223016
- inspectorCoordinator.setTheme(getVSCodeTheme2());
223017
- }));
223018
- context.subscriptions.push(vscode23.workspace.onDidChangeConfiguration((event) => {
223019
- if (!event.affectsConfiguration("behavior3.inspectorMode")) {
223020
- return;
223021
- }
223022
- const nextInspectorMode = vscode23.workspace.getConfiguration("behavior3").get("inspectorMode", "sidebar");
223023
- inspectorCoordinator.setInspectorMode(nextInspectorMode);
223024
- void vscode23.commands.executeCommand(
223025
- "setContext",
223026
- "behavior3.inspectorSidebarMode",
223027
- nextInspectorMode === "sidebar"
223028
- );
223029
- }));
223268
+ context.subscriptions.push(
223269
+ vscode23.window.tabGroups.onDidChangeTabs(() => {
223270
+ syncActiveInspectorDocument();
223271
+ })
223272
+ );
223273
+ context.subscriptions.push(
223274
+ vscode23.window.tabGroups.onDidChangeTabGroups(() => {
223275
+ syncActiveInspectorDocument();
223276
+ })
223277
+ );
223278
+ context.subscriptions.push(
223279
+ vscode23.window.onDidChangeActiveColorTheme(() => {
223280
+ inspectorCoordinator.setTheme(getVSCodeTheme2());
223281
+ })
223282
+ );
223283
+ context.subscriptions.push(
223284
+ vscode23.workspace.onDidChangeConfiguration((event) => {
223285
+ if (!event.affectsConfiguration("behavior3.inspectorMode")) {
223286
+ return;
223287
+ }
223288
+ const nextInspectorMode = vscode23.workspace.getConfiguration("behavior3").get("inspectorMode", "sidebar");
223289
+ inspectorCoordinator.setInspectorMode(nextInspectorMode);
223290
+ void vscode23.commands.executeCommand(
223291
+ "setContext",
223292
+ "behavior3.inspectorSidebarMode",
223293
+ nextInspectorMode === "sidebar"
223294
+ );
223295
+ })
223296
+ );
223030
223297
  const autoCheckedJsonWhileOpen = /* @__PURE__ */ new Set();
223031
223298
  const autoOpeningJsonUris = /* @__PURE__ */ new Set();
223032
223299
  const skipNextAutoOpenUris = /* @__PURE__ */ new Set();
@@ -223070,14 +223337,35 @@ function activate(context) {
223070
223337
  );
223071
223338
  context.subscriptions.push(
223072
223339
  vscode23.commands.registerCommand("behavior3.toggleInspectorNodeJson", async () => {
223340
+ const activeEditorUri = getActiveBehaviorTreeEditorUri();
223341
+ const activeInspectorMode = vscode23.workspace.getConfiguration("behavior3").get("inspectorMode", "sidebar");
223342
+ if (activeInspectorMode === "embedded" && activeEditorUri) {
223343
+ TreeEditorProvider.postMessageToDocument(activeEditorUri.toString(), {
223344
+ type: "toggleInspectorNodeJson"
223345
+ });
223346
+ return;
223347
+ }
223073
223348
  inspectorCoordinator.toggleNodeJsonView();
223074
223349
  })
223075
223350
  );
223076
223351
  context.subscriptions.push(
223077
- vscode23.commands.registerCommand("behavior3.batchProcess", async (uri) => {
223078
- await runBatchProcess(context, uri);
223352
+ vscode23.commands.registerCommand("behavior3.createBuildScript", async (uri) => {
223353
+ await createBehavior3Script("build", uri);
223079
223354
  })
223080
223355
  );
223356
+ context.subscriptions.push(
223357
+ vscode23.commands.registerCommand("behavior3.createBatchScript", async (uri) => {
223358
+ await createBehavior3Script("batch", uri);
223359
+ })
223360
+ );
223361
+ context.subscriptions.push(
223362
+ vscode23.commands.registerCommand(
223363
+ "behavior3.createCheckerScript",
223364
+ async (uri) => {
223365
+ await createBehavior3Script("checker", uri);
223366
+ }
223367
+ )
223368
+ );
223081
223369
  context.subscriptions.push(
223082
223370
  vscode23.commands.registerCommand(
223083
223371
  "behavior3.runBatchProcessScript",
@@ -223292,6 +223580,62 @@ function activate(context) {
223292
223580
  }
223293
223581
  function deactivate() {
223294
223582
  }
223583
+ async function createBehavior3Script(kind, uri) {
223584
+ const folderUri = await resolveFolderTargetUri(uri);
223585
+ if (!folderUri) {
223586
+ void vscode23.window.showErrorMessage("Please open a workspace folder first.");
223587
+ return;
223588
+ }
223589
+ const baseName = await vscode23.window.showInputBox({
223590
+ prompt: `Enter ${getScriptScaffoldPromptLabel(kind)} file name (without extension)`,
223591
+ placeHolder: getScriptScaffoldDefaultBaseName(kind),
223592
+ value: getScriptScaffoldDefaultBaseName(kind),
223593
+ validateInput: validateScriptScaffoldBaseName
223594
+ });
223595
+ if (!baseName) {
223596
+ return;
223597
+ }
223598
+ const normalizedBaseName = normalizeScriptScaffoldBaseName(baseName);
223599
+ const fileName = createScriptScaffoldFileName(normalizedBaseName);
223600
+ const fileUri = vscode23.Uri.file(path13.join(folderUri.fsPath, fileName));
223601
+ if (fs8.existsSync(fileUri.fsPath)) {
223602
+ void vscode23.window.showErrorMessage(`File already exists: ${fileName}`);
223603
+ return;
223604
+ }
223605
+ try {
223606
+ await fs8.promises.writeFile(
223607
+ fileUri.fsPath,
223608
+ createScriptScaffoldContent(kind, normalizedBaseName),
223609
+ "utf-8"
223610
+ );
223611
+ await vscode23.window.showTextDocument(fileUri);
223612
+ } catch (e) {
223613
+ void vscode23.window.showErrorMessage(
223614
+ `Failed to create file: ${e instanceof Error ? e.message : e}`
223615
+ );
223616
+ }
223617
+ }
223618
+ async function resolveFolderTargetUri(uri) {
223619
+ if (uri?.scheme === "file") {
223620
+ try {
223621
+ const stat = await vscode23.workspace.fs.stat(uri);
223622
+ return stat.type === vscode23.FileType.Directory ? uri : vscode23.Uri.file(path13.dirname(uri.fsPath));
223623
+ } catch {
223624
+ return void 0;
223625
+ }
223626
+ }
223627
+ return vscode23.workspace.workspaceFolders?.[0]?.uri;
223628
+ }
223629
+ function getScriptScaffoldPromptLabel(kind) {
223630
+ switch (kind) {
223631
+ case "build":
223632
+ return "build script";
223633
+ case "batch":
223634
+ return "batch script";
223635
+ case "checker":
223636
+ return "checker script";
223637
+ }
223638
+ }
223295
223639
  async function tryAutoOpenBehaviorEditor(uri, autoCheckedJsonWhileOpen, autoOpeningJsonUris, skipNextAutoOpenUris) {
223296
223640
  if (uri.scheme !== "file") {
223297
223641
  return;