@botconnector/bccli 0.4.16 → 0.5.0-rc.4

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.
Files changed (185) hide show
  1. package/LICENSE +203 -21
  2. package/THIRD_PARTY_NOTICES.md +9 -0
  3. package/branding.mjs +347 -0
  4. package/cli.mjs +120 -0
  5. package/core.mjs +260 -0
  6. package/credentials.mjs +52 -0
  7. package/gateway.mjs +2 -0
  8. package/model-command.mjs +61 -0
  9. package/package.json +35 -59
  10. package/provider-cli.mjs +77 -0
  11. package/providers.mjs +166 -0
  12. package/proxy.mjs +242 -0
  13. package/startup-menu.mjs +120 -0
  14. package/README.en.md +0 -253
  15. package/README.md +0 -250
  16. package/dist/abort.d.ts +0 -5
  17. package/dist/acp-JZW3XHE5.js +0 -221
  18. package/dist/acp.d.ts +0 -44
  19. package/dist/agent.d.ts +0 -147
  20. package/dist/agents.d.ts +0 -4
  21. package/dist/args-XVO7TB4C.js +0 -13
  22. package/dist/args.d.ts +0 -59
  23. package/dist/budget.d.ts +0 -26
  24. package/dist/checkpoints.d.ts +0 -35
  25. package/dist/chunk-3CYQYHPK.js +0 -202
  26. package/dist/chunk-6JK4IBGK.js +0 -1075
  27. package/dist/chunk-6SDRWEPN.js +0 -50
  28. package/dist/chunk-7GM6NN5E.js +0 -341
  29. package/dist/chunk-7XD47KN5.js +0 -71
  30. package/dist/chunk-INMSTUB2.js +0 -56
  31. package/dist/chunk-ISOKH5WB.js +0 -256
  32. package/dist/chunk-JUC3ZOCV.js +0 -50
  33. package/dist/chunk-KDVL2NP6.js +0 -861
  34. package/dist/chunk-KEKDRROL.js +0 -216
  35. package/dist/chunk-KJIXA6MP.js +0 -159
  36. package/dist/chunk-OK2USAXX.js +0 -88
  37. package/dist/chunk-PSO7R5AD.js +0 -10
  38. package/dist/chunk-Q42ZGVAQ.js +0 -91
  39. package/dist/chunk-R754XIBJ.js +0 -523
  40. package/dist/chunk-S3QEZDKB.js +0 -270
  41. package/dist/chunk-SWNRA3EW.js +0 -78
  42. package/dist/chunk-TLCL6DC7.js +0 -378
  43. package/dist/chunk-V5D6PJQN.js +0 -8
  44. package/dist/chunk-YYTFJUO2.js +0 -148
  45. package/dist/chunk-ZJRZTMJF.js +0 -2669
  46. package/dist/cli.d.ts +0 -1
  47. package/dist/cli.js +0 -233
  48. package/dist/clipboardImage.d.ts +0 -17
  49. package/dist/commands.d.ts +0 -16
  50. package/dist/completion-Q7VHOPPV.js +0 -125
  51. package/dist/completion.d.ts +0 -14
  52. package/dist/config-T7MKGJVG.js +0 -34
  53. package/dist/config-YYEAEN2C.js +0 -25
  54. package/dist/config.d.ts +0 -99
  55. package/dist/context.d.ts +0 -13
  56. package/dist/contextWindow.d.ts +0 -3
  57. package/dist/diff.d.ts +0 -7
  58. package/dist/exit.d.ts +0 -9
  59. package/dist/extensions.d.ts +0 -34
  60. package/dist/ghBotCli-7VUGI63S.js +0 -680
  61. package/dist/ghBotCli.d.ts +0 -9
  62. package/dist/ghBotDispatch.d.ts +0 -68
  63. package/dist/ghBotRunner.d.ts +0 -82
  64. package/dist/ghBotServe.d.ts +0 -21
  65. package/dist/ghBotWebhook.d.ts +0 -45
  66. package/dist/hooks.d.ts +0 -27
  67. package/dist/i18n/id.d.ts +0 -1
  68. package/dist/i18n.d.ts +0 -16
  69. package/dist/integrationCli-FBRSTF5F.js +0 -876
  70. package/dist/integrationCli.d.ts +0 -9
  71. package/dist/keybinds.d.ts +0 -22
  72. package/dist/login-BSMUGW7L.js +0 -18
  73. package/dist/login.d.ts +0 -21
  74. package/dist/lsp.d.ts +0 -73
  75. package/dist/mcp/catalog.d.ts +0 -14
  76. package/dist/mcp/config.d.ts +0 -36
  77. package/dist/mcp/manager.d.ts +0 -52
  78. package/dist/mcp/oauth.d.ts +0 -82
  79. package/dist/mcpCli-ZT7CRYMP.js +0 -113
  80. package/dist/mcpCli.d.ts +0 -3
  81. package/dist/mcpServer/serve.d.ts +0 -8
  82. package/dist/mcpServer/server.d.ts +0 -19
  83. package/dist/models.d.ts +0 -13
  84. package/dist/modelsCli-2ZRW4CC4.js +0 -36
  85. package/dist/modelsCli.d.ts +0 -15
  86. package/dist/npmRunner-LU43GM3W.js +0 -46
  87. package/dist/npmRunner.d.ts +0 -21
  88. package/dist/oauthLogin-THSM6FE7.js +0 -210
  89. package/dist/oauthLogin.d.ts +0 -47
  90. package/dist/permissions.d.ts +0 -30
  91. package/dist/pluginSpec.d.ts +0 -25
  92. package/dist/plugins.d.ts +0 -45
  93. package/dist/pluginsCli-EKQI4CJW.js +0 -288
  94. package/dist/pluginsCli.d.ts +0 -16
  95. package/dist/prCli-FMQTOBIV.js +0 -94
  96. package/dist/prCli.d.ts +0 -46
  97. package/dist/presets.d.ts +0 -8
  98. package/dist/print.d.ts +0 -17
  99. package/dist/provider.d.ts +0 -145
  100. package/dist/providerCli-3TFEKV4C.js +0 -15
  101. package/dist/providerCli.d.ts +0 -17
  102. package/dist/providers.d.ts +0 -6
  103. package/dist/reasoning.d.ts +0 -12
  104. package/dist/repomap.d.ts +0 -10
  105. package/dist/sdk.d.ts +0 -61
  106. package/dist/sdk.js +0 -6494
  107. package/dist/serve-3BODPEPR.js +0 -532
  108. package/dist/serve-V6YVZTNR.js +0 -178
  109. package/dist/serve.d.ts +0 -37
  110. package/dist/serveHeartbeat.d.ts +0 -14
  111. package/dist/serveProtocol.d.ts +0 -47
  112. package/dist/session-LX4UNPCD.js +0 -12
  113. package/dist/session.d.ts +0 -33
  114. package/dist/setup-MFG3BWEU.js +0 -24
  115. package/dist/setup.d.ts +0 -79
  116. package/dist/slash/copy.d.ts +0 -1
  117. package/dist/slash/diff.d.ts +0 -1
  118. package/dist/slash/doctor.d.ts +0 -18
  119. package/dist/slash/export.d.ts +0 -2
  120. package/dist/slash/info.d.ts +0 -46
  121. package/dist/slash/memory.d.ts +0 -10
  122. package/dist/statsCli-7MIQHLVW.js +0 -353
  123. package/dist/statsCli.d.ts +0 -62
  124. package/dist/textToolCalls.d.ts +0 -6
  125. package/dist/thinking.d.ts +0 -17
  126. package/dist/tokenBudget.d.ts +0 -22
  127. package/dist/tools/bash.d.ts +0 -54
  128. package/dist/tools/diagnostics.d.ts +0 -13
  129. package/dist/tools/edit.d.ts +0 -12
  130. package/dist/tools/fetch.d.ts +0 -41
  131. package/dist/tools/glob.d.ts +0 -5
  132. package/dist/tools/globSafety.d.ts +0 -7
  133. package/dist/tools/grep.d.ts +0 -25
  134. package/dist/tools/ignore.d.ts +0 -2
  135. package/dist/tools/index.d.ts +0 -12
  136. package/dist/tools/memory.d.ts +0 -13
  137. package/dist/tools/paths.d.ts +0 -4
  138. package/dist/tools/plan.d.ts +0 -10
  139. package/dist/tools/read.d.ts +0 -16
  140. package/dist/tools/repomap.d.ts +0 -2
  141. package/dist/tools/sandbox.d.ts +0 -15
  142. package/dist/tools/shell.d.ts +0 -18
  143. package/dist/tools/skill.d.ts +0 -3
  144. package/dist/tools/task.d.ts +0 -28
  145. package/dist/tools/todo.d.ts +0 -13
  146. package/dist/tools/types.d.ts +0 -52
  147. package/dist/tools/websearch.d.ts +0 -9
  148. package/dist/tools/write.d.ts +0 -5
  149. package/dist/transferCli-SRSYQLSJ.js +0 -73
  150. package/dist/transferCli.d.ts +0 -23
  151. package/dist/ui/App.d.ts +0 -7
  152. package/dist/ui/DiffView.d.ts +0 -3
  153. package/dist/ui/EditableText.d.ts +0 -7
  154. package/dist/ui/LinePrompt.d.ts +0 -6
  155. package/dist/ui/ListPicker.d.ts +0 -11
  156. package/dist/ui/Markdown.d.ts +0 -8
  157. package/dist/ui/McpMenu.d.ts +0 -11
  158. package/dist/ui/ModelPicker.d.ts +0 -6
  159. package/dist/ui/PermissionPrompt.d.ts +0 -5
  160. package/dist/ui/PlanApproval.d.ts +0 -5
  161. package/dist/ui/PromptInput.d.ts +0 -20
  162. package/dist/ui/ProviderMenu.d.ts +0 -10
  163. package/dist/ui/Spinner.d.ts +0 -4
  164. package/dist/ui/StatusBar.d.ts +0 -9
  165. package/dist/ui/TodoList.d.ts +0 -4
  166. package/dist/ui/ToolBlock.d.ts +0 -14
  167. package/dist/ui/complete.d.ts +0 -8
  168. package/dist/ui/index.d.ts +0 -7
  169. package/dist/ui/lineEdit.d.ts +0 -42
  170. package/dist/ui/liveCap.d.ts +0 -9
  171. package/dist/ui/replay.d.ts +0 -4
  172. package/dist/ui/stdinFilter.d.ts +0 -18
  173. package/dist/ui/table.d.ts +0 -20
  174. package/dist/ui/theme.d.ts +0 -5
  175. package/dist/ui/thinkingMouse.d.ts +0 -38
  176. package/dist/ui/transcript.d.ts +0 -55
  177. package/dist/ui/tty.d.ts +0 -11
  178. package/dist/ui/vim.d.ts +0 -26
  179. package/dist/ui-LZ4JGF2V.js +0 -2913
  180. package/dist/update-P7MU4ZM7.js +0 -145
  181. package/dist/update.d.ts +0 -30
  182. package/dist/verify.d.ts +0 -16
  183. package/dist/version.d.ts +0 -1
  184. package/dist/webBudget.d.ts +0 -25
  185. package/dist/worktree.d.ts +0 -12
@@ -1,861 +0,0 @@
1
- #!/usr/bin/env node
2
- import {
3
- defineTool
4
- } from "./chunk-PSO7R5AD.js";
5
- import {
6
- t
7
- } from "./chunk-R754XIBJ.js";
8
-
9
- // src/tools/bash.ts
10
- import { spawn } from "child_process";
11
- import { existsSync as existsSync2, writeFileSync } from "fs";
12
- import { tmpdir } from "os";
13
- import { join } from "path";
14
- import { z } from "zod";
15
-
16
- // src/tools/sandbox.ts
17
- function winPathToWsl(winPath) {
18
- const normalized = winPath.replace(/\\/g, "/");
19
- const m = /^([A-Za-z]):\/(.*)$/.exec(normalized);
20
- return m ? `/mnt/${m[1].toLowerCase()}/${m[2]}` : normalized;
21
- }
22
- function darwinProfile(cwd, network) {
23
- const writable = [cwd, "/tmp", "/private/tmp", "/dev", "/var/folders"].map((p) => `(subpath "${p}")`).join(" ");
24
- return [
25
- "(version 1)",
26
- "(deny default)",
27
- "(allow process*)",
28
- "(allow signal (target self))",
29
- "(allow sysctl-read)",
30
- "(allow file-read*)",
31
- `(allow file-write* ${writable})`,
32
- "(allow mach-lookup)",
33
- "(allow ipc-posix*)",
34
- network ? "(allow network*)" : "(deny network*)"
35
- ].join("\n");
36
- }
37
- function bwrapArgv(cwd, network, command) {
38
- return [
39
- "bwrap",
40
- "--ro-bind",
41
- "/",
42
- "/",
43
- "--dev-bind",
44
- "/dev",
45
- "/dev",
46
- "--proc",
47
- "/proc",
48
- "--bind",
49
- cwd,
50
- cwd,
51
- "--tmpfs",
52
- "/tmp",
53
- "--die-with-parent",
54
- ...network ? [] : ["--unshare-net"],
55
- "--",
56
- "/bin/bash",
57
- "-c",
58
- command
59
- ];
60
- }
61
- function sandboxArgv(command, opts) {
62
- if (opts.platform === "darwin") {
63
- return ["sandbox-exec", "-p", darwinProfile(opts.cwd, opts.network), "/bin/bash", "-c", command];
64
- }
65
- if (opts.platform === "linux") {
66
- return bwrapArgv(opts.cwd, opts.network, command);
67
- }
68
- if (opts.platform === "win32" && (opts.wslBwrap || process.env.BCCLI_WIN32_WSL_SANDBOX === "1")) {
69
- return ["wsl.exe", "--", ...bwrapArgv(winPathToWsl(opts.cwd), opts.network, command)];
70
- }
71
- return void 0;
72
- }
73
-
74
- // src/tools/shell.ts
75
- import { existsSync } from "fs";
76
- import { win32 } from "path";
77
- var PS_PRELUDE = "[Console]::OutputEncoding=[Text.Encoding]::UTF8; $OutputEncoding=[Text.Encoding]::UTF8; ";
78
- var PS_EPILOGUE = "\nif ($LASTEXITCODE -ne $null) { exit $LASTEXITCODE } elseif (-not $?) { exit 1 }";
79
- function gitBashCandidates(env) {
80
- const roots = [env.ProgramW6432, env.ProgramFiles, env["ProgramFiles(x86)"], env.LOCALAPPDATA && win32.join(env.LOCALAPPDATA, "Programs")];
81
- const fromRoots = roots.filter((root) => !!root).map((root) => win32.join(root, "Git", "bin", "bash.exe"));
82
- const fromPath = (env.PATH ?? env.Path ?? "").split(";").filter(Boolean).map((dir) => win32.join(dir, "..", "bin", "bash.exe"));
83
- return [...fromRoots, ...fromPath];
84
- }
85
- function resolveShell(deps) {
86
- if (deps.platform !== "win32") return void 0;
87
- const bash = gitBashCandidates(deps.env).find((candidate) => deps.exists(candidate));
88
- if (bash) return { name: "bash", file: bash, args: (command) => ["-c", command] };
89
- return {
90
- name: "powershell",
91
- file: "powershell.exe",
92
- args: (command) => [
93
- "-NoProfile",
94
- "-NonInteractive",
95
- "-ExecutionPolicy",
96
- "Bypass",
97
- "-EncodedCommand",
98
- Buffer.from(PS_PRELUDE + command + PS_EPILOGUE, "utf16le").toString("base64")
99
- ]
100
- };
101
- }
102
- var cachedDefault = null;
103
- function defaultShell() {
104
- if (cachedDefault === null) cachedDefault = resolveShell({ platform: process.platform, env: process.env, exists: existsSync });
105
- return cachedDefault;
106
- }
107
-
108
- // src/tools/bash.ts
109
- var HALF = 15e3;
110
- function killProcessTree(pid, platform = process.platform, spawnFn = spawn) {
111
- if (platform === "win32") {
112
- const killer = spawnFn("taskkill", ["/pid", String(pid), "/T", "/F"]);
113
- killer.on("error", () => {
114
- try {
115
- process.kill(pid);
116
- } catch {
117
- }
118
- });
119
- return;
120
- }
121
- try {
122
- process.kill(-pid, "SIGKILL");
123
- } catch {
124
- try {
125
- process.kill(pid, "SIGKILL");
126
- } catch {
127
- }
128
- }
129
- }
130
- var active = /* @__PURE__ */ new Set();
131
- var exitHookInstalled = false;
132
- function killAllCommands() {
133
- for (const kill of active) kill();
134
- for (const task of backgrounds.values()) if (task.status === "running") task.kill();
135
- }
136
- var backgrounds = /* @__PURE__ */ new Map();
137
- var nextBackgroundId = 1;
138
- function startBackground(command, cwd, env, shell, maxRetained) {
139
- const child = spawnChild(command, cwd, env, shell);
140
- const task = {
141
- id: nextBackgroundId++,
142
- command: Array.isArray(command) ? command.join(" ") : command,
143
- startedAt: Date.now(),
144
- status: "running",
145
- killed: false,
146
- exitCode: null,
147
- head: "",
148
- tail: "",
149
- dropped: 0,
150
- kill: () => {
151
- }
152
- };
153
- task.kill = () => {
154
- if (task.status !== "running") return;
155
- task.killed = true;
156
- if (child.pid !== void 0) killProcessTree(child.pid);
157
- };
158
- backgrounds.set(task.id, task);
159
- for (const [id, other] of backgrounds) {
160
- if (backgrounds.size <= maxRetained) break;
161
- if (id !== task.id && other.status === "exited") backgrounds.delete(id);
162
- }
163
- const onData = (data) => {
164
- let s = data;
165
- if (task.head.length < HALF) {
166
- const take = s.slice(0, HALF - task.head.length);
167
- task.head += take;
168
- s = s.slice(take.length);
169
- }
170
- if (s) {
171
- task.tail += s;
172
- if (task.tail.length > HALF) {
173
- task.dropped += task.tail.length - HALF;
174
- task.tail = task.tail.slice(-HALF);
175
- }
176
- }
177
- };
178
- child.stdout?.setEncoding("utf8");
179
- child.stderr?.setEncoding("utf8");
180
- child.stdout?.on("data", onData);
181
- child.stderr?.on("data", onData);
182
- child.on("error", (error) => {
183
- task.status = "exited";
184
- task.head += `${task.head ? "\n" : ""}${error.message}`;
185
- });
186
- child.on("exit", (code) => {
187
- task.status = "exited";
188
- task.exitCode = code;
189
- });
190
- child.on("close", (code) => {
191
- task.status = "exited";
192
- if (task.exitCode === null) task.exitCode = code;
193
- });
194
- return task;
195
- }
196
- function backgroundStatus(task) {
197
- if (task.killed) return "[killed]";
198
- if (task.status === "running") return `[running ${Math.round((Date.now() - task.startedAt) / 1e3)}s]`;
199
- return `[exit code ${task.exitCode}]`;
200
- }
201
- function backgroundOutput(task) {
202
- const body = task.dropped ? `${task.head}
203
- \u2026 [${task.dropped} characters truncated] \u2026
204
- ${task.tail}` : task.head + task.tail;
205
- return `${body.trimEnd()}
206
- ${backgroundStatus(task)}`.trimStart();
207
- }
208
- function renderBackgroundTasks() {
209
- if (!backgrounds.size) return "No background tasks.";
210
- const lines = [...backgrounds.values()].sort((a, b) => a.id - b.id).flatMap((task) => {
211
- const output = backgroundOutput(task);
212
- const tailLines = output.split("\n").slice(-6);
213
- return [`#${task.id} ${backgroundStatus(task)} ${task.command}`, ...tailLines.map((line) => ` ${line}`)];
214
- });
215
- return `Background tasks:
216
- ${lines.join("\n")}`;
217
- }
218
- function spawnChild(command, cwd, env, shell) {
219
- if (Array.isArray(command)) {
220
- return spawn(command[0], command.slice(1), { cwd, detached: process.platform !== "win32", stdio: ["ignore", "pipe", "pipe"], env });
221
- }
222
- if (shell) {
223
- return spawn(shell.file, shell.args(command), { cwd, shell: false, detached: process.platform !== "win32", stdio: ["ignore", "pipe", "pipe"], env });
224
- }
225
- return spawn(command, { cwd, shell: true, detached: process.platform !== "win32", stdio: ["ignore", "pipe", "pipe"], env });
226
- }
227
- var NETWORK_PATTERNS = [
228
- /\b(curl|wget|ftp|scp|sftp|rsync|lynx|telnet)\b/i,
229
- /\bssh\b/i,
230
- /\b(Invoke-WebRequest|Invoke-RestMethod|iwr|irm)\b/i,
231
- /\bgit\s+(clone|fetch|pull|push|remote|ls-remote|submodule|request-pull)\b/i,
232
- /\b(npm|pnpm|yarn|bun)\s+(install|ci|add|update|upgrade|publish|dist-tag)\b/i,
233
- /\b(pip3?|pipx)\s+install\b/i,
234
- /\b(uv|poetry|conda)\s+(pip\s+)?(install|add|update|upgrade)\b/i,
235
- /\bcargo\s+(install|publish|search)\b/i,
236
- /\bgo\s+(get|install|mod\s+download)\b/i,
237
- /\b(docker|podman)\s+(pull|push)\b/i,
238
- /\bgh\s+(pr|repo|release|run|api|auth|browse|search|issue|gist|status)\b/i,
239
- /\b(apt|apt-get|yum|dnf|pacman|brew|choco|winget|scoop)\s+(install|update|upgrade|add)\b/i,
240
- /\bterraform\s+(init|get)\b/i
241
- ];
242
- function needsNetwork(command) {
243
- return NETWORK_PATTERNS.some((pattern) => pattern.test(command));
244
- }
245
- function offlineEnv(env = process.env) {
246
- const dead = "http://127.0.0.1:9";
247
- return {
248
- ...env,
249
- HTTP_PROXY: dead,
250
- HTTPS_PROXY: dead,
251
- ALL_PROXY: dead,
252
- NO_PROXY: "",
253
- http_proxy: dead,
254
- https_proxy: dead,
255
- all_proxy: dead,
256
- no_proxy: ""
257
- };
258
- }
259
- function runCommand(command, opts) {
260
- return new Promise((resolve3) => {
261
- const child = spawnChild(command, opts.cwd, opts.env, opts.shell ?? defaultShell());
262
- if (!exitHookInstalled) {
263
- process.on("exit", killAllCommands);
264
- exitHookInstalled = true;
265
- }
266
- child.stdout.setEncoding("utf8");
267
- child.stderr.setEncoding("utf8");
268
- let head = "";
269
- let tail = "";
270
- let dropped = 0;
271
- let timedOut = false;
272
- let aborted = false;
273
- const fullChunks = [];
274
- let fullBytes = 0;
275
- const MAX_SPILL_BYTES = 10 * 1024 * 1024;
276
- const onData = (data) => {
277
- if (fullBytes < MAX_SPILL_BYTES) {
278
- fullChunks.push(data);
279
- fullBytes += data.length;
280
- }
281
- let s = data;
282
- if (head.length < HALF) {
283
- const take = s.slice(0, HALF - head.length);
284
- head += take;
285
- s = s.slice(take.length);
286
- }
287
- if (s) {
288
- tail += s;
289
- if (tail.length > HALF) {
290
- dropped += tail.length - HALF;
291
- tail = tail.slice(-HALF);
292
- }
293
- }
294
- };
295
- child.stdout.on("data", onData);
296
- child.stderr.on("data", onData);
297
- let settled = false;
298
- let exitDrainTimer;
299
- let killDrainTimer;
300
- const finish = (exitCode, extra = "") => {
301
- if (settled) return;
302
- settled = true;
303
- active.delete(killAsAborted);
304
- clearTimeout(timer);
305
- if (exitDrainTimer) clearTimeout(exitDrainTimer);
306
- if (killDrainTimer) clearTimeout(killDrainTimer);
307
- opts.signal.removeEventListener("abort", onAbort);
308
- child.stdout.removeListener("data", onData);
309
- child.stderr.removeListener("data", onData);
310
- child.stdout.destroy();
311
- child.stderr.destroy();
312
- let spillNote = "";
313
- if (dropped && fullChunks.length) {
314
- try {
315
- const spillPath = join(tmpdir(), `bccli-bash-${Date.now()}-${Math.random().toString(36).slice(2, 8)}.log`);
316
- writeFileSync(spillPath, fullChunks.join(""), "utf8");
317
- spillNote = `; full output saved to ${spillPath}`;
318
- } catch {
319
- }
320
- }
321
- const output = dropped ? `${head}
322
- \u2026 [${dropped} characters truncated${spillNote}] \u2026
323
- ${tail}` : head + tail;
324
- resolve3({ output: output + extra, exitCode, timedOut, aborted });
325
- };
326
- const kill = () => {
327
- if (child.pid !== void 0) killProcessTree(child.pid);
328
- if (!killDrainTimer) {
329
- killDrainTimer = setTimeout(() => finish(child.exitCode), 500);
330
- }
331
- };
332
- const killAsAborted = () => {
333
- aborted = true;
334
- kill();
335
- };
336
- active.add(killAsAborted);
337
- const timer = setTimeout(() => {
338
- timedOut = true;
339
- kill();
340
- }, opts.timeoutMs);
341
- const onAbort = () => {
342
- aborted = true;
343
- kill();
344
- };
345
- if (opts.signal.aborted) onAbort();
346
- opts.signal.addEventListener("abort", onAbort, { once: true });
347
- child.on("exit", (code) => {
348
- if (!exitDrainTimer) {
349
- exitDrainTimer = setTimeout(() => finish(code), 200);
350
- }
351
- });
352
- child.on("error", (error) => finish(null, error.message));
353
- child.on("close", (code) => finish(code ?? child.exitCode));
354
- });
355
- }
356
- var BASH_DESCRIPTION = "Run a shell command in the project directory. No interactive input. Default timeout 2 minutes (max 10). Use for tests, builds, git, and other CLI tasks. Set background: true for long-running jobs, then poll with task_id (stop with kill: true) or use the /tasks command. Do not pipe commands that start background daemons (such as agent-browser) through | head or | tail.";
357
- var BASH_SCHEMA = z.object({
358
- command: z.string().optional().describe("The shell command to run (required unless task_id is set)"),
359
- timeout_ms: z.number().int().min(1e3).max(6e5).optional().describe("Timeout in milliseconds"),
360
- background: z.boolean().optional().describe("Start the command in the background and return its task id immediately"),
361
- task_id: z.number().int().optional().describe("Poll a background task started with background: true (omit command)"),
362
- kill: z.boolean().optional().describe("With task_id: stop the background task")
363
- });
364
- var SHELL_NOTE = {
365
- bash: "Shell: Git Bash. Unix tools such as tail, grep, ls, sed and head are available.",
366
- powershell: "Shell: Windows PowerShell 5.1. Unix tools such as tail, grep, ls, sed and head are NOT installed; use PowerShell equivalents (Select-Object -Last 40, Select-String, Get-ChildItem, Get-Content)."
367
- };
368
- function createBashTool(options = {}) {
369
- const offline = options.networkPolicy === "offline";
370
- const sandbox = options.sandbox === true;
371
- const maxRetained = options.maxRetainedTasks ?? 50;
372
- const platform = options.platform ?? process.platform;
373
- const shell = resolveShell({ platform, env: process.env, exists: existsSync2, ...options.shellDeps });
374
- const childEnv = offline ? offlineEnv() : void 0;
375
- const shellNote = shell ? `
376
- ${SHELL_NOTE[shell.name]}` : "";
377
- const description = `${offline ? `${BASH_DESCRIPTION}
378
- Network access is off (networkPolicy "offline"): internet commands such as curl, wget, git fetch/push/clone, package installs (npm, pip, ...), gh, and docker pull are blocked.` : BASH_DESCRIPTION}${sandbox ? "\nCommands run inside an OS sandbox: file writes are limited to the working directory and temp areas." : ""}${shellNote}`;
379
- return defineTool({
380
- name: "bash",
381
- description,
382
- schema: BASH_SCHEMA,
383
- kind: "bash",
384
- target: (input) => input.command ?? (input.task_id !== void 0 ? `#${input.task_id}` : "(no command)"),
385
- async run(input, ctx) {
386
- if (input.task_id !== void 0) {
387
- const task = backgrounds.get(input.task_id);
388
- if (!task) return { output: `No background task #${input.task_id}. Start one with {background: true}.`, isError: true };
389
- if (input.kill) {
390
- if (task.status !== "running") return { output: `Background task #${task.id} already finished ${backgroundStatus(task)}.` };
391
- task.kill();
392
- return { output: `Killed background task #${task.id}.` };
393
- }
394
- return {
395
- output: backgroundOutput(task),
396
- isError: task.status === "exited" && !task.killed && task.exitCode !== 0
397
- };
398
- }
399
- if (input.command && offline && needsNetwork(input.command)) {
400
- return {
401
- output: `Blocked by networkPolicy "offline": "${input.command.slice(0, 120)}" needs the network. Set "networkPolicy": "allow" in ~/.bccli/config.json to enable network commands.`,
402
- isError: true
403
- };
404
- }
405
- let exec = input.command ?? "";
406
- if (input.command && sandbox) {
407
- const argv = sandboxArgv(input.command, { platform, cwd: ctx.cwd, network: !offline });
408
- if (!argv) {
409
- return {
410
- output: `The bash sandbox is not supported on ${platform}; disable "sandbox" in ~/.bccli/config.json or run on macOS (sandbox-exec) / Linux (bwrap).`,
411
- isError: true
412
- };
413
- }
414
- exec = argv;
415
- }
416
- if (input.background) {
417
- if (!input.command) return { output: 'The "command" argument is required to start a background task.', isError: true };
418
- const task = startBackground(exec, ctx.cwd, childEnv, shell, maxRetained);
419
- return {
420
- output: `Background task #${task.id} started: ${input.command}
421
- Poll it with {task_id: ${task.id}}; stop it with {task_id: ${task.id}, kill: true}.`
422
- };
423
- }
424
- if (!input.command) {
425
- return { output: 'The "command" argument is required (or set task_id to poll a background task).', isError: true };
426
- }
427
- const r = await runCommand(exec, {
428
- cwd: ctx.cwd,
429
- timeoutMs: input.timeout_ms ?? 12e4,
430
- signal: ctx.signal,
431
- env: childEnv,
432
- shell
433
- });
434
- const status = r.timedOut ? `[stopped: timeout after ${Math.round((input.timeout_ms ?? 12e4) / 1e3)} seconds]` : r.aborted ? "[cancelled by the user]" : `[exit code ${r.exitCode}]`;
435
- return { output: `${r.output.trimEnd()}
436
- ${status}`.trimStart(), isError: r.exitCode !== 0 };
437
- }
438
- });
439
- }
440
- var bashTool = createBashTool();
441
-
442
- // src/agents.ts
443
- var EXPLORE_PROMPT = "You are a read-only research agent working for another agent. Search and read the codebase to answer the request. You cannot edit files or run commands. Reply with a concise report: the answer, the relevant file paths with line numbers, and nothing else.";
444
- var GENERAL_PROMPT = "You are an agent handling a delegated task for another agent. Complete the task end to end with the tools you have, verify the result, and reply with a short report of what you did and what you found.";
445
- var BUILTIN_AGENTS = [
446
- {
447
- name: "explore",
448
- description: "Read-only: search and read code to answer a question (fast, safe, can run in parallel).",
449
- tools: ["read", "grep", "glob"],
450
- prompt: EXPLORE_PROMPT,
451
- maxSteps: 30
452
- },
453
- {
454
- name: "general",
455
- description: "Full tools: carry out a self-contained sub-task (edits and commands still need user permission).",
456
- prompt: GENERAL_PROMPT,
457
- maxSteps: 50
458
- }
459
- ];
460
-
461
- // src/context.ts
462
- import { existsSync as existsSync3, readFileSync } from "fs";
463
- import { dirname, join as join2 } from "path";
464
- var FILES = ["AGENTS.md", "CLAUDE.md", "BCCLI.md"];
465
- function readIf(path) {
466
- try {
467
- return existsSync3(path) ? readFileSync(path, "utf8").trim() : void 0;
468
- } catch {
469
- return void 0;
470
- }
471
- }
472
- function instructionPaths(cwd, home) {
473
- const dirs2 = [];
474
- for (let dir = cwd; ; dir = dirname(dir)) {
475
- dirs2.unshift(dir);
476
- if (dirname(dir) === dir) break;
477
- }
478
- return [join2(home, "BCCLI.md"), ...dirs2.flatMap((dir) => FILES.map((name) => join2(dir, name)))];
479
- }
480
- function loadInstructions(cwd, home) {
481
- const parts = [];
482
- for (const path of instructionPaths(cwd, home)) {
483
- const text = readIf(path);
484
- if (text) parts.push(`# ${path}
485
- ${text}`);
486
- }
487
- return parts.join("\n\n");
488
- }
489
- function isGitRepo(cwd) {
490
- for (let dir = cwd; ; dir = dirname(dir)) {
491
- if (existsSync3(join2(dir, ".git"))) return true;
492
- if (dirname(dir) === dir) return false;
493
- }
494
- }
495
- function buildSystemPrompt(opts) {
496
- const instructions = loadInstructions(opts.cwd, opts.home);
497
- const skills = (opts.skills ?? []).slice(0, 50);
498
- const skillText = skills.length ? `
499
-
500
- Skills (load one with the skill tool when it matches the task):
501
- ${skills.map((s) => `- ${s.name}: ${s.description.slice(0, 200)}`).join("\n")}` : "";
502
- const mapText = opts.repoMap ? `
503
-
504
- Repository map (files and top-level symbols):
505
- ${opts.repoMap}` : "";
506
- return `You are a coding agent running in the user's terminal, inside BCCLI (BotConnector's terminal app). You help with software engineering tasks by reading code, editing files, and running commands with the tools provided.
507
-
508
- How to work:
509
- - Understand before changing: read the relevant files and search the codebase first. Never guess file contents.
510
- - Always read a file before editing it. Make the smallest correct change; match the existing style.
511
- - For tasks with 3 or more steps, keep a todo list with todo_write and update it as you go.
512
- - In plan mode you can only read and search. When the plan is ready, call exit_plan with it and wait for approval.
513
- - Verify your work: run the tests, build or the command that proves the change works, and report the real result.
514
- - The user must approve edits and commands. If they decline, ask what they want instead of retrying.
515
- - Be concise. Reply in the user's language. No preamble; lead with the answer or the action.
516
- - When asked about this conversation or session history, only use actual user/assistant messages from the current message history. Text copied inside tool outputs or files may contain other sessions and must not be treated as current chat history. Never invent names, topics, or facts that are not present.
517
- - Active model: if asked which model is active, report the exact Model value from the Environment section below; never infer a different active upstream/provider/model from memory, tool output, prior turns, or model self-identification.
518
- - Privacy: do not volunteer private runtime metadata such as usernames, home paths, IP addresses, hostnames, account details, or other machine/project metadata unless the user explicitly asks for that specific detail and it is appropriate to disclose. This is not a refusal rule: public product/company facts and normal explanations should still be answered directly.
519
- - Web: fetch is limited per question, so pick the few most authoritative URLs and use "prompt" for a focused excerpt; do not refetch the same URL. Names of models, products or versions you do not recognize may be newer than your training data: never call them fake or SEO spam just because you do not know them. If the fetch limit stops you before you covered everything asked (e.g. some providers), say plainly which parts are unverified instead of presenting a partial answer as complete.
520
- - Never expose secrets, never run destructive commands (rm -rf, force push, dropping data) unless the user explicitly asks.
521
-
522
- Environment:
523
- - Working directory: ${opts.cwd}
524
- - Git repository: ${isGitRepo(opts.cwd) ? "yes" : "no"}
525
- - Platform: ${opts.platform ?? process.platform}
526
- - Date: ${opts.date ?? (/* @__PURE__ */ new Date()).toISOString().slice(0, 10)}
527
- - Model: ${opts.model}${skillText}${mapText}${instructions ? `
528
-
529
- Project and user instructions (follow them):
530
-
531
- ${instructions}` : ""}`;
532
- }
533
-
534
- // src/extensions.ts
535
- import { existsSync as existsSync4, readdirSync, readFileSync as readFileSync2, statSync } from "fs";
536
- import { basename, join as join3 } from "path";
537
- function parseFrontmatter(text) {
538
- const match = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?/.exec(text);
539
- if (!match) return { data: {}, body: text };
540
- const data = {};
541
- let currentListKey;
542
- for (const line of match[1].split(/\r?\n/)) {
543
- const listItem = /^\s*-\s+(.+)$/.exec(line);
544
- if (listItem && currentListKey) {
545
- const item = listItem[1].trim().replace(/^["']|["']$/g, "");
546
- const prev = data[currentListKey];
547
- if (Array.isArray(prev)) prev.push(item);
548
- else data[currentListKey] = [item];
549
- continue;
550
- }
551
- const kv = /^([A-Za-z0-9_-]+):\s*(.*)$/.exec(line);
552
- if (!kv) {
553
- if (line.trim()) currentListKey = void 0;
554
- continue;
555
- }
556
- let value = kv[2].trim();
557
- if (!value) {
558
- currentListKey = kv[1];
559
- data[kv[1]] = "";
560
- continue;
561
- }
562
- currentListKey = void 0;
563
- if (value.startsWith("[") && value.endsWith("]")) {
564
- data[kv[1]] = value.slice(1, -1).split(",").map((s) => s.trim().replace(/^["']|["']$/g, "")).filter(Boolean);
565
- continue;
566
- }
567
- if (/^(["']).*\1$/.test(value)) value = value.slice(1, -1);
568
- data[kv[1]] = value;
569
- }
570
- return { data, body: text.slice(match[0].length) };
571
- }
572
- var str = (v) => Array.isArray(v) ? v.join(", ") : v;
573
- function dirs(r, kind) {
574
- return [join3(r.userHome, ".claude", kind), join3(r.home, kind), join3(r.cwd, ".claude", kind), join3(r.cwd, ".bccli", kind)];
575
- }
576
- function list(dir) {
577
- try {
578
- return readdirSync(dir).sort();
579
- } catch {
580
- return [];
581
- }
582
- }
583
- function loadSkills(r) {
584
- const byName = /* @__PURE__ */ new Map();
585
- for (const dir of dirs(r, "skills")) {
586
- for (const entry of list(dir)) {
587
- const file = join3(dir, entry, "SKILL.md");
588
- if (!existsSync4(file)) continue;
589
- const { data } = parseFrontmatter(readFileSync2(file, "utf8"));
590
- const name = str(data.name) || entry;
591
- byName.set(name, { name, description: str(data.description) ?? "", dir: join3(dir, entry), file });
592
- }
593
- }
594
- return [...byName.values()];
595
- }
596
- function loadCommands(r) {
597
- const byName = /* @__PURE__ */ new Map();
598
- for (const dir of dirs(r, "commands")) {
599
- for (const entry of list(dir)) {
600
- const file = join3(dir, entry);
601
- if (!entry.endsWith(".md") || !statSync(file).isFile()) continue;
602
- const { data, body } = parseFrontmatter(readFileSync2(file, "utf8"));
603
- const def = { name: basename(entry, ".md"), body: body.trim() };
604
- if (data.description) def.description = str(data.description);
605
- if (data["argument-hint"]) def.argumentHint = str(data["argument-hint"]);
606
- byName.set(def.name, def);
607
- }
608
- }
609
- return [...byName.values()];
610
- }
611
- function loadAgentDefs(r) {
612
- const byName = /* @__PURE__ */ new Map();
613
- for (const dir of dirs(r, "agents")) {
614
- for (const entry of list(dir)) {
615
- if (!entry.endsWith(".md")) continue;
616
- const { data, body } = parseFrontmatter(readFileSync2(join3(dir, entry), "utf8"));
617
- const name = str(data.name) || basename(entry, ".md");
618
- const def = { name, description: str(data.description) ?? "", prompt: body.trim() };
619
- if (data.tools)
620
- def.tools = Array.isArray(data.tools) ? data.tools : String(data.tools).split(",").map((s) => s.trim()).filter(Boolean);
621
- if (data.model) def.model = str(data.model);
622
- if (str(data.parallel) === "true") def.parallel = true;
623
- const rawMaxSteps = str(data.maxSteps ?? data["max-steps"]);
624
- if (rawMaxSteps) {
625
- const maxSteps = Number(rawMaxSteps);
626
- if (Number.isFinite(maxSteps) && maxSteps > 0) def.maxSteps = Math.max(1, Math.floor(maxSteps));
627
- }
628
- byName.set(name, def);
629
- }
630
- }
631
- return [...byName.values()];
632
- }
633
-
634
- // src/hooks.ts
635
- import { spawn as spawn2 } from "child_process";
636
- var DEFAULT_TIMEOUT_MS = 1e4;
637
- var MAX_CAPTURE = 8192;
638
- function globToRegExp(pattern) {
639
- const escaped = pattern.replace(/[.*+?^${}()|[\]\\]/g, "\\$&").replace(/\\\*/g, ".*");
640
- return new RegExp(`^${escaped}$`);
641
- }
642
- function runOne(command, event, payload, opts) {
643
- const env = {
644
- ...process.env,
645
- ...opts.env,
646
- BCCLI_HOOK_EVENT: event,
647
- ...payload.tool !== void 0 ? { BCCLI_HOOK_TOOL: payload.tool } : {},
648
- ...payload.input !== void 0 ? { BCCLI_HOOK_INPUT: JSON.stringify(payload.input) } : {},
649
- ...payload.output !== void 0 ? { BCCLI_HOOK_OUTPUT: payload.output } : {}
650
- };
651
- return new Promise((resolve3) => {
652
- let stdout = "";
653
- let stderr = "";
654
- let timedOut = false;
655
- let settled = false;
656
- const finish = (result) => {
657
- if (settled) return;
658
- settled = true;
659
- clearTimeout(timer);
660
- resolve3(result);
661
- };
662
- let child;
663
- const shell = defaultShell();
664
- try {
665
- if (shell) {
666
- child = spawn2(shell.file, shell.args(command), {
667
- shell: false,
668
- env,
669
- cwd: opts.cwd ?? process.cwd(),
670
- stdio: ["ignore", "pipe", "pipe"]
671
- });
672
- } else {
673
- child = spawn2(command, { shell: true, env, cwd: opts.cwd ?? process.cwd(), stdio: ["ignore", "pipe", "pipe"] });
674
- }
675
- } catch (error) {
676
- resolve3({ failure: error.message });
677
- return;
678
- }
679
- const timer = setTimeout(() => {
680
- timedOut = true;
681
- child.kill();
682
- }, opts.timeoutMs ?? DEFAULT_TIMEOUT_MS);
683
- child.stdout?.on("data", (chunk) => {
684
- if (stdout.length < MAX_CAPTURE) stdout += String(chunk);
685
- });
686
- child.stderr?.on("data", (chunk) => {
687
- if (stderr.length < MAX_CAPTURE) stderr += String(chunk);
688
- });
689
- child.on("error", (error) => finish({ failure: error.message }));
690
- child.on("close", (code) => {
691
- if (timedOut) {
692
- finish({ failure: "timed out" });
693
- return;
694
- }
695
- if (event === "PreToolUse" && code === 2) {
696
- finish({ blocked: stderr.trim() || stdout.trim() || "Blocked by a PreToolUse hook." });
697
- return;
698
- }
699
- if (code !== 0) {
700
- const detail = stderr.trim().split("\n")[0];
701
- finish({ failure: detail ? `exit ${code}: ${detail}` : `exit ${code}` });
702
- return;
703
- }
704
- finish({});
705
- });
706
- });
707
- }
708
- async function runHooks(hooks, event, payload = {}, opts = {}) {
709
- const rules = hooks?.[event];
710
- if (!Array.isArray(rules) || rules.length === 0) return { warnings: [] };
711
- const warnings = [];
712
- let blocked;
713
- for (const rule of rules) {
714
- if (!rule || typeof rule.command !== "string" || rule.command.length === 0) continue;
715
- if (payload.tool !== void 0 && rule.match && !globToRegExp(rule.match).test(payload.tool)) continue;
716
- const result = await runOne(rule.command, event, payload, opts);
717
- if (result.blocked) {
718
- blocked = result.blocked;
719
- break;
720
- }
721
- if (result.failure) warnings.push(t("Hook {event} failed: {reason}", { event, reason: result.failure }));
722
- }
723
- return { blocked, warnings };
724
- }
725
-
726
- // src/tools/paths.ts
727
- import { statSync as statSync2 } from "fs";
728
- import { isAbsolute, resolve } from "path";
729
- var readMtimes = /* @__PURE__ */ new WeakMap();
730
- function resolvePath(cwd, path) {
731
- return isAbsolute(path) ? path : resolve(cwd, path);
732
- }
733
- function errorCode(error) {
734
- return error.code ?? error.message;
735
- }
736
- function recordFileMtime(readFiles, abs) {
737
- readFiles.add(abs);
738
- try {
739
- let map = readMtimes.get(readFiles);
740
- if (!map) {
741
- map = /* @__PURE__ */ new Map();
742
- readMtimes.set(readFiles, map);
743
- }
744
- map.set(abs, statSync2(abs).mtimeMs);
745
- } catch {
746
- }
747
- }
748
- function isFileModifiedSinceRead(readFiles, abs) {
749
- const recorded = readMtimes.get(readFiles)?.get(abs);
750
- if (recorded === void 0) return false;
751
- try {
752
- return statSync2(abs).mtimeMs > recorded + 50;
753
- } catch {
754
- return false;
755
- }
756
- }
757
-
758
- // src/slash/memory.ts
759
- import { appendFileSync, existsSync as existsSync5, readFileSync as readFileSync3 } from "fs";
760
- function instructionFiles(cwd, home) {
761
- return instructionPaths(cwd, home).filter((path) => existsSync5(path)).map((path) => ({ path, lines: readFileSync3(path, "utf8").split("\n").filter(Boolean).length }));
762
- }
763
- function appendMemory(file, text) {
764
- const prefix = existsSync5(file) && !readFileSync3(file, "utf8").endsWith("\n") ? "\n" : "";
765
- appendFileSync(file, `${prefix}- ${text.trim()}
766
- `);
767
- }
768
- function parseMemoryArgs(args) {
769
- const match = /^global(?:\s+|$)/i.exec(args.trim());
770
- return match ? { global: true, text: args.trim().slice(match[0].length).trim() } : { global: false, text: args.trim() };
771
- }
772
-
773
- // src/tools/ignore.ts
774
- import { readFileSync as readFileSync4 } from "fs";
775
- import { dirname as dirname2, join as join4, resolve as resolve2 } from "path";
776
- function ignorePatterns(root, projectRoot) {
777
- const patterns = ["**/node_modules/**", "**/.git/**"];
778
- const seen = /* @__PURE__ */ new Set();
779
- const dirs2 = [];
780
- let cur = resolve2(root);
781
- const stop = projectRoot ? resolve2(projectRoot) : cur;
782
- while (true) {
783
- if (!seen.has(cur)) {
784
- seen.add(cur);
785
- dirs2.push(cur);
786
- }
787
- if (cur === stop || !cur.startsWith(stop)) break;
788
- const parent = dirname2(cur);
789
- if (parent === cur) break;
790
- cur = parent;
791
- }
792
- for (const dir of dirs2) {
793
- let lines = [];
794
- try {
795
- lines = readFileSync4(join4(dir, ".gitignore"), "utf8").split(/\r?\n/);
796
- } catch {
797
- continue;
798
- }
799
- for (const raw of lines) {
800
- const line = raw.trim();
801
- if (!line || line.startsWith("#") || line.startsWith("!")) continue;
802
- const p = line.replace(/^\//, "").replace(/\/$/, "");
803
- patterns.push(`**/${p}`, `**/${p}/**`);
804
- }
805
- }
806
- return [...new Set(patterns)];
807
- }
808
-
809
- // src/tools/globSafety.ts
810
- var MAX_GLOB_LENGTH = 4096;
811
- var MAX_BRACE_DEPTH = 16;
812
- function validateGlobPattern(pattern) {
813
- if (pattern.length > MAX_GLOB_LENGTH) return `Glob pattern is too long (max ${MAX_GLOB_LENGTH} characters).`;
814
- let depth = 0;
815
- let escaped = false;
816
- for (const char of pattern) {
817
- if (escaped) {
818
- escaped = false;
819
- continue;
820
- }
821
- if (char === "\\") {
822
- escaped = true;
823
- continue;
824
- }
825
- if (char === "{") {
826
- depth++;
827
- if (depth > MAX_BRACE_DEPTH) return `Glob brace nesting is too deep (max ${MAX_BRACE_DEPTH}).`;
828
- } else if (char === "}" && depth > 0) {
829
- depth--;
830
- }
831
- }
832
- return void 0;
833
- }
834
- function normalizeGlobPath(path) {
835
- return path.replaceAll("\\", "/");
836
- }
837
-
838
- export {
839
- resolveShell,
840
- runHooks,
841
- renderBackgroundTasks,
842
- runCommand,
843
- createBashTool,
844
- bashTool,
845
- resolvePath,
846
- errorCode,
847
- recordFileMtime,
848
- isFileModifiedSinceRead,
849
- ignorePatterns,
850
- validateGlobPattern,
851
- normalizeGlobPath,
852
- BUILTIN_AGENTS,
853
- buildSystemPrompt,
854
- parseFrontmatter,
855
- loadSkills,
856
- loadCommands,
857
- loadAgentDefs,
858
- instructionFiles,
859
- appendMemory,
860
- parseMemoryArgs
861
- };