@actalk/inkos-core 1.5.0 → 1.6.1

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.
Files changed (187) hide show
  1. package/dist/agent/agent-session.d.ts +4 -0
  2. package/dist/agent/agent-session.d.ts.map +1 -1
  3. package/dist/agent/agent-session.js +78 -5
  4. package/dist/agent/agent-session.js.map +1 -1
  5. package/dist/agent/agent-system-prompt.d.ts +2 -0
  6. package/dist/agent/agent-system-prompt.d.ts.map +1 -1
  7. package/dist/agent/agent-system-prompt.js +181 -16
  8. package/dist/agent/agent-system-prompt.js.map +1 -1
  9. package/dist/agent/agent-tools.d.ts +97 -1
  10. package/dist/agent/agent-tools.d.ts.map +1 -1
  11. package/dist/agent/agent-tools.js +434 -3
  12. package/dist/agent/agent-tools.js.map +1 -1
  13. package/dist/agent/film-authoring-tools.d.ts +89 -0
  14. package/dist/agent/film-authoring-tools.d.ts.map +1 -0
  15. package/dist/agent/film-authoring-tools.js +336 -0
  16. package/dist/agent/film-authoring-tools.js.map +1 -0
  17. package/dist/agent/index.d.ts +2 -1
  18. package/dist/agent/index.d.ts.map +1 -1
  19. package/dist/agent/index.js +2 -1
  20. package/dist/agent/index.js.map +1 -1
  21. package/dist/agent/llm-stub.d.ts +19 -0
  22. package/dist/agent/llm-stub.d.ts.map +1 -0
  23. package/dist/agent/llm-stub.js +134 -0
  24. package/dist/agent/llm-stub.js.map +1 -0
  25. package/dist/agents/composer.d.ts.map +1 -1
  26. package/dist/agents/composer.js +24 -12
  27. package/dist/agents/composer.js.map +1 -1
  28. package/dist/agents/researcher.d.ts +38 -0
  29. package/dist/agents/researcher.d.ts.map +1 -0
  30. package/dist/agents/researcher.js +164 -0
  31. package/dist/agents/researcher.js.map +1 -0
  32. package/dist/agents/script-storyboard.d.ts +51 -0
  33. package/dist/agents/script-storyboard.d.ts.map +1 -0
  34. package/dist/agents/script-storyboard.js +368 -0
  35. package/dist/agents/script-storyboard.js.map +1 -0
  36. package/dist/index.d.ts +23 -2
  37. package/dist/index.d.ts.map +1 -1
  38. package/dist/index.js +24 -2
  39. package/dist/index.js.map +1 -1
  40. package/dist/interaction/action-envelope.d.ts +669 -1
  41. package/dist/interaction/action-envelope.d.ts.map +1 -1
  42. package/dist/interaction/action-envelope.js +87 -0
  43. package/dist/interaction/action-envelope.js.map +1 -1
  44. package/dist/interaction/edit-controller.d.ts.map +1 -1
  45. package/dist/interaction/edit-controller.js +91 -1
  46. package/dist/interaction/edit-controller.js.map +1 -1
  47. package/dist/interaction/intents.d.ts +2 -2
  48. package/dist/interaction/project-control.d.ts +1 -1
  49. package/dist/interaction/session-transcript-schema.d.ts +22 -22
  50. package/dist/interaction/session.d.ts +14 -14
  51. package/dist/interaction/session.d.ts.map +1 -1
  52. package/dist/interaction/session.js +1 -1
  53. package/dist/interaction/session.js.map +1 -1
  54. package/dist/interactive-film/authoring-generate.d.ts +4 -0
  55. package/dist/interactive-film/authoring-generate.d.ts.map +1 -0
  56. package/dist/interactive-film/authoring-generate.js +16 -0
  57. package/dist/interactive-film/authoring-generate.js.map +1 -0
  58. package/dist/interactive-film/authoring-store.d.ts +35 -0
  59. package/dist/interactive-film/authoring-store.d.ts.map +1 -0
  60. package/dist/interactive-film/authoring-store.js +114 -0
  61. package/dist/interactive-film/authoring-store.js.map +1 -0
  62. package/dist/interactive-film/authoring-tools.d.ts +9 -0
  63. package/dist/interactive-film/authoring-tools.d.ts.map +1 -0
  64. package/dist/interactive-film/authoring-tools.js +19 -0
  65. package/dist/interactive-film/authoring-tools.js.map +1 -0
  66. package/dist/interactive-film/delta.d.ts +591 -0
  67. package/dist/interactive-film/delta.d.ts.map +1 -0
  68. package/dist/interactive-film/delta.js +54 -0
  69. package/dist/interactive-film/delta.js.map +1 -0
  70. package/dist/interactive-film/emotion.d.ts +20 -0
  71. package/dist/interactive-film/emotion.d.ts.map +1 -0
  72. package/dist/interactive-film/emotion.js +57 -0
  73. package/dist/interactive-film/emotion.js.map +1 -0
  74. package/dist/interactive-film/evaluator.d.ts +7 -0
  75. package/dist/interactive-film/evaluator.d.ts.map +1 -0
  76. package/dist/interactive-film/evaluator.js +40 -0
  77. package/dist/interactive-film/evaluator.js.map +1 -0
  78. package/dist/interactive-film/export-html.d.ts +6 -0
  79. package/dist/interactive-film/export-html.d.ts.map +1 -0
  80. package/dist/interactive-film/export-html.js +84 -0
  81. package/dist/interactive-film/export-html.js.map +1 -0
  82. package/dist/interactive-film/export-ink.d.ts +3 -0
  83. package/dist/interactive-film/export-ink.d.ts.map +1 -0
  84. package/dist/interactive-film/export-ink.js +51 -0
  85. package/dist/interactive-film/export-ink.js.map +1 -0
  86. package/dist/interactive-film/film-context.d.ts +4 -0
  87. package/dist/interactive-film/film-context.d.ts.map +1 -0
  88. package/dist/interactive-film/film-context.js +30 -0
  89. package/dist/interactive-film/film-context.js.map +1 -0
  90. package/dist/interactive-film/generate.d.ts +13 -0
  91. package/dist/interactive-film/generate.d.ts.map +1 -0
  92. package/dist/interactive-film/generate.js +32 -0
  93. package/dist/interactive-film/generate.js.map +1 -0
  94. package/dist/interactive-film/graph-schema.d.ts +819 -0
  95. package/dist/interactive-film/graph-schema.d.ts.map +1 -0
  96. package/dist/interactive-film/graph-schema.js +84 -0
  97. package/dist/interactive-film/graph-schema.js.map +1 -0
  98. package/dist/interactive-film/graph-store.d.ts +5 -0
  99. package/dist/interactive-film/graph-store.d.ts.map +1 -0
  100. package/dist/interactive-film/graph-store.js +24 -0
  101. package/dist/interactive-film/graph-store.js.map +1 -0
  102. package/dist/interactive-film/memory-link.d.ts +9 -0
  103. package/dist/interactive-film/memory-link.d.ts.map +1 -0
  104. package/dist/interactive-film/memory-link.js +15 -0
  105. package/dist/interactive-film/memory-link.js.map +1 -0
  106. package/dist/interactive-film/node-image.d.ts +29 -0
  107. package/dist/interactive-film/node-image.d.ts.map +1 -0
  108. package/dist/interactive-film/node-image.js +52 -0
  109. package/dist/interactive-film/node-image.js.map +1 -0
  110. package/dist/interactive-film/paths.d.ts +14 -0
  111. package/dist/interactive-film/paths.d.ts.map +1 -0
  112. package/dist/interactive-film/paths.js +60 -0
  113. package/dist/interactive-film/paths.js.map +1 -0
  114. package/dist/interactive-film/validation.d.ts +14 -0
  115. package/dist/interactive-film/validation.d.ts.map +1 -0
  116. package/dist/interactive-film/validation.js +292 -0
  117. package/dist/interactive-film/validation.js.map +1 -0
  118. package/dist/llm/provider.d.ts.map +1 -1
  119. package/dist/llm/provider.js +53 -16
  120. package/dist/llm/provider.js.map +1 -1
  121. package/dist/models/book.d.ts +13 -0
  122. package/dist/models/book.d.ts.map +1 -1
  123. package/dist/models/book.js +3 -0
  124. package/dist/models/book.js.map +1 -1
  125. package/dist/models/input-governance.d.ts +14 -5
  126. package/dist/models/input-governance.d.ts.map +1 -1
  127. package/dist/models/input-governance.js +3 -0
  128. package/dist/models/input-governance.js.map +1 -1
  129. package/dist/models/project.d.ts +63 -10
  130. package/dist/models/project.d.ts.map +1 -1
  131. package/dist/models/project.js +11 -0
  132. package/dist/models/project.js.map +1 -1
  133. package/dist/pipeline/runner.js +1 -1
  134. package/dist/pipeline/runner.js.map +1 -1
  135. package/dist/pipeline/script-storyboard-runner.d.ts +127 -0
  136. package/dist/pipeline/script-storyboard-runner.d.ts.map +1 -0
  137. package/dist/pipeline/script-storyboard-runner.js +446 -0
  138. package/dist/pipeline/script-storyboard-runner.js.map +1 -0
  139. package/dist/play/play-agents.d.ts.map +1 -1
  140. package/dist/play/play-agents.js +5 -2
  141. package/dist/play/play-agents.js.map +1 -1
  142. package/dist/play/play-store.d.ts +2 -2
  143. package/dist/skills/builtin-prompts.d.ts +10 -0
  144. package/dist/skills/builtin-prompts.d.ts.map +1 -0
  145. package/dist/skills/builtin-prompts.js +152 -0
  146. package/dist/skills/builtin-prompts.js.map +1 -0
  147. package/dist/skills/builtin.d.ts +3 -0
  148. package/dist/skills/builtin.d.ts.map +1 -0
  149. package/dist/skills/builtin.js +252 -0
  150. package/dist/skills/builtin.js.map +1 -0
  151. package/dist/skills/context-planner.d.ts +17 -0
  152. package/dist/skills/context-planner.d.ts.map +1 -0
  153. package/dist/skills/context-planner.js +48 -0
  154. package/dist/skills/context-planner.js.map +1 -0
  155. package/dist/skills/external-loader.d.ts +20 -0
  156. package/dist/skills/external-loader.d.ts.map +1 -0
  157. package/dist/skills/external-loader.js +126 -0
  158. package/dist/skills/external-loader.js.map +1 -0
  159. package/dist/skills/index.d.ts +8 -0
  160. package/dist/skills/index.d.ts.map +1 -0
  161. package/dist/skills/index.js +8 -0
  162. package/dist/skills/index.js.map +1 -0
  163. package/dist/skills/prompt-pack.d.ts +33 -0
  164. package/dist/skills/prompt-pack.d.ts.map +1 -0
  165. package/dist/skills/prompt-pack.js +82 -0
  166. package/dist/skills/prompt-pack.js.map +1 -0
  167. package/dist/skills/registry.d.ts +6 -0
  168. package/dist/skills/registry.d.ts.map +1 -0
  169. package/dist/skills/registry.js +101 -0
  170. package/dist/skills/registry.js.map +1 -0
  171. package/dist/skills/types.d.ts +146 -0
  172. package/dist/skills/types.d.ts.map +1 -0
  173. package/dist/skills/types.js +32 -0
  174. package/dist/skills/types.js.map +1 -0
  175. package/dist/state/manager.d.ts +8 -2
  176. package/dist/state/manager.d.ts.map +1 -1
  177. package/dist/state/manager.js +58 -5
  178. package/dist/state/manager.js.map +1 -1
  179. package/dist/utils/context-assembly.d.ts +3 -0
  180. package/dist/utils/context-assembly.d.ts.map +1 -1
  181. package/dist/utils/context-assembly.js +3 -0
  182. package/dist/utils/context-assembly.js.map +1 -1
  183. package/dist/utils/web-search.d.ts +6 -1
  184. package/dist/utils/web-search.d.ts.map +1 -1
  185. package/dist/utils/web-search.js +8 -4
  186. package/dist/utils/web-search.js.map +1 -1
  187. package/package.json +14 -3
@@ -0,0 +1,57 @@
1
+ import { enumerateRuntimePaths } from "./paths.js";
2
+ // Initial lexicon (extendable). Maps common Chinese emotion words to a valence in [-1,1].
3
+ const EMOTION_LEXICON = {
4
+ "喜悦": 0.9, "高兴": 0.8, "快乐": 0.8, "希望": 0.6, "坚定": 0.5, "温暖": 0.6, "感动": 0.6, "释然": 0.4, "平静": 0.0, "中性": 0.0,
5
+ "紧张": -0.4, "焦虑": -0.5, "愤怒": -0.6, "恐惧": -0.7, "悲伤": -0.8, "绝望": -0.95, "痛苦": -0.8, "失落": -0.5, "犹豫": -0.2, "冷漠": -0.3,
6
+ };
7
+ export function emotionScore(word) {
8
+ const w = word.trim();
9
+ if (!w)
10
+ return 0;
11
+ if (w in EMOTION_LEXICON)
12
+ return EMOTION_LEXICON[w];
13
+ // partial match: if any lexicon key is contained in the word (e.g. "很悲伤")
14
+ // Negation guard: if the character immediately before the matched key is a negation character
15
+ // (不/没/无/别/未), flip the valence so "不高兴" scores negative rather than positive.
16
+ for (const key of Object.keys(EMOTION_LEXICON)) {
17
+ if (w.includes(key)) {
18
+ const keyIdx = w.indexOf(key);
19
+ const charBefore = keyIdx > 0 ? w[keyIdx - 1] : "";
20
+ if ("不没无别未".includes(charBefore))
21
+ return -EMOTION_LEXICON[key];
22
+ return EMOTION_LEXICON[key];
23
+ }
24
+ }
25
+ return 0;
26
+ }
27
+ export function nodeEmotion(node) {
28
+ const lines = node.dialogue ?? [];
29
+ if (lines.length === 0)
30
+ return 0;
31
+ const sum = lines.reduce((acc, l) => acc + emotionScore(l.emotion), 0);
32
+ return sum / lines.length;
33
+ }
34
+ export function analyzeEmotionalArcs(graph) {
35
+ const { paths, truncated } = enumerateRuntimePaths(graph);
36
+ const nodeById = new Map(graph.nodes.map((n) => [n.id, n]));
37
+ const arcs = paths.map((p) => ({
38
+ endingId: p.endingId,
39
+ points: p.nodeIds.map((id) => {
40
+ const node = nodeById.get(id);
41
+ return { nodeId: id, score: node ? nodeEmotion(node) : 0 };
42
+ }),
43
+ }));
44
+ return { arcs, truncated };
45
+ }
46
+ export function analyzePathDistribution(graph) {
47
+ const { paths, truncated } = enumerateRuntimePaths(graph);
48
+ const byEnding = {};
49
+ const lengthHistogram = {};
50
+ for (const p of paths) {
51
+ const key = p.endingId ?? "(dead-end)";
52
+ byEnding[key] = (byEnding[key] ?? 0) + 1;
53
+ lengthHistogram[p.length] = (lengthHistogram[p.length] ?? 0) + 1;
54
+ }
55
+ return { total: paths.length, truncated, byEnding, lengthHistogram };
56
+ }
57
+ //# sourceMappingURL=emotion.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"emotion.js","sourceRoot":"","sources":["../../src/interactive-film/emotion.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import type { Condition, Effect, StoryNode, Choice, Variable, VarValue } from "./graph-schema.js";
2
+ export type VarState = Record<string, VarValue>;
3
+ export declare function evaluateCondition(condition: Condition | undefined, vars: VarState): boolean;
4
+ export declare function applyEffects(vars: VarState, effects: readonly Effect[] | undefined): VarState;
5
+ export declare function visibleChoices(node: StoryNode, vars: VarState): Choice[];
6
+ export declare function initVarState(variables: readonly Variable[]): VarState;
7
+ //# sourceMappingURL=evaluator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"evaluator.d.ts","sourceRoot":"","sources":["../../src/interactive-film/evaluator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAElG,MAAM,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;AAEhD,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,SAAS,GAAG,SAAS,EAAE,IAAI,EAAE,QAAQ,GAAG,OAAO,CAY3F;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,GAAG,QAAQ,CAa7F;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,QAAQ,GAAG,MAAM,EAAE,CAExE;AAED,wBAAgB,YAAY,CAAC,SAAS,EAAE,SAAS,QAAQ,EAAE,GAAG,QAAQ,CAIrE"}
@@ -0,0 +1,40 @@
1
+ export function evaluateCondition(condition, vars) {
2
+ if (!condition)
3
+ return true;
4
+ const lhs = vars[condition.var];
5
+ const rhs = condition.value;
6
+ switch (condition.op) {
7
+ case "==": return lhs === rhs;
8
+ case "!=": return lhs !== rhs;
9
+ case ">=": return Number(lhs) >= Number(rhs);
10
+ case "<=": return Number(lhs) <= Number(rhs);
11
+ case ">": return Number(lhs) > Number(rhs);
12
+ case "<": return Number(lhs) < Number(rhs);
13
+ }
14
+ }
15
+ export function applyEffects(vars, effects) {
16
+ if (!effects || effects.length === 0)
17
+ return vars;
18
+ const next = { ...vars };
19
+ for (const e of effects) {
20
+ if (e.op === "set") {
21
+ next[e.var] = e.value;
22
+ }
23
+ else {
24
+ const cur = Number(next[e.var] ?? 0);
25
+ const delta = Number(e.value);
26
+ next[e.var] = e.op === "add" ? cur + delta : cur - delta;
27
+ }
28
+ }
29
+ return next;
30
+ }
31
+ export function visibleChoices(node, vars) {
32
+ return node.choices.filter((c) => evaluateCondition(c.condition, vars));
33
+ }
34
+ export function initVarState(variables) {
35
+ const state = {};
36
+ for (const v of variables)
37
+ state[v.name] = v.default;
38
+ return state;
39
+ }
40
+ //# sourceMappingURL=evaluator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"evaluator.js","sourceRoot":"","sources":["../../src/interactive-film/evaluator.ts"],"names":[],"mappings":"AAIA,MAAM,UAAU,iBAAiB,CAAC,SAAgC,EAAE,IAAc;IAChF,IAAI,CAAC,SAAS;QAAE,OAAO,IAAI,CAAC;IAC5B,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;IAChC,MAAM,GAAG,GAAG,SAAS,CAAC,KAAK,CAAC;IAC5B,QAAQ,SAAS,CAAC,EAAE,EAAE,CAAC;QACrB,KAAK,IAAI,CAAC,CAAC,OAAO,GAAG,KAAK,GAAG,CAAC;QAC9B,KAAK,IAAI,CAAC,CAAC,OAAO,GAAG,KAAK,GAAG,CAAC;QAC9B,KAAK,IAAI,CAAC,CAAC,OAAO,MAAM,CAAC,GAAG,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC;QAC7C,KAAK,IAAI,CAAC,CAAC,OAAO,MAAM,CAAC,GAAG,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC;QAC7C,KAAK,GAAG,CAAC,CAAE,OAAO,MAAM,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;QAC5C,KAAK,GAAG,CAAC,CAAE,OAAO,MAAM,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;IAC9C,CAAC;AACH,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,IAAc,EAAE,OAAsC;IACjF,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAClD,MAAM,IAAI,GAAa,EAAE,GAAG,IAAI,EAAE,CAAC;IACnC,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;QACxB,IAAI,CAAC,CAAC,EAAE,KAAK,KAAK,EAAE,CAAC;YACnB,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC;QACxB,CAAC;aAAM,CAAC;YACN,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;YACrC,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;YAC9B,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,KAAK,CAAC,CAAC,CAAC,GAAG,GAAG,KAAK,CAAC,CAAC,CAAC,GAAG,GAAG,KAAK,CAAC;QAC3D,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,IAAe,EAAE,IAAc;IAC5D,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,CAAC,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC,CAAC;AAC1E,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,SAA8B;IACzD,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,MAAM,CAAC,IAAI,SAAS;QAAE,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC;IACrD,OAAO,KAAK,CAAC;AACf,CAAC"}
@@ -0,0 +1,6 @@
1
+ import type { StoryGraph } from "./graph-schema.js";
2
+ export declare function buildPlayableHtml(graph: StoryGraph, opts?: {
3
+ assetDataUris?: Record<string, string>;
4
+ title?: string;
5
+ }): string;
6
+ //# sourceMappingURL=export-html.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"export-html.d.ts","sourceRoot":"","sources":["../../src/interactive-film/export-html.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AA6EpD,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,UAAU,EACjB,IAAI,CAAC,EAAE;IAAE,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,GAChE,MAAM,CAWR"}
@@ -0,0 +1,84 @@
1
+ const PLAYER_JS = String.raw `
2
+ (function(){
3
+ function h(s){ return String(s==null?"":s).replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;"); }
4
+ var vars = {};
5
+ (GRAPH.variables||[]).forEach(function(v){ vars[v.name] = v.default; });
6
+ var nodeById = {}; (GRAPH.nodes||[]).forEach(function(n){ nodeById[n.id] = n; });
7
+ var endingByNode = {}; (GRAPH.endings||[]).forEach(function(e){ endingByNode[e.nodeId] = e; });
8
+ function evalCond(c){ if(!c) return true; var v = vars[c.var];
9
+ switch(c.op){ case ">=": return Number(v)>=Number(c.value); case "<=": return Number(v)<=Number(c.value); case ">": return Number(v)>Number(c.value); case "<": return Number(v)<Number(c.value); case "==": return v===c.value; case "!=": return v!==c.value; } return true; }
10
+ function applyEffects(effects){ (effects||[]).forEach(function(e){
11
+ if(e.op==="add") vars[e.var]=Number(vars[e.var]||0)+Number(e.value); else if(e.op==="sub") vars[e.var]=Number(vars[e.var]||0)-Number(e.value); else vars[e.var]=e.value; }); }
12
+ function visible(node){ return (node.choices||[]).filter(function(c){ return evalCond(c.condition); }); }
13
+ var root = document.getElementById("if-player");
14
+ function hud(){ var s = Object.keys(vars).map(function(k){ return h(k)+": "+h(String(vars[k])); }).join(" · "); return s ? '<div class="hud">'+s+'</div>' : ''; }
15
+ function render(node){
16
+ if(!node){ root.innerHTML = "<p>节点缺失</p>"; return; }
17
+ var html = hud();
18
+ if(node.imageSlot && node.imageSlot.assetRef && ASSETS[node.imageSlot.assetRef]) html += '<img class="scene" src="'+ASSETS[node.imageSlot.assetRef]+'" alt=""/>';
19
+ if(node.title) html += '<h2>'+h(node.title)+'</h2>';
20
+ if(node.sceneDesc) html += '<p class="scene-desc">'+h(node.sceneDesc)+'</p>';
21
+ (node.dialogue||[]).forEach(function(d){ html += '<p class="line"><b>'+h(d.speaker)+':</b>'+h(d.text)+'</p>'; });
22
+ var end = endingByNode[node.id] || node.type==="ending";
23
+ if(end){ var e = endingByNode[node.id];
24
+ html += '<div class="ending"><div class="ending-type">'+h(e?e.type:"ending")+'</div><div class="ending-title">'+h(e?e.title:(node.title||"结局"))+'</div></div>';
25
+ html += '<button class="restart">重新开始</button>';
26
+ root.innerHTML = html;
27
+ root.querySelector(".restart").onclick = function(){ start(); };
28
+ return;
29
+ }
30
+ var vis = visible(node);
31
+ html += '<div class="choices">';
32
+ vis.forEach(function(c,i){ html += '<button class="choice" data-i="'+i+'">'+h(c.text)+'</button>'; });
33
+ html += '</div>';
34
+ if(vis.length===0) html += '<p class="deadend">(没有可走的选项)</p>';
35
+ root.innerHTML = html;
36
+ Array.prototype.forEach.call(root.querySelectorAll(".choice"), function(btn){
37
+ btn.onclick = function(){ var c = vis[parseInt(btn.getAttribute("data-i"),10)]; applyEffects(c.effects); render(nodeById[c.targetNodeId]); };
38
+ });
39
+ }
40
+ function start(){ vars = {}; (GRAPH.variables||[]).forEach(function(v){ vars[v.name]=v.default; }); var s = (GRAPH.nodes||[]).filter(function(n){return n.type==="start";})[0] || GRAPH.nodes[0]; render(s); }
41
+ start();
42
+ })();
43
+ `;
44
+ const CSS = String.raw `
45
+ body{font-family:system-ui,'PingFang SC',sans-serif;background:#14110f;color:#eee;margin:0;display:flex;justify-content:center;}
46
+ #wrap{max-width:680px;width:100%;padding:24px;}
47
+ h1{font-size:18px;color:#caa;}
48
+ #if-player .scene{width:100%;border-radius:10px;margin-bottom:12px;}
49
+ #if-player h2{font-size:20px;margin:8px 0;}
50
+ .scene-desc{color:#bbb;} .line{margin:6px 0;} .line b{color:#d8b27a;}
51
+ .hud{font-size:12px;color:#998;border:1px solid #333;border-radius:8px;padding:6px 10px;margin-bottom:12px;display:inline-block;}
52
+ .choices{display:flex;flex-direction:column;gap:8px;margin-top:16px;}
53
+ .choice{text-align:left;padding:12px 16px;border:1px solid #444;border-radius:10px;background:#1d1916;color:#eee;cursor:pointer;font-size:15px;}
54
+ .choice:hover{border-color:#caa;}
55
+ .ending{margin-top:20px;padding:16px;border:1px solid #553;border-radius:10px;}
56
+ .ending-type{font-size:12px;color:#caa;text-transform:uppercase;} .ending-title{font-size:22px;margin-top:4px;}
57
+ .restart{margin-top:12px;padding:10px 18px;border-radius:8px;background:#caa;color:#14110f;border:none;cursor:pointer;}
58
+ `;
59
+ // Escape only `<` so an embedded `</script>` inside a JSON string value cannot break out of the <script> tag.
60
+ // JSON.parse reads < back as `<`. Do NOT strip whitespace.
61
+ function esc(s) {
62
+ return s.replace(/</g, "\\u003c");
63
+ }
64
+ // Escape user-controlled strings before interpolating into the HTML template itself (title, h1).
65
+ function escHtml(s) {
66
+ return s
67
+ .replace(/&/g, "&amp;")
68
+ .replace(/</g, "&lt;")
69
+ .replace(/>/g, "&gt;")
70
+ .replace(/"/g, "&quot;");
71
+ }
72
+ export function buildPlayableHtml(graph, opts) {
73
+ const title = opts?.title ?? graph.title ?? graph.projectId;
74
+ const graphJson = esc(JSON.stringify(graph));
75
+ const assetsJson = esc(JSON.stringify(opts?.assetDataUris ?? {}));
76
+ return `<!doctype html>
77
+ <html lang="zh"><head><meta charset="utf-8"/><meta name="viewport" content="width=device-width,initial-scale=1"/>
78
+ <title>${escHtml(title)}</title><style>${CSS}</style></head>
79
+ <body><div id="wrap"><h1>${escHtml(title)}</h1><div id="if-player" data-if-player></div></div>
80
+ <script>var GRAPH=${graphJson};var ASSETS=${assetsJson};</script>
81
+ <script>${PLAYER_JS}</script>
82
+ </body></html>`;
83
+ }
84
+ //# sourceMappingURL=export-html.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"export-html.js","sourceRoot":"","sources":["../../src/interactive-film/export-html.ts"],"names":[],"mappings":"AAEA,MAAM,SAAS,GAAG,MAAM,CAAC,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA0C3B,CAAC;AAEF,MAAM,GAAG,GAAG,MAAM,CAAC,GAAG,CAAA;;;;;;;;;;;;;;CAcrB,CAAC;AAEF,8GAA8G;AAC9G,2DAA2D;AAC3D,SAAS,GAAG,CAAC,CAAS;IACpB,OAAO,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;AACpC,CAAC;AAED,iGAAiG;AACjG,SAAS,OAAO,CAAC,CAAS;IACxB,OAAO,CAAC;SACL,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC;SACtB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;AAC7B,CAAC;AAED,MAAM,UAAU,iBAAiB,CAC/B,KAAiB,EACjB,IAAiE;IAEjE,MAAM,KAAK,GAAG,IAAI,EAAE,KAAK,IAAI,KAAK,CAAC,KAAK,IAAI,KAAK,CAAC,SAAS,CAAC;IAC5D,MAAM,SAAS,GAAG,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC;IAC7C,MAAM,UAAU,GAAG,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,aAAa,IAAI,EAAE,CAAC,CAAC,CAAC;IAClE,OAAO;;SAEA,OAAO,CAAC,KAAK,CAAC,kBAAkB,GAAG;2BACjB,OAAO,CAAC,KAAK,CAAC;oBACrB,SAAS,eAAe,UAAU;UAC5C,SAAS;eACJ,CAAC;AAChB,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { StoryGraph } from "./graph-schema.js";
2
+ export declare function exportInk(graph: StoryGraph): string;
3
+ //# sourceMappingURL=export-ink.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"export-ink.d.ts","sourceRoot":"","sources":["../../src/interactive-film/export-ink.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAqB,MAAM,mBAAmB,CAAC;AAcvE,wBAAgB,SAAS,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CA4BnD"}
@@ -0,0 +1,51 @@
1
+ function sanitize(id) {
2
+ const s = id.replace(/[^A-Za-z0-9_]/g, "_");
3
+ return /^[0-9]/.test(s) ? `n_${s}` : s;
4
+ }
5
+ const knot = (id) => `node_${sanitize(id)}`;
6
+ const effectLine = (e) => {
7
+ const v = typeof e.value === "string" ? JSON.stringify(e.value) : String(e.value);
8
+ if (e.op === "add")
9
+ return ` ~ ${sanitize(e.var)} += ${v}`;
10
+ if (e.op === "sub")
11
+ return ` ~ ${sanitize(e.var)} -= ${v}`;
12
+ return ` ~ ${sanitize(e.var)} = ${v}`; // set
13
+ };
14
+ export function exportInk(graph) {
15
+ const lines = [];
16
+ lines.push(`// ${graph.title || graph.projectId} — exported from InkOS interactive film`);
17
+ for (const v of graph.variables) {
18
+ const d = typeof v.default === "string" ? JSON.stringify(v.default) : String(v.default);
19
+ lines.push(`VAR ${sanitize(v.name)} = ${d}`);
20
+ }
21
+ const start = graph.nodes.find((n) => n.type === "start") ?? graph.nodes[0];
22
+ if (start)
23
+ lines.push("", `-> ${knot(start.id)}`);
24
+ const endingNodeIds = new Set(graph.endings.map((e) => e.nodeId));
25
+ for (const node of graph.nodes) {
26
+ lines.push("", `=== ${knot(node.id)} ===`);
27
+ if (node.title)
28
+ lines.push(`# ${node.title}`);
29
+ if (node.sceneDesc)
30
+ lines.push(node.sceneDesc);
31
+ for (const d of node.dialogue ?? [])
32
+ lines.push(`${d.speaker}: ${d.text}`);
33
+ if (node.type === "ending" || endingNodeIds.has(node.id)) {
34
+ lines.push("-> END");
35
+ continue;
36
+ }
37
+ if (node.choices.length === 0) {
38
+ lines.push("-> END");
39
+ continue;
40
+ }
41
+ for (const c of node.choices) {
42
+ const cond = c.condition ? ` {${sanitize(c.condition.var)} ${c.condition.op} ${typeof c.condition.value === "string" ? JSON.stringify(c.condition.value) : c.condition.value}}` : "";
43
+ lines.push(`*${cond} [${c.text}]`);
44
+ for (const e of c.effects ?? [])
45
+ lines.push(effectLine(e));
46
+ lines.push(` -> ${knot(c.targetNodeId)}`);
47
+ }
48
+ }
49
+ return lines.join("\n") + "\n";
50
+ }
51
+ //# sourceMappingURL=export-ink.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"export-ink.js","sourceRoot":"","sources":["../../src/interactive-film/export-ink.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { StoryGraph } from "./graph-schema.js";
2
+ export declare function summarizeStoryGraph(graph: StoryGraph): string;
3
+ export declare function buildFilmAuthoringContext(graph: StoryGraph): string;
4
+ //# sourceMappingURL=film-context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"film-context.d.ts","sourceRoot":"","sources":["../../src/interactive-film/film-context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAEpD,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAgB7D;AAED,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAWnE"}
@@ -0,0 +1,30 @@
1
+ export function summarizeStoryGraph(graph) {
2
+ const lines = [];
3
+ lines.push(`# 互动影游:${graph.title || graph.projectId}`);
4
+ if (graph.worldAnchor) {
5
+ const w = graph.worldAnchor;
6
+ lines.push(`核心:${w.storyCore} / 主题:${w.theme} / 题材:${w.genre} / 规则:${w.worldRules} / 时长:${w.durationMinutes}分`);
7
+ }
8
+ if (graph.variables.length > 0) {
9
+ lines.push(`变量:${graph.variables.map((v) => v.name).join(", ")}`);
10
+ }
11
+ lines.push("节点:");
12
+ for (const n of graph.nodes) {
13
+ const edges = n.choices.map((c) => `${c.text}→${c.targetNodeId}`).join(", ");
14
+ lines.push(`- ${n.id}[${n.type}] ${n.title}${edges ? ` -> ${edges}` : ""}`);
15
+ }
16
+ return lines.join("\n");
17
+ }
18
+ export function buildFilmAuthoringContext(graph) {
19
+ const blocks = [summarizeStoryGraph(graph)];
20
+ if (graph.characters.length > 0) {
21
+ const chars = graph.characters.map((c) => {
22
+ const vp = c.voiceProfile;
23
+ const voice = vp ? [vp.speakingRhythm, vp.vocabulary].filter(Boolean).join(" / ") : "";
24
+ return `- ${c.name}(${c.role})动机:${c.motivation}${voice ? ` 口吻:${voice}` : ""}`;
25
+ });
26
+ blocks.push(["角色档案:", ...chars].join("\n"));
27
+ }
28
+ return blocks.join("\n\n");
29
+ }
30
+ //# sourceMappingURL=film-context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"film-context.js","sourceRoot":"","sources":["../../src/interactive-film/film-context.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,mBAAmB,CAAC,KAAiB;IACnD,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,CAAC,IAAI,CAAC,UAAU,KAAK,CAAC,KAAK,IAAI,KAAK,CAAC,SAAS,EAAE,CAAC,CAAC;IACvD,IAAI,KAAK,CAAC,WAAW,EAAE,CAAC;QACtB,MAAM,CAAC,GAAG,KAAK,CAAC,WAAW,CAAC;QAC5B,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,SAAS,SAAS,CAAC,CAAC,KAAK,SAAS,CAAC,CAAC,KAAK,SAAS,CAAC,CAAC,UAAU,SAAS,CAAC,CAAC,eAAe,GAAG,CAAC,CAAC;IAClH,CAAC;IACD,IAAI,KAAK,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC/B,KAAK,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACpE,CAAC;IACD,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAClB,KAAK,MAAM,CAAC,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;QAC5B,MAAM,KAAK,GAAG,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,YAAY,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC7E,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,OAAO,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAC9E,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED,MAAM,UAAU,yBAAyB,CAAC,KAAiB;IACzD,MAAM,MAAM,GAAa,CAAC,mBAAmB,CAAC,KAAK,CAAC,CAAC,CAAC;IACtD,IAAI,KAAK,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAChC,MAAM,KAAK,GAAG,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;YACvC,MAAM,EAAE,GAAG,CAAC,CAAC,YAAY,CAAC;YAC1B,MAAM,KAAK,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,cAAc,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YACvF,OAAO,KAAK,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,IAAI,OAAO,CAAC,CAAC,UAAU,GAAG,KAAK,CAAC,CAAC,CAAC,OAAO,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;QAClF,CAAC,CAAC,CAAC;QACH,MAAM,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,GAAG,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IAC9C,CAAC;IACD,OAAO,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AAC7B,CAAC"}
@@ -0,0 +1,13 @@
1
+ import { type LLMClient } from "../llm/provider.js";
2
+ import { type StoryGraph } from "./graph-schema.js";
3
+ export declare function extractJson(text: string): unknown;
4
+ export declare function buildStoryGraphFromLLMText(text: string, projectId: string): StoryGraph;
5
+ export interface GenerateStoryGraphInput {
6
+ readonly projectId: string;
7
+ readonly title: string;
8
+ readonly premise: string;
9
+ }
10
+ export declare function generateStoryGraph(client: LLMClient, model: string, input: GenerateStoryGraphInput, options?: {
11
+ readonly maxTokens?: number;
12
+ }): Promise<StoryGraph>;
13
+ //# sourceMappingURL=generate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate.d.ts","sourceRoot":"","sources":["../../src/interactive-film/generate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,KAAK,SAAS,EAAE,MAAM,oBAAoB,CAAC;AACpE,OAAO,EAAoB,KAAK,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAOtE,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CASjD;AAED,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,UAAU,CAOtF;AAED,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,SAAS,EACjB,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,uBAAuB,EAC9B,OAAO,CAAC,EAAE;IAAE,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,GACxC,OAAO,CAAC,UAAU,CAAC,CAMrB"}
@@ -0,0 +1,32 @@
1
+ import { chatCompletion } from "../llm/provider.js";
2
+ import { StoryGraphSchema } from "./graph-schema.js";
3
+ const SYSTEM_PROMPT = `你是互动影游编剧。根据用户的故事前提,生成一个小而完整的可玩分支图。
4
+ 严格只输出 JSON,结构如下:
5
+ {"schemaVersion":1,"projectId":"","title":"","variables":[{"name":"","type":"flag|counter|relationship|item","default":0,"desc":""}],"nodes":[{"id":"","title":"","type":"start|normal|branch|ending","sceneDesc":"","dialogue":[{"speaker":"","text":"","emotion":""}],"choices":[{"id":"","text":"","targetNodeId":"","condition":{"var":"","op":">=","value":0},"effects":[{"var":"","op":"add","value":1}]}]}],"endings":[{"id":"","nodeId":"","title":"","type":"good|bad|neutral|secret","description":""}]}
6
+ 要求:恰好 1 个 type=start 节点;至少 2 个 branch 节点;至少 2 个差异化 ending;每条路径都能到达某个 ending;condition/effects 可省略;不要输出 JSON 以外的任何文字。`;
7
+ export function extractJson(text) {
8
+ const fenced = text.match(/```(?:json)?\s*([\s\S]*?)```/);
9
+ const body = fenced ? fenced[1] : text;
10
+ const start = body.indexOf("{");
11
+ const end = body.lastIndexOf("}");
12
+ if (start === -1 || end === -1 || end <= start) {
13
+ throw new Error("LLM 未返回可解析的 JSON 对象");
14
+ }
15
+ return JSON.parse(body.slice(start, end + 1));
16
+ }
17
+ export function buildStoryGraphFromLLMText(text, projectId) {
18
+ const parsed = extractJson(text);
19
+ const graph = StoryGraphSchema.parse({ ...parsed, projectId });
20
+ if (graph.nodes.length === 0) {
21
+ throw new Error("Invalid story graph: nodes array must not be empty");
22
+ }
23
+ return graph;
24
+ }
25
+ export async function generateStoryGraph(client, model, input, options) {
26
+ const res = await chatCompletion(client, model, [
27
+ { role: "system", content: SYSTEM_PROMPT },
28
+ { role: "user", content: `标题:${input.title}\n前提:${input.premise}` },
29
+ ], { temperature: 0.5, maxTokens: options?.maxTokens ?? 8000 });
30
+ return buildStoryGraphFromLLMText(res.content, input.projectId);
31
+ }
32
+ //# sourceMappingURL=generate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate.js","sourceRoot":"","sources":["../../src/interactive-film/generate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAkB,MAAM,oBAAoB,CAAC;AACpE,OAAO,EAAE,gBAAgB,EAAmB,MAAM,mBAAmB,CAAC;AAEtE,MAAM,aAAa,GAAG;;;qHAG+F,CAAC;AAEtH,MAAM,UAAU,WAAW,CAAC,IAAY;IACtC,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,8BAA8B,CAAC,CAAC;IAC1D,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IACvC,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAChC,MAAM,GAAG,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IAClC,IAAI,KAAK,KAAK,CAAC,CAAC,IAAI,GAAG,KAAK,CAAC,CAAC,IAAI,GAAG,IAAI,KAAK,EAAE,CAAC;QAC/C,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAC;IACzC,CAAC;IACD,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC;AAChD,CAAC;AAED,MAAM,UAAU,0BAA0B,CAAC,IAAY,EAAE,SAAiB;IACxE,MAAM,MAAM,GAAG,WAAW,CAAC,IAAI,CAA4B,CAAC;IAC5D,MAAM,KAAK,GAAG,gBAAgB,CAAC,KAAK,CAAC,EAAE,GAAG,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC;IAC/D,IAAI,KAAK,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC7B,MAAM,IAAI,KAAK,CAAC,oDAAoD,CAAC,CAAC;IACxE,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAQD,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,MAAiB,EACjB,KAAa,EACb,KAA8B,EAC9B,OAAyC;IAEzC,MAAM,GAAG,GAAG,MAAM,cAAc,CAAC,MAAM,EAAE,KAAK,EAAE;QAC9C,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,aAAa,EAAE;QAC1C,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,CAAC,KAAK,QAAQ,KAAK,CAAC,OAAO,EAAE,EAAE;KACpE,EAAE,EAAE,WAAW,EAAE,GAAG,EAAE,SAAS,EAAE,OAAO,EAAE,SAAS,IAAI,IAAI,EAAE,CAAC,CAAC;IAChE,OAAO,0BAA0B,CAAC,GAAG,CAAC,OAAO,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC;AAClE,CAAC"}