@caupulican/pi-adaptative 0.81.42 → 0.84.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +57 -0
- package/dist/bun/cli.d.ts.map +1 -1
- package/dist/bun/cli.js.map +1 -1
- package/dist/bun/register-bedrock.d.ts.map +1 -1
- package/dist/bun/restore-sandbox-env.d.ts.map +1 -1
- package/dist/bun/restore-sandbox-env.js.map +1 -1
- package/dist/bundled-resources/extensions/tmux-agent-manager/dispatch-grant.d.ts.map +1 -1
- package/dist/bundled-resources/extensions/tmux-agent-manager/dispatch-grant.js.map +1 -1
- package/dist/bundled-resources/extensions/tmux-agent-manager/index.d.ts.map +1 -1
- package/dist/bundled-resources/extensions/tmux-agent-manager/index.js +52 -49
- package/dist/bundled-resources/extensions/tmux-agent-manager/index.js.map +1 -1
- package/dist/bundled-resources/extensions/tmux-agent-manager/index.ts +62 -57
- package/dist/bundled-resources/prompts/skillify.md +1 -1
- package/dist/bundled-resources/runtimes/pi-shell-engine/commands/fs.py +16 -19
- package/dist/bundled-resources/runtimes/pi-shell-engine/commands/search.py +12 -26
- package/dist/bundled-resources/runtimes/pi-shell-engine/commands/strings.py +15 -121
- package/dist/bundled-resources/runtimes/pi-shell-engine/commands/text.py +52 -79
- package/dist/bundled-resources/runtimes/pi-shell-engine/escapes.py +70 -0
- package/dist/bundled-resources/runtimes/pi-shell-engine/exec.py +110 -61
- package/dist/bundled-resources/runtimes/pi-shell-engine/main.py +106 -23
- package/dist/bundled-resources/runtimes/pi-shell-engine/paths.py +10 -0
- package/dist/bundled-resources/runtimes/pi-shell-engine/proc.py +12 -4
- package/dist/bundled-resources/runtimes/pi-shell-engine/shell_args.py +22 -0
- package/dist/bundled-resources/runtimes/pi-shell-engine/state.py +9 -2
- package/dist/bundled-resources/runtimes/pi-shell-engine/tokens.py +129 -259
- package/dist/bundled-resources/skills/authorized-web-security-audit/SKILL.md +187 -0
- package/dist/bundled-resources/skills/authorized-web-security-audit/references/assessment-contract.md +92 -0
- package/dist/bundled-resources/skills/deduplicate-by-evidence/SKILL.md +134 -0
- package/dist/bundled-resources/skills/evidence-gated-tdd/SKILL.md +93 -0
- package/dist/bundled-resources/skills/evidence-gated-tdd/references/evidence-model.md +27 -0
- package/dist/bundled-resources/skills/evidence-gated-tdd/references/security-scanners.md +24 -0
- package/dist/bundled-resources/skills/harness-self-adaptation/SKILL.md +4 -2
- package/dist/bundled-resources/skills/secure-agent-tool-surfaces/SKILL.md +217 -0
- package/dist/bundled-resources/skills/secure-agent-tool-surfaces/references/defensive-exploit-catalogue.md +175 -0
- package/dist/bundled-resources/skills/secure-agent-tool-surfaces/references/tool-boundary-checklist.md +87 -0
- package/dist/bundled-resources/skills/skill-architect/SKILL.md +2 -2
- package/dist/bundled-resources/skills/skill-creator/SKILL.md +188 -0
- package/dist/bundled-resources/skills/skill-creator/references/pi-skill-contract.md +73 -0
- package/dist/bundled-resources/skills/skill-creator/scripts/init-skill.mjs +142 -0
- package/dist/bundled-resources/skills/skill-creator/scripts/validate-skill.mjs +122 -0
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js.map +1 -1
- package/dist/cli/config-selector.d.ts.map +1 -1
- package/dist/cli/config-selector.js.map +1 -1
- package/dist/cli/file-processor.d.ts.map +1 -1
- package/dist/cli/file-processor.js +8 -8
- package/dist/cli/file-processor.js.map +1 -1
- package/dist/cli/initial-message.d.ts +1 -1
- package/dist/cli/initial-message.d.ts.map +1 -1
- package/dist/cli/initial-message.js.map +1 -1
- package/dist/cli/list-models.d.ts.map +1 -1
- package/dist/cli/list-models.js.map +1 -1
- package/dist/cli/piped-stdin.d.ts +4 -0
- package/dist/cli/piped-stdin.d.ts.map +1 -0
- package/dist/cli/piped-stdin.js +13 -0
- package/dist/cli/piped-stdin.js.map +1 -0
- package/dist/cli/session-picker.d.ts.map +1 -1
- package/dist/cli/session-picker.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +10 -15
- package/dist/config.js.map +1 -1
- package/dist/core/agent-directory-layout.d.ts.map +1 -1
- package/dist/core/agent-directory-layout.js.map +1 -1
- package/dist/core/agent-paths.d.ts +1 -1
- package/dist/core/agent-paths.d.ts.map +1 -1
- package/dist/core/agent-paths.js +1 -1
- package/dist/core/agent-paths.js.map +1 -1
- package/dist/core/agent-session-contracts.d.ts +5 -9
- package/dist/core/agent-session-contracts.d.ts.map +1 -1
- package/dist/core/agent-session-contracts.js +1 -12
- package/dist/core/agent-session-contracts.js.map +1 -1
- package/dist/core/agent-session-runtime.d.ts.map +1 -1
- package/dist/core/agent-session-runtime.js +10 -25
- package/dist/core/agent-session-runtime.js.map +1 -1
- package/dist/core/agent-session-services.d.ts.map +1 -1
- package/dist/core/agent-session-services.js.map +1 -1
- package/dist/core/agent-session.d.ts +24 -1
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +210 -237
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/auth-guidance.d.ts.map +1 -1
- package/dist/core/auth-guidance.js.map +1 -1
- package/dist/core/auth-storage.d.ts +4 -1
- package/dist/core/auth-storage.d.ts.map +1 -1
- package/dist/core/auth-storage.js +13 -39
- package/dist/core/auth-storage.js.map +1 -1
- package/dist/core/autonomy/approval-gate.d.ts.map +1 -1
- package/dist/core/autonomy/approval-gate.js.map +1 -1
- package/dist/core/autonomy/bounded-completion.d.ts.map +1 -1
- package/dist/core/autonomy/bounded-completion.js.map +1 -1
- package/dist/core/autonomy/contracts.d.ts.map +1 -1
- package/dist/core/autonomy/envelope-enforcement.d.ts.map +1 -1
- package/dist/core/autonomy/envelope-enforcement.js.map +1 -1
- package/dist/core/autonomy/evidence-finding-projection.d.ts +11 -0
- package/dist/core/autonomy/evidence-finding-projection.d.ts.map +1 -0
- package/dist/core/autonomy/evidence-finding-projection.js +37 -0
- package/dist/core/autonomy/evidence-finding-projection.js.map +1 -0
- package/dist/core/autonomy/foreground-envelope.d.ts.map +1 -1
- package/dist/core/autonomy/foreground-envelope.js.map +1 -1
- package/dist/core/autonomy/gates.d.ts.map +1 -1
- package/dist/core/autonomy/gates.js.map +1 -1
- package/dist/core/autonomy/lane-private-paths.d.ts.map +1 -1
- package/dist/core/autonomy/lane-private-paths.js.map +1 -1
- package/dist/core/autonomy/lane-tool-surface.d.ts.map +1 -1
- package/dist/core/autonomy/lane-tool-surface.js.map +1 -1
- package/dist/core/autonomy/lane-tracker.d.ts.map +1 -1
- package/dist/core/autonomy/lane-tracker.js +2 -3
- package/dist/core/autonomy/lane-tracker.js.map +1 -1
- package/dist/core/autonomy/path-scope.d.ts.map +1 -1
- package/dist/core/autonomy/path-scope.js.map +1 -1
- package/dist/core/autonomy/risk-assessment.d.ts.map +1 -1
- package/dist/core/autonomy/session-lane-record.d.ts.map +1 -1
- package/dist/core/autonomy/session-lane-record.js.map +1 -1
- package/dist/core/autonomy/status.d.ts.map +1 -1
- package/dist/core/autonomy/status.js.map +1 -1
- package/dist/core/autonomy/subagent-prompt.d.ts.map +1 -1
- package/dist/core/autonomy/subagent-prompt.js.map +1 -1
- package/dist/core/autonomy/telemetry-events.d.ts.map +1 -1
- package/dist/core/autonomy/telemetry-events.js.map +1 -1
- package/dist/core/autonomy-telemetry.d.ts.map +1 -1
- package/dist/core/autonomy-telemetry.js +2 -4
- package/dist/core/autonomy-telemetry.js.map +1 -1
- package/dist/core/background-lane-controller.d.ts.map +1 -1
- package/dist/core/background-lane-controller.js +2 -15
- package/dist/core/background-lane-controller.js.map +1 -1
- package/dist/core/background-tool-task-controller.d.ts +88 -0
- package/dist/core/background-tool-task-controller.d.ts.map +1 -0
- package/dist/core/background-tool-task-controller.js +470 -0
- package/dist/core/background-tool-task-controller.js.map +1 -0
- package/dist/core/bash-execution-controller.d.ts +1 -0
- package/dist/core/bash-execution-controller.d.ts.map +1 -1
- package/dist/core/bash-execution-controller.js +5 -4
- package/dist/core/bash-execution-controller.js.map +1 -1
- package/dist/core/bash-executor.d.ts.map +1 -1
- package/dist/core/bash-executor.js.map +1 -1
- package/dist/core/bedrock-sso-login.d.ts.map +1 -1
- package/dist/core/bedrock-sso-login.js.map +1 -1
- package/dist/core/billing-failover-controller.d.ts.map +1 -1
- package/dist/core/billing-failover-controller.js +3 -3
- package/dist/core/billing-failover-controller.js.map +1 -1
- package/dist/core/billing-failover.d.ts.map +1 -1
- package/dist/core/billing-failover.js.map +1 -1
- package/dist/core/capability-contract.d.ts.map +1 -1
- package/dist/core/catalog-manager.d.ts.map +1 -1
- package/dist/core/catalog-manager.js +0 -0
- package/dist/core/catalog-manager.js.map +1 -1
- package/dist/core/compaction-controller.d.ts +2 -0
- package/dist/core/compaction-controller.d.ts.map +1 -1
- package/dist/core/compaction-controller.js +21 -8
- package/dist/core/compaction-controller.js.map +1 -1
- package/dist/core/compaction-support.d.ts +8 -0
- package/dist/core/compaction-support.d.ts.map +1 -1
- package/dist/core/compaction-support.js +0 -2
- package/dist/core/compaction-support.js.map +1 -1
- package/dist/core/context/artifact-retrieval.d.ts.map +1 -1
- package/dist/core/context/artifact-retrieval.js.map +1 -1
- package/dist/core/context/brain-curator.d.ts.map +1 -1
- package/dist/core/context/brain-curator.js +14 -33
- package/dist/core/context/brain-curator.js.map +1 -1
- package/dist/core/context/context-artifacts.d.ts.map +1 -1
- package/dist/core/context/context-artifacts.js +16 -24
- package/dist/core/context/context-artifacts.js.map +1 -1
- package/dist/core/context/context-audit.d.ts.map +1 -1
- package/dist/core/context/context-audit.js +3 -17
- package/dist/core/context/context-audit.js.map +1 -1
- package/dist/core/context/context-composition.d.ts.map +1 -1
- package/dist/core/context/context-composition.js.map +1 -1
- package/dist/core/context/context-item.d.ts.map +1 -1
- package/dist/core/context/context-item.js.map +1 -1
- package/dist/core/context/context-prompt-enforcement.d.ts.map +1 -1
- package/dist/core/context/context-prompt-enforcement.js +3 -16
- package/dist/core/context/context-prompt-enforcement.js.map +1 -1
- package/dist/core/context/context-prompt-policy.d.ts.map +1 -1
- package/dist/core/context/context-prompt-policy.js.map +1 -1
- package/dist/core/context/context-retention.d.ts.map +1 -1
- package/dist/core/context/context-retention.js.map +1 -1
- package/dist/core/context/context-store-retention.d.ts.map +1 -1
- package/dist/core/context/context-store-retention.js.map +1 -1
- package/dist/core/context/context-store.d.ts.map +1 -1
- package/dist/core/context/context-store.js.map +1 -1
- package/dist/core/context/context-tool-result.d.ts +4 -0
- package/dist/core/context/context-tool-result.d.ts.map +1 -0
- package/dist/core/context/context-tool-result.js +15 -0
- package/dist/core/context/context-tool-result.js.map +1 -0
- package/dist/core/context/current-work-memory.d.ts.map +1 -1
- package/dist/core/context/current-work-memory.js.map +1 -1
- package/dist/core/context/file-store-memory-provider.d.ts.map +1 -1
- package/dist/core/context/file-store-memory-provider.js +7 -28
- package/dist/core/context/file-store-memory-provider.js.map +1 -1
- package/dist/core/context/local-memory-search.d.ts +11 -0
- package/dist/core/context/local-memory-search.d.ts.map +1 -0
- package/dist/core/context/local-memory-search.js +37 -0
- package/dist/core/context/local-memory-search.js.map +1 -0
- package/dist/core/context/long-term-memory-trigger.d.ts.map +1 -1
- package/dist/core/context/long-term-memory-trigger.js.map +1 -1
- package/dist/core/context/memory-diagnostics.d.ts.map +1 -1
- package/dist/core/context/memory-diagnostics.js.map +1 -1
- package/dist/core/context/memory-index-store.d.ts.map +1 -1
- package/dist/core/context/memory-index-store.js.map +1 -1
- package/dist/core/context/memory-prompt-block.d.ts.map +1 -1
- package/dist/core/context/memory-prompt-block.js.map +1 -1
- package/dist/core/context/memory-prompt-budget.d.ts.map +1 -1
- package/dist/core/context/memory-prompt-budget.js.map +1 -1
- package/dist/core/context/memory-provider-contract.d.ts.map +1 -1
- package/dist/core/context/memory-provider-contract.js.map +1 -1
- package/dist/core/context/memory-retrieval.d.ts.map +1 -1
- package/dist/core/context/memory-retrieval.js.map +1 -1
- package/dist/core/context/memory-tier-composer.d.ts.map +1 -1
- package/dist/core/context/memory-tier-composer.js.map +1 -1
- package/dist/core/context/message-text.d.ts +7 -0
- package/dist/core/context/message-text.d.ts.map +1 -0
- package/dist/core/context/message-text.js +68 -0
- package/dist/core/context/message-text.js.map +1 -0
- package/dist/core/context/okf-memory-provider.d.ts.map +1 -1
- package/dist/core/context/okf-memory-provider.js +4 -30
- package/dist/core/context/okf-memory-provider.js.map +1 -1
- package/dist/core/context/okf-memory.d.ts.map +1 -1
- package/dist/core/context/okf-memory.js.map +1 -1
- package/dist/core/context/policy-engine.d.ts.map +1 -1
- package/dist/core/context/policy-engine.js.map +1 -1
- package/dist/core/context/policy-types.d.ts.map +1 -1
- package/dist/core/context/sqlite-runtime-index.d.ts.map +1 -1
- package/dist/core/context/sqlite-runtime-index.js.map +1 -1
- package/dist/core/context/storage-authority.d.ts.map +1 -1
- package/dist/core/context/tool-output-packer.d.ts.map +1 -1
- package/dist/core/context/tool-output-packer.js.map +1 -1
- package/dist/core/context-gc.d.ts.map +1 -1
- package/dist/core/context-gc.js +14 -21
- package/dist/core/context-gc.js.map +1 -1
- package/dist/core/context-pipeline.d.ts +1 -3
- package/dist/core/context-pipeline.d.ts.map +1 -1
- package/dist/core/context-pipeline.js +64 -145
- package/dist/core/context-pipeline.js.map +1 -1
- package/dist/core/cost/cost-summary.d.ts.map +1 -1
- package/dist/core/cost/cost-summary.js.map +1 -1
- package/dist/core/cost/daily-usage.d.ts.map +1 -1
- package/dist/core/cost/daily-usage.js.map +1 -1
- package/dist/core/cost/session-usage.d.ts.map +1 -1
- package/dist/core/cost/session-usage.js.map +1 -1
- package/dist/core/cost-guard.d.ts.map +1 -1
- package/dist/core/cost-guard.js.map +1 -1
- package/dist/core/default-tool-surface.d.ts.map +1 -1
- package/dist/core/default-tool-surface.js +1 -0
- package/dist/core/default-tool-surface.js.map +1 -1
- package/dist/core/defaults.d.ts.map +1 -1
- package/dist/core/delegation/managed-lane-controller.d.ts.map +1 -1
- package/dist/core/delegation/managed-lane-controller.js +2 -6
- package/dist/core/delegation/managed-lane-controller.js.map +1 -1
- package/dist/core/delegation/session-worker-claim.d.ts.map +1 -1
- package/dist/core/delegation/session-worker-claim.js.map +1 -1
- package/dist/core/delegation/worker-action-journal.d.ts.map +1 -1
- package/dist/core/delegation/worker-action-journal.js +0 -4
- package/dist/core/delegation/worker-action-journal.js.map +1 -1
- package/dist/core/delegation/worker-actions.d.ts.map +1 -1
- package/dist/core/delegation/worker-actions.js.map +1 -1
- package/dist/core/delegation/worker-agent-control-coordinator.d.ts +1 -0
- package/dist/core/delegation/worker-agent-control-coordinator.d.ts.map +1 -1
- package/dist/core/delegation/worker-agent-control-coordinator.js +13 -15
- package/dist/core/delegation/worker-agent-control-coordinator.js.map +1 -1
- package/dist/core/delegation/worker-agent-control.d.ts.map +1 -1
- package/dist/core/delegation/worker-agent-control.js +1 -4
- package/dist/core/delegation/worker-agent-control.js.map +1 -1
- package/dist/core/delegation/worker-attempt-executor.d.ts.map +1 -1
- package/dist/core/delegation/worker-attempt-executor.js.map +1 -1
- package/dist/core/delegation/worker-claim.d.ts.map +1 -1
- package/dist/core/delegation/worker-claim.js.map +1 -1
- package/dist/core/delegation/worker-conversation-store.d.ts.map +1 -1
- package/dist/core/delegation/worker-conversation-store.js +0 -2
- package/dist/core/delegation/worker-conversation-store.js.map +1 -1
- package/dist/core/delegation/worker-delegation-controller.d.ts.map +1 -1
- package/dist/core/delegation/worker-delegation-controller.js +5 -14
- package/dist/core/delegation/worker-delegation-controller.js.map +1 -1
- package/dist/core/delegation/worker-delegation-request.d.ts.map +1 -1
- package/dist/core/delegation/worker-dispatch-scheduler.d.ts.map +1 -1
- package/dist/core/delegation/worker-dispatch-scheduler.js +5 -6
- package/dist/core/delegation/worker-dispatch-scheduler.js.map +1 -1
- package/dist/core/delegation/worker-execution-policy.d.ts.map +1 -1
- package/dist/core/delegation/worker-execution-policy.js.map +1 -1
- package/dist/core/delegation/worker-lane-projection.d.ts.map +1 -1
- package/dist/core/delegation/worker-lane-projection.js.map +1 -1
- package/dist/core/delegation/worker-lifecycle.d.ts.map +1 -1
- package/dist/core/delegation/worker-lifecycle.js +0 -3
- package/dist/core/delegation/worker-lifecycle.js.map +1 -1
- package/dist/core/delegation/worker-notification-coordinator.d.ts.map +1 -1
- package/dist/core/delegation/worker-notification-coordinator.js +4 -5
- package/dist/core/delegation/worker-notification-coordinator.js.map +1 -1
- package/dist/core/delegation/worker-process-owner.d.ts.map +1 -1
- package/dist/core/delegation/worker-process-owner.js.map +1 -1
- package/dist/core/delegation/worker-profile-resolver.d.ts.map +1 -1
- package/dist/core/delegation/worker-profile-resolver.js +1 -2
- package/dist/core/delegation/worker-profile-resolver.js.map +1 -1
- package/dist/core/delegation/worker-recovery-coordinator.d.ts.map +1 -1
- package/dist/core/delegation/worker-recovery-coordinator.js +3 -4
- package/dist/core/delegation/worker-recovery-coordinator.js.map +1 -1
- package/dist/core/delegation/worker-resource-catalog.d.ts.map +1 -1
- package/dist/core/delegation/worker-resource-catalog.js.map +1 -1
- package/dist/core/delegation/worker-resource-materializer.d.ts.map +1 -1
- package/dist/core/delegation/worker-resource-materializer.js +1 -4
- package/dist/core/delegation/worker-resource-materializer.js.map +1 -1
- package/dist/core/delegation/worker-runner.d.ts +2 -4
- package/dist/core/delegation/worker-runner.d.ts.map +1 -1
- package/dist/core/delegation/worker-runner.js +6 -18
- package/dist/core/delegation/worker-runner.js.map +1 -1
- package/dist/core/delegation/worker-task-label.d.ts.map +1 -1
- package/dist/core/delegation/worker-task-label.js.map +1 -1
- package/dist/core/delegation/worker-terminal-finalizer.d.ts.map +1 -1
- package/dist/core/delegation/worker-terminal-finalizer.js.map +1 -1
- package/dist/core/delegation/worker-write-reservation-coordinator.d.ts.map +1 -1
- package/dist/core/delegation/worker-write-reservation-coordinator.js +1 -4
- package/dist/core/delegation/worker-write-reservation-coordinator.js.map +1 -1
- package/dist/core/delegation/worker-write-reservation.d.ts.map +1 -1
- package/dist/core/delegation/worker-write-reservation.js +0 -2
- package/dist/core/delegation/worker-write-reservation.js.map +1 -1
- package/dist/core/diagnostics.d.ts.map +1 -1
- package/dist/core/doctor.d.ts +5 -5
- package/dist/core/doctor.d.ts.map +1 -1
- package/dist/core/doctor.js +16 -20
- package/dist/core/doctor.js.map +1 -1
- package/dist/core/event-bus.d.ts.map +1 -1
- package/dist/core/event-bus.js.map +1 -1
- package/dist/core/exec.d.ts.map +1 -1
- package/dist/core/exec.js +26 -7
- package/dist/core/exec.js.map +1 -1
- package/dist/core/export-html/ansi-to-html.d.ts.map +1 -1
- package/dist/core/export-html/ansi-to-html.js +21 -74
- package/dist/core/export-html/ansi-to-html.js.map +1 -1
- package/dist/core/export-html/index.d.ts.map +1 -1
- package/dist/core/export-html/index.js +4 -0
- package/dist/core/export-html/index.js.map +1 -1
- package/dist/core/export-html/session-tree-foundations.d.mts +67 -0
- package/dist/core/export-html/session-tree-foundations.mjs +313 -0
- package/dist/core/export-html/template.css +14 -41
- package/dist/core/export-html/template.html +3 -1
- package/dist/core/export-html/template.js +26 -435
- package/dist/core/export-html/tool-renderer.d.ts.map +1 -1
- package/dist/core/export-html/tool-renderer.js.map +1 -1
- package/dist/core/extension-import-authority.d.ts.map +1 -1
- package/dist/core/extension-import-authority.js.map +1 -1
- package/dist/core/extension-metadata.d.ts.map +1 -1
- package/dist/core/extension-metadata.js.map +1 -1
- package/dist/core/extensions/builtin.d.ts +17 -0
- package/dist/core/extensions/builtin.d.ts.map +1 -1
- package/dist/core/extensions/builtin.js +18 -54
- package/dist/core/extensions/builtin.js.map +1 -1
- package/dist/core/extensions/entry-resolution.d.ts +3 -0
- package/dist/core/extensions/entry-resolution.d.ts.map +1 -0
- package/dist/core/extensions/entry-resolution.js +17 -0
- package/dist/core/extensions/entry-resolution.js.map +1 -0
- package/dist/core/extensions/index.d.ts.map +1 -1
- package/dist/core/extensions/loader.d.ts.map +1 -1
- package/dist/core/extensions/loader.js +76 -21
- package/dist/core/extensions/loader.js.map +1 -1
- package/dist/core/extensions/runner.d.ts +2 -0
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +41 -112
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/extensions/stale-context.d.ts.map +1 -1
- package/dist/core/extensions/storage.d.ts.map +1 -1
- package/dist/core/extensions/storage.js.map +1 -1
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/extensions/wrapper.d.ts.map +1 -1
- package/dist/core/extensions/wrapper.js.map +1 -1
- package/dist/core/failure-corpus.d.ts.map +1 -1
- package/dist/core/failure-corpus.js +2 -5
- package/dist/core/failure-corpus.js.map +1 -1
- package/dist/core/footer-data-provider.d.ts.map +1 -1
- package/dist/core/footer-data-provider.js +27 -33
- package/dist/core/footer-data-provider.js.map +1 -1
- package/dist/core/foreground-recovery-controller.d.ts.map +1 -1
- package/dist/core/foreground-recovery-controller.js +0 -4
- package/dist/core/foreground-recovery-controller.js.map +1 -1
- package/dist/core/gateways/channel-provider.d.ts.map +1 -1
- package/dist/core/gateways/channel-provider.js +7 -5
- package/dist/core/gateways/channel-provider.js.map +1 -1
- package/dist/core/goal-loop-controller.d.ts.map +1 -1
- package/dist/core/goal-loop-controller.js +0 -1
- package/dist/core/goal-loop-controller.js.map +1 -1
- package/dist/core/goals/compact-goal-context.d.ts.map +1 -1
- package/dist/core/goals/compact-goal-context.js +2 -4
- package/dist/core/goals/compact-goal-context.js.map +1 -1
- package/dist/core/goals/goal-acceptance.d.ts.map +1 -1
- package/dist/core/goals/goal-acceptance.js.map +1 -1
- package/dist/core/goals/goal-auto-continue-controller.d.ts.map +1 -1
- package/dist/core/goals/goal-auto-continue-controller.js +1 -3
- package/dist/core/goals/goal-auto-continue-controller.js.map +1 -1
- package/dist/core/goals/goal-continuation-controller.d.ts.map +1 -1
- package/dist/core/goals/goal-continuation-controller.js.map +1 -1
- package/dist/core/goals/goal-continuation-defaults.d.ts.map +1 -1
- package/dist/core/goals/goal-continuation-prompt.d.ts.map +1 -1
- package/dist/core/goals/goal-continuation-prompt.js.map +1 -1
- package/dist/core/goals/goal-lifecycle.d.ts.map +1 -1
- package/dist/core/goals/goal-lifecycle.js.map +1 -1
- package/dist/core/goals/goal-record.d.ts.map +1 -1
- package/dist/core/goals/goal-record.js.map +1 -1
- package/dist/core/goals/goal-runtime-snapshot.d.ts.map +1 -1
- package/dist/core/goals/goal-runtime-snapshot.js.map +1 -1
- package/dist/core/goals/goal-session-controller.d.ts +15 -0
- package/dist/core/goals/goal-session-controller.d.ts.map +1 -1
- package/dist/core/goals/goal-session-controller.js +27 -3
- package/dist/core/goals/goal-session-controller.js.map +1 -1
- package/dist/core/goals/goal-state.d.ts.map +1 -1
- package/dist/core/goals/goal-state.js +35 -51
- package/dist/core/goals/goal-state.js.map +1 -1
- package/dist/core/goals/goal-tool-core.d.ts.map +1 -1
- package/dist/core/goals/goal-tool-core.js.map +1 -1
- package/dist/core/goals/natural-language-goal.d.ts +9 -0
- package/dist/core/goals/natural-language-goal.d.ts.map +1 -0
- package/dist/core/goals/natural-language-goal.js +23 -0
- package/dist/core/goals/natural-language-goal.js.map +1 -0
- package/dist/core/goals/session-goal-state.d.ts.map +1 -1
- package/dist/core/goals/session-goal-state.js.map +1 -1
- package/dist/core/http-dispatcher.d.ts.map +1 -1
- package/dist/core/http-dispatcher.js.map +1 -1
- package/dist/core/human-input-controller.d.ts.map +1 -1
- package/dist/core/human-input-controller.js +2 -3
- package/dist/core/human-input-controller.js.map +1 -1
- package/dist/core/human-input.d.ts.map +1 -1
- package/dist/core/human-input.js.map +1 -1
- package/dist/core/improvement-loop.d.ts.map +1 -1
- package/dist/core/improvement-loop.js +11 -11
- package/dist/core/improvement-loop.js.map +1 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/install-telemetry.d.ts.map +1 -1
- package/dist/core/install-telemetry.js.map +1 -1
- package/dist/core/isolated-text-completion.d.ts +17 -0
- package/dist/core/isolated-text-completion.d.ts.map +1 -0
- package/dist/core/isolated-text-completion.js +15 -0
- package/dist/core/isolated-text-completion.js.map +1 -0
- package/dist/core/keybindings.d.ts +47 -2
- package/dist/core/keybindings.d.ts.map +1 -1
- package/dist/core/keybindings.js +12 -1
- package/dist/core/keybindings.js.map +1 -1
- package/dist/core/learning/learning-audit.d.ts.map +1 -1
- package/dist/core/learning/learning-audit.js.map +1 -1
- package/dist/core/learning/learning-gate.d.ts.map +1 -1
- package/dist/core/learning/learning-gate.js.map +1 -1
- package/dist/core/learning/observation-store.d.ts.map +1 -1
- package/dist/core/learning/observation-store.js +0 -2
- package/dist/core/learning/observation-store.js.map +1 -1
- package/dist/core/learning/reflection-engine.d.ts +1 -1
- package/dist/core/learning/reflection-engine.d.ts.map +1 -1
- package/dist/core/learning/reflection-engine.js +3 -0
- package/dist/core/learning/reflection-engine.js.map +1 -1
- package/dist/core/learning/reflection-turn-analysis.d.ts +20 -0
- package/dist/core/learning/reflection-turn-analysis.d.ts.map +1 -0
- package/dist/core/learning/reflection-turn-analysis.js +136 -0
- package/dist/core/learning/reflection-turn-analysis.js.map +1 -0
- package/dist/core/learning/session-learning-decision.d.ts.map +1 -1
- package/dist/core/learning/session-learning-decision.js.map +1 -1
- package/dist/core/learning/skill-curator.d.ts.map +1 -1
- package/dist/core/learning/skill-curator.js +0 -3
- package/dist/core/learning/skill-curator.js.map +1 -1
- package/dist/core/local-runtime-controller.d.ts +39 -0
- package/dist/core/local-runtime-controller.d.ts.map +1 -1
- package/dist/core/local-runtime-controller.js +41 -62
- package/dist/core/local-runtime-controller.js.map +1 -1
- package/dist/core/memory/effectiveness-tracker.d.ts.map +1 -1
- package/dist/core/memory/effectiveness-tracker.js +4 -2
- package/dist/core/memory/effectiveness-tracker.js.map +1 -1
- package/dist/core/memory/memory-manager.d.ts.map +1 -1
- package/dist/core/memory/memory-manager.js +7 -7
- package/dist/core/memory/memory-manager.js.map +1 -1
- package/dist/core/memory/memory-provider.d.ts.map +1 -1
- package/dist/core/memory/providers/file-store.d.ts +7 -0
- package/dist/core/memory/providers/file-store.d.ts.map +1 -1
- package/dist/core/memory/providers/file-store.js +48 -13
- package/dist/core/memory/providers/file-store.js.map +1 -1
- package/dist/core/memory/providers/transcript-recall-worker-protocol.d.ts +47 -0
- package/dist/core/memory/providers/transcript-recall-worker-protocol.d.ts.map +1 -0
- package/dist/core/memory/providers/transcript-recall-worker-protocol.js +50 -0
- package/dist/core/memory/providers/transcript-recall-worker-protocol.js.map +1 -0
- package/dist/core/memory/providers/transcript-recall-worker.d.ts +2 -0
- package/dist/core/memory/providers/transcript-recall-worker.d.ts.map +1 -0
- package/dist/core/memory/providers/transcript-recall-worker.js +143 -0
- package/dist/core/memory/providers/transcript-recall-worker.js.map +1 -0
- package/dist/core/memory/providers/transcript-recall.d.ts +24 -13
- package/dist/core/memory/providers/transcript-recall.d.ts.map +1 -1
- package/dist/core/memory/providers/transcript-recall.js +143 -141
- package/dist/core/memory/providers/transcript-recall.js.map +1 -1
- package/dist/core/memory/providers/user-memory-archive.d.ts +39 -0
- package/dist/core/memory/providers/user-memory-archive.d.ts.map +1 -0
- package/dist/core/memory/providers/user-memory-archive.js +258 -0
- package/dist/core/memory/providers/user-memory-archive.js.map +1 -0
- package/dist/core/memory/transcript-index.d.ts.map +1 -1
- package/dist/core/memory/transcript-index.js +1 -1
- package/dist/core/memory/transcript-index.js.map +1 -1
- package/dist/core/memory-controller.d.ts +9 -0
- package/dist/core/memory-controller.d.ts.map +1 -1
- package/dist/core/memory-controller.js +57 -16
- package/dist/core/memory-controller.js.map +1 -1
- package/dist/core/model-capability.d.ts.map +1 -1
- package/dist/core/model-capability.js.map +1 -1
- package/dist/core/model-output-json.d.ts +10 -0
- package/dist/core/model-output-json.d.ts.map +1 -0
- package/dist/core/model-output-json.js +43 -0
- package/dist/core/model-output-json.js.map +1 -0
- package/dist/core/model-registry.d.ts +8 -8
- package/dist/core/model-registry.d.ts.map +1 -1
- package/dist/core/model-registry.js +29 -52
- package/dist/core/model-registry.js.map +1 -1
- package/dist/core/model-resolver.d.ts.map +1 -1
- package/dist/core/model-resolver.js +1 -1
- package/dist/core/model-resolver.js.map +1 -1
- package/dist/core/model-router/config-diagnostics.d.ts.map +1 -1
- package/dist/core/model-router/config-diagnostics.js.map +1 -1
- package/dist/core/model-router/executor-route.d.ts.map +1 -1
- package/dist/core/model-router/executor-route.js.map +1 -1
- package/dist/core/model-router/fitness-gate.d.ts.map +1 -1
- package/dist/core/model-router/fitness-gate.js.map +1 -1
- package/dist/core/model-router/intent-classifier.d.ts.map +1 -1
- package/dist/core/model-router/route-judge.d.ts.map +1 -1
- package/dist/core/model-router/route-judge.js +18 -36
- package/dist/core/model-router/route-judge.js.map +1 -1
- package/dist/core/model-router/session-buffer.d.ts.map +1 -1
- package/dist/core/model-router/session-buffer.js.map +1 -1
- package/dist/core/model-router/status.d.ts.map +1 -1
- package/dist/core/model-router/status.js.map +1 -1
- package/dist/core/model-router/tool-escalation.d.ts.map +1 -1
- package/dist/core/model-router/tool-escalation.js.map +1 -1
- package/dist/core/model-router-controller.d.ts +1 -0
- package/dist/core/model-router-controller.d.ts.map +1 -1
- package/dist/core/model-router-controller.js +25 -56
- package/dist/core/model-router-controller.js.map +1 -1
- package/dist/core/model-selection-controller.d.ts +10 -0
- package/dist/core/model-selection-controller.d.ts.map +1 -1
- package/dist/core/model-selection-controller.js +0 -1
- package/dist/core/model-selection-controller.js.map +1 -1
- package/dist/core/model-tool-protocol.d.ts.map +1 -1
- package/dist/core/model-tool-protocol.js.map +1 -1
- package/dist/core/models/adaptation-store.d.ts.map +1 -1
- package/dist/core/models/adaptation-store.js +0 -1
- package/dist/core/models/adaptation-store.js.map +1 -1
- package/dist/core/models/context-sizing.d.ts.map +1 -1
- package/dist/core/models/context-sizing.js.map +1 -1
- package/dist/core/models/default-model-suggestions.d.ts.map +1 -1
- package/dist/core/models/default-model-suggestions.js.map +1 -1
- package/dist/core/models/fitness-store.d.ts.map +1 -1
- package/dist/core/models/fitness-store.js +0 -1
- package/dist/core/models/fitness-store.js.map +1 -1
- package/dist/core/models/host-state-store.d.ts.map +1 -1
- package/dist/core/models/host-state-store.js +1 -6
- package/dist/core/models/host-state-store.js.map +1 -1
- package/dist/core/models/llamacpp-runtime.d.ts +4 -19
- package/dist/core/models/llamacpp-runtime.d.ts.map +1 -1
- package/dist/core/models/llamacpp-runtime.js +32 -136
- package/dist/core/models/llamacpp-runtime.js.map +1 -1
- package/dist/core/models/local-registration.d.ts.map +1 -1
- package/dist/core/models/local-registration.js +82 -115
- package/dist/core/models/local-registration.js.map +1 -1
- package/dist/core/models/local-runtime.d.ts +12 -18
- package/dist/core/models/local-runtime.d.ts.map +1 -1
- package/dist/core/models/local-runtime.js +60 -204
- package/dist/core/models/local-runtime.js.map +1 -1
- package/dist/core/models/model-endpoint.d.ts.map +1 -1
- package/dist/core/models/model-endpoint.js.map +1 -1
- package/dist/core/models/model-ref.d.ts.map +1 -1
- package/dist/core/models/model-ref.js.map +1 -1
- package/dist/core/models/needle-runtime.d.ts +7 -3
- package/dist/core/models/needle-runtime.d.ts.map +1 -1
- package/dist/core/models/needle-runtime.js +16 -92
- package/dist/core/models/needle-runtime.js.map +1 -1
- package/dist/core/models/perf-profile.d.ts +1 -1
- package/dist/core/models/perf-profile.d.ts.map +1 -1
- package/dist/core/models/perf-profile.js +6 -13
- package/dist/core/models/perf-profile.js.map +1 -1
- package/dist/core/models/prism-llamacpp-lifecycle.d.ts.map +1 -1
- package/dist/core/models/prism-llamacpp-lifecycle.js.map +1 -1
- package/dist/core/models/runtime-arbiter.d.ts.map +1 -1
- package/dist/core/models/runtime-arbiter.js +3 -15
- package/dist/core/models/runtime-arbiter.js.map +1 -1
- package/dist/core/models/runtime-process.d.ts +100 -0
- package/dist/core/models/runtime-process.d.ts.map +1 -0
- package/dist/core/models/runtime-process.js +183 -0
- package/dist/core/models/runtime-process.js.map +1 -0
- package/dist/core/orchestration/agent-resume.d.ts.map +1 -1
- package/dist/core/orchestration/agent-resume.js.map +1 -1
- package/dist/core/orchestration/attempt-usage.d.ts.map +1 -1
- package/dist/core/orchestration/attempt-usage.js.map +1 -1
- package/dist/core/orchestration/capability-gateway.d.ts.map +1 -1
- package/dist/core/orchestration/capability-gateway.js +0 -14
- package/dist/core/orchestration/capability-gateway.js.map +1 -1
- package/dist/core/orchestration/contracts.d.ts.map +1 -1
- package/dist/core/orchestration/contracts.js.map +1 -1
- package/dist/core/orchestration/delegation-ledger.d.ts.map +1 -1
- package/dist/core/orchestration/delegation-ledger.js +0 -2
- package/dist/core/orchestration/delegation-ledger.js.map +1 -1
- package/dist/core/orchestration/event-store.d.ts.map +1 -1
- package/dist/core/orchestration/event-store.js +1 -14
- package/dist/core/orchestration/event-store.js.map +1 -1
- package/dist/core/orchestration/lane-tool-manifests.d.ts.map +1 -1
- package/dist/core/orchestration/lane-tool-manifests.js.map +1 -1
- package/dist/core/orchestration/model-binding.d.ts.map +1 -1
- package/dist/core/orchestration/model-binding.js.map +1 -1
- package/dist/core/orchestration/policy-compiler.d.ts.map +1 -1
- package/dist/core/orchestration/policy-compiler.js +0 -3
- package/dist/core/orchestration/policy-compiler.js.map +1 -1
- package/dist/core/orchestration/policy-gate.d.ts.map +1 -1
- package/dist/core/orchestration/policy-gate.js +0 -2
- package/dist/core/orchestration/policy-gate.js.map +1 -1
- package/dist/core/orchestration/profile-registry.d.ts.map +1 -1
- package/dist/core/orchestration/profile-registry.js +1 -1
- package/dist/core/orchestration/profile-registry.js.map +1 -1
- package/dist/core/orchestration/profile-store.d.ts.map +1 -1
- package/dist/core/orchestration/profile-store.js +0 -3
- package/dist/core/orchestration/profile-store.js.map +1 -1
- package/dist/core/orchestration/risk-budget.d.ts.map +1 -1
- package/dist/core/orchestration/risk-budget.js.map +1 -1
- package/dist/core/orchestration/task-runtime.d.ts +1 -0
- package/dist/core/orchestration/task-runtime.d.ts.map +1 -1
- package/dist/core/orchestration/task-runtime.js +27 -42
- package/dist/core/orchestration/task-runtime.js.map +1 -1
- package/dist/core/orchestration/work-state-projection.d.ts.map +1 -1
- package/dist/core/orchestration/work-state-projection.js.map +1 -1
- package/dist/core/orchestration/worker-execution-contract.d.ts.map +1 -1
- package/dist/core/orchestration/worker-execution-contract.js.map +1 -1
- package/dist/core/orchestration/worker-result-adapter.d.ts.map +1 -1
- package/dist/core/orchestration/worker-result-adapter.js.map +1 -1
- package/dist/core/output-guard.d.ts.map +1 -1
- package/dist/core/output-guard.js.map +1 -1
- package/dist/core/package-manager.d.ts +3 -0
- package/dist/core/package-manager.d.ts.map +1 -1
- package/dist/core/package-manager.js +88 -353
- package/dist/core/package-manager.js.map +1 -1
- package/dist/core/process-identity.d.ts.map +1 -1
- package/dist/core/process-identity.js.map +1 -1
- package/dist/core/process-liveness.d.ts +3 -0
- package/dist/core/process-liveness.d.ts.map +1 -0
- package/dist/core/process-liveness.js +17 -0
- package/dist/core/process-liveness.js.map +1 -0
- package/dist/core/process-matrix/codes.d.ts.map +1 -1
- package/dist/core/process-matrix/resume-launcher.d.ts.map +1 -1
- package/dist/core/process-matrix/resume-launcher.js.map +1 -1
- package/dist/core/process-matrix/runtime.d.ts.map +1 -1
- package/dist/core/process-matrix/runtime.js.map +1 -1
- package/dist/core/process-matrix/store.d.ts.map +1 -1
- package/dist/core/process-matrix/store.js.map +1 -1
- package/dist/core/process-matrix/supervisor.d.ts.map +1 -1
- package/dist/core/process-matrix/supervisor.js.map +1 -1
- package/dist/core/profile-filter-controller.d.ts.map +1 -1
- package/dist/core/profile-filter-controller.js +7 -8
- package/dist/core/profile-filter-controller.js.map +1 -1
- package/dist/core/profile-registry.d.ts.map +1 -1
- package/dist/core/profile-registry.js +1 -2
- package/dist/core/profile-registry.js.map +1 -1
- package/dist/core/profile-resource-selection.d.ts.map +1 -1
- package/dist/core/profile-resource-selection.js +18 -59
- package/dist/core/profile-resource-selection.js.map +1 -1
- package/dist/core/prompt-markup.d.ts +3 -0
- package/dist/core/prompt-markup.d.ts.map +1 -0
- package/dist/core/prompt-markup.js +7 -0
- package/dist/core/prompt-markup.js.map +1 -0
- package/dist/core/prompt-templates.d.ts.map +1 -1
- package/dist/core/prompt-templates.js +13 -39
- package/dist/core/prompt-templates.js.map +1 -1
- package/dist/core/provider-display-names.d.ts.map +1 -1
- package/dist/core/python-runtime.d.ts.map +1 -1
- package/dist/core/python-runtime.js.map +1 -1
- package/dist/core/reflection-controller.d.ts +22 -1
- package/dist/core/reflection-controller.d.ts.map +1 -1
- package/dist/core/reflection-controller.js +143 -25
- package/dist/core/reflection-controller.js.map +1 -1
- package/dist/core/reload-blockers.d.ts +2 -1
- package/dist/core/reload-blockers.d.ts.map +1 -1
- package/dist/core/reload-blockers.js +4 -14
- package/dist/core/reload-blockers.js.map +1 -1
- package/dist/core/request-auth.d.ts.map +1 -1
- package/dist/core/request-auth.js.map +1 -1
- package/dist/core/research/automata-provider.d.ts.map +1 -1
- package/dist/core/research/automata-provider.js.map +1 -1
- package/dist/core/research/evidence-bundle.d.ts.map +1 -1
- package/dist/core/research/evidence-bundle.js.map +1 -1
- package/dist/core/research/lane-model-resolver.d.ts.map +1 -1
- package/dist/core/research/lane-model-resolver.js +0 -1
- package/dist/core/research/lane-model-resolver.js.map +1 -1
- package/dist/core/research/model-fitness-controller.d.ts.map +1 -1
- package/dist/core/research/model-fitness-controller.js +17 -33
- package/dist/core/research/model-fitness-controller.js.map +1 -1
- package/dist/core/research/model-fitness.d.ts.map +1 -1
- package/dist/core/research/model-fitness.js +4 -25
- package/dist/core/research/model-fitness.js.map +1 -1
- package/dist/core/research/research-gate.d.ts.map +1 -1
- package/dist/core/research/research-gate.js.map +1 -1
- package/dist/core/research/research-lane-controller.d.ts.map +1 -1
- package/dist/core/research/research-lane-controller.js +5 -10
- package/dist/core/research/research-lane-controller.js.map +1 -1
- package/dist/core/research/research-runner.d.ts +2 -4
- package/dist/core/research/research-runner.d.ts.map +1 -1
- package/dist/core/research/research-runner.js +17 -48
- package/dist/core/research/research-runner.js.map +1 -1
- package/dist/core/research/session-evidence-bundle.d.ts.map +1 -1
- package/dist/core/research/session-evidence-bundle.js.map +1 -1
- package/dist/core/research/workspace-collector.d.ts.map +1 -1
- package/dist/core/research/workspace-collector.js.map +1 -1
- package/dist/core/resolve-config-value.d.ts.map +1 -1
- package/dist/core/resolve-config-value.js.map +1 -1
- package/dist/core/resource-ignore.d.ts +6 -0
- package/dist/core/resource-ignore.d.ts.map +1 -0
- package/dist/core/resource-ignore.js +44 -0
- package/dist/core/resource-ignore.js.map +1 -0
- package/dist/core/resource-loader.d.ts +0 -1
- package/dist/core/resource-loader.d.ts.map +1 -1
- package/dist/core/resource-loader.js +52 -187
- package/dist/core/resource-loader.js.map +1 -1
- package/dist/core/resource-profile-blocks.d.ts +3 -1
- package/dist/core/resource-profile-blocks.d.ts.map +1 -1
- package/dist/core/resource-profile-blocks.js +8 -5
- package/dist/core/resource-profile-blocks.js.map +1 -1
- package/dist/core/resource-profile-equality.d.ts.map +1 -1
- package/dist/core/resource-profile-equality.js.map +1 -1
- package/dist/core/resource-traversal.d.ts +43 -0
- package/dist/core/resource-traversal.d.ts.map +1 -0
- package/dist/core/resource-traversal.js +84 -0
- package/dist/core/resource-traversal.js.map +1 -0
- package/dist/core/risk-classifier.d.ts.map +1 -1
- package/dist/core/risk-classifier.js.map +1 -1
- package/dist/core/runtime-builder.d.ts +4 -1
- package/dist/core/runtime-builder.d.ts.map +1 -1
- package/dist/core/runtime-builder.js +25 -50
- package/dist/core/runtime-builder.js.map +1 -1
- package/dist/core/scout-controller.d.ts.map +1 -1
- package/dist/core/scout-controller.js +0 -1
- package/dist/core/scout-controller.js.map +1 -1
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/secrets/credential-exposure-guard.d.ts.map +1 -1
- package/dist/core/secrets/credential-exposure-guard.js +101 -43
- package/dist/core/secrets/credential-exposure-guard.js.map +1 -1
- package/dist/core/secrets/secret-dotenv.d.ts.map +1 -1
- package/dist/core/secrets/secret-dotenv.js +0 -1
- package/dist/core/secrets/secret-dotenv.js.map +1 -1
- package/dist/core/secrets/secret-vault-format.d.ts.map +1 -1
- package/dist/core/secrets/secret-vault-format.js +0 -1
- package/dist/core/secrets/secret-vault-format.js.map +1 -1
- package/dist/core/secrets/secret-vault.d.ts.map +1 -1
- package/dist/core/secrets/secret-vault.js +2 -10
- package/dist/core/secrets/secret-vault.js.map +1 -1
- package/dist/core/security/secret-text.d.ts.map +1 -1
- package/dist/core/security/secret-text.js.map +1 -1
- package/dist/core/security/untrusted-boundary.d.ts.map +1 -1
- package/dist/core/security/untrusted-boundary.js.map +1 -1
- package/dist/core/session-analytics.d.ts.map +1 -1
- package/dist/core/session-analytics.js +18 -50
- package/dist/core/session-analytics.js.map +1 -1
- package/dist/core/session-artifact-bundle.d.ts.map +1 -1
- package/dist/core/session-artifact-bundle.js.map +1 -1
- package/dist/core/session-cwd.d.ts.map +1 -1
- package/dist/core/session-cwd.js +0 -1
- package/dist/core/session-cwd.js.map +1 -1
- package/dist/core/session-entry-index.d.ts +8 -0
- package/dist/core/session-entry-index.d.ts.map +1 -0
- package/dist/core/session-entry-index.js +16 -0
- package/dist/core/session-entry-index.js.map +1 -0
- package/dist/core/session-image-store.d.ts.map +1 -1
- package/dist/core/session-image-store.js +0 -3
- package/dist/core/session-image-store.js.map +1 -1
- package/dist/core/session-jsonl-writer.d.ts +3 -0
- package/dist/core/session-jsonl-writer.d.ts.map +1 -0
- package/dist/core/session-jsonl-writer.js +38 -0
- package/dist/core/session-jsonl-writer.js.map +1 -0
- package/dist/core/session-manager-factory.d.ts.map +1 -1
- package/dist/core/session-manager-factory.js.map +1 -1
- package/dist/core/session-role.d.ts.map +1 -1
- package/dist/core/session-role.js.map +1 -1
- package/dist/core/session-snapshot.d.ts.map +1 -1
- package/dist/core/session-snapshot.js.map +1 -1
- package/dist/core/session-supervision-runtime.d.ts.map +1 -1
- package/dist/core/session-supervision-runtime.js +1 -4
- package/dist/core/session-supervision-runtime.js.map +1 -1
- package/dist/core/session-tree-navigator.d.ts.map +1 -1
- package/dist/core/session-tree-navigator.js +0 -1
- package/dist/core/session-tree-navigator.js.map +1 -1
- package/dist/core/settings-manager.d.ts +2 -1
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +64 -162
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/skill-block.d.mts +8 -0
- package/dist/core/skill-block.mjs +52 -0
- package/dist/core/skill-discovery.d.ts +5 -0
- package/dist/core/skill-discovery.d.ts.map +1 -0
- package/dist/core/skill-discovery.js +34 -0
- package/dist/core/skill-discovery.js.map +1 -0
- package/dist/core/skills.d.ts.map +1 -1
- package/dist/core/skills.js +23 -159
- package/dist/core/skills.js.map +1 -1
- package/dist/core/slash-commands.d.ts.map +1 -1
- package/dist/core/source-info.d.ts.map +1 -1
- package/dist/core/source-info.js.map +1 -1
- package/dist/core/spawned-usage.d.ts +21 -0
- package/dist/core/spawned-usage.d.ts.map +1 -0
- package/dist/core/spawned-usage.js +29 -0
- package/dist/core/spawned-usage.js.map +1 -0
- package/dist/core/system-prompt-builder.d.ts +4 -0
- package/dist/core/system-prompt-builder.d.ts.map +1 -1
- package/dist/core/system-prompt-builder.js +15 -8
- package/dist/core/system-prompt-builder.js.map +1 -1
- package/dist/core/system-prompt.d.ts.map +1 -1
- package/dist/core/system-prompt.js +53 -35
- package/dist/core/system-prompt.js.map +1 -1
- package/dist/core/tasks/session-task-state.d.ts.map +1 -1
- package/dist/core/tasks/session-task-state.js.map +1 -1
- package/dist/core/tasks/task-command.d.ts.map +1 -1
- package/dist/core/tasks/task-command.js.map +1 -1
- package/dist/core/tasks/task-contract-monitor.d.ts.map +1 -1
- package/dist/core/tasks/task-contract-monitor.js.map +1 -1
- package/dist/core/tasks/task-projection.d.ts.map +1 -1
- package/dist/core/tasks/task-projection.js.map +1 -1
- package/dist/core/tasks/task-state.d.ts.map +1 -1
- package/dist/core/tasks/task-state.js.map +1 -1
- package/dist/core/text-preview.d.ts +4 -0
- package/dist/core/text-preview.d.ts.map +1 -0
- package/dist/core/text-preview.js +33 -0
- package/dist/core/text-preview.js.map +1 -0
- package/dist/core/timings.d.ts.map +1 -1
- package/dist/core/timings.js.map +1 -1
- package/dist/core/tool-capability-policy.d.ts.map +1 -1
- package/dist/core/tool-capability-policy.js.map +1 -1
- package/dist/core/tool-gate-controller.d.ts.map +1 -1
- package/dist/core/tool-gate-controller.js +86 -87
- package/dist/core/tool-gate-controller.js.map +1 -1
- package/dist/core/tool-protocol-controller.d.ts +4 -1
- package/dist/core/tool-protocol-controller.d.ts.map +1 -1
- package/dist/core/tool-protocol-controller.js +19 -23
- package/dist/core/tool-protocol-controller.js.map +1 -1
- package/dist/core/tool-recovery-log-records.d.ts.map +1 -1
- package/dist/core/tool-recovery-log-records.js.map +1 -1
- package/dist/core/tool-recovery-log-worker.d.ts.map +1 -1
- package/dist/core/tool-recovery-log-worker.js.map +1 -1
- package/dist/core/tool-recovery-logger.d.ts.map +1 -1
- package/dist/core/tool-recovery-logger.js +12 -24
- package/dist/core/tool-recovery-logger.js.map +1 -1
- package/dist/core/tool-recovery-stats.d.ts.map +1 -1
- package/dist/core/tool-recovery-stats.js +16 -22
- package/dist/core/tool-recovery-stats.js.map +1 -1
- package/dist/core/tool-repair-health.d.ts.map +1 -1
- package/dist/core/tool-repair-health.js.map +1 -1
- package/dist/core/tool-repair-settings.d.ts.map +1 -1
- package/dist/core/tool-repair-settings.js.map +1 -1
- package/dist/core/tool-selection/expected-utility.d.ts.map +1 -1
- package/dist/core/tool-selection/expected-utility.js.map +1 -1
- package/dist/core/tool-selection/promotion.d.ts.map +1 -1
- package/dist/core/tool-selection/promotion.js.map +1 -1
- package/dist/core/tool-selection/tool-performance-store.d.ts +2 -0
- package/dist/core/tool-selection/tool-performance-store.d.ts.map +1 -1
- package/dist/core/tool-selection/tool-performance-store.js +49 -7
- package/dist/core/tool-selection/tool-performance-store.js.map +1 -1
- package/dist/core/tool-selection/tool-phase-timing.d.ts +19 -0
- package/dist/core/tool-selection/tool-phase-timing.d.ts.map +1 -0
- package/dist/core/tool-selection/tool-phase-timing.js +63 -0
- package/dist/core/tool-selection/tool-phase-timing.js.map +1 -0
- package/dist/core/tool-selection/tool-selection-controller.d.ts +2 -5
- package/dist/core/tool-selection/tool-selection-controller.d.ts.map +1 -1
- package/dist/core/tool-selection/tool-selection-controller.js +50 -30
- package/dist/core/tool-selection/tool-selection-controller.js.map +1 -1
- package/dist/core/toolkit/reflex-interpreter.d.ts +16 -0
- package/dist/core/toolkit/reflex-interpreter.d.ts.map +1 -1
- package/dist/core/toolkit/reflex-interpreter.js +21 -0
- package/dist/core/toolkit/reflex-interpreter.js.map +1 -1
- package/dist/core/toolkit/script-registry.d.ts.map +1 -1
- package/dist/core/toolkit/script-registry.js.map +1 -1
- package/dist/core/toolkit/script-runner.d.ts.map +1 -1
- package/dist/core/toolkit/script-runner.js.map +1 -1
- package/dist/core/tools/artifact-retrieve.d.ts.map +1 -1
- package/dist/core/tools/artifact-retrieve.js.map +1 -1
- package/dist/core/tools/ask-question.d.ts +2 -3
- package/dist/core/tools/ask-question.d.ts.map +1 -1
- package/dist/core/tools/ask-question.js +14 -40
- package/dist/core/tools/ask-question.js.map +1 -1
- package/dist/core/tools/bash.d.ts +2 -0
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +83 -30
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/core/tools/context-scout.d.ts.map +1 -1
- package/dist/core/tools/context-scout.js.map +1 -1
- package/dist/core/tools/delegate-status.d.ts.map +1 -1
- package/dist/core/tools/delegate-status.js +9 -7
- package/dist/core/tools/delegate-status.js.map +1 -1
- package/dist/core/tools/delegate.d.ts.map +1 -1
- package/dist/core/tools/delegate.js +6 -6
- package/dist/core/tools/delegate.js.map +1 -1
- package/dist/core/tools/edit-diff.d.ts.map +1 -1
- package/dist/core/tools/edit-diff.js.map +1 -1
- package/dist/core/tools/edit.d.ts.map +1 -1
- package/dist/core/tools/edit.js.map +1 -1
- package/dist/core/tools/extensionify.d.ts.map +1 -1
- package/dist/core/tools/extensionify.js.map +1 -1
- package/dist/core/tools/fff-search-backend.d.ts +19 -0
- package/dist/core/tools/fff-search-backend.d.ts.map +1 -1
- package/dist/core/tools/fff-search-backend.js +28 -2
- package/dist/core/tools/fff-search-backend.js.map +1 -1
- package/dist/core/tools/file-encoding-policy.d.ts.map +1 -1
- package/dist/core/tools/file-encoding-policy.js.map +1 -1
- package/dist/core/tools/file-mutation-queue.d.ts.map +1 -1
- package/dist/core/tools/file-mutation-queue.js.map +1 -1
- package/dist/core/tools/find.d.ts +1 -1
- package/dist/core/tools/find.d.ts.map +1 -1
- package/dist/core/tools/find.js +44 -108
- package/dist/core/tools/find.js.map +1 -1
- package/dist/core/tools/git-filter.d.ts.map +1 -1
- package/dist/core/tools/git-filter.js.map +1 -1
- package/dist/core/tools/goal.d.ts.map +1 -1
- package/dist/core/tools/goal.js +7 -7
- package/dist/core/tools/goal.js.map +1 -1
- package/dist/core/tools/grep.d.ts +1 -1
- package/dist/core/tools/grep.d.ts.map +1 -1
- package/dist/core/tools/grep.js +42 -102
- package/dist/core/tools/grep.js.map +1 -1
- package/dist/core/tools/index.d.ts.map +1 -1
- package/dist/core/tools/index.js.map +1 -1
- package/dist/core/tools/ls.d.ts.map +1 -1
- package/dist/core/tools/ls.js +20 -36
- package/dist/core/tools/ls.js.map +1 -1
- package/dist/core/tools/model-fitness.d.ts.map +1 -1
- package/dist/core/tools/model-fitness.js.map +1 -1
- package/dist/core/tools/orchestration-panel.d.ts +5 -0
- package/dist/core/tools/orchestration-panel.d.ts.map +1 -1
- package/dist/core/tools/orchestration-panel.js +5 -5
- package/dist/core/tools/orchestration-panel.js.map +1 -1
- package/dist/core/tools/output-accumulator.d.ts +2 -0
- package/dist/core/tools/output-accumulator.d.ts.map +1 -1
- package/dist/core/tools/output-accumulator.js +24 -36
- package/dist/core/tools/output-accumulator.js.map +1 -1
- package/dist/core/tools/path-utils.d.ts.map +1 -1
- package/dist/core/tools/path-utils.js.map +1 -1
- package/dist/core/tools/persistent-process-coordinator.d.ts +31 -0
- package/dist/core/tools/persistent-process-coordinator.d.ts.map +1 -0
- package/dist/core/tools/persistent-process-coordinator.js +123 -0
- package/dist/core/tools/persistent-process-coordinator.js.map +1 -0
- package/dist/core/tools/python.d.ts.map +1 -1
- package/dist/core/tools/python.js.map +1 -1
- package/dist/core/tools/read.d.ts.map +1 -1
- package/dist/core/tools/read.js +14 -13
- package/dist/core/tools/read.js.map +1 -1
- package/dist/core/tools/render-utils.d.ts +29 -0
- package/dist/core/tools/render-utils.d.ts.map +1 -1
- package/dist/core/tools/render-utils.js +31 -1
- package/dist/core/tools/render-utils.js.map +1 -1
- package/dist/core/tools/run-process.d.ts.map +1 -1
- package/dist/core/tools/run-process.js.map +1 -1
- package/dist/core/tools/run-toolkit-script.d.ts.map +1 -1
- package/dist/core/tools/run-toolkit-script.js.map +1 -1
- package/dist/core/tools/search-command-guard.d.ts +10 -0
- package/dist/core/tools/search-command-guard.d.ts.map +1 -1
- package/dist/core/tools/search-command-guard.js +118 -31
- package/dist/core/tools/search-command-guard.js.map +1 -1
- package/dist/core/tools/search-router.d.ts.map +1 -1
- package/dist/core/tools/search-router.js.map +1 -1
- package/dist/core/tools/search-tool-runtime.d.ts +19 -0
- package/dist/core/tools/search-tool-runtime.d.ts.map +1 -0
- package/dist/core/tools/search-tool-runtime.js +12 -0
- package/dist/core/tools/search-tool-runtime.js.map +1 -0
- package/dist/core/tools/secret-store.d.ts.map +1 -1
- package/dist/core/tools/secret-store.js.map +1 -1
- package/dist/core/tools/shell-command-parser.d.ts.map +1 -1
- package/dist/core/tools/shell-command-parser.js.map +1 -1
- package/dist/core/tools/shell-contract-router.d.ts.map +1 -1
- package/dist/core/tools/shell-contract-router.js +4 -1
- package/dist/core/tools/shell-contract-router.js.map +1 -1
- package/dist/core/tools/shell-execution-session.d.ts +4 -0
- package/dist/core/tools/shell-execution-session.d.ts.map +1 -0
- package/dist/core/tools/shell-execution-session.js +11 -0
- package/dist/core/tools/shell-execution-session.js.map +1 -0
- package/dist/core/tools/shell-output-projection.d.ts +49 -0
- package/dist/core/tools/shell-output-projection.d.ts.map +1 -0
- package/dist/core/tools/shell-output-projection.js +381 -0
- package/dist/core/tools/shell-output-projection.js.map +1 -0
- package/dist/core/tools/shell-session.d.ts +2 -13
- package/dist/core/tools/shell-session.d.ts.map +1 -1
- package/dist/core/tools/shell-session.js +36 -136
- package/dist/core/tools/shell-session.js.map +1 -1
- package/dist/core/tools/skill-audit.d.ts.map +1 -1
- package/dist/core/tools/skill-audit.js.map +1 -1
- package/dist/core/tools/skillify.d.ts.map +1 -1
- package/dist/core/tools/skillify.js.map +1 -1
- package/dist/core/tools/task-steps.d.ts +8 -8
- package/dist/core/tools/task-steps.d.ts.map +1 -1
- package/dist/core/tools/task-steps.js +17 -18
- package/dist/core/tools/task-steps.js.map +1 -1
- package/dist/core/tools/tmux-dispatch.d.ts.map +1 -1
- package/dist/core/tools/tmux-dispatch.js.map +1 -1
- package/dist/core/tools/tool-definition-wrapper.d.ts.map +1 -1
- package/dist/core/tools/tool-definition-wrapper.js.map +1 -1
- package/dist/core/tools/tool-task.d.ts +23 -0
- package/dist/core/tools/tool-task.d.ts.map +1 -0
- package/dist/core/tools/tool-task.js +93 -0
- package/dist/core/tools/tool-task.js.map +1 -0
- package/dist/core/tools/windows-shell-engine.d.ts +17 -11
- package/dist/core/tools/windows-shell-engine.d.ts.map +1 -1
- package/dist/core/tools/windows-shell-engine.js +339 -117
- package/dist/core/tools/windows-shell-engine.js.map +1 -1
- package/dist/core/tools/windows-shell-state.d.ts.map +1 -1
- package/dist/core/tools/windows-shell-state.js.map +1 -1
- package/dist/core/tools/worktree-sync.d.ts.map +1 -1
- package/dist/core/tools/worktree-sync.js +8 -12
- package/dist/core/tools/worktree-sync.js.map +1 -1
- package/dist/core/tools/write.d.ts.map +1 -1
- package/dist/core/tools/write.js +0 -1
- package/dist/core/tools/write.js.map +1 -1
- package/dist/core/trust-manager.d.ts.map +1 -1
- package/dist/core/trust-manager.js +7 -40
- package/dist/core/trust-manager.js.map +1 -1
- package/dist/core/util/atomic-file.d.ts +19 -0
- package/dist/core/util/atomic-file.d.ts.map +1 -1
- package/dist/core/util/atomic-file.js +50 -15
- package/dist/core/util/atomic-file.js.map +1 -1
- package/dist/core/util/bounded-file.d.ts.map +1 -1
- package/dist/core/util/bounded-file.js.map +1 -1
- package/dist/core/util/bounded-jsonl.d.ts.map +1 -1
- package/dist/core/util/bounded-jsonl.js +2 -9
- package/dist/core/util/bounded-jsonl.js.map +1 -1
- package/dist/core/util/bounded-value.d.ts.map +1 -1
- package/dist/core/util/bounded-value.js.map +1 -1
- package/dist/core/util/json-size.d.ts +3 -0
- package/dist/core/util/json-size.d.ts.map +1 -0
- package/dist/core/util/json-size.js +95 -0
- package/dist/core/util/json-size.js.map +1 -0
- package/dist/core/util/minimatch-cache.d.ts.map +1 -1
- package/dist/core/util/minimatch-cache.js.map +1 -1
- package/dist/core/util/value-guards.d.ts.map +1 -1
- package/dist/core/util/value-guards.js.map +1 -1
- package/dist/core/worktree-sync/codes.d.ts.map +1 -1
- package/dist/core/worktree-sync/git-engine.d.ts.map +1 -1
- package/dist/core/worktree-sync/git-engine.js +20 -36
- package/dist/core/worktree-sync/git-engine.js.map +1 -1
- package/dist/core/worktree-sync/lane-gate.d.ts.map +1 -1
- package/dist/core/worktree-sync/lane-gate.js +1 -4
- package/dist/core/worktree-sync/lane-gate.js.map +1 -1
- package/dist/core/worktree-sync/runtime.d.ts.map +1 -1
- package/dist/core/worktree-sync/runtime.js.map +1 -1
- package/dist/core/worktree-sync/store.d.ts.map +1 -1
- package/dist/core/worktree-sync/store.js.map +1 -1
- package/dist/core/worktree-sync/watcher.d.ts.map +1 -1
- package/dist/core/worktree-sync/watcher.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +10 -32
- package/dist/main.js.map +1 -1
- package/dist/migrations.d.ts.map +1 -1
- package/dist/migrations.js +6 -19
- package/dist/migrations.js.map +1 -1
- package/dist/modes/index.d.ts.map +1 -1
- package/dist/modes/interactive/auth-dialogs-controller.d.ts +3 -0
- package/dist/modes/interactive/auth-dialogs-controller.d.ts.map +1 -1
- package/dist/modes/interactive/auth-dialogs-controller.js +96 -132
- package/dist/modes/interactive/auth-dialogs-controller.js.map +1 -1
- package/dist/modes/interactive/auto-learn-controller.d.ts +1 -31
- package/dist/modes/interactive/auto-learn-controller.d.ts.map +1 -1
- package/dist/modes/interactive/auto-learn-controller.js +86 -307
- package/dist/modes/interactive/auto-learn-controller.js.map +1 -1
- package/dist/modes/interactive/autocomplete-provider.d.ts.map +1 -1
- package/dist/modes/interactive/autocomplete-provider.js.map +1 -1
- package/dist/modes/interactive/autonomy-commands.d.ts.map +1 -1
- package/dist/modes/interactive/autonomy-commands.js +2 -8
- package/dist/modes/interactive/autonomy-commands.js.map +1 -1
- package/dist/modes/interactive/clipboard-input.d.ts +5 -1
- package/dist/modes/interactive/clipboard-input.d.ts.map +1 -1
- package/dist/modes/interactive/clipboard-input.js +17 -0
- package/dist/modes/interactive/clipboard-input.js.map +1 -1
- package/dist/modes/interactive/compaction-queue.d.ts.map +1 -1
- package/dist/modes/interactive/compaction-queue.js +13 -18
- package/dist/modes/interactive/compaction-queue.js.map +1 -1
- package/dist/modes/interactive/components/activity-lane.d.ts.map +1 -1
- package/dist/modes/interactive/components/activity-lane.js +6 -10
- package/dist/modes/interactive/components/activity-lane.js.map +1 -1
- package/dist/modes/interactive/components/armin.d.ts +1 -0
- package/dist/modes/interactive/components/armin.d.ts.map +1 -1
- package/dist/modes/interactive/components/armin.js +10 -21
- package/dist/modes/interactive/components/armin.js.map +1 -1
- package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/assistant-message.js +1 -6
- package/dist/modes/interactive/components/assistant-message.js.map +1 -1
- package/dist/modes/interactive/components/bash-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/bash-execution.js +4 -9
- package/dist/modes/interactive/components/bash-execution.js.map +1 -1
- package/dist/modes/interactive/components/bordered-loader.d.ts.map +1 -1
- package/dist/modes/interactive/components/bordered-loader.js +0 -3
- package/dist/modes/interactive/components/bordered-loader.js.map +1 -1
- package/dist/modes/interactive/components/branch-summary-message.d.ts +3 -8
- package/dist/modes/interactive/components/branch-summary-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/branch-summary-message.js +13 -35
- package/dist/modes/interactive/components/branch-summary-message.js.map +1 -1
- package/dist/modes/interactive/components/compaction-summary-message.d.ts +3 -8
- package/dist/modes/interactive/components/compaction-summary-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/compaction-summary-message.js +14 -36
- package/dist/modes/interactive/components/compaction-summary-message.js.map +1 -1
- package/dist/modes/interactive/components/config-selector.d.ts +1 -0
- package/dist/modes/interactive/components/config-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/config-selector.js +20 -43
- package/dist/modes/interactive/components/config-selector.js.map +1 -1
- package/dist/modes/interactive/components/countdown-timer.d.ts.map +1 -1
- package/dist/modes/interactive/components/countdown-timer.js +0 -5
- package/dist/modes/interactive/components/countdown-timer.js.map +1 -1
- package/dist/modes/interactive/components/custom-editor.d.ts +2 -0
- package/dist/modes/interactive/components/custom-editor.d.ts.map +1 -1
- package/dist/modes/interactive/components/custom-editor.js +4 -8
- package/dist/modes/interactive/components/custom-editor.js.map +1 -1
- package/dist/modes/interactive/components/custom-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/custom-message.js +1 -6
- package/dist/modes/interactive/components/custom-message.js.map +1 -1
- package/dist/modes/interactive/components/daxnuts.d.ts.map +1 -1
- package/dist/modes/interactive/components/daxnuts.js +6 -8
- package/dist/modes/interactive/components/daxnuts.js.map +1 -1
- package/dist/modes/interactive/components/diff.d.ts.map +1 -1
- package/dist/modes/interactive/components/diff.js.map +1 -1
- package/dist/modes/interactive/components/dynamic-border.d.ts.map +1 -1
- package/dist/modes/interactive/components/dynamic-border.js +0 -1
- package/dist/modes/interactive/components/dynamic-border.js.map +1 -1
- package/dist/modes/interactive/components/earendil-announcement.d.ts.map +1 -1
- package/dist/modes/interactive/components/earendil-announcement.js.map +1 -1
- package/dist/modes/interactive/components/expandable-markdown-message.d.ts +21 -0
- package/dist/modes/interactive/components/expandable-markdown-message.d.ts.map +1 -0
- package/dist/modes/interactive/components/expandable-markdown-message.js +48 -0
- package/dist/modes/interactive/components/expandable-markdown-message.js.map +1 -0
- package/dist/modes/interactive/components/expandable-text.d.ts.map +1 -1
- package/dist/modes/interactive/components/expandable-text.js +0 -2
- package/dist/modes/interactive/components/expandable-text.js.map +1 -1
- package/dist/modes/interactive/components/extension-editor.d.ts.map +1 -1
- package/dist/modes/interactive/components/extension-editor.js +1 -9
- package/dist/modes/interactive/components/extension-editor.js.map +1 -1
- package/dist/modes/interactive/components/extension-input.d.ts.map +1 -1
- package/dist/modes/interactive/components/extension-input.js +2 -8
- package/dist/modes/interactive/components/extension-input.js.map +1 -1
- package/dist/modes/interactive/components/extension-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/extension-selector.js +5 -20
- package/dist/modes/interactive/components/extension-selector.js.map +1 -1
- package/dist/modes/interactive/components/fitness-role-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/fitness-role-selector.js +0 -1
- package/dist/modes/interactive/components/fitness-role-selector.js.map +1 -1
- package/dist/modes/interactive/components/footer.d.ts.map +1 -1
- package/dist/modes/interactive/components/footer.js +1 -5
- package/dist/modes/interactive/components/footer.js.map +1 -1
- package/dist/modes/interactive/components/index.d.ts.map +1 -1
- package/dist/modes/interactive/components/keybinding-hints.d.ts.map +1 -1
- package/dist/modes/interactive/components/keybinding-hints.js.map +1 -1
- package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
- package/dist/modes/interactive/components/login-dialog.js +4 -10
- package/dist/modes/interactive/components/login-dialog.js.map +1 -1
- package/dist/modes/interactive/components/model-selector.d.ts +2 -2
- package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/model-selector.js +21 -44
- package/dist/modes/interactive/components/model-selector.js.map +1 -1
- package/dist/modes/interactive/components/model-suggestion-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/model-suggestion-selector.js +0 -1
- package/dist/modes/interactive/components/model-suggestion-selector.js.map +1 -1
- package/dist/modes/interactive/components/oauth-selector.d.ts +1 -1
- package/dist/modes/interactive/components/oauth-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/oauth-selector.js +16 -32
- package/dist/modes/interactive/components/oauth-selector.js.map +1 -1
- package/dist/modes/interactive/components/profile-resource-editor.d.ts +3 -4
- package/dist/modes/interactive/components/profile-resource-editor.d.ts.map +1 -1
- package/dist/modes/interactive/components/profile-resource-editor.js +34 -93
- package/dist/modes/interactive/components/profile-resource-editor.js.map +1 -1
- package/dist/modes/interactive/components/profile-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/profile-selector.js +0 -1
- package/dist/modes/interactive/components/profile-selector.js.map +1 -1
- package/dist/modes/interactive/components/scoped-models-selector.d.ts +3 -4
- package/dist/modes/interactive/components/scoped-models-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/scoped-models-selector.js +34 -79
- package/dist/modes/interactive/components/scoped-models-selector.js.map +1 -1
- package/dist/modes/interactive/components/selector-list.d.ts +63 -0
- package/dist/modes/interactive/components/selector-list.d.ts.map +1 -0
- package/dist/modes/interactive/components/selector-list.js +186 -0
- package/dist/modes/interactive/components/selector-list.js.map +1 -0
- package/dist/modes/interactive/components/session-selector-search.d.ts.map +1 -1
- package/dist/modes/interactive/components/session-selector-search.js.map +1 -1
- package/dist/modes/interactive/components/session-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/session-selector.js +34 -59
- package/dist/modes/interactive/components/session-selector.js.map +1 -1
- package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/settings-selector.js +40 -138
- package/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/dist/modes/interactive/components/show-images-selector.d.ts +2 -4
- package/dist/modes/interactive/components/show-images-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/show-images-selector.js +9 -28
- package/dist/modes/interactive/components/show-images-selector.js.map +1 -1
- package/dist/modes/interactive/components/skill-invocation-message.d.ts +3 -8
- package/dist/modes/interactive/components/skill-invocation-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/skill-invocation-message.js +12 -40
- package/dist/modes/interactive/components/skill-invocation-message.js.map +1 -1
- package/dist/modes/interactive/components/theme-selector.d.ts +2 -5
- package/dist/modes/interactive/components/theme-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/theme-selector.js +11 -37
- package/dist/modes/interactive/components/theme-selector.js.map +1 -1
- package/dist/modes/interactive/components/thinking-selector.d.ts +2 -4
- package/dist/modes/interactive/components/thinking-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/thinking-selector.js +9 -31
- package/dist/modes/interactive/components/thinking-selector.js.map +1 -1
- package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/tool-execution.js +9 -28
- package/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/dist/modes/interactive/components/tool-group.d.ts.map +1 -1
- package/dist/modes/interactive/components/tool-group.js +2 -3
- package/dist/modes/interactive/components/tool-group.js.map +1 -1
- package/dist/modes/interactive/components/tool-panel-registry.d.ts.map +1 -1
- package/dist/modes/interactive/components/tool-panel-registry.js +5 -3
- package/dist/modes/interactive/components/tool-panel-registry.js.map +1 -1
- package/dist/modes/interactive/components/tool-title.d.ts.map +1 -1
- package/dist/modes/interactive/components/tool-title.js +0 -4
- package/dist/modes/interactive/components/tool-title.js.map +1 -1
- package/dist/modes/interactive/components/transcript-pager.d.ts +26 -0
- package/dist/modes/interactive/components/transcript-pager.d.ts.map +1 -0
- package/dist/modes/interactive/components/transcript-pager.js +81 -0
- package/dist/modes/interactive/components/transcript-pager.js.map +1 -0
- package/dist/modes/interactive/components/tree-selector.d.ts +1 -12
- package/dist/modes/interactive/components/tree-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/tree-selector.js +42 -402
- package/dist/modes/interactive/components/tree-selector.js.map +1 -1
- package/dist/modes/interactive/components/trust-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/trust-selector.js +4 -16
- package/dist/modes/interactive/components/trust-selector.js.map +1 -1
- package/dist/modes/interactive/components/usage-action-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/usage-action-selector.js +2 -10
- package/dist/modes/interactive/components/usage-action-selector.js.map +1 -1
- package/dist/modes/interactive/components/user-message-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/user-message-selector.js +3 -6
- package/dist/modes/interactive/components/user-message-selector.js.map +1 -1
- package/dist/modes/interactive/components/user-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/user-message.js +0 -1
- package/dist/modes/interactive/components/user-message.js.map +1 -1
- package/dist/modes/interactive/components/visual-truncate.d.ts.map +1 -1
- package/dist/modes/interactive/components/visual-truncate.js.map +1 -1
- package/dist/modes/interactive/config-backup.d.ts.map +1 -1
- package/dist/modes/interactive/config-backup.js.map +1 -1
- package/dist/modes/interactive/editor-overlay-host.d.ts.map +1 -1
- package/dist/modes/interactive/editor-overlay-host.js +0 -3
- package/dist/modes/interactive/editor-overlay-host.js.map +1 -1
- package/dist/modes/interactive/extension-ui-host.d.ts +2 -0
- package/dist/modes/interactive/extension-ui-host.d.ts.map +1 -1
- package/dist/modes/interactive/extension-ui-host.js +51 -72
- package/dist/modes/interactive/extension-ui-host.js.map +1 -1
- package/dist/modes/interactive/external-editor.d.ts.map +1 -1
- package/dist/modes/interactive/external-editor.js +2 -15
- package/dist/modes/interactive/external-editor.js.map +1 -1
- package/dist/modes/interactive/history-reload-math.d.ts.map +1 -1
- package/dist/modes/interactive/history-reload-math.js.map +1 -1
- package/dist/modes/interactive/interactive-event-controller.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-event-controller.js +23 -16
- package/dist/modes/interactive/interactive-event-controller.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +13 -4
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +126 -207
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/interactive-selection-prompts.d.ts +20 -0
- package/dist/modes/interactive/interactive-selection-prompts.d.ts.map +1 -0
- package/dist/modes/interactive/interactive-selection-prompts.js +43 -0
- package/dist/modes/interactive/interactive-selection-prompts.js.map +1 -0
- package/dist/modes/interactive/key-handlers.d.ts +2 -1
- package/dist/modes/interactive/key-handlers.d.ts.map +1 -1
- package/dist/modes/interactive/key-handlers.js +4 -2
- package/dist/modes/interactive/key-handlers.js.map +1 -1
- package/dist/modes/interactive/loaded-resources-view.d.ts.map +1 -1
- package/dist/modes/interactive/loaded-resources-view.js.map +1 -1
- package/dist/modes/interactive/local-model-commands.d.ts.map +1 -1
- package/dist/modes/interactive/local-model-commands.js +4 -9
- package/dist/modes/interactive/local-model-commands.js.map +1 -1
- package/dist/modes/interactive/model-fitness-presentation.d.ts +21 -0
- package/dist/modes/interactive/model-fitness-presentation.d.ts.map +1 -0
- package/dist/modes/interactive/model-fitness-presentation.js +13 -0
- package/dist/modes/interactive/model-fitness-presentation.js.map +1 -0
- package/dist/modes/interactive/profile-menu-controller.d.ts +2 -0
- package/dist/modes/interactive/profile-menu-controller.d.ts.map +1 -1
- package/dist/modes/interactive/profile-menu-controller.js +79 -171
- package/dist/modes/interactive/profile-menu-controller.js.map +1 -1
- package/dist/modes/interactive/report-commands.d.ts +2 -0
- package/dist/modes/interactive/report-commands.d.ts.map +1 -1
- package/dist/modes/interactive/report-commands.js +12 -6
- package/dist/modes/interactive/report-commands.js.map +1 -1
- package/dist/modes/interactive/resource-display.d.ts.map +1 -1
- package/dist/modes/interactive/resource-display.js.map +1 -1
- package/dist/modes/interactive/resource-shell-commands.d.ts.map +1 -1
- package/dist/modes/interactive/resource-shell-commands.js +6 -23
- package/dist/modes/interactive/resource-shell-commands.js.map +1 -1
- package/dist/modes/interactive/session-flow-commands.d.ts.map +1 -1
- package/dist/modes/interactive/session-flow-commands.js +21 -25
- package/dist/modes/interactive/session-flow-commands.js.map +1 -1
- package/dist/modes/interactive/session-io-commands.d.ts.map +1 -1
- package/dist/modes/interactive/session-io-commands.js.map +1 -1
- package/dist/modes/interactive/session-replacement-errors.d.ts.map +1 -1
- package/dist/modes/interactive/session-replacement-errors.js.map +1 -1
- package/dist/modes/interactive/settings-selector-flow.d.ts.map +1 -1
- package/dist/modes/interactive/settings-selector-flow.js.map +1 -1
- package/dist/modes/interactive/signal-lifecycle.d.ts.map +1 -1
- package/dist/modes/interactive/signal-lifecycle.js.map +1 -1
- package/dist/modes/interactive/startup-checks.d.ts.map +1 -1
- package/dist/modes/interactive/startup-checks.js +12 -8
- package/dist/modes/interactive/startup-checks.js.map +1 -1
- package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
- package/dist/modes/interactive/theme/theme.js +10 -76
- package/dist/modes/interactive/theme/theme.js.map +1 -1
- package/dist/modes/interactive/usage-commands.d.ts.map +1 -1
- package/dist/modes/interactive/usage-commands.js.map +1 -1
- package/dist/modes/print-mode.d.ts.map +1 -1
- package/dist/modes/print-mode.js +5 -22
- package/dist/modes/print-mode.js.map +1 -1
- package/dist/modes/rpc/jsonl.d.ts.map +1 -1
- package/dist/modes/rpc/jsonl.js +1 -1
- package/dist/modes/rpc/jsonl.js.map +1 -1
- package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-client.js +7 -8
- package/dist/modes/rpc/rpc-client.js.map +1 -1
- package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-mode.js +5 -20
- package/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-types.js.map +1 -1
- package/dist/modes/termination-signals.d.ts +4 -0
- package/dist/modes/termination-signals.d.ts.map +1 -0
- package/dist/modes/termination-signals.js +21 -0
- package/dist/modes/termination-signals.js.map +1 -0
- package/dist/package-manager-cli.d.ts.map +1 -1
- package/dist/package-manager-cli.js.map +1 -1
- package/dist/utils/ansi-colors.d.ts +5 -0
- package/dist/utils/ansi-colors.d.ts.map +1 -0
- package/dist/utils/ansi-colors.js +38 -0
- package/dist/utils/ansi-colors.js.map +1 -0
- package/dist/utils/ansi.d.ts.map +1 -1
- package/dist/utils/ansi.js.map +1 -1
- package/dist/utils/changelog.d.ts.map +1 -1
- package/dist/utils/changelog.js.map +1 -1
- package/dist/utils/child-process.d.ts.map +1 -1
- package/dist/utils/child-process.js.map +1 -1
- package/dist/utils/clipboard-image.d.ts.map +1 -1
- package/dist/utils/clipboard-image.js.map +1 -1
- package/dist/utils/clipboard-native.d.ts.map +1 -1
- package/dist/utils/clipboard-native.js.map +1 -1
- package/dist/utils/clipboard.d.ts.map +1 -1
- package/dist/utils/clipboard.js.map +1 -1
- package/dist/utils/deprecation.d.ts.map +1 -1
- package/dist/utils/deprecation.js.map +1 -1
- package/dist/utils/exif-orientation.d.ts.map +1 -1
- package/dist/utils/exif-orientation.js.map +1 -1
- package/dist/utils/external-editor-command.d.ts.map +1 -1
- package/dist/utils/external-editor-command.js.map +1 -1
- package/dist/utils/frontmatter.d.ts.map +1 -1
- package/dist/utils/frontmatter.js.map +1 -1
- package/dist/utils/fs-watch.d.ts.map +1 -1
- package/dist/utils/fs-watch.js.map +1 -1
- package/dist/utils/git.d.ts.map +1 -1
- package/dist/utils/git.js +20 -28
- package/dist/utils/git.js.map +1 -1
- package/dist/utils/highlight-js-languages.d.ts.map +1 -1
- package/dist/utils/html.d.ts.map +1 -1
- package/dist/utils/html.js.map +1 -1
- package/dist/utils/image-convert.d.ts.map +1 -1
- package/dist/utils/image-convert.js.map +1 -1
- package/dist/utils/image-resize-core.d.ts.map +1 -1
- package/dist/utils/image-resize-core.js.map +1 -1
- package/dist/utils/image-resize-worker.d.ts.map +1 -1
- package/dist/utils/image-resize-worker.js.map +1 -1
- package/dist/utils/image-resize.d.ts.map +1 -1
- package/dist/utils/image-resize.js.map +1 -1
- package/dist/utils/json.d.ts.map +1 -1
- package/dist/utils/json.js.map +1 -1
- package/dist/utils/mime.d.ts.map +1 -1
- package/dist/utils/mime.js.map +1 -1
- package/dist/utils/open-browser.d.ts.map +1 -1
- package/dist/utils/open-browser.js.map +1 -1
- package/dist/utils/paths.d.ts.map +1 -1
- package/dist/utils/paths.js.map +1 -1
- package/dist/utils/photon.d.ts.map +1 -1
- package/dist/utils/photon.js.map +1 -1
- package/dist/utils/pi-user-agent.d.ts.map +1 -1
- package/dist/utils/pi-user-agent.js.map +1 -1
- package/dist/utils/platform.d.ts.map +1 -1
- package/dist/utils/platform.js.map +1 -1
- package/dist/utils/process-memory.d.ts.map +1 -1
- package/dist/utils/process-memory.js.map +1 -1
- package/dist/utils/safe-write-stream.d.ts.map +1 -1
- package/dist/utils/safe-write-stream.js.map +1 -1
- package/dist/utils/shell.d.ts.map +1 -1
- package/dist/utils/shell.js.map +1 -1
- package/dist/utils/sleep.d.ts.map +1 -1
- package/dist/utils/sleep.js +2 -15
- package/dist/utils/sleep.js.map +1 -1
- package/dist/utils/stdin-events.d.ts +8 -0
- package/dist/utils/stdin-events.d.ts.map +1 -0
- package/dist/utils/stdin-events.js +19 -0
- package/dist/utils/stdin-events.js.map +1 -0
- package/dist/utils/syntax-highlight.d.ts.map +1 -1
- package/dist/utils/syntax-highlight.js +20 -13
- package/dist/utils/syntax-highlight.js.map +1 -1
- package/dist/utils/tools-manager.d.ts +6 -1
- package/dist/utils/tools-manager.d.ts.map +1 -1
- package/dist/utils/tools-manager.js +59 -2
- package/dist/utils/tools-manager.js.map +1 -1
- package/dist/utils/version-check.d.ts.map +1 -1
- package/dist/utils/version-check.js.map +1 -1
- package/dist/utils/windows-self-update.d.ts.map +1 -1
- package/dist/utils/windows-self-update.js.map +1 -1
- package/dist/utils/work-directory.d.ts.map +1 -1
- package/dist/utils/work-directory.js.map +1 -1
- package/docs/compaction.md +11 -3
- package/docs/development.md +1 -1
- package/docs/sessions.md +6 -0
- package/docs/settings.md +1 -1
- package/docs/windows.md +28 -3
- package/docs/work-directory.md +10 -2
- package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
- package/examples/extensions/custom-provider-anthropic/package.json +1 -1
- package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
- package/examples/extensions/sandbox/package-lock.json +2 -2
- package/examples/extensions/sandbox/package.json +1 -1
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/npm-shrinkwrap.json +27 -27
- package/package.json +11 -11
- package/dist/utils/streaming-lines.d.ts +0 -20
- package/dist/utils/streaming-lines.d.ts.map +0 -1
- package/dist/utils/streaming-lines.js +0 -79
- package/dist/utils/streaming-lines.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"needle-runtime.d.ts","sourceRoot":"","sources":["../../../src/core/models/needle-runtime.ts"],"names":[],"mappings":"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","sourcesContent":["import { createHash } from \"node:crypto\";\nimport { createWriteStream, existsSync, mkdirSync, readFileSync, rmSync, statSync, writeFileSync } from \"node:fs\";\nimport { platform as osPlatform } from \"node:os\";\nimport { join } from \"node:path\";\nimport { type Readable, Transform } from \"node:stream\";\nimport { pipeline } from \"node:stream/promises\";\nimport { spawnProcess, spawnProcessSync, waitForChildProcessWithTermination } from \"../../utils/child-process.ts\";\nimport { modelsDir as agentModelsDir, runtimesDir as agentRuntimesDir } from \"../agent-paths.ts\";\nimport type { RuntimeCommandResult, RuntimeCommandRunner } from \"./local-runtime.ts\";\n\n/**\n * Managed runtime for needle (https://github.com/cactus-compute/needle), a 26M-parameter single-shot\n * function-calling model. Needle exposes no server — the only integration surface is CLI/library\n * invocation — so this module owns clone+build of a pinned commit into a contained venv, base\n * checkpoint download, and one-shot `needle run` invocation/parsing. Mirrors local-runtime.ts's\n * OllamaRuntime/TransformersRuntime and llamacpp-runtime.ts's PrismLlamaCppRuntime: injectable seams\n * for exists/fetch/run-command, pi-owned directories under agentDir (runtimes/, models/), onProgress\n * as best-effort UI feedback, and honest error taxonomies instead of silent fallbacks.\n *\n * Investigation findings (verified against a real clone + real venv + real CPU inference run, not\n * just the README):\n *\n * - `needle run` (the CLI's single-inference subcommand) takes a REQUIRED `--checkpoint` and does\n * NOT auto-download one — unlike `needle playground`/`finetune`, which resolve a checkpoint\n * internally. The pretrained base checkpoint (`needle.pkl`) lives on `Cactus-Compute/needle` on\n * Hugging Face and is fetched directly by {@link NeedleRuntime.downloadWeights} (never invoked\n * implicitly by installManaged/runFunctionCall — this module never silently starts a large\n * download on the caller's behalf).\n * - SECURITY (owner-flagged, verified during investigation): `Cactus-Compute/needle` on Hugging Face\n * publishes THREE weight artifacts — `needle.pkl` (52,633,098 bytes), `model.safetensors`\n * (reported as a different param count on the HF model card, 30.4M vs the 26,315,421 a real\n * `needle run` printed — likely not even the same checkpoint), and `needle-cq4.zip`. I grepped the\n * ENTIRE needle package (cli.py, model/run.py, model/export.py, model/quantize.py,\n * training/{finetune,pretrain,train}.py, utils/distributed.py, ui/server.py — every `pickle`/`.zip`\n * hit in the repo) and confirmed every checkpoint load/save path in the codebase — including the\n * one `needle run` uses — is `pickle.load`/`pickle.dump` on a `.pkl` file. There is NO safetensors\n * reader anywhere in the package; `model.safetensors` is not consumed by any code this module\n * drives. `needle-cq4.zip` (\"Cactus Quantized 4-bit\"?) isn't referenced by any code here either —\n * the README states production inference runs on the separate Cactus C++ engine\n * (cactus-compute/cactus), which very plausibly consumes its own format; that repo was not audited\n * here. Bottom line: **this module has no choice but to fetch and deserialize `needle.pkl` via\n * Python's `pickle` module, which executes arbitrary code by construction** — there is no\n * safetensors alternative available in the code path we drive. Given that, {@link\n * NeedleRuntime.downloadWeights} pins the exact sha256 ({@link NEEDLE_WEIGHTS_SHA256}) and byte\n * count ({@link NEEDLE_WEIGHTS_BYTES}) of the file as verified on 2026-07-18 (direct `sha256sum` of\n * a real download, cross-checked against Hugging Face's own `x-linked-etag`/`x-linked-size`\n * headers on the resolve redirect, at repo commit `5f89b4307696d669c3df1d38ae057e6e1728b107`) and\n * VERIFIES every download against that pin, refusing to keep any file that doesn't match — this\n * catches a compromised/tampered/swapped artifact but does NOT make loading a pickle file safe in\n * the abstract; the actual `pickle.load` execution happens entirely inside needle's own Python\n * process, outside this module's control. The owner should decide whether serving this model at\n * all is acceptable given upstream's format choice.\n * - The upstream `setup` script does more than a contained managed install can honor: it can `sudo\n * apt-get install` a newer Python or `python3-venv`, `sudo modprobe` TPU kernel modules, toggle\n * transparent hugepages via a root-owned sysfs write, and interactively prompts for a\n * WANDB_API_KEY. None of that is available under containment (no writes outside the pi-owned dir,\n * no sudo, no interactive prompts, no global installs) and none of it is required for the\n * documented Mac/PC single-inference quickstart path. {@link NeedleRuntime.installManaged} instead\n * replicates only the containable core: `python3 -m venv`, `pip install -e <clonedRepo>` (the\n * script's own `pip install -e . -q`), and the CPU (or CUDA, when an NVIDIA GPU is detected) JAX\n * backend install. TPU support and the sudo-gated OS package/kernel-module steps are intentionally\n * NOT replicated.\n * - `needle run`'s console-script entry point (`<venv>/bin/needle`, installed by\n * `pip install -e .` from the `[project.scripts]` table) is the only way to invoke the CLI:\n * `needle/cli.py` has no `if __name__ == \"__main__\":` guard, so `python -m needle.cli` silently\n * does nothing — the installed console script is required.\n * - A verified real stdout capture of `needle run --checkpoint <path> --query \"...\" --tools '[...]'`\n * is multi-line diagnostic prose followed by the tool call:\n * ```\n * Loading checkpoint: <path>\n * Downloading pretrained tokenizer from HuggingFace... (first run only — cached after)\n * Model parameters: 26,315,421\n *\n * Query: <query>\n * Tools: <tools JSON, truncated to 80 chars>...\n *\n * <tool_call>[{\"name\":\"get_weather\",\"arguments\":{\"location\":\"SanFrancisco\"}}]\n * ```\n * The `<tool_call>` marker is a literal SentencePiece user-defined-symbol token, always emitted as\n * the first generated token per the model's own answer format. {@link NeedleRuntime}'s stdout\n * parser locates that marker and strictly `JSON.parse`s everything after it — never guessing a\n * result from unparseable output.\n * - Known upstream quirk (verified against a live run with a camelCase tool name): `needle run`'s CLI\n * wrapper (`main()` in `needle/model/run.py`) streams tokens straight to stdout and never applies\n * the tool-name restoration its own `generate()` return value receives — a tool name that wasn't\n * already snake_case (e.g. `getWeatherNow`) is reported back snake-cased (`get_weather_now`), not\n * in its original casing. This is a limitation of the upstream CLI, not something patched here.\n * - Pinned commit `ffb1c5144c5a16cb8ec650dbc8a6f6fd3854f8f2` was captured via a real `git clone` of\n * the repo's default branch HEAD on 2026-07-18 (the repo's own history shows no pushes since\n * 2026-07-01, so this is not stale). A plain `git clone --depth 1` only reliably lands on a pinned\n * commit when it still happens to be the remote's current tip; {@link NeedleRuntime.installManaged}\n * instead fetches the exact commit SHA directly (`git fetch --depth 1 origin <sha>`), which GitHub\n * serves for any reachable commit on a public repo, so the pin holds even after upstream moves on.\n */\n\nexport const NEEDLE_REPO_URL = \"https://github.com/cactus-compute/needle.git\";\n\n/**\n * Pinned needle commit — captured via a real `git clone` of the repo's default-branch HEAD on\n * 2026-07-18 (`git ls-remote https://github.com/cactus-compute/needle HEAD` resolves to the same\n * SHA). Bump here (re-verify with the same command) when a newer commit is needed.\n */\nexport const NEEDLE_PINNED_COMMIT = \"ffb1c5144c5a16cb8ec650dbc8a6f6fd3854f8f2\";\n\nconst NEEDLE_HF_MODEL_REPO = \"Cactus-Compute/needle\";\nconst NEEDLE_CHECKPOINT_FILENAME = \"needle.pkl\";\nconst NEEDLE_TOOL_CALL_MARKER = \"<tool_call>\";\n\n/**\n * Pinned integrity for `needle.pkl` — see the module-level SECURITY note: this is a pickle file\n * (arbitrary code execution on load by construction), so every download is verified against this\n * exact sha256+size before being kept. Captured 2026-07-18: `sha256sum` of a real download matched\n * Hugging Face's `x-linked-etag` header on the resolve redirect at repo commit\n * `5f89b4307696d669c3df1d38ae057e6e1728b107`. Bump both together (re-verify the same way) only for a\n * deliberate, reviewed upstream weights update.\n */\nexport const NEEDLE_WEIGHTS_SHA256 = \"40a32e91d1d4197bf15ba559b74f6727c342dc8746918742fc7d8e2c1f18df40\";\nexport const NEEDLE_WEIGHTS_BYTES = 52_633_098;\n\nconst NEEDLE_COMMAND_TIMEOUT_MS = 10 * 60_000;\nconst NEEDLE_KILL_GRACE_MS = 2_000;\n\nconst NEEDLE_SMOKE_QUERY = \"What's the weather in San Francisco?\";\nconst NEEDLE_SMOKE_TOOLS = [\n\t{\n\t\tname: \"get_weather\",\n\t\tdescription: \"Get current weather for a city.\",\n\t\tparameters: { location: { type: \"string\", description: \"City name.\", required: true } },\n\t},\n];\n\nexport interface NeedleDetectResult {\n\tinstalled: boolean;\n\tinstallDir?: string;\n\tcommit?: string;\n\tpythonAvailable: boolean;\n\tcheckpointPresent: boolean;\n}\n\nexport interface NeedleFunctionCallRequest {\n\tquery: string;\n\t/** A JSON-serializable tool schema value (never a pre-stringified JSON string) — serialized\n\t * exactly once by {@link NeedleRuntime.runFunctionCall}, never by the caller. */\n\ttools: unknown;\n}\n\nexport interface NeedleFunctionCall {\n\tname: string;\n\targuments: Record<string, unknown>;\n}\n\nexport type NeedleFunctionCallResult =\n\t| { ok: true; call: NeedleFunctionCall }\n\t| { ok: false; error: string; rawOutput: string };\n\nexport interface NeedleSmokeTestResult {\n\tok: boolean;\n\tlatencyMs: number;\n\tcall?: NeedleFunctionCall;\n\terror?: string;\n}\n\nexport interface NeedleWeightsDownloadResult {\n\tok: boolean;\n\tpath?: string;\n\tskipped?: boolean;\n\terror?: string;\n}\n\ninterface NeedleWeightsIntegrity {\n\tsha256: string;\n\tbytes: number;\n}\n\nexport interface NeedleRuntimeDeps {\n\texistsFn?: (path: string) => boolean;\n\tfetchFn?: typeof fetch;\n\t/** Runs git/pip/python commands. Injectable so installManaged/runFunctionCall's orchestration is\n\t * testable without a real clone/venv/inference. Defaults to a real spawn-and-collect-output\n\t * runner (installs can run long; a single inference call is comparatively quick but still shells\n\t * out to a real interpreter). */\n\trunCommand?: RuntimeCommandRunner;\n\t/** Whether a named command exists on PATH (git, python3, nvidia-smi). */\n\thasCommand?: (command: string) => boolean;\n\thasNvidiaGpu?: () => boolean;\n\tplatform?: () => string;\n\t/** Expected weights sha256+size. Defaults to {@link NEEDLE_WEIGHTS_SHA256}/{@link\n\t * NEEDLE_WEIGHTS_BYTES} — the real pinned values. Overridable ONLY so tests can exercise the full\n\t * download+verify path with small synthetic content instead of the real 52MB pickle; this is a\n\t * constructor-level seam for a trusted caller, the same trust boundary every other injectable dep\n\t * in this class already relies on (fetchFn/runCommand could equally be used to bypass anything).\n\t */\n\tweightsIntegrity?: NeedleWeightsIntegrity;\n}\n\ninterface NeedleInstallMetadata {\n\tcommit: string;\n\tentryCommand: string;\n}\n\nfunction tailLines(value: string | undefined, count = 3): string {\n\treturn value?.trim().split(\"\\n\").slice(-count).join(\"\\n\") || \"unknown error\";\n}\n\n/** Pass bytes through unchanged while feeding them into a running hash — lets a single `pipeline()`\n * call both write the download to disk and compute its sha256 in one streaming pass. */\nfunction hashingPassThrough(hash: ReturnType<typeof createHash>): Transform {\n\treturn new Transform({\n\t\ttransform(chunk: Buffer, _encoding, callback) {\n\t\t\thash.update(chunk);\n\t\t\tcallback(null, chunk);\n\t\t},\n\t});\n}\n\nasync function defaultRunCommand(\n\tcommand: string,\n\targs: string[],\n\toptions: { env?: NodeJS.ProcessEnv; onOutput?: (chunk: string) => void } = {},\n): Promise<RuntimeCommandResult> {\n\ttry {\n\t\tconst proc = spawnProcess(command, args, {\n\t\t\tdetached: process.platform !== \"win32\",\n\t\t\tstdio: [\"ignore\", \"pipe\", \"pipe\"],\n\t\t\tenv: options.env ? { ...process.env, ...options.env } : process.env,\n\t\t});\n\t\tlet stdout = \"\";\n\t\tlet stderr = \"\";\n\t\tproc.stdout.setEncoding(\"utf8\");\n\t\tproc.stderr.setEncoding(\"utf8\");\n\t\tproc.stdout.on(\"data\", (chunk: string) => {\n\t\t\tstdout = `${stdout}${chunk}`.slice(-1024 * 1024);\n\t\t\toptions.onOutput?.(chunk);\n\t\t});\n\t\tproc.stderr.on(\"data\", (chunk: string) => {\n\t\t\tstderr = `${stderr}${chunk}`.slice(-1024 * 1024);\n\t\t\toptions.onOutput?.(chunk);\n\t\t});\n\t\tconst terminal = await waitForChildProcessWithTermination(proc, {\n\t\t\ttimeoutMs: NEEDLE_COMMAND_TIMEOUT_MS,\n\t\t\tkillGraceMs: NEEDLE_KILL_GRACE_MS,\n\t\t});\n\t\tconst timedOut = terminal.reason === \"timeout\";\n\t\treturn {\n\t\t\tok: terminal.code === 0,\n\t\t\tstdout,\n\t\t\tstderr,\n\t\t\tcode: terminal.code,\n\t\t\t...(terminal.code === 0\n\t\t\t\t? {}\n\t\t\t\t: {\n\t\t\t\t\t\terror: timedOut\n\t\t\t\t\t\t\t? `${command} timed out after ${NEEDLE_COMMAND_TIMEOUT_MS}ms`\n\t\t\t\t\t\t\t: stderr.trim() || stdout.trim() || `exit code ${terminal.code ?? \"unknown\"}`,\n\t\t\t\t\t}),\n\t\t};\n\t} catch (error) {\n\t\treturn { ok: false, stdout: \"\", stderr: \"\", error: error instanceof Error ? error.message : String(error) };\n\t}\n}\n\nexport class NeedleRuntime {\n\tprivate readonly _agentDir: string;\n\tprivate readonly _exists: (path: string) => boolean;\n\tprivate readonly _fetch: typeof fetch;\n\tprivate readonly _runCommand: RuntimeCommandRunner;\n\tprivate readonly _hasCommand: (command: string) => boolean;\n\tprivate readonly _hasNvidiaGpu: () => boolean;\n\tprivate readonly _platform: () => string;\n\tprivate readonly _weightsIntegrity: NeedleWeightsIntegrity;\n\n\tconstructor(args: { agentDir: string; deps?: NeedleRuntimeDeps }) {\n\t\tthis._agentDir = args.agentDir;\n\t\tthis._exists = args.deps?.existsFn ?? existsSync;\n\t\tthis._fetch = args.deps?.fetchFn ?? fetch;\n\t\tthis._runCommand = args.deps?.runCommand ?? defaultRunCommand;\n\t\tthis._hasCommand =\n\t\t\targs.deps?.hasCommand ??\n\t\t\t((command) =>\n\t\t\t\tspawnProcessSync(command, [\"--version\"], { encoding: \"utf8\", timeout: 5_000 }).error === undefined);\n\t\tthis._hasNvidiaGpu = args.deps?.hasNvidiaGpu ?? (() => this._hasCommand(\"nvidia-smi\"));\n\t\tthis._platform = args.deps?.platform ?? osPlatform;\n\t\tthis._weightsIntegrity = args.deps?.weightsIntegrity ?? {\n\t\t\tsha256: NEEDLE_WEIGHTS_SHA256,\n\t\t\tbytes: NEEDLE_WEIGHTS_BYTES,\n\t\t};\n\t}\n\n\truntimeDir(): string {\n\t\treturn agentRuntimesDir(\"needle\", this._agentDir);\n\t}\n\n\tmodelsDir(): string {\n\t\treturn agentModelsDir(\"needle\", this._agentDir);\n\t}\n\n\tcheckpointPath(): string {\n\t\treturn join(this.modelsDir(), NEEDLE_CHECKPOINT_FILENAME);\n\t}\n\n\tprivate _srcDir(): string {\n\t\treturn join(this.runtimeDir(), \"src\");\n\t}\n\n\tprivate _venvDir(): string {\n\t\treturn join(this.runtimeDir(), \"venv\");\n\t}\n\n\tprivate _pythonPath(): string {\n\t\treturn this._platform() === \"win32\"\n\t\t\t? join(this._venvDir(), \"Scripts\", \"python.exe\")\n\t\t\t: join(this._venvDir(), \"bin\", \"python\");\n\t}\n\n\t/** The installed `needle` console script (from `[project.scripts]`, written by `pip install -e`)\n\t * — the only invokable entry point, since `needle/cli.py` has no `__main__` guard. */\n\tprivate _entryPath(): string {\n\t\treturn this._platform() === \"win32\"\n\t\t\t? join(this._venvDir(), \"Scripts\", \"needle.exe\")\n\t\t\t: join(this._venvDir(), \"bin\", \"needle\");\n\t}\n\n\tprivate _manifestPath(): string {\n\t\treturn join(this.runtimeDir(), \"install.json\");\n\t}\n\n\tprivate _readManifest(): NeedleInstallMetadata | undefined {\n\t\ttry {\n\t\t\tconst parsed = JSON.parse(readFileSync(this._manifestPath(), \"utf8\")) as {\n\t\t\t\tcommit?: unknown;\n\t\t\t\tentryCommand?: unknown;\n\t\t\t};\n\t\t\treturn typeof parsed.commit === \"string\" && typeof parsed.entryCommand === \"string\"\n\t\t\t\t? { commit: parsed.commit, entryCommand: parsed.entryCommand }\n\t\t\t\t: undefined;\n\t\t} catch {\n\t\t\treturn undefined;\n\t\t}\n\t}\n\n\tprivate _writeManifest(metadata: NeedleInstallMetadata): void {\n\t\twriteFileSync(this._manifestPath(), JSON.stringify(metadata, null, \"\\t\"));\n\t}\n\n\tasync detect(): Promise<NeedleDetectResult> {\n\t\tconst installed = this._exists(this._entryPath());\n\t\treturn {\n\t\t\tinstalled,\n\t\t\tinstallDir: installed ? this.runtimeDir() : undefined,\n\t\t\tcommit: this._readManifest()?.commit,\n\t\t\tpythonAvailable: this._hasCommand(\"python3\"),\n\t\t\tcheckpointPresent: this._exists(this.checkpointPath()),\n\t\t};\n\t}\n\n\t/**\n\t * Clone the pinned needle commit and build a contained, pi-owned runtime (consent-gated by the\n\t * caller, same contract as OllamaRuntime#installManaged / PrismLlamaCppRuntime#installManaged —\n\t * this method only does the mechanical clone+build+verify and reports the outcome honestly). See\n\t * the module docstring for exactly which upstream `setup` steps are and are not replicated under\n\t * containment.\n\t */\n\tasync installManaged(onProgress?: (status: string) => void): Promise<{ ok: boolean; error?: string }> {\n\t\tif (!this._hasCommand(\"git\")) {\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\terror: `git-missing: git is required to clone needle (${NEEDLE_REPO_URL}). Install git (e.g. \\`apt-get install git\\`, \\`brew install git\\`) and try again.`,\n\t\t\t};\n\t\t}\n\t\tif (!this._hasCommand(\"python3\")) {\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\terror: \"python-missing: python3 (>=3.11) is required to run needle. Install Python 3.11+ (e.g. `apt-get install python3 python3-venv`, `brew install python@3.12`) and try again.\",\n\t\t\t};\n\t\t}\n\n\t\tmkdirSync(this.runtimeDir(), { recursive: true });\n\t\tconst srcDir = this._srcDir();\n\t\tif (this._exists(srcDir)) rmSync(srcDir, { recursive: true, force: true });\n\n\t\tonProgress?.(`Cloning ${NEEDLE_REPO_URL}…`);\n\t\tconst cloned = await this._cloneAtPinnedCommit(srcDir);\n\t\tif (!cloned.ok) return cloned;\n\n\t\tonProgress?.(`Creating isolated Python venv at ${this._venvDir()}…`);\n\t\tconst venv = await this._runCommand(\"python3\", [\"-m\", \"venv\", this._venvDir()]);\n\t\tif (!venv.ok) return { ok: false, error: `setup-fail: ${tailLines(venv.error ?? venv.stderr)}` };\n\t\tif (!this._exists(this._pythonPath())) {\n\t\t\treturn { ok: false, error: `setup-fail: venv created but ${this._pythonPath()} was not found` };\n\t\t}\n\n\t\tonProgress?.(\"Upgrading pip inside the pi-managed venv…\");\n\t\tconst pipUpgrade = await this._runCommand(this._pythonPath(), [\"-m\", \"pip\", \"install\", \"--upgrade\", \"pip\"]);\n\t\tif (!pipUpgrade.ok) {\n\t\t\treturn { ok: false, error: `setup-fail: ${tailLines(pipUpgrade.error ?? pipUpgrade.stderr)}` };\n\t\t}\n\n\t\tonProgress?.(\"Installing needle (editable) into the pi-managed venv…\");\n\t\tconst install = await this._runCommand(this._pythonPath(), [\"-m\", \"pip\", \"install\", \"-e\", srcDir]);\n\t\tif (!install.ok) return { ok: false, error: `setup-fail: ${tailLines(install.error ?? install.stderr)}` };\n\n\t\tconst cudaAvailable = this._hasNvidiaGpu();\n\t\tonProgress?.(cudaAvailable ? \"Installing JAX (CUDA 12 backend)…\" : \"Installing JAX (CPU backend)…\");\n\t\tconst jaxArgs = cudaAvailable ? [\"jax[cuda12]\"] : [\"jax\"];\n\t\tconst jax = await this._runCommand(this._pythonPath(), [\"-m\", \"pip\", \"install\", \"-U\", ...jaxArgs]);\n\t\tif (!jax.ok) return { ok: false, error: `setup-fail: ${tailLines(jax.error ?? jax.stderr)}` };\n\n\t\tonProgress?.(\"Verifying the needle install…\");\n\t\tconst verify = await this._runCommand(this._pythonPath(), [\"-c\", \"import jax, needle; print(needle.__file__)\"]);\n\t\tif (!verify.ok) return { ok: false, error: `verify-fail: ${tailLines(verify.error ?? verify.stderr)}` };\n\n\t\tconst entryCommand = this._entryPath();\n\t\tif (!this._exists(entryCommand)) {\n\t\t\treturn { ok: false, error: `verify-fail: install reported success but ${entryCommand} was not found` };\n\t\t}\n\n\t\tthis._writeManifest({ commit: NEEDLE_PINNED_COMMIT, entryCommand });\n\t\tonProgress?.(\"needle installed.\");\n\t\treturn { ok: true };\n\t}\n\n\t/**\n\t * A plain `git clone --depth 1` only lands on {@link NEEDLE_PINNED_COMMIT} when it still happens\n\t * to be the remote's current default-branch tip. Fetching the exact SHA directly instead (verified\n\t * against the real repo) pins reliably even after upstream moves on: GitHub serves any reachable\n\t * commit for a public repo via `git fetch <sha>`, not just refs.\n\t */\n\tprivate async _cloneAtPinnedCommit(srcDir: string): Promise<{ ok: boolean; error?: string }> {\n\t\tconst init = await this._runCommand(\"git\", [\"init\", \"-q\", srcDir]);\n\t\tif (!init.ok) return { ok: false, error: `clone-fail: ${tailLines(init.error ?? init.stderr)}` };\n\t\tconst remote = await this._runCommand(\"git\", [\"-C\", srcDir, \"remote\", \"add\", \"origin\", NEEDLE_REPO_URL]);\n\t\tif (!remote.ok) return { ok: false, error: `clone-fail: ${tailLines(remote.error ?? remote.stderr)}` };\n\t\tconst fetched = await this._runCommand(\"git\", [\n\t\t\t\"-C\",\n\t\t\tsrcDir,\n\t\t\t\"fetch\",\n\t\t\t\"--depth\",\n\t\t\t\"1\",\n\t\t\t\"origin\",\n\t\t\tNEEDLE_PINNED_COMMIT,\n\t\t]);\n\t\tif (!fetched.ok) return { ok: false, error: `clone-fail: ${tailLines(fetched.error ?? fetched.stderr)}` };\n\t\tconst checkout = await this._runCommand(\"git\", [\"-C\", srcDir, \"checkout\", \"-q\", \"FETCH_HEAD\"]);\n\t\tif (!checkout.ok) return { ok: false, error: `clone-fail: ${tailLines(checkout.error ?? checkout.stderr)}` };\n\t\treturn { ok: true };\n\t}\n\n\t/**\n\t * Download the pretrained base weights (`needle.pkl`). `needle run` takes an explicit\n\t * `--checkpoint` and does NOT auto-download one (unlike `needle playground`/`finetune`) — see the\n\t * module docstring. Never called implicitly by installManaged/runFunctionCall; the caller decides\n\t * when to pull weights.\n\t *\n\t * `needle.pkl` is a pickle file — arbitrary code execution on load by construction (see the\n\t * module-level SECURITY note) — so every download is verified against the pinned sha256+size\n\t * ({@link NEEDLE_WEIGHTS_SHA256}/{@link NEEDLE_WEIGHTS_BYTES}, overridable only via the\n\t * `weightsIntegrity` test seam) computed in the same streaming pass that writes the file, with the\n\t * partial/mismatched file deleted on ANY failure — this never leaves an unverified or wrong pickle\n\t * sitting where {@link runFunctionCall} would load it.\n\t */\n\tasync downloadWeights(onProgress?: (status: string) => void): Promise<NeedleWeightsDownloadResult> {\n\t\tconst destPath = this.checkpointPath();\n\t\tconst url = `https://huggingface.co/${NEEDLE_HF_MODEL_REPO}/resolve/main/${NEEDLE_CHECKPOINT_FILENAME}`;\n\t\tmkdirSync(this.modelsDir(), { recursive: true });\n\n\t\tif (this._exists(destPath) && this._fileSizeBytes(destPath) === this._weightsIntegrity.bytes) {\n\t\t\tonProgress?.(\n\t\t\t\t`${NEEDLE_CHECKPOINT_FILENAME} already downloaded (${this._weightsIntegrity.bytes} bytes) — skipping.`,\n\t\t\t);\n\t\t\treturn { ok: true, path: destPath, skipped: true };\n\t\t}\n\n\t\tonProgress?.(`Downloading ${NEEDLE_CHECKPOINT_FILENAME} from ${NEEDLE_HF_MODEL_REPO}…`);\n\t\tlet response: Response;\n\t\ttry {\n\t\t\tresponse = await this._fetch(url);\n\t\t} catch (error) {\n\t\t\treturn { ok: false, error: `download-fail: ${error instanceof Error ? error.message : String(error)}` };\n\t\t}\n\t\tif (!response.ok || !response.body) {\n\t\t\treturn { ok: false, error: `download-fail: HTTP ${response.status}` };\n\t\t}\n\n\t\tconst hash = createHash(\"sha256\");\n\t\ttry {\n\t\t\tawait pipeline(response.body as unknown as Readable, hashingPassThrough(hash), createWriteStream(destPath));\n\t\t} catch (error) {\n\t\t\tthis._cleanupPartial(destPath);\n\t\t\treturn { ok: false, error: `download-fail: ${error instanceof Error ? error.message : String(error)}` };\n\t\t}\n\n\t\tconst actualBytes = this._fileSizeBytes(destPath);\n\t\tconst actualSha256 = hash.digest(\"hex\");\n\t\tif (actualBytes !== this._weightsIntegrity.bytes || actualSha256 !== this._weightsIntegrity.sha256) {\n\t\t\tthis._cleanupPartial(destPath);\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\terror: `integrity-fail: downloaded ${NEEDLE_CHECKPOINT_FILENAME} does not match the pinned checksum — expected sha256 ${this._weightsIntegrity.sha256} (${this._weightsIntegrity.bytes} bytes), got ${actualSha256} (${actualBytes ?? 0} bytes). Refusing to keep a pickle file that failed integrity verification.`,\n\t\t\t};\n\t\t}\n\n\t\tonProgress?.(`${NEEDLE_CHECKPOINT_FILENAME} downloaded and verified (sha256 ${actualSha256}).`);\n\t\treturn { ok: true, path: destPath };\n\t}\n\n\tprivate _fileSizeBytes(path: string): number | undefined {\n\t\ttry {\n\t\t\treturn statSync(path).size;\n\t\t} catch {\n\t\t\treturn undefined;\n\t\t}\n\t}\n\n\tprivate _cleanupPartial(path: string): void {\n\t\ttry {\n\t\t\trmSync(path, { force: true });\n\t\t} catch {\n\t\t\t// best-effort cleanup\n\t\t}\n\t}\n\n\t/**\n\t * Run one single-shot inference through `needle run --checkpoint ... --query ... --tools ...`\n\t * inside the contained venv's installed console script. Argv is passed as an array to the\n\t * injected `runCommand` seam — never a shell string — so query/tools text containing quotes,\n\t * spaces, or other shell-hostile characters is passed through literally (verified against a real\n\t * invocation; see the module docstring). `tools` is serialized with `JSON.stringify` exactly once.\n\t */\n\tasync runFunctionCall(\n\t\trequest: NeedleFunctionCallRequest,\n\t\toptions?: { checkpointPath?: string },\n\t): Promise<NeedleFunctionCallResult> {\n\t\tconst entryCommand = this._entryPath();\n\t\tif (!this._exists(entryCommand)) {\n\t\t\treturn { ok: false, error: \"not-installed: run installManaged() first\", rawOutput: \"\" };\n\t\t}\n\t\tconst checkpointPath = options?.checkpointPath ?? this.checkpointPath();\n\t\tif (!this._exists(checkpointPath)) {\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\terror: `checkpoint-missing: no checkpoint at ${checkpointPath} — run downloadWeights() first`,\n\t\t\t\trawOutput: \"\",\n\t\t\t};\n\t\t}\n\n\t\tconst argv = [\n\t\t\t\"run\",\n\t\t\t\"--checkpoint\",\n\t\t\tcheckpointPath,\n\t\t\t\"--query\",\n\t\t\trequest.query,\n\t\t\t\"--tools\",\n\t\t\tJSON.stringify(request.tools),\n\t\t];\n\t\tconst result = await this._runCommand(entryCommand, argv);\n\t\tconst rawOutput = [result.stdout, result.stderr].filter(Boolean).join(\"\\n\");\n\t\tif (!result.ok) {\n\t\t\treturn { ok: false, error: `run-fail: ${tailLines(result.error ?? result.stderr)}`, rawOutput };\n\t\t}\n\t\treturn this._parseFunctionCall(result.stdout, rawOutput);\n\t}\n\n\t/**\n\t * Strictly parse a real `needle run` stdout capture:\n\t * ```\n\t * Loading checkpoint: <path>\n\t * Model parameters: <n>\n\t *\n\t * Query: <query>\n\t * Tools: <tools, truncated to 80 chars>...\n\t *\n\t * <tool_call>[{\"name\":\"...\",\"arguments\":{...}}]\n\t * ```\n\t * (diagnostic lines above the marker vary — e.g. a one-time \"Downloading pretrained tokenizer...\"\n\t * line on a cold cache — so parsing locates the `<tool_call>` marker rather than assuming a fixed\n\t * line count/position). Unparseable output is always an error carrying the raw text, never a\n\t * guessed result.\n\t */\n\tprivate _parseFunctionCall(stdout: string, rawOutput: string): NeedleFunctionCallResult {\n\t\tconst markerIndex = stdout.indexOf(NEEDLE_TOOL_CALL_MARKER);\n\t\tif (markerIndex < 0) {\n\t\t\treturn { ok: false, error: `unparseable-output: no ${NEEDLE_TOOL_CALL_MARKER} marker in stdout`, rawOutput };\n\t\t}\n\t\tconst jsonText = stdout.slice(markerIndex + NEEDLE_TOOL_CALL_MARKER.length).trim();\n\t\tlet parsed: unknown;\n\t\ttry {\n\t\t\tparsed = JSON.parse(jsonText);\n\t\t} catch (error) {\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\terror: `unparseable-output: ${error instanceof Error ? error.message : String(error)}`,\n\t\t\t\trawOutput,\n\t\t\t};\n\t\t}\n\t\tif (!Array.isArray(parsed) || parsed.length === 0) {\n\t\t\treturn { ok: false, error: \"unparseable-output: expected a non-empty tool-call array\", rawOutput };\n\t\t}\n\t\tconst first = parsed[0] as { name?: unknown; arguments?: unknown };\n\t\tif (\n\t\t\ttypeof first !== \"object\" ||\n\t\t\tfirst === null ||\n\t\t\ttypeof first.name !== \"string\" ||\n\t\t\ttypeof first.arguments !== \"object\" ||\n\t\t\tfirst.arguments === null\n\t\t) {\n\t\t\treturn { ok: false, error: \"unparseable-output: tool call missing name/arguments\", rawOutput };\n\t\t}\n\t\treturn { ok: true, call: { name: first.name, arguments: first.arguments as Record<string, unknown> } };\n\t}\n\n\t/** Canned get_weather query/tool through {@link runFunctionCall}; the wiring task uses this as the\n\t * post-install verification step. */\n\tasync smokeTest(onProgress?: (status: string) => void): Promise<NeedleSmokeTestResult> {\n\t\tonProgress?.(\"Running needle smoke test…\");\n\t\tconst startedAt = Date.now();\n\t\tconst result = await this.runFunctionCall({ query: NEEDLE_SMOKE_QUERY, tools: NEEDLE_SMOKE_TOOLS });\n\t\tconst latencyMs = Date.now() - startedAt;\n\t\tif (!result.ok) {\n\t\t\tonProgress?.(`Smoke test failed: ${result.error}`);\n\t\t\treturn { ok: false, latencyMs, error: result.error };\n\t\t}\n\t\tonProgress?.(`Smoke test ok (${latencyMs}ms): ${result.call.name}`);\n\t\treturn { ok: true, latencyMs, call: result.call };\n\t}\n\n\t/**\n\t * No-op: every needle invocation here is a single-shot `runCommand` call that spawns, waits for\n\t * exit, and returns — there is no persistent/detached child process this runtime owns between\n\t * calls for dispose() to track or kill (contrast OllamaRuntime/PrismLlamaCppRuntime's long-lived\n\t * `serve()` child).\n\t */\n\tdispose(): void {}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"needle-runtime.d.ts","sourceRoot":"","sources":["../../../src/core/models/needle-runtime.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
|
-
import {
|
|
2
|
+
import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
3
3
|
import { platform as osPlatform } from "node:os";
|
|
4
4
|
import { join } from "node:path";
|
|
5
5
|
import { Transform } from "node:stream";
|
|
6
|
-
import { pipeline } from "node:stream/promises";
|
|
7
|
-
import { spawnProcess, spawnProcessSync, waitForChildProcessWithTermination } from "../../utils/child-process.js";
|
|
8
6
|
import { modelsDir as agentModelsDir, runtimesDir as agentRuntimesDir } from "../agent-paths.js";
|
|
7
|
+
import { createRuntimeCommandRunner, fetchRuntimeDownload, removePartialDownload, runtimeCommandAvailable, tryFileSizeBytes, writeRuntimeDownload, } from "./runtime-process.js";
|
|
9
8
|
/**
|
|
10
9
|
* Managed runtime for needle (https://github.com/cactus-compute/needle), a 26M-parameter single-shot
|
|
11
10
|
* function-calling model. Needle exposes no server — the only integration surface is CLI/library
|
|
@@ -133,65 +132,17 @@ function hashingPassThrough(hash) {
|
|
|
133
132
|
},
|
|
134
133
|
});
|
|
135
134
|
}
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
stdio: ["ignore", "pipe", "pipe"],
|
|
141
|
-
env: options.env ? { ...process.env, ...options.env } : process.env,
|
|
142
|
-
});
|
|
143
|
-
let stdout = "";
|
|
144
|
-
let stderr = "";
|
|
145
|
-
proc.stdout.setEncoding("utf8");
|
|
146
|
-
proc.stderr.setEncoding("utf8");
|
|
147
|
-
proc.stdout.on("data", (chunk) => {
|
|
148
|
-
stdout = `${stdout}${chunk}`.slice(-1024 * 1024);
|
|
149
|
-
options.onOutput?.(chunk);
|
|
150
|
-
});
|
|
151
|
-
proc.stderr.on("data", (chunk) => {
|
|
152
|
-
stderr = `${stderr}${chunk}`.slice(-1024 * 1024);
|
|
153
|
-
options.onOutput?.(chunk);
|
|
154
|
-
});
|
|
155
|
-
const terminal = await waitForChildProcessWithTermination(proc, {
|
|
156
|
-
timeoutMs: NEEDLE_COMMAND_TIMEOUT_MS,
|
|
157
|
-
killGraceMs: NEEDLE_KILL_GRACE_MS,
|
|
158
|
-
});
|
|
159
|
-
const timedOut = terminal.reason === "timeout";
|
|
160
|
-
return {
|
|
161
|
-
ok: terminal.code === 0,
|
|
162
|
-
stdout,
|
|
163
|
-
stderr,
|
|
164
|
-
code: terminal.code,
|
|
165
|
-
...(terminal.code === 0
|
|
166
|
-
? {}
|
|
167
|
-
: {
|
|
168
|
-
error: timedOut
|
|
169
|
-
? `${command} timed out after ${NEEDLE_COMMAND_TIMEOUT_MS}ms`
|
|
170
|
-
: stderr.trim() || stdout.trim() || `exit code ${terminal.code ?? "unknown"}`,
|
|
171
|
-
}),
|
|
172
|
-
};
|
|
173
|
-
}
|
|
174
|
-
catch (error) {
|
|
175
|
-
return { ok: false, stdout: "", stderr: "", error: error instanceof Error ? error.message : String(error) };
|
|
176
|
-
}
|
|
177
|
-
}
|
|
135
|
+
const defaultRunCommand = createRuntimeCommandRunner({
|
|
136
|
+
timeoutMs: NEEDLE_COMMAND_TIMEOUT_MS,
|
|
137
|
+
killGraceMs: NEEDLE_KILL_GRACE_MS,
|
|
138
|
+
});
|
|
178
139
|
export class NeedleRuntime {
|
|
179
|
-
_agentDir;
|
|
180
|
-
_exists;
|
|
181
|
-
_fetch;
|
|
182
|
-
_runCommand;
|
|
183
|
-
_hasCommand;
|
|
184
|
-
_hasNvidiaGpu;
|
|
185
|
-
_platform;
|
|
186
|
-
_weightsIntegrity;
|
|
187
140
|
constructor(args) {
|
|
188
141
|
this._agentDir = args.agentDir;
|
|
189
142
|
this._exists = args.deps?.existsFn ?? existsSync;
|
|
190
143
|
this._fetch = args.deps?.fetchFn ?? fetch;
|
|
191
144
|
this._runCommand = args.deps?.runCommand ?? defaultRunCommand;
|
|
192
|
-
this._hasCommand =
|
|
193
|
-
args.deps?.hasCommand ??
|
|
194
|
-
((command) => spawnProcessSync(command, ["--version"], { encoding: "utf8", timeout: 5_000 }).error === undefined);
|
|
145
|
+
this._hasCommand = args.deps?.hasCommand ?? runtimeCommandAvailable;
|
|
195
146
|
this._hasNvidiaGpu = args.deps?.hasNvidiaGpu ?? (() => this._hasCommand("nvidia-smi"));
|
|
196
147
|
this._platform = args.deps?.platform ?? osPlatform;
|
|
197
148
|
this._weightsIntegrity = args.deps?.weightsIntegrity ?? {
|
|
@@ -361,33 +312,22 @@ export class NeedleRuntime {
|
|
|
361
312
|
const destPath = this.checkpointPath();
|
|
362
313
|
const url = `https://huggingface.co/${NEEDLE_HF_MODEL_REPO}/resolve/main/${NEEDLE_CHECKPOINT_FILENAME}`;
|
|
363
314
|
mkdirSync(this.modelsDir(), { recursive: true });
|
|
364
|
-
if (this._exists(destPath) &&
|
|
315
|
+
if (this._exists(destPath) && tryFileSizeBytes(destPath) === this._weightsIntegrity.bytes) {
|
|
365
316
|
onProgress?.(`${NEEDLE_CHECKPOINT_FILENAME} already downloaded (${this._weightsIntegrity.bytes} bytes) — skipping.`);
|
|
366
317
|
return { ok: true, path: destPath, skipped: true };
|
|
367
318
|
}
|
|
368
319
|
onProgress?.(`Downloading ${NEEDLE_CHECKPOINT_FILENAME} from ${NEEDLE_HF_MODEL_REPO}…`);
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
}
|
|
373
|
-
catch (error) {
|
|
374
|
-
return { ok: false, error: `download-fail: ${error instanceof Error ? error.message : String(error)}` };
|
|
375
|
-
}
|
|
376
|
-
if (!response.ok || !response.body) {
|
|
377
|
-
return { ok: false, error: `download-fail: HTTP ${response.status}` };
|
|
378
|
-
}
|
|
320
|
+
const download = await fetchRuntimeDownload(this._fetch, url);
|
|
321
|
+
if (!download.ok)
|
|
322
|
+
return download;
|
|
379
323
|
const hash = createHash("sha256");
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
this._cleanupPartial(destPath);
|
|
385
|
-
return { ok: false, error: `download-fail: ${error instanceof Error ? error.message : String(error)}` };
|
|
386
|
-
}
|
|
387
|
-
const actualBytes = this._fileSizeBytes(destPath);
|
|
324
|
+
const written = await writeRuntimeDownload(download.body, destPath, hashingPassThrough(hash));
|
|
325
|
+
if (!written.ok)
|
|
326
|
+
return written;
|
|
327
|
+
const actualBytes = tryFileSizeBytes(destPath);
|
|
388
328
|
const actualSha256 = hash.digest("hex");
|
|
389
329
|
if (actualBytes !== this._weightsIntegrity.bytes || actualSha256 !== this._weightsIntegrity.sha256) {
|
|
390
|
-
|
|
330
|
+
removePartialDownload(destPath);
|
|
391
331
|
return {
|
|
392
332
|
ok: false,
|
|
393
333
|
error: `integrity-fail: downloaded ${NEEDLE_CHECKPOINT_FILENAME} does not match the pinned checksum — expected sha256 ${this._weightsIntegrity.sha256} (${this._weightsIntegrity.bytes} bytes), got ${actualSha256} (${actualBytes ?? 0} bytes). Refusing to keep a pickle file that failed integrity verification.`,
|
|
@@ -396,22 +336,6 @@ export class NeedleRuntime {
|
|
|
396
336
|
onProgress?.(`${NEEDLE_CHECKPOINT_FILENAME} downloaded and verified (sha256 ${actualSha256}).`);
|
|
397
337
|
return { ok: true, path: destPath };
|
|
398
338
|
}
|
|
399
|
-
_fileSizeBytes(path) {
|
|
400
|
-
try {
|
|
401
|
-
return statSync(path).size;
|
|
402
|
-
}
|
|
403
|
-
catch {
|
|
404
|
-
return undefined;
|
|
405
|
-
}
|
|
406
|
-
}
|
|
407
|
-
_cleanupPartial(path) {
|
|
408
|
-
try {
|
|
409
|
-
rmSync(path, { force: true });
|
|
410
|
-
}
|
|
411
|
-
catch {
|
|
412
|
-
// best-effort cleanup
|
|
413
|
-
}
|
|
414
|
-
}
|
|
415
339
|
/**
|
|
416
340
|
* Run one single-shot inference through `needle run --checkpoint ... --query ... --tools ...`
|
|
417
341
|
* inside the contained venv's installed console script. Argv is passed as an array to the
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"needle-runtime.js","sourceRoot":"","sources":["../../../src/core/models/needle-runtime.ts"],"names":[],"mappings":"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","sourcesContent":["import { createHash } from \"node:crypto\";\nimport { createWriteStream, existsSync, mkdirSync, readFileSync, rmSync, statSync, writeFileSync } from \"node:fs\";\nimport { platform as osPlatform } from \"node:os\";\nimport { join } from \"node:path\";\nimport { type Readable, Transform } from \"node:stream\";\nimport { pipeline } from \"node:stream/promises\";\nimport { spawnProcess, spawnProcessSync, waitForChildProcessWithTermination } from \"../../utils/child-process.ts\";\nimport { modelsDir as agentModelsDir, runtimesDir as agentRuntimesDir } from \"../agent-paths.ts\";\nimport type { RuntimeCommandResult, RuntimeCommandRunner } from \"./local-runtime.ts\";\n\n/**\n * Managed runtime for needle (https://github.com/cactus-compute/needle), a 26M-parameter single-shot\n * function-calling model. Needle exposes no server — the only integration surface is CLI/library\n * invocation — so this module owns clone+build of a pinned commit into a contained venv, base\n * checkpoint download, and one-shot `needle run` invocation/parsing. Mirrors local-runtime.ts's\n * OllamaRuntime/TransformersRuntime and llamacpp-runtime.ts's PrismLlamaCppRuntime: injectable seams\n * for exists/fetch/run-command, pi-owned directories under agentDir (runtimes/, models/), onProgress\n * as best-effort UI feedback, and honest error taxonomies instead of silent fallbacks.\n *\n * Investigation findings (verified against a real clone + real venv + real CPU inference run, not\n * just the README):\n *\n * - `needle run` (the CLI's single-inference subcommand) takes a REQUIRED `--checkpoint` and does\n * NOT auto-download one — unlike `needle playground`/`finetune`, which resolve a checkpoint\n * internally. The pretrained base checkpoint (`needle.pkl`) lives on `Cactus-Compute/needle` on\n * Hugging Face and is fetched directly by {@link NeedleRuntime.downloadWeights} (never invoked\n * implicitly by installManaged/runFunctionCall — this module never silently starts a large\n * download on the caller's behalf).\n * - SECURITY (owner-flagged, verified during investigation): `Cactus-Compute/needle` on Hugging Face\n * publishes THREE weight artifacts — `needle.pkl` (52,633,098 bytes), `model.safetensors`\n * (reported as a different param count on the HF model card, 30.4M vs the 26,315,421 a real\n * `needle run` printed — likely not even the same checkpoint), and `needle-cq4.zip`. I grepped the\n * ENTIRE needle package (cli.py, model/run.py, model/export.py, model/quantize.py,\n * training/{finetune,pretrain,train}.py, utils/distributed.py, ui/server.py — every `pickle`/`.zip`\n * hit in the repo) and confirmed every checkpoint load/save path in the codebase — including the\n * one `needle run` uses — is `pickle.load`/`pickle.dump` on a `.pkl` file. There is NO safetensors\n * reader anywhere in the package; `model.safetensors` is not consumed by any code this module\n * drives. `needle-cq4.zip` (\"Cactus Quantized 4-bit\"?) isn't referenced by any code here either —\n * the README states production inference runs on the separate Cactus C++ engine\n * (cactus-compute/cactus), which very plausibly consumes its own format; that repo was not audited\n * here. Bottom line: **this module has no choice but to fetch and deserialize `needle.pkl` via\n * Python's `pickle` module, which executes arbitrary code by construction** — there is no\n * safetensors alternative available in the code path we drive. Given that, {@link\n * NeedleRuntime.downloadWeights} pins the exact sha256 ({@link NEEDLE_WEIGHTS_SHA256}) and byte\n * count ({@link NEEDLE_WEIGHTS_BYTES}) of the file as verified on 2026-07-18 (direct `sha256sum` of\n * a real download, cross-checked against Hugging Face's own `x-linked-etag`/`x-linked-size`\n * headers on the resolve redirect, at repo commit `5f89b4307696d669c3df1d38ae057e6e1728b107`) and\n * VERIFIES every download against that pin, refusing to keep any file that doesn't match — this\n * catches a compromised/tampered/swapped artifact but does NOT make loading a pickle file safe in\n * the abstract; the actual `pickle.load` execution happens entirely inside needle's own Python\n * process, outside this module's control. The owner should decide whether serving this model at\n * all is acceptable given upstream's format choice.\n * - The upstream `setup` script does more than a contained managed install can honor: it can `sudo\n * apt-get install` a newer Python or `python3-venv`, `sudo modprobe` TPU kernel modules, toggle\n * transparent hugepages via a root-owned sysfs write, and interactively prompts for a\n * WANDB_API_KEY. None of that is available under containment (no writes outside the pi-owned dir,\n * no sudo, no interactive prompts, no global installs) and none of it is required for the\n * documented Mac/PC single-inference quickstart path. {@link NeedleRuntime.installManaged} instead\n * replicates only the containable core: `python3 -m venv`, `pip install -e <clonedRepo>` (the\n * script's own `pip install -e . -q`), and the CPU (or CUDA, when an NVIDIA GPU is detected) JAX\n * backend install. TPU support and the sudo-gated OS package/kernel-module steps are intentionally\n * NOT replicated.\n * - `needle run`'s console-script entry point (`<venv>/bin/needle`, installed by\n * `pip install -e .` from the `[project.scripts]` table) is the only way to invoke the CLI:\n * `needle/cli.py` has no `if __name__ == \"__main__\":` guard, so `python -m needle.cli` silently\n * does nothing — the installed console script is required.\n * - A verified real stdout capture of `needle run --checkpoint <path> --query \"...\" --tools '[...]'`\n * is multi-line diagnostic prose followed by the tool call:\n * ```\n * Loading checkpoint: <path>\n * Downloading pretrained tokenizer from HuggingFace... (first run only — cached after)\n * Model parameters: 26,315,421\n *\n * Query: <query>\n * Tools: <tools JSON, truncated to 80 chars>...\n *\n * <tool_call>[{\"name\":\"get_weather\",\"arguments\":{\"location\":\"SanFrancisco\"}}]\n * ```\n * The `<tool_call>` marker is a literal SentencePiece user-defined-symbol token, always emitted as\n * the first generated token per the model's own answer format. {@link NeedleRuntime}'s stdout\n * parser locates that marker and strictly `JSON.parse`s everything after it — never guessing a\n * result from unparseable output.\n * - Known upstream quirk (verified against a live run with a camelCase tool name): `needle run`'s CLI\n * wrapper (`main()` in `needle/model/run.py`) streams tokens straight to stdout and never applies\n * the tool-name restoration its own `generate()` return value receives — a tool name that wasn't\n * already snake_case (e.g. `getWeatherNow`) is reported back snake-cased (`get_weather_now`), not\n * in its original casing. This is a limitation of the upstream CLI, not something patched here.\n * - Pinned commit `ffb1c5144c5a16cb8ec650dbc8a6f6fd3854f8f2` was captured via a real `git clone` of\n * the repo's default branch HEAD on 2026-07-18 (the repo's own history shows no pushes since\n * 2026-07-01, so this is not stale). A plain `git clone --depth 1` only reliably lands on a pinned\n * commit when it still happens to be the remote's current tip; {@link NeedleRuntime.installManaged}\n * instead fetches the exact commit SHA directly (`git fetch --depth 1 origin <sha>`), which GitHub\n * serves for any reachable commit on a public repo, so the pin holds even after upstream moves on.\n */\n\nexport const NEEDLE_REPO_URL = \"https://github.com/cactus-compute/needle.git\";\n\n/**\n * Pinned needle commit — captured via a real `git clone` of the repo's default-branch HEAD on\n * 2026-07-18 (`git ls-remote https://github.com/cactus-compute/needle HEAD` resolves to the same\n * SHA). Bump here (re-verify with the same command) when a newer commit is needed.\n */\nexport const NEEDLE_PINNED_COMMIT = \"ffb1c5144c5a16cb8ec650dbc8a6f6fd3854f8f2\";\n\nconst NEEDLE_HF_MODEL_REPO = \"Cactus-Compute/needle\";\nconst NEEDLE_CHECKPOINT_FILENAME = \"needle.pkl\";\nconst NEEDLE_TOOL_CALL_MARKER = \"<tool_call>\";\n\n/**\n * Pinned integrity for `needle.pkl` — see the module-level SECURITY note: this is a pickle file\n * (arbitrary code execution on load by construction), so every download is verified against this\n * exact sha256+size before being kept. Captured 2026-07-18: `sha256sum` of a real download matched\n * Hugging Face's `x-linked-etag` header on the resolve redirect at repo commit\n * `5f89b4307696d669c3df1d38ae057e6e1728b107`. Bump both together (re-verify the same way) only for a\n * deliberate, reviewed upstream weights update.\n */\nexport const NEEDLE_WEIGHTS_SHA256 = \"40a32e91d1d4197bf15ba559b74f6727c342dc8746918742fc7d8e2c1f18df40\";\nexport const NEEDLE_WEIGHTS_BYTES = 52_633_098;\n\nconst NEEDLE_COMMAND_TIMEOUT_MS = 10 * 60_000;\nconst NEEDLE_KILL_GRACE_MS = 2_000;\n\nconst NEEDLE_SMOKE_QUERY = \"What's the weather in San Francisco?\";\nconst NEEDLE_SMOKE_TOOLS = [\n\t{\n\t\tname: \"get_weather\",\n\t\tdescription: \"Get current weather for a city.\",\n\t\tparameters: { location: { type: \"string\", description: \"City name.\", required: true } },\n\t},\n];\n\nexport interface NeedleDetectResult {\n\tinstalled: boolean;\n\tinstallDir?: string;\n\tcommit?: string;\n\tpythonAvailable: boolean;\n\tcheckpointPresent: boolean;\n}\n\nexport interface NeedleFunctionCallRequest {\n\tquery: string;\n\t/** A JSON-serializable tool schema value (never a pre-stringified JSON string) — serialized\n\t * exactly once by {@link NeedleRuntime.runFunctionCall}, never by the caller. */\n\ttools: unknown;\n}\n\nexport interface NeedleFunctionCall {\n\tname: string;\n\targuments: Record<string, unknown>;\n}\n\nexport type NeedleFunctionCallResult =\n\t| { ok: true; call: NeedleFunctionCall }\n\t| { ok: false; error: string; rawOutput: string };\n\nexport interface NeedleSmokeTestResult {\n\tok: boolean;\n\tlatencyMs: number;\n\tcall?: NeedleFunctionCall;\n\terror?: string;\n}\n\nexport interface NeedleWeightsDownloadResult {\n\tok: boolean;\n\tpath?: string;\n\tskipped?: boolean;\n\terror?: string;\n}\n\ninterface NeedleWeightsIntegrity {\n\tsha256: string;\n\tbytes: number;\n}\n\nexport interface NeedleRuntimeDeps {\n\texistsFn?: (path: string) => boolean;\n\tfetchFn?: typeof fetch;\n\t/** Runs git/pip/python commands. Injectable so installManaged/runFunctionCall's orchestration is\n\t * testable without a real clone/venv/inference. Defaults to a real spawn-and-collect-output\n\t * runner (installs can run long; a single inference call is comparatively quick but still shells\n\t * out to a real interpreter). */\n\trunCommand?: RuntimeCommandRunner;\n\t/** Whether a named command exists on PATH (git, python3, nvidia-smi). */\n\thasCommand?: (command: string) => boolean;\n\thasNvidiaGpu?: () => boolean;\n\tplatform?: () => string;\n\t/** Expected weights sha256+size. Defaults to {@link NEEDLE_WEIGHTS_SHA256}/{@link\n\t * NEEDLE_WEIGHTS_BYTES} — the real pinned values. Overridable ONLY so tests can exercise the full\n\t * download+verify path with small synthetic content instead of the real 52MB pickle; this is a\n\t * constructor-level seam for a trusted caller, the same trust boundary every other injectable dep\n\t * in this class already relies on (fetchFn/runCommand could equally be used to bypass anything).\n\t */\n\tweightsIntegrity?: NeedleWeightsIntegrity;\n}\n\ninterface NeedleInstallMetadata {\n\tcommit: string;\n\tentryCommand: string;\n}\n\nfunction tailLines(value: string | undefined, count = 3): string {\n\treturn value?.trim().split(\"\\n\").slice(-count).join(\"\\n\") || \"unknown error\";\n}\n\n/** Pass bytes through unchanged while feeding them into a running hash — lets a single `pipeline()`\n * call both write the download to disk and compute its sha256 in one streaming pass. */\nfunction hashingPassThrough(hash: ReturnType<typeof createHash>): Transform {\n\treturn new Transform({\n\t\ttransform(chunk: Buffer, _encoding, callback) {\n\t\t\thash.update(chunk);\n\t\t\tcallback(null, chunk);\n\t\t},\n\t});\n}\n\nasync function defaultRunCommand(\n\tcommand: string,\n\targs: string[],\n\toptions: { env?: NodeJS.ProcessEnv; onOutput?: (chunk: string) => void } = {},\n): Promise<RuntimeCommandResult> {\n\ttry {\n\t\tconst proc = spawnProcess(command, args, {\n\t\t\tdetached: process.platform !== \"win32\",\n\t\t\tstdio: [\"ignore\", \"pipe\", \"pipe\"],\n\t\t\tenv: options.env ? { ...process.env, ...options.env } : process.env,\n\t\t});\n\t\tlet stdout = \"\";\n\t\tlet stderr = \"\";\n\t\tproc.stdout.setEncoding(\"utf8\");\n\t\tproc.stderr.setEncoding(\"utf8\");\n\t\tproc.stdout.on(\"data\", (chunk: string) => {\n\t\t\tstdout = `${stdout}${chunk}`.slice(-1024 * 1024);\n\t\t\toptions.onOutput?.(chunk);\n\t\t});\n\t\tproc.stderr.on(\"data\", (chunk: string) => {\n\t\t\tstderr = `${stderr}${chunk}`.slice(-1024 * 1024);\n\t\t\toptions.onOutput?.(chunk);\n\t\t});\n\t\tconst terminal = await waitForChildProcessWithTermination(proc, {\n\t\t\ttimeoutMs: NEEDLE_COMMAND_TIMEOUT_MS,\n\t\t\tkillGraceMs: NEEDLE_KILL_GRACE_MS,\n\t\t});\n\t\tconst timedOut = terminal.reason === \"timeout\";\n\t\treturn {\n\t\t\tok: terminal.code === 0,\n\t\t\tstdout,\n\t\t\tstderr,\n\t\t\tcode: terminal.code,\n\t\t\t...(terminal.code === 0\n\t\t\t\t? {}\n\t\t\t\t: {\n\t\t\t\t\t\terror: timedOut\n\t\t\t\t\t\t\t? `${command} timed out after ${NEEDLE_COMMAND_TIMEOUT_MS}ms`\n\t\t\t\t\t\t\t: stderr.trim() || stdout.trim() || `exit code ${terminal.code ?? \"unknown\"}`,\n\t\t\t\t\t}),\n\t\t};\n\t} catch (error) {\n\t\treturn { ok: false, stdout: \"\", stderr: \"\", error: error instanceof Error ? error.message : String(error) };\n\t}\n}\n\nexport class NeedleRuntime {\n\tprivate readonly _agentDir: string;\n\tprivate readonly _exists: (path: string) => boolean;\n\tprivate readonly _fetch: typeof fetch;\n\tprivate readonly _runCommand: RuntimeCommandRunner;\n\tprivate readonly _hasCommand: (command: string) => boolean;\n\tprivate readonly _hasNvidiaGpu: () => boolean;\n\tprivate readonly _platform: () => string;\n\tprivate readonly _weightsIntegrity: NeedleWeightsIntegrity;\n\n\tconstructor(args: { agentDir: string; deps?: NeedleRuntimeDeps }) {\n\t\tthis._agentDir = args.agentDir;\n\t\tthis._exists = args.deps?.existsFn ?? existsSync;\n\t\tthis._fetch = args.deps?.fetchFn ?? fetch;\n\t\tthis._runCommand = args.deps?.runCommand ?? defaultRunCommand;\n\t\tthis._hasCommand =\n\t\t\targs.deps?.hasCommand ??\n\t\t\t((command) =>\n\t\t\t\tspawnProcessSync(command, [\"--version\"], { encoding: \"utf8\", timeout: 5_000 }).error === undefined);\n\t\tthis._hasNvidiaGpu = args.deps?.hasNvidiaGpu ?? (() => this._hasCommand(\"nvidia-smi\"));\n\t\tthis._platform = args.deps?.platform ?? osPlatform;\n\t\tthis._weightsIntegrity = args.deps?.weightsIntegrity ?? {\n\t\t\tsha256: NEEDLE_WEIGHTS_SHA256,\n\t\t\tbytes: NEEDLE_WEIGHTS_BYTES,\n\t\t};\n\t}\n\n\truntimeDir(): string {\n\t\treturn agentRuntimesDir(\"needle\", this._agentDir);\n\t}\n\n\tmodelsDir(): string {\n\t\treturn agentModelsDir(\"needle\", this._agentDir);\n\t}\n\n\tcheckpointPath(): string {\n\t\treturn join(this.modelsDir(), NEEDLE_CHECKPOINT_FILENAME);\n\t}\n\n\tprivate _srcDir(): string {\n\t\treturn join(this.runtimeDir(), \"src\");\n\t}\n\n\tprivate _venvDir(): string {\n\t\treturn join(this.runtimeDir(), \"venv\");\n\t}\n\n\tprivate _pythonPath(): string {\n\t\treturn this._platform() === \"win32\"\n\t\t\t? join(this._venvDir(), \"Scripts\", \"python.exe\")\n\t\t\t: join(this._venvDir(), \"bin\", \"python\");\n\t}\n\n\t/** The installed `needle` console script (from `[project.scripts]`, written by `pip install -e`)\n\t * — the only invokable entry point, since `needle/cli.py` has no `__main__` guard. */\n\tprivate _entryPath(): string {\n\t\treturn this._platform() === \"win32\"\n\t\t\t? join(this._venvDir(), \"Scripts\", \"needle.exe\")\n\t\t\t: join(this._venvDir(), \"bin\", \"needle\");\n\t}\n\n\tprivate _manifestPath(): string {\n\t\treturn join(this.runtimeDir(), \"install.json\");\n\t}\n\n\tprivate _readManifest(): NeedleInstallMetadata | undefined {\n\t\ttry {\n\t\t\tconst parsed = JSON.parse(readFileSync(this._manifestPath(), \"utf8\")) as {\n\t\t\t\tcommit?: unknown;\n\t\t\t\tentryCommand?: unknown;\n\t\t\t};\n\t\t\treturn typeof parsed.commit === \"string\" && typeof parsed.entryCommand === \"string\"\n\t\t\t\t? { commit: parsed.commit, entryCommand: parsed.entryCommand }\n\t\t\t\t: undefined;\n\t\t} catch {\n\t\t\treturn undefined;\n\t\t}\n\t}\n\n\tprivate _writeManifest(metadata: NeedleInstallMetadata): void {\n\t\twriteFileSync(this._manifestPath(), JSON.stringify(metadata, null, \"\\t\"));\n\t}\n\n\tasync detect(): Promise<NeedleDetectResult> {\n\t\tconst installed = this._exists(this._entryPath());\n\t\treturn {\n\t\t\tinstalled,\n\t\t\tinstallDir: installed ? this.runtimeDir() : undefined,\n\t\t\tcommit: this._readManifest()?.commit,\n\t\t\tpythonAvailable: this._hasCommand(\"python3\"),\n\t\t\tcheckpointPresent: this._exists(this.checkpointPath()),\n\t\t};\n\t}\n\n\t/**\n\t * Clone the pinned needle commit and build a contained, pi-owned runtime (consent-gated by the\n\t * caller, same contract as OllamaRuntime#installManaged / PrismLlamaCppRuntime#installManaged —\n\t * this method only does the mechanical clone+build+verify and reports the outcome honestly). See\n\t * the module docstring for exactly which upstream `setup` steps are and are not replicated under\n\t * containment.\n\t */\n\tasync installManaged(onProgress?: (status: string) => void): Promise<{ ok: boolean; error?: string }> {\n\t\tif (!this._hasCommand(\"git\")) {\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\terror: `git-missing: git is required to clone needle (${NEEDLE_REPO_URL}). Install git (e.g. \\`apt-get install git\\`, \\`brew install git\\`) and try again.`,\n\t\t\t};\n\t\t}\n\t\tif (!this._hasCommand(\"python3\")) {\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\terror: \"python-missing: python3 (>=3.11) is required to run needle. Install Python 3.11+ (e.g. `apt-get install python3 python3-venv`, `brew install python@3.12`) and try again.\",\n\t\t\t};\n\t\t}\n\n\t\tmkdirSync(this.runtimeDir(), { recursive: true });\n\t\tconst srcDir = this._srcDir();\n\t\tif (this._exists(srcDir)) rmSync(srcDir, { recursive: true, force: true });\n\n\t\tonProgress?.(`Cloning ${NEEDLE_REPO_URL}…`);\n\t\tconst cloned = await this._cloneAtPinnedCommit(srcDir);\n\t\tif (!cloned.ok) return cloned;\n\n\t\tonProgress?.(`Creating isolated Python venv at ${this._venvDir()}…`);\n\t\tconst venv = await this._runCommand(\"python3\", [\"-m\", \"venv\", this._venvDir()]);\n\t\tif (!venv.ok) return { ok: false, error: `setup-fail: ${tailLines(venv.error ?? venv.stderr)}` };\n\t\tif (!this._exists(this._pythonPath())) {\n\t\t\treturn { ok: false, error: `setup-fail: venv created but ${this._pythonPath()} was not found` };\n\t\t}\n\n\t\tonProgress?.(\"Upgrading pip inside the pi-managed venv…\");\n\t\tconst pipUpgrade = await this._runCommand(this._pythonPath(), [\"-m\", \"pip\", \"install\", \"--upgrade\", \"pip\"]);\n\t\tif (!pipUpgrade.ok) {\n\t\t\treturn { ok: false, error: `setup-fail: ${tailLines(pipUpgrade.error ?? pipUpgrade.stderr)}` };\n\t\t}\n\n\t\tonProgress?.(\"Installing needle (editable) into the pi-managed venv…\");\n\t\tconst install = await this._runCommand(this._pythonPath(), [\"-m\", \"pip\", \"install\", \"-e\", srcDir]);\n\t\tif (!install.ok) return { ok: false, error: `setup-fail: ${tailLines(install.error ?? install.stderr)}` };\n\n\t\tconst cudaAvailable = this._hasNvidiaGpu();\n\t\tonProgress?.(cudaAvailable ? \"Installing JAX (CUDA 12 backend)…\" : \"Installing JAX (CPU backend)…\");\n\t\tconst jaxArgs = cudaAvailable ? [\"jax[cuda12]\"] : [\"jax\"];\n\t\tconst jax = await this._runCommand(this._pythonPath(), [\"-m\", \"pip\", \"install\", \"-U\", ...jaxArgs]);\n\t\tif (!jax.ok) return { ok: false, error: `setup-fail: ${tailLines(jax.error ?? jax.stderr)}` };\n\n\t\tonProgress?.(\"Verifying the needle install…\");\n\t\tconst verify = await this._runCommand(this._pythonPath(), [\"-c\", \"import jax, needle; print(needle.__file__)\"]);\n\t\tif (!verify.ok) return { ok: false, error: `verify-fail: ${tailLines(verify.error ?? verify.stderr)}` };\n\n\t\tconst entryCommand = this._entryPath();\n\t\tif (!this._exists(entryCommand)) {\n\t\t\treturn { ok: false, error: `verify-fail: install reported success but ${entryCommand} was not found` };\n\t\t}\n\n\t\tthis._writeManifest({ commit: NEEDLE_PINNED_COMMIT, entryCommand });\n\t\tonProgress?.(\"needle installed.\");\n\t\treturn { ok: true };\n\t}\n\n\t/**\n\t * A plain `git clone --depth 1` only lands on {@link NEEDLE_PINNED_COMMIT} when it still happens\n\t * to be the remote's current default-branch tip. Fetching the exact SHA directly instead (verified\n\t * against the real repo) pins reliably even after upstream moves on: GitHub serves any reachable\n\t * commit for a public repo via `git fetch <sha>`, not just refs.\n\t */\n\tprivate async _cloneAtPinnedCommit(srcDir: string): Promise<{ ok: boolean; error?: string }> {\n\t\tconst init = await this._runCommand(\"git\", [\"init\", \"-q\", srcDir]);\n\t\tif (!init.ok) return { ok: false, error: `clone-fail: ${tailLines(init.error ?? init.stderr)}` };\n\t\tconst remote = await this._runCommand(\"git\", [\"-C\", srcDir, \"remote\", \"add\", \"origin\", NEEDLE_REPO_URL]);\n\t\tif (!remote.ok) return { ok: false, error: `clone-fail: ${tailLines(remote.error ?? remote.stderr)}` };\n\t\tconst fetched = await this._runCommand(\"git\", [\n\t\t\t\"-C\",\n\t\t\tsrcDir,\n\t\t\t\"fetch\",\n\t\t\t\"--depth\",\n\t\t\t\"1\",\n\t\t\t\"origin\",\n\t\t\tNEEDLE_PINNED_COMMIT,\n\t\t]);\n\t\tif (!fetched.ok) return { ok: false, error: `clone-fail: ${tailLines(fetched.error ?? fetched.stderr)}` };\n\t\tconst checkout = await this._runCommand(\"git\", [\"-C\", srcDir, \"checkout\", \"-q\", \"FETCH_HEAD\"]);\n\t\tif (!checkout.ok) return { ok: false, error: `clone-fail: ${tailLines(checkout.error ?? checkout.stderr)}` };\n\t\treturn { ok: true };\n\t}\n\n\t/**\n\t * Download the pretrained base weights (`needle.pkl`). `needle run` takes an explicit\n\t * `--checkpoint` and does NOT auto-download one (unlike `needle playground`/`finetune`) — see the\n\t * module docstring. Never called implicitly by installManaged/runFunctionCall; the caller decides\n\t * when to pull weights.\n\t *\n\t * `needle.pkl` is a pickle file — arbitrary code execution on load by construction (see the\n\t * module-level SECURITY note) — so every download is verified against the pinned sha256+size\n\t * ({@link NEEDLE_WEIGHTS_SHA256}/{@link NEEDLE_WEIGHTS_BYTES}, overridable only via the\n\t * `weightsIntegrity` test seam) computed in the same streaming pass that writes the file, with the\n\t * partial/mismatched file deleted on ANY failure — this never leaves an unverified or wrong pickle\n\t * sitting where {@link runFunctionCall} would load it.\n\t */\n\tasync downloadWeights(onProgress?: (status: string) => void): Promise<NeedleWeightsDownloadResult> {\n\t\tconst destPath = this.checkpointPath();\n\t\tconst url = `https://huggingface.co/${NEEDLE_HF_MODEL_REPO}/resolve/main/${NEEDLE_CHECKPOINT_FILENAME}`;\n\t\tmkdirSync(this.modelsDir(), { recursive: true });\n\n\t\tif (this._exists(destPath) && this._fileSizeBytes(destPath) === this._weightsIntegrity.bytes) {\n\t\t\tonProgress?.(\n\t\t\t\t`${NEEDLE_CHECKPOINT_FILENAME} already downloaded (${this._weightsIntegrity.bytes} bytes) — skipping.`,\n\t\t\t);\n\t\t\treturn { ok: true, path: destPath, skipped: true };\n\t\t}\n\n\t\tonProgress?.(`Downloading ${NEEDLE_CHECKPOINT_FILENAME} from ${NEEDLE_HF_MODEL_REPO}…`);\n\t\tlet response: Response;\n\t\ttry {\n\t\t\tresponse = await this._fetch(url);\n\t\t} catch (error) {\n\t\t\treturn { ok: false, error: `download-fail: ${error instanceof Error ? error.message : String(error)}` };\n\t\t}\n\t\tif (!response.ok || !response.body) {\n\t\t\treturn { ok: false, error: `download-fail: HTTP ${response.status}` };\n\t\t}\n\n\t\tconst hash = createHash(\"sha256\");\n\t\ttry {\n\t\t\tawait pipeline(response.body as unknown as Readable, hashingPassThrough(hash), createWriteStream(destPath));\n\t\t} catch (error) {\n\t\t\tthis._cleanupPartial(destPath);\n\t\t\treturn { ok: false, error: `download-fail: ${error instanceof Error ? error.message : String(error)}` };\n\t\t}\n\n\t\tconst actualBytes = this._fileSizeBytes(destPath);\n\t\tconst actualSha256 = hash.digest(\"hex\");\n\t\tif (actualBytes !== this._weightsIntegrity.bytes || actualSha256 !== this._weightsIntegrity.sha256) {\n\t\t\tthis._cleanupPartial(destPath);\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\terror: `integrity-fail: downloaded ${NEEDLE_CHECKPOINT_FILENAME} does not match the pinned checksum — expected sha256 ${this._weightsIntegrity.sha256} (${this._weightsIntegrity.bytes} bytes), got ${actualSha256} (${actualBytes ?? 0} bytes). Refusing to keep a pickle file that failed integrity verification.`,\n\t\t\t};\n\t\t}\n\n\t\tonProgress?.(`${NEEDLE_CHECKPOINT_FILENAME} downloaded and verified (sha256 ${actualSha256}).`);\n\t\treturn { ok: true, path: destPath };\n\t}\n\n\tprivate _fileSizeBytes(path: string): number | undefined {\n\t\ttry {\n\t\t\treturn statSync(path).size;\n\t\t} catch {\n\t\t\treturn undefined;\n\t\t}\n\t}\n\n\tprivate _cleanupPartial(path: string): void {\n\t\ttry {\n\t\t\trmSync(path, { force: true });\n\t\t} catch {\n\t\t\t// best-effort cleanup\n\t\t}\n\t}\n\n\t/**\n\t * Run one single-shot inference through `needle run --checkpoint ... --query ... --tools ...`\n\t * inside the contained venv's installed console script. Argv is passed as an array to the\n\t * injected `runCommand` seam — never a shell string — so query/tools text containing quotes,\n\t * spaces, or other shell-hostile characters is passed through literally (verified against a real\n\t * invocation; see the module docstring). `tools` is serialized with `JSON.stringify` exactly once.\n\t */\n\tasync runFunctionCall(\n\t\trequest: NeedleFunctionCallRequest,\n\t\toptions?: { checkpointPath?: string },\n\t): Promise<NeedleFunctionCallResult> {\n\t\tconst entryCommand = this._entryPath();\n\t\tif (!this._exists(entryCommand)) {\n\t\t\treturn { ok: false, error: \"not-installed: run installManaged() first\", rawOutput: \"\" };\n\t\t}\n\t\tconst checkpointPath = options?.checkpointPath ?? this.checkpointPath();\n\t\tif (!this._exists(checkpointPath)) {\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\terror: `checkpoint-missing: no checkpoint at ${checkpointPath} — run downloadWeights() first`,\n\t\t\t\trawOutput: \"\",\n\t\t\t};\n\t\t}\n\n\t\tconst argv = [\n\t\t\t\"run\",\n\t\t\t\"--checkpoint\",\n\t\t\tcheckpointPath,\n\t\t\t\"--query\",\n\t\t\trequest.query,\n\t\t\t\"--tools\",\n\t\t\tJSON.stringify(request.tools),\n\t\t];\n\t\tconst result = await this._runCommand(entryCommand, argv);\n\t\tconst rawOutput = [result.stdout, result.stderr].filter(Boolean).join(\"\\n\");\n\t\tif (!result.ok) {\n\t\t\treturn { ok: false, error: `run-fail: ${tailLines(result.error ?? result.stderr)}`, rawOutput };\n\t\t}\n\t\treturn this._parseFunctionCall(result.stdout, rawOutput);\n\t}\n\n\t/**\n\t * Strictly parse a real `needle run` stdout capture:\n\t * ```\n\t * Loading checkpoint: <path>\n\t * Model parameters: <n>\n\t *\n\t * Query: <query>\n\t * Tools: <tools, truncated to 80 chars>...\n\t *\n\t * <tool_call>[{\"name\":\"...\",\"arguments\":{...}}]\n\t * ```\n\t * (diagnostic lines above the marker vary — e.g. a one-time \"Downloading pretrained tokenizer...\"\n\t * line on a cold cache — so parsing locates the `<tool_call>` marker rather than assuming a fixed\n\t * line count/position). Unparseable output is always an error carrying the raw text, never a\n\t * guessed result.\n\t */\n\tprivate _parseFunctionCall(stdout: string, rawOutput: string): NeedleFunctionCallResult {\n\t\tconst markerIndex = stdout.indexOf(NEEDLE_TOOL_CALL_MARKER);\n\t\tif (markerIndex < 0) {\n\t\t\treturn { ok: false, error: `unparseable-output: no ${NEEDLE_TOOL_CALL_MARKER} marker in stdout`, rawOutput };\n\t\t}\n\t\tconst jsonText = stdout.slice(markerIndex + NEEDLE_TOOL_CALL_MARKER.length).trim();\n\t\tlet parsed: unknown;\n\t\ttry {\n\t\t\tparsed = JSON.parse(jsonText);\n\t\t} catch (error) {\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\terror: `unparseable-output: ${error instanceof Error ? error.message : String(error)}`,\n\t\t\t\trawOutput,\n\t\t\t};\n\t\t}\n\t\tif (!Array.isArray(parsed) || parsed.length === 0) {\n\t\t\treturn { ok: false, error: \"unparseable-output: expected a non-empty tool-call array\", rawOutput };\n\t\t}\n\t\tconst first = parsed[0] as { name?: unknown; arguments?: unknown };\n\t\tif (\n\t\t\ttypeof first !== \"object\" ||\n\t\t\tfirst === null ||\n\t\t\ttypeof first.name !== \"string\" ||\n\t\t\ttypeof first.arguments !== \"object\" ||\n\t\t\tfirst.arguments === null\n\t\t) {\n\t\t\treturn { ok: false, error: \"unparseable-output: tool call missing name/arguments\", rawOutput };\n\t\t}\n\t\treturn { ok: true, call: { name: first.name, arguments: first.arguments as Record<string, unknown> } };\n\t}\n\n\t/** Canned get_weather query/tool through {@link runFunctionCall}; the wiring task uses this as the\n\t * post-install verification step. */\n\tasync smokeTest(onProgress?: (status: string) => void): Promise<NeedleSmokeTestResult> {\n\t\tonProgress?.(\"Running needle smoke test…\");\n\t\tconst startedAt = Date.now();\n\t\tconst result = await this.runFunctionCall({ query: NEEDLE_SMOKE_QUERY, tools: NEEDLE_SMOKE_TOOLS });\n\t\tconst latencyMs = Date.now() - startedAt;\n\t\tif (!result.ok) {\n\t\t\tonProgress?.(`Smoke test failed: ${result.error}`);\n\t\t\treturn { ok: false, latencyMs, error: result.error };\n\t\t}\n\t\tonProgress?.(`Smoke test ok (${latencyMs}ms): ${result.call.name}`);\n\t\treturn { ok: true, latencyMs, call: result.call };\n\t}\n\n\t/**\n\t * No-op: every needle invocation here is a single-shot `runCommand` call that spawns, waits for\n\t * exit, and returns — there is no persistent/detached child process this runtime owns between\n\t * calls for dispose() to track or kill (contrast OllamaRuntime/PrismLlamaCppRuntime's long-lived\n\t * `serve()` child).\n\t */\n\tdispose(): void {}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"needle-runtime.js","sourceRoot":"","sources":["../../../src/core/models/needle-runtime.ts"],"names":[],"mappings":"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","sourcesContent":["import { createHash } from \"node:crypto\";\nimport { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from \"node:fs\";\nimport { platform as osPlatform } from \"node:os\";\nimport { join } from \"node:path\";\nimport { type Readable, Transform } from \"node:stream\";\nimport { modelsDir as agentModelsDir, runtimesDir as agentRuntimesDir } from \"../agent-paths.ts\";\nimport {\n\tcreateRuntimeCommandRunner,\n\tfetchRuntimeDownload,\n\ttype RuntimeCommandRunner,\n\tremovePartialDownload,\n\truntimeCommandAvailable,\n\ttryFileSizeBytes,\n\twriteRuntimeDownload,\n} from \"./runtime-process.ts\";\n\n/**\n * Managed runtime for needle (https://github.com/cactus-compute/needle), a 26M-parameter single-shot\n * function-calling model. Needle exposes no server — the only integration surface is CLI/library\n * invocation — so this module owns clone+build of a pinned commit into a contained venv, base\n * checkpoint download, and one-shot `needle run` invocation/parsing. Mirrors local-runtime.ts's\n * OllamaRuntime/TransformersRuntime and llamacpp-runtime.ts's PrismLlamaCppRuntime: injectable seams\n * for exists/fetch/run-command, pi-owned directories under agentDir (runtimes/, models/), onProgress\n * as best-effort UI feedback, and honest error taxonomies instead of silent fallbacks.\n *\n * Investigation findings (verified against a real clone + real venv + real CPU inference run, not\n * just the README):\n *\n * - `needle run` (the CLI's single-inference subcommand) takes a REQUIRED `--checkpoint` and does\n * NOT auto-download one — unlike `needle playground`/`finetune`, which resolve a checkpoint\n * internally. The pretrained base checkpoint (`needle.pkl`) lives on `Cactus-Compute/needle` on\n * Hugging Face and is fetched directly by {@link NeedleRuntime.downloadWeights} (never invoked\n * implicitly by installManaged/runFunctionCall — this module never silently starts a large\n * download on the caller's behalf).\n * - SECURITY (owner-flagged, verified during investigation): `Cactus-Compute/needle` on Hugging Face\n * publishes THREE weight artifacts — `needle.pkl` (52,633,098 bytes), `model.safetensors`\n * (reported as a different param count on the HF model card, 30.4M vs the 26,315,421 a real\n * `needle run` printed — likely not even the same checkpoint), and `needle-cq4.zip`. I grepped the\n * ENTIRE needle package (cli.py, model/run.py, model/export.py, model/quantize.py,\n * training/{finetune,pretrain,train}.py, utils/distributed.py, ui/server.py — every `pickle`/`.zip`\n * hit in the repo) and confirmed every checkpoint load/save path in the codebase — including the\n * one `needle run` uses — is `pickle.load`/`pickle.dump` on a `.pkl` file. There is NO safetensors\n * reader anywhere in the package; `model.safetensors` is not consumed by any code this module\n * drives. `needle-cq4.zip` (\"Cactus Quantized 4-bit\"?) isn't referenced by any code here either —\n * the README states production inference runs on the separate Cactus C++ engine\n * (cactus-compute/cactus), which very plausibly consumes its own format; that repo was not audited\n * here. Bottom line: **this module has no choice but to fetch and deserialize `needle.pkl` via\n * Python's `pickle` module, which executes arbitrary code by construction** — there is no\n * safetensors alternative available in the code path we drive. Given that, {@link\n * NeedleRuntime.downloadWeights} pins the exact sha256 ({@link NEEDLE_WEIGHTS_SHA256}) and byte\n * count ({@link NEEDLE_WEIGHTS_BYTES}) of the file as verified on 2026-07-18 (direct `sha256sum` of\n * a real download, cross-checked against Hugging Face's own `x-linked-etag`/`x-linked-size`\n * headers on the resolve redirect, at repo commit `5f89b4307696d669c3df1d38ae057e6e1728b107`) and\n * VERIFIES every download against that pin, refusing to keep any file that doesn't match — this\n * catches a compromised/tampered/swapped artifact but does NOT make loading a pickle file safe in\n * the abstract; the actual `pickle.load` execution happens entirely inside needle's own Python\n * process, outside this module's control. The owner should decide whether serving this model at\n * all is acceptable given upstream's format choice.\n * - The upstream `setup` script does more than a contained managed install can honor: it can `sudo\n * apt-get install` a newer Python or `python3-venv`, `sudo modprobe` TPU kernel modules, toggle\n * transparent hugepages via a root-owned sysfs write, and interactively prompts for a\n * WANDB_API_KEY. None of that is available under containment (no writes outside the pi-owned dir,\n * no sudo, no interactive prompts, no global installs) and none of it is required for the\n * documented Mac/PC single-inference quickstart path. {@link NeedleRuntime.installManaged} instead\n * replicates only the containable core: `python3 -m venv`, `pip install -e <clonedRepo>` (the\n * script's own `pip install -e . -q`), and the CPU (or CUDA, when an NVIDIA GPU is detected) JAX\n * backend install. TPU support and the sudo-gated OS package/kernel-module steps are intentionally\n * NOT replicated.\n * - `needle run`'s console-script entry point (`<venv>/bin/needle`, installed by\n * `pip install -e .` from the `[project.scripts]` table) is the only way to invoke the CLI:\n * `needle/cli.py` has no `if __name__ == \"__main__\":` guard, so `python -m needle.cli` silently\n * does nothing — the installed console script is required.\n * - A verified real stdout capture of `needle run --checkpoint <path> --query \"...\" --tools '[...]'`\n * is multi-line diagnostic prose followed by the tool call:\n * ```\n * Loading checkpoint: <path>\n * Downloading pretrained tokenizer from HuggingFace... (first run only — cached after)\n * Model parameters: 26,315,421\n *\n * Query: <query>\n * Tools: <tools JSON, truncated to 80 chars>...\n *\n * <tool_call>[{\"name\":\"get_weather\",\"arguments\":{\"location\":\"SanFrancisco\"}}]\n * ```\n * The `<tool_call>` marker is a literal SentencePiece user-defined-symbol token, always emitted as\n * the first generated token per the model's own answer format. {@link NeedleRuntime}'s stdout\n * parser locates that marker and strictly `JSON.parse`s everything after it — never guessing a\n * result from unparseable output.\n * - Known upstream quirk (verified against a live run with a camelCase tool name): `needle run`'s CLI\n * wrapper (`main()` in `needle/model/run.py`) streams tokens straight to stdout and never applies\n * the tool-name restoration its own `generate()` return value receives — a tool name that wasn't\n * already snake_case (e.g. `getWeatherNow`) is reported back snake-cased (`get_weather_now`), not\n * in its original casing. This is a limitation of the upstream CLI, not something patched here.\n * - Pinned commit `ffb1c5144c5a16cb8ec650dbc8a6f6fd3854f8f2` was captured via a real `git clone` of\n * the repo's default branch HEAD on 2026-07-18 (the repo's own history shows no pushes since\n * 2026-07-01, so this is not stale). A plain `git clone --depth 1` only reliably lands on a pinned\n * commit when it still happens to be the remote's current tip; {@link NeedleRuntime.installManaged}\n * instead fetches the exact commit SHA directly (`git fetch --depth 1 origin <sha>`), which GitHub\n * serves for any reachable commit on a public repo, so the pin holds even after upstream moves on.\n */\n\nexport const NEEDLE_REPO_URL = \"https://github.com/cactus-compute/needle.git\";\n\n/**\n * Pinned needle commit — captured via a real `git clone` of the repo's default-branch HEAD on\n * 2026-07-18 (`git ls-remote https://github.com/cactus-compute/needle HEAD` resolves to the same\n * SHA). Bump here (re-verify with the same command) when a newer commit is needed.\n */\nexport const NEEDLE_PINNED_COMMIT = \"ffb1c5144c5a16cb8ec650dbc8a6f6fd3854f8f2\";\n\nconst NEEDLE_HF_MODEL_REPO = \"Cactus-Compute/needle\";\nconst NEEDLE_CHECKPOINT_FILENAME = \"needle.pkl\";\nconst NEEDLE_TOOL_CALL_MARKER = \"<tool_call>\";\n\n/**\n * Pinned integrity for `needle.pkl` — see the module-level SECURITY note: this is a pickle file\n * (arbitrary code execution on load by construction), so every download is verified against this\n * exact sha256+size before being kept. Captured 2026-07-18: `sha256sum` of a real download matched\n * Hugging Face's `x-linked-etag` header on the resolve redirect at repo commit\n * `5f89b4307696d669c3df1d38ae057e6e1728b107`. Bump both together (re-verify the same way) only for a\n * deliberate, reviewed upstream weights update.\n */\nexport const NEEDLE_WEIGHTS_SHA256 = \"40a32e91d1d4197bf15ba559b74f6727c342dc8746918742fc7d8e2c1f18df40\";\nexport const NEEDLE_WEIGHTS_BYTES = 52_633_098;\n\nconst NEEDLE_COMMAND_TIMEOUT_MS = 10 * 60_000;\nconst NEEDLE_KILL_GRACE_MS = 2_000;\n\nconst NEEDLE_SMOKE_QUERY = \"What's the weather in San Francisco?\";\nconst NEEDLE_SMOKE_TOOLS = [\n\t{\n\t\tname: \"get_weather\",\n\t\tdescription: \"Get current weather for a city.\",\n\t\tparameters: { location: { type: \"string\", description: \"City name.\", required: true } },\n\t},\n];\n\nexport interface NeedleDetectResult {\n\tinstalled: boolean;\n\tinstallDir?: string;\n\tcommit?: string;\n\tpythonAvailable: boolean;\n\tcheckpointPresent: boolean;\n}\n\nexport interface NeedleFunctionCallRequest {\n\tquery: string;\n\t/** A JSON-serializable tool schema value (never a pre-stringified JSON string) — serialized\n\t * exactly once by {@link NeedleRuntime.runFunctionCall}, never by the caller. */\n\ttools: unknown;\n}\n\nexport interface NeedleFunctionCall {\n\tname: string;\n\targuments: Record<string, unknown>;\n}\n\nexport type NeedleFunctionCallResult =\n\t| { ok: true; call: NeedleFunctionCall }\n\t| { ok: false; error: string; rawOutput: string };\n\nexport interface NeedleSmokeTestResult {\n\tok: boolean;\n\tlatencyMs: number;\n\tcall?: NeedleFunctionCall;\n\terror?: string;\n}\n\nexport interface NeedleWeightsDownloadResult {\n\tok: boolean;\n\tpath?: string;\n\tskipped?: boolean;\n\terror?: string;\n}\n\ninterface NeedleWeightsIntegrity {\n\tsha256: string;\n\tbytes: number;\n}\n\nexport interface NeedleRuntimeDeps {\n\texistsFn?: (path: string) => boolean;\n\tfetchFn?: typeof fetch;\n\t/** Runs git/pip/python commands. Injectable so installManaged/runFunctionCall's orchestration is\n\t * testable without a real clone/venv/inference. Defaults to a real spawn-and-collect-output\n\t * runner (installs can run long; a single inference call is comparatively quick but still shells\n\t * out to a real interpreter). */\n\trunCommand?: RuntimeCommandRunner;\n\t/** Whether a named command exists on PATH (git, python3, nvidia-smi). */\n\thasCommand?: (command: string) => boolean;\n\thasNvidiaGpu?: () => boolean;\n\tplatform?: () => string;\n\t/** Expected weights sha256+size. Defaults to {@link NEEDLE_WEIGHTS_SHA256}/{@link\n\t * NEEDLE_WEIGHTS_BYTES} — the real pinned values. Overridable ONLY so tests can exercise the full\n\t * download+verify path with small synthetic content instead of the real 52MB pickle; this is a\n\t * constructor-level seam for a trusted caller, the same trust boundary every other injectable dep\n\t * in this class already relies on (fetchFn/runCommand could equally be used to bypass anything).\n\t */\n\tweightsIntegrity?: NeedleWeightsIntegrity;\n}\n\ninterface NeedleInstallMetadata {\n\tcommit: string;\n\tentryCommand: string;\n}\n\nfunction tailLines(value: string | undefined, count = 3): string {\n\treturn value?.trim().split(\"\\n\").slice(-count).join(\"\\n\") || \"unknown error\";\n}\n\n/** Pass bytes through unchanged while feeding them into a running hash — lets a single `pipeline()`\n * call both write the download to disk and compute its sha256 in one streaming pass. */\nfunction hashingPassThrough(hash: ReturnType<typeof createHash>): Transform {\n\treturn new Transform({\n\t\ttransform(chunk: Buffer, _encoding, callback) {\n\t\t\thash.update(chunk);\n\t\t\tcallback(null, chunk);\n\t\t},\n\t});\n}\n\nconst defaultRunCommand = createRuntimeCommandRunner({\n\ttimeoutMs: NEEDLE_COMMAND_TIMEOUT_MS,\n\tkillGraceMs: NEEDLE_KILL_GRACE_MS,\n});\n\nexport class NeedleRuntime {\n\tprivate readonly _agentDir: string;\n\tprivate readonly _exists: (path: string) => boolean;\n\tprivate readonly _fetch: typeof fetch;\n\tprivate readonly _runCommand: RuntimeCommandRunner;\n\tprivate readonly _hasCommand: (command: string) => boolean;\n\tprivate readonly _hasNvidiaGpu: () => boolean;\n\tprivate readonly _platform: () => string;\n\tprivate readonly _weightsIntegrity: NeedleWeightsIntegrity;\n\n\tconstructor(args: { agentDir: string; deps?: NeedleRuntimeDeps }) {\n\t\tthis._agentDir = args.agentDir;\n\t\tthis._exists = args.deps?.existsFn ?? existsSync;\n\t\tthis._fetch = args.deps?.fetchFn ?? fetch;\n\t\tthis._runCommand = args.deps?.runCommand ?? defaultRunCommand;\n\t\tthis._hasCommand = args.deps?.hasCommand ?? runtimeCommandAvailable;\n\t\tthis._hasNvidiaGpu = args.deps?.hasNvidiaGpu ?? (() => this._hasCommand(\"nvidia-smi\"));\n\t\tthis._platform = args.deps?.platform ?? osPlatform;\n\t\tthis._weightsIntegrity = args.deps?.weightsIntegrity ?? {\n\t\t\tsha256: NEEDLE_WEIGHTS_SHA256,\n\t\t\tbytes: NEEDLE_WEIGHTS_BYTES,\n\t\t};\n\t}\n\n\truntimeDir(): string {\n\t\treturn agentRuntimesDir(\"needle\", this._agentDir);\n\t}\n\n\tmodelsDir(): string {\n\t\treturn agentModelsDir(\"needle\", this._agentDir);\n\t}\n\n\tcheckpointPath(): string {\n\t\treturn join(this.modelsDir(), NEEDLE_CHECKPOINT_FILENAME);\n\t}\n\n\tprivate _srcDir(): string {\n\t\treturn join(this.runtimeDir(), \"src\");\n\t}\n\n\tprivate _venvDir(): string {\n\t\treturn join(this.runtimeDir(), \"venv\");\n\t}\n\n\tprivate _pythonPath(): string {\n\t\treturn this._platform() === \"win32\"\n\t\t\t? join(this._venvDir(), \"Scripts\", \"python.exe\")\n\t\t\t: join(this._venvDir(), \"bin\", \"python\");\n\t}\n\n\t/** The installed `needle` console script (from `[project.scripts]`, written by `pip install -e`)\n\t * — the only invokable entry point, since `needle/cli.py` has no `__main__` guard. */\n\tprivate _entryPath(): string {\n\t\treturn this._platform() === \"win32\"\n\t\t\t? join(this._venvDir(), \"Scripts\", \"needle.exe\")\n\t\t\t: join(this._venvDir(), \"bin\", \"needle\");\n\t}\n\n\tprivate _manifestPath(): string {\n\t\treturn join(this.runtimeDir(), \"install.json\");\n\t}\n\n\tprivate _readManifest(): NeedleInstallMetadata | undefined {\n\t\ttry {\n\t\t\tconst parsed = JSON.parse(readFileSync(this._manifestPath(), \"utf8\")) as {\n\t\t\t\tcommit?: unknown;\n\t\t\t\tentryCommand?: unknown;\n\t\t\t};\n\t\t\treturn typeof parsed.commit === \"string\" && typeof parsed.entryCommand === \"string\"\n\t\t\t\t? { commit: parsed.commit, entryCommand: parsed.entryCommand }\n\t\t\t\t: undefined;\n\t\t} catch {\n\t\t\treturn undefined;\n\t\t}\n\t}\n\n\tprivate _writeManifest(metadata: NeedleInstallMetadata): void {\n\t\twriteFileSync(this._manifestPath(), JSON.stringify(metadata, null, \"\\t\"));\n\t}\n\n\tasync detect(): Promise<NeedleDetectResult> {\n\t\tconst installed = this._exists(this._entryPath());\n\t\treturn {\n\t\t\tinstalled,\n\t\t\tinstallDir: installed ? this.runtimeDir() : undefined,\n\t\t\tcommit: this._readManifest()?.commit,\n\t\t\tpythonAvailable: this._hasCommand(\"python3\"),\n\t\t\tcheckpointPresent: this._exists(this.checkpointPath()),\n\t\t};\n\t}\n\n\t/**\n\t * Clone the pinned needle commit and build a contained, pi-owned runtime (consent-gated by the\n\t * caller, same contract as OllamaRuntime#installManaged / PrismLlamaCppRuntime#installManaged —\n\t * this method only does the mechanical clone+build+verify and reports the outcome honestly). See\n\t * the module docstring for exactly which upstream `setup` steps are and are not replicated under\n\t * containment.\n\t */\n\tasync installManaged(onProgress?: (status: string) => void): Promise<{ ok: boolean; error?: string }> {\n\t\tif (!this._hasCommand(\"git\")) {\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\terror: `git-missing: git is required to clone needle (${NEEDLE_REPO_URL}). Install git (e.g. \\`apt-get install git\\`, \\`brew install git\\`) and try again.`,\n\t\t\t};\n\t\t}\n\t\tif (!this._hasCommand(\"python3\")) {\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\terror: \"python-missing: python3 (>=3.11) is required to run needle. Install Python 3.11+ (e.g. `apt-get install python3 python3-venv`, `brew install python@3.12`) and try again.\",\n\t\t\t};\n\t\t}\n\n\t\tmkdirSync(this.runtimeDir(), { recursive: true });\n\t\tconst srcDir = this._srcDir();\n\t\tif (this._exists(srcDir)) rmSync(srcDir, { recursive: true, force: true });\n\n\t\tonProgress?.(`Cloning ${NEEDLE_REPO_URL}…`);\n\t\tconst cloned = await this._cloneAtPinnedCommit(srcDir);\n\t\tif (!cloned.ok) return cloned;\n\n\t\tonProgress?.(`Creating isolated Python venv at ${this._venvDir()}…`);\n\t\tconst venv = await this._runCommand(\"python3\", [\"-m\", \"venv\", this._venvDir()]);\n\t\tif (!venv.ok) return { ok: false, error: `setup-fail: ${tailLines(venv.error ?? venv.stderr)}` };\n\t\tif (!this._exists(this._pythonPath())) {\n\t\t\treturn { ok: false, error: `setup-fail: venv created but ${this._pythonPath()} was not found` };\n\t\t}\n\n\t\tonProgress?.(\"Upgrading pip inside the pi-managed venv…\");\n\t\tconst pipUpgrade = await this._runCommand(this._pythonPath(), [\"-m\", \"pip\", \"install\", \"--upgrade\", \"pip\"]);\n\t\tif (!pipUpgrade.ok) {\n\t\t\treturn { ok: false, error: `setup-fail: ${tailLines(pipUpgrade.error ?? pipUpgrade.stderr)}` };\n\t\t}\n\n\t\tonProgress?.(\"Installing needle (editable) into the pi-managed venv…\");\n\t\tconst install = await this._runCommand(this._pythonPath(), [\"-m\", \"pip\", \"install\", \"-e\", srcDir]);\n\t\tif (!install.ok) return { ok: false, error: `setup-fail: ${tailLines(install.error ?? install.stderr)}` };\n\n\t\tconst cudaAvailable = this._hasNvidiaGpu();\n\t\tonProgress?.(cudaAvailable ? \"Installing JAX (CUDA 12 backend)…\" : \"Installing JAX (CPU backend)…\");\n\t\tconst jaxArgs = cudaAvailable ? [\"jax[cuda12]\"] : [\"jax\"];\n\t\tconst jax = await this._runCommand(this._pythonPath(), [\"-m\", \"pip\", \"install\", \"-U\", ...jaxArgs]);\n\t\tif (!jax.ok) return { ok: false, error: `setup-fail: ${tailLines(jax.error ?? jax.stderr)}` };\n\n\t\tonProgress?.(\"Verifying the needle install…\");\n\t\tconst verify = await this._runCommand(this._pythonPath(), [\"-c\", \"import jax, needle; print(needle.__file__)\"]);\n\t\tif (!verify.ok) return { ok: false, error: `verify-fail: ${tailLines(verify.error ?? verify.stderr)}` };\n\n\t\tconst entryCommand = this._entryPath();\n\t\tif (!this._exists(entryCommand)) {\n\t\t\treturn { ok: false, error: `verify-fail: install reported success but ${entryCommand} was not found` };\n\t\t}\n\n\t\tthis._writeManifest({ commit: NEEDLE_PINNED_COMMIT, entryCommand });\n\t\tonProgress?.(\"needle installed.\");\n\t\treturn { ok: true };\n\t}\n\n\t/**\n\t * A plain `git clone --depth 1` only lands on {@link NEEDLE_PINNED_COMMIT} when it still happens\n\t * to be the remote's current default-branch tip. Fetching the exact SHA directly instead (verified\n\t * against the real repo) pins reliably even after upstream moves on: GitHub serves any reachable\n\t * commit for a public repo via `git fetch <sha>`, not just refs.\n\t */\n\tprivate async _cloneAtPinnedCommit(srcDir: string): Promise<{ ok: boolean; error?: string }> {\n\t\tconst init = await this._runCommand(\"git\", [\"init\", \"-q\", srcDir]);\n\t\tif (!init.ok) return { ok: false, error: `clone-fail: ${tailLines(init.error ?? init.stderr)}` };\n\t\tconst remote = await this._runCommand(\"git\", [\"-C\", srcDir, \"remote\", \"add\", \"origin\", NEEDLE_REPO_URL]);\n\t\tif (!remote.ok) return { ok: false, error: `clone-fail: ${tailLines(remote.error ?? remote.stderr)}` };\n\t\tconst fetched = await this._runCommand(\"git\", [\n\t\t\t\"-C\",\n\t\t\tsrcDir,\n\t\t\t\"fetch\",\n\t\t\t\"--depth\",\n\t\t\t\"1\",\n\t\t\t\"origin\",\n\t\t\tNEEDLE_PINNED_COMMIT,\n\t\t]);\n\t\tif (!fetched.ok) return { ok: false, error: `clone-fail: ${tailLines(fetched.error ?? fetched.stderr)}` };\n\t\tconst checkout = await this._runCommand(\"git\", [\"-C\", srcDir, \"checkout\", \"-q\", \"FETCH_HEAD\"]);\n\t\tif (!checkout.ok) return { ok: false, error: `clone-fail: ${tailLines(checkout.error ?? checkout.stderr)}` };\n\t\treturn { ok: true };\n\t}\n\n\t/**\n\t * Download the pretrained base weights (`needle.pkl`). `needle run` takes an explicit\n\t * `--checkpoint` and does NOT auto-download one (unlike `needle playground`/`finetune`) — see the\n\t * module docstring. Never called implicitly by installManaged/runFunctionCall; the caller decides\n\t * when to pull weights.\n\t *\n\t * `needle.pkl` is a pickle file — arbitrary code execution on load by construction (see the\n\t * module-level SECURITY note) — so every download is verified against the pinned sha256+size\n\t * ({@link NEEDLE_WEIGHTS_SHA256}/{@link NEEDLE_WEIGHTS_BYTES}, overridable only via the\n\t * `weightsIntegrity` test seam) computed in the same streaming pass that writes the file, with the\n\t * partial/mismatched file deleted on ANY failure — this never leaves an unverified or wrong pickle\n\t * sitting where {@link runFunctionCall} would load it.\n\t */\n\tasync downloadWeights(onProgress?: (status: string) => void): Promise<NeedleWeightsDownloadResult> {\n\t\tconst destPath = this.checkpointPath();\n\t\tconst url = `https://huggingface.co/${NEEDLE_HF_MODEL_REPO}/resolve/main/${NEEDLE_CHECKPOINT_FILENAME}`;\n\t\tmkdirSync(this.modelsDir(), { recursive: true });\n\n\t\tif (this._exists(destPath) && tryFileSizeBytes(destPath) === this._weightsIntegrity.bytes) {\n\t\t\tonProgress?.(\n\t\t\t\t`${NEEDLE_CHECKPOINT_FILENAME} already downloaded (${this._weightsIntegrity.bytes} bytes) — skipping.`,\n\t\t\t);\n\t\t\treturn { ok: true, path: destPath, skipped: true };\n\t\t}\n\n\t\tonProgress?.(`Downloading ${NEEDLE_CHECKPOINT_FILENAME} from ${NEEDLE_HF_MODEL_REPO}…`);\n\t\tconst download = await fetchRuntimeDownload(this._fetch, url);\n\t\tif (!download.ok) return download;\n\n\t\tconst hash = createHash(\"sha256\");\n\t\tconst written = await writeRuntimeDownload(\n\t\t\tdownload.body as unknown as Readable,\n\t\t\tdestPath,\n\t\t\thashingPassThrough(hash),\n\t\t);\n\t\tif (!written.ok) return written;\n\n\t\tconst actualBytes = tryFileSizeBytes(destPath);\n\t\tconst actualSha256 = hash.digest(\"hex\");\n\t\tif (actualBytes !== this._weightsIntegrity.bytes || actualSha256 !== this._weightsIntegrity.sha256) {\n\t\t\tremovePartialDownload(destPath);\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\terror: `integrity-fail: downloaded ${NEEDLE_CHECKPOINT_FILENAME} does not match the pinned checksum — expected sha256 ${this._weightsIntegrity.sha256} (${this._weightsIntegrity.bytes} bytes), got ${actualSha256} (${actualBytes ?? 0} bytes). Refusing to keep a pickle file that failed integrity verification.`,\n\t\t\t};\n\t\t}\n\n\t\tonProgress?.(`${NEEDLE_CHECKPOINT_FILENAME} downloaded and verified (sha256 ${actualSha256}).`);\n\t\treturn { ok: true, path: destPath };\n\t}\n\n\t/**\n\t * Run one single-shot inference through `needle run --checkpoint ... --query ... --tools ...`\n\t * inside the contained venv's installed console script. Argv is passed as an array to the\n\t * injected `runCommand` seam — never a shell string — so query/tools text containing quotes,\n\t * spaces, or other shell-hostile characters is passed through literally (verified against a real\n\t * invocation; see the module docstring). `tools` is serialized with `JSON.stringify` exactly once.\n\t */\n\tasync runFunctionCall(\n\t\trequest: NeedleFunctionCallRequest,\n\t\toptions?: { checkpointPath?: string },\n\t): Promise<NeedleFunctionCallResult> {\n\t\tconst entryCommand = this._entryPath();\n\t\tif (!this._exists(entryCommand)) {\n\t\t\treturn { ok: false, error: \"not-installed: run installManaged() first\", rawOutput: \"\" };\n\t\t}\n\t\tconst checkpointPath = options?.checkpointPath ?? this.checkpointPath();\n\t\tif (!this._exists(checkpointPath)) {\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\terror: `checkpoint-missing: no checkpoint at ${checkpointPath} — run downloadWeights() first`,\n\t\t\t\trawOutput: \"\",\n\t\t\t};\n\t\t}\n\n\t\tconst argv = [\n\t\t\t\"run\",\n\t\t\t\"--checkpoint\",\n\t\t\tcheckpointPath,\n\t\t\t\"--query\",\n\t\t\trequest.query,\n\t\t\t\"--tools\",\n\t\t\tJSON.stringify(request.tools),\n\t\t];\n\t\tconst result = await this._runCommand(entryCommand, argv);\n\t\tconst rawOutput = [result.stdout, result.stderr].filter(Boolean).join(\"\\n\");\n\t\tif (!result.ok) {\n\t\t\treturn { ok: false, error: `run-fail: ${tailLines(result.error ?? result.stderr)}`, rawOutput };\n\t\t}\n\t\treturn this._parseFunctionCall(result.stdout, rawOutput);\n\t}\n\n\t/**\n\t * Strictly parse a real `needle run` stdout capture:\n\t * ```\n\t * Loading checkpoint: <path>\n\t * Model parameters: <n>\n\t *\n\t * Query: <query>\n\t * Tools: <tools, truncated to 80 chars>...\n\t *\n\t * <tool_call>[{\"name\":\"...\",\"arguments\":{...}}]\n\t * ```\n\t * (diagnostic lines above the marker vary — e.g. a one-time \"Downloading pretrained tokenizer...\"\n\t * line on a cold cache — so parsing locates the `<tool_call>` marker rather than assuming a fixed\n\t * line count/position). Unparseable output is always an error carrying the raw text, never a\n\t * guessed result.\n\t */\n\tprivate _parseFunctionCall(stdout: string, rawOutput: string): NeedleFunctionCallResult {\n\t\tconst markerIndex = stdout.indexOf(NEEDLE_TOOL_CALL_MARKER);\n\t\tif (markerIndex < 0) {\n\t\t\treturn { ok: false, error: `unparseable-output: no ${NEEDLE_TOOL_CALL_MARKER} marker in stdout`, rawOutput };\n\t\t}\n\t\tconst jsonText = stdout.slice(markerIndex + NEEDLE_TOOL_CALL_MARKER.length).trim();\n\t\tlet parsed: unknown;\n\t\ttry {\n\t\t\tparsed = JSON.parse(jsonText);\n\t\t} catch (error) {\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\terror: `unparseable-output: ${error instanceof Error ? error.message : String(error)}`,\n\t\t\t\trawOutput,\n\t\t\t};\n\t\t}\n\t\tif (!Array.isArray(parsed) || parsed.length === 0) {\n\t\t\treturn { ok: false, error: \"unparseable-output: expected a non-empty tool-call array\", rawOutput };\n\t\t}\n\t\tconst first = parsed[0] as { name?: unknown; arguments?: unknown };\n\t\tif (\n\t\t\ttypeof first !== \"object\" ||\n\t\t\tfirst === null ||\n\t\t\ttypeof first.name !== \"string\" ||\n\t\t\ttypeof first.arguments !== \"object\" ||\n\t\t\tfirst.arguments === null\n\t\t) {\n\t\t\treturn { ok: false, error: \"unparseable-output: tool call missing name/arguments\", rawOutput };\n\t\t}\n\t\treturn { ok: true, call: { name: first.name, arguments: first.arguments as Record<string, unknown> } };\n\t}\n\n\t/** Canned get_weather query/tool through {@link runFunctionCall}; the wiring task uses this as the\n\t * post-install verification step. */\n\tasync smokeTest(onProgress?: (status: string) => void): Promise<NeedleSmokeTestResult> {\n\t\tonProgress?.(\"Running needle smoke test…\");\n\t\tconst startedAt = Date.now();\n\t\tconst result = await this.runFunctionCall({ query: NEEDLE_SMOKE_QUERY, tools: NEEDLE_SMOKE_TOOLS });\n\t\tconst latencyMs = Date.now() - startedAt;\n\t\tif (!result.ok) {\n\t\t\tonProgress?.(`Smoke test failed: ${result.error}`);\n\t\t\treturn { ok: false, latencyMs, error: result.error };\n\t\t}\n\t\tonProgress?.(`Smoke test ok (${latencyMs}ms): ${result.call.name}`);\n\t\treturn { ok: true, latencyMs, call: result.call };\n\t}\n\n\t/**\n\t * No-op: every needle invocation here is a single-shot `runCommand` call that spawns, waits for\n\t * exit, and returns — there is no persistent/detached child process this runtime owns between\n\t * calls for dispose() to track or kill (contrast OllamaRuntime/PrismLlamaCppRuntime's long-lived\n\t * `serve()` child).\n\t */\n\tdispose(): void {}\n}\n"]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { StreamFn, StreamIdleOptions } from "@caupulican/pi-agent-core";
|
|
2
|
-
import {
|
|
2
|
+
import type { Api, Context, Model } from "@caupulican/pi-ai/types";
|
|
3
3
|
export declare const DEFAULT_ADAPTIVE_STREAM_IDLE_CEILING_MS: number;
|
|
4
4
|
export interface ModelPerfProfile {
|
|
5
5
|
prefillTokensPerSecond?: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"perf-profile.d.ts","sourceRoot":"","sources":["../../../src/core/models/perf-profile.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC7E,OAAO,EACN,KAAK,GAAG,EAGR,KAAK,OAAO,EAEZ,KAAK,KAAK,EAEV,MAAM,mBAAmB,CAAC;AAM3B,eAAO,MAAM,uCAAuC,QAAiB,CAAC;AAEtE,MAAM,WAAW,gBAAgB;IAChC,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,eAAe;IAC/B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,EAAE,CAAC,EAAE,MAAM,CAAC;CACZ;AAED,MAAM,WAAW,uBAAuB;IACvC,IAAI,EAAE,iBAAiB,CAAC;IACxB,OAAO,CAAC,EAAE,gBAAgB,CAAC;IAC3B,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,8BAA8B;IAC9C,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,KAAK,MAAM,GAAG,SAAS,CAAC;IACpD,YAAY,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,eAAe,KAAK,IAAI,CAAC;IAClE,KAAK,CAAC,EAAE,MAAM,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,MAAM,CAAC;CACtB;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,gBAAgB,CAa5E;AAED,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAMzE;AAED,wBAAgB,sBAAsB,CACrC,OAAO,EAAE,gBAAgB,GAAG,SAAS,EACrC,MAAM,EAAE,eAAe,EACvB,EAAE,GAAE,MAA8C,GAChD,gBAAgB,GAAG,SAAS,CAyB9B;AAED,wBAAgB,gCAAgC,CAAC,KAAK,EAAE,uBAAuB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CA0B3G;AAED,wBAAgB,2BAA2B,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAQpE;AAED,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,8BAA8B,GAAG,QAAQ,CA4D3G","sourcesContent":["import type { StreamFn, StreamIdleOptions } from \"@caupulican/pi-agent-core\";\nimport {\n\ttype Api,\n\ttype AssistantMessage,\n\ttype AssistantMessageEvent,\n\ttype Context,\n\tcreateAssistantMessageEventStream,\n\ttype Model,\n\ttype ProviderResponse,\n} from \"@caupulican/pi-ai\";\n\nconst PERF_EWMA_ALPHA = 0.3;\nconst CHARS_PER_TOKEN_ESTIMATE = 4;\nconst DEFERRED_HEADERS_MAX_GAP_MS = 100;\nconst DEFERRED_HEADERS_MIN_REQUEST_MS = 1_000;\nexport const DEFAULT_ADAPTIVE_STREAM_IDLE_CEILING_MS = 30 * 60 * 1000;\n\nexport interface ModelPerfProfile {\n\tprefillTokensPerSecond?: number;\n\tdecodeTokensPerSecond?: number;\n\tloadMs?: number;\n\tsamples: number;\n\tupdatedAt: string;\n}\n\nexport interface ModelPerfSample {\n\tpromptTokens?: number;\n\tcompletionTokens?: number;\n\theadersToFirstTokenMs?: number;\n\trequestToFirstTokenMs?: number;\n\tfirstTokenToDoneMs?: number;\n\tloadMs?: number;\n\tat?: string;\n}\n\nexport interface AdaptiveStreamIdleInput {\n\tbase: StreamIdleOptions;\n\tprofile?: ModelPerfProfile;\n\tpromptTokens: number;\n\tceilingMs?: number;\n\tlocalClass?: boolean;\n}\n\nexport interface ModelPerfProfileStreamRecorder {\n\tmodelKey: (model: Model<Api>) => string | undefined;\n\trecordSample: (modelKey: string, sample: ModelPerfSample) => void;\n\tnowMs?: () => number;\n\tnowIso?: () => string;\n}\n\nexport function isModelPerfProfile(value: unknown): value is ModelPerfProfile {\n\tif (typeof value !== \"object\" || value === null || Array.isArray(value)) return false;\n\tconst record = value as Record<string, unknown>;\n\tconst samples = record.samples;\n\treturn (\n\t\t(record.prefillTokensPerSecond === undefined || isPositiveFiniteNumber(record.prefillTokensPerSecond)) &&\n\t\t(record.decodeTokensPerSecond === undefined || isPositiveFiniteNumber(record.decodeTokensPerSecond)) &&\n\t\t(record.loadMs === undefined || isPositiveFiniteNumber(record.loadMs)) &&\n\t\ttypeof samples === \"number\" &&\n\t\tNumber.isInteger(samples) &&\n\t\tsamples >= 0 &&\n\t\ttypeof record.updatedAt === \"string\"\n\t);\n}\n\nexport function hasUsableModelPerfSample(sample: ModelPerfSample): boolean {\n\treturn (\n\t\tprefillRateFromSample(sample) !== undefined ||\n\t\tdecodeRateFromSample(sample) !== undefined ||\n\t\tisPositiveFiniteNumber(sample.loadMs)\n\t);\n}\n\nexport function updateModelPerfProfile(\n\tcurrent: ModelPerfProfile | undefined,\n\tsample: ModelPerfSample,\n\tat: string = sample.at ?? new Date().toISOString(),\n): ModelPerfProfile | undefined {\n\tconst prefillRate = prefillRateFromSample(sample);\n\tconst decodeRate = decodeRateFromSample(sample);\n\tconst loadMs = isPositiveFiniteNumber(sample.loadMs) ? sample.loadMs : undefined;\n\tif (prefillRate === undefined && decodeRate === undefined && loadMs === undefined) return current;\n\n\tconst previousSamples = current?.samples ?? 0;\n\treturn {\n\t\t...(prefillRate !== undefined && {\n\t\t\tprefillTokensPerSecond: updateEwma(current?.prefillTokensPerSecond, prefillRate, previousSamples),\n\t\t}),\n\t\t...(prefillRate === undefined && current?.prefillTokensPerSecond !== undefined\n\t\t\t? { prefillTokensPerSecond: current.prefillTokensPerSecond }\n\t\t\t: {}),\n\t\t...(decodeRate !== undefined && {\n\t\t\tdecodeTokensPerSecond: updateEwma(current?.decodeTokensPerSecond, decodeRate, previousSamples),\n\t\t}),\n\t\t...(decodeRate === undefined && current?.decodeTokensPerSecond !== undefined\n\t\t\t? { decodeTokensPerSecond: current.decodeTokensPerSecond }\n\t\t\t: {}),\n\t\t...(loadMs !== undefined && { loadMs: updateEwma(current?.loadMs, loadMs, previousSamples) }),\n\t\t...(loadMs === undefined && current?.loadMs !== undefined ? { loadMs: current.loadMs } : {}),\n\t\tsamples: previousSamples + 1,\n\t\tupdatedAt: at,\n\t};\n}\n\nexport function resolveAdaptiveStreamIdleOptions(input: AdaptiveStreamIdleInput): Partial<StreamIdleOptions> {\n\tconst profile = input.profile;\n\tconst result: Partial<StreamIdleOptions> = {};\n\tconst localConnectDefaultMs = input.localClass\n\t\t? Math.max(input.base.connectMs, input.base.quietIdleMs)\n\t\t: input.base.connectMs;\n\tconst quietCeilingMs = Math.max(input.base.quietIdleMs, input.ceilingMs ?? DEFAULT_ADAPTIVE_STREAM_IDLE_CEILING_MS);\n\tconst connectCeilingMs = Math.max(localConnectDefaultMs, input.ceilingMs ?? DEFAULT_ADAPTIVE_STREAM_IDLE_CEILING_MS);\n\n\tconst expectedPrefillMs = expectedPrefillFromProfile(profile, input.promptTokens);\n\tif (expectedPrefillMs !== undefined) {\n\t\tconst quietIdleMs = adaptiveBound(input.base.quietIdleMs, quietCeilingMs, expectedPrefillMs);\n\t\tif (quietIdleMs > input.base.quietIdleMs) result.quietIdleMs = quietIdleMs;\n\t}\n\n\tif (input.localClass) {\n\t\tconst expectedConnectWorkMs =\n\t\t\texpectedPrefillMs !== undefined ? expectedPrefillMs + (profile?.loadMs ?? 0) : profile?.loadMs;\n\t\tconst connectMs =\n\t\t\texpectedConnectWorkMs !== undefined\n\t\t\t\t? adaptiveBound(localConnectDefaultMs, connectCeilingMs, expectedConnectWorkMs)\n\t\t\t\t: localConnectDefaultMs;\n\t\tif (connectMs > input.base.connectMs) result.connectMs = connectMs;\n\t}\n\n\treturn result;\n}\n\nexport function estimateContextPromptTokens(context: Context): number {\n\tconst serialized = JSON.stringify({\n\t\tsystemPrompt: context.systemPrompt,\n\t\tmessages: context.messages,\n\t\ttools: context.tools,\n\t});\n\tif (!serialized) return 0;\n\treturn Math.ceil(serialized.length / CHARS_PER_TOKEN_ESTIMATE);\n}\n\nexport function withModelPerfProfile(streamFn: StreamFn, recorder: ModelPerfProfileStreamRecorder): StreamFn {\n\treturn async (model, context, streamOptions) => {\n\t\tconst nowMs = recorder.nowMs ?? Date.now;\n\t\tconst nowIso = recorder.nowIso ?? (() => new Date().toISOString());\n\t\tconst requestStartedAtMs = nowMs();\n\t\tlet responseHeadersAtMs: number | undefined;\n\t\tlet firstTokenAtMs: number | undefined;\n\t\tconst originalOnResponse = streamOptions?.onResponse;\n\t\tconst outer = createAssistantMessageEventStream();\n\t\tlet latest = emptyAssistantMessage(model);\n\t\tlet inner: Awaited<ReturnType<StreamFn>>;\n\t\ttry {\n\t\t\tinner = await streamFn(model, context, {\n\t\t\t\t...streamOptions,\n\t\t\t\tonResponse: async (response: ProviderResponse, responseModel: Model<Api>) => {\n\t\t\t\t\tresponseHeadersAtMs ??= nowMs();\n\t\t\t\t\tawait originalOnResponse?.(response, responseModel);\n\t\t\t\t},\n\t\t\t});\n\t\t} catch (error) {\n\t\t\touter.push(perfStreamFailure(latest, streamOptions?.signal?.aborted === true, error));\n\t\t\treturn outer;\n\t\t}\n\n\t\tvoid (async () => {\n\t\t\tlet terminalPushed = false;\n\t\t\ttry {\n\t\t\t\tfor await (const event of inner) {\n\t\t\t\t\tlatest = assistantMessageFromEvent(event);\n\t\t\t\t\tif (firstTokenAtMs === undefined && isFirstTokenEvent(event)) {\n\t\t\t\t\t\tfirstTokenAtMs = nowMs();\n\t\t\t\t\t}\n\t\t\t\t\tif (event.type === \"done\") {\n\t\t\t\t\t\tterminalPushed = true;\n\t\t\t\t\t\trecordSuccessfulStreamSample({\n\t\t\t\t\t\t\tcompletionTokens: event.message.usage.output,\n\t\t\t\t\t\t\tdoneAtMs: nowMs(),\n\t\t\t\t\t\t\tfirstTokenAtMs,\n\t\t\t\t\t\t\tmodel,\n\t\t\t\t\t\t\tnowIso,\n\t\t\t\t\t\t\tpromptTokens:\n\t\t\t\t\t\t\t\tevent.message.usage.input + event.message.usage.cacheRead + event.message.usage.cacheWrite,\n\t\t\t\t\t\t\trecorder,\n\t\t\t\t\t\t\trequestStartedAtMs,\n\t\t\t\t\t\t\tresponseHeadersAtMs,\n\t\t\t\t\t\t});\n\t\t\t\t\t} else if (event.type === \"error\") {\n\t\t\t\t\t\tterminalPushed = true;\n\t\t\t\t\t}\n\t\t\t\t\touter.push(event);\n\t\t\t\t\tif (terminalPushed) return;\n\t\t\t\t}\n\t\t\t\touter.push(perfStreamFailure(latest, streamOptions?.signal?.aborted === true));\n\t\t\t} catch (error) {\n\t\t\t\touter.push(perfStreamFailure(latest, streamOptions?.signal?.aborted === true, error));\n\t\t\t}\n\t\t})();\n\n\t\treturn outer;\n\t};\n}\n\nfunction assistantMessageFromEvent(event: AssistantMessageEvent): AssistantMessage {\n\tif (event.type === \"done\") return event.message;\n\tif (event.type === \"error\") return event.error;\n\treturn event.partial;\n}\n\nfunction emptyAssistantMessage(model: Model<Api>): AssistantMessage {\n\treturn {\n\t\trole: \"assistant\",\n\t\tcontent: [],\n\t\tapi: model.api,\n\t\tprovider: model.provider,\n\t\tmodel: model.id,\n\t\tusage: {\n\t\t\tinput: 0,\n\t\t\toutput: 0,\n\t\t\tcacheRead: 0,\n\t\t\tcacheWrite: 0,\n\t\t\ttotalTokens: 0,\n\t\t\tcost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },\n\t\t},\n\t\tstopReason: \"stop\",\n\t\ttimestamp: Date.now(),\n\t};\n}\n\nfunction perfStreamFailure(latest: AssistantMessage, aborted: boolean, error?: unknown): AssistantMessageEvent {\n\tconst stopReason = aborted ? \"aborted\" : \"error\";\n\tconst detail = error instanceof Error ? `: ${error.message}` : error === undefined ? \"\" : `: ${String(error)}`;\n\treturn {\n\t\ttype: \"error\",\n\t\treason: stopReason,\n\t\terror: {\n\t\t\t...latest,\n\t\t\tstopReason,\n\t\t\terrorMessage: aborted\n\t\t\t\t? `stream aborted before terminal event${detail}`\n\t\t\t\t: `stream ended without terminal event${detail}`,\n\t\t},\n\t};\n}\n\nfunction recordSuccessfulStreamSample(input: {\n\tmodel: Model<Api>;\n\trecorder: ModelPerfProfileStreamRecorder;\n\trequestStartedAtMs: number;\n\tresponseHeadersAtMs: number | undefined;\n\tfirstTokenAtMs: number | undefined;\n\tdoneAtMs: number;\n\tpromptTokens: number;\n\tcompletionTokens: number;\n\tnowIso: () => string;\n}): void {\n\tif (input.firstTokenAtMs === undefined) return;\n\tconst modelKey = input.recorder.modelKey(input.model);\n\tif (!modelKey) return;\n\tconst requestToFirstTokenMs = input.firstTokenAtMs - input.requestStartedAtMs;\n\tconst sample: ModelPerfSample = {\n\t\tpromptTokens: input.promptTokens,\n\t\tcompletionTokens: input.completionTokens,\n\t\trequestToFirstTokenMs,\n\t\tfirstTokenToDoneMs: input.doneAtMs - input.firstTokenAtMs,\n\t\tat: input.nowIso(),\n\t};\n\tif (input.responseHeadersAtMs !== undefined) {\n\t\tconst headersToFirstTokenMs = input.firstTokenAtMs - input.responseHeadersAtMs;\n\t\tconst headersWereEffectivelyDeferred =\n\t\t\trequestToFirstTokenMs >= DEFERRED_HEADERS_MIN_REQUEST_MS &&\n\t\t\theadersToFirstTokenMs <= DEFERRED_HEADERS_MAX_GAP_MS;\n\t\tif (!headersWereEffectivelyDeferred) sample.headersToFirstTokenMs = headersToFirstTokenMs;\n\t}\n\tif (!hasUsableModelPerfSample(sample)) return;\n\ttry {\n\t\tinput.recorder.recordSample(modelKey, sample);\n\t} catch {\n\t\t// Perf profiling must never fail the user turn.\n\t}\n}\n\nfunction isFirstTokenEvent(event: AssistantMessageEvent): boolean {\n\treturn (\n\t\t(event.type === \"text_delta\" || event.type === \"thinking_delta\" || event.type === \"toolcall_delta\") &&\n\t\tevent.delta.length > 0\n\t);\n}\n\nfunction expectedPrefillFromProfile(profile: ModelPerfProfile | undefined, promptTokens: number): number | undefined {\n\tconst prefillRate = profile?.prefillTokensPerSecond;\n\tif (!profile || profile.samples < 1 || !prefillRate || promptTokens <= 0) return undefined;\n\tconst expectedPrefillMs = (promptTokens / prefillRate) * 1000;\n\treturn Number.isFinite(expectedPrefillMs) && expectedPrefillMs > 0 ? expectedPrefillMs : undefined;\n}\n\nfunction adaptiveBound(defaultMs: number, ceilingMs: number, expectedMs: number): number {\n\treturn Math.min(Math.ceil(Math.max(defaultMs, expectedMs * 3)), ceilingMs);\n}\n\nfunction prefillRateFromSample(sample: ModelPerfSample): number | undefined {\n\tconst durationMs = isPositiveFiniteNumber(sample.headersToFirstTokenMs)\n\t\t? sample.headersToFirstTokenMs\n\t\t: sample.requestToFirstTokenMs;\n\treturn tokensPerSecond(sample.promptTokens, durationMs);\n}\n\nfunction decodeRateFromSample(sample: ModelPerfSample): number | undefined {\n\treturn tokensPerSecond(sample.completionTokens, sample.firstTokenToDoneMs);\n}\n\nfunction tokensPerSecond(tokens: number | undefined, durationMs: number | undefined): number | undefined {\n\tif (!isPositiveFiniteNumber(tokens) || !isPositiveFiniteNumber(durationMs)) return undefined;\n\treturn tokens / (durationMs / 1000);\n}\n\nfunction updateEwma(previous: number | undefined, next: number, previousSamples: number): number {\n\tif (previous === undefined || previousSamples === 0) return next;\n\treturn previous * (1 - PERF_EWMA_ALPHA) + next * PERF_EWMA_ALPHA;\n}\n\nfunction isPositiveFiniteNumber(value: unknown): value is number {\n\treturn typeof value === \"number\" && Number.isFinite(value) && value > 0;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"perf-profile.d.ts","sourceRoot":"","sources":["../../../src/core/models/perf-profile.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAE7E,OAAO,KAAK,EACX,GAAG,EAGH,OAAO,EACP,KAAK,EAEL,MAAM,yBAAyB,CAAC;AAQjC,eAAO,MAAM,uCAAuC,QAAiB,CAAC;AAEtE,MAAM,WAAW,gBAAgB;IAChC,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,eAAe;IAC/B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,EAAE,CAAC,EAAE,MAAM,CAAC;CACZ;AAED,MAAM,WAAW,uBAAuB;IACvC,IAAI,EAAE,iBAAiB,CAAC;IACxB,OAAO,CAAC,EAAE,gBAAgB,CAAC;IAC3B,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,8BAA8B;IAC9C,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,KAAK,MAAM,GAAG,SAAS,CAAC;IACpD,YAAY,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,eAAe,KAAK,IAAI,CAAC;IAClE,KAAK,CAAC,EAAE,MAAM,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,MAAM,CAAC;CACtB;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,gBAAgB,CAa5E;AAED,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAMzE;AAED,wBAAgB,sBAAsB,CACrC,OAAO,EAAE,gBAAgB,GAAG,SAAS,EACrC,MAAM,EAAE,eAAe,EACvB,EAAE,GAAE,MAA8C,GAChD,gBAAgB,GAAG,SAAS,CAyB9B;AAED,wBAAgB,gCAAgC,CAAC,KAAK,EAAE,uBAAuB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CA0B3G;AAED,wBAAgB,2BAA2B,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAOpE;AAED,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,8BAA8B,GAAG,QAAQ,CA4D3G"}
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import { createAssistantMessageEventStream
|
|
1
|
+
import { createAssistantMessageEventStream } from "@caupulican/pi-ai/event-stream";
|
|
2
|
+
import { createEmptyUsage } from "@caupulican/pi-ai/usage";
|
|
3
|
+
import { measureJsonLength } from "../util/json-size.js";
|
|
2
4
|
const PERF_EWMA_ALPHA = 0.3;
|
|
3
5
|
const CHARS_PER_TOKEN_ESTIMATE = 4;
|
|
4
6
|
const DEFERRED_HEADERS_MAX_GAP_MS = 100;
|
|
@@ -73,14 +75,12 @@ export function resolveAdaptiveStreamIdleOptions(input) {
|
|
|
73
75
|
return result;
|
|
74
76
|
}
|
|
75
77
|
export function estimateContextPromptTokens(context) {
|
|
76
|
-
const
|
|
78
|
+
const serializedLength = measureJsonLength({
|
|
77
79
|
systemPrompt: context.systemPrompt,
|
|
78
80
|
messages: context.messages,
|
|
79
81
|
tools: context.tools,
|
|
80
82
|
});
|
|
81
|
-
|
|
82
|
-
return 0;
|
|
83
|
-
return Math.ceil(serialized.length / CHARS_PER_TOKEN_ESTIMATE);
|
|
83
|
+
return serializedLength === undefined ? 0 : Math.ceil(serializedLength / CHARS_PER_TOKEN_ESTIMATE);
|
|
84
84
|
}
|
|
85
85
|
export function withModelPerfProfile(streamFn, recorder) {
|
|
86
86
|
return async (model, context, streamOptions) => {
|
|
@@ -158,14 +158,7 @@ function emptyAssistantMessage(model) {
|
|
|
158
158
|
api: model.api,
|
|
159
159
|
provider: model.provider,
|
|
160
160
|
model: model.id,
|
|
161
|
-
usage:
|
|
162
|
-
input: 0,
|
|
163
|
-
output: 0,
|
|
164
|
-
cacheRead: 0,
|
|
165
|
-
cacheWrite: 0,
|
|
166
|
-
totalTokens: 0,
|
|
167
|
-
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },
|
|
168
|
-
},
|
|
161
|
+
usage: createEmptyUsage(),
|
|
169
162
|
stopReason: "stop",
|
|
170
163
|
timestamp: Date.now(),
|
|
171
164
|
};
|