@code-yeongyu/senpi 2026.7.11 → 2026.7.13
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/CHANGELOG.md +17 -0
- package/dist/core/agent-session.d.ts +9 -0
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +56 -15
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/extensions/builtin/prompt-preset/gpt-5.6.d.ts.map +1 -1
- package/dist/core/extensions/builtin/prompt-preset/gpt-5.6.js +76 -25
- package/dist/core/extensions/builtin/prompt-preset/gpt-5.6.js.map +1 -1
- package/dist/core/resource-loader.d.ts +1 -0
- package/dist/core/resource-loader.d.ts.map +1 -1
- package/dist/core/resource-loader.js +20 -2
- package/dist/core/resource-loader.js.map +1 -1
- package/dist/modes/interactive/compaction-queue-transfer.d.ts +22 -0
- package/dist/modes/interactive/compaction-queue-transfer.d.ts.map +1 -0
- package/dist/modes/interactive/compaction-queue-transfer.js +82 -0
- package/dist/modes/interactive/compaction-queue-transfer.js.map +1 -0
- package/dist/modes/interactive/interactive-mode.d.ts +4 -0
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +83 -69
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/node_modules/@babel/helper-string-parser/LICENSE +22 -0
- package/node_modules/@babel/helper-string-parser/README.md +19 -0
- package/node_modules/@babel/helper-string-parser/lib/index.js +295 -0
- package/node_modules/@babel/helper-string-parser/lib/index.js.map +1 -0
- package/node_modules/@babel/helper-string-parser/package.json +31 -0
- package/node_modules/@babel/helper-validator-identifier/LICENSE +22 -0
- package/node_modules/@babel/helper-validator-identifier/README.md +19 -0
- package/node_modules/@babel/helper-validator-identifier/lib/identifier.js +70 -0
- package/node_modules/@babel/helper-validator-identifier/lib/identifier.js.map +1 -0
- package/node_modules/@babel/helper-validator-identifier/lib/index.js +57 -0
- package/node_modules/@babel/helper-validator-identifier/lib/index.js.map +1 -0
- package/node_modules/@babel/helper-validator-identifier/lib/keyword.js +35 -0
- package/node_modules/@babel/helper-validator-identifier/lib/keyword.js.map +1 -0
- package/node_modules/@babel/helper-validator-identifier/package.json +31 -0
- package/node_modules/@babel/parser/LICENSE +19 -0
- package/node_modules/@babel/parser/README.md +19 -0
- package/node_modules/@babel/parser/bin/babel-parser.js +15 -0
- package/node_modules/@babel/parser/lib/index.js +14599 -0
- package/node_modules/@babel/parser/lib/index.js.map +1 -0
- package/node_modules/@babel/parser/package.json +50 -0
- package/node_modules/@babel/parser/typings/babel-parser.d.ts +262 -0
- package/node_modules/@babel/types/LICENSE +22 -0
- package/node_modules/@babel/types/README.md +19 -0
- package/node_modules/@babel/types/lib/asserts/assertNode.js +16 -0
- package/node_modules/@babel/types/lib/asserts/assertNode.js.map +1 -0
- package/node_modules/@babel/types/lib/asserts/generated/index.js +1251 -0
- package/node_modules/@babel/types/lib/asserts/generated/index.js.map +1 -0
- package/node_modules/@babel/types/lib/ast-types/generated/index.js +3 -0
- package/node_modules/@babel/types/lib/ast-types/generated/index.js.map +1 -0
- package/node_modules/@babel/types/lib/builders/flow/createFlowUnionType.js +18 -0
- package/node_modules/@babel/types/lib/builders/flow/createFlowUnionType.js.map +1 -0
- package/node_modules/@babel/types/lib/builders/flow/createTypeAnnotationBasedOnTypeof.js +31 -0
- package/node_modules/@babel/types/lib/builders/flow/createTypeAnnotationBasedOnTypeof.js.map +1 -0
- package/node_modules/@babel/types/lib/builders/generated/index.js +29 -0
- package/node_modules/@babel/types/lib/builders/generated/index.js.map +1 -0
- package/node_modules/@babel/types/lib/builders/generated/lowercase.js +2902 -0
- package/node_modules/@babel/types/lib/builders/generated/lowercase.js.map +1 -0
- package/node_modules/@babel/types/lib/builders/generated/uppercase.js +272 -0
- package/node_modules/@babel/types/lib/builders/generated/uppercase.js.map +1 -0
- package/node_modules/@babel/types/lib/builders/productions.js +12 -0
- package/node_modules/@babel/types/lib/builders/productions.js.map +1 -0
- package/node_modules/@babel/types/lib/builders/react/buildChildren.js +24 -0
- package/node_modules/@babel/types/lib/builders/react/buildChildren.js.map +1 -0
- package/node_modules/@babel/types/lib/builders/typescript/createTSUnionType.js +22 -0
- package/node_modules/@babel/types/lib/builders/typescript/createTSUnionType.js.map +1 -0
- package/node_modules/@babel/types/lib/builders/validateNode.js +21 -0
- package/node_modules/@babel/types/lib/builders/validateNode.js.map +1 -0
- package/node_modules/@babel/types/lib/clone/clone.js +12 -0
- package/node_modules/@babel/types/lib/clone/clone.js.map +1 -0
- package/node_modules/@babel/types/lib/clone/cloneDeep.js +12 -0
- package/node_modules/@babel/types/lib/clone/cloneDeep.js.map +1 -0
- package/node_modules/@babel/types/lib/clone/cloneDeepWithoutLoc.js +12 -0
- package/node_modules/@babel/types/lib/clone/cloneDeepWithoutLoc.js.map +1 -0
- package/node_modules/@babel/types/lib/clone/cloneNode.js +107 -0
- package/node_modules/@babel/types/lib/clone/cloneNode.js.map +1 -0
- package/node_modules/@babel/types/lib/clone/cloneWithoutLoc.js +12 -0
- package/node_modules/@babel/types/lib/clone/cloneWithoutLoc.js.map +1 -0
- package/node_modules/@babel/types/lib/comments/addComment.js +15 -0
- package/node_modules/@babel/types/lib/comments/addComment.js.map +1 -0
- package/node_modules/@babel/types/lib/comments/addComments.js +22 -0
- package/node_modules/@babel/types/lib/comments/addComments.js.map +1 -0
- package/node_modules/@babel/types/lib/comments/inheritInnerComments.js +12 -0
- package/node_modules/@babel/types/lib/comments/inheritInnerComments.js.map +1 -0
- package/node_modules/@babel/types/lib/comments/inheritLeadingComments.js +12 -0
- package/node_modules/@babel/types/lib/comments/inheritLeadingComments.js.map +1 -0
- package/node_modules/@babel/types/lib/comments/inheritTrailingComments.js +12 -0
- package/node_modules/@babel/types/lib/comments/inheritTrailingComments.js.map +1 -0
- package/node_modules/@babel/types/lib/comments/inheritsComments.js +17 -0
- package/node_modules/@babel/types/lib/comments/inheritsComments.js.map +1 -0
- package/node_modules/@babel/types/lib/comments/removeComments.js +15 -0
- package/node_modules/@babel/types/lib/comments/removeComments.js.map +1 -0
- package/node_modules/@babel/types/lib/constants/generated/index.js +60 -0
- package/node_modules/@babel/types/lib/constants/generated/index.js.map +1 -0
- package/node_modules/@babel/types/lib/constants/index.js +31 -0
- package/node_modules/@babel/types/lib/constants/index.js.map +1 -0
- package/node_modules/@babel/types/lib/converters/ensureBlock.js +14 -0
- package/node_modules/@babel/types/lib/converters/ensureBlock.js.map +1 -0
- package/node_modules/@babel/types/lib/converters/gatherSequenceExpressions.js +65 -0
- package/node_modules/@babel/types/lib/converters/gatherSequenceExpressions.js.map +1 -0
- package/node_modules/@babel/types/lib/converters/toBindingIdentifierName.js +14 -0
- package/node_modules/@babel/types/lib/converters/toBindingIdentifierName.js.map +1 -0
- package/node_modules/@babel/types/lib/converters/toBlock.js +29 -0
- package/node_modules/@babel/types/lib/converters/toBlock.js.map +1 -0
- package/node_modules/@babel/types/lib/converters/toComputedKey.js +14 -0
- package/node_modules/@babel/types/lib/converters/toComputedKey.js.map +1 -0
- package/node_modules/@babel/types/lib/converters/toExpression.js +28 -0
- package/node_modules/@babel/types/lib/converters/toExpression.js.map +1 -0
- package/node_modules/@babel/types/lib/converters/toIdentifier.js +25 -0
- package/node_modules/@babel/types/lib/converters/toIdentifier.js.map +1 -0
- package/node_modules/@babel/types/lib/converters/toKeyAlias.js +38 -0
- package/node_modules/@babel/types/lib/converters/toKeyAlias.js.map +1 -0
- package/node_modules/@babel/types/lib/converters/toSequenceExpression.js +19 -0
- package/node_modules/@babel/types/lib/converters/toSequenceExpression.js.map +1 -0
- package/node_modules/@babel/types/lib/converters/toStatement.js +39 -0
- package/node_modules/@babel/types/lib/converters/toStatement.js.map +1 -0
- package/node_modules/@babel/types/lib/converters/valueToNode.js +89 -0
- package/node_modules/@babel/types/lib/converters/valueToNode.js.map +1 -0
- package/node_modules/@babel/types/lib/definitions/core.js +1725 -0
- package/node_modules/@babel/types/lib/definitions/core.js.map +1 -0
- package/node_modules/@babel/types/lib/definitions/deprecated-aliases.js +11 -0
- package/node_modules/@babel/types/lib/definitions/deprecated-aliases.js.map +1 -0
- package/node_modules/@babel/types/lib/definitions/experimental.js +124 -0
- package/node_modules/@babel/types/lib/definitions/experimental.js.map +1 -0
- package/node_modules/@babel/types/lib/definitions/flow.js +495 -0
- package/node_modules/@babel/types/lib/definitions/flow.js.map +1 -0
- package/node_modules/@babel/types/lib/definitions/index.js +106 -0
- package/node_modules/@babel/types/lib/definitions/index.js.map +1 -0
- package/node_modules/@babel/types/lib/definitions/jsx.js +157 -0
- package/node_modules/@babel/types/lib/definitions/jsx.js.map +1 -0
- package/node_modules/@babel/types/lib/definitions/misc.js +31 -0
- package/node_modules/@babel/types/lib/definitions/misc.js.map +1 -0
- package/node_modules/@babel/types/lib/definitions/placeholders.js +27 -0
- package/node_modules/@babel/types/lib/definitions/placeholders.js.map +1 -0
- package/node_modules/@babel/types/lib/definitions/typescript.js +528 -0
- package/node_modules/@babel/types/lib/definitions/typescript.js.map +1 -0
- package/node_modules/@babel/types/lib/definitions/utils.js +296 -0
- package/node_modules/@babel/types/lib/definitions/utils.js.map +1 -0
- package/node_modules/@babel/types/lib/index-legacy.d.ts +2797 -0
- package/node_modules/@babel/types/lib/index.d.ts +3617 -0
- package/node_modules/@babel/types/lib/index.js +582 -0
- package/node_modules/@babel/types/lib/index.js.flow +2650 -0
- package/node_modules/@babel/types/lib/index.js.map +1 -0
- package/node_modules/@babel/types/lib/modifications/appendToMemberExpression.js +15 -0
- package/node_modules/@babel/types/lib/modifications/appendToMemberExpression.js.map +1 -0
- package/node_modules/@babel/types/lib/modifications/flow/removeTypeDuplicates.js +65 -0
- package/node_modules/@babel/types/lib/modifications/flow/removeTypeDuplicates.js.map +1 -0
- package/node_modules/@babel/types/lib/modifications/inherits.js +28 -0
- package/node_modules/@babel/types/lib/modifications/inherits.js.map +1 -0
- package/node_modules/@babel/types/lib/modifications/prependToMemberExpression.js +17 -0
- package/node_modules/@babel/types/lib/modifications/prependToMemberExpression.js.map +1 -0
- package/node_modules/@babel/types/lib/modifications/removeProperties.js +24 -0
- package/node_modules/@babel/types/lib/modifications/removeProperties.js.map +1 -0
- package/node_modules/@babel/types/lib/modifications/removePropertiesDeep.js +14 -0
- package/node_modules/@babel/types/lib/modifications/removePropertiesDeep.js.map +1 -0
- package/node_modules/@babel/types/lib/modifications/typescript/removeTypeDuplicates.js +66 -0
- package/node_modules/@babel/types/lib/modifications/typescript/removeTypeDuplicates.js.map +1 -0
- package/node_modules/@babel/types/lib/retrievers/getAssignmentIdentifiers.js +48 -0
- package/node_modules/@babel/types/lib/retrievers/getAssignmentIdentifiers.js.map +1 -0
- package/node_modules/@babel/types/lib/retrievers/getBindingIdentifiers.js +102 -0
- package/node_modules/@babel/types/lib/retrievers/getBindingIdentifiers.js.map +1 -0
- package/node_modules/@babel/types/lib/retrievers/getFunctionName.js +63 -0
- package/node_modules/@babel/types/lib/retrievers/getFunctionName.js.map +1 -0
- package/node_modules/@babel/types/lib/retrievers/getOuterBindingIdentifiers.js +13 -0
- package/node_modules/@babel/types/lib/retrievers/getOuterBindingIdentifiers.js.map +1 -0
- package/node_modules/@babel/types/lib/traverse/traverse.js +50 -0
- package/node_modules/@babel/types/lib/traverse/traverse.js.map +1 -0
- package/node_modules/@babel/types/lib/traverse/traverseFast.js +40 -0
- package/node_modules/@babel/types/lib/traverse/traverseFast.js.map +1 -0
- package/node_modules/@babel/types/lib/utils/deprecationWarning.js +44 -0
- package/node_modules/@babel/types/lib/utils/deprecationWarning.js.map +1 -0
- package/node_modules/@babel/types/lib/utils/inherit.js +13 -0
- package/node_modules/@babel/types/lib/utils/inherit.js.map +1 -0
- package/node_modules/@babel/types/lib/utils/react/cleanJSXElementLiteralChild.js +40 -0
- package/node_modules/@babel/types/lib/utils/react/cleanJSXElementLiteralChild.js.map +1 -0
- package/node_modules/@babel/types/lib/utils/shallowEqual.js +17 -0
- package/node_modules/@babel/types/lib/utils/shallowEqual.js.map +1 -0
- package/node_modules/@babel/types/lib/validators/buildMatchMemberExpression.js +13 -0
- package/node_modules/@babel/types/lib/validators/buildMatchMemberExpression.js.map +1 -0
- package/node_modules/@babel/types/lib/validators/generated/index.js +2797 -0
- package/node_modules/@babel/types/lib/validators/generated/index.js.map +1 -0
- package/node_modules/@babel/types/lib/validators/is.js +27 -0
- package/node_modules/@babel/types/lib/validators/is.js.map +1 -0
- package/node_modules/@babel/types/lib/validators/isBinding.js +27 -0
- package/node_modules/@babel/types/lib/validators/isBinding.js.map +1 -0
- package/node_modules/@babel/types/lib/validators/isBlockScoped.js +13 -0
- package/node_modules/@babel/types/lib/validators/isBlockScoped.js.map +1 -0
- package/node_modules/@babel/types/lib/validators/isImmutable.js +21 -0
- package/node_modules/@babel/types/lib/validators/isImmutable.js.map +1 -0
- package/node_modules/@babel/types/lib/validators/isLet.js +13 -0
- package/node_modules/@babel/types/lib/validators/isLet.js.map +1 -0
- package/node_modules/@babel/types/lib/validators/isNode.js +12 -0
- package/node_modules/@babel/types/lib/validators/isNode.js.map +1 -0
- package/node_modules/@babel/types/lib/validators/isNodesEquivalent.js +57 -0
- package/node_modules/@babel/types/lib/validators/isNodesEquivalent.js.map +1 -0
- package/node_modules/@babel/types/lib/validators/isPlaceholderType.js +15 -0
- package/node_modules/@babel/types/lib/validators/isPlaceholderType.js.map +1 -0
- package/node_modules/@babel/types/lib/validators/isReferenced.js +96 -0
- package/node_modules/@babel/types/lib/validators/isReferenced.js.map +1 -0
- package/node_modules/@babel/types/lib/validators/isScope.js +18 -0
- package/node_modules/@babel/types/lib/validators/isScope.js.map +1 -0
- package/node_modules/@babel/types/lib/validators/isSpecifierDefault.js +14 -0
- package/node_modules/@babel/types/lib/validators/isSpecifierDefault.js.map +1 -0
- package/node_modules/@babel/types/lib/validators/isType.js +17 -0
- package/node_modules/@babel/types/lib/validators/isType.js.map +1 -0
- package/node_modules/@babel/types/lib/validators/isValidES3Identifier.js +13 -0
- package/node_modules/@babel/types/lib/validators/isValidES3Identifier.js.map +1 -0
- package/node_modules/@babel/types/lib/validators/isValidIdentifier.js +18 -0
- package/node_modules/@babel/types/lib/validators/isValidIdentifier.js.map +1 -0
- package/node_modules/@babel/types/lib/validators/isVar.js +15 -0
- package/node_modules/@babel/types/lib/validators/isVar.js.map +1 -0
- package/node_modules/@babel/types/lib/validators/matchesPattern.js +44 -0
- package/node_modules/@babel/types/lib/validators/matchesPattern.js.map +1 -0
- package/node_modules/@babel/types/lib/validators/react/isCompatTag.js +11 -0
- package/node_modules/@babel/types/lib/validators/react/isCompatTag.js.map +1 -0
- package/node_modules/@babel/types/lib/validators/react/isReactComponent.js +11 -0
- package/node_modules/@babel/types/lib/validators/react/isReactComponent.js.map +1 -0
- package/node_modules/@babel/types/lib/validators/validate.js +42 -0
- package/node_modules/@babel/types/lib/validators/validate.js.map +1 -0
- package/node_modules/@babel/types/package.json +39 -0
- package/node_modules/@code-yeongyu/senpi-codemode/CHANGELOG.md +10 -2
- package/node_modules/@code-yeongyu/senpi-codemode/README.md +128 -78
- package/node_modules/@code-yeongyu/senpi-codemode/package.json +4 -3
- package/node_modules/@code-yeongyu/senpi-codemode/src/bridge/protocol.ts +15 -2
- package/node_modules/@code-yeongyu/senpi-codemode/src/bridge/reserved.ts +9 -0
- package/node_modules/@code-yeongyu/senpi-codemode/src/bridges/agent-bridge.ts +197 -0
- package/node_modules/@code-yeongyu/senpi-codemode/src/bridges/output-bridge.ts +96 -0
- package/node_modules/@code-yeongyu/senpi-codemode/src/bridges/schema-injection.ts +3 -0
- package/node_modules/@code-yeongyu/senpi-codemode/src/completion/handler.ts +95 -26
- package/node_modules/@code-yeongyu/senpi-codemode/src/completion/tool-bridge.ts +11 -2
- package/node_modules/@code-yeongyu/senpi-codemode/src/config/settings.ts +96 -8
- package/node_modules/@code-yeongyu/senpi-codemode/src/extension/session-manager.ts +24 -3
- package/node_modules/@code-yeongyu/senpi-codemode/src/index.ts +155 -21
- package/node_modules/@code-yeongyu/senpi-codemode/src/interpreters/detect.ts +1 -1
- package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/jl/prelude.jl +252 -48
- package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/jl/runner.jl +263 -83
- package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/context-manager.ts +11 -5
- package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/local-module-loader.ts +108 -0
- package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/prelude.ts +8 -6
- package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/rewrite-imports.ts +164 -0
- package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/worker-core.js +6 -1
- package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/worker-runtime.js +307 -41
- package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/py/kernel.ts +3 -2
- package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/py/prelude.py +792 -79
- package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/rb/prelude.rb +234 -21
- package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/rb/runner.rb +154 -51
- package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/shared/subprocess-queue.ts +1 -0
- package/node_modules/@code-yeongyu/senpi-codemode/src/output/output-meta.ts +89 -0
- package/node_modules/@code-yeongyu/senpi-codemode/src/output/streaming-output.ts +296 -0
- package/node_modules/@code-yeongyu/senpi-codemode/src/prompt/eval-prompt.ts +107 -30
- package/node_modules/@code-yeongyu/senpi-codemode/src/timeouts/bridge-timeout.ts +2 -0
- package/node_modules/@code-yeongyu/senpi-codemode/src/timeouts/idle-timeout.ts +8 -19
- package/node_modules/@code-yeongyu/senpi-codemode/src/tool/cell-handler.ts +175 -113
- package/node_modules/@code-yeongyu/senpi-codemode/src/tool/eval-tool.ts +130 -120
- package/node_modules/@code-yeongyu/senpi-codemode/src/tool/image.ts +274 -0
- package/node_modules/@code-yeongyu/senpi-codemode/src/tool/json-tree.ts +247 -0
- package/node_modules/@code-yeongyu/senpi-codemode/src/tool/render.ts +641 -38
- package/node_modules/@code-yeongyu/senpi-codemode/src/tool/status-events.ts +12 -0
- package/node_modules/@code-yeongyu/senpi-codemode/src/tool/types.ts +29 -1
- package/node_modules/@earendil-works/pi-agent-core/package.json +2 -2
- package/node_modules/@earendil-works/pi-ai/dist/providers/openrouter.models.js +16 -16
- package/node_modules/@earendil-works/pi-ai/dist/providers/openrouter.models.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/vercel-ai-gateway.models.js +6 -6
- package/node_modules/@earendil-works/pi-ai/dist/providers/vercel-ai-gateway.models.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/package.json +2 -2
- package/node_modules/@earendil-works/pi-pty/package.json +1 -1
- package/node_modules/@earendil-works/pi-tui/package.json +1 -1
- package/package.json +6 -6
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import type { AgentToolResult } from "@code-yeongyu/senpi";
|
|
2
|
+
import { type Static, Type } from "typebox";
|
|
3
|
+
import { Check, Errors } from "typebox/value";
|
|
4
|
+
import type { ExecuteTool } from "../tool/types.ts";
|
|
5
|
+
|
|
6
|
+
const outputArgsSchema = Type.Object(
|
|
7
|
+
{
|
|
8
|
+
ids: Type.Array(Type.String({ minLength: 1 }), { minItems: 1 }),
|
|
9
|
+
format: Type.Optional(Type.Union([Type.Literal("raw"), Type.Literal("tail")])),
|
|
10
|
+
offset: Type.Optional(Type.Integer({ minimum: 1 })),
|
|
11
|
+
limit: Type.Optional(Type.Integer({ minimum: 1 })),
|
|
12
|
+
},
|
|
13
|
+
{ additionalProperties: false },
|
|
14
|
+
);
|
|
15
|
+
|
|
16
|
+
type OutputArgs = Static<typeof outputArgsSchema>;
|
|
17
|
+
|
|
18
|
+
export type OutputExecuteTool = ExecuteTool & {
|
|
19
|
+
readonly isToolAvailable?: (name: string) => boolean;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export type MarshalledToolResult = {
|
|
23
|
+
readonly text: string;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export interface RunEvalOutputOptions {
|
|
27
|
+
readonly taskOutputToolName: string;
|
|
28
|
+
readonly executeTool: OutputExecuteTool;
|
|
29
|
+
readonly signal?: AbortSignal;
|
|
30
|
+
readonly marshalToolResult: (result: AgentToolResult<unknown>) => MarshalledToolResult;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
class OutputArgumentsError extends Error {
|
|
34
|
+
readonly name = "OutputArgumentsError";
|
|
35
|
+
|
|
36
|
+
constructor(summary: string) {
|
|
37
|
+
super(`output() received invalid arguments: ${summary}`);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
class OutputUnavailableError extends Error {
|
|
42
|
+
readonly name = "OutputUnavailableError";
|
|
43
|
+
|
|
44
|
+
constructor(toolName: string) {
|
|
45
|
+
super(`output() unavailable: no "${toolName}" tool is registered in this session`);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export async function runEvalOutput(args: unknown, options: RunEvalOutputOptions): Promise<string | readonly string[]> {
|
|
50
|
+
const parsed = parseOutputArgs(args);
|
|
51
|
+
if (options.executeTool.isToolAvailable?.(options.taskOutputToolName) === false) {
|
|
52
|
+
throw new OutputUnavailableError(options.taskOutputToolName);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const mode = parsed.format === "tail" ? "tail" : "full";
|
|
56
|
+
const transcripts = await Promise.all(
|
|
57
|
+
parsed.ids.map(async (id) => {
|
|
58
|
+
let result: AgentToolResult<unknown>;
|
|
59
|
+
try {
|
|
60
|
+
result = await options.executeTool(
|
|
61
|
+
options.taskOutputToolName,
|
|
62
|
+
{
|
|
63
|
+
...(id.startsWith("st_") ? { task_id: id } : { name: id }),
|
|
64
|
+
mode,
|
|
65
|
+
block: true,
|
|
66
|
+
},
|
|
67
|
+
options.signal === undefined ? undefined : { signal: options.signal },
|
|
68
|
+
);
|
|
69
|
+
} catch (error) {
|
|
70
|
+
if (isUnavailableToolError(error)) throw new OutputUnavailableError(options.taskOutputToolName);
|
|
71
|
+
throw error;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// ADAPTATION: task_output owns transcripts, so no AgentOutputManager cache or
|
|
75
|
+
// oh-my-pi query/json/stripped formats exist on this bridge.
|
|
76
|
+
const transcript = options.marshalToolResult(result).text;
|
|
77
|
+
const lines = transcript.split(/\r?\n/u);
|
|
78
|
+
const start = (parsed.offset ?? 1) - 1;
|
|
79
|
+
return lines.slice(start, parsed.limit === undefined ? undefined : start + parsed.limit).join("\n");
|
|
80
|
+
}),
|
|
81
|
+
);
|
|
82
|
+
return transcripts.length === 1 ? transcripts[0] : transcripts;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function parseOutputArgs(value: unknown): OutputArgs {
|
|
86
|
+
if (Check(outputArgsSchema, value)) return value;
|
|
87
|
+
const summary = Errors(outputArgsSchema, value)
|
|
88
|
+
.map((error) => `${error.instancePath || "/"} ${error.message}`)
|
|
89
|
+
.join("; ");
|
|
90
|
+
throw new OutputArgumentsError(summary || "invalid value");
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function isUnavailableToolError(error: unknown): boolean {
|
|
94
|
+
if (typeof error !== "object" || error === null || Array.isArray(error)) return false;
|
|
95
|
+
return "code" in error && (error.code === "unknown_tool" || error.code === "inactive_tool");
|
|
96
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { ExtensionContext } from "@code-yeongyu/senpi";
|
|
2
2
|
import type { Api, AssistantMessage, Context, Model, SimpleStreamOptions } from "@earendil-works/pi-ai/compat";
|
|
3
3
|
import { completeSimple } from "@earendil-works/pi-ai/compat";
|
|
4
|
+
import { injectSchemaInstruction } from "../bridges/schema-injection.ts";
|
|
4
5
|
|
|
5
6
|
export interface CompletionRequest {
|
|
6
7
|
readonly prompt: string;
|
|
@@ -20,19 +21,27 @@ export type CompleteSimple = (
|
|
|
20
21
|
options?: SimpleStreamOptions,
|
|
21
22
|
) => Promise<AssistantMessage>;
|
|
22
23
|
|
|
23
|
-
|
|
24
|
+
type CompletionDetails = {
|
|
24
25
|
readonly model: string;
|
|
25
26
|
readonly structured: boolean;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
type CompletionTier = "smol" | "default" | "slow";
|
|
30
|
+
|
|
31
|
+
class CompletionUnknownTierError extends Error {
|
|
32
|
+
readonly name = "CompletionUnknownTierError";
|
|
33
|
+
|
|
34
|
+
constructor(tier: string) {
|
|
35
|
+
super(`completion() could not resolve the "${tier}" model tier; expected "smol", "default", or "slow".`);
|
|
36
|
+
}
|
|
26
37
|
}
|
|
27
38
|
|
|
28
|
-
|
|
29
|
-
readonly
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
readonly upstreamModelId?: string;
|
|
35
|
-
readonly error?: string;
|
|
39
|
+
class CompletionTierUnavailableError extends Error {
|
|
40
|
+
readonly name = "CompletionTierUnavailableError";
|
|
41
|
+
|
|
42
|
+
constructor(tier: Exclude<CompletionTier, "default">) {
|
|
43
|
+
super(`completion() could not resolve the "${tier}" model tier: no configured models are available.`);
|
|
44
|
+
}
|
|
36
45
|
}
|
|
37
46
|
|
|
38
47
|
export function createCompletionHandler(
|
|
@@ -46,16 +55,20 @@ async function runCompletion(
|
|
|
46
55
|
request: CompletionRequest,
|
|
47
56
|
complete: CompleteSimple,
|
|
48
57
|
): Promise<CompletionResult> {
|
|
49
|
-
const
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
58
|
+
const tier = resolveCompletionTier(request.model);
|
|
59
|
+
const model = resolveRequestedModel(ctx, tier);
|
|
60
|
+
if (!model) throw unavailableModelError(tier);
|
|
61
|
+
const auth = await ctx.modelRegistry.getApiKeyAndHeaders(model);
|
|
62
|
+
if (!auth.ok) throw noModelCredentialsError(auth.error);
|
|
63
|
+
if (!auth.apiKey) throw noModelCredentialsError();
|
|
53
64
|
const requestModel = auth.upstreamModelId ? { ...model, id: auth.upstreamModelId } : model;
|
|
65
|
+
const structured = request.schema !== undefined;
|
|
66
|
+
const prompt = structured ? injectSchemaInstruction(request.prompt, request.schema) : request.prompt;
|
|
54
67
|
const message = await complete(
|
|
55
68
|
requestModel,
|
|
56
69
|
{
|
|
57
70
|
systemPrompt: request.system ?? "You are a helpful assistant.",
|
|
58
|
-
messages: [{ role: "user", content: [{ type: "text", text:
|
|
71
|
+
messages: [{ role: "user", content: [{ type: "text", text: prompt }], timestamp: Date.now() }],
|
|
59
72
|
},
|
|
60
73
|
{
|
|
61
74
|
apiKey: auth.apiKey,
|
|
@@ -65,7 +78,7 @@ async function runCompletion(
|
|
|
65
78
|
signal: ctx.signal,
|
|
66
79
|
},
|
|
67
80
|
);
|
|
68
|
-
return formatCompletion(message, model,
|
|
81
|
+
return formatCompletion(message, model, structured);
|
|
69
82
|
}
|
|
70
83
|
|
|
71
84
|
function normalizeRequest(request: CompletionRequest): CompletionRequest {
|
|
@@ -78,25 +91,77 @@ function normalizeRequest(request: CompletionRequest): CompletionRequest {
|
|
|
78
91
|
};
|
|
79
92
|
}
|
|
80
93
|
|
|
81
|
-
function
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
94
|
+
function resolveCompletionTier(requested: string | undefined): CompletionTier {
|
|
95
|
+
switch (requested) {
|
|
96
|
+
case undefined:
|
|
97
|
+
case "default":
|
|
98
|
+
return "default";
|
|
99
|
+
case "smol":
|
|
100
|
+
return "smol";
|
|
101
|
+
case "slow":
|
|
102
|
+
return "slow";
|
|
103
|
+
default:
|
|
104
|
+
throw new CompletionUnknownTierError(requested);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function resolveRequestedModel(ctx: ExtensionContext, tier: CompletionTier): Model<Api> | undefined {
|
|
109
|
+
switch (tier) {
|
|
110
|
+
case "default":
|
|
111
|
+
return ctx.model;
|
|
112
|
+
case "smol":
|
|
113
|
+
return lowestCostModel(ctx.modelRegistry.getAvailable());
|
|
114
|
+
case "slow":
|
|
115
|
+
return highestCostModel(ctx.modelRegistry.getAvailable());
|
|
116
|
+
default:
|
|
117
|
+
return assertNever(tier);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function unavailableModelError(tier: CompletionTier): Error {
|
|
122
|
+
switch (tier) {
|
|
123
|
+
case "default":
|
|
124
|
+
return noModelCredentialsError();
|
|
125
|
+
case "smol":
|
|
126
|
+
case "slow":
|
|
127
|
+
return new CompletionTierUnavailableError(tier);
|
|
128
|
+
default:
|
|
129
|
+
return assertNever(tier);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
function lowestCostModel(models: readonly Model<Api>[]): Model<Api> | undefined {
|
|
134
|
+
let selected: Model<Api> | undefined;
|
|
135
|
+
for (const model of models) {
|
|
136
|
+
if (selected === undefined || promptAndResponseCost(model) < promptAndResponseCost(selected)) selected = model;
|
|
85
137
|
}
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
138
|
+
return selected;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
function highestCostModel(models: readonly Model<Api>[]): Model<Api> | undefined {
|
|
142
|
+
let selected: Model<Api> | undefined;
|
|
143
|
+
for (const model of models) {
|
|
144
|
+
if (selected === undefined || promptAndResponseCost(model) > promptAndResponseCost(selected)) selected = model;
|
|
145
|
+
}
|
|
146
|
+
return selected;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
function promptAndResponseCost(model: Model<Api>): number {
|
|
150
|
+
return model.cost.input + model.cost.output;
|
|
89
151
|
}
|
|
90
152
|
|
|
91
153
|
function formatCompletion(message: AssistantMessage, model: Model<Api>, structured: boolean): CompletionResult {
|
|
92
154
|
if (message.stopReason === "error") throw new Error(message.errorMessage ?? "completion() request failed.");
|
|
93
155
|
if (message.stopReason === "aborted") throw new Error("completion() request aborted.");
|
|
94
156
|
const text = extractText(message);
|
|
95
|
-
|
|
157
|
+
const details = { model: formatModel(model), structured };
|
|
158
|
+
if (!structured) return { text, details };
|
|
96
159
|
try {
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
160
|
+
const value: unknown = JSON.parse(text);
|
|
161
|
+
return { value, details };
|
|
162
|
+
} catch (error) {
|
|
163
|
+
if (error instanceof SyntaxError) return { value: { parseError: error.message }, details };
|
|
164
|
+
throw error;
|
|
100
165
|
}
|
|
101
166
|
}
|
|
102
167
|
|
|
@@ -121,3 +186,7 @@ function formatModel(model: Model<Api>): string {
|
|
|
121
186
|
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
122
187
|
return typeof value === "object" && value !== null;
|
|
123
188
|
}
|
|
189
|
+
|
|
190
|
+
function assertNever(value: never): never {
|
|
191
|
+
throw new CompletionUnknownTierError(String(value));
|
|
192
|
+
}
|
|
@@ -15,9 +15,14 @@ export type CompletionToolCallSummary = { readonly ok: true } | { readonly ok: f
|
|
|
15
15
|
|
|
16
16
|
export async function handleCompletionToolCall(options: CompletionToolCallOptions): Promise<CompletionToolCallSummary> {
|
|
17
17
|
try {
|
|
18
|
-
const
|
|
18
|
+
const result = await options.complete(toCompletionRequest(options.message.args), options.ctx);
|
|
19
19
|
if (!options.isActive()) return { ok: false, error: "completion() result ignored after eval finalization" };
|
|
20
|
-
options.kernel.deliverToolReply({
|
|
20
|
+
options.kernel.deliverToolReply({
|
|
21
|
+
type: "tool-reply",
|
|
22
|
+
callId: options.message.callId,
|
|
23
|
+
ok: true,
|
|
24
|
+
value: completionReplyValue(result),
|
|
25
|
+
});
|
|
21
26
|
return { ok: true };
|
|
22
27
|
} catch (error) {
|
|
23
28
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -44,3 +49,7 @@ function toCompletionRequest(value: unknown): CompletionRequest {
|
|
|
44
49
|
}
|
|
45
50
|
throw new Error("completion() received invalid arguments");
|
|
46
51
|
}
|
|
52
|
+
|
|
53
|
+
function completionReplyValue(result: CompletionResult): unknown {
|
|
54
|
+
return "value" in result ? result.value : result.text;
|
|
55
|
+
}
|
|
@@ -20,12 +20,41 @@ export const codemodeSettingsSchema = Type.Object(
|
|
|
20
20
|
),
|
|
21
21
|
cellTimeoutSeconds: Type.Optional(Type.Number({ minimum: 1 })),
|
|
22
22
|
parallelPoolWidth: Type.Optional(Type.Number({ minimum: 1 })),
|
|
23
|
+
taskTools: Type.Optional(
|
|
24
|
+
Type.Object(
|
|
25
|
+
{
|
|
26
|
+
task: Type.Optional(Type.String()),
|
|
27
|
+
output: Type.Optional(Type.String()),
|
|
28
|
+
},
|
|
29
|
+
{ additionalProperties: false },
|
|
30
|
+
),
|
|
31
|
+
),
|
|
32
|
+
outputSink: Type.Optional(
|
|
33
|
+
Type.Object(
|
|
34
|
+
{
|
|
35
|
+
headBytes: Type.Optional(Type.Number({ minimum: 0 })),
|
|
36
|
+
maxColumns: Type.Optional(Type.Number({ minimum: 0 })),
|
|
37
|
+
},
|
|
38
|
+
{ additionalProperties: false },
|
|
39
|
+
),
|
|
40
|
+
),
|
|
41
|
+
statusEvents: Type.Optional(Type.Boolean()),
|
|
23
42
|
},
|
|
24
43
|
{ additionalProperties: false },
|
|
25
44
|
);
|
|
26
45
|
|
|
27
46
|
export type CodemodeSettingsInput = Static<typeof codemodeSettingsSchema>;
|
|
28
47
|
|
|
48
|
+
export interface CodemodeTaskTools {
|
|
49
|
+
readonly task: string;
|
|
50
|
+
readonly output: string;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export interface CodemodeOutputSink {
|
|
54
|
+
readonly headBytes: number;
|
|
55
|
+
readonly maxColumns: number;
|
|
56
|
+
}
|
|
57
|
+
|
|
29
58
|
export interface CodemodeSettings {
|
|
30
59
|
readonly languages: {
|
|
31
60
|
readonly py: boolean;
|
|
@@ -35,22 +64,31 @@ export interface CodemodeSettings {
|
|
|
35
64
|
};
|
|
36
65
|
readonly cellTimeoutSeconds: number;
|
|
37
66
|
readonly parallelPoolWidth: number;
|
|
67
|
+
readonly taskTools?: CodemodeTaskTools;
|
|
68
|
+
readonly outputSink?: CodemodeOutputSink;
|
|
69
|
+
readonly statusEvents?: boolean;
|
|
38
70
|
}
|
|
39
71
|
|
|
72
|
+
export type ResolvedCodemodeSettings = CodemodeSettings & {
|
|
73
|
+
readonly taskTools: CodemodeTaskTools;
|
|
74
|
+
readonly outputSink: CodemodeOutputSink;
|
|
75
|
+
readonly statusEvents: boolean;
|
|
76
|
+
};
|
|
77
|
+
|
|
40
78
|
export interface LoadCodemodeSettingsOptions {
|
|
41
79
|
readonly cwd?: string;
|
|
42
80
|
readonly homeDir?: string;
|
|
43
81
|
}
|
|
44
82
|
|
|
45
83
|
export interface LoadedCodemodeSettings {
|
|
46
|
-
readonly settings:
|
|
84
|
+
readonly settings: ResolvedCodemodeSettings;
|
|
47
85
|
readonly source: string | null;
|
|
48
86
|
readonly warnings: readonly string[];
|
|
49
87
|
}
|
|
50
88
|
|
|
51
89
|
// OMP settings-schema.ts:3211-3299 has language/path settings only; eval.ts:427
|
|
52
90
|
// defaults timeout to 30s, and codemode pins concurrency-bridge.ts:30 width to 4.
|
|
53
|
-
export const defaultCodemodeSettings:
|
|
91
|
+
export const defaultCodemodeSettings: ResolvedCodemodeSettings = {
|
|
54
92
|
languages: {
|
|
55
93
|
py: true,
|
|
56
94
|
js: true,
|
|
@@ -59,8 +97,26 @@ export const defaultCodemodeSettings: CodemodeSettings = {
|
|
|
59
97
|
},
|
|
60
98
|
cellTimeoutSeconds: 30,
|
|
61
99
|
parallelPoolWidth: 4,
|
|
100
|
+
taskTools: {
|
|
101
|
+
task: "task",
|
|
102
|
+
output: "task_output",
|
|
103
|
+
},
|
|
104
|
+
outputSink: {
|
|
105
|
+
headBytes: 20_480,
|
|
106
|
+
maxColumns: 768,
|
|
107
|
+
},
|
|
108
|
+
statusEvents: true,
|
|
62
109
|
};
|
|
63
110
|
|
|
111
|
+
const languageEnvironmentFlags = {
|
|
112
|
+
py: "SENPI_CODEMODE_PY",
|
|
113
|
+
js: "SENPI_CODEMODE_JS",
|
|
114
|
+
rb: "SENPI_CODEMODE_RB",
|
|
115
|
+
jl: "SENPI_CODEMODE_JL",
|
|
116
|
+
} as const;
|
|
117
|
+
|
|
118
|
+
type Environment = Readonly<Record<string, string | undefined>>;
|
|
119
|
+
|
|
64
120
|
export async function loadCodemodeSettings(options: LoadCodemodeSettingsOptions = {}): Promise<LoadedCodemodeSettings> {
|
|
65
121
|
const cwd = options.cwd ?? process.cwd();
|
|
66
122
|
const homeDir = options.homeDir ?? homedir();
|
|
@@ -76,16 +132,29 @@ export async function loadCodemodeSettings(options: LoadCodemodeSettingsOptions
|
|
|
76
132
|
return { settings: defaultCodemodeSettings, source: null, warnings: [] };
|
|
77
133
|
}
|
|
78
134
|
|
|
135
|
+
export function resolveEnabledLanguages(
|
|
136
|
+
settings: CodemodeSettings,
|
|
137
|
+
env: Environment = process.env,
|
|
138
|
+
): CodemodeSettings["languages"] {
|
|
139
|
+
return {
|
|
140
|
+
py: resolveLanguage(settings.languages.py, env[languageEnvironmentFlags.py]),
|
|
141
|
+
js: resolveLanguage(settings.languages.js, env[languageEnvironmentFlags.js]),
|
|
142
|
+
rb: resolveLanguage(settings.languages.rb, env[languageEnvironmentFlags.rb]),
|
|
143
|
+
jl: resolveLanguage(settings.languages.jl, env[languageEnvironmentFlags.jl]),
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
|
|
79
147
|
async function loadSettingsFile(path: string): Promise<LoadedCodemodeSettings> {
|
|
80
148
|
const raw = await readFile(path, "utf8");
|
|
81
149
|
let parsed: unknown;
|
|
82
150
|
try {
|
|
83
151
|
parsed = JSON.parse(raw);
|
|
84
152
|
} catch (error) {
|
|
153
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
85
154
|
return {
|
|
86
155
|
settings: defaultCodemodeSettings,
|
|
87
156
|
source: path,
|
|
88
|
-
warnings: [`Invalid JSON in ${path}: ${
|
|
157
|
+
warnings: [`Invalid JSON in ${path}: ${message}. Falling back to codemode defaults.`],
|
|
89
158
|
};
|
|
90
159
|
}
|
|
91
160
|
|
|
@@ -100,7 +169,7 @@ async function loadSettingsFile(path: string): Promise<LoadedCodemodeSettings> {
|
|
|
100
169
|
return { settings: mergeSettings(parsed), source: path, warnings: [] };
|
|
101
170
|
}
|
|
102
171
|
|
|
103
|
-
function mergeSettings(input: CodemodeSettingsInput):
|
|
172
|
+
function mergeSettings(input: CodemodeSettingsInput): ResolvedCodemodeSettings {
|
|
104
173
|
return {
|
|
105
174
|
languages: {
|
|
106
175
|
py: input.languages?.py ?? defaultCodemodeSettings.languages.py,
|
|
@@ -110,9 +179,32 @@ function mergeSettings(input: CodemodeSettingsInput): CodemodeSettings {
|
|
|
110
179
|
},
|
|
111
180
|
cellTimeoutSeconds: input.cellTimeoutSeconds ?? defaultCodemodeSettings.cellTimeoutSeconds,
|
|
112
181
|
parallelPoolWidth: input.parallelPoolWidth ?? defaultCodemodeSettings.parallelPoolWidth,
|
|
182
|
+
taskTools: {
|
|
183
|
+
task: input.taskTools?.task ?? defaultCodemodeSettings.taskTools.task,
|
|
184
|
+
output: input.taskTools?.output ?? defaultCodemodeSettings.taskTools.output,
|
|
185
|
+
},
|
|
186
|
+
outputSink: {
|
|
187
|
+
headBytes: input.outputSink?.headBytes ?? defaultCodemodeSettings.outputSink.headBytes,
|
|
188
|
+
maxColumns: input.outputSink?.maxColumns ?? defaultCodemodeSettings.outputSink.maxColumns,
|
|
189
|
+
},
|
|
190
|
+
statusEvents: input.statusEvents ?? defaultCodemodeSettings.statusEvents,
|
|
113
191
|
};
|
|
114
192
|
}
|
|
115
193
|
|
|
194
|
+
function resolveLanguage(fileSetting: boolean, environmentValue: string | undefined): boolean {
|
|
195
|
+
if (environmentValue === undefined) return fileSetting;
|
|
196
|
+
switch (environmentValue.trim().toLowerCase()) {
|
|
197
|
+
case "0":
|
|
198
|
+
case "false":
|
|
199
|
+
return false;
|
|
200
|
+
case "1":
|
|
201
|
+
case "true":
|
|
202
|
+
return true;
|
|
203
|
+
default:
|
|
204
|
+
return fileSetting;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
116
208
|
async function fileExists(path: string): Promise<boolean> {
|
|
117
209
|
try {
|
|
118
210
|
await access(path);
|
|
@@ -121,7 +213,3 @@ async function fileExists(path: string): Promise<boolean> {
|
|
|
121
213
|
return false;
|
|
122
214
|
}
|
|
123
215
|
}
|
|
124
|
-
|
|
125
|
-
function errorMessage(error: unknown): string {
|
|
126
|
-
return error instanceof Error ? error.message : String(error);
|
|
127
|
-
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { join } from "node:path";
|
|
1
2
|
import type { ExtensionContext } from "@code-yeongyu/senpi";
|
|
2
3
|
import { type BridgeServerHandle, startBridgeServer } from "../bridge/http-server.ts";
|
|
3
4
|
import type { KernelToHostMessage } from "../bridge/protocol.ts";
|
|
@@ -16,11 +17,20 @@ export interface CodemodeSessionManager extends EvalKernelManager {
|
|
|
16
17
|
setContext?(ctx: ExtensionContext): void;
|
|
17
18
|
}
|
|
18
19
|
|
|
20
|
+
export interface EvalExecutionTracker {
|
|
21
|
+
assertEvalExecutionAllowed(): void;
|
|
22
|
+
trackEvalExecution<Result>(execution: Promise<Result>, controller: AbortController): Promise<Result>;
|
|
23
|
+
}
|
|
24
|
+
|
|
19
25
|
export interface CreateCodemodeSessionManagerOptions {
|
|
20
26
|
readonly sessionId: string;
|
|
21
27
|
readonly cwd: string;
|
|
22
28
|
readonly settings: CodemodeSettings;
|
|
23
29
|
readonly availability: InterpreterAvailability;
|
|
30
|
+
/** Session-scoped roots exposed to kernel helpers such as local://. */
|
|
31
|
+
readonly localRoots?: Readonly<Record<string, string>>;
|
|
32
|
+
/** Session-adjacent directory used for persisted eval artifacts. */
|
|
33
|
+
readonly artifactsDir?: string;
|
|
24
34
|
readonly executeTool: ExecuteTool;
|
|
25
35
|
readonly complete: (request: CompletionRequest, ctx: ExtensionContext) => Promise<CompletionResult>;
|
|
26
36
|
}
|
|
@@ -33,7 +43,7 @@ export async function createCodemodeSessionManager(
|
|
|
33
43
|
return manager;
|
|
34
44
|
}
|
|
35
45
|
|
|
36
|
-
class CodemodeSessionDisposedError extends Error {
|
|
46
|
+
export class CodemodeSessionDisposedError extends Error {
|
|
37
47
|
readonly name = "CodemodeSessionDisposedError";
|
|
38
48
|
|
|
39
49
|
constructor() {
|
|
@@ -148,17 +158,28 @@ class DefaultCodemodeSessionManager implements CodemodeSessionManager {
|
|
|
148
158
|
async #createKernel(language: EvalLanguage, onMessage: (message: KernelToHostMessage) => void): Promise<EvalKernel> {
|
|
149
159
|
const bridge = this.#bridge;
|
|
150
160
|
if (!bridge) throw new Error("codemode bridge server is not running");
|
|
161
|
+
const configuredPoolWidth = this.#options.settings.parallelPoolWidth;
|
|
162
|
+
const parallelPoolWidth = Number.isFinite(configuredPoolWidth) ? Math.max(1, Math.trunc(configuredPoolWidth)) : 1;
|
|
151
163
|
if (language === "js") {
|
|
152
164
|
return new JavaScriptKernel({
|
|
153
165
|
sessionId: this.#options.sessionId,
|
|
154
166
|
cwd: this.#options.cwd,
|
|
155
|
-
parallelPoolWidth
|
|
167
|
+
parallelPoolWidth,
|
|
156
168
|
onMessage,
|
|
157
169
|
});
|
|
158
170
|
}
|
|
159
171
|
const detected = this.#options.availability[language].detected;
|
|
160
172
|
if (!detected.ok) throw new Error(`No ${language} interpreter is available`);
|
|
161
|
-
const
|
|
173
|
+
const localRoots =
|
|
174
|
+
this.#options.localRoots ??
|
|
175
|
+
(this.#options.artifactsDir ? { local: join(this.#options.artifactsDir, "local") } : undefined);
|
|
176
|
+
const connection = {
|
|
177
|
+
port: bridge.port,
|
|
178
|
+
token: bridge.token,
|
|
179
|
+
parallelPoolWidth,
|
|
180
|
+
...(localRoots ? { localRoots: { ...localRoots } } : {}),
|
|
181
|
+
...(this.#options.artifactsDir ? { artifactsDir: this.#options.artifactsDir } : {}),
|
|
182
|
+
};
|
|
162
183
|
if (language === "py") {
|
|
163
184
|
return await PythonKernel.start({
|
|
164
185
|
interpreterPath: detected.path,
|