@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,292 @@
1
+ import { enumerateRuntimePaths } from "./paths.js";
2
+ function label(node) {
3
+ return node.title || node.id;
4
+ }
5
+ export function validateStoryGraph(graph) {
6
+ const issues = [];
7
+ const ids = new Set(graph.nodes.map((n) => n.id));
8
+ const nodeMap = new Map(graph.nodes.map((n) => [n.id, n]));
9
+ // BROKEN_LINK
10
+ for (const node of graph.nodes) {
11
+ for (const c of node.choices) {
12
+ if (!ids.has(c.targetNodeId)) {
13
+ issues.push({
14
+ code: "BROKEN_LINK",
15
+ level: "error",
16
+ message: `节点「${label(node)}」的选项「${c.text}」指向不存在的节点 ${c.targetNodeId}`,
17
+ nodeIds: [node.id],
18
+ });
19
+ }
20
+ }
21
+ }
22
+ // DEAD_END:非结局节点没有任何指向存在节点的出口
23
+ for (const node of graph.nodes) {
24
+ if (node.type === "ending")
25
+ continue;
26
+ const hasExit = node.choices.some((c) => ids.has(c.targetNodeId));
27
+ if (!hasExit) {
28
+ issues.push({
29
+ code: "DEAD_END",
30
+ level: "error",
31
+ message: `节点「${label(node)}」是死路:没有任何有效出口`,
32
+ nodeIds: [node.id],
33
+ });
34
+ }
35
+ }
36
+ // 可达性 BFS
37
+ const start = graph.nodes.find((n) => n.type === "start") ?? graph.nodes[0];
38
+ const reachable = new Set();
39
+ if (start) {
40
+ const queue = [start.id];
41
+ while (queue.length > 0) {
42
+ const cur = queue.shift();
43
+ if (reachable.has(cur))
44
+ continue;
45
+ reachable.add(cur);
46
+ const n = nodeMap.get(cur);
47
+ if (!n)
48
+ continue;
49
+ for (const c of n.choices) {
50
+ if (ids.has(c.targetNodeId) && !reachable.has(c.targetNodeId))
51
+ queue.push(c.targetNodeId);
52
+ }
53
+ }
54
+ }
55
+ // UNREACHABLE
56
+ for (const node of graph.nodes) {
57
+ if (graph.nodes.length > 1 && !reachable.has(node.id)) {
58
+ issues.push({
59
+ code: "UNREACHABLE",
60
+ level: "warning",
61
+ message: `节点「${label(node)}」从开场无法到达`,
62
+ nodeIds: [node.id],
63
+ });
64
+ }
65
+ }
66
+ // NO_PATH_TO_ENDING
67
+ if (start) {
68
+ let canEnd = false;
69
+ for (const id of reachable) {
70
+ if (nodeMap.get(id)?.type === "ending") {
71
+ canEnd = true;
72
+ break;
73
+ }
74
+ }
75
+ if (!canEnd) {
76
+ issues.push({
77
+ code: "NO_PATH_TO_ENDING",
78
+ level: "error",
79
+ message: `从开场节点「${label(start)}」出发无法到达任何结局`,
80
+ nodeIds: [start.id],
81
+ });
82
+ }
83
+ }
84
+ return { ok: issues.every((i) => i.level !== "error"), issues };
85
+ }
86
+ export function reviewStoryGraph(graph) {
87
+ const issues = [...validateStoryGraph(graph).issues];
88
+ const reads = new Set();
89
+ const writes = new Set();
90
+ for (const node of graph.nodes) {
91
+ for (const choice of node.choices) {
92
+ if (choice.condition)
93
+ reads.add(choice.condition.var);
94
+ for (const effect of choice.effects)
95
+ writes.add(effect.var);
96
+ }
97
+ }
98
+ for (const v of reads) {
99
+ if (!writes.has(v)) {
100
+ issues.push({
101
+ code: "VARIABLE_UNWRITTEN",
102
+ level: "warning",
103
+ message: `变量「${v}」被选项条件读取,但没有任何选项写入它——该条件门除默认值外永远不会改变`,
104
+ nodeIds: [],
105
+ });
106
+ }
107
+ }
108
+ for (const v of graph.variables.map((vv) => vv.name)) {
109
+ if (!reads.has(v) && !writes.has(v)) {
110
+ issues.push({
111
+ code: "VARIABLE_UNUSED",
112
+ level: "info",
113
+ message: `变量「${v}」声明了但没有任何选项写入、也没有任何条件读取它——这是个多余的声明`,
114
+ nodeIds: [],
115
+ });
116
+ }
117
+ }
118
+ if (graph.endings.length >= 2) {
119
+ const types = new Set(graph.endings.map((e) => e.type));
120
+ if (types.size === 1) {
121
+ issues.push({
122
+ code: "ENDING_VARIETY",
123
+ level: "info",
124
+ message: `${graph.endings.length} 个结局都是同一类型(${[...types][0]}),重玩价值低——考虑设计不同基调的结局`,
125
+ nodeIds: graph.endings.map((e) => e.nodeId),
126
+ });
127
+ }
128
+ }
129
+ for (const node of graph.nodes) {
130
+ if (node.type !== "ending" && !node.imageSlot?.assetRef) {
131
+ issues.push({
132
+ code: "IMAGE_MISSING",
133
+ level: "info",
134
+ message: `节点「${node.title || node.id}」还没有配图`,
135
+ nodeIds: [node.id],
136
+ });
137
+ }
138
+ }
139
+ // --- P6 new rules ---
140
+ const { paths, truncated } = enumerateRuntimePaths(graph);
141
+ const reachedNodeIds = new Set();
142
+ for (const p of paths) {
143
+ for (const id of p.nodeIds)
144
+ reachedNodeIds.add(id);
145
+ }
146
+ const edgeReachable = computeEdgeReachable(graph);
147
+ // GATED_UNREACHABLE and ENDING_UNREACHABLE rely on a complete path enumeration.
148
+ // When enumeration is truncated (>200 paths), the reached-node set is incomplete,
149
+ // so asserting unreachability would be unsound. Skip both loops in that case.
150
+ if (!truncated) {
151
+ // GATED_UNREACHABLE: edge-reachable but not runtime-reachable (endings are reported by ENDING_UNREACHABLE)
152
+ for (const node of graph.nodes) {
153
+ if (node.type === "start")
154
+ continue;
155
+ if (node.type === "ending")
156
+ continue;
157
+ if (edgeReachable.has(node.id) && !reachedNodeIds.has(node.id)) {
158
+ issues.push({
159
+ code: "GATED_UNREACHABLE",
160
+ level: "warning",
161
+ message: `节点「${node.title || node.id}」连边可达,但没有任何满足变量条件的路径能到达——它被一个永远不成立的条件挡住了`,
162
+ nodeIds: [node.id],
163
+ });
164
+ }
165
+ }
166
+ // ENDING_UNREACHABLE: check by ending.nodeId presence in reached nodes (handles multiple endings sharing the same node)
167
+ for (const ending of graph.endings) {
168
+ if (!reachedNodeIds.has(ending.nodeId)) {
169
+ issues.push({
170
+ code: "ENDING_UNREACHABLE",
171
+ level: "warning",
172
+ message: `结局「${ending.title}」没有任何真实路径能到达`,
173
+ nodeIds: [ending.nodeId],
174
+ });
175
+ }
176
+ }
177
+ }
178
+ // LINEAR_GRAPH: only meaningful when there are intermediate normal nodes (a pure start→ending stub is not a drama)
179
+ const hasBranch = graph.nodes.some((n) => n.choices.length >= 2);
180
+ const hasNormalNode = graph.nodes.some((n) => n.type === "normal");
181
+ if (graph.nodes.some((n) => n.type === "start") && graph.endings.length > 0 && hasNormalNode && !hasBranch) {
182
+ issues.push({
183
+ code: "LINEAR_GRAPH",
184
+ level: "info",
185
+ message: `整个故事没有任何分叉选择——更像线性剧本而非互动影游,考虑加入分支`,
186
+ nodeIds: [],
187
+ });
188
+ }
189
+ // ISOLATED_NODE (endings are reported by ENDING_UNREACHABLE, not as generic isolated nodes)
190
+ // Skip nodes that already carry an UNREACHABLE issue from validateStoryGraph — that report
191
+ // is more informative (BFS-based, not just topology), so the duplicate is noise.
192
+ const incoming = new Set();
193
+ for (const n of graph.nodes)
194
+ for (const c of n.choices)
195
+ incoming.add(c.targetNodeId);
196
+ for (const node of graph.nodes) {
197
+ if (node.type !== "start" && node.type !== "ending" && !incoming.has(node.id)) {
198
+ if (issues.some((i) => i.code === "UNREACHABLE" && i.nodeIds.includes(node.id)))
199
+ continue;
200
+ issues.push({
201
+ code: "ISOLATED_NODE",
202
+ level: "info",
203
+ message: `节点「${node.title || node.id}」没有任何选项指向它——孤立节点`,
204
+ nodeIds: [node.id],
205
+ });
206
+ }
207
+ }
208
+ // ILLUSORY_BRANCH: a branch where all choices share the same target and have no effects
209
+ for (const node of graph.nodes) {
210
+ if (node.choices.length >= 2) {
211
+ const targets = new Set(node.choices.map((c) => c.targetNodeId));
212
+ const allNoEffect = node.choices.every((c) => (c.effects?.length ?? 0) === 0);
213
+ if (targets.size === 1 && allNoEffect) {
214
+ issues.push({
215
+ code: "ILLUSORY_BRANCH",
216
+ level: "info",
217
+ message: `节点「${node.title || node.id}」的所有选项都通向同一个节点且没有不同效果——这是个假分支`,
218
+ nodeIds: [node.id],
219
+ });
220
+ }
221
+ }
222
+ }
223
+ // LONG_LINEAR_CHAIN: >=5 consecutive single-choice normal nodes
224
+ const CHAIN_THRESHOLD = 5;
225
+ const longChainHeads = findLongLinearChainHeads(graph, CHAIN_THRESHOLD);
226
+ for (const id of longChainHeads) {
227
+ issues.push({
228
+ code: "LONG_LINEAR_CHAIN",
229
+ level: "info",
230
+ message: `从节点「${id}」开始有一段较长的无分支直链(≥${CHAIN_THRESHOLD} 个单选项节点)——节奏可能偏拖,考虑插入分支或事件`,
231
+ nodeIds: [id],
232
+ });
233
+ }
234
+ return { ok: issues.every((i) => i.level !== "error"), issues };
235
+ }
236
+ function computeEdgeReachable(graph) {
237
+ const start = graph.nodes.find((n) => n.type === "start");
238
+ const reachable = new Set();
239
+ if (!start)
240
+ return reachable;
241
+ const nodeById = new Map(graph.nodes.map((n) => [n.id, n]));
242
+ const queue = [start.id];
243
+ while (queue.length > 0) {
244
+ const cur = queue.shift();
245
+ if (reachable.has(cur))
246
+ continue;
247
+ reachable.add(cur);
248
+ const node = nodeById.get(cur);
249
+ if (!node)
250
+ continue;
251
+ for (const choice of node.choices) {
252
+ if (!reachable.has(choice.targetNodeId))
253
+ queue.push(choice.targetNodeId);
254
+ }
255
+ }
256
+ return reachable;
257
+ }
258
+ function findLongLinearChainHeads(graph, threshold) {
259
+ const nodeById = new Map(graph.nodes.map((n) => [n.id, n]));
260
+ const isChainNode = (id) => {
261
+ const n = nodeById.get(id);
262
+ return n !== undefined && n.type === "normal" && n.choices.length === 1;
263
+ };
264
+ const incomingIsChainNode = new Map();
265
+ for (const n of graph.nodes) {
266
+ for (const c of n.choices) {
267
+ if (isChainNode(n.id)) {
268
+ incomingIsChainNode.set(c.targetNodeId, true);
269
+ }
270
+ }
271
+ }
272
+ const heads = [];
273
+ for (const node of graph.nodes) {
274
+ if (!isChainNode(node.id))
275
+ continue;
276
+ if (incomingIsChainNode.get(node.id))
277
+ continue;
278
+ let length = 0;
279
+ let cur = node.id;
280
+ const visited = new Set();
281
+ while (cur !== undefined && isChainNode(cur) && !visited.has(cur)) {
282
+ visited.add(cur);
283
+ length++;
284
+ const chainNode = nodeById.get(cur);
285
+ cur = chainNode.choices[0].targetNodeId;
286
+ }
287
+ if (length >= threshold)
288
+ heads.push(node.id);
289
+ }
290
+ return heads;
291
+ }
292
+ //# sourceMappingURL=validation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validation.js","sourceRoot":"","sources":["../../src/interactive-film/validation.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../../src/llm/provider.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../../src/llm/provider.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAKtD,OAAO,KAAK,EACV,GAAG,IAAI,KAAK,EACZ,KAAK,IAAI,OAAO,EAChB,OAAO,IAAI,SAAS,EAErB,MAAM,qBAAqB,CAAC;AAW7B,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,CAAC;CACvC;AAED,MAAM,MAAM,gBAAgB,GAAG,CAAC,QAAQ,EAAE,cAAc,KAAK,IAAI,CAAC;AAgClE,wBAAgB,mBAAmB,CACjC,UAAU,CAAC,EAAE,gBAAgB,EAC7B,UAAU,GAAE,MAAc,GACzB;IAAE,QAAQ,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,IAAI,CAAA;CAAE,CAmCzE;AAID,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,KAAK,EAAE;QACd,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;QAC9B,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;QAClC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;KAC9B,CAAC;CACH;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,IAAI,EAAE,QAAQ,GAAG,MAAM,GAAG,WAAW,CAAC;IAC/C,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,QAAQ,EAAE,QAAQ,GAAG,WAAW,CAAC;IAC1C,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,YAAY,CAAC,EAAE,SAAS,CAAC,cAAc,CAAC,CAAC;IAClD,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,WAAW,CAAC;IACzC,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC;IACnC,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,QAAQ,EAAE;QACjB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;QAC7B;;;WAGG;QACH,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;QAC3B;;;;WAIG;QACH,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QACtC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;QAChC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KACzC,CAAC;CACH;AAID,wBAAgB,eAAe,CAAC,MAAM,EAAE,SAAS,GAAG,SAAS,CAoE5D;AA+CD,qBAAa,oBAAqB,SAAQ,KAAK;IAC7C,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;gBACpB,cAAc,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO;CAKnD;AAED,qBAAa,0BAA2B,SAAQ,KAAK;IACnD,QAAQ,CAAC,oBAAoB,EAAE,MAAM,CAAC;IACtC,QAAQ,CAAC,oBAAoB,EAAE,MAAM,CAAC;IACtC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;gBAEnB,MAAM,EAAE;QAClB,QAAQ,CAAC,oBAAoB,EAAE,MAAM,CAAC;QACtC,QAAQ,CAAC,oBAAoB,EAAE,MAAM,CAAC;QACtC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;QAC/B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;KACxB;CAYF;AA8CD,wBAAgB,+BAA+B,IAAI,IAAI,CAEtD;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAKvD;AA4CD,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,SAAS,GAAG,MAAM,CAuBlE;AAED,wBAAgB,yBAAyB,CAAC,MAAM,EAAE;IAChD,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC;IACjC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,oBAAoB,EAAE,MAAM,CAAC;IACtC,QAAQ,CAAC,oBAAoB,EAAE,MAAM,CAAC;CACvC,GAAG,IAAI,CAUP;AA2HD;;;;;;;;;GASG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAkB/D;AA2jBD,wBAAsB,cAAc,CAClC,MAAM,EAAE,SAAS,EACjB,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,aAAa,CAAC,UAAU,CAAC,EACnC,OAAO,CAAC,EAAE;IACR,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC;IAC7B,QAAQ,CAAC,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IAC7C,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAG9C,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;CAC1B,GACA,OAAO,CAAC,WAAW,CAAC,CAwCtB"}
@@ -4,6 +4,7 @@ import { getEndpoint } from "./providers/index.js";
4
4
  import { lookupModel } from "./providers/lookup.js";
5
5
  import { fetchWithProxy } from "../utils/proxy-fetch.js";
6
6
  import { isApiKeyOptionalForEndpoint } from "../utils/llm-endpoint-auth.js";
7
+ import { isLlmStubEnabled, stubChatCompletion } from "../agent/llm-stub.js";
7
8
  const INKOS_USER_AGENT = "InkOS/1.3.5";
8
9
  const UNKNOWN_MODEL_FALLBACK_MAX_TOKENS = 8192 * 3;
9
10
  const TRANSIENT_LLM_RETRIES = 2;
@@ -170,7 +171,10 @@ function parseEnvHeaders() {
170
171
  }
171
172
  return undefined;
172
173
  }
173
- // === Partial Response (stream interrupted but usable content received) ===
174
+ // === Partial Response(流式生成中途被掐断)===
175
+ // 语义:内容不完整、不可信。由 withTransientLLMRetry 整体重新生成;
176
+ // 重试耗尽后如实抛错。绝不把半截内容当成功返回(那会产出写到一半就
177
+ // 结束的章节/设定文件)。partialContent 仅用于错误诊断。
174
178
  export class PartialResponseError extends Error {
175
179
  partialContent;
176
180
  constructor(partialContent, cause) {
@@ -179,8 +183,6 @@ export class PartialResponseError extends Error {
179
183
  this.partialContent = partialContent;
180
184
  }
181
185
  }
182
- /** Minimum chars to consider a partial response salvageable (Chinese ~2 chars/word → 500 chars ≈ 250 words) */
183
- const MIN_SALVAGEABLE_CHARS = 500;
184
186
  export class ContextWindowExceededError extends Error {
185
187
  estimatedInputTokens;
186
188
  reservedOutputTokens;
@@ -461,7 +463,11 @@ export function isTransientLLMHttpError(error) {
461
463
  return statusHit || phraseHit;
462
464
  }
463
465
  function isRetryableLLMError(error) {
464
- return isTransientLLMTransportError(error) || isTransientLLMHttpError(error);
466
+ // PartialResponseError = 流在生成中途被掐断(网关切长连接等)。重试会完整
467
+ // 重新生成一次,比把半截内容当成功交付(截断的章节/设定文件)要正确。
468
+ return error instanceof PartialResponseError
469
+ || isTransientLLMTransportError(error)
470
+ || isTransientLLMHttpError(error);
465
471
  }
466
472
  async function withTransientLLMRetry(run, options) {
467
473
  const enabled = options?.enabled ?? true;
@@ -474,7 +480,6 @@ async function withTransientLLMRetry(run, options) {
474
480
  lastError = error;
475
481
  if (!enabled
476
482
  || attempt >= TRANSIENT_LLM_RETRIES
477
- || error instanceof PartialResponseError
478
483
  || !isRetryableLLMError(error)) {
479
484
  throw error;
480
485
  }
@@ -719,6 +724,7 @@ async function chatCompletionViaCustomAnthropicCompatible(client, model, message
719
724
  let buffer = "";
720
725
  let content = "";
721
726
  let usage = { promptTokens: 0, completionTokens: 0, totalTokens: 0 };
727
+ let sawMessageStop = false;
722
728
  const monitor = createStreamMonitor(onStreamProgress);
723
729
  try {
724
730
  while (true) {
@@ -744,6 +750,7 @@ async function chatCompletionViaCustomAnthropicCompatible(client, model, message
744
750
  usage.completionTokens = json.usage.output_tokens ?? usage.completionTokens;
745
751
  }
746
752
  if (json.type === "message_stop") {
753
+ sawMessageStop = true;
747
754
  usage.totalTokens = usage.promptTokens + usage.completionTokens;
748
755
  }
749
756
  }
@@ -755,6 +762,10 @@ async function chatCompletionViaCustomAnthropicCompatible(client, model, message
755
762
  if (!content) {
756
763
  throw wrapLLMError(new Error("LLM returned empty response from stream"), errorCtx);
757
764
  }
765
+ if (!sawMessageStop) {
766
+ // Anthropic 协议的正常结束必须有 message_stop;没有就是流被中途掐断
767
+ throw new PartialResponseError(content, new Error("stream closed without message_stop"));
768
+ }
758
769
  if (!usage.totalTokens) {
759
770
  usage.totalTokens = usage.promptTokens + usage.completionTokens;
760
771
  }
@@ -811,6 +822,7 @@ async function chatCompletionViaCustomOpenAICompatible(client, model, messages,
811
822
  let buffer = "";
812
823
  let content = "";
813
824
  let usage = { promptTokens: 0, completionTokens: 0, totalTokens: 0 };
825
+ let sawResponseTerminal = false;
814
826
  const monitor = createStreamMonitor(onStreamProgress);
815
827
  try {
816
828
  while (true) {
@@ -829,7 +841,8 @@ async function chatCompletionViaCustomOpenAICompatible(client, model, messages,
829
841
  monitor.onChunk(json.delta);
830
842
  onTextDelta?.(json.delta);
831
843
  }
832
- if (json.type === "response.completed") {
844
+ if (json.type === "response.completed" || json.type === "response.incomplete") {
845
+ sawResponseTerminal = true;
833
846
  usage = {
834
847
  promptTokens: json.response?.usage?.input_tokens ?? 0,
835
848
  completionTokens: json.response?.usage?.output_tokens ?? 0,
@@ -848,6 +861,10 @@ async function chatCompletionViaCustomOpenAICompatible(client, model, messages,
848
861
  if (!content) {
849
862
  throw wrapLLMError(new Error("LLM returned empty response from stream"), errorCtx);
850
863
  }
864
+ if (!sawResponseTerminal) {
865
+ // Responses 协议的正常结束必须有 response.completed/incomplete 终止事件
866
+ throw new PartialResponseError(content, new Error("stream closed without response.completed"));
867
+ }
851
868
  return { content, usage };
852
869
  }
853
870
  const payload = {
@@ -901,6 +918,9 @@ async function chatCompletionViaCustomOpenAICompatible(client, model, messages,
901
918
  let content = "";
902
919
  let reasoningContent = "";
903
920
  let usage = { promptTokens: 0, completionTokens: 0, totalTokens: 0 };
921
+ // OpenAI 协议的正常结束必须出现 [DONE] 哨兵或带 finish_reason 的 chunk。
922
+ // 网关掐断长连接时流会"干净地"关闭但没有任何终止信号——那是截断,不是完成。
923
+ let sawTerminal = false;
904
924
  const monitor = createStreamMonitor(onStreamProgress);
905
925
  try {
906
926
  while (true) {
@@ -911,9 +931,16 @@ async function chatCompletionViaCustomOpenAICompatible(client, model, messages,
911
931
  const parsed = parseSseEvents(buffer);
912
932
  buffer = parsed.rest;
913
933
  for (const event of parsed.events) {
914
- if (!event.data || event.data === "[DONE]")
934
+ if (!event.data)
915
935
  continue;
936
+ if (event.data === "[DONE]") {
937
+ sawTerminal = true;
938
+ continue;
939
+ }
916
940
  const json = JSON.parse(event.data);
941
+ if (json?.choices?.[0]?.finish_reason) {
942
+ sawTerminal = true;
943
+ }
917
944
  const delta = extractChatDeltaContent(json);
918
945
  if (delta) {
919
946
  content += delta;
@@ -944,10 +971,15 @@ async function chatCompletionViaCustomOpenAICompatible(client, model, messages,
944
971
  if (!finalContent) {
945
972
  throw wrapLLMError(new Error("LLM returned empty response from stream"), errorCtx);
946
973
  }
974
+ if (!sawTerminal) {
975
+ throw new PartialResponseError(finalContent, new Error("stream closed without [DONE]/finish_reason"));
976
+ }
947
977
  return { content: finalContent, usage };
948
978
  }
949
979
  // === Simple Chat (used by all agents via BaseAgent.chat()) ===
950
980
  export async function chatCompletion(client, model, messages, options) {
981
+ if (isLlmStubEnabled())
982
+ return Promise.resolve(stubChatCompletion(messages, model));
951
983
  // C1 (v2.0.0):删除 maxTokensCap 机制。per-call 显式传的 maxTokens 永远不被裁剪。
952
984
  const resolved = {
953
985
  temperature: clampTemperatureForModel(client.service, model, options?.temperature ?? client.defaults.temperature),
@@ -975,13 +1007,9 @@ export async function chatCompletion(client, model, messages, options) {
975
1007
  { enabled: (options?.retry ?? true) && !onTextDelta });
976
1008
  }
977
1009
  catch (error) {
978
- // Stream interrupted but partial content is usable — return truncated response
979
- if (error instanceof PartialResponseError) {
980
- return {
981
- content: error.partialContent,
982
- usage: { promptTokens: 0, completionTokens: 0, totalTokens: 0 },
983
- };
984
- }
1010
+ // 注意:中断的流(PartialResponseError)不再"打捞"半截内容当成功返回——
1011
+ // 那会产出写到一半就结束的章节/设定文件。重试由 withTransientLLMRetry
1012
+ // 负责(完整重新生成);重试耗尽后如实抛错。
985
1013
  throw wrapLLMError(error, errorCtx);
986
1014
  }
987
1015
  }
@@ -1059,6 +1087,7 @@ async function chatCompletionViaPiAi(client, model, messages, resolved, onStream
1059
1087
  const monitor = createStreamMonitor(onStreamProgress);
1060
1088
  let inputTokens = 0;
1061
1089
  let outputTokens = 0;
1090
+ let sawDone = false;
1062
1091
  try {
1063
1092
  for await (const event of eventStream) {
1064
1093
  if (event.type === "text_delta") {
@@ -1070,9 +1099,12 @@ async function chatCompletionViaPiAi(client, model, messages, resolved, onStream
1070
1099
  const msg = event.type === "done" ? event.message : event.error;
1071
1100
  inputTokens = msg.usage.input;
1072
1101
  outputTokens = msg.usage.output;
1102
+ if (event.type === "done") {
1103
+ sawDone = true;
1104
+ }
1073
1105
  if (event.type === "error" && msg.errorMessage) {
1074
1106
  const partial = chunks.join("");
1075
- if (partial.length >= MIN_SALVAGEABLE_CHARS) {
1107
+ if (partial) {
1076
1108
  throw new PartialResponseError(partial, new Error(msg.errorMessage));
1077
1109
  }
1078
1110
  throw new Error(msg.errorMessage);
@@ -1085,7 +1117,8 @@ async function chatCompletionViaPiAi(client, model, messages, resolved, onStream
1085
1117
  if (streamError instanceof PartialResponseError)
1086
1118
  throw streamError;
1087
1119
  const partial = chunks.join("");
1088
- if (partial.length >= MIN_SALVAGEABLE_CHARS) {
1120
+ if (partial) {
1121
+ // 带着已收到的部分内容抛 PartialResponseError,让瞬时重试整体重新生成
1089
1122
  throw new PartialResponseError(partial, streamError);
1090
1123
  }
1091
1124
  throw streamError;
@@ -1099,6 +1132,10 @@ async function chatCompletionViaPiAi(client, model, messages, resolved, onStream
1099
1132
  console.warn(`[inkos] LLM 流式响应无文本内容 (${diag})`);
1100
1133
  throw new Error(`LLM returned empty response from stream (${diag})`);
1101
1134
  }
1135
+ if (!sawDone) {
1136
+ // 事件流没有以 done 收尾就结束 = 上游把流掐断了,内容不可信
1137
+ throw new PartialResponseError(content, new Error("stream ended without done event"));
1138
+ }
1102
1139
  return {
1103
1140
  content,
1104
1141
  usage: {