bincode-cli 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +27 -0
- package/README.md +15 -0
- package/bin/bincode +98 -0
- package/bunfig.toml +4 -0
- package/package.json +124 -0
- package/parsers-config.ts +239 -0
- package/script/build.ts +167 -0
- package/script/postinstall.mjs +206 -0
- package/script/publish.ts +99 -0
- package/script/schema.ts +47 -0
- package/src/acp/README.md +164 -0
- package/src/acp/agent.ts +1051 -0
- package/src/acp/session.ts +101 -0
- package/src/acp/types.ts +22 -0
- package/src/agent/agent.ts +398 -0
- package/src/agent/generate.txt +75 -0
- package/src/agent/prompt/compaction.txt +12 -0
- package/src/agent/prompt/explore.txt +18 -0
- package/src/agent/prompt/summary.txt +10 -0
- package/src/agent/prompt/title.txt +36 -0
- package/src/auth/bineric-login.ts +506 -0
- package/src/auth/index.ts +70 -0
- package/src/bun/index.ts +114 -0
- package/src/bus/bus-event.ts +43 -0
- package/src/bus/global.ts +10 -0
- package/src/bus/index.ts +105 -0
- package/src/cli/auth-check.ts +61 -0
- package/src/cli/bootstrap.ts +21 -0
- package/src/cli/cmd/acp.ts +88 -0
- package/src/cli/cmd/agent.ts +256 -0
- package/src/cli/cmd/auth.ts +436 -0
- package/src/cli/cmd/cmd.ts +7 -0
- package/src/cli/cmd/debug/config.ts +15 -0
- package/src/cli/cmd/debug/file.ts +91 -0
- package/src/cli/cmd/debug/index.ts +43 -0
- package/src/cli/cmd/debug/lsp.ts +48 -0
- package/src/cli/cmd/debug/ripgrep.ts +83 -0
- package/src/cli/cmd/debug/scrap.ts +15 -0
- package/src/cli/cmd/debug/skill.ts +15 -0
- package/src/cli/cmd/debug/snapshot.ts +48 -0
- package/src/cli/cmd/export.ts +88 -0
- package/src/cli/cmd/generate.ts +38 -0
- package/src/cli/cmd/github.ts +1399 -0
- package/src/cli/cmd/import.ts +98 -0
- package/src/cli/cmd/login.ts +112 -0
- package/src/cli/cmd/logout.ts +38 -0
- package/src/cli/cmd/mcp.ts +654 -0
- package/src/cli/cmd/models.ts +77 -0
- package/src/cli/cmd/pr.ts +112 -0
- package/src/cli/cmd/run.ts +368 -0
- package/src/cli/cmd/serve.ts +31 -0
- package/src/cli/cmd/session.ts +106 -0
- package/src/cli/cmd/stats.ts +298 -0
- package/src/cli/cmd/tui/app.tsx +669 -0
- package/src/cli/cmd/tui/attach.ts +30 -0
- package/src/cli/cmd/tui/component/border.tsx +21 -0
- package/src/cli/cmd/tui/component/dialog-agent.tsx +31 -0
- package/src/cli/cmd/tui/component/dialog-command.tsx +123 -0
- package/src/cli/cmd/tui/component/dialog-mcp.tsx +86 -0
- package/src/cli/cmd/tui/component/dialog-model.tsx +223 -0
- package/src/cli/cmd/tui/component/dialog-provider.tsx +224 -0
- package/src/cli/cmd/tui/component/dialog-session-list.tsx +102 -0
- package/src/cli/cmd/tui/component/dialog-session-rename.tsx +31 -0
- package/src/cli/cmd/tui/component/dialog-status.tsx +162 -0
- package/src/cli/cmd/tui/component/dialog-tag.tsx +44 -0
- package/src/cli/cmd/tui/component/dialog-theme-list.tsx +50 -0
- package/src/cli/cmd/tui/component/logo.tsx +32 -0
- package/src/cli/cmd/tui/component/prompt/autocomplete.tsx +560 -0
- package/src/cli/cmd/tui/component/prompt/history.tsx +108 -0
- package/src/cli/cmd/tui/component/prompt/index.tsx +1052 -0
- package/src/cli/cmd/tui/context/args.tsx +14 -0
- package/src/cli/cmd/tui/context/directory.ts +13 -0
- package/src/cli/cmd/tui/context/exit.tsx +23 -0
- package/src/cli/cmd/tui/context/helper.tsx +25 -0
- package/src/cli/cmd/tui/context/keybind.tsx +101 -0
- package/src/cli/cmd/tui/context/kv.tsx +49 -0
- package/src/cli/cmd/tui/context/local.tsx +339 -0
- package/src/cli/cmd/tui/context/prompt.tsx +18 -0
- package/src/cli/cmd/tui/context/route.tsx +46 -0
- package/src/cli/cmd/tui/context/sdk.tsx +74 -0
- package/src/cli/cmd/tui/context/sync.tsx +372 -0
- package/src/cli/cmd/tui/context/theme/aura.json +69 -0
- package/src/cli/cmd/tui/context/theme/ayu.json +80 -0
- package/src/cli/cmd/tui/context/theme/bincode.json +245 -0
- package/src/cli/cmd/tui/context/theme/catppuccin-frappe.json +233 -0
- package/src/cli/cmd/tui/context/theme/catppuccin-macchiato.json +233 -0
- package/src/cli/cmd/tui/context/theme/catppuccin.json +112 -0
- package/src/cli/cmd/tui/context/theme/cobalt2.json +228 -0
- package/src/cli/cmd/tui/context/theme/cursor.json +249 -0
- package/src/cli/cmd/tui/context/theme/dracula.json +219 -0
- package/src/cli/cmd/tui/context/theme/everforest.json +241 -0
- package/src/cli/cmd/tui/context/theme/flexoki.json +237 -0
- package/src/cli/cmd/tui/context/theme/github.json +233 -0
- package/src/cli/cmd/tui/context/theme/gruvbox.json +95 -0
- package/src/cli/cmd/tui/context/theme/kanagawa.json +77 -0
- package/src/cli/cmd/tui/context/theme/lucent-orng.json +227 -0
- package/src/cli/cmd/tui/context/theme/material.json +235 -0
- package/src/cli/cmd/tui/context/theme/matrix.json +77 -0
- package/src/cli/cmd/tui/context/theme/mercury.json +252 -0
- package/src/cli/cmd/tui/context/theme/monokai.json +221 -0
- package/src/cli/cmd/tui/context/theme/nightowl.json +221 -0
- package/src/cli/cmd/tui/context/theme/nord.json +223 -0
- package/src/cli/cmd/tui/context/theme/one-dark.json +84 -0
- package/src/cli/cmd/tui/context/theme/orng.json +245 -0
- package/src/cli/cmd/tui/context/theme/palenight.json +222 -0
- package/src/cli/cmd/tui/context/theme/rosepine.json +234 -0
- package/src/cli/cmd/tui/context/theme/solarized.json +223 -0
- package/src/cli/cmd/tui/context/theme/synthwave84.json +226 -0
- package/src/cli/cmd/tui/context/theme/tokyonight.json +243 -0
- package/src/cli/cmd/tui/context/theme/vercel.json +245 -0
- package/src/cli/cmd/tui/context/theme/vesper.json +218 -0
- package/src/cli/cmd/tui/context/theme/zenburn.json +223 -0
- package/src/cli/cmd/tui/context/theme.tsx +1109 -0
- package/src/cli/cmd/tui/event.ts +40 -0
- package/src/cli/cmd/tui/routes/home.tsx +105 -0
- package/src/cli/cmd/tui/routes/session/dialog-fork-from-timeline.tsx +64 -0
- package/src/cli/cmd/tui/routes/session/dialog-message.tsx +109 -0
- package/src/cli/cmd/tui/routes/session/dialog-subagent.tsx +26 -0
- package/src/cli/cmd/tui/routes/session/dialog-timeline.tsx +47 -0
- package/src/cli/cmd/tui/routes/session/footer.tsx +88 -0
- package/src/cli/cmd/tui/routes/session/header.tsx +141 -0
- package/src/cli/cmd/tui/routes/session/index.tsx +1888 -0
- package/src/cli/cmd/tui/routes/session/sidebar.tsx +321 -0
- package/src/cli/cmd/tui/spawn.ts +60 -0
- package/src/cli/cmd/tui/thread.ts +120 -0
- package/src/cli/cmd/tui/ui/dialog-alert.tsx +57 -0
- package/src/cli/cmd/tui/ui/dialog-confirm.tsx +83 -0
- package/src/cli/cmd/tui/ui/dialog-help.tsx +38 -0
- package/src/cli/cmd/tui/ui/dialog-prompt.tsx +77 -0
- package/src/cli/cmd/tui/ui/dialog-select.tsx +330 -0
- package/src/cli/cmd/tui/ui/dialog.tsx +170 -0
- package/src/cli/cmd/tui/ui/spinner.ts +368 -0
- package/src/cli/cmd/tui/ui/toast.tsx +100 -0
- package/src/cli/cmd/tui/util/clipboard.ts +127 -0
- package/src/cli/cmd/tui/util/editor.ts +32 -0
- package/src/cli/cmd/tui/util/terminal.ts +114 -0
- package/src/cli/cmd/tui/worker.ts +63 -0
- package/src/cli/cmd/uninstall.ts +344 -0
- package/src/cli/cmd/upgrade.ts +67 -0
- package/src/cli/cmd/web.ts +84 -0
- package/src/cli/error.ts +55 -0
- package/src/cli/ui.ts +84 -0
- package/src/cli/upgrade.ts +25 -0
- package/src/command/index.ts +80 -0
- package/src/command/template/initialize.txt +10 -0
- package/src/command/template/review.txt +97 -0
- package/src/config/config.ts +995 -0
- package/src/config/markdown.ts +41 -0
- package/src/env/index.ts +26 -0
- package/src/file/ignore.ts +83 -0
- package/src/file/index.ts +328 -0
- package/src/file/ripgrep.ts +393 -0
- package/src/file/time.ts +64 -0
- package/src/file/watcher.ts +103 -0
- package/src/flag/flag.ts +46 -0
- package/src/format/formatter.ts +315 -0
- package/src/format/index.ts +137 -0
- package/src/global/index.ts +52 -0
- package/src/id/id.ts +73 -0
- package/src/ide/index.ts +76 -0
- package/src/index.ts +217 -0
- package/src/installation/index.ts +196 -0
- package/src/lsp/client.ts +229 -0
- package/src/lsp/index.ts +485 -0
- package/src/lsp/language.ts +116 -0
- package/src/lsp/server.ts +1895 -0
- package/src/mcp/auth.ts +135 -0
- package/src/mcp/index.ts +654 -0
- package/src/mcp/oauth-callback.ts +200 -0
- package/src/mcp/oauth-provider.ts +154 -0
- package/src/patch/index.ts +622 -0
- package/src/permission/index.ts +199 -0
- package/src/plugin/index.ts +101 -0
- package/src/project/bootstrap.ts +31 -0
- package/src/project/instance.ts +78 -0
- package/src/project/project.ts +221 -0
- package/src/project/state.ts +65 -0
- package/src/project/vcs.ts +76 -0
- package/src/provider/auth.ts +143 -0
- package/src/provider/models-macro.ts +11 -0
- package/src/provider/models.ts +106 -0
- package/src/provider/provider.ts +1071 -0
- package/src/provider/sdk/openai-compatible/src/README.md +5 -0
- package/src/provider/sdk/openai-compatible/src/index.ts +2 -0
- package/src/provider/sdk/openai-compatible/src/openai-compatible-provider.ts +101 -0
- package/src/provider/sdk/openai-compatible/src/responses/convert-to-openai-responses-input.ts +303 -0
- package/src/provider/sdk/openai-compatible/src/responses/map-openai-responses-finish-reason.ts +22 -0
- package/src/provider/sdk/openai-compatible/src/responses/openai-config.ts +18 -0
- package/src/provider/sdk/openai-compatible/src/responses/openai-error.ts +22 -0
- package/src/provider/sdk/openai-compatible/src/responses/openai-responses-api-types.ts +207 -0
- package/src/provider/sdk/openai-compatible/src/responses/openai-responses-language-model.ts +1713 -0
- package/src/provider/sdk/openai-compatible/src/responses/openai-responses-prepare-tools.ts +177 -0
- package/src/provider/sdk/openai-compatible/src/responses/openai-responses-settings.ts +1 -0
- package/src/provider/sdk/openai-compatible/src/responses/tool/code-interpreter.ts +88 -0
- package/src/provider/sdk/openai-compatible/src/responses/tool/file-search.ts +128 -0
- package/src/provider/sdk/openai-compatible/src/responses/tool/image-generation.ts +115 -0
- package/src/provider/sdk/openai-compatible/src/responses/tool/local-shell.ts +65 -0
- package/src/provider/sdk/openai-compatible/src/responses/tool/web-search-preview.ts +104 -0
- package/src/provider/sdk/openai-compatible/src/responses/tool/web-search.ts +103 -0
- package/src/provider/transform.ts +455 -0
- package/src/pty/index.ts +231 -0
- package/src/server/error.ts +36 -0
- package/src/server/project.ts +79 -0
- package/src/server/server.ts +2642 -0
- package/src/server/tui.ts +71 -0
- package/src/session/compaction.ts +223 -0
- package/src/session/index.ts +458 -0
- package/src/session/llm.ts +201 -0
- package/src/session/message-v2.ts +659 -0
- package/src/session/message.ts +189 -0
- package/src/session/processor.ts +409 -0
- package/src/session/prompt/anthropic-20250930.txt +166 -0
- package/src/session/prompt/anthropic.txt +104 -0
- package/src/session/prompt/anthropic_spoof.txt +1 -0
- package/src/session/prompt/beast.txt +147 -0
- package/src/session/prompt/build-switch.txt +5 -0
- package/src/session/prompt/codex.txt +318 -0
- package/src/session/prompt/copilot-gpt-5.txt +143 -0
- package/src/session/prompt/gemini.txt +155 -0
- package/src/session/prompt/max-steps.txt +16 -0
- package/src/session/prompt/plan-reminder-anthropic.txt +67 -0
- package/src/session/prompt/plan.txt +26 -0
- package/src/session/prompt/polaris.txt +106 -0
- package/src/session/prompt/qwen.txt +109 -0
- package/src/session/prompt.ts +1446 -0
- package/src/session/retry.ts +86 -0
- package/src/session/revert.ts +108 -0
- package/src/session/status.ts +76 -0
- package/src/session/summary.ts +194 -0
- package/src/session/system.ts +120 -0
- package/src/session/todo.ts +37 -0
- package/src/share/share-next.ts +194 -0
- package/src/share/share.ts +87 -0
- package/src/shell/shell.ts +67 -0
- package/src/skill/index.ts +1 -0
- package/src/skill/skill.ts +83 -0
- package/src/snapshot/index.ts +197 -0
- package/src/storage/storage.ts +226 -0
- package/src/tool/bash.ts +306 -0
- package/src/tool/bash.txt +158 -0
- package/src/tool/batch.ts +175 -0
- package/src/tool/batch.txt +24 -0
- package/src/tool/codesearch.ts +138 -0
- package/src/tool/codesearch.txt +12 -0
- package/src/tool/edit.ts +675 -0
- package/src/tool/edit.txt +10 -0
- package/src/tool/glob.ts +65 -0
- package/src/tool/glob.txt +6 -0
- package/src/tool/grep.ts +121 -0
- package/src/tool/grep.txt +8 -0
- package/src/tool/invalid.ts +17 -0
- package/src/tool/ls.ts +110 -0
- package/src/tool/ls.txt +1 -0
- package/src/tool/lsp-diagnostics.ts +26 -0
- package/src/tool/lsp-diagnostics.txt +1 -0
- package/src/tool/lsp-hover.ts +31 -0
- package/src/tool/lsp-hover.txt +1 -0
- package/src/tool/lsp.ts +87 -0
- package/src/tool/lsp.txt +19 -0
- package/src/tool/multiedit.ts +46 -0
- package/src/tool/multiedit.txt +41 -0
- package/src/tool/patch.ts +233 -0
- package/src/tool/patch.txt +1 -0
- package/src/tool/read.ts +219 -0
- package/src/tool/read.txt +12 -0
- package/src/tool/registry.ts +162 -0
- package/src/tool/skill.ts +100 -0
- package/src/tool/task.ts +136 -0
- package/src/tool/task.txt +60 -0
- package/src/tool/todo.ts +39 -0
- package/src/tool/todoread.txt +14 -0
- package/src/tool/todowrite.txt +167 -0
- package/src/tool/tool.ts +71 -0
- package/src/tool/webfetch.ts +187 -0
- package/src/tool/webfetch.txt +13 -0
- package/src/tool/websearch.ts +150 -0
- package/src/tool/websearch.txt +11 -0
- package/src/tool/write.ts +110 -0
- package/src/tool/write.txt +8 -0
- package/src/util/archive.ts +16 -0
- package/src/util/color.ts +19 -0
- package/src/util/context.ts +25 -0
- package/src/util/defer.ts +12 -0
- package/src/util/eventloop.ts +20 -0
- package/src/util/filesystem.ts +83 -0
- package/src/util/fn.ts +11 -0
- package/src/util/iife.ts +3 -0
- package/src/util/keybind.ts +102 -0
- package/src/util/lazy.ts +11 -0
- package/src/util/locale.ts +81 -0
- package/src/util/lock.ts +98 -0
- package/src/util/log.ts +180 -0
- package/src/util/queue.ts +32 -0
- package/src/util/rpc.ts +42 -0
- package/src/util/scrap.ts +10 -0
- package/src/util/signal.ts +12 -0
- package/src/util/timeout.ts +14 -0
- package/src/util/token.ts +7 -0
- package/src/util/wildcard.ts +54 -0
- package/tsconfig.json +16 -0
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import z from "zod"
|
|
2
|
+
import type { ZodType } from "zod"
|
|
3
|
+
import { Log } from "../util/log"
|
|
4
|
+
|
|
5
|
+
export namespace BusEvent {
|
|
6
|
+
const log = Log.create({ service: "event" })
|
|
7
|
+
|
|
8
|
+
export type Definition = ReturnType<typeof define>
|
|
9
|
+
|
|
10
|
+
const registry = new Map<string, Definition>()
|
|
11
|
+
|
|
12
|
+
export function define<Type extends string, Properties extends ZodType>(type: Type, properties: Properties) {
|
|
13
|
+
const result = {
|
|
14
|
+
type,
|
|
15
|
+
properties,
|
|
16
|
+
}
|
|
17
|
+
registry.set(type, result)
|
|
18
|
+
return result
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function payloads() {
|
|
22
|
+
return z
|
|
23
|
+
.discriminatedUnion(
|
|
24
|
+
"type",
|
|
25
|
+
registry
|
|
26
|
+
.entries()
|
|
27
|
+
.map(([type, def]) => {
|
|
28
|
+
return z
|
|
29
|
+
.object({
|
|
30
|
+
type: z.literal(type),
|
|
31
|
+
properties: def.properties,
|
|
32
|
+
})
|
|
33
|
+
.meta({
|
|
34
|
+
ref: "Event" + "." + def.type,
|
|
35
|
+
})
|
|
36
|
+
})
|
|
37
|
+
.toArray() as any,
|
|
38
|
+
)
|
|
39
|
+
.meta({
|
|
40
|
+
ref: "Event",
|
|
41
|
+
})
|
|
42
|
+
}
|
|
43
|
+
}
|
package/src/bus/index.ts
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import z from "zod"
|
|
2
|
+
import { Log } from "../util/log"
|
|
3
|
+
import { Instance } from "../project/instance"
|
|
4
|
+
import { BusEvent } from "./bus-event"
|
|
5
|
+
import { GlobalBus } from "./global"
|
|
6
|
+
|
|
7
|
+
export namespace Bus {
|
|
8
|
+
const log = Log.create({ service: "bus" })
|
|
9
|
+
type Subscription = (event: any) => void
|
|
10
|
+
|
|
11
|
+
export const InstanceDisposed = BusEvent.define(
|
|
12
|
+
"server.instance.disposed",
|
|
13
|
+
z.object({
|
|
14
|
+
directory: z.string(),
|
|
15
|
+
}),
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
const state = Instance.state(
|
|
19
|
+
() => {
|
|
20
|
+
const subscriptions = new Map<any, Subscription[]>()
|
|
21
|
+
|
|
22
|
+
return {
|
|
23
|
+
subscriptions,
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
async (entry) => {
|
|
27
|
+
const wildcard = entry.subscriptions.get("*")
|
|
28
|
+
if (!wildcard) return
|
|
29
|
+
const event = {
|
|
30
|
+
type: InstanceDisposed.type,
|
|
31
|
+
properties: {
|
|
32
|
+
directory: Instance.directory,
|
|
33
|
+
},
|
|
34
|
+
}
|
|
35
|
+
for (const sub of [...wildcard]) {
|
|
36
|
+
sub(event)
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
export async function publish<Definition extends BusEvent.Definition>(
|
|
42
|
+
def: Definition,
|
|
43
|
+
properties: z.output<Definition["properties"]>,
|
|
44
|
+
) {
|
|
45
|
+
const payload = {
|
|
46
|
+
type: def.type,
|
|
47
|
+
properties,
|
|
48
|
+
}
|
|
49
|
+
log.info("publishing", {
|
|
50
|
+
type: def.type,
|
|
51
|
+
})
|
|
52
|
+
const pending = []
|
|
53
|
+
for (const key of [def.type, "*"]) {
|
|
54
|
+
const match = state().subscriptions.get(key)
|
|
55
|
+
for (const sub of match ?? []) {
|
|
56
|
+
pending.push(sub(payload))
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
GlobalBus.emit("event", {
|
|
60
|
+
directory: Instance.directory,
|
|
61
|
+
payload,
|
|
62
|
+
})
|
|
63
|
+
return Promise.all(pending)
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export function subscribe<Definition extends BusEvent.Definition>(
|
|
67
|
+
def: Definition,
|
|
68
|
+
callback: (event: { type: Definition["type"]; properties: z.infer<Definition["properties"]> }) => void,
|
|
69
|
+
) {
|
|
70
|
+
return raw(def.type, callback)
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export function once<Definition extends BusEvent.Definition>(
|
|
74
|
+
def: Definition,
|
|
75
|
+
callback: (event: {
|
|
76
|
+
type: Definition["type"]
|
|
77
|
+
properties: z.infer<Definition["properties"]>
|
|
78
|
+
}) => "done" | undefined,
|
|
79
|
+
) {
|
|
80
|
+
const unsub = subscribe(def, (event) => {
|
|
81
|
+
if (callback(event)) unsub()
|
|
82
|
+
})
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export function subscribeAll(callback: (event: any) => void) {
|
|
86
|
+
return raw("*", callback)
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function raw(type: string, callback: (event: any) => void) {
|
|
90
|
+
log.info("subscribing", { type })
|
|
91
|
+
const subscriptions = state().subscriptions
|
|
92
|
+
let match = subscriptions.get(type) ?? []
|
|
93
|
+
match.push(callback)
|
|
94
|
+
subscriptions.set(type, match)
|
|
95
|
+
|
|
96
|
+
return () => {
|
|
97
|
+
log.info("unsubscribing", { type })
|
|
98
|
+
const match = subscriptions.get(type)
|
|
99
|
+
if (!match) return
|
|
100
|
+
const index = match.indexOf(callback)
|
|
101
|
+
if (index === -1) return
|
|
102
|
+
match.splice(index, 1)
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { Filesystem } from "../util/filesystem"
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Check if user is authenticated by checking for Bineric API key in config files
|
|
5
|
+
* This function works without requiring Instance initialization
|
|
6
|
+
*/
|
|
7
|
+
export async function checkAuth(command: string | undefined): Promise<{ isAuthenticated: boolean; needsLogin: boolean }> {
|
|
8
|
+
// Skip auth check for auth commands
|
|
9
|
+
if (command === "auth" || command === "login" || command === "logout") {
|
|
10
|
+
return { isAuthenticated: true, needsLogin: false }
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
// Skip for help and version commands
|
|
14
|
+
if (command === "help" || command === "version" || command === "--help" || command === "--version" || command === "-h" || command === "-v") {
|
|
15
|
+
return { isAuthenticated: true, needsLogin: false }
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// Check if Bineric provider has API key in bincode.json files
|
|
19
|
+
try {
|
|
20
|
+
const configFiles = ["bincode.jsonc", "bincode.json"]
|
|
21
|
+
const currentDir = process.cwd()
|
|
22
|
+
|
|
23
|
+
for (const file of configFiles) {
|
|
24
|
+
const found = await Filesystem.findUp(file, currentDir, undefined)
|
|
25
|
+
for (const configPath of found) {
|
|
26
|
+
const config = await Bun.file(configPath).json().catch(() => null)
|
|
27
|
+
// Check for token (preferred) or apiKey (legacy)
|
|
28
|
+
const token = config?.provider?.Bineric?.options?.token
|
|
29
|
+
const apiKey = config?.provider?.Bineric?.options?.apiKey
|
|
30
|
+
|
|
31
|
+
if (token && token.length > 10) {
|
|
32
|
+
return { isAuthenticated: true, needsLogin: false }
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Legacy: check apiKey if token not found
|
|
36
|
+
if (apiKey && apiKey !== "not-needed" && apiKey.length > 10) {
|
|
37
|
+
return { isAuthenticated: true, needsLogin: false }
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Also check if Bineric is enabled in config - if it is, we need login
|
|
43
|
+
for (const file of configFiles) {
|
|
44
|
+
const found = await Filesystem.findUp(file, currentDir, undefined)
|
|
45
|
+
for (const configPath of found) {
|
|
46
|
+
const config = await Bun.file(configPath).json().catch(() => null)
|
|
47
|
+
if (config?.enabled_providers?.includes("Bineric") || config?.provider?.Bineric) {
|
|
48
|
+
return { isAuthenticated: false, needsLogin: true }
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// If no config found, assume login is required for CLI usage
|
|
54
|
+
// This ensures users always login before using the CLI
|
|
55
|
+
return { isAuthenticated: false, needsLogin: true }
|
|
56
|
+
} catch (error) {
|
|
57
|
+
// On error, assume login is required
|
|
58
|
+
return { isAuthenticated: false, needsLogin: true }
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { InstanceBootstrap } from "../project/bootstrap"
|
|
2
|
+
import { Instance } from "../project/instance"
|
|
3
|
+
import { BinericLogin } from "../auth/bineric-login"
|
|
4
|
+
|
|
5
|
+
export async function bootstrap<T>(directory: string, cb: () => Promise<T>) {
|
|
6
|
+
return Instance.provide({
|
|
7
|
+
directory,
|
|
8
|
+
init: InstanceBootstrap,
|
|
9
|
+
fn: async () => {
|
|
10
|
+
try {
|
|
11
|
+
// Auth check is now handled in middleware (index.ts)
|
|
12
|
+
// This ensures users are authenticated before any command runs
|
|
13
|
+
const result = await cb()
|
|
14
|
+
return result
|
|
15
|
+
} finally {
|
|
16
|
+
await Instance.dispose()
|
|
17
|
+
await BinericLogin.stop()
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
})
|
|
21
|
+
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { Log } from "@/util/log"
|
|
2
|
+
import { bootstrap } from "../bootstrap"
|
|
3
|
+
import { cmd } from "./cmd"
|
|
4
|
+
import { AgentSideConnection, ndJsonStream } from "@agentclientprotocol/sdk"
|
|
5
|
+
import { ACP } from "@/acp/agent"
|
|
6
|
+
import { Server } from "@/server/server"
|
|
7
|
+
import { createBincodeClient } from "@bincode-ai/sdk/v2"
|
|
8
|
+
|
|
9
|
+
const log = Log.create({ service: "acp-command" })
|
|
10
|
+
|
|
11
|
+
process.on("unhandledRejection", (reason, promise) => {
|
|
12
|
+
log.error("Unhandled rejection", {
|
|
13
|
+
promise,
|
|
14
|
+
reason,
|
|
15
|
+
})
|
|
16
|
+
})
|
|
17
|
+
|
|
18
|
+
export const AcpCommand = cmd({
|
|
19
|
+
command: "acp",
|
|
20
|
+
describe: "start ACP (Agent Client Protocol) server",
|
|
21
|
+
builder: (yargs) => {
|
|
22
|
+
return yargs
|
|
23
|
+
.option("cwd", {
|
|
24
|
+
describe: "working directory",
|
|
25
|
+
type: "string",
|
|
26
|
+
default: process.cwd(),
|
|
27
|
+
})
|
|
28
|
+
.option("port", {
|
|
29
|
+
type: "number",
|
|
30
|
+
describe: "port to listen on",
|
|
31
|
+
default: 0,
|
|
32
|
+
})
|
|
33
|
+
.option("hostname", {
|
|
34
|
+
type: "string",
|
|
35
|
+
describe: "hostname to listen on",
|
|
36
|
+
default: "127.0.0.1",
|
|
37
|
+
})
|
|
38
|
+
},
|
|
39
|
+
handler: async (args) => {
|
|
40
|
+
await bootstrap(process.cwd(), async () => {
|
|
41
|
+
const server = Server.listen({
|
|
42
|
+
port: args.port,
|
|
43
|
+
hostname: args.hostname,
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
const sdk = createBincodeClient({
|
|
47
|
+
baseUrl: `http://${server.hostname}:${server.port}`,
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
const input = new WritableStream<Uint8Array>({
|
|
51
|
+
write(chunk) {
|
|
52
|
+
return new Promise<void>((resolve, reject) => {
|
|
53
|
+
process.stdout.write(chunk, (err) => {
|
|
54
|
+
if (err) {
|
|
55
|
+
reject(err)
|
|
56
|
+
} else {
|
|
57
|
+
resolve()
|
|
58
|
+
}
|
|
59
|
+
})
|
|
60
|
+
})
|
|
61
|
+
},
|
|
62
|
+
})
|
|
63
|
+
const output = new ReadableStream<Uint8Array>({
|
|
64
|
+
start(controller) {
|
|
65
|
+
process.stdin.on("data", (chunk: Buffer) => {
|
|
66
|
+
controller.enqueue(new Uint8Array(chunk))
|
|
67
|
+
})
|
|
68
|
+
process.stdin.on("end", () => controller.close())
|
|
69
|
+
process.stdin.on("error", (err) => controller.error(err))
|
|
70
|
+
},
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
const stream = ndJsonStream(input, output)
|
|
74
|
+
const agent = await ACP.init({ sdk })
|
|
75
|
+
|
|
76
|
+
new AgentSideConnection((conn) => {
|
|
77
|
+
return agent.create(conn, { sdk })
|
|
78
|
+
}, stream)
|
|
79
|
+
|
|
80
|
+
log.info("setup connection")
|
|
81
|
+
process.stdin.resume()
|
|
82
|
+
await new Promise((resolve, reject) => {
|
|
83
|
+
process.stdin.on("end", resolve)
|
|
84
|
+
process.stdin.on("error", reject)
|
|
85
|
+
})
|
|
86
|
+
})
|
|
87
|
+
},
|
|
88
|
+
})
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
import { cmd } from "./cmd"
|
|
2
|
+
import * as prompts from "@clack/prompts"
|
|
3
|
+
import { UI } from "../ui"
|
|
4
|
+
import { Global } from "../../global"
|
|
5
|
+
import { Agent } from "../../agent/agent"
|
|
6
|
+
import { Provider } from "../../provider/provider"
|
|
7
|
+
import path from "path"
|
|
8
|
+
import fs from "fs/promises"
|
|
9
|
+
import matter from "gray-matter"
|
|
10
|
+
import { Instance } from "../../project/instance"
|
|
11
|
+
import { EOL } from "os"
|
|
12
|
+
import type { Argv } from "yargs"
|
|
13
|
+
|
|
14
|
+
type AgentMode = "all" | "primary" | "subagent"
|
|
15
|
+
|
|
16
|
+
const AVAILABLE_TOOLS = [
|
|
17
|
+
"bash",
|
|
18
|
+
"read",
|
|
19
|
+
"write",
|
|
20
|
+
"edit",
|
|
21
|
+
"list",
|
|
22
|
+
"glob",
|
|
23
|
+
"grep",
|
|
24
|
+
"webfetch",
|
|
25
|
+
"task",
|
|
26
|
+
"todowrite",
|
|
27
|
+
"todoread",
|
|
28
|
+
]
|
|
29
|
+
|
|
30
|
+
const AgentCreateCommand = cmd({
|
|
31
|
+
command: "create",
|
|
32
|
+
describe: "create a new agent",
|
|
33
|
+
builder: (yargs: Argv) =>
|
|
34
|
+
yargs
|
|
35
|
+
.option("path", {
|
|
36
|
+
type: "string",
|
|
37
|
+
describe: "directory path to generate the agent file",
|
|
38
|
+
})
|
|
39
|
+
.option("description", {
|
|
40
|
+
type: "string",
|
|
41
|
+
describe: "what the agent should do",
|
|
42
|
+
})
|
|
43
|
+
.option("mode", {
|
|
44
|
+
type: "string",
|
|
45
|
+
describe: "agent mode",
|
|
46
|
+
choices: ["all", "primary", "subagent"] as const,
|
|
47
|
+
})
|
|
48
|
+
.option("tools", {
|
|
49
|
+
type: "string",
|
|
50
|
+
describe: `comma-separated list of tools to enable (default: all). Available: "${AVAILABLE_TOOLS.join(", ")}"`,
|
|
51
|
+
})
|
|
52
|
+
.option("model", {
|
|
53
|
+
type: "string",
|
|
54
|
+
alias: ["m"],
|
|
55
|
+
describe: "model to use in the format of provider/model",
|
|
56
|
+
}),
|
|
57
|
+
async handler(args) {
|
|
58
|
+
await Instance.provide({
|
|
59
|
+
directory: process.cwd(),
|
|
60
|
+
async fn() {
|
|
61
|
+
const cliPath = args.path
|
|
62
|
+
const cliDescription = args.description
|
|
63
|
+
const cliMode = args.mode as AgentMode | undefined
|
|
64
|
+
const cliTools = args.tools
|
|
65
|
+
|
|
66
|
+
const isFullyNonInteractive = cliPath && cliDescription && cliMode && cliTools !== undefined
|
|
67
|
+
|
|
68
|
+
if (!isFullyNonInteractive) {
|
|
69
|
+
UI.empty()
|
|
70
|
+
prompts.intro("Create agent")
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const project = Instance.project
|
|
74
|
+
|
|
75
|
+
// Determine scope/path
|
|
76
|
+
let targetPath: string
|
|
77
|
+
if (cliPath) {
|
|
78
|
+
targetPath = path.join(cliPath, "agent")
|
|
79
|
+
} else {
|
|
80
|
+
let scope: "global" | "project" = "global"
|
|
81
|
+
if (project.vcs === "git") {
|
|
82
|
+
const scopeResult = await prompts.select({
|
|
83
|
+
message: "Location",
|
|
84
|
+
options: [
|
|
85
|
+
{
|
|
86
|
+
label: "Current project",
|
|
87
|
+
value: "project" as const,
|
|
88
|
+
hint: Instance.worktree,
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
label: "Global",
|
|
92
|
+
value: "global" as const,
|
|
93
|
+
hint: Global.Path.config,
|
|
94
|
+
},
|
|
95
|
+
],
|
|
96
|
+
})
|
|
97
|
+
if (prompts.isCancel(scopeResult)) throw new UI.CancelledError()
|
|
98
|
+
scope = scopeResult
|
|
99
|
+
}
|
|
100
|
+
targetPath = path.join(
|
|
101
|
+
scope === "global" ? Global.Path.config : path.join(Instance.worktree, ".bincode"),
|
|
102
|
+
"agent",
|
|
103
|
+
)
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Get description
|
|
107
|
+
let description: string
|
|
108
|
+
if (cliDescription) {
|
|
109
|
+
description = cliDescription
|
|
110
|
+
} else {
|
|
111
|
+
const query = await prompts.text({
|
|
112
|
+
message: "Description",
|
|
113
|
+
placeholder: "What should this agent do?",
|
|
114
|
+
validate: (x) => (x && x.length > 0 ? undefined : "Required"),
|
|
115
|
+
})
|
|
116
|
+
if (prompts.isCancel(query)) throw new UI.CancelledError()
|
|
117
|
+
description = query
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// Generate agent
|
|
121
|
+
const spinner = prompts.spinner()
|
|
122
|
+
spinner.start("Generating agent configuration...")
|
|
123
|
+
const model = args.model ? Provider.parseModel(args.model) : undefined
|
|
124
|
+
const generated = await Agent.generate({ description, model }).catch((error) => {
|
|
125
|
+
spinner.stop(`LLM failed to generate agent: ${error.message}`, 1)
|
|
126
|
+
if (isFullyNonInteractive) process.exit(1)
|
|
127
|
+
throw new UI.CancelledError()
|
|
128
|
+
})
|
|
129
|
+
spinner.stop(`Agent ${generated.identifier} generated`)
|
|
130
|
+
|
|
131
|
+
// Select tools
|
|
132
|
+
let selectedTools: string[]
|
|
133
|
+
if (cliTools !== undefined) {
|
|
134
|
+
selectedTools = cliTools ? cliTools.split(",").map((t) => t.trim()) : AVAILABLE_TOOLS
|
|
135
|
+
} else {
|
|
136
|
+
const result = await prompts.multiselect({
|
|
137
|
+
message: "Select tools to enable",
|
|
138
|
+
options: AVAILABLE_TOOLS.map((tool) => ({
|
|
139
|
+
label: tool,
|
|
140
|
+
value: tool,
|
|
141
|
+
})),
|
|
142
|
+
initialValues: AVAILABLE_TOOLS,
|
|
143
|
+
})
|
|
144
|
+
if (prompts.isCancel(result)) throw new UI.CancelledError()
|
|
145
|
+
selectedTools = result
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// Get mode
|
|
149
|
+
let mode: AgentMode
|
|
150
|
+
if (cliMode) {
|
|
151
|
+
mode = cliMode
|
|
152
|
+
} else {
|
|
153
|
+
const modeResult = await prompts.select({
|
|
154
|
+
message: "Agent mode",
|
|
155
|
+
options: [
|
|
156
|
+
{
|
|
157
|
+
label: "All",
|
|
158
|
+
value: "all" as const,
|
|
159
|
+
hint: "Can function in both primary and subagent roles",
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
label: "Primary",
|
|
163
|
+
value: "primary" as const,
|
|
164
|
+
hint: "Acts as a primary/main agent",
|
|
165
|
+
},
|
|
166
|
+
{
|
|
167
|
+
label: "Subagent",
|
|
168
|
+
value: "subagent" as const,
|
|
169
|
+
hint: "Can be used as a subagent by other agents",
|
|
170
|
+
},
|
|
171
|
+
],
|
|
172
|
+
initialValue: "all" as const,
|
|
173
|
+
})
|
|
174
|
+
if (prompts.isCancel(modeResult)) throw new UI.CancelledError()
|
|
175
|
+
mode = modeResult
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// Build tools config
|
|
179
|
+
const tools: Record<string, boolean> = {}
|
|
180
|
+
for (const tool of AVAILABLE_TOOLS) {
|
|
181
|
+
if (!selectedTools.includes(tool)) {
|
|
182
|
+
tools[tool] = false
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// Build frontmatter
|
|
187
|
+
const frontmatter: {
|
|
188
|
+
description: string
|
|
189
|
+
mode: AgentMode
|
|
190
|
+
tools?: Record<string, boolean>
|
|
191
|
+
} = {
|
|
192
|
+
description: generated.whenToUse,
|
|
193
|
+
mode,
|
|
194
|
+
}
|
|
195
|
+
if (Object.keys(tools).length > 0) {
|
|
196
|
+
frontmatter.tools = tools
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// Write file
|
|
200
|
+
const content = matter.stringify(generated.systemPrompt, frontmatter)
|
|
201
|
+
const filePath = path.join(targetPath, `${generated.identifier}.md`)
|
|
202
|
+
|
|
203
|
+
await fs.mkdir(targetPath, { recursive: true })
|
|
204
|
+
|
|
205
|
+
const file = Bun.file(filePath)
|
|
206
|
+
if (await file.exists()) {
|
|
207
|
+
if (isFullyNonInteractive) {
|
|
208
|
+
console.error(`Error: Agent file already exists: ${filePath}`)
|
|
209
|
+
process.exit(1)
|
|
210
|
+
}
|
|
211
|
+
prompts.log.error(`Agent file already exists: ${filePath}`)
|
|
212
|
+
throw new UI.CancelledError()
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
await Bun.write(filePath, content)
|
|
216
|
+
|
|
217
|
+
if (isFullyNonInteractive) {
|
|
218
|
+
console.log(filePath)
|
|
219
|
+
} else {
|
|
220
|
+
prompts.log.success(`Agent created: ${filePath}`)
|
|
221
|
+
prompts.outro("Done")
|
|
222
|
+
}
|
|
223
|
+
},
|
|
224
|
+
})
|
|
225
|
+
},
|
|
226
|
+
})
|
|
227
|
+
|
|
228
|
+
const AgentListCommand = cmd({
|
|
229
|
+
command: "list",
|
|
230
|
+
describe: "list all available agents",
|
|
231
|
+
async handler() {
|
|
232
|
+
await Instance.provide({
|
|
233
|
+
directory: process.cwd(),
|
|
234
|
+
async fn() {
|
|
235
|
+
const agents = await Agent.list()
|
|
236
|
+
const sortedAgents = agents.sort((a, b) => {
|
|
237
|
+
if (a.native !== b.native) {
|
|
238
|
+
return a.native ? -1 : 1
|
|
239
|
+
}
|
|
240
|
+
return a.name.localeCompare(b.name)
|
|
241
|
+
})
|
|
242
|
+
|
|
243
|
+
for (const agent of sortedAgents) {
|
|
244
|
+
process.stdout.write(`${agent.name} (${agent.mode})${EOL}`)
|
|
245
|
+
}
|
|
246
|
+
},
|
|
247
|
+
})
|
|
248
|
+
},
|
|
249
|
+
})
|
|
250
|
+
|
|
251
|
+
export const AgentCommand = cmd({
|
|
252
|
+
command: "agent",
|
|
253
|
+
describe: "manage agents",
|
|
254
|
+
builder: (yargs) => yargs.command(AgentCreateCommand).command(AgentListCommand).demandCommand(),
|
|
255
|
+
async handler() {},
|
|
256
|
+
})
|