@code0123/opencode-android-arm64 1.1.54 → 1.1.56
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/opencode +3 -1
- package/package.json +1 -80
- package/runtime/highlights-eq9cgrbb.scm +604 -0
- package/runtime/highlights-ghv9g403.scm +205 -0
- package/runtime/highlights-hk7bwhj4.scm +284 -0
- package/runtime/highlights-r812a2qc.scm +150 -0
- package/runtime/highlights-x6tmsnaa.scm +115 -0
- package/runtime/index.js +287124 -0
- package/runtime/injections-73j83es3.scm +27 -0
- package/runtime/parser.worker.js +4081 -0
- package/runtime/tree-sitter-3jzf13jk.wasm +0 -0
- package/runtime/tree-sitter-bash-hq5s6fxb.wasm +0 -0
- package/runtime/tree-sitter-javascript-nd0q4pe9.wasm +0 -0
- package/runtime/tree-sitter-markdown-411r6y9b.wasm +0 -0
- package/runtime/tree-sitter-markdown_inline-j5349f42.wasm +0 -0
- package/runtime/tree-sitter-typescript-zxjzwt75.wasm +0 -0
- package/runtime/tree-sitter-zig-e78zbjpm.wasm +0 -0
- package/runtime/worker.js +208338 -0
- package/parsers-config.ts +0 -253
- package/src/acp/README.md +0 -164
- package/src/acp/agent.ts +0 -1676
- package/src/acp/session.ts +0 -117
- package/src/acp/types.ts +0 -23
- package/src/agent/agent.ts +0 -338
- 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 -44
- package/src/auth/index.ts +0 -70
- package/src/bun/index.ts +0 -137
- package/src/bun/registry.ts +0 -48
- 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 -70
- 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 -167
- 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 -1540
- package/src/cli/cmd/import.ts +0 -147
- 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 -598
- package/src/cli/cmd/serve.ts +0 -20
- package/src/cli/cmd/session.ts +0 -135
- package/src/cli/cmd/stats.ts +0 -426
- package/src/cli/cmd/tui/app.tsx +0 -801
- package/src/cli/cmd/tui/attach.ts +0 -52
- 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 -266
- package/src/cli/cmd/tui/component/dialog-session-list.tsx +0 -108
- package/src/cli/cmd/tui/component/dialog-session-rename.tsx +0 -31
- package/src/cli/cmd/tui/component/dialog-skill.tsx +0 -36
- package/src/cli/cmd/tui/component/dialog-stash.tsx +0 -87
- package/src/cli/cmd/tui/component/dialog-status.tsx +0 -177
- 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 -85
- package/src/cli/cmd/tui/component/prompt/autocomplete.tsx +0 -666
- 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 -1132
- package/src/cli/cmd/tui/component/prompt/stash.tsx +0 -101
- package/src/cli/cmd/tui/component/spinner.tsx +0 -24
- 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 -15
- package/src/cli/cmd/tui/context/directory.ts +0 -13
- package/src/cli/cmd/tui/context/exit.tsx +0 -52
- package/src/cli/cmd/tui/context/helper.tsx +0 -25
- package/src/cli/cmd/tui/context/keybind.tsx +0 -100
- package/src/cli/cmd/tui/context/kv.tsx +0 -52
- package/src/cli/cmd/tui/context/local.tsx +0 -409
- 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 -101
- package/src/cli/cmd/tui/context/sync.tsx +0 -470
- 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 -242
- 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/opencode.json +0 -245
- 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 -142
- package/src/cli/cmd/tui/routes/session/index.tsx +0 -2126
- package/src/cli/cmd/tui/routes/session/permission.tsx +0 -508
- package/src/cli/cmd/tui/routes/session/question.tsx +0 -466
- package/src/cli/cmd/tui/routes/session/sidebar.tsx +0 -313
- package/src/cli/cmd/tui/thread.ts +0 -175
- package/src/cli/cmd/tui/ui/dialog-alert.tsx +0 -68
- package/src/cli/cmd/tui/ui/dialog-confirm.tsx +0 -93
- package/src/cli/cmd/tui/ui/dialog-export-options.tsx +0 -215
- package/src/cli/cmd/tui/ui/dialog-help.tsx +0 -49
- package/src/cli/cmd/tui/ui/dialog-prompt.tsx +0 -88
- package/src/cli/cmd/tui/ui/dialog-select.tsx +0 -399
- 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 -159
- 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/logo.ts +0 -6
- package/src/cli/network.ts +0 -60
- package/src/cli/ui.ts +0 -113
- package/src/cli/upgrade.ts +0 -25
- package/src/command/index.ts +0 -150
- package/src/command/template/initialize.txt +0 -10
- package/src/command/template/review.txt +0 -99
- package/src/config/config.ts +0 -1477
- package/src/config/markdown.ts +0 -98
- package/src/env/index.ts +0 -28
- package/src/file/ignore.ts +0 -83
- package/src/file/index.ts +0 -583
- package/src/file/ripgrep.ts +0 -384
- package/src/file/time.ts +0 -69
- package/src/file/watcher.ts +0 -148
- package/src/flag/flag.ts +0 -93
- package/src/format/formatter.ts +0 -366
- 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 -132
- package/src/mcp/index.ts +0 -934
- 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 -280
- package/src/plugin/codex.ts +0 -624
- package/src/plugin/copilot.ts +0 -327
- package/src/plugin/index.ts +0 -138
- package/src/project/bootstrap.ts +0 -35
- package/src/project/instance.ts +0 -114
- package/src/project/project.ts +0 -371
- package/src/project/state.ts +0 -70
- package/src/project/vcs.ts +0 -76
- package/src/provider/auth.ts +0 -147
- package/src/provider/models-snapshot.ts +0 -38414
- package/src/provider/models.ts +0 -133
- package/src/provider/provider.ts +0 -1262
- package/src/provider/sdk/copilot/README.md +0 -5
- package/src/provider/sdk/copilot/chat/convert-to-openai-compatible-chat-messages.ts +0 -164
- package/src/provider/sdk/copilot/chat/get-response-metadata.ts +0 -15
- package/src/provider/sdk/copilot/chat/map-openai-compatible-finish-reason.ts +0 -17
- package/src/provider/sdk/copilot/chat/openai-compatible-api-types.ts +0 -64
- package/src/provider/sdk/copilot/chat/openai-compatible-chat-language-model.ts +0 -780
- package/src/provider/sdk/copilot/chat/openai-compatible-chat-options.ts +0 -28
- package/src/provider/sdk/copilot/chat/openai-compatible-metadata-extractor.ts +0 -44
- package/src/provider/sdk/copilot/chat/openai-compatible-prepare-tools.ts +0 -87
- package/src/provider/sdk/copilot/copilot-provider.ts +0 -100
- package/src/provider/sdk/copilot/index.ts +0 -2
- package/src/provider/sdk/copilot/openai-compatible-error.ts +0 -27
- package/src/provider/sdk/copilot/responses/convert-to-openai-responses-input.ts +0 -303
- package/src/provider/sdk/copilot/responses/map-openai-responses-finish-reason.ts +0 -22
- package/src/provider/sdk/copilot/responses/openai-config.ts +0 -18
- package/src/provider/sdk/copilot/responses/openai-error.ts +0 -22
- package/src/provider/sdk/copilot/responses/openai-responses-api-types.ts +0 -207
- package/src/provider/sdk/copilot/responses/openai-responses-language-model.ts +0 -1732
- package/src/provider/sdk/copilot/responses/openai-responses-prepare-tools.ts +0 -177
- package/src/provider/sdk/copilot/responses/openai-responses-settings.ts +0 -1
- package/src/provider/sdk/copilot/responses/tool/code-interpreter.ts +0 -88
- package/src/provider/sdk/copilot/responses/tool/file-search.ts +0 -128
- package/src/provider/sdk/copilot/responses/tool/image-generation.ts +0 -115
- package/src/provider/sdk/copilot/responses/tool/local-shell.ts +0 -65
- package/src/provider/sdk/copilot/responses/tool/web-search-preview.ts +0 -104
- package/src/provider/sdk/copilot/responses/tool/web-search.ts +0 -103
- package/src/provider/transform.ts +0 -828
- package/src/pty/index.ts +0 -250
- package/src/question/index.ts +0 -171
- package/src/scheduler/index.ts +0 -61
- package/src/server/error.ts +0 -36
- package/src/server/event.ts +0 -7
- package/src/server/mdns.ts +0 -60
- package/src/server/routes/config.ts +0 -92
- package/src/server/routes/experimental.ts +0 -208
- package/src/server/routes/file.ts +0 -197
- package/src/server/routes/global.ts +0 -183
- 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 -939
- package/src/server/routes/tui.ts +0 -379
- package/src/server/server.ts +0 -613
- package/src/session/compaction.ts +0 -226
- package/src/session/index.ts +0 -517
- package/src/session/instruction.ts +0 -197
- package/src/session/llm.ts +0 -289
- package/src/session/message-v2.ts +0 -802
- package/src/session/message.ts +0 -189
- package/src/session/processor.ts +0 -407
- package/src/session/prompt/anthropic-20250930.txt +0 -166
- package/src/session/prompt/anthropic.txt +0 -105
- package/src/session/prompt/beast.txt +0 -147
- package/src/session/prompt/build-switch.txt +0 -5
- package/src/session/prompt/codex_header.txt +0 -79
- 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/trinity.txt +0 -97
- package/src/session/prompt.ts +0 -1866
- package/src/session/retry.ts +0 -97
- package/src/session/revert.ts +0 -121
- package/src/session/status.ts +0 -76
- package/src/session/summary.ts +0 -217
- package/src/session/system.ts +0 -54
- package/src/session/todo.ts +0 -37
- package/src/share/share-next.ts +0 -200
- package/src/share/share.ts +0 -92
- package/src/shell/shell.ts +0 -67
- package/src/skill/discovery.ts +0 -97
- package/src/skill/index.ts +0 -1
- package/src/skill/skill.ts +0 -188
- package/src/snapshot/index.ts +0 -255
- package/src/storage/storage.ts +0 -227
- package/src/tool/apply_patch.ts +0 -281
- package/src/tool/apply_patch.txt +0 -33
- package/src/tool/bash.ts +0 -269
- 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 -655
- package/src/tool/edit.txt +0 -10
- package/src/tool/external-directory.ts +0 -32
- package/src/tool/glob.ts +0 -78
- package/src/tool/glob.txt +0 -6
- package/src/tool/grep.ts +0 -147
- 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 -211
- package/src/tool/read.txt +0 -12
- package/src/tool/registry.ts +0 -160
- package/src/tool/skill.ts +0 -123
- package/src/tool/task.ts +0 -165
- 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 -89
- package/src/tool/truncation.ts +0 -106
- package/src/tool/webfetch.ts +0 -186
- 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 -85
- package/src/tool/write.txt +0 -8
- package/src/util/abort.ts +0 -35
- 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/proxied.ts +0 -3
- 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 -574
- package/tsconfig.json +0 -10
package/src/share/share-next.ts
DELETED
|
@@ -1,200 +0,0 @@
|
|
|
1
|
-
import { Bus } from "@/bus"
|
|
2
|
-
import { Config } from "@/config/config"
|
|
3
|
-
import { ulid } from "ulid"
|
|
4
|
-
import { Provider } from "@/provider/provider"
|
|
5
|
-
import { Session } from "@/session"
|
|
6
|
-
import { MessageV2 } from "@/session/message-v2"
|
|
7
|
-
import { Storage } from "@/storage/storage"
|
|
8
|
-
import { Log } from "@/util/log"
|
|
9
|
-
import type * as SDK from "@opencode-ai/sdk/v2"
|
|
10
|
-
|
|
11
|
-
export namespace ShareNext {
|
|
12
|
-
const log = Log.create({ service: "share-next" })
|
|
13
|
-
|
|
14
|
-
export async function url() {
|
|
15
|
-
return Config.get().then((x) => x.enterprise?.url ?? "https://opncd.ai")
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
const disabled = process.env["OPENCODE_DISABLE_SHARE"] === "true" || process.env["OPENCODE_DISABLE_SHARE"] === "1"
|
|
19
|
-
|
|
20
|
-
export async function init() {
|
|
21
|
-
if (disabled) return
|
|
22
|
-
Bus.subscribe(Session.Event.Updated, async (evt) => {
|
|
23
|
-
await sync(evt.properties.info.id, [
|
|
24
|
-
{
|
|
25
|
-
type: "session",
|
|
26
|
-
data: evt.properties.info,
|
|
27
|
-
},
|
|
28
|
-
])
|
|
29
|
-
})
|
|
30
|
-
Bus.subscribe(MessageV2.Event.Updated, async (evt) => {
|
|
31
|
-
await sync(evt.properties.info.sessionID, [
|
|
32
|
-
{
|
|
33
|
-
type: "message",
|
|
34
|
-
data: evt.properties.info,
|
|
35
|
-
},
|
|
36
|
-
])
|
|
37
|
-
if (evt.properties.info.role === "user") {
|
|
38
|
-
await sync(evt.properties.info.sessionID, [
|
|
39
|
-
{
|
|
40
|
-
type: "model",
|
|
41
|
-
data: [
|
|
42
|
-
await Provider.getModel(evt.properties.info.model.providerID, evt.properties.info.model.modelID).then(
|
|
43
|
-
(m) => m,
|
|
44
|
-
),
|
|
45
|
-
],
|
|
46
|
-
},
|
|
47
|
-
])
|
|
48
|
-
}
|
|
49
|
-
})
|
|
50
|
-
Bus.subscribe(MessageV2.Event.PartUpdated, async (evt) => {
|
|
51
|
-
await sync(evt.properties.part.sessionID, [
|
|
52
|
-
{
|
|
53
|
-
type: "part",
|
|
54
|
-
data: evt.properties.part,
|
|
55
|
-
},
|
|
56
|
-
])
|
|
57
|
-
})
|
|
58
|
-
Bus.subscribe(Session.Event.Diff, async (evt) => {
|
|
59
|
-
await sync(evt.properties.sessionID, [
|
|
60
|
-
{
|
|
61
|
-
type: "session_diff",
|
|
62
|
-
data: evt.properties.diff,
|
|
63
|
-
},
|
|
64
|
-
])
|
|
65
|
-
})
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
export async function create(sessionID: string) {
|
|
69
|
-
if (disabled) return { id: "", url: "", secret: "" }
|
|
70
|
-
log.info("creating share", { sessionID })
|
|
71
|
-
const result = await fetch(`${await url()}/api/share`, {
|
|
72
|
-
method: "POST",
|
|
73
|
-
headers: {
|
|
74
|
-
"Content-Type": "application/json",
|
|
75
|
-
},
|
|
76
|
-
body: JSON.stringify({ sessionID: sessionID }),
|
|
77
|
-
})
|
|
78
|
-
.then((x) => x.json())
|
|
79
|
-
.then((x) => x as { id: string; url: string; secret: string })
|
|
80
|
-
await Storage.write(["session_share", sessionID], result)
|
|
81
|
-
fullSync(sessionID)
|
|
82
|
-
return result
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
function get(sessionID: string) {
|
|
86
|
-
return Storage.read<{
|
|
87
|
-
id: string
|
|
88
|
-
secret: string
|
|
89
|
-
url: string
|
|
90
|
-
}>(["session_share", sessionID])
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
type Data =
|
|
94
|
-
| {
|
|
95
|
-
type: "session"
|
|
96
|
-
data: SDK.Session
|
|
97
|
-
}
|
|
98
|
-
| {
|
|
99
|
-
type: "message"
|
|
100
|
-
data: SDK.Message
|
|
101
|
-
}
|
|
102
|
-
| {
|
|
103
|
-
type: "part"
|
|
104
|
-
data: SDK.Part
|
|
105
|
-
}
|
|
106
|
-
| {
|
|
107
|
-
type: "session_diff"
|
|
108
|
-
data: SDK.FileDiff[]
|
|
109
|
-
}
|
|
110
|
-
| {
|
|
111
|
-
type: "model"
|
|
112
|
-
data: SDK.Model[]
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
const queue = new Map<string, { timeout: NodeJS.Timeout; data: Map<string, Data> }>()
|
|
116
|
-
async function sync(sessionID: string, data: Data[]) {
|
|
117
|
-
if (disabled) return
|
|
118
|
-
const existing = queue.get(sessionID)
|
|
119
|
-
if (existing) {
|
|
120
|
-
for (const item of data) {
|
|
121
|
-
existing.data.set("id" in item ? (item.id as string) : ulid(), item)
|
|
122
|
-
}
|
|
123
|
-
return
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
const dataMap = new Map<string, Data>()
|
|
127
|
-
for (const item of data) {
|
|
128
|
-
dataMap.set("id" in item ? (item.id as string) : ulid(), item)
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
const timeout = setTimeout(async () => {
|
|
132
|
-
const queued = queue.get(sessionID)
|
|
133
|
-
if (!queued) return
|
|
134
|
-
queue.delete(sessionID)
|
|
135
|
-
const share = await get(sessionID).catch(() => undefined)
|
|
136
|
-
if (!share) return
|
|
137
|
-
|
|
138
|
-
await fetch(`${await url()}/api/share/${share.id}/sync`, {
|
|
139
|
-
method: "POST",
|
|
140
|
-
headers: {
|
|
141
|
-
"Content-Type": "application/json",
|
|
142
|
-
},
|
|
143
|
-
body: JSON.stringify({
|
|
144
|
-
secret: share.secret,
|
|
145
|
-
data: Array.from(queued.data.values()),
|
|
146
|
-
}),
|
|
147
|
-
})
|
|
148
|
-
}, 1000)
|
|
149
|
-
queue.set(sessionID, { timeout, data: dataMap })
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
export async function remove(sessionID: string) {
|
|
153
|
-
if (disabled) return
|
|
154
|
-
log.info("removing share", { sessionID })
|
|
155
|
-
const share = await get(sessionID)
|
|
156
|
-
if (!share) return
|
|
157
|
-
await fetch(`${await url()}/api/share/${share.id}`, {
|
|
158
|
-
method: "DELETE",
|
|
159
|
-
headers: {
|
|
160
|
-
"Content-Type": "application/json",
|
|
161
|
-
},
|
|
162
|
-
body: JSON.stringify({
|
|
163
|
-
secret: share.secret,
|
|
164
|
-
}),
|
|
165
|
-
})
|
|
166
|
-
await Storage.remove(["session_share", sessionID])
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
async function fullSync(sessionID: string) {
|
|
170
|
-
log.info("full sync", { sessionID })
|
|
171
|
-
const session = await Session.get(sessionID)
|
|
172
|
-
const diffs = await Session.diff(sessionID)
|
|
173
|
-
const messages = await Array.fromAsync(MessageV2.stream(sessionID))
|
|
174
|
-
const models = await Promise.all(
|
|
175
|
-
messages
|
|
176
|
-
.filter((m) => m.info.role === "user")
|
|
177
|
-
.map((m) => (m.info as SDK.UserMessage).model)
|
|
178
|
-
.map((m) => Provider.getModel(m.providerID, m.modelID).then((m) => m)),
|
|
179
|
-
)
|
|
180
|
-
await sync(sessionID, [
|
|
181
|
-
{
|
|
182
|
-
type: "session",
|
|
183
|
-
data: session,
|
|
184
|
-
},
|
|
185
|
-
...messages.map((x) => ({
|
|
186
|
-
type: "message" as const,
|
|
187
|
-
data: x.info,
|
|
188
|
-
})),
|
|
189
|
-
...messages.flatMap((x) => x.parts.map((y) => ({ type: "part" as const, data: y }))),
|
|
190
|
-
{
|
|
191
|
-
type: "session_diff",
|
|
192
|
-
data: diffs,
|
|
193
|
-
},
|
|
194
|
-
{
|
|
195
|
-
type: "model",
|
|
196
|
-
data: models,
|
|
197
|
-
},
|
|
198
|
-
])
|
|
199
|
-
}
|
|
200
|
-
}
|
package/src/share/share.ts
DELETED
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
import { Bus } from "../bus"
|
|
2
|
-
import { Installation } from "../installation"
|
|
3
|
-
import { Session } from "../session"
|
|
4
|
-
import { MessageV2 } from "../session/message-v2"
|
|
5
|
-
import { Log } from "../util/log"
|
|
6
|
-
|
|
7
|
-
export namespace Share {
|
|
8
|
-
const log = Log.create({ service: "share" })
|
|
9
|
-
|
|
10
|
-
let queue: Promise<void> = Promise.resolve()
|
|
11
|
-
const pending = new Map<string, any>()
|
|
12
|
-
|
|
13
|
-
export async function sync(key: string, content: any) {
|
|
14
|
-
if (disabled) return
|
|
15
|
-
const [root, ...splits] = key.split("/")
|
|
16
|
-
if (root !== "session") return
|
|
17
|
-
const [sub, sessionID] = splits
|
|
18
|
-
if (sub === "share") return
|
|
19
|
-
const share = await Session.getShare(sessionID).catch(() => {})
|
|
20
|
-
if (!share) return
|
|
21
|
-
const { secret } = share
|
|
22
|
-
pending.set(key, content)
|
|
23
|
-
queue = queue
|
|
24
|
-
.then(async () => {
|
|
25
|
-
const content = pending.get(key)
|
|
26
|
-
if (content === undefined) return
|
|
27
|
-
pending.delete(key)
|
|
28
|
-
|
|
29
|
-
return fetch(`${URL}/share_sync`, {
|
|
30
|
-
method: "POST",
|
|
31
|
-
body: JSON.stringify({
|
|
32
|
-
sessionID: sessionID,
|
|
33
|
-
secret,
|
|
34
|
-
key: key,
|
|
35
|
-
content,
|
|
36
|
-
}),
|
|
37
|
-
})
|
|
38
|
-
})
|
|
39
|
-
.then((x) => {
|
|
40
|
-
if (x) {
|
|
41
|
-
log.info("synced", {
|
|
42
|
-
key: key,
|
|
43
|
-
status: x.status,
|
|
44
|
-
})
|
|
45
|
-
}
|
|
46
|
-
})
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
export function init() {
|
|
50
|
-
Bus.subscribe(Session.Event.Updated, async (evt) => {
|
|
51
|
-
await sync("session/info/" + evt.properties.info.id, evt.properties.info)
|
|
52
|
-
})
|
|
53
|
-
Bus.subscribe(MessageV2.Event.Updated, async (evt) => {
|
|
54
|
-
await sync("session/message/" + evt.properties.info.sessionID + "/" + evt.properties.info.id, evt.properties.info)
|
|
55
|
-
})
|
|
56
|
-
Bus.subscribe(MessageV2.Event.PartUpdated, async (evt) => {
|
|
57
|
-
await sync(
|
|
58
|
-
"session/part/" +
|
|
59
|
-
evt.properties.part.sessionID +
|
|
60
|
-
"/" +
|
|
61
|
-
evt.properties.part.messageID +
|
|
62
|
-
"/" +
|
|
63
|
-
evt.properties.part.id,
|
|
64
|
-
evt.properties.part,
|
|
65
|
-
)
|
|
66
|
-
})
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
export const URL =
|
|
70
|
-
process.env["OPENCODE_API"] ??
|
|
71
|
-
(Installation.isPreview() || Installation.isLocal() ? "https://api.dev.opencode.ai" : "https://api.opencode.ai")
|
|
72
|
-
|
|
73
|
-
const disabled = process.env["OPENCODE_DISABLE_SHARE"] === "true" || process.env["OPENCODE_DISABLE_SHARE"] === "1"
|
|
74
|
-
|
|
75
|
-
export async function create(sessionID: string) {
|
|
76
|
-
if (disabled) return { url: "", secret: "" }
|
|
77
|
-
return fetch(`${URL}/share_create`, {
|
|
78
|
-
method: "POST",
|
|
79
|
-
body: JSON.stringify({ sessionID: sessionID }),
|
|
80
|
-
})
|
|
81
|
-
.then((x) => x.json())
|
|
82
|
-
.then((x) => x as { url: string; secret: string })
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
export async function remove(sessionID: string, secret: string) {
|
|
86
|
-
if (disabled) return {}
|
|
87
|
-
return fetch(`${URL}/share_delete`, {
|
|
88
|
-
method: "POST",
|
|
89
|
-
body: JSON.stringify({ sessionID, secret }),
|
|
90
|
-
}).then((x) => x.json())
|
|
91
|
-
}
|
|
92
|
-
}
|
package/src/shell/shell.ts
DELETED
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
import { Flag } from "@/flag/flag"
|
|
2
|
-
import { lazy } from "@/util/lazy"
|
|
3
|
-
import path from "path"
|
|
4
|
-
import { spawn, type ChildProcess } from "child_process"
|
|
5
|
-
|
|
6
|
-
const SIGKILL_TIMEOUT_MS = 200
|
|
7
|
-
|
|
8
|
-
export namespace Shell {
|
|
9
|
-
export async function killTree(proc: ChildProcess, opts?: { exited?: () => boolean }): Promise<void> {
|
|
10
|
-
const pid = proc.pid
|
|
11
|
-
if (!pid || opts?.exited?.()) return
|
|
12
|
-
|
|
13
|
-
if (process.platform === "win32") {
|
|
14
|
-
await new Promise<void>((resolve) => {
|
|
15
|
-
const killer = spawn("taskkill", ["/pid", String(pid), "/f", "/t"], { stdio: "ignore" })
|
|
16
|
-
killer.once("exit", () => resolve())
|
|
17
|
-
killer.once("error", () => resolve())
|
|
18
|
-
})
|
|
19
|
-
return
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
try {
|
|
23
|
-
process.kill(-pid, "SIGTERM")
|
|
24
|
-
await Bun.sleep(SIGKILL_TIMEOUT_MS)
|
|
25
|
-
if (!opts?.exited?.()) {
|
|
26
|
-
process.kill(-pid, "SIGKILL")
|
|
27
|
-
}
|
|
28
|
-
} catch (_e) {
|
|
29
|
-
proc.kill("SIGTERM")
|
|
30
|
-
await Bun.sleep(SIGKILL_TIMEOUT_MS)
|
|
31
|
-
if (!opts?.exited?.()) {
|
|
32
|
-
proc.kill("SIGKILL")
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
const BLACKLIST = new Set(["fish", "nu"])
|
|
37
|
-
|
|
38
|
-
function fallback() {
|
|
39
|
-
if (process.platform === "win32") {
|
|
40
|
-
if (Flag.OPENCODE_GIT_BASH_PATH) return Flag.OPENCODE_GIT_BASH_PATH
|
|
41
|
-
const git = Bun.which("git")
|
|
42
|
-
if (git) {
|
|
43
|
-
// git.exe is typically at: C:\Program Files\Git\cmd\git.exe
|
|
44
|
-
// bash.exe is at: C:\Program Files\Git\bin\bash.exe
|
|
45
|
-
const bash = path.join(git, "..", "..", "bin", "bash.exe")
|
|
46
|
-
if (Bun.file(bash).size) return bash
|
|
47
|
-
}
|
|
48
|
-
return process.env.COMSPEC || "cmd.exe"
|
|
49
|
-
}
|
|
50
|
-
if (process.platform === "darwin") return "/bin/zsh"
|
|
51
|
-
const bash = Bun.which("bash")
|
|
52
|
-
if (bash) return bash
|
|
53
|
-
return "/bin/sh"
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
export const preferred = lazy(() => {
|
|
57
|
-
const s = process.env.SHELL
|
|
58
|
-
if (s) return s
|
|
59
|
-
return fallback()
|
|
60
|
-
})
|
|
61
|
-
|
|
62
|
-
export const acceptable = lazy(() => {
|
|
63
|
-
const s = process.env.SHELL
|
|
64
|
-
if (s && !BLACKLIST.has(process.platform === "win32" ? path.win32.basename(s) : path.basename(s))) return s
|
|
65
|
-
return fallback()
|
|
66
|
-
})
|
|
67
|
-
}
|
package/src/skill/discovery.ts
DELETED
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
import path from "path"
|
|
2
|
-
import { mkdir } from "fs/promises"
|
|
3
|
-
import { Log } from "../util/log"
|
|
4
|
-
import { Global } from "../global"
|
|
5
|
-
|
|
6
|
-
export namespace Discovery {
|
|
7
|
-
const log = Log.create({ service: "skill-discovery" })
|
|
8
|
-
|
|
9
|
-
type Index = {
|
|
10
|
-
skills: Array<{
|
|
11
|
-
name: string
|
|
12
|
-
description: string
|
|
13
|
-
files: string[]
|
|
14
|
-
}>
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export function dir() {
|
|
18
|
-
return path.join(Global.Path.cache, "skills")
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
async function get(url: string, dest: string): Promise<boolean> {
|
|
22
|
-
if (await Bun.file(dest).exists()) return true
|
|
23
|
-
return fetch(url)
|
|
24
|
-
.then(async (response) => {
|
|
25
|
-
if (!response.ok) {
|
|
26
|
-
log.error("failed to download", { url, status: response.status })
|
|
27
|
-
return false
|
|
28
|
-
}
|
|
29
|
-
await Bun.write(dest, await response.text())
|
|
30
|
-
return true
|
|
31
|
-
})
|
|
32
|
-
.catch((err) => {
|
|
33
|
-
log.error("failed to download", { url, err })
|
|
34
|
-
return false
|
|
35
|
-
})
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
export async function pull(url: string): Promise<string[]> {
|
|
39
|
-
const result: string[] = []
|
|
40
|
-
const base = url.endsWith("/") ? url : `${url}/`
|
|
41
|
-
const index = new URL("index.json", base).href
|
|
42
|
-
const cache = dir()
|
|
43
|
-
const host = base.slice(0, -1)
|
|
44
|
-
|
|
45
|
-
log.info("fetching index", { url: index })
|
|
46
|
-
const data = await fetch(index)
|
|
47
|
-
.then(async (response) => {
|
|
48
|
-
if (!response.ok) {
|
|
49
|
-
log.error("failed to fetch index", { url: index, status: response.status })
|
|
50
|
-
return undefined
|
|
51
|
-
}
|
|
52
|
-
return response
|
|
53
|
-
.json()
|
|
54
|
-
.then((json) => json as Index)
|
|
55
|
-
.catch((err) => {
|
|
56
|
-
log.error("failed to parse index", { url: index, err })
|
|
57
|
-
return undefined
|
|
58
|
-
})
|
|
59
|
-
})
|
|
60
|
-
.catch((err) => {
|
|
61
|
-
log.error("failed to fetch index", { url: index, err })
|
|
62
|
-
return undefined
|
|
63
|
-
})
|
|
64
|
-
|
|
65
|
-
if (!data?.skills || !Array.isArray(data.skills)) {
|
|
66
|
-
log.warn("invalid index format", { url: index })
|
|
67
|
-
return result
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
const list = data.skills.filter((skill) => {
|
|
71
|
-
if (!skill?.name || !Array.isArray(skill.files)) {
|
|
72
|
-
log.warn("invalid skill entry", { url: index, skill })
|
|
73
|
-
return false
|
|
74
|
-
}
|
|
75
|
-
return true
|
|
76
|
-
})
|
|
77
|
-
|
|
78
|
-
await Promise.all(
|
|
79
|
-
list.map(async (skill) => {
|
|
80
|
-
const root = path.join(cache, skill.name)
|
|
81
|
-
await Promise.all(
|
|
82
|
-
skill.files.map(async (file) => {
|
|
83
|
-
const link = new URL(file, `${host}/${skill.name}/`).href
|
|
84
|
-
const dest = path.join(root, file)
|
|
85
|
-
await mkdir(path.dirname(dest), { recursive: true })
|
|
86
|
-
await get(link, dest)
|
|
87
|
-
}),
|
|
88
|
-
)
|
|
89
|
-
|
|
90
|
-
const md = path.join(root, "SKILL.md")
|
|
91
|
-
if (await Bun.file(md).exists()) result.push(root)
|
|
92
|
-
}),
|
|
93
|
-
)
|
|
94
|
-
|
|
95
|
-
return result
|
|
96
|
-
}
|
|
97
|
-
}
|
package/src/skill/index.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from "./skill"
|
package/src/skill/skill.ts
DELETED
|
@@ -1,188 +0,0 @@
|
|
|
1
|
-
import z from "zod"
|
|
2
|
-
import path from "path"
|
|
3
|
-
import os from "os"
|
|
4
|
-
import { Config } from "../config/config"
|
|
5
|
-
import { Instance } from "../project/instance"
|
|
6
|
-
import { NamedError } from "@opencode-ai/util/error"
|
|
7
|
-
import { ConfigMarkdown } from "../config/markdown"
|
|
8
|
-
import { Log } from "../util/log"
|
|
9
|
-
import { Global } from "@/global"
|
|
10
|
-
import { Filesystem } from "@/util/filesystem"
|
|
11
|
-
import { Flag } from "@/flag/flag"
|
|
12
|
-
import { Bus } from "@/bus"
|
|
13
|
-
import { Session } from "@/session"
|
|
14
|
-
import { Discovery } from "./discovery"
|
|
15
|
-
|
|
16
|
-
export namespace Skill {
|
|
17
|
-
const log = Log.create({ service: "skill" })
|
|
18
|
-
export const Info = z.object({
|
|
19
|
-
name: z.string(),
|
|
20
|
-
description: z.string(),
|
|
21
|
-
location: z.string(),
|
|
22
|
-
content: z.string(),
|
|
23
|
-
})
|
|
24
|
-
export type Info = z.infer<typeof Info>
|
|
25
|
-
|
|
26
|
-
export const InvalidError = NamedError.create(
|
|
27
|
-
"SkillInvalidError",
|
|
28
|
-
z.object({
|
|
29
|
-
path: z.string(),
|
|
30
|
-
message: z.string().optional(),
|
|
31
|
-
issues: z.custom<z.core.$ZodIssue[]>().optional(),
|
|
32
|
-
}),
|
|
33
|
-
)
|
|
34
|
-
|
|
35
|
-
export const NameMismatchError = NamedError.create(
|
|
36
|
-
"SkillNameMismatchError",
|
|
37
|
-
z.object({
|
|
38
|
-
path: z.string(),
|
|
39
|
-
expected: z.string(),
|
|
40
|
-
actual: z.string(),
|
|
41
|
-
}),
|
|
42
|
-
)
|
|
43
|
-
|
|
44
|
-
// External skill directories to search for (project-level and global)
|
|
45
|
-
// These follow the directory layout used by Claude Code and other agents.
|
|
46
|
-
const EXTERNAL_DIRS = [".claude", ".agents"]
|
|
47
|
-
const EXTERNAL_SKILL_GLOB = new Bun.Glob("skills/**/SKILL.md")
|
|
48
|
-
|
|
49
|
-
const OPENCODE_SKILL_GLOB = new Bun.Glob("{skill,skills}/**/SKILL.md")
|
|
50
|
-
const SKILL_GLOB = new Bun.Glob("**/SKILL.md")
|
|
51
|
-
|
|
52
|
-
export const state = Instance.state(async () => {
|
|
53
|
-
const skills: Record<string, Info> = {}
|
|
54
|
-
const dirs = new Set<string>()
|
|
55
|
-
|
|
56
|
-
const addSkill = async (match: string) => {
|
|
57
|
-
const md = await ConfigMarkdown.parse(match).catch((err) => {
|
|
58
|
-
const message = ConfigMarkdown.FrontmatterError.isInstance(err)
|
|
59
|
-
? err.data.message
|
|
60
|
-
: `Failed to parse skill ${match}`
|
|
61
|
-
Bus.publish(Session.Event.Error, { error: new NamedError.Unknown({ message }).toObject() })
|
|
62
|
-
log.error("failed to load skill", { skill: match, err })
|
|
63
|
-
return undefined
|
|
64
|
-
})
|
|
65
|
-
|
|
66
|
-
if (!md) return
|
|
67
|
-
|
|
68
|
-
const parsed = Info.pick({ name: true, description: true }).safeParse(md.data)
|
|
69
|
-
if (!parsed.success) return
|
|
70
|
-
|
|
71
|
-
// Warn on duplicate skill names
|
|
72
|
-
if (skills[parsed.data.name]) {
|
|
73
|
-
log.warn("duplicate skill name", {
|
|
74
|
-
name: parsed.data.name,
|
|
75
|
-
existing: skills[parsed.data.name].location,
|
|
76
|
-
duplicate: match,
|
|
77
|
-
})
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
dirs.add(path.dirname(match))
|
|
81
|
-
|
|
82
|
-
skills[parsed.data.name] = {
|
|
83
|
-
name: parsed.data.name,
|
|
84
|
-
description: parsed.data.description,
|
|
85
|
-
location: match,
|
|
86
|
-
content: md.content,
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
const scanExternal = async (root: string, scope: "global" | "project") => {
|
|
91
|
-
return Array.fromAsync(
|
|
92
|
-
EXTERNAL_SKILL_GLOB.scan({
|
|
93
|
-
cwd: root,
|
|
94
|
-
absolute: true,
|
|
95
|
-
onlyFiles: true,
|
|
96
|
-
followSymlinks: true,
|
|
97
|
-
dot: true,
|
|
98
|
-
}),
|
|
99
|
-
)
|
|
100
|
-
.then((matches) => Promise.all(matches.map(addSkill)))
|
|
101
|
-
.catch((error) => {
|
|
102
|
-
log.error(`failed to scan ${scope} skills`, { dir: root, error })
|
|
103
|
-
})
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
// Scan external skill directories (.claude/skills/, .agents/skills/, etc.)
|
|
107
|
-
// Load global (home) first, then project-level (so project-level overwrites)
|
|
108
|
-
if (!Flag.OPENCODE_DISABLE_EXTERNAL_SKILLS) {
|
|
109
|
-
for (const dir of EXTERNAL_DIRS) {
|
|
110
|
-
const root = path.join(Global.Path.home, dir)
|
|
111
|
-
if (!(await Filesystem.isDir(root))) continue
|
|
112
|
-
await scanExternal(root, "global")
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
for await (const root of Filesystem.up({
|
|
116
|
-
targets: EXTERNAL_DIRS,
|
|
117
|
-
start: Instance.directory,
|
|
118
|
-
stop: Instance.worktree,
|
|
119
|
-
})) {
|
|
120
|
-
await scanExternal(root, "project")
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
// Scan .opencode/skill/ directories
|
|
125
|
-
for (const dir of await Config.directories()) {
|
|
126
|
-
for await (const match of OPENCODE_SKILL_GLOB.scan({
|
|
127
|
-
cwd: dir,
|
|
128
|
-
absolute: true,
|
|
129
|
-
onlyFiles: true,
|
|
130
|
-
followSymlinks: true,
|
|
131
|
-
})) {
|
|
132
|
-
await addSkill(match)
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
// Scan additional skill paths from config
|
|
137
|
-
const config = await Config.get()
|
|
138
|
-
for (const skillPath of config.skills?.paths ?? []) {
|
|
139
|
-
const expanded = skillPath.startsWith("~/") ? path.join(os.homedir(), skillPath.slice(2)) : skillPath
|
|
140
|
-
const resolved = path.isAbsolute(expanded) ? expanded : path.join(Instance.directory, expanded)
|
|
141
|
-
if (!(await Filesystem.isDir(resolved))) {
|
|
142
|
-
log.warn("skill path not found", { path: resolved })
|
|
143
|
-
continue
|
|
144
|
-
}
|
|
145
|
-
for await (const match of SKILL_GLOB.scan({
|
|
146
|
-
cwd: resolved,
|
|
147
|
-
absolute: true,
|
|
148
|
-
onlyFiles: true,
|
|
149
|
-
followSymlinks: true,
|
|
150
|
-
})) {
|
|
151
|
-
await addSkill(match)
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
// Download and load skills from URLs
|
|
156
|
-
for (const url of config.skills?.urls ?? []) {
|
|
157
|
-
const list = await Discovery.pull(url)
|
|
158
|
-
for (const dir of list) {
|
|
159
|
-
dirs.add(dir)
|
|
160
|
-
for await (const match of SKILL_GLOB.scan({
|
|
161
|
-
cwd: dir,
|
|
162
|
-
absolute: true,
|
|
163
|
-
onlyFiles: true,
|
|
164
|
-
followSymlinks: true,
|
|
165
|
-
})) {
|
|
166
|
-
await addSkill(match)
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
return {
|
|
172
|
-
skills,
|
|
173
|
-
dirs: Array.from(dirs),
|
|
174
|
-
}
|
|
175
|
-
})
|
|
176
|
-
|
|
177
|
-
export async function get(name: string) {
|
|
178
|
-
return state().then((x) => x.skills[name])
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
export async function all() {
|
|
182
|
-
return state().then((x) => Object.values(x.skills))
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
export async function dirs() {
|
|
186
|
-
return state().then((x) => x.dirs)
|
|
187
|
-
}
|
|
188
|
-
}
|