@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.
@@ -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(returnType, this.project)
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
- this.requireAssignable(
34622
- value.type,
34623
- expected,
34624
- statement.expr.pos,
34625
- "return"
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
- { projectIndex: compilationProjectIndex(context.project), source }
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@neocompose/cli",
3
- "version": "0.71.1",
3
+ "version": "0.71.3",
4
4
  "description": "Neo Compose native project-source CLI with bidirectional sync.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -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.71.1 -->
12
+ <!-- reviewed-through-cli: 0.71.3 -->
13
13
 
14
14
  # Neo Compose CLI
15
15
 
@@ -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.1 -->
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