narraeon 0.7.5 → 0.7.6
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/node/protocol/v1.js +4 -0
- package/dist/node/runtime/V1Runtime.js +12 -0
- package/dist/node/runtime/model/ToolArgumentCoercion.js +138 -0
- package/dist/node/runtime/play/FileNativePlayTimelineStore.js +6 -2
- package/dist/node/runtime/play/OrderedPlayPrompts.js +3 -6
- package/dist/node/runtime/play/PlayCallChain.js +76 -24
- package/dist/node/runtime/play/PlayDocumentTools.js +19 -0
- package/dist/node/runtime/prompt/FileNativePromptCompiler.js +3 -3
- package/dist/node/runtime/prompt/FileNativeToolRegistry.js +15 -0
- package/dist/node/runtime/prompt/ToolNameAlias.js +14 -0
- package/dist/node/runtime/setting/SettingAuthoringTransaction.js +62 -6
- package/dist/node/shared/ordered-play-prompts.js +5 -0
- package/dist/node/shared/turn-guide.js +27 -2
- package/dist/web/assets/index-Cj2JYCia.js +1408 -0
- package/dist/web/index.html +1 -1
- package/package.json +1 -1
- package/dist/web/assets/index-9N9kO8kY.js +0 -1408
|
@@ -2,10 +2,12 @@ import { isPackageFollowupControlPath } from "../content/PackageFollowups.js";
|
|
|
2
2
|
import { renderWorldMaintenanceReport } from "../prompt/WorldMaintenanceReport.js";
|
|
3
3
|
import { listWorldDocuments as listQueryableWorldDocuments } from "../prompt/WorldMaintenanceReport.js";
|
|
4
4
|
import { defaultAppLocale } from "../../protocol/appPreferences.js";
|
|
5
|
-
import { gameplayLabel, gameplayPath, readGameplay, } from "../../protocol/gameplay.js";
|
|
5
|
+
import { fictionGameplay, gameplayLabel, gameplayPath, readGameplay, } from "../../protocol/gameplay.js";
|
|
6
6
|
import { isScalar, isSeq, parseDocument, stringify } from "yaml";
|
|
7
7
|
import { tabletopSchemeReceipt } from "../play/TabletopRules.js";
|
|
8
8
|
import { inspectContentPackageCurrentTree } from "../content/FileNativeContentTree.js";
|
|
9
|
+
import { coerceToolArguments, renderCoercionNote, } from "../model/ToolArgumentCoercion.js";
|
|
10
|
+
import { renderToolAliasNote, resolveToolName, } from "../prompt/ToolNameAlias.js";
|
|
9
11
|
import { worldMaterialCoverage } from "../prompt/WorldMaterialCoverage.js";
|
|
10
12
|
import { WorldDocumentStore, } from "../world/WorldDocumentStore.js";
|
|
11
13
|
export const settingImprovementToolNames = [
|
|
@@ -434,11 +436,20 @@ export class SettingAuthoringTransaction {
|
|
|
434
436
|
};
|
|
435
437
|
}
|
|
436
438
|
execute(calls) {
|
|
437
|
-
const normalized = calls.map((call) => normalizeCall(call, this.#surface));
|
|
439
|
+
const normalized = calls.map((call) => normalizeCall(call, this.#surface, this.#locale));
|
|
438
440
|
const results = [];
|
|
439
441
|
const responseBase = this.files();
|
|
440
442
|
let lastSuccessfulWrite = -1;
|
|
441
443
|
for (const call of normalized) {
|
|
444
|
+
if (call.rejection !== undefined) {
|
|
445
|
+
results.push({
|
|
446
|
+
toolCallId: call.id,
|
|
447
|
+
markdown: `# Runtime tool rejected\n\n${call.rejection}`,
|
|
448
|
+
isError: true,
|
|
449
|
+
changes: [],
|
|
450
|
+
});
|
|
451
|
+
continue;
|
|
452
|
+
}
|
|
442
453
|
const before = this.files();
|
|
443
454
|
const unavailable = unavailableArgument(this.#surface, call.arguments, this.#locale);
|
|
444
455
|
if (unavailable !== null) {
|
|
@@ -466,6 +477,20 @@ export class SettingAuthoringTransaction {
|
|
|
466
477
|
// model only needs what this tool response changed.
|
|
467
478
|
settled.markdown = `${settled.markdown}\n\n${renderAutomaticReview(this.#review, fileDiff(responseBase, this.#snapshot.files), this.#snapshot, this.#surface, this.#locale)}`;
|
|
468
479
|
}
|
|
480
|
+
normalized.forEach((call, index) => {
|
|
481
|
+
const notes = [
|
|
482
|
+
...(call.coerced.length === 0
|
|
483
|
+
? []
|
|
484
|
+
: [renderCoercionNote(call.coerced, this.#locale)]),
|
|
485
|
+
...(call.alias === undefined
|
|
486
|
+
? []
|
|
487
|
+
: [renderToolAliasNote(call.alias, call.name, this.#locale)]),
|
|
488
|
+
];
|
|
489
|
+
if (notes.length === 0)
|
|
490
|
+
return;
|
|
491
|
+
const result = results[index];
|
|
492
|
+
result.markdown = `${result.markdown}\n\n${notes.join("\n\n")}`;
|
|
493
|
+
});
|
|
469
494
|
return results;
|
|
470
495
|
}
|
|
471
496
|
#executeRead(call) {
|
|
@@ -758,14 +783,41 @@ class SettingAuthoringError extends Error {
|
|
|
758
783
|
this.name = "SettingAuthoringError";
|
|
759
784
|
}
|
|
760
785
|
}
|
|
761
|
-
function normalizeCall(call, surface) {
|
|
786
|
+
function normalizeCall(call, surface, locale) {
|
|
787
|
+
const cloned = isRecord(call.arguments)
|
|
788
|
+
? structuredClone(call.arguments)
|
|
789
|
+
: {};
|
|
790
|
+
const definitions = authoringToolDefinitions(surface, locale, fictionGameplay);
|
|
791
|
+
const provided = definitions.map(({ name }) => name);
|
|
792
|
+
const resolved = resolveToolName(call.name, provided);
|
|
793
|
+
if (resolved.kind === "rejected")
|
|
794
|
+
return {
|
|
795
|
+
id: call.id,
|
|
796
|
+
name: call.name,
|
|
797
|
+
operation: null,
|
|
798
|
+
arguments: cloned,
|
|
799
|
+
coerced: [],
|
|
800
|
+
rejection: unknownToolMessage(call.name, provided, locale),
|
|
801
|
+
};
|
|
802
|
+
const name = resolved.name;
|
|
803
|
+
const schema = definitions.find((definition) => definition.name === name)?.inputSchema;
|
|
804
|
+
const repaired = schema === undefined
|
|
805
|
+
? { arguments: cloned, coerced: [] }
|
|
806
|
+
: coerceToolArguments(schema, cloned);
|
|
762
807
|
return {
|
|
763
808
|
id: call.id,
|
|
764
|
-
name
|
|
765
|
-
operation: authoringOperation(surface,
|
|
766
|
-
arguments:
|
|
809
|
+
name,
|
|
810
|
+
operation: authoringOperation(surface, name),
|
|
811
|
+
arguments: repaired.arguments,
|
|
812
|
+
coerced: repaired.coerced,
|
|
813
|
+
...(resolved.kind === "alias" ? { alias: resolved.declared } : {}),
|
|
767
814
|
};
|
|
768
815
|
}
|
|
816
|
+
function unknownToolMessage(name, provided, locale) {
|
|
817
|
+
return locale === "zh-CN"
|
|
818
|
+
? `${name} 不是本界面提供的工具。可用工具:${provided.join(", ")}。`
|
|
819
|
+
: `${name} is not a tool on this surface. Available tools: ${provided.join(", ")}.`;
|
|
820
|
+
}
|
|
769
821
|
function isReadOperation(operation) {
|
|
770
822
|
return operation === "list" || operation === "search" || operation === "read";
|
|
771
823
|
}
|
|
@@ -1474,6 +1526,8 @@ function requiredSettingRef(value, locale) {
|
|
|
1474
1526
|
return value;
|
|
1475
1527
|
}
|
|
1476
1528
|
function requiredAliases(value) {
|
|
1529
|
+
if (typeof value === "string")
|
|
1530
|
+
throw new SettingAuthoringError("aliases must be a JSON array of at most 16 strings, not a string");
|
|
1477
1531
|
if (!Array.isArray(value) ||
|
|
1478
1532
|
value.length > 16 ||
|
|
1479
1533
|
!value.every((item) => typeof item === "string" &&
|
|
@@ -1508,6 +1562,8 @@ function assertNoLiteralUnicodeEscapes(value, locale) {
|
|
|
1508
1562
|
walk(value);
|
|
1509
1563
|
}
|
|
1510
1564
|
function requiredYamlLocatorPath(value, name) {
|
|
1565
|
+
if (typeof value === "string")
|
|
1566
|
+
throw new SettingAuthoringError(`${name} must be a JSON array of map keys or zero-based array indexes, not a string`);
|
|
1511
1567
|
if (!Array.isArray(value) ||
|
|
1512
1568
|
value.length === 0 ||
|
|
1513
1569
|
!value.every((item) => (typeof item === "string" && item.length > 0) ||
|
|
@@ -16,6 +16,11 @@ export function isPromptGroup(value) {
|
|
|
16
16
|
/** Soft limits for the turn guide; exceeding them warns without rejecting. */
|
|
17
17
|
export const turnGuideLineSoftLimit = 120;
|
|
18
18
|
export const turnGuideLinesSoftLimit = 10;
|
|
19
|
+
/** One turn-guide line: no line breaks, bounded length; empty clears a builtin default. */
|
|
20
|
+
const turnGuideLinePattern = /^[^\r\n\0]{0,1000}$/u;
|
|
21
|
+
export function isTurnGuideLine(value) {
|
|
22
|
+
return turnGuideLinePattern.test(value);
|
|
23
|
+
}
|
|
19
24
|
/**
|
|
20
25
|
* Unscoped prompts always apply. A scoped prompt applies only when the compiled
|
|
21
26
|
* world or package is tabletop, so fiction requests never see it.
|
|
@@ -1,12 +1,37 @@
|
|
|
1
1
|
import { turnGuideLineSoftLimit, turnGuideLinesSoftLimit, } from "./ordered-play-prompts.js";
|
|
2
|
+
/** The source of the player's one-turn request line. */
|
|
3
|
+
export const turnNoteSource = "player:turn";
|
|
2
4
|
/**
|
|
3
5
|
* The fixed Runtime header. It is mechanical: it tells the model what the
|
|
4
6
|
* suffix is and that the prose, not a reply to the suffix, is wanted.
|
|
5
7
|
*/
|
|
6
8
|
export function turnGuideHeader(locale) {
|
|
7
9
|
return locale === "zh-CN"
|
|
8
|
-
? "[Runtime 本轮提示]\n
|
|
9
|
-
: "[Runtime turn guide]\nThese are the
|
|
10
|
+
? "[Runtime 本轮提示]\n以下是对这一轮正文的提示,来自预设、世界设定和玩家的临时要求。不要回应本提示,直接写正文。"
|
|
11
|
+
: "[Runtime turn guide]\nThese are notes for this turn's prose, from the preset, the world, and the player's requests for this turn. Do not reply to this notice; write the prose.";
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* The player's one-turn request as a turn-guide line. The prefix only names
|
|
15
|
+
* the source; it adds no constraint of its own.
|
|
16
|
+
*/
|
|
17
|
+
export function turnNoteLine(locale, turnNote) {
|
|
18
|
+
return {
|
|
19
|
+
source: turnNoteSource,
|
|
20
|
+
text: locale === "zh-CN"
|
|
21
|
+
? `玩家本轮要求:${turnNote}`
|
|
22
|
+
: `Player's request for this turn: ${turnNote}`,
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Appends the player's request line to a compiled turn guide, creating the
|
|
27
|
+
* suffix when no preset or world line exists. Without a request the guide is
|
|
28
|
+
* returned unchanged.
|
|
29
|
+
*/
|
|
30
|
+
export function turnGuideWithTurnNote(locale, guide, turnNote) {
|
|
31
|
+
if (turnNote === undefined)
|
|
32
|
+
return guide;
|
|
33
|
+
const lines = [...(guide?.lines ?? []), turnNoteLine(locale, turnNote)];
|
|
34
|
+
return { text: turnGuideText(locale, lines), lines };
|
|
10
35
|
}
|
|
11
36
|
/** The complete suffix text: header, then one line per enabled entry in list order. */
|
|
12
37
|
export function turnGuideText(locale, lines) {
|