@neocompose/cli 0.71.1 → 0.71.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 +20 -0
- package/dist/neo.mjs +2351 -1016
- package/dist/test-worker.mjs +118 -66
- package/package.json +1 -1
- package/skills/neocompose-cli/SKILL.md +1 -1
- package/skills/neocompose-cli/references/animation-and-world-authoring.md +38 -0
- package/skills/neocompose-cli/references/cli-development.md +2 -2
package/dist/test-worker.mjs
CHANGED
|
@@ -33573,6 +33573,7 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
|
|
|
33573
33573
|
tryMutationContexts = [];
|
|
33574
33574
|
functionControlBoundaries = [];
|
|
33575
33575
|
debugSource;
|
|
33576
|
+
inferredExpressionReturnType;
|
|
33576
33577
|
initialScope() {
|
|
33577
33578
|
const scope = new Scope(null, this.options.onFlowScope !== void 0);
|
|
33578
33579
|
scope.define(
|
|
@@ -33777,6 +33778,23 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
|
|
|
33777
33778
|
this.context.kind === "action" || this.context.kind === "setter" || this.context.kind === "constructor" || isVoid(this.context.returnType),
|
|
33778
33779
|
describeUnitKind(this.context.kind)
|
|
33779
33780
|
);
|
|
33781
|
+
if (this.options.inferExpressionReturnType) {
|
|
33782
|
+
if (this.context.kind !== "getter")
|
|
33783
|
+
throw new CompileError(
|
|
33784
|
+
"Expression inference requires a getter.",
|
|
33785
|
+
body.pos
|
|
33786
|
+
);
|
|
33787
|
+
if (statements.length !== 1)
|
|
33788
|
+
throw new CompileError(
|
|
33789
|
+
"Expression inference requires one return expression.",
|
|
33790
|
+
body.pos
|
|
33791
|
+
);
|
|
33792
|
+
if (statements[0]?.kind !== "return" || statements[0].expr === null)
|
|
33793
|
+
throw new CompileError(
|
|
33794
|
+
"Expression inference requires a returned value.",
|
|
33795
|
+
body.pos
|
|
33796
|
+
);
|
|
33797
|
+
}
|
|
33780
33798
|
const instructions = this.resolveStatements(statements, scope);
|
|
33781
33799
|
if ((this.context.kind === "function" || this.context.kind === "getter" || this.context.kind === "condition" || this.context.kind === "initializer") && !isVoid(this.context.returnType) && !instructionsTerminate(instructions)) {
|
|
33782
33800
|
throw new CompileError(
|
|
@@ -33793,7 +33811,10 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
|
|
|
33793
33811
|
source: this.debugSource,
|
|
33794
33812
|
parameters,
|
|
33795
33813
|
instructions,
|
|
33796
|
-
typeInfo: toWireType(
|
|
33814
|
+
typeInfo: toWireType(
|
|
33815
|
+
this.inferredExpressionReturnType ?? returnType,
|
|
33816
|
+
this.project
|
|
33817
|
+
)
|
|
33797
33818
|
};
|
|
33798
33819
|
} finally {
|
|
33799
33820
|
this.expectedReturnStack.pop();
|
|
@@ -34595,10 +34616,11 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
|
|
|
34595
34616
|
}
|
|
34596
34617
|
const inference = this.lambdaReturnInference.at(-1);
|
|
34597
34618
|
const inferring = inference?.depth === this.lambdaDepth;
|
|
34619
|
+
const inferExpression = this.options.inferExpressionReturnType && this.lambdaDepth === 0;
|
|
34598
34620
|
const value = this.resolveExpression(
|
|
34599
34621
|
statement.expr,
|
|
34600
34622
|
scope,
|
|
34601
|
-
inferring ? void 0 : expected
|
|
34623
|
+
inferring || inferExpression ? void 0 : expected
|
|
34602
34624
|
);
|
|
34603
34625
|
if (inferring) {
|
|
34604
34626
|
inference.returns.push({
|
|
@@ -34618,12 +34640,21 @@ var StrictNeoScriptResolver = class _StrictNeoScriptResolver {
|
|
|
34618
34640
|
statement.pos
|
|
34619
34641
|
);
|
|
34620
34642
|
}
|
|
34621
|
-
|
|
34622
|
-
value.type
|
|
34623
|
-
|
|
34624
|
-
|
|
34625
|
-
|
|
34626
|
-
|
|
34643
|
+
if (inferExpression) {
|
|
34644
|
+
if (isVoid(value.type))
|
|
34645
|
+
throw new CompileError(
|
|
34646
|
+
"A text expression must return a value, not void.",
|
|
34647
|
+
statement.expr.pos
|
|
34648
|
+
);
|
|
34649
|
+
this.inferredExpressionReturnType = value.type;
|
|
34650
|
+
} else {
|
|
34651
|
+
this.requireAssignable(
|
|
34652
|
+
value.type,
|
|
34653
|
+
expected,
|
|
34654
|
+
statement.expr.pos,
|
|
34655
|
+
"return"
|
|
34656
|
+
);
|
|
34657
|
+
}
|
|
34627
34658
|
return {
|
|
34628
34659
|
type: "return" /* Return */,
|
|
34629
34660
|
pointer: value.pointer
|
|
@@ -42677,7 +42708,8 @@ function compileNeoScriptStrict(document2, context, options = {}) {
|
|
|
42677
42708
|
{
|
|
42678
42709
|
source: options.source,
|
|
42679
42710
|
onFlowScope: options.onFlowScope,
|
|
42680
|
-
sourceUri: document2.uri
|
|
42711
|
+
sourceUri: document2.uri,
|
|
42712
|
+
inferExpressionReturnType: options.inferExpressionReturnType
|
|
42681
42713
|
}
|
|
42682
42714
|
).compile(ast);
|
|
42683
42715
|
const ir = attachDependencyManifest(
|
|
@@ -46261,6 +46293,20 @@ function compileNSGetter(code, ctx) {
|
|
|
46261
46293
|
ctx.source
|
|
46262
46294
|
);
|
|
46263
46295
|
}
|
|
46296
|
+
function compileNSInferredExpressionGetter(code, ctx) {
|
|
46297
|
+
const compiled = compileStrict(
|
|
46298
|
+
code,
|
|
46299
|
+
createContext(ctx, {
|
|
46300
|
+
scriptKind: "getter",
|
|
46301
|
+
dialogueContext: ctx.dialogueContext
|
|
46302
|
+
}),
|
|
46303
|
+
ctx.source,
|
|
46304
|
+
true
|
|
46305
|
+
);
|
|
46306
|
+
if (!isNSGetter(compiled))
|
|
46307
|
+
throw new Error("Expression compiler did not produce a getter.");
|
|
46308
|
+
return compiled;
|
|
46309
|
+
}
|
|
46264
46310
|
function compileNSVoidBody(code, ctx) {
|
|
46265
46311
|
const context = createContext(ctx, {
|
|
46266
46312
|
scriptKind: "action",
|
|
@@ -46359,9 +46405,10 @@ function withInitializerSourcePosition(error) {
|
|
|
46359
46405
|
error.unit
|
|
46360
46406
|
);
|
|
46361
46407
|
}
|
|
46362
|
-
function compileStrict(code, context, sourceInfo) {
|
|
46408
|
+
function compileStrict(code, context, sourceInfo, inferExpressionReturnType = false) {
|
|
46363
46409
|
const source = sourceInfo?.code === code ? sourceInfo.source : void 0;
|
|
46364
46410
|
const cacheKey = JSON.stringify({
|
|
46411
|
+
inferExpressionReturnType,
|
|
46365
46412
|
code,
|
|
46366
46413
|
source,
|
|
46367
46414
|
projectIdentity: compilationProjectIdentity(context.project),
|
|
@@ -46394,7 +46441,11 @@ function compileStrict(code, context, sourceInfo) {
|
|
|
46394
46441
|
text: code
|
|
46395
46442
|
},
|
|
46396
46443
|
context,
|
|
46397
|
-
{
|
|
46444
|
+
{
|
|
46445
|
+
projectIndex: compilationProjectIndex(context.project),
|
|
46446
|
+
source,
|
|
46447
|
+
inferExpressionReturnType
|
|
46448
|
+
}
|
|
46398
46449
|
);
|
|
46399
46450
|
if (result.diagnostics.length) {
|
|
46400
46451
|
const error = result.diagnostics[0];
|
|
@@ -46513,6 +46564,7 @@ __export(compiler_adapter_exports, {
|
|
|
46513
46564
|
compileNSConstructor: () => compileNSConstructor,
|
|
46514
46565
|
compileNSFunction: () => compileNSFunction,
|
|
46515
46566
|
compileNSGetter: () => compileNSGetter,
|
|
46567
|
+
compileNSInferredExpressionGetter: () => compileNSInferredExpressionGetter,
|
|
46516
46568
|
compileNSInitializer: () => compileNSInitializer,
|
|
46517
46569
|
compileNSSetter: () => compileNSSetter,
|
|
46518
46570
|
compileNSVoidBody: () => compileNSVoidBody,
|
|
@@ -52912,61 +52964,6 @@ function invalidDocument(record4, path, message) {
|
|
|
52912
52964
|
);
|
|
52913
52965
|
}
|
|
52914
52966
|
|
|
52915
|
-
// src/project-source/structured-leaf-source.ts
|
|
52916
|
-
var STRUCTURED_LEAF_SOURCE_FORMS = {
|
|
52917
|
-
sprite: { kind: 11 /* Sprite */, typeName: "SpriteInfo" },
|
|
52918
|
-
vector2: { kind: 14 /* Vector2 */, typeName: "Vector2" },
|
|
52919
|
-
vector2Int: { kind: 15 /* Vector2Int */, typeName: "Vector2Int" },
|
|
52920
|
-
vector3: { kind: 16 /* Vector3 */, typeName: "Vector3" },
|
|
52921
|
-
vector3Int: { kind: 17 /* Vector3Int */, typeName: "Vector3Int" },
|
|
52922
|
-
color: { kind: 19 /* Color */, typeName: "Color" }
|
|
52923
|
-
};
|
|
52924
|
-
var STRUCTURED_LEAF_SOURCE_ENTRIES = Object.entries(STRUCTURED_LEAF_SOURCE_FORMS);
|
|
52925
|
-
|
|
52926
|
-
// src/project-source/member-kind-type-names.ts
|
|
52927
|
-
var MEMBER_KIND_SOURCE_TYPE_NAMES = {
|
|
52928
|
-
null: "null",
|
|
52929
|
-
bool: "bool",
|
|
52930
|
-
int: "int",
|
|
52931
|
-
string: "string",
|
|
52932
|
-
float: "float",
|
|
52933
|
-
decimal: "decimal",
|
|
52934
|
-
sprite: "SpriteInfo",
|
|
52935
|
-
audio: "AudioClipInfo",
|
|
52936
|
-
vector2: "Vector2",
|
|
52937
|
-
vector2Int: "Vector2Int",
|
|
52938
|
-
vector3: "Vector3",
|
|
52939
|
-
vector3Int: "Vector3Int",
|
|
52940
|
-
color: "Color"
|
|
52941
|
-
};
|
|
52942
|
-
var MEMBER_KIND_NUMBERS = {
|
|
52943
|
-
null: 0 /* Null */,
|
|
52944
|
-
bool: 1 /* Bool */,
|
|
52945
|
-
int: 2 /* Int */,
|
|
52946
|
-
string: 3 /* String */,
|
|
52947
|
-
float: 4 /* Float */,
|
|
52948
|
-
decimal: 20 /* Decimal */,
|
|
52949
|
-
sprite: 11 /* Sprite */,
|
|
52950
|
-
audio: 12 /* Audio */,
|
|
52951
|
-
vector2: 14 /* Vector2 */,
|
|
52952
|
-
vector2Int: 15 /* Vector2Int */,
|
|
52953
|
-
vector3: 16 /* Vector3 */,
|
|
52954
|
-
vector3Int: 17 /* Vector3Int */,
|
|
52955
|
-
color: 19 /* Color */
|
|
52956
|
-
};
|
|
52957
|
-
var SOURCE_TYPE_NAME_BY_MEMBER_KIND_NUMBER = new Map(
|
|
52958
|
-
Object.entries(MEMBER_KIND_NUMBERS).map(([slug, kind]) => [
|
|
52959
|
-
kind,
|
|
52960
|
-
MEMBER_KIND_SOURCE_TYPE_NAMES[slug]
|
|
52961
|
-
])
|
|
52962
|
-
);
|
|
52963
|
-
|
|
52964
|
-
// src/project-source/value-sources.ts
|
|
52965
|
-
var INITIALIZER_KEY_PLACEHOLDER = new RegExp(
|
|
52966
|
-
`${PENDING_ID_PREFIX}reference-key:init:\\d+`,
|
|
52967
|
-
"g"
|
|
52968
|
-
);
|
|
52969
|
-
|
|
52970
52967
|
// src/project-manifest/record-adapters/enum.ts
|
|
52971
52968
|
var ENUM_SCHEMA_RECORD_ADAPTER = {
|
|
52972
52969
|
recordKind: "enum",
|
|
@@ -54021,6 +54018,61 @@ var SCHEMA_RECORD_ADAPTERS = [
|
|
|
54021
54018
|
SCHEMA_RECORD_ADAPTER_REGISTRY["internal-record-relation"]
|
|
54022
54019
|
];
|
|
54023
54020
|
|
|
54021
|
+
// src/project-source/structured-leaf-source.ts
|
|
54022
|
+
var STRUCTURED_LEAF_SOURCE_FORMS = {
|
|
54023
|
+
sprite: { kind: 11 /* Sprite */, typeName: "SpriteInfo" },
|
|
54024
|
+
vector2: { kind: 14 /* Vector2 */, typeName: "Vector2" },
|
|
54025
|
+
vector2Int: { kind: 15 /* Vector2Int */, typeName: "Vector2Int" },
|
|
54026
|
+
vector3: { kind: 16 /* Vector3 */, typeName: "Vector3" },
|
|
54027
|
+
vector3Int: { kind: 17 /* Vector3Int */, typeName: "Vector3Int" },
|
|
54028
|
+
color: { kind: 19 /* Color */, typeName: "Color" }
|
|
54029
|
+
};
|
|
54030
|
+
var STRUCTURED_LEAF_SOURCE_ENTRIES = Object.entries(STRUCTURED_LEAF_SOURCE_FORMS);
|
|
54031
|
+
|
|
54032
|
+
// src/project-source/member-kind-type-names.ts
|
|
54033
|
+
var MEMBER_KIND_SOURCE_TYPE_NAMES = {
|
|
54034
|
+
null: "null",
|
|
54035
|
+
bool: "bool",
|
|
54036
|
+
int: "int",
|
|
54037
|
+
string: "string",
|
|
54038
|
+
float: "float",
|
|
54039
|
+
decimal: "decimal",
|
|
54040
|
+
sprite: "SpriteInfo",
|
|
54041
|
+
audio: "AudioClipInfo",
|
|
54042
|
+
vector2: "Vector2",
|
|
54043
|
+
vector2Int: "Vector2Int",
|
|
54044
|
+
vector3: "Vector3",
|
|
54045
|
+
vector3Int: "Vector3Int",
|
|
54046
|
+
color: "Color"
|
|
54047
|
+
};
|
|
54048
|
+
var MEMBER_KIND_NUMBERS = {
|
|
54049
|
+
null: 0 /* Null */,
|
|
54050
|
+
bool: 1 /* Bool */,
|
|
54051
|
+
int: 2 /* Int */,
|
|
54052
|
+
string: 3 /* String */,
|
|
54053
|
+
float: 4 /* Float */,
|
|
54054
|
+
decimal: 20 /* Decimal */,
|
|
54055
|
+
sprite: 11 /* Sprite */,
|
|
54056
|
+
audio: 12 /* Audio */,
|
|
54057
|
+
vector2: 14 /* Vector2 */,
|
|
54058
|
+
vector2Int: 15 /* Vector2Int */,
|
|
54059
|
+
vector3: 16 /* Vector3 */,
|
|
54060
|
+
vector3Int: 17 /* Vector3Int */,
|
|
54061
|
+
color: 19 /* Color */
|
|
54062
|
+
};
|
|
54063
|
+
var SOURCE_TYPE_NAME_BY_MEMBER_KIND_NUMBER = new Map(
|
|
54064
|
+
Object.entries(MEMBER_KIND_NUMBERS).map(([slug, kind]) => [
|
|
54065
|
+
kind,
|
|
54066
|
+
MEMBER_KIND_SOURCE_TYPE_NAMES[slug]
|
|
54067
|
+
])
|
|
54068
|
+
);
|
|
54069
|
+
|
|
54070
|
+
// src/project-source/value-sources.ts
|
|
54071
|
+
var INITIALIZER_KEY_PLACEHOLDER = new RegExp(
|
|
54072
|
+
`${PENDING_ID_PREFIX}reference-key:init:\\d+`,
|
|
54073
|
+
"g"
|
|
54074
|
+
);
|
|
54075
|
+
|
|
54024
54076
|
// ../packages/neoscript-language/src/project-schema-contract.generated.ts
|
|
54025
54077
|
var PROJECT_FILE_UPLOAD_BATCH_SIZE = 32;
|
|
54026
54078
|
|
package/package.json
CHANGED
|
@@ -497,3 +497,41 @@ project candidate, including new dialogues and pending schema or value changes,
|
|
|
497
497
|
without fetching or committing server content. Exit 1 means the graph
|
|
498
498
|
would fail on device. Keep every dialogue edit in the tracked `.neoflow` source
|
|
499
499
|
and commit it with `neo push`.
|
|
500
|
+
|
|
501
|
+
### Dialogue group names and local symbols
|
|
502
|
+
|
|
503
|
+
Use `DialogueGroup QuestUnlocks = new(kind: .Standard, parent: Quests, name: "Unlocks")`
|
|
504
|
+
when the local identifier should differ from the record's display name. Omitting
|
|
505
|
+
`name` uses the identifier. Unity generates its dialogue API from the stored
|
|
506
|
+
name (`Quests.Unlocks`), independently of the local identifier. Pull, force-pull,
|
|
507
|
+
and reset retain the local identifier and authored file path by `@id`; a remote
|
|
508
|
+
rename updates the `name:` argument.
|
|
509
|
+
|
|
510
|
+
Trigger groups accept both `group: QuestUnlocks.Medium` and
|
|
511
|
+
`group: Quests.Unlocks.Medium`. Qualified paths use the group's display name
|
|
512
|
+
converted to an identifier; priority options use their declared names.
|
|
513
|
+
Completion, hover, navigation, and diagnostics resolve both forms. Sibling
|
|
514
|
+
groups that produce the same path segment require their distinct local aliases.
|
|
515
|
+
|
|
516
|
+
### NeoFlow display names
|
|
517
|
+
|
|
518
|
+
For `Text`, `Actions`, `Conditions`, `Option`, and `Outcome`, omitting `name:`
|
|
519
|
+
infers the label from a custom authored symbol. `Option Accept = new()` gets
|
|
520
|
+
label `Accept`, regardless of its prose. Dialogue classes use the same rule
|
|
521
|
+
when `@settings(name: ...)` is omitted.
|
|
522
|
+
|
|
523
|
+
Generated symbols such as `Text1`, `Actions2`, `Option1_2`, `Outcome1`, and the
|
|
524
|
+
identity-based `Node_...` forms stay unlabeled for their corresponding kinds.
|
|
525
|
+
A symbol from another kind is custom: `Option Text1` gets label `Text1`.
|
|
526
|
+
Explicit names win, including
|
|
527
|
+
`name: ""` for clearing a label, or `name: null` on optional graph labels. Dialogues and outcomes store
|
|
528
|
+
an empty string for an unset label; optional graph labels store null. Pull
|
|
529
|
+
writes explicit empty overrides where omission would otherwise infer a name,
|
|
530
|
+
and omits a redundant label equal to the inferred symbol.
|
|
531
|
+
|
|
532
|
+
The fixed `Trigger` member does not infer a label. Reusable condition and action
|
|
533
|
+
functions keep their function identifiers as `sourceFunctionName`; they have
|
|
534
|
+
no separate display-name field or `name:` constructor. Rename the function
|
|
535
|
+
and its uses to change that source name. Linked-value aliases likewise retain
|
|
536
|
+
their `sourceName`. These names never come from prose, and the naming rule does
|
|
537
|
+
not change IDs, destinations, or condition/action use identities.
|
|
@@ -71,7 +71,7 @@ live in `packages/manifest`. Contract generation and its registry live in
|
|
|
71
71
|
|
|
72
72
|
The CLI uses plain document snapshots and shared runtime functions. Keep Retree and web view models out of its imports. The headless architecture check follows CLI imports, and `cli/build.mjs` rejects UI modules and packages in the actual bundle metadata.
|
|
73
73
|
|
|
74
|
-
Keep parsing, strict resolution, formatting, diagnostics, symbols, and
|
|
74
|
+
Keep parsing, strict resolution, formatting, diagnostics with authored file and expression ranges, symbols, and
|
|
75
75
|
NeoScript compilation in the browser-safe `@neocompose/neoscript-language`
|
|
76
76
|
service. Monaco, VS Code, CLI, trusted server, and corpus tooling must consume
|
|
77
77
|
that shared implementation. Do not add language intelligence to one adapter.
|
|
@@ -118,7 +118,7 @@ wrappers.
|
|
|
118
118
|
The marker near the top of `SKILL.md` must exactly match the package version:
|
|
119
119
|
|
|
120
120
|
```html
|
|
121
|
-
<!-- reviewed-through-cli: 0.71.
|
|
121
|
+
<!-- reviewed-through-cli: 0.71.3 -->
|
|
122
122
|
```
|
|
123
123
|
|
|
124
124
|
The quoted version above is checked too, so this instruction cannot go stale
|