@kruntime/komputer 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +368 -0
- package/dist/agent/approvals.d.ts +28 -0
- package/dist/agent/approvals.js +109 -0
- package/dist/agent/approvals.js.map +1 -0
- package/dist/agent/messages.d.ts +67 -0
- package/dist/agent/messages.js +213 -0
- package/dist/agent/messages.js.map +1 -0
- package/dist/agent/recovery.d.ts +13 -0
- package/dist/agent/recovery.js +112 -0
- package/dist/agent/recovery.js.map +1 -0
- package/dist/agent/session-utils.d.ts +17 -0
- package/dist/agent/session-utils.js +77 -0
- package/dist/agent/session-utils.js.map +1 -0
- package/dist/agent-session.d.ts +303 -0
- package/dist/agent-session.js +3031 -0
- package/dist/agent-session.js.map +1 -0
- package/dist/authority.d.ts +34 -0
- package/dist/authority.js +105 -0
- package/dist/authority.js.map +1 -0
- package/dist/content.d.ts +17 -0
- package/dist/content.js +69 -0
- package/dist/content.js.map +1 -0
- package/dist/cron.d.ts +20 -0
- package/dist/cron.js +25 -0
- package/dist/cron.js.map +1 -0
- package/dist/drive.d.ts +198 -0
- package/dist/drive.js +656 -0
- package/dist/drive.js.map +1 -0
- package/dist/events.d.ts +20 -0
- package/dist/events.js +149 -0
- package/dist/events.js.map +1 -0
- package/dist/fs-mode.d.ts +9 -0
- package/dist/fs-mode.js +98 -0
- package/dist/fs-mode.js.map +1 -0
- package/dist/index.d.ts +26 -0
- package/dist/index.js +15 -0
- package/dist/index.js.map +1 -0
- package/dist/komputer.d.ts +123 -0
- package/dist/komputer.js +733 -0
- package/dist/komputer.js.map +1 -0
- package/dist/kstate.d.ts +107 -0
- package/dist/kstate.js +529 -0
- package/dist/kstate.js.map +1 -0
- package/dist/model.d.ts +81 -0
- package/dist/model.js +824 -0
- package/dist/model.js.map +1 -0
- package/dist/node.d.ts +2 -0
- package/dist/node.js +3 -0
- package/dist/node.js.map +1 -0
- package/dist/path.d.ts +4 -0
- package/dist/path.js +38 -0
- package/dist/path.js.map +1 -0
- package/dist/pool.d.ts +56 -0
- package/dist/pool.js +172 -0
- package/dist/pool.js.map +1 -0
- package/dist/receipts.d.ts +44 -0
- package/dist/receipts.js +35 -0
- package/dist/receipts.js.map +1 -0
- package/dist/remote-node.d.ts +2 -0
- package/dist/remote-node.js +122 -0
- package/dist/remote-node.js.map +1 -0
- package/dist/remote.d.ts +84 -0
- package/dist/remote.js +11 -0
- package/dist/remote.js.map +1 -0
- package/dist/sandbox.d.ts +4 -0
- package/dist/sandbox.js +70 -0
- package/dist/sandbox.js.map +1 -0
- package/dist/shell/builtins/catalog.d.ts +6 -0
- package/dist/shell/builtins/catalog.js +12 -0
- package/dist/shell/builtins/catalog.js.map +1 -0
- package/dist/shell/builtins/commands/filesystem/basename.d.ts +2 -0
- package/dist/shell/builtins/commands/filesystem/basename.js +23 -0
- package/dist/shell/builtins/commands/filesystem/basename.js.map +1 -0
- package/dist/shell/builtins/commands/filesystem/cat.d.ts +2 -0
- package/dist/shell/builtins/commands/filesystem/cat.js +85 -0
- package/dist/shell/builtins/commands/filesystem/cat.js.map +1 -0
- package/dist/shell/builtins/commands/filesystem/cd.d.ts +2 -0
- package/dist/shell/builtins/commands/filesystem/cd.js +14 -0
- package/dist/shell/builtins/commands/filesystem/cd.js.map +1 -0
- package/dist/shell/builtins/commands/filesystem/chmod.d.ts +2 -0
- package/dist/shell/builtins/commands/filesystem/chmod.js +46 -0
- package/dist/shell/builtins/commands/filesystem/chmod.js.map +1 -0
- package/dist/shell/builtins/commands/filesystem/copy-directory.d.ts +4 -0
- package/dist/shell/builtins/commands/filesystem/copy-directory.js +48 -0
- package/dist/shell/builtins/commands/filesystem/copy-directory.js.map +1 -0
- package/dist/shell/builtins/commands/filesystem/cp.d.ts +2 -0
- package/dist/shell/builtins/commands/filesystem/cp.js +92 -0
- package/dist/shell/builtins/commands/filesystem/cp.js.map +1 -0
- package/dist/shell/builtins/commands/filesystem/dirname.d.ts +2 -0
- package/dist/shell/builtins/commands/filesystem/dirname.js +23 -0
- package/dist/shell/builtins/commands/filesystem/dirname.js.map +1 -0
- package/dist/shell/builtins/commands/filesystem/du.d.ts +2 -0
- package/dist/shell/builtins/commands/filesystem/du.js +93 -0
- package/dist/shell/builtins/commands/filesystem/du.js.map +1 -0
- package/dist/shell/builtins/commands/filesystem/find.d.ts +2 -0
- package/dist/shell/builtins/commands/filesystem/find.js +111 -0
- package/dist/shell/builtins/commands/filesystem/find.js.map +1 -0
- package/dist/shell/builtins/commands/filesystem/install.d.ts +2 -0
- package/dist/shell/builtins/commands/filesystem/install.js +89 -0
- package/dist/shell/builtins/commands/filesystem/install.js.map +1 -0
- package/dist/shell/builtins/commands/filesystem/ln.d.ts +2 -0
- package/dist/shell/builtins/commands/filesystem/ln.js +57 -0
- package/dist/shell/builtins/commands/filesystem/ln.js.map +1 -0
- package/dist/shell/builtins/commands/filesystem/ls.d.ts +2 -0
- package/dist/shell/builtins/commands/filesystem/ls.js +153 -0
- package/dist/shell/builtins/commands/filesystem/ls.js.map +1 -0
- package/dist/shell/builtins/commands/filesystem/mkdir.d.ts +2 -0
- package/dist/shell/builtins/commands/filesystem/mkdir.js +41 -0
- package/dist/shell/builtins/commands/filesystem/mkdir.js.map +1 -0
- package/dist/shell/builtins/commands/filesystem/mktemp.d.ts +2 -0
- package/dist/shell/builtins/commands/filesystem/mktemp.js +94 -0
- package/dist/shell/builtins/commands/filesystem/mktemp.js.map +1 -0
- package/dist/shell/builtins/commands/filesystem/mv.d.ts +2 -0
- package/dist/shell/builtins/commands/filesystem/mv.js +41 -0
- package/dist/shell/builtins/commands/filesystem/mv.js.map +1 -0
- package/dist/shell/builtins/commands/filesystem/pwd.d.ts +2 -0
- package/dist/shell/builtins/commands/filesystem/pwd.js +2 -0
- package/dist/shell/builtins/commands/filesystem/pwd.js.map +1 -0
- package/dist/shell/builtins/commands/filesystem/realpath.d.ts +3 -0
- package/dist/shell/builtins/commands/filesystem/realpath.js +61 -0
- package/dist/shell/builtins/commands/filesystem/realpath.js.map +1 -0
- package/dist/shell/builtins/commands/filesystem/rm.d.ts +2 -0
- package/dist/shell/builtins/commands/filesystem/rm.js +38 -0
- package/dist/shell/builtins/commands/filesystem/rm.js.map +1 -0
- package/dist/shell/builtins/commands/filesystem/stat.d.ts +2 -0
- package/dist/shell/builtins/commands/filesystem/stat.js +141 -0
- package/dist/shell/builtins/commands/filesystem/stat.js.map +1 -0
- package/dist/shell/builtins/commands/filesystem/touch.d.ts +2 -0
- package/dist/shell/builtins/commands/filesystem/touch.js +143 -0
- package/dist/shell/builtins/commands/filesystem/touch.js.map +1 -0
- package/dist/shell/builtins/commands/filesystem.d.ts +2 -0
- package/dist/shell/builtins/commands/filesystem.js +44 -0
- package/dist/shell/builtins/commands/filesystem.js.map +1 -0
- package/dist/shell/builtins/commands/network/curl.d.ts +2 -0
- package/dist/shell/builtins/commands/network/curl.js +25 -0
- package/dist/shell/builtins/commands/network/curl.js.map +1 -0
- package/dist/shell/builtins/commands/network/http.d.ts +27 -0
- package/dist/shell/builtins/commands/network/http.js +226 -0
- package/dist/shell/builtins/commands/network/http.js.map +1 -0
- package/dist/shell/builtins/commands/network/wget.d.ts +2 -0
- package/dist/shell/builtins/commands/network/wget.js +32 -0
- package/dist/shell/builtins/commands/network/wget.js.map +1 -0
- package/dist/shell/builtins/commands/network.d.ts +2 -0
- package/dist/shell/builtins/commands/network.js +9 -0
- package/dist/shell/builtins/commands/network.js.map +1 -0
- package/dist/shell/builtins/commands/process/bg.d.ts +2 -0
- package/dist/shell/builtins/commands/process/bg.js +10 -0
- package/dist/shell/builtins/commands/process/bg.js.map +1 -0
- package/dist/shell/builtins/commands/process/fg.d.ts +2 -0
- package/dist/shell/builtins/commands/process/fg.js +14 -0
- package/dist/shell/builtins/commands/process/fg.js.map +1 -0
- package/dist/shell/builtins/commands/process/jobs.d.ts +2 -0
- package/dist/shell/builtins/commands/process/jobs.js +8 -0
- package/dist/shell/builtins/commands/process/jobs.js.map +1 -0
- package/dist/shell/builtins/commands/process/jobspec.d.ts +4 -0
- package/dist/shell/builtins/commands/process/jobspec.js +20 -0
- package/dist/shell/builtins/commands/process/jobspec.js.map +1 -0
- package/dist/shell/builtins/commands/process/kill.d.ts +2 -0
- package/dist/shell/builtins/commands/process/kill.js +35 -0
- package/dist/shell/builtins/commands/process/kill.js.map +1 -0
- package/dist/shell/builtins/commands/process/ps.d.ts +2 -0
- package/dist/shell/builtins/commands/process/ps.js +6 -0
- package/dist/shell/builtins/commands/process/ps.js.map +1 -0
- package/dist/shell/builtins/commands/process/sleep.d.ts +2 -0
- package/dist/shell/builtins/commands/process/sleep.js +6 -0
- package/dist/shell/builtins/commands/process/sleep.js.map +1 -0
- package/dist/shell/builtins/commands/process/wait.d.ts +2 -0
- package/dist/shell/builtins/commands/process/wait.js +21 -0
- package/dist/shell/builtins/commands/process/wait.js.map +1 -0
- package/dist/shell/builtins/commands/process.d.ts +2 -0
- package/dist/shell/builtins/commands/process.js +19 -0
- package/dist/shell/builtins/commands/process.js.map +1 -0
- package/dist/shell/builtins/commands/system/command.d.ts +2 -0
- package/dist/shell/builtins/commands/system/command.js +42 -0
- package/dist/shell/builtins/commands/system/command.js.map +1 -0
- package/dist/shell/builtins/commands/system/date.d.ts +2 -0
- package/dist/shell/builtins/commands/system/date.js +121 -0
- package/dist/shell/builtins/commands/system/date.js.map +1 -0
- package/dist/shell/builtins/commands/system/env.d.ts +2 -0
- package/dist/shell/builtins/commands/system/env.js +84 -0
- package/dist/shell/builtins/commands/system/env.js.map +1 -0
- package/dist/shell/builtins/commands/system/export.d.ts +2 -0
- package/dist/shell/builtins/commands/system/export.js +18 -0
- package/dist/shell/builtins/commands/system/export.js.map +1 -0
- package/dist/shell/builtins/commands/system/false.d.ts +2 -0
- package/dist/shell/builtins/commands/system/false.js +4 -0
- package/dist/shell/builtins/commands/system/false.js.map +1 -0
- package/dist/shell/builtins/commands/system/help.d.ts +2 -0
- package/dist/shell/builtins/commands/system/help.js +38 -0
- package/dist/shell/builtins/commands/system/help.js.map +1 -0
- package/dist/shell/builtins/commands/system/hostname.d.ts +2 -0
- package/dist/shell/builtins/commands/system/hostname.js +6 -0
- package/dist/shell/builtins/commands/system/hostname.js.map +1 -0
- package/dist/shell/builtins/commands/system/id.d.ts +2 -0
- package/dist/shell/builtins/commands/system/id.js +55 -0
- package/dist/shell/builtins/commands/system/id.js.map +1 -0
- package/dist/shell/builtins/commands/system/printenv.d.ts +2 -0
- package/dist/shell/builtins/commands/system/printenv.js +22 -0
- package/dist/shell/builtins/commands/system/printenv.js.map +1 -0
- package/dist/shell/builtins/commands/system/read.d.ts +2 -0
- package/dist/shell/builtins/commands/system/read.js +75 -0
- package/dist/shell/builtins/commands/system/read.js.map +1 -0
- package/dist/shell/builtins/commands/system/resolve-command.d.ts +3 -0
- package/dist/shell/builtins/commands/system/resolve-command.js +34 -0
- package/dist/shell/builtins/commands/system/resolve-command.js.map +1 -0
- package/dist/shell/builtins/commands/system/set.d.ts +2 -0
- package/dist/shell/builtins/commands/system/set.js +49 -0
- package/dist/shell/builtins/commands/system/set.js.map +1 -0
- package/dist/shell/builtins/commands/system/sh.d.ts +2 -0
- package/dist/shell/builtins/commands/system/sh.js +55 -0
- package/dist/shell/builtins/commands/system/sh.js.map +1 -0
- package/dist/shell/builtins/commands/system/source.d.ts +2 -0
- package/dist/shell/builtins/commands/system/source.js +42 -0
- package/dist/shell/builtins/commands/system/source.js.map +1 -0
- package/dist/shell/builtins/commands/system/test-expression.d.ts +2 -0
- package/dist/shell/builtins/commands/system/test-expression.js +93 -0
- package/dist/shell/builtins/commands/system/test-expression.js.map +1 -0
- package/dist/shell/builtins/commands/system/test.d.ts +4 -0
- package/dist/shell/builtins/commands/system/test.js +19 -0
- package/dist/shell/builtins/commands/system/test.js.map +1 -0
- package/dist/shell/builtins/commands/system/true.d.ts +2 -0
- package/dist/shell/builtins/commands/system/true.js +2 -0
- package/dist/shell/builtins/commands/system/true.js.map +1 -0
- package/dist/shell/builtins/commands/system/type.d.ts +2 -0
- package/dist/shell/builtins/commands/system/type.js +77 -0
- package/dist/shell/builtins/commands/system/type.js.map +1 -0
- package/dist/shell/builtins/commands/system/uname.d.ts +2 -0
- package/dist/shell/builtins/commands/system/uname.js +39 -0
- package/dist/shell/builtins/commands/system/uname.js.map +1 -0
- package/dist/shell/builtins/commands/system/unset.d.ts +2 -0
- package/dist/shell/builtins/commands/system/unset.js +9 -0
- package/dist/shell/builtins/commands/system/unset.js.map +1 -0
- package/dist/shell/builtins/commands/system/which.d.ts +2 -0
- package/dist/shell/builtins/commands/system/which.js +38 -0
- package/dist/shell/builtins/commands/system/which.js.map +1 -0
- package/dist/shell/builtins/commands/system/whoami.d.ts +2 -0
- package/dist/shell/builtins/commands/system/whoami.js +6 -0
- package/dist/shell/builtins/commands/system/whoami.js.map +1 -0
- package/dist/shell/builtins/commands/system.d.ts +2 -0
- package/dist/shell/builtins/commands/system.js +49 -0
- package/dist/shell/builtins/commands/system.js.map +1 -0
- package/dist/shell/builtins/commands/text/awk.d.ts +2 -0
- package/dist/shell/builtins/commands/text/awk.js +8 -0
- package/dist/shell/builtins/commands/text/awk.js.map +1 -0
- package/dist/shell/builtins/commands/text/base64.d.ts +2 -0
- package/dist/shell/builtins/commands/text/base64.js +69 -0
- package/dist/shell/builtins/commands/text/base64.js.map +1 -0
- package/dist/shell/builtins/commands/text/cut.d.ts +2 -0
- package/dist/shell/builtins/commands/text/cut.js +35 -0
- package/dist/shell/builtins/commands/text/cut.js.map +1 -0
- package/dist/shell/builtins/commands/text/diff.d.ts +2 -0
- package/dist/shell/builtins/commands/text/diff.js +83 -0
- package/dist/shell/builtins/commands/text/diff.js.map +1 -0
- package/dist/shell/builtins/commands/text/echo.d.ts +2 -0
- package/dist/shell/builtins/commands/text/echo.js +6 -0
- package/dist/shell/builtins/commands/text/echo.js.map +1 -0
- package/dist/shell/builtins/commands/text/grep.d.ts +2 -0
- package/dist/shell/builtins/commands/text/grep.js +123 -0
- package/dist/shell/builtins/commands/text/grep.js.map +1 -0
- package/dist/shell/builtins/commands/text/head.d.ts +2 -0
- package/dist/shell/builtins/commands/text/head.js +8 -0
- package/dist/shell/builtins/commands/text/head.js.map +1 -0
- package/dist/shell/builtins/commands/text/jq.d.ts +2 -0
- package/dist/shell/builtins/commands/text/jq.js +239 -0
- package/dist/shell/builtins/commands/text/jq.js.map +1 -0
- package/dist/shell/builtins/commands/text/printf.d.ts +2 -0
- package/dist/shell/builtins/commands/text/printf.js +3 -0
- package/dist/shell/builtins/commands/text/printf.js.map +1 -0
- package/dist/shell/builtins/commands/text/sed.d.ts +2 -0
- package/dist/shell/builtins/commands/text/sed.js +21 -0
- package/dist/shell/builtins/commands/text/sed.js.map +1 -0
- package/dist/shell/builtins/commands/text/sha256sum.d.ts +2 -0
- package/dist/shell/builtins/commands/text/sha256sum.js +63 -0
- package/dist/shell/builtins/commands/text/sha256sum.js.map +1 -0
- package/dist/shell/builtins/commands/text/sort.d.ts +2 -0
- package/dist/shell/builtins/commands/text/sort.js +134 -0
- package/dist/shell/builtins/commands/text/sort.js.map +1 -0
- package/dist/shell/builtins/commands/text/tail.d.ts +2 -0
- package/dist/shell/builtins/commands/text/tail.js +10 -0
- package/dist/shell/builtins/commands/text/tail.js.map +1 -0
- package/dist/shell/builtins/commands/text/tee.d.ts +2 -0
- package/dist/shell/builtins/commands/text/tee.js +29 -0
- package/dist/shell/builtins/commands/text/tee.js.map +1 -0
- package/dist/shell/builtins/commands/text/tr.d.ts +2 -0
- package/dist/shell/builtins/commands/text/tr.js +3 -0
- package/dist/shell/builtins/commands/text/tr.js.map +1 -0
- package/dist/shell/builtins/commands/text/uniq.d.ts +2 -0
- package/dist/shell/builtins/commands/text/uniq.js +8 -0
- package/dist/shell/builtins/commands/text/uniq.js.map +1 -0
- package/dist/shell/builtins/commands/text/wc.d.ts +2 -0
- package/dist/shell/builtins/commands/text/wc.js +30 -0
- package/dist/shell/builtins/commands/text/wc.js.map +1 -0
- package/dist/shell/builtins/commands/text/xargs.d.ts +2 -0
- package/dist/shell/builtins/commands/text/xargs.js +138 -0
- package/dist/shell/builtins/commands/text/xargs.js.map +1 -0
- package/dist/shell/builtins/commands/text.d.ts +2 -0
- package/dist/shell/builtins/commands/text.js +41 -0
- package/dist/shell/builtins/commands/text.js.map +1 -0
- package/dist/shell/builtins/help-text.d.ts +69 -0
- package/dist/shell/builtins/help-text.js +381 -0
- package/dist/shell/builtins/help-text.js.map +1 -0
- package/dist/shell/builtins/path.d.ts +28 -0
- package/dist/shell/builtins/path.js +184 -0
- package/dist/shell/builtins/path.js.map +1 -0
- package/dist/shell/builtins/registry.d.ts +3 -0
- package/dist/shell/builtins/registry.js +75 -0
- package/dist/shell/builtins/registry.js.map +1 -0
- package/dist/shell/builtins/run.d.ts +4 -0
- package/dist/shell/builtins/run.js +29 -0
- package/dist/shell/builtins/run.js.map +1 -0
- package/dist/shell/builtins/runtime.d.ts +83 -0
- package/dist/shell/builtins/runtime.js +46 -0
- package/dist/shell/builtins/runtime.js.map +1 -0
- package/dist/shell/builtins/text.d.ts +90 -0
- package/dist/shell/builtins/text.js +970 -0
- package/dist/shell/builtins/text.js.map +1 -0
- package/dist/shell/control.d.ts +31 -0
- package/dist/shell/control.js +232 -0
- package/dist/shell/control.js.map +1 -0
- package/dist/shell/expansion.d.ts +30 -0
- package/dist/shell/expansion.js +514 -0
- package/dist/shell/expansion.js.map +1 -0
- package/dist/shell/functions.d.ts +10 -0
- package/dist/shell/functions.js +108 -0
- package/dist/shell/functions.js.map +1 -0
- package/dist/shell/runtime.d.ts +44 -0
- package/dist/shell/runtime.js +276 -0
- package/dist/shell/runtime.js.map +1 -0
- package/dist/shell/time.d.ts +1 -0
- package/dist/shell/time.js +68 -0
- package/dist/shell/time.js.map +1 -0
- package/dist/state-backend.d.ts +61 -0
- package/dist/state-backend.js +275 -0
- package/dist/state-backend.js.map +1 -0
- package/dist/state-node.d.ts +2 -0
- package/dist/state-node.js +266 -0
- package/dist/state-node.js.map +1 -0
- package/dist/types.d.ts +462 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/utils.d.ts +5 -0
- package/dist/utils.js +117 -0
- package/dist/utils.js.map +1 -0
- package/dist/vbash.d.ts +40 -0
- package/dist/vbash.js +389 -0
- package/dist/vbash.js.map +1 -0
- package/dist/vfs.d.ts +64 -0
- package/dist/vfs.js +248 -0
- package/dist/vfs.js.map +1 -0
- package/dist/vprocess.d.ts +139 -0
- package/dist/vprocess.js +756 -0
- package/dist/vprocess.js.map +1 -0
- package/package.json +28 -0
package/dist/model.js
ADDED
|
@@ -0,0 +1,824 @@
|
|
|
1
|
+
import { blocksToText, textBlock } from "./content.js";
|
|
2
|
+
export function echoModel(id = 'default') {
|
|
3
|
+
return {
|
|
4
|
+
id,
|
|
5
|
+
kind: 'llm',
|
|
6
|
+
capabilities: { streaming: true, toolUse: true, vision: true, audioIn: true, videoIn: true },
|
|
7
|
+
async complete(req) {
|
|
8
|
+
const last = [...req.messages].reverse().find((m) => m.role === 'user');
|
|
9
|
+
const text = last ? blocksToText(last.content || []) : '';
|
|
10
|
+
return {
|
|
11
|
+
text: `Echo(${id}): ${text}`,
|
|
12
|
+
message: { role: 'assistant', content: [textBlock(`Echo(${id}): ${text}`)] },
|
|
13
|
+
finishReason: 'stop',
|
|
14
|
+
usage: { inputTokens: text.length, outputTokens: text.length + 8 },
|
|
15
|
+
};
|
|
16
|
+
},
|
|
17
|
+
async *stream(req) {
|
|
18
|
+
const result = await this.complete(req);
|
|
19
|
+
yield { type: 'content', content: { type: 'text', text: result.text } };
|
|
20
|
+
yield { type: 'message', message: result.message, usage: result.usage, finishReason: result.finishReason };
|
|
21
|
+
},
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
export function toolUseModel(id = 'tool-model', toolName = 'demo.tool') {
|
|
25
|
+
return {
|
|
26
|
+
id,
|
|
27
|
+
kind: 'llm',
|
|
28
|
+
capabilities: { toolUse: true },
|
|
29
|
+
async complete() {
|
|
30
|
+
const toolUseId = `tool_${Date.now()}`;
|
|
31
|
+
return {
|
|
32
|
+
text: '',
|
|
33
|
+
finishReason: 'tool_use',
|
|
34
|
+
message: {
|
|
35
|
+
role: 'assistant',
|
|
36
|
+
content: [{ type: 'tool_use', id: toolUseId, name: toolName, input: { demo: true } }],
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
},
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
export function openaiResponsesModel(options) {
|
|
43
|
+
const baseURL = trimSlash(options.baseURL || 'https://api.openai.com/v1');
|
|
44
|
+
const fetchImpl = options.fetch || defaultFetch();
|
|
45
|
+
const wsState = openAIResponsesWebSocketState(options, baseURL);
|
|
46
|
+
return {
|
|
47
|
+
id: options.id || options.model,
|
|
48
|
+
kind: 'llm',
|
|
49
|
+
capabilities: { provider: 'openai', protocol: 'responses', transport: options.webSocket || options.transport === 'websocket' ? 'websocket' : 'http', text: true, vision: true },
|
|
50
|
+
async complete(req) {
|
|
51
|
+
const body = openAIResponsesRequestBody(options, req.messages);
|
|
52
|
+
const record = await openAIResponsesRecord(options, baseURL, fetchImpl, wsState, body);
|
|
53
|
+
return openAIResponsesResult(options, record);
|
|
54
|
+
},
|
|
55
|
+
async *stream(req) {
|
|
56
|
+
const body = openAIResponsesRequestBody(options, req.messages);
|
|
57
|
+
if (!shouldUseOpenAIResponsesWebSocket(options)) {
|
|
58
|
+
const result = openAIResponsesResult(options, await openAIResponsesRecord(options, baseURL, fetchImpl, wsState, body));
|
|
59
|
+
if (result.text)
|
|
60
|
+
yield { type: 'content', content: textBlock(result.text), text: result.text };
|
|
61
|
+
yield { type: 'message', message: result.message, usage: result.usage, finishReason: result.finishReason, provider: result.provider };
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
yield* openAIResponsesWebSocketStream(options, wsState, body);
|
|
65
|
+
},
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
export function openaiChatCompletionsModel(options) {
|
|
69
|
+
const baseURL = trimSlash(options.baseURL || 'https://api.openai.com/v1');
|
|
70
|
+
const fetchImpl = options.fetch || defaultFetch();
|
|
71
|
+
return {
|
|
72
|
+
id: options.id || options.model,
|
|
73
|
+
kind: 'llm',
|
|
74
|
+
capabilities: { provider: 'openai', protocol: 'chat-completions', text: true, vision: true },
|
|
75
|
+
async complete(req) {
|
|
76
|
+
const body = {
|
|
77
|
+
...(options.extra || {}),
|
|
78
|
+
model: options.model,
|
|
79
|
+
messages: messagesForOpenAIChat(req.messages, options),
|
|
80
|
+
};
|
|
81
|
+
if (options.maxTokens !== undefined)
|
|
82
|
+
body.max_tokens = options.maxTokens;
|
|
83
|
+
if (options.temperature !== undefined)
|
|
84
|
+
body.temperature = options.temperature;
|
|
85
|
+
const json = await postJson(fetchImpl, `${baseURL}/chat/completions`, {
|
|
86
|
+
Authorization: `Bearer ${options.apiKey}`,
|
|
87
|
+
'Content-Type': 'application/json',
|
|
88
|
+
}, body);
|
|
89
|
+
const record = asRecord(json);
|
|
90
|
+
const firstChoice = firstOpenAIChatChoice(record);
|
|
91
|
+
const message = messageFromOpenAIChatChoice(firstChoice, options);
|
|
92
|
+
const text = extractOpenAIChatText(firstChoice);
|
|
93
|
+
return {
|
|
94
|
+
text,
|
|
95
|
+
message,
|
|
96
|
+
finishReason: normalizeFinishReason(firstChoice.finish_reason ?? record.status),
|
|
97
|
+
usage: normalizeOpenAIUsage(record.usage),
|
|
98
|
+
provider: {
|
|
99
|
+
name: 'openai',
|
|
100
|
+
model: options.model,
|
|
101
|
+
requestId: stringField(record, 'id'),
|
|
102
|
+
raw: record,
|
|
103
|
+
},
|
|
104
|
+
};
|
|
105
|
+
},
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
export function anthropicMessagesModel(options) {
|
|
109
|
+
const baseURL = trimSlash(options.baseURL || 'https://api.anthropic.com/v1');
|
|
110
|
+
const fetchImpl = options.fetch || defaultFetch();
|
|
111
|
+
const providerName = options.providerName || 'anthropic';
|
|
112
|
+
const protocol = options.protocol || 'messages';
|
|
113
|
+
return {
|
|
114
|
+
id: options.id || options.model,
|
|
115
|
+
kind: 'llm',
|
|
116
|
+
capabilities: { provider: providerName, protocol, text: true, vision: true },
|
|
117
|
+
async complete(req) {
|
|
118
|
+
const { system, messages } = messagesForAnthropic(req.messages);
|
|
119
|
+
const body = {
|
|
120
|
+
model: options.model,
|
|
121
|
+
max_tokens: options.maxTokens ?? 4096,
|
|
122
|
+
system: system || undefined,
|
|
123
|
+
messages,
|
|
124
|
+
};
|
|
125
|
+
const json = await postJson(fetchImpl, `${baseURL}/messages`, {
|
|
126
|
+
'x-api-key': options.apiKey,
|
|
127
|
+
'anthropic-version': '2023-06-01',
|
|
128
|
+
'Content-Type': 'application/json',
|
|
129
|
+
}, body);
|
|
130
|
+
const record = asRecord(json);
|
|
131
|
+
const text = extractAnthropicText(record);
|
|
132
|
+
return {
|
|
133
|
+
text,
|
|
134
|
+
message: messageFromAnthropic(record, providerName),
|
|
135
|
+
finishReason: normalizeFinishReason(record.stop_reason),
|
|
136
|
+
usage: normalizeAnthropicUsage(record.usage),
|
|
137
|
+
provider: {
|
|
138
|
+
name: providerName,
|
|
139
|
+
model: options.model,
|
|
140
|
+
requestId: stringField(record, 'id'),
|
|
141
|
+
raw: record,
|
|
142
|
+
},
|
|
143
|
+
};
|
|
144
|
+
},
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
export function deepseekMessagesModel(options) {
|
|
148
|
+
return anthropicMessagesModel({
|
|
149
|
+
...options,
|
|
150
|
+
baseURL: options.baseURL || 'https://api.deepseek.com/anthropic',
|
|
151
|
+
providerName: 'deepseek',
|
|
152
|
+
protocol: 'anthropic-messages',
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
export function deepseekOpenAIModel(options) {
|
|
156
|
+
const base = openaiChatCompletionsModel({
|
|
157
|
+
...options,
|
|
158
|
+
baseURL: options.baseURL || 'https://api.deepseek.com',
|
|
159
|
+
providerName: 'deepseek',
|
|
160
|
+
reasoningField: options.reasoningField || 'reasoning_content',
|
|
161
|
+
reasoningFieldFormat: options.reasoningFieldFormat || 'string',
|
|
162
|
+
reasoningInput: options.reasoningInput || 'omit',
|
|
163
|
+
});
|
|
164
|
+
return {
|
|
165
|
+
...base,
|
|
166
|
+
id: options.id || options.model,
|
|
167
|
+
capabilities: { ...(base.capabilities || {}), provider: 'deepseek', protocol: 'openai-chat-completions' },
|
|
168
|
+
async complete(req) {
|
|
169
|
+
const result = await base.complete(req);
|
|
170
|
+
return {
|
|
171
|
+
...result,
|
|
172
|
+
provider: {
|
|
173
|
+
...(result.provider || {}),
|
|
174
|
+
name: 'deepseek',
|
|
175
|
+
model: options.model,
|
|
176
|
+
},
|
|
177
|
+
};
|
|
178
|
+
},
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
export function minimaxOpenAIModel(options) {
|
|
182
|
+
const base = openaiChatCompletionsModel({
|
|
183
|
+
...options,
|
|
184
|
+
baseURL: options.baseURL || 'https://api.minimax.io/v1',
|
|
185
|
+
providerName: 'minimax',
|
|
186
|
+
extra: { reasoning_split: true, ...(options.extra || {}) },
|
|
187
|
+
preserveAssistantMessage: options.preserveAssistantMessage ?? true,
|
|
188
|
+
reasoningField: options.reasoningField || 'reasoning_details',
|
|
189
|
+
reasoningFieldFormat: options.reasoningFieldFormat || 'details-array',
|
|
190
|
+
reasoningInput: options.reasoningInput || 'preserve',
|
|
191
|
+
});
|
|
192
|
+
return {
|
|
193
|
+
...base,
|
|
194
|
+
id: options.id || options.model,
|
|
195
|
+
capabilities: { ...(base.capabilities || {}), provider: 'minimax', protocol: 'openai-chat-completions' },
|
|
196
|
+
async complete(req) {
|
|
197
|
+
const result = await base.complete(req);
|
|
198
|
+
return {
|
|
199
|
+
...result,
|
|
200
|
+
provider: {
|
|
201
|
+
...(result.provider || {}),
|
|
202
|
+
name: 'minimax',
|
|
203
|
+
model: options.model,
|
|
204
|
+
},
|
|
205
|
+
};
|
|
206
|
+
},
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
export function modelset(models = {}) {
|
|
210
|
+
const resolved = {};
|
|
211
|
+
for (const [alias, model] of Object.entries(models)) {
|
|
212
|
+
resolved[alias] = typeof model === 'string'
|
|
213
|
+
? () => {
|
|
214
|
+
const target = resolved[model];
|
|
215
|
+
if (!target)
|
|
216
|
+
throw new Error(`model alias not bound: ${model}`);
|
|
217
|
+
return target();
|
|
218
|
+
}
|
|
219
|
+
: () => model;
|
|
220
|
+
}
|
|
221
|
+
return {
|
|
222
|
+
get(alias = 'default') {
|
|
223
|
+
const factory = resolved[alias];
|
|
224
|
+
if (!factory)
|
|
225
|
+
throw new Error(`model not bound: ${alias}`);
|
|
226
|
+
return factory();
|
|
227
|
+
},
|
|
228
|
+
aliases() {
|
|
229
|
+
return Object.keys(resolved);
|
|
230
|
+
},
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
export const providers = {
|
|
234
|
+
echo: echoModel,
|
|
235
|
+
toolUse: toolUseModel,
|
|
236
|
+
openaiResponses: openaiResponsesModel,
|
|
237
|
+
openaiChatCompletions: openaiChatCompletionsModel,
|
|
238
|
+
anthropicMessages: anthropicMessagesModel,
|
|
239
|
+
deepseekMessages: deepseekMessagesModel,
|
|
240
|
+
deepseekOpenAI: deepseekOpenAIModel,
|
|
241
|
+
minimaxOpenAI: minimaxOpenAIModel,
|
|
242
|
+
};
|
|
243
|
+
function defaultFetch() {
|
|
244
|
+
if (typeof fetch !== 'function')
|
|
245
|
+
throw new Error('global fetch is not available; pass a fetch implementation to the model provider');
|
|
246
|
+
return fetch;
|
|
247
|
+
}
|
|
248
|
+
async function postJson(fetchImpl, url, headers, body) {
|
|
249
|
+
const response = await fetchImpl(url, {
|
|
250
|
+
method: 'POST',
|
|
251
|
+
headers,
|
|
252
|
+
body: JSON.stringify(body),
|
|
253
|
+
});
|
|
254
|
+
if (!response.ok) {
|
|
255
|
+
const text = await response.text().catch(() => '');
|
|
256
|
+
throw new Error(`model provider request failed: ${response.status ?? ''} ${response.statusText ?? ''} ${text}`.trim());
|
|
257
|
+
}
|
|
258
|
+
return response.json();
|
|
259
|
+
}
|
|
260
|
+
function openAIResponsesRequestBody(options, messages) {
|
|
261
|
+
const { instructions, input, previousResponseId } = transcriptForOpenAIResponses(messages);
|
|
262
|
+
const body = {
|
|
263
|
+
model: options.model,
|
|
264
|
+
instructions: instructions || undefined,
|
|
265
|
+
input,
|
|
266
|
+
};
|
|
267
|
+
if (options.include?.length)
|
|
268
|
+
body.include = options.include;
|
|
269
|
+
if (options.reasoning)
|
|
270
|
+
body.reasoning = options.reasoning;
|
|
271
|
+
if (options.store !== undefined)
|
|
272
|
+
body.store = options.store;
|
|
273
|
+
if (options.previousResponseId || previousResponseId)
|
|
274
|
+
body.previous_response_id = options.previousResponseId || previousResponseId;
|
|
275
|
+
return body;
|
|
276
|
+
}
|
|
277
|
+
async function openAIResponsesRecord(options, baseURL, fetchImpl, wsState, body) {
|
|
278
|
+
if (shouldUseOpenAIResponsesWebSocket(options)) {
|
|
279
|
+
return withOpenAIResponsesWebSocketTurn(wsState, () => collectOpenAIResponsesWebSocket(options, wsState, body));
|
|
280
|
+
}
|
|
281
|
+
return asRecord(await postJson(fetchImpl, `${baseURL}/responses`, openAIResponsesHttpHeaders(options), body));
|
|
282
|
+
}
|
|
283
|
+
function openAIResponsesResult(options, record) {
|
|
284
|
+
const text = extractOpenAIText(record);
|
|
285
|
+
const outputItems = Array.isArray(record.output) ? record.output.map((item) => asRecord(item)) : [];
|
|
286
|
+
const reasoningItems = openAIResponsesReasoningItems(outputItems);
|
|
287
|
+
const responseId = stringField(record, 'id');
|
|
288
|
+
return {
|
|
289
|
+
text,
|
|
290
|
+
message: {
|
|
291
|
+
role: 'assistant',
|
|
292
|
+
content: [textBlock(text)],
|
|
293
|
+
provider: {
|
|
294
|
+
anchor: true,
|
|
295
|
+
openaiResponses: {
|
|
296
|
+
responseId,
|
|
297
|
+
outputItems,
|
|
298
|
+
reasoningItems,
|
|
299
|
+
encryptedReasoningItems: reasoningItems.filter((item) => typeof item.encrypted_content === 'string'),
|
|
300
|
+
},
|
|
301
|
+
},
|
|
302
|
+
},
|
|
303
|
+
finishReason: normalizeFinishReason(record.status),
|
|
304
|
+
usage: normalizeOpenAIUsage(record.usage),
|
|
305
|
+
provider: {
|
|
306
|
+
name: 'openai',
|
|
307
|
+
model: options.model,
|
|
308
|
+
requestId: responseId,
|
|
309
|
+
cacheRef: responseId,
|
|
310
|
+
openaiResponses: {
|
|
311
|
+
responseId,
|
|
312
|
+
outputItems,
|
|
313
|
+
reasoningItems,
|
|
314
|
+
encryptedReasoningItems: reasoningItems.filter((item) => typeof item.encrypted_content === 'string'),
|
|
315
|
+
},
|
|
316
|
+
raw: record,
|
|
317
|
+
},
|
|
318
|
+
};
|
|
319
|
+
}
|
|
320
|
+
function shouldUseOpenAIResponsesWebSocket(options) {
|
|
321
|
+
return Boolean(options.webSocket) || options.transport === 'websocket';
|
|
322
|
+
}
|
|
323
|
+
function openAIResponsesWebSocketState(_options, _baseURL) {
|
|
324
|
+
return { lock: Promise.resolve() };
|
|
325
|
+
}
|
|
326
|
+
async function withOpenAIResponsesWebSocketTurn(state, task) {
|
|
327
|
+
const release = await acquireOpenAIResponsesWebSocketTurn(state);
|
|
328
|
+
try {
|
|
329
|
+
return await task();
|
|
330
|
+
}
|
|
331
|
+
finally {
|
|
332
|
+
release();
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
async function collectOpenAIResponsesWebSocket(options, state, body) {
|
|
336
|
+
let text = '';
|
|
337
|
+
const socket = await openAIResponsesSocket(options, state);
|
|
338
|
+
await socket.send({ type: 'response.create', ...body });
|
|
339
|
+
while (true) {
|
|
340
|
+
const event = await socket.receive();
|
|
341
|
+
const type = stringField(event, 'type');
|
|
342
|
+
if (type === 'response.output_text.delta') {
|
|
343
|
+
const delta = stringField(event, 'delta');
|
|
344
|
+
if (delta)
|
|
345
|
+
text += delta;
|
|
346
|
+
continue;
|
|
347
|
+
}
|
|
348
|
+
if (type === 'response.completed')
|
|
349
|
+
return responseRecordFromCompletedEvent(event, text);
|
|
350
|
+
if (isOpenAIResponsesFailureEvent(type))
|
|
351
|
+
throw openAIResponsesEventError(event);
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
async function* openAIResponsesWebSocketStream(options, state, body) {
|
|
355
|
+
const release = await acquireOpenAIResponsesWebSocketTurn(state);
|
|
356
|
+
let text = '';
|
|
357
|
+
try {
|
|
358
|
+
const socket = await openAIResponsesSocket(options, state);
|
|
359
|
+
await socket.send({ type: 'response.create', ...body });
|
|
360
|
+
while (true) {
|
|
361
|
+
const event = await socket.receive();
|
|
362
|
+
const type = stringField(event, 'type');
|
|
363
|
+
if (type === 'response.output_text.delta') {
|
|
364
|
+
const delta = stringField(event, 'delta') || '';
|
|
365
|
+
if (delta) {
|
|
366
|
+
text += delta;
|
|
367
|
+
yield { type: 'content', content: textBlock(delta), text: delta };
|
|
368
|
+
}
|
|
369
|
+
continue;
|
|
370
|
+
}
|
|
371
|
+
if (type === 'response.completed') {
|
|
372
|
+
const record = responseRecordFromCompletedEvent(event, text);
|
|
373
|
+
const result = openAIResponsesResult(options, record);
|
|
374
|
+
yield { type: 'message', message: result.message, usage: result.usage, finishReason: result.finishReason, provider: result.provider };
|
|
375
|
+
return;
|
|
376
|
+
}
|
|
377
|
+
if (isOpenAIResponsesFailureEvent(type))
|
|
378
|
+
throw openAIResponsesEventError(event);
|
|
379
|
+
yield { type: 'provider', event };
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
finally {
|
|
383
|
+
release();
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
async function acquireOpenAIResponsesWebSocketTurn(state) {
|
|
387
|
+
const previous = state.lock;
|
|
388
|
+
let release;
|
|
389
|
+
state.lock = previous.then(() => new Promise((resolve) => {
|
|
390
|
+
release = resolve;
|
|
391
|
+
}), () => new Promise((resolve) => {
|
|
392
|
+
release = resolve;
|
|
393
|
+
}));
|
|
394
|
+
await previous;
|
|
395
|
+
return release;
|
|
396
|
+
}
|
|
397
|
+
async function openAIResponsesSocket(options, state) {
|
|
398
|
+
if (!options.webSocket)
|
|
399
|
+
throw new Error('OpenAI Responses WebSocket transport requires webSocket.connect');
|
|
400
|
+
if (!state.socket) {
|
|
401
|
+
state.socket = Promise.resolve(options.webSocket.connect({
|
|
402
|
+
url: options.webSocket.url || httpUrlToWebSocketUrl(trimSlash(options.baseURL || 'https://api.openai.com/v1'), '/responses'),
|
|
403
|
+
headers: openAIResponsesHttpHeaders(options),
|
|
404
|
+
}));
|
|
405
|
+
}
|
|
406
|
+
return state.socket;
|
|
407
|
+
}
|
|
408
|
+
function openAIResponsesHttpHeaders(options) {
|
|
409
|
+
return {
|
|
410
|
+
Authorization: `Bearer ${options.apiKey}`,
|
|
411
|
+
'Content-Type': 'application/json',
|
|
412
|
+
};
|
|
413
|
+
}
|
|
414
|
+
function responseRecordFromCompletedEvent(event, streamedText) {
|
|
415
|
+
const response = cloneRecord(asRecord(event.response));
|
|
416
|
+
if (!stringField(response, 'output_text') && streamedText)
|
|
417
|
+
response.output_text = streamedText;
|
|
418
|
+
return response;
|
|
419
|
+
}
|
|
420
|
+
function isOpenAIResponsesFailureEvent(type) {
|
|
421
|
+
return type === 'error' || type === 'response.failed' || type === 'response.incomplete';
|
|
422
|
+
}
|
|
423
|
+
function openAIResponsesEventError(event) {
|
|
424
|
+
const error = asRecord(event.error);
|
|
425
|
+
const message = stringField(error, 'message') || stringField(event, 'message') || JSON.stringify(event);
|
|
426
|
+
const code = stringField(error, 'code') || stringField(event, 'code');
|
|
427
|
+
return new Error(code ? `${code}: ${message}` : message);
|
|
428
|
+
}
|
|
429
|
+
function httpUrlToWebSocketUrl(baseURL, suffix) {
|
|
430
|
+
const url = `${baseURL}${suffix}`;
|
|
431
|
+
if (url.startsWith('https://'))
|
|
432
|
+
return `wss://${url.slice('https://'.length)}`;
|
|
433
|
+
if (url.startsWith('http://'))
|
|
434
|
+
return `ws://${url.slice('http://'.length)}`;
|
|
435
|
+
return url;
|
|
436
|
+
}
|
|
437
|
+
function transcriptForOpenAIResponses(messages) {
|
|
438
|
+
const instructions = messages.filter((message) => message.role === 'system').map((message) => blocksToText(message.content)).filter(Boolean).join('\n\n');
|
|
439
|
+
const continuation = lastOpenAIResponsesContinuation(messages);
|
|
440
|
+
const textMessages = continuation ? messages.slice(continuation.index + 1) : messages;
|
|
441
|
+
const text = textMessages
|
|
442
|
+
.filter((message) => message.role !== 'system')
|
|
443
|
+
.map((message) => `${message.role}: ${blocksToText(message.content)}`)
|
|
444
|
+
.filter((line) => !line.endsWith(': '))
|
|
445
|
+
.join('\n\n');
|
|
446
|
+
if (continuation?.responseId)
|
|
447
|
+
return { instructions, input: text, previousResponseId: continuation.responseId };
|
|
448
|
+
const providerItems = messages.flatMap((message) => openAIResponsesInputItems(message));
|
|
449
|
+
if (!providerItems.length)
|
|
450
|
+
return { instructions, input: text };
|
|
451
|
+
const input = [
|
|
452
|
+
...providerItems,
|
|
453
|
+
{
|
|
454
|
+
type: 'message',
|
|
455
|
+
role: 'user',
|
|
456
|
+
content: [{ type: 'input_text', text }],
|
|
457
|
+
},
|
|
458
|
+
];
|
|
459
|
+
return { instructions, input };
|
|
460
|
+
}
|
|
461
|
+
function lastOpenAIResponsesContinuation(messages) {
|
|
462
|
+
for (let index = messages.length - 1; index >= 0; index -= 1) {
|
|
463
|
+
const provider = asRecord(messages[index].provider);
|
|
464
|
+
const state = asRecord(provider.openaiResponses);
|
|
465
|
+
const responseId = stringField(state, 'responseId');
|
|
466
|
+
if (responseId)
|
|
467
|
+
return { index, responseId };
|
|
468
|
+
}
|
|
469
|
+
return undefined;
|
|
470
|
+
}
|
|
471
|
+
function openAIResponsesInputItems(message) {
|
|
472
|
+
const provider = asRecord(message.provider);
|
|
473
|
+
const state = asRecord(provider.openaiResponses);
|
|
474
|
+
const items = Array.isArray(state.reasoningItems)
|
|
475
|
+
? state.reasoningItems
|
|
476
|
+
: Array.isArray(state.outputItems)
|
|
477
|
+
? state.outputItems.filter((item) => asRecord(item).type === 'reasoning' || asRecord(item).type === 'compaction')
|
|
478
|
+
: [];
|
|
479
|
+
return items.map((item) => asRecord(item)).filter((item) => item.type === 'reasoning' || item.type === 'compaction');
|
|
480
|
+
}
|
|
481
|
+
function messagesForAnthropic(messages) {
|
|
482
|
+
const system = messages.filter((message) => message.role === 'system').map((message) => blocksToText(message.content)).filter(Boolean).join('\n\n');
|
|
483
|
+
const output = [];
|
|
484
|
+
for (const message of messages) {
|
|
485
|
+
if (message.role === 'system')
|
|
486
|
+
continue;
|
|
487
|
+
const role = message.role === 'assistant' ? 'assistant' : 'user';
|
|
488
|
+
const content = anthropicContentBlocks(message.content, role);
|
|
489
|
+
if (!content.length)
|
|
490
|
+
continue;
|
|
491
|
+
const last = output.at(-1);
|
|
492
|
+
if (last?.role === role && canMergeAnthropicContent(last.content) && canMergeAnthropicContent(content)) {
|
|
493
|
+
last.content[0].text += `\n\n${String(content[0].text)}`;
|
|
494
|
+
}
|
|
495
|
+
else {
|
|
496
|
+
output.push({ role, content });
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
if (!output.length)
|
|
500
|
+
output.push({ role: 'user', content: [{ type: 'text', text: '' }] });
|
|
501
|
+
return { system, messages: output };
|
|
502
|
+
}
|
|
503
|
+
function messagesForOpenAIChat(messages, options) {
|
|
504
|
+
const output = [];
|
|
505
|
+
for (const message of messages) {
|
|
506
|
+
const role = message.role === 'system' ? 'system' : message.role === 'assistant' ? 'assistant' : 'user';
|
|
507
|
+
if (message.role === 'tool' || message.content.some((block) => block.type === 'tool_result')) {
|
|
508
|
+
for (const block of message.content) {
|
|
509
|
+
if (block.type !== 'tool_result')
|
|
510
|
+
continue;
|
|
511
|
+
output.push({
|
|
512
|
+
role: 'tool',
|
|
513
|
+
tool_call_id: block.toolUseId || block.id || block.name || 'tool',
|
|
514
|
+
content: blocksToText([block]),
|
|
515
|
+
});
|
|
516
|
+
}
|
|
517
|
+
continue;
|
|
518
|
+
}
|
|
519
|
+
if (role === 'assistant') {
|
|
520
|
+
output.push(openAIChatAssistantMessage(message, options));
|
|
521
|
+
continue;
|
|
522
|
+
}
|
|
523
|
+
const text = blocksToText(message.content);
|
|
524
|
+
if (!text)
|
|
525
|
+
continue;
|
|
526
|
+
const last = output.at(-1);
|
|
527
|
+
if (last?.role === role && typeof last.content === 'string')
|
|
528
|
+
last.content += `\n\n${text}`;
|
|
529
|
+
else
|
|
530
|
+
output.push({ role, content: text });
|
|
531
|
+
}
|
|
532
|
+
if (!output.length)
|
|
533
|
+
output.push({ role: 'user', content: '' });
|
|
534
|
+
return output;
|
|
535
|
+
}
|
|
536
|
+
function anthropicContentBlocks(blocks, role) {
|
|
537
|
+
const output = [];
|
|
538
|
+
for (const block of blocks) {
|
|
539
|
+
if (block.type === 'text') {
|
|
540
|
+
if (block.text)
|
|
541
|
+
output.push({ type: 'text', text: block.text });
|
|
542
|
+
}
|
|
543
|
+
else if (block.type === 'thinking' && role === 'assistant') {
|
|
544
|
+
if (block.provider !== 'anthropic')
|
|
545
|
+
continue;
|
|
546
|
+
const raw = asRecord(block.raw);
|
|
547
|
+
if (raw.type === 'thinking' || raw.type === 'redacted_thinking')
|
|
548
|
+
output.push(cloneRecord(raw));
|
|
549
|
+
else if (block.signature)
|
|
550
|
+
output.push({
|
|
551
|
+
type: 'thinking',
|
|
552
|
+
thinking: block.text || block.thinking || '',
|
|
553
|
+
signature: block.signature,
|
|
554
|
+
});
|
|
555
|
+
}
|
|
556
|
+
else if (block.type === 'tool_use' && role === 'assistant') {
|
|
557
|
+
output.push({ type: 'tool_use', id: block.id, name: block.name, input: block.input ?? {} });
|
|
558
|
+
}
|
|
559
|
+
else if (block.type === 'tool_result') {
|
|
560
|
+
output.push({
|
|
561
|
+
type: 'tool_result',
|
|
562
|
+
tool_use_id: block.toolUseId || block.id,
|
|
563
|
+
content: blocksToText([block]),
|
|
564
|
+
is_error: block.ok === false || block.status === 'failed',
|
|
565
|
+
});
|
|
566
|
+
}
|
|
567
|
+
else {
|
|
568
|
+
const text = blocksToText([block]);
|
|
569
|
+
if (text)
|
|
570
|
+
output.push({ type: 'text', text });
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
return output;
|
|
574
|
+
}
|
|
575
|
+
function canMergeAnthropicContent(content) {
|
|
576
|
+
return content.length === 1 && content[0].type === 'text' && typeof content[0].text === 'string';
|
|
577
|
+
}
|
|
578
|
+
function openAIChatAssistantMessage(message, options) {
|
|
579
|
+
if (options.preserveAssistantMessage) {
|
|
580
|
+
const preserved = preservedOpenAIChatAssistantMessage(message, openAIChatProviderName(options));
|
|
581
|
+
if (preserved)
|
|
582
|
+
return preserved;
|
|
583
|
+
}
|
|
584
|
+
const textBlocks = message.content.filter((block) => block.type !== 'tool_use' && block.type !== 'thinking');
|
|
585
|
+
const text = blocksToText(textBlocks);
|
|
586
|
+
const toolCalls = message.content.filter((block) => block.type === 'tool_use').map((block) => ({
|
|
587
|
+
id: block.id || idFromToolCall(String(block.name || 'tool')),
|
|
588
|
+
type: 'function',
|
|
589
|
+
function: {
|
|
590
|
+
name: block.name || 'tool',
|
|
591
|
+
arguments: JSON.stringify(block.input ?? {}),
|
|
592
|
+
},
|
|
593
|
+
}));
|
|
594
|
+
const output = { role: 'assistant', content: text || (toolCalls.length ? null : '') };
|
|
595
|
+
if (toolCalls.length)
|
|
596
|
+
output.tool_calls = toolCalls;
|
|
597
|
+
if (options.reasoningField && options.reasoningInput !== 'omit') {
|
|
598
|
+
const thinking = openAIChatReasoningInput(message, options);
|
|
599
|
+
if (thinking !== undefined)
|
|
600
|
+
output[options.reasoningField] = thinking;
|
|
601
|
+
}
|
|
602
|
+
return output;
|
|
603
|
+
}
|
|
604
|
+
function preservedOpenAIChatAssistantMessage(message, providerName) {
|
|
605
|
+
const provider = asRecord(message.provider);
|
|
606
|
+
const state = asRecord(provider.openaiChat);
|
|
607
|
+
if (state.providerName !== providerName)
|
|
608
|
+
return undefined;
|
|
609
|
+
const responseMessage = asRecord(state.responseMessage);
|
|
610
|
+
if (responseMessage.role !== 'assistant')
|
|
611
|
+
return undefined;
|
|
612
|
+
return cloneRecord(responseMessage);
|
|
613
|
+
}
|
|
614
|
+
function openAIChatReasoningInput(message, options) {
|
|
615
|
+
const provider = asRecord(message.provider);
|
|
616
|
+
const state = asRecord(provider.openaiChat);
|
|
617
|
+
if (state.providerName !== openAIChatProviderName(options))
|
|
618
|
+
return undefined;
|
|
619
|
+
const reasoning = state.reasoning;
|
|
620
|
+
if (options.reasoningFieldFormat === 'details-array') {
|
|
621
|
+
if (!Array.isArray(reasoning))
|
|
622
|
+
return undefined;
|
|
623
|
+
const details = reasoning.map((item) => {
|
|
624
|
+
const record = asRecord(item);
|
|
625
|
+
return Object.keys(record).length ? cloneRecord(record) : undefined;
|
|
626
|
+
}).filter((detail) => Boolean(detail));
|
|
627
|
+
return details.length ? details : undefined;
|
|
628
|
+
}
|
|
629
|
+
return typeof reasoning === 'string' && reasoning ? reasoning : undefined;
|
|
630
|
+
}
|
|
631
|
+
function extractOpenAIText(record) {
|
|
632
|
+
if (typeof record.output_text === 'string')
|
|
633
|
+
return record.output_text;
|
|
634
|
+
const output = Array.isArray(record.output) ? record.output : [];
|
|
635
|
+
const chunks = [];
|
|
636
|
+
for (const item of output) {
|
|
637
|
+
const itemRecord = asRecord(item);
|
|
638
|
+
const content = Array.isArray(itemRecord.content) ? itemRecord.content : [];
|
|
639
|
+
for (const block of content) {
|
|
640
|
+
const blockRecord = asRecord(block);
|
|
641
|
+
if (typeof blockRecord.text === 'string')
|
|
642
|
+
chunks.push(blockRecord.text);
|
|
643
|
+
if (typeof blockRecord.value === 'string')
|
|
644
|
+
chunks.push(blockRecord.value);
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
return chunks.join('');
|
|
648
|
+
}
|
|
649
|
+
function openAIResponsesReasoningItems(outputItems) {
|
|
650
|
+
return outputItems
|
|
651
|
+
.filter((item) => item.type === 'reasoning' || item.type === 'compaction')
|
|
652
|
+
.map((item) => ({ ...item }));
|
|
653
|
+
}
|
|
654
|
+
function firstOpenAIChatChoice(record) {
|
|
655
|
+
const choices = Array.isArray(record.choices) ? record.choices : [];
|
|
656
|
+
return asRecord(choices[0]);
|
|
657
|
+
}
|
|
658
|
+
function extractOpenAIChatText(choice) {
|
|
659
|
+
const message = asRecord(choice.message);
|
|
660
|
+
const content = message.content;
|
|
661
|
+
if (typeof content === 'string')
|
|
662
|
+
return content;
|
|
663
|
+
if (!Array.isArray(content))
|
|
664
|
+
return '';
|
|
665
|
+
const chunks = [];
|
|
666
|
+
for (const block of content) {
|
|
667
|
+
const record = asRecord(block);
|
|
668
|
+
if (typeof record.text === 'string')
|
|
669
|
+
chunks.push(record.text);
|
|
670
|
+
if (typeof record.value === 'string')
|
|
671
|
+
chunks.push(record.value);
|
|
672
|
+
}
|
|
673
|
+
return chunks.join('');
|
|
674
|
+
}
|
|
675
|
+
function messageFromOpenAIChatChoice(choice, options) {
|
|
676
|
+
const message = asRecord(choice.message);
|
|
677
|
+
const content = [];
|
|
678
|
+
const reasoningField = options.reasoningField;
|
|
679
|
+
const reasoning = reasoningField ? message[reasoningField] : undefined;
|
|
680
|
+
const text = extractOpenAIChatText(choice);
|
|
681
|
+
if (text)
|
|
682
|
+
content.push(textBlock(text));
|
|
683
|
+
const toolCalls = Array.isArray(message.tool_calls) ? message.tool_calls : [];
|
|
684
|
+
for (const call of toolCalls) {
|
|
685
|
+
const record = asRecord(call);
|
|
686
|
+
const fn = asRecord(record.function);
|
|
687
|
+
const name = typeof fn.name === 'string' ? fn.name : typeof record.name === 'string' ? record.name : 'tool';
|
|
688
|
+
content.push({
|
|
689
|
+
type: 'tool_use',
|
|
690
|
+
id: typeof record.id === 'string' ? record.id : idFromToolCall(name),
|
|
691
|
+
name,
|
|
692
|
+
input: parseToolCallArguments(fn.arguments),
|
|
693
|
+
});
|
|
694
|
+
}
|
|
695
|
+
return {
|
|
696
|
+
role: 'assistant',
|
|
697
|
+
content: content.length ? content : [textBlock('')],
|
|
698
|
+
provider: {
|
|
699
|
+
openaiChat: {
|
|
700
|
+
providerName: openAIChatProviderName(options),
|
|
701
|
+
responseMessage: cloneRecord(message),
|
|
702
|
+
reasoning: cloneReasoningValue(reasoning),
|
|
703
|
+
reasoningField,
|
|
704
|
+
reasoningFieldFormat: options.reasoningFieldFormat || 'string',
|
|
705
|
+
},
|
|
706
|
+
},
|
|
707
|
+
};
|
|
708
|
+
}
|
|
709
|
+
function extractAnthropicText(record) {
|
|
710
|
+
const content = Array.isArray(record.content) ? record.content : [];
|
|
711
|
+
return content.map((block) => {
|
|
712
|
+
const item = asRecord(block);
|
|
713
|
+
return item.type === 'text' && typeof item.text === 'string' ? item.text : '';
|
|
714
|
+
}).join('');
|
|
715
|
+
}
|
|
716
|
+
function messageFromAnthropic(record, providerName = 'anthropic') {
|
|
717
|
+
const content = Array.isArray(record.content) ? record.content : [];
|
|
718
|
+
const blocks = [];
|
|
719
|
+
const privateThinking = [];
|
|
720
|
+
for (const block of content) {
|
|
721
|
+
const item = asRecord(block);
|
|
722
|
+
if (item.type === 'text' && typeof item.text === 'string')
|
|
723
|
+
blocks.push(textBlock(item.text));
|
|
724
|
+
else if (item.type === 'thinking' || item.type === 'redacted_thinking') {
|
|
725
|
+
if (providerName === 'anthropic') {
|
|
726
|
+
blocks.push({
|
|
727
|
+
type: 'thinking',
|
|
728
|
+
text: item.type === 'thinking' && typeof item.thinking === 'string' ? item.thinking : '',
|
|
729
|
+
signature: item.signature,
|
|
730
|
+
provider: 'anthropic',
|
|
731
|
+
raw: cloneRecord(item),
|
|
732
|
+
});
|
|
733
|
+
}
|
|
734
|
+
else {
|
|
735
|
+
privateThinking.push(cloneRecord(item));
|
|
736
|
+
}
|
|
737
|
+
}
|
|
738
|
+
else if (item.type === 'tool_use')
|
|
739
|
+
blocks.push({ type: 'tool_use', id: stringField(item, 'id'), name: stringField(item, 'name'), input: item.input ?? {} });
|
|
740
|
+
}
|
|
741
|
+
return {
|
|
742
|
+
role: 'assistant',
|
|
743
|
+
content: blocks.length ? blocks : [textBlock('')],
|
|
744
|
+
provider: privateThinking.length
|
|
745
|
+
? { messages: { providerName, thinkingBlocks: privateThinking } }
|
|
746
|
+
: undefined,
|
|
747
|
+
};
|
|
748
|
+
}
|
|
749
|
+
function normalizeOpenAIUsage(value) {
|
|
750
|
+
const usage = asRecord(value);
|
|
751
|
+
if (!Object.keys(usage).length)
|
|
752
|
+
return undefined;
|
|
753
|
+
return {
|
|
754
|
+
inputTokens: numberField(usage, 'input_tokens') ?? numberField(usage, 'prompt_tokens'),
|
|
755
|
+
outputTokens: numberField(usage, 'output_tokens') ?? numberField(usage, 'completion_tokens'),
|
|
756
|
+
totalTokens: numberField(usage, 'total_tokens'),
|
|
757
|
+
cachedInputTokens: numberField(asRecord(usage.input_tokens_details), 'cached_tokens') ?? numberField(usage, 'prompt_cache_hit_tokens'),
|
|
758
|
+
};
|
|
759
|
+
}
|
|
760
|
+
function openAIChatProviderName(options) {
|
|
761
|
+
return options.providerName || 'openai';
|
|
762
|
+
}
|
|
763
|
+
function cloneReasoningValue(value) {
|
|
764
|
+
if (typeof value === 'string')
|
|
765
|
+
return value;
|
|
766
|
+
if (Array.isArray(value))
|
|
767
|
+
return value.map((item) => {
|
|
768
|
+
const record = asRecord(item);
|
|
769
|
+
return Object.keys(record).length ? cloneRecord(record) : item;
|
|
770
|
+
});
|
|
771
|
+
return undefined;
|
|
772
|
+
}
|
|
773
|
+
function normalizeAnthropicUsage(value) {
|
|
774
|
+
const usage = asRecord(value);
|
|
775
|
+
if (!Object.keys(usage).length)
|
|
776
|
+
return undefined;
|
|
777
|
+
return {
|
|
778
|
+
inputTokens: numberField(usage, 'input_tokens'),
|
|
779
|
+
outputTokens: numberField(usage, 'output_tokens'),
|
|
780
|
+
cachedInputTokens: numberField(usage, 'cache_read_input_tokens'),
|
|
781
|
+
};
|
|
782
|
+
}
|
|
783
|
+
function normalizeFinishReason(value) {
|
|
784
|
+
if (value === 'completed' || value === 'end_turn' || value === 'stop_sequence' || value === 'stop')
|
|
785
|
+
return 'stop';
|
|
786
|
+
if (value === 'max_tokens' || value === 'length' || value === 'incomplete')
|
|
787
|
+
return 'length';
|
|
788
|
+
if (value === 'tool_use' || value === 'tool_calls')
|
|
789
|
+
return 'tool_use';
|
|
790
|
+
if (value === 'content_filter')
|
|
791
|
+
return 'content_filter';
|
|
792
|
+
return 'unknown';
|
|
793
|
+
}
|
|
794
|
+
function parseToolCallArguments(value) {
|
|
795
|
+
if (typeof value !== 'string' || !value.trim())
|
|
796
|
+
return {};
|
|
797
|
+
try {
|
|
798
|
+
return JSON.parse(value);
|
|
799
|
+
}
|
|
800
|
+
catch {
|
|
801
|
+
return value;
|
|
802
|
+
}
|
|
803
|
+
}
|
|
804
|
+
function idFromToolCall(name) {
|
|
805
|
+
return `tool_${name.replace(/[^A-Za-z0-9_-]+/g, '_') || 'call'}`;
|
|
806
|
+
}
|
|
807
|
+
function asRecord(value) {
|
|
808
|
+
return value && typeof value === 'object' ? value : {};
|
|
809
|
+
}
|
|
810
|
+
function cloneRecord(value) {
|
|
811
|
+
return JSON.parse(JSON.stringify(value));
|
|
812
|
+
}
|
|
813
|
+
function stringField(record, key) {
|
|
814
|
+
const value = record[key];
|
|
815
|
+
return typeof value === 'string' ? value : undefined;
|
|
816
|
+
}
|
|
817
|
+
function numberField(record, key) {
|
|
818
|
+
const value = record[key];
|
|
819
|
+
return typeof value === 'number' ? value : undefined;
|
|
820
|
+
}
|
|
821
|
+
function trimSlash(value) {
|
|
822
|
+
return value.replace(/\/+$/, '');
|
|
823
|
+
}
|
|
824
|
+
//# sourceMappingURL=model.js.map
|