@kienmatu/inkos-core 0.1.0
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/LICENSE +661 -0
- package/dist/agent/agent-session.d.ts +100 -0
- package/dist/agent/agent-session.d.ts.map +1 -0
- package/dist/agent/agent-session.js +1102 -0
- package/dist/agent/agent-session.js.map +1 -0
- package/dist/agent/agent-system-prompt.d.ts +12 -0
- package/dist/agent/agent-system-prompt.d.ts.map +1 -0
- package/dist/agent/agent-system-prompt.js +596 -0
- package/dist/agent/agent-system-prompt.js.map +1 -0
- package/dist/agent/agent-tools.d.ts +508 -0
- package/dist/agent/agent-tools.d.ts.map +1 -0
- package/dist/agent/agent-tools.js +3083 -0
- package/dist/agent/agent-tools.js.map +1 -0
- package/dist/agent/chapter-import-source.d.ts +16 -0
- package/dist/agent/chapter-import-source.d.ts.map +1 -0
- package/dist/agent/chapter-import-source.js +48 -0
- package/dist/agent/chapter-import-source.js.map +1 -0
- package/dist/agent/context-transform.d.ts +13 -0
- package/dist/agent/context-transform.d.ts.map +1 -0
- package/dist/agent/context-transform.js +183 -0
- package/dist/agent/context-transform.js.map +1 -0
- package/dist/agent/film-authoring-tools.d.ts +98 -0
- package/dist/agent/film-authoring-tools.d.ts.map +1 -0
- package/dist/agent/film-authoring-tools.js +405 -0
- package/dist/agent/film-authoring-tools.js.map +1 -0
- package/dist/agent/forecast-tools.d.ts +22 -0
- package/dist/agent/forecast-tools.d.ts.map +1 -0
- package/dist/agent/forecast-tools.js +153 -0
- package/dist/agent/forecast-tools.js.map +1 -0
- package/dist/agent/index.d.ts +8 -0
- package/dist/agent/index.d.ts.map +1 -0
- package/dist/agent/index.js +8 -0
- package/dist/agent/index.js.map +1 -0
- package/dist/agent/llm-stub.d.ts +19 -0
- package/dist/agent/llm-stub.d.ts.map +1 -0
- package/dist/agent/llm-stub.js +134 -0
- package/dist/agent/llm-stub.js.map +1 -0
- package/dist/agent/pi-stream.d.ts +8 -0
- package/dist/agent/pi-stream.d.ts.map +1 -0
- package/dist/agent/pi-stream.js +31 -0
- package/dist/agent/pi-stream.js.map +1 -0
- package/dist/agent/skill-tool.d.ts +42 -0
- package/dist/agent/skill-tool.d.ts.map +1 -0
- package/dist/agent/skill-tool.js +279 -0
- package/dist/agent/skill-tool.js.map +1 -0
- package/dist/agent/worker-agent.d.ts +24 -0
- package/dist/agent/worker-agent.d.ts.map +1 -0
- package/dist/agent/worker-agent.js +288 -0
- package/dist/agent/worker-agent.js.map +1 -0
- package/dist/agents/ai-tells.d.ts +26 -0
- package/dist/agents/ai-tells.d.ts.map +1 -0
- package/dist/agents/ai-tells.js +140 -0
- package/dist/agents/ai-tells.js.map +1 -0
- package/dist/agents/architect.d.ts +78 -0
- package/dist/agents/architect.d.ts.map +1 -0
- package/dist/agents/architect.js +1184 -0
- package/dist/agents/architect.js.map +1 -0
- package/dist/agents/base.d.ts +42 -0
- package/dist/agents/base.d.ts.map +1 -0
- package/dist/agents/base.js +123 -0
- package/dist/agents/base.js.map +1 -0
- package/dist/agents/chapter-analyzer.d.ts +30 -0
- package/dist/agents/chapter-analyzer.d.ts.map +1 -0
- package/dist/agents/chapter-analyzer.js +509 -0
- package/dist/agents/chapter-analyzer.js.map +1 -0
- package/dist/agents/composer.d.ts +67 -0
- package/dist/agents/composer.d.ts.map +1 -0
- package/dist/agents/composer.js +936 -0
- package/dist/agents/composer.js.map +1 -0
- package/dist/agents/consolidator.d.ts +39 -0
- package/dist/agents/consolidator.d.ts.map +1 -0
- package/dist/agents/consolidator.js +179 -0
- package/dist/agents/consolidator.js.map +1 -0
- package/dist/agents/continuity.d.ts +45 -0
- package/dist/agents/continuity.d.ts.map +1 -0
- package/dist/agents/continuity.js +722 -0
- package/dist/agents/continuity.js.map +1 -0
- package/dist/agents/detection-insights.d.ts +9 -0
- package/dist/agents/detection-insights.d.ts.map +1 -0
- package/dist/agents/detection-insights.js +54 -0
- package/dist/agents/detection-insights.js.map +1 -0
- package/dist/agents/detector.d.ts +17 -0
- package/dist/agents/detector.d.ts.map +1 -0
- package/dist/agents/detector.js +77 -0
- package/dist/agents/detector.js.map +1 -0
- package/dist/agents/en-prompt-sections.d.ts +4 -0
- package/dist/agents/en-prompt-sections.d.ts.map +1 -0
- package/dist/agents/en-prompt-sections.js +9 -0
- package/dist/agents/en-prompt-sections.js.map +1 -0
- package/dist/agents/fanfic-canon-importer.d.ts +16 -0
- package/dist/agents/fanfic-canon-importer.d.ts.map +1 -0
- package/dist/agents/fanfic-canon-importer.js +164 -0
- package/dist/agents/fanfic-canon-importer.js.map +1 -0
- package/dist/agents/fanfic-dimensions.d.ts +14 -0
- package/dist/agents/fanfic-dimensions.d.ts.map +1 -0
- package/dist/agents/fanfic-dimensions.js +63 -0
- package/dist/agents/fanfic-dimensions.js.map +1 -0
- package/dist/agents/fanfic-prompt-sections.d.ts +5 -0
- package/dist/agents/fanfic-prompt-sections.d.ts.map +1 -0
- package/dist/agents/fanfic-prompt-sections.js +85 -0
- package/dist/agents/fanfic-prompt-sections.js.map +1 -0
- package/dist/agents/foundation-reviewer.d.ts +34 -0
- package/dist/agents/foundation-reviewer.d.ts.map +1 -0
- package/dist/agents/foundation-reviewer.js +174 -0
- package/dist/agents/foundation-reviewer.js.map +1 -0
- package/dist/agents/observer-prompts.d.ts +10 -0
- package/dist/agents/observer-prompts.d.ts.map +1 -0
- package/dist/agents/observer-prompts.js +113 -0
- package/dist/agents/observer-prompts.js.map +1 -0
- package/dist/agents/planner-context.d.ts +53 -0
- package/dist/agents/planner-context.d.ts.map +1 -0
- package/dist/agents/planner-context.js +238 -0
- package/dist/agents/planner-context.js.map +1 -0
- package/dist/agents/planner-prompts.d.ts +45 -0
- package/dist/agents/planner-prompts.d.ts.map +1 -0
- package/dist/agents/planner-prompts.js +391 -0
- package/dist/agents/planner-prompts.js.map +1 -0
- package/dist/agents/planner.d.ts +90 -0
- package/dist/agents/planner.d.ts.map +1 -0
- package/dist/agents/planner.js +715 -0
- package/dist/agents/planner.js.map +1 -0
- package/dist/agents/polisher.d.ts +33 -0
- package/dist/agents/polisher.d.ts.map +1 -0
- package/dist/agents/polisher.js +122 -0
- package/dist/agents/polisher.js.map +1 -0
- package/dist/agents/post-write-validator.d.ts +35 -0
- package/dist/agents/post-write-validator.d.ts.map +1 -0
- package/dist/agents/post-write-validator.js +758 -0
- package/dist/agents/post-write-validator.js.map +1 -0
- package/dist/agents/radar-source.d.ts +38 -0
- package/dist/agents/radar-source.d.ts.map +1 -0
- package/dist/agents/radar-source.js +92 -0
- package/dist/agents/radar-source.js.map +1 -0
- package/dist/agents/radar.d.ts +24 -0
- package/dist/agents/radar.d.ts.map +1 -0
- package/dist/agents/radar.js +85 -0
- package/dist/agents/radar.js.map +1 -0
- package/dist/agents/researcher.d.ts +38 -0
- package/dist/agents/researcher.d.ts.map +1 -0
- package/dist/agents/researcher.js +164 -0
- package/dist/agents/researcher.js.map +1 -0
- package/dist/agents/reviser.d.ts +35 -0
- package/dist/agents/reviser.d.ts.map +1 -0
- package/dist/agents/reviser.js +496 -0
- package/dist/agents/reviser.js.map +1 -0
- package/dist/agents/rules-reader.d.ts +32 -0
- package/dist/agents/rules-reader.d.ts.map +1 -0
- package/dist/agents/rules-reader.js +129 -0
- package/dist/agents/rules-reader.js.map +1 -0
- package/dist/agents/script-storyboard.d.ts +66 -0
- package/dist/agents/script-storyboard.d.ts.map +1 -0
- package/dist/agents/script-storyboard.js +657 -0
- package/dist/agents/script-storyboard.js.map +1 -0
- package/dist/agents/sensitive-words.d.ts +24 -0
- package/dist/agents/sensitive-words.d.ts.map +1 -0
- package/dist/agents/sensitive-words.js +103 -0
- package/dist/agents/sensitive-words.js.map +1 -0
- package/dist/agents/settler-delta-parser.d.ts +7 -0
- package/dist/agents/settler-delta-parser.d.ts.map +1 -0
- package/dist/agents/settler-delta-parser.js +40 -0
- package/dist/agents/settler-delta-parser.js.map +1 -0
- package/dist/agents/settler-parser.d.ts +13 -0
- package/dist/agents/settler-parser.d.ts.map +1 -0
- package/dist/agents/settler-parser.js +20 -0
- package/dist/agents/settler-parser.js.map +1 -0
- package/dist/agents/settler-prompts.d.ts +22 -0
- package/dist/agents/settler-prompts.d.ts.map +1 -0
- package/dist/agents/settler-prompts.js +195 -0
- package/dist/agents/settler-prompts.js.map +1 -0
- package/dist/agents/short-fiction.d.ts +120 -0
- package/dist/agents/short-fiction.d.ts.map +1 -0
- package/dist/agents/short-fiction.js +353 -0
- package/dist/agents/short-fiction.js.map +1 -0
- package/dist/agents/state-validator.d.ts +33 -0
- package/dist/agents/state-validator.d.ts.map +1 -0
- package/dist/agents/state-validator.js +262 -0
- package/dist/agents/state-validator.js.map +1 -0
- package/dist/agents/style-analyzer.d.ts +11 -0
- package/dist/agents/style-analyzer.d.ts.map +1 -0
- package/dist/agents/style-analyzer.js +98 -0
- package/dist/agents/style-analyzer.js.map +1 -0
- package/dist/agents/writer-parser.d.ts +17 -0
- package/dist/agents/writer-parser.d.ts.map +1 -0
- package/dist/agents/writer-parser.js +131 -0
- package/dist/agents/writer-parser.js.map +1 -0
- package/dist/agents/writer-prompts.d.ts +12 -0
- package/dist/agents/writer-prompts.d.ts.map +1 -0
- package/dist/agents/writer-prompts.js +495 -0
- package/dist/agents/writer-prompts.js.map +1 -0
- package/dist/agents/writer.d.ts +102 -0
- package/dist/agents/writer.d.ts.map +1 -0
- package/dist/agents/writer.js +882 -0
- package/dist/agents/writer.js.map +1 -0
- package/dist/forecast/agent.d.ts +22 -0
- package/dist/forecast/agent.d.ts.map +1 -0
- package/dist/forecast/agent.js +48 -0
- package/dist/forecast/agent.js.map +1 -0
- package/dist/forecast/context-builder.d.ts +35 -0
- package/dist/forecast/context-builder.d.ts.map +1 -0
- package/dist/forecast/context-builder.js +214 -0
- package/dist/forecast/context-builder.js.map +1 -0
- package/dist/forecast/prompts.d.ts +12 -0
- package/dist/forecast/prompts.d.ts.map +1 -0
- package/dist/forecast/prompts.js +114 -0
- package/dist/forecast/prompts.js.map +1 -0
- package/dist/forecast/render.d.ts +9 -0
- package/dist/forecast/render.d.ts.map +1 -0
- package/dist/forecast/render.js +154 -0
- package/dist/forecast/render.js.map +1 -0
- package/dist/forecast/runner.d.ts +51 -0
- package/dist/forecast/runner.d.ts.map +1 -0
- package/dist/forecast/runner.js +115 -0
- package/dist/forecast/runner.js.map +1 -0
- package/dist/forecast/schema.d.ts +767 -0
- package/dist/forecast/schema.d.ts.map +1 -0
- package/dist/forecast/schema.js +115 -0
- package/dist/forecast/schema.js.map +1 -0
- package/dist/forecast/store.d.ts +32 -0
- package/dist/forecast/store.d.ts.map +1 -0
- package/dist/forecast/store.js +129 -0
- package/dist/forecast/store.js.map +1 -0
- package/dist/index.d.ts +160 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +172 -0
- package/dist/index.js.map +1 -0
- package/dist/interaction/action-envelope.d.ts +1493 -0
- package/dist/interaction/action-envelope.d.ts.map +1 -0
- package/dist/interaction/action-envelope.js +257 -0
- package/dist/interaction/action-envelope.js.map +1 -0
- package/dist/interaction/book-session-store.d.ts +29 -0
- package/dist/interaction/book-session-store.d.ts.map +1 -0
- package/dist/interaction/book-session-store.js +185 -0
- package/dist/interaction/book-session-store.js.map +1 -0
- package/dist/interaction/draft-directive-parser.d.ts +38 -0
- package/dist/interaction/draft-directive-parser.d.ts.map +1 -0
- package/dist/interaction/draft-directive-parser.js +208 -0
- package/dist/interaction/draft-directive-parser.js.map +1 -0
- package/dist/interaction/edit-controller.d.ts +62 -0
- package/dist/interaction/edit-controller.d.ts.map +1 -0
- package/dist/interaction/edit-controller.js +381 -0
- package/dist/interaction/edit-controller.js.map +1 -0
- package/dist/interaction/events.d.ts +45 -0
- package/dist/interaction/events.d.ts.map +1 -0
- package/dist/interaction/events.js +32 -0
- package/dist/interaction/events.js.map +1 -0
- package/dist/interaction/export-artifact.d.ts +32 -0
- package/dist/interaction/export-artifact.d.ts.map +1 -0
- package/dist/interaction/export-artifact.js +103 -0
- package/dist/interaction/export-artifact.js.map +1 -0
- package/dist/interaction/intents.d.ts +99 -0
- package/dist/interaction/intents.d.ts.map +1 -0
- package/dist/interaction/intents.js +59 -0
- package/dist/interaction/intents.js.map +1 -0
- package/dist/interaction/modes.d.ts +5 -0
- package/dist/interaction/modes.d.ts.map +1 -0
- package/dist/interaction/modes.js +7 -0
- package/dist/interaction/modes.js.map +1 -0
- package/dist/interaction/project-control.d.ts +45 -0
- package/dist/interaction/project-control.d.ts.map +1 -0
- package/dist/interaction/project-control.js +71 -0
- package/dist/interaction/project-control.js.map +1 -0
- package/dist/interaction/project-session-store.d.ts +9 -0
- package/dist/interaction/project-session-store.d.ts.map +1 -0
- package/dist/interaction/project-session-store.js +64 -0
- package/dist/interaction/project-session-store.js.map +1 -0
- package/dist/interaction/project-tools.d.ts +23 -0
- package/dist/interaction/project-tools.d.ts.map +1 -0
- package/dist/interaction/project-tools.js +408 -0
- package/dist/interaction/project-tools.js.map +1 -0
- package/dist/interaction/request-router.d.ts +3 -0
- package/dist/interaction/request-router.d.ts.map +1 -0
- package/dist/interaction/request-router.js +5 -0
- package/dist/interaction/request-router.js.map +1 -0
- package/dist/interaction/runtime.d.ts +54 -0
- package/dist/interaction/runtime.d.ts.map +1 -0
- package/dist/interaction/runtime.js +919 -0
- package/dist/interaction/runtime.js.map +1 -0
- package/dist/interaction/session-transcript-legacy.d.ts +4 -0
- package/dist/interaction/session-transcript-legacy.d.ts.map +1 -0
- package/dist/interaction/session-transcript-legacy.js +102 -0
- package/dist/interaction/session-transcript-legacy.js.map +1 -0
- package/dist/interaction/session-transcript-restore.d.ts +18 -0
- package/dist/interaction/session-transcript-restore.d.ts.map +1 -0
- package/dist/interaction/session-transcript-restore.js +746 -0
- package/dist/interaction/session-transcript-restore.js.map +1 -0
- package/dist/interaction/session-transcript-schema.d.ts +435 -0
- package/dist/interaction/session-transcript-schema.d.ts.map +1 -0
- package/dist/interaction/session-transcript-schema.js +65 -0
- package/dist/interaction/session-transcript-schema.js.map +1 -0
- package/dist/interaction/session-transcript.d.ts +21 -0
- package/dist/interaction/session-transcript.d.ts.map +1 -0
- package/dist/interaction/session-transcript.js +164 -0
- package/dist/interaction/session-transcript.js.map +1 -0
- package/dist/interaction/session.d.ts +1194 -0
- package/dist/interaction/session.d.ts.map +1 -0
- package/dist/interaction/session.js +194 -0
- package/dist/interaction/session.js.map +1 -0
- package/dist/interaction/truth-authority.d.ts +4 -0
- package/dist/interaction/truth-authority.d.ts.map +1 -0
- package/dist/interaction/truth-authority.js +37 -0
- package/dist/interaction/truth-authority.js.map +1 -0
- package/dist/interactive-film/authoring-store.d.ts +35 -0
- package/dist/interactive-film/authoring-store.d.ts.map +1 -0
- package/dist/interactive-film/authoring-store.js +114 -0
- package/dist/interactive-film/authoring-store.js.map +1 -0
- package/dist/interactive-film/authoring-tools.d.ts +9 -0
- package/dist/interactive-film/authoring-tools.d.ts.map +1 -0
- package/dist/interactive-film/authoring-tools.js +19 -0
- package/dist/interactive-film/authoring-tools.js.map +1 -0
- package/dist/interactive-film/delta.d.ts +591 -0
- package/dist/interactive-film/delta.d.ts.map +1 -0
- package/dist/interactive-film/delta.js +54 -0
- package/dist/interactive-film/delta.js.map +1 -0
- package/dist/interactive-film/emotion.d.ts +20 -0
- package/dist/interactive-film/emotion.d.ts.map +1 -0
- package/dist/interactive-film/emotion.js +57 -0
- package/dist/interactive-film/emotion.js.map +1 -0
- package/dist/interactive-film/evaluator.d.ts +7 -0
- package/dist/interactive-film/evaluator.d.ts.map +1 -0
- package/dist/interactive-film/evaluator.js +40 -0
- package/dist/interactive-film/evaluator.js.map +1 -0
- package/dist/interactive-film/export-html.d.ts +6 -0
- package/dist/interactive-film/export-html.d.ts.map +1 -0
- package/dist/interactive-film/export-html.js +84 -0
- package/dist/interactive-film/export-html.js.map +1 -0
- package/dist/interactive-film/export-ink.d.ts +3 -0
- package/dist/interactive-film/export-ink.d.ts.map +1 -0
- package/dist/interactive-film/export-ink.js +51 -0
- package/dist/interactive-film/export-ink.js.map +1 -0
- package/dist/interactive-film/film-context.d.ts +4 -0
- package/dist/interactive-film/film-context.d.ts.map +1 -0
- package/dist/interactive-film/film-context.js +30 -0
- package/dist/interactive-film/film-context.js.map +1 -0
- package/dist/interactive-film/generate.d.ts +15 -0
- package/dist/interactive-film/generate.d.ts.map +1 -0
- package/dist/interactive-film/generate.js +51 -0
- package/dist/interactive-film/generate.js.map +1 -0
- package/dist/interactive-film/graph-schema.d.ts +819 -0
- package/dist/interactive-film/graph-schema.d.ts.map +1 -0
- package/dist/interactive-film/graph-schema.js +84 -0
- package/dist/interactive-film/graph-schema.js.map +1 -0
- package/dist/interactive-film/graph-store.d.ts +5 -0
- package/dist/interactive-film/graph-store.d.ts.map +1 -0
- package/dist/interactive-film/graph-store.js +24 -0
- package/dist/interactive-film/graph-store.js.map +1 -0
- package/dist/interactive-film/memory-link.d.ts +9 -0
- package/dist/interactive-film/memory-link.d.ts.map +1 -0
- package/dist/interactive-film/memory-link.js +15 -0
- package/dist/interactive-film/memory-link.js.map +1 -0
- package/dist/interactive-film/node-image.d.ts +29 -0
- package/dist/interactive-film/node-image.d.ts.map +1 -0
- package/dist/interactive-film/node-image.js +52 -0
- package/dist/interactive-film/node-image.js.map +1 -0
- package/dist/interactive-film/paths.d.ts +14 -0
- package/dist/interactive-film/paths.d.ts.map +1 -0
- package/dist/interactive-film/paths.js +60 -0
- package/dist/interactive-film/paths.js.map +1 -0
- package/dist/interactive-film/tool-schemas.d.ts +182 -0
- package/dist/interactive-film/tool-schemas.d.ts.map +1 -0
- package/dist/interactive-film/tool-schemas.js +125 -0
- package/dist/interactive-film/tool-schemas.js.map +1 -0
- package/dist/interactive-film/validation.d.ts +14 -0
- package/dist/interactive-film/validation.d.ts.map +1 -0
- package/dist/interactive-film/validation.js +292 -0
- package/dist/interactive-film/validation.js.map +1 -0
- package/dist/llm/agent-trajectory.d.ts +27 -0
- package/dist/llm/agent-trajectory.d.ts.map +1 -0
- package/dist/llm/agent-trajectory.js +74 -0
- package/dist/llm/agent-trajectory.js.map +1 -0
- package/dist/llm/config-migration.d.ts +5 -0
- package/dist/llm/config-migration.d.ts.map +1 -0
- package/dist/llm/config-migration.js +51 -0
- package/dist/llm/config-migration.js.map +1 -0
- package/dist/llm/cover-providers.d.ts +14 -0
- package/dist/llm/cover-providers.d.ts.map +1 -0
- package/dist/llm/cover-providers.js +51 -0
- package/dist/llm/cover-providers.js.map +1 -0
- package/dist/llm/long-form-completion.d.ts +16 -0
- package/dist/llm/long-form-completion.d.ts.map +1 -0
- package/dist/llm/long-form-completion.js +62 -0
- package/dist/llm/long-form-completion.js.map +1 -0
- package/dist/llm/provider.d.ts +110 -0
- package/dist/llm/provider.d.ts.map +1 -0
- package/dist/llm/provider.js +1405 -0
- package/dist/llm/provider.js.map +1 -0
- package/dist/llm/providers/endpoints/ai360.d.ts +10 -0
- package/dist/llm/providers/endpoints/ai360.d.ts.map +1 -0
- package/dist/llm/providers/endpoints/ai360.js +34 -0
- package/dist/llm/providers/endpoints/ai360.js.map +1 -0
- package/dist/llm/providers/endpoints/anthropic.d.ts +12 -0
- package/dist/llm/providers/endpoints/anthropic.d.ts.map +1 -0
- package/dist/llm/providers/endpoints/anthropic.js +72 -0
- package/dist/llm/providers/endpoints/anthropic.js.map +1 -0
- package/dist/llm/providers/endpoints/astronCodingPlan.d.ts +16 -0
- package/dist/llm/providers/endpoints/astronCodingPlan.d.ts.map +1 -0
- package/dist/llm/providers/endpoints/astronCodingPlan.js +16 -0
- package/dist/llm/providers/endpoints/astronCodingPlan.js.map +1 -0
- package/dist/llm/providers/endpoints/baichuan.d.ts +10 -0
- package/dist/llm/providers/endpoints/baichuan.d.ts.map +1 -0
- package/dist/llm/providers/endpoints/baichuan.js +20 -0
- package/dist/llm/providers/endpoints/baichuan.js.map +1 -0
- package/dist/llm/providers/endpoints/bailian.d.ts +25 -0
- package/dist/llm/providers/endpoints/bailian.d.ts.map +1 -0
- package/dist/llm/providers/endpoints/bailian.js +42 -0
- package/dist/llm/providers/endpoints/bailian.js.map +1 -0
- package/dist/llm/providers/endpoints/bailianCodingPlan.d.ts +10 -0
- package/dist/llm/providers/endpoints/bailianCodingPlan.d.ts.map +1 -0
- package/dist/llm/providers/endpoints/bailianCodingPlan.js +22 -0
- package/dist/llm/providers/endpoints/bailianCodingPlan.js.map +1 -0
- package/dist/llm/providers/endpoints/custom.d.ts +16 -0
- package/dist/llm/providers/endpoints/custom.d.ts.map +1 -0
- package/dist/llm/providers/endpoints/custom.js +15 -0
- package/dist/llm/providers/endpoints/custom.js.map +1 -0
- package/dist/llm/providers/endpoints/deepseek.d.ts +17 -0
- package/dist/llm/providers/endpoints/deepseek.d.ts.map +1 -0
- package/dist/llm/providers/endpoints/deepseek.js +20 -0
- package/dist/llm/providers/endpoints/deepseek.js.map +1 -0
- package/dist/llm/providers/endpoints/giteeai.d.ts +10 -0
- package/dist/llm/providers/endpoints/giteeai.d.ts.map +1 -0
- package/dist/llm/providers/endpoints/giteeai.js +33 -0
- package/dist/llm/providers/endpoints/giteeai.js.map +1 -0
- package/dist/llm/providers/endpoints/githubCopilot.d.ts +10 -0
- package/dist/llm/providers/endpoints/githubCopilot.d.ts.map +1 -0
- package/dist/llm/providers/endpoints/githubCopilot.js +35 -0
- package/dist/llm/providers/endpoints/githubCopilot.js.map +1 -0
- package/dist/llm/providers/endpoints/glmCodingPlan.d.ts +9 -0
- package/dist/llm/providers/endpoints/glmCodingPlan.d.ts.map +1 -0
- package/dist/llm/providers/endpoints/glmCodingPlan.js +21 -0
- package/dist/llm/providers/endpoints/glmCodingPlan.js.map +1 -0
- package/dist/llm/providers/endpoints/google.d.ts +12 -0
- package/dist/llm/providers/endpoints/google.d.ts.map +1 -0
- package/dist/llm/providers/endpoints/google.js +41 -0
- package/dist/llm/providers/endpoints/google.js.map +1 -0
- package/dist/llm/providers/endpoints/hunyuan.d.ts +10 -0
- package/dist/llm/providers/endpoints/hunyuan.d.ts.map +1 -0
- package/dist/llm/providers/endpoints/hunyuan.js +34 -0
- package/dist/llm/providers/endpoints/hunyuan.js.map +1 -0
- package/dist/llm/providers/endpoints/infiniai.d.ts +10 -0
- package/dist/llm/providers/endpoints/infiniai.d.ts.map +1 -0
- package/dist/llm/providers/endpoints/infiniai.js +64 -0
- package/dist/llm/providers/endpoints/infiniai.js.map +1 -0
- package/dist/llm/providers/endpoints/internlm.d.ts +10 -0
- package/dist/llm/providers/endpoints/internlm.d.ts.map +1 -0
- package/dist/llm/providers/endpoints/internlm.js +20 -0
- package/dist/llm/providers/endpoints/internlm.js.map +1 -0
- package/dist/llm/providers/endpoints/kimiCode.d.ts +9 -0
- package/dist/llm/providers/endpoints/kimiCode.d.ts.map +1 -0
- package/dist/llm/providers/endpoints/kimiCode.js +16 -0
- package/dist/llm/providers/endpoints/kimiCode.js.map +1 -0
- package/dist/llm/providers/endpoints/kimiCodingPlan.d.ts +9 -0
- package/dist/llm/providers/endpoints/kimiCodingPlan.d.ts.map +1 -0
- package/dist/llm/providers/endpoints/kimiCodingPlan.js +17 -0
- package/dist/llm/providers/endpoints/kimiCodingPlan.js.map +1 -0
- package/dist/llm/providers/endpoints/kkaiapi.d.ts +14 -0
- package/dist/llm/providers/endpoints/kkaiapi.d.ts.map +1 -0
- package/dist/llm/providers/endpoints/kkaiapi.js +44 -0
- package/dist/llm/providers/endpoints/kkaiapi.js.map +1 -0
- package/dist/llm/providers/endpoints/lmstudio.d.ts +10 -0
- package/dist/llm/providers/endpoints/lmstudio.d.ts.map +1 -0
- package/dist/llm/providers/endpoints/lmstudio.js +15 -0
- package/dist/llm/providers/endpoints/lmstudio.js.map +1 -0
- package/dist/llm/providers/endpoints/longcat.d.ts +9 -0
- package/dist/llm/providers/endpoints/longcat.d.ts.map +1 -0
- package/dist/llm/providers/endpoints/longcat.js +18 -0
- package/dist/llm/providers/endpoints/longcat.js.map +1 -0
- package/dist/llm/providers/endpoints/minimax.d.ts +15 -0
- package/dist/llm/providers/endpoints/minimax.d.ts.map +1 -0
- package/dist/llm/providers/endpoints/minimax.js +27 -0
- package/dist/llm/providers/endpoints/minimax.js.map +1 -0
- package/dist/llm/providers/endpoints/minimaxCodingPlan.d.ts +9 -0
- package/dist/llm/providers/endpoints/minimaxCodingPlan.d.ts.map +1 -0
- package/dist/llm/providers/endpoints/minimaxCodingPlan.js +21 -0
- package/dist/llm/providers/endpoints/minimaxCodingPlan.js.map +1 -0
- package/dist/llm/providers/endpoints/mistral.d.ts +11 -0
- package/dist/llm/providers/endpoints/mistral.d.ts.map +1 -0
- package/dist/llm/providers/endpoints/mistral.js +31 -0
- package/dist/llm/providers/endpoints/mistral.js.map +1 -0
- package/dist/llm/providers/endpoints/modelscope.d.ts +10 -0
- package/dist/llm/providers/endpoints/modelscope.d.ts.map +1 -0
- package/dist/llm/providers/endpoints/modelscope.js +22 -0
- package/dist/llm/providers/endpoints/modelscope.js.map +1 -0
- package/dist/llm/providers/endpoints/moonshot.d.ts +12 -0
- package/dist/llm/providers/endpoints/moonshot.d.ts.map +1 -0
- package/dist/llm/providers/endpoints/moonshot.js +29 -0
- package/dist/llm/providers/endpoints/moonshot.js.map +1 -0
- package/dist/llm/providers/endpoints/newapi.d.ts +14 -0
- package/dist/llm/providers/endpoints/newapi.d.ts.map +1 -0
- package/dist/llm/providers/endpoints/newapi.js +14 -0
- package/dist/llm/providers/endpoints/newapi.js.map +1 -0
- package/dist/llm/providers/endpoints/ollama.d.ts +12 -0
- package/dist/llm/providers/endpoints/ollama.d.ts.map +1 -0
- package/dist/llm/providers/endpoints/ollama.js +63 -0
- package/dist/llm/providers/endpoints/ollama.js.map +1 -0
- package/dist/llm/providers/endpoints/openai.d.ts +12 -0
- package/dist/llm/providers/endpoints/openai.d.ts.map +1 -0
- package/dist/llm/providers/endpoints/openai.js +67 -0
- package/dist/llm/providers/endpoints/openai.js.map +1 -0
- package/dist/llm/providers/endpoints/opencodeCodingPlan.d.ts +9 -0
- package/dist/llm/providers/endpoints/opencodeCodingPlan.d.ts.map +1 -0
- package/dist/llm/providers/endpoints/opencodeCodingPlan.js +23 -0
- package/dist/llm/providers/endpoints/opencodeCodingPlan.js.map +1 -0
- package/dist/llm/providers/endpoints/openrouter.d.ts +15 -0
- package/dist/llm/providers/endpoints/openrouter.d.ts.map +1 -0
- package/dist/llm/providers/endpoints/openrouter.js +75 -0
- package/dist/llm/providers/endpoints/openrouter.js.map +1 -0
- package/dist/llm/providers/endpoints/ppio.d.ts +15 -0
- package/dist/llm/providers/endpoints/ppio.d.ts.map +1 -0
- package/dist/llm/providers/endpoints/ppio.js +73 -0
- package/dist/llm/providers/endpoints/ppio.js.map +1 -0
- package/dist/llm/providers/endpoints/qiniu.d.ts +10 -0
- package/dist/llm/providers/endpoints/qiniu.d.ts.map +1 -0
- package/dist/llm/providers/endpoints/qiniu.js +24 -0
- package/dist/llm/providers/endpoints/qiniu.js.map +1 -0
- package/dist/llm/providers/endpoints/sensenova.d.ts +10 -0
- package/dist/llm/providers/endpoints/sensenova.d.ts.map +1 -0
- package/dist/llm/providers/endpoints/sensenova.js +37 -0
- package/dist/llm/providers/endpoints/sensenova.js.map +1 -0
- package/dist/llm/providers/endpoints/siliconcloud.d.ts +14 -0
- package/dist/llm/providers/endpoints/siliconcloud.d.ts.map +1 -0
- package/dist/llm/providers/endpoints/siliconcloud.js +114 -0
- package/dist/llm/providers/endpoints/siliconcloud.js.map +1 -0
- package/dist/llm/providers/endpoints/spark.d.ts +14 -0
- package/dist/llm/providers/endpoints/spark.d.ts.map +1 -0
- package/dist/llm/providers/endpoints/spark.js +21 -0
- package/dist/llm/providers/endpoints/spark.js.map +1 -0
- package/dist/llm/providers/endpoints/stepfun.d.ts +10 -0
- package/dist/llm/providers/endpoints/stepfun.d.ts.map +1 -0
- package/dist/llm/providers/endpoints/stepfun.js +27 -0
- package/dist/llm/providers/endpoints/stepfun.js.map +1 -0
- package/dist/llm/providers/endpoints/tencentcloud.d.ts +10 -0
- package/dist/llm/providers/endpoints/tencentcloud.d.ts.map +1 -0
- package/dist/llm/providers/endpoints/tencentcloud.js +17 -0
- package/dist/llm/providers/endpoints/tencentcloud.js.map +1 -0
- package/dist/llm/providers/endpoints/volcengine.d.ts +10 -0
- package/dist/llm/providers/endpoints/volcengine.d.ts.map +1 -0
- package/dist/llm/providers/endpoints/volcengine.js +44 -0
- package/dist/llm/providers/endpoints/volcengine.js.map +1 -0
- package/dist/llm/providers/endpoints/volcengineCodingPlan.d.ts +19 -0
- package/dist/llm/providers/endpoints/volcengineCodingPlan.d.ts.map +1 -0
- package/dist/llm/providers/endpoints/volcengineCodingPlan.js +25 -0
- package/dist/llm/providers/endpoints/volcengineCodingPlan.js.map +1 -0
- package/dist/llm/providers/endpoints/wenxin.d.ts +10 -0
- package/dist/llm/providers/endpoints/wenxin.d.ts.map +1 -0
- package/dist/llm/providers/endpoints/wenxin.js +98 -0
- package/dist/llm/providers/endpoints/wenxin.js.map +1 -0
- package/dist/llm/providers/endpoints/xai.d.ts +11 -0
- package/dist/llm/providers/endpoints/xai.d.ts.map +1 -0
- package/dist/llm/providers/endpoints/xai.js +25 -0
- package/dist/llm/providers/endpoints/xai.js.map +1 -0
- package/dist/llm/providers/endpoints/xiaomimimo.d.ts +12 -0
- package/dist/llm/providers/endpoints/xiaomimimo.d.ts.map +1 -0
- package/dist/llm/providers/endpoints/xiaomimimo.js +16 -0
- package/dist/llm/providers/endpoints/xiaomimimo.js.map +1 -0
- package/dist/llm/providers/endpoints/zeroone.d.ts +10 -0
- package/dist/llm/providers/endpoints/zeroone.d.ts.map +1 -0
- package/dist/llm/providers/endpoints/zeroone.js +26 -0
- package/dist/llm/providers/endpoints/zeroone.js.map +1 -0
- package/dist/llm/providers/endpoints/zhipu.d.ts +12 -0
- package/dist/llm/providers/endpoints/zhipu.d.ts.map +1 -0
- package/dist/llm/providers/endpoints/zhipu.js +51 -0
- package/dist/llm/providers/endpoints/zhipu.js.map +1 -0
- package/dist/llm/providers/index.d.ts +5 -0
- package/dist/llm/providers/index.d.ts.map +1 -0
- package/dist/llm/providers/index.js +64 -0
- package/dist/llm/providers/index.js.map +1 -0
- package/dist/llm/providers/lookup.d.ts +16 -0
- package/dist/llm/providers/lookup.d.ts.map +1 -0
- package/dist/llm/providers/lookup.js +68 -0
- package/dist/llm/providers/lookup.js.map +1 -0
- package/dist/llm/providers/probe.d.ts +11 -0
- package/dist/llm/providers/probe.d.ts.map +1 -0
- package/dist/llm/providers/probe.js +24 -0
- package/dist/llm/providers/probe.js.map +1 -0
- package/dist/llm/providers/types.d.ts +71 -0
- package/dist/llm/providers/types.d.ts.map +1 -0
- package/dist/llm/providers/types.js +9 -0
- package/dist/llm/providers/types.js.map +1 -0
- package/dist/llm/providers/verify.d.ts +27 -0
- package/dist/llm/providers/verify.d.ts.map +1 -0
- package/dist/llm/providers/verify.js +77 -0
- package/dist/llm/providers/verify.js.map +1 -0
- package/dist/llm/secrets.d.ts +9 -0
- package/dist/llm/secrets.d.ts.map +1 -0
- package/dist/llm/secrets.js +56 -0
- package/dist/llm/secrets.js.map +1 -0
- package/dist/llm/service-presets.d.ts +45 -0
- package/dist/llm/service-presets.d.ts.map +1 -0
- package/dist/llm/service-presets.js +180 -0
- package/dist/llm/service-presets.js.map +1 -0
- package/dist/llm/service-resolver.d.ts +10 -0
- package/dist/llm/service-resolver.d.ts.map +1 -0
- package/dist/llm/service-resolver.js +62 -0
- package/dist/llm/service-resolver.js.map +1 -0
- package/dist/llm/think-tag-stripper.d.ts +15 -0
- package/dist/llm/think-tag-stripper.d.ts.map +1 -0
- package/dist/llm/think-tag-stripper.js +60 -0
- package/dist/llm/think-tag-stripper.js.map +1 -0
- package/dist/materials/ingest.d.ts +31 -0
- package/dist/materials/ingest.d.ts.map +1 -0
- package/dist/materials/ingest.js +224 -0
- package/dist/materials/ingest.js.map +1 -0
- package/dist/materials/retrieve.d.ts +20 -0
- package/dist/materials/retrieve.d.ts.map +1 -0
- package/dist/materials/retrieve.js +109 -0
- package/dist/materials/retrieve.js.map +1 -0
- package/dist/models/book-rules.d.ts +142 -0
- package/dist/models/book-rules.d.ts.map +1 -0
- package/dist/models/book-rules.js +286 -0
- package/dist/models/book-rules.js.map +1 -0
- package/dist/models/book.d.ts +94 -0
- package/dist/models/book.d.ts.map +1 -0
- package/dist/models/book.js +79 -0
- package/dist/models/book.js.map +1 -0
- package/dist/models/chapter.d.ts +131 -0
- package/dist/models/chapter.d.ts.map +1 -0
- package/dist/models/chapter.js +38 -0
- package/dist/models/chapter.js.map +1 -0
- package/dist/models/context-compression.d.ts +13 -0
- package/dist/models/context-compression.d.ts.map +1 -0
- package/dist/models/context-compression.js +2 -0
- package/dist/models/context-compression.js.map +1 -0
- package/dist/models/detection.d.ts +25 -0
- package/dist/models/detection.d.ts.map +1 -0
- package/dist/models/detection.js +2 -0
- package/dist/models/detection.js.map +1 -0
- package/dist/models/genre-profile.d.ts +45 -0
- package/dist/models/genre-profile.d.ts.map +1 -0
- package/dist/models/genre-profile.js +26 -0
- package/dist/models/genre-profile.js.map +1 -0
- package/dist/models/input-governance.d.ts +437 -0
- package/dist/models/input-governance.d.ts.map +1 -0
- package/dist/models/input-governance.js +104 -0
- package/dist/models/input-governance.js.map +1 -0
- package/dist/models/length-governance.d.ts +85 -0
- package/dist/models/length-governance.d.ts.map +1 -0
- package/dist/models/length-governance.js +31 -0
- package/dist/models/length-governance.js.map +1 -0
- package/dist/models/play.d.ts +530 -0
- package/dist/models/play.d.ts.map +1 -0
- package/dist/models/play.js +318 -0
- package/dist/models/play.js.map +1 -0
- package/dist/models/project.d.ts +797 -0
- package/dist/models/project.d.ts.map +1 -0
- package/dist/models/project.js +152 -0
- package/dist/models/project.js.map +1 -0
- package/dist/models/runtime-state.d.ts +708 -0
- package/dist/models/runtime-state.d.ts.map +1 -0
- package/dist/models/runtime-state.js +105 -0
- package/dist/models/runtime-state.js.map +1 -0
- package/dist/models/state.d.ts +48 -0
- package/dist/models/state.d.ts.map +1 -0
- package/dist/models/state.js +6 -0
- package/dist/models/state.js.map +1 -0
- package/dist/models/style-profile.d.ts +16 -0
- package/dist/models/style-profile.d.ts.map +1 -0
- package/dist/models/style-profile.js +2 -0
- package/dist/models/style-profile.js.map +1 -0
- package/dist/notify/dispatcher.d.ts +10 -0
- package/dist/notify/dispatcher.d.ts.map +1 -0
- package/dist/notify/dispatcher.js +67 -0
- package/dist/notify/dispatcher.js.map +1 -0
- package/dist/notify/feishu.d.ts +6 -0
- package/dist/notify/feishu.d.ts.map +1 -0
- package/dist/notify/feishu.js +32 -0
- package/dist/notify/feishu.js.map +1 -0
- package/dist/notify/format.d.ts +12 -0
- package/dist/notify/format.d.ts.map +1 -0
- package/dist/notify/format.js +11 -0
- package/dist/notify/format.js.map +1 -0
- package/dist/notify/telegram.d.ts +7 -0
- package/dist/notify/telegram.d.ts.map +1 -0
- package/dist/notify/telegram.js +18 -0
- package/dist/notify/telegram.js.map +1 -0
- package/dist/notify/webhook.d.ts +15 -0
- package/dist/notify/webhook.d.ts.map +1 -0
- package/dist/notify/webhook.js +28 -0
- package/dist/notify/webhook.js.map +1 -0
- package/dist/notify/wechat-work.d.ts +6 -0
- package/dist/notify/wechat-work.d.ts.map +1 -0
- package/dist/notify/wechat-work.js +15 -0
- package/dist/notify/wechat-work.js.map +1 -0
- package/dist/pipeline/chapter-persistence.d.ts +33 -0
- package/dist/pipeline/chapter-persistence.d.ts.map +1 -0
- package/dist/pipeline/chapter-persistence.js +39 -0
- package/dist/pipeline/chapter-persistence.js.map +1 -0
- package/dist/pipeline/chapter-review-cycle.d.ts +81 -0
- package/dist/pipeline/chapter-review-cycle.d.ts.map +1 -0
- package/dist/pipeline/chapter-review-cycle.js +190 -0
- package/dist/pipeline/chapter-review-cycle.js.map +1 -0
- package/dist/pipeline/chapter-state-recovery.d.ts +61 -0
- package/dist/pipeline/chapter-state-recovery.d.ts.map +1 -0
- package/dist/pipeline/chapter-state-recovery.js +135 -0
- package/dist/pipeline/chapter-state-recovery.js.map +1 -0
- package/dist/pipeline/chapter-truth-validation.d.ts +42 -0
- package/dist/pipeline/chapter-truth-validation.d.ts.map +1 -0
- package/dist/pipeline/chapter-truth-validation.js +93 -0
- package/dist/pipeline/chapter-truth-validation.js.map +1 -0
- package/dist/pipeline/detection-runner.d.ts +31 -0
- package/dist/pipeline/detection-runner.d.ts.map +1 -0
- package/dist/pipeline/detection-runner.js +109 -0
- package/dist/pipeline/detection-runner.js.map +1 -0
- package/dist/pipeline/persisted-governed-plan.d.ts +5 -0
- package/dist/pipeline/persisted-governed-plan.d.ts.map +1 -0
- package/dist/pipeline/persisted-governed-plan.js +249 -0
- package/dist/pipeline/persisted-governed-plan.js.map +1 -0
- package/dist/pipeline/runner.d.ts +334 -0
- package/dist/pipeline/runner.d.ts.map +1 -0
- package/dist/pipeline/runner.js +2974 -0
- package/dist/pipeline/runner.js.map +1 -0
- package/dist/pipeline/scheduler.d.ts +58 -0
- package/dist/pipeline/scheduler.d.ts.map +1 -0
- package/dist/pipeline/scheduler.js +322 -0
- package/dist/pipeline/scheduler.js.map +1 -0
- package/dist/pipeline/script-storyboard-runner.d.ts +130 -0
- package/dist/pipeline/script-storyboard-runner.d.ts.map +1 -0
- package/dist/pipeline/script-storyboard-runner.js +532 -0
- package/dist/pipeline/script-storyboard-runner.js.map +1 -0
- package/dist/pipeline/short-fiction-runner.d.ts +110 -0
- package/dist/pipeline/short-fiction-runner.d.ts.map +1 -0
- package/dist/pipeline/short-fiction-runner.js +864 -0
- package/dist/pipeline/short-fiction-runner.js.map +1 -0
- package/dist/play/play-agents.d.ts +72 -0
- package/dist/play/play-agents.d.ts.map +1 -0
- package/dist/play/play-agents.js +580 -0
- package/dist/play/play-agents.js.map +1 -0
- package/dist/play/play-db-factory.d.ts +9 -0
- package/dist/play/play-db-factory.d.ts.map +1 -0
- package/dist/play/play-db-factory.js +18 -0
- package/dist/play/play-db-factory.js.map +1 -0
- package/dist/play/play-db.d.ts +22 -0
- package/dist/play/play-db.d.ts.map +1 -0
- package/dist/play/play-db.js +248 -0
- package/dist/play/play-db.js.map +1 -0
- package/dist/play/play-file-db.d.ts +32 -0
- package/dist/play/play-file-db.d.ts.map +1 -0
- package/dist/play/play-file-db.js +156 -0
- package/dist/play/play-file-db.js.map +1 -0
- package/dist/play/play-image.d.ts +58 -0
- package/dist/play/play-image.d.ts.map +1 -0
- package/dist/play/play-image.js +142 -0
- package/dist/play/play-image.js.map +1 -0
- package/dist/play/play-reducer.d.ts +31 -0
- package/dist/play/play-reducer.d.ts.map +1 -0
- package/dist/play/play-reducer.js +261 -0
- package/dist/play/play-reducer.js.map +1 -0
- package/dist/play/play-runner.d.ts +116 -0
- package/dist/play/play-runner.d.ts.map +1 -0
- package/dist/play/play-runner.js +582 -0
- package/dist/play/play-runner.js.map +1 -0
- package/dist/play/play-store.d.ts +113 -0
- package/dist/play/play-store.d.ts.map +1 -0
- package/dist/play/play-store.js +314 -0
- package/dist/play/play-store.js.map +1 -0
- package/dist/production/harness.d.ts +57 -0
- package/dist/production/harness.d.ts.map +1 -0
- package/dist/production/harness.js +51 -0
- package/dist/production/harness.js.map +1 -0
- package/dist/prompts/builtin-prompts.d.ts +10 -0
- package/dist/prompts/builtin-prompts.d.ts.map +1 -0
- package/dist/prompts/builtin-prompts.js +157 -0
- package/dist/prompts/builtin-prompts.js.map +1 -0
- package/dist/prompts/index.d.ts +5 -0
- package/dist/prompts/index.d.ts.map +1 -0
- package/dist/prompts/index.js +5 -0
- package/dist/prompts/index.js.map +1 -0
- package/dist/prompts/prompt-pack.d.ts +33 -0
- package/dist/prompts/prompt-pack.d.ts.map +1 -0
- package/dist/prompts/prompt-pack.js +82 -0
- package/dist/prompts/prompt-pack.js.map +1 -0
- package/dist/prompts/short-fiction.d.ts +58 -0
- package/dist/prompts/short-fiction.d.ts.map +1 -0
- package/dist/prompts/short-fiction.js +480 -0
- package/dist/prompts/short-fiction.js.map +1 -0
- package/dist/prompts/types.d.ts +22 -0
- package/dist/prompts/types.d.ts.map +1 -0
- package/dist/prompts/types.js +9 -0
- package/dist/prompts/types.js.map +1 -0
- package/dist/references/book-references.d.ts +40 -0
- package/dist/references/book-references.d.ts.map +1 -0
- package/dist/references/book-references.js +207 -0
- package/dist/references/book-references.js.map +1 -0
- package/dist/references/reference-context.d.ts +26 -0
- package/dist/references/reference-context.d.ts.map +1 -0
- package/dist/references/reference-context.js +120 -0
- package/dist/references/reference-context.js.map +1 -0
- package/dist/retrieval/local-search.d.ts +38 -0
- package/dist/retrieval/local-search.d.ts.map +1 -0
- package/dist/retrieval/local-search.js +232 -0
- package/dist/retrieval/local-search.js.map +1 -0
- package/dist/skills/builtin-loader.d.ts +9 -0
- package/dist/skills/builtin-loader.d.ts.map +1 -0
- package/dist/skills/builtin-loader.js +24 -0
- package/dist/skills/builtin-loader.js.map +1 -0
- package/dist/skills/external-loader.d.ts +26 -0
- package/dist/skills/external-loader.d.ts.map +1 -0
- package/dist/skills/external-loader.js +186 -0
- package/dist/skills/external-loader.js.map +1 -0
- package/dist/skills/index.d.ts +6 -0
- package/dist/skills/index.d.ts.map +1 -0
- package/dist/skills/index.js +6 -0
- package/dist/skills/index.js.map +1 -0
- package/dist/skills/production-bindings.d.ts +18 -0
- package/dist/skills/production-bindings.d.ts.map +1 -0
- package/dist/skills/production-bindings.js +37 -0
- package/dist/skills/production-bindings.js.map +1 -0
- package/dist/skills/registry.d.ts +6 -0
- package/dist/skills/registry.d.ts.map +1 -0
- package/dist/skills/registry.js +68 -0
- package/dist/skills/registry.js.map +1 -0
- package/dist/skills/types.d.ts +42 -0
- package/dist/skills/types.d.ts.map +1 -0
- package/dist/skills/types.js +10 -0
- package/dist/skills/types.js.map +1 -0
- package/dist/state/chapter-delete.d.ts +30 -0
- package/dist/state/chapter-delete.d.ts.map +1 -0
- package/dist/state/chapter-delete.js +78 -0
- package/dist/state/chapter-delete.js.map +1 -0
- package/dist/state/chapter-word-sync.d.ts +30 -0
- package/dist/state/chapter-word-sync.d.ts.map +1 -0
- package/dist/state/chapter-word-sync.js +62 -0
- package/dist/state/chapter-word-sync.js.map +1 -0
- package/dist/state/chapter-workspace.d.ts +15 -0
- package/dist/state/chapter-workspace.d.ts.map +1 -0
- package/dist/state/chapter-workspace.js +118 -0
- package/dist/state/chapter-workspace.js.map +1 -0
- package/dist/state/manager.d.ts +70 -0
- package/dist/state/manager.d.ts.map +1 -0
- package/dist/state/manager.js +727 -0
- package/dist/state/manager.js.map +1 -0
- package/dist/state/memory-db.d.ts +83 -0
- package/dist/state/memory-db.d.ts.map +1 -0
- package/dist/state/memory-db.js +249 -0
- package/dist/state/memory-db.js.map +1 -0
- package/dist/state/runtime-state-store.d.ts +38 -0
- package/dist/state/runtime-state-store.d.ts.map +1 -0
- package/dist/state/runtime-state-store.js +164 -0
- package/dist/state/runtime-state-store.js.map +1 -0
- package/dist/state/state-bootstrap.d.ts +21 -0
- package/dist/state/state-bootstrap.d.ts.map +1 -0
- package/dist/state/state-bootstrap.js +476 -0
- package/dist/state/state-bootstrap.js.map +1 -0
- package/dist/state/state-projections.d.ts +7 -0
- package/dist/state/state-projections.d.ts.map +1 -0
- package/dist/state/state-projections.js +209 -0
- package/dist/state/state-projections.js.map +1 -0
- package/dist/state/state-reducer.d.ts +13 -0
- package/dist/state/state-reducer.d.ts.map +1 -0
- package/dist/state/state-reducer.js +193 -0
- package/dist/state/state-reducer.js.map +1 -0
- package/dist/state/state-validator.d.ts +12 -0
- package/dist/state/state-validator.d.ts.map +1 -0
- package/dist/state/state-validator.js +67 -0
- package/dist/state/state-validator.js.map +1 -0
- package/dist/translation/epub.d.ts +10 -0
- package/dist/translation/epub.d.ts.map +1 -0
- package/dist/translation/epub.js +86 -0
- package/dist/translation/epub.js.map +1 -0
- package/dist/translation/export.d.ts +6 -0
- package/dist/translation/export.d.ts.map +1 -0
- package/dist/translation/export.js +68 -0
- package/dist/translation/export.js.map +1 -0
- package/dist/translation/index.d.ts +9 -0
- package/dist/translation/index.d.ts.map +1 -0
- package/dist/translation/index.js +9 -0
- package/dist/translation/index.js.map +1 -0
- package/dist/translation/llm-model.d.ts +11 -0
- package/dist/translation/llm-model.d.ts.map +1 -0
- package/dist/translation/llm-model.js +135 -0
- package/dist/translation/llm-model.js.map +1 -0
- package/dist/translation/project.d.ts +3 -0
- package/dist/translation/project.d.ts.map +1 -0
- package/dist/translation/project.js +76 -0
- package/dist/translation/project.js.map +1 -0
- package/dist/translation/run-store.d.ts +12 -0
- package/dist/translation/run-store.d.ts.map +1 -0
- package/dist/translation/run-store.js +69 -0
- package/dist/translation/run-store.js.map +1 -0
- package/dist/translation/runner.d.ts +6 -0
- package/dist/translation/runner.d.ts.map +1 -0
- package/dist/translation/runner.js +155 -0
- package/dist/translation/runner.js.map +1 -0
- package/dist/translation/source.d.ts +12 -0
- package/dist/translation/source.d.ts.map +1 -0
- package/dist/translation/source.js +66 -0
- package/dist/translation/source.js.map +1 -0
- package/dist/translation/text.d.ts +10 -0
- package/dist/translation/text.d.ts.map +1 -0
- package/dist/translation/text.js +110 -0
- package/dist/translation/text.js.map +1 -0
- package/dist/translation/types.d.ts +96 -0
- package/dist/translation/types.d.ts.map +1 -0
- package/dist/translation/types.js +2 -0
- package/dist/translation/types.js.map +1 -0
- package/dist/utils/analytics.d.ts +39 -0
- package/dist/utils/analytics.d.ts.map +1 -0
- package/dist/utils/analytics.js +50 -0
- package/dist/utils/analytics.js.map +1 -0
- package/dist/utils/atomic-file-set.d.ts +12 -0
- package/dist/utils/atomic-file-set.d.ts.map +1 -0
- package/dist/utils/atomic-file-set.js +93 -0
- package/dist/utils/atomic-file-set.js.map +1 -0
- package/dist/utils/book-eval.d.ts +35 -0
- package/dist/utils/book-eval.d.ts.map +1 -0
- package/dist/utils/book-eval.js +116 -0
- package/dist/utils/book-eval.js.map +1 -0
- package/dist/utils/book-id.d.ts +4 -0
- package/dist/utils/book-id.d.ts.map +1 -0
- package/dist/utils/book-id.js +27 -0
- package/dist/utils/book-id.js.map +1 -0
- package/dist/utils/cadence-policy.d.ts +36 -0
- package/dist/utils/cadence-policy.d.ts.map +1 -0
- package/dist/utils/cadence-policy.js +38 -0
- package/dist/utils/cadence-policy.js.map +1 -0
- package/dist/utils/chapter-cadence.d.ts +34 -0
- package/dist/utils/chapter-cadence.d.ts.map +1 -0
- package/dist/utils/chapter-cadence.js +143 -0
- package/dist/utils/chapter-cadence.js.map +1 -0
- package/dist/utils/chapter-memo-parser.d.ts +22 -0
- package/dist/utils/chapter-memo-parser.d.ts.map +1 -0
- package/dist/utils/chapter-memo-parser.js +158 -0
- package/dist/utils/chapter-memo-parser.js.map +1 -0
- package/dist/utils/chapter-splitter.d.ts +18 -0
- package/dist/utils/chapter-splitter.d.ts.map +1 -0
- package/dist/utils/chapter-splitter.js +60 -0
- package/dist/utils/chapter-splitter.js.map +1 -0
- package/dist/utils/config-loader.d.ts +11 -0
- package/dist/utils/config-loader.d.ts.map +1 -0
- package/dist/utils/config-loader.js +16 -0
- package/dist/utils/config-loader.js.map +1 -0
- package/dist/utils/context-assembly.d.ts +29 -0
- package/dist/utils/context-assembly.d.ts.map +1 -0
- package/dist/utils/context-assembly.js +117 -0
- package/dist/utils/context-assembly.js.map +1 -0
- package/dist/utils/context-filter.d.ts +31 -0
- package/dist/utils/context-filter.d.ts.map +1 -0
- package/dist/utils/context-filter.js +163 -0
- package/dist/utils/context-filter.js.map +1 -0
- package/dist/utils/effective-llm-config.d.ts +34 -0
- package/dist/utils/effective-llm-config.d.ts.map +1 -0
- package/dist/utils/effective-llm-config.js +463 -0
- package/dist/utils/effective-llm-config.js.map +1 -0
- package/dist/utils/governed-context.d.ts +11 -0
- package/dist/utils/governed-context.d.ts.map +1 -0
- package/dist/utils/governed-context.js +42 -0
- package/dist/utils/governed-context.js.map +1 -0
- package/dist/utils/governed-working-set.d.ts +18 -0
- package/dist/utils/governed-working-set.d.ts.map +1 -0
- package/dist/utils/governed-working-set.js +296 -0
- package/dist/utils/governed-working-set.js.map +1 -0
- package/dist/utils/hook-arbiter.d.ts +16 -0
- package/dist/utils/hook-arbiter.d.ts.map +1 -0
- package/dist/utils/hook-arbiter.js +161 -0
- package/dist/utils/hook-arbiter.js.map +1 -0
- package/dist/utils/hook-governance.d.ts +26 -0
- package/dist/utils/hook-governance.d.ts.map +1 -0
- package/dist/utils/hook-governance.js +65 -0
- package/dist/utils/hook-governance.js.map +1 -0
- package/dist/utils/hook-health.d.ts +15 -0
- package/dist/utils/hook-health.d.ts.map +1 -0
- package/dist/utils/hook-health.js +131 -0
- package/dist/utils/hook-health.js.map +1 -0
- package/dist/utils/hook-ledger-validator.d.ts +82 -0
- package/dist/utils/hook-ledger-validator.d.ts.map +1 -0
- package/dist/utils/hook-ledger-validator.js +225 -0
- package/dist/utils/hook-ledger-validator.js.map +1 -0
- package/dist/utils/hook-lifecycle.d.ts +41 -0
- package/dist/utils/hook-lifecycle.d.ts.map +1 -0
- package/dist/utils/hook-lifecycle.js +183 -0
- package/dist/utils/hook-lifecycle.js.map +1 -0
- package/dist/utils/hook-policy.d.ts +57 -0
- package/dist/utils/hook-policy.d.ts.map +1 -0
- package/dist/utils/hook-policy.js +96 -0
- package/dist/utils/hook-policy.js.map +1 -0
- package/dist/utils/hook-promotion.d.ts +83 -0
- package/dist/utils/hook-promotion.d.ts.map +1 -0
- package/dist/utils/hook-promotion.js +241 -0
- package/dist/utils/hook-promotion.js.map +1 -0
- package/dist/utils/hook-stale-detection.d.ts +51 -0
- package/dist/utils/hook-stale-detection.d.ts.map +1 -0
- package/dist/utils/hook-stale-detection.js +125 -0
- package/dist/utils/hook-stale-detection.js.map +1 -0
- package/dist/utils/language.d.ts +19 -0
- package/dist/utils/language.d.ts.map +1 -0
- package/dist/utils/language.js +29 -0
- package/dist/utils/language.js.map +1 -0
- package/dist/utils/length-metrics.d.ts +12 -0
- package/dist/utils/length-metrics.d.ts.map +1 -0
- package/dist/utils/length-metrics.js +85 -0
- package/dist/utils/length-metrics.js.map +1 -0
- package/dist/utils/llm-endpoint-auth.d.ts +5 -0
- package/dist/utils/llm-endpoint-auth.d.ts.map +1 -0
- package/dist/utils/llm-endpoint-auth.js +36 -0
- package/dist/utils/llm-endpoint-auth.js.map +1 -0
- package/dist/utils/llm-env.d.ts +14 -0
- package/dist/utils/llm-env.d.ts.map +1 -0
- package/dist/utils/llm-env.js +53 -0
- package/dist/utils/llm-env.js.map +1 -0
- package/dist/utils/logger.d.ts +31 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +79 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/long-span-fatigue.d.ts +28 -0
- package/dist/utils/long-span-fatigue.d.ts.map +1 -0
- package/dist/utils/long-span-fatigue.js +406 -0
- package/dist/utils/long-span-fatigue.js.map +1 -0
- package/dist/utils/memory-retrieval.d.ts +71 -0
- package/dist/utils/memory-retrieval.d.ts.map +1 -0
- package/dist/utils/memory-retrieval.js +360 -0
- package/dist/utils/memory-retrieval.js.map +1 -0
- package/dist/utils/narrative-control.d.ts +16 -0
- package/dist/utils/narrative-control.d.ts.map +1 -0
- package/dist/utils/narrative-control.js +131 -0
- package/dist/utils/narrative-control.js.map +1 -0
- package/dist/utils/outline-paths.d.ts +63 -0
- package/dist/utils/outline-paths.d.ts.map +1 -0
- package/dist/utils/outline-paths.js +311 -0
- package/dist/utils/outline-paths.js.map +1 -0
- package/dist/utils/path-safety.d.ts +2 -0
- package/dist/utils/path-safety.d.ts.map +1 -0
- package/dist/utils/path-safety.js +11 -0
- package/dist/utils/path-safety.js.map +1 -0
- package/dist/utils/planning-materials.d.ts +35 -0
- package/dist/utils/planning-materials.d.ts.map +1 -0
- package/dist/utils/planning-materials.js +123 -0
- package/dist/utils/planning-materials.js.map +1 -0
- package/dist/utils/posix-path.d.ts +2 -0
- package/dist/utils/posix-path.d.ts.map +1 -0
- package/dist/utils/posix-path.js +7 -0
- package/dist/utils/posix-path.js.map +1 -0
- package/dist/utils/pov-filter.d.ts +30 -0
- package/dist/utils/pov-filter.d.ts.map +1 -0
- package/dist/utils/pov-filter.js +129 -0
- package/dist/utils/pov-filter.js.map +1 -0
- package/dist/utils/proxy-fetch.d.ts +9 -0
- package/dist/utils/proxy-fetch.d.ts.map +1 -0
- package/dist/utils/proxy-fetch.js +31 -0
- package/dist/utils/proxy-fetch.js.map +1 -0
- package/dist/utils/runtime-writer.d.ts +14 -0
- package/dist/utils/runtime-writer.d.ts.map +1 -0
- package/dist/utils/runtime-writer.js +21 -0
- package/dist/utils/runtime-writer.js.map +1 -0
- package/dist/utils/spot-fix-patches.d.ts +21 -0
- package/dist/utils/spot-fix-patches.d.ts.map +1 -0
- package/dist/utils/spot-fix-patches.js +148 -0
- package/dist/utils/spot-fix-patches.js.map +1 -0
- package/dist/utils/story-markdown.d.ts +13 -0
- package/dist/utils/story-markdown.d.ts.map +1 -0
- package/dist/utils/story-markdown.js +320 -0
- package/dist/utils/story-markdown.js.map +1 -0
- package/dist/utils/web-search.d.ts +28 -0
- package/dist/utils/web-search.d.ts.map +1 -0
- package/dist/utils/web-search.js +72 -0
- package/dist/utils/web-search.js.map +1 -0
- package/dist/utils/writing-methodology.d.ts +10 -0
- package/dist/utils/writing-methodology.d.ts.map +1 -0
- package/dist/utils/writing-methodology.js +163 -0
- package/dist/utils/writing-methodology.js.map +1 -0
- package/genres/cozy.md +43 -0
- package/genres/cultivation.md +42 -0
- package/genres/dungeon-core.md +40 -0
- package/genres/horror.md +51 -0
- package/genres/isekai.md +43 -0
- package/genres/litrpg.md +43 -0
- package/genres/other.md +24 -0
- package/genres/progression.md +41 -0
- package/genres/romantasy.md +45 -0
- package/genres/sci-fi.md +42 -0
- package/genres/system-apocalypse.md +40 -0
- package/genres/tower-climber.md +41 -0
- package/genres/urban.md +53 -0
- package/genres/xianxia.md +46 -0
- package/genres/xuanhuan.md +64 -0
- package/package.json +76 -0
- package/skills/inkos-interactive-film/SKILL.md +16 -0
- package/skills/inkos-interactive-film/references/branch-state-craft.md +13 -0
- package/skills/inkos-long-market-research/SKILL.md +16 -0
- package/skills/inkos-long-market-research/references/research-rubric.md +19 -0
- package/skills/inkos-long-story-analysis/SKILL.md +17 -0
- package/skills/inkos-long-story-analysis/references/analysis-lens.md +16 -0
- package/skills/inkos-long-writing/SKILL.md +17 -0
- package/skills/inkos-long-writing/references/reader-contract-and-progression.md +13 -0
- package/skills/inkos-long-writing/references/scene-dialogue-and-length-budget.md +13 -0
- package/skills/inkos-play-world/SKILL.md +17 -0
- package/skills/inkos-play-world/references/world-turn-continuity.md +13 -0
- package/skills/inkos-script-writing/SKILL.md +15 -0
- package/skills/inkos-script-writing/references/episode-scene-craft.md +13 -0
- package/skills/inkos-short-market-research/SKILL.md +17 -0
- package/skills/inkos-short-market-research/references/short-market-rubric.md +16 -0
- package/skills/inkos-short-story-analysis/SKILL.md +16 -0
- package/skills/inkos-short-story-analysis/references/deconstruction-template.md +14 -0
- package/skills/inkos-short-writing/SKILL.md +18 -0
- package/skills/inkos-short-writing/references/production-checklist.md +19 -0
- package/skills/inkos-story-cover/SKILL.md +17 -0
- package/skills/inkos-story-cover/references/cover-brief.md +16 -0
- package/skills/inkos-story-deslop/SKILL.md +16 -0
- package/skills/inkos-story-deslop/references/semantic-cleanup.md +13 -0
- package/skills/inkos-story-import/SKILL.md +19 -0
- package/skills/inkos-story-import/references/reconstruction-rubric.md +13 -0
- package/skills/inkos-story-review/SKILL.md +16 -0
- package/skills/inkos-story-review/references/review-matrix.md +21 -0
- package/skills/inkos-storyboard/SKILL.md +15 -0
- package/skills/inkos-storyboard/references/shot-continuity.md +13 -0
- package/skills/inkos-translation/SKILL.md +14 -0
- package/skills/inkos-translation/references/long-form-consistency.md +13 -0
|
@@ -0,0 +1,1405 @@
|
|
|
1
|
+
import { streamSimple as piStreamSimple, completeSimple as piCompleteSimple, createAssistantMessageEventStream, } from "@mariozechner/pi-ai";
|
|
2
|
+
import { resolveServicePreset } from "./service-presets.js";
|
|
3
|
+
import { getEndpoint } from "./providers/index.js";
|
|
4
|
+
import { lookupModel } from "./providers/lookup.js";
|
|
5
|
+
import { fetchWithProxy } from "../utils/proxy-fetch.js";
|
|
6
|
+
import { isApiKeyOptionalForEndpoint } from "../utils/llm-endpoint-auth.js";
|
|
7
|
+
import { isLlmStubEnabled, stubChatCompletion } from "../agent/llm-stub.js";
|
|
8
|
+
import { createLeadingThinkTagStripper, stripLeadingThinkBlock } from "./think-tag-stripper.js";
|
|
9
|
+
import { agentTrajectoryHeaders, beginAgentModelCall, } from "./agent-trajectory.js";
|
|
10
|
+
const INKOS_USER_AGENT = "InkOS/1.3.5";
|
|
11
|
+
const UNKNOWN_MODEL_FALLBACK_MAX_TOKENS = 8192 * 3;
|
|
12
|
+
const TRANSIENT_LLM_RETRIES = 2;
|
|
13
|
+
const DEFAULT_FIRST_STREAM_EVENT_TIMEOUT_MS = 120_000;
|
|
14
|
+
const DEFAULT_STREAM_IDLE_TIMEOUT_MS = 90_000;
|
|
15
|
+
const DEFAULT_PIPELINE_FIRST_STREAM_EVENT_TIMEOUT_MS = 300_000;
|
|
16
|
+
const DEFAULT_PIPELINE_STREAM_IDLE_TIMEOUT_MS = 180_000;
|
|
17
|
+
export class LLMStreamInactivityError extends Error {
|
|
18
|
+
stage;
|
|
19
|
+
timeoutMs;
|
|
20
|
+
constructor(stage, timeoutMs) {
|
|
21
|
+
super(stage === "first-event"
|
|
22
|
+
? `LLM stream produced no event within ${timeoutMs}ms`
|
|
23
|
+
: `LLM stream produced no new event for ${timeoutMs}ms`);
|
|
24
|
+
this.stage = stage;
|
|
25
|
+
this.timeoutMs = timeoutMs;
|
|
26
|
+
this.name = "LLMStreamInactivityError";
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
function createStreamActivityDeadline(callerSignal, defaults = {
|
|
30
|
+
firstEventTimeoutMs: DEFAULT_FIRST_STREAM_EVENT_TIMEOUT_MS,
|
|
31
|
+
idleTimeoutMs: DEFAULT_STREAM_IDLE_TIMEOUT_MS,
|
|
32
|
+
}, overrides) {
|
|
33
|
+
const firstEventTimeoutMs = readPositiveTimeout(process.env.INKOS_LLM_FIRST_EVENT_TIMEOUT_MS, readPositiveTimeout(overrides?.firstEventTimeoutMs, defaults.firstEventTimeoutMs));
|
|
34
|
+
const idleTimeoutMs = readPositiveTimeout(process.env.INKOS_LLM_STREAM_IDLE_TIMEOUT_MS, readPositiveTimeout(overrides?.idleTimeoutMs, defaults.idleTimeoutMs));
|
|
35
|
+
const controller = new AbortController();
|
|
36
|
+
const signal = callerSignal
|
|
37
|
+
? AbortSignal.any([callerSignal, controller.signal])
|
|
38
|
+
: controller.signal;
|
|
39
|
+
let timeoutError;
|
|
40
|
+
let timer;
|
|
41
|
+
const arm = (stage, timeoutMs) => {
|
|
42
|
+
if (timer)
|
|
43
|
+
clearTimeout(timer);
|
|
44
|
+
timer = setTimeout(() => {
|
|
45
|
+
timeoutError = new LLMStreamInactivityError(stage, timeoutMs);
|
|
46
|
+
controller.abort(timeoutError);
|
|
47
|
+
}, timeoutMs);
|
|
48
|
+
timer.unref?.();
|
|
49
|
+
};
|
|
50
|
+
arm("first-event", firstEventTimeoutMs);
|
|
51
|
+
return {
|
|
52
|
+
signal,
|
|
53
|
+
activity: () => {
|
|
54
|
+
if (!signal.aborted)
|
|
55
|
+
arm("idle", idleTimeoutMs);
|
|
56
|
+
},
|
|
57
|
+
stop: () => {
|
|
58
|
+
if (timer)
|
|
59
|
+
clearTimeout(timer);
|
|
60
|
+
timer = undefined;
|
|
61
|
+
},
|
|
62
|
+
timeoutError: () => timeoutError,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
function readPositiveTimeout(value, fallback) {
|
|
66
|
+
const parsed = Number(value);
|
|
67
|
+
return Number.isFinite(parsed) && parsed > 0 ? Math.floor(parsed) : fallback;
|
|
68
|
+
}
|
|
69
|
+
export function guardAssistantMessageStream(model, start, callerSignal, deadlineOptions) {
|
|
70
|
+
const guarded = createAssistantMessageEventStream();
|
|
71
|
+
const deadline = createStreamActivityDeadline(callerSignal, undefined, deadlineOptions);
|
|
72
|
+
void (async () => {
|
|
73
|
+
let terminalSeen = false;
|
|
74
|
+
try {
|
|
75
|
+
const upstream = start(deadline.signal);
|
|
76
|
+
const iterator = upstream[Symbol.asyncIterator]();
|
|
77
|
+
while (true) {
|
|
78
|
+
const next = await nextWithAbort(iterator, deadline.signal);
|
|
79
|
+
if (next.done)
|
|
80
|
+
break;
|
|
81
|
+
const event = next.value;
|
|
82
|
+
deadline.activity();
|
|
83
|
+
terminalSeen ||= event.type === "done" || event.type === "error";
|
|
84
|
+
guarded.push(event);
|
|
85
|
+
}
|
|
86
|
+
if (!terminalSeen)
|
|
87
|
+
throw new Error("LLM stream ended without a terminal event");
|
|
88
|
+
}
|
|
89
|
+
catch (error) {
|
|
90
|
+
const resolved = deadline.timeoutError() ?? error;
|
|
91
|
+
const message = {
|
|
92
|
+
role: "assistant",
|
|
93
|
+
content: [],
|
|
94
|
+
api: model.api,
|
|
95
|
+
provider: model.provider,
|
|
96
|
+
model: model.id,
|
|
97
|
+
usage: {
|
|
98
|
+
input: 0,
|
|
99
|
+
output: 0,
|
|
100
|
+
cacheRead: 0,
|
|
101
|
+
cacheWrite: 0,
|
|
102
|
+
totalTokens: 0,
|
|
103
|
+
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },
|
|
104
|
+
},
|
|
105
|
+
stopReason: callerSignal?.aborted ? "aborted" : "error",
|
|
106
|
+
errorMessage: resolved instanceof Error ? resolved.message : String(resolved),
|
|
107
|
+
timestamp: Date.now(),
|
|
108
|
+
};
|
|
109
|
+
guarded.push({
|
|
110
|
+
type: "error",
|
|
111
|
+
reason: message.stopReason === "aborted" ? "aborted" : "error",
|
|
112
|
+
error: message,
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
finally {
|
|
116
|
+
deadline.stop();
|
|
117
|
+
}
|
|
118
|
+
})();
|
|
119
|
+
return guarded;
|
|
120
|
+
}
|
|
121
|
+
async function nextWithAbort(iterator, signal) {
|
|
122
|
+
if (signal.aborted)
|
|
123
|
+
throw signal.reason;
|
|
124
|
+
return new Promise((resolve, reject) => {
|
|
125
|
+
const onAbort = () => reject(signal.reason ?? new Error("LLM stream aborted"));
|
|
126
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
127
|
+
void iterator.next().then(resolve, reject).finally(() => {
|
|
128
|
+
signal.removeEventListener("abort", onAbort);
|
|
129
|
+
});
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
function isByteString(value) {
|
|
133
|
+
for (let i = 0; i < value.length; i++) {
|
|
134
|
+
if (value.charCodeAt(i) > 255)
|
|
135
|
+
return false;
|
|
136
|
+
}
|
|
137
|
+
return true;
|
|
138
|
+
}
|
|
139
|
+
function isValidHeaderName(value) {
|
|
140
|
+
return /^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$/.test(value);
|
|
141
|
+
}
|
|
142
|
+
function sanitizeHttpHeaders(headers) {
|
|
143
|
+
if (!headers)
|
|
144
|
+
return undefined;
|
|
145
|
+
const sanitized = {};
|
|
146
|
+
for (const [key, value] of Object.entries(headers)) {
|
|
147
|
+
if (!isValidHeaderName(key))
|
|
148
|
+
continue;
|
|
149
|
+
if (!isByteString(value))
|
|
150
|
+
continue;
|
|
151
|
+
sanitized[key] = value;
|
|
152
|
+
}
|
|
153
|
+
return Object.keys(sanitized).length > 0 ? sanitized : undefined;
|
|
154
|
+
}
|
|
155
|
+
function mergeUserAgent(headers) {
|
|
156
|
+
return { "User-Agent": INKOS_USER_AGENT, ...(sanitizeHttpHeaders(headers) ?? {}) };
|
|
157
|
+
}
|
|
158
|
+
export function createStreamMonitor(onProgress, intervalMs = 30000) {
|
|
159
|
+
let totalChars = 0;
|
|
160
|
+
let chineseChars = 0;
|
|
161
|
+
const startTime = Date.now();
|
|
162
|
+
let timer;
|
|
163
|
+
if (onProgress) {
|
|
164
|
+
timer = setInterval(() => {
|
|
165
|
+
onProgress({
|
|
166
|
+
elapsedMs: Date.now() - startTime,
|
|
167
|
+
totalChars,
|
|
168
|
+
chineseChars,
|
|
169
|
+
status: "streaming",
|
|
170
|
+
});
|
|
171
|
+
}, intervalMs);
|
|
172
|
+
}
|
|
173
|
+
return {
|
|
174
|
+
onChunk(text) {
|
|
175
|
+
totalChars += text.length;
|
|
176
|
+
chineseChars += (text.match(/[\u4e00-\u9fff]/g) || []).length;
|
|
177
|
+
},
|
|
178
|
+
stop() {
|
|
179
|
+
if (timer !== undefined) {
|
|
180
|
+
clearInterval(timer);
|
|
181
|
+
timer = undefined;
|
|
182
|
+
}
|
|
183
|
+
onProgress?.({
|
|
184
|
+
elapsedMs: Date.now() - startTime,
|
|
185
|
+
totalChars,
|
|
186
|
+
chineseChars,
|
|
187
|
+
status: "done",
|
|
188
|
+
});
|
|
189
|
+
},
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
// === Factory ===
|
|
193
|
+
export function createLLMClient(config) {
|
|
194
|
+
// C1 (v2.0.0):config.maxTokens / maxTokensCap 已删除;defaults.maxTokens 完全从 modelCard 推导。
|
|
195
|
+
const _earlyCard = lookupModel(config.service ?? "custom", config.model);
|
|
196
|
+
const defaults = {
|
|
197
|
+
temperature: config.temperature ?? 0.7,
|
|
198
|
+
maxTokens: _earlyCard?.maxOutput ?? UNKNOWN_MODEL_FALLBACK_MAX_TOKENS,
|
|
199
|
+
thinkingBudget: config.thinkingBudget ?? 0,
|
|
200
|
+
extra: config.extra ?? {},
|
|
201
|
+
};
|
|
202
|
+
const apiFormat = config.apiFormat ?? "chat";
|
|
203
|
+
const stream = config.stream ?? true;
|
|
204
|
+
// --- Build pi-ai Model object ---
|
|
205
|
+
const serviceName = config.service ?? "custom";
|
|
206
|
+
const preset = resolveServicePreset(serviceName);
|
|
207
|
+
const inkosProvider = getEndpoint(serviceName);
|
|
208
|
+
const modelCard = lookupModel(serviceName, config.model);
|
|
209
|
+
const piApi = resolvePiApi(serviceName, config.apiFormat, (inkosProvider?.api ?? preset?.api));
|
|
210
|
+
const baseUrl = config.baseUrl || inkosProvider?.baseUrl || preset?.baseUrl || "";
|
|
211
|
+
const extraHeaders = sanitizeHttpHeaders(config.headers ?? parseEnvHeaders());
|
|
212
|
+
const compat = piApi === "openai-completions"
|
|
213
|
+
? resolveProviderCompat(inkosProvider, baseUrl)
|
|
214
|
+
: undefined;
|
|
215
|
+
const provider = config.provider === "anthropic" ? "anthropic" : "openai";
|
|
216
|
+
// pi-ai provider 字段:大多数情况 pi-ai 会按 baseUrl 自动嗅探(openrouter.ai / api.z.ai /
|
|
217
|
+
// api.x.ai / deepseek.com / anthropic.com 等)。这里只列 pi-ai 嗅探不到、需要显式指定的少数情况。
|
|
218
|
+
let piProvider;
|
|
219
|
+
if (inkosProvider?.id === "google")
|
|
220
|
+
piProvider = "google";
|
|
221
|
+
else if (inkosProvider?.id === "zhipu")
|
|
222
|
+
piProvider = "zai";
|
|
223
|
+
else if (inkosProvider?.id === "openrouter")
|
|
224
|
+
piProvider = "openrouter";
|
|
225
|
+
else if (inkosProvider?.id === "githubCopilot")
|
|
226
|
+
piProvider = "githubCopilot";
|
|
227
|
+
else if (inkosProvider?.id === "ollama")
|
|
228
|
+
piProvider = "ollama";
|
|
229
|
+
else if (inkosProvider?.api === "anthropic-messages")
|
|
230
|
+
piProvider = "anthropic";
|
|
231
|
+
else
|
|
232
|
+
piProvider = provider;
|
|
233
|
+
const piModel = {
|
|
234
|
+
id: modelCard?.deploymentName ?? config.model,
|
|
235
|
+
name: config.model,
|
|
236
|
+
api: piApi,
|
|
237
|
+
provider: piProvider,
|
|
238
|
+
baseUrl,
|
|
239
|
+
// 注意:piModel.reasoning 是"激活 reasoning 模式"标志(会让 pi-ai 把 system 改成 developer role 等),
|
|
240
|
+
// 不是"模型能力"标签。只有用户显式配了 thinkingBudget > 0 才启用 reasoning mode。
|
|
241
|
+
// 千万不要从 lobe abilities.reasoning 自动推导,否则 Moonshot 这类不支持 developer role 的服务
|
|
242
|
+
// 会把 content 吃掉,只返回 reasoning_content(见 R4 bug 1 诊断)。
|
|
243
|
+
reasoning: (config.thinkingBudget ?? 0) > 0,
|
|
244
|
+
input: ["text"],
|
|
245
|
+
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
|
246
|
+
contextWindow: modelCard?.contextWindowTokens ?? 128_000,
|
|
247
|
+
maxTokens: modelCard?.maxOutput ?? UNKNOWN_MODEL_FALLBACK_MAX_TOKENS,
|
|
248
|
+
...(extraHeaders ? { headers: extraHeaders } : {}),
|
|
249
|
+
...(compat ? { compat } : {}),
|
|
250
|
+
};
|
|
251
|
+
return {
|
|
252
|
+
provider,
|
|
253
|
+
service: serviceName,
|
|
254
|
+
configSource: config.configSource,
|
|
255
|
+
apiFormat,
|
|
256
|
+
stream,
|
|
257
|
+
proxyUrl: config.proxyUrl,
|
|
258
|
+
_piModel: piModel,
|
|
259
|
+
_apiKey: config.apiKey,
|
|
260
|
+
defaults,
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
function resolvePiApi(serviceName, apiFormat, presetApi) {
|
|
264
|
+
if (serviceName === "custom") {
|
|
265
|
+
return apiFormat === "responses" ? "openai-responses" : "openai-completions";
|
|
266
|
+
}
|
|
267
|
+
return (presetApi ?? "openai-completions");
|
|
268
|
+
}
|
|
269
|
+
function resolveProviderCompat(provider, baseUrl) {
|
|
270
|
+
const compat = {
|
|
271
|
+
...(provider?.compat ?? {}),
|
|
272
|
+
...(baseUrl.includes("generativelanguage.googleapis.com") ? { supportsStore: false } : {}),
|
|
273
|
+
};
|
|
274
|
+
return Object.keys(compat).length > 0 ? compat : undefined;
|
|
275
|
+
}
|
|
276
|
+
function parseEnvHeaders() {
|
|
277
|
+
const raw = process.env.INKOS_LLM_HEADERS;
|
|
278
|
+
if (!raw)
|
|
279
|
+
return undefined;
|
|
280
|
+
try {
|
|
281
|
+
const parsed = JSON.parse(raw);
|
|
282
|
+
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
283
|
+
return parsed;
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
catch {
|
|
287
|
+
// not JSON — treat as single "Key: Value" pair
|
|
288
|
+
const idx = raw.indexOf(":");
|
|
289
|
+
if (idx > 0) {
|
|
290
|
+
return { [raw.slice(0, idx).trim()]: raw.slice(idx + 1).trim() };
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
return undefined;
|
|
294
|
+
}
|
|
295
|
+
// === Partial Response(流式生成中途被掐断)===
|
|
296
|
+
// 语义:内容不完整、不可信。由 withTransientLLMRetry 整体重新生成;
|
|
297
|
+
// 重试耗尽后如实抛错。绝不把半截内容当成功返回(那会产出写到一半就
|
|
298
|
+
// 结束的章节/设定文件)。partialContent 仅用于错误诊断。
|
|
299
|
+
export class PartialResponseError extends Error {
|
|
300
|
+
partialContent;
|
|
301
|
+
reason;
|
|
302
|
+
constructor(partialContent, cause, reason = "interrupted") {
|
|
303
|
+
super(`Stream interrupted after ${partialContent.length} chars: ${String(cause)}`);
|
|
304
|
+
this.name = "PartialResponseError";
|
|
305
|
+
this.partialContent = partialContent;
|
|
306
|
+
this.reason = reason;
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
export class ContextWindowExceededError extends Error {
|
|
310
|
+
estimatedInputTokens;
|
|
311
|
+
reservedOutputTokens;
|
|
312
|
+
contextWindow;
|
|
313
|
+
constructor(params) {
|
|
314
|
+
super(`InkOS context window guard: estimated input ${params.estimatedInputTokens} tokens + ` +
|
|
315
|
+
`reserved output ${params.reservedOutputTokens} tokens exceeds context window ${params.contextWindow} ` +
|
|
316
|
+
`for model "${params.model}". Please compress the active book/session context before retrying; ` +
|
|
317
|
+
`InkOS will not truncate semantic text automatically.`);
|
|
318
|
+
this.name = "ContextWindowExceededError";
|
|
319
|
+
this.estimatedInputTokens = params.estimatedInputTokens;
|
|
320
|
+
this.reservedOutputTokens = params.reservedOutputTokens;
|
|
321
|
+
this.contextWindow = params.contextWindow;
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
/** Keys managed by the provider layer — prevent extra from overriding them. */
|
|
325
|
+
const RESERVED_KEYS = new Set(["max_tokens", "temperature", "model", "messages", "stream"]);
|
|
326
|
+
function stripReservedKeys(extra) {
|
|
327
|
+
const result = {};
|
|
328
|
+
for (const [key, value] of Object.entries(extra)) {
|
|
329
|
+
if (!RESERVED_KEYS.has(key))
|
|
330
|
+
result[key] = value;
|
|
331
|
+
}
|
|
332
|
+
return result;
|
|
333
|
+
}
|
|
334
|
+
// === Fixed-Temperature Model Clamp ===
|
|
335
|
+
//
|
|
336
|
+
// 部分 thinking 模型(如 Moonshot kimi-k2.5/k2.6、kimi-k2-thinking)的 API
|
|
337
|
+
// 硬要求 temperature === 1,其他值会被直接 400 拒绝(Moonshot 返回
|
|
338
|
+
// `invalid temperature: only 1 is allowed for this model`)。
|
|
339
|
+
//
|
|
340
|
+
// inkos 让 writer/validator/architect 各自带 per-call 温度(0.1~1.5),
|
|
341
|
+
// 所以 provider 层统一夹制:如果 bank 里模型卡标了 temperature 字段,
|
|
342
|
+
// 就把 per-call 温度 clamp 到那个值,并对每个模型名打一次 warning。
|
|
343
|
+
//
|
|
344
|
+
// 这个字段只表达"服务端硬约束",普通模型不要标,避免误伤 per-call 调参。
|
|
345
|
+
const warnedFixedTemperatureModels = new Set();
|
|
346
|
+
function clampTemperatureForModel(service, model, requested) {
|
|
347
|
+
const card = service ? lookupModel(service, model) : undefined;
|
|
348
|
+
if (card?.temperature === undefined)
|
|
349
|
+
return requested;
|
|
350
|
+
const locked = card.temperature;
|
|
351
|
+
if (requested === locked)
|
|
352
|
+
return locked;
|
|
353
|
+
if (!warnedFixedTemperatureModels.has(model)) {
|
|
354
|
+
warnedFixedTemperatureModels.add(model);
|
|
355
|
+
console.warn(`[inkos] 模型 "${model}" API 要求 temperature=${locked},已 clamp(原值 ${requested})`);
|
|
356
|
+
}
|
|
357
|
+
return locked;
|
|
358
|
+
}
|
|
359
|
+
// 仅测试用:清空 warning 去重集合。
|
|
360
|
+
export function __resetFixedTemperatureWarnings() {
|
|
361
|
+
warnedFixedTemperatureModels.clear();
|
|
362
|
+
}
|
|
363
|
+
export function estimateTextTokens(text) {
|
|
364
|
+
if (!text)
|
|
365
|
+
return 0;
|
|
366
|
+
const cjk = text.match(/[\u3400-\u9fff]/g)?.length ?? 0;
|
|
367
|
+
const nonCjk = text.length - cjk;
|
|
368
|
+
return Math.ceil(cjk + nonCjk / 4);
|
|
369
|
+
}
|
|
370
|
+
function estimateJsonTokens(value) {
|
|
371
|
+
try {
|
|
372
|
+
return estimateTextTokens(JSON.stringify(value) ?? "");
|
|
373
|
+
}
|
|
374
|
+
catch {
|
|
375
|
+
return estimateTextTokens(String(value));
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
function estimateLLMMessagesTokens(messages) {
|
|
379
|
+
return messages.reduce((total, message) => total + estimateTextTokens(message.content), 0);
|
|
380
|
+
}
|
|
381
|
+
function estimatePiContentTokens(content) {
|
|
382
|
+
if (typeof content === "string")
|
|
383
|
+
return estimateTextTokens(content);
|
|
384
|
+
let total = 0;
|
|
385
|
+
for (const block of content) {
|
|
386
|
+
if (block.type === "text") {
|
|
387
|
+
total += estimateTextTokens(typeof block.text === "string" ? block.text : "");
|
|
388
|
+
continue;
|
|
389
|
+
}
|
|
390
|
+
if (block.type === "thinking") {
|
|
391
|
+
total += estimateTextTokens(typeof block.thinking === "string" ? block.thinking : "");
|
|
392
|
+
continue;
|
|
393
|
+
}
|
|
394
|
+
if (block.type === "toolCall") {
|
|
395
|
+
total += estimateTextTokens(typeof block.name === "string" ? block.name : "");
|
|
396
|
+
total += estimateTextTokens(typeof block.id === "string" ? block.id : "");
|
|
397
|
+
total += estimateJsonTokens(block.arguments);
|
|
398
|
+
continue;
|
|
399
|
+
}
|
|
400
|
+
if (block.type === "image") {
|
|
401
|
+
total += estimateTextTokens(typeof block.mimeType === "string" ? block.mimeType : "");
|
|
402
|
+
total += estimateTextTokens(typeof block.data === "string" ? block.data : "");
|
|
403
|
+
continue;
|
|
404
|
+
}
|
|
405
|
+
total += estimateJsonTokens(block);
|
|
406
|
+
}
|
|
407
|
+
return total;
|
|
408
|
+
}
|
|
409
|
+
export function estimatePiContextTokens(context) {
|
|
410
|
+
let total = estimateTextTokens(context.systemPrompt ?? "");
|
|
411
|
+
for (const message of context.messages) {
|
|
412
|
+
total += estimateTextTokens(message.role);
|
|
413
|
+
if (message.role === "assistant") {
|
|
414
|
+
total += estimatePiContentTokens(message.content);
|
|
415
|
+
total += estimateTextTokens(message.model ?? "");
|
|
416
|
+
total += estimateTextTokens(message.provider ?? "");
|
|
417
|
+
total += estimateTextTokens(message.api ?? "");
|
|
418
|
+
continue;
|
|
419
|
+
}
|
|
420
|
+
if (message.role === "toolResult") {
|
|
421
|
+
total += estimateTextTokens(message.toolCallId);
|
|
422
|
+
total += estimateTextTokens(message.toolName);
|
|
423
|
+
total += estimatePiContentTokens(message.content);
|
|
424
|
+
continue;
|
|
425
|
+
}
|
|
426
|
+
total += estimatePiContentTokens(message.content);
|
|
427
|
+
}
|
|
428
|
+
if (context.tools && context.tools.length > 0) {
|
|
429
|
+
total += estimateJsonTokens(context.tools);
|
|
430
|
+
}
|
|
431
|
+
return total;
|
|
432
|
+
}
|
|
433
|
+
export function assertWithinContextWindow(params) {
|
|
434
|
+
const contextWindow = params.piModel.contextWindow;
|
|
435
|
+
if (!Number.isFinite(contextWindow) || contextWindow <= 0)
|
|
436
|
+
return;
|
|
437
|
+
if (params.estimatedInputTokens + params.reservedOutputTokens <= contextWindow)
|
|
438
|
+
return;
|
|
439
|
+
throw new ContextWindowExceededError({
|
|
440
|
+
estimatedInputTokens: params.estimatedInputTokens,
|
|
441
|
+
reservedOutputTokens: params.reservedOutputTokens,
|
|
442
|
+
contextWindow,
|
|
443
|
+
model: params.model,
|
|
444
|
+
});
|
|
445
|
+
}
|
|
446
|
+
// === Error Wrapping ===
|
|
447
|
+
function wrapLLMError(error, context) {
|
|
448
|
+
const msg = String(error);
|
|
449
|
+
const ctxLine = context
|
|
450
|
+
? `\n (baseUrl: ${context.baseUrl}, model: ${context.model})`
|
|
451
|
+
: "";
|
|
452
|
+
if (msg.includes("400")) {
|
|
453
|
+
// 抽上游 error body 的 message / reason / code(和下方 5xx 一致),让真实错因浮到用户面前
|
|
454
|
+
let detail = "";
|
|
455
|
+
if (error && typeof error === "object") {
|
|
456
|
+
const err = error;
|
|
457
|
+
const bodyLike = err.error ?? err.body;
|
|
458
|
+
if (bodyLike && typeof bodyLike === "object") {
|
|
459
|
+
const b = bodyLike;
|
|
460
|
+
if (b.message)
|
|
461
|
+
detail = b.type ? `${b.type}: ${b.message}` : b.message;
|
|
462
|
+
else if (b.reason)
|
|
463
|
+
detail = b.reason;
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
return new Error(`API 返回 400(请求参数错误)。${detail ? `上游详情:${detail}。\n` : ""}` +
|
|
467
|
+
`常见原因:\n` +
|
|
468
|
+
` 1. temperature / max_tokens 超出模型约束(如 Moonshot kimi-k2.X 强制 temperature=1)\n` +
|
|
469
|
+
` 2. 模型名称不正确或未上架\n` +
|
|
470
|
+
` 3. 消息格式不兼容(部分服务不支持 system role 或 developer role)${ctxLine}`);
|
|
471
|
+
}
|
|
472
|
+
if (msg.includes("403")) {
|
|
473
|
+
return new Error(`API 返回 403 (请求被拒绝)。可能原因:\n` +
|
|
474
|
+
` 1. API Key 无效或过期\n` +
|
|
475
|
+
` 2. API 提供方的内容审查拦截了请求(公益/免费 API 常见)\n` +
|
|
476
|
+
` 3. 账户余额不足\n` +
|
|
477
|
+
` 建议:用 inkos doctor 测试 API 连通性,或换一个不限制内容的 API 提供方${ctxLine}`);
|
|
478
|
+
}
|
|
479
|
+
if (msg.includes("401")) {
|
|
480
|
+
return new Error(`API 返回 401 (未授权)。请检查 .env 中的 INKOS_LLM_API_KEY 是否正确。${ctxLine}`);
|
|
481
|
+
}
|
|
482
|
+
if (msg.includes("429")) {
|
|
483
|
+
return new Error(`API 返回 429 (请求过多)。请稍后重试,或检查 API 配额。${ctxLine}`);
|
|
484
|
+
}
|
|
485
|
+
if (msg.includes("Connection error")
|
|
486
|
+
|| msg.includes("ECONNREFUSED")
|
|
487
|
+
|| msg.includes("ENOTFOUND")
|
|
488
|
+
|| msg.includes("fetch failed")
|
|
489
|
+
|| msg.includes("terminated")
|
|
490
|
+
|| msg.includes("UND_ERR_SOCKET")
|
|
491
|
+
|| msg.includes("ECONNRESET")
|
|
492
|
+
|| msg.includes("ETIMEDOUT")
|
|
493
|
+
|| msg.includes("EPIPE")) {
|
|
494
|
+
return new Error(`无法连接到 API 服务。可能原因:\n` +
|
|
495
|
+
` 1. baseUrl 地址不正确(当前:${context?.baseUrl ?? "未知"})\n` +
|
|
496
|
+
` 2. 网络不通或被防火墙拦截\n` +
|
|
497
|
+
` 3. API 服务暂时不可用\n` +
|
|
498
|
+
` 建议:检查 INKOS_LLM_BASE_URL 是否包含完整路径(如 /v1)`);
|
|
499
|
+
}
|
|
500
|
+
// R4 Bug 2: 5xx "status code (no body)" — 尝试从 OpenAI SDK APIError 里抽 body 给用户看具体原因
|
|
501
|
+
// (如 PPIO 的 {"code":500,"reason":"MODEL_NOT_AVAILABLE","message":"model not available"})
|
|
502
|
+
if (msg.includes("status code") && msg.includes("no body")) {
|
|
503
|
+
let detail = "";
|
|
504
|
+
if (error && typeof error === "object") {
|
|
505
|
+
const err = error;
|
|
506
|
+
const bodyLike = err.error ?? err.body;
|
|
507
|
+
if (bodyLike && typeof bodyLike === "object") {
|
|
508
|
+
const b = bodyLike;
|
|
509
|
+
if (b.reason)
|
|
510
|
+
detail = `${b.reason}${b.message ? `: ${b.message}` : ""}`;
|
|
511
|
+
else if (b.message)
|
|
512
|
+
detail = b.message;
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
return new Error(`API 返回 5xx(上游服务异常)。${detail ? `上游详情:${detail}。` : ""}\n` +
|
|
516
|
+
`可能原因:\n` +
|
|
517
|
+
` 1. 模型在 /models 列表但 inference 未上架(如 PPIO 返回 MODEL_NOT_AVAILABLE)\n` +
|
|
518
|
+
` 2. 服务端临时故障,稍后重试\n` +
|
|
519
|
+
` 3. 当前 apikey 无权限调用该模型${ctxLine}`);
|
|
520
|
+
}
|
|
521
|
+
return error instanceof Error ? error : new Error(msg);
|
|
522
|
+
}
|
|
523
|
+
function collectErrorText(error, depth = 0) {
|
|
524
|
+
if (depth > 4 || error === null || error === undefined)
|
|
525
|
+
return "";
|
|
526
|
+
const parts = [String(error)];
|
|
527
|
+
if (error instanceof Error) {
|
|
528
|
+
parts.push(error.name, error.message);
|
|
529
|
+
const cause = error.cause;
|
|
530
|
+
if (cause)
|
|
531
|
+
parts.push(collectErrorText(cause, depth + 1));
|
|
532
|
+
}
|
|
533
|
+
else if (typeof error === "object") {
|
|
534
|
+
const err = error;
|
|
535
|
+
if (err.name)
|
|
536
|
+
parts.push(String(err.name));
|
|
537
|
+
if (err.message)
|
|
538
|
+
parts.push(String(err.message));
|
|
539
|
+
if (err.code)
|
|
540
|
+
parts.push(String(err.code));
|
|
541
|
+
if (err.cause)
|
|
542
|
+
parts.push(collectErrorText(err.cause, depth + 1));
|
|
543
|
+
}
|
|
544
|
+
return parts.join("\n");
|
|
545
|
+
}
|
|
546
|
+
function isTransientLLMTransportError(error) {
|
|
547
|
+
const text = collectErrorText(error);
|
|
548
|
+
return [
|
|
549
|
+
"terminated",
|
|
550
|
+
"UND_ERR_SOCKET",
|
|
551
|
+
"ECONNRESET",
|
|
552
|
+
"ETIMEDOUT",
|
|
553
|
+
"EPIPE",
|
|
554
|
+
"socket hang up",
|
|
555
|
+
"other side closed",
|
|
556
|
+
"network socket disconnected",
|
|
557
|
+
].some((needle) => text.includes(needle));
|
|
558
|
+
}
|
|
559
|
+
/**
|
|
560
|
+
* Transient *HTTP-level* upstream failures worth retrying: 429 (rate limit),
|
|
561
|
+
* 502/503/504 (gateway / temporarily unavailable / overloaded). These are the
|
|
562
|
+
* aggregator blips that previously aborted whole architect/writer/short runs
|
|
563
|
+
* because only transport-level errors were retried.
|
|
564
|
+
*
|
|
565
|
+
* Deliberately does NOT match a bare 500 / "MODEL_NOT_AVAILABLE": on providers
|
|
566
|
+
* like PPIO a 500 means the model isn't on inference at all — retrying is futile
|
|
567
|
+
* and just delays the real error.
|
|
568
|
+
*/
|
|
569
|
+
export function isTransientLLMHttpError(error) {
|
|
570
|
+
const text = collectErrorText(error).toLowerCase();
|
|
571
|
+
if (text.includes("model_not_available") || text.includes("model not available")) {
|
|
572
|
+
return false;
|
|
573
|
+
}
|
|
574
|
+
const statusHit = /\b(429|502|503|504)\b/.test(text);
|
|
575
|
+
const phraseHit = [
|
|
576
|
+
"temporarily unavailable",
|
|
577
|
+
"service unavailable",
|
|
578
|
+
"bad gateway",
|
|
579
|
+
"gateway timeout",
|
|
580
|
+
"too many requests",
|
|
581
|
+
"rate limit",
|
|
582
|
+
"overloaded",
|
|
583
|
+
"please retry",
|
|
584
|
+
"try again later",
|
|
585
|
+
].some((needle) => text.includes(needle));
|
|
586
|
+
return statusHit || phraseHit;
|
|
587
|
+
}
|
|
588
|
+
function isIncompleteLLMResponseError(error) {
|
|
589
|
+
const text = collectErrorText(error).toLowerCase();
|
|
590
|
+
return text.includes("llm returned reasoning without a final answer")
|
|
591
|
+
|| text.includes("llm returned empty response");
|
|
592
|
+
}
|
|
593
|
+
function isRetryableLLMError(error) {
|
|
594
|
+
// PartialResponseError = 流在生成中途被掐断(网关切长连接等)。重试会完整
|
|
595
|
+
// 重新生成一次,比把半截内容当成功交付(截断的章节/设定文件)要正确。
|
|
596
|
+
return error instanceof PartialResponseError
|
|
597
|
+
|| isIncompleteLLMResponseError(error)
|
|
598
|
+
|| isTransientLLMTransportError(error)
|
|
599
|
+
|| isTransientLLMHttpError(error);
|
|
600
|
+
}
|
|
601
|
+
async function withTransientLLMRetry(run, options) {
|
|
602
|
+
const enabled = options?.enabled ?? true;
|
|
603
|
+
let lastError;
|
|
604
|
+
for (let attempt = 0; attempt <= TRANSIENT_LLM_RETRIES; attempt++) {
|
|
605
|
+
options?.signal?.throwIfAborted();
|
|
606
|
+
try {
|
|
607
|
+
return await run(attempt + 1);
|
|
608
|
+
}
|
|
609
|
+
catch (error) {
|
|
610
|
+
lastError = error;
|
|
611
|
+
if (!enabled
|
|
612
|
+
|| attempt >= TRANSIENT_LLM_RETRIES
|
|
613
|
+
|| !isRetryableLLMError(error)) {
|
|
614
|
+
throw error;
|
|
615
|
+
}
|
|
616
|
+
// Back off before retrying — immediate re-fire on a 429/503 just makes it
|
|
617
|
+
// worse. Linear is enough for a 2-retry budget (~0.8s, ~1.6s).
|
|
618
|
+
await abortableDelay(800 * (attempt + 1), options?.signal);
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
throw lastError;
|
|
622
|
+
}
|
|
623
|
+
async function abortableDelay(delayMs, signal) {
|
|
624
|
+
if (!signal) {
|
|
625
|
+
await new Promise((resolveDelay) => setTimeout(resolveDelay, delayMs));
|
|
626
|
+
return;
|
|
627
|
+
}
|
|
628
|
+
signal.throwIfAborted();
|
|
629
|
+
await new Promise((resolveDelay, rejectDelay) => {
|
|
630
|
+
const timer = setTimeout(() => {
|
|
631
|
+
signal.removeEventListener("abort", onAbort);
|
|
632
|
+
resolveDelay();
|
|
633
|
+
}, delayMs);
|
|
634
|
+
const onAbort = () => {
|
|
635
|
+
clearTimeout(timer);
|
|
636
|
+
rejectDelay(signal.reason ?? new Error("LLM request aborted"));
|
|
637
|
+
};
|
|
638
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
639
|
+
});
|
|
640
|
+
}
|
|
641
|
+
function shouldUseNativeCustomTransport(client) {
|
|
642
|
+
if (client.service === "minimax" && client.provider === "openai") {
|
|
643
|
+
return true;
|
|
644
|
+
}
|
|
645
|
+
if (client.service === "kkaiapi" && client.provider === "openai") {
|
|
646
|
+
return true;
|
|
647
|
+
}
|
|
648
|
+
if (client.service === "custom") {
|
|
649
|
+
if (client.configSource === "studio"
|
|
650
|
+
&& (client.provider === "openai" || client.provider === "anthropic")) {
|
|
651
|
+
return true;
|
|
652
|
+
}
|
|
653
|
+
return client.provider === "openai" && shouldUseNativeLocalOpenAICompatibleTransport(client);
|
|
654
|
+
}
|
|
655
|
+
return (client.service === "ollama" || client.service === "lmstudio")
|
|
656
|
+
&& client.provider === "openai"
|
|
657
|
+
&& shouldUseNativeLocalOpenAICompatibleTransport(client);
|
|
658
|
+
}
|
|
659
|
+
function shouldUseNativeLocalOpenAICompatibleTransport(client) {
|
|
660
|
+
return !client._apiKey
|
|
661
|
+
&& isApiKeyOptionalForEndpoint({
|
|
662
|
+
provider: client.provider,
|
|
663
|
+
baseUrl: client._piModel?.baseUrl,
|
|
664
|
+
});
|
|
665
|
+
}
|
|
666
|
+
function buildCustomHeaders(client, traceHeaders) {
|
|
667
|
+
const apiKey = sanitizeHeaderApiKey(client._apiKey);
|
|
668
|
+
return sanitizeHttpHeaders({
|
|
669
|
+
"Content-Type": "application/json",
|
|
670
|
+
...(apiKey ? { Authorization: `Bearer ${apiKey}` } : {}),
|
|
671
|
+
...(client._piModel?.headers ?? {}),
|
|
672
|
+
...traceHeaders,
|
|
673
|
+
}) ?? { "Content-Type": "application/json" };
|
|
674
|
+
}
|
|
675
|
+
function defaultOpenAIChatExtra(client, model) {
|
|
676
|
+
if (client.service !== "minimax")
|
|
677
|
+
return {};
|
|
678
|
+
// MiniMax OpenAI 兼容端点(issue #329):
|
|
679
|
+
// - reasoning_split: true 让 thinking 拆分到 reasoning_content / reasoning_details,
|
|
680
|
+
// 不再以 <think>...</think> 内联在 content 里。M2.x 系列的 thinking 无法关闭,
|
|
681
|
+
// 不拆分的话思考内容会混进章节/对话正文。
|
|
682
|
+
// - M3 系列额外默认关闭 thinking(M2.x 不支持 thinking 参数,不能发送)。
|
|
683
|
+
return {
|
|
684
|
+
reasoning_split: true,
|
|
685
|
+
...(/^minimax-m3(?:$|[-_.])/i.test(model) ? { thinking: { type: "disabled" } } : {}),
|
|
686
|
+
};
|
|
687
|
+
}
|
|
688
|
+
function sanitizeHeaderApiKey(apiKey) {
|
|
689
|
+
const trimmed = apiKey?.trim() ?? "";
|
|
690
|
+
if (!trimmed)
|
|
691
|
+
return "";
|
|
692
|
+
if (!/^[\x20-\x7e]+$/.test(trimmed)) {
|
|
693
|
+
throw new Error("API Key contains non-ASCII characters; please remove any pasted Chinese notes or whitespace.");
|
|
694
|
+
}
|
|
695
|
+
return trimmed;
|
|
696
|
+
}
|
|
697
|
+
function joinSystemPrompt(messages) {
|
|
698
|
+
const systemParts = messages
|
|
699
|
+
.filter((message) => message.role === "system" && message.content.trim().length > 0)
|
|
700
|
+
.map((message) => message.content.trim());
|
|
701
|
+
return systemParts.length > 0 ? systemParts.join("\n\n") : undefined;
|
|
702
|
+
}
|
|
703
|
+
function buildChatMessages(messages) {
|
|
704
|
+
return messages
|
|
705
|
+
.filter((message) => message.role !== "system")
|
|
706
|
+
.map((message) => ({
|
|
707
|
+
role: message.role,
|
|
708
|
+
content: message.content,
|
|
709
|
+
}));
|
|
710
|
+
}
|
|
711
|
+
function buildAnthropicMessages(messages) {
|
|
712
|
+
return messages
|
|
713
|
+
.filter((message) => message.role === "user" || message.role === "assistant")
|
|
714
|
+
.map((message) => ({
|
|
715
|
+
role: message.role,
|
|
716
|
+
content: message.content,
|
|
717
|
+
}));
|
|
718
|
+
}
|
|
719
|
+
function buildResponsesInput(messages) {
|
|
720
|
+
return messages
|
|
721
|
+
.filter((message) => message.role !== "system")
|
|
722
|
+
.map((message) => ({
|
|
723
|
+
role: message.role,
|
|
724
|
+
content: [{ type: "input_text", text: message.content }],
|
|
725
|
+
}));
|
|
726
|
+
}
|
|
727
|
+
function hasSystemMessages(messages) {
|
|
728
|
+
return messages.some((message) => message.role === "system" && message.content.trim().length > 0);
|
|
729
|
+
}
|
|
730
|
+
function foldSystemMessagesIntoFirstUser(messages) {
|
|
731
|
+
const system = joinSystemPrompt(messages);
|
|
732
|
+
const nonSystemMessages = messages.filter((message) => message.role !== "system");
|
|
733
|
+
if (!system)
|
|
734
|
+
return [...nonSystemMessages];
|
|
735
|
+
const firstUserIndex = nonSystemMessages.findIndex((message) => message.role === "user");
|
|
736
|
+
const prefix = `System instructions:\n${system}\n\nUser request:\n`;
|
|
737
|
+
if (firstUserIndex < 0) {
|
|
738
|
+
return [{ role: "user", content: `System instructions:\n${system}` }, ...nonSystemMessages];
|
|
739
|
+
}
|
|
740
|
+
return nonSystemMessages.map((message, index) => index === firstUserIndex
|
|
741
|
+
? { ...message, content: `${prefix}${message.content}` }
|
|
742
|
+
: message);
|
|
743
|
+
}
|
|
744
|
+
function isSystemRoleUnsupportedErrorText(text) {
|
|
745
|
+
const normalized = text.toLowerCase();
|
|
746
|
+
const mentionsSystemRole = normalized.includes("system") && normalized.includes("role");
|
|
747
|
+
if (!mentionsSystemRole)
|
|
748
|
+
return false;
|
|
749
|
+
return normalized.includes("unsupported")
|
|
750
|
+
|| normalized.includes("not support")
|
|
751
|
+
|| normalized.includes("does not support")
|
|
752
|
+
|| normalized.includes("invalid")
|
|
753
|
+
|| normalized.includes("不支持")
|
|
754
|
+
|| normalized.includes("不允许");
|
|
755
|
+
}
|
|
756
|
+
async function readErrorResponse(res) {
|
|
757
|
+
const text = await res.text().catch(() => "");
|
|
758
|
+
try {
|
|
759
|
+
const json = JSON.parse(text);
|
|
760
|
+
if (typeof json.error === "string" && json.error)
|
|
761
|
+
return `${res.status} ${json.error}`;
|
|
762
|
+
if (json.error && typeof json.error === "object" && typeof json.error.message === "string") {
|
|
763
|
+
return `${res.status} ${json.error.message}`;
|
|
764
|
+
}
|
|
765
|
+
if (typeof json.detail === "string" && json.detail)
|
|
766
|
+
return `${res.status} ${json.detail}`;
|
|
767
|
+
}
|
|
768
|
+
catch {
|
|
769
|
+
// fall through
|
|
770
|
+
}
|
|
771
|
+
return `${res.status} ${text || res.statusText}`.trim();
|
|
772
|
+
}
|
|
773
|
+
function parseSseEvents(buffer) {
|
|
774
|
+
const chunks = buffer.split(/\n\n/);
|
|
775
|
+
const rest = chunks.pop() ?? "";
|
|
776
|
+
const events = [];
|
|
777
|
+
for (const chunk of chunks) {
|
|
778
|
+
const lines = chunk.split(/\r?\n/);
|
|
779
|
+
let eventName;
|
|
780
|
+
const dataLines = [];
|
|
781
|
+
for (const line of lines) {
|
|
782
|
+
if (line.startsWith("event:")) {
|
|
783
|
+
eventName = line.slice("event:".length).trim();
|
|
784
|
+
}
|
|
785
|
+
else if (line.startsWith("data:")) {
|
|
786
|
+
dataLines.push(line.slice("data:".length).trimStart());
|
|
787
|
+
}
|
|
788
|
+
}
|
|
789
|
+
if (eventName || dataLines.length > 0) {
|
|
790
|
+
events.push({
|
|
791
|
+
...(eventName ? { event: eventName } : {}),
|
|
792
|
+
...(dataLines.length > 0 ? { data: dataLines.join("\n") } : {}),
|
|
793
|
+
});
|
|
794
|
+
}
|
|
795
|
+
}
|
|
796
|
+
return { events, rest };
|
|
797
|
+
}
|
|
798
|
+
function extractOpenAITextPart(value) {
|
|
799
|
+
if (typeof value === "string")
|
|
800
|
+
return value;
|
|
801
|
+
if (Array.isArray(value)) {
|
|
802
|
+
return value
|
|
803
|
+
.map((item) => typeof item?.text === "string" ? item.text : typeof item?.content === "string" ? item.content : "")
|
|
804
|
+
.join("");
|
|
805
|
+
}
|
|
806
|
+
return "";
|
|
807
|
+
}
|
|
808
|
+
function extractChatContent(json) {
|
|
809
|
+
const message = json?.choices?.[0]?.message;
|
|
810
|
+
return extractOpenAITextPart(message?.content);
|
|
811
|
+
}
|
|
812
|
+
function extractChatReasoningContent(json) {
|
|
813
|
+
return extractOpenAITextPart(json?.choices?.[0]?.message?.reasoning_content)
|
|
814
|
+
|| extractOpenAITextPart(json?.choices?.[0]?.message?.reasoning_details);
|
|
815
|
+
}
|
|
816
|
+
function extractChatDeltaContent(json) {
|
|
817
|
+
return extractOpenAITextPart(json?.choices?.[0]?.delta?.content);
|
|
818
|
+
}
|
|
819
|
+
function extractChatDeltaReasoningContent(json) {
|
|
820
|
+
const delta = json?.choices?.[0]?.delta;
|
|
821
|
+
// MiniMax reasoning_split 模式下流式 thinking 走 delta.reasoning_details
|
|
822
|
+
//([{ text: "..." }] 数组);其它服务走 delta.reasoning_content。
|
|
823
|
+
return extractOpenAITextPart(delta?.reasoning_content)
|
|
824
|
+
|| extractOpenAITextPart(delta?.reasoning_details);
|
|
825
|
+
}
|
|
826
|
+
function extractResponsesContent(json) {
|
|
827
|
+
const output = Array.isArray(json?.output) ? json.output : [];
|
|
828
|
+
return output
|
|
829
|
+
.flatMap((item) => Array.isArray(item?.content) ? item.content : [])
|
|
830
|
+
.map((part) => {
|
|
831
|
+
if (typeof part?.text === "string")
|
|
832
|
+
return part.text;
|
|
833
|
+
if (typeof part?.content === "string")
|
|
834
|
+
return part.content;
|
|
835
|
+
if (typeof part?.output_text === "string")
|
|
836
|
+
return part.output_text;
|
|
837
|
+
return "";
|
|
838
|
+
})
|
|
839
|
+
.join("");
|
|
840
|
+
}
|
|
841
|
+
function extractAnthropicContent(json) {
|
|
842
|
+
const content = Array.isArray(json?.content) ? json.content : [];
|
|
843
|
+
return content
|
|
844
|
+
.map((part) => typeof part?.text === "string" ? part.text : "")
|
|
845
|
+
.join("");
|
|
846
|
+
}
|
|
847
|
+
async function chatCompletionViaCustomAnthropicCompatible(client, model, messages, resolved, onStreamProgress, onTextDelta, signal, traceHeaders = {}, onStreamActivity) {
|
|
848
|
+
const baseUrl = client._piModel?.baseUrl ?? "";
|
|
849
|
+
const errorCtx = { baseUrl, model, service: client.service };
|
|
850
|
+
const extra = stripReservedKeys(resolved.extra);
|
|
851
|
+
const payload = {
|
|
852
|
+
model,
|
|
853
|
+
messages: buildAnthropicMessages(messages),
|
|
854
|
+
stream: client.stream,
|
|
855
|
+
max_tokens: resolved.maxTokens,
|
|
856
|
+
temperature: resolved.temperature,
|
|
857
|
+
...extra,
|
|
858
|
+
};
|
|
859
|
+
const system = joinSystemPrompt(messages);
|
|
860
|
+
if (system)
|
|
861
|
+
payload.system = system;
|
|
862
|
+
const apiKey = sanitizeHeaderApiKey(client._apiKey);
|
|
863
|
+
const response = await fetchWithProxy(`${baseUrl.replace(/\/$/, "")}/messages`, {
|
|
864
|
+
method: "POST",
|
|
865
|
+
headers: sanitizeHttpHeaders({
|
|
866
|
+
"User-Agent": INKOS_USER_AGENT,
|
|
867
|
+
"x-api-key": apiKey,
|
|
868
|
+
"anthropic-version": "2023-06-01",
|
|
869
|
+
"Content-Type": "application/json",
|
|
870
|
+
...(apiKey ? { Authorization: `Bearer ${apiKey}` } : {}),
|
|
871
|
+
...(client._piModel?.headers ?? {}),
|
|
872
|
+
...traceHeaders,
|
|
873
|
+
}) ?? { "Content-Type": "application/json" },
|
|
874
|
+
body: JSON.stringify(payload),
|
|
875
|
+
signal,
|
|
876
|
+
}, client.proxyUrl);
|
|
877
|
+
if (!response.ok) {
|
|
878
|
+
throw wrapLLMError(new Error(await readErrorResponse(response)), errorCtx);
|
|
879
|
+
}
|
|
880
|
+
if (!client.stream) {
|
|
881
|
+
const json = await response.json();
|
|
882
|
+
const content = extractAnthropicContent(json);
|
|
883
|
+
if (!content) {
|
|
884
|
+
throw wrapLLMError(new Error("LLM returned empty response"), errorCtx);
|
|
885
|
+
}
|
|
886
|
+
return {
|
|
887
|
+
content,
|
|
888
|
+
usage: {
|
|
889
|
+
promptTokens: json?.usage?.input_tokens ?? 0,
|
|
890
|
+
completionTokens: json?.usage?.output_tokens ?? 0,
|
|
891
|
+
totalTokens: (json?.usage?.input_tokens ?? 0) + (json?.usage?.output_tokens ?? 0),
|
|
892
|
+
},
|
|
893
|
+
};
|
|
894
|
+
}
|
|
895
|
+
const reader = response.body?.getReader();
|
|
896
|
+
if (!reader)
|
|
897
|
+
throw wrapLLMError(new Error("Streaming body unavailable"), errorCtx);
|
|
898
|
+
const decoder = new TextDecoder();
|
|
899
|
+
let buffer = "";
|
|
900
|
+
let content = "";
|
|
901
|
+
let usage = { promptTokens: 0, completionTokens: 0, totalTokens: 0 };
|
|
902
|
+
let sawMessageStop = false;
|
|
903
|
+
const monitor = createStreamMonitor(onStreamProgress);
|
|
904
|
+
try {
|
|
905
|
+
while (true) {
|
|
906
|
+
const { value, done } = await reader.read();
|
|
907
|
+
if (done)
|
|
908
|
+
break;
|
|
909
|
+
onStreamActivity?.();
|
|
910
|
+
buffer += decoder.decode(value, { stream: true });
|
|
911
|
+
const parsed = parseSseEvents(buffer);
|
|
912
|
+
buffer = parsed.rest;
|
|
913
|
+
for (const event of parsed.events) {
|
|
914
|
+
if (!event.data)
|
|
915
|
+
continue;
|
|
916
|
+
const json = JSON.parse(event.data);
|
|
917
|
+
if (json.type === "message_start" && json.message?.usage) {
|
|
918
|
+
usage.promptTokens = json.message.usage.input_tokens ?? usage.promptTokens;
|
|
919
|
+
}
|
|
920
|
+
if (json.type === "content_block_delta" && json.delta?.type === "text_delta" && typeof json.delta.text === "string") {
|
|
921
|
+
content += json.delta.text;
|
|
922
|
+
monitor.onChunk(json.delta.text);
|
|
923
|
+
onTextDelta?.(json.delta.text);
|
|
924
|
+
}
|
|
925
|
+
if (json.type === "message_delta" && json.usage) {
|
|
926
|
+
usage.completionTokens = json.usage.output_tokens ?? usage.completionTokens;
|
|
927
|
+
}
|
|
928
|
+
if (json.type === "message_stop") {
|
|
929
|
+
sawMessageStop = true;
|
|
930
|
+
usage.totalTokens = usage.promptTokens + usage.completionTokens;
|
|
931
|
+
}
|
|
932
|
+
}
|
|
933
|
+
}
|
|
934
|
+
}
|
|
935
|
+
finally {
|
|
936
|
+
monitor.stop();
|
|
937
|
+
}
|
|
938
|
+
if (!content) {
|
|
939
|
+
throw wrapLLMError(new Error("LLM returned empty response from stream"), errorCtx);
|
|
940
|
+
}
|
|
941
|
+
if (!sawMessageStop) {
|
|
942
|
+
// Anthropic 协议的正常结束必须有 message_stop;没有就是流被中途掐断
|
|
943
|
+
throw new PartialResponseError(content, new Error("stream closed without message_stop"));
|
|
944
|
+
}
|
|
945
|
+
if (!usage.totalTokens) {
|
|
946
|
+
usage.totalTokens = usage.promptTokens + usage.completionTokens;
|
|
947
|
+
}
|
|
948
|
+
return { content, usage };
|
|
949
|
+
}
|
|
950
|
+
async function chatCompletionViaCustomOpenAICompatible(client, model, messages, resolved, onStreamProgress, onTextDelta, signal, traceHeaders = {}, onStreamActivity, allowSystemRoleFallback = true) {
|
|
951
|
+
if (client.provider === "anthropic") {
|
|
952
|
+
return chatCompletionViaCustomAnthropicCompatible(client, model, messages, resolved, onStreamProgress, onTextDelta, signal, traceHeaders, onStreamActivity);
|
|
953
|
+
}
|
|
954
|
+
const baseUrl = client._piModel?.baseUrl ?? "";
|
|
955
|
+
const headers = buildCustomHeaders(client, traceHeaders);
|
|
956
|
+
const errorCtx = { baseUrl, model, service: client.service };
|
|
957
|
+
const extra = stripReservedKeys(resolved.extra);
|
|
958
|
+
if (client.apiFormat === "responses") {
|
|
959
|
+
const payload = {
|
|
960
|
+
model,
|
|
961
|
+
input: buildResponsesInput(messages),
|
|
962
|
+
stream: client.stream,
|
|
963
|
+
store: false,
|
|
964
|
+
max_output_tokens: resolved.maxTokens,
|
|
965
|
+
temperature: resolved.temperature,
|
|
966
|
+
...extra,
|
|
967
|
+
};
|
|
968
|
+
const instructions = joinSystemPrompt(messages);
|
|
969
|
+
if (instructions)
|
|
970
|
+
payload.instructions = instructions;
|
|
971
|
+
const response = await fetchWithProxy(`${baseUrl.replace(/\/$/, "")}/responses`, {
|
|
972
|
+
method: "POST",
|
|
973
|
+
headers,
|
|
974
|
+
body: JSON.stringify(payload),
|
|
975
|
+
signal,
|
|
976
|
+
}, client.proxyUrl);
|
|
977
|
+
if (!response.ok) {
|
|
978
|
+
throw wrapLLMError(new Error(await readErrorResponse(response)), errorCtx);
|
|
979
|
+
}
|
|
980
|
+
if (!client.stream) {
|
|
981
|
+
const json = await response.json();
|
|
982
|
+
const content = extractResponsesContent(json);
|
|
983
|
+
if (!content) {
|
|
984
|
+
throw wrapLLMError(new Error("LLM returned empty response"), errorCtx);
|
|
985
|
+
}
|
|
986
|
+
return {
|
|
987
|
+
content,
|
|
988
|
+
usage: {
|
|
989
|
+
promptTokens: json?.usage?.input_tokens ?? 0,
|
|
990
|
+
completionTokens: json?.usage?.output_tokens ?? 0,
|
|
991
|
+
totalTokens: json?.usage?.total_tokens ?? 0,
|
|
992
|
+
},
|
|
993
|
+
};
|
|
994
|
+
}
|
|
995
|
+
const reader = response.body?.getReader();
|
|
996
|
+
if (!reader)
|
|
997
|
+
throw wrapLLMError(new Error("Streaming body unavailable"), errorCtx);
|
|
998
|
+
const decoder = new TextDecoder();
|
|
999
|
+
let buffer = "";
|
|
1000
|
+
let content = "";
|
|
1001
|
+
let usage = { promptTokens: 0, completionTokens: 0, totalTokens: 0 };
|
|
1002
|
+
let sawResponseTerminal = false;
|
|
1003
|
+
let sawResponseIncomplete = false;
|
|
1004
|
+
const monitor = createStreamMonitor(onStreamProgress);
|
|
1005
|
+
try {
|
|
1006
|
+
while (true) {
|
|
1007
|
+
const { value, done } = await reader.read();
|
|
1008
|
+
if (done)
|
|
1009
|
+
break;
|
|
1010
|
+
onStreamActivity?.();
|
|
1011
|
+
buffer += decoder.decode(value, { stream: true });
|
|
1012
|
+
const parsed = parseSseEvents(buffer);
|
|
1013
|
+
buffer = parsed.rest;
|
|
1014
|
+
for (const event of parsed.events) {
|
|
1015
|
+
if (!event.data)
|
|
1016
|
+
continue;
|
|
1017
|
+
const json = JSON.parse(event.data);
|
|
1018
|
+
if (json.type === "response.output_text.delta" && typeof json.delta === "string") {
|
|
1019
|
+
content += json.delta;
|
|
1020
|
+
monitor.onChunk(json.delta);
|
|
1021
|
+
onTextDelta?.(json.delta);
|
|
1022
|
+
}
|
|
1023
|
+
if (json.type === "response.completed" || json.type === "response.incomplete") {
|
|
1024
|
+
sawResponseTerminal = true;
|
|
1025
|
+
if (json.type === "response.incomplete")
|
|
1026
|
+
sawResponseIncomplete = true;
|
|
1027
|
+
usage = {
|
|
1028
|
+
promptTokens: json.response?.usage?.input_tokens ?? 0,
|
|
1029
|
+
completionTokens: json.response?.usage?.output_tokens ?? 0,
|
|
1030
|
+
totalTokens: json.response?.usage?.total_tokens ?? 0,
|
|
1031
|
+
};
|
|
1032
|
+
if (!content) {
|
|
1033
|
+
content = extractResponsesContent(json.response);
|
|
1034
|
+
}
|
|
1035
|
+
}
|
|
1036
|
+
}
|
|
1037
|
+
}
|
|
1038
|
+
}
|
|
1039
|
+
finally {
|
|
1040
|
+
monitor.stop();
|
|
1041
|
+
}
|
|
1042
|
+
if (!content) {
|
|
1043
|
+
throw wrapLLMError(new Error("LLM returned empty response from stream"), errorCtx);
|
|
1044
|
+
}
|
|
1045
|
+
if (!sawResponseTerminal) {
|
|
1046
|
+
// Responses 协议的正常结束必须有 response.completed/incomplete 终止事件
|
|
1047
|
+
throw new PartialResponseError(content, new Error("stream closed without response.completed"));
|
|
1048
|
+
}
|
|
1049
|
+
if (sawResponseIncomplete) {
|
|
1050
|
+
throw new PartialResponseError(content, new Error("response ended before the final answer was complete"));
|
|
1051
|
+
}
|
|
1052
|
+
return { content, usage };
|
|
1053
|
+
}
|
|
1054
|
+
const payload = {
|
|
1055
|
+
model,
|
|
1056
|
+
messages: [
|
|
1057
|
+
...messages
|
|
1058
|
+
.filter((message) => message.role === "system")
|
|
1059
|
+
.map((message) => ({ role: "system", content: message.content })),
|
|
1060
|
+
...buildChatMessages(messages),
|
|
1061
|
+
],
|
|
1062
|
+
stream: client.stream,
|
|
1063
|
+
temperature: resolved.temperature,
|
|
1064
|
+
max_tokens: resolved.maxTokens,
|
|
1065
|
+
...defaultOpenAIChatExtra(client, model),
|
|
1066
|
+
...extra,
|
|
1067
|
+
};
|
|
1068
|
+
if (client.stream) {
|
|
1069
|
+
payload.stream_options = { include_usage: true };
|
|
1070
|
+
}
|
|
1071
|
+
const response = await fetchWithProxy(`${baseUrl.replace(/\/$/, "")}/chat/completions`, {
|
|
1072
|
+
method: "POST",
|
|
1073
|
+
headers,
|
|
1074
|
+
body: JSON.stringify(payload),
|
|
1075
|
+
signal,
|
|
1076
|
+
}, client.proxyUrl);
|
|
1077
|
+
if (!response.ok) {
|
|
1078
|
+
const detail = await readErrorResponse(response);
|
|
1079
|
+
if (allowSystemRoleFallback && hasSystemMessages(messages) && isSystemRoleUnsupportedErrorText(detail)) {
|
|
1080
|
+
return chatCompletionViaCustomOpenAICompatible(client, model, foldSystemMessagesIntoFirstUser(messages), resolved, onStreamProgress, onTextDelta, signal, traceHeaders, onStreamActivity, false);
|
|
1081
|
+
}
|
|
1082
|
+
throw wrapLLMError(new Error(detail), errorCtx);
|
|
1083
|
+
}
|
|
1084
|
+
if (!client.stream) {
|
|
1085
|
+
const json = await response.json();
|
|
1086
|
+
// MiniMax M2.x 等模型可能把思考内容以 <think>...</think> 内联在 content 开头,
|
|
1087
|
+
// 剥掉起始处的完整 think 块,防止思考内容混进章节/对话正文(issue #329)。
|
|
1088
|
+
const content = stripLeadingThinkBlock(extractChatContent(json));
|
|
1089
|
+
const finishReason = json?.choices?.[0]?.finish_reason;
|
|
1090
|
+
if (finishReason === "length" || finishReason === "max_tokens") {
|
|
1091
|
+
throw new PartialResponseError(content || extractChatReasoningContent(json), new Error(`model reached the output limit (${finishReason})`), "output-limit");
|
|
1092
|
+
}
|
|
1093
|
+
if (!content) {
|
|
1094
|
+
if (extractChatReasoningContent(json)) {
|
|
1095
|
+
throw wrapLLMError(new Error("LLM returned reasoning without a final answer"), errorCtx);
|
|
1096
|
+
}
|
|
1097
|
+
throw wrapLLMError(new Error("LLM returned empty response"), errorCtx);
|
|
1098
|
+
}
|
|
1099
|
+
return {
|
|
1100
|
+
content,
|
|
1101
|
+
usage: {
|
|
1102
|
+
promptTokens: json?.usage?.prompt_tokens ?? 0,
|
|
1103
|
+
completionTokens: json?.usage?.completion_tokens ?? 0,
|
|
1104
|
+
totalTokens: json?.usage?.total_tokens ?? 0,
|
|
1105
|
+
},
|
|
1106
|
+
};
|
|
1107
|
+
}
|
|
1108
|
+
const reader = response.body?.getReader();
|
|
1109
|
+
if (!reader)
|
|
1110
|
+
throw wrapLLMError(new Error("Streaming body unavailable"), errorCtx);
|
|
1111
|
+
const decoder = new TextDecoder();
|
|
1112
|
+
let buffer = "";
|
|
1113
|
+
let content = "";
|
|
1114
|
+
let reasoningContent = "";
|
|
1115
|
+
let usage = { promptTokens: 0, completionTokens: 0, totalTokens: 0 };
|
|
1116
|
+
// OpenAI 协议的正常结束必须出现 [DONE] 哨兵或带 finish_reason 的 chunk。
|
|
1117
|
+
// 网关掐断长连接时流会"干净地"关闭但没有任何终止信号——那是截断,不是完成。
|
|
1118
|
+
let sawTerminal = false;
|
|
1119
|
+
let terminalFinishReason;
|
|
1120
|
+
const monitor = createStreamMonitor(onStreamProgress);
|
|
1121
|
+
// 内联 <think>...</think> 的模型(如 MiniMax M2.x):剥掉响应起始处的完整
|
|
1122
|
+
// think 块,思考内容既不并入正文也不通过 onTextDelta 发给 UI(issue #329)。
|
|
1123
|
+
const thinkStripper = createLeadingThinkTagStripper();
|
|
1124
|
+
try {
|
|
1125
|
+
while (true) {
|
|
1126
|
+
const { value, done } = await reader.read();
|
|
1127
|
+
if (done)
|
|
1128
|
+
break;
|
|
1129
|
+
onStreamActivity?.();
|
|
1130
|
+
buffer += decoder.decode(value, { stream: true });
|
|
1131
|
+
const parsed = parseSseEvents(buffer);
|
|
1132
|
+
buffer = parsed.rest;
|
|
1133
|
+
for (const event of parsed.events) {
|
|
1134
|
+
if (!event.data)
|
|
1135
|
+
continue;
|
|
1136
|
+
if (event.data === "[DONE]") {
|
|
1137
|
+
sawTerminal = true;
|
|
1138
|
+
continue;
|
|
1139
|
+
}
|
|
1140
|
+
const json = JSON.parse(event.data);
|
|
1141
|
+
if (json?.choices?.[0]?.finish_reason) {
|
|
1142
|
+
sawTerminal = true;
|
|
1143
|
+
terminalFinishReason = String(json.choices[0].finish_reason);
|
|
1144
|
+
}
|
|
1145
|
+
const delta = extractChatDeltaContent(json);
|
|
1146
|
+
if (delta) {
|
|
1147
|
+
monitor.onChunk(delta);
|
|
1148
|
+
const emittable = thinkStripper.push(delta);
|
|
1149
|
+
if (emittable) {
|
|
1150
|
+
content += emittable;
|
|
1151
|
+
onTextDelta?.(emittable);
|
|
1152
|
+
}
|
|
1153
|
+
}
|
|
1154
|
+
else {
|
|
1155
|
+
const reasoningDelta = extractChatDeltaReasoningContent(json);
|
|
1156
|
+
if (reasoningDelta) {
|
|
1157
|
+
reasoningContent += reasoningDelta;
|
|
1158
|
+
monitor.onChunk(reasoningDelta);
|
|
1159
|
+
}
|
|
1160
|
+
}
|
|
1161
|
+
if (json?.usage) {
|
|
1162
|
+
usage = {
|
|
1163
|
+
promptTokens: json.usage.prompt_tokens ?? usage.promptTokens,
|
|
1164
|
+
completionTokens: json.usage.completion_tokens ?? usage.completionTokens,
|
|
1165
|
+
totalTokens: json.usage.total_tokens ?? usage.totalTokens,
|
|
1166
|
+
};
|
|
1167
|
+
}
|
|
1168
|
+
}
|
|
1169
|
+
}
|
|
1170
|
+
}
|
|
1171
|
+
finally {
|
|
1172
|
+
monitor.stop();
|
|
1173
|
+
}
|
|
1174
|
+
// 流结束仍缓冲在剥离器里的文本(未闭合的 think 块等)原样并回,避免数据丢失。
|
|
1175
|
+
content += thinkStripper.flush();
|
|
1176
|
+
if (terminalFinishReason === "length" || terminalFinishReason === "max_tokens") {
|
|
1177
|
+
throw new PartialResponseError(content || reasoningContent, new Error(`model reached the output limit (${terminalFinishReason})`), "output-limit");
|
|
1178
|
+
}
|
|
1179
|
+
if (!content) {
|
|
1180
|
+
if (reasoningContent) {
|
|
1181
|
+
throw wrapLLMError(new Error("LLM returned reasoning without a final answer"), errorCtx);
|
|
1182
|
+
}
|
|
1183
|
+
throw wrapLLMError(new Error("LLM returned empty response from stream"), errorCtx);
|
|
1184
|
+
}
|
|
1185
|
+
if (!sawTerminal) {
|
|
1186
|
+
throw new PartialResponseError(content, new Error("stream closed without [DONE]/finish_reason"));
|
|
1187
|
+
}
|
|
1188
|
+
return { content, usage };
|
|
1189
|
+
}
|
|
1190
|
+
// === Simple Chat (used by all agents via BaseAgent.chat()) ===
|
|
1191
|
+
export async function chatCompletion(client, model, messages, options) {
|
|
1192
|
+
if (isLlmStubEnabled())
|
|
1193
|
+
return Promise.resolve(stubChatCompletion(messages, model));
|
|
1194
|
+
// C1 (v2.0.0):删除 maxTokensCap 机制。per-call 显式传的 maxTokens 永远不被裁剪。
|
|
1195
|
+
const resolved = {
|
|
1196
|
+
temperature: clampTemperatureForModel(client.service, model, options?.temperature ?? client.defaults.temperature),
|
|
1197
|
+
maxTokens: options?.maxTokens ?? client.defaults.maxTokens,
|
|
1198
|
+
extra: client.defaults.extra,
|
|
1199
|
+
};
|
|
1200
|
+
const onStreamProgress = options?.onStreamProgress;
|
|
1201
|
+
const onTextDelta = options?.onTextDelta;
|
|
1202
|
+
const signal = options?.signal;
|
|
1203
|
+
const errorCtx = { baseUrl: client._piModel?.baseUrl ?? "(unknown)", model, service: client.service };
|
|
1204
|
+
const modelCall = beginAgentModelCall();
|
|
1205
|
+
try {
|
|
1206
|
+
return await withTransientLLMRetry(async (attempt) => {
|
|
1207
|
+
signal?.throwIfAborted();
|
|
1208
|
+
const traceHeaders = agentTrajectoryHeaders(client._piModel?.baseUrl, modelCall, attempt, {
|
|
1209
|
+
effort: client.defaults.thinkingBudget > 0 ? "enabled" : "disabled",
|
|
1210
|
+
...(client.defaults.thinkingBudget > 0
|
|
1211
|
+
? { budgetTokens: client.defaults.thinkingBudget }
|
|
1212
|
+
: {}),
|
|
1213
|
+
});
|
|
1214
|
+
// Pipeline agents often perform long-form generation before yielding the
|
|
1215
|
+
// first token. Keep that path bounded, but do not apply the tighter
|
|
1216
|
+
// interactive-chat deadline to it.
|
|
1217
|
+
const deadline = client.stream
|
|
1218
|
+
? createStreamActivityDeadline(signal, {
|
|
1219
|
+
firstEventTimeoutMs: DEFAULT_PIPELINE_FIRST_STREAM_EVENT_TIMEOUT_MS,
|
|
1220
|
+
idleTimeoutMs: DEFAULT_PIPELINE_STREAM_IDLE_TIMEOUT_MS,
|
|
1221
|
+
}, {
|
|
1222
|
+
firstEventTimeoutMs: options?.firstEventTimeoutMs,
|
|
1223
|
+
idleTimeoutMs: options?.streamIdleTimeoutMs,
|
|
1224
|
+
})
|
|
1225
|
+
: undefined;
|
|
1226
|
+
assertWithinContextWindow({
|
|
1227
|
+
piModel: resolvePiModel(client, model),
|
|
1228
|
+
model,
|
|
1229
|
+
estimatedInputTokens: estimateLLMMessagesTokens(messages),
|
|
1230
|
+
reservedOutputTokens: resolved.maxTokens,
|
|
1231
|
+
});
|
|
1232
|
+
try {
|
|
1233
|
+
if (shouldUseNativeCustomTransport(client)) {
|
|
1234
|
+
return await chatCompletionViaCustomOpenAICompatible(client, model, messages, resolved, onStreamProgress, onTextDelta, deadline?.signal ?? signal, traceHeaders, deadline?.activity);
|
|
1235
|
+
}
|
|
1236
|
+
return await chatCompletionViaPiAi(client, model, messages, resolved, onStreamProgress, onTextDelta, deadline?.signal ?? signal, traceHeaders, deadline?.activity);
|
|
1237
|
+
}
|
|
1238
|
+
catch (error) {
|
|
1239
|
+
throw deadline?.timeoutError() ?? error;
|
|
1240
|
+
}
|
|
1241
|
+
finally {
|
|
1242
|
+
deadline?.stop();
|
|
1243
|
+
}
|
|
1244
|
+
},
|
|
1245
|
+
// Retrying after UI text deltas have been emitted can duplicate visible
|
|
1246
|
+
// text; callers can also opt out (e.g. fast-fail diagnostics).
|
|
1247
|
+
{ enabled: (options?.retry ?? true) && !onTextDelta, signal });
|
|
1248
|
+
}
|
|
1249
|
+
catch (error) {
|
|
1250
|
+
// 注意:中断的流(PartialResponseError)不再"打捞"半截内容当成功返回——
|
|
1251
|
+
// 那会产出写到一半就结束的章节/设定文件。重试由 withTransientLLMRetry
|
|
1252
|
+
// 负责(完整重新生成);重试耗尽后如实抛错。
|
|
1253
|
+
throw wrapLLMError(error, errorCtx);
|
|
1254
|
+
}
|
|
1255
|
+
}
|
|
1256
|
+
// === pi-ai Unified Implementation ===
|
|
1257
|
+
/**
|
|
1258
|
+
* Build a pi-ai Model<Api> for a specific per-call model name.
|
|
1259
|
+
* The base template comes from client._piModel (created in createLLMClient);
|
|
1260
|
+
* we override .id / .name when the caller passes a different model string
|
|
1261
|
+
* (e.g. agent overrides).
|
|
1262
|
+
*/
|
|
1263
|
+
function resolvePiModel(client, model) {
|
|
1264
|
+
const base = client._piModel;
|
|
1265
|
+
if (base.id === model)
|
|
1266
|
+
return base;
|
|
1267
|
+
return { ...base, id: model, name: model };
|
|
1268
|
+
}
|
|
1269
|
+
/** Convert inkos LLMMessage[] to pi-ai Context. */
|
|
1270
|
+
function toPiContext(messages) {
|
|
1271
|
+
const systemParts = messages.filter((m) => m.role === "system").map((m) => m.content);
|
|
1272
|
+
const systemPrompt = systemParts.length > 0 ? systemParts.join("\n\n") : undefined;
|
|
1273
|
+
const piMessages = messages
|
|
1274
|
+
.filter((m) => m.role !== "system")
|
|
1275
|
+
.map((m) => {
|
|
1276
|
+
if (m.role === "user") {
|
|
1277
|
+
return { role: "user", content: m.content, timestamp: Date.now() };
|
|
1278
|
+
}
|
|
1279
|
+
// assistant
|
|
1280
|
+
return {
|
|
1281
|
+
role: "assistant",
|
|
1282
|
+
content: [{ type: "text", text: m.content }],
|
|
1283
|
+
api: "openai-completions",
|
|
1284
|
+
provider: "openai",
|
|
1285
|
+
model: "",
|
|
1286
|
+
usage: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, totalTokens: 0, cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 } },
|
|
1287
|
+
stopReason: "stop",
|
|
1288
|
+
timestamp: Date.now(),
|
|
1289
|
+
};
|
|
1290
|
+
});
|
|
1291
|
+
return { systemPrompt, messages: piMessages };
|
|
1292
|
+
}
|
|
1293
|
+
async function chatCompletionViaPiAi(client, model, messages, resolved, onStreamProgress, onTextDelta, signal, traceHeaders = {}, onStreamActivity) {
|
|
1294
|
+
const piModel = resolvePiModel(client, model);
|
|
1295
|
+
const context = toPiContext(messages);
|
|
1296
|
+
const streamOpts = {
|
|
1297
|
+
temperature: resolved.temperature,
|
|
1298
|
+
maxTokens: resolved.maxTokens,
|
|
1299
|
+
apiKey: client._apiKey,
|
|
1300
|
+
headers: mergeUserAgent({ ...(piModel.headers ?? {}), ...traceHeaders }),
|
|
1301
|
+
signal,
|
|
1302
|
+
};
|
|
1303
|
+
if (!client.stream) {
|
|
1304
|
+
const response = await piCompleteSimple(piModel, context, streamOpts);
|
|
1305
|
+
if (response.stopReason === "error" && response.errorMessage) {
|
|
1306
|
+
throw new Error(response.errorMessage);
|
|
1307
|
+
}
|
|
1308
|
+
const content = response.content
|
|
1309
|
+
.filter((block) => block.type === "text")
|
|
1310
|
+
.map((block) => block.text)
|
|
1311
|
+
.join("");
|
|
1312
|
+
if (response.stopReason === "length") {
|
|
1313
|
+
throw new PartialResponseError(content, new Error("model reached the output limit (length)"), "output-limit");
|
|
1314
|
+
}
|
|
1315
|
+
if (!content) {
|
|
1316
|
+
const diag = `usage=${response.usage.input}+${response.usage.output}`;
|
|
1317
|
+
console.warn(`[inkos] LLM 非流式响应无文本内容 (${diag})`);
|
|
1318
|
+
throw new Error(`LLM returned empty response (${diag})`);
|
|
1319
|
+
}
|
|
1320
|
+
return {
|
|
1321
|
+
content,
|
|
1322
|
+
usage: {
|
|
1323
|
+
promptTokens: response.usage.input,
|
|
1324
|
+
completionTokens: response.usage.output,
|
|
1325
|
+
totalTokens: response.usage.totalTokens,
|
|
1326
|
+
},
|
|
1327
|
+
};
|
|
1328
|
+
}
|
|
1329
|
+
const eventStream = piStreamSimple(piModel, context, streamOpts);
|
|
1330
|
+
const chunks = [];
|
|
1331
|
+
const monitor = createStreamMonitor(onStreamProgress);
|
|
1332
|
+
let inputTokens = 0;
|
|
1333
|
+
let outputTokens = 0;
|
|
1334
|
+
let sawDone = false;
|
|
1335
|
+
let stoppedAtOutputLimit = false;
|
|
1336
|
+
try {
|
|
1337
|
+
const iterator = eventStream[Symbol.asyncIterator]();
|
|
1338
|
+
while (true) {
|
|
1339
|
+
const next = signal
|
|
1340
|
+
? await nextWithAbort(iterator, signal)
|
|
1341
|
+
: await iterator.next();
|
|
1342
|
+
if (next.done)
|
|
1343
|
+
break;
|
|
1344
|
+
const event = next.value;
|
|
1345
|
+
onStreamActivity?.();
|
|
1346
|
+
if (event.type === "text_delta") {
|
|
1347
|
+
chunks.push(event.delta);
|
|
1348
|
+
monitor.onChunk(event.delta);
|
|
1349
|
+
onTextDelta?.(event.delta);
|
|
1350
|
+
}
|
|
1351
|
+
if (event.type === "done" || event.type === "error") {
|
|
1352
|
+
const msg = event.type === "done" ? event.message : event.error;
|
|
1353
|
+
inputTokens = msg.usage.input;
|
|
1354
|
+
outputTokens = msg.usage.output;
|
|
1355
|
+
if (event.type === "done") {
|
|
1356
|
+
sawDone = true;
|
|
1357
|
+
stoppedAtOutputLimit = msg.stopReason === "length";
|
|
1358
|
+
}
|
|
1359
|
+
if (event.type === "error" && msg.errorMessage) {
|
|
1360
|
+
const partial = chunks.join("");
|
|
1361
|
+
if (partial) {
|
|
1362
|
+
throw new PartialResponseError(partial, new Error(msg.errorMessage));
|
|
1363
|
+
}
|
|
1364
|
+
throw new Error(msg.errorMessage);
|
|
1365
|
+
}
|
|
1366
|
+
}
|
|
1367
|
+
}
|
|
1368
|
+
}
|
|
1369
|
+
catch (streamError) {
|
|
1370
|
+
monitor.stop();
|
|
1371
|
+
if (streamError instanceof PartialResponseError)
|
|
1372
|
+
throw streamError;
|
|
1373
|
+
const partial = chunks.join("");
|
|
1374
|
+
if (partial) {
|
|
1375
|
+
// 带着已收到的部分内容抛 PartialResponseError,让瞬时重试整体重新生成
|
|
1376
|
+
throw new PartialResponseError(partial, streamError);
|
|
1377
|
+
}
|
|
1378
|
+
throw streamError;
|
|
1379
|
+
}
|
|
1380
|
+
finally {
|
|
1381
|
+
monitor.stop();
|
|
1382
|
+
}
|
|
1383
|
+
const content = chunks.join("");
|
|
1384
|
+
if (stoppedAtOutputLimit) {
|
|
1385
|
+
throw new PartialResponseError(content, new Error("model reached the output limit (length)"), "output-limit");
|
|
1386
|
+
}
|
|
1387
|
+
if (!content) {
|
|
1388
|
+
const diag = `usage=${inputTokens}+${outputTokens}`;
|
|
1389
|
+
console.warn(`[inkos] LLM 流式响应无文本内容 (${diag})`);
|
|
1390
|
+
throw new Error(`LLM returned empty response from stream (${diag})`);
|
|
1391
|
+
}
|
|
1392
|
+
if (!sawDone) {
|
|
1393
|
+
// 事件流没有以 done 收尾就结束 = 上游把流掐断了,内容不可信
|
|
1394
|
+
throw new PartialResponseError(content, new Error("stream ended without done event"));
|
|
1395
|
+
}
|
|
1396
|
+
return {
|
|
1397
|
+
content,
|
|
1398
|
+
usage: {
|
|
1399
|
+
promptTokens: inputTokens,
|
|
1400
|
+
completionTokens: outputTokens,
|
|
1401
|
+
totalTokens: inputTokens + outputTokens,
|
|
1402
|
+
},
|
|
1403
|
+
};
|
|
1404
|
+
}
|
|
1405
|
+
//# sourceMappingURL=provider.js.map
|