nuwaxcode 1.1.34 → 1.1.45
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/bin/nuwaxcode +19 -1
- package/package.json +15 -117
- package/{script/postinstall.mjs → postinstall.mjs} +18 -6
- package/AGENTS.md +0 -27
- package/Dockerfile +0 -18
- package/README.md +0 -15
- package/bunfig.toml +0 -7
- package/parsers-config.ts +0 -253
- package/script/build.ts +0 -172
- package/script/publish-registries.ts +0 -187
- package/script/publish.ts +0 -70
- package/script/schema.ts +0 -47
- package/src/acp/README.md +0 -164
- package/src/acp/agent.ts +0 -1280
- package/src/acp/session.ts +0 -111
- package/src/acp/types.ts +0 -24
- package/src/agent/agent.ts +0 -332
- package/src/agent/generate.txt +0 -75
- package/src/agent/prompt/compaction.txt +0 -12
- package/src/agent/prompt/explore.txt +0 -18
- package/src/agent/prompt/summary.txt +0 -11
- package/src/agent/prompt/title.txt +0 -43
- package/src/auth/index.ts +0 -73
- package/src/bun/index.ts +0 -134
- package/src/bus/bus-event.ts +0 -43
- package/src/bus/global.ts +0 -10
- package/src/bus/index.ts +0 -105
- package/src/cli/bootstrap.ts +0 -17
- package/src/cli/cmd/acp.ts +0 -69
- package/src/cli/cmd/agent.ts +0 -257
- package/src/cli/cmd/auth.ts +0 -400
- package/src/cli/cmd/cmd.ts +0 -7
- package/src/cli/cmd/debug/agent.ts +0 -166
- package/src/cli/cmd/debug/config.ts +0 -16
- package/src/cli/cmd/debug/file.ts +0 -97
- package/src/cli/cmd/debug/index.ts +0 -48
- package/src/cli/cmd/debug/lsp.ts +0 -52
- package/src/cli/cmd/debug/ripgrep.ts +0 -87
- package/src/cli/cmd/debug/scrap.ts +0 -16
- package/src/cli/cmd/debug/skill.ts +0 -16
- package/src/cli/cmd/debug/snapshot.ts +0 -52
- package/src/cli/cmd/export.ts +0 -88
- package/src/cli/cmd/generate.ts +0 -38
- package/src/cli/cmd/github.ts +0 -1548
- package/src/cli/cmd/import.ts +0 -98
- package/src/cli/cmd/mcp.ts +0 -755
- package/src/cli/cmd/models.ts +0 -77
- package/src/cli/cmd/pr.ts +0 -112
- package/src/cli/cmd/run.ts +0 -395
- package/src/cli/cmd/serve.ts +0 -20
- package/src/cli/cmd/session.ts +0 -135
- package/src/cli/cmd/stats.ts +0 -402
- package/src/cli/cmd/tui/app.tsx +0 -761
- package/src/cli/cmd/tui/attach.ts +0 -31
- package/src/cli/cmd/tui/component/border.tsx +0 -21
- package/src/cli/cmd/tui/component/dialog-agent.tsx +0 -31
- package/src/cli/cmd/tui/component/dialog-command.tsx +0 -148
- package/src/cli/cmd/tui/component/dialog-mcp.tsx +0 -86
- package/src/cli/cmd/tui/component/dialog-model.tsx +0 -234
- package/src/cli/cmd/tui/component/dialog-provider.tsx +0 -256
- package/src/cli/cmd/tui/component/dialog-session-list.tsx +0 -114
- package/src/cli/cmd/tui/component/dialog-session-rename.tsx +0 -31
- package/src/cli/cmd/tui/component/dialog-stash.tsx +0 -87
- package/src/cli/cmd/tui/component/dialog-status.tsx +0 -164
- package/src/cli/cmd/tui/component/dialog-tag.tsx +0 -44
- package/src/cli/cmd/tui/component/dialog-theme-list.tsx +0 -50
- package/src/cli/cmd/tui/component/logo.tsx +0 -88
- package/src/cli/cmd/tui/component/prompt/autocomplete.tsx +0 -632
- package/src/cli/cmd/tui/component/prompt/frecency.tsx +0 -89
- package/src/cli/cmd/tui/component/prompt/history.tsx +0 -108
- package/src/cli/cmd/tui/component/prompt/index.tsx +0 -1096
- package/src/cli/cmd/tui/component/prompt/stash.tsx +0 -101
- package/src/cli/cmd/tui/component/textarea-keybindings.ts +0 -73
- package/src/cli/cmd/tui/component/tips.tsx +0 -153
- package/src/cli/cmd/tui/component/todo-item.tsx +0 -32
- package/src/cli/cmd/tui/context/args.tsx +0 -14
- package/src/cli/cmd/tui/context/directory.ts +0 -13
- package/src/cli/cmd/tui/context/exit.tsx +0 -23
- package/src/cli/cmd/tui/context/helper.tsx +0 -25
- package/src/cli/cmd/tui/context/keybind.tsx +0 -101
- package/src/cli/cmd/tui/context/kv.tsx +0 -52
- package/src/cli/cmd/tui/context/local.tsx +0 -402
- package/src/cli/cmd/tui/context/prompt.tsx +0 -18
- package/src/cli/cmd/tui/context/route.tsx +0 -46
- package/src/cli/cmd/tui/context/sdk.tsx +0 -94
- package/src/cli/cmd/tui/context/sync.tsx +0 -427
- package/src/cli/cmd/tui/context/theme/aura.json +0 -69
- package/src/cli/cmd/tui/context/theme/ayu.json +0 -80
- package/src/cli/cmd/tui/context/theme/carbonfox.json +0 -248
- package/src/cli/cmd/tui/context/theme/catppuccin-frappe.json +0 -233
- package/src/cli/cmd/tui/context/theme/catppuccin-macchiato.json +0 -233
- package/src/cli/cmd/tui/context/theme/catppuccin.json +0 -112
- package/src/cli/cmd/tui/context/theme/cobalt2.json +0 -228
- package/src/cli/cmd/tui/context/theme/cursor.json +0 -249
- package/src/cli/cmd/tui/context/theme/dracula.json +0 -219
- package/src/cli/cmd/tui/context/theme/everforest.json +0 -241
- package/src/cli/cmd/tui/context/theme/flexoki.json +0 -237
- package/src/cli/cmd/tui/context/theme/github.json +0 -233
- package/src/cli/cmd/tui/context/theme/gruvbox.json +0 -95
- package/src/cli/cmd/tui/context/theme/kanagawa.json +0 -77
- package/src/cli/cmd/tui/context/theme/lucent-orng.json +0 -237
- package/src/cli/cmd/tui/context/theme/material.json +0 -235
- package/src/cli/cmd/tui/context/theme/matrix.json +0 -77
- package/src/cli/cmd/tui/context/theme/mercury.json +0 -252
- package/src/cli/cmd/tui/context/theme/monokai.json +0 -221
- package/src/cli/cmd/tui/context/theme/nightowl.json +0 -221
- package/src/cli/cmd/tui/context/theme/nord.json +0 -223
- package/src/cli/cmd/tui/context/theme/one-dark.json +0 -84
- package/src/cli/cmd/tui/context/theme/orng.json +0 -249
- package/src/cli/cmd/tui/context/theme/osaka-jade.json +0 -93
- package/src/cli/cmd/tui/context/theme/palenight.json +0 -222
- package/src/cli/cmd/tui/context/theme/rosepine.json +0 -234
- package/src/cli/cmd/tui/context/theme/solarized.json +0 -223
- package/src/cli/cmd/tui/context/theme/synthwave84.json +0 -226
- package/src/cli/cmd/tui/context/theme/tokyonight.json +0 -243
- package/src/cli/cmd/tui/context/theme/vercel.json +0 -245
- package/src/cli/cmd/tui/context/theme/vesper.json +0 -218
- package/src/cli/cmd/tui/context/theme/zenburn.json +0 -223
- package/src/cli/cmd/tui/context/theme.tsx +0 -1152
- package/src/cli/cmd/tui/event.ts +0 -48
- package/src/cli/cmd/tui/routes/home.tsx +0 -140
- package/src/cli/cmd/tui/routes/session/dialog-fork-from-timeline.tsx +0 -64
- package/src/cli/cmd/tui/routes/session/dialog-message.tsx +0 -109
- package/src/cli/cmd/tui/routes/session/dialog-subagent.tsx +0 -26
- package/src/cli/cmd/tui/routes/session/dialog-timeline.tsx +0 -47
- package/src/cli/cmd/tui/routes/session/footer.tsx +0 -91
- package/src/cli/cmd/tui/routes/session/header.tsx +0 -136
- package/src/cli/cmd/tui/routes/session/index.tsx +0 -2050
- package/src/cli/cmd/tui/routes/session/permission.tsx +0 -495
- package/src/cli/cmd/tui/routes/session/question.tsx +0 -435
- package/src/cli/cmd/tui/routes/session/sidebar.tsx +0 -312
- package/src/cli/cmd/tui/thread.ts +0 -165
- package/src/cli/cmd/tui/ui/dialog-alert.tsx +0 -57
- package/src/cli/cmd/tui/ui/dialog-confirm.tsx +0 -83
- package/src/cli/cmd/tui/ui/dialog-export-options.tsx +0 -204
- package/src/cli/cmd/tui/ui/dialog-help.tsx +0 -38
- package/src/cli/cmd/tui/ui/dialog-prompt.tsx +0 -77
- package/src/cli/cmd/tui/ui/dialog-select.tsx +0 -354
- package/src/cli/cmd/tui/ui/dialog.tsx +0 -167
- package/src/cli/cmd/tui/ui/link.tsx +0 -28
- package/src/cli/cmd/tui/ui/spinner.ts +0 -368
- package/src/cli/cmd/tui/ui/toast.tsx +0 -100
- package/src/cli/cmd/tui/util/clipboard.ts +0 -160
- package/src/cli/cmd/tui/util/editor.ts +0 -32
- package/src/cli/cmd/tui/util/signal.ts +0 -7
- package/src/cli/cmd/tui/util/terminal.ts +0 -114
- package/src/cli/cmd/tui/util/transcript.ts +0 -98
- package/src/cli/cmd/tui/worker.ts +0 -152
- package/src/cli/cmd/uninstall.ts +0 -357
- package/src/cli/cmd/upgrade.ts +0 -73
- package/src/cli/cmd/web.ts +0 -81
- package/src/cli/error.ts +0 -57
- package/src/cli/network.ts +0 -53
- package/src/cli/ui.ts +0 -84
- package/src/cli/upgrade.ts +0 -25
- package/src/command/index.ts +0 -131
- package/src/command/template/initialize.txt +0 -10
- package/src/command/template/review.txt +0 -99
- package/src/config/config.ts +0 -1255
- package/src/config/markdown.ts +0 -93
- package/src/env/index.ts +0 -26
- package/src/file/ignore.ts +0 -83
- package/src/file/index.ts +0 -411
- package/src/file/ripgrep.ts +0 -409
- package/src/file/time.ts +0 -64
- package/src/file/watcher.ts +0 -118
- package/src/flag/flag.ts +0 -54
- package/src/format/formatter.ts +0 -359
- package/src/format/index.ts +0 -137
- package/src/global/index.ts +0 -55
- package/src/id/id.ts +0 -83
- package/src/ide/index.ts +0 -76
- package/src/index.ts +0 -159
- package/src/installation/index.ts +0 -246
- package/src/lsp/client.ts +0 -252
- package/src/lsp/index.ts +0 -485
- package/src/lsp/language.ts +0 -119
- package/src/lsp/server.ts +0 -2046
- package/src/mcp/auth.ts +0 -135
- package/src/mcp/index.ts +0 -926
- package/src/mcp/oauth-callback.ts +0 -200
- package/src/mcp/oauth-provider.ts +0 -154
- package/src/patch/index.ts +0 -680
- package/src/permission/arity.ts +0 -163
- package/src/permission/index.ts +0 -210
- package/src/permission/next.ts +0 -269
- package/src/plugin/codex.ts +0 -493
- package/src/plugin/copilot.ts +0 -269
- package/src/plugin/index.ts +0 -135
- package/src/project/bootstrap.ts +0 -35
- package/src/project/instance.ts +0 -91
- package/src/project/project.ts +0 -320
- package/src/project/state.ts +0 -66
- package/src/project/vcs.ts +0 -76
- package/src/provider/auth.ts +0 -147
- package/src/provider/models-macro.ts +0 -11
- package/src/provider/models.ts +0 -112
- package/src/provider/provider.ts +0 -1219
- package/src/provider/sdk/openai-compatible/src/README.md +0 -5
- package/src/provider/sdk/openai-compatible/src/index.ts +0 -2
- package/src/provider/sdk/openai-compatible/src/openai-compatible-provider.ts +0 -100
- package/src/provider/sdk/openai-compatible/src/responses/convert-to-openai-responses-input.ts +0 -303
- package/src/provider/sdk/openai-compatible/src/responses/map-openai-responses-finish-reason.ts +0 -22
- package/src/provider/sdk/openai-compatible/src/responses/openai-config.ts +0 -18
- package/src/provider/sdk/openai-compatible/src/responses/openai-error.ts +0 -22
- package/src/provider/sdk/openai-compatible/src/responses/openai-responses-api-types.ts +0 -207
- package/src/provider/sdk/openai-compatible/src/responses/openai-responses-language-model.ts +0 -1732
- package/src/provider/sdk/openai-compatible/src/responses/openai-responses-prepare-tools.ts +0 -177
- package/src/provider/sdk/openai-compatible/src/responses/openai-responses-settings.ts +0 -1
- package/src/provider/sdk/openai-compatible/src/responses/tool/code-interpreter.ts +0 -88
- package/src/provider/sdk/openai-compatible/src/responses/tool/file-search.ts +0 -128
- package/src/provider/sdk/openai-compatible/src/responses/tool/image-generation.ts +0 -115
- package/src/provider/sdk/openai-compatible/src/responses/tool/local-shell.ts +0 -65
- package/src/provider/sdk/openai-compatible/src/responses/tool/web-search-preview.ts +0 -104
- package/src/provider/sdk/openai-compatible/src/responses/tool/web-search.ts +0 -103
- package/src/provider/transform.ts +0 -724
- package/src/pty/index.ts +0 -229
- package/src/question/index.ts +0 -171
- package/src/scheduler/index.ts +0 -61
- package/src/server/error.ts +0 -36
- package/src/server/mdns.ts +0 -59
- package/src/server/routes/config.ts +0 -92
- package/src/server/routes/experimental.ts +0 -157
- package/src/server/routes/file.ts +0 -197
- package/src/server/routes/global.ts +0 -135
- package/src/server/routes/mcp.ts +0 -225
- package/src/server/routes/permission.ts +0 -68
- package/src/server/routes/project.ts +0 -82
- package/src/server/routes/provider.ts +0 -165
- package/src/server/routes/pty.ts +0 -169
- package/src/server/routes/question.ts +0 -98
- package/src/server/routes/session.ts +0 -935
- package/src/server/routes/tui.ts +0 -379
- package/src/server/server.ts +0 -578
- package/src/session/compaction.ts +0 -225
- package/src/session/index.ts +0 -488
- package/src/session/llm.ts +0 -279
- package/src/session/message-v2.ts +0 -702
- package/src/session/message.ts +0 -189
- package/src/session/processor.ts +0 -406
- package/src/session/prompt/anthropic-20250930.txt +0 -166
- package/src/session/prompt/anthropic.txt +0 -105
- package/src/session/prompt/anthropic_spoof.txt +0 -1
- package/src/session/prompt/beast.txt +0 -147
- package/src/session/prompt/build-switch.txt +0 -5
- package/src/session/prompt/codex.txt +0 -73
- package/src/session/prompt/codex_header.txt +0 -72
- package/src/session/prompt/copilot-gpt-5.txt +0 -143
- package/src/session/prompt/gemini.txt +0 -155
- package/src/session/prompt/max-steps.txt +0 -16
- package/src/session/prompt/plan-reminder-anthropic.txt +0 -67
- package/src/session/prompt/plan.txt +0 -26
- package/src/session/prompt/qwen.txt +0 -109
- package/src/session/prompt.ts +0 -1805
- package/src/session/retry.ts +0 -90
- package/src/session/revert.ts +0 -108
- package/src/session/status.ts +0 -76
- package/src/session/summary.ts +0 -150
- package/src/session/system.ts +0 -138
- package/src/session/todo.ts +0 -37
- package/src/share/share-next.ts +0 -194
- package/src/share/share.ts +0 -87
- package/src/shell/shell.ts +0 -67
- package/src/skill/index.ts +0 -1
- package/src/skill/skill.ts +0 -136
- package/src/snapshot/index.ts +0 -236
- package/src/storage/storage.ts +0 -227
- package/src/tool/apply_patch.ts +0 -277
- package/src/tool/apply_patch.txt +0 -1
- package/src/tool/bash.ts +0 -258
- package/src/tool/bash.txt +0 -115
- package/src/tool/batch.ts +0 -175
- package/src/tool/batch.txt +0 -24
- package/src/tool/codesearch.ts +0 -132
- package/src/tool/codesearch.txt +0 -12
- package/src/tool/edit.ts +0 -645
- package/src/tool/edit.txt +0 -10
- package/src/tool/external-directory.ts +0 -32
- package/src/tool/glob.ts +0 -77
- package/src/tool/glob.txt +0 -6
- package/src/tool/grep.ts +0 -154
- package/src/tool/grep.txt +0 -8
- package/src/tool/invalid.ts +0 -17
- package/src/tool/ls.ts +0 -121
- package/src/tool/ls.txt +0 -1
- package/src/tool/lsp.ts +0 -96
- package/src/tool/lsp.txt +0 -19
- package/src/tool/multiedit.ts +0 -46
- package/src/tool/multiedit.txt +0 -41
- package/src/tool/plan-enter.txt +0 -14
- package/src/tool/plan-exit.txt +0 -13
- package/src/tool/plan.ts +0 -130
- package/src/tool/question.ts +0 -33
- package/src/tool/question.txt +0 -10
- package/src/tool/read.ts +0 -202
- package/src/tool/read.txt +0 -12
- package/src/tool/registry.ts +0 -158
- package/src/tool/skill.ts +0 -75
- package/src/tool/task.ts +0 -188
- package/src/tool/task.txt +0 -60
- package/src/tool/todo.ts +0 -53
- package/src/tool/todoread.txt +0 -14
- package/src/tool/todowrite.txt +0 -167
- package/src/tool/tool.ts +0 -88
- package/src/tool/truncation.ts +0 -106
- package/src/tool/webfetch.ts +0 -182
- package/src/tool/webfetch.txt +0 -13
- package/src/tool/websearch.ts +0 -150
- package/src/tool/websearch.txt +0 -14
- package/src/tool/write.ts +0 -80
- package/src/tool/write.txt +0 -8
- package/src/util/archive.ts +0 -16
- package/src/util/color.ts +0 -19
- package/src/util/context.ts +0 -25
- package/src/util/defer.ts +0 -12
- package/src/util/eventloop.ts +0 -20
- package/src/util/filesystem.ts +0 -93
- package/src/util/fn.ts +0 -11
- package/src/util/format.ts +0 -20
- package/src/util/iife.ts +0 -3
- package/src/util/keybind.ts +0 -103
- package/src/util/lazy.ts +0 -18
- package/src/util/locale.ts +0 -81
- package/src/util/lock.ts +0 -98
- package/src/util/log.ts +0 -180
- package/src/util/queue.ts +0 -32
- package/src/util/rpc.ts +0 -66
- package/src/util/scrap.ts +0 -10
- package/src/util/signal.ts +0 -12
- package/src/util/timeout.ts +0 -14
- package/src/util/token.ts +0 -7
- package/src/util/wildcard.ts +0 -56
- package/src/worktree/index.ts +0 -217
- package/sst-env.d.ts +0 -9
- package/test/acp/event-subscription.test.ts +0 -436
- package/test/acp/system-prompt.test.ts +0 -262
- package/test/agent/agent.test.ts +0 -638
- package/test/bun.test.ts +0 -53
- package/test/cli/github-action.test.ts +0 -129
- package/test/cli/github-remote.test.ts +0 -80
- package/test/cli/tui/transcript.test.ts +0 -297
- package/test/config/agent-color.test.ts +0 -66
- package/test/config/config.test.ts +0 -1414
- package/test/config/fixtures/empty-frontmatter.md +0 -4
- package/test/config/fixtures/frontmatter.md +0 -28
- package/test/config/fixtures/no-frontmatter.md +0 -1
- package/test/config/markdown.test.ts +0 -192
- package/test/file/ignore.test.ts +0 -10
- package/test/file/path-traversal.test.ts +0 -198
- package/test/fixture/fixture.ts +0 -45
- package/test/fixture/lsp/fake-lsp-server.js +0 -77
- package/test/ide/ide.test.ts +0 -82
- package/test/keybind.test.ts +0 -421
- package/test/lsp/client.test.ts +0 -95
- package/test/mcp/headers.test.ts +0 -153
- package/test/mcp/oauth-browser.test.ts +0 -261
- package/test/patch/patch.test.ts +0 -348
- package/test/permission/arity.test.ts +0 -33
- package/test/permission/next.test.ts +0 -652
- package/test/permission-task.test.ts +0 -319
- package/test/plugin/codex.test.ts +0 -123
- package/test/preload.ts +0 -65
- package/test/project/project.test.ts +0 -120
- package/test/provider/amazon-bedrock.test.ts +0 -268
- package/test/provider/gitlab-duo.test.ts +0 -286
- package/test/provider/provider.test.ts +0 -2149
- package/test/provider/transform.test.ts +0 -1596
- package/test/question/question.test.ts +0 -300
- package/test/scheduler.test.ts +0 -73
- package/test/server/session-list.test.ts +0 -39
- package/test/server/session-select.test.ts +0 -78
- package/test/session/compaction.test.ts +0 -293
- package/test/session/llm.test.ts +0 -90
- package/test/session/message-v2.test.ts +0 -662
- package/test/session/retry.test.ts +0 -131
- package/test/session/revert-compact.test.ts +0 -285
- package/test/session/session.test.ts +0 -71
- package/test/skill/skill.test.ts +0 -185
- package/test/snapshot/snapshot.test.ts +0 -939
- package/test/tool/__snapshots__/tool.test.ts.snap +0 -9
- package/test/tool/apply_patch.test.ts +0 -515
- package/test/tool/bash.test.ts +0 -320
- package/test/tool/external-directory.test.ts +0 -126
- package/test/tool/fixtures/large-image.png +0 -0
- package/test/tool/fixtures/models-api.json +0 -33453
- package/test/tool/grep.test.ts +0 -109
- package/test/tool/question.test.ts +0 -105
- package/test/tool/read.test.ts +0 -332
- package/test/tool/registry.test.ts +0 -76
- package/test/tool/truncation.test.ts +0 -159
- package/test/util/filesystem.test.ts +0 -39
- package/test/util/format.test.ts +0 -59
- package/test/util/iife.test.ts +0 -36
- package/test/util/lazy.test.ts +0 -50
- package/test/util/lock.test.ts +0 -72
- package/test/util/timeout.test.ts +0 -21
- package/test/util/wildcard.test.ts +0 -75
- package/tsconfig.json +0 -16
package/test/tool/grep.test.ts
DELETED
|
@@ -1,109 +0,0 @@
|
|
|
1
|
-
import { describe, expect, test } from "bun:test"
|
|
2
|
-
import path from "path"
|
|
3
|
-
import { GrepTool } from "../../src/tool/grep"
|
|
4
|
-
import { Instance } from "../../src/project/instance"
|
|
5
|
-
import { tmpdir } from "../fixture/fixture"
|
|
6
|
-
|
|
7
|
-
const ctx = {
|
|
8
|
-
sessionID: "test",
|
|
9
|
-
messageID: "",
|
|
10
|
-
callID: "",
|
|
11
|
-
agent: "build",
|
|
12
|
-
abort: AbortSignal.any([]),
|
|
13
|
-
metadata: () => {},
|
|
14
|
-
ask: async () => {},
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
const projectRoot = path.join(__dirname, "../..")
|
|
18
|
-
|
|
19
|
-
describe("tool.grep", () => {
|
|
20
|
-
test("basic search", async () => {
|
|
21
|
-
await Instance.provide({
|
|
22
|
-
directory: projectRoot,
|
|
23
|
-
fn: async () => {
|
|
24
|
-
const grep = await GrepTool.init()
|
|
25
|
-
const result = await grep.execute(
|
|
26
|
-
{
|
|
27
|
-
pattern: "export",
|
|
28
|
-
path: path.join(projectRoot, "src/tool"),
|
|
29
|
-
include: "*.ts",
|
|
30
|
-
},
|
|
31
|
-
ctx,
|
|
32
|
-
)
|
|
33
|
-
expect(result.metadata.matches).toBeGreaterThan(0)
|
|
34
|
-
expect(result.output).toContain("Found")
|
|
35
|
-
},
|
|
36
|
-
})
|
|
37
|
-
})
|
|
38
|
-
|
|
39
|
-
test("no matches returns correct output", async () => {
|
|
40
|
-
await using tmp = await tmpdir({
|
|
41
|
-
init: async (dir) => {
|
|
42
|
-
await Bun.write(path.join(dir, "test.txt"), "hello world")
|
|
43
|
-
},
|
|
44
|
-
})
|
|
45
|
-
await Instance.provide({
|
|
46
|
-
directory: tmp.path,
|
|
47
|
-
fn: async () => {
|
|
48
|
-
const grep = await GrepTool.init()
|
|
49
|
-
const result = await grep.execute(
|
|
50
|
-
{
|
|
51
|
-
pattern: "xyznonexistentpatternxyz123",
|
|
52
|
-
path: tmp.path,
|
|
53
|
-
},
|
|
54
|
-
ctx,
|
|
55
|
-
)
|
|
56
|
-
expect(result.metadata.matches).toBe(0)
|
|
57
|
-
expect(result.output).toBe("No files found")
|
|
58
|
-
},
|
|
59
|
-
})
|
|
60
|
-
})
|
|
61
|
-
|
|
62
|
-
test("handles CRLF line endings in output", async () => {
|
|
63
|
-
// This test verifies the regex split handles both \n and \r\n
|
|
64
|
-
await using tmp = await tmpdir({
|
|
65
|
-
init: async (dir) => {
|
|
66
|
-
// Create a test file with content
|
|
67
|
-
await Bun.write(path.join(dir, "test.txt"), "line1\nline2\nline3")
|
|
68
|
-
},
|
|
69
|
-
})
|
|
70
|
-
await Instance.provide({
|
|
71
|
-
directory: tmp.path,
|
|
72
|
-
fn: async () => {
|
|
73
|
-
const grep = await GrepTool.init()
|
|
74
|
-
const result = await grep.execute(
|
|
75
|
-
{
|
|
76
|
-
pattern: "line",
|
|
77
|
-
path: tmp.path,
|
|
78
|
-
},
|
|
79
|
-
ctx,
|
|
80
|
-
)
|
|
81
|
-
expect(result.metadata.matches).toBeGreaterThan(0)
|
|
82
|
-
},
|
|
83
|
-
})
|
|
84
|
-
})
|
|
85
|
-
})
|
|
86
|
-
|
|
87
|
-
describe("CRLF regex handling", () => {
|
|
88
|
-
test("regex correctly splits Unix line endings", () => {
|
|
89
|
-
const unixOutput = "file1.txt|1|content1\nfile2.txt|2|content2\nfile3.txt|3|content3"
|
|
90
|
-
const lines = unixOutput.trim().split(/\r?\n/)
|
|
91
|
-
expect(lines.length).toBe(3)
|
|
92
|
-
expect(lines[0]).toBe("file1.txt|1|content1")
|
|
93
|
-
expect(lines[2]).toBe("file3.txt|3|content3")
|
|
94
|
-
})
|
|
95
|
-
|
|
96
|
-
test("regex correctly splits Windows CRLF line endings", () => {
|
|
97
|
-
const windowsOutput = "file1.txt|1|content1\r\nfile2.txt|2|content2\r\nfile3.txt|3|content3"
|
|
98
|
-
const lines = windowsOutput.trim().split(/\r?\n/)
|
|
99
|
-
expect(lines.length).toBe(3)
|
|
100
|
-
expect(lines[0]).toBe("file1.txt|1|content1")
|
|
101
|
-
expect(lines[2]).toBe("file3.txt|3|content3")
|
|
102
|
-
})
|
|
103
|
-
|
|
104
|
-
test("regex handles mixed line endings", () => {
|
|
105
|
-
const mixedOutput = "file1.txt|1|content1\nfile2.txt|2|content2\r\nfile3.txt|3|content3"
|
|
106
|
-
const lines = mixedOutput.trim().split(/\r?\n/)
|
|
107
|
-
expect(lines.length).toBe(3)
|
|
108
|
-
})
|
|
109
|
-
})
|
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
import { describe, expect, test, spyOn, beforeEach, afterEach } from "bun:test"
|
|
2
|
-
import { z } from "zod"
|
|
3
|
-
import { QuestionTool } from "../../src/tool/question"
|
|
4
|
-
import * as QuestionModule from "../../src/question"
|
|
5
|
-
|
|
6
|
-
const ctx = {
|
|
7
|
-
sessionID: "test-session",
|
|
8
|
-
messageID: "test-message",
|
|
9
|
-
callID: "test-call",
|
|
10
|
-
agent: "test-agent",
|
|
11
|
-
abort: AbortSignal.any([]),
|
|
12
|
-
metadata: () => {},
|
|
13
|
-
ask: async () => {},
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
describe("tool.question", () => {
|
|
17
|
-
let askSpy: any
|
|
18
|
-
|
|
19
|
-
beforeEach(() => {
|
|
20
|
-
askSpy = spyOn(QuestionModule.Question, "ask").mockImplementation(async () => {
|
|
21
|
-
return []
|
|
22
|
-
})
|
|
23
|
-
})
|
|
24
|
-
|
|
25
|
-
afterEach(() => {
|
|
26
|
-
askSpy.mockRestore()
|
|
27
|
-
})
|
|
28
|
-
|
|
29
|
-
test("should successfully execute with valid question parameters", async () => {
|
|
30
|
-
const tool = await QuestionTool.init()
|
|
31
|
-
const questions = [
|
|
32
|
-
{
|
|
33
|
-
question: "What is your favorite color?",
|
|
34
|
-
header: "Color",
|
|
35
|
-
options: [
|
|
36
|
-
{ label: "Red", description: "The color of passion" },
|
|
37
|
-
{ label: "Blue", description: "The color of sky" },
|
|
38
|
-
],
|
|
39
|
-
multiple: false,
|
|
40
|
-
},
|
|
41
|
-
]
|
|
42
|
-
|
|
43
|
-
askSpy.mockResolvedValueOnce([["Red"]])
|
|
44
|
-
|
|
45
|
-
const result = await tool.execute({ questions }, ctx)
|
|
46
|
-
expect(askSpy).toHaveBeenCalledTimes(1)
|
|
47
|
-
expect(result.title).toBe("Asked 1 question")
|
|
48
|
-
})
|
|
49
|
-
|
|
50
|
-
test("should now pass with a header longer than 12 but less than 30 chars", async () => {
|
|
51
|
-
const tool = await QuestionTool.init()
|
|
52
|
-
const questions = [
|
|
53
|
-
{
|
|
54
|
-
question: "What is your favorite animal?",
|
|
55
|
-
header: "This Header is Over 12",
|
|
56
|
-
options: [{ label: "Dog", description: "Man's best friend" }],
|
|
57
|
-
},
|
|
58
|
-
]
|
|
59
|
-
|
|
60
|
-
askSpy.mockResolvedValueOnce([["Dog"]])
|
|
61
|
-
|
|
62
|
-
const result = await tool.execute({ questions }, ctx)
|
|
63
|
-
expect(result.output).toContain(`"What is your favorite animal?"="Dog"`)
|
|
64
|
-
})
|
|
65
|
-
|
|
66
|
-
test("should throw an Error for header exceeding 30 characters", async () => {
|
|
67
|
-
const tool = await QuestionTool.init()
|
|
68
|
-
const questions = [
|
|
69
|
-
{
|
|
70
|
-
question: "What is your favorite animal?",
|
|
71
|
-
header: "This Header is Definitely More Than Thirty Characters Long",
|
|
72
|
-
options: [{ label: "Dog", description: "Man's best friend" }],
|
|
73
|
-
},
|
|
74
|
-
]
|
|
75
|
-
try {
|
|
76
|
-
await tool.execute({ questions }, ctx)
|
|
77
|
-
// If it reaches here, the test should fail
|
|
78
|
-
expect(true).toBe(false)
|
|
79
|
-
} catch (e: any) {
|
|
80
|
-
expect(e).toBeInstanceOf(Error)
|
|
81
|
-
expect(e.cause).toBeInstanceOf(z.ZodError)
|
|
82
|
-
}
|
|
83
|
-
})
|
|
84
|
-
|
|
85
|
-
test("should throw an Error for label exceeding 30 characters", async () => {
|
|
86
|
-
const tool = await QuestionTool.init()
|
|
87
|
-
const questions = [
|
|
88
|
-
{
|
|
89
|
-
question: "A question with a very long label",
|
|
90
|
-
header: "Long Label",
|
|
91
|
-
options: [
|
|
92
|
-
{ label: "This is a very, very, very long label that will exceed the limit", description: "A description" },
|
|
93
|
-
],
|
|
94
|
-
},
|
|
95
|
-
]
|
|
96
|
-
try {
|
|
97
|
-
await tool.execute({ questions }, ctx)
|
|
98
|
-
// If it reaches here, the test should fail
|
|
99
|
-
expect(true).toBe(false)
|
|
100
|
-
} catch (e: any) {
|
|
101
|
-
expect(e).toBeInstanceOf(Error)
|
|
102
|
-
expect(e.cause).toBeInstanceOf(z.ZodError)
|
|
103
|
-
}
|
|
104
|
-
})
|
|
105
|
-
})
|
package/test/tool/read.test.ts
DELETED
|
@@ -1,332 +0,0 @@
|
|
|
1
|
-
import { describe, expect, test } from "bun:test"
|
|
2
|
-
import path from "path"
|
|
3
|
-
import { ReadTool } from "../../src/tool/read"
|
|
4
|
-
import { Instance } from "../../src/project/instance"
|
|
5
|
-
import { tmpdir } from "../fixture/fixture"
|
|
6
|
-
import { PermissionNext } from "../../src/permission/next"
|
|
7
|
-
import { Agent } from "../../src/agent/agent"
|
|
8
|
-
|
|
9
|
-
const FIXTURES_DIR = path.join(import.meta.dir, "fixtures")
|
|
10
|
-
|
|
11
|
-
const ctx = {
|
|
12
|
-
sessionID: "test",
|
|
13
|
-
messageID: "",
|
|
14
|
-
callID: "",
|
|
15
|
-
agent: "build",
|
|
16
|
-
abort: AbortSignal.any([]),
|
|
17
|
-
metadata: () => {},
|
|
18
|
-
ask: async () => {},
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
describe("tool.read external_directory permission", () => {
|
|
22
|
-
test("allows reading absolute path inside project directory", async () => {
|
|
23
|
-
await using tmp = await tmpdir({
|
|
24
|
-
init: async (dir) => {
|
|
25
|
-
await Bun.write(path.join(dir, "test.txt"), "hello world")
|
|
26
|
-
},
|
|
27
|
-
})
|
|
28
|
-
await Instance.provide({
|
|
29
|
-
directory: tmp.path,
|
|
30
|
-
fn: async () => {
|
|
31
|
-
const read = await ReadTool.init()
|
|
32
|
-
const result = await read.execute({ filePath: path.join(tmp.path, "test.txt") }, ctx)
|
|
33
|
-
expect(result.output).toContain("hello world")
|
|
34
|
-
},
|
|
35
|
-
})
|
|
36
|
-
})
|
|
37
|
-
|
|
38
|
-
test("allows reading file in subdirectory inside project directory", async () => {
|
|
39
|
-
await using tmp = await tmpdir({
|
|
40
|
-
init: async (dir) => {
|
|
41
|
-
await Bun.write(path.join(dir, "subdir", "test.txt"), "nested content")
|
|
42
|
-
},
|
|
43
|
-
})
|
|
44
|
-
await Instance.provide({
|
|
45
|
-
directory: tmp.path,
|
|
46
|
-
fn: async () => {
|
|
47
|
-
const read = await ReadTool.init()
|
|
48
|
-
const result = await read.execute({ filePath: path.join(tmp.path, "subdir", "test.txt") }, ctx)
|
|
49
|
-
expect(result.output).toContain("nested content")
|
|
50
|
-
},
|
|
51
|
-
})
|
|
52
|
-
})
|
|
53
|
-
|
|
54
|
-
test("asks for external_directory permission when reading absolute path outside project", async () => {
|
|
55
|
-
await using outerTmp = await tmpdir({
|
|
56
|
-
init: async (dir) => {
|
|
57
|
-
await Bun.write(path.join(dir, "secret.txt"), "secret data")
|
|
58
|
-
},
|
|
59
|
-
})
|
|
60
|
-
await using tmp = await tmpdir({ git: true })
|
|
61
|
-
await Instance.provide({
|
|
62
|
-
directory: tmp.path,
|
|
63
|
-
fn: async () => {
|
|
64
|
-
const read = await ReadTool.init()
|
|
65
|
-
const requests: Array<Omit<PermissionNext.Request, "id" | "sessionID" | "tool">> = []
|
|
66
|
-
const testCtx = {
|
|
67
|
-
...ctx,
|
|
68
|
-
ask: async (req: Omit<PermissionNext.Request, "id" | "sessionID" | "tool">) => {
|
|
69
|
-
requests.push(req)
|
|
70
|
-
},
|
|
71
|
-
}
|
|
72
|
-
await read.execute({ filePath: path.join(outerTmp.path, "secret.txt") }, testCtx)
|
|
73
|
-
const extDirReq = requests.find((r) => r.permission === "external_directory")
|
|
74
|
-
expect(extDirReq).toBeDefined()
|
|
75
|
-
expect(extDirReq!.patterns.some((p) => p.includes(outerTmp.path))).toBe(true)
|
|
76
|
-
},
|
|
77
|
-
})
|
|
78
|
-
})
|
|
79
|
-
|
|
80
|
-
test("asks for external_directory permission when reading relative path outside project", async () => {
|
|
81
|
-
await using tmp = await tmpdir({ git: true })
|
|
82
|
-
await Instance.provide({
|
|
83
|
-
directory: tmp.path,
|
|
84
|
-
fn: async () => {
|
|
85
|
-
const read = await ReadTool.init()
|
|
86
|
-
const requests: Array<Omit<PermissionNext.Request, "id" | "sessionID" | "tool">> = []
|
|
87
|
-
const testCtx = {
|
|
88
|
-
...ctx,
|
|
89
|
-
ask: async (req: Omit<PermissionNext.Request, "id" | "sessionID" | "tool">) => {
|
|
90
|
-
requests.push(req)
|
|
91
|
-
},
|
|
92
|
-
}
|
|
93
|
-
// This will fail because file doesn't exist, but we can check if permission was asked
|
|
94
|
-
await read.execute({ filePath: "../outside.txt" }, testCtx).catch(() => {})
|
|
95
|
-
const extDirReq = requests.find((r) => r.permission === "external_directory")
|
|
96
|
-
expect(extDirReq).toBeDefined()
|
|
97
|
-
},
|
|
98
|
-
})
|
|
99
|
-
})
|
|
100
|
-
|
|
101
|
-
test("does not ask for external_directory permission when reading inside project", async () => {
|
|
102
|
-
await using tmp = await tmpdir({
|
|
103
|
-
git: true,
|
|
104
|
-
init: async (dir) => {
|
|
105
|
-
await Bun.write(path.join(dir, "internal.txt"), "internal content")
|
|
106
|
-
},
|
|
107
|
-
})
|
|
108
|
-
await Instance.provide({
|
|
109
|
-
directory: tmp.path,
|
|
110
|
-
fn: async () => {
|
|
111
|
-
const read = await ReadTool.init()
|
|
112
|
-
const requests: Array<Omit<PermissionNext.Request, "id" | "sessionID" | "tool">> = []
|
|
113
|
-
const testCtx = {
|
|
114
|
-
...ctx,
|
|
115
|
-
ask: async (req: Omit<PermissionNext.Request, "id" | "sessionID" | "tool">) => {
|
|
116
|
-
requests.push(req)
|
|
117
|
-
},
|
|
118
|
-
}
|
|
119
|
-
await read.execute({ filePath: path.join(tmp.path, "internal.txt") }, testCtx)
|
|
120
|
-
const extDirReq = requests.find((r) => r.permission === "external_directory")
|
|
121
|
-
expect(extDirReq).toBeUndefined()
|
|
122
|
-
},
|
|
123
|
-
})
|
|
124
|
-
})
|
|
125
|
-
})
|
|
126
|
-
|
|
127
|
-
describe("tool.read env file permissions", () => {
|
|
128
|
-
const cases: [string, boolean][] = [
|
|
129
|
-
[".env", true],
|
|
130
|
-
[".env.local", true],
|
|
131
|
-
[".env.production", true],
|
|
132
|
-
[".env.development.local", true],
|
|
133
|
-
[".env.example", false],
|
|
134
|
-
[".envrc", false],
|
|
135
|
-
["environment.ts", false],
|
|
136
|
-
]
|
|
137
|
-
|
|
138
|
-
describe.each(["build", "plan"])("agent=%s", (agentName) => {
|
|
139
|
-
test.each(cases)("%s asks=%s", async (filename, shouldAsk) => {
|
|
140
|
-
await using tmp = await tmpdir({
|
|
141
|
-
init: (dir) => Bun.write(path.join(dir, filename), "content"),
|
|
142
|
-
})
|
|
143
|
-
await Instance.provide({
|
|
144
|
-
directory: tmp.path,
|
|
145
|
-
fn: async () => {
|
|
146
|
-
const agent = await Agent.get(agentName)
|
|
147
|
-
let askedForEnv = false
|
|
148
|
-
const ctxWithPermissions = {
|
|
149
|
-
...ctx,
|
|
150
|
-
ask: async (req: Omit<PermissionNext.Request, "id" | "sessionID" | "tool">) => {
|
|
151
|
-
for (const pattern of req.patterns) {
|
|
152
|
-
const rule = PermissionNext.evaluate(req.permission, pattern, agent.permission)
|
|
153
|
-
if (rule.action === "ask" && req.permission === "read") {
|
|
154
|
-
askedForEnv = true
|
|
155
|
-
}
|
|
156
|
-
if (rule.action === "deny") {
|
|
157
|
-
throw new PermissionNext.DeniedError(agent.permission)
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
},
|
|
161
|
-
}
|
|
162
|
-
const read = await ReadTool.init()
|
|
163
|
-
await read.execute({ filePath: path.join(tmp.path, filename) }, ctxWithPermissions)
|
|
164
|
-
expect(askedForEnv).toBe(shouldAsk)
|
|
165
|
-
},
|
|
166
|
-
})
|
|
167
|
-
})
|
|
168
|
-
})
|
|
169
|
-
})
|
|
170
|
-
|
|
171
|
-
describe("tool.read truncation", () => {
|
|
172
|
-
test("truncates large file by bytes and sets truncated metadata", async () => {
|
|
173
|
-
await using tmp = await tmpdir({
|
|
174
|
-
init: async (dir) => {
|
|
175
|
-
const content = await Bun.file(path.join(FIXTURES_DIR, "models-api.json")).text()
|
|
176
|
-
await Bun.write(path.join(dir, "large.json"), content)
|
|
177
|
-
},
|
|
178
|
-
})
|
|
179
|
-
await Instance.provide({
|
|
180
|
-
directory: tmp.path,
|
|
181
|
-
fn: async () => {
|
|
182
|
-
const read = await ReadTool.init()
|
|
183
|
-
const result = await read.execute({ filePath: path.join(tmp.path, "large.json") }, ctx)
|
|
184
|
-
expect(result.metadata.truncated).toBe(true)
|
|
185
|
-
expect(result.output).toContain("Output truncated at")
|
|
186
|
-
expect(result.output).toContain("bytes")
|
|
187
|
-
},
|
|
188
|
-
})
|
|
189
|
-
})
|
|
190
|
-
|
|
191
|
-
test("truncates by line count when limit is specified", async () => {
|
|
192
|
-
await using tmp = await tmpdir({
|
|
193
|
-
init: async (dir) => {
|
|
194
|
-
const lines = Array.from({ length: 100 }, (_, i) => `line${i}`).join("\n")
|
|
195
|
-
await Bun.write(path.join(dir, "many-lines.txt"), lines)
|
|
196
|
-
},
|
|
197
|
-
})
|
|
198
|
-
await Instance.provide({
|
|
199
|
-
directory: tmp.path,
|
|
200
|
-
fn: async () => {
|
|
201
|
-
const read = await ReadTool.init()
|
|
202
|
-
const result = await read.execute({ filePath: path.join(tmp.path, "many-lines.txt"), limit: 10 }, ctx)
|
|
203
|
-
expect(result.metadata.truncated).toBe(true)
|
|
204
|
-
expect(result.output).toContain("File has more lines")
|
|
205
|
-
expect(result.output).toContain("line0")
|
|
206
|
-
expect(result.output).toContain("line9")
|
|
207
|
-
expect(result.output).not.toContain("line10")
|
|
208
|
-
},
|
|
209
|
-
})
|
|
210
|
-
})
|
|
211
|
-
|
|
212
|
-
test("does not truncate small file", async () => {
|
|
213
|
-
await using tmp = await tmpdir({
|
|
214
|
-
init: async (dir) => {
|
|
215
|
-
await Bun.write(path.join(dir, "small.txt"), "hello world")
|
|
216
|
-
},
|
|
217
|
-
})
|
|
218
|
-
await Instance.provide({
|
|
219
|
-
directory: tmp.path,
|
|
220
|
-
fn: async () => {
|
|
221
|
-
const read = await ReadTool.init()
|
|
222
|
-
const result = await read.execute({ filePath: path.join(tmp.path, "small.txt") }, ctx)
|
|
223
|
-
expect(result.metadata.truncated).toBe(false)
|
|
224
|
-
expect(result.output).toContain("End of file")
|
|
225
|
-
},
|
|
226
|
-
})
|
|
227
|
-
})
|
|
228
|
-
|
|
229
|
-
test("respects offset parameter", async () => {
|
|
230
|
-
await using tmp = await tmpdir({
|
|
231
|
-
init: async (dir) => {
|
|
232
|
-
const lines = Array.from({ length: 20 }, (_, i) => `line${i}`).join("\n")
|
|
233
|
-
await Bun.write(path.join(dir, "offset.txt"), lines)
|
|
234
|
-
},
|
|
235
|
-
})
|
|
236
|
-
await Instance.provide({
|
|
237
|
-
directory: tmp.path,
|
|
238
|
-
fn: async () => {
|
|
239
|
-
const read = await ReadTool.init()
|
|
240
|
-
const result = await read.execute({ filePath: path.join(tmp.path, "offset.txt"), offset: 10, limit: 5 }, ctx)
|
|
241
|
-
expect(result.output).toContain("line10")
|
|
242
|
-
expect(result.output).toContain("line14")
|
|
243
|
-
expect(result.output).not.toContain("line0")
|
|
244
|
-
expect(result.output).not.toContain("line15")
|
|
245
|
-
},
|
|
246
|
-
})
|
|
247
|
-
})
|
|
248
|
-
|
|
249
|
-
test("truncates long lines", async () => {
|
|
250
|
-
await using tmp = await tmpdir({
|
|
251
|
-
init: async (dir) => {
|
|
252
|
-
const longLine = "x".repeat(3000)
|
|
253
|
-
await Bun.write(path.join(dir, "long-line.txt"), longLine)
|
|
254
|
-
},
|
|
255
|
-
})
|
|
256
|
-
await Instance.provide({
|
|
257
|
-
directory: tmp.path,
|
|
258
|
-
fn: async () => {
|
|
259
|
-
const read = await ReadTool.init()
|
|
260
|
-
const result = await read.execute({ filePath: path.join(tmp.path, "long-line.txt") }, ctx)
|
|
261
|
-
expect(result.output).toContain("...")
|
|
262
|
-
expect(result.output.length).toBeLessThan(3000)
|
|
263
|
-
},
|
|
264
|
-
})
|
|
265
|
-
})
|
|
266
|
-
|
|
267
|
-
test("image files set truncated to false", async () => {
|
|
268
|
-
await using tmp = await tmpdir({
|
|
269
|
-
init: async (dir) => {
|
|
270
|
-
// 1x1 red PNG
|
|
271
|
-
const png = Buffer.from(
|
|
272
|
-
"iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8DwHwAFBQIAX8jx0gAAAABJRU5ErkJggg==",
|
|
273
|
-
"base64",
|
|
274
|
-
)
|
|
275
|
-
await Bun.write(path.join(dir, "image.png"), png)
|
|
276
|
-
},
|
|
277
|
-
})
|
|
278
|
-
await Instance.provide({
|
|
279
|
-
directory: tmp.path,
|
|
280
|
-
fn: async () => {
|
|
281
|
-
const read = await ReadTool.init()
|
|
282
|
-
const result = await read.execute({ filePath: path.join(tmp.path, "image.png") }, ctx)
|
|
283
|
-
expect(result.metadata.truncated).toBe(false)
|
|
284
|
-
expect(result.attachments).toBeDefined()
|
|
285
|
-
expect(result.attachments?.length).toBe(1)
|
|
286
|
-
},
|
|
287
|
-
})
|
|
288
|
-
})
|
|
289
|
-
|
|
290
|
-
test("large image files are properly attached without error", async () => {
|
|
291
|
-
await Instance.provide({
|
|
292
|
-
directory: FIXTURES_DIR,
|
|
293
|
-
fn: async () => {
|
|
294
|
-
const read = await ReadTool.init()
|
|
295
|
-
const result = await read.execute({ filePath: path.join(FIXTURES_DIR, "large-image.png") }, ctx)
|
|
296
|
-
expect(result.metadata.truncated).toBe(false)
|
|
297
|
-
expect(result.attachments).toBeDefined()
|
|
298
|
-
expect(result.attachments?.length).toBe(1)
|
|
299
|
-
expect(result.attachments?.[0].type).toBe("file")
|
|
300
|
-
},
|
|
301
|
-
})
|
|
302
|
-
})
|
|
303
|
-
|
|
304
|
-
test(".fbs files (FlatBuffers schema) are read as text, not images", async () => {
|
|
305
|
-
await using tmp = await tmpdir({
|
|
306
|
-
init: async (dir) => {
|
|
307
|
-
// FlatBuffers schema content
|
|
308
|
-
const fbsContent = `namespace MyGame;
|
|
309
|
-
|
|
310
|
-
table Monster {
|
|
311
|
-
pos:Vec3;
|
|
312
|
-
name:string;
|
|
313
|
-
inventory:[ubyte];
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
root_type Monster;`
|
|
317
|
-
await Bun.write(path.join(dir, "schema.fbs"), fbsContent)
|
|
318
|
-
},
|
|
319
|
-
})
|
|
320
|
-
await Instance.provide({
|
|
321
|
-
directory: tmp.path,
|
|
322
|
-
fn: async () => {
|
|
323
|
-
const read = await ReadTool.init()
|
|
324
|
-
const result = await read.execute({ filePath: path.join(tmp.path, "schema.fbs") }, ctx)
|
|
325
|
-
// Should be read as text, not as image
|
|
326
|
-
expect(result.attachments).toBeUndefined()
|
|
327
|
-
expect(result.output).toContain("namespace MyGame")
|
|
328
|
-
expect(result.output).toContain("table Monster")
|
|
329
|
-
},
|
|
330
|
-
})
|
|
331
|
-
})
|
|
332
|
-
})
|
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
import { describe, expect, test } from "bun:test"
|
|
2
|
-
import path from "path"
|
|
3
|
-
import fs from "fs/promises"
|
|
4
|
-
import { tmpdir } from "../fixture/fixture"
|
|
5
|
-
import { Instance } from "../../src/project/instance"
|
|
6
|
-
import { ToolRegistry } from "../../src/tool/registry"
|
|
7
|
-
|
|
8
|
-
describe("tool.registry", () => {
|
|
9
|
-
test("loads tools from .opencode/tool (singular)", async () => {
|
|
10
|
-
await using tmp = await tmpdir({
|
|
11
|
-
init: async (dir) => {
|
|
12
|
-
const opencodeDir = path.join(dir, ".opencode")
|
|
13
|
-
await fs.mkdir(opencodeDir, { recursive: true })
|
|
14
|
-
|
|
15
|
-
const toolDir = path.join(opencodeDir, "tool")
|
|
16
|
-
await fs.mkdir(toolDir, { recursive: true })
|
|
17
|
-
|
|
18
|
-
await Bun.write(
|
|
19
|
-
path.join(toolDir, "hello.ts"),
|
|
20
|
-
[
|
|
21
|
-
"export default {",
|
|
22
|
-
" description: 'hello tool',",
|
|
23
|
-
" args: {},",
|
|
24
|
-
" execute: async () => {",
|
|
25
|
-
" return 'hello world'",
|
|
26
|
-
" },",
|
|
27
|
-
"}",
|
|
28
|
-
"",
|
|
29
|
-
].join("\n"),
|
|
30
|
-
)
|
|
31
|
-
},
|
|
32
|
-
})
|
|
33
|
-
|
|
34
|
-
await Instance.provide({
|
|
35
|
-
directory: tmp.path,
|
|
36
|
-
fn: async () => {
|
|
37
|
-
const ids = await ToolRegistry.ids()
|
|
38
|
-
expect(ids).toContain("hello")
|
|
39
|
-
},
|
|
40
|
-
})
|
|
41
|
-
})
|
|
42
|
-
|
|
43
|
-
test("loads tools from .opencode/tools (plural)", async () => {
|
|
44
|
-
await using tmp = await tmpdir({
|
|
45
|
-
init: async (dir) => {
|
|
46
|
-
const opencodeDir = path.join(dir, ".opencode")
|
|
47
|
-
await fs.mkdir(opencodeDir, { recursive: true })
|
|
48
|
-
|
|
49
|
-
const toolsDir = path.join(opencodeDir, "tools")
|
|
50
|
-
await fs.mkdir(toolsDir, { recursive: true })
|
|
51
|
-
|
|
52
|
-
await Bun.write(
|
|
53
|
-
path.join(toolsDir, "hello.ts"),
|
|
54
|
-
[
|
|
55
|
-
"export default {",
|
|
56
|
-
" description: 'hello tool',",
|
|
57
|
-
" args: {},",
|
|
58
|
-
" execute: async () => {",
|
|
59
|
-
" return 'hello world'",
|
|
60
|
-
" },",
|
|
61
|
-
"}",
|
|
62
|
-
"",
|
|
63
|
-
].join("\n"),
|
|
64
|
-
)
|
|
65
|
-
},
|
|
66
|
-
})
|
|
67
|
-
|
|
68
|
-
await Instance.provide({
|
|
69
|
-
directory: tmp.path,
|
|
70
|
-
fn: async () => {
|
|
71
|
-
const ids = await ToolRegistry.ids()
|
|
72
|
-
expect(ids).toContain("hello")
|
|
73
|
-
},
|
|
74
|
-
})
|
|
75
|
-
})
|
|
76
|
-
})
|