@akanjs/cli 3.0.0-beta.16 → 3.0.0-beta.17

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/.build-stamp CHANGED
@@ -1 +1 @@
1
- 6491b2d0e0e0215fa142863a77651ee2089f845be399582cd40b8149669b2a6f
1
+ 8adda265985140249a01af8a9966dd10b8dd38c2c3dd887ea8919e4aeff4a70e
@@ -1,8 +1,8 @@
1
1
  // @bun
2
2
  import {
3
3
  CodeAgent2
4
- } from "./index-5405kc0x.js";
5
- import"./index-jgrnpt6y.js";
4
+ } from "./index-2sq06vv0.js";
5
+ import"./index-qt8dqgnf.js";
6
6
  import"./index-7md2g9vw.js";
7
7
  export {
8
8
  CodeAgent2 as CodeAgent
@@ -1,16 +1,18 @@
1
1
  // @bun
2
2
  import {
3
- SubagentPool2
4
- } from "./index-jgrnpt6y.js";
3
+ SubagentPool2,
4
+ McpServerConfig
5
+ } from "./index-qt8dqgnf.js";
5
6
  import {
7
+ CodeTuiLines2,
8
+ CodeTuiAgents2,
6
9
  CodeTuiClipboard2,
7
10
  CodeTuiCommands2,
8
- CodeTuiLines2,
9
11
  CodeTuiEditor2,
10
12
  CodeTuiFiles2,
11
13
  CodeTuiMarkdown2,
12
14
  CodeTuiParts2
13
- } from "./index-sxg87a8f.js";
15
+ } from "./index-bzakk0c2.js";
14
16
 
15
17
  // pkgs/@akanjs/cli/code/CodeTui.tsx
16
18
  import {
@@ -22,6 +24,41 @@ import { render } from "ink";
22
24
  // pkgs/@akanjs/cli/ui/CodeTuiApp.tsx
23
25
  import { Box, Text, useCursor, useInput } from "ink";
24
26
  import { useEffect, useRef, useState } from "react";
27
+
28
+ // pkgs/@akanjs/cli/code/CodeTuiMouse.ts
29
+ class CodeTuiMouse {
30
+ static on = "\x1B[?1000h\x1B[?1006h";
31
+ static off = "\x1B[?1006l\x1B[?1000l";
32
+ static step = 3;
33
+ #pending = 0;
34
+ read(input) {
35
+ if (this.#pending) {
36
+ const button = (input.codePointAt(0) ?? 32) - 32;
37
+ const rest = input.slice(this.#pending);
38
+ this.#pending = 0;
39
+ return { rows: CodeTuiMouse.rowsOf(button), rest };
40
+ }
41
+ const sgr = /^\[<(\d+);\d+;\d+[Mm]$/.exec(input);
42
+ if (sgr)
43
+ return { rows: CodeTuiMouse.rowsOf(Number(sgr[1])), rest: "" };
44
+ if (input !== "[M")
45
+ return;
46
+ this.#pending = 3;
47
+ return { rows: 0, rest: "" };
48
+ }
49
+ static rowsOf(button) {
50
+ if (!(button & 64))
51
+ return 0;
52
+ const direction = button & 3;
53
+ if (direction === 0)
54
+ return -CodeTuiMouse.step;
55
+ if (direction === 1)
56
+ return CodeTuiMouse.step;
57
+ return 0;
58
+ }
59
+ }
60
+
61
+ // pkgs/@akanjs/cli/ui/CodeTuiApp.tsx
25
62
  import { jsxDEV } from "react/jsx-dev-runtime";
26
63
  var promptMarkWidth = 2;
27
64
  var pasteOpen = "[200~";
@@ -113,6 +150,7 @@ var Menu = ({ options, selected, marker, checked }) => /* @__PURE__ */ jsxDEV(Bo
113
150
  var CodeTuiApp = ({ actions }) => {
114
151
  const [snapshot, setSnapshot] = useState(actions.snapshot);
115
152
  const pasting = useRef(null);
153
+ const mouse = useRef(new CodeTuiMouse);
116
154
  const { setCursorPosition } = useCursor();
117
155
  useEffect(() => {
118
156
  const unsubscribe = actions.subscribe(() => setSnapshot(actions.snapshot()));
@@ -136,6 +174,14 @@ var CodeTuiApp = ({ actions }) => {
136
174
  ` : key.tab ? "\t" : input);
137
175
  return;
138
176
  }
177
+ const wheel = mouse.current.read(input);
178
+ if (wheel) {
179
+ if (wheel.rows)
180
+ actions.scroll(wheel.rows);
181
+ if (wheel.rest)
182
+ actions.type(wheel.rest);
183
+ return;
184
+ }
139
185
  if (key.ctrl && input === "c")
140
186
  return actions.interrupt();
141
187
  if (key.pageUp)
@@ -267,6 +313,12 @@ var CodeTuiApp = ({ actions }) => {
267
313
  }, undefined, false, undefined, this) : null
268
314
  ]
269
315
  }, undefined, true, undefined, this),
316
+ snapshot.subagents.length ? /* @__PURE__ */ jsxDEV(Box, {
317
+ flexDirection: "column",
318
+ children: snapshot.subagents.map((line) => /* @__PURE__ */ jsxDEV(Line, {
319
+ line
320
+ }, line.key, false, undefined, this))
321
+ }, undefined, false, undefined, this) : null,
270
322
  /* @__PURE__ */ jsxDEV(Rule, {
271
323
  spans: snapshot.bottomRule
272
324
  }, undefined, false, undefined, this),
@@ -283,6 +335,79 @@ var CodeTuiApp = ({ actions }) => {
283
335
  }, undefined, true, undefined, this);
284
336
  };
285
337
 
338
+ // pkgs/@akanjs/cli/code/CodeTuiMcp.ts
339
+ class CodeTuiMcp {
340
+ static namePattern = /^[a-zA-Z0-9_-]+$/;
341
+ static usage = [
342
+ "/mcp add <name> <command> [args\u2026] declare a server this session starts",
343
+ "/mcp add <name> <https://\u2026> declare one it reaches over http",
344
+ "/mcp remove <name> undeclare it",
345
+ "/mcp reload reopen this session so the file takes effect"
346
+ ];
347
+ static list(view) {
348
+ const lines = view.problem ? [view.problem, ""] : [];
349
+ const rows = CodeTuiMcp.#rows(view);
350
+ if (!rows.length)
351
+ return [
352
+ ...lines,
353
+ "No MCP server is declared.",
354
+ "",
355
+ `Declare one here, or paste an editor's \`mcpServers\` block into ${view.file}.`,
356
+ "",
357
+ ...CodeTuiMcp.usage
358
+ ].join(`
359
+ `);
360
+ const width = (at) => Math.max(...rows.map((row) => (row[at] ?? "").length)) + 2;
361
+ const [name, transport, target] = [width(0), width(1), width(2)];
362
+ return [
363
+ ...lines,
364
+ `${rows.length} server${rows.length === 1 ? "" : "s"} \xB7 ${view.file}`,
365
+ "",
366
+ ...rows.map(([a, b, c, d]) => `${(a ?? "").padEnd(name)}${(b ?? "").padEnd(transport)}${(c ?? "").padEnd(target)}${d ?? ""}`),
367
+ "",
368
+ ...CodeTuiMcp.usage
369
+ ].join(`
370
+ `);
371
+ }
372
+ static #rows(view) {
373
+ const byName = new Map;
374
+ for (const entry of view.declared)
375
+ byName.set(entry.ref.name, { ref: entry.ref, disabled: entry.disabled });
376
+ for (const live of view.status)
377
+ byName.set(live.name, { ...byName.get(live.name), live });
378
+ return [...byName].sort(([a], [b]) => a.localeCompare(b)).map(([name, entry]) => {
379
+ const transport = entry.live?.transport ?? entry.ref?.transport ?? "";
380
+ const target = entry.live?.target ?? CodeTuiMcp.targetOf(entry.ref);
381
+ return [name, transport, target, CodeTuiMcp.#stateOf(entry)];
382
+ });
383
+ }
384
+ static #stateOf(entry) {
385
+ if (entry.disabled)
386
+ return "disabled in the file";
387
+ if (!entry.live)
388
+ return "declared \xB7 /mcp reload to connect";
389
+ if (entry.live.error)
390
+ return `unreachable \u2014 ${entry.live.error}`;
391
+ if (!entry.ref)
392
+ return `${entry.live.tools.length} tools \xB7 removed from the file`;
393
+ return `${entry.live.tools.length} tool${entry.live.tools.length === 1 ? "" : "s"}`;
394
+ }
395
+ static targetOf(ref) {
396
+ if (!ref)
397
+ return "";
398
+ return ref.url ?? [ref.command, ...ref.args ?? []].filter(Boolean).join(" ");
399
+ }
400
+ static tools(status) {
401
+ if (status.error)
402
+ return `${status.name} is unreachable \u2014 ${status.error}`;
403
+ if (!status.tools.length)
404
+ return `${status.name} connected and published no tools.`;
405
+ return [`${status.name} \xB7 ${status.target}`, "", status.tools.join(`
406
+ `)].join(`
407
+ `);
408
+ }
409
+ }
410
+
286
411
  // pkgs/@akanjs/cli/code/CodeTui.tsx
287
412
  import { jsxDEV as jsxDEV2 } from "react/jsx-dev-runtime";
288
413
 
@@ -360,7 +485,7 @@ class CodeTui {
360
485
  });
361
486
  }
362
487
  async run(seed) {
363
- this.#stdout.write(CodeTui.pasteOn);
488
+ this.#stdout.write(`${CodeTui.pasteOn}${CodeTuiMouse.on}`);
364
489
  if (this.#opening)
365
490
  this.#say(this.#opening);
366
491
  this.#unsubscribe = this.#agent.on((event) => {
@@ -433,10 +558,10 @@ class CodeTui {
433
558
  for (const listener of this.#listeners)
434
559
  listener();
435
560
  }
436
- static layout(frameRows, askRows) {
437
- const room = Math.max(1, frameRows - CodeTui.minBodyRows - CodeTui.chromeRows);
561
+ static layout(frameRows, askRows, railRows = 0) {
562
+ const room = Math.max(1, frameRows - CodeTui.minBodyRows - CodeTui.chromeRows - railRows);
438
563
  const ask = Math.max(1, Math.min(askRows, room));
439
- return { ask, bodyHeight: Math.max(CodeTui.minBodyRows, frameRows - ask - CodeTui.chromeRows) };
564
+ return { ask, bodyHeight: Math.max(CodeTui.minBodyRows, frameRows - ask - CodeTui.chromeRows - railRows) };
440
565
  }
441
566
  static frameRowsOf(terminalRows) {
442
567
  return Math.max(CodeTui.minBodyRows + CodeTui.chromeRows + 1, terminalRows - 1);
@@ -449,8 +574,9 @@ class CodeTui {
449
574
  const question = this.#transcript.question;
450
575
  const approval = this.#transcript.approval;
451
576
  const mode = CodeTui.#modeOf(question, approval);
452
- const ask = mode === "input" ? this.#inputBlock(columns, frameRows) : this.#askBlock(question, frameRows);
453
- const { bodyHeight } = CodeTui.layout(frameRows, ask.rows);
577
+ const subagents = this.#railRows(columns);
578
+ const ask = mode === "input" ? this.#inputBlock(columns, frameRows - subagents.length) : this.#askBlock(question, frameRows - subagents.length);
579
+ const { bodyHeight } = CodeTui.layout(frameRows, ask.rows, subagents.length);
454
580
  const width = columns - 2;
455
581
  const lines = this.#lines(width);
456
582
  const end = this.#anchor === null ? lines.length : Math.min(lines.length, Math.max(bodyHeight, this.#anchor));
@@ -466,6 +592,7 @@ class CodeTui {
466
592
  following: this.#anchor === null,
467
593
  overlay: this.#overlayBlock(width, bodyHeight),
468
594
  status: this.#status(),
595
+ subagents,
469
596
  mode,
470
597
  placeholder: this.#transcript.streaming ? "type to steer, esc to interrupt" : "ask for something, / for commands",
471
598
  offered: this.#offered,
@@ -489,6 +616,14 @@ class CodeTui {
489
616
  ...CodeTuiParts2.lines(this.#transcript.parts, width, { thinking: this.#thinking })
490
617
  ];
491
618
  }
619
+ #railRows(columns) {
620
+ const agents = this.#transcript.subagents;
621
+ if (!agents.length)
622
+ return [];
623
+ const rows = CodeTuiAgents2.rows(agents, this.#transcript.info?.name ?? "main", columns);
624
+ const room = CodeTui.frameRowsOf(Math.max(10, this.#stdout.rows || 24)) - CodeTui.minBodyRows - CodeTui.chromeRows - 2 * CodeTui.promptRuleRows - 1;
625
+ return rows.length <= room ? rows : [];
626
+ }
492
627
  #banner() {
493
628
  const cwd = this.#transcript.info?.cwd;
494
629
  return [
@@ -848,7 +983,7 @@ class CodeTui {
848
983
  if (this.#exiting)
849
984
  return;
850
985
  this.#exiting = true;
851
- this.#stdout.write(CodeTui.pasteOff);
986
+ this.#stdout.write(`${CodeTuiMouse.off}${CodeTui.pasteOff}`);
852
987
  this.#instance.clear();
853
988
  this.#instance.unmount();
854
989
  }
@@ -995,6 +1130,8 @@ ${tools.join(" \xB7 ")}`);
995
1130
  return this.#fork(argument);
996
1131
  case "agents":
997
1132
  return this.#open("agents", this.#agentList());
1133
+ case "mcp":
1134
+ return this.#mcp(argument);
998
1135
  case "name":
999
1136
  if (!argument)
1000
1137
  return this.#open("name", "Usage: /name <what this session is about>");
@@ -1021,6 +1158,54 @@ ${CodeTuiCommands2.help()}`);
1021
1158
  ].join(`
1022
1159
  `);
1023
1160
  }
1161
+ #mcp(argument) {
1162
+ const [verb, name, ...rest] = argument.split(" ").filter(Boolean);
1163
+ const root = this.#agent.workspaceRoot;
1164
+ if (!verb)
1165
+ return this.#open("mcp", CodeTuiMcp.list(this.#mcpView()));
1166
+ if (verb === "reload")
1167
+ return this.#reload("reconnected the MCP servers");
1168
+ if (verb !== "add" && verb !== "remove") {
1169
+ const status = this.#agent.mcpServers().find((entry) => entry.name === verb);
1170
+ if (status)
1171
+ return this.#open(`mcp \xB7 ${verb}`, CodeTuiMcp.tools(status));
1172
+ return this.#open("mcp", [`There is no /mcp ${verb}.`, "", ...CodeTuiMcp.usage].join(`
1173
+ `));
1174
+ }
1175
+ if (!name)
1176
+ return this.#open("mcp", [`Usage:`, "", ...CodeTuiMcp.usage].join(`
1177
+ `));
1178
+ if (!CodeTuiMcp.namePattern.test(name))
1179
+ return this.#open("mcp", `"${name}" cannot name a server: letters, digits, dash and underscore only.`);
1180
+ try {
1181
+ if (verb === "remove") {
1182
+ if (!McpServerConfig.remove(root, name))
1183
+ return this.#open("mcp", `No server named "${name}" is declared.`);
1184
+ return this.#reload(`removed ${name}`);
1185
+ }
1186
+ const ref = McpServerConfig.add(root, name, rest);
1187
+ return this.#reload(`added ${name} \xB7 ${McpServerConfig.targetOf(ref)}`);
1188
+ } catch (error) {
1189
+ this.#fail(error);
1190
+ }
1191
+ }
1192
+ #mcpView() {
1193
+ const root = this.#agent.workspaceRoot;
1194
+ const problem = McpServerConfig.problem(root);
1195
+ return {
1196
+ status: this.#agent.mcpServers(),
1197
+ declared: McpServerConfig.declared(root),
1198
+ file: McpServerConfig.file(root),
1199
+ ...problem ? { problem } : {}
1200
+ };
1201
+ }
1202
+ #reload(notice) {
1203
+ const id = this.#transcript.info?.sessionId;
1204
+ if (!id || !this.#agent.sessions().some((entry) => entry.id === id))
1205
+ return this.#open("mcp", "This session is not on disk yet, so there is nothing to reopen. Say something first, or start a new `akan code`.");
1206
+ this.#switchTo = { id, notice };
1207
+ this.#quit();
1208
+ }
1024
1209
  static #peerList(peers) {
1025
1210
  if (!peers.length)
1026
1211
  return "No other akan code session is running in this workspace.";
package/akanCode.js CHANGED
@@ -11,14 +11,12 @@ import {
11
11
  VerifyFeedback2,
12
12
  AkanToolPack2,
13
13
  MailToolPack2,
14
- akanCodePaths2,
15
14
  McpClient2,
16
15
  McpToolPack2,
17
16
  SessionToolPack2,
18
17
  WebToolPack2,
19
18
  AkanCodePlugins2,
20
19
  AkanEnvKeys2,
21
- AkanAuthStorageBackend2,
22
20
  akanSystemPrompt2,
23
21
  CodeSessionIndex2,
24
22
  AkanCodeServices2,
@@ -29,32 +27,33 @@ import {
29
27
  CodeMailbox2,
30
28
  CodeSessionFork2,
31
29
  CodeAgent2
32
- } from "./index-5405kc0x.js";
30
+ } from "./index-2sq06vv0.js";
33
31
  import {
34
32
  akanCodeDefaultModel2,
35
33
  akanCodeModel2,
36
34
  akanCodeModelSupportsImages2,
37
35
  akanCodeModelWarnings2,
38
36
  CodeAgentStreamPrinter2
39
- } from "./index-wfwknnje.js";
37
+ } from "./index-jwrpsrg3.js";
40
38
  import {
41
- SubagentPool2
42
- } from "./index-jgrnpt6y.js";
39
+ SubagentPool2,
40
+ akanCodePaths2
41
+ } from "./index-qt8dqgnf.js";
43
42
  import"./index-7md2g9vw.js";
44
43
  import {
45
44
  CodeAgentRpcHost2
46
45
  } from "./index-8k16atqy.js";
47
46
  import {
47
+ CodeTuiLines2,
48
+ CodeTuiAgents2,
48
49
  CodeTuiClipboard2,
49
50
  CodeTuiCommands2,
50
- CodeTuiLines2,
51
51
  CodeTuiEditor2,
52
52
  CodeTuiFiles2,
53
53
  CodeTuiMarkdown2,
54
54
  CodeTuiParts2
55
- } from "./index-sxg87a8f.js";
55
+ } from "./index-bzakk0c2.js";
56
56
  export {
57
- AkanAuthStorageBackend2 as AkanAuthStorageBackend,
58
57
  AkanCli2 as AkanCli,
59
58
  AkanCodePlugins2 as AkanCodePlugins,
60
59
  AkanCodeServices2 as AkanCodeServices,
@@ -72,6 +71,7 @@ export {
72
71
  CodeMailbox2 as CodeMailbox,
73
72
  CodeSessionFork2 as CodeSessionFork,
74
73
  CodeSessionIndex2 as CodeSessionIndex,
74
+ CodeTuiAgents2 as CodeTuiAgents,
75
75
  CodeTuiClipboard2 as CodeTuiClipboard,
76
76
  CodeTuiCommands2 as CodeTuiCommands,
77
77
  CodeTuiEditor2 as CodeTuiEditor,
@@ -14,11 +14,11 @@ import"./index-3mg4h788.js";
14
14
  import"./index-hwkygn9s.js";
15
15
  import"./index-7md2g9vw.js";
16
16
  import"./index-kcxmv48c.js";
17
- import"./index-018dszb3.js";
17
+ import"./index-p0tew3fq.js";
18
18
  import"./index-57p9p179.js";
19
19
  import {
20
20
  CloudScript2
21
- } from "./index-zg0v1zte.js";
21
+ } from "./index-n8kt2wh6.js";
22
22
  import"./index-sn7dnzq4.js";
23
23
 
24
24
  // pkgs/@akanjs/cli/cloud/cloud.command.ts
@@ -1,12 +1,12 @@
1
1
  // @bun
2
2
  import {
3
3
  CloudScript2
4
- } from "./index-zg0v1zte.js";
4
+ } from "./index-n8kt2wh6.js";
5
5
  import"./index-57p9p179.js";
6
6
  import"./index-ns128c4q.js";
7
7
  import"./index-sn7dnzq4.js";
8
8
  import"./index-3mg4h788.js";
9
- import"./index-018dszb3.js";
9
+ import"./index-p0tew3fq.js";
10
10
  import"./index-myj01w9r.js";
11
11
  import"./index-6na0sd2b.js";
12
12
  import"./index-7md2g9vw.js";
@@ -11,7 +11,7 @@ import"./index-6wwzs1bc.js";
11
11
  import {
12
12
  akanCodeDefaultModel2,
13
13
  CodeAgentStreamPrinter2
14
- } from "./index-wfwknnje.js";
14
+ } from "./index-jwrpsrg3.js";
15
15
 
16
16
  // pkgs/@akanjs/cli/code/code.runner.ts
17
17
  import { codeAgentPresets, isCodeAgentPresetName } from "akanjs/common";
@@ -20,7 +20,7 @@ class CodeRunner extends runner("code") {
20
20
  async serve(options) {
21
21
  await import("./consoleToStderr-h5bryj94.js");
22
22
  const [{ CodeAgent }, { CodeAgentRpcHost }] = await Promise.all([
23
- import("./CodeAgent-zgccwajm.js"),
23
+ import("./CodeAgent-gjqnc2mg.js"),
24
24
  import("./CodeAgentRpcHost-qvwfv0n9.js")
25
25
  ]);
26
26
  const profile = CodeRunner.profileOf(options);
@@ -36,8 +36,8 @@ class CodeRunner extends runner("code") {
36
36
  }
37
37
  async tui(options, seed) {
38
38
  const [{ CodeAgent }, { CodeTui }] = await Promise.all([
39
- import("./CodeAgent-zgccwajm.js"),
40
- import("./CodeTui-993tx7gf.js")
39
+ import("./CodeAgent-gjqnc2mg.js"),
40
+ import("./CodeTui-nd9hqvrw.js")
41
41
  ]);
42
42
  const profile = CodeRunner.profileOf(options);
43
43
  const apps = options.app ? [options.app] : await options.workspace.getApps();
@@ -71,7 +71,7 @@ class CodeRunner extends runner("code") {
71
71
  }
72
72
  }
73
73
  async run(prompt, options) {
74
- const { CodeAgent } = await import("./CodeAgent-zgccwajm.js");
74
+ const { CodeAgent } = await import("./CodeAgent-gjqnc2mg.js");
75
75
  const profile = CodeRunner.profileOf(options);
76
76
  const agent = await CodeAgent.create({
77
77
  workspace: options.workspace,