@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,296 @@
|
|
|
1
|
+
import { createWriteStream, mkdirSync, type WriteStream } from "node:fs";
|
|
2
|
+
import { dirname } from "node:path";
|
|
3
|
+
import { DEFAULT_MAX_BYTES, DEFAULT_MAX_LINES, truncateTail } from "../host-sdk.ts";
|
|
4
|
+
import { formatMiddleElisionMarker } from "./output-meta.ts";
|
|
5
|
+
|
|
6
|
+
export { artifactNotice, formatMiddleElisionMarker, resolveSessionArtifactsDir } from "./output-meta.ts";
|
|
7
|
+
export { DEFAULT_MAX_BYTES, DEFAULT_MAX_LINES, truncateTail };
|
|
8
|
+
|
|
9
|
+
export const ARTIFACT_DEFAULT_HEAD_BYTES = 3 * 1024 * 1024;
|
|
10
|
+
|
|
11
|
+
export interface OutputSummary {
|
|
12
|
+
readonly output: string;
|
|
13
|
+
readonly truncated: boolean;
|
|
14
|
+
readonly totalLines: number;
|
|
15
|
+
readonly totalBytes: number;
|
|
16
|
+
readonly outputLines: number;
|
|
17
|
+
readonly outputBytes: number;
|
|
18
|
+
readonly elidedBytes?: number;
|
|
19
|
+
readonly elidedLines?: number;
|
|
20
|
+
readonly columnDroppedBytes?: number;
|
|
21
|
+
readonly columnTruncatedLines?: number;
|
|
22
|
+
readonly artifactId?: string;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface OutputSinkOptions {
|
|
26
|
+
readonly artifactPath?: string;
|
|
27
|
+
readonly spillThreshold?: number;
|
|
28
|
+
readonly headBytes?: number;
|
|
29
|
+
readonly maxColumns?: number;
|
|
30
|
+
readonly onChunk?: (chunk: string) => void;
|
|
31
|
+
readonly chunkThrottleMs?: number;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
interface ByteSlice {
|
|
35
|
+
readonly text: string;
|
|
36
|
+
readonly bytes: number;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function countNewlines(text: string): number {
|
|
40
|
+
let count = 0;
|
|
41
|
+
let cursor = text.indexOf("\n");
|
|
42
|
+
while (cursor !== -1) {
|
|
43
|
+
count++;
|
|
44
|
+
cursor = text.indexOf("\n", cursor + 1);
|
|
45
|
+
}
|
|
46
|
+
return count;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function lineCount(text: string): number {
|
|
50
|
+
return text.length === 0 ? 0 : countNewlines(text) + 1;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function truncateHeadBytes(text: string, maxBytes: number): ByteSlice {
|
|
54
|
+
if (maxBytes <= 0) return { text: "", bytes: 0 };
|
|
55
|
+
const buffer = Buffer.from(text, "utf8");
|
|
56
|
+
if (buffer.length <= maxBytes) return { text, bytes: buffer.length };
|
|
57
|
+
let end = maxBytes;
|
|
58
|
+
while (end > 0 && (buffer[end] & 0xc0) === 0x80) end--;
|
|
59
|
+
const slice = buffer.subarray(0, end);
|
|
60
|
+
return { text: slice.toString("utf8"), bytes: slice.length };
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function truncateTailBytes(text: string, maxBytes: number): ByteSlice {
|
|
64
|
+
if (maxBytes <= 0) return { text: "", bytes: 0 };
|
|
65
|
+
const buffer = Buffer.from(text, "utf8");
|
|
66
|
+
if (buffer.length <= maxBytes) return { text, bytes: buffer.length };
|
|
67
|
+
let start = buffer.length - maxBytes;
|
|
68
|
+
while (start < buffer.length && (buffer[start] & 0xc0) === 0x80) start++;
|
|
69
|
+
const slice = buffer.subarray(start);
|
|
70
|
+
return { text: slice.toString("utf8"), bytes: slice.length };
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export class TailBuffer {
|
|
74
|
+
readonly #maxBytes: number;
|
|
75
|
+
#text = "";
|
|
76
|
+
#bytes = 0;
|
|
77
|
+
|
|
78
|
+
constructor(maxBytes: number) {
|
|
79
|
+
this.#maxBytes = Math.max(0, Math.floor(maxBytes));
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
append(text: string): void {
|
|
83
|
+
if (text.length === 0) return;
|
|
84
|
+
if (this.#maxBytes === 0) {
|
|
85
|
+
this.#text = "";
|
|
86
|
+
this.#bytes = 0;
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
const incomingBytes = Buffer.byteLength(text, "utf8");
|
|
90
|
+
const next =
|
|
91
|
+
incomingBytes >= this.#maxBytes
|
|
92
|
+
? truncateTailBytes(text, this.#maxBytes)
|
|
93
|
+
: truncateTailBytes(this.#text + text, this.#maxBytes);
|
|
94
|
+
this.#text = next.text;
|
|
95
|
+
this.#bytes = next.bytes;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
text(): string {
|
|
99
|
+
return this.#text;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
bytes(): number {
|
|
103
|
+
return this.#bytes;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export class OutputSink {
|
|
108
|
+
readonly #artifactPath: string | undefined;
|
|
109
|
+
readonly #spillThreshold: number;
|
|
110
|
+
readonly #headLimit: number;
|
|
111
|
+
readonly #maxColumns: number;
|
|
112
|
+
readonly #onChunk: ((chunk: string) => void) | undefined;
|
|
113
|
+
readonly #chunkThrottleMs: number;
|
|
114
|
+
readonly #tail: TailBuffer;
|
|
115
|
+
#head = "";
|
|
116
|
+
#headBytes = 0;
|
|
117
|
+
#totalNewlines = 0;
|
|
118
|
+
#totalBytes = 0;
|
|
119
|
+
#sawData = false;
|
|
120
|
+
#truncated = false;
|
|
121
|
+
#currentLineBytes = 0;
|
|
122
|
+
#columnCapped = false;
|
|
123
|
+
#columnDroppedBytes = 0;
|
|
124
|
+
#columnTruncatedLines = 0;
|
|
125
|
+
#lastChunkTime = 0;
|
|
126
|
+
#pendingChunk = "";
|
|
127
|
+
#beforeSpill = "";
|
|
128
|
+
#file: WriteStream | undefined;
|
|
129
|
+
#fileError: Error | undefined;
|
|
130
|
+
#dumpPromise: Promise<OutputSummary> | undefined;
|
|
131
|
+
|
|
132
|
+
constructor(options: OutputSinkOptions = {}) {
|
|
133
|
+
this.#artifactPath = options.artifactPath;
|
|
134
|
+
this.#spillThreshold = Math.max(0, Math.floor(options.spillThreshold ?? DEFAULT_MAX_BYTES));
|
|
135
|
+
this.#headLimit = Math.max(0, Math.floor(options.headBytes ?? 0));
|
|
136
|
+
this.#maxColumns = Math.max(0, Math.floor(options.maxColumns ?? 0));
|
|
137
|
+
this.#onChunk = options.onChunk;
|
|
138
|
+
this.#chunkThrottleMs = Math.max(0, Math.floor(options.chunkThrottleMs ?? 0));
|
|
139
|
+
this.#tail = new TailBuffer(this.#spillThreshold);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
push(chunk: string): void {
|
|
143
|
+
if (chunk.length === 0) return;
|
|
144
|
+
this.#emitPreview(chunk);
|
|
145
|
+
const rawBytes = Buffer.byteLength(chunk, "utf8");
|
|
146
|
+
this.#totalBytes += rawBytes;
|
|
147
|
+
this.#totalNewlines += countNewlines(chunk);
|
|
148
|
+
this.#sawData = true;
|
|
149
|
+
this.#mirrorRaw(chunk);
|
|
150
|
+
this.#retain(this.#maxColumns > 0 ? this.#clampColumns(chunk) : chunk);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
dump(notice?: string): Promise<OutputSummary> {
|
|
154
|
+
this.#dumpPromise ??= this.#finishDump(notice);
|
|
155
|
+
return this.#dumpPromise;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
#emitPreview(chunk: string): void {
|
|
159
|
+
if (this.#onChunk === undefined) return;
|
|
160
|
+
const now = Date.now();
|
|
161
|
+
if (now - this.#lastChunkTime >= this.#chunkThrottleMs) {
|
|
162
|
+
this.#lastChunkTime = now;
|
|
163
|
+
this.#onChunk(this.#pendingChunk + chunk);
|
|
164
|
+
this.#pendingChunk = "";
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
this.#pendingChunk += chunk;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
#mirrorRaw(chunk: string): void {
|
|
171
|
+
if (this.#artifactPath === undefined) return;
|
|
172
|
+
if (this.#file !== undefined) {
|
|
173
|
+
this.#file.write(chunk);
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
if (this.#totalBytes <= this.#spillThreshold) {
|
|
177
|
+
this.#beforeSpill += chunk;
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
mkdirSync(dirname(this.#artifactPath), { recursive: true });
|
|
181
|
+
const stream = createWriteStream(this.#artifactPath, { encoding: "utf8" });
|
|
182
|
+
stream.on("error", (error) => {
|
|
183
|
+
this.#fileError = error;
|
|
184
|
+
});
|
|
185
|
+
this.#file = stream;
|
|
186
|
+
if (this.#beforeSpill.length > 0) stream.write(this.#beforeSpill);
|
|
187
|
+
this.#beforeSpill = "";
|
|
188
|
+
stream.write(chunk);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
#retain(text: string): void {
|
|
192
|
+
let tailText = text;
|
|
193
|
+
if (this.#headBytes < this.#headLimit) {
|
|
194
|
+
const head = truncateHeadBytes(text, this.#headLimit - this.#headBytes);
|
|
195
|
+
this.#head += head.text;
|
|
196
|
+
this.#headBytes += head.bytes;
|
|
197
|
+
tailText = text.substring(head.text.length);
|
|
198
|
+
}
|
|
199
|
+
this.#tail.append(tailText);
|
|
200
|
+
const effectiveBytes = this.#totalBytes - this.#columnDroppedBytes;
|
|
201
|
+
if (effectiveBytes > this.#headBytes + this.#tail.bytes()) this.#truncated = true;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
#clampColumns(chunk: string): string {
|
|
205
|
+
const output: string[] = [];
|
|
206
|
+
let cursor = 0;
|
|
207
|
+
while (cursor < chunk.length) {
|
|
208
|
+
const newline = chunk.indexOf("\n", cursor);
|
|
209
|
+
const end = newline === -1 ? chunk.length : newline;
|
|
210
|
+
const segment = chunk.substring(cursor, end);
|
|
211
|
+
if (segment.length > 0) {
|
|
212
|
+
const segmentBytes = Buffer.byteLength(segment, "utf8");
|
|
213
|
+
if (this.#columnCapped) {
|
|
214
|
+
this.#columnDroppedBytes += segmentBytes;
|
|
215
|
+
} else {
|
|
216
|
+
const remaining = Math.max(0, this.#maxColumns - this.#currentLineBytes);
|
|
217
|
+
const kept = truncateHeadBytes(segment, remaining);
|
|
218
|
+
output.push(kept.text);
|
|
219
|
+
this.#currentLineBytes += kept.bytes;
|
|
220
|
+
if (kept.bytes < segmentBytes) {
|
|
221
|
+
output.push("…");
|
|
222
|
+
this.#columnDroppedBytes += segmentBytes - kept.bytes;
|
|
223
|
+
this.#columnTruncatedLines++;
|
|
224
|
+
this.#columnCapped = true;
|
|
225
|
+
this.#truncated = true;
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
if (newline === -1) break;
|
|
230
|
+
output.push("\n");
|
|
231
|
+
this.#currentLineBytes = 0;
|
|
232
|
+
this.#columnCapped = false;
|
|
233
|
+
cursor = newline + 1;
|
|
234
|
+
}
|
|
235
|
+
return output.join("");
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
async #finishDump(notice: string | undefined): Promise<OutputSummary> {
|
|
239
|
+
if (this.#onChunk !== undefined && this.#pendingChunk.length > 0) {
|
|
240
|
+
this.#onChunk(this.#pendingChunk);
|
|
241
|
+
this.#pendingChunk = "";
|
|
242
|
+
}
|
|
243
|
+
await this.#closeFile();
|
|
244
|
+
let tail = this.#tail.text();
|
|
245
|
+
if (lineCount(tail) > DEFAULT_MAX_LINES) {
|
|
246
|
+
tail = truncateTail(tail, { maxLines: DEFAULT_MAX_LINES, maxBytes: Number.MAX_SAFE_INTEGER }).content;
|
|
247
|
+
this.#truncated = true;
|
|
248
|
+
}
|
|
249
|
+
const totalLines = this.#sawData ? this.#totalNewlines + 1 : 0;
|
|
250
|
+
const tailBytes = Buffer.byteLength(tail, "utf8");
|
|
251
|
+
const effectiveBytes = Math.max(0, this.#totalBytes - this.#columnDroppedBytes);
|
|
252
|
+
let body = this.#head + tail;
|
|
253
|
+
let elidedBytes: number | undefined;
|
|
254
|
+
let elidedLines: number | undefined;
|
|
255
|
+
if (this.#headBytes > 0 && effectiveBytes > this.#headBytes + tailBytes) {
|
|
256
|
+
elidedBytes = effectiveBytes - this.#headBytes - tailBytes;
|
|
257
|
+
elidedLines = Math.max(0, totalLines - lineCount(this.#head) - lineCount(tail));
|
|
258
|
+
const headSeparator = this.#head.endsWith("\n") ? "" : "\n";
|
|
259
|
+
const tailSeparator = tail.length === 0 || tail.startsWith("\n") ? "" : "\n";
|
|
260
|
+
body = `${this.#head}${headSeparator}${formatMiddleElisionMarker(elidedLines, elidedBytes)}${tailSeparator}${tail}`;
|
|
261
|
+
this.#truncated = true;
|
|
262
|
+
}
|
|
263
|
+
return {
|
|
264
|
+
output: notice === undefined ? body : `[${notice}]\n${body}`,
|
|
265
|
+
truncated: this.#truncated,
|
|
266
|
+
totalLines,
|
|
267
|
+
totalBytes: this.#totalBytes,
|
|
268
|
+
outputLines: lineCount(body),
|
|
269
|
+
outputBytes: Buffer.byteLength(body, "utf8"),
|
|
270
|
+
elidedBytes,
|
|
271
|
+
elidedLines,
|
|
272
|
+
columnDroppedBytes: this.#columnDroppedBytes > 0 ? this.#columnDroppedBytes : undefined,
|
|
273
|
+
columnTruncatedLines: this.#columnTruncatedLines > 0 ? this.#columnTruncatedLines : undefined,
|
|
274
|
+
artifactId: this.#file === undefined ? undefined : this.#artifactPath,
|
|
275
|
+
};
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
async #closeFile(): Promise<void> {
|
|
279
|
+
const stream = this.#file;
|
|
280
|
+
if (stream === undefined) return;
|
|
281
|
+
if (this.#fileError !== undefined) throw this.#fileError;
|
|
282
|
+
await new Promise<void>((resolve, reject) => {
|
|
283
|
+
const onError = (error: Error) => {
|
|
284
|
+
stream.off("finish", onFinish);
|
|
285
|
+
reject(error);
|
|
286
|
+
};
|
|
287
|
+
const onFinish = () => {
|
|
288
|
+
stream.off("error", onError);
|
|
289
|
+
resolve();
|
|
290
|
+
};
|
|
291
|
+
stream.once("error", onError);
|
|
292
|
+
stream.once("finish", onFinish);
|
|
293
|
+
stream.end();
|
|
294
|
+
});
|
|
295
|
+
}
|
|
296
|
+
}
|
|
@@ -11,13 +11,58 @@ export interface EvalPromptParts {
|
|
|
11
11
|
readonly promptGuidelines: readonly string[];
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
+
export interface EvalPromptOptions {
|
|
15
|
+
readonly spawns: boolean;
|
|
16
|
+
readonly spawnDefaultAgent?: string;
|
|
17
|
+
}
|
|
18
|
+
|
|
14
19
|
type ContextValue = string | boolean;
|
|
15
20
|
type Context = Readonly<Record<string, ContextValue>>;
|
|
21
|
+
type EvalPromptExample = {
|
|
22
|
+
readonly caption: string;
|
|
23
|
+
readonly language: keyof EnabledLanguages;
|
|
24
|
+
readonly title: string;
|
|
25
|
+
readonly code: string;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
// senpi ToolDefinition has no examples field, so description embeds parity examples.
|
|
29
|
+
const REUSE_CHAIN_EXAMPLES = [
|
|
30
|
+
{
|
|
31
|
+
caption: "First call — set up once",
|
|
32
|
+
language: "py",
|
|
33
|
+
title: "imports",
|
|
34
|
+
code: "import json\nfrom pathlib import Path",
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
caption: "Second call — reuse, do NOT re-import",
|
|
38
|
+
language: "py",
|
|
39
|
+
title: "load config",
|
|
40
|
+
code: "data = json.loads(read('package.json'))\ndisplay(data)",
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
caption: "Third call — reuse the loaded config",
|
|
44
|
+
language: "py",
|
|
45
|
+
title: "scan deps",
|
|
46
|
+
code: "display(sorted(data['dependencies']))",
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
caption: "Ruby first call — set up once",
|
|
50
|
+
language: "rb",
|
|
51
|
+
title: "setup",
|
|
52
|
+
code: "require 'json'\npkg_path = 'package.json'",
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
caption: "Ruby second call — reuse, do NOT re-require",
|
|
56
|
+
language: "rb",
|
|
57
|
+
title: "load config",
|
|
58
|
+
code: "pkg = JSON.parse(read(pkg_path))\ndisplay(pkg.keys.sort)",
|
|
59
|
+
},
|
|
60
|
+
] as const satisfies readonly EvalPromptExample[];
|
|
16
61
|
|
|
17
62
|
const EVAL_PROMPT_TEMPLATE = `Run one step of code in a persistent kernel.
|
|
18
63
|
|
|
19
64
|
<instruction>
|
|
20
|
-
**One eval call = one cell = one logical step.** State persists per language across separate eval calls and tool calls — define helpers, datasets, and clients in one call, then later calls reuse them directly.
|
|
65
|
+
**One eval call = one cell = one logical step.** State persists per language across separate eval calls and tool calls{{#if spawns}}, and \`task\` subagents{{/if}} — define helpers, datasets, and clients in one call, then later calls reuse them directly.
|
|
21
66
|
|
|
22
67
|
Work incrementally: imports in one call, define in the next, test, then use — each its own eval call. Re-run setup ONLY after \`reset\`, a kernel crash, or a \`NameError\`/\`ReferenceError\` proving the state is gone. Parallelize work *within* a cell with the \`parallel(thunks)\` helper, not by batching steps.
|
|
23
68
|
|
|
@@ -26,61 +71,93 @@ Fields:
|
|
|
26
71
|
- \`language\` — {{#if py}}\`"py"\` IPython kernel{{/if}}{{#ifAll py js}}, {{/ifAll}}{{#if js}}\`"js"\` persistent JavaScript VM{{/if}}{{#if rb}}{{#ifAny py js}}, {{/ifAny}}\`"rb"\` persistent Ruby kernel{{/if}}{{#if jl}}{{#ifAny py js rb}}, {{/ifAny}}\`"jl"\` persistent Julia kernel{{/if}}.
|
|
27
72
|
- \`code\` — cell body, verbatim. Newlines/quotes JSON-encoded; no fences, no headers.
|
|
28
73
|
- \`title\` (optional) — short transcript label (e.g. \`"imports"\`).
|
|
29
|
-
- \`timeout\` (optional) — seconds. Raise only for heavy compute or long
|
|
74
|
+
- \`timeout\` (optional) — seconds. Raise only for heavy compute or long{{#if spawns}} non-agent{{/if}} tool calls.
|
|
30
75
|
- \`reset\` (optional) — wipe this language's kernel first.{{#ifAll py js}} Per-language: a \`py\` reset never touches the JS VM.{{/ifAll}}
|
|
31
76
|
|
|
32
|
-
{{#if py}}Live event loop: use top-level \`await\` directly; \`asyncio.run(
|
|
77
|
+
{{#if py}}Live event loop: use top-level \`await\` directly; \`asyncio.run(…)\` raises "cannot be called from a running event loop".{{/if}}
|
|
33
78
|
{{#if js}}JS runs under Node.js worker: top-level \`await\`/\`return\` work; \`fetch\`/\`Buffer\` available.{{/if}}
|
|
34
|
-
{{#if rb}}Ruby: synchronous; helper options are keyword args; the last expression auto-displays unless it is \`nil\`, an assignment, or a definition.{{/if}}
|
|
35
|
-
{{#if jl}}Julia: synchronous; helper options are standard keyword args; the last expression auto-displays unless it is an assignment or a definition.{{/if}}
|
|
79
|
+
{{#if rb}}Ruby: synchronous; helper options are keyword args{{#if spawns}} (e.g. \`output("id", limit: 2)\`){{/if}}; the last expression auto-displays unless it is \`nil\`, an assignment, or a definition (like IRB).{{/if}}
|
|
80
|
+
{{#if jl}}Julia: synchronous; helper options are standard keyword args{{#if spawns}} (e.g. \`output("id", limit=2)\`){{/if}}; the last expression auto-displays unless it is an assignment or a definition (like the Julia REPL).{{/if}}
|
|
36
81
|
On error, fix and re-run only the failing step — prior calls' state survives.
|
|
37
82
|
</instruction>
|
|
38
83
|
|
|
39
84
|
<prelude>
|
|
40
|
-
{{#ifAll py js}}Same helpers + arg order, both runtimes. Python: sync, options = trailing kwargs. JS: async/\`await\`able, options = ONE trailing object literal, never positional.{{else}}{{#if py}}Sync; options = trailing kwargs.{{/if}}{{#if js}}Async/\`await\`able; options = ONE trailing object literal, never positional.{{/if}}{{/ifAll}}{{#if rb}} Ruby: sync, options = trailing keyword args.{{/if}}{{#if jl}} Julia: sync, options = trailing keyword args.{{/if}}
|
|
85
|
+
{{#ifAll py js}}Same helpers + arg order, both runtimes. Python: sync, options = trailing kwargs. JS: async/\`await\`able, options = ONE trailing object literal, never positional (extras throw).{{else}}{{#if py}}Sync; options = trailing kwargs.{{/if}}{{#if js}}Async/\`await\`able; options = ONE trailing object literal, never positional (extras throw).{{/if}}{{/ifAll}}{{#if rb}} Ruby: sync, options = trailing keyword args.{{/if}}{{#if jl}} Julia: sync, options = trailing keyword args.{{/if}}
|
|
41
86
|
\`\`\`
|
|
42
|
-
display(value)
|
|
43
|
-
Cell
|
|
44
|
-
print(value, ...)
|
|
45
|
-
Text
|
|
46
|
-
read(path, offset?=1, limit?=None)
|
|
47
|
-
File as text; offset/limit are 1-indexed lines.
|
|
48
|
-
write(path, content)
|
|
49
|
-
Write file
|
|
50
|
-
env(key?=None, value?=None)
|
|
51
|
-
No args
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
87
|
+
display(value) → None
|
|
88
|
+
Cell output; figures/images/dataframes shown natively.
|
|
89
|
+
print(value, ...) → None
|
|
90
|
+
Text output.
|
|
91
|
+
read(path, offset?=1, limit?=None) → str
|
|
92
|
+
File as text; offset/limit are 1-indexed lines. Accepts \`local://…\`.
|
|
93
|
+
write(path, content) → str
|
|
94
|
+
Write file (creates parents) → resolved path. \`local://…\` persists across turns/subagents.
|
|
95
|
+
env(key?=None, value?=None) → str | None | dict
|
|
96
|
+
No args → full env dict; one → value of \`key\`; two → set \`key=value\`, return value.
|
|
97
|
+
{{#if spawns}}output(*ids, format?="raw", offset?=None, limit?=None) → str | dict | list[dict]
|
|
98
|
+
Task/agent output by id. \`format\` selects full (\`"raw"\`) or trailing (\`"tail"\`) output.
|
|
99
|
+
{{/if}}tool.<name>(args) → unknown
|
|
100
|
+
Invoke any session tool; \`args\` = its parameter object.
|
|
101
|
+
completion(prompt, model?="default", system?=None, schema?=None) → str | dict
|
|
102
|
+
Oneshot, stateless (no history/tools). \`model\`: \`"smol"\` fast | \`"default"\` session | \`"slow"\` most capable. \`schema\` (JSON-Schema) → structured output, parsed object.
|
|
103
|
+
{{#if spawns}}agent(prompt, agent?="{{spawnDefaultAgent}}", model?=None, label?=None, schema?=None, handle?=False) → str | dict
|
|
104
|
+
Run a subagent → final output. \`agent\` picks another discovered agent; omit it to use \`{{spawnDefaultAgent}}\`. \`schema\` as in completion(). Background via \`local://\` files named in the prompt. \`handle\` → DAG node dict { text, output, handle: \`agent://<id>\`, id, agent } (parsed under \`data\` when \`schema\` set).
|
|
105
|
+
{{#if js}} JS: options are ONE trailing object — agent(prompt, { agent, schema, handle }).
|
|
106
|
+
{{/if}}{{/if}}parallel(thunks) → list
|
|
107
|
+
Thunks through a bounded pool (wide as a \`task\` batch — don't pre-shrink), input order kept; returns when all finish, a throwing thunk propagates.
|
|
108
|
+
pipeline(items, ...stages) → list
|
|
59
109
|
Map items through one-arg stages left-to-right, barrier between stages; stage 1 gets the item, later stages the previous result.
|
|
60
|
-
log(message)
|
|
110
|
+
log(message) → None
|
|
61
111
|
Progress line above the status tree.
|
|
62
|
-
phase(title)
|
|
112
|
+
phase(title) → None
|
|
63
113
|
Phase grouping subsequent status lines.
|
|
64
114
|
\`\`\`
|
|
65
115
|
</prelude>
|
|
116
|
+
{{#if spawns}}
|
|
117
|
+
<dag>
|
|
118
|
+
Pipe handles through stage helpers to build a dependency graph — acyclic waves:
|
|
119
|
+
- **Name nodes.** Capture each \`agent(…, {{#if py}}handle=True{{/if}}{{#if js}}{ handle: true }{{/if}}{{#if jl}}handle=true{{/if}})\` result; carries \`handle\` (\`agent://<id>\`) + \`output\`.
|
|
120
|
+
- **Wire edges by reference.** Put an upstream node's \`handle\`/\`output\` in the dependent stage's prompt — large transcript never re-inlined. Bulk: \`write("local://<name>.md", …)\`, pass the URI.
|
|
121
|
+
- **\`pipeline(items, *stages)\` = staged waves**, barrier between stages (every item clears stage N before any enters N+1). **\`parallel(thunks)\` = one wave** of independent nodes.
|
|
122
|
+
- **Isolate failure.** A raising node re-raises the lowest-index error, aborts its wave; wrap risky nodes in try/except so a failure degrades only its dependent subtree, independent branches finish.
|
|
123
|
+
- **Acyclic only.** A node never waits on its own descendant.
|
|
124
|
+
</dag>
|
|
125
|
+
{{/if}}
|
|
66
126
|
|
|
67
127
|
<critical>
|
|
68
|
-
Prior top-level names survive into the next eval call — reuse them; NEVER re-import, re-require, or re-declare a helper. Re-read a file only if it may have changed since the last read. Re-run setup only after \`reset\`, a crash, or a \`NameError\`/\`ReferenceError\`.
|
|
128
|
+
Prior top-level names (\`data\`, \`sessions\`, helpers, imports) survive into the next eval call — reuse them; NEVER re-import, re-require, or re-declare a helper. Re-read a file only if it may have changed since the last read. Re-run setup only after \`reset\`, a crash, or a \`NameError\`/\`ReferenceError\`.
|
|
69
129
|
</critical>`;
|
|
70
130
|
|
|
71
|
-
export function buildEvalPrompt(
|
|
131
|
+
export function buildEvalPrompt(
|
|
132
|
+
enabled: EnabledLanguages,
|
|
133
|
+
options: EvalPromptOptions = { spawns: false },
|
|
134
|
+
): EvalPromptParts {
|
|
72
135
|
if (!enabled.py && !enabled.js && !enabled.rb && !enabled.jl) {
|
|
73
136
|
throw new Error("no kernels enabled for eval prompt");
|
|
74
137
|
}
|
|
138
|
+
const spawnDefaultAgent = options.spawnDefaultAgent ?? "task";
|
|
75
139
|
const context: Context = {
|
|
76
140
|
py: enabled.py,
|
|
77
141
|
js: enabled.js,
|
|
78
142
|
rb: enabled.rb,
|
|
79
143
|
jl: enabled.jl,
|
|
144
|
+
spawns: options.spawns,
|
|
145
|
+
spawnDefaultAgent,
|
|
80
146
|
};
|
|
81
|
-
const
|
|
82
|
-
.
|
|
83
|
-
|
|
147
|
+
const examples = REUSE_CHAIN_EXAMPLES.filter((example) => enabled[example.language])
|
|
148
|
+
.map((example) => {
|
|
149
|
+
const call = { language: example.language, title: example.title, code: example.code };
|
|
150
|
+
return `### ${example.caption}\n\`\`\`json\n${JSON.stringify(call, null, 2)}\n\`\`\``;
|
|
151
|
+
})
|
|
152
|
+
.join("\n\n");
|
|
153
|
+
const description = [
|
|
154
|
+
renderTemplate(EVAL_PROMPT_TEMPLATE, context)
|
|
155
|
+
.replace(/\n{3,}/g, "\n\n")
|
|
156
|
+
.trim(),
|
|
157
|
+
examples === "" ? "" : `<examples>\n${examples}\n</examples>`,
|
|
158
|
+
]
|
|
159
|
+
.filter((part) => part !== "")
|
|
160
|
+
.join("\n\n");
|
|
84
161
|
return {
|
|
85
162
|
description,
|
|
86
163
|
promptSnippet: "Run one incremental code cell in a persistent language kernel.",
|
|
@@ -16,10 +16,10 @@ export interface TimeoutPauseHandle {
|
|
|
16
16
|
|
|
17
17
|
export class IdleTimeout implements TimeoutPauseHandle {
|
|
18
18
|
readonly #cellId: string;
|
|
19
|
-
readonly #timeoutMs: number;
|
|
20
19
|
readonly #onTimeout: (event: IdleTimeoutEvent) => void;
|
|
21
20
|
readonly #controller = new AbortController();
|
|
22
|
-
|
|
21
|
+
readonly signal = this.#controller.signal;
|
|
22
|
+
readonly timeoutMs: number;
|
|
23
23
|
#deadlineMs: number;
|
|
24
24
|
#timer: ReturnType<typeof setTimeout> | undefined;
|
|
25
25
|
#pauseDepth = 0;
|
|
@@ -27,26 +27,16 @@ export class IdleTimeout implements TimeoutPauseHandle {
|
|
|
27
27
|
|
|
28
28
|
constructor(options: IdleTimeoutOptions) {
|
|
29
29
|
this.#cellId = options.cellId;
|
|
30
|
-
this
|
|
31
|
-
this.#
|
|
32
|
-
this.#deadlineMs = Date.now() + this.#remainingMs;
|
|
30
|
+
this.timeoutMs = Math.max(1, Math.floor(options.timeoutMs));
|
|
31
|
+
this.#deadlineMs = Date.now() + this.timeoutMs;
|
|
33
32
|
this.#onTimeout = options.onTimeout;
|
|
34
|
-
this.#arm(this
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
get signal(): AbortSignal {
|
|
38
|
-
return this.#controller.signal;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
get timeoutMs(): number {
|
|
42
|
-
return this.#timeoutMs;
|
|
33
|
+
this.#arm(this.timeoutMs);
|
|
43
34
|
}
|
|
44
35
|
|
|
45
36
|
pause(): void {
|
|
46
37
|
if (this.#settled) return;
|
|
47
38
|
this.#pauseDepth++;
|
|
48
39
|
if (this.#pauseDepth !== 1) return;
|
|
49
|
-
this.#remainingMs = Math.max(0, this.#deadlineMs - Date.now());
|
|
50
40
|
this.#clearTimer();
|
|
51
41
|
}
|
|
52
42
|
|
|
@@ -54,8 +44,8 @@ export class IdleTimeout implements TimeoutPauseHandle {
|
|
|
54
44
|
if (this.#settled || this.#pauseDepth === 0) return;
|
|
55
45
|
this.#pauseDepth--;
|
|
56
46
|
if (this.#pauseDepth > 0) return;
|
|
57
|
-
this.#deadlineMs = Date.now() + this
|
|
58
|
-
this.#arm(this
|
|
47
|
+
this.#deadlineMs = Date.now() + this.timeoutMs;
|
|
48
|
+
this.#arm(this.timeoutMs);
|
|
59
49
|
}
|
|
60
50
|
|
|
61
51
|
dispose(): void {
|
|
@@ -81,13 +71,12 @@ export class IdleTimeout implements TimeoutPauseHandle {
|
|
|
81
71
|
if (this.#settled || this.#pauseDepth > 0) return;
|
|
82
72
|
const remainingMs = this.#deadlineMs - Date.now();
|
|
83
73
|
if (remainingMs > 0) {
|
|
84
|
-
this.#remainingMs = remainingMs;
|
|
85
74
|
this.#arm(remainingMs);
|
|
86
75
|
return;
|
|
87
76
|
}
|
|
88
77
|
this.#settled = true;
|
|
89
78
|
this.#timer = undefined;
|
|
90
|
-
const error = new Error(`Cell timed out after ${this
|
|
79
|
+
const error = new Error(`Cell timed out after ${this.timeoutMs}ms`);
|
|
91
80
|
error.name = "TimeoutError";
|
|
92
81
|
this.#controller.abort(error);
|
|
93
82
|
this.#onTimeout({ cellId: this.#cellId, error });
|