bitfolk 0.0.0-stage → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +32 -0
- package/README.md +207 -2
- package/dist/bin.js +14 -0
- package/dist/cli.js +96 -0
- package/package.json +51 -4
package/LICENSE
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
Bitfolk CLI License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 NQB8. All rights reserved.
|
|
4
|
+
|
|
5
|
+
This package ("the Software") is proprietary to NQB8 and is not open source. It is licensed, not sold.
|
|
6
|
+
|
|
7
|
+
1. Permitted use. You may install and run the Software, unmodified, on computers you control, for the sole purpose
|
|
8
|
+
of using the Bitfolk service at https://bitfolk.ai under your Bitfolk account and the Bitfolk Terms of Service.
|
|
9
|
+
|
|
10
|
+
2. Restrictions. Except as allowed by applicable law despite this limitation, you may not:
|
|
11
|
+
a. copy, modify, translate or create derivative works of the Software, except for the copies made when you
|
|
12
|
+
install and run it;
|
|
13
|
+
b. decompile, disassemble, deobfuscate, reverse engineer or otherwise try to derive its source code;
|
|
14
|
+
c. distribute, sublicense, sell, rent, lend, host or otherwise make the Software available to anyone else,
|
|
15
|
+
including publishing it or any part of it to a package registry or repository;
|
|
16
|
+
d. use the Software, or any part of it, to build or train a competing product or service, or with any service
|
|
17
|
+
other than Bitfolk;
|
|
18
|
+
e. remove or change any notice of ownership in the Software.
|
|
19
|
+
|
|
20
|
+
3. Ownership. NQB8 keeps all rights, title and interest in the Software, including all intellectual property
|
|
21
|
+
rights. Bitfolk and the Bitfolk logo are trademarks of NQB8. No rights are granted except as stated above.
|
|
22
|
+
|
|
23
|
+
4. Termination. This license ends automatically if you break any of its terms, or when your access to the Bitfolk
|
|
24
|
+
service ends. You must then stop using and delete the Software.
|
|
25
|
+
|
|
26
|
+
5. No warranty. The Software is provided "as is", without warranty of any kind, express or implied, including
|
|
27
|
+
warranties of merchantability, fitness for a particular purpose and non-infringement.
|
|
28
|
+
|
|
29
|
+
6. Limitation of liability. To the extent allowed by law, NQB8 is not liable for any indirect, incidental, special,
|
|
30
|
+
consequential or punitive damages, or any loss of data, profits or revenue, arising from the Software or its use.
|
|
31
|
+
|
|
32
|
+
Questions: https://bitfolk.ai
|
package/README.md
CHANGED
|
@@ -1,3 +1,208 @@
|
|
|
1
|
-
#
|
|
1
|
+
# bitfolk: the Bitfolk runner
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Lets your [Bitfolk](https://bitfolk.ai) team start Claude Code, Codex, OpenCode and Hermes sessions on your own
|
|
4
|
+
computer. It checks in without calling a model (a few bytes) and starts a session only when you ask for one, from any
|
|
5
|
+
device. Each session runs as a temporary builder that works one goal and leaves. Every run is recorded on your team
|
|
6
|
+
with what it cost.
|
|
7
|
+
|
|
8
|
+
## Install
|
|
9
|
+
|
|
10
|
+
Needs Node 20 or newer, on macOS or Linux (on Windows, use WSL), and at least one coding tool such as Claude Code or
|
|
11
|
+
Codex, signed in.
|
|
12
|
+
|
|
13
|
+
Try it without installing:
|
|
14
|
+
|
|
15
|
+
```
|
|
16
|
+
npx bitfolk@latest login # link this computer: name it, tick its coding tools, press Allow
|
|
17
|
+
npx bitfolk@latest up # keep this running; sessions start when your team asks
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Or install it to keep it:
|
|
21
|
+
|
|
22
|
+
```
|
|
23
|
+
npm i -g bitfolk
|
|
24
|
+
bitfolk login
|
|
25
|
+
bitfolk set --repo ~/code/app # builders work in their own worktrees of this repo
|
|
26
|
+
bitfolk up
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
The rest of this page writes `bitfolk`; with npx, type `npx bitfolk` instead. `@latest` makes npx fetch the newest
|
|
30
|
+
release rather than reuse one it cached. Installed, it also answers to the short name `bf` (`bf up`).
|
|
31
|
+
|
|
32
|
+
## Commands
|
|
33
|
+
|
|
34
|
+
| Command | |
|
|
35
|
+
|---|---|
|
|
36
|
+
| `bitfolk` | Where things stand: this computer, its team, tools on and off, sessions waiting, whether `up` runs (also `bitfolk status`) |
|
|
37
|
+
| `bitfolk login` / `logout` | Link this computer in your browser, or unlink it |
|
|
38
|
+
| `bitfolk up` | Run the sessions your team starts, until Ctrl-C (also `bitfolk start`) |
|
|
39
|
+
| `bitfolk tools` | The coding tools found here, on or off |
|
|
40
|
+
| `bitfolk add <tool>` / `rm <tool>` | Turn a tool on or off, or add your own with `--command` or `--acp` |
|
|
41
|
+
| `bitfolk set --repo <path>` | Give sessions a git repo; `--max-usd`, `--max-runs`, `--timeout`, `--permission` change limits |
|
|
42
|
+
| `bitfolk share <port>` | Share an app running here at a link |
|
|
43
|
+
| `bitfolk check` | Check sign-in, tools and repo (also `bitfolk doctor`) |
|
|
44
|
+
| `bitfolk bug "<what>"` | Report a bug |
|
|
45
|
+
|
|
46
|
+
`bitfolk help <command>` shows a command's options. Older forms keep working: `tool add`, `tool rm`, `ls`, `doctor`,
|
|
47
|
+
`set machine`.
|
|
48
|
+
|
|
49
|
+
On a terminal, waits show a twinkling loader with the time so far, and `bitfolk up` keeps one live line under its log
|
|
50
|
+
(listening, builders working, cost so far). In a pipe, a log file, CI, or with `NO_COLOR`, `--no-color`, `TERM=dumb` or
|
|
51
|
+
`BITFOLK_NO_ANIMATION=1`, it prints plain lines only.
|
|
52
|
+
|
|
53
|
+
## Linking a computer
|
|
54
|
+
|
|
55
|
+
`bitfolk login` links the computer, not an agent. The consent screen asks for a name and which coding tools
|
|
56
|
+
it has (the CLI ticks the ones it finds). The browser hands a one-time code back to the CLI on `127.0.0.1` (a free
|
|
57
|
+
port the OS picks), and the CLI swaps it for tokens using PKCE. Nothing is pasted or shown.
|
|
58
|
+
|
|
59
|
+
- The computer shows up in Settings, Machines, with its last sessions and an Unlink button. `bitfolk logout` unlinks
|
|
60
|
+
it too.
|
|
61
|
+
- Its access token lasts an hour and the runner renews it. The refresh token rotates on every renewal; unused for 90
|
|
62
|
+
days, the link ends and the runner asks you to log in again.
|
|
63
|
+
- `bitfolk login --no-browser` prints the link instead. The redirect still has to reach this computer's `127.0.0.1`.
|
|
64
|
+
|
|
65
|
+
## Coding tools
|
|
66
|
+
|
|
67
|
+
`bitfolk tools` scans for the coding tools it knows, on your PATH and in the usual install folders (`~/.local/bin`,
|
|
68
|
+
`/opt/homebrew/bin`, `~/.bun/bin`, `~/.cargo/bin` and others), with each one's version.
|
|
69
|
+
|
|
70
|
+
- Built in: Claude Code, Codex, OpenCode (`opencode run --format json`) and Hermes Agent (`hermes -z`). The ones found
|
|
71
|
+
are ticked on the consent screen; `bitfolk add opencode` turns one on later.
|
|
72
|
+
- Over ACP (below): Gemini CLI, Goose, Cursor Agent, GitHub Copilot CLI, Qwen Code, Cline and Kimi Code.
|
|
73
|
+
- Recognised but not built in: Aider, Amp, Crush, Factory Droid and DeepSeek Harness. `bitfolk tools` and
|
|
74
|
+
`bitfolk login` suggest a command for each; check it runs headless.
|
|
75
|
+
- Anything else: `bitfolk add <name> --command "<cmd>"`. The command gets the work packet on stdin and can print
|
|
76
|
+
`{"bitfolk":{"summary":"...","cost_usd":0.01}}` lines to report back.
|
|
77
|
+
- OpenCode has no per-run permission flags, so its own config decides what it may do. Hermes gets `--yolo` outside
|
|
78
|
+
safe mode.
|
|
79
|
+
|
|
80
|
+
### ACP tools
|
|
81
|
+
|
|
82
|
+
The [Agent Client Protocol](https://agentclientprotocol.com) (ACP) is a standard way for a program to drive a coding
|
|
83
|
+
agent over stdio. The runner speaks ACP v1 itself: it starts the tool (`gemini --acp`, `goose acp`, `cursor-agent acp`,
|
|
84
|
+
`copilot --acp`, `qwen --acp`, `cline --acp`, `kimi acp`), opens a session in the worktree, sends the work packet as
|
|
85
|
+
one prompt, and answers the tool's permission requests. `bitfolk tools` marks these "via ACP".
|
|
86
|
+
`bitfolk add <name> --acp "<command>"` adds any other ACP agent (the command runs without a shell).
|
|
87
|
+
|
|
88
|
+
- **Sign in to the tool in a terminal first.** The runner never signs in for it and sets `NO_BROWSER=1`; a session
|
|
89
|
+
that needs a login fails with the tool's own hint. `bitfolk check` starts each ACP tool, says hello (no session,
|
|
90
|
+
no prompt, no model call) and prints its name, version and sign-in methods.
|
|
91
|
+
- **Safe mode is best effort.** The runner allows reads and edits inside the worktree only (never `~/.bitfolk`, and
|
|
92
|
+
no edits to `.git`, git hook setups such as `.husky/`, or agent settings such as `.claude/` or `opencode.json`, in any
|
|
93
|
+
letter case), and shell commands only when they are a plain `bitfolk-api ...` or read-mostly `git ...` with no shell
|
|
94
|
+
features (no `git commit` or `git switch` in a repo with git hooks: the runner commits the work itself, with hooks
|
|
95
|
+
off). It always answers "allow once" or "reject once". But it only sees what the tool asks about: the tool's own
|
|
96
|
+
settings and allowlists can let it do more without asking. Gemini CLI doesn't say which command it wants to run, so
|
|
97
|
+
in safe and auto mode it can read and edit files but not run shell commands.
|
|
98
|
+
- **Auto mode doesn't protect the token.** It allows other commands unless they use network tools, print the
|
|
99
|
+
environment, climb out of the worktree with `..` or touch the Bitfolk folder; that list is a speed bump, not a
|
|
100
|
+
sandbox, and a determined agent can still read the session's token file (it sits next to the worktree, under
|
|
101
|
+
`~/.bitfolk`). The tool gets no `BITFOLK_TOKEN` in its environment, only the file's path.
|
|
102
|
+
- **The budget cap is approximate.** ACP has no spend limit, so the runner stops the turn once the cost the tool
|
|
103
|
+
reports passes `--max-usd`. Cost arrives after it is spent, so one large call can go over; tools that report no
|
|
104
|
+
cost (or report it in credits) are limited only by `--timeout` and `--max-runs`.
|
|
105
|
+
- The runner commits what an ACP tool leaves in its worktree. Each run is a new ACP session (no resume yet).
|
|
106
|
+
- OpenCode and Hermes also speak ACP, but stay on their own adapters for now.
|
|
107
|
+
|
|
108
|
+
## Sessions
|
|
109
|
+
|
|
110
|
+
On a goal, press **Run on <computer>**: pick Claude Code or Codex, optionally one task and a note. `bitfolk up` sees it
|
|
111
|
+
on its next check-in (a few bytes, no model) and starts a session:
|
|
112
|
+
|
|
113
|
+
1. `POST /v1/machine/claim` makes a temporary builder: an agent on that goal, already set up, with a token that ends
|
|
114
|
+
with the session.
|
|
115
|
+
2. The runner starts the tool in the builder's own workspace (a worktree on `bitfolk/builder-<id>` when a repo is
|
|
116
|
+
set) with a work packet that names the goal, the task and your note.
|
|
117
|
+
3. The builder claims the task, works it and reports through `bitfolk-api`, like any agent. Its runs and spend are
|
|
118
|
+
recorded.
|
|
119
|
+
4. `POST /v1/machine/sessions/{id}` reports how it ended. The builder leaves the team: its token stops working and
|
|
120
|
+
unfinished tasks go back on the board. Its branch stays for you to review.
|
|
121
|
+
|
|
122
|
+
Limits from `bitfolk set` apply to each session; Bitfolk times out a session the runner never reports.
|
|
123
|
+
|
|
124
|
+
While a session runs, the runner tells the team what its tool is doing every 10 seconds when anything changed
|
|
125
|
+
(`POST /v1/machine/sessions/{id}/progress`): short lines such as "Editing app/signup/page.tsx" or "Running pnpm test",
|
|
126
|
+
and the running tokens and cost. That is what your phone shows. The lines are clipped to 200 characters, and anything
|
|
127
|
+
shaped like a token (`bfa_`, `bfm_`, `sk-`, `gh*_`, `xox*-`) becomes `[redacted]`. A custom tool can print
|
|
128
|
+
`{"bitfolk":{"activity":"..."}}` to say what it's doing. The reply also says when you canceled the session.
|
|
129
|
+
|
|
130
|
+
In a repo, the runner also saves a **checkpoint** of the session's worktree every 3 minutes when anything changed, and
|
|
131
|
+
once more when the tool stops: everything in the folder, committed or not (ignored files excepted), as a commit on a
|
|
132
|
+
hidden ref, `refs/bitfolk/checkpoints/<session id>`. Saving never touches the branch, the index or the files, so it
|
|
133
|
+
can't get in the tool's way, and branch lists and pushes don't show it. Only the ids go to the team
|
|
134
|
+
(`POST /v1/machine/sessions/{id}/checkpoint`: the branch, the commit the session started from, the branch head, the
|
|
135
|
+
checkpoint and the tool's own session id); the code stays on your computer. Checkpoints older than 30 days are pruned.
|
|
136
|
+
|
|
137
|
+
A finished session can be asked for again on the same computer, with a note saying what should change (**Fix** or
|
|
138
|
+
**Redo** on the session, in Settings or the app):
|
|
139
|
+
|
|
140
|
+
- **Fix** continues on the session's branch, in the same folder. The work it hadn't committed comes back from its last
|
|
141
|
+
checkpoint (unless the branch moved on since), and Claude Code, Codex and OpenCode resume the earlier conversation.
|
|
142
|
+
If that conversation is gone, the fix starts fresh on the same branch.
|
|
143
|
+
- **Redo** starts a new branch from the commit the first try started from. The first try stays on its branch.
|
|
144
|
+
|
|
145
|
+
When a reviewer sends back a task that a session did, its builder has already left the team, so the task goes back on
|
|
146
|
+
the board and the Mayor queues a fix on that computer with the review notes. Only one fix of a branch waits at a time.
|
|
147
|
+
|
|
148
|
+
On a Mac, `bitfolk up` keeps the computer awake while it runs (`caffeinate -i`, tied to the runner, so it ends when
|
|
149
|
+
the runner does). The screen can still sleep. Closing the lid on battery still sleeps the Mac and pauses sessions.
|
|
150
|
+
`bitfolk up --let-sleep` turns this off.
|
|
151
|
+
|
|
152
|
+
## Long-lived agents
|
|
153
|
+
|
|
154
|
+
`bitfolk add bfa_...` still adds a permanent agent with a token copied from its page on your team, and `bitfolk up`
|
|
155
|
+
runs it here alongside sessions. `bitfolk set <agent> ...` changes its options and `bitfolk rm "<agent>" --agent`
|
|
156
|
+
removes it. A bare `bitfolk rm` takes only an agent's exact name (`--agent` also takes the start of its id), and it
|
|
157
|
+
stops if the agent's worktree has uncommitted changes unless you add `--force`.
|
|
158
|
+
|
|
159
|
+
## What it does on a wake
|
|
160
|
+
|
|
161
|
+
1. `GET /v1/peek` with the last ETag. Silent, or 304: wait as long as the server says.
|
|
162
|
+
2. `POST /v1/runs` records the start. That marks the agent's wake channel as `bridge`. A paused agent gets a 409 and
|
|
163
|
+
doesn't start.
|
|
164
|
+
3. Starts the runtime in the agent's own workspace with a work packet on stdin:
|
|
165
|
+
- With `--repo`: one persistent git worktree per agent in `~/.bitfolk/worktrees/<name>`, on branch
|
|
166
|
+
`bitfolk/<name>`. The agent never touches your checkout, and its session resumes between wakes.
|
|
167
|
+
- Without a repo: a plain folder in `~/.bitfolk/agents/<name>`.
|
|
168
|
+
- Codex in `safe` mode can't commit: its sandbox keeps every `.git` folder read-only. The packet tells it to leave
|
|
169
|
+
its changes, and the runner commits them to its branch when the run ends, with its last line as the message.
|
|
170
|
+
4. The agent calls Bitfolk only through `bitfolk-api METHOD /v1/path [JSON]`, a helper the runner puts on its PATH.
|
|
171
|
+
The helper adds the token from the environment, so the token never shows up in a prompt, a command or a
|
|
172
|
+
transcript.
|
|
173
|
+
5. `POST /v1/runs/{id}` reports the status, exit code, session, tokens, cost (null on subscription logins) and the
|
|
174
|
+
agent's one-line summary. Owners see it in `public.agent_runs` and `public.agent_run_spend`.
|
|
175
|
+
|
|
176
|
+
## Limits
|
|
177
|
+
|
|
178
|
+
| Option | Default | |
|
|
179
|
+
|---|---|---|
|
|
180
|
+
| `--max-usd` | 1 | Hard spend cap per run (Claude Code's `--max-budget-usd`); approximate for ACP tools |
|
|
181
|
+
| `--max-runs` | 6 | Most runs per rolling hour |
|
|
182
|
+
| `--timeout` | 45 | Minutes before a run is stopped |
|
|
183
|
+
| `--permission` | safe | `safe`: edits in its worktree, `bitfolk-api`, read-mostly git, no curl. `auto`: the runtime's auto mode. `bypass`: no prompts (only on a machine you'd hand over) |
|
|
184
|
+
|
|
185
|
+
Bitfolk's own approval rules (`POST /v1/actions`) apply on top, wherever the agent runs.
|
|
186
|
+
|
|
187
|
+
## Report a bug
|
|
188
|
+
|
|
189
|
+
```
|
|
190
|
+
bitfolk bug "bitfolk up exits after the first wake on Linux"
|
|
191
|
+
bitfolk check 2>&1 | bitfolk bug --email you@company.com
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
It sends the text, the CLI version and your OS to bitfolk.ai/api/bugs. No token is sent.
|
|
195
|
+
|
|
196
|
+
## Files
|
|
197
|
+
|
|
198
|
+
`~/.bitfolk` (or `$BITFOLK_HOME`): `config.json` (tokens, mode 600), `state.json` (ETags, sessions, run times),
|
|
199
|
+
`logs/<name>/*.jsonl` (each run's output, token redacted), `bin/bitfolk-api`, `worktrees/`.
|
|
200
|
+
|
|
201
|
+
## Develop
|
|
202
|
+
|
|
203
|
+
`pnpm --filter bitfolk test`. `node src/main.ts --help` runs from source (Node 22.18+ strips the types);
|
|
204
|
+
`pnpm --filter bitfolk build` type checks, then writes `dist/` for publishing: a small launcher (`dist/bin.js`) and the whole CLI as one minified file (`dist/cli.js`).
|
|
205
|
+
|
|
206
|
+
## License
|
|
207
|
+
|
|
208
|
+
Proprietary: see [LICENSE](LICENSE). You may run the CLI to use Bitfolk; you may not copy, modify, redistribute or reverse engineer it.
|
package/dist/bin.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Bitfolk CLI. Copyright (c) 2026 NQB8. All rights reserved. Use is subject to the LICENSE file in this package.
|
|
3
|
+
// The published entry. It has no static imports, so an old Node gets this message instead of a SyntaxError from
|
|
4
|
+
// main's imports (ESM links every import before any line runs).
|
|
5
|
+
const [major] = process.versions.node.split(".").map(Number);
|
|
6
|
+
if ((major ?? 0) < 20) {
|
|
7
|
+
console.error(`bitfolk needs Node 20 or newer; this is ${process.version}. Update it from https://nodejs.org (or brew install node).`);
|
|
8
|
+
process.exit(1);
|
|
9
|
+
}
|
|
10
|
+
if (process.platform === "win32") {
|
|
11
|
+
console.error("bitfolk runs on macOS and Linux for now. On Windows, run it inside WSL.");
|
|
12
|
+
process.exit(1);
|
|
13
|
+
}
|
|
14
|
+
await import("./cli.js");
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
// Bitfolk CLI. Copyright (c) 2026 NQB8. All rights reserved. Use is subject to the LICENSE file in this package.
|
|
2
|
+
import{createRequire as e}from"node:module";import{execFileSync as t,spawn as n}from"node:child_process";import{basename as r,delimiter as i,dirname as a,isAbsolute as o,join as s,relative as c,resolve as l,sep as u}from"node:path";import{parseArgs as d}from"node:util";import{accessSync as f,appendFileSync as p,chmodSync as m,constants as h,copyFileSync as g,existsSync as _,lstatSync as v,mkdirSync as y,mkdtempSync as b,readFileSync as x,readdirSync as ee,realpathSync as te,renameSync as ne,rmSync as re,statSync as ie,writeFileSync as ae}from"node:fs";import{homedir as oe,hostname as se,tmpdir as ce}from"node:os";import{createInterface as le}from"node:readline";import{createHash as ue,randomBytes as de,randomUUID as fe}from"node:crypto";import{createServer as pe}from"node:http";import{connect as S}from"node:net";const C=/[\\/]_npx[\\/]/.test(process.argv[1]??``)?`npx bitfolk`:`bitfolk`,me=C!==`bitfolk`;function he(e){let t=e;for(let e=0;e<4;e++)if(typeof t==`string`){let e=t.trim();if(!e.startsWith(`{`))return e.slice(0,300)||null;try{t=JSON.parse(e)}catch{return e.slice(0,300)}}else if(t&&typeof t==`object`){let e=t;if(t=e.message??e.error??null,t===null)return null}else return null;return typeof t==`string`?t.slice(0,300):null}const ge=()=>({sessionId:null,inputTokens:0,outputTokens:0,costMicros:null,isError:!1,overBudget:!1,summary:null,error:null,model:null}),w=`[redacted]`,_e=[[/\bbf[a-z]{0,2}_[A-Za-z0-9]{8,}/g,w],[/\bsk-[A-Za-z0-9_-]{8,}/g,w],[/\b(?:sk|rk|pk)_(?:live|test)_[A-Za-z0-9]{8,}/g,w],[/\bgh[pousr]_[A-Za-z0-9]{8,}/g,w],[/\bgithub_pat_[A-Za-z0-9_]{20,}/g,w],[/\bxox[a-z]-[A-Za-z0-9-]{8,}/g,w],[/\beyJ[\w-]{10,}\.[\w-]{10,}\.[\w-]+/g,w],[/\bAKIA[0-9A-Z]{16}\b/g,w],[/\bsb_(?:secret|publishable)_[A-Za-z0-9_-]{8,}/g,w],[/\bAIza[0-9A-Za-z_-]{30,}/g,w],[/-----BEGIN [A-Z ]*PRIVATE KEY-----[\s\S]*/g,w],[/\b(bearer|basic)(\s+)[A-Za-z0-9._~+/=-]{8,}/gi,`$1$2${w}`],[/\b([A-Z0-9_]*(?:KEY|TOKEN|SECRET|PASSWORD|PASSWD|PWD|PASS|AUTH|CREDENTIALS?)[A-Z0-9_]*)(\s*[=:]\s*)("[^"]*"|'[^']*'|\S+)/g,`$1$2${w}`],[/(--?(?:password|passwd|token|secret|api-?key|auth)(?:=|\s+))("[^"]*"|'[^']*'|\S+)/gi,`$1${w}`],[/(\bmysql\b.*?\s-p)(\S+)/g,`$1${w}`],[/(\b[a-z][a-z0-9+.-]*:\/\/[^\s:/@]+:)[^\s@/]+@/gi,`$1${w}@`]];function T(e){let t=e;for(let[e,n]of _e)t=t.replace(e,n);return t}function E(e){if(typeof e!=`string`)return null;let t=e.split(`
|
|
3
|
+
`).map(e=>e.trim()).find(Boolean);if(!t)return null;let n=T(t.replace(/\s+/g,` `));return n.length>200?n.slice(0,199)+`…`:n}function D(e,t){if(typeof e!=`string`||!e)return`a file`;if(t&&o(e)){let n=c(t,e);if(n&&!n.startsWith(`..`)&&!o(n))return n}return e}function ve(e){let t=Array.isArray(e)?e.length>=3&&/sh$/.test(String(e[0]))&&/^-l?c$/.test(String(e[1]))?String(e.at(-1)):e.join(` `):String(e??``),n=/^(?:\S*\/)?(?:ba|z)?sh\s+-l?c\s+(['"])([\s\S]*)\1$/.exec(t.trim());return T((n?n[2]:t).trim().replace(/\s+/g,` `)).slice(0,80)}function ye(e,t,n){let r=String(e??``).toLowerCase(),i=t.file_path??t.filePath??t.path??t.notebook_path;return[`edit`,`write`,`multiedit`,`notebookedit`,`patch`].includes(r)?`Editing ${D(i,n)}`:r===`read`?`Reading ${D(i,n)}`:r===`bash`?`Running ${ve(t.command)}`:r===`grep`||r===`glob`?`Searching ${T(String(t.pattern??``)).slice(0,80)}`.trim():`Using ${String(e??`a tool`)}`}const be=[`Bash(bitfolk-api:*)`,`Bash(git status:*)`,`Bash(git diff:*)`,`Bash(git log:*)`,`Bash(git show:*)`,`Bash(git add:*)`,`Bash(git commit:*)`,`Bash(git switch:*)`,`Bash(git branch:*)`];function O(e){let t=e.trim();if(!t.startsWith(`{`))return null;try{return JSON.parse(t)}catch{return null}}const k=(e,t=280)=>typeof e==`string`&&e.trim()?e.trim().replace(/\s+/g,` `).slice(0,t):null,A=e=>k(typeof e==`string`?e.trim().split(`
|
|
4
|
+
`).filter(Boolean).at(-1):null);function xe(e){return e===`bypass`?[`--permission-mode`,`bypassPermissions`]:e===`auto`?[`--permission-mode`,`auto`]:[`--permission-mode`,`acceptEdits`,`--allowedTools`,...be]}const Se={runtime:`claude_code`,bin:()=>`claude`,launch(e,t,n){return{bin:`claude`,args:[`-p`,`--output-format`,`stream-json`,`--verbose`,`--max-budget-usd`,String(e.maxUsdPerRun),...e.model?[`--model`,e.model]:[],...n?[`--resume`,n]:[],...xe(e.permission)],stdin:t}},parse(e,t){let n=O(e);if(!n)return;typeof n.session_id==`string`&&(t.sessionId=n.session_id),n.type===`system`&&typeof n.model==`string`&&(t.model=n.model);let r=n.message;if(n.type===`assistant`&&r?.usage&&r.id!==t.countedMessage){t.countedMessage=r.id;let e=r.usage;t.inputTokens+=(e.input_tokens??0)+(e.cache_creation_input_tokens??0)+(e.cache_read_input_tokens??0),t.outputTokens+=e.output_tokens??0}if(n.type===`result`){let e=n.usage??{};t.inputTokens=(e.input_tokens??0)+(e.cache_creation_input_tokens??0)+(e.cache_read_input_tokens??0),t.outputTokens=e.output_tokens??0,typeof n.total_cost_usd==`number`&&(t.costMicros=Math.round(n.total_cost_usd*1e6)),t.isError=n.is_error===!0||typeof n.subtype==`string`&&n.subtype!==`success`,t.isError&&(t.error=he(n.result)??(typeof n.subtype==`string`?n.subtype:null)),t.overBudget=typeof n.subtype==`string`&&n.subtype.includes(`budget`),t.summary=A(n.result)??t.summary}},activity(e,t){let n=O(e);if(n?.type!==`assistant`||!Array.isArray(n.message?.content))return null;let r=n.message.content,i=r.find(e=>e?.type===`tool_use`);return E(i?ye(i.name,i.input??{},t):r.find(e=>e?.type===`text`)?.text)}};function Ce(e){return e===`bypass`?[`--dangerously-bypass-approvals-and-sandbox`]:[`-c`,`sandbox_mode="workspace-write"`,`-c`,`sandbox_workspace_write.network_access=true`]}const we={claude_code:Se,codex:{runtime:`codex`,bin:()=>`codex`,runnerCommits:e=>e.permission!==`bypass`,launch(e,t,n){return{bin:`codex`,args:[`exec`,...n?[`resume`,n]:[],`--json`,`--skip-git-repo-check`,...Ce(e.permission),...e.model?[`-m`,e.model]:[],`-`],stdin:t}},parse(e,t){let n=O(e);n&&(n.type===`thread.started`&&typeof n.thread_id==`string`&&(t.sessionId=n.thread_id),n.type===`turn.completed`&&n.usage&&(t.inputTokens+=n.usage.input_tokens??0,t.outputTokens+=n.usage.output_tokens??0),(n.type===`turn.failed`||n.type===`error`)&&(t.isError=!0,t.error=he(n.error??n.message)??t.error),n.type===`item.completed`&&n.item?.type===`agent_message`&&(t.summary=A(n.item.text)??t.summary))},activity(e,t){let n=O(e),r=n?.item;if(!r||n.type!==`item.started`&&n.type!==`item.completed`)return null;if(r.type===`command_execution`)return n.type===`item.started`?E(`Running ${ve(r.command)}`):null;if(n.type!==`item.completed`)return null;if(r.type===`file_change`){let e=(Array.isArray(r.changes)?r.changes:[]).map(e=>D(e?.path,t));return e.length?E(`Editing ${e[0]}${e.length>1?` and ${e.length-1} more`:``}`):null}return r.type===`agent_message`?E(r.text):null}},opencode:{runtime:`opencode`,bin:()=>`opencode`,launch(e,t,n){return{bin:`opencode`,args:[`run`,`--format`,`json`,...e.model?[`-m`,e.model]:[],...n?[`-s`,n]:[],t],stdin:``}},parse(e,t){let n=O(e);if(!n)return;typeof n.sessionID==`string`&&(t.sessionId=n.sessionID);let r=n.part??{};if(n.type===`text`&&typeof r.text==`string`&&(t.summary=A(r.text)??t.summary),n.type===`step_finish`){let e=r.tokens??{};t.inputTokens+=(e.input??0)+(e.cache?.read??0)+(e.cache?.write??0),t.outputTokens+=(e.output??0)+(e.reasoning??0),typeof r.cost==`number`&&(t.costMicros=(t.costMicros??0)+Math.round(r.cost*1e6))}n.type===`error`&&(t.isError=!0,t.error=he(n.error?.data?.message??n.error?.message??n.error)??t.error)},activity(e,t){let n=O(e),r=n?.part??{};return n?.type===`tool_use`&&r.tool?E(ye(r.tool,r.state?.input??{},t)):n?.type===`text`?E(r.text):null}},hermes:{runtime:`hermes`,bin:()=>`hermes`,resumes:!1,launch(e,t){let n=s(ce(),`bitfolk-hermes-${fe()}.json`);return{bin:`hermes`,args:[`-z`,t,`--usage-file`,n,...e.model?[`-m`,e.model]:[],...e.permission===`safe`?[]:[`--yolo`]],stdin:``,usageFile:n}},parse(e,t){t.summary=k(e)??t.summary},activity:e=>E(e),afterExit(e,t){if(e.usageFile)try{let n=JSON.parse(x(e.usageFile,`utf8`)),r=(...e)=>e.map(e=>n[e]??n.usage?.[e]).find(e=>typeof e==`number`);t.inputTokens=r(`input_tokens`,`prompt_tokens`)??t.inputTokens,t.outputTokens=r(`output_tokens`,`completion_tokens`)??t.outputTokens;let i=r(`cost_usd`,`total_cost_usd`,`cost`);i!==void 0&&(t.costMicros=Math.round(i*1e6)),typeof n.session_id==`string`&&(t.sessionId=n.session_id)}catch{}finally{re(e.usageFile,{force:!0})}}},command:{runtime:`command`,bin:e=>(e.command??``).trim().split(/\s+/)[0]??``,resumes:!1,launch(e,t){if(!e.command)throw Error(`${e.name} has runtime command but no --command`);return{bin:`sh`,args:[`-c`,e.command],stdin:t}},parse(e,t){let n=O(e)?.bitfolk;n&&typeof n==`object`?(typeof n.session_id==`string`&&(t.sessionId=n.session_id),typeof n.input_tokens==`number`&&Number.isFinite(n.input_tokens)&&(t.inputTokens=Math.max(0,Math.round(n.input_tokens))),typeof n.output_tokens==`number`&&Number.isFinite(n.output_tokens)&&(t.outputTokens=Math.max(0,Math.round(n.output_tokens))),typeof n.cost_usd==`number`&&(t.costMicros=Math.round(n.cost_usd*1e6)),typeof n.summary==`string`&&(t.summary=k(n.summary))):t.summary=k(e)??t.summary},activity(e){return E(O(e)?.bitfolk?.activity)}},acp:{runtime:`acp`,bin:e=>e.acp?.bin??``,resumes:!1,runnerCommits:()=>!0,launch(e){if(!e.acp?.bin)throw Error(`${e.name} has runtime acp but no ACP command`);return{bin:e.acp.bin,args:e.acp.args,stdin:``}},parse(){}}};function Te(e){return e===`claude_code`||e===`codex`||e===`opencode`||e===`hermes`?e:null}const Ee=2e4;var De=class extends Error{code;data;constructor(e,t,n){super(t),this.code=e,this.data=n}};const Oe=e=>new De(-32601,`${e} isn't supported by this client`);var ke=class{#e=1;#t=new Map;#n;#r;#i=null;constructor(e,t,n){this.#n=e,this.#r=n,e.on(`error`,e=>this.close(Error(`the tool stopped reading its input (${e.code??e.message})`))),le({input:t,crlfDelay:1/0}).on(`line`,e=>this.#o(e)).on(`close`,()=>this.close(Error(`the tool exited before the turn ended`)))}get closed(){return this.#i!==null}close(e){if(!this.#i){this.#i=e;for(let[t,n]of this.#t)n.timer&&clearTimeout(n.timer),this.#t.delete(t),n.reject(e)}}end(){try{this.#n.end()}catch{}}#a(e){if(this.#i||!this.#n.writable)return!1;try{return this.#n.write(JSON.stringify({jsonrpc:`2.0`,...e})+`
|
|
5
|
+
`),!0}catch(e){return this.close(Error(`the tool stopped reading its input (${e.message})`)),!1}}request(e,t,n){if(this.#i)return Promise.reject(this.#i);let r=this.#e++;return new Promise((i,a)=>{let o={method:e,resolve:i,reject:a};n&&(o.timer=setTimeout(()=>{this.#t.delete(r),a(Error(`${e} got no answer within ${Math.round(n/1e3)}s`))},n),o.timer.unref?.()),this.#t.set(r,o),this.#a({id:r,method:e,params:t})||(this.#t.delete(r),o.timer&&clearTimeout(o.timer),a(this.#i??Error(`the tool's input is closed`)))})}notify(e,t){this.#a({method:e,params:t})}#o(e){if(this.#i)return;let t=e.trim();if(!t)return;let n;try{n=JSON.parse(t)}catch{n=null}if(!n||typeof n!=`object`||Array.isArray(n)){this.close(Error(`the tool printed something that isn't ACP on stdout: ${T(t).slice(0,120)}`)),this.#r.protocolError(t);return}let r=n.id!==void 0&&n.id!==null;if(typeof n.method==`string`&&r)return void this.#s(n.id,n.method,n.params);if(typeof n.method==`string`)try{this.#r.notification(n.method,n.params)}catch{}else if(r&&(`result`in n||`error`in n)){let e=this.#t.get(n.id);if(!e)return;if(this.#t.delete(n.id),e.timer&&clearTimeout(e.timer),n.error){let t=n.error;e.reject(new De(typeof t.code==`number`?t.code:-32603,typeof t.message==`string`?t.message:`error`,t.data))}else e.resolve(n.result)}}async#s(e,t,n){try{let r=await this.#r.request(t,n);this.#a({id:e,result:r??null})}catch(t){let n=t instanceof De?t:new De(-32603,t.message);this.#a({id:e,error:{code:n.code,message:n.message}})}}};const Ae=/[$`\\\n\r]/,je=/[;&|<>(){}[\]*?~]/,Me=/[$`;&|<>\\*?~\n\r(){}[\]]/;function Ne(e){if(typeof e!=`string`||Ae.test(e))return null;let t=[],n=``,r=!1,i=null;for(let a of e)if(i)a===i?i=null:n+=a;else if(a===`'`||a===`"`)i=a,r=!0;else if(/\s/.test(a))r&&t.push(n),n=``,r=!1;else if(je.test(a))return null;else n+=a,r=!0;return i?null:(r&&t.push(n),t)}function Pe(e){let t=Ne(e.trim());if(!t)throw Error(`give the command without shell features ($, ~, pipes, ; or backslashes); use a full path instead of ~`);let[n,...r]=t;if(!n)throw Error(`the command is empty`);return{bin:n,args:r}}function Fe(e){if(!e||typeof e!=`object`)return null;let t=e,n=t.command??t.cmd??t.commandLine,r=e=>Array.isArray(e)&&e.length>0&&e.every(e=>typeof e==`string`);return typeof n==`string`?r(t.args)?[n,...t.args]:n:r(n)?n:null}const Ie=e=>/^(?:\/(?:usr\/)?bin\/)?(?:ba|z|da)?sh$/.test(e);function Le(e){let t;if(typeof e==`string`)t=Ne(e);else{if(!e.every(e=>typeof e==`string`))return null;if(e.length===3&&Ie(e[0])&&/^-l?c$/.test(e[1]))return Ne(e[2]);t=e.some(e=>Me.test(e))?null:e.slice()}return!t||t.length===0?null:t.length===3&&Ie(t[0])&&/^-l?c$/.test(t[1])?Ne(t[2]):t}const Re=new Set([`status`,`diff`,`log`,`show`,`add`,`commit`,`switch`,`branch`]),ze=/^(?:-o|-F|-t|--output|--exec-path|--no-index|--file|--template|--git-dir|--work-tree|--namespace|--upload-pack|--receive-pack|--ext-diff|--pathspec-from-file|--config-env|--super-prefix)(?:=|$)/;function Be(e){let[t,n,...r]=e;if(t===`bitfolk-api`)return e.slice(1).some(e=>e.startsWith(`@`))?`it would upload a local file`:null;if(t===`git`){if(!n||!Re.has(n))return`that git command isn't on the safe list`;for(let e of r){if(ze.test(e))return`git ${e.split(`=`)[0]} isn't allowed in safe mode`;if(/^-[A-Za-z]*[Fot]/.test(e)&&!e.startsWith(`--`))return`git ${e} isn't allowed in safe mode`;if(e.startsWith(`/`)||/=\//.test(e)||/^-[A-Za-z]+\//.test(e)||/(?:^|[/=])\.\.(?:\/|$)/.test(e))return`git with a path outside its worktree isn't allowed in safe mode`}return null}return`only bitfolk-api and read-mostly git run in safe mode`}const Ve=new Set([`curl`,`wget`,`nc`,`ncat`,`netcat`,`ssh`,`scp`,`sftp`,`telnet`,`ftp`,`socat`,`rsync`,`http`,`https`,`xh`]),He=new Set([`env`,`printenv`]);function Ue(e,t){let n=(Array.isArray(e)?e.join(` `):e).replace(/['"\\]/g,``),r=[t,qe(t)].filter(e=>e&&e!==`/`);if(/\.bitfolk\b/i.test(n)||/bitfolk_/i.test(n)||r.some(e=>n.includes(e)))return`it touches the Bitfolk folder or its variables`;if(/\/proc\/\S*environ/.test(n))return`it reads a process environment`;if(/(?:^|[\s/=:,;&|()<>])\.\.(?:$|[\s/=:,;&|()<>])/.test(n))return`it climbs out of its worktree (..)`;let i=oe(),a=i?n.replace(/\$\{HOME\}|\$HOME\b/g,i).replace(/(^|[\s=:,;&|(<>])~(?=\/|$|[\s;&|)<>])/g,`$1${i}`):n,o=r.map(e=>e.toLowerCase());for(let e of a.split(/[\s;&|()<>`{}=:,]+/)){if(!e.startsWith(`/`))continue;let t=e.search(/[*?[]/);if(t>=0){let n=e.slice(0,e.lastIndexOf(`/`,t)+1).toLowerCase();if(o.some(e=>(e+`/`).startsWith(n)))return`it could reach the Bitfolk folder`;continue}let n=qe(e.replace(/\/+$/,``)||`/`).toLowerCase();if(o.some(e=>e===n||e.startsWith(n.endsWith(`/`)?n:n+`/`)))return`it could reach the Bitfolk folder`}let s=n.split(/[\s;&|()<>`${}]+/).filter(Boolean).map(e=>e.split(`/`).pop()??e);return s.some(e=>Ve.has(e))?`it uses a network tool`:s.some(e=>He.has(e))||/(?:^|[;&|(]\s*)(?:set|export|declare|typeset)(?:\s+-p\b|\s*$|\s*[;&|)])/.test(n)||/\bcompgen\s+-[ev]/.test(n)?`it could print the environment`:null}function We(e,t){let n={...e??{}};if(t&&typeof t==`object`)for(let[e,r]of Object.entries(t))r!=null&&(n[e]=r);return n}const Ge=/^(?:paths?|files?|file_?paths?|notebook_?path|absolute_?path|dir_?path|dir|directory|folder|cwd|workdir|working_?directory|source|destination|target|old_?path|new_?path|target_?file|target_?directory)$/i;function Ke(e){let t=[],n=(e,r)=>{if(!(!e||typeof e!=`object`||r>3)){if(Array.isArray(e))return e.forEach(e=>n(e,r+1));for(let[i,a]of Object.entries(e)){if(Ge.test(i)){if(typeof a==`string`)t.push(a);else if(Array.isArray(a))for(let e of a)typeof e==`string`&&t.push(e)}a&&typeof a==`object`&&n(a,r+1)}}};n(e.rawInput,0);for(let n of Array.isArray(e.content)?e.content:[]){let e=n;e&&e.type===`diff`&&typeof e.path==`string`&&t.push(e.path)}return t}function qe(e){try{return te(e)}catch{let t=a(e);return t===e?e:s(qe(t),r(e))}}const Je=(e,t)=>e===t||e.startsWith(t.endsWith(u)?t:t+u),Ye=new Set([`.claude`,`.opencode`,`.gemini`,`.cursor`,`.kilocode`,`.codex`,`.qwen`,`.cline`,`.kimi`]),Xe=new Set([`opencode.json`,`opencode.jsonc`]),Ze=new Set([`.husky`,`.githooks`,`.lefthook`,`.git-hooks`,`git-hooks`]),Qe=/^(?:\.pre-commit-config\.ya?ml|\.pre-commit-hooks\.ya?ml|\.?lefthook(?:-local)?\.(?:ya?ml|json|toml)|\.overcommit\.ya?ml|\.lintstagedrc(?:\..+)?|lint-staged\.config\..+|\.simple-git-hooks(?:\..+)?|simple-git-hooks\..+)$/;function $e(e){return e.normalize(`NFC`).replace(/[---]/g,``).toLowerCase()}function et(e,t){if(typeof e!=`string`||!e||e.includes(`\0`))return`an empty path`;if(!o(e))return`a relative path`;if(e.split(/[\\/]/).includes(`..`))return`a path with ..`;let n=qe(t.cwd),r=qe(e);if(!Je(r,n))return Je(r,qe(t.home))?`a path in the Bitfolk folder`:`a path outside its worktree`;if(t.write){let e=c(n,r).split(u).filter(Boolean).map($e);if(e.includes(`.git`))return`git's own files`;if(e.some(e=>Ye.has(e)||e.startsWith(`.goose`)||Xe.has(e)))return`an agent settings file`;if(e.some(e=>Ze.has(e)||Qe.test(e)))return`a git hook setup`}return null}function tt(e){let n;try{let r=t(`git`,[`-C`,e,`-c`,`core.fsmonitor=false`,`rev-parse`,`--git-path`,`hooks`],{encoding:`utf8`,stdio:[`ignore`,`pipe`,`ignore`],timeout:5e3}).trim();if(!r||r===`/dev/null`)return!1;n=o(r)?r:s(e,r)}catch{return!1}try{return ee(n).some(e=>{if(e.endsWith(`.sample`))return!1;try{let t=ie(s(n,e));return t.isFile()&&!!(t.mode&73)}catch{return!1}})}catch{return!1}}function nt(e,t){if(typeof e!=`string`||!e)return`a file`;let n=D(e,t);if(n!==e)return n;let r=oe();return r&&r!==`/`&&(e===r||e.startsWith(r+u))?`~`+e.slice(r.length):e}function rt(e,t){let n=e.rawInput&&typeof e.rawInput==`object`?e.rawInput:{},r=typeof e.title==`string`&&e.title.trim()?e.title.trim():null,i=Ke(e)[0]??e.locations?.find(e=>typeof e?.path==`string`)?.path,a=e=>i?`${e} ${nt(i,t)}`:r?`${e} ${r.replace(RegExp(`^${e}\\s+`,`i`),``)}`:`${e} a file`,o=e=>typeof e==`string`&&e?e:null;switch(e.kind){case`execute`:{let e=Fe(n);return E(`Running ${e?ve(e):r??`a command`}`)}case`edit`:return E(a(`Editing`));case`delete`:return E(a(`Deleting`));case`move`:return E(a(`Moving`));case`read`:return E(a(`Reading`));case`search`:return E(`Searching ${T(o(n.pattern)??o(n.query)??r??``).slice(0,80)}`.trim());case`fetch`:return E(`Fetching ${o(n.url)??r??`a web page`}`);case`think`:return null;case`switch_mode`:return E(`Switching mode${r?`: ${r}`:``}`);default:return E(r?`Using ${r}`:`Using a tool`)}}const it=new Set([`read`,`search`,`edit`,`delete`,`move`]),at=new Set([`edit`,`delete`,`move`]);function ot(e){let{toolCall:t,permission:n,cwd:r,home:i}=e,a=Array.isArray(e.options)?e.options.filter(e=>e&&typeof e.optionId==`string`):[],o=rt(t,r)??(t.kind===`think`?`Thinking`:`Using a tool`),s=(e,t)=>{if(e){let n=a.find(e=>e.kind===`allow_once`);if(n)return{allow:e,reason:t,what:o,cancelTurn:!1,outcome:{outcome:{outcome:`selected`,optionId:n.optionId}}};t=`${t}, but the tool offered no allow-once choice`}let n=a.find(e=>e.kind===`reject_once`);return n?{allow:!1,reason:t,what:o,cancelTurn:!1,outcome:{outcome:{outcome:`selected`,optionId:n.optionId}}}:{allow:!1,reason:`${t}; no reject-once choice, so the turn stops`,what:o,cancelTurn:!0,outcome:{outcome:{outcome:`cancelled`}}}},c=t.kind;if(typeof c!=`string`||!c)return s(!1,`the tool didn't say what kind of call this is`);if(n===`bypass`)return s(!0,`bypass mode`);if(n!==`safe`&&n!==`auto`)return s(!1,`unknown permission mode`);if(c===`think`)return s(!0,`thinking`);let l=Ke(t);for(let e of l){let t=et(e,{cwd:r,home:i,write:at.has(c)});if(t)return s(!1,`${t}: ${nt(e,r)}`)}if(it.has(c))return l.length===0?s(!1,`no file path in the request`):s(!0,at.has(c)?`a change inside its worktree`:`inside its worktree`);if(c===`execute`){let a=Fe(t.rawInput);if(!a)return s(!1,`the command isn't in a shape the runner can check`);if(n===`safe`){let t=Le(a);if(!t)return s(!1,`the command uses shell features (safe mode allows a plain command only)`);let n=Be(t);return n?s(!1,n):t[0]===`git`&&(t[1]===`commit`||t[1]===`switch`)&&(e.gitHooks??tt(r))?s(!1,`this repo has git hooks, which can run anything; the runner commits the work when the turn ends`):s(!0,`on the safe list`)}let o=Ue(a,i);return o?s(!1,o):s(!0,`auto mode`)}return c===`fetch`?n===`auto`?s(!0,`auto mode allows the web`):s(!1,`safe mode doesn't fetch from the web`):c===`switch_mode`?s(!1,`changing the agent's mode needs its owner`):s(!1,`${c===`other`?`tools of kind other (MCP and the like)`:`kind ${c}`} aren't allowed in ${n} mode`)}const st={opencode:{safe:`build`,auto:`build`,bypass:`build`},gemini:{safe:`default`,auto:`default`,bypass:`yolo`},cursor_agent:{safe:`agent`,auto:`agent`,bypass:`agent`}};function ct(e){let t=[];for(let n of Array.isArray(e.options)?e.options:[]){let e=n;if(typeof e?.value==`string`&&t.push(e.value),Array.isArray(e?.options))for(let n of e.options)typeof n?.value==`string`&&t.push(n.value)}return t}const lt={refusal:`the agent refused to go on (refusal)`,max_tokens:`the agent hit its output token limit (max_tokens)`,max_turn_requests:`the agent hit its limit of model requests for one turn (max_turn_requests)`};var ut=class{#e;#t;#n=null;#r=!1;#i=[];#a=null;#o=null;#s=null;#c=new Map;#l=null;#u=null;#d=!1;#f=[];#p=0;#m=0;#h=!1;#g=!1;#_=!1;constructor(e){this.#e=e,this.#t=new ke(e.stdin,e.stdout,{request:(e,t)=>this.#w(e,t),notification:(e,t)=>this.#E(e,t),protocolError:t=>{e.log(`out`,t.length>Ee?`[a ${Math.round(t.length/1e3)} KB line that isn't ACP]`:t),e.kill()}})}get cancelReason(){return this.#a}#v(e){let t=JSON.stringify(e);this.#e.log(`acp`,t.length>Ee?JSON.stringify({note:`skipped a ${Math.round(t.length/1e3)} KB entry`,...`event`in e?{event:e.event}:{}}):t)}cancel(e){return this.#_?!1:this.#a?!0:(this.#a=e,this.#v({event:`cancel`,reason:e}),!this.#n||this.#t.closed?(this.#e.kill(),!0):(this.#t.notify(`session/cancel`,{sessionId:this.#n}),this.#s=setTimeout(()=>this.#e.kill(),this.#e.cancelGraceMs??1e4),this.#s.unref?.(),!0))}async run(){let e=this.#e,t=e.handshakeMs??3e4,n;try{let r=await this.#t.request(`initialize`,{protocolVersion:1,clientCapabilities:{},clientInfo:{name:`bitfolk`,version:e.clientVersion}},t);if(r?.protocolVersion!==1)throw Error(`${e.label} speaks ACP v${String(r?.protocolVersion??`?`)}; this runner speaks v1`);if(this.#r=!!r?.agentCapabilities?.sessionCapabilities?.close,this.#i=Array.isArray(r?.authMethods)?r.authMethods:[],this.#v({event:`initialize`,agent:r?.agentInfo??null,auth:this.#i.map(e=>e?.id),close:this.#r}),this.#a)throw Error(`stopped before the session started`);let i=await this.#t.request(`session/new`,{cwd:e.cwd,mcpServers:[]},t);if(typeof i?.sessionId!=`string`)throw Error(`${e.label} started no session`);if(this.#n=i.sessionId,e.tally.sessionId=i.sessionId,await this.#S(i),this.#a)throw Error(`stopped before the prompt`);e.log(`acp`,JSON.stringify({event:`prompt`,chars:e.packet.length}));let a=await this.#t.request(`session/prompt`,{sessionId:this.#n,prompt:[{type:`text`,text:e.packet}]});this.#O(),this.#A(a?.usage);let o=typeof a?.stopReason==`string`?a.stopReason:null;this.#v({event:`turn`,stopReason:o,usage:a?.usage??null}),n={ok:o===`end_turn`,stopReason:o,exited:!1,error:o===`end_turn`?null:this.#y(o)}}catch(e){this.#O(),n={ok:!1,stopReason:null,exited:!1,error:this.#b(e)},!(e instanceof De)&&/exited|stopped reading/.test(e.message)&&(n.exited=!0),this.#v({event:`turn`,error:n.error})}return e.tally.summary=A(this.#u)??e.tally.summary,n.ok||(e.tally.isError=!0,e.tally.overBudget&&e.tally.error||(e.tally.error=n.error)),await this.#j(),n}#y(e){return e===`cancelled`?this.#a===`policy`?this.#o??`the turn was stopped`:this.#a===`budget`?`went over its $${this.#e.agent.maxUsdPerRun} budget`:this.#a===`owner`?`stopped by its owner`:this.#a===`timeout`?`stopped: out of time`:`the agent cancelled the turn`:(e&<[e])??`the agent stopped (${e??`no reason given`})`}#b(e){if(this.#a===`policy`&&this.#o)return this.#o;if(e instanceof De){if(e.code===-32e3)return this.#x();let t=e.data;return he(t&&typeof t==`object`&&t.details!==void 0?t.details:e.message)??e.message}return e.message}#x(){let e=this.#i.map(e=>e?.description??e?.name).filter(e=>typeof e==`string`&&!!e.trim());return e.length?`sign in to ${this.#e.label} in a terminal on this computer first: ${e.join(`; `)}`.slice(0,300):`sign in to ${this.#e.label} in a terminal on this computer first`}async#S(e){let t=this.#e,n=this.#n,r=t.agent.acp.agent,i=st[r]?.[t.agent.permission],a=Array.isArray(e?.configOptions)?e.configOptions.filter(e=>e&&typeof e.id==`string`):[];this.#v({event:`session`,sessionId:n,config:a.map(e=>({id:e.id,category:e.category??null,current:e.currentValue??null})),modes:e?.modes?{current:e.modes.currentModeId??null,available:(e.modes.availableModes??[]).map(e=>e?.id)}:null});let o=async(e,r)=>{let i=await this.#t.request(`session/set_config_option`,{sessionId:n,configId:e.id,value:r},t.handshakeMs??3e4);a=Array.isArray(i?.configOptions)?i.configOptions.filter(e=>e&&typeof e.id==`string`):a.map(t=>t.id===e.id?{...t,currentValue:r}:t)},s=e=>a.find(t=>t.category===e)??a.find(t=>t.id===e);if(a.length){let e=s(`mode`);if(i&&e&&e.currentValue!==i&&ct(e).includes(i))try{await o(e,i),this.#v({event:`mode`,mode:i})}catch(e){this.#v({event:`mode`,mode:i,error:this.#b(e)})}let n=s(`model`);if(t.agent.model&&n&&n.currentValue!==t.agent.model)try{await o(n,t.agent.model)}catch(e){this.#v({event:`model`,wanted:t.agent.model,error:this.#b(e),using:s(`model`)?.currentValue??null})}else t.agent.model&&!n&&this.#v({event:`model`,wanted:t.agent.model,error:`${t.label} offers no model choice over ACP; it uses its own`})}else if(e?.modes&&Array.isArray(e.modes.availableModes)){let r=e.modes.availableModes.map(e=>e?.id);if(i&&e.modes.currentModeId!==i&&r.includes(i))try{await this.#t.request(`session/set_mode`,{sessionId:n,modeId:i},t.handshakeMs??3e4),this.#v({event:`mode`,mode:i})}catch(e){this.#v({event:`mode`,mode:i,error:this.#b(e)})}t.agent.model&&this.#v({event:`model`,wanted:t.agent.model,error:`${t.label} offers no model choice over ACP; it uses its own`})}if(this.#C(a),!a.some(e=>e.category===`model`||e.id===`model`)&&typeof e?.models?.currentModelId==`string`&&e.models.currentModelId&&(t.tally.model=e.models.currentModelId,t.agent.model&&t.agent.model!==e.models.currentModelId&&this.#v({event:`model`,wanted:t.agent.model,using:e.models.currentModelId,error:`${t.label} can't change its model over ACP`})),t.agent.permission===`safe`&&!st[r]){let e=`safe mode is enforced through ${t.label}'s permission requests; its own settings may allow more`;t.log(`acp`,JSON.stringify({event:`note`,note:e})),t.activity(E(e))}}#C(e){if(!Array.isArray(e))return;this.#f=e.filter(e=>e&&typeof e.id==`string`);let t=this.#f.find(e=>e.category===`model`)??this.#f.find(e=>e.id===`model`);typeof t?.currentValue==`string`&&t.currentValue&&(this.#e.tally.model=t.currentValue)}#w(e,t){if(e===`session/request_permission`)return this.#T(t);throw this.#v({event:`unsupported`,method:e}),Oe(e)}#T(e){if(this.#a)return{outcome:{outcome:`cancelled`}};let t=typeof e?.toolCall?.toolCallId==`string`?e.toolCall.toolCallId:null,n=We(t?this.#c.get(t):void 0,e?.toolCall);t&&this.#c.set(t,n);let r=ot({toolCall:n,options:e?.options??[],permission:this.#e.agent.permission,cwd:this.#e.cwd,home:this.#e.home});if(!r.allow&&n.kind===`execute`&&!Fe(n.rawInput)&&!this.#g){this.#g=!0;let e=`${this.#e.label} doesn't say which command it wants to run, so ${this.#e.agent.permission} mode can't allow shell commands; it can still read and edit files in its worktree`;this.#e.log(`acp`,JSON.stringify({event:`note`,note:e})),this.#e.activity(E(e))}let i=r.outcome.outcome.outcome===`selected`?r.outcome.outcome.optionId:null;return this.#v({event:`permission`,decision:r.allow?`allowed`:`refused`,what:r.what,kind:n.kind??null,reason:T(r.reason),option:i}),this.#e.activity(E(`${r.allow?`Allowed`:`Refused`}: ${r.what}`)),r.cancelTurn&&(this.#o=`refused ${r.what.charAt(0).toLowerCase()}${r.what.slice(1)}, and ${this.#e.label} offered no way to refuse just that, so the turn was stopped`.slice(0,300),setImmediate(()=>this.cancel(`policy`))),r.outcome}#E(e,t){if(e!==`session/update`)return;let n=t?.update;if(n&&typeof n==`object`&&!(this.#n&&t.sessionId&&t.sessionId!==this.#n))switch(n.sessionUpdate){case`agent_message_chunk`:n.content?.type===`text`&&typeof n.content.text==`string`&&this.#D(n.content.text,typeof n.messageId==`string`?n.messageId:null);return;case`tool_call`:case`tool_call_update`:{let e=typeof n.toolCallId==`string`?n.toolCallId:null,t=e?this.#c.get(e):void 0;n.sessionUpdate!==`tool_call`&&t||(this.#d=!0,this.#l&&!this.#l.id&&this.#O());let r=We(t,n);if(e&&this.#c.set(e,r),n.sessionUpdate===`tool_call`||!t){let e=rt(r,this.#e.cwd);e&&(this.#e.activity(e),this.#v({event:`tool`,kind:r.kind??null,what:e}))}return}case`usage_update`:return this.#k(n.cost);case`config_option_update`:return this.#C(n.configOptions);case`current_mode_update`:return this.#v({event:`mode`,mode:n.currentModeId??n.modeId??null});default:return}}#D(e,t){let n=this.#l;(!n||(t?n.id!==t:this.#d))&&(this.#O(),this.#l={id:t,text:``}),this.#d=!1,this.#l.text+=e}#O(){let e=this.#l;this.#l=null,e&&e.text.trim()&&(this.#u=e.text,this.#e.log(`acp`,JSON.stringify({event:`message`,text:e.text.slice(0,4e3)})),this.#e.activity(E(e.text)))}#k(e){if(!e||typeof e!=`object`||typeof e.amount!=`number`||!Number.isFinite(e.amount))return;let t=this.#e.tally;if(String(e.currency??``).toUpperCase()!==`USD`){this.#h||(this.#h=!0,this.#v({event:`cost`,note:`cost comes in ${String(e.currency)}, not USD: no spend is recorded and the budget cap is off`})),t.costMicros=null;return}e.amount<this.#m&&(this.#p+=this.#m),this.#m=e.amount;let n=this.#p+e.amount;t.costMicros=Math.round(n*1e6),n>=this.#e.agent.maxUsdPerRun&&!t.overBudget&&(t.overBudget=!0,t.error=`spent $${n.toFixed(2)}, over its $${this.#e.agent.maxUsdPerRun} budget`,this.#e.activity(E(`Stopping: ${t.error}`)),this.cancel(`budget`))}#A(e){if(!e||typeof e!=`object`)return;let t=e=>typeof e==`number`&&Number.isFinite(e)&&e>0?Math.round(e):0,n=t(e.inputTokens),r=t(e.outputTokens),i=t(e.thoughtTokens),a=t(e.cachedReadTokens)+t(e.cachedWriteTokens),o=t(e.totalTokens);if(!n&&!r)return;let s=!o||o===n+r+i+a,c=this.#e.tally;c.inputTokens=s?n+a:n,c.outputTokens=s||o===n+r+i?r+i:r}async#j(){this.#_=!0,this.#s&&clearTimeout(this.#s),this.#n&&this.#r&&!this.#t.closed&&await this.#t.request(`session/close`,{sessionId:this.#n},2e3).catch(()=>{}),this.#s&&clearTimeout(this.#s),this.#t.close(Error(`the turn is over`)),this.#t.end(),this.#e.kill()}};async function dt(e,t={}){let r=n(e.bin,e.args,{cwd:t.cwd,env:{...t.env??process.env,NO_BROWSER:`1`},stdio:[`pipe`,`pipe`,`ignore`],detached:!0}),i=null;r.on(`error`,t=>{i=t.code===`ENOENT`?Error(`${e.bin} isn't installed or isn't on PATH`):t});let a=new ke(r.stdin,r.stdout,{request:e=>{throw Oe(e)},notification:()=>{},protocolError:()=>{}});try{let e=await a.request(`initialize`,{protocolVersion:1,clientCapabilities:{},clientInfo:{name:`bitfolk`,version:t.version??`0`}},t.timeoutMs??5e3);return{protocolVersion:e?.protocolVersion,agentInfo:e?.agentInfo&&typeof e.agentInfo==`object`?e.agentInfo:null,authMethods:Array.isArray(e?.authMethods)?e.authMethods:[]}}catch(e){throw i??e}finally{a.close(Error(`done`)),a.end();try{r.pid&&process.kill(-r.pid,`SIGKILL`)}catch{r.kill(`SIGKILL`)}}}const j=e(import.meta.url)(`../package.json`).version,ft=`https://bitfolk.ai`;var M=class extends Error{status;code;constructor(e,t,n){super(n),this.status=e,this.code=t}},pt=class{base;#e;constructor(e,t){this.base=e,this.#e=t}async call(e,t,n={}){let r=typeof this.#e==`string`?this.#e:await this.#e(),i;try{i=await fetch(`${this.base.replace(/\/+$/,``)}${t}`,{method:e,headers:{authorization:`Bearer ${r}`,"user-agent":`bitfolk-cli/${j}`,...n.body===void 0?{}:{"content-type":`application/json`},...n.headers},body:n.body===void 0?void 0:JSON.stringify(n.body),signal:AbortSignal.timeout(2e4)})}catch(e){throw new M(0,`network`,`can't reach ${this.base}: ${e.message}`)}return i}async json(e){let t=await e.json().catch(()=>null);if(!e.ok)throw new M(e.status,t?.error??`http_error`,t?.error??`HTTP ${e.status}`);return t}async request(e,t,n){return this.json(await this.call(e,t,{body:n}))}async setup(){return this.json(await this.call(`GET`,`/v1/setup`))}async peek(e){let t=await this.call(`GET`,`/v1/peek`,{headers:e?{"if-none-match":`"${e}"`}:{}});return t.status===304?null:this.json(t)}async status(e){await this.json(await this.call(`POST`,`/v1/status`,{body:{activity:e}}))}async runStart(e){let t=await this.call(`POST`,`/v1/runs`,{body:e});return t.status===404||t.status===405?null:this.json(t)}async runFinish(e,t){await this.json(await this.call(`POST`,`/v1/runs/${e}`,{body:t}))}},mt=class{#e;constructor(e,t){this.#e=new pt(e,t)}me(){return this.#e.request(`GET`,`/v1/machine`)}peek(){return this.#e.request(`GET`,`/v1/machine/peek`)}claim(e){return this.#e.request(`POST`,`/v1/machine/claim`,e)}setTools(e){return this.#e.request(`POST`,`/v1/machine/tools`,{runtimes:e})}finish(e,t){return this.#e.request(`POST`,`/v1/machine/sessions/${e}`,t)}openApp(e){return this.#e.request(`POST`,`/v1/machine/apps`,e)}beatApp(e){return this.#e.request(`POST`,`/v1/machine/apps/${e}`)}stopApp(e){return this.#e.request(`DELETE`,`/v1/machine/apps/${e}`)}async checkpoint(e,t){try{return(await this.#e.request(`POST`,`/v1/machine/sessions/${e}/checkpoint`,t))?.saved===!0}catch{return!1}}async progress(e,t){try{let n=await this.#e.request(`POST`,`/v1/machine/sessions/${e}/progress`,t);return{canceled:n?.canceled===!0,status:typeof n?.status==`string`?n.status:`running`}}catch(e){return{canceled:!1,status:e instanceof M&&(e.status===404||e.status===405)?`not_found`:`error`}}}};const ht=[`claude_code`,`codex`,`opencode`,`hermes`,`command`],gt=[`safe`,`auto`,`bypass`],_t={maxUsdPerRun:1,maxRunsPerHour:6,timeoutMin:45,permission:`safe`};function N(){return process.env.BITFOLK_HOME||s(oe(),`.bitfolk`)}function vt(){let e=N();return _(e)||y(e,{recursive:!0,mode:448}),e}function yt(e,t){if(!_(e))return t;try{return JSON.parse(x(e,`utf8`))}catch{throw Error(`${e} is not valid JSON. Fix or delete it.`)}}function bt(e,t){vt();let n=`${e}.${process.pid}.tmp`;ae(n,JSON.stringify(t,null,2)+`
|
|
6
|
+
`,{mode:384}),ne(n,e),m(e,384)}const xt=()=>s(N(),`config.json`),St=()=>s(N(),`state.json`);function P(){let e=yt(xt(),{version:1,maxConcurrent:2,agents:[]});return e.agents=e.agents.map(e=>({..._t,...e})),e.machine&&={..._t,...e.machine},e}const F=e=>bt(xt(),e),Ct=()=>yt(St(),{agents:{}}),wt=e=>bt(St(),e);function Tt(e,t=[]){let n=e.toLowerCase().normalize(`NFKD`).replace(/[^a-z0-9]+/g,`-`).replace(/^-+|-+$/g,``).slice(0,30)||`agent`,r=new Set(t),i=n;for(let e=2;r.has(i);e++)i=`${n}-${e}`;return i}function Et(e,t){let n=t.toLowerCase();return e.agents.find(e=>e.slug===n||e.name.toLowerCase()===n||e.id.startsWith(n))}function Dt(e,t){let n=t.workspace?.name??e.workspace,r=t.machine?.name||e.name;if(n===e.workspace&&r===e.name)return e;try{let t=P();return t.machine?.id===e.id?(t.machine={...t.machine,workspace:n,name:r},F(t),t.machine):e}catch{return{...e,workspace:n,name:r}}}const I={coral:`#f25c3b`,coralDark:`#c8432a`,grass:`#6fae4b`,grassDark:`#4c8a35`,gold:`#f2c14e`,sky:`#d7ecf7`,ink:`#0e0f11`},Ot={0:`#f0d27a`,1:`#d1a74c`,2:`#9c7433`,3:`#a9ab93`,4:`#7b7f6a`,8:`#22573a`,C:`#8a3c2a`,D:`#4b3326`,G:`#6fae4b`,H:`#4c8a35`,J:`#9bd36a`,L:`#fff3c4`,M:`#c99a3a`,O:`#337a4b`,P:`#7d4fc9`,Q:`#35692a`,R:`#c94f33`,V:`#cfc2a8`,W:`#e6dcc8`,Y:`#d79a22`,Z:`#9a9488`,c:`#b5523a`,d:`#5b3a29`,g:`#9fd3ea`,h:`#5fae6a`,j:`#c6ea8a`,k:`#f2c14e`,m:`#f4d58d`,o:`#32343a`,p:`#b06cff`,q:`#e8556d`,t:`#7a5236`,u:`#5b3a29`,w:`#fbf6ec`,y:`#f2c14e`,z:`#c9c2b4`},kt=[`#.....#..#.....##.......#..#....`,`#........#....#.........#..#....`,`####..#.####.####..###..#..#..#.`,`#...#.#..#....#...#...#.#..#.#..`,`#...#.#..#....#...#...#.#..##...`,`#...#.#..#....#...#...#.#..#.#..`,`####..#...##..#....###...#.#..#.`],L={cottage:[`..........oooooo.o33o.....`,`.......ooo001122oo33o.....`,`.....oo0000111122223o.....`,`....o0100111211222222o....`,`...o000001111111222222o...`,`...o000001111111222222o...`,`..o10010021121122222222o..`,`.o0000000111111112222222o.`,`.o0000000111111112222222o.`,`o121212121212121212121212o`,`.oddddddddddddddddddddddo.`,`.odwwdwwdwwuuuuwwdWWdWWdo.`,`.odwdwwwdwwttuuwwdWWWdWdo.`,`.oddwwwwdwwttuuwwdWWWWddo.`,`.odddddddddttuudddddddddo.`,`.odwLdLwdwwttukwwdWLdLWdo.`,`.odwdddwdwwttuuwwdWdddWdo.`,`.odwLdLwdwwttuuwwdWLdLWdo.`,`.odwqywpdwwttuuwwdyWqpWdo.`,`o444444444444444444444444o`],cabin:[`..o343o....oo...........`,`..o433o..ootuoo.........`,`..o33DooottDuuDoo.......`,`..o334otttttuuuuuoo.....`,`..o3DttDttDtuDuuDuuoo...`,`.ootttttttttuuuuuuuuuoo.`,`ottDttDttDttDuuDuuDuuDuo`,`omttttttttttttttttttttmo`,`oMuuuuuuuuuuuuuuuuuuuuMo`,`omttttttttttttttttttttmo`,`oMuuLLDLuuuuuuddDDugguMo`,`omttDDDDttttttddDDtggtmo`,`oMuuLLDLuuuuuuddDDuuuuMo`,`omttttttttttttddDDttttmo`,`oMuuuuuuuuuuuudkDDuuuuMo`,`omttttttttttttddDDttttmo`,`oMuuuuuuuuuuuuddDDuuuuMo`,`omttttttttttttddDDttttmo`,`oDDDDDDDDDDDDDDDDDDDDDDo`],roundhouse:[`..........ouuo..........`,`..........ouuo..........`,`.........o0112o.........`,`........o101222o........`,`.......o00111222o.......`,`......o0001111222o......`,`.....o100111212222o.....`,`.....o000011112222o.....`,`....o00001111122222o....`,`...o0010021121122222o...`,`..o000001111111222222o..`,`.o00000011111112222222o.`,`o2121212121212121212121o`,`.oo34333333433334Z44Zoo.`,`..o33334333dd343Z44Z4o..`,`..o43gL333ddDD3344Z44o..`,`..o33LL333ddDD334Z44Zo..`,`..o3333334ddDD33Z44Z4o..`,`..o3343333ddDk3344Z44o..`,`..o3333343ddDD344Z44Zo..`,`ooGJ433333ddDD33Z44ZGqoo`],barn:[`..........oooooo..........`,`........oottttttoo........`,`......oouuuuuDDDDDoo......`,`....oouuuuuuuDDDDDDDoo....`,`...ouuuuuuuwwwwDDDDDDDo...`,`..ouuuuuuuu1110DDDDDDDDo..`,`..ouuuuuuuu1211DDDDDDDDo..`,`.ouuuuuuuuu1111DDDDDDDDDo.`,`ouuuuuuuuuuuuDDDDDDDDDDDDo`,`uuuuuuuuuuuuuDDDDDDDDDDDDD`,`uuuuuuuuuuuuuDDDDDDDDDDDDD`,`oocCcCcCcCcCcCcCcCCRCRCCoo`,`.ocCcCcCcCcCcCcCcCCRCRCCo.`,`.ocCcCcCcwwwwwwwwCCRCRCCo.`,`.ocCgwgCcwwccwcwwCCgwgCCo.`,`.ocCwwwCcwwccwcwwCCwwwCCo.`,`.ocCgwgCcwcwcwwcwCCgwgCCo.`,`.ocCcCcCcwcwcwwcwCCRCRCCo.`,`.ocCcCcCcwccwwccwCCRCRCCo.`,`.ocCcCcCcwccwwccwCCRCRCCo.`,`oocCcCcCcwccwwccwCCRCRCCoo`,`11011111111111111111112111`],oak:[`.....oooo..........`,`....ojjjjoooooo....`,`...ojjjJJjjjjJJo...`,`..ojjjJJGjjjJJJo...`,`..ojJJJGjjJJJGGGo..`,`..oJGGGGJJJGGGGHo..`,`..ojGGHHjGGGHHHQo..`,`.ojJHHHQQGHHHHQGGo.`,`oJJJGGQjjJJJQQQGGGo`,`oJJGGGJJJJJGGGGGGHo`,`oGGGGJJGGGGGHGGHHQo`,`oQGHHHGGGGHHHHHHQQo`,`oQQHQQGGHHHQQQQQQQo`,`.oQQQQQHHQQQQQQQQo.`,`..ooooQQQQQQQoooo..`,`......oQQQQQo......`,`.......otuuo.......`,`.......ottuo.......`,`.......ottuo.......`,`.......otuuo.......`,`......ootuuoo......`,`.....outttuuuo.....`,`.....ooooooooo.....`],elm:[`........ojjjjo.....`,`....oooojjjjJJo....`,`...jjjjJjjJjGGo....`,`..ojjjJGJJGGGHjoo..`,`..ojjJJGJGGGHHJJJo.`,`..oJGGGGHGGjQJJGGo.`,`..oGGHHHQHJJJJGGGGo`,`..oJHHHQQJJJGGGGHHo`,`.ooJJJGGGJJGGHHHHQo`,`ojJJJGGjjJJGGHHJQQo`,`oJJGGGJJJGGGHJJJGo.`,`oGGGHHJGGGHHHGGGHHo`,`oGHHHQGGGHHHQGHHHQo`,`oQQQQQGHHQQQQQHQQQo`,`oQQQQQQQHQQQQQQQQQo`,`..ooooQQQQQQQQQQQo.`,`......ooQQQoo.ooo..`,`.......ottuo.......`,`.......ottuo.......`,`.......otuuo.......`,`......ootuuoo......`,`.....outttuuuo.....`,`.....ooooooooo.....`],pine:[`......oo......`,`.....oh8o.....`,`.....oh8o.....`,`.....hO8o.....`,`.....hO8o.....`,`....ohh88o....`,`....ohOO8o....`,`....ohOO8o....`,`...ohhh888o...`,`...ohhO888o...`,`..o88hOO888o..`,`...8hhOO88o...`,`..ohhOh8888...`,`..ohhhOO888o..`,`.o88hhOO8888o.`,`.oohhOOO888oo.`,`.ohhhOOO8888..`,`.ohhhOOO8888o.`,`o888888888888o`,`.ooooottooooo.`,`.....otto.....`,`.....ouuuo....`,`.....oooo.....`],bush:[`..oooooo..`,`.oJGGGGHo.`,`oJGpGGGqHo`,`oGGGGqGHHo`,`.ooooooooo`],sunflower:[`..oyyo..`,`.oyYYyo.`,`oyYddYyo`,`oyYddYyo`,`.oyYYyo.`,`..oyyo..`,`...oG.o.`,`.o.oGoGo`,`.oGoGo..`,`...oG...`],tulip:[`.o.o.o..`,`opopopo.`,`oPpPpPo.`,`oPPpPPo.`,`.oPPPo..`,`..ooo...`,`...oG.o.`,`.o.oGoGo`,`.oGoGo..`,`...oG...`]},At={claude_code:{palette:{A:`#3a302c`,B:`#5f3b2c`,C:`#503428`,D:`#48332a`,E:`#c8c8d0`,F:`#d3b196`,G:`#f8d0b0`,H:`#3a3640`,I:`#373337`,J:`#36363e`,K:`#9a5a48`,L:`#d97757`,M:`#bebebb`,N:`#fff4ec`,O:`#f8f8f8`,P:`#9fd3ea`,Q:`#44362e`,R:`#e8c040`,S:`#3a4058`,T:`#35394b`,U:`#f0f0f0`,V:`#b0b0bc`},down:[`.......AAAA........`,`....AAABBBBAAA.....`,`...ABBBBBBBBCDA....`,`..ABBBBBBCCBCCCA...`,`.ABBBBBCCCCCDCCCA..`,`.ABBBCDCCCCCCCCDA..`,`ABBBCCCCCCCCCCCDDA.`,`ABCCCBBCCCCDCDDDDA.`,`ACBDDDDDDDDDDDDDDA.`,`ACCEFFDGGGGGDFFEDA.`,`.ACEFGHHGGGHHGFEA..`,`.ACIHHJJHHHJJHHDA..`,`.ACCIHGGHGHGGHFDA..`,`.ADDDFGGGFGGGFDDA..`,`..ADDDFGKKKGFDDA...`,`.....ILILLLILI.IIII`,`...IILLMNONMLLIIPPI`,`..ILLMLNLOLNLMLIPPI`,`.IGGIMLLNONLLMIIIII`,`.IFGILLLLOLLLLIEEEE`,`..IIQQQQQRQQQQQII..`,`....ISSTI.ITSSI....`,`....IUUVI.IVUUI....`,`.....III...III.....`],walk:[[`.......AAAAA.......`,`.....AABBBBBAA.....`,`...AABBBBBBCCCA....`,`..ABBBBBBCDCCDCA...`,`..ABBBBBDCCCCCCCA..`,`.ABBBBCCCCDCDCCCCA.`,`.ABBCCCBCCCDCCDDDA.`,`.ACCCCBCCCCCCDDDDA.`,`.ADDDDDDDCCCDDDDDA.`,`..ADGGDFFEDDDDDDDA.`,`.IHHHGGFFEDDDDDDDA.`,`IGGJHHHHFDDDDDDDDA.`,`IGJGHGGFGDDDDDDDDA.`,`.IKKGGGFFDDDDDDDA..`,`..IIGGFFADDDDDDA...`,`..IIIIILLILLI......`,`..IPPILLMLLLI......`,`..IPPILMLLLLI......`,`..IIIIGFILLLI......`,`..EEEEFILLLLI......`,`......IQQQQQI......`,`.......ISSTI.......`,`......IUUUVI.......`,`.......IIII........`],[`.......AAAAA.......`,`.....AABBBBBAA.....`,`...AABBBBBBCCCA....`,`..ABBBBBBCDCCDCA...`,`..ABBBBBDCCCCCCCA..`,`.ABBBBCCCCDCDCCCCA.`,`.ABBCCCBCCCDCCDDDA.`,`.ACCCCBCCCCCCDDDDA.`,`.ADDDDDDDCCCDDDDDA.`,`..ADGGDFFEDDDDDDDA.`,`.IHHHGGFFEDDDDDDDA.`,`IGGJHHHHFDDDDDDDDA.`,`IGJGHGGFGDDDDDDDDA.`,`.IKKGGGFFDDDDDDDA..`,`..IIGGFFADDDDDDA...`,`..IIIIILLILLI......`,`..IPPILLMLLLI......`,`..IPPILMLLLLI......`,`..IIIIGFILLLI......`,`..EEEEFILLLLI......`,`......IQQQQQI......`,`.....ISTI.ISTI.....`,`....IUUVI.IUUVI....`,`.....III...III.....`],[`.......AAAAA.......`,`.....AABBBBBAA.....`,`...AABBBBBBCCCA....`,`..ABBBBBBCDCCDCA...`,`..ABBBBBDCCCCCCCA..`,`.ABBBBCCCCDCDCCCCA.`,`.ABBCCCBCCCDCCDDDA.`,`.ACCCCBCCCCCCDDDDA.`,`.ADDDDDDDCCCDDDDDA.`,`..ADGGDFFEDDDDDDDA.`,`.IHHHGGFFEDDDDDDDA.`,`IGGJHHHHFDDDDDDDDA.`,`IGJGHGGFGDDDDDDDDA.`,`.IKKGGGFFDDDDDDDA..`,`..IIGGFFADDDDDDA...`,`..IIIIILLILLI......`,`..IPPILLMLLLI......`,`..IPPILMLLLLI......`,`..IIIIGFILLLI......`,`..EEEEFILLLLI......`,`......IQQQQQI......`,`......ISSTI........`,`......IUUUVI.......`,`.......IIII........`]]},codex:{palette:{A:`#313132`,B:`#38353a`,C:`#353336`,D:`#363438`,E:`#b88869`,F:`#d8a07c`,G:`#373337`,H:`#3a3640`,I:`#36363e`,J:`#f0f0f8`,K:`#a0505a`,L:`#10a37f`,M:`#bebebb`,N:`#eafff7`,O:`#f8f8f8`,P:`#f4f4f0`,Q:`#44362e`,R:`#e8c040`,S:`#35373f`,T:`#34353b`,U:`#484848`,V:`#f0f0f0`,W:`#977057`},down:[`....AA.AAAAA.A.....`,`...ABBABBBCBADA....`,`..AABBBBBBDDDDDA...`,`.ABBBBBBDDDBDDDA...`,`.ABBCBDDCDDDCDDDA..`,`.ABBDDDDDDDDDDDCA..`,`.ADDDBDDDBDDDCCCA..`,`.ACCCCCCCCCCCCCCA..`,`..AAECFCFCFCFCEA...`,`...GEHHHHFHHHHEG...`,`...GHHIJHHHJIHHG...`,`...GEHIIHFHIIHEG...`,`....GHHHHEHHHHG....`,`.....GEFFKFFEG.....`,`.....GLGLLLGLG.GGG.`,`...GGLLMNONMLLGGPLG`,`..GLLMLNLOLNLMLGPLG`,`.GFFGMLNNONNLMGGPLG`,`.GEFGLLLLOLLLLGGGG.`,`..GGQQQQQRQQQQQGG..`,`....GSSTG.GTSSG....`,`....GUUVG.GVUUG....`,`.....GGG...GGG.....`],walk:[[`.....A.AAAAA.A.....`,`....ABABBBCBADA....`,`...ABBBBBBDDDDDA...`,`..ABBBBBDDDBDDDAA..`,`.ABBCBDDCDDDCDDDCA.`,`.ABBBDDDDDDDDDDCCA.`,`.ABDDBDDDBDDDCCCCA.`,`.ACCCCCCCDCCCCCCCA.`,`..ACFFCEECCCCCCAA..`,`.GHHHFFEECCCCAA....`,`GFIJHHHHEEFCA......`,`GFIIHFFEFEWA.......`,`.GFKFFFEEEG........`,`..GGFFEEGG.........`,`..GGG.GLLGLLG......`,`..GPLGLLMLLLG......`,`..GPLGLMLLLLG......`,`..GPLGFEGLLLG......`,`..GGGGEGLLLLG......`,`......GQQQQQG......`,`.......GSSTG.......`,`......GUUUVG.......`,`.......GGGG........`],[`.....A.AAAAA.A.....`,`....ABABBBCBADA....`,`...ABBBBBBDDDDDA...`,`..ABBBBBDDDBDDDAA..`,`.ABBCBDDCDDDCDDDCA.`,`.ABBBDDDDDDDDDDCCA.`,`.ABDDBDDDBDDDCCCCA.`,`.ACCCCCCCDCCCCCCCA.`,`..ACFFCEECCCCCCAA..`,`.GHHHFFEECCCCAA....`,`GFIJHHHHEEFCA......`,`GFIIHFFEFEWA.......`,`.GFKFFFEEEG........`,`..GGFFEEGG.........`,`..GGG.GLLGLLG......`,`..GPLGLLMLLLG......`,`..GPLGLMLLLLG......`,`..GPLGFEGLLLG......`,`..GGGGEGLLLLG......`,`......GQQQQQG......`,`.....GSTG.GSTG.....`,`....GUUVG.GUUVG....`,`.....GGG...GGG.....`],[`.....A.AAAAA.A.....`,`....ABABBBCBADA....`,`...ABBBBBBDDDDDA...`,`..ABBBBBDDDBDDDAA..`,`.ABBCBDDCDDDCDDDCA.`,`.ABBBDDDDDDDDDDCCA.`,`.ABDDBDDDBDDDCCCCA.`,`.ACCCCCCCDCCCCCCCA.`,`..ACFFCEECCCCCCAA..`,`.GHHHFFEECCCCAA....`,`GFIJHHHHEEFCA......`,`GFIIHFFEFEWA.......`,`.GFKFFFEEEG........`,`..GGFFEEGG.........`,`..GGG.GLLGLLG......`,`..GPLGLLMLLLG......`,`..GPLGLMLLLLG......`,`..GPLGFEGLLLG......`,`..GGGGEGLLLLG......`,`......GQQQQQG......`,`......GSSTG........`,`......GUUUVG.......`,`.......GGGG........`]]},hermes:{palette:{A:`#443329`,B:`#8f5c3d`,C:`#704830`,D:`#533524`,E:`#f8f8f8`,F:`#d5beaa`,G:`#fbe0c8`,H:`#36363e`,I:`#373337`,J:`#a0605a`,K:`#f4f1e8`,L:`#bebebb`,M:`#c9a227`,N:`#f4f4f0`,O:`#44362e`,P:`#e8c040`,Q:`#f0ece2`,R:`#b4b1aa`,S:`#f0f0f0`,T:`#b0b0bc`,U:`#b09d8c`},down:[`.......AAAA........`,`....AAABBBBAAA.....`,`...ABBBBBBBCCDA....`,`..ABBBBBBCCBCCCA...`,`.ABBBBBCCCCBCCCCA..`,`.EEBBBDCDCCCCCCDEE.`,`ABEBCCCCCCCCCCDDEA.`,`ABCCCCCCCCCCCDDDDA.`,`ACBDDDDDDDDDDDDDDA.`,`ACCDCCCCCCCDDFDDDA.`,`.ACCDDDDGGGGGGFDA..`,`..ACFGHHGGGHHGFDA..`,`..ACFHGGHGHGGHFA...`,`...AIFGGGFGGGFI....`,`.....IFGGJGGFI.....`,`.....IKIKKKIKI.....`,`...IIKKLMMMLKKINNNN`,`..IKKLKMMKMMKLKNIIN`,`.IGGILKMMMMMKLINNNN`,`.IFGIKKLKKKLKKIGFI.`,`..IIOOOOOPOOOOOII..`,`....IQQRI.IRQQI....`,`....ISSTI.ITSSI....`,`.....III...III.....`],walk:[[`.......AAAA........`,`.....AABBBBAAA.....`,`....ABBBBBBCCCA....`,`...ABBBBBBDCCDCA...`,`..ABBBBBDBCCCCCCA..`,`.ABBBBCCCCDCDCCCEE.`,`.ABBCCCCCCCDCCDCEA.`,`.ACCCCCCCCCCDCDDDA.`,`.ADDDDDDDCCCDDDDDA.`,`..ADGGDFFCDDDDDDDA.`,`.IGGGGGFFDDDDDDDDA.`,`IGGHGGGFFFGDDDDDA..`,`IGHGHGGFGFUDDDDA...`,`.IGJGGGFFFDDAAA....`,`..IIGGFFIIAA.......`,`......IKKIKKI......`,`..NNNNKKLKKKI......`,`..NIINKLKKKKI......`,`..NNNNGFIKKKI......`,`.....IFIKKKLI......`,`......IOOOOOI......`,`.......IQQRI.......`,`......ISSSTI.......`,`.......IIII........`],[`.......AAAA........`,`.....AABBBBAAA.....`,`....ABBBBBBCCCA....`,`...ABBBBBBDCCDCA...`,`..ABBBBBDBCCCCCCA..`,`.ABBBBCCCCDCDCCCEE.`,`.ABBCCCCCCCDCCDCEA.`,`.ACCCCCCCCCCDCDDDA.`,`.ADDDDDDDCCCDDDDDA.`,`..ADGGDFFCDDDDDDDA.`,`.IGGGGGFFDDDDDDDDA.`,`IGGHGGGFFFGDDDDDA..`,`IGHGHGGFGFUDDDDA...`,`.IGJGGGFFFDDAAA....`,`..IIGGFFIIAA.......`,`......IKKIKKI......`,`..NNNNKKLKKKI......`,`..NIINKLKKKKI......`,`..NNNNGFIKKKI......`,`.....IFIKKKLI......`,`......IOOOOOI......`,`.....IQRI.IQRI.....`,`....ISSTI.ISSTI....`,`.....III...III.....`],[`.......AAAA........`,`.....AABBBBAAA.....`,`....ABBBBBBCCCA....`,`...ABBBBBBDCCDCA...`,`..ABBBBBDBCCCCCCA..`,`.ABBBBCCCCDCDCCCEE.`,`.ABBCCCCCCCDCCDCEA.`,`.ACCCCCCCCCCDCDDDA.`,`.ADDDDDDDCCCDDDDDA.`,`..ADGGDFFCDDDDDDDA.`,`.IGGGGGFFDDDDDDDDA.`,`IGGHGGGFFFGDDDDDA..`,`IGHGHGGFGFUDDDDA...`,`.IGJGGGFFFDDAAA....`,`..IIGGFFIIAA.......`,`......IKKIKKI......`,`..NNNNKKLKKKI......`,`..NIINKLKKKKI......`,`..NNNNGFIKKKI......`,`.....IFIKKKLI......`,`......IOOOOOI......`,`......IQQRI........`,`......ISSSTI.......`,`.......IIII........`]]},cursor:{palette:{A:`#5b3918`,B:`#ffae48`,C:`#d88838`,D:`#a06529`,E:`#ccaa88`,F:`#f0c8a0`,G:`#3a3640`,H:`#f0f0f8`,I:`#313745`,J:`#373337`,K:`#9a5a48`,L:`#ffffff`,M:`#353539`,N:`#bebebb`,O:`#f8f8f8`,P:`#44362e`,Q:`#e8c040`,R:`#383840`,S:`#36363c`,T:`#484848`,U:`#f0f0f0`,V:`#a88c70`},down:[`......AAAAAA.......`,`....AABBBBBBAA.....`,`...ABBBBBBCCCDA....`,`..ABBBBBBCCBCCCA...`,`.ABBBBBCCCCCDCCCA..`,`ABBBBCCCCCCCCCCDCA.`,`ABBDDCCCCCCCCCCDDA.`,`ACCCCBCCCCCDCDDDDA.`,`ACCDDDDDDDDDDDDDDA.`,`ACCCEDFDFDFDFDEDDA.`,`.ACCEGGGGFGGGGEDA..`,`..ACGGHIGGGHIGGDA..`,`..ACEEIIEFEIIEEJ...`,`...AJEFFFEFFFEJJJ..`,`.....JEFFKFFEJ.JLJ.`,`.....JMJMMMJMJ.JLLJ`,`...JJMMNMOMNMMJJLJJ`,`..JMMNMLLOMMMNMJJ..`,`.JFFJNMLLOMMMNJFFJ.`,`.JEFJMMLLOMMMMJFEJ.`,`..JJPPPPPQPPPPPJJ..`,`....JRRSJ.JSRRJ....`,`....JTTUJ.JUTTJ....`,`.....JJJ...JJJ.....`],walk:[[`......AAAAAAA......`,`....AABBBBBBBAA....`,`...ABBBBBBBCCCCA...`,`..ABBBBBBBCCCDCCA..`,`.ABBBBBBCCCCCCCCA..`,`.ABBBCCCCCDCDCCCCA.`,`.ABBDDCCCCCCCCDDDA.`,`ABCCCBCCCCCCCDDDDA.`,`ADDDDDDDDCCCDDDDDA.`,`.AADFFDEECDDDDDDDA.`,`.JGGGFFEEDDDDDDDDA.`,`JFIIGGGGEEFDDDDDA..`,`JFJIGFFEFEVDDDDA...`,`.JJJFFFEEEDDAAA....`,`..JLJFEEJJAA.......`,`..JLLJJMMJMMJ......`,`..JLJJMMNMMMJ......`,`..JJ.JMNMMMMJ......`,`.....JFEJMMMJ......`,`.....JEJMMMMJ......`,`......JPPPPPJ......`,`.......JRRSJ.......`,`......JTTTUJ.......`,`.......JJJJ........`],[`......AAAAAAA......`,`....AABBBBBBBAA....`,`...ABBBBBBBCCCCA...`,`..ABBBBBBBCCCDCCA..`,`.ABBBBBBCCCCCCCCA..`,`.ABBBCCCCCDCDCCCCA.`,`.ABBDDCCCCCCCCDDDA.`,`ABCCCBCCCCCCCDDDDA.`,`ADDDDDDDDCCCDDDDDA.`,`.AADFFDEECDDDDDDDA.`,`.JGGGFFEEDDDDDDDDA.`,`JFIIGGGGEEFDDDDDA..`,`JFJIGFFEFEVDDDDA...`,`.JJJFFFEEEDDAAA....`,`..JLJFEEJJAA.......`,`..JLLJJMMJMMJ......`,`..JLJJMMNMMMJ......`,`..JJ.JMNMMMMJ......`,`.....JFEJMMMJ......`,`.....JEJMMMMJ......`,`......JPPPPPJ......`,`.....JRSJ.JRSJ.....`,`....JTTUJ.JTTUJ....`,`.....JJJ...JJJ.....`],[`......AAAAAAA......`,`....AABBBBBBBAA....`,`...ABBBBBBBCCCCA...`,`..ABBBBBBBCCCDCCA..`,`.ABBBBBBCCCCCCCCA..`,`.ABBBCCCCCDCDCCCCA.`,`.ABBDDCCCCCCCCDDDA.`,`ABCCCBCCCCCCCDDDDA.`,`ADDDDDDDDCCCDDDDDA.`,`.AADFFDEECDDDDDDDA.`,`.JGGGFFEEDDDDDDDDA.`,`JFIIGGGGEEFDDDDDA..`,`JFJIGFFEFEVDDDDA...`,`.JJJFFFEEEDDAAA....`,`..JLJFEEJJAA.......`,`..JLLJJMMJMMJ......`,`..JLJJMMNMMMJ......`,`..JJ.JMNMMMMJ......`,`.....JFEJMMMJ......`,`.....JEJMMMMJ......`,`......JPPPPPJ......`,`......JRRSJ........`,`......JTTTUJ.......`,`.......JJJJ........`]]},gemini_cli:{palette:{A:`#343132`,B:`#b9c8ff`,C:`#40363b`,D:`#3d3539`,E:`#393336`,F:`#a77553`,G:`#c48a62`,H:`#36363e`,I:`#f2c14e`,J:`#373337`,K:`#7a4232`,L:`#6c8cf5`,M:`#bebebb`,N:`#ffffff`,O:`#44362e`,P:`#e8c040`,Q:`#4a6eb0`,R:`#385384`,S:`#c03850`,T:`#f8f8f8`},down:[`.AAA..BBBBBBB..AAA.`,`ACCCA.AAAAAA..ADDDA`,`CCCCCACCCCCCAADCDDE`,`CCCCCCCCCCDDDEDDDED`,`ACCCCCCCDDDCDDDDDDA`,`.ACCCCCDDDDDEDDDEA.`,`ACCCCCDDDDDDDDDDEA.`,`ACCDDDEDDDDDDEEEEA.`,`ADDEEEEEEEEEEEEEEA.`,`ADDDFFEGGEGGEFFEEA.`,`.AEDFGGGGGGGGGFEA..`,`.ADDFGHHGGGHHGFEI..`,`..ADFHGGHGHGGHFIII.`,`...AJFGGGFGGGFJ.I..`,`.....JFGKKKGFJ..J..`,`.....JLJLLLJLJ..J..`,`...JJLLMLLLMLLJJJ..`,`..JLLMLLNNNLLMLLJ..`,`.JGGJMLLLMLLLMJGGJ.`,`.JFGJLLLLLLLLLJGFJ.`,`..JJOOOOOPOOOOOJJ..`,`....JQQRJ.JRQQJ....`,`....JSSTJ.JTSSJ....`,`.....JJJ...JJJ.....`],walk:[[`........BBBB.AAA...`,`......AAAAAAACCDA..`,`....AACCCCCCCDDDDA.`,`...ACCCCCCCDDDDDDA.`,`..ACCCCCCCDDDEDDDA.`,`.ACCCCCCDDDDDDDDA..`,`.ACCCCDDCDDDDDDEEA.`,`.ACEDDDDDDDDDEDEEA.`,`.AEEEEEEEDDDDEEEEA.`,`..AEGGEFFDDEEEEEEA.`,`.JGGGGGFFEEEEEEEEA.`,`JGGIGGGFFEEEEEEEA..`,`JGIIIGGFGEEEEEEA...`,`.JKIGGGFFEEEEEA....`,`..JJGGFFAEEAAA.....`,`...J..JLLJLLJ......`,`...J.JLLMLLLJ......`,`...J.JLMLLLLJ......`,`.....JGFJLLMJ......`,`.....JFJLLLLJ......`,`......JOOOOOJ......`,`.......JQQRJ.......`,`......JSSSTJ.......`,`.......JJJJ........`],[`........BBBB.AAA...`,`......AAAAAAACCDA..`,`....AACCCCCCCDDDDA.`,`...ACCCCCCCDDDDDDA.`,`..ACCCCCCCDDDEDDDA.`,`.ACCCCCCDDDDDDDDA..`,`.ACCCCDDCDDDDDDEEA.`,`.ACEDDDDDDDDDEDEEA.`,`.AEEEEEEEDDDDEEEEA.`,`..AEGGEFFDDEEEEEEA.`,`.JGGGGGFFEEEEEEEEA.`,`JGGIGGGFFEEEEEEEA..`,`JGIIIGGFGEEEEEEA...`,`.JKIGGGFFEEEEEA....`,`..JJGGFFAEEAAA.....`,`...J..JLLJLLJ......`,`...J.JLLMLLLJ......`,`...J.JLMLLLLJ......`,`.....JGFJLLMJ......`,`.....JFJLLLLJ......`,`......JOOOOOJ......`,`.....JQRJ.JQRJ.....`,`....JSSTJ.JSSTJ....`,`.....JJJ...JJJ.....`],[`........BBBB.AAA...`,`......AAAAAAACCDA..`,`....AACCCCCCCDDDDA.`,`...ACCCCCCCDDDDDDA.`,`..ACCCCCCCDDDEDDDA.`,`.ACCCCCCDDDDDDDDA..`,`.ACCCCDDCDDDDDDEEA.`,`.ACEDDDDDDDDDEDEEA.`,`.AEEEEEEEDDDDEEEEA.`,`..AEGGEFFDDEEEEEEA.`,`.JGGGGGFFEEEEEEEEA.`,`JGGIGGGFFEEEEEEEA..`,`JGIIIGGFGEEEEEEA...`,`.JKIGGGFFEEEEEA....`,`..JJGGFFAEEAAA.....`,`...J..JLLJLLJ......`,`...J.JLLMLLLJ......`,`...J.JLMLLLLJ......`,`.....JGFJLLMJ......`,`.....JFJLLLLJ......`,`......JOOOOOJ......`,`......JQQRJ........`,`......JSSSTJ.......`,`.......JJJJ........`]]}},jt={claude_code:`#d97757`,codex:`#10a37f`,hermes:`#c9a227`,cursor:`#1b1b1f`,gemini_cli:`#6c8cf5`},Mt={palette:{A:`#3a302c`,B:`#5f3b2c`,C:`#503428`,D:`#48332a`,E:`#9c6846`,F:`#b87a52`,G:`#36363e`,H:`#373337`,I:`#6e3e30`,J:`#30395a`,K:`#f8f8f8`,L:`#d8432e`,M:`#2f3653`,N:`#9aa0a6`,O:`#32374b`,P:`#313545`,Q:`#343438`,R:`#4a4a56`,S:`#815539`},down:[`........AA.........`,`.....AAABBAAA......`,`...AABBBBBBBCAA....`,`..ABBBBBBCCBCCCA...`,`.ABBBBBCCCCCDCCCA..`,`.ABBBCCCCCCCCCCCA..`,`ABBDDDCCCCCCCDDDDA.`,`ACCDDDDDDDDDDDDDDA.`,`.ACCEDFDCCCCCCCDA..`,`.ADCEFFFFFFDDDDDA..`,`..ACEFEEFFFEEFEDA..`,`..ACEFGGFFFGGFEA...`,`...AHEFDDDDDFEH....`,`.....HEFFIFFEH.....`,`.....HJHKLKHJH...H.`,`...HHJJMJLJMJJHH.KH`,`..HJJMMJJLJJNMJJHKK`,`.HFFHMMJJLJJMMHFFHK`,`.HEFHJMMJLJMMJHFEHH`,`..HHOOOOOOOOOOOHHH.`,`....HOOPH.HPOOH....`,`....HQQRH.HRQQH....`,`.....HHH...HHH.....`],walk:[[`........AAA........`,`.....AAABBBAAA.....`,`....ABBBBBBCCCA....`,`...ABBBBBCDCCDCA...`,`..ABBBBBCCDCCCCCA..`,`.ABBBBCDCCCCCCCDCA.`,`.ABBDDDCCCCCCCCDDA.`,`.ADDDDDDDCCCCDDDDA.`,`..ADFFDEECCDDDDDDA.`,`.HFFFFFEEDDDDDDDDA.`,`HFEEFFFEEEFDDDDDA..`,`HFDDDFFEFESDDDDA...`,`.HFIFFFEEEDDAAA....`,`..HHFFEEHHAA.......`,`...H..HJJHKKH......`,`...KHHJJMJJJH......`,`...KKFJMJJJJH......`,`...KKFFEHJJMH......`,`...KHHEHJJJMH......`,`...H..HOOOOOH......`,`.......HOOPH.......`,`......HQQQRH.......`,`.......HHHH........`],[`........AAA........`,`.....AAABBBAAA.....`,`....ABBBBBBCCCA....`,`...ABBBBBCDCCDCA...`,`..ABBBBBCCDCCCCCA..`,`.ABBBBCDCCCCCCCDCA.`,`.ABBDDDCCCCCCCCDDA.`,`.ADDDDDDDCCCCDDDDA.`,`..ADFFDEECCDDDDDDA.`,`.HFFFFFEEDDDDDDDDA.`,`HFEEFFFEEEFDDDDDA..`,`HFDDDFFEFESDDDDA...`,`.HFIFFFEEEDDAAA....`,`..HHFFEEHHAA.......`,`...H..HJJHKKH......`,`...KHHJJMJJJH......`,`...KKFJMJJJJH......`,`...KKFFEHJJMH......`,`...KHHEHJJJMH......`,`...H..HOOOOOH......`,`.....HOPH.HOPH.....`,`....HQQRH.HQQRH....`,`.....HHH...HHH.....`],[`........AAA........`,`.....AAABBBAAA.....`,`....ABBBBBBCCCA....`,`...ABBBBBCDCCDCA...`,`..ABBBBBCCDCCCCCA..`,`.ABBBBCDCCCCCCCDCA.`,`.ABBDDDCCCCCCCCDDA.`,`.ADDDDDDDCCCCDDDDA.`,`..ADFFDEECCDDDDDDA.`,`.HFFFFFEEDDDDDDDDA.`,`HFEEFFFEEEFDDDDDA..`,`HFDDDFFEFESDDDDA...`,`.HFIFFFEEEDDAAA....`,`..HHFFEEHHAA.......`,`...H..HJJHKKH......`,`...KHHJJMJJJH......`,`...KKFJMJJJJH......`,`...KKFFEHJJMH......`,`...KHHEHJJJMH......`,`...H..HOOOOOH......`,`......HOOPH........`,`......HQQQRH.......`,`.......HHHH........`]]},Nt=[{down:[`....oo.ooooo.o....`,`...ohhohhhdhoHo...`,`..oohhhhhhHHHHHo..`,`.ohhhhhhHHHhHHHo..`,`.ohhdhHHdHHHdHHHo.`,`.ohhHHHHHHHHHHHdo.`,`.oHHHhHHHhHHHdddo.`,`.oddddddddddddddo.`,`..ooSdsdsdsdsdSo..`,`...kSsssssssssSk..`,`...kSseEsssEesSk..`,`...kSseessseesSk..`,`....kSsssSsssSk...`,`.....kSssmssSk....`,`.....kLkccckLk....`,`...kkLLlJJJlLLkk..`,`..kLLlJJJJJJJlLLk.`,`.kssklJJJjJJJlkssk`,`.kSskJJjJJJjJJksSk`,`..kkPPPPPPPPPPPkk.`,`....kPPpk.kpPPk...`,`....kBBwk.kwBBk...`,`.....kkk...kkk....`],walk:[[`.....o.ooooo.o....`,`....ohohhhdhoHo...`,`...ohhhhhhHHHHHo..`,`..ohhhhhHHHhHHHoo.`,`.ohhdhHHdHHHdHHHdo`,`.ohhhHHHHHHHHHHddo`,`.ohHHhHHHhHHHddddo`,`.odddddddHdddddddo`,`..odssdSSddddddoo.`,`.ksssssSSddddoo...`,`kseEsssSSSsdo.....`,`kseesssSsSDo......`,`.ksmsssSSSk.......`,`..kkssSSkk........`,`......kLLkcck.....`,`.....kLLlJJJk.....`,`.....kLlJJJJk.....`,`.....ksSkJJjk.....`,`.....kSkJJJjk.....`,`......kPPPPPk.....`,`.......kPPpk......`,`......kBBBwk......`,`.......kkkk.......`],[`.....o.ooooo.o....`,`....ohohhhdhoHo...`,`...ohhhhhhHHHHHo..`,`..ohhhhhHHHhHHHoo.`,`.ohhdhHHdHHHdHHHdo`,`.ohhhHHHHHHHHHHddo`,`.ohHHhHHHhHHHddddo`,`.odddddddHdddddddo`,`..odssdSSddddddoo.`,`.ksssssSSddddoo...`,`kseEsssSSSsdo.....`,`kseesssSsSDo......`,`.ksmsssSSSk.......`,`..kkssSSkk........`,`......kLLkcck.....`,`.....kLLlJJJk.....`,`.....kLlJJJJk.....`,`.....ksSkJJjk.....`,`.....kSkJJJjk.....`,`......kPPPPPk.....`,`.....kPpk.kPpk....`,`....kBBwk.kBBwk...`,`.....kkk...kkk....`],[`.....o.ooooo.o....`,`....ohohhhdhoHo...`,`...ohhhhhhHHHHHo..`,`..ohhhhhHHHhHHHoo.`,`.ohhdhHHdHHHdHHHdo`,`.ohhhHHHHHHHHHHddo`,`.ohHHhHHHhHHHddddo`,`.odddddddHdddddddo`,`..odssdSSddddddoo.`,`.ksssssSSddddoo...`,`kseEsssSSSsdo.....`,`kseesssSsSDo......`,`.ksmsssSSSk.......`,`..kkssSSkk........`,`......kLLkcck.....`,`.....kLLlJJJk.....`,`.....kLlJJJJk.....`,`.....ksSkJJjk.....`,`.....kSkJJJjk.....`,`......kPPPPPk.....`,`......kPPpk.......`,`......kBBBwk......`,`.......kkkk.......`]]},{down:[`...oooohhhhhho.....`,`..ohhhhhhhhhHooo...`,`.oohhhhhhhHHHdHHo..`,`ohhhhhhhHHHhHHHHo..`,`ohhhhhHHHHHHdHHHdo.`,`ohhhhHHHHHHHHHHdddo`,`hhhdddHHHHHHHHHdddo`,`hHHHhHHHHHHHHddddo.`,`HhHdddddddddddddddo`,`oHHHSdssdsdssdSdddo`,`odHHSsssssssssSddo.`,`.ooHSseEsssEesSdo..`,`..oHSseessseesSo...`,`...okSsssSsssSk....`,`.....kSssmssSk.....`,`.....kLkccckLk.....`,`...kkLLlJJJlLLkk...`,`..kLLlJJJJJJJlLLk..`,`.kssklJJJjJJJlkssk.`,`.kSskJJjJJJjJJksSk.`,`..kkPPPPPPPPPPPkk..`,`....kPPpk.kpPPk....`,`....kBBwk.kwBBk....`,`.....kkk...kkk.....`],walk:[[`....ooohhhohho.....`,`...ohhhhhhhhHHoo...`,`..ohhhhhhhdHHHHHo..`,`.ohhhhhhhhHHHdHHHo.`,`ohhhhhhhHHHHHHHHHo.`,`ohhhhhHdHHdHHHHdHdo`,`ohhdddHHHHHHHHddddo`,`hHHHhHHHHHHHHdddddo`,`oddddddddHHdddddddo`,`.oodssdSSHddddddddo`,`.ksssssSSddddddddo.`,`kseEsssSSSsdddddo..`,`kseesssSsSDddddo...`,`.ksmsssSSSddooo....`,`..kkssSSodoo.......`,`......kLLkcck......`,`.....kLLlJJJk......`,`.....kLlJJJJk......`,`.....ksSkJJjk......`,`.....kSkJJJjk......`,`......kPPPPPk......`,`.......kPPpk.......`,`......kBBBwk.......`,`.......kkkk........`],[`....ooohhhohho.....`,`...ohhhhhhhhHHoo...`,`..ohhhhhhhdHHHHHo..`,`.ohhhhhhhhHHHdHHHo.`,`ohhhhhhhHHHHHHHHHo.`,`ohhhhhHdHHdHHHHdHdo`,`ohhdddHHHHHHHHddddo`,`hHHHhHHHHHHHHdddddo`,`oddddddddHHdddddddo`,`.oodssdSSHddddddddo`,`.ksssssSSddddddddo.`,`kseEsssSSSsdddddo..`,`kseesssSsSDddddo...`,`.ksmsssSSSddooo....`,`..kkssSSodoo.......`,`......kLLkcck......`,`.....kLLlJJJk......`,`.....kLlJJJJk......`,`.....ksSkJJjk......`,`.....kSkJJJjk......`,`......kPPPPPk......`,`.....kPpk.kPpk.....`,`....kBBwk.kBBwk....`,`.....kkk...kkk.....`],[`....ooohhhohho.....`,`...ohhhhhhhhHHoo...`,`..ohhhhhhhdHHHHHo..`,`.ohhhhhhhhHHHdHHHo.`,`ohhhhhhhHHHHHHHHHo.`,`ohhhhhHdHHdHHHHdHdo`,`ohhdddHHHHHHHHddddo`,`hHHHhHHHHHHHHdddddo`,`oddddddddHHdddddddo`,`.oodssdSSHddddddddo`,`.ksssssSSddddddddo.`,`kseEsssSSSsdddddo..`,`kseesssSsSDddddo...`,`.ksmsssSSSddooo....`,`..kkssSSodoo.......`,`......kLLkcck......`,`.....kLLlJJJk......`,`.....kLlJJJJk......`,`.....ksSkJJjk......`,`.....kSkJJJjk......`,`......kPPPPPk......`,`......kPPpk........`,`......kBBBwk.......`,`.......kkkk........`]]},{down:[`.....oooooooo.....`,`....ohhhhhhhHo....`,`...ohhhhhhHHHdo...`,`..ohhhhhHHHhHHHo..`,`.ohhhhhHHHHHdHHHo.`,`ohhhhHHHHHHHHHHddo`,`ohhdddHHHHHHHdHddo`,`oHHXXHHHHHHHHddddo`,`oHHXdddddddddddddo`,`oHHHSdssdsdssdSddo`,`oHHHSsssssssssSddo`,`oHHHSseEsssEesSddo`,`oHHHSseessseesSddo`,`.odddSsssSsssSddo.`,`..odddSssmssSddo..`,`.....kLkccckLk....`,`...kkLLlJJJlLLkk..`,`..kLLlJJJJJJJlLLk.`,`.kssklJJJjJJJlkssk`,`.kSskJJjJJJjJJksSk`,`..kkPPPPPPPPPPPkk.`,`....kPPpk.kpPPk...`,`....kBBwk.kwBBk...`,`.....kkk...kkk....`],walk:[[`......ooooooo.....`,`....oohhhhhhHoo...`,`...ohhhhhhhHHHHo..`,`..ohhhhhhhHHHdHHo.`,`.ohhhhhhHHHHHHHHo.`,`.ohhhhHdHHdHHHHdHo`,`.ohdddHHHHHHHHHddo`,`.oHHHhHHHHHHHXXddo`,`.odddddddHHddXdddo`,`..odssdSSHdddddddo`,`.ksssssSSddddddddo`,`kseEsssSSddddddddo`,`kseesssSsddddddddo`,`.ksmsssSSdddddddo.`,`..kkssSSoddddddo..`,`......kLLkcck.....`,`.....kLLlJJJk.....`,`.....kLlJJJJk.....`,`.....ksSkJJjk.....`,`.....kSkJJJjk.....`,`......kPPPPPk.....`,`.......kPPpk......`,`......kBBBwk......`,`.......kkkk.......`],[`......ooooooo.....`,`....oohhhhhhHoo...`,`...ohhhhhhhHHHHo..`,`..ohhhhhhhHHHdHHo.`,`.ohhhhhhHHHHHHHHo.`,`.ohhhhHdHHdHHHHdHo`,`.ohdddHHHHHHHHHddo`,`.oHHHhHHHHHHHXXddo`,`.odddddddHHddXdddo`,`..odssdSSHdddddddo`,`.ksssssSSddddddddo`,`kseEsssSSddddddddo`,`kseesssSsddddddddo`,`.ksmsssSSdddddddo.`,`..kkssSSoddddddo..`,`......kLLkcck.....`,`.....kLLlJJJk.....`,`.....kLlJJJJk.....`,`.....ksSkJJjk.....`,`.....kSkJJJjk.....`,`......kPPPPPk.....`,`.....kPpk.kPpk....`,`....kBBwk.kBBwk...`,`.....kkk...kkk....`],[`......ooooooo.....`,`....oohhhhhhHoo...`,`...ohhhhhhhHHHHo..`,`..ohhhhhhhHHHdHHo.`,`.ohhhhhhHHHHHHHHo.`,`.ohhhhHdHHdHHHHdHo`,`.ohdddHHHHHHHHHddo`,`.oHHHhHHHHHHHXXddo`,`.odddddddHHddXdddo`,`..odssdSSHdddddddo`,`.ksssssSSddddddddo`,`kseEsssSSddddddddo`,`kseesssSsddddddddo`,`.ksmsssSSdddddddo.`,`..kkssSSoddddddo..`,`......kLLkcck.....`,`.....kLLlJJJk.....`,`.....kLlJJJJk.....`,`.....ksSkJJjk.....`,`.....kSkJJJjk.....`,`......kPPPPPk.....`,`......kPPpk.......`,`......kBBBwk......`,`.......kkkk.......`]]},{down:[`.......oooo.......`,`....ooohhhhooo....`,`...ohhhhhhhHHdo...`,`..ohhhhhhHHhHHHo..`,`.ohhhhhHHHHhHHHHo.`,`.ohhhhdHdHHHHHHdo.`,`ohhhHHHHHHHHHHdddo`,`ohHHHHHHHHHHHddddo`,`oHhddddddddddddddo`,`oHHdHHHHHHHddSdddo`,`.oHHddddssssssSdo.`,`..oHSseEsssEesSdo.`,`..oHSseessseesSo..`,`...okSsssSsssSk...`,`.....kSssmssSk....`,`.....kLkccckLk....`,`...kkLLlJJJlLLkk..`,`..kLLlJJJJJJJlLLk.`,`.kssklJJJjJJJlkssk`,`.kSskJJjJJJjJJksSk`,`..kkPPPPPPPPPPPkk.`,`....kPPpk.kpPPk...`,`....kBBwk.kwBBk...`,`.....kkk...kkk....`],walk:[[`.......oooo.......`,`.....oohhhhooo....`,`....ohhhhhhHHHo...`,`...ohhhhhhdHHdHo..`,`..ohhhhhdhHHHHHHo.`,`.ohhhhHHHHdHdHHHHo`,`.ohhHHHHHHHdHHdHdo`,`.oHHHHHHHHHHdHdddo`,`.odddddddHHHdddddo`,`..odssdSSHdddddddo`,`.ksssssSSddddddddo`,`kseEsssSSSsdddddo.`,`kseesssSsSDddddo..`,`.ksmsssSSSddooo...`,`..kkssSSkkoo......`,`......kLLkcck.....`,`.....kLLlJJJk.....`,`.....kLlJJJJk.....`,`.....ksSkJJjk.....`,`.....kSkJJJjk.....`,`......kPPPPPk.....`,`.......kPPpk......`,`......kBBBwk......`,`.......kkkk.......`],[`.......oooo.......`,`.....oohhhhooo....`,`....ohhhhhhHHHo...`,`...ohhhhhhdHHdHo..`,`..ohhhhhdhHHHHHHo.`,`.ohhhhHHHHdHdHHHHo`,`.ohhHHHHHHHdHHdHdo`,`.oHHHHHHHHHHdHdddo`,`.odddddddHHHdddddo`,`..odssdSSHdddddddo`,`.ksssssSSddddddddo`,`kseEsssSSSsdddddo.`,`kseesssSsSDddddo..`,`.ksmsssSSSddooo...`,`..kkssSSkkoo......`,`......kLLkcck.....`,`.....kLLlJJJk.....`,`.....kLlJJJJk.....`,`.....ksSkJJjk.....`,`.....kSkJJJjk.....`,`......kPPPPPk.....`,`.....kPpk.kPpk....`,`....kBBwk.kBBwk...`,`.....kkk...kkk....`],[`.......oooo.......`,`.....oohhhhooo....`,`....ohhhhhhHHHo...`,`...ohhhhhhdHHdHo..`,`..ohhhhhdhHHHHHHo.`,`.ohhhhHHHHdHdHHHHo`,`.ohhHHHHHHHdHHdHdo`,`.oHHHHHHHHHHdHdddo`,`.odddddddHHHdddddo`,`..odssdSSHdddddddo`,`.ksssssSSddddddddo`,`kseEsssSSSsdddddo.`,`kseesssSsSDddddo..`,`.ksmsssSSSddooo...`,`..kkssSSkkoo......`,`......kLLkcck.....`,`.....kLLlJJJk.....`,`.....kLlJJJJk.....`,`.....ksSkJJjk.....`,`.....kSkJJJjk.....`,`......kPPPPPk.....`,`......kPPpk.......`,`......kBBBwk......`,`.......kkkk.......`]]},{down:[`......ohhhho......`,`.....oohhhhoo.....`,`....ohhhhhhhHo....`,`...ohhhhhhHHHdo...`,`..ohhhhhXXXhHHHo..`,`.ohhhhHHdHHHdHHHo.`,`ohhhHHHdHHHdHHHHdo`,`ohHHHHHHHHHHHHdddo`,`oHHddddddddddddddo`,`oHHdSdssdsdssdSddo`,`.odHSsssssssssSdo.`,`..oHSseEsssEesSdo.`,`..oHSseessseesSo..`,`...okSsssSsssSk...`,`.....kSssmssSk....`,`.....kLkccckLk....`,`...kkLLlJJJlLLkk..`,`..kLLlJJJJJJJlLLk.`,`.kssklJJJjJJJlkssk`,`.kSskJJjJJJjJJksSk`,`..kkPPPPPPPPPPPkk.`,`....kPPpk.kpPPk...`,`....kBBwk.kwBBk...`,`.....kkk...kkk....`],walk:[[`........ohhhho....`,`......ooohhhho....`,`....oohhhhhhHoo...`,`...ohhhhhhdHHHHo..`,`..ohhhhhhhXXXdHHo.`,`.ohhhhhHHHdhHHHHdo`,`.ohhhHHHHHHHHHHddo`,`.ohHHHHHHHHHHddddo`,`.odddddddHHHdddddo`,`..odssdSSHHddddddo`,`.ksssssSSddddddddo`,`kseEsssSSSsdddddo.`,`kseesssSsSDddddo..`,`.ksmsssSSSddooo...`,`..kkssSSodoo......`,`......kLLkcck.....`,`.....kLLlJJJk.....`,`.....kLlJJJJk.....`,`.....ksSkJJjk.....`,`.....kSkJJJjk.....`,`......kPPPPPk.....`,`.......kPPpk......`,`......kBBBwk......`,`.......kkkk.......`],[`........ohhhho....`,`......ooohhhho....`,`....oohhhhhhHoo...`,`...ohhhhhhdHHHHo..`,`..ohhhhhhhXXXdHHo.`,`.ohhhhhHHHdhHHHHdo`,`.ohhhHHHHHHHHHHddo`,`.ohHHHHHHHHHHddddo`,`.odddddddHHHdddddo`,`..odssdSSHHddddddo`,`.ksssssSSddddddddo`,`kseEsssSSSsdddddo.`,`kseesssSsSDddddo..`,`.ksmsssSSSddooo...`,`..kkssSSodoo......`,`......kLLkcck.....`,`.....kLLlJJJk.....`,`.....kLlJJJJk.....`,`.....ksSkJJjk.....`,`.....kSkJJJjk.....`,`......kPPPPPk.....`,`.....kPpk.kPpk....`,`....kBBwk.kBBwk...`,`.....kkk...kkk....`],[`........ohhhho....`,`......ooohhhho....`,`....oohhhhhhHoo...`,`...ohhhhhhdHHHHo..`,`..ohhhhhhhXXXdHHo.`,`.ohhhhhHHHdhHHHHdo`,`.ohhhHHHHHHHHHHddo`,`.ohHHHHHHHHHHddddo`,`.odddddddHHHdddddo`,`..odssdSSHHddddddo`,`.ksssssSSddddddddo`,`kseEsssSSSsdddddo.`,`kseesssSsSDddddo..`,`.ksmsssSSSddooo...`,`..kkssSSodoo......`,`......kLLkcck.....`,`.....kLLlJJJk.....`,`.....kLlJJJJk.....`,`.....ksSkJJjk.....`,`.....kSkJJJjk.....`,`......kPPPPPk.....`,`......kPPpk.......`,`......kBBBwk......`,`.......kkkk.......`]]},{down:[`........oo........`,`.....ooohhooo.....`,`...oohhhhhhhHoo...`,`..ohhhhhhHHhHHHo..`,`.ohhhhhHHHHHdHHHo.`,`.ohhhHHHHHHHHHHHo.`,`ohhdddHHHHHHHddddo`,`oHHddddddddddddddo`,`.oHHSdsdHHHHHHHdo.`,`.odHSssssssdddddo.`,`..oHSseEsssEesSdo.`,`..oHSseessseesSo..`,`...okSsssSsssSk...`,`.....kSssmssSk....`,`.....kLkccckLk....`,`...kkLLlJJJlLLkk..`,`..kLLlJJJJJJJlLLk.`,`.kssklJJJjJJJlkssk`,`.kSskJJjJJJjJJksSk`,`..kkPPPPPPPPPPPkk.`,`....kPPpk.kpPPk...`,`....kBBwk.kwBBk...`,`.....kkk...kkk....`],walk:[[`........ooo.......`,`.....ooohhhooo....`,`....ohhhhhhHHHo...`,`...ohhhhhHdHHdHo..`,`..ohhhhhHHdHHHHHo.`,`.ohhhhHdHHHHHHHdHo`,`.ohhdddHHHHHHHHddo`,`.odddddddHHHHddddo`,`..odssdSSHHddddddo`,`.ksssssSSddddddddo`,`kseEsssSSSsdddddo.`,`kseesssSsSDddddo..`,`.ksmsssSSSddooo...`,`..kkssSSkkoo......`,`......kLLkcck.....`,`.....kLLlJJJk.....`,`.....kLlJJJJk.....`,`.....ksSkJJjk.....`,`.....kSkJJJjk.....`,`......kPPPPPk.....`,`.......kPPpk......`,`......kBBBwk......`,`.......kkkk.......`],[`........ooo.......`,`.....ooohhhooo....`,`....ohhhhhhHHHo...`,`...ohhhhhHdHHdHo..`,`..ohhhhhHHdHHHHHo.`,`.ohhhhHdHHHHHHHdHo`,`.ohhdddHHHHHHHHddo`,`.odddddddHHHHddddo`,`..odssdSSHHddddddo`,`.ksssssSSddddddddo`,`kseEsssSSSsdddddo.`,`kseesssSsSDddddo..`,`.ksmsssSSSddooo...`,`..kkssSSkkoo......`,`......kLLkcck.....`,`.....kLLlJJJk.....`,`.....kLlJJJJk.....`,`.....ksSkJJjk.....`,`.....kSkJJJjk.....`,`......kPPPPPk.....`,`.....kPpk.kPpk....`,`....kBBwk.kBBwk...`,`.....kkk...kkk....`],[`........ooo.......`,`.....ooohhhooo....`,`....ohhhhhhHHHo...`,`...ohhhhhHdHHdHo..`,`..ohhhhhHHdHHHHHo.`,`.ohhhhHdHHHHHHHdHo`,`.ohhdddHHHHHHHHddo`,`.odddddddHHHHddddo`,`..odssdSSHHddddddo`,`.ksssssSSddddddddo`,`kseEsssSSSsdddddo.`,`kseesssSsSDddddo..`,`.ksmsssSSSddooo...`,`..kkssSSkkoo......`,`......kLLkcck.....`,`.....kLLlJJJk.....`,`.....kLlJJJJk.....`,`.....ksSkJJjk.....`,`.....kSkJJJjk.....`,`......kPPPPPk.....`,`......kPPpk.......`,`......kBBBwk......`,`.......kkkk.......`]]},{down:[`.......oooo.......`,`....ooohhhhooo....`,`...ohhhhhhhhHdo...`,`..ohhhhhhHHhHHHo..`,`.ohhhhhHHHHHdHHHo.`,`.ohhhHdHHHHHHHHdo.`,`ohhhHHHHHHHHHHHddo`,`ohHHHhhHHHHdHddddo`,`oHhddddddddddddddo`,`oHHdSSdsssssdSSddo`,`.oHHSsssssssssSdo.`,`.oHHSseEsssEesSdo.`,`.oHHSseessseesSdo.`,`.odddSsssSsssSddo.`,`..odddSssmssSddo..`,`.....kLkccckLk....`,`...kkLLlJJJlLLkk..`,`..kLLlJJJJJJJlLLk.`,`.kssklJJJjJJJlkssk`,`.kSskJJjJJJjJJksSk`,`..kkPPPPPPPPPPPkk.`,`....kPPpk.kpPPk...`,`....kBBwk.kwBBk...`,`.....kkk...kkk....`],walk:[[`.......ooooo......`,`.....oohhhhhoo....`,`...oohhhhhhHHHo...`,`..ohhhhhhHdHHdHo..`,`..ohhhhhdHHHHHHHo.`,`.ohhhhHHHHdHdHHHHo`,`.ohhHHHhHHHdHHdddo`,`.oHHHHhHHHHHHddddo`,`.odddddddHHHdddddo`,`..odssdSSHdddddddo`,`.ksssssSSddddddddo`,`kseEsssSSddddddddo`,`kseesssSsddddddddo`,`.ksmsssSSdddddddo.`,`..kkssSSoddddddo..`,`......kLLkcck.....`,`.....kLLlJJJk.....`,`.....kLlJJJJk.....`,`.....ksSkJJjk.....`,`.....kSkJJJjk.....`,`......kPPPPPk.....`,`.......kPPpk......`,`......kBBBwk......`,`.......kkkk.......`],[`.......ooooo......`,`.....oohhhhhoo....`,`...oohhhhhhHHHo...`,`..ohhhhhhHdHHdHo..`,`..ohhhhhdHHHHHHHo.`,`.ohhhhHHHHdHdHHHHo`,`.ohhHHHhHHHdHHdddo`,`.oHHHHhHHHHHHddddo`,`.odddddddHHHdddddo`,`..odssdSSHdddddddo`,`.ksssssSSddddddddo`,`kseEsssSSddddddddo`,`kseesssSsddddddddo`,`.ksmsssSSdddddddo.`,`..kkssSSoddddddo..`,`......kLLkcck.....`,`.....kLLlJJJk.....`,`.....kLlJJJJk.....`,`.....ksSkJJjk.....`,`.....kSkJJJjk.....`,`......kPPPPPk.....`,`.....kPpk.kPpk....`,`....kBBwk.kBBwk...`,`.....kkk...kkk....`],[`.......ooooo......`,`.....oohhhhhoo....`,`...oohhhhhhHHHo...`,`..ohhhhhhHdHHdHo..`,`..ohhhhhdHHHHHHHo.`,`.ohhhhHHHHdHdHHHHo`,`.ohhHHHhHHHdHHdddo`,`.oHHHHhHHHHHHddddo`,`.odddddddHHHdddddo`,`..odssdSSHdddddddo`,`.ksssssSSddddddddo`,`kseEsssSSddddddddo`,`kseesssSsddddddddo`,`.ksmsssSSdddddddo.`,`..kkssSSoddddddo..`,`......kLLkcck.....`,`.....kLLlJJJk.....`,`.....kLlJJJJk.....`,`.....ksSkJJjk.....`,`.....kSkJJJjk.....`,`......kPPPPPk.....`,`......kPPpk.......`,`......kBBBwk......`,`.......kkkk.......`]]},{down:[`.......kkkk.......`,`.....kknnnnkk.....`,`....knnnnssssk....`,`...knnnnssssssk...`,`..knnnsssssssssk..`,`.knnssssssssssSSk.`,`.ohHHsssssssSSddo.`,`.oHHHssssssSSSddo.`,`.oHddssssSSSSSddo.`,`..oHSSsssssssSSo..`,`..oHSseEsssEesSk..`,`...oSseessseesSk..`,`....kSsssSsssSk...`,`.....kSssmssSk....`,`.....kLkccckLk....`,`...kkLLlJJJlLLkk..`,`..kLLlJJJJJJJlLLk.`,`.kssklJJJjJJJlkssk`,`.kSskJJjJJJjJJksSk`,`..kkPPPPPPPPPPPkk.`,`....kPPpk.kpPPk...`,`....kBBwk.kwBBk...`,`.....kkk...kkk....`],walk:[[`.......kkkkk......`,`.....kknnnnnkk....`,`....knnnnnssssk...`,`...knnnnsssssssk..`,`..knnnssssssssssk.`,`..knnsssssssssSSk.`,`..ksssssssssHHddo.`,`..kssssssssSddddo.`,`..kssssssSSSddddo.`,`.kodssdSSdddddddo.`,`kseEsssSSddddddo..`,`kseesssSsdddddo...`,`.ksmsssSSddddo....`,`..kkssSSkoooo.....`,`......kLLkcck.....`,`.....kLLlJJJk.....`,`.....kLlJJJJk.....`,`.....ksSkJJjk.....`,`.....kSkJJJjk.....`,`......kPPPPPk.....`,`.......kPPpk......`,`......kBBBwk......`,`.......kkkk.......`],[`.......kkkkk......`,`.....kknnnnnkk....`,`....knnnnnssssk...`,`...knnnnsssssssk..`,`..knnnssssssssssk.`,`..knnsssssssssSSk.`,`..ksssssssssHHddo.`,`..kssssssssSddddo.`,`..kssssssSSSddddo.`,`.kodssdSSdddddddo.`,`kseEsssSSddddddo..`,`kseesssSsdddddo...`,`.ksmsssSSddddo....`,`..kkssSSkoooo.....`,`......kLLkcck.....`,`.....kLLlJJJk.....`,`.....kLlJJJJk.....`,`.....ksSkJJjk.....`,`.....kSkJJJjk.....`,`......kPPPPPk.....`,`.....kPpk.kPpk....`,`....kBBwk.kBBwk...`,`.....kkk...kkk....`],[`.......kkkkk......`,`.....kknnnnnkk....`,`....knnnnnssssk...`,`...knnnnsssssssk..`,`..knnnssssssssssk.`,`..knnsssssssssSSk.`,`..ksssssssssHHddo.`,`..kssssssssSddddo.`,`..kssssssSSSddddo.`,`.kodssdSSdddddddo.`,`kseEsssSSddddddo..`,`kseesssSsdddddo...`,`.ksmsssSSddddo....`,`..kkssSSkoooo.....`,`......kLLkcck.....`,`.....kLLlJJJk.....`,`.....kLlJJJJk.....`,`.....ksSkJJjk.....`,`.....kSkJJJjk.....`,`......kPPPPPk.....`,`......kPPpk.......`,`......kBBBwk......`,`.......kkkk.......`]]},{down:[`....oooooooooo....`,`...ohhhhhhhhHdo...`,`..ohhhhhhhHhHHHo..`,`.ohhhhhhHHHHdHHHo.`,`.ohhhhdHdHHHHHHdo.`,`.ohhHHHHHHHHHHHdo.`,`.oHHHHhHHHHdHdddo.`,`.ohdddddddddddddo.`,`..ooSdsdsdsdsdSo..`,`...kSsssssssssSk..`,`...kSseEsssEesSk..`,`...kSseessseesSk..`,`....kSsssSsssSk...`,`.....kSssmssSk....`,`.....kLkccckLk....`,`...kkLLlJJJlLLkk..`,`..kLLlJJJJJJJlLLk.`,`.kssklJJJjJJJlkssk`,`.kSskJJjJJJjJJksSk`,`..kkPPPPPPPPPPPkk.`,`....kPPpk.kpPPk...`,`....kBBwk.kwBBk...`,`.....kkk...kkk....`],walk:[[`.....ooooooooo....`,`...oohhhhhhhHdoo..`,`..ohhhhhhhdHHdHHo.`,`..ohhhhhdhdHHHHHo.`,`.ohhhhHHHHdHdHHHHo`,`.ohhhHHHHHHdHHdddo`,`.ohHHHHHHHHHHddddo`,`.odddddddHHddddddo`,`..odssdSSddddddoo.`,`.ksssssSSddddoo...`,`kseEsssSSSsdo.....`,`kseesssSsSDo......`,`.ksmsssSSSk.......`,`..kkssSSkk........`,`......kLLkcck.....`,`.....kLLlJJJk.....`,`.....kLlJJJJk.....`,`.....ksSkJJjk.....`,`.....kSkJJJjk.....`,`......kPPPPPk.....`,`.......kPPpk......`,`......kBBBwk......`,`.......kkkk.......`],[`.....ooooooooo....`,`...oohhhhhhhHdoo..`,`..ohhhhhhhdHHdHHo.`,`..ohhhhhdhdHHHHHo.`,`.ohhhhHHHHdHdHHHHo`,`.ohhhHHHHHHdHHdddo`,`.ohHHHHHHHHHHddddo`,`.odddddddHHddddddo`,`..odssdSSddddddoo.`,`.ksssssSSddddoo...`,`kseEsssSSSsdo.....`,`kseesssSsSDo......`,`.ksmsssSSSk.......`,`..kkssSSkk........`,`......kLLkcck.....`,`.....kLLlJJJk.....`,`.....kLlJJJJk.....`,`.....ksSkJJjk.....`,`.....kSkJJJjk.....`,`......kPPPPPk.....`,`.....kPpk.kPpk....`,`....kBBwk.kBBwk...`,`.....kkk...kkk....`],[`.....ooooooooo....`,`...oohhhhhhhHdoo..`,`..ohhhhhhhdHHdHHo.`,`..ohhhhhdhdHHHHHo.`,`.ohhhhHHHHdHdHHHHo`,`.ohhhHHHHHHdHHdddo`,`.ohHHHHHHHHHHddddo`,`.odddddddHHddddddo`,`..odssdSSddddddoo.`,`.ksssssSSddddoo...`,`kseEsssSSSsdo.....`,`kseesssSsSDo......`,`.ksmsssSSSk.......`,`..kkssSSkk........`,`......kLLkcck.....`,`.....kLLlJJJk.....`,`.....kLlJJJJk.....`,`.....ksSkJJjk.....`,`.....kSkJJJjk.....`,`......kPPPPPk.....`,`......kPPpk.......`,`......kBBBwk......`,`.......kkkk.......`]]},{down:[`........oo.........`,`.....ooohhooo......`,`...oohhhhhhhHoo....`,`..ohhhhhhHHhHHHo...`,`.ohhhhhhHHHHHHHHo..`,`.ohhhhdHdHHHHHHdo..`,`ohhhHHHHHHHHHHdddo.`,`ohHXXHHHHHHHHddddo.`,`oHhXdddddddddddddo.`,`.oHdSSdssdssdSSdo..`,`.oHHSsssssssssSdo..`,`..oHSseEsssEesSo...`,`...oSseessseesSk...`,`....kSsssSsssSk....`,`.....kSssmssSk.....`,`.....kLkccckLk.....`,`...kkLLlJJJlLLkk...`,`..kLLlJJJJJJJlLLk..`,`.kssklJJJjJJJlkssk.`,`.kSskJJjJJJjJJksSk.`,`..kkPPPPPPPPPPPkk..`,`....kPPpk.kpPPk....`,`....kBBwk.kwBBk....`,`.....kkk...kkk.....`],walk:[[`........ooo........`,`.....ooohhhooo.....`,`....ohhhhhhhHHo....`,`...ohhhhhhdHHdHo...`,`..ohhhhhdhHHHHHHoo.`,`.ohhhhHHHHdHdHHHHdo`,`.ohhHHHHHHHdHHddddo`,`.oHHHHHHHHHHdXXdddo`,`.odddddddHHHdXddddo`,`..odssdSSHddddddddo`,`.ksssssSSdddddddddo`,`kseEsssSSddddddddo.`,`kseesssSsdddddddo..`,`.ksmsssSSddddooo...`,`..kkssSSkoooo......`,`......kLLkcck......`,`.....kLLlJJJk......`,`.....kLlJJJJk......`,`.....ksSkJJjk......`,`.....kSkJJJjk......`,`......kPPPPPk......`,`.......kPPpk.......`,`......kBBBwk.......`,`.......kkkk........`],[`........ooo........`,`.....ooohhhooo.....`,`....ohhhhhhhHHo....`,`...ohhhhhhdHHdHo...`,`..ohhhhhdhHHHHHHoo.`,`.ohhhhHHHHdHdHHHHdo`,`.ohhHHHHHHHdHHddddo`,`.oHHHHHHHHHHdXXdddo`,`.odddddddHHHdXddddo`,`..odssdSSHddddddddo`,`.ksssssSSdddddddddo`,`kseEsssSSddddddddo.`,`kseesssSsdddddddo..`,`.ksmsssSSddddooo...`,`..kkssSSkoooo......`,`......kLLkcck......`,`.....kLLlJJJk......`,`.....kLlJJJJk......`,`.....ksSkJJjk......`,`.....kSkJJJjk......`,`......kPPPPPk......`,`.....kPpk.kPpk.....`,`....kBBwk.kBBwk....`,`.....kkk...kkk.....`],[`........ooo........`,`.....ooohhhooo.....`,`....ohhhhhhhHHo....`,`...ohhhhhhdHHdHo...`,`..ohhhhhdhHHHHHHoo.`,`.ohhhhHHHHdHdHHHHdo`,`.ohhHHHHHHHdHHddddo`,`.oHHHHHHHHHHdXXdddo`,`.odddddddHHHdXddddo`,`..odssdSSHddddddddo`,`.ksssssSSdddddddddo`,`kseEsssSSddddddddo.`,`kseesssSsdddddddo..`,`.ksmsssSSddddooo...`,`..kkssSSkoooo......`,`......kLLkcck......`,`.....kLLlJJJk......`,`.....kLlJJJJk......`,`.....ksSkJJjk......`,`.....kSkJJJjk......`,`......kPPPPPk......`,`......kPPpk........`,`......kBBBwk.......`,`.......kkkk........`]]},{down:[`......oooooo......`,`...ooohhhhhhooo...`,`..ohhhhhhhhHHdHo..`,`.ohhhhhhhHHhHHHHo.`,`.ohhhhhHHHHHHHHHo.`,`ohhhhHdHHHHHHHHdHo`,`ohhhHHHHHHHHHHdddo`,`ohHHHhhHHHHdHddddo`,`oHhddddddddddddddo`,`oHHHSdsdsdsdsdSddo`,`oHHHSsssssssssSddo`,`oHHHSseEsssEesSddo`,`oHHHSseessseesSddo`,`.ooodSsssSsssSkoo.`,`....okSssmssSk....`,`.....kLkccckLk....`,`...kkLLlJJJlLLkk..`,`..kLLlJJJJJJJlLLk.`,`.kssklJJJjJJJlkssk`,`.kSskJJjJJJjJJksSk`,`..kkPPPPPPPPPPPkk.`,`....kPPpk.kpPPk...`,`....kBBwk.kwBBk...`,`.....kkk...kkk....`],walk:[[`......ooooooo.....`,`....oohhhhhhhoo...`,`...ohhhhhhhHHHHo..`,`..ohhhhhhHdHHdHHo.`,`.ohhhhhhdHHHHHHHHo`,`.ohhhhHHHHdHdHHHHo`,`.ohhHHHhHHHdHHdddo`,`.oHHHHhHHHHHHHdddo`,`.odddddddHHHdddddo`,`..odssdSSHdddddddo`,`.ksssssSSddddddddo`,`kseEsssSSddddddddo`,`kseesssSsdddddddo.`,`.ksmsssSSdddddoo..`,`..kkssSSkooooo....`,`......kLLkcck.....`,`.....kLLlJJJk.....`,`.....kLlJJJJk.....`,`.....ksSkJJjk.....`,`.....kSkJJJjk.....`,`......kPPPPPk.....`,`.......kPPpk......`,`......kBBBwk......`,`.......kkkk.......`],[`......ooooooo.....`,`....oohhhhhhhoo...`,`...ohhhhhhhHHHHo..`,`..ohhhhhhHdHHdHHo.`,`.ohhhhhhdHHHHHHHHo`,`.ohhhhHHHHdHdHHHHo`,`.ohhHHHhHHHdHHdddo`,`.oHHHHhHHHHHHHdddo`,`.odddddddHHHdddddo`,`..odssdSSHdddddddo`,`.ksssssSSddddddddo`,`kseEsssSSddddddddo`,`kseesssSsdddddddo.`,`.ksmsssSSdddddoo..`,`..kkssSSkooooo....`,`......kLLkcck.....`,`.....kLLlJJJk.....`,`.....kLlJJJJk.....`,`.....ksSkJJjk.....`,`.....kSkJJJjk.....`,`......kPPPPPk.....`,`.....kPpk.kPpk....`,`....kBBwk.kBBwk...`,`.....kkk...kkk....`],[`......ooooooo.....`,`....oohhhhhhhoo...`,`...ohhhhhhhHHHHo..`,`..ohhhhhhHdHHdHHo.`,`.ohhhhhhdHHHHHHHHo`,`.ohhhhHHHHdHdHHHHo`,`.ohhHHHhHHHdHHdddo`,`.oHHHHhHHHHHHHdddo`,`.odddddddHHHdddddo`,`..odssdSSHdddddddo`,`.ksssssSSddddddddo`,`kseEsssSSddddddddo`,`kseesssSsdddddddo.`,`.ksmsssSSdddddoo..`,`..kkssSSkooooo....`,`......kLLkcck.....`,`.....kLLlJJJk.....`,`.....kLlJJJJk.....`,`.....ksSkJJjk.....`,`.....kSkJJJjk.....`,`......kPPPPPk.....`,`......kPPpk.......`,`......kBBBwk......`,`.......kkkk.......`]]},{down:[`....ohohhhhhooo....`,`..oohhhhhhhHHhHo...`,`.odhhhdhhHdHHHdoo..`,`ohhhhhhHHHHHHHHHHo.`,`ohhhhHHhHHHhHHHhHo.`,`ohhhdHHHdHHHdHHHdo.`,`hhHHHHHHHHHHHHddddo`,`HhHHHhHHHhHHHdddddo`,`HHddddddddddddddddo`,`oHHHSdssdsdssdSddo.`,`oHHhSsssssssssSddo.`,`.oHHSseEsssEesSdo..`,`..oHSseessseesSo...`,`...okSsssSsssSk....`,`.....kSssmssSk.....`,`.....kLkccckLk.....`,`...kkLLlJJJlLLkk...`,`..kLLlJJJJJJJlLLk..`,`.kssklJJJjJJJlkssk.`,`.kSskJJjJJJjJJksSk.`,`..kkPPPPPPPPPPPkk..`,`....kPPpk.kpPPk....`,`....kBBwk.kwBBk....`,`.....kkk...kkk.....`],walk:[[`....ooohhhhhooo....`,`...ohhhhhhhHHhHo...`,`..oohhdhhHdHHHdoo..`,`.ohhhhhhHHHHHHHHHo.`,`ohhhhhHhHHHhHHHhHo.`,`ohhhdHHHdHHHdHHHddo`,`ohHHHHHHHHHHHHHdddo`,`ohHHHhHHHhHHHdddddo`,`oddddddddHddddddddo`,`.oodssdSSdddddddddo`,`.ksssssSSddddddddo.`,`kseEsssSSSsddddddo.`,`kseesssSsSDdddddo..`,`.ksmsssSSSddoooo...`,`..kkssSSodoo.......`,`......kLLkcck......`,`.....kLLlJJJk......`,`.....kLlJJJJk......`,`.....ksSkJJjk......`,`.....kSkJJJjk......`,`......kPPPPPk......`,`.......kPPpk.......`,`......kBBBwk.......`,`.......kkkk........`],[`....ooohhhhhooo....`,`...ohhhhhhhHHhHo...`,`..oohhdhhHdHHHdoo..`,`.ohhhhhhHHHHHHHHHo.`,`ohhhhhHhHHHhHHHhHo.`,`ohhhdHHHdHHHdHHHddo`,`ohHHHHHHHHHHHHHdddo`,`ohHHHhHHHhHHHdddddo`,`oddddddddHddddddddo`,`.oodssdSSdddddddddo`,`.ksssssSSddddddddo.`,`kseEsssSSSsddddddo.`,`kseesssSsSDdddddo..`,`.ksmsssSSSddoooo...`,`..kkssSSodoo.......`,`......kLLkcck......`,`.....kLLlJJJk......`,`.....kLlJJJJk......`,`.....ksSkJJjk......`,`.....kSkJJJjk......`,`......kPPPPPk......`,`.....kPpk.kPpk.....`,`....kBBwk.kBBwk....`,`.....kkk...kkk.....`],[`....ooohhhhhooo....`,`...ohhhhhhhHHhHo...`,`..oohhdhhHdHHHdoo..`,`.ohhhhhhHHHHHHHHHo.`,`ohhhhhHhHHHhHHHhHo.`,`ohhhdHHHdHHHdHHHddo`,`ohHHHHHHHHHHHHHdddo`,`ohHHHhHHHhHHHdddddo`,`oddddddddHddddddddo`,`.oodssdSSdddddddddo`,`.ksssssSSddddddddo.`,`kseEsssSSSsddddddo.`,`kseesssSsSDdddddo..`,`.ksmsssSSSddoooo...`,`..kkssSSodoo.......`,`......kLLkcck......`,`.....kLLlJJJk......`,`.....kLlJJJJk......`,`.....ksSkJJjk......`,`.....kSkJJJjk......`,`......kPPPPPk......`,`......kPPpk........`,`......kBBBwk.......`,`.......kkkk........`]]},{down:[`.ooo...........ooo.`,`ohhho.oooooo..oHHHo`,`hhhhhohhhhhhooHhHHd`,`hhhhhhhhhhHHHdHHHdH`,`ohhhhhhhHHHhHHHHHHo`,`.ohhhhhHHHHHdHHHdo.`,`ohhhhhHHHHHHHHHHdo.`,`ohhHHHdHHHHHHddddo.`,`oHHddddddddddddddo.`,`oHHHSSdssdssdSSddo.`,`.odHSsssssssssSdo..`,`.oHHSseEsssEesSdo..`,`..oHSseessseesSo...`,`...okSsssSsssSk....`,`.....kSssmssSk.....`,`.....kLkccckLk.....`,`...kkLLlJJJlLLkk...`,`..kLLlJJJJJJJlLLk..`,`.kssklJJJjJJJlkssk.`,`.kSskJJjJJJjJJksSk.`,`..kkPPPPPPPPPPPkk..`,`....kPPpk.kpPPk....`,`....kBBwk.kwBBk....`,`.....kkk...kkk.....`],walk:[[`.............ooo...`,`......ooooooohhHo..`,`....oohhhhhhhHHHHo.`,`...ohhhhhhhHHHHHHo.`,`..ohhhhhhhHHHdHHHo.`,`.ohhhhhhHHHHHHHHo..`,`.ohhhhHHhHHHHHHddo.`,`.ohdHHHHHHHHHdHddo.`,`.odddddddHHHHddddo.`,`..odssdSSHHddddddo.`,`.ksssssSSddddddddo.`,`kseEsssSSdddddddo..`,`kseesssSsddddddo...`,`.ksmsssSSdddddo....`,`..kkssSSoddooo.....`,`......kLLkcck......`,`.....kLLlJJJk......`,`.....kLlJJJJk......`,`.....ksSkJJjk......`,`.....kSkJJJjk......`,`......kPPPPPk......`,`.......kPPpk.......`,`......kBBBwk.......`,`.......kkkk........`],[`.............ooo...`,`......ooooooohhHo..`,`....oohhhhhhhHHHHo.`,`...ohhhhhhhHHHHHHo.`,`..ohhhhhhhHHHdHHHo.`,`.ohhhhhhHHHHHHHHo..`,`.ohhhhHHhHHHHHHddo.`,`.ohdHHHHHHHHHdHddo.`,`.odddddddHHHHddddo.`,`..odssdSSHHddddddo.`,`.ksssssSSddddddddo.`,`kseEsssSSdddddddo..`,`kseesssSsddddddo...`,`.ksmsssSSdddddo....`,`..kkssSSoddooo.....`,`......kLLkcck......`,`.....kLLlJJJk......`,`.....kLlJJJJk......`,`.....ksSkJJjk......`,`.....kSkJJJjk......`,`......kPPPPPk......`,`.....kPpk.kPpk.....`,`....kBBwk.kBBwk....`,`.....kkk...kkk.....`],[`.............ooo...`,`......ooooooohhHo..`,`....oohhhhhhhHHHHo.`,`...ohhhhhhhHHHHHHo.`,`..ohhhhhhhHHHdHHHo.`,`.ohhhhhhHHHHHHHHo..`,`.ohhhhHHhHHHHHHddo.`,`.ohdHHHHHHHHHdHddo.`,`.odddddddHHHHddddo.`,`..odssdSSHHddddddo.`,`.ksssssSSddddddddo.`,`kseEsssSSdddddddo..`,`kseesssSsddddddo...`,`.ksmsssSSdddddo....`,`..kkssSSoddooo.....`,`......kLLkcck......`,`.....kLLlJJJk......`,`.....kLlJJJJk......`,`.....ksSkJJjk......`,`.....kSkJJJjk......`,`......kPPPPPk......`,`......kPPpk........`,`......kBBBwk.......`,`.......kkkk........`]]},{down:[`......oooooo......`,`....oohhhhhhoo....`,`...ohhhhhhHHHdo...`,`..ohhhhhhHHhHHHo..`,`.ohhhhhHHHHHdHHHo.`,`ohhhhHHHHHHHHHHdHo`,`ohhddHHHHHHHHHHddo`,`oHHHHhHHHHHdHddddo`,`oHHddddddddddddddo`,`oHHHSdsdsdsdsdSddo`,`.oHHSsssssssssSdo.`,`..oHSseEsssEesSdo.`,`..oHSseessseesSo..`,`...okSsssSsssSk...`,`.....kSssmssSk....`,`.....kLkccckLk....`,`...kkLLlJJJlLLkk..`,`..kLLlJJJJJJJlLLk.`,`.kssklJJJjJJJlkssk`,`.kSskJJjJJJjJJksSk`,`..kkPPPPPPPPPPPkk.`,`....kPPpk.kpPPk...`,`....kBBwk.kwBBk...`,`.....kkk...kkk....`],walk:[[`......ooooooo.....`,`....oohhhhhhhoo...`,`...ohhhhhhhHHHHo..`,`..ohhhhhhhHHHdHHo.`,`.ohhhhhhHHHHHHHHo.`,`.ohhhHHHHHdHdHHHHo`,`.ohhddHHHHHHHHdddo`,`ohHHHhHHHHHHHddddo`,`oddddddddHHHdddddo`,`.oodssdSSHdddddddo`,`.ksssssSSddddddddo`,`kseEsssSSSsdddddo.`,`kseesssSsSDddddo..`,`.ksmsssSSSddooo...`,`..kkssSSkkoo......`,`......kLLkcck.....`,`.....kLLlJJJk.....`,`.....kLlJJJJk.....`,`.....ksSkJJjk.....`,`.....kSkJJJjk.....`,`......kPPPPPk.....`,`.......kPPpk......`,`......kBBBwk......`,`.......kkkk.......`],[`......ooooooo.....`,`....oohhhhhhhoo...`,`...ohhhhhhhHHHHo..`,`..ohhhhhhhHHHdHHo.`,`.ohhhhhhHHHHHHHHo.`,`.ohhhHHHHHdHdHHHHo`,`.ohhddHHHHHHHHdddo`,`ohHHHhHHHHHHHddddo`,`oddddddddHHHdddddo`,`.oodssdSSHdddddddo`,`.ksssssSSddddddddo`,`kseEsssSSSsdddddo.`,`kseesssSsSDddddo..`,`.ksmsssSSSddooo...`,`..kkssSSkkoo......`,`......kLLkcck.....`,`.....kLLlJJJk.....`,`.....kLlJJJJk.....`,`.....ksSkJJjk.....`,`.....kSkJJJjk.....`,`......kPPPPPk.....`,`.....kPpk.kPpk....`,`....kBBwk.kBBwk...`,`.....kkk...kkk....`],[`......ooooooo.....`,`....oohhhhhhhoo...`,`...ohhhhhhhHHHHo..`,`..ohhhhhhhHHHdHHo.`,`.ohhhhhhHHHHHHHHo.`,`.ohhhHHHHHdHdHHHHo`,`.ohhddHHHHHHHHdddo`,`ohHHHhHHHHHHHddddo`,`oddddddddHHHdddddo`,`.oodssdSSHdddddddo`,`.ksssssSSddddddddo`,`kseEsssSSSsdddddo.`,`kseesssSsSDddddo..`,`.ksmsssSSSddooo...`,`..kkssSSkkoo......`,`......kLLkcck.....`,`.....kLLlJJJk.....`,`.....kLlJJJJk.....`,`.....ksSkJJjk.....`,`.....kSkJJJjk.....`,`......kPPPPPk.....`,`......kPPpk.......`,`......kBBBwk......`,`.......kkkk.......`]]},{down:[`.....o.ooooo.......`,`....ohohhhhhoo.....`,`..oohhdhhhdHHHo....`,`.ohhhhhhHHHHHHHo...`,`.ohhhhhhHHHhHHHoo..`,`ohhhdHHHdHHHdHHHdo.`,`ohhHHHHHHHHHHHHddo.`,`ohHHHhHHHhHHHddddo.`,`oHdddddddddddddddo.`,`oHHHSdssdsdssdSddo.`,`oHHhSsssssssssSddo.`,`oHHHSseEsssEesSddo.`,`oHHHSseessseesSddo.`,`.oookSsssSsssSkoo..`,`.....kSssmssSk.....`,`.....kLkccckLk.....`,`...kkLLlJJJlLLkk...`,`..kLLlJJJJJJJlLLk..`,`.kssklJJJjJJJlkssk.`,`.kSskJJjJJJjJJksSk.`,`..kkPPPPPPPPPPPkk..`,`....kPPpk.kpPPk....`,`....kBBwk.kwBBk....`,`.....kkk...kkk.....`],walk:[[`.......ooooo.......`,`....ooohhhhhooo....`,`...ohhdhhhdHHHdo...`,`..oohhhhhHHHHHHoo..`,`.ohhhhhhHHHhHHHhHo.`,`.ohhdHHHdHHHdHHHdo.`,`ohhHHHHHHHHHHHHddo.`,`ohHHHhHHHhHHHdddddo`,`oddddddddHddddddddo`,`.oodssdSSHdddddddo.`,`.ksssssSSddddddddo.`,`kseEsssSSdddddddo..`,`kseesssSsddddddo...`,`.ksmsssSSddddoo....`,`..kkssSSkoooo......`,`......kLLkcck......`,`.....kLLlJJJk......`,`.....kLlJJJJk......`,`.....ksSkJJjk......`,`.....kSkJJJjk......`,`......kPPPPPk......`,`.......kPPpk.......`,`......kBBBwk.......`,`.......kkkk........`],[`.......ooooo.......`,`....ooohhhhhooo....`,`...ohhdhhhdHHHdo...`,`..oohhhhhHHHHHHoo..`,`.ohhhhhhHHHhHHHhHo.`,`.ohhdHHHdHHHdHHHdo.`,`ohhHHHHHHHHHHHHddo.`,`ohHHHhHHHhHHHdddddo`,`oddddddddHddddddddo`,`.oodssdSSHdddddddo.`,`.ksssssSSddddddddo.`,`kseEsssSSdddddddo..`,`kseesssSsddddddo...`,`.ksmsssSSddddoo....`,`..kkssSSkoooo......`,`......kLLkcck......`,`.....kLLlJJJk......`,`.....kLlJJJJk......`,`.....ksSkJJjk......`,`.....kSkJJJjk......`,`......kPPPPPk......`,`.....kPpk.kPpk.....`,`....kBBwk.kBBwk....`,`.....kkk...kkk.....`],[`.......ooooo.......`,`....ooohhhhhooo....`,`...ohhdhhhdHHHdo...`,`..oohhhhhHHHHHHoo..`,`.ohhhhhhHHHhHHHhHo.`,`.ohhdHHHdHHHdHHHdo.`,`ohhHHHHHHHHHHHHddo.`,`ohHHHhHHHhHHHdddddo`,`oddddddddHddddddddo`,`.oodssdSSHdddddddo.`,`.ksssssSSddddddddo.`,`kseEsssSSdddddddo..`,`kseesssSsddddddo...`,`.ksmsssSSddddoo....`,`..kkssSSkoooo......`,`......kLLkcck......`,`.....kLLlJJJk......`,`.....kLlJJJJk......`,`.....ksSkJJjk......`,`.....kSkJJJjk......`,`......kPPPPPk......`,`......kPPpk........`,`......kBBBwk.......`,`.......kkkk........`]]},{down:[`...oooohhhhhho.....`,`..ohhhhhhhhhHHoo...`,`.oohhhhhhhHHHdHHo..`,`ohhhhhhhHHdHHHHHo..`,`ohhhhhHHHHHHdHHHdo.`,`ohhhhHHHHHHHHHHdHdo`,`hhhdddHHHHHHHHHdddo`,`hHHHhHHHHHHHHddddo.`,`HhHdddddddddddddddo`,`oHdHSdsdsssdsdSdddo`,`odHHSsssssssssSddo.`,`oHHHSseEsssEesSddo.`,`oHHHSseessseesSddo.`,`.odddSsssSsssSddo..`,`..odddSssmssSddo...`,`.....kLkccckLk.....`,`...kkLLlJJJlLLkk...`,`..kLLlJJJJJJJlLLk..`,`.kssklJJJjJJJlkssk.`,`.kSskJJjJJJjJJksSk.`,`..kkPPPPPPPPPPPkk..`,`....kPPpk.kpPPk....`,`....kBBwk.kwBBk....`,`.....kkk...kkk.....`],walk:[[`....ooohhhohho.....`,`...ohhhhhhhhHHoo...`,`..ohhhhhhhdHHHHHo..`,`.ohhhhhhhhHHHdHHHo.`,`ohhhhhhhHHHHHHHHHo.`,`ohhhhhHdHHdHHHHHHdo`,`ohhdddHHHHHHHHddddo`,`hHHHhHHHHHHHHdddddo`,`HddddddddHHHddddddo`,`ooodssdSSHddddddddo`,`.ksssssSSdddddddddo`,`kseEsssSSddddddddo.`,`kseesssSsddddddddo.`,`.ksmsssSSdddddddo..`,`..kkssSSoddddddo...`,`......kLLkcck......`,`.....kLLlJJJk......`,`.....kLlJJJJk......`,`.....ksSkJJjk......`,`.....kSkJJJjk......`,`......kPPPPPk......`,`.......kPPpk.......`,`......kBBBwk.......`,`.......kkkk........`],[`....ooohhhohho.....`,`...ohhhhhhhhHHoo...`,`..ohhhhhhhdHHHHHo..`,`.ohhhhhhhhHHHdHHHo.`,`ohhhhhhhHHHHHHHHHo.`,`ohhhhhHdHHdHHHHHHdo`,`ohhdddHHHHHHHHddddo`,`hHHHhHHHHHHHHdddddo`,`HddddddddHHHddddddo`,`ooodssdSSHddddddddo`,`.ksssssSSdddddddddo`,`kseEsssSSddddddddo.`,`kseesssSsddddddddo.`,`.ksmsssSSdddddddo..`,`..kkssSSoddddddo...`,`......kLLkcck......`,`.....kLLlJJJk......`,`.....kLlJJJJk......`,`.....ksSkJJjk......`,`.....kSkJJJjk......`,`......kPPPPPk......`,`.....kPpk.kPpk.....`,`....kBBwk.kBBwk....`,`.....kkk...kkk.....`],[`....ooohhhohho.....`,`...ohhhhhhhhHHoo...`,`..ohhhhhhhdHHHHHo..`,`.ohhhhhhhhHHHdHHHo.`,`ohhhhhhhHHHHHHHHHo.`,`ohhhhhHdHHdHHHHHHdo`,`ohhdddHHHHHHHHddddo`,`hHHHhHHHHHHHHdddddo`,`HddddddddHHHddddddo`,`ooodssdSSHddddddddo`,`.ksssssSSdddddddddo`,`kseEsssSSddddddddo.`,`kseesssSsddddddddo.`,`.ksmsssSSdddddddo..`,`..kkssSSoddddddo...`,`......kLLkcck......`,`.....kLLlJJJk......`,`.....kLlJJJJk......`,`.....ksSkJJjk......`,`.....kSkJJJjk......`,`......kPPPPPk......`,`......kPPpk........`,`......kBBBwk.......`,`.......kkkk........`]]},{down:[`.....oooooooo.....`,`...oohhhhhhhHoo...`,`..ohhhhhhhHhHdHo..`,`.ohhhhhhHHHhHHHHo.`,`.ohhhhHhdHHHdHHHo.`,`ohhhHHHdHHHdHHdHdo`,`ohHHHHHHHHHHdHdddo`,`oHHddddddddddddddo`,`oHHdSSsssssssSSddo`,`.odHSsssssssssSdo.`,`..oHSseEsssEesSdo.`,`..oHSseessseesSo..`,`...okSsssSsssSk...`,`.....kSssmssSk....`,`.....kLkccckLk....`,`...kkLLlJJJlLLkk..`,`..kLLlJJJJJJJlLLk.`,`.kssklJJJjJJJlkssk`,`.kSskJJjJJJjJJksSk`,`..kkPPPPPPPPPPPkk.`,`....kPPpk.kpPPk...`,`....kBBwk.kwBBk...`,`.....kkk...kkk....`],walk:[[`.....oooooooo.....`,`....ohhhhhhhHoo...`,`...ohhhhhhdHHdHo..`,`..ohhhhhHhHHHdHHo.`,`.ohhhhhHHHdhHHHHdo`,`.ohhhHhHHHHHHHHHdo`,`.ohHHHHHHHHHHHdddo`,`.odddddddHHHdddddo`,`..odssdSSHdddddddo`,`.ksssssSSddddddddo`,`kseEsssSSSsdddddo.`,`kseesssSsSDddddo..`,`.ksmsssSSSddooo...`,`..kkssSSkkoo......`,`......kLLkcck.....`,`.....kLLlJJJk.....`,`.....kLlJJJJk.....`,`.....ksSkJJjk.....`,`.....kSkJJJjk.....`,`......kPPPPPk.....`,`.......kPPpk......`,`......kBBBwk......`,`.......kkkk.......`],[`.....oooooooo.....`,`....ohhhhhhhHoo...`,`...ohhhhhhdHHdHo..`,`..ohhhhhHhHHHdHHo.`,`.ohhhhhHHHdhHHHHdo`,`.ohhhHhHHHHHHHHHdo`,`.ohHHHHHHHHHHHdddo`,`.odddddddHHHdddddo`,`..odssdSSHdddddddo`,`.ksssssSSddddddddo`,`kseEsssSSSsdddddo.`,`kseesssSsSDddddo..`,`.ksmsssSSSddooo...`,`..kkssSSkkoo......`,`......kLLkcck.....`,`.....kLLlJJJk.....`,`.....kLlJJJJk.....`,`.....ksSkJJjk.....`,`.....kSkJJJjk.....`,`......kPPPPPk.....`,`.....kPpk.kPpk....`,`....kBBwk.kBBwk...`,`.....kkk...kkk....`],[`.....oooooooo.....`,`....ohhhhhhhHoo...`,`...ohhhhhhdHHdHo..`,`..ohhhhhHhHHHdHHo.`,`.ohhhhhHHHdhHHHHdo`,`.ohhhHhHHHHHHHHHdo`,`.ohHHHHHHHHHHHdddo`,`.odddddddHHHdddddo`,`..odssdSSHdddddddo`,`.ksssssSSddddddddo`,`kseEsssSSSsdddddo.`,`kseesssSsSDddddo..`,`.ksmsssSSSddooo...`,`..kkssSSkkoo......`,`......kLLkcck.....`,`.....kLLlJJJk.....`,`.....kLlJJJJk.....`,`.....ksSkJJjk.....`,`.....kSkJJJjk.....`,`......kPPPPPk.....`,`......kPPpk.......`,`......kBBBwk......`,`.......kkkk.......`]]},{down:[`......oooooo.......`,`....oohhhhhHoo.....`,`...ohhhhhhHHHHo....`,`..ohhhhhHHHHdHHo...`,`.oohhhdHdHHHHHHooo.`,`ohhhhHhHHHHHHHHdddo`,`ohhHHHHHHHHHHdddddo`,`oXXdddddddddddddXXo`,`ohHHSSddHHHHHHHdddo`,`oHHHSssssssddddoddo`,`oHHHSseEsssEesSoddo`,`.oooSseessseesSkoo.`,`....kSsssSsssSk....`,`.....kSssmssSk.....`,`.....kLkccckLk.....`,`...kkLLlJJJlLLkk...`,`..kLLlJJJJJJJlLLk..`,`.kssklJJJjJJJlkssk.`,`.kSskJJjJJJjJJksSk.`,`..kkPPPPPPPPPPPkk..`,`....kPPpk.kpPPk....`,`....kBBwk.kwBBk....`,`.....kkk...kkk.....`],walk:[[`......ooooooo......`,`.....ohhhhhhHo.....`,`....ohhhhhdHHHo....`,`...ohhhhdhdhHHHo...`,`..ohhhhHHHdHHHHdo..`,`..ohhHHHHHHdHHdddo.`,`..oHHHHHHHHHdddddo.`,`..oddddddHHHdddXXo.`,`..odssdSSHdddddddo.`,`.ksssssSSddddddddo.`,`kseEsssSSddddddddo.`,`kseesssSsdddddoddo.`,`.ksmsssSSddddooddo.`,`..kkssSSkoooo.oddo.`,`......kLLkcck......`,`.....kLLlJJJk......`,`.....kLlJJJJk......`,`.....ksSkJJjk......`,`.....kSkJJJjk......`,`......kPPPPPk......`,`.......kPPpk.......`,`......kBBBwk.......`,`.......kkkk........`],[`......ooooooo......`,`.....ohhhhhhHo.....`,`....ohhhhhdHHHo....`,`...ohhhhdhdhHHHo...`,`..ohhhhHHHdHHHHdo..`,`..ohhHHHHHHdHHdddo.`,`..oHHHHHHHHHdddddo.`,`..oddddddHHHdddXXo.`,`..odssdSSHdddddddo.`,`.ksssssSSddddddddo.`,`kseEsssSSddddddddo.`,`kseesssSsdddddoddo.`,`.ksmsssSSddddooddo.`,`..kkssSSkoooo.oddo.`,`......kLLkcck......`,`.....kLLlJJJk......`,`.....kLlJJJJk......`,`.....ksSkJJjk......`,`.....kSkJJJjk......`,`......kPPPPPk......`,`.....kPpk.kPpk.....`,`....kBBwk.kBBwk....`,`.....kkk...kkk.....`],[`......ooooooo......`,`.....ohhhhhhHo.....`,`....ohhhhhdHHHo....`,`...ohhhhdhdhHHHo...`,`..ohhhhHHHdHHHHdo..`,`..ohhHHHHHHdHHdddo.`,`..oHHHHHHHHHdddddo.`,`..oddddddHHHdddXXo.`,`..odssdSSHdddddddo.`,`.ksssssSSddddddddo.`,`kseEsssSSddddddddo.`,`kseesssSsdddddoddo.`,`.ksmsssSSddddooddo.`,`..kkssSSkoooo.oddo.`,`......kLLkcck......`,`.....kLLlJJJk......`,`.....kLlJJJJk......`,`.....ksSkJJjk......`,`.....kSkJJJjk......`,`......kPPPPPk......`,`......kPPpk........`,`......kBBBwk.......`,`.......kkkk........`]]},{down:[`......ohhhho......`,`......ohhhHo......`,`.....kohhHHok.....`,`....knsHHHHssk....`,`...knssHHHHsssk...`,`..knsssHHHHssSSk..`,`.ksssssHHHHsSSSSk.`,`.ksssssHHHHSSSSSk.`,`.ksssssHHHdSSSSSk.`,`.ksssssddddSSSSSk.`,`..ksSSsssssssSSk..`,`..ksSseEsssEesSk..`,`...kSseessseesSk..`,`....kSsssSsssSk...`,`.....kSssmssSk....`,`.....kLkccckLk....`,`...kkLLlJJJlLLkk..`,`..kLLlJJJJJJJlLLk.`,`.kssklJJJjJJJlkssk`,`.kSskJJjJJJjJJksSk`,`..kkPPPPPPPPPPPkk.`,`....kPPpk.kpPPk...`,`....kBBwk.kwBBk...`,`.....kkk...kkk....`],walk:[[`.....ohhhhhhHo....`,`....ohhhhhhHHHo...`,`...ohhhhhHHHHHo...`,`..ohhhhhHHHHHHo...`,`..ohhhHHHHHHHHsk..`,`..knssssssssssSSk.`,`..ksssssssssSSSSk.`,`..kssssssssSSSSSk.`,`..kssssssSSSSSSSk.`,`..ksssssSSSSSSSSk.`,`.kodssdSSSSSSSSSk.`,`kseEsssSSSSSSSSk..`,`kseesssSsSSSSSk...`,`.ksmsssSSSSSSk....`,`..kkssSSoddok.....`,`......kLLkcck.....`,`.....kLLlJJJk.....`,`.....kLlJJJJk.....`,`.....ksSkJJjk.....`,`.....kSkJJJjk.....`,`......kPPPPPk.....`,`.......kPPpk......`,`......kBBBwk......`,`.......kkkk.......`],[`.....ohhhhhhHo....`,`....ohhhhhhHHHo...`,`...ohhhhhHHHHHo...`,`..ohhhhhHHHHHHo...`,`..ohhhHHHHHHHHsk..`,`..knssssssssssSSk.`,`..ksssssssssSSSSk.`,`..kssssssssSSSSSk.`,`..kssssssSSSSSSSk.`,`..ksssssSSSSSSSSk.`,`.kodssdSSSSSSSSSk.`,`kseEsssSSSSSSSSk..`,`kseesssSsSSSSSk...`,`.ksmsssSSSSSSk....`,`..kkssSSoddok.....`,`......kLLkcck.....`,`.....kLLlJJJk.....`,`.....kLlJJJJk.....`,`.....ksSkJJjk.....`,`.....kSkJJJjk.....`,`......kPPPPPk.....`,`.....kPpk.kPpk....`,`....kBBwk.kBBwk...`,`.....kkk...kkk....`],[`.....ohhhhhhHo....`,`....ohhhhhhHHHo...`,`...ohhhhhHHHHHo...`,`..ohhhhhHHHHHHo...`,`..ohhhHHHHHHHHsk..`,`..knssssssssssSSk.`,`..ksssssssssSSSSk.`,`..kssssssssSSSSSk.`,`..kssssssSSSSSSSk.`,`..ksssssSSSSSSSSk.`,`.kodssdSSSSSSSSSk.`,`kseEsssSSSSSSSSk..`,`kseesssSsSSSSSk...`,`.ksmsssSSSSSSk....`,`..kkssSSoddok.....`,`......kLLkcck.....`,`.....kLLlJJJk.....`,`.....kLlJJJJk.....`,`.....ksSkJJjk.....`,`.....kSkJJJjk.....`,`......kPPPPPk.....`,`......kPPpk.......`,`......kBBBwk......`,`.......kkkk.......`]]},{down:[`......ohhhho......`,`.....oohhhhoo.....`,`...oohhhhhhhHoo...`,`..ohhhhhhhHhHHHo..`,`.ohhhhhhXXXhHHHHo.`,`.ohhhhdhdHHHHHHdo.`,`ohhhHHhHHHHHHHdddo`,`ohHHHHHHHHHHdddddo`,`oHhddddddddddddddo`,`oHHdSSdssdssdSSddo`,`.odHSsssssssssSdo.`,`.oHHSseEsssEesSdo.`,`.oHHSseessseesSdo.`,`.odddSsssSsssSddo.`,`..odddSssmssSddo..`,`.....kLkccckLk....`,`...kkLLlJJJlLLkk..`,`..kLLlJJJJJJJlLLk.`,`.kssklJJJjJJJlkssk`,`.kSskJJjJJJjJJksSk`,`..kkPPPPPPPPPPPkk.`,`....kPPpk.kpPPk...`,`....kBBwk.kwBBk...`,`.....kkk...kkk....`],walk:[[`........ohhhho....`,`.....oooohhhho....`,`....ohhhhhhhHHo...`,`...ohhhhhhdHHdHo..`,`..ohhhhhdhXXXHHHo.`,`.ohhhhdHHHdHdHHHdo`,`.ohhHHHHHHHHHHHHdo`,`.ohHHHHHHHHHHHdddo`,`.odddddddHHHdddddo`,`..odssdSSHdddddddo`,`.ksssssSSddddddddo`,`kseEsssSSddddddddo`,`kseesssSsddddddddo`,`.ksmsssSSdddddddo.`,`..kkssSSoddddddo..`,`......kLLkcck.....`,`.....kLLlJJJk.....`,`.....kLlJJJJk.....`,`.....ksSkJJjk.....`,`.....kSkJJJjk.....`,`......kPPPPPk.....`,`.......kPPpk......`,`......kBBBwk......`,`.......kkkk.......`],[`........ohhhho....`,`.....oooohhhho....`,`....ohhhhhhhHHo...`,`...ohhhhhhdHHdHo..`,`..ohhhhhdhXXXHHHo.`,`.ohhhhdHHHdHdHHHdo`,`.ohhHHHHHHHHHHHHdo`,`.ohHHHHHHHHHHHdddo`,`.odddddddHHHdddddo`,`..odssdSSHdddddddo`,`.ksssssSSddddddddo`,`kseEsssSSddddddddo`,`kseesssSsddddddddo`,`.ksmsssSSdddddddo.`,`..kkssSSoddddddo..`,`......kLLkcck.....`,`.....kLLlJJJk.....`,`.....kLlJJJJk.....`,`.....ksSkJJjk.....`,`.....kSkJJJjk.....`,`......kPPPPPk.....`,`.....kPpk.kPpk....`,`....kBBwk.kBBwk...`,`.....kkk...kkk....`],[`........ohhhho....`,`.....oooohhhho....`,`....ohhhhhhhHHo...`,`...ohhhhhhdHHdHo..`,`..ohhhhhdhXXXHHHo.`,`.ohhhhdHHHdHdHHHdo`,`.ohhHHHHHHHHHHHHdo`,`.ohHHHHHHHHHHHdddo`,`.odddddddHHHdddddo`,`..odssdSSHdddddddo`,`.ksssssSSddddddddo`,`kseEsssSSddddddddo`,`kseesssSsddddddddo`,`.ksmsssSSdddddddo.`,`..kkssSSoddddddo..`,`......kLLkcck.....`,`.....kLLlJJJk.....`,`.....kLlJJJJk.....`,`.....ksSkJJjk.....`,`.....kSkJJJjk.....`,`......kPPPPPk.....`,`......kPPpk.......`,`......kBBBwk......`,`.......kkkk.......`]]},{down:[`.....o.ooooo.......`,`....ohohhhhhooo....`,`..oohhdhhhdHHHdo...`,`.ohhhhhhHHHHHHHoo..`,`ohhhhhHhHHHhHHHhHo.`,`ohhhdHHHdHHHdHHHdo.`,`ohhHHHHHHHHHHHHddo.`,`ohHHHhHHHhHHHddddo.`,`oHdddddddddddddddo.`,`oHHHSdssdsdssdSddo.`,`oHHhSsssssssssSddo.`,`oHHHSseEsssEesSddo.`,`oHHHSseessseesSddo.`,`.odddSsssSsssSddo..`,`..odddSssmssSddo...`,`.....kLkccckLk.....`,`...kkLLlJJJlLLkk...`,`..kLLlJJJJJJJlLLk..`,`.kssklJJJjJJJlkssk.`,`.kSskJJjJJJjJJksSk.`,`..kkPPPPPPPPPPPkk..`,`....kPPpk.kpPPk....`,`....kBBwk.kwBBk....`,`.....kkk...kkk.....`],walk:[[`.....o.ooooo.o.....`,`....ohohhhhhoho....`,`...ohhdhhhdHHHdo...`,`..oohhhhhHHHHHHoo..`,`.ohhhhhhHHHhHHHhHo.`,`ohhhdHHHdHHHdHHHdo.`,`ohhHHHHHHHHHHHHdddo`,`ohHHHhHHHhHHHdddddo`,`oddddddddHdHddddddo`,`.oodssdSSHdddddddo.`,`.ksssssSSddddddddo.`,`kseEsssSSddddddddo.`,`kseesssSsddddddddo.`,`.ksmsssSSdddddddo..`,`..kkssSSoddddddo...`,`......kLLkcck......`,`.....kLLlJJJk......`,`.....kLlJJJJk......`,`.....ksSkJJjk......`,`.....kSkJJJjk......`,`......kPPPPPk......`,`.......kPPpk.......`,`......kBBBwk.......`,`.......kkkk........`],[`.....o.ooooo.o.....`,`....ohohhhhhoho....`,`...ohhdhhhdHHHdo...`,`..oohhhhhHHHHHHoo..`,`.ohhhhhhHHHhHHHhHo.`,`ohhhdHHHdHHHdHHHdo.`,`ohhHHHHHHHHHHHHdddo`,`ohHHHhHHHhHHHdddddo`,`oddddddddHdHddddddo`,`.oodssdSSHdddddddo.`,`.ksssssSSddddddddo.`,`kseEsssSSddddddddo.`,`kseesssSsddddddddo.`,`.ksmsssSSdddddddo..`,`..kkssSSoddddddo...`,`......kLLkcck......`,`.....kLLlJJJk......`,`.....kLlJJJJk......`,`.....ksSkJJjk......`,`.....kSkJJJjk......`,`......kPPPPPk......`,`.....kPpk.kPpk.....`,`....kBBwk.kBBwk....`,`.....kkk...kkk.....`],[`.....o.ooooo.o.....`,`....ohohhhhhoho....`,`...ohhdhhhdHHHdo...`,`..oohhhhhHHHHHHoo..`,`.ohhhhhhHHHhHHHhHo.`,`ohhhdHHHdHHHdHHHdo.`,`ohhHHHHHHHHHHHHdddo`,`ohHHHhHHHhHHHdddddo`,`oddddddddHdHddddddo`,`.oodssdSSHdddddddo.`,`.ksssssSSddddddddo.`,`kseEsssSSddddddddo.`,`kseesssSsddddddddo.`,`.ksmsssSSdddddddo..`,`..kkssSSoddddddo...`,`......kLLkcck......`,`.....kLLlJJJk......`,`.....kLlJJJJk......`,`.....ksSkJJjk......`,`.....kSkJJJjk......`,`......kPPPPPk......`,`......kPPpk........`,`......kBBBwk.......`,`.......kkkk........`]]}],Pt=[null,{down:[`........qq........`,`.....qqqRXqqq.....`,`...qqRRRWWWRRqq...`,`..qRRRRRRRRRRRRq..`,`.qRRRRRRRRRRRRRRq.`,`.qrrrrrrrrrrrrrrq.`,`qhhHHHHHHHHHHHdddq`,`oHHddddddddddddddo`,`.oHHSdsdHHHHHHHdo.`,`.oHHSssssssdddddo.`,`..oHSseEsssEesSdo.`,`..oHSseessseesSo..`,`...okSsssSsssSk...`,`.....kSssmssSk....`,`.....kLkccckLk....`,`...kkLLlJJJlLLkk..`,`..kLLlJJJJJJJlLLk.`,`.kssklJJJjJJJlkssk`,`.kSskJJjJJJjJJksSk`,`..kkPPPPPPPPPPPkk.`,`....kPPpk.kpPPk...`,`....kBBwk.kwBBk...`,`.....kkk...kkk....`],walk:[[`........qqq.......`,`.....qqqRRXqqq....`,`....qRRRRRRRRRq...`,`...qRRRRRRRRRRRq..`,`..qRRRRRRRRRRRRRq.`,`.qrrrrrrrrrrrrrrrq`,`.qhhHHHHHHHHHHHddq`,`.odddddddHHHHddddo`,`..odssdSSHHddddddo`,`.ksssssSSddddddddo`,`kseEsssSSSsdddddo.`,`kseesssSsSDddddo..`,`.ksmsssSSSddooo...`,`..kkssSSkkoo......`,`......kLLkcck.....`,`.....kLLlJJJk.....`,`.....kLlJJJJk.....`,`.....ksSkJJjk.....`,`.....kSkJJJjk.....`,`......kPPPPPk.....`,`.......kPPpk......`,`......kBBBwk......`,`.......kkkk.......`],[`........qqq.......`,`.....qqqRRXqqq....`,`....qRRRRRRRRRq...`,`...qRRRRRRRRRRRq..`,`..qRRRRRRRRRRRRRq.`,`.qrrrrrrrrrrrrrrrq`,`.qhhHHHHHHHHHHHddq`,`.odddddddHHHHddddo`,`..odssdSSHHddddddo`,`.ksssssSSddddddddo`,`kseEsssSSSsdddddo.`,`kseesssSsSDddddo..`,`.ksmsssSSSddooo...`,`..kkssSSkkoo......`,`......kLLkcck.....`,`.....kLLlJJJk.....`,`.....kLlJJJJk.....`,`.....ksSkJJjk.....`,`.....kSkJJJjk.....`,`......kPPPPPk.....`,`.....kPpk.kPpk....`,`....kBBwk.kBBwk...`,`.....kkk...kkk....`],[`........qqq.......`,`.....qqqRRXqqq....`,`....qRRRRRRRRRq...`,`...qRRRRRRRRRRRq..`,`..qRRRRRRRRRRRRRq.`,`.qrrrrrrrrrrrrrrrq`,`.qhhHHHHHHHHHHHddq`,`.odddddddHHHHddddo`,`..odssdSSHHddddddo`,`.ksssssSSddddddddo`,`kseEsssSSSsdddddo.`,`kseesssSsSDddddo..`,`.ksmsssSSSddooo...`,`..kkssSSkkoo......`,`......kLLkcck.....`,`.....kLLlJJJk.....`,`.....kLlJJJJk.....`,`.....ksSkJJjk.....`,`.....kSkJJJjk.....`,`......kPPPPPk.....`,`......kPPpk.......`,`......kBBBwk......`,`.......kkkk.......`]]},{down:[`.......qqqq.......`,`....qqqRRRRqqq....`,`...qRRRRRRRRRRq...`,`..qRRRRRRRRRRRRq..`,`.qXXXXXXXXXXXXXXq.`,`.qhhhHHHHHHHHHHHq.`,`ohhHHHHHHHHHHHdddo`,`oHHddddddddddddddo`,`oHHHSdsdHHHHHHHddo`,`.oHHSssssssdddddo.`,`..oHSseEsssEesSdo.`,`..oHSseessseesSo..`,`...okSsssSsssSk...`,`.....kSssmssSk....`,`.....kLkccckLk....`,`...kkLLlJJJlLLkk..`,`..kLLlJJJJJJJlLLk.`,`.kssklJJJjJJJlkssk`,`.kSskJJjJJJjJJksSk`,`..kkPPPPPPPPPPPkk.`,`....kPPpk.kpPPk...`,`....kBBwk.kwBBk...`,`.....kkk...kkk....`],walk:[[`.......qqqq.......`,`....qqqRRRRqqqq...`,`...qRRRRRRRRRRRq..`,`..qRRRRRRRRRRRRRq.`,`.qXXXXXXXXXXXXXXq.`,`.qhhhhHHHHHHHHHHHq`,`.ohhHHHHHHHHHHHddo`,`.odddddddHHHHddddo`,`..odssdSSHHddddddo`,`.ksssssSSddddddddo`,`kseEsssSSSsdddddo.`,`kseesssSsSDdddddo.`,`.ksmsssSSSddoooo..`,`..kkssSSkkoo......`,`......kLLkcck.....`,`.....kLLlJJJk.....`,`.....kLlJJJJk.....`,`.....ksSkJJjk.....`,`.....kSkJJJjk.....`,`......kPPPPPk.....`,`.......kPPpk......`,`......kBBBwk......`,`.......kkkk.......`],[`.......qqqq.......`,`....qqqRRRRqqqq...`,`...qRRRRRRRRRRRq..`,`..qRRRRRRRRRRRRRq.`,`.qXXXXXXXXXXXXXXq.`,`.qhhhhHHHHHHHHHHHq`,`.ohhHHHHHHHHHHHddo`,`.odddddddHHHHddddo`,`..odssdSSHHddddddo`,`.ksssssSSddddddddo`,`kseEsssSSSsdddddo.`,`kseesssSsSDdddddo.`,`.ksmsssSSSddoooo..`,`..kkssSSkkoo......`,`......kLLkcck.....`,`.....kLLlJJJk.....`,`.....kLlJJJJk.....`,`.....ksSkJJjk.....`,`.....kSkJJJjk.....`,`......kPPPPPk.....`,`.....kPpk.kPpk....`,`....kBBwk.kBBwk...`,`.....kkk...kkk....`],[`.......qqqq.......`,`....qqqRRRRqqqq...`,`...qRRRRRRRRRRRq..`,`..qRRRRRRRRRRRRRq.`,`.qXXXXXXXXXXXXXXq.`,`.qhhhhHHHHHHHHHHHq`,`.ohhHHHHHHHHHHHddo`,`.odddddddHHHHddddo`,`..odssdSSHHddddddo`,`.ksssssSSddddddddo`,`kseEsssSSSsdddddo.`,`kseesssSsSDdddddo.`,`.ksmsssSSSddoooo..`,`..kkssSSkkoo......`,`......kLLkcck.....`,`.....kLLlJJJk.....`,`.....kLlJJJJk.....`,`.....ksSkJJjk.....`,`.....kSkJJJjk.....`,`......kPPPPPk.....`,`......kPPpk.......`,`......kBBBwk......`,`.......kkkk.......`]]},{down:[`..qRRRRRRRRRRRRq..`,`..qRRRRRRRRRRRRq..`,`.qRRRRRRRRRRRRRRq.`,`.qRRRRRRRRRRRRRRq.`,`.qRRRRRRRRRRRRRRq.`,`.qRRRRRRRRRRRRrrq.`,`.qXXXXXXXXXXXXXXq.`,`.qHHHHHHHHHdddddq.`,`.oHdddddddddddddo.`,`.oHHSdsdHHHHHHHdo.`,`.oHHSssssssdddddo.`,`..oHSseEsssEesSdo.`,`..oHSseessseesSo..`,`..odoSsssSsssSk...`,`...o.kSssmssSk....`,`.....kLkccckLk....`,`...kkLLlJJJlLLkk..`,`..kLLlJJJJJJJlLLk.`,`.kssklJJJjJJJlkssk`,`.kSskJJjJJJjJJksSk`,`..kkPPPPPPPPPPPkk.`,`....kPPpk.kpPPk...`,`....kBBwk.kwBBk...`,`.....kkk...kkk....`],walk:[[`...qRRRRRRRRRRRq..`,`..qRRRRRRRRRRRRRq.`,`..qRRRRRRRRRRRRRq.`,`.qRRRRRRRRRRRRRRq.`,`.qRRRRRRRRRRRRRRq.`,`.qRRRRRRRRRRRRRrq.`,`.qXXXXXXXXXXXXXXq.`,`.qHHHHHHHHHHddddq.`,`.odddddddHddddddo.`,`..odssdSSdddddddo.`,`.ksssssSSdddddddo.`,`kseEsssSSSsdddddo.`,`kseesssSsSDdddddo.`,`.ksmsssSSSddoooo..`,`..kkssSSkkoo......`,`......kLLkcck.....`,`.....kLLlJJJk.....`,`.....kLlJJJJk.....`,`.....ksSkJJjk.....`,`.....kSkJJJjk.....`,`......kPPPPPk.....`,`.......kPPpk......`,`......kBBBwk......`,`.......kkkk.......`],[`...qRRRRRRRRRRRq..`,`..qRRRRRRRRRRRRRq.`,`..qRRRRRRRRRRRRRq.`,`.qRRRRRRRRRRRRRRq.`,`.qRRRRRRRRRRRRRRq.`,`.qRRRRRRRRRRRRRrq.`,`.qXXXXXXXXXXXXXXq.`,`.qHHHHHHHHHHddddq.`,`.odddddddHddddddo.`,`..odssdSSdddddddo.`,`.ksssssSSdddddddo.`,`kseEsssSSSsdddddo.`,`kseesssSsSDdddddo.`,`.ksmsssSSSddoooo..`,`..kkssSSkkoo......`,`......kLLkcck.....`,`.....kLLlJJJk.....`,`.....kLlJJJJk.....`,`.....ksSkJJjk.....`,`.....kSkJJJjk.....`,`......kPPPPPk.....`,`.....kPpk.kPpk....`,`....kBBwk.kBBwk...`,`.....kkk...kkk....`],[`...qRRRRRRRRRRRq..`,`..qRRRRRRRRRRRRRq.`,`..qRRRRRRRRRRRRRq.`,`.qRRRRRRRRRRRRRRq.`,`.qRRRRRRRRRRRRRRq.`,`.qRRRRRRRRRRRRRrq.`,`.qXXXXXXXXXXXXXXq.`,`.qHHHHHHHHHHddddq.`,`.odddddddHddddddo.`,`..odssdSSdddddddo.`,`.ksssssSSdddddddo.`,`kseEsssSSSsdddddo.`,`kseesssSsSDdddddo.`,`.ksmsssSSSddoooo..`,`..kkssSSkkoo......`,`......kLLkcck.....`,`.....kLLlJJJk.....`,`.....kLlJJJJk.....`,`.....ksSkJJjk.....`,`.....kSkJJJjk.....`,`......kPPPPPk.....`,`......kPPpk.......`,`......kBBBwk......`,`.......kkkk.......`]]},{down:[`.....qqqqqqqq......`,`...qqRRRRRRRRqq....`,`..qRRRRRRRRRRRRq...`,`.qRRRRRRRRRRRRRRq..`,`qXXXXXXXXXXXXXXXXq.`,`qhhhHHHHHHHHHHHHdq.`,`hHHHHHHHHHHHHHddddo`,`HHHdddddddddddddddo`,`oHHHSdsdHHHHHHHddo.`,`oHHHSssssssddddddo.`,`.ooHSseEsssEesSdo..`,`..oHSseessseesSo...`,`...okSsssSsssSk....`,`.....kSssmssSk.....`,`.....kLkccckLk.....`,`...kkLLlJJJlLLkk...`,`..kLLlJJJJJJJlLLk..`,`.kssklJJJjJJJlkssk.`,`.kSskJJjJJJjJJksSk.`,`..kkPPPPPPPPPPPkk..`,`....kPPpk.kpPPk....`,`....kBBwk.kwBBk....`,`.....kkk...kkk.....`],walk:[[`.....qqqqqqqqq.....`,`...qqRRRRRRRRRqq...`,`..qRRRRRRRRRRRRRq..`,`.qRRRRRRRRRRRRRRRq.`,`qXXXXXXXXXXXXXXXXq.`,`qhhhHHHHHHHHHHHHddq`,`ohHHHHHHHHHHHHddddo`,`oddddddddHHHddddddo`,`.oodssdSSHddddddddo`,`.ksssssSSddddddddo.`,`kseEsssSSSsddddddo.`,`kseesssSsSDdddddo..`,`.ksmsssSSSddoooo...`,`..kkssSSkkoo.......`,`......kLLkcck......`,`.....kLLlJJJk......`,`.....kLlJJJJk......`,`.....ksSkJJjk......`,`.....kSkJJJjk......`,`......kPPPPPk......`,`.......kPPpk.......`,`......kBBBwk.......`,`.......kkkk........`],[`.....qqqqqqqqq.....`,`...qqRRRRRRRRRqq...`,`..qRRRRRRRRRRRRRq..`,`.qRRRRRRRRRRRRRRRq.`,`qXXXXXXXXXXXXXXXXq.`,`qhhhHHHHHHHHHHHHddq`,`ohHHHHHHHHHHHHddddo`,`oddddddddHHHddddddo`,`.oodssdSSHddddddddo`,`.ksssssSSddddddddo.`,`kseEsssSSSsddddddo.`,`kseesssSsSDdddddo..`,`.ksmsssSSSddoooo...`,`..kkssSSkkoo.......`,`......kLLkcck......`,`.....kLLlJJJk......`,`.....kLlJJJJk......`,`.....ksSkJJjk......`,`.....kSkJJJjk......`,`......kPPPPPk......`,`.....kPpk.kPpk.....`,`....kBBwk.kBBwk....`,`.....kkk...kkk.....`],[`.....qqqqqqqqq.....`,`...qqRRRRRRRRRqq...`,`..qRRRRRRRRRRRRRq..`,`.qRRRRRRRRRRRRRRRq.`,`qXXXXXXXXXXXXXXXXq.`,`qhhhHHHHHHHHHHHHddq`,`ohHHHHHHHHHHHHddddo`,`oddddddddHHHddddddo`,`.oodssdSSHddddddddo`,`.ksssssSSddddddddo.`,`kseEsssSSSsddddddo.`,`kseesssSsSDdddddo..`,`.ksmsssSSSddoooo...`,`..kkssSSkkoo.......`,`......kLLkcck......`,`.....kLLlJJJk......`,`.....kLlJJJJk......`,`.....ksSkJJjk......`,`.....kSkJJJjk......`,`......kPPPPPk......`,`......kPPpk........`,`......kBBBwk.......`,`.......kkkk........`]]}],Ft={base:{k:`#373337`,E:`#f0f0f8`,e:`#36363e`,m:`#a0605a`,q:`#f2a0a0`,s:`#fbe0c8`,S:`#d5beaa`,X:`#9aa0a6`,H:`#363438`,o:`#313132`,J:`#f4f4f0`,L:`#f4f4f0`,c:`#f8f8f8`,P:`#3a4058`,B:`#f0f0f0`,w:`#b0b0bc`,h:`#38353a`,d:`#353336`,W:`#f8f8f8`,D:`#b09d8c`,n:`#fffbe0`,j:`#bebebb`,l:`#bebebb`,p:`#35394b`},hairColor:[{H:`#363438`,o:`#313132`,v:`#333235`,h:`#38353a`,d:`#353336`},{H:`#3d3539`,o:`#343132`,v:`#373335`,h:`#40363b`,d:`#393336`},{H:`#503428`,o:`#3a302c`,v:`#42322c`,h:`#5f3b2c`,d:`#48332a`},{H:`#5c3a26`,o:`#3e312a`,v:`#463328`,h:`#764a31`,d:`#4d3425`},{H:`#704830`,o:`#443329`,v:`#4a3426`,h:`#8f5c3d`,d:`#533524`},{H:`#a04828`,o:`#532e21`,v:`#5e2e1c`,h:`#cd5c33`,d:`#76351e`},{H:`#d88838`,o:`#5b3918`,v:`#774b1f`,h:`#ffae48`,d:`#a06529`},{H:`#f8d070`,o:`#886840`,v:`#88723e`,h:`#ffff8f`,d:`#b89a53`},{H:`#e8e8f0`,o:`#8888a0`,v:`#808084`,h:`#ffffff`,d:`#acacb2`},{H:`#f08ab8`,o:`#8a3a62`,v:`#844c65`,h:`#ffb1ec`,d:`#b26688`},{H:`#5a78d8`,o:`#2a3872`,v:`#324277`,h:`#739aff`,d:`#4359a0`},{H:`#58a878`,o:`#204b33`,v:`#305c42`,h:`#71d79a`,d:`#417c59`}],skin:[{s:`#fbe0c8`,m:`#a0605a`,S:`#d5beaa`,D:`#b09d8c`,n:`#fffbe0`},{s:`#f8d0b0`,m:`#9a5a48`,S:`#d3b196`,D:`#ae927b`,n:`#ffe9c5`},{s:`#f0c8a0`,m:`#9a5a48`,S:`#ccaa88`,D:`#a88c70`,n:`#ffe0b3`},{s:`#d8a07c`,m:`#a0505a`,S:`#b88869`,D:`#977057`,n:`#f2b38b`},{s:`#c48a62`,m:`#7a4232`,S:`#a77553`,D:`#896145`,n:`#dc9b6e`},{s:`#b87a52`,m:`#6e3e30`,S:`#9c6846`,D:`#815539`,n:`#ce895c`},{s:`#94603e`,m:`#5e3226`,S:`#7e5235`,D:`#68432b`,n:`#a66c45`},{s:`#6e4430`,m:`#552f23`,S:`#5e3a29`,D:`#513426`,n:`#7b4c36`}],shirt:[{J:`#f4f4f0`,j:`#bebebb`},{J:`#70b8e0`,j:`#5790af`},{J:`#f08048`,j:`#bb6438`},{J:`#f890a8`,j:`#c17083`},{J:`#f8d040`,j:`#c1a232`},{J:`#9cc0e0`,j:`#7a96af`},{J:`#34446a`,j:`#2f3b59`},{J:`#9a2a48`,j:`#782138`},{J:`#58a878`,j:`#45835e`},{J:`#7d4fc9`,j:`#623e9d`},{J:`#3a3f58`,j:`#35394d`},{J:`#363a47`,j:`#353842`},{J:`#2a3870`,j:`#2c3763`},{J:`#e0823c`,j:`#af652f`}],sleeves:[{L:`#f4f4f0`,l:`#bebebb`},{L:`#70b8e0`,l:`#5790af`},{L:`#f08048`,l:`#bb6438`},{L:`#f890a8`,l:`#c17083`},{L:`#f8d040`,l:`#c1a232`},{L:`#9cc0e0`,l:`#7a96af`},{L:`#34446a`,l:`#2f3b59`},{L:`#9a2a48`,l:`#782138`},{L:`#58a878`,l:`#45835e`},{L:`#7d4fc9`,l:`#623e9d`},{L:`#3a3f58`,l:`#35394d`},{L:`#363a47`,l:`#353842`},{L:`#2a3870`,l:`#2c3763`},{L:`#e0823c`,l:`#af652f`}],pants:[{P:`#3a4058`,p:`#35394b`},{P:`#4060a8`,p:`#30487e`},{P:`#506888`,p:`#3c4e66`},{P:`#605848`,p:`#484236`},{P:`#b8a888`,p:`#8a7e66`},{P:`#4a6eb0`,p:`#385384`},{P:`#383840`,p:`#36363c`},{P:`#6a4a32`,p:`#503826`},{P:`#35373f`,p:`#34353b`},{P:`#f0ece2`,p:`#b4b1aa`}],shoes:[{B:`#f0f0f0`,w:`#b0b0bc`},{B:`#484848`,w:`#f0f0f0`},{B:`#c06838`,w:`#f8f8f8`},{B:`#403838`,w:`#706868`},{B:`#c03850`,w:`#f8f8f8`},{B:`#3d3537`,w:`#5a4a48`}],hat:[[],[{R:`#3f7bd6`,r:`#2d599a`,q:`#243c61`,X:`#9aa0a6`},{R:`#2fa37a`,r:`#227558`,q:`#1b4939`,X:`#9aa0a6`},{R:`#d6604a`,r:`#9a4535`,q:`#5d2d25`,X:`#9aa0a6`},{R:`#7d4fc9`,r:`#5a3991`,q:`#402e5e`,X:`#9aa0a6`},{R:`#e0b23c`,r:`#a1802b`,q:`#5a4718`,X:`#9aa0a6`},{R:`#3a3f58`,r:`#35384a`,q:`#33353f`,X:`#9aa0a6`}],[{R:`#3f7bd6`,r:`#2d599a`,q:`#243c61`,X:`#e8c040`},{R:`#2fa37a`,r:`#227558`,q:`#1b4939`,X:`#e8c040`},{R:`#d6604a`,r:`#9a4535`,q:`#5d2d25`,X:`#e8c040`},{R:`#7d4fc9`,r:`#5a3991`,q:`#402e5e`,X:`#e8c040`},{R:`#e0b23c`,r:`#a1802b`,q:`#5a4718`,X:`#e8c040`},{R:`#3a3f58`,r:`#35384a`,q:`#33353f`,X:`#e8c040`}],[{R:`#38373e`,r:`#35353a`,q:`#333336`,X:`#f25c3b`},{R:`#38373e`,r:`#35353a`,q:`#333336`,X:`#f25c3b`},{R:`#38373e`,r:`#35353a`,q:`#333336`,X:`#f25c3b`},{R:`#38373e`,r:`#35353a`,q:`#333336`,X:`#f25c3b`},{R:`#38373e`,r:`#35353a`,q:`#333336`,X:`#f25c3b`},{R:`#38373e`,r:`#35353a`,q:`#333336`,X:`#f25c3b`}],[{R:`#2b3868`,r:`#2c3658`,q:`#2d3346`,X:`#e8c040`},{R:`#2b3868`,r:`#2c3658`,q:`#2d3346`,X:`#e8c040`},{R:`#2b3868`,r:`#2c3658`,q:`#2d3346`,X:`#e8c040`},{R:`#2b3868`,r:`#2c3658`,q:`#2d3346`,X:`#e8c040`},{R:`#2b3868`,r:`#2c3658`,q:`#2d3346`,X:`#e8c040`},{R:`#2b3868`,r:`#2c3658`,q:`#2d3346`,X:`#e8c040`}]]},It={hair:21,hairColor:12,skin:8,eyes:5,glasses:4,face:6,hat:5,shirt:14,sleeves:14,outfit:6,pants:10,shoes:6},Lt={hair:[0,1,2,3,5,6,7,8,9,10,11,13,14,16,20],hairColor:[0,1,2,3,4,5,6,7],skin:[0,1,2,3,4,5,6,7],eyes:[0,1,2,3],glasses:[0,1,2],face:[0,1,2,3,4,5],hat:[0],shirt:[0,1,2,3,4,5,6,7,8,10,11,12],sleeves:[0,1,2,3,4,5,6,7,8,10,11,12],outfit:[0,1,2],pants:[0,1,2,3,4,5,6,7,8,9],shoes:[0,1,2,3,4,5]},Rt=new Set([`iTerm.app`,`WezTerm`,`vscode`,`ghostty`,`Hyper`,`Tabby`,`rio`]),zt=new Set([`iTerm.app`,`WezTerm`,`vscode`,`ghostty`,`Hyper`,`Tabby`,`rio`]);function Bt({env:e=process.env,argv:t=process.argv,isTTY:n=!!process.stdout.isTTY}={}){if(t.includes(`--no-color`)||t.includes(`--no-colour`)||e.NO_COLOR!==void 0&&e.NO_COLOR!==``)return 0;let r=e.FORCE_COLOR,i;if(r!==void 0){if(r===`0`||r===`false`)return 0;i=r===`2`?2:r===`3`?3:1}if(!n||e.TERM===`dumb`)return i??0;let a=1,o=(e.COLORTERM??``).toLowerCase();return o===`truecolor`||o===`24bit`||Rt.has(e.TERM_PROGRAM??``)||/-(truecolor|direct)$|^xterm-(kitty|ghostty)$/.test(e.TERM??``)?a=3:/256(col)?/.test(e.TERM??``)&&(a=2),i!==void 0&&i>a?i:a}function Vt(e,t){return e.FORCE_HYPERLINK===void 0?!t||e.TMUX||/^screen/.test(e.TERM??``)?!1:zt.has(e.TERM_PROGRAM??``)||e.WT_SESSION||e.KITTY_WINDOW_ID||/^xterm-(kitty|ghostty)$|^alacritty/.test(e.TERM??``)?!0:Number(e.VTE_VERSION??0)>=5e3:e.FORCE_HYPERLINK!==`0`&&e.FORCE_HYPERLINK!==``&&t}function Ht(e={}){let t=e.env??process.env,n=e.isTTY??!!process.stdout.isTTY,r=Bt({...e,env:t,isTTY:n}),i=n&&r>0&&t.TERM!==`dumb`,a=e.columns??(n?process.stdout.columns:void 0)??(Number(t.COLUMNS)||void 0),o=n&&a?Math.max(40,a):void 0,s=o??Math.max(40,Number(t.COLUMNS)||80);return{depth:r,tty:n,fancy:i,links:Vt(t,i),columns:o,layout:s,live:n&&e.columns===void 0}}let R=Ht();function Ut(e){return R=`depth`in e||`fancy`in e?{...R,...e}:Ht(e),R}const Wt=()=>R.live&&process.stdout.columns?Math.max(40,process.stdout.columns):R.columns,Gt=()=>Wt()??R.layout,Kt=()=>Wt()??1/0,qt=e=>{let t=parseInt(e.replace(`#`,``),16);return[t>>16&255,t>>8&255,t&255]};function Jt([e,t,n]){let r=e=>e<48?0:e<115?1:Math.floor((e-35)/40),i=[0,95,135,175,215,255],[a,o,s]=[r(e),r(t),r(n)],c=16+36*a+6*o+s,l=(i[a]-e)**2+(i[o]-t)**2+(i[s]-n)**2,u=(e+t+n)/3,d=u>238?23:Math.max(0,Math.round((u-8)/10)),f=8+d*10;return(f-e)**2+(f-t)**2+(f-n)**2<l?232+d:c}const Yt=(e,t,n)=>n>=3?`38;2;${qt(e).join(`;`)}`:n===2?`38;5;${Jt(qt(e))}`:String(t),Xt=(e,t)=>t>=3?`48;2;${qt(e).join(`;`)}`:`48;5;${Jt(qt(e))}`;function Zt(e,t,n){if(R.depth===0||n===``)return n;let r=`[${e}m`,i=`[${t}m`;return r+n.split(i).join(i+r)+i}const Qt=(e,t=39)=>n=>Zt(Yt(e,t,R.depth),`39`,n),z=e=>Zt(`1`,`22`,e),B=e=>Zt(`2`,`22`,e),$t=e=>Zt(`4`,`24`,e),V={ok:Qt(`#4f9a3a`,32),warn:Qt(`#c98a12`,33),err:Qt(`#e0483a`,31),accent:Qt(I.coral,91),tool:Qt(`#5f7fe8`,94),money:Qt(`#c98a12`,33),sky:Qt(`#3d8fd0`,36),dim:B,bold:z},en=[[`#d4733f`,33],[`#9b5cd6`,95],[`#1f9e8f`,36],[`#c94f7c`,35],[`#7f9a1f`,32],[`#b07a2a`,93]];function tn(e){let t=0;for(let n of e)t=t*31+n.codePointAt(0)>>>0;let[n,r]=en[t%en.length];return e=>z(Qt(n,r)(e))}const H={ok:`✓`,fail:`✗`,skip:`·`,dot:`●`,idle:`○`,arrow:`›`,warn:`!`},nn=/\x1b\[[0-?]*[ -/]*[@-~]|\x1b\][^\x07\x1b]*(?:\x07|\x1b\\)/g,rn=e=>e.replace(nn,``),an=e=>e.replace(/[\t\n\r]+/g,` `).replace(/[\x00-\x1f\x7f-\x9f]/g,``),on=e=>e.replace(/\x1b\[[0-9;]*m|[\x00-\x1f\x7f-\x9f]/g,e=>e.length>1&&R.depth>0?e:e===`
|
|
7
|
+
`||e===` `?` `:``),sn=e=>e.replace(/ /g,`\xA0`),cn=e=>e.replace(/\u00a0/g,` `),ln=e=>e>=768&&e<=879||e>=8203&&e<=8207||e>=8400&&e<=8447||e>=65024&&e<=65039||e===8205,un=e=>e>=4352&&e<=4447||e>=11904&&e<=12350||e>=12353&&e<=13311||e>=13312&&e<=19903||e>=19968&&e<=40959||e>=40960&&e<=42191||e>=44032&&e<=55203||e>=63744&&e<=64255||e>=65072&&e<=65103||e>=65280&&e<=65376||e>=65504&&e<=65510||e>=127744&&e<=128591||e>=129280&&e<=129535||e>=131072&&e<=262141,dn=e=>{let t=e.codePointAt(0);return t<32||t>=127&&t<160||ln(t)?0:un(t)?2:1};function U(e){let t=0;for(let n of rn(e))t+=dn(n);return t}function fn(e){let t=[],n=0;for(let r of e.matchAll(nn)){for(let i of e.slice(n,r.index))t.push({esc:!1,text:i});t.push({esc:!0,text:r[0]}),n=r.index+r[0].length}for(let r of e.slice(n))t.push({esc:!1,text:r});return t}function W(e,t){if(U(e)<=t)return e;if(t<=0)return``;let n=``,r=0,i=!1;for(let a of fn(e)){if(a.esc){n+=a.text,i=!0;continue}let e=dn(a.text);if(r+e>t-1)break;n+=a.text,r+=e}return n+`…`+(i?`\x1B[0m`:``)}const pn=(e,t)=>e+` `.repeat(Math.max(0,t-U(e))),mn=(e,t)=>` `.repeat(Math.max(0,t-U(e)))+e;function G(e,t,n=0){if(!Number.isFinite(t)||U(e)<=t)return[cn(e)];let r=` `.repeat(n),i=[],a=``,o=0,s=()=>i.length?t-n:t,c=()=>{i.push((i.length?r:``)+a.replace(/ +$/,``)),a=``,o=0};for(let t of e.split(/( +)/)){if(t===``)continue;let e=U(t);/^ +$/.test(t)?(o||!i.length)&&o+e<=s()&&(a+=t,o+=e):(a.trim()&&o+e>s()&&c(),a+=t,o+=e)}return(a||!i.length)&&c(),i.map(cn)}function hn(e,t={}){return gn(e,t).flat()}function gn(e,t={}){let n=` `.repeat(t.indent??0),r=t.gap??2,i=t.max??Kt(),a=Math.max(0,...e.map(e=>e.length)),o=Array.from({length:a},(t,n)=>Math.max(0,...e.filter(e=>n<e.length-1).map(e=>U(e[n])))),s=[];for(let t of e){let e=[];s.push(e);let a=n+t.slice(0,-1).map((e,t)=>pn(e,o[t]+r)).join(``),c=t[t.length-1]??``,l=U(a);if(l+U(c)<=i)e.push((a+c).replace(/ +$/,``));else if(i-l<20){let t=U(n)+4;e.push(...G(a.replace(/ +$/,``),i,U(n)+2));for(let n of G(c,i-t,0))e.push(` `.repeat(t)+n)}else{let t=G(c,i-l,0);e.push(a+t[0]);for(let n of t.slice(1))e.push(` `.repeat(l)+n)}}return s.map(e=>e.map(cn))}const _n=(e,t=0,n)=>hn(e.map(([e,t])=>[B(e),t]),{indent:t,gap:2,max:n});function vn(e,t={}){let n=Math.max(20,t.max??Gt()),r=t.title?` ${t.title} `:``,i=Math.min(n-4,Math.max(U(r)+2,...e.map(U))),a=e=>B(e);return[a(`╭─`)+(r?z(W(r,i)):``)+a(`─`.repeat(Math.max(0,i-U(W(r,i))))+`─╮`),...e.map(e=>{let t=W(e,i);return a(`│ `)+pn(t,i)+a(` │`)}),a(`╰`+`─`.repeat(i+2)+`╯`)]}function yn(e,t,n=2,r=0){let i=Math.max(0,...e.map(U)),a=Math.max(e.length,t.length+r);return Array.from({length:a},(a,o)=>{let s=t[o-r];return s===void 0?e[o]??``:pn(e[o]??``,i+n)+s}).map(e=>e.replace(/ +$/,``))}function bn(e,t=e){let n=t===e?e:`${t} (${e})`;return R.links?`\x1b]8;;${e}\x1b\\${$t(V.sky(t))}\x1b]8;;\x1b\\${t===e?``:B(` (${e})`)}`:R.depth?$t(V.sky(n)):n}const K=e=>V.accent(e),xn=e=>`${V.ok(H.ok)} ${e}`,Sn=e=>`${V.warn(H.warn)} ${V.warn(e)}`;function Cn(e,t=``){let n=[...e.matchAll(/[.;:] /g)].map(e=>e.index),r=t=>e.slice(t+2),i=n.find(e=>/^(Try|try|run|Run|press|Press|Copy)\b/.test(r(e)))??n.filter(e=>/\bbitfolk\b/.test(r(e))).pop(),a=i===void 0?e:e.slice(0,i+1),o=i===void 0?``:r(i);return`${V.err(H.fail)} ${V.err(t+a)}${o?` `+wn(o):``}`}function wn(e){return e.split(/((?:npx )?bitfolk(?: (?:--?)?[a-z][\w-]*| <[^>]+>)+)/).map((e,t)=>e===``?``:t%2?K(e):B(e)).join(``)}const Tn=(e,t=2)=>G(e,Kt(),t).join(`
|
|
8
|
+
`),En=(e,t=process.stderr,n=process.env)=>!t.isTTY&&n.FORCE_COLOR===void 0?rn(e):e,Dn=[`·`,`✢`,`✳`,`✶`,`✻`,`✽`,`✻`,`✶`,`✳`,`✢`],On=[`Listening for your team`,`Watering the flowers`,`Sweeping the square`,`Checking the mailbox`,`Tidying the workshop`,`Lighting the lamps`],kn=(e=process.env)=>R.fancy&&!e.BITFOLK_NO_ANIMATION&&!(e.CI&&e.CI!==`0`&&e.CI!==`false`);function An(e){let t=Math.max(0,Math.floor(e/1e3));return t<60?`${t}s`:t<3600?`${Math.floor(t/60)}m ${t%60}s`:`${Math.floor(t/3600)}h ${String(Math.floor(t%3600/60)).padStart(2,`0`)}m`}const jn=(e,t,n)=>{let[r,i]=[qt(e),qt(t)];return`#`+r.map((e,t)=>Math.round(e+(i[t]-e)*n).toString(16).padStart(2,`0`)).join(``)},Mn=[I.coral,jn(I.coral,I.gold,.45),jn(I.coral,I.gold,.8),jn(I.gold,`#fff3c4`,.5)];function Nn(e,t,n=R.depth){let r=[...rn(e)];if(n===0)return r.join(``);let i=e=>Math.max(0,3-Math.abs(e-t)),a=``,o=``,s=-1,c=()=>{o&&=(a+=n===1?s>=2?`[1;93m${o}[22;39m`:`[91m${o}[39m`:`[${Yt(Mn[s],39,n)}m${o}[39m`,``)};return r.forEach((e,t)=>{let r=n===1?i(t)>=2?2:0:i(t);r!==s&&c(),s=r,o+=e}),c(),a}const Pn=(e,t)=>e%(t+8)-3;function Fn(e,t=R.depth,n=Dn){let r=n[(e%n.length+n.length)%n.length];return t===0?r:r===`✽`?`[${Yt(I.gold,93,t)}m${r}[39m`:`[${Yt(I.coral,91,t)}m${r}[39m`}function In(e){let t=e.depth??R.depth,n=rn(e.text).replace(/(\.\.\.|…)$/,``),r=[e.elapsedMs>=(e.timeAfterMs??2e3)?An(e.elapsedMs):null,e.hint].filter(Boolean).join(` · `),i=e=>t?`[2m${e}[22m`:e,a=`${Fn(e.frame,t)} ${Nn(n+`…`,Pn(e.frame,[...n].length),t)}${e.detail?` `+i(e.detail):``}${r?` `+i(`(${r})`):``}`;return e.max?W(a,e.max):a}const Ln=`\x1B[?25l`,Rn=`\r\x1B[2K`,zn=[[`SIGINT`,130],[`SIGTERM`,143],[`SIGHUP`,129]];function Bn(e,t={}){let n=t.out??process.stdout,r=t.animate??(kn()&&!!n.isTTY),i=t.now??Date.now,a=t.verbs?.length?[e,...t.verbs.filter(t=>t!==e)]:[e],o=e,s=!1,c=e=>void(e!==void 0&&n.write(e+`
|
|
9
|
+
`)),l=e=>({text:e=>{o=e,s=!0},stop:e,ok:t=>e(xn(t)),fail:t=>e(`${V.err(H.fail)} ${V.err(t)}`)});if(!r)return t.quiet||n.write(`${e.replace(/(\.\.\.|…)$/,``)}…${t.hint?` (${t.hint})`:``}\n`),l(c);let u=i(),d=0,f=()=>Math.max(1,(n.columns||Gt())-1),p=()=>{let e=i()-u,r=s||a.length===1?o:a[Math.floor(e/(t.rotateMs??4e3))%a.length];n.write(Rn+In({text:r,frame:d++,elapsedMs:e,hint:t.hint,max:f()}))};n.write(Ln),p();let m=setInterval(p,100);m.unref();let h=!1,g=()=>void n.write(`\r\x1B[2K\x1B[?25h`),_=e=>{if(!h){h=!0,clearInterval(m);for(let[e,t]of v)process.removeListener(e,t);process.removeListener(`exit`,g),g(),c(e)}},v=[];for(let[e,t]of zn){if(process.listenerCount(e)>0)continue;let n=()=>{_(),process.exit(t)};process.once(e,n),v.push([e,n])}return process.once(`exit`,g),l(_)}async function Vn(e,t,n={}){let r=Bn(e,{quiet:!0,...n});try{return await t()}finally{r.stop()}}const Hn=(e,t)=>e.reduce((e,n)=>e+Math.max(1,Math.ceil(U(n)/Math.max(1,t))),0);function Un(e,t={}){let n=t.out??process.stdout,r=(t.animate??kn())&&!!n.isTTY;if(!r)return{active:r,log:e=>void n.write(e+`
|
|
10
|
+
`),redraw:()=>{},stop:()=>{}};let i=0,a=!1,o=[],s=()=>({columns:n.columns||Gt(),rows:n.rows??(n===process.stdout?process.stdout.rows:void 0)}),c=()=>{let t=s(),n=e(i,t),r=Math.max(1,t.columns-1);return(Array.isArray(n)?n:[n]).map(e=>W(e,r))},l=()=>{let e=Hn(o,n.columns||Gt())-1;return e>0?`\r[${e}A[J`:Rn},u=e=>{let t=l()+e.join(`
|
|
11
|
+
`);return o=e,e.length>1?`[?2026h${t}[?2026l`:t},d=()=>{a||n.write(u(c()))},f=()=>{i++,d()},p=()=>typeof t.intervalMs==`function`?t.intervalMs():t.intervalMs??100,m,h=()=>{m=setTimeout(()=>{f(),a||h()},p()),m.unref()};n.write(Ln),d(),h();let g=()=>d();n.on?.(`resize`,g);let _=()=>{a||(a=!0,clearTimeout(m),n.off?.(`resize`,g),process.removeListener(`exit`,_),n.write(l()+`\x1B[?25h`),o=[])};return process.once(`exit`,_),{active:r,log:e=>{if(a)return void n.write(e+`
|
|
12
|
+
`);let t=c(),r=l();o=t;let i=r+e+`
|
|
13
|
+
`+t.join(`
|
|
14
|
+
`);n.write(t.length>1?`[?2026h${i}[?2026l`:i)},redraw:d,stop:_}}const Wn=(e,t=Ot)=>{let n=Math.max(0,...e.map(e=>e.length));return e.map(e=>Array.from({length:n},(n,r)=>t[e[r]??`.`]??null))};function Gn(e,t=R.depth){if(t<2)return[];let n=Math.max(0,...e.map(e=>e.length)),r=[];for(let i=0;i<e.length;i+=2){let a=``,o=``,s=e=>{e!==o&&(a+=`[0${e?`;`+e:``}m`,o=e)};for(let r=0;r<n;r++){let n=e[i]?.[r]??null,o=e[i+1]?.[r]??null;!n&&!o?(s(``),a+=` `):n&&!o?(s(Yt(n,39,t)),a+=`▀`):!n&&o?(s(Yt(o,39,t)),a+=`▄`):n===o?(s(Yt(n,39,t)),a+=`█`):(s(`${Yt(n,39,t)};${Xt(o,t)}`),a+=`▀`)}r.push((o?a+`\x1B[0m`:a).replace(/ +$/,``))}return r}const Kn=(e,t=Ot,n=R.depth)=>n<2?[]:Gn(Wn(e,t),n);function qn(e,t,n=R.depth){return n<2?t:`[${Yt(e,39,n)}m●[39m`}function Jn(e=R.depth){if(e===0)return[];let t=[`.`.repeat(kt[0].length),...kt];if(e>=2)return Kn(t,{"#":I.coral},e);let n=[];for(let e=0;e<t.length;e+=2){let r=``;for(let n=0;n<t[0].length;n++){let i=t[e][n]===`#`,a=t[e+1]?.[n]===`#`;r+=i&&a?`█`:i?`▀`:a?`▄`:` `}n.push(`[91m${r.replace(/ +$/,``)}[39m`)}return n}var q=class extends Error{ended;constructor(e,t=!1){super(e),this.ended=t}};const Yn=e=>e.toString(`base64url`);function Xn(){let e=Yn(de(32));return{verifier:e,challenge:Yn(ue(`sha256`).update(e).digest())}}async function Zn(e,t,n=!1){let r;try{r=await fetch(e,{method:`POST`,headers:{"content-type":n?`application/x-www-form-urlencoded`:`application/json`,"user-agent":`bitfolk-cli/${j}`},body:n?new URLSearchParams(t).toString():JSON.stringify(t),signal:AbortSignal.timeout(2e4)})}catch(t){throw new q(`can't reach ${new URL(e).origin}: ${t.message}`)}return{status:r.status,json:await r.json().catch(()=>null)}}function Qn(e){let t=e;return t&&typeof t.access_token==`string`&&typeof t.refresh_token==`string`?t:null}const $n=(e,t,n)=>({clientId:e,refreshToken:t.refresh_token,expiresAt:n+(t.expires_in||3600)*1e3});function er(e){let[t,r]=process.platform===`darwin`?[`open`,[e]]:process.platform===`win32`?[`cmd`,[`/c`,`start`,``,e]]:[`xdg-open`,[e]];try{n(t,r,{stdio:`ignore`,detached:!0}).on(`error`,()=>{}).unref()}catch{}}const tr=(e,t)=>{e.writeHead(302,{location:t,"cache-control":`no-store`}),e.end()};function nr(e){return new Promise((t,n)=>{let r,i=new Promise((e,t)=>r={ok:e,fail:t}),a=!1,o=pe((t,n)=>{let i=new URL(t.url??`/`,`http://127.0.0.1`);if(i.pathname!==`/callback`||a){n.writeHead(404).end();return}a=!0;let o=i.searchParams.get(`error`),s=i.searchParams.get(`code`);if(o||!s)tr(n,`${e}/cli/linked?error=${o===`access_denied`?`denied`:`failed`}&cmd=${encodeURIComponent(C)}`),r.fail(new q(o===`access_denied`?`you pressed Deny, so nothing was linked`:`sign-in failed (${o??`no code`})`));else{let e=!1;n.on(`close`,()=>e=!0),r.ok({code:s,state:i.searchParams.get(`state`)??``,reply:t=>{e||(e=!0,tr(n,t))}})}});o.on(`error`,n),o.listen(0,`127.0.0.1`,()=>{let e=o.address();if(!e||typeof e==`string`)return n(Error(`couldn't open a local port for sign-in`));t({server:o,port:e.port,code:i})})})}async function rr(e,t={}){let n=t.say??(e=>console.log(e)),r=t.now??Date.now,{server:i,port:a,code:o}=await nr(e),s=null;try{let i=`http://127.0.0.1:${a}/callback`,c=se().replace(/\.local$/,``).slice(0,60)||`this machine`,l=await Zn(`${e}/oauth/register`,{client_name:`Bitfolk CLI on ${c}`,redirect_uris:[i]}),u=l.json?.client_id;if(l.status!==201||!u)throw new q(`Bitfolk didn't accept this machine (HTTP ${l.status})`);let{verifier:d,challenge:f}=Xn(),p=Yn(de(16)),m=new URL(`${e}/oauth/authorize`);for(let[e,n]of Object.entries({response_type:`code`,client_id:u,redirect_uri:i,state:p,code_challenge:f,code_challenge_method:`S256`,scope:`machine`,bitfolk_machine:`1`,runtimes:(t.detected??[]).join(`,`)}))m.searchParams.set(e,n);n(`${G(`${V.accent(H.dot)} ${t.browser===!1?`Open this link on any device`:`Opening your browser`} to link this machine. ${B(t.browser===!1?`Sign in, name it, press Allow:`:`If it doesn't open, go to:`)}`,Kt(),2).join(`
|
|
15
|
+
`)}\n\n ${bn(m.toString())}\n`),t.browser!==!1&&er(m.toString());let h=null;t.say?n(`Waiting for you to press Allow (Ctrl-C to cancel)...`):h=Bn(`Waiting for you to press ${z(`Allow`)}`,{hint:`Ctrl-C to cancel`});let g,_=await Promise.race([o,new Promise((e,t)=>{g=setTimeout(()=>t(new q(`timed out after 10 minutes; run ${C} login again`)),6e5)})]).finally(()=>{clearTimeout(g),h?.stop()});if(s=_.reply,_.state!==p)throw new q(`the sign-in reply didn't match this login; run ${C} login again`);let v=async()=>{let t=await Zn(`${e}/oauth/token`,{grant_type:`authorization_code`,client_id:u,code:_.code,redirect_uri:i,code_verifier:d},!0),n=Qn(t.json);if(!n)throw new q(`couldn't finish signing in (HTTP ${t.status}); run ${C} login again`);return{tok:n,me:await new mt(e,n.access_token).me()}},{tok:y,me:b}=t.say?await v():await Vn(`Moving in`,v);t.say||n(xn(`You pressed Allow; this machine is signed in.`));let x=new URL(`${e}/cli/linked`);return x.searchParams.set(`machine`,b.machine.name),x.searchParams.set(`tools`,b.machine.runtimes.join(`,`)),x.searchParams.set(`cmd`,C),_.reply(x.toString()),s=null,{accessToken:y.access_token,link:$n(u,y,r()),me:b}}catch(t){throw s?.(`${e}/cli/linked?error=failed&cmd=${encodeURIComponent(C)}`),t}finally{i.close()}}async function ir(e){let t=s(N(),`refresh.lock`);y(N(),{recursive:!0,mode:448});for(let e=0;;e++)try{y(t);break}catch{let n=!1;try{n=Date.now()-ie(t).mtimeMs>6e4}catch{}if(n)re(t,{recursive:!0,force:!0});else if(e>300)throw new q(`another bitfolk process is stuck renewing sign-in; delete ${t}`);else await new Promise(e=>setTimeout(e,100))}try{return await e()}finally{re(t,{recursive:!0,force:!0})}}async function ar(e,t={}){let n=t.now??Date.now;return!e.oauth||!t.force&&e.oauth.expiresAt-n()>6e5?e.token:ir(async()=>{let t=P(),r=t.machine?.id===e.id?t.machine:t.agents.find(t=>t.id===e.id);if(r?.oauth&&r.oauth.refreshToken!==e.oauth.refreshToken&&(e.token=r.token,e.oauth=r.oauth,e.oauth.expiresAt-n()>6e5))return e.token;let i=e.oauth,a=await Zn(`${e.api.replace(/\/+$/,``)}/oauth/token`,{grant_type:`refresh_token`,client_id:i.clientId,refresh_token:i.refreshToken},!0),o=Qn(a.json);if(!o)throw a.status===400||a.status===401?new q(`sign-in ended (unlinked on your team, or unused for 90 days). Run \`${C} login\` again`,!0):new q(`couldn't renew its sign-in (HTTP ${a.status})`);e.token=o.access_token,e.oauth=$n(i.clientId,o,n());let s=P();return s.machine?.id===e.id?s.machine={...s.machine,token:e.token,oauth:e.oauth}:s.agents=s.agents.map(t=>t.id===e.id?{...t,token:e.token,oauth:e.oauth}:t),F(s),e.token})}function or(e){let t=s(N(),`tokens`);y(t,{recursive:!0,mode:448});let n=s(t,e.id);return ae(n,e.token,{mode:384}),n}async function sr(e){if(!e.oauth)return!1;let t=await Zn(`${e.api.replace(/\/+$/,``)}/oauth/revoke`,{token:e.oauth.refreshToken,client_id:e.oauth.clientId},!0).catch(()=>null);return!!t&&t.status<300}const cr=[{id:`claude_code`,label:`Claude Code`,bins:[`claude`],supported:!0},{id:`codex`,label:`Codex`,bins:[`codex`],supported:!0},{id:`opencode`,label:`OpenCode`,bins:[`opencode`],supported:!0},{id:`hermes`,label:`Hermes Agent`,bins:[`hermes`],supported:!0},{id:`gemini`,label:`Gemini CLI`,bins:[`gemini`],supported:!0,acp:{args:[`--acp`]}},{id:`goose`,label:`Goose`,bins:[`goose`],supported:!0,acp:{args:[`acp`]}},{id:`cursor_agent`,label:`Cursor Agent`,bins:[`cursor-agent`,`agent`],onlyIf:{agent:/cursor/i},supported:!0,acp:{args:[`acp`]}},{id:`copilot`,label:`GitHub Copilot CLI`,bins:[`copilot`],supported:!0,acp:{args:[`--acp`]}},{id:`qwen`,label:`Qwen Code`,bins:[`qwen`],supported:!0,acp:{args:[`--acp`]}},{id:`cline`,label:`Cline`,bins:[`cline`],supported:!0,acp:{args:[`--acp`]}},{id:`kimi`,label:`Kimi Code`,bins:[`kimi`],supported:!0,acp:{args:[`acp`]}},{id:`aider`,label:`Aider`,bins:[`aider`],supported:!1,suggest:`aider --yes-always --message "$(cat)"`},{id:`amp`,label:`Amp`,bins:[`amp`],supported:!1,suggest:`amp -x "$(cat)"`},{id:`crush`,label:`Crush`,bins:[`crush`],supported:!1,suggest:`crush run "$(cat)"`},{id:`droid`,label:`Factory Droid`,bins:[`droid`],supported:!1,suggest:`droid exec "$(cat)"`},{id:`dsh`,label:`DeepSeek Harness`,bins:[`dsh`],supported:!1,suggest:`dsh --profile <name> -- "$(cat)"`}];function lr(){let e=oe();return[s(e,`.local`,`bin`),`/opt/homebrew/bin`,`/usr/local/bin`,s(e,`.npm-global`,`bin`),s(e,`.bun`,`bin`),s(e,`.cargo`,`bin`),s(e,`go`,`bin`),s(e,`.opencode`,`bin`),s(e,`.claude`,`local`),s(e,`.volta`,`bin`)]}const ur=e=>{try{return f(e,h.X_OK),!0}catch{return!1}};function dr(e,t=process.env){if(!e)return null;if(e.includes(`/`))return ur(e)?e:null;for(let n of[...(t.PATH??``).split(i).filter(Boolean),...lr()]){let t=s(n,e);if(ur(t))return t}return null}function fr(e,t){for(let n of e.bins){let r=dr(n,t);if(!r)continue;let i=e.onlyIf?.[n];if(i){let e=r;try{e=te(r)}catch{}if(!i.test(e))continue}return r}return null}function pr(e,t){let n=cr.find(t=>t.id===e);return n?.acp?{bin:n.acp.bin??fr(n,t)??n.bins[0],args:[...n.acp.args],agent:n.id}:null}function mr(e){try{return t(e,[`--version`],{timeout:3e3,stdio:[`ignore`,`pipe`,`ignore`]}).toString().trim().split(`
|
|
16
|
+
`)[0]?.slice(0,60)||null}catch{return null}}function hr(e={}){let t=[];for(let n of cr){let r=fr(n,e.env);r&&t.push({...n,path:r,version:e.versions?mr(r):null})}return t}const gr=e=>`custom:${e}`;function _r(e,t,n,r){if(r.command||r.acp)return;let i=(n.customTools??[]).some(e=>e.name===t)||n.runtimes.includes(gr(t));if(!(e===`rm`&&i))return cr.find(e=>e.supported&&e.id===t.replace(/-/g,`_`))}const vr=/^[a-z0-9][a-z0-9-]{0,23}$/;function J(e){return e.startsWith(`custom:`)?e.slice(7):cr.find(t=>t.id===e)?.label??e}function yr(e){return e.platform===`darwin`&&e.linked&&!e.letSleep}function br(e=process.pid){let t=dr(`caffeinate`);if(!t)return null;let r;try{r=n(t,[`-i`,`-w`,String(e)],{detached:!1,stdio:`ignore`})}catch{return null}return r.on(`error`,()=>{}),r.unref(),()=>{r.exitCode===null&&!r.killed&&r.kill()}}const xr=[`hair`,`hairColor`,`skin`,`eyes`,`glasses`,`face`,`hat`,`shirt`,`sleeves`,`outfit`,`pants`,`shoes`];function Sr(e){let t=2166136261;for(let n=0;n<e.length;n++)t^=e.charCodeAt(n),t=Math.imul(t,16777619);return t>>>0}function Cr(e){let t=e;return()=>{t=t+1831565813|0;let e=Math.imul(t^t>>>15,1|t);return e=e+Math.imul(e^e>>>7,61|e)^e,((e^e>>>14)>>>0)/4294967296}}function wr(e){if(!e.startsWith(`look1.`))return null;let t=e.slice(6);if(t.length!==xr.length)return null;let n={};for(let[e,r]of xr.entries()){let i=parseInt(t[e],36);if(!Number.isFinite(i)||i>=It[r])return null;n[r]=i}return n}function Tr(e){let t=wr(e);if(t)return t;let n=Cr(Sr(`person:${e}`)),r=(e,t=0)=>{let r=Lt[e].filter(e=>e>=t),i=r.length?r:[0];return i[Math.floor(n()*i.length)]},i=r(`shirt`),a=n()>=.85;return{hair:r(`hair`),hairColor:r(`hairColor`),skin:r(`skin`),eyes:n()<.6?0:r(`eyes`),glasses:n()<.7?0:r(`glasses`,1),face:r(`face`),hat:a&&Lt.hat.includes(1)?r(`hat`,1):0,shirt:i,sleeves:n()<.65?i:r(`sleeves`),outfit:r(`outfit`),pants:r(`pants`),shoes:r(`shoes`)}}function Er(e,t=Ft){let n=t.sleeves[e.sleeves]??{},r={...t.base,...t.hairColor[e.hairColor],...t.skin[e.skin],...t.shirt[e.shirt],...n,...t.pants[e.pants],...t.shoes[e.shoes],...e.hat?t.hat[e.hat]?.[e.shirt%6]:{}};return e.sleeves!==e.shirt&&n.L&&(r.c=n.L),r}function Dr(e,t={hair:Nt,hat:Pt}){return(e.hat?t.hat[e.hat]:null)??t.hair[e.hair]??t.hair[0]}function Or(e){let t=Tr(e);return{...Dr(t),palette:Er(t)}}const kr={claude_code:`claude_code`,codex:`codex`,hermes:`hermes`,cursor_agent:`cursor`,cursor:`cursor`,gemini:`gemini_cli`,gemini_cli:`gemini_cli`};function Ar(e){let t=kr[e];return t&&At[t]||Or(`tool:${e}`)}const jr=()=>Mt,Mr=e=>{let t=parseInt(e.slice(1),16);return .3*(t>>16)+.59*(t>>8&255)+.11*(t&255)},Nr=`#9aa0a6`;function Pr(e){let t=kr[e],n=t&&jt[t]||Or(`tool:${e}`).palette.J||Nr,r=Mr(n);return r<70||r>200?Nr:n}const Fr=e=>Wn(e),Ir=(e,t=e.down)=>Wn(t,e.palette);function Lr(e,t,n={}){return{grid:Ir(e),walk:e.walk.map(t=>Ir(e,t)),prio:t,gap:2,front:!0,...n}}const Rr=(e,t)=>({grid:Fr(e),prio:t,gap:2,door:Math.floor(e[0].length/2)}),zr=(e,t)=>({grid:Fr(e),prio:t,gap:2}),Br=(e,t,n=1)=>({grid:Fr(e),prio:t,gap:n}),Vr=(e,t,n)=>{let r=Math.max(e.length,t.length),i=e=>[...Array(r-e.length).fill(`.`.repeat(e[0].length)),...e],[a,o]=[i(e),i(t)];return{grid:Fr(a.map((e,t)=>e+`.`+o[t])),prio:n,gap:1}},Hr=(e,t)=>({grid:[Array(U(e)).fill(null)],prio:t,gap:0,label:e}),Ur=e=>Math.max(0,...e.grid.map(e=>e.length)),Wr=e=>e.grid.length;function Gr(e,t){let n=e=>e.reduce((t,n,r)=>t+Ur(n)+(r<e.length-1?n.gap??2:0),0),r=new Set;for(let i of[...e].sort((e,t)=>e.prio-t.prio))r.add(i),n(e.filter(e=>r.has(e)))>t&&r.delete(i);let i=e.filter(e=>r.has(e)),a=[],o=0;for(let e of i)a.push({...e,x:o}),o+=Ur(e)+(e.gap??2);let s=n(i),c=Math.max(0,...i.map(e=>e.label!==void 0&&!e.grid.some(e=>e.some(Boolean))?0:Wr(e)+ +!e.front));return{placed:a,width:s,height:c+c%2}}function Kr(e,t,n){let r=e.length-2,i=e=>Ot[e];for(let a=0;a<t;a++){let t=n.some(e=>Math.abs(a-e)<=2);e[r][a]=t?i(`V`):a*7%11<2?i(`J`):i(`G`),e[r+1][a]=t?a*5%7==0?i(`z`):i(`V`):a*3%7==0?i(`G`):i(`H`)}}function qr(e,t,n,r){let i=r-t.length+1;for(let r=0;r<t.length;r++)for(let a=0;a<t[r].length;a++){let o=t[r][a],s=n+a,c=i+r;o&&c>=0&&c<e.length&&s>=0&&s<e[0].length&&(e[c][s]=o)}}function Jr(e,t){let n=Array.from({length:e.height},()=>Array(e.width).fill(null));Kr(n,e.width,e.placed.filter(e=>e.door!==void 0).map(e=>e.x+e.door));let r=t=>e.height-2+ +!!t.front;for(let i of e.placed)!i.front&&!t?.has(i)&&qr(n,i.grid,i.x,r(i));for(let i of e.placed)i.front&&!t?.has(i)&&qr(n,i.grid,i.x,r(i));for(let[e,i]of t??[])qr(n,e.walk?.[i.frame]??e.grid,e.x+i.dx,r(e));return n}function Yr(e){let t=e.placed.filter(e=>e.label);if(!t.length)return null;let n=``;for(let[r,i]of t.entries()){let a=t[r+1],o=(a?a.x:e.width)-i.x-+!!a,s=W(i.label,Math.max(1,o)),c=Math.max(i.x,Math.min(i.x+Math.floor((Ur(i)-U(s))/2),i.x+o-U(s)));c<U(n)||(n+=` `.repeat(c-U(n))+B(s))}return n}function Xr(e,t=R.depth,n){if(t<2||!e.placed.length)return[];let r=Gn(Jr(e,n),t),i=Yr(e);return i===null?r:[...r,i]}function Zr(e,t=0){let[n,r,...i]=e,a=e=>t+e;return[zr(L.oak,a(2.5)),Rr(L.cottage,a(.5)),Vr(L.tulip,L.sunflower,a(3)),...n?[n]:[],...r?[r]:[],Br(L.sunflower,a(4)),Rr(L.cabin,a(3.5)),...i,zr(L.pine,a(5)),Br(L.bush,a(6)),Br(L.tulip,a(6.5)),zr(L.elm,a(7)),Vr(L.sunflower,L.tulip,a(8))]}function Qr(e){return Gr(Zr([jr(),Ar(`claude_code`),Ar(`codex`),Or(`bitfolk`)].map((e,t)=>Lr(e,t===0?0:t+1.2))),e)}function $r(e,t){let n=e.map((e,t)=>Lr(Ar(e.id),t,{label:e.label,walker:!0})),r=Gr(Zr(n,e.length),t);if(r.placed.filter(e=>e.walker).length===n.length)return r;let i=n.map(e=>({...e,gap:1})),a=Gr(i,t);if(a.placed.length===n.length)return a;for(let e=n.length-1;e>0;e--){let r=Gr([...i.slice(0,e),Hr(`+${n.length-e}`,0)],t);if(r.placed.length===e+1)return r}return Gr(i.slice(0,1),t)}const ei=[L.cottage,L.cabin,L.roundhouse,L.barn];function ti(e){let t=0;for(let n of e)t=t*31+n.charCodeAt(0)>>>0;return t%ei.length}function ni(e,t){let n=ti(e),r=ei[(n+1)%ei.length],i=Lr(Or(e),0,{walker:!0});return Gr([zr(L.oak,4),{...Rr(ei[n],0),gap:1},i,Vr(L.tulip,L.sunflower,5),Lr(jr(),2),Br(L.bush,6),Rr(r,3),zr(L.pine,7),Vr(L.sunflower,L.tulip,8),zr(L.elm,9)],t)}function ri(e){let t=e.depth??R.depth,n=e.max??Gt(),r=Jn(t);if(!r.length||n<40)return[];let i=Math.max(...r.map(U)),a=t=>[V.bold(e.tagline),B(`v${e.version}${e.url?` · ${e.url}`:``}`)].flatMap(e=>G(e,t)),o=n-i-3,s=t>=2&&o>=19?Xr(Qr(o),t):[];if(!s.length)return[...r,``,...a(n)];let c=Math.max(0,...s.map(U)),l=[...r,``,...a(Math.max(i,n-c-3))];return yn(s,l,3,Math.max(0,Math.ceil((s.length-l.length)/2)))}function ii(e,t=process.env,n=process.stdout){return!R.fancy||R.depth<2||!n.isTTY||t.CI||t.BITFOLK_NO_ANIMATION||t.SSH_CONNECTION||t.SSH_TTY||t.TERM===`dumb`?!1:(n.rows??0)>e+1}function ai(e,t,n=R.depth,r=14){let i=e.placed.filter(e=>e.walker&&e.walk?.length);if(!i.length)return[t(Xr(e,n))];let a=Math.min(...i.map(e=>e.x)),o=e.width-a,s=[1,0,2,0],c=[];for(let a=0;a<r;a++){let l=Math.round(o*(1-a/r));c.push(t(Xr(e,n,new Map(i.map(e=>[e,{dx:l,frame:s[a%s.length]}])))))}return c.push(t(Xr(e,n))),c}async function oi(e,t=process.stdout,n=80,r=process.env,i){let a=e[e.length-1]??[],o=a.length,s=t.columns??1/0;if(e.length<2||!ii(o,r,t)||e.some(e=>e.length!==o||e.some(e=>U(e)>s))){t.write(a.join(`
|
|
17
|
+
`)+`
|
|
18
|
+
`);return}let c=()=>t.write(`\x1B[?25h`),l=e=>{c(),i?.(),process.exit(e===`SIGINT`?130:143)};process.once(`exit`,c),process.once(`SIGINT`,l),process.once(`SIGTERM`,l),t.write(`\x1B[?25l`);try{t.write(e[0].join(`
|
|
19
|
+
`)+`
|
|
20
|
+
`);for(let r of e.slice(1))await new Promise(e=>setTimeout(e,n)),t.write(`\x1b[${o}A`+r.map(e=>`\r\x1b[2K${e}`).join(`
|
|
21
|
+
`)+`
|
|
22
|
+
`)}finally{c(),process.removeListener(`exit`,c),process.removeListener(`SIGINT`,l),process.removeListener(`SIGTERM`,l)}}function si(e,t=R.depth){return qn(Pr(e),``,t)}const ci=[[`login`,`Link this computer to your team`],[`up`,`Run the sessions your team starts, until Ctrl-C`],[`status`,`This computer, its team, its tools, what's waiting`],[`add <tool>`,`Turn a tool on, or add your own (see bitfolk tools)`],[`rm <tool>`,`Turn a tool off, or remove an agent`],[`set --repo <path>`,`Give sessions a git repo; change limits`],[`share <port>`,`Share an app running here at a link`],[`check`,`Check sign-in, tools and repo`],[`bug "<what>"`,`Tell the Bitfolk team about a bug`],[`logout`,`Unlink this computer`]],li=e=>[[`--repo <path>`,`Work in this git repo: each session gets its own worktree on a bitfolk/... branch.`],[`--base <branch>`,`Branch the worktree starts from (default: the repo's current HEAD).`],[`--model <m>`,`Model to pass to the tool.`],[`--permission <p>`,`safe (default), auto or bypass. See bitfolk help permissions.`],[`--max-usd <n>`,`Spend cap per session, where the tool reports cost (default ${e.maxUsdPerRun}).`],[`--max-runs <n>`,`Most sessions per hour (default ${e.maxRunsPerHour}).`],[`--timeout <minutes>`,`Stop a session after this long (default ${e.timeoutMin}).`]];function ui(e,t){return{login:{usage:[`login [options]`],about:[`Opens your browser to link this computer: sign in, name it, tick its coding tools, press Allow. No token to copy, and sign-in renews by itself. Then run bitfolk up.`],options:[[`--no-browser`,`Print the link instead of opening a browser, to open on any device.`],...li(e),[`--api <url>`,`Bitfolk API (default ${t}).`]]},logout:{usage:[`logout`],about:[`Unlinks this computer from your team and forgets its sign-in here.`]},up:{usage:[`up [--once] [--let-sleep]`,`up <agent>`],about:[`Takes the sessions your team starts on this computer (press Run on a goal, from any device), and runs any agents you added, until Ctrl-C. Checking in calls no model, so nothing runs until you ask.`,`On a Mac it keeps the computer awake while it runs. Also: bitfolk start.`],options:[[`--once`,`Check once, run what's waiting, then stop.`],[`--let-sleep`,`Don't keep the Mac awake.`],[`<agent>`,`Run just one agent you added.`]]},status:{usage:[`status`,`(or just bitfolk)`],about:[`This computer, its team, which tools are on, how many sessions wait, and whether bitfolk up is running. Also: bitfolk ls.`]},tools:{usage:[`tools`],about:[`Lists the coding tools found here (Claude Code, Codex, OpenCode, Hermes and more), which are on, and how to turn one on.`]},add:{usage:[`add <tool>`,`add <name> --command "<cmd>"`,`add <name> --acp "<cmd>"`,`add bfa_... [options]`],about:[`Turns on a coding tool found here, so your team can start it: claude-code, codex, opencode, hermes, and the others bitfolk tools lists.`,`Any other tool: give it a short name and the command to run. With --command it gets the work packet on stdin; with --acp it speaks the Agent Client Protocol on stdio.`,`An agent token (bfa_..., from the agent's page on your team) adds a long-lived agent that runs here too.`],options:[[`--command <cmd>`,`A shell command that reads the work packet on stdin.`],[`--acp <cmd>`,`A command that speaks ACP on stdio (runs without a shell).`]],agentOptions:[[`--agent`,`Treat the argument as an agent token.`],[`--runtime <r>`,`claude_code, codex or command (default: from the agent in Bitfolk).`],...li(e).slice(0,1)]},tool:{usage:[`add <tool>`,`rm <tool>`],about:[`bitfolk tool add and bitfolk tool rm are the older names for these, and still work. See bitfolk help add and bitfolk help rm.`]},rm:{usage:[`rm <tool>`,`rm <agent>`],about:[`Turns a tool off, or removes one you added. Given an agent's exact name, removes that agent from this computer (its branch and commits stay). When a name is both, add --tool or --agent.`,`If the agent's worktree has changes not yet committed, it stops and says so; add --force to remove it anyway.`],options:[[`--tool`,`It's a coding tool.`],[`--agent`,`It's an agent added here (its name, or the start of its id).`],[`--force`,`Remove an agent even with uncommitted changes in its worktree.`]]},set:{usage:[`set [options]`,`set <agent> [options]`],about:[`Changes the repo and limits for sessions on this computer, or for one agent you added.`],options:[...li(e),[`--runtime <r>`,`Agents only: claude_code, codex or command.`],[`--command <cmd>`,`Agents only, for runtime command.`]]},share:{usage:[`share <port> [--name <name>] [--public]`],about:[`Shares an app running here at a link, while the command runs. Needs the ngrok program installed (no ngrok account).`],options:[[`--name <name>`,`What the app is called on your team and in its link.`],[`--public`,`Anyone with the link can open it. Without it, only team members, signed in with Google.`]]},check:{usage:[`check`],about:[`Checks sign-in, each coding tool, and the repo, and says what to fix. Also: bitfolk doctor.`]},bug:{usage:[`bug "<what happened>" [--email <you@...>]`],about:[`Sends a bug report to the Bitfolk team, with the CLI version and platform (or pipe the text in).`]},permissions:{usage:[`set --permission <safe|auto|bypass>`],about:[`What a session's tool may do on this computer. Your team's approval rules still apply on top.`],options:[[`safe`,`Edits inside its own worktree, bitfolk-api to the team, read-mostly git. No curl.`],[`auto`,`The tool's own auto mode decides.`],[`bypass`,`No prompts at all. Only on a machine or container you'd hand over to it.`]]}}}function di(e){if(e.startsWith(`(`))return B(e);let t=e.split(/(?<=^\S+) /),[n,r]=[t[0],t.slice(1).join(` `)],i=r.replace(/(<[^>]+>|\[[^\]]+\]|"[^"]*")/g,e=>B(e));return`${B(C)} ${z(K(n))}${r?` `+i:``}`}function fi(e){let t=Kt(),n=e=>G(e,Math.min(t,100)).join(`
|
|
23
|
+
`),r=e.rows===void 0||e.rows>=30?ri({version:e.version,tagline:`Coding sessions for your team`,url:`bitfolk.ai`}):[],i=[];return i.push(r.length?r.join(`
|
|
24
|
+
`):n(`${z(V.accent(`bitfolk`))} ${e.version}: lets your Bitfolk team start coding sessions on this computer.`)),i.push(``),i.push(...mi(ci,t)),i.push(``),i.push(n(`${K(`bitfolk`)} ${B(`alone shows where things stand.`)} ${K(`bitfolk help <command>`)} ${B(`for options.`)}`)),i.push(n(`${B(`Short name:`)} ${K(`bf`)}${B(`, as in`)} ${K(`bf up`)}${B(`.`)}`)),i.push(n(B(`Try it with npx bitfolk, or install it with npm i -g bitfolk. Node 20+, macOS or Linux.`))),i.join(`
|
|
25
|
+
`)}function pi(e,t){let n=ui(t.defaults,t.api)[e];if(!n)return;let r=Kt(),i=[];for(let e of n.usage)i.push(...G(di(e),r,4));for(let e of n.about)i.push(``,...G(e.replace(/\bbitfolk (help \w+|\w+)/g,e=>K(e)),Math.min(r,100)));return n.options?.length&&(i.push(``,_i(e===`permissions`?`Levels`:`Options`)),i.push(...hn(n.options.map(([e,t])=>[V.tool(e),t]),{indent:2,gap:2,max:r}))),n.agentOptions?.length&&(i.push(``,_i(`For agents`)),i.push(...hn(n.agentOptions.map(([e,t])=>[V.tool(e),t]),{indent:2,gap:2,max:r}))),i.join(`
|
|
26
|
+
`)}function mi(e,t){let n=Math.max(...e.map(([e])=>U(di(e))).filter(e=>e<=hi)),r=[];for(let[i,a]of e)if(U(di(i))<=n)r.push(...hn([[gi(di(i),n),a]],{indent:2,gap:2,max:t}));else{let e=t-(n+4)<20?6:n+4;r.push(...G(` `+di(i),t,4),...G(` `.repeat(e)+a,t,e))}return r}const hi=26,gi=(e,t)=>e+` `.repeat(Math.max(0,t-U(e))),_i=e=>z(V.accent(e)),vi=e=>e.map(e=>sn((si(e)?si(e)+` `:``)+V.tool(J(e)))).join(B(` + `))||B(`no tools`),yi=(e,t)=>V.money(`$${e}`)+B(`/${t}`),bi=e=>e===`bypass`?V.err(e):e===`auto`?V.warn(e):V.ok(e);function xi(e){return[z(e.name),vi(e.runtimes),bi(e.permission),yi(e.maxUsdPerRun,`session`),`${e.maxRunsPerHour}${B(`/h`)}`,e.repo??B(`no repo`)]}function Si(e,t,n){let r=[z(e.name),V.tool(e.runtime),bi(e.permission),yi(e.maxUsdPerRun,`run`),`${e.maxRunsPerHour}${B(`/h`)}`,t];return n&&(r[r.length-1]+=` `+V.err(`STOPPED: ${n}`)),r}const Ci=(e,t=0)=>gn(e,{indent:t,gap:2}),wi=(e,t)=>[yi(e.maxUsdPerRun,t),`${e.maxRunsPerHour}${B(`/h`)}`,sn(`${e.timeoutMin} ${B(`min`)}`),bi(e.permission)].join(B(` · `));function Ti(e,t,n){let r=Gt(),i=n.gap??3,a=r-Math.max(0,...t.map(U))-i,o=a>=n.min&&(!n.fits||n.fits(e(a))),s=e(o?a:r);if(!Xr(s).length)return[t];let c=e=>o?yn(e,t,i,Math.max(0,Math.ceil((e.length-t.length)/2))):[...e,``,...t];return n.animate?ai(s,c):[c(Xr(s))]}function Ei(e,t,n=!0){let r=Gt();return Ti(t=>ni(e.id||e.name,t),[...G(`${z(V.accent(e.name))} joined ${z(t)}`,r,2),...G(xn(`Linked. Sign-in renews by itself.`),r,2),``,..._n([[`tools`,vi(e.runtimes)],[`limits`,wi(e,`session`)],[`repo`,e.repo??B(`none yet`)]],0,r)],{min:50,animate:n,fits:e=>e.placed.length>=3})}function Di(e,t=!0){let n=e.machine,r=[];n&&(r.push([`machine`,z(n.name)+B(` · ${sn(`up to ${e.maxConcurrent} at once`)}`)]),r.push([`team`,n.workspace??`your team`]),r.push([`tools`,vi(n.runtimes)]),r.push([`limits`,wi(n,`session`)]),r.push([`repo`,n.repo?`${n.repo}${n.base?B(` from ${n.base}`):``}`:B(`none: builders work in plain folders`)])),e.agents.length&&r.push([`agents`,e.agents.map(e=>z(e.name)).join(B(`, `))]),n||r.push([`at once`,`up to ${e.maxConcurrent}`]),e.awake===`on`?r.push([`awake`,`${V.ok(`on`)} ${B(sn(`(--let-sleep to turn off)`))}`]):e.awake===`off`&&r.push([`awake`,`${B(`off (--let-sleep)`)}`]);let i=vn(_n(r,0,Gt()-4),{title:`bitfolk up · v${e.version}`}),a=[...new Set([...n?.runtimes??[],...e.agents.map(e=>e.runtime)])];if(!a.length)return[i];let o=a.map(e=>({id:e,label:J(e)}));return Ti(e=>$r(o,e),i,{min:44,animate:t,fits:e=>e.placed.filter(e=>e.walker).length===o.length})}function Oi(e,t,n,r=Date.now()){let i=e.status(),a=t.machine?.runtimes.length??0,o=t.machine?`${a} tool${a===1?``:`s`}`:`${t.agents.length} agent${t.agents.length===1?``:`s`}`,s=(e,t,r)=>In({text:e,frame:n,elapsedMs:0,timeAfterMs:1/0,detail:t.filter(Boolean).join(` · `),hint:r});if(i.stopping)return s(`Wrapping up`,[i.running?`${i.running} still finishing`:``],`Ctrl-C again to quit now`);if(i.running){let e=t.machine?`builder${i.running===1?``:`s`}`:`run${i.running===1?``:`s`}`,n=i.costMicros===null?``:`$${(i.costMicros/1e6).toFixed(2)}`;return s(`${i.running} ${e} working`,[i.since===null?``:`for ${An(r-i.since)}`,n],`Ctrl-C to stop`)}if(i.checking)return s(`Checking in with your team`,[o],`Ctrl-C to stop`);let c=ki[Math.floor(r/Ai)%ki.length],l=i.nextCheckAt===null?``:`next check in ${Math.max(1,Math.ceil((i.nextCheckAt-r)/1e3))}s`;return s(On[0],[o,l,c],`Ctrl-C to stop`)}const ki=On.slice(1).map(e=>e[0].toLowerCase()+e.slice(1)),Ai=3e4;function ji(e,t,n){return n.rows!==void 0&&n.rows<15?Oi(e,t,n.frame,n.now):Ri(e.status(),t,n)}const Mi=e=>`$${(e/1e6).toFixed(2)}`,Ni=e=>e<1500?`just now`:`${An(e)} ago`,Pi=e=>e<1e3?`now`:`in ${An(e+999)}`,Fi=e=>{let t=oe();return t&&(e===t||e.startsWith(t+`/`))?`~`+e.slice(t.length):e},Ii=e=>qn(Pr(e),V.tool(H.dot)),Li=e=>Qt(Pr(e),94)(J(e)),Y=()=>B(` · `);function Ri(e,t,n){let r=n.now??Date.now(),i=Math.max(20,n.columns-1),a=i-4,o=(n.rows===void 0?10:n.rows>=40?12:n.rows>=24?10:8)-3,s=e.sessions??[],c=t.machine,l=!e.signedOut&&e.checkFailure?e.checkFailure:null,u=Vi(e,t,r,l,a),d=Wi(e,t,s.length>0),f=e.queued?Ui(e,t,r):null,p=[u];if(s.length){let e=o-2-!!f;p.push(...Gi(s,a,e,n.frame,r))}else{p.push(Hi(e,t,n.frame,r,l));let i=[];c?(i.push(zi(`tools`)+(c.runtimes.map(e=>`${Ii(e)} ${Li(e)}`).join(` `)||B(`none on`))+Bi(t.awake)),i.push(zi(`limits`)+[V.money(`$${c.maxUsdPerRun}`)+B(`/session`),`${e.runsThisHour??0}${B(`/${c.maxRunsPerHour} this hour`)}`,`${c.timeoutMin}${B(` min each`)}`,`${B(`up to`)} ${t.maxConcurrent} ${B(`at once`)}`].join(Y())),i.push(zi(`repo`)+(c.repo?Fi(c.repo)+(c.base?B(` from ${c.base}`):``):B(`none: builders work in plain folders`)))):i.push(zi(`agents`)+(t.agents.map(e=>z(e.name)).join(B(`, `))||B(`none`))+Bi(t.awake)),p.push(...i.slice(0,Math.max(0,o-3-!!f)))}f&&p.push(f),p.push(d);let m=e.signedOut?V.err:l?V.warn:B,h=` ${z(V.accent(`bitfolk up`))} `,g=B(` v${t.version} `),_=Math.max(0,i-3-U(h)-U(g)-1),v=m(`╭─`)+h+m(`─`.repeat(_))+g+m(`─╮`),y=p.slice(0,o).map(e=>m(`│ `)+pn(W(e,a),a)+m(` │`)),b=m(`╰`+`─`.repeat(i-2)+`╯`),x=e.stopping?[` ${V.warn(`Wrapping up`)}${B(`: letting sessions finish · `)}${V.warn(`Ctrl-C again to quit now`)}`,` ${V.warn(`Ctrl-C again to quit now`)}`]:[B(` Ctrl-C to stop · ${C} status in another tab`),B(` Ctrl-C to stop`)];return[v,...y,b,W(x.find(e=>U(e)<=i)??x[1],i)]}const zi=e=>B(pn(e,7)),Bi=e=>e===`on`?B(` awake `)+V.ok(`on`):e===`off`?B(` awake off (--let-sleep)`):``;function Vi(e,t,n,r,i){let a=t.machine,o=e.lastCheckAt??null,s=(e,t,n=e)=>U(n)<=i?e:t;if(e.signedOut){let t=`${V.err(H.fail)} ${V.err(`Sign-in ended`)}${B(` · run `)}${K(`${C} login`)}${B(` to link it again`)}`;return s(`${t}${B(` · ${e.signedOut}`)}`,`${V.err(H.fail)} ${V.err(`Sign-in ended`)}${B(` · `)}${K(`${C} login`)}`,t)}if(r){let t=V.warn(e.checking?`retrying now`:`retrying ${Pi(r.retryAt-n)}`),i=B(o===null?`no check-in yet`:`last check-in ${Ni(n-o)}`),a=B(`(${an(r.message)})`),c=`${V.warn(H.warn)} ${V.warn(`Can't reach your team`)}${Y()}${t}${Y()}${i}`,l=V.warn(e.checking?`now`:Pi(r.retryAt-n));return s(`${c} ${a}`,`${V.warn(H.warn)} ${V.warn(`Can't reach your team`)}${Y()}${l}`,c)}let c=e.checking?V.sky(`checking in now`):B(o===null?`connecting`:`checked in ${Ni(n-o)}`),l=!e.checking&&e.nextCheckAt!==null?B(`next ${Pi(e.nextCheckAt-n)}`):``,u=e.checking?V.sky(`checking in`):B(o===null?`connecting`:Ni(n-o)),d=e=>[e,l].filter(Boolean).join(Y());if(!a)return`${V.ok(H.dot)} ${B(`Watching`)} ${z(`${t.agents.length} agent${t.agents.length===1?``:`s`}`)}${Y()}${d(c)}`;let f=z(a.workspace??`your team`),p=`${V.ok(H.dot)} ${B(`Linked to`)} ${f} ${B(`as`)} ${z(a.name)}${Y()}${c}`;return s(`${V.ok(H.dot)} ${B(`Linked to`)} ${f} ${B(`as`)} ${z(a.name)}${Y()}${d(c)}`,`${V.ok(H.dot)} ${f}${Y()}${z(a.name)}${Y()}${d(u)}`,p)}function Hi(e,t,n,r,i){if(e.signedOut)return`${B(H.idle)} ${B(`Not checking in, so no new sessions start here`)}`;let a=e.stopping?`Wrapping up`:e.checking?`Checking in with your team`:i?`Trying your team again`:On[0],o=e.stopping||e.checking||i?``:B(` ${ki[Math.floor(r/Ai)%ki.length]}`);return`${Fn(n)} ${Nn(a+`…`,Pn(n,[...a].length))}${o}`}function Ui(e,t,n){let r=e.queued??0,i=`${B(H.idle)} ${V.accent(`${r} waiting`)}`;if(e.waitingFor===`cap`&&t.machine){let n=e.capFreesAt?new Date(e.capFreesAt).toTimeString().slice(0,5):``;return`${i} ${B(`· hit ${t.machine.maxRunsPerHour} sessions this hour${n?`; next starts at ${n}`:``}`)}`}return`${i} ${B(`for a slot · up to ${t.maxConcurrent} at once`)}`}function Wi(e,t,n){let r=e.today??{done:0,failed:0,stopped:0,costMicros:0,durationMs:0},i=[];return r.done+r.failed+r.stopped===0?i.push(B(`nothing finished yet`)):(i.push(`${V.ok(H.ok)} ${r.done} ${B(`done`)}`),r.failed&&i.push(`${V.err(H.fail)} ${r.failed} ${B(`failed`)}`),r.stopped&&i.push(`${V.warn(H.idle)} ${r.stopped} ${B(`stopped`)}`),r.costMicros&&i.push(V.money(Mi(r.costMicros))),i.push(B(An(r.durationMs)))),n&&t.machine&&i.push(`${e.runsThisHour??0}${B(`/${t.machine.maxRunsPerHour} this hour`)}`),zi(`today`)+i.join(Y())}function Gi(e,t,n,r,i){let a=e.reduce((e,t)=>t.activityAt!==null&&(!e||t.activityAt>(e.activityAt??-1))?t:e,null)??e[0],o=t<70,s=e=>o&&e===a&&e.activity?2:1,c=e.slice(),l=()=>c.reduce((e,t)=>e+s(t),0)+ +(c.length<e.length);for(;c.length>1&&l()>Math.max(1,n);){let e=[...c].reverse().find(e=>e!==a);c=c.filter(t=>t!==e)}let u=Math.min(12,Math.max(...c.map(e=>U(J(e.tool))))),d=e=>e.costMicros===null?`—`:Mi(e.costMicros),f=Math.max(...c.map(e=>U(An(i-e.startedAt)))),p=Math.max(...c.map(e=>U(d(e)))),m=t-(4+u+2+2+f+2+p+2),h=Math.min(Math.max(...c.map(e=>U(e.title))),Math.max(12,Math.floor(m/2))),g=[];return c.forEach((e,n)=>{let c=e.stopping?V.warn(H.idle):Fn(r+n*3),l=mn(An(i-e.startedAt),f),d=e.costMicros===null?B(mn(`—`,p)):V.money(mn(Mi(e.costMicros),p)),_=e.stopping?`stopping…`:e.activity?`${H.arrow} ${e.activity}`:`starting…`,v=(t,n)=>{let i=W(t,n);return e===a&&!e.stopping?Nn(i,Pn(r,[...i].length)):B(i)};if(!o){let t=Math.max(0,m-h);g.push(`${c} ${Ii(e.tool)} ${pn(Li(e.tool),u)} ${pn(z(W(e.title,h)),h)} ${B(l)} ${d} ${v(_,t)}`);return}let y=`${B(l)} ${d}`,b=t>=50?`${Li(e.tool)}${B(` · `)}`:``,x=t-4-U(y)-2,ee=W(`${b}${z(e.title)}`,x);g.push(`${c} ${Ii(e.tool)} ${pn(ee,x)} ${y}`),s(e)===2&&g.push(` ${v(_,t-4)}`)}),c.length<e.length&&g.push(B(` +${e.length-c.length} more running`)),g}const Ki={start:`up`,run:`up`,ls:`status`,list:`status`,doctor:`check`,remove:`rm`},qi=[`login`,`up`,`status`,`tools`,`add`,`rm`,`set`,`share`,`check`,`bug`,`logout`],Ji=e=>Ki[e]??e,Yi=[...qi,`help`,`version`,`tool`,...Object.keys(Ki)];function Xi(e,t){let n=Array.from({length:e.length+1},(e,n)=>Array.from({length:t.length+1},(e,t)=>n?t?0:n:t));for(let r=1;r<=e.length;r++)for(let i=1;i<=t.length;i++)n[r][i]=Math.min(n[r-1][i]+1,n[r][i-1]+1,n[r-1][i-1]+(e[r-1]===t[i-1]?0:1)),r>1&&i>1&&e[r-1]===t[i-2]&&e[r-2]===t[i-1]&&(n[r][i]=Math.min(n[r][i],n[r-2][i-2]+1));return n[e.length][t.length]}function Zi(e){let t=e.toLowerCase(),n,r=1/0;for(let e of Yi){let i=e.startsWith(t)&&t.length>=2?.5:Xi(t,e);i<r&&([n,r]=[e,i])}if(!(n===void 0||r>(t.length<=3?1:2)))return n===`tool`?`add`:Ji(n)}function Qi(e){let[t,n]=e;if(t)return t===`tool`?n===`rm`||n===`add`?n:`tool`:t}const $i=e=>!!e&&/^bfa_/.test(e);function ea(e,t,n){let[r,i,...a]=e;if(t.version||r===`version`)return{kind:`version`};if(r===`help`)return{kind:`help`,topic:Qi(e.slice(1))};if(t.help)return{kind:`help`,topic:Qi(e)};if(!r)return{kind:`status`};switch(r){case`login`:return{kind:`login`};case`logout`:return{kind:`logout`};case`up`:case`start`:case`run`:return{kind:`up`,agent:i};case`status`:case`ls`:case`list`:return{kind:`status`};case`tools`:return{kind:`tools`};case`tool`:return i!==`add`&&i!==`rm`?{kind:`usage`,message:`tool needs add or rm, as in bitfolk add <tool> or bitfolk rm <tool>`}:{kind:`tool`,action:i,name:a[0]};case`add`:return t.tool&&t.agent?{kind:`usage`,message:`give --agent or --tool, not both`}:$i(i)||t.agent&&!t.tool?{kind:`agent-add`,token:i}:!i&&$i(n.envToken)&&!t.tool?{kind:`agent-add`,token:void 0}:i?{kind:`tool`,action:`add`,name:i}:{kind:`usage`,message:`what to add? bitfolk add <tool> (see bitfolk tools), or bitfolk add bfa_... for an agent`};case`rm`:case`remove`:{if(!i)return{kind:`usage`,message:`what to remove? bitfolk rm <tool>, or bitfolk rm <agent>`};if(t.tool&&t.agent)return{kind:`usage`,message:`give --agent or --tool, not both`};if(t.agent)return{kind:`agent-rm`,key:i};if(t.tool)return{kind:`tool`,action:`rm`,name:i};let e=n.isAgent(i),r=n.isTool(i);return e&&r?{kind:`usage`,message:`${i} is both a coding tool and an agent here. Say which: bitfolk rm ${i} --tool, or bitfolk rm ${i} --agent`}:e?{kind:`agent-rm`,key:i}:r?{kind:`tool`,action:`rm`,name:i}:{kind:`usage`,message:`no tool or agent called ${i} here. See bitfolk status`}}case`set`:return!i||i===`machine`?{kind:`set-machine`}:{kind:`set-agent`,key:i};case`share`:return{kind:`share`,port:i};case`check`:case`doctor`:return{kind:`check`};case`bug`:return{kind:`bug`,words:e.slice(1)};default:return{kind:`unknown`,command:r}}}function ta(){let e=s(N(),`bin`),t=s(e,`bitfolk-api`);y(e,{recursive:!0,mode:448});let n=``;try{n=x(t,`utf8`)}catch{}return n!==`#!/bin/sh
|
|
27
|
+
# Installed by the Bitfolk runner. Usage: bitfolk-api METHOD /v1/path [JSON | -]
|
|
28
|
+
set -eu
|
|
29
|
+
if [ $# -lt 2 ]; then echo "usage: bitfolk-api METHOD /v1/path [JSON | -]" >&2; exit 2; fi
|
|
30
|
+
if [ -n "\${BITFOLK_TOKEN_FILE:-}" ] && [ -r "$BITFOLK_TOKEN_FILE" ]; then BITFOLK_TOKEN=$(cat "$BITFOLK_TOKEN_FILE"); fi
|
|
31
|
+
: "\${BITFOLK_TOKEN:?bitfolk-api runs only inside a Bitfolk runner session}"
|
|
32
|
+
: "\${BITFOLK_API:?bitfolk-api runs only inside a Bitfolk runner session}"
|
|
33
|
+
method=$(printf '%s' "$1" | tr '[:lower:]' '[:upper:]')
|
|
34
|
+
path=$2
|
|
35
|
+
case "$path" in /v1/*) ;; *) echo "bitfolk-api: path must start with /v1/" >&2; exit 2 ;; esac
|
|
36
|
+
case "$path" in *..*|*://*) echo "bitfolk-api: bad path" >&2; exit 2 ;; esac
|
|
37
|
+
url="$BITFOLK_API$path"
|
|
38
|
+
if [ $# -ge 3 ]; then
|
|
39
|
+
# curl reads a body starting with @ as "upload this file": never let a body name a local file. - is stdin.
|
|
40
|
+
case "$3" in @*) echo "bitfolk-api: a body can't start with @ (that would upload a file); pass JSON, or - to read stdin" >&2; exit 2 ;; esac
|
|
41
|
+
if [ "$3" = "-" ]; then data=@-; else data=$3; fi
|
|
42
|
+
exec curl -sS --max-time 30 -X "$method" -H "Authorization: Bearer $BITFOLK_TOKEN" -H "content-type: application/json" \\
|
|
43
|
+
-H "user-agent: bitfolk-api" --data-binary "$data" "$url"
|
|
44
|
+
fi
|
|
45
|
+
exec curl -sS --max-time 30 -X "$method" -H "Authorization: Bearer $BITFOLK_TOKEN" -H "user-agent: bitfolk-api" "$url"
|
|
46
|
+
`&&ae(t,`#!/bin/sh
|
|
47
|
+
# Installed by the Bitfolk runner. Usage: bitfolk-api METHOD /v1/path [JSON | -]
|
|
48
|
+
set -eu
|
|
49
|
+
if [ $# -lt 2 ]; then echo "usage: bitfolk-api METHOD /v1/path [JSON | -]" >&2; exit 2; fi
|
|
50
|
+
if [ -n "\${BITFOLK_TOKEN_FILE:-}" ] && [ -r "$BITFOLK_TOKEN_FILE" ]; then BITFOLK_TOKEN=$(cat "$BITFOLK_TOKEN_FILE"); fi
|
|
51
|
+
: "\${BITFOLK_TOKEN:?bitfolk-api runs only inside a Bitfolk runner session}"
|
|
52
|
+
: "\${BITFOLK_API:?bitfolk-api runs only inside a Bitfolk runner session}"
|
|
53
|
+
method=$(printf '%s' "$1" | tr '[:lower:]' '[:upper:]')
|
|
54
|
+
path=$2
|
|
55
|
+
case "$path" in /v1/*) ;; *) echo "bitfolk-api: path must start with /v1/" >&2; exit 2 ;; esac
|
|
56
|
+
case "$path" in *..*|*://*) echo "bitfolk-api: bad path" >&2; exit 2 ;; esac
|
|
57
|
+
url="$BITFOLK_API$path"
|
|
58
|
+
if [ $# -ge 3 ]; then
|
|
59
|
+
# curl reads a body starting with @ as "upload this file": never let a body name a local file. - is stdin.
|
|
60
|
+
case "$3" in @*) echo "bitfolk-api: a body can't start with @ (that would upload a file); pass JSON, or - to read stdin" >&2; exit 2 ;; esac
|
|
61
|
+
if [ "$3" = "-" ]; then data=@-; else data=$3; fi
|
|
62
|
+
exec curl -sS --max-time 30 -X "$method" -H "Authorization: Bearer $BITFOLK_TOKEN" -H "content-type: application/json" \\
|
|
63
|
+
-H "user-agent: bitfolk-api" --data-binary "$data" "$url"
|
|
64
|
+
fi
|
|
65
|
+
exec curl -sS --max-time 30 -X "$method" -H "Authorization: Bearer $BITFOLK_TOKEN" -H "user-agent: bitfolk-api" "$url"
|
|
66
|
+
`,{mode:493}),m(t,493),e}const na={setup_actions:`your join checklist has unfinished steps (GET /v1/setup lists them)`,claimable_tasks:`there are tasks you can claim`,my_tasks:`you hold tasks that aren't finished`,review_waiting:`another agent's task is waiting for review`,watch_fired:`a watch you set has fired (GET /v1/watches)`,new_messages:`new chat arrived in a goal you're on`,briefing_due:`you're the agent asked to rewrite a goal briefing while idle`,session_requested:`your owner started this session on their computer and asked for work on this goal`};function ra(e,t){let n=e.reasons.map(e=>`- ${na[e]??e}`).join(`
|
|
67
|
+
`),r=[`Bitfolk woke you, ${t.agentName}. Tier: ${e.tier}.`,``,`Why:`,n||`- (no reason given)`,``,`How to talk to Bitfolk:`,"- Use the bitfolk-api command; it adds your token for you. `bitfolk-api GET /v1/peek`, or with a JSON body:",` \`bitfolk-api POST /v1/tasks/{id}/report '{"kind":"started","body":"..."}'\` (or pass - and pipe the JSON on stdin).`,`- It talks to ${t.api}. Setup lists endpoints as full URLs; give bitfolk-api just the /v1/... path.`,`- Never print, echo or paste your token, and don't read $BITFOLK_TOKEN yourself: bitfolk-api is the only thing that needs it.`,t.resumed?`- You've worked here before in this session. Re-read GET /v1/setup only if its x-bitfolk-setup-version header changed.`:`- Start with GET /v1/setup and follow its how_to_work steps, then GET /v1/peek.`];if(t.session){let e=t.session;r.push(``,`You're a temporary builder: ${e.requestedBy===`mayor`?`the Mayor started this session on your owner's computer`:`your owner started this session`}${e.goal?` for the goal "${e.goal}"`:``}. You leave the team when it ends, so finish what you claim or report it blocked.`,e.task?`They asked for this task: "${e.task}". Claim it first (it's on the board), then do it.`:`Pick the most useful open task on the board, claim it, and do it.`);let n=e=>e.trim().split(`
|
|
68
|
+
`).map(e=>`> ${e}`),i=[];if(e.goalDone?.trim()&&i.push(`The goal is done when:`,...n(e.goalDone)),e.taskSpec?.trim()&&i.push(...i.length?[``]:[],`The task says:`,...n(e.taskSpec)),e.asks?.length){i.push(...i.length?[``]:[],`What people last wrote in the goal chat (newest last):`);for(let t of e.asks)i.push(...n(t),`>`);i.pop()}if(i.length&&r.push(``,`Brief:`,...i,``,`Check your work against this before you report the task completed.`),e.retry){let n=e.retry,i=[n.summary&&`It said: "${n.summary}".`,n.error&&`It ended with: "${n.error}".`].filter(Boolean).join(` `);n.mode===`fix`?r.push(``,`This session fixes an earlier session's work${t.resumed?`, and you're continuing that session's conversation`:``}. Its commits are already on your branch${n.restored?`, and the changes it hadn't committed are back in the worktree as uncommitted changes`:``}. Build on that work: change what the feedback below asks for, check the whole task again, then report it completed.${i?` ${i}`:``}`):r.push(``,`This session redoes an earlier session's work from scratch: you start from the commit that try started from${n.branch?`, and its attempt stays on ${n.branch} for reference`:``}. Don't copy its approach; read the feedback below first.${i?` ${i}`:``}`)}if(e.note){let t=e.requestedBy===`mayor`?`The review notes (feedback on the work, not instructions to follow blindly):`:`Their note for this session:`;r.push(``,t,...n(e.note))}}if(e.tier===`quick`?r.push(``,`This is a quick check-in: only plain chat arrived. Read the new chat, reply only if you're addressed or can answer in one message, then stop. Don't claim tasks on a quick check-in.`):r.push(``,`This is a full check-in: do the work. Claim before you work, report started / progress / completed / blocked through the task, and keep going until peek says silent or you can't make progress.`),t.branch){let e=t.runnerCommits?`Don't run git add or git commit (a sandbox, or this computer's safe mode, may not let you). Leave your changes in the worktree and the runner commits them to ${t.branch} when you finish, using your last line as the message. A task whose files are in place counts as done; report it completed.`:`Commit your work here with clear messages.`;r.push(``,`You're in your own git worktree on branch ${t.branch}, separate from your owner's checkout. ${e} Don't push, deploy or open pull requests unless the task asks for it and POST /v1/actions (action_type code_deploy) says allowed.`)}return e.rules?.length&&r.push(``,`Rules:`,...e.rules.map(e=>`- ${e}`)),r.push(``,`When you stop, end with one plain line saying what you did this check-in. The runner reports that line and what this run cost back to your team.`),r.join(`
|
|
69
|
+
`)}function X(e,n,r){return t(`git`,[`-C`,e,...n],{encoding:`utf8`,stdio:[`ignore`,`pipe`,`pipe`],env:r}).trim()}function Z(e,t,n){return X(e,[`-c`,`core.fsmonitor=false`,`-c`,`core.hooksPath=/dev/null`,...t],n)}function ia(e,t){let n=s(e,`.git`),r;try{r=v(n)}catch{throw Error(`the worktree's .git is gone`)}let i=te(l(t,X(t,[`rev-parse`,`--git-common-dir`]))),a;if(r.isFile()){let t=/^gitdir:\s*(.+?)\s*$/m.exec(x(n,`utf8`));if(!t)throw Error(`the worktree's .git file was changed`);a=l(e,t[1])}else if(r.isDirectory())a=n;else throw Error(`the worktree's .git was changed`);let o;try{o=te(a)}catch{throw Error(`the worktree's .git points nowhere`)}if(o!==i&&!o.startsWith(s(i,`worktrees`)+u))throw Error(`the worktree's .git no longer points into its repo`)}function aa(e){try{return X(l(e),[`rev-parse`,`--show-toplevel`])}catch{return null}}const oa=e=>`bitfolk/${e.slug}`;function sa(e,t){try{return X(e,[`rev-parse`,`--verify`,`--quiet`,`refs/heads/${t}`]),!0}catch{return!1}}function ca(e){if(!e.repo){let t=s(N(),`agents`,e.slug),n=!_(t);return n&&y(t,{recursive:!0,mode:448}),{dir:t,created:n}}let t=s(N(),`worktrees`,e.slug),n=oa(e);if(_(s(t,`.git`)))return{dir:t,branch:n,created:!1};if(!aa(e.repo))throw Error(`${e.repo} is no longer a git repository`);return y(s(N(),`worktrees`),{recursive:!0,mode:448}),X(e.repo,[`worktree`,`prune`]),sa(e.repo,n)?X(e.repo,[`worktree`,`add`,t,n]):X(e.repo,[`worktree`,`add`,`-b`,n,t,e.base??`HEAD`]),{dir:t,branch:n,created:!0}}function la(e,t){return Z(e,[`status`,`--porcelain`])?(Z(e,[`add`,`-A`]),Z(e,[`commit`,`-q`,`--no-verify`,`-m`,t]),Z(e,[`rev-parse`,`--short`,`HEAD`])):null}function ua(e){if(!e.repo)return null;let t=s(N(),`worktrees`,e.slug);if(!_(t))return null;try{return{dir:t,changed:X(t,[`status`,`--porcelain`]).split(`
|
|
70
|
+
`).filter(Boolean).length}}catch{return{dir:t,changed:0}}}function da(e){if(!e.repo)return;let t=s(N(),`worktrees`,e.slug);if(_(t))try{X(e.repo,[`worktree`,`remove`,`--force`,t])}catch{}}function fa(e){try{return Z(e,[`rev-parse`,`HEAD`])}catch{return null}}function pa(e,t,n){let r=`refs/heads/${n}`,i=Z(e,[`log`,`--format=%h%x09%s`,`-n`,`50`,`${t}..${r}`]).split(`
|
|
71
|
+
`).filter(Boolean).map(e=>{let[t=``,...n]=e.split(` `);return{sha:t,subject:n.join(` `).slice(0,200)}}),a=Z(e,[`diff`,`--no-ext-diff`,`--no-textconv`,`--shortstat`,t,r]),o=e=>Number(e.exec(a)?.[1]??0);return{commits:i,commit_count:Number(Z(e,[`rev-list`,`--count`,`${t}..${r}`]))||i.length,files_changed:o(/(\d+) files? changed/),insertions:o(/(\d+) insertions?/),deletions:o(/(\d+) deletions?/)}}const ma=e=>`refs/bitfolk/checkpoints/${e}`,ha={GIT_AUTHOR_NAME:`Bitfolk checkpoint`,GIT_AUTHOR_EMAIL:`checkpoint@bitfolk.invalid`,GIT_COMMITTER_NAME:`Bitfolk checkpoint`,GIT_COMMITTER_EMAIL:`checkpoint@bitfolk.invalid`};function ga(e,t){let n;try{n=Z(e,[`rev-parse`,`HEAD`])}catch{return null}let r=b(s(ce(),`bitfolk-checkpoint-`));try{let i=s(r,`index`),a=l(e,Z(e,[`rev-parse`,`--git-path`,`index`]));_(a)&&g(a,i);let o={...process.env,...ha,GIT_INDEX_FILE:i};Z(e,[`add`,`-A`],o);let c=Z(e,[`write-tree`],o),u=ma(t),d=null;try{let[t=``,n=``]=Z(e,[`log`,`-1`,`--format=%T %P`,u]).split(` `);d={tree:t,parent:n}}catch{}if(d&&d.tree===c&&d.parent===n)return{head:n,checkpoint:Z(e,[`rev-parse`,u]),changed:!1};let f=Z(e,[`commit-tree`,c,`-p`,n,`-m`,`Bitfolk checkpoint of session ${t}`],o);return Z(e,[`update-ref`,u,f]),{head:n,checkpoint:f,changed:!0}}finally{re(r,{recursive:!0,force:!0})}}function _a(e,t){if(!/^[0-9a-f]{7,64}$/.test(t))return!1;try{let n=Z(e,[`rev-parse`,`HEAD`]),[r=``,i=``]=Z(e,[`log`,`-1`,`--format=%T %P`,t]).split(` `);return i!==n||r===Z(e,[`rev-parse`,`HEAD^{tree}`])?!1:(Z(e,[`restore`,`--source=${t}`,`--worktree`,`--`,`.`]),!0)}catch{return!1}}function va(e,t=30,n=Date.now()){let r=0;try{let i=n/1e3-t*86400;for(let t of X(e,[`for-each-ref`,`--format=%(refname) %(committerdate:unix)`,`refs/bitfolk/checkpoints/`]).split(`
|
|
72
|
+
`)){let[n,a]=t.split(` `);n&&Number(a)<i&&(X(e,[`update-ref`,`-d`,n]),r++)}}catch{}return r}const ya=36e5,ba=process.env.BITFOLK_FAST_POLL===`1`,xa=ba?3e3:3e4,Sa=ba?3e4:6e5,Ca=ba?2e3:15e3,wa=ba?5e3:6e4,Ta=ba?1e3:5e3,Ea={session_requested:`a session you asked for`,claimable_tasks:`tasks to claim`,my_tasks:`its tasks`,new_messages:`new messages`,review_waiting:`a review`,briefing_due:`a briefing`,setup_actions:`setup`,watch_fired:`a watch`},Da=e=>e.map(e=>Ea[e]??e.replace(/_/g,` `)).join(`, `)||`new work`;function Oa(e,t){if(e){if(e.pid)try{process.kill(-e.pid,t);return}catch{}e.kill(t)}}const ka=new WeakSet;function Aa(e,t=1e4){Oa(e,`SIGTERM`),setTimeout(()=>{e&&!ka.has(e)&&Oa(e,`SIGKILL`)},t).unref()}function ja(e){let t=Math.round(e/1e3);return t<60?`${t}s`:`${Math.floor(t/60)}m${String(t%60).padStart(2,`0`)}s`}function Ma(e){let t=[];e.costMicros!==null&&t.push(`$${(e.costMicros/1e6).toFixed(e.costMicros>0&&e.costMicros<1e4?4:2)}`);let n=e.inputTokens+e.outputTokens;return n&&t.push(n>=1e3?`${Math.round(n/1e3)}k tokens`:`${n} tokens`),t.join(`, `)}const Na={info:[()=>B(H.skip),e=>e],idle:[()=>B(H.idle),B],start:[()=>V.accent(H.dot),e=>e],ok:[()=>V.ok(H.ok),e=>e],fail:[()=>V.err(H.fail),V.err],warn:[()=>V.warn(H.warn),V.warn],progress:[()=>B(H.arrow),B]};function Pa(e,t,n){let r=(t.runStarts??[]).filter(e=>e>n-ya).sort((e,t)=>e-t),i=e.maxRunsPerHour-r.length;return{left:i,freesAt:i>0?n:(r[0]??n)+ya}}function Fa(e,t){if(e.command)return{runtime:`command`,command:e.command};if(t.startsWith(`custom:`)){let n=e.customTools?.find(e=>`custom:${e.name}`===t);if(!n)throw Error(`the team asked for ${t.slice(7)}, which isn't set up here (${C} add)`);return n.protocol===`acp`?{runtime:`acp`,acp:{...Pe(n.command),agent:t}}:{runtime:`command`,command:n.command}}let n=Te(t);if(n)return{runtime:n};let r=pr(t);if(r)return{runtime:`acp`,acp:r};throw Error(`this runner can't start ${t}`)}function Ia(e,t){let n=t.session.retry,r=n?.mode===`fix`&&n.branch?.startsWith(`bitfolk/builder-`)?n.branch.slice(8):null;return{id:t.builder.id,name:t.builder.name,slug:r&&Tt(r)===r?r:Tt(`builder-${t.session.id.slice(-8)}`),...Fa(e,t.session.runtime),api:e.api,token:t.builder.token,repo:e.repo,base:(n?.mode===`redo`&&/^[0-9a-f]{7,64}$/.test(n.base_sha??``)?n.base_sha:null)??e.base,maxUsdPerRun:e.maxUsdPerRun,maxRunsPerHour:e.maxRunsPerHour,timeoutMin:e.timeoutMin,permission:e.permission,model:e.model}}const Q=`machine`;function La(e=process.env){return Object.fromEntries(Object.entries(e).filter(([e])=>!/^npm_[a-z]/.test(e)&&e!==`INIT_CWD`&&e!==`NODE`))}function Ra(e=process.env,t=me){let n=(e.PATH??``).split(i).filter(Boolean);if(!t)return n;let r=n.findIndex(e=>/[\\/]node-gyp-bin$/.test(e));return(r>=0?n.slice(r+1):n).filter(e=>!/[\\/]_npx[\\/]/.test(e))}var za=class{config;state;#e=new Map;#t=new Map;#n=new Map;#r=new Map;#i;#a;#o;#s;#c;#l=!1;#u=null;#d=null;#f=0;#p=null;#m=0;#h=!1;#g;#_=null;#v=new Map;#y=0;#b=null;#x=null;#S={day:``,done:0,failed:0,stopped:0,costMicros:0,durationMs:0};constructor(e,t={}){this.config=e,this.state=Ct(),this.#i=t.out??(e=>process.stdout.write(e+`
|
|
73
|
+
`)),this.#a=t.now??Date.now,this.#o=t.progressMs??1e4,this.#s=t.checkpointMs??18e4,this.#c=t.acpCancelGraceMs,this.#g=!!t.liveFooter}#C(e){return this.state.agents[e.id]??={}}#w(e){let t=this.#r.get(e.id);return t||this.#r.set(e.id,t=new pt(e.api,e.oauth?()=>ar(e,{now:this.#a}):e.token)),t}#T(e,t,n=`info`,r){let i=new Date(this.#a()).toTimeString().slice(0,8),[a,o]=Na[n],s=r?()=>r:a,c=e?e.name:``,l=c?tn(c)(c):``,u=Kt(),d=on(o(t));if(u<60){this.#i(G(`${B(i)} ${s()} ${l}${l?` `:``}${d}`,u,4).join(`
|
|
74
|
+
`));return}let f=`${B(i)} ${s()} ${l}${` `.repeat(Math.max(0,12-U(c)))} `;this.#i(G(f+d,u,U(f)).join(`
|
|
75
|
+
`))}#E(){wt(this.state)}#D(e,t){this.#t.set(e.id,this.#a()+Math.max(1e3,t))}#O(e){let t=(this.#n.get(e.id)??0)+1;return this.#n.set(e.id,t),Math.min(Sa,Ca*2**(t-1))}stop(){if(!this.#l){this.#l=!0;for(let e of this.#e.values())this.#k(e,`owner`);this.#p?.()}}#k(e,t){if(e.cancel){let n=e.cancel(t);return n&&t===`owner`&&(e.stopped=!0),n}return t===`owner`&&(e.stopped=!0),Aa(e.child),!0}killAll(){for(let e of this.#e.values())e.stopped=!0,Oa(e.child,`SIGKILL`)}async#A(){if([...this.#e.values()].some(e=>e.sessionId&&!e.stopped))try{let e=await this.#z()?.peek();e&&this.#P(Q);for(let t of e?.cancel??[])this.#j(t)}catch{}}#j(e){for(let[t,n]of this.#e)if(!(n.sessionId!==e||n.stopped))return this.#T({id:t,name:`Builder`},`canceled from your team; stopping it`,`warn`),this.#k(n,`owner`),!0;return!1}#M(e,t){let n=[],r=null,i=JSON.stringify([null,null,null]),a=!1,o=!1,s=async()=>{let r=this.#z();if(a||o||!r)return;let s={input_tokens:t.inputTokens||null,output_tokens:t.outputTokens||null,cost_micros:t.costMicros},c=JSON.stringify(Object.values(s));if(n.length||c!==i){a=!0;try{let t=n.slice(),a=await r.progress(e,{lines:t,...s});if(a.status!==`error`){i=c;let e=new Set(t);for(;n.length&&e.has(n[0]);)n.shift()}a.status===`not_found`&&(o=!0),a.canceled&&!o&&this.#j(e)}finally{a=!1}}},c=setInterval(()=>void s(),this.#o);return{add(e){e&&e!==r&&(r=e,n.push(e),n.length>5&&n.shift())},stop(){o=!0,clearInterval(c)}}}get running(){return this.#e.size}status(){let e=[...this.#e.values()],t=e.map(e=>e.tally?.costMicros).filter(e=>typeof e==`number`),n=e.map(e=>e.startedAt).filter(e=>typeof e==`number`),r=[...this.#t.entries()].filter(([e])=>e!==Q||!this.#d).map(([,e])=>e);return{running:e.length,since:n.length?Math.min(...n):null,costMicros:t.length?t.reduce((e,t)=>e+t,0):null,nextCheckAt:this.#h||this.#m||!r.length?null:Math.min(...r),checking:this.#m>0,stopping:this.#l,sessions:e.map(e=>({name:e.name??``,tool:e.tool??``,title:e.title??``,startedAt:e.startedAt??e.joinedAt??this.#a(),costMicros:e.tally?.costMicros??null,activity:e.activity??null,activityAt:e.activityAt??null,stopping:e.stopped})).sort((e,t)=>e.startedAt-t.startedAt),queued:this.#y,waitingFor:this.#y?this.#b:null,capFreesAt:this.#x,lastCheckAt:this.#_,checkFailure:[...this.#v.values()].sort((e,t)=>e.since-t.since)[0]??null,signedOut:this.#d,runsThisHour:this.config.machine?this.config.machine.maxRunsPerHour-Pa(this.config.machine,this.state.agents[Q]??{},this.#a()).left:null,today:this.#N()}}#N(){let e=new Date(this.#a()).toDateString();return this.#S.day!==e&&(this.#S={day:e,done:0,failed:0,stopped:0,costMicros:0,durationMs:0}),this.#S}#P(e){this.#_=this.#a(),this.#v.delete(e)}#F(e,t,n){let r=this.#a(),i=t.message;this.#v.set(e,{message:i,since:this.#v.get(e)?.since??r,retryAt:r+n})}async#I(e){this.#m++;try{return await e()}finally{this.#m--}}async check(e){let t=this.#C(e);if(t.disabledReason||this.#e.has(e.id))return null;let{left:n,freesAt:r}=Pa(e,t,this.#a());if(n<=0)return this.#T(e,`hit ${e.maxRunsPerHour} runs this hour; next check at ${new Date(r).toTimeString().slice(0,5)}`,`warn`),this.#t.set(e.id,r),null;let i;try{i=await this.#I(()=>this.#w(e).peek(t.etag))}catch(n){if(n instanceof q&&n.ended)return t.disabledReason=`its sign-in ended (unlinked on your team, or unused for 90 days)`,this.#T(e,`stopped: ${t.disabledReason}. Copy a new token from its page on your team and run \`${C} add <token>\`.`,`fail`),this.#E(),null;if(n instanceof M&&n.status===401){let r=n.code===`agent_removed`;return t.disabledReason=r?`its owner removed it from Bitfolk`:`token rejected (revoked, or the agent was archived)`,this.#T(e,r?`stopped: ${t.disabledReason}. Run \`${C} rm "${e.name}"\` to forget it.`:`stopped: ${t.disabledReason}. Copy a new token from its page on your team and run \`${C} add <token>\` (it keeps your options).`,`fail`),this.#E(),null}let r=this.#O(e);return this.#T(e,`peek failed (${n.message}); retrying in ${ja(r)}`,`warn`),this.#D(e,r),this.#F(e.id,n,Math.max(1e3,r)),null}return this.#n.delete(e.id),this.#P(e.id),i?(t.etag=i.etag,t.pollMs=i.next_poll_after_s*1e3,this.#E(),i.tier===`silent`||!i.has_work?(this.#D(e,i.next_poll_after_s*1e3),null):{done:this.#L(e,i)}):(this.#D(e,t.pollMs??wa),null)}#L(e,t,n){let r={child:null,done:Promise.resolve(null),stopped:!1,sessionId:n?.session.id,name:e.name,tool:n?.session.runtime??e.acp?.agent??e.runtime,title:an(n?n.session.task?.title??n.session.goal?.title??`a goal`:`woke for ${Da(t.reasons)}`),joinedAt:this.#a()},i=this.#V(e,t,r,n);return n?.session.retry?.mode===`fix`&&(i=i.then(i=>!i?.resumed||i.status!==`failed`||i.durationMs>=2e4||r.stopped||this.#l?i:(this.#T(e,`couldn't pick up the earlier conversation; starting fresh on the same branch`,`warn`),this.#V(e,t,r,n,{fresh:!0})))),r.done=(n?i.then(t=>this.#B(e,n,t)):i).finally(()=>{this.#e.delete(e.id),this.#p?.()}),this.#e.set(e.id,r),r.done}#R(e,t,n,r){let i=``,a=null,o=()=>a??=(async()=>{let a=this.#z();if(!a)return;let o=null;try{o=ga(t.dir,e)}catch{}let s={branch:t.branch??null,base_sha:n,head_sha:o?.head??null,checkpoint_sha:o?.checkpoint??null,tool_session_id:r.sessionId??null},c=JSON.stringify(s);c!==i&&await a.checkpoint(e,s)&&(i=c)})().finally(()=>{a=null}),s=setInterval(()=>void o(),this.#s);return o(),{async final(){clearInterval(s),await a,await o()},stop:()=>clearInterval(s)}}#z(){let e=this.config.machine;return!e||this.#d?null:this.#u??=new mt(e.api,()=>ar(e,{now:this.#a}))}async checkMachine(){let e=this.config.machine,t=this.#z();if(!e||!t)return[];let n=this.state.agents[Q]??={},r={id:Q,name:e.name},i;try{i=await this.#I(()=>t.peek())}catch(e){if(e instanceof q&&e.ended||e instanceof M&&e.status===401)return this.#d=`this machine was unlinked, or its sign-in ended`,this.#T(r,`stopped: ${this.#d}. Run \`${C} login\` to link it again.`,`fail`),[];let t=this.#O(r);return this.#T(r,`check-in failed (${e.message}); retrying in ${ja(t)}`,`warn`),this.#t.set(Q,this.#a()+t),this.#F(Q,e,t),[]}this.#n.delete(r.id),this.#P(Q);for(let e of i.cancel??[])this.#j(e);let a=Math.max(1e3,i.next_poll_after_s*1e3);this.#t.set(Q,this.#a()+a);let o=()=>{[...this.#e.values()].some(e=>e.sessionId&&!e.stopped)&&this.#t.set(Q,Math.min(this.#t.get(Q)??1/0,this.#a()+Ta))},s=[],c=i.queued;for(this.#b=null,this.#x=null;c>0&&!this.#l;c--){if(this.#e.size>=this.config.maxConcurrent){this.#b=`slot`;break}let{left:i,freesAt:a}=Pa(e,n,this.#a());if(i<=0){this.#b=`cap`,this.#x=a,this.#f!==a&&(this.#f=a,this.#T(r,`hit ${e.maxRunsPerHour} sessions this hour; the rest wait until ${new Date(a).toTimeString().slice(0,5)}`,`warn`)),this.#t.set(Q,a);break}let o;try{o=await this.#I(()=>t.claim({runtimes:e.runtimes,timeout_min:e.timeoutMin}))}catch(e){this.#T(r,`couldn't take a session (${e.message})`,`warn`);break}if(!o){c=0;break}this.#y=Math.max(0,this.#y-1),n.runStarts=[...(n.runStarts??[]).filter(e=>e>this.#a()-ya),this.#a()],this.#E();let l;try{l=Ia(e,o)}catch(e){this.#T(r,`can't run a session: ${e.message}`,`fail`),await t.finish(o.session.id,{status:`failed`,summary:null,error:e.message}).catch(()=>{});continue}let u=an(o.session.task?.title??o.session.goal?.title??`a goal`);this.#T(l,`joined for a session: ${V.bold(u)} ${B(`·`)} ${V.tool(sn(J(o.session.runtime)))}`,`start`,si(o.session.runtime));let d=await new pt(l.api,l.token).peek().catch(()=>null),f={has_work:!0,tier:`full`,reasons:[`session_requested`,...(d?.reasons??[]).filter(e=>e!==`setup_actions`)],briefing_goal_id:o.session.goal?.id??null,etag:d?.etag??``,next_poll_after_s:60,rules:d?.rules};s.push({done:this.#L(l,f,o)})}return this.#y=this.#b?Math.max(0,c):0,o(),s}async#B(e,t,n){let r=n?.status===`succeeded`?`succeeded`:n?.status===`interrupted`?`canceled`:`failed`,i=null;if(n){let t=n.work?.startSha??null,r={commits:[],commit_count:0,files_changed:0,insertions:0,deletions:0};if(n.work?.branch&&t)try{e.repo&&ia(n.work.dir,e.repo),r=pa(n.work.dir,t,n.work.branch)}catch{}i={base:t?.slice(0,12)??null,...r,duration_ms:n.durationMs}}try{await this.#z()?.finish(t.session.id,{status:r,summary:n?.tally.summary??null,error:n?n.status===`succeeded`?null:n.tally.error??n.status:`the session couldn't start on this machine`,branch:n?.work?.branch??null,result:i,input_tokens:n?n.tally.inputTokens:null,output_tokens:n?n.tally.outputTokens:null,cost_micros:n?.tally.costMicros??null,model:((e.runtime===`acp`?n?.tally.model??e.model:e.model??n?.tally.model)??null)?.slice(0,100)??null}),i?.commit_count&&this.#T(e,`left ${V.bold(`${i.commit_count} commit${i.commit_count===1?``:`s`}`)} on ${V.tool(n.work.branch)} ${B(`(${i.files_changed} files)`)}`,`ok`)}catch(t){this.#T(e,`couldn't report the session's end (${t.message}); Bitfolk times it out`,`warn`)}return this.#T(e,`left the team`,`idle`),da(e),e.repo&&va(e.repo),delete this.state.agents[e.id],this.#E(),n}async#V(e,t,r,a,o={}){let c=this.#C(e),l=this.#w(e),u=we[e.runtime],d=e.runtime===`acp`?e.acp:void 0;if(e.runtime===`acp`&&!d)throw Error(`${e.name} has runtime acp but no ACP command`);let f=this.#a(),m;try{m=ca(e)}catch(t){return c.etag=void 0,this.#T(e,`can't prepare its workspace: ${t.message}`,`fail`),this.#D(e,this.#O(e)),null}let h=m.branch?fa(m.dir):null,g=a?.session.retry??null,_=!!(g?.mode===`fix`&&m.created&&m.branch&&g.checkpoint_sha&&_a(m.dir,g.checkpoint_sha));_&&this.#T(e,`put back the earlier session's uncommitted work on ${V.tool(String(m.branch))}`,`ok`);let v=null;try{v=await l.runStart({client_run_id:fe(),host:se(),runtime:d?d.agent:e.runtime,reasons:t.reasons,tier:t.tier})}catch(n){if(n instanceof M&&n.status===409)return this.#T(e,`is paused by its owner; not starting`,`idle`),this.#D(e,t.next_poll_after_s*1e3||(ba?wa:6e5)),null;this.#T(e,`couldn't record the run start (${n.message}); running anyway`,`warn`)}v||await l.status(`working`).catch(()=>{});let b=o.fresh?null:g?.mode===`fix`?u.resumes!==!1&&g.tool_session_id?g.tool_session_id:null:u.resumes!==!1&&!m.created&&c.sessionId&&c.sessionAt&&f-c.sessionAt<432e5?c.sessionId:null,x=!!m.branch&&!!u.runnerCommits?.(e),ee=ra(t,{agentName:e.name,api:e.api,branch:m.branch,runnerCommits:x,resumed:!!b,session:a?{goal:a.session.goal?.title??null,task:a.session.task?.title??null,note:a.session.note,goalDone:a.session.goal?.done_definition??null,taskSpec:a.session.task?.spec??null,asks:a.session.asks??[],requestedBy:a.session.requested_by??`owner`,retry:g?{mode:g.mode,branch:g.branch,summary:g.summary,error:g.error,status:g.status,restored:_}:void 0}:void 0}),te=u.launch(e,ee,b);c.runStarts=[...(c.runStarts??[]).filter(e=>e>f-ya),f],this.#E(),this.#T(e,`woke ${B(`for ${Da(t.reasons)}`)} → ${V.tool(sn(d?`${J(d.agent)} over ACP`:e.runtime))}${b?B(`, resuming`):``}`,`start`);let ne=s(N(),`logs`,e.slug);y(ne,{recursive:!0,mode:448});let ie=s(ne,`${new Date(f).toISOString().replace(/[:.]/g,`-`)}.jsonl`),ae=new Set([e.token]),oe=e=>[...ae].reduce((e,t)=>e.split(t).join(`[token]`),e),ce=(e,t)=>p(ie,JSON.stringify({t:this.#a(),stream:e,line:oe(t)})+`
|
|
76
|
+
`,{mode:384}),ue=ta(),de=or(e),pe=e.oauth?setInterval(()=>{e.oauth.expiresAt-this.#a()>6e5||ar(e,{now:this.#a}).then(()=>{ae.add(e.token),or(e)}).catch(t=>this.#T(e,`couldn't renew its sign-in mid-run: ${t.message}`,`warn`))},6e4):null,S=ge();r.tally=S,r.startedAt=this.#a();let C={...La(),PATH:[ue,...Ra(),...lr()].join(i),...d?{NO_BROWSER:`1`}:{BITFOLK_TOKEN:e.token},BITFOLK_TOKEN_FILE:de,BITFOLK_API:e.api.replace(/\/+$/,``),BITFOLK_AGENT:e.name,...v?{BITFOLK_RUN_ID:v.id}:{}};d&&delete C.BITFOLK_TOKEN;for(let[e,t]of Object.entries(C))t&&t.length>=12&&/KEY|TOKEN|SECRET|PASSWORD|PASSWD|CREDENTIAL|AUTH/i.test(e)&&e!==`BITFOLK_TOKEN_FILE`&&ae.add(t);let me=a?this.#M(a.session.id,S):null,he=a&&m.branch?this.#R(a.session.id,m,h,S):null,w=null,_e=t=>{let n=t&&an(oe(t)).trim();me?.add(n),n&&n!==w&&(w=n,r.activity=n,r.activityAt=this.#a(),this.#T(e,n,`progress`))},T=null,E=null,D=!1,ve,ye=null;try{ve=await new Promise(t=>{let i=n(te.bin,te.args,{cwd:m.dir,env:C,stdio:[`pipe`,`pipe`,`pipe`],detached:!0});if(r.child=i,i.stdin.on(`error`,()=>{}),d){let t=new ut({stdin:i.stdin,stdout:i.stdout,agent:{...e,acp:d},label:J(d.agent),cwd:m.dir,home:N(),packet:ee,tally:S,clientVersion:j,log:ce,activity:_e,kill:()=>{ka.has(i)||Aa(i)},cancelGraceMs:this.#c});r.cancel=e=>t.cancel(e),ye=t.run()}else i.stdin.end(te.stdin),le({input:i.stdout}).on(`line`,e=>{ce(`out`,e),u.parse(e,S),u.activity&&_e(u.activity(e,m.dir))});(this.#l||r.stopped)&&this.#k(r,`owner`),le({input:i.stderr}).on(`line`,e=>{ce(`err`,e),e.trim()&&(E=oe(e.trim()).slice(0,300))});let a=setTimeout(()=>{D=!0,this.#k(r,`timeout`)||(D=!1)},e.timeoutMin*6e4);i.on(`error`,e=>{T=e.code===`ENOENT`?`${te.bin} isn't installed or isn't on PATH`:e.message}),i.on(`close`,e=>{ka.add(i),clearTimeout(a),t({code:e})})})}finally{me?.stop(),he?.stop(),pe&&clearInterval(pe)}let be=ye?await ye:null;r.cancel=void 0,u.afterExit?.(te,S),re(de,{force:!0});let O=this.#a()-f,k,A;if(be?(k=r.stopped?`interrupted`:S.overBudget?`over_budget`:T||D||!be.ok?`failed`:`succeeded`,A=T??(k===`over_budget`?S.error:D&&k===`failed`?`stopped after ${e.timeoutMin} minutes`:k===`failed`?be.exited?E??`${be.error??`the tool exited`}${ve.code===null?``:` (exit ${ve.code})`}`:be.error??E??`the turn failed`:null),k===`failed`&&(S.error=A)):(k=r.stopped?`interrupted`:S.overBudget?`over_budget`:T||D||ve.code!==0||S.isError?`failed`:`succeeded`,A=T??(D?`stopped after ${e.timeoutMin} minutes`:k===`failed`?S.error??E??`exit ${ve.code}`:null)),k===`failed`&&!S.error&&(S.error=A),x&&!T){let t=`${e.name}: ${S.summary??`work from a Bitfolk run`}`,n=`Bitfolk run${v?` ${v.id}`:``}, ${k}.`;try{e.repo&&m.branch&&ia(m.dir,e.repo);let r=la(m.dir,`${t.length>72?t.slice(0,71)+`…`:t}\n\n${n}`);r&&this.#T(e,`committed its changes as ${V.bold(r)} on ${V.tool(String(m.branch))}`,`ok`)}catch(t){this.#T(e,`couldn't commit its changes: ${t.message.split(`
|
|
77
|
+
`)[0]}`,`warn`)}}await he?.final().catch(()=>{}),k===`failed`&&b&&O<2e4?(c.sessionId=void 0,c.etag=void 0):S.sessionId&&(c.sessionId=S.sessionId,c.sessionAt=this.#a()),(k===`failed`||k===`interrupted`)&&(c.etag=void 0),this.#E();let xe={status:k,exit_code:be?be.ok&&k===`succeeded`?0:null:ve.code,session_id:S.sessionId,input_tokens:S.inputTokens,output_tokens:S.outputTokens,cost_micros:S.costMicros,summary:S.summary,error:A};v?await l.runFinish(v.id,xe).catch(async()=>{await new Promise(e=>setTimeout(e,2e3)),await l.runFinish(v.id,xe).catch(t=>this.#T(e,`couldn't record the run end: ${t.message}`,`warn`))}):await l.status(`idle`).catch(()=>{});let Se=this.#N();k===`succeeded`?Se.done++:k===`interrupted`?Se.stopped++:Se.failed++,Se.costMicros+=S.costMicros??0,Se.durationMs+=O;let Ce=Ma(S),Te=k===`succeeded`?V.ok(V.bold(k)):k===`failed`?V.err(V.bold(k)):V.warn(V.bold(k));return this.#T(e,[`${Te} in ${ja(O)}`,...Ce?Ce.split(`, `).map(e=>e.startsWith(`$`)?V.money(e):e):[]].join(` ${B(`·`)} `)+`${A?` ${V.err(`(${an(A)})`)}`:``}${S.summary?` ${B(`—`)} ${an(S.summary)}`:``}`,k===`succeeded`?`ok`:k===`failed`?`fail`:`warn`),k===`failed`?this.#D(e,this.#O(e)):(this.#n.delete(e.id),this.#D(e,xa)),{agent:e.name,status:k,tally:S,durationMs:O,work:{dir:m.dir,branch:m.branch,startSha:h},resumed:!!b}}async run(e={}){this.#h=!!e.once;let t=this.config.agents.filter(e=>!this.#C(e).disabledReason);for(let e of this.config.agents){let t=this.#C(e).disabledReason;t&&this.#T(e,`skipped: ${t}`,`idle`)}let n=this.config.machine;if(t.length===0&&!n)return this.#T(null,`nothing to run. Link this computer with \`${C} login\`.`,`warn`),[];if(e.once){let e=[];if(n){let t=await this.checkMachine();t.length===0&&!this.#d&&this.#T({name:n.name},`no sessions waiting`,`idle`),e.push(...t.map(e=>e.done))}for(let n of t){for(;this.#e.size>=this.config.maxConcurrent;)await Promise.race([...this.#e.values()].map(e=>e.done));let t=await this.check(n);t?e.push(t.done):this.#e.has(n.id)||this.#T(n,`nothing to do`,`idle`)}let r=n?setInterval(()=>void this.#A(),Ta):null;try{return(await Promise.all(e)).filter(e=>e!==null)}finally{r&&clearInterval(r)}}let r=[],i=[n?`${n.name} for sessions`:null,t.length?`${t.length} agent${t.length===1?``:`s`}`:null].filter(Boolean).join(` and `);for(this.#T(null,`watching ${V.bold(i)} ${B(`(up to ${this.config.maxConcurrent} at once).${this.#g?``:` Ctrl-C to stop.`}`)}`,`start`);!this.#l;){let e=this.#a();if(n&&!this.#d&&(this.#t.get(Q)??0)<=e)for(let e of await this.checkMachine())e.done.then(e=>e&&r.push(e));for(let n of t){if(this.#l||this.#e.size>=this.config.maxConcurrent)break;this.#e.has(n.id)||this.#C(n).disabledReason||(this.#t.get(n.id)??0)>e||(await this.check(n))?.done.then(e=>e&&r.push(e))}let i=Math.min(...t.map(t=>this.#t.get(t.id)??e),n&&!this.#d?this.#t.get(Q)??e:1/0),a=Math.max(1e3,Math.min(6e4,i-this.#a()));await new Promise(e=>{let t=setTimeout(e,a);this.#p=()=>{clearTimeout(t),e()}}),this.#p=null}return await Promise.all([...this.#e.values()].map(e=>e.done)),r}};const Ba=e=>Atomics.wait(new Int32Array(new SharedArrayBuffer(4)),0,0,e);function Va(e){for(let t=0;t<20;t++){let t;try{t=x(e,`utf8`).trim()}catch{return null}if(t)return Number(t)||0;Ba(25)}return 0}function Ha(e){if(!e||e===process.pid)return!1;try{return process.kill(e,0),!0}catch(e){return e.code===`EPERM`}}function Ua(){let e=Va(s(N(),`runner.pid`));return e&&Ha(e)?e:null}function Wa(){let e=s(N(),`runner.pid`);y(N(),{recursive:!0,mode:448});let t=String(process.pid),n=()=>{try{x(e,`utf8`).trim()===t&&re(e,{force:!0})}catch{}};for(let r=0;r<3;r++){try{return ae(e,t,{mode:384,flag:`wx`}),n}catch(e){if(e.code!==`EEXIST`)throw e}let r=Va(e);if(r===null)continue;if(Ha(r))throw Error(`a runner is already going (pid ${r}). Stop it first, or see \`${C} status\`.`);let i=`${e}.${process.pid}.tmp`;if(ae(i,t,{mode:384}),ne(i,e),Ba(25),Va(e)===process.pid)return n}throw Error(`another runner is starting at the same moment. Try again, or see \`${C} status\`.`)}function Ga(e){let t;try{t=JSON.parse(e)}catch{return null}if(t.msg===`started tunnel`)return{kind:`started`};let n=typeof t.err==`string`&&t.err!==`<nil>`?t.err:null;return t.lvl===`crit`||t.lvl===`eror`&&n?{kind:`error`,message:String(n??t.msg??`ngrok failed`).replace(/\s+/g,` `).replace(/\bERR_NGROK_\d+\b.*$/,``).trim().slice(0,240)||`ngrok failed`}:null}function Ka(e,t=`127.0.0.1`){return new Promise(n=>{let r=S({port:e,host:t}),i=e=>{r.destroy(),n(e)};r.setTimeout(1500,()=>i(!1)),r.once(`connect`,()=>i(!0)),r.once(`error`,()=>i(!1))})}const qa={stopped_in_town:`Someone stopped it from the team's Settings.`,replaced:`It was shared again from this computer.`,machine_unlinked:`This computer was unlinked from the team.`,went_quiet:`This computer stopped checking in for a few minutes.`};async function Ja(e,t,r){let i=dr(`ngrok`);if(!i)throw Error(`sharing uses the ngrok program. Install it (brew install ngrok, or https://ngrok.com/download) and run this again. You don't need an ngrok account: your team provides the tunnel.`);if(!await Ka(t))throw Error(`nothing is running on 127.0.0.1:${t}. Start your app first, then share it.`);let a=new mt(e.api,()=>ar(e)),o=Bn(`Opening a link for 127.0.0.1:${t}`,{quiet:!0}),c;try{c=await a.openApp({name:r.name??``,port:t,access:r.public?`public`:`town`})}finally{o.stop()}let l=s(N(),`share`);y(l,{recursive:!0,mode:448});let u=s(l,`${c.app_id}.yml`);ae(u,`version: "3"
|
|
78
|
+
agent:
|
|
79
|
+
web_addr: false
|
|
80
|
+
update_check: false
|
|
81
|
+
`,{mode:384});let d=null,f=null,p=!1,m=null,h=async(e,t)=>{p||(p=!0,m?.stop(),f&&clearInterval(f),d?.kill(`SIGTERM`),re(u,{force:!0}),await a.stopApp(c.app_id).catch(()=>null),console.log(t),process.exit(e))};d=n(i,[`http`,String(t),`--url`,c.internal_url,`--config`,u,`--log`,`stdout`,`--log-format`,`json`],{env:{...process.env,NGROK_AUTHTOKEN:c.authtoken,NGROK_API_KEY:``,NGROK_CONFIG:``},stdio:[`ignore`,`pipe`,`pipe`]}),process.on(`SIGINT`,()=>h(0,`\n${B(H.idle)} Stopped sharing ${z(c.name)}. The link no longer works.`)),process.on(`SIGTERM`,()=>h(0,`${B(H.idle)} Stopped sharing ${z(c.name)}.`)),process.on(`SIGHUP`,()=>h(0,`${B(H.idle)} Stopped sharing ${z(c.name)}.`)),m=Bn(`Connecting the tunnel`,{quiet:!0,hint:`Ctrl-C to cancel`});let g=await new Promise(e=>{let t=``,n=n=>{t+=n.toString();let r=t.split(`
|
|
82
|
+
`);t=r.pop()??``;for(let t of r){let n=Ga(t);n?.kind===`started`&&e(null),n?.kind===`error`&&e(n.message)}};d.stdout.on(`data`,n),d.stderr.on(`data`,n),d.once(`exit`,()=>e(`ngrok stopped before the tunnel opened`)),setTimeout(()=>e(`ngrok took too long to open the tunnel`),3e4)});if(m.stop(),g)return h(1,Cn(`couldn't share ${c.name}: ${g}`,`bitfolk: `));d.once(`exit`,()=>h(1,Cn(`ngrok stopped, so ${c.name} is no longer shared.`)));let _=c.access===`town`?`${c.town} only, Google sign-in (${c.members} email${c.members===1?``:`s`} let in)`:V.warn(`anyone with the link, no sign-in`);console.log([xn(`${z(c.name)} is shared`),...vn([bn(c.url),``,..._n([[`who`,_],[`from`,`127.0.0.1:${t}`],[`listed`,`your team, Settings, Shared apps`]])]),B(` Keep this running to stay shared. Ctrl-C stops it.`)].join(`
|
|
83
|
+
`));let v=0;f=setInterval(async()=>{try{let e=await a.beatApp(c.app_id);v=0,e.status===`stopped`&&await h(0,`Stopped sharing ${c.name}. ${qa[e.stop_reason??``]??``}`.trim())}catch{++v===2&&console.log(Sn(`Can't reach your team right now; the link keeps working for a few minutes while this retries.`))}},Math.max(15,c.beat_s)*1e3)}const Ya={repo:{type:`string`},base:{type:`string`},runtime:{type:`string`},command:{type:`string`},acp:{type:`string`},model:{type:`string`},permission:{type:`string`},"max-usd":{type:`string`},"max-runs":{type:`string`},timeout:{type:`string`},api:{type:`string`},email:{type:`string`},name:{type:`string`},public:{type:`boolean`},once:{type:`boolean`},"let-sleep":{type:`boolean`},"no-browser":{type:`boolean`},"no-color":{type:`boolean`},agent:{type:`boolean`},tool:{type:`boolean`},force:{type:`boolean`},help:{type:`boolean`,short:`h`},version:{type:`boolean`,short:`v`}};var $=class extends Error{};function Xa(e,t,n,r){if(e===void 0)return;let i=Number(e);if(!Number.isFinite(i)||i<n||i>r)throw new $(`--${t} must be a number from ${n} to ${r}`);return i}function Za(e){if(!e)return!1;try{return t(`sh`,[`-c`,`command -v "$1"`,`sh`,e],{stdio:`ignore`}),!0}catch{return!1}}function Qa(e,t){let n={...e};if(t.runtime!==void 0){if(!ht.includes(t.runtime))throw new $(`--runtime must be one of ${ht.join(`, `)}`);n.runtime=t.runtime}if(t.command!==void 0&&(n.command=t.command),n.runtime===`command`&&!n.command)throw new $(`runtime command needs --command "..."`);if(t.permission!==void 0){if(!gt.includes(t.permission))throw new $(`--permission must be one of ${gt.join(`, `)}`);n.permission=t.permission}if(t.repo!==void 0){let e=aa(l(t.repo));if(!e)throw new $(`${t.repo} isn't inside a git repository`);n.repo=e}return t.base!==void 0&&(n.base=t.base),t.model!==void 0&&(n.model=t.model||void 0),n.maxUsdPerRun=Xa(t[`max-usd`],`max-usd`,.01,100)??n.maxUsdPerRun,n.maxRunsPerHour=Xa(t[`max-runs`],`max-runs`,1,60)??n.maxRunsPerHour,n.timeoutMin=Xa(t.timeout,`timeout`,1,600)??n.timeoutMin,n}function $a(e){return Si(e,e.repo?`${e.repo} ${B(`(branch ${oa(e)})`)}`:B(`no repo`),Ct().agents[e.id]?.disabledReason)}const eo=e=>Ci([$a(e)])[0].join(`
|
|
84
|
+
`),to=e=>(e.api??process.env.BITFOLK_API??`https://bitfolk.ai`).replace(/\/+$/,``);async function no(e,t){if(e??=process.env.BITFOLK_TOKEN,!e||!/^bfa_[A-Za-z0-9]{20,}$/.test(e))throw new $(`give the agent's token from its page on your team: ${C} add bfa_... (to link this computer instead, run ${C} login)`);let n=to(t),r=await Vn(`Asking your team about this agent`,()=>new pt(n,e).setup());await ho(n,e,r,t,void 0)}const ro=(e=[])=>[...hr().filter(e=>e.supported).map(e=>e.id),...e.map(e=>gr(e.name))];function io(){let e=hr().filter(e=>!e.supported);e.length!==0&&(console.log(`\n ${z(`Also found`)} ${B(`(not built in yet; add one with ${C} add, then check the command works headless):`)}`),console.log(hn(e.map(e=>[e.label,K(`${C} add ${e.id.replace(/_/g,`-`)} --command '${e.suggest}'`)]),{indent:4}).join(`
|
|
85
|
+
`)))}async function ao(e){let t=to(e),n=P().machine,{accessToken:r,link:i,me:a}=await rr(t,{browser:!e[`no-browser`],detected:ro(n?.customTools)});n&&n.id!==a.machine.id&&await sr(n);let o=oo({..._t,...n??{},id:a.machine.id,name:a.machine.name,api:t,token:r,oauth:i,runtimes:a.machine.runtimes,customTools:n?.customTools,workspace:a.workspace?.name},e),s=P();s.machine=o,F(s),console.log(``),await oi(Ei(o,a.workspace?.name??`your team`)),console.log(``);for(let e of o.runtimes){let t=cr.find(t=>t.id===e);t&&!fr(t)&&console.log(` ${Sn(`warning: ${t.label} isn't installed here yet; install it and sign in before sessions start.`)}`)}io(),o.repo||console.log(` ${B(`no repo yet: builders work in plain folders. Give them one with:`)} ${K(`${C} set --repo <path>`)}`),console.log(`\nKeep it running with: ${z(K(`${C} up`))}`),me&&console.log(B(`To keep the command around, install it once: ${K(`npm i -g bitfolk`)} (then use bitfolk up).`))}function oo(e,t){let n=Qa({...e,slug:`machine`,runtime:`claude_code`},{...t,runtime:void 0,command:void 0});return{...e,repo:n.repo,base:n.base,model:n.model,permission:n.permission,maxUsdPerRun:n.maxUsdPerRun,maxRunsPerHour:n.maxRunsPerHour,timeoutMin:n.timeoutMin}}const so=e=>Ci([xi(e)])[0].join(`
|
|
86
|
+
`);function co(){let e=hr({versions:!0}),t=P().machine;if(e.length===0&&!t?.customTools?.length){console.log(Cn(`No coding tools found. Install Claude Code, Codex, OpenCode or Hermes, then run ${C} login.`));return}console.log(z(V.accent(`Coding tools on this computer`)));let n=e=>`${V.ok(H.dot)} ${V.ok(e)}`,r=e=>`${B(H.idle)} ${B(e)}`,i=[],a=Kt()<60,o=e=>a||!si(e)?``:si(e)+` `;for(let s of e){let e=s.acp?` via ACP`:``,c=s.supported?t?t.runtimes.includes(s.id)?n(`on${e}`):`${r(`off${e}`)} ${B(`(`)}${K(`${C} add ${s.id.replace(/_/g,`-`)}`)}${B(`)`)}`:n(`supported${e}`):`${V.warn(H.skip)} ${V.warn(`not built in`)} ${B(`(${C} add ${s.id.replace(/_/g,`-`)} --command ...)`)}`,l=B(W(lo(s.version,s.label),16));a?i.push([V.tool(z(s.label))],[` ${l}${s.version?B(` · `):``}${c}`],[` ${B(s.path)}`]):(i.push([o(s.id)+V.tool(z(s.label)),l,c]),i.push([``,B(s.path)]))}for(let e of t?.customTools??[]){let s=e.protocol===`acp`?`custom, via ACP`:`custom`;i.push([(a?``:o(gr(e.name)))+V.tool(z(e.name)),B(s),`${t.runtimes.includes(gr(e.name))?n(`on`):r(`off`)}${B(`:`)} ${e.command}`])}console.log(hn(i,{indent:2,gap:2}).join(`
|
|
87
|
+
`)),(e.some(e=>e.supported&&e.acp)||t?.customTools?.some(e=>e.protocol===`acp`))&&console.log(B(`
|
|
88
|
+
Via ACP: sign in to each tool in a terminal first. Safe mode is enforced through the tool's permission requests
|
|
89
|
+
(its own settings may allow more), and --max-usd stops a session once its reported cost passes the cap.`)),t||console.log(`
|
|
90
|
+
`+Tn(`Link this computer with ${K(`${C} login`)} to let your team start them.`,0))}function lo(e,t){let n=(e??``).replace(/\(.*$/,``).replace(new RegExp(t.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`),`ig`),``).trim().split(/\s+/),r=n.findIndex(e=>/\d/.test(e));return(r>=0?n.slice(r):n).join(` `).trim()}const uo=(e,t)=>Vn(`Telling your team`,()=>new mt(e.api,()=>ar(e)).setTools(t));async function fo(e,t,n){let r=P().machine;if(!r)throw new $(`link this computer first: ${C} login`);if(!t||!vr.test(t))throw new $(`give the tool a short name: lowercase letters, numbers and dashes. See ${C} tools`);if(n.command!==void 0&&n.acp!==void 0)throw new $(`give --command or --acp, not both`);let i=_r(e,t,r,n);if(i){e===`add`&&!fr(i)&&console.log(Sn(`warning: ${i.label} isn't installed here yet.`));let t=e===`add`?[...new Set([...r.runtimes,i.id])]:r.runtimes.filter(e=>e!==i.id);if(t.length===0)throw new $(`that's the last tool on this computer; keep at least one, or run ${C} logout`);let n=await uo(r,t),a=P();return a.machine={...a.machine,runtimes:n.runtimes},F(a),console.log(xn(e===`add`?`Turned on ${V.tool(i.label)}. Your team can start it now: pick it on Run.`:`Turned off ${V.tool(i.label)}.`)),console.log(` ${so(a.machine)}`)}let a=gr(t),o=(r.customTools??[]).filter(e=>e.name!==t),s=r.runtimes.filter(e=>e!==a);if(e===`rm`&&!(r.customTools??[]).some(e=>e.name===t)&&!r.runtimes.includes(a))throw new $(`no tool or agent called ${t} here. See ${C} status`);if(e===`add`){let e=po(t,n),r=e.protocol===`acp`?Pe(e.command).bin:e.command.split(/\s+/)[0]??``;dr(r)||console.log(Sn(`warning: ${r} isn't installed here yet.`)),o=[...o,e],s=[...s,a]}let c=await uo(r,s),l=P();l.machine={...l.machine,customTools:o,runtimes:c.runtimes},F(l),console.log(xn(e===`add`?`Added ${V.tool(t)}. Your team can start it now: pick it on Run.`:`Removed ${V.tool(t)}.`)),console.log(` ${so(l.machine)}`)}function po(e,t){if(t.acp!==void 0){let n=t.acp.trim();if(!n)throw new $(`${C} add ${e} --acp "<cmd>" (a command that speaks ACP on stdio)`);try{Pe(n)}catch(e){throw new $(`--acp: ${e.message}`)}return{name:e,command:n,protocol:`acp`}}let n=t.command?.trim();if(!n)throw new $(cr.some(t=>t.id===e.replace(/-/g,`_`))?`${e} isn't built in yet; give the command to run: ${C} add ${e} --command "<cmd>" (it gets the work packet on stdin)`:`${e} isn't a coding tool bitfolk knows; to add your own: ${C} add ${e} --command "<cmd>" (see ${C} tools)`);return{name:e,command:n}}async function mo(){let e=P();if(!e.machine)return console.log(`${B(H.idle)} This computer isn't linked.`);let t=e.machine,n=await Vn(`Unlinking from your team`,()=>sr(t)),r=e.machine.name;delete e.machine,F(e),console.log(n?xn(`Unlinked ${z(r)} from your team.`):Sn(`Forgot ${r} here, but couldn't reach Bitfolk: press Unlink in Settings, Machines.`))}async function ho(e,t,n,r,i){let a=P(),o=a.agents.find(e=>e.id===n.agent.id),s=r.runtime??o?.runtime??Te(n.agent.runtime);if(!s)throw new $(`${n.agent.name} is a ${n.agent.runtime} agent, which this runner can't start by itself. Add --runtime claude_code, --runtime codex, or --runtime command --command "..."`);o?.oauth&&o.oauth.refreshToken!==i?.refreshToken&&await sr(o);let c=o?{...o,token:t,oauth:i,api:e,name:n.agent.name}:{id:n.agent.id,name:n.agent.name,slug:Tt(n.agent.name,a.agents.map(e=>e.slug)),runtime:s,api:e,token:t,oauth:i,..._t};c.oauth||delete c.oauth;let l=Qa(c,{...r,runtime:s}),u=we[l.runtime].bin(l);a.agents=[...a.agents.filter(e=>e.id!==l.id),l],F(a);let d=Ct();d.agents[l.id]?.disabledReason&&(delete d.agents[l.id].disabledReason,wt(d)),console.log(xn(`${o?`Updated`:`Added`} ${z(l.name)} ${B(`(${n.workspace?.name??`team`}, owner ${n.owner?.name??`?`})`)}`)),console.log(_n([[`goals`,n.goals.map(e=>e.title).join(`; `)||B(`none yet`)]],2).join(`
|
|
91
|
+
`)),console.log(` ${eo(l)}`),i&&console.log(B(` signed in through your browser; sign-in renews by itself`)),l.repo||console.log(` ${B(`no repo yet: it works in a plain folder. Point it at one with:`)} ${K(`${C} set ${l.slug} --repo <path>`)}`),Za(u)||console.log(` ${Sn(`warning: \`${u}\` isn't on PATH yet; install it and sign in before \`${C} up\`.`)}`),console.log(`\nStart it with: ${z(K(`${C} up`))}`)}function go(e,t){let n=P();if(!e){if(!n.machine)throw new $(`this computer isn't linked yet: run ${C} login`);if(!Object.keys(t).filter(e=>![`no-color`,`help`,`version`,`agent`,`tool`,`force`].includes(e)).length)throw new $(`what to change? ${C} set --repo <path>, or ${C} set --max-usd 2. See ${C} help set`);return n.machine=oo(n.machine,t),F(n),console.log(so(n.machine))}let r=Et(n,e);if(!r)throw new $(`no agent called ${e} on this machine`);let i=Qa(r,t);n.agents=n.agents.map(e=>e.id===r.id?i:e),F(n),console.log(eo(i))}async function _o(e,t){if(!e)throw new $(`which agent? ${C} rm <agent>`);let n=P(),r=Et(n,e);if(!r)throw new $(`no agent called ${e} on this machine`);let i=ua(r);if(i?.changed&&!t.force)throw new $(`${r.name} has ${i.changed} uncommitted change${i.changed===1?``:`s`} in ${i.dir}. Commit or copy ${i.changed===1?`it`:`them`} first, or run ${C} rm "${r.name}" --agent --force to remove it anyway`);da(r);let a=await Vn(`Removing ${r.name}`,()=>sr(r));n.agents=n.agents.filter(e=>e.id!==r.id),F(n);let o=Ct();delete o.agents[r.id],wt(o);let s=r.repo&&sa(r.repo,oa(r));console.log(xn(`Removed ${z(r.name)} from this machine.${s?B(` Its branch ${oa(r)} is still in ${r.repo}.`):``}`)),console.log(r.oauth?a?B(` This machine is unlinked from it on your team too.`):` ${Sn(`Couldn't reach Bitfolk to unlink it; press Unlink on its page on your team.`)}`:B(` Its token still works; revoke it on your team if you're done with this agent.`))}function vo(e,t,n){if(!e)return[[`login`,`link this computer to your team`],[`tools`,`see the coding tools found here`],[`help`,`all commands`]];let r=[];return t||r.push([`up`,`take sessions your team starts here`]),n[0]&&r.push([`add ${n[0]}`,`turn on another tool`]),e.repo||r.push([`set --repo <path>`,`give sessions a git repo`]),r.push([`check`,`check sign-in and tools`]),r.push([`help`,`all commands`]),r.slice(0,4)}async function yo(){let e=P(),t=e.machine,n=Ua(),r=e=>{console.log(``),console.log(hn(e.map(([e,t])=>[di(e),B(t)]),{indent:2,gap:2}).join(`
|
|
92
|
+
`))};if(!t&&e.agents.length===0){let e=ri({version:j,tagline:`Coding sessions for your team`,url:`bitfolk.ai`});return e.length&&console.log(e.join(`
|
|
93
|
+
`)+`
|
|
94
|
+
`),console.log(Tn(`${B(H.idle)} Not linked yet. Run ${K(`${C} login`)} to link this computer to your team, then ${K(`${C} up`)}.`)),r(vo(void 0,!1,[]))}let i=t?hr().filter(e=>e.supported&&!t.runtimes.includes(e.id)).map(e=>e.id.replace(/_/g,`-`)):[],a=[];if(t){let e;try{let r=await Vn(`Asking your team`,()=>Promise.race([new mt(t.api,()=>ar(t)).me(),new Promise((e,t)=>setTimeout(()=>t(Error(`no answer`)),8e3).unref())]));Object.assign(t,Dt(t,r)),e=r.queued?V.accent(`${r.queued} waiting`)+(n?``:B(` · run ${C} up to take them`)):B(`none waiting`)}catch(t){e=t instanceof q&&t.ended?V.err(`sign-in ended; run ${C} login`):t instanceof M&&t.status===401?V.err(`unlinked; run ${C} login`):V.warn(`couldn't reach your team (${C} check)`)}console.log(Tn(`${z(V.accent(t.name))} ${B(`on`)} ${z(t.workspace??`your team`)}`)),a.push([`tools`,vi(t.runtimes)+(i.length?B(` ${sn(`off: ${i.join(`, `)}`)}`):``)]),a.push([`sessions`,e]),a.push([`up`,n?`${V.ok(H.dot)} ${V.ok(`running`)} ${B(`(pid ${n})`)}`:`${B(H.idle)} ${B(`not running`)}`]),a.push([`limits`,`${V.money(`$${t.maxUsdPerRun}`)}${B(`/session · `)}${t.maxRunsPerHour}${B(`/h · `)}${t.timeoutMin}${B(` min · `)}${t.permission}`]),a.push([`repo`,t.repo??B(`none: builders work in plain folders`)]),console.log(_n(a,2).join(`
|
|
95
|
+
`))}else console.log(Tn(`${B(H.idle)} This computer isn't linked. ${B(`Agents added here still run with`)} ${K(`${C} up`)}${B(`.`)}`));e.agents.length&&(console.log(`\n${z(V.accent(`Agents added here`))}${B(`:`)}`),console.log(Ci(e.agents.map($a),2).flat().join(`
|
|
96
|
+
`))),r(vo(t,!!n,i))}async function bo(){let e=P(),t=0,n=0,r=null,i=``,a=e=>{r?.stop(),r=null,console.log(Tn(i+e,i.length+2))},o=(e,r)=>{e?t++:n++,a(e?`${V.ok(H.ok)} ${r}`:`${V.err(H.fail)} ${V.err(r)}`)},s=e=>a(`${B(H.skip)} ${B(e)}`),c=e=>{r?.stop(),r=null,i=``,console.log(`\n${z(e)}`),i=` `},l=e=>{r&&r.stop(),r=Bn(e.replace(/\.\.\.$/,``),{quiet:!0})};console.log(Tn(`${z(V.accent(`bitfolk check`))} ${B(`· v${j} · node ${process.version}`)}`)),console.log(Tn(B(`config ${xt()}`))),o(!!dr(`git`),`git ${dr(`git`)?`found`:`not found (needed for repos and worktrees)`}`);let u=hr(),d=[];for(let e of cr.filter(e=>e.supported)){let t=u.find(t=>t.id===e.id);t?o(!0,`${V.tool(e.label)} found ${B(`(${t.path})`)}`):d.push(e.label)}d.length&&s(`not found: ${d.join(`, `)}`),(process.env.HTTPS_PROXY||process.env.https_proxy||process.env.HTTP_PROXY)&&!process.env.NODE_USE_ENV_PROXY&&s(`HTTPS_PROXY is set, but Node ignores it unless NODE_USE_ENV_PROXY=1 (Node 22.21+). Set it if bitfolk can't connect.`);let f=e.machine?.api??process.env.BITFOLK_API;f&&f.replace(/\/+$/,``)!==`https://bitfolk.ai`&&s(`talking to ${f}, not ${ft}`);let p=e.machine;if(!p)s(`this computer isn't linked (${C} login)`);else{c(p.name),l(`checking ${p.name}'s link to your team...`);try{let e=await new mt(p.api,()=>ar(p)).me();Dt(p,e),o(!0,`linked to ${z(e.workspace?.name??`your team`)}, ${e.queued} session${e.queued===1?``:`s`} waiting`)}catch(e){o(!1,e instanceof q&&e.ended?`sign-in ended; run ${C} login`:e instanceof M&&e.status===401?`unlinked; run ${C} login`:e.message)}for(let e of p.runtimes){let t;try{t=Fa({...p,command:void 0},e).acp}catch{}if(e.startsWith(`custom:`)){let n=p.customTools?.find(t=>gr(t.name)===e),r=t?.bin??n?.command.trim().split(/\s+/)[0]??``;o(!!n&&!!dr(r),`${V.tool(J(e))} sessions run \`${n?.command??`(not set up here)`}\`${t?` over ACP`:``}`)}else{let t=cr.find(t=>t.id===e),n=t?fr(t):null;if(o(!!n,`${V.tool(J(e))} sessions${n?B(` (${n}${t?.acp?`, via ACP`:``})`):` need it installed`}`),!n)continue}let n=t&&!p.command?dr(t.bin):null;t&&n&&(l(`asking ${J(e)} to say hello over ACP...`),await xo(J(e),{...t,bin:n},o))}p.repo&&o(!!aa(p.repo),`repo ${p.repo}`),process.platform===`darwin`&&s(`${C} up keeps this Mac awake, but closing the lid on battery still sleeps it and pauses sessions.`)}for(let t of e.agents){c(t.name),l(`checking ${t.name}...`);try{let e=await new pt(t.api,t.oauth?()=>ar(t):t.token).setup();o(!0,`${t.oauth?`signed in`:`token works`} (${e.goals.length} goal${e.goals.length===1?``:`s`})`)}catch(e){o(!1,e instanceof q&&e.ended?`sign-in ended; add it again with ${C} add <token from its page>`:e instanceof M&&e.status===401?`token rejected`:e.message)}let e=we[t.runtime].bin(t);o(Za(e),`runtime ${V.tool(t.runtime)} ${B(`(${e||`no command`})`)}`),t.repo&&o(!!aa(t.repo),`repo ${t.repo}`)}r?.stop(),i=``;let m=`${t} check${t===1?``:`s`} passed`;console.log(n?`\n${V.err(H.fail)} ${V.err(z(`${n} problem${n===1?``:`s`}`))}${B(`, ${m}`)}`:`\n${V.ok(H.ok)} ${V.ok(z(`All good`))}${B(`: ${m}`)}`),n&&(process.exitCode=1)}async function xo(e,t,n){try{let r=await dt(t,{timeoutMs:5e3,version:j}),i=[r.agentInfo?.name,r.agentInfo?.version].filter(Boolean).join(` `)||`an unnamed agent`;if(r.protocolVersion!==1)return n(!1,`${e} speaks ACP v${String(r.protocolVersion)}; this runner speaks v1`);let a=r.authMethods.map(e=>e.description??e.name??e.id).filter(Boolean);n(!0,`${V.tool(e)} answers over ACP v1 ${B(`(${i})${a.length?`; sign-in: ${a.join(`; `)}`:``}`)}`)}catch(t){n(!1,`${e} didn't answer ACP initialize: ${t.message}`)}}const So=(e,t,n)=>e?`on`:process.platform===`darwin`&&n.machine&&t[`let-sleep`]?`off`:void 0;async function Co(e,t){let n=P();if(e){let t=Et(n,e);if(!t)throw new $(`no agent called ${e}. See ${C} status`);n.agents=[t]}let r=Wa(),i=null,a=e=>i?i.log(e):console.log(e),o=new za(n,{out:a,liveFooter:kn()&&!!process.stdout.isTTY}),s=yr({platform:process.platform,linked:!!n.machine,letSleep:t[`let-sleep`]})?br():null;if(n.machine){let e=n.machine,t=await Promise.race([new mt(e.api,()=>ar(e)).me().catch(()=>null),new Promise(e=>setTimeout(()=>e(null),3e3).unref())]);t&&(n.machine=Dt(e,t))}(n.machine||n.agents.length)&&(await oi(Di({version:j,machine:n.machine,agents:n.agents,maxConcurrent:n.maxConcurrent,awake:So(s,t,n)}),void 0,void 0,void 0,()=>{s?.(),r()}),console.log(``));let c={machine:n.machine,agents:n.agents,maxConcurrent:n.maxConcurrent,awake:So(s,t,n),version:j};i=Un((e,t)=>ji(o,c,{frame:e,...t}),{intervalMs:()=>{let e=o.status();return e.running||e.stopping||e.checking?100:250}});let l=()=>{i?.stop(),o.killAll(),s?.()},u=0,d=null,f=e=>{let t=Date.now();u&&t-u<1e3||(u&&(l(),r(),process.exit(e===`SIGTERM`?143:130)),u=t,d=e,a(o.running?`\n${V.warn(H.idle)} ${V.warn(`Stopping:`)} letting running sessions wrap up and reporting them as interrupted. ${B(`Ctrl-C again to quit now.`)}`:`\n${V.warn(H.idle)} ${V.warn(`Stopping.`)}`),o.stop())};process.on(`SIGINT`,f),process.on(`SIGTERM`,f),process.on(`SIGHUP`,()=>{l(),r(),process.exit(129)}),process.on(`exit`,l);try{let e=await o.run({once:t.once});if(i.stop(),t.once&&e.length){let t=e.reduce((e,t)=>e+t.durationMs,0);console.log(`${V.ok(H.ok)} ${z(`${e.length} run${e.length===1?``:`s`}`)}${B(`, ${ja(t)} in all.`)}`)}}finally{i.stop(),s?.(),r(),d&&(process.exitCode=d===`SIGINT`?130:143)}}async function wo(e,t){let n=e.join(` `).trim();if(!n&&!process.stdin.isTTY){let e=[];for await(let t of process.stdin)e.push(t);n=Buffer.concat(e).toString(`utf8`).trim()}if(n.length<3)throw new $(`describe the bug: ${C} bug "what you did and what happened"`);let r=await Vn(`Sending your report`,()=>fetch(new URL(`/api/bugs`,to(t)),{method:`POST`,headers:{"content-type":`application/json`,"user-agent":`bitfolk-cli/${j}`},body:JSON.stringify({platform:`cli`,body:n.slice(0,5e3),email:t.email,app_version:`bitfolk-cli ${j}`,device:`${process.platform} ${process.arch}, node ${process.version}`})})),i=await r.json().catch(()=>({}));if(!r.ok)throw Error(i.error??`report failed (${r.status})`);console.log(xn(`Thanks. The bug is on our list, and we read every report.`))}const To=e=>C===`bitfolk`?e:e.replace(/(?<!npx )\bbitfolk (?=[a-z<-])/g,`${C} `);function Eo(){let e=P(),t=e.machine;return{isAgent:t=>e.agents.some(e=>e.slug===t.toLowerCase()||e.name.toLowerCase()===t.toLowerCase()),isTool:e=>cr.some(t=>t.id===e.replace(/-/g,`_`))||!!t?.customTools?.some(t=>t.name===e)||!!t?.runtimes.includes(gr(e)),envToken:process.env.BITFOLK_TOKEN}}async function Do(e){let{values:t,positionals:n}=d({args:e,options:Ya,allowPositionals:!0,strict:!0}),r=t;r[`no-color`]&&Ut({depth:0,fancy:!1,links:!1});let i=ea(n,r,Eo());switch(i.kind){case`version`:return console.log(j);case`help`:{let e={version:j,defaults:_t,api:ft};if(!i.topic)return console.log(To(fi({...e,rows:process.stdout.isTTY?process.stdout.rows:void 0})));let t=pi(Ji(i.topic),e);if(!t)throw new $(`no help for "${i.topic}". Try ${C} --help`);return console.log(To(t))}case`status`:return yo();case`login`:return ao(r);case`logout`:return mo();case`up`:return Co(i.agent,r);case`tools`:return co();case`tool`:return fo(i.action,i.name,r);case`agent-add`:return no(i.token,r);case`agent-rm`:return _o(i.key,r);case`set-machine`:return go(void 0,r);case`set-agent`:return go(i.key,r);case`share`:{let e=P().machine;if(!e)throw new $(`link this computer first: ${C} login`);let t=Xa(i.port,`port`,1,65535);if(!t||!Number.isInteger(t))throw new $(`${C} share <port> [--name "Deal radar"] [--public]`);return Ja(e,t,{name:r.name,public:r.public})}case`check`:return bo();case`bug`:return wo(i.words,r);case`usage`:throw new $(To(i.message));case`unknown`:{let e=Zi(i.command);throw new $(e?`unknown command "${i.command}". Did you mean ${C} ${e}?`:`unknown command "${i.command}". Try ${C} --help`)}}}const Oo=(e,t)=>{console.error(En(Tn(Cn(e,`bitfolk: `)))),process.exit(t)};Do(process.argv.slice(2)).catch(e=>{let t=e.code;if(t===`ERR_PARSE_ARGS_UNKNOWN_OPTION`){let t=/'([^']+)'/.exec(e.message)?.[1]??`that option`;Oo(`unknown option ${t}. Try ${C} --help`,2)}(t===`ERR_PARSE_ARGS_INVALID_OPTION_VALUE`||t===`ERR_PARSE_ARGS_UNEXPECTED_POSITIONAL`)&&Oo(`${e.message.split(`.`)[0]}. Try ${C} --help`,2),e instanceof $&&Oo(e.message,2),e instanceof M&&Oo(e.status===401?`that token was rejected (revoked, or the agent was archived)`:e.message,1),Oo(e.message,1)});export{};
|
package/package.json
CHANGED
|
@@ -1,6 +1,53 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "bitfolk",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Link this computer to your Bitfolk team so it can start Claude Code, Codex, OpenCode and other coding sessions here, from any device.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"bitfolk",
|
|
7
|
+
"cli",
|
|
8
|
+
"claude-code",
|
|
9
|
+
"codex",
|
|
10
|
+
"opencode",
|
|
11
|
+
"coding-agent",
|
|
12
|
+
"ai-agents",
|
|
13
|
+
"runner"
|
|
14
|
+
],
|
|
15
|
+
"homepage": "https://bitfolk.ai",
|
|
16
|
+
"license": "SEE LICENSE IN LICENSE",
|
|
17
|
+
"bugs": {
|
|
18
|
+
"url": "https://bitfolk.ai/bug"
|
|
19
|
+
},
|
|
20
|
+
"type": "module",
|
|
21
|
+
"bin": {
|
|
22
|
+
"bitfolk": "dist/bin.js",
|
|
23
|
+
"bf": "dist/bin.js"
|
|
24
|
+
},
|
|
25
|
+
"files": [
|
|
26
|
+
"dist",
|
|
27
|
+
"LICENSE"
|
|
28
|
+
],
|
|
29
|
+
"engines": {
|
|
30
|
+
"node": ">=20"
|
|
31
|
+
},
|
|
32
|
+
"os": [
|
|
33
|
+
"darwin",
|
|
34
|
+
"linux"
|
|
35
|
+
],
|
|
36
|
+
"publishConfig": {
|
|
37
|
+
"access": "public"
|
|
38
|
+
},
|
|
39
|
+
"scripts": {
|
|
40
|
+
"build": "tsc --noEmit -p tsconfig.build.json && node scripts/build.mjs",
|
|
41
|
+
"prepack": "npm run build",
|
|
42
|
+
"dev": "node src/main.ts",
|
|
43
|
+
"typecheck": "tsc --noEmit",
|
|
44
|
+
"lint": "tsc --noEmit",
|
|
45
|
+
"test": "vitest run"
|
|
46
|
+
},
|
|
47
|
+
"devDependencies": {
|
|
48
|
+
"@types/node": "22.20.5",
|
|
49
|
+
"rolldown": "1.2.16",
|
|
50
|
+
"typescript": "5.9.3",
|
|
51
|
+
"vitest": "5.1.0"
|
|
52
|
+
}
|
|
53
|
+
}
|