@neocompose/cli 0.67.1 → 0.67.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/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.67.3] - 2026-10-04
|
|
4
|
+
|
|
5
|
+
- `neo pull --force` and `neo pull --reset` keep the dialogue source names the server stores. Previously both regenerated names, so a force pull renamed bindings like `npc` to `AdoringFan` without rewriting the code that used them, left dozens of unrequested changes in `neo status`, and failed `neo push --dry-run` with "Unknown identifier".
|
|
6
|
+
- `neo pull --regenerate-source-names` only replaces generated defaults such as `Value_1a2b3c4d5e6f`, `NeoFunction_…`, and `Conditions1`. Names you chose are kept. When it renames a binding, it rewrites references to it in dialogue functions, conditions, actions, and text variables. A node that re-links a dialogue value now uses the dialogue's name for it, so a function shared by several nodes reads the same in each.
|
|
7
|
+
|
|
8
|
+
## [0.67.2] - 2026-10-04
|
|
9
|
+
|
|
10
|
+
- `neo pull --force` reads the workspace layout against the server's records instead of the baseline it is about to replace. Previously a baseline pulled before 0.67.0 failed with "Cannot recover local initializer placement before reset" in any workspace with local values, so the `--force` remedy 0.67.1 suggests could not run.
|
|
11
|
+
- Pull writes `float` setting bounds as the shortest decimal that reads back as the stored float, so `@settings(max: 23.99)` stays `23.99`. Previously it wrote `23.989999771118164`.
|
|
12
|
+
|
|
3
13
|
## [0.67.1] - 2026-10-04
|
|
4
14
|
|
|
5
15
|
- Pull adopts records the server only recompiled into `.neo/state.json` before it reads local sources, even when the same pull also merges authored changes. Previously one authored change anywhere in the pull sent every recompiled record through the merge, which read the stale baseline and failed.
|
package/README.md
CHANGED
|
@@ -479,7 +479,7 @@ authorization boundary.
|
|
|
479
479
|
| `logout [--api <url>]` | Delete the stored credential for one API origin and revoke its session. |
|
|
480
480
|
| `init --project <id> [--version <id>]` | Create a format-4 working copy and perform its first reset pull. |
|
|
481
481
|
| `doctor` | Validate format/compiler/editor/source/file contracts; no .NET discovery. |
|
|
482
|
-
| `pull [--force\|--reset] [--regenerate-source-names]` | Merge remote changes or regenerate canonical source
|
|
482
|
+
| `pull [--force\|--reset] [--regenerate-source-names]` | Merge remote changes or regenerate canonical source and binaries. |
|
|
483
483
|
| `status [--json]` | Compile source and summarize semantic records and upload intent. |
|
|
484
484
|
| `diff [--json]` | Show semantic records, spans, digests, and upload intent. |
|
|
485
485
|
| `push [--dry-run] [--accept-bump] [--no-verify]` | Validate or commit one atomic compare-and-swap transaction. |
|
|
@@ -514,9 +514,9 @@ security boundary.
|
|
|
514
514
|
|
|
515
515
|
## Regenerating dialogue source names
|
|
516
516
|
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
517
|
+
Every pull, including `--force` and `--reset`, keeps the dialogue source names
|
|
518
|
+
the server stores. To replace generated defaults such as `Value_1a2b3c4d5e6f`,
|
|
519
|
+
`NeoFunction_…`, or `Conditions1` with names derived from the editor, run:
|
|
520
520
|
|
|
521
521
|
```sh
|
|
522
522
|
neo pull --regenerate-source-names
|
|
@@ -524,11 +524,12 @@ neo status
|
|
|
524
524
|
neo push --dry-run
|
|
525
525
|
```
|
|
526
526
|
|
|
527
|
-
|
|
528
|
-
|
|
527
|
+
Names you chose are kept. When a binding is renamed, code that refers to it is
|
|
528
|
+
rewritten to match. Custom linked values prefer a non-empty string member named
|
|
529
|
+
`Name`, using PascalCase at dialogue scope and camelCase inside nodes.
|
|
529
530
|
|
|
530
|
-
The
|
|
531
|
-
|
|
531
|
+
The pull leaves the regenerated names as local changes. IDs are unchanged, and
|
|
532
|
+
nothing is written to the server until `neo push` succeeds.
|
|
532
533
|
|
|
533
534
|
## Packaging
|
|
534
535
|
|
package/dist/neo.mjs
CHANGED
|
@@ -30114,7 +30114,7 @@ var init_registry = __esm({
|
|
|
30114
30114
|
"../packages/manifest/schema-contract/registry.mjs"() {
|
|
30115
30115
|
"use strict";
|
|
30116
30116
|
PROJECT_SCHEMA_CONTRACT = Object.freeze({
|
|
30117
|
-
cliVersion: "0.67.
|
|
30117
|
+
cliVersion: "0.67.3",
|
|
30118
30118
|
projectFileUploadBatchSize: 32,
|
|
30119
30119
|
documentRecords: {
|
|
30120
30120
|
member: {
|
|
@@ -52644,14 +52644,17 @@ function renderExtendsGenericBindings(context, schemaClass2, base) {
|
|
|
52644
52644
|
});
|
|
52645
52645
|
return `<${argumentsValue.join(", ")}>`;
|
|
52646
52646
|
}
|
|
52647
|
+
function settingsBound(value) {
|
|
52648
|
+
return typeof value === "number" ? formatNeoNumber(value) : value;
|
|
52649
|
+
}
|
|
52647
52650
|
function memberSettings(context, member) {
|
|
52648
52651
|
const settings = [];
|
|
52649
52652
|
if (member.kind === "string") {
|
|
52650
52653
|
if (!member.localizable) settings.push("format: .Plain");
|
|
52651
52654
|
if (member.searchKey) settings.push("searchBy: .MemberKey");
|
|
52652
52655
|
} else if (member.kind === "int" || member.kind === "float" || member.kind === "decimal") {
|
|
52653
|
-
if (member.min !== null) settings.push(`min: ${member.min}`);
|
|
52654
|
-
if (member.max !== null) settings.push(`max: ${member.max}`);
|
|
52656
|
+
if (member.min !== null) settings.push(`min: ${settingsBound(member.min)}`);
|
|
52657
|
+
if (member.max !== null) settings.push(`max: ${settingsBound(member.max)}`);
|
|
52655
52658
|
if (member.kind !== "int" && member.decimalPoints !== null) {
|
|
52656
52659
|
settings.push(`decimalPoints: ${member.decimalPoints}`);
|
|
52657
52660
|
}
|
|
@@ -59688,6 +59691,23 @@ function rewriteNeoScriptThisReceiver(source, alias) {
|
|
|
59688
59691
|
}
|
|
59689
59692
|
return result + source.slice(cursor);
|
|
59690
59693
|
}
|
|
59694
|
+
function renameNeoScriptIdentifiers(source, renames) {
|
|
59695
|
+
if (renames.size === 0) return source;
|
|
59696
|
+
let result = "";
|
|
59697
|
+
let cursor = 0;
|
|
59698
|
+
let previous;
|
|
59699
|
+
for (const token of lex(source).tokens) {
|
|
59700
|
+
if (token.kind === "comment") continue;
|
|
59701
|
+
const isMemberName = previous?.text === "." || previous?.text === "?.";
|
|
59702
|
+
previous = token;
|
|
59703
|
+
if (token.kind !== "identifier" || isMemberName) continue;
|
|
59704
|
+
const renamed = renames.get(token.text);
|
|
59705
|
+
if (renamed === void 0) continue;
|
|
59706
|
+
result += source.slice(cursor, token.start) + renamed;
|
|
59707
|
+
cursor = token.end;
|
|
59708
|
+
}
|
|
59709
|
+
return result + source.slice(cursor);
|
|
59710
|
+
}
|
|
59691
59711
|
var init_neoscript_source_rewrite = __esm({
|
|
59692
59712
|
"src/project-source/neoscript-source-rewrite.ts"() {
|
|
59693
59713
|
"use strict";
|
|
@@ -59715,58 +59735,116 @@ function regenerateDialogueSourceNamesV4(records2) {
|
|
|
59715
59735
|
live.filter((record6) => record6.recordKind === "dialogue-node").map((record6) => ({ record: record6, data: recordData2(record6) })),
|
|
59716
59736
|
({ data }) => stringField(data, "dialogueId")
|
|
59717
59737
|
);
|
|
59738
|
+
const keptClassNames = claimKeptNames(
|
|
59739
|
+
typeNames,
|
|
59740
|
+
dialogues.map((record6) => [record6.recordId, recordData2(record6).sourceName])
|
|
59741
|
+
);
|
|
59718
59742
|
dialogues.forEach((dialogueRecord, dialogueIndex) => {
|
|
59719
59743
|
const dialogue = recordData2(dialogueRecord);
|
|
59720
59744
|
const dialogueId = dialogueRecord.recordId;
|
|
59721
|
-
const className = typeNames.claim(
|
|
59745
|
+
const className = keptClassNames.get(dialogueId) ?? typeNames.claim(
|
|
59722
59746
|
dialogueSourceNameFromDisplayName(
|
|
59723
59747
|
optionalString2(dialogue.name),
|
|
59724
59748
|
`Dialogue${dialogueIndex + 1}`
|
|
59725
59749
|
)
|
|
59726
59750
|
);
|
|
59727
|
-
const nodeEntries = nodesByDialogue.get(dialogueId) ?? []
|
|
59751
|
+
const nodeEntries = (nodesByDialogue.get(dialogueId) ?? []).map(
|
|
59752
|
+
({ record: record6, data }) => ({
|
|
59753
|
+
record: record6,
|
|
59754
|
+
data,
|
|
59755
|
+
links: linkedValueRecords(data.linkedValues, "Dialogue-node")
|
|
59756
|
+
})
|
|
59757
|
+
);
|
|
59728
59758
|
const nodes = nodeEntries.map(({ data }) => data);
|
|
59729
|
-
const
|
|
59759
|
+
const bodyNodes = orderedBodyNodes(
|
|
59760
|
+
nodes,
|
|
59761
|
+
optionalString2(dialogue.triggerNodeId)
|
|
59762
|
+
);
|
|
59763
|
+
const links = linkedValueRecords(dialogue.linkedValues, "Dialogue");
|
|
59764
|
+
const functions = sourceFunctionUses(nodes);
|
|
59730
59765
|
const classMembers = new DialogueSourceNameAllocator(["Trigger"]);
|
|
59731
|
-
const
|
|
59732
|
-
|
|
59733
|
-
|
|
59766
|
+
const keptMembers = claimKeptNames(classMembers, [
|
|
59767
|
+
...bodyNodes.map(
|
|
59768
|
+
(node) => [`node:${stringField(node, "id")}`, node.sourceName]
|
|
59769
|
+
),
|
|
59770
|
+
...links.map(
|
|
59771
|
+
(link) => [`value:${stringField(link, "valueId")}`, link.sourceName]
|
|
59772
|
+
),
|
|
59773
|
+
...[...functions].map(
|
|
59774
|
+
([id2, fn]) => [`function:${id2}`, fn.existingName]
|
|
59775
|
+
)
|
|
59776
|
+
]);
|
|
59777
|
+
const valueIdsByOldName = /* @__PURE__ */ new Map();
|
|
59778
|
+
const ambiguousOldNames = /* @__PURE__ */ new Set();
|
|
59779
|
+
for (const { links: nodeLinks } of nodeEntries) {
|
|
59780
|
+
for (const link of nodeLinks) {
|
|
59781
|
+
const kept = keptSourceName(link.sourceName);
|
|
59782
|
+
if (kept !== null) classMembers.reserve(kept);
|
|
59783
|
+
const oldName = optionalString2(link.sourceName);
|
|
59784
|
+
if (oldName === null) continue;
|
|
59785
|
+
const valueId = stringField(link, "valueId");
|
|
59786
|
+
const seen = valueIdsByOldName.get(oldName);
|
|
59787
|
+
if (seen === void 0) valueIdsByOldName.set(oldName, valueId);
|
|
59788
|
+
else if (seen !== valueId) ambiguousOldNames.add(oldName);
|
|
59789
|
+
}
|
|
59790
|
+
}
|
|
59791
|
+
const nodeNames = regeneratedNodeNames(
|
|
59792
|
+
bodyNodes,
|
|
59734
59793
|
classMembers,
|
|
59735
|
-
|
|
59736
|
-
"pascal"
|
|
59794
|
+
keptMembers
|
|
59737
59795
|
);
|
|
59738
|
-
const
|
|
59739
|
-
|
|
59740
|
-
|
|
59741
|
-
|
|
59742
|
-
|
|
59796
|
+
const dialogueLinks = regenerateBindingSourceNames(
|
|
59797
|
+
links,
|
|
59798
|
+
classMembers,
|
|
59799
|
+
keptMembers,
|
|
59800
|
+
placements
|
|
59743
59801
|
);
|
|
59744
|
-
const functionNames =
|
|
59745
|
-
|
|
59746
|
-
|
|
59747
|
-
|
|
59802
|
+
const functionNames = allocateSourceFunctionNames(
|
|
59803
|
+
functions,
|
|
59804
|
+
classMembers,
|
|
59805
|
+
keptMembers
|
|
59748
59806
|
);
|
|
59749
|
-
|
|
59750
|
-
|
|
59751
|
-
|
|
59807
|
+
const namesByOldName = /* @__PURE__ */ new Map();
|
|
59808
|
+
const dialogueNamesByValueId = /* @__PURE__ */ new Map();
|
|
59809
|
+
links.forEach((link, index) => {
|
|
59810
|
+
const name = stringField(dialogueLinks[index], "sourceName");
|
|
59811
|
+
dialogueNamesByValueId.set(stringField(link, "valueId"), name);
|
|
59812
|
+
const oldName = optionalString2(link.sourceName);
|
|
59813
|
+
if (oldName !== null) namesByOldName.set(oldName, name);
|
|
59752
59814
|
});
|
|
59753
|
-
|
|
59754
|
-
const nodeId = stringField(data, "id");
|
|
59755
|
-
const nodeName = nodeNames.get(nodeId) ?? "Trigger";
|
|
59756
|
-
const nodeLinks = regenerateNodeBindingSourceNames(
|
|
59757
|
-
data.linkedValues,
|
|
59758
|
-
placements,
|
|
59759
|
-
dialogueBindingNames
|
|
59760
|
-
);
|
|
59815
|
+
const nextNodes = nodeEntries.map(({ record: record6, data, links: nodeLinks }) => {
|
|
59761
59816
|
let nextNode = {
|
|
59762
59817
|
...data,
|
|
59763
|
-
sourceName:
|
|
59764
|
-
linkedValues:
|
|
59818
|
+
sourceName: nodeNames.get(stringField(data, "id")) ?? "Trigger",
|
|
59819
|
+
linkedValues: regenerateNodeBindingSourceNames(
|
|
59820
|
+
nodeLinks,
|
|
59821
|
+
classMembers,
|
|
59822
|
+
placements,
|
|
59823
|
+
dialogueNamesByValueId,
|
|
59824
|
+
ambiguousOldNames,
|
|
59825
|
+
namesByOldName
|
|
59826
|
+
)
|
|
59765
59827
|
};
|
|
59766
59828
|
if (data.type === 1) nextNode = regenerateTextChildren(nextNode);
|
|
59767
59829
|
if (data.type === 3) nextNode = regenerateConditionOutcomes(nextNode);
|
|
59768
|
-
|
|
59769
|
-
|
|
59830
|
+
return { record: record6, data: nextNode };
|
|
59831
|
+
});
|
|
59832
|
+
const renames = new Map(
|
|
59833
|
+
[...namesByOldName].filter(([oldName, name]) => oldName !== name)
|
|
59834
|
+
);
|
|
59835
|
+
result.set(recordKey(dialogueRecord), {
|
|
59836
|
+
...dialogueRecord,
|
|
59837
|
+
data: rewriteSourceReferences(
|
|
59838
|
+
{ ...dialogue, sourceName: className, linkedValues: dialogueLinks },
|
|
59839
|
+
functionNames,
|
|
59840
|
+
renames
|
|
59841
|
+
)
|
|
59842
|
+
});
|
|
59843
|
+
for (const { record: record6, data } of nextNodes) {
|
|
59844
|
+
result.set(recordKey(record6), {
|
|
59845
|
+
...record6,
|
|
59846
|
+
data: rewriteSourceReferences(data, functionNames, renames)
|
|
59847
|
+
});
|
|
59770
59848
|
}
|
|
59771
59849
|
});
|
|
59772
59850
|
for (const record6 of live.filter(
|
|
@@ -59777,23 +59855,54 @@ function regenerateDialogueSourceNamesV4(records2) {
|
|
|
59777
59855
|
if (functionNames.size === 0) continue;
|
|
59778
59856
|
result.set(recordKey(record6), {
|
|
59779
59857
|
...record6,
|
|
59780
|
-
data:
|
|
59858
|
+
data: rewriteSourceReferences(data, functionNames, /* @__PURE__ */ new Map())
|
|
59781
59859
|
});
|
|
59782
59860
|
}
|
|
59783
59861
|
return result;
|
|
59784
59862
|
}
|
|
59785
|
-
function
|
|
59863
|
+
function claimKeptNames(allocator, entries) {
|
|
59864
|
+
const result = /* @__PURE__ */ new Map();
|
|
59865
|
+
for (const [key, name] of entries) {
|
|
59866
|
+
if (result.has(key)) continue;
|
|
59867
|
+
const kept = keptSourceName(name);
|
|
59868
|
+
if (kept !== null) result.set(key, allocator.claim(kept));
|
|
59869
|
+
}
|
|
59870
|
+
return result;
|
|
59871
|
+
}
|
|
59872
|
+
function keptSourceName(value) {
|
|
59873
|
+
if (!isDialogueSourceIdentifier(value)) return null;
|
|
59874
|
+
return isDefaultDialogueSourceName(value) ? null : value;
|
|
59875
|
+
}
|
|
59876
|
+
function isDefaultDialogueSourceName(value) {
|
|
59877
|
+
return /^(?:Dialogue|Node|Option|Outcome|Value)_[0-9a-f_]{8,}$/iu.test(value) || /^NeoFunction_[0-9a-f]{16,}$/iu.test(value) || /^(?:Actions?|Conditions?|Dialogue|Node|Option|Outcome|Text|TextValue|Value)[0-9]+(?:_[0-9]+)?$/iu.test(
|
|
59878
|
+
value
|
|
59879
|
+
);
|
|
59880
|
+
}
|
|
59881
|
+
function linkedValueRecords(rawLinks, owner) {
|
|
59882
|
+
if (!Array.isArray(rawLinks)) return [];
|
|
59883
|
+
return rawLinks.map((rawLink, index) => {
|
|
59884
|
+
if (!isObjectRecord2(rawLink)) {
|
|
59885
|
+
throw new Error(`${owner} linked value ${index} is not an object.`);
|
|
59886
|
+
}
|
|
59887
|
+
if (typeof rawLink.valueId !== "string") {
|
|
59888
|
+
throw new Error(`${owner} linked value ${index} has no valueId.`);
|
|
59889
|
+
}
|
|
59890
|
+
return rawLink;
|
|
59891
|
+
});
|
|
59892
|
+
}
|
|
59893
|
+
function regeneratedNodeNames(bodyNodes, allocator, kept) {
|
|
59786
59894
|
const result = /* @__PURE__ */ new Map();
|
|
59787
|
-
if (triggerId !== null) result.set(triggerId, "Trigger");
|
|
59788
|
-
const bodyNodes = orderedBodyNodes(nodes, triggerId);
|
|
59789
59895
|
const descriptors = bodyNodes.map((node) => ({
|
|
59790
|
-
node,
|
|
59791
59896
|
id: stringField(node, "id"),
|
|
59792
59897
|
displayName: optionalMeaningfulString(node.name),
|
|
59793
59898
|
kind: dialogueNodeKindName(node.type)
|
|
59794
59899
|
}));
|
|
59795
59900
|
for (const descriptor of descriptors) {
|
|
59796
|
-
|
|
59901
|
+
const keptName = kept.get(`node:${descriptor.id}`);
|
|
59902
|
+
if (keptName !== void 0) result.set(descriptor.id, keptName);
|
|
59903
|
+
}
|
|
59904
|
+
for (const descriptor of descriptors) {
|
|
59905
|
+
if (result.has(descriptor.id) || descriptor.displayName === null) continue;
|
|
59797
59906
|
result.set(
|
|
59798
59907
|
descriptor.id,
|
|
59799
59908
|
allocator.claim(
|
|
@@ -59813,111 +59922,79 @@ function regeneratedNodeNames(nodes, triggerId, allocator) {
|
|
|
59813
59922
|
}
|
|
59814
59923
|
return result;
|
|
59815
59924
|
}
|
|
59816
|
-
function regenerateBindingSourceNames(
|
|
59817
|
-
|
|
59818
|
-
|
|
59819
|
-
|
|
59820
|
-
|
|
59821
|
-
|
|
59822
|
-
|
|
59823
|
-
|
|
59824
|
-
|
|
59825
|
-
casing
|
|
59925
|
+
function regenerateBindingSourceNames(links, allocator, kept, placements) {
|
|
59926
|
+
return links.map((link, index) => {
|
|
59927
|
+
const valueId = stringField(link, "valueId");
|
|
59928
|
+
const sourceName = kept.get(`value:${valueId}`) ?? allocator.claim(
|
|
59929
|
+
placements.preferredBindingName(
|
|
59930
|
+
valueId,
|
|
59931
|
+
optionalString2(link.declaredTypeName) ?? `value${index + 1}`,
|
|
59932
|
+
"pascal"
|
|
59933
|
+
)
|
|
59826
59934
|
);
|
|
59827
|
-
return { ...
|
|
59935
|
+
return { ...link, sourceName };
|
|
59828
59936
|
});
|
|
59829
59937
|
}
|
|
59830
|
-
function regenerateNodeBindingSourceNames(
|
|
59831
|
-
|
|
59832
|
-
|
|
59833
|
-
if (!isObjectRecord2(rawLink) || typeof rawLink.valueId !== "string") {
|
|
59834
|
-
throw new Error(`Dialogue-node linked value ${index} is malformed.`);
|
|
59835
|
-
}
|
|
59836
|
-
return rawLink;
|
|
59837
|
-
});
|
|
59838
|
-
const inheritedValueIds = new Set(
|
|
59839
|
-
links.flatMap((link) => {
|
|
59840
|
-
const valueId = stringField(link, "valueId");
|
|
59841
|
-
return dialogueNamesByValueId.has(valueId) ? [valueId] : [];
|
|
59842
|
-
})
|
|
59843
|
-
);
|
|
59844
|
-
const allocator = new DialogueSourceNameAllocator(
|
|
59845
|
-
[...dialogueNamesByValueId].filter(([valueId]) => !inheritedValueIds.has(valueId)).map(([, name]) => name)
|
|
59846
|
-
);
|
|
59847
|
-
const namesByValueId = /* @__PURE__ */ new Map();
|
|
59848
|
-
const allocate = (link, index) => {
|
|
59938
|
+
function regenerateNodeBindingSourceNames(links, allocator, placements, dialogueNamesByValueId, ambiguousOldNames, namesByOldName) {
|
|
59939
|
+
return links.map((link, index) => {
|
|
59940
|
+
if (keptSourceName(link.sourceName) !== null) return link;
|
|
59849
59941
|
const valueId = stringField(link, "valueId");
|
|
59850
|
-
|
|
59851
|
-
|
|
59852
|
-
|
|
59853
|
-
|
|
59854
|
-
|
|
59855
|
-
|
|
59856
|
-
|
|
59857
|
-
|
|
59942
|
+
const oldName = optionalString2(link.sourceName);
|
|
59943
|
+
const mapped = oldName === null ? void 0 : namesByOldName.get(oldName);
|
|
59944
|
+
const inherited = oldName !== null && ambiguousOldNames.has(oldName) ? void 0 : dialogueNamesByValueId.get(valueId);
|
|
59945
|
+
const sourceName = mapped ?? inherited ?? allocator.claim(
|
|
59946
|
+
placements.preferredBindingName(
|
|
59947
|
+
valueId,
|
|
59948
|
+
optionalString2(link.declaredTypeName) ?? `value${index + 1}`,
|
|
59949
|
+
"camel"
|
|
59858
59950
|
)
|
|
59859
59951
|
);
|
|
59860
|
-
|
|
59861
|
-
|
|
59862
|
-
if (dialogueNamesByValueId.has(stringField(link, "valueId"))) {
|
|
59863
|
-
allocate(link, index);
|
|
59864
|
-
}
|
|
59865
|
-
});
|
|
59866
|
-
links.forEach((link, index) => {
|
|
59867
|
-
if (!dialogueNamesByValueId.has(stringField(link, "valueId"))) {
|
|
59868
|
-
allocate(link, index);
|
|
59869
|
-
}
|
|
59952
|
+
if (oldName !== null) namesByOldName.set(oldName, sourceName);
|
|
59953
|
+
return { ...link, sourceName };
|
|
59870
59954
|
});
|
|
59871
|
-
return links.map((link) => ({
|
|
59872
|
-
...link,
|
|
59873
|
-
sourceName: requiredMap(
|
|
59874
|
-
namesByValueId,
|
|
59875
|
-
stringField(link, "valueId"),
|
|
59876
|
-
"dialogue-node linked value"
|
|
59877
|
-
)
|
|
59878
|
-
}));
|
|
59879
59955
|
}
|
|
59880
59956
|
function regenerateTextChildren(node) {
|
|
59881
59957
|
if (!isObjectRecord2(node.optionSettings)) return node;
|
|
59882
59958
|
if (!Array.isArray(node.optionSettings.options)) return node;
|
|
59883
|
-
const allocator = new DialogueSourceNameAllocator();
|
|
59884
|
-
const options = node.optionSettings.options.map((rawOption, index) => {
|
|
59885
|
-
if (!isObjectRecord2(rawOption)) return rawOption;
|
|
59886
|
-
return {
|
|
59887
|
-
...rawOption,
|
|
59888
|
-
sourceName: allocator.claim(
|
|
59889
|
-
dialogueSourceNameFromDisplayName(
|
|
59890
|
-
optionalMeaningfulString(rawOption.name),
|
|
59891
|
-
`Option${index + 1}`
|
|
59892
|
-
)
|
|
59893
|
-
)
|
|
59894
|
-
};
|
|
59895
|
-
});
|
|
59896
59959
|
return {
|
|
59897
59960
|
...node,
|
|
59898
|
-
optionSettings: {
|
|
59961
|
+
optionSettings: {
|
|
59962
|
+
...node.optionSettings,
|
|
59963
|
+
options: regenerateEntrySourceNames(
|
|
59964
|
+
node.optionSettings.options,
|
|
59965
|
+
"Option"
|
|
59966
|
+
)
|
|
59967
|
+
}
|
|
59899
59968
|
};
|
|
59900
59969
|
}
|
|
59901
59970
|
function regenerateConditionOutcomes(node) {
|
|
59902
59971
|
if (!Array.isArray(node.outcomes)) return node;
|
|
59903
|
-
const allocator = new DialogueSourceNameAllocator();
|
|
59904
59972
|
return {
|
|
59905
59973
|
...node,
|
|
59906
|
-
outcomes: node.outcomes
|
|
59907
|
-
if (!isObjectRecord2(rawOutcome)) return rawOutcome;
|
|
59908
|
-
return {
|
|
59909
|
-
...rawOutcome,
|
|
59910
|
-
sourceName: allocator.claim(
|
|
59911
|
-
dialogueSourceNameFromDisplayName(
|
|
59912
|
-
optionalMeaningfulString(rawOutcome.name),
|
|
59913
|
-
`Outcome${index + 1}`
|
|
59914
|
-
)
|
|
59915
|
-
)
|
|
59916
|
-
};
|
|
59917
|
-
})
|
|
59974
|
+
outcomes: regenerateEntrySourceNames(node.outcomes, "Outcome")
|
|
59918
59975
|
};
|
|
59919
59976
|
}
|
|
59920
|
-
function
|
|
59977
|
+
function regenerateEntrySourceNames(entries, fallback) {
|
|
59978
|
+
const allocator = new DialogueSourceNameAllocator();
|
|
59979
|
+
const kept = claimKeptNames(
|
|
59980
|
+
allocator,
|
|
59981
|
+
entries.map((entry, index) => [
|
|
59982
|
+
String(index),
|
|
59983
|
+
isObjectRecord2(entry) ? entry.sourceName : null
|
|
59984
|
+
])
|
|
59985
|
+
);
|
|
59986
|
+
return entries.map((entry, index) => {
|
|
59987
|
+
if (!isObjectRecord2(entry)) return entry;
|
|
59988
|
+
const sourceName = kept.get(String(index)) ?? allocator.claim(
|
|
59989
|
+
dialogueSourceNameFromDisplayName(
|
|
59990
|
+
optionalMeaningfulString(entry.name),
|
|
59991
|
+
`${fallback}${index + 1}`
|
|
59992
|
+
)
|
|
59993
|
+
);
|
|
59994
|
+
return { ...entry, sourceName };
|
|
59995
|
+
});
|
|
59996
|
+
}
|
|
59997
|
+
function sourceFunctionUses(nodes) {
|
|
59921
59998
|
const functions = /* @__PURE__ */ new Map();
|
|
59922
59999
|
const register = (raw, role) => {
|
|
59923
60000
|
if (!isObjectRecord2(raw)) return;
|
|
@@ -59959,7 +60036,7 @@ function regeneratedSourceFunctionNames(nodes, allocator) {
|
|
|
59959
60036
|
registerConditions(option.settings.selectableConditions);
|
|
59960
60037
|
}
|
|
59961
60038
|
}
|
|
59962
|
-
return
|
|
60039
|
+
return functions;
|
|
59963
60040
|
}
|
|
59964
60041
|
function regeneratedGroupFunctionNames(rawConditions) {
|
|
59965
60042
|
const functions = /* @__PURE__ */ new Map();
|
|
@@ -59974,40 +60051,50 @@ function regeneratedGroupFunctionNames(rawConditions) {
|
|
|
59974
60051
|
});
|
|
59975
60052
|
}
|
|
59976
60053
|
}
|
|
59977
|
-
|
|
59978
|
-
|
|
59979
|
-
|
|
60054
|
+
const allocator = new DialogueSourceNameAllocator();
|
|
60055
|
+
const kept = claimKeptNames(
|
|
60056
|
+
allocator,
|
|
60057
|
+
[...functions].map(([id2, fn]) => [`function:${id2}`, fn.existingName])
|
|
59980
60058
|
);
|
|
60059
|
+
return allocateSourceFunctionNames(functions, allocator, kept);
|
|
59981
60060
|
}
|
|
59982
|
-
function allocateSourceFunctionNames(functions, allocator) {
|
|
60061
|
+
function allocateSourceFunctionNames(functions, allocator, kept) {
|
|
59983
60062
|
const result = /* @__PURE__ */ new Map();
|
|
59984
60063
|
const roleCounts = /* @__PURE__ */ new Map();
|
|
59985
60064
|
for (const [id2, fn] of functions) {
|
|
59986
|
-
const keepExisting = fn.existingName !== null && isDialogueSourceIdentifier(fn.existingName) && !isMachineGeneratedDialogueSourceName(fn.existingName);
|
|
59987
60065
|
const ordinal = (roleCounts.get(fn.role) ?? 0) + 1;
|
|
59988
60066
|
roleCounts.set(fn.role, ordinal);
|
|
59989
|
-
|
|
59990
|
-
|
|
60067
|
+
result.set(
|
|
60068
|
+
id2,
|
|
60069
|
+
kept.get(`function:${id2}`) ?? allocator.claim(`${fn.role}${ordinal}`)
|
|
60070
|
+
);
|
|
59991
60071
|
}
|
|
59992
60072
|
return result;
|
|
59993
60073
|
}
|
|
59994
|
-
function
|
|
60074
|
+
function rewriteSourceReferences(value, functionNames, bindingRenames) {
|
|
59995
60075
|
if (Array.isArray(value)) {
|
|
59996
|
-
return value.map(
|
|
60076
|
+
return value.map(
|
|
60077
|
+
(entry) => rewriteSourceReferences(entry, functionNames, bindingRenames)
|
|
60078
|
+
);
|
|
59997
60079
|
}
|
|
59998
60080
|
if (!isObjectRecord2(value)) return value;
|
|
59999
60081
|
const result = Object.fromEntries(
|
|
60000
60082
|
Object.entries(value).map(([key, entry]) => [
|
|
60001
60083
|
key,
|
|
60002
|
-
|
|
60084
|
+
renamedBindingReference(key, entry, bindingRenames) ?? rewriteSourceReferences(entry, functionNames, bindingRenames)
|
|
60003
60085
|
])
|
|
60004
60086
|
);
|
|
60005
60087
|
const id2 = optionalString2(value.sourceFunctionId);
|
|
60006
|
-
const name = id2 === null ? null :
|
|
60088
|
+
const name = id2 === null ? null : functionNames.get(id2);
|
|
60007
60089
|
return name === void 0 || name === null ? result : { ...result, sourceFunctionName: name };
|
|
60008
60090
|
}
|
|
60009
|
-
function
|
|
60010
|
-
|
|
60091
|
+
function renamedBindingReference(key, value, renames) {
|
|
60092
|
+
if (typeof value !== "string") return null;
|
|
60093
|
+
if (key === "code") return renameNeoScriptIdentifiers(value, renames);
|
|
60094
|
+
if (key !== "sourcePath" || PERSISTED_VARIABLE_PATH.test(value)) return null;
|
|
60095
|
+
const head = value.split(".", 1)[0];
|
|
60096
|
+
const renamed = renames.get(head);
|
|
60097
|
+
return renamed === void 0 ? value : renamed + value.slice(head.length);
|
|
60011
60098
|
}
|
|
60012
60099
|
function dialogueNodeKindName(value) {
|
|
60013
60100
|
if (value === 1) return "Text";
|
|
@@ -60565,7 +60652,7 @@ function recoverableProse(context, textId, rawVariables, owner, nodeBindings, pr
|
|
|
60565
60652
|
}
|
|
60566
60653
|
}
|
|
60567
60654
|
function authoredVariablePath(sourcePath, nodeBindings, dialogueBindings, memberNames) {
|
|
60568
|
-
const persisted =
|
|
60655
|
+
const persisted = PERSISTED_VARIABLE_PATH.exec(sourcePath);
|
|
60569
60656
|
const lexicalPath = persisted ? (() => {
|
|
60570
60657
|
const valueId = persisted[1];
|
|
60571
60658
|
const binding = nodeBindings.get(valueId) ?? dialogueBindings.get(valueId);
|
|
@@ -60947,7 +61034,7 @@ function requiredMap(map, id2, label) {
|
|
|
60947
61034
|
function quote3(value) {
|
|
60948
61035
|
return quoteNeoString(value);
|
|
60949
61036
|
}
|
|
60950
|
-
var DIALOGUE_SYSTEM_TYPE_NAMES, ValuePlacementIndex, UniqueNames;
|
|
61037
|
+
var PERSISTED_VARIABLE_PATH, DIALOGUE_SYSTEM_TYPE_NAMES, ValuePlacementIndex, UniqueNames;
|
|
60951
61038
|
var init_dialogue_sources = __esm({
|
|
60952
61039
|
"src/project-source/dialogue-sources.ts"() {
|
|
60953
61040
|
"use strict";
|
|
@@ -60960,6 +61047,7 @@ var init_dialogue_sources = __esm({
|
|
|
60960
61047
|
init_neoscript_source_rewrite();
|
|
60961
61048
|
init_source_format();
|
|
60962
61049
|
init_ui_action_source();
|
|
61050
|
+
PERSISTED_VARIABLE_PATH = /^(?:ref|linked):([^.]+)(\..+)?$/u;
|
|
60963
61051
|
DIALOGUE_SYSTEM_TYPE_NAMES = [
|
|
60964
61052
|
"Dialogue",
|
|
60965
61053
|
"Trigger",
|
|
@@ -131368,9 +131456,25 @@ function workspaceBinaryPathsV4(workspace, local) {
|
|
|
131368
131456
|
for (const file of local ?? []) paths.set(file.fileId, file.path);
|
|
131369
131457
|
return paths;
|
|
131370
131458
|
}
|
|
131371
|
-
function readWorkspaceLayoutStatusV4(workspace) {
|
|
131459
|
+
function readWorkspaceLayoutStatusV4(workspace, document) {
|
|
131460
|
+
const records2 = {};
|
|
131461
|
+
for (const [key, server] of document.records) {
|
|
131462
|
+
if (server.deleted) continue;
|
|
131463
|
+
const previous = workspace.state.records[key];
|
|
131464
|
+
records2[key] = {
|
|
131465
|
+
recordKind: server.recordKind,
|
|
131466
|
+
recordId: server.recordId,
|
|
131467
|
+
contentHash: server.contentHash,
|
|
131468
|
+
data: server.data,
|
|
131469
|
+
...previous?.file === void 0 ? {} : { file: previous.file },
|
|
131470
|
+
...previous?.projectBinary === void 0 ? {} : { projectBinary: previous.projectBinary }
|
|
131471
|
+
};
|
|
131472
|
+
}
|
|
131372
131473
|
try {
|
|
131373
|
-
const status = computeWorkspaceStatus2(
|
|
131474
|
+
const status = computeWorkspaceStatus2({
|
|
131475
|
+
...workspace,
|
|
131476
|
+
state: { ...workspace.state, records: records2 }
|
|
131477
|
+
});
|
|
131374
131478
|
const failure = status.parseErrors.find(isBlockingSchemaSourceError);
|
|
131375
131479
|
if (failure !== void 0) throw failure;
|
|
131376
131480
|
return status;
|
|
@@ -131382,8 +131486,8 @@ function readWorkspaceLayoutStatusV4(workspace) {
|
|
|
131382
131486
|
for (const path of listProjectSourceFilesV4(workspace.root)) {
|
|
131383
131487
|
const content = readFileSync9(path, "utf8");
|
|
131384
131488
|
if (neoProjectSourceKind(path, content) !== "definition") continue;
|
|
131385
|
-
const
|
|
131386
|
-
if (
|
|
131489
|
+
const document2 = parseNeoProjectSource(content, "definition", path);
|
|
131490
|
+
if (document2.declarations.some(
|
|
131387
131491
|
(declaration) => declaration.kind === "global" && isLocalValueGlobal(declaration)
|
|
131388
131492
|
)) {
|
|
131389
131493
|
throw new Error(
|
|
@@ -137771,7 +137875,7 @@ import { dirname as dirname8, join as join13, relative as relative7, sep as sep7
|
|
|
137771
137875
|
function prepareWorkspaceResetV4(workspace, document, options = {}) {
|
|
137772
137876
|
const emissionRecords = options.regenerateSourceNames ? regenerateDialogueSourceNamesV4(document.records) : document.records;
|
|
137773
137877
|
const layoutWorkspace = workspaceForSourceLayoutV4(workspace, document);
|
|
137774
|
-
const status = listProjectSourceFilesV4(workspace.root).length === 0 ? null : readWorkspaceLayoutStatusV4(layoutWorkspace);
|
|
137878
|
+
const status = listProjectSourceFilesV4(workspace.root).length === 0 ? null : readWorkspaceLayoutStatusV4(layoutWorkspace, document);
|
|
137775
137879
|
const localValues = status?.localValues ?? workspace.state.localValues;
|
|
137776
137880
|
const emitted = emitProjectDocumentFilesV4(emissionRecords, {
|
|
137777
137881
|
localValues,
|
|
@@ -137991,7 +138095,7 @@ import {
|
|
|
137991
138095
|
import { dirname as dirname9 } from "node:path";
|
|
137992
138096
|
async function runPull(workspace, options, progress = spinner("Checking local workspace\u2026")) {
|
|
137993
138097
|
if (options.reset) {
|
|
137994
|
-
await runResetPull(workspace, progress);
|
|
138098
|
+
await runResetPull(workspace, options.regenerateSourceNames, progress);
|
|
137995
138099
|
return;
|
|
137996
138100
|
}
|
|
137997
138101
|
try {
|
|
@@ -138233,18 +138337,18 @@ ${blockingErrors.map((error) => ` ${error.message}`).join("\n")}`
|
|
|
138233
138337
|
conflictKeys,
|
|
138234
138338
|
localStatus,
|
|
138235
138339
|
destructive,
|
|
138236
|
-
regenerateSourceNames:
|
|
138340
|
+
regenerateSourceNames: options.regenerateSourceNames,
|
|
138237
138341
|
changedRecordKeys,
|
|
138238
138342
|
nextCursor,
|
|
138239
138343
|
progress
|
|
138240
138344
|
});
|
|
138241
138345
|
}
|
|
138242
|
-
async function runResetPull(workspace, progress) {
|
|
138346
|
+
async function runResetPull(workspace, regenerateSourceNames, progress) {
|
|
138243
138347
|
progress.update("Pulling project snapshot\u2026");
|
|
138244
138348
|
try {
|
|
138245
138349
|
const document = await fetchProjectDocument(workspace);
|
|
138246
138350
|
const preparation = prepareWorkspaceResetV4(workspace, document, {
|
|
138247
|
-
regenerateSourceNames
|
|
138351
|
+
regenerateSourceNames
|
|
138248
138352
|
});
|
|
138249
138353
|
progress.update("Downloading project files\u2026");
|
|
138250
138354
|
const previousRecords = workspace.state.records;
|
|
@@ -138258,7 +138362,7 @@ async function runResetPull(workspace, progress) {
|
|
|
138258
138362
|
});
|
|
138259
138363
|
progress.update("Regenerating Neo sources\u2026");
|
|
138260
138364
|
const reset = resetWorkspaceToProjectSourcesV4(workspace, document, {
|
|
138261
|
-
regenerateSourceNames
|
|
138365
|
+
regenerateSourceNames,
|
|
138262
138366
|
preparation
|
|
138263
138367
|
});
|
|
138264
138368
|
for (const recovery of reset.staticMemberOwnershipRecoveries ?? []) {
|
|
@@ -138343,7 +138447,7 @@ async function finishFormat4Pull(args) {
|
|
|
138343
138447
|
for (const [key, record6] of localStatus?.reconstructed ?? []) {
|
|
138344
138448
|
if (record6.file != null) recordFiles.set(key, record6.file);
|
|
138345
138449
|
}
|
|
138346
|
-
const layoutStatus = localStatus ?? (destructive ? readWorkspaceLayoutStatusV4(layoutWorkspace) : null);
|
|
138450
|
+
const layoutStatus = localStatus ?? (destructive ? readWorkspaceLayoutStatusV4(layoutWorkspace, document) : null);
|
|
138347
138451
|
const localValues = layoutStatus?.localValues ?? workspace.state.localValues;
|
|
138348
138452
|
const binaryPaths = workspaceBinaryPathsV4(
|
|
138349
138453
|
workspace,
|
|
@@ -156706,9 +156810,9 @@ ${h("Usage")}
|
|
|
156706
156810
|
neo pull ${d("[--force|--reset] [--regenerate-source-names]")}
|
|
156707
156811
|
|
|
156708
156812
|
${h("Flags")}
|
|
156709
|
-
--force ${d("Discard local edits
|
|
156710
|
-
--reset ${d("Destructively regenerate the entire working copy
|
|
156711
|
-
--regenerate-source-names ${d("
|
|
156813
|
+
--force ${d("Discard local edits and take the current server schema.")}
|
|
156814
|
+
--reset ${d("Destructively regenerate the entire working copy and binaries, even when the sync head is unchanged.")}
|
|
156815
|
+
--regenerate-source-names ${d("Replace generated default dialogue symbols with readable names.")}
|
|
156712
156816
|
|
|
156713
156817
|
Use ${h("--reset")} to reconstruct every managed ${h(".neo")}/${h(".neoflow")} source file
|
|
156714
156818
|
and tracked project binary from the authoritative server records.
|
|
@@ -156833,7 +156937,7 @@ There is no --keep-current: preserving current semantic state defines flatten.
|
|
|
156833
156937
|
async function main() {
|
|
156834
156938
|
const args = parseArgs(process.argv.slice(2));
|
|
156835
156939
|
if (args.command === "--version") {
|
|
156836
|
-
console.log("0.67.
|
|
156940
|
+
console.log("0.67.3");
|
|
156837
156941
|
return;
|
|
156838
156942
|
}
|
|
156839
156943
|
if (args.command === null || args.command === "help" || args.command === "--help" || args.command === "-h") {
|
package/package.json
CHANGED
|
@@ -9,7 +9,7 @@ description: >-
|
|
|
9
9
|
`@neocompose/cli` or `node cli/bin/neo.mjs` in the neo-compose repository.
|
|
10
10
|
---
|
|
11
11
|
|
|
12
|
-
<!-- reviewed-through-cli: 0.67.
|
|
12
|
+
<!-- reviewed-through-cli: 0.67.3 -->
|
|
13
13
|
|
|
14
14
|
# Neo Compose CLI
|
|
15
15
|
|
|
@@ -91,10 +91,10 @@ upgrader. Reconstruct an authoritative format-4 checkout with `neo init`.
|
|
|
91
91
|
|
|
92
92
|
For an existing checkout:
|
|
93
93
|
|
|
94
|
-
- `neo pull --reset` regenerates canonical source
|
|
94
|
+
- `neo pull --reset` regenerates canonical source and managed binaries.
|
|
95
95
|
- `neo pull --force` discards local edits in favor of the server.
|
|
96
|
-
- `neo pull --regenerate-source-names`
|
|
97
|
-
|
|
96
|
+
- `neo pull --regenerate-source-names` replaces generated default dialogue
|
|
97
|
+
names with readable ones, keeps chosen names, and rewrites references.
|
|
98
98
|
|
|
99
99
|
Use reset and force only when their destructive effect is intended.
|
|
100
100
|
|
|
@@ -110,7 +110,7 @@ wrappers.
|
|
|
110
110
|
The marker near the top of `SKILL.md` must exactly match the package version:
|
|
111
111
|
|
|
112
112
|
```html
|
|
113
|
-
<!-- reviewed-through-cli: 0.67.
|
|
113
|
+
<!-- reviewed-through-cli: 0.67.3 -->
|
|
114
114
|
```
|
|
115
115
|
|
|
116
116
|
The quoted version above is checked too, so this instruction cannot go stale
|
|
@@ -29,11 +29,11 @@ neo push
|
|
|
29
29
|
neo push --dry-run --force-recompile
|
|
30
30
|
```
|
|
31
31
|
|
|
32
|
-
Use `neo pull --regenerate-source-names` to
|
|
33
|
-
|
|
34
|
-
and managed binaries. Reset retains
|
|
35
|
-
by the workspace, while
|
|
36
|
-
per-declaration layout. Use `--force` only to discard local edits for the server
|
|
32
|
+
Use `neo pull --regenerate-source-names` to replace generated default dialogue
|
|
33
|
+
names with readable ones. It keeps chosen names and rewrites references. Use
|
|
34
|
+
`--reset` to regenerate canonical source and managed binaries. Reset retains
|
|
35
|
+
declaration file grouping already recorded by the workspace, while
|
|
36
|
+
declarations with no prior placement use the canonical per-declaration layout. Use `--force` only to discard local edits for the server
|
|
37
37
|
version. Normal pulls persist a transaction cursor and fetch only changed
|
|
38
38
|
records. If the remote head is unchanged, pull preserves the local source
|
|
39
39
|
without compiling it; use `neo status` to inspect local edits and diagnostics.
|