@teammates/cli 0.1.0 → 0.2.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/README.md +31 -22
- package/dist/adapter.d.ts +1 -1
- package/dist/adapter.js +68 -56
- package/dist/adapter.test.js +34 -21
- package/dist/adapters/cli-proxy.d.ts +11 -4
- package/dist/adapters/cli-proxy.js +176 -162
- package/dist/adapters/copilot.d.ts +50 -0
- package/dist/adapters/copilot.js +210 -0
- package/dist/adapters/echo.d.ts +2 -2
- package/dist/adapters/echo.js +2 -1
- package/dist/adapters/echo.test.js +4 -2
- package/dist/cli-utils.d.ts +21 -0
- package/dist/cli-utils.js +74 -0
- package/dist/cli-utils.test.d.ts +1 -0
- package/dist/cli-utils.test.js +179 -0
- package/dist/cli.js +3160 -961
- package/dist/compact.d.ts +39 -0
- package/dist/compact.js +269 -0
- package/dist/compact.test.d.ts +1 -0
- package/dist/compact.test.js +198 -0
- package/dist/console/ansi.d.ts +18 -0
- package/dist/console/ansi.js +20 -0
- package/dist/console/ansi.test.d.ts +1 -0
- package/dist/console/ansi.test.js +50 -0
- package/dist/console/dropdown.d.ts +23 -0
- package/dist/console/dropdown.js +63 -0
- package/dist/console/file-drop.d.ts +59 -0
- package/dist/console/file-drop.js +186 -0
- package/dist/console/file-drop.test.d.ts +1 -0
- package/dist/console/file-drop.test.js +145 -0
- package/dist/console/index.d.ts +22 -0
- package/dist/console/index.js +23 -0
- package/dist/console/interactive-readline.d.ts +65 -0
- package/dist/console/interactive-readline.js +132 -0
- package/dist/console/markdown-table.d.ts +17 -0
- package/dist/console/markdown-table.js +270 -0
- package/dist/console/markdown-table.test.d.ts +1 -0
- package/dist/console/markdown-table.test.js +130 -0
- package/dist/console/mutable-output.d.ts +21 -0
- package/dist/console/mutable-output.js +51 -0
- package/dist/console/paste-handler.d.ts +63 -0
- package/dist/console/paste-handler.js +177 -0
- package/dist/console/prompt-box.d.ts +55 -0
- package/dist/console/prompt-box.js +120 -0
- package/dist/console/prompt-input.d.ts +136 -0
- package/dist/console/prompt-input.js +618 -0
- package/dist/console/startup.d.ts +20 -0
- package/dist/console/startup.js +138 -0
- package/dist/console/startup.test.d.ts +1 -0
- package/dist/console/startup.test.js +41 -0
- package/dist/console/wordwheel.d.ts +75 -0
- package/dist/console/wordwheel.js +123 -0
- package/dist/dropdown.js +4 -21
- package/dist/index.d.ts +5 -5
- package/dist/index.js +3 -3
- package/dist/onboard.d.ts +24 -0
- package/dist/onboard.js +174 -11
- package/dist/orchestrator.d.ts +8 -11
- package/dist/orchestrator.js +33 -81
- package/dist/orchestrator.test.js +59 -79
- package/dist/registry.d.ts +1 -1
- package/dist/registry.js +56 -12
- package/dist/registry.test.js +57 -13
- package/dist/theme.d.ts +56 -0
- package/dist/theme.js +54 -0
- package/dist/types.d.ts +18 -13
- package/package.json +8 -3
- package/template/CROSS-TEAM.md +2 -2
- package/template/PROTOCOL.md +72 -15
- package/template/README.md +2 -2
- package/template/TEMPLATE.md +118 -15
- package/template/example/SOUL.md +2 -1
- package/template/example/WISDOM.md +9 -0
- package/dist/adapters/codex.d.ts +0 -50
- package/dist/adapters/codex.js +0 -213
- package/template/example/MEMORIES.md +0 -26
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Animated startup sequence for the teammates CLI.
|
|
3
|
+
*
|
|
4
|
+
* Phase 1: Reveals "teammates" letter by letter in block font, left-aligned.
|
|
5
|
+
* Phase 2: Replaces with compact "TM" block logo + stats panel to the right.
|
|
6
|
+
*/
|
|
7
|
+
import chalk from "chalk";
|
|
8
|
+
// ── Timing helpers ────────────────────────────────────────────────
|
|
9
|
+
function sleep(ms) {
|
|
10
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
11
|
+
}
|
|
12
|
+
function write(text) {
|
|
13
|
+
process.stdout.write(text);
|
|
14
|
+
}
|
|
15
|
+
// ── Block font glyphs (2 rows tall) ─────────────────────────────
|
|
16
|
+
//
|
|
17
|
+
// Each glyph is [topLine, bottomLine]. Uses Unicode half-blocks
|
|
18
|
+
// (▀ ▄ █ ▐ ▌) for a clean, compact large-text look.
|
|
19
|
+
const GLYPHS = {
|
|
20
|
+
t: ["▀█▀", " █ "],
|
|
21
|
+
e: ["█▀▀", "██▄"],
|
|
22
|
+
a: ["▄▀█", "█▀█"],
|
|
23
|
+
m: ["█▀▄▀█", "█ ▀ █"],
|
|
24
|
+
s: ["█▀", "▄█"],
|
|
25
|
+
};
|
|
26
|
+
/** Build the two-line title from a word using the block font. */
|
|
27
|
+
export function buildTitle(word) {
|
|
28
|
+
const top = [];
|
|
29
|
+
const bot = [];
|
|
30
|
+
for (const ch of word) {
|
|
31
|
+
const g = GLYPHS[ch.toLowerCase()];
|
|
32
|
+
if (g) {
|
|
33
|
+
top.push(g[0]);
|
|
34
|
+
bot.push(g[1]);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return [top.join(" "), bot.join(" ")];
|
|
38
|
+
}
|
|
39
|
+
export async function playStartup(info) {
|
|
40
|
+
const termWidth = process.stdout.columns || 100;
|
|
41
|
+
const word = "teammates";
|
|
42
|
+
const indent = " ";
|
|
43
|
+
// Hide cursor during animation
|
|
44
|
+
write("\x1b[?25l");
|
|
45
|
+
console.log();
|
|
46
|
+
// Phase 1: reveal full "teammates" title letter by letter, left-aligned
|
|
47
|
+
// Reserve two lines for the title area
|
|
48
|
+
write(`${indent}\n${indent}\n`);
|
|
49
|
+
write("\x1b[2A"); // move back up
|
|
50
|
+
let builtTop = "";
|
|
51
|
+
let builtBot = "";
|
|
52
|
+
for (const ch of word) {
|
|
53
|
+
const g = GLYPHS[ch.toLowerCase()];
|
|
54
|
+
if (!g)
|
|
55
|
+
continue;
|
|
56
|
+
if (builtTop.length > 0) {
|
|
57
|
+
builtTop += " ";
|
|
58
|
+
builtBot += " ";
|
|
59
|
+
}
|
|
60
|
+
builtTop += g[0];
|
|
61
|
+
builtBot += g[1];
|
|
62
|
+
write(`\r${indent}${chalk.cyan(builtTop)}`);
|
|
63
|
+
write(`\n\r${indent}${chalk.cyan(builtBot)}`);
|
|
64
|
+
write("\x1b[1A");
|
|
65
|
+
await sleep(60);
|
|
66
|
+
}
|
|
67
|
+
// Pause on the full title
|
|
68
|
+
await sleep(1000);
|
|
69
|
+
// Roll out version to the right of the logo on the bottom row
|
|
70
|
+
const versionTag = chalk.gray(` v${info.version}`);
|
|
71
|
+
write(`\n\r${indent}${chalk.cyan(builtBot)}${versionTag}`);
|
|
72
|
+
write("\x1b[1A"); // back to top line
|
|
73
|
+
await sleep(2000);
|
|
74
|
+
// Phase 2: Replace title with compact TM + stats
|
|
75
|
+
// Erase the two title lines and rewrite
|
|
76
|
+
write("\r\x1b[K"); // erase top line
|
|
77
|
+
write("\n\r\x1b[K"); // erase bottom line
|
|
78
|
+
write("\x1b[1A"); // back to top
|
|
79
|
+
const [tmTop, tmBot] = buildTitle("tm");
|
|
80
|
+
const tmWidth = tmTop.length; // "▀█▀ █▀▄▀█" = 9 chars
|
|
81
|
+
const gap = " ";
|
|
82
|
+
// Build info lines to sit to the right of TM
|
|
83
|
+
const rightLine1 = chalk.white(info.adapterName) +
|
|
84
|
+
chalk.gray(` · ${info.teammateCount} teammate${info.teammateCount === 1 ? "" : "s"}`) +
|
|
85
|
+
chalk.gray(` · v${info.version}`);
|
|
86
|
+
const rightLine2 = chalk.gray(info.cwd);
|
|
87
|
+
const rightLine3 = info.recallInstalled
|
|
88
|
+
? chalk.green("● recall") + chalk.gray(" installed")
|
|
89
|
+
: chalk.yellow("○ recall") + chalk.gray(" not installed");
|
|
90
|
+
// TM row 1 + first stat
|
|
91
|
+
write(`${indent + chalk.cyan(tmTop) + gap + rightLine1}\n`);
|
|
92
|
+
await sleep(40);
|
|
93
|
+
// TM row 2 + second stat
|
|
94
|
+
write(`${indent + chalk.cyan(tmBot) + gap + rightLine2}\n`);
|
|
95
|
+
await sleep(40);
|
|
96
|
+
// Blank TM area + third stat
|
|
97
|
+
write(`${indent + " ".repeat(tmWidth) + gap + rightLine3}\n`);
|
|
98
|
+
await sleep(80);
|
|
99
|
+
// Phase 3: roster
|
|
100
|
+
if (info.teammates.length > 0) {
|
|
101
|
+
console.log();
|
|
102
|
+
for (const t of info.teammates) {
|
|
103
|
+
const line = chalk.gray(" ") +
|
|
104
|
+
chalk.cyan("●") +
|
|
105
|
+
chalk.cyan(` @${t.name}`.padEnd(14)) +
|
|
106
|
+
chalk.gray(t.role);
|
|
107
|
+
console.log(line);
|
|
108
|
+
await sleep(40);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
await sleep(80);
|
|
112
|
+
// Phase 4: quick reference
|
|
113
|
+
console.log();
|
|
114
|
+
console.log(chalk.gray("─".repeat(termWidth)));
|
|
115
|
+
const col1 = [
|
|
116
|
+
["@mention", "assign to teammate"],
|
|
117
|
+
["text", "auto-route task"],
|
|
118
|
+
["/queue", "view task queue"],
|
|
119
|
+
];
|
|
120
|
+
const col2 = [
|
|
121
|
+
["/status", "session overview"],
|
|
122
|
+
["/debug", "raw agent output"],
|
|
123
|
+
["/log", "last task output"],
|
|
124
|
+
];
|
|
125
|
+
const col3 = [
|
|
126
|
+
["/install", "add a service"],
|
|
127
|
+
["/help", "all commands"],
|
|
128
|
+
["/exit", "exit session"],
|
|
129
|
+
];
|
|
130
|
+
for (let i = 0; i < col1.length; i++) {
|
|
131
|
+
const c1 = chalk.cyan(col1[i][0].padEnd(12)) + chalk.gray(col1[i][1].padEnd(22));
|
|
132
|
+
const c2 = chalk.cyan(col2[i][0].padEnd(12)) + chalk.gray(col2[i][1].padEnd(22));
|
|
133
|
+
const c3 = chalk.cyan(col3[i][0].padEnd(12)) + chalk.gray(col3[i][1]);
|
|
134
|
+
console.log(` ${c1}${c2}${c3}`);
|
|
135
|
+
await sleep(30);
|
|
136
|
+
}
|
|
137
|
+
console.log();
|
|
138
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { buildTitle } from "./startup.js";
|
|
3
|
+
describe("buildTitle", () => {
|
|
4
|
+
it("produces two-line output for known characters", () => {
|
|
5
|
+
const [top, bot] = buildTitle("team");
|
|
6
|
+
// "t", "e", "a", "m" are all known glyphs
|
|
7
|
+
expect(top.length).toBeGreaterThan(0);
|
|
8
|
+
expect(bot.length).toBeGreaterThan(0);
|
|
9
|
+
// Should contain glyph fragments
|
|
10
|
+
expect(top).toContain("▀");
|
|
11
|
+
expect(bot).toContain("█");
|
|
12
|
+
});
|
|
13
|
+
it("renders a single character", () => {
|
|
14
|
+
const [top, bot] = buildTitle("t");
|
|
15
|
+
expect(top).toBe("▀█▀");
|
|
16
|
+
expect(bot).toBe(" █ ");
|
|
17
|
+
});
|
|
18
|
+
it("renders a multi-character word with spaces between glyphs", () => {
|
|
19
|
+
const [top, bot] = buildTitle("te");
|
|
20
|
+
// "t" top = "▀█▀", "e" top = "█▀▀" => joined with space
|
|
21
|
+
expect(top).toBe("▀█▀ █▀▀");
|
|
22
|
+
expect(bot).toBe(" █ ██▄");
|
|
23
|
+
});
|
|
24
|
+
it("returns empty strings for an empty input", () => {
|
|
25
|
+
const [top, bot] = buildTitle("");
|
|
26
|
+
expect(top).toBe("");
|
|
27
|
+
expect(bot).toBe("");
|
|
28
|
+
});
|
|
29
|
+
it("skips unknown characters", () => {
|
|
30
|
+
const [top, bot] = buildTitle("z");
|
|
31
|
+
// "z" is not in the GLYPHS map
|
|
32
|
+
expect(top).toBe("");
|
|
33
|
+
expect(bot).toBe("");
|
|
34
|
+
});
|
|
35
|
+
it("handles mixed known and unknown characters", () => {
|
|
36
|
+
const [top, bot] = buildTitle("txe");
|
|
37
|
+
// "x" is unknown, so only "t" and "e" glyphs appear
|
|
38
|
+
expect(top).toBe("▀█▀ █▀▀");
|
|
39
|
+
expect(bot).toBe(" █ ██▄");
|
|
40
|
+
});
|
|
41
|
+
});
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Wordwheel — autocomplete dropdown engine for readline REPLs.
|
|
3
|
+
*
|
|
4
|
+
* Manages a list of completion candidates, keyboard navigation (up/down/tab),
|
|
5
|
+
* and renders them via a Dropdown instance.
|
|
6
|
+
*
|
|
7
|
+
* The Wordwheel doesn't know about specific completions — you provide
|
|
8
|
+
* an ItemProvider callback that returns candidates for the current input.
|
|
9
|
+
*/
|
|
10
|
+
import type { Interface as ReadlineInterface } from "node:readline";
|
|
11
|
+
import type { Dropdown } from "./dropdown.js";
|
|
12
|
+
export interface WordwheelItem {
|
|
13
|
+
/** Left column display text (e.g. command name, ~14 chars). */
|
|
14
|
+
label: string;
|
|
15
|
+
/** Right column description text. */
|
|
16
|
+
description: string;
|
|
17
|
+
/** Full line content to set when this item is accepted. */
|
|
18
|
+
completion: string;
|
|
19
|
+
}
|
|
20
|
+
export interface WordwheelOptions {
|
|
21
|
+
/** Readline interface. */
|
|
22
|
+
rl: ReadlineInterface;
|
|
23
|
+
/** Dropdown to render into. */
|
|
24
|
+
dropdown: Dropdown;
|
|
25
|
+
/** Returns completion items for the current line/cursor state. */
|
|
26
|
+
getItems: (line: string, cursor: number) => WordwheelItem[];
|
|
27
|
+
/**
|
|
28
|
+
* Format a highlighted item line.
|
|
29
|
+
* Default: "▸ " + bold label + description
|
|
30
|
+
*/
|
|
31
|
+
formatHighlighted?: (item: WordwheelItem) => string;
|
|
32
|
+
/**
|
|
33
|
+
* Format a normal item line.
|
|
34
|
+
* Default: " " + label + description
|
|
35
|
+
*/
|
|
36
|
+
formatNormal?: (item: WordwheelItem) => string;
|
|
37
|
+
}
|
|
38
|
+
export declare class Wordwheel {
|
|
39
|
+
items: WordwheelItem[];
|
|
40
|
+
index: number;
|
|
41
|
+
private rl;
|
|
42
|
+
private dropdown;
|
|
43
|
+
private getItems;
|
|
44
|
+
private formatHighlighted;
|
|
45
|
+
private formatNormal;
|
|
46
|
+
constructor(options: WordwheelOptions);
|
|
47
|
+
/** Recompute items based on current readline state. */
|
|
48
|
+
update(): void;
|
|
49
|
+
/** Render the current items to the dropdown. */
|
|
50
|
+
render(): void;
|
|
51
|
+
/** Clear items and dropdown. */
|
|
52
|
+
clear(): void;
|
|
53
|
+
/** Move selection down. Returns true if handled. */
|
|
54
|
+
moveDown(): boolean;
|
|
55
|
+
/** Move selection up. Returns true if handled. */
|
|
56
|
+
moveUp(): boolean;
|
|
57
|
+
/**
|
|
58
|
+
* Accept the currently highlighted item.
|
|
59
|
+
* Sets the readline line to the item's completion text.
|
|
60
|
+
* Returns the accepted item, or null if nothing was selected.
|
|
61
|
+
*/
|
|
62
|
+
accept(): WordwheelItem | null;
|
|
63
|
+
/**
|
|
64
|
+
* Handle a key event. Returns true if the key was consumed.
|
|
65
|
+
* Call this from your _ttyWrite override before passing to readline.
|
|
66
|
+
*/
|
|
67
|
+
handleKey(key: {
|
|
68
|
+
name?: string;
|
|
69
|
+
} | undefined): boolean;
|
|
70
|
+
/**
|
|
71
|
+
* Handle Enter key — accepts highlighted item into the line
|
|
72
|
+
* but does NOT consume the key (caller should still pass to readline).
|
|
73
|
+
*/
|
|
74
|
+
handleEnter(): void;
|
|
75
|
+
}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Wordwheel — autocomplete dropdown engine for readline REPLs.
|
|
3
|
+
*
|
|
4
|
+
* Manages a list of completion candidates, keyboard navigation (up/down/tab),
|
|
5
|
+
* and renders them via a Dropdown instance.
|
|
6
|
+
*
|
|
7
|
+
* The Wordwheel doesn't know about specific completions — you provide
|
|
8
|
+
* an ItemProvider callback that returns candidates for the current input.
|
|
9
|
+
*/
|
|
10
|
+
export class Wordwheel {
|
|
11
|
+
items = [];
|
|
12
|
+
index = -1;
|
|
13
|
+
rl;
|
|
14
|
+
dropdown;
|
|
15
|
+
getItems;
|
|
16
|
+
formatHighlighted;
|
|
17
|
+
formatNormal;
|
|
18
|
+
constructor(options) {
|
|
19
|
+
this.rl = options.rl;
|
|
20
|
+
this.dropdown = options.dropdown;
|
|
21
|
+
this.getItems = options.getItems;
|
|
22
|
+
this.formatHighlighted =
|
|
23
|
+
options.formatHighlighted ??
|
|
24
|
+
((item) => `▸ ${item.label.padEnd(14)}${item.description}`);
|
|
25
|
+
this.formatNormal =
|
|
26
|
+
options.formatNormal ??
|
|
27
|
+
((item) => ` ${item.label.padEnd(14)}${item.description}`);
|
|
28
|
+
}
|
|
29
|
+
/** Recompute items based on current readline state. */
|
|
30
|
+
update() {
|
|
31
|
+
this.dropdown.clear();
|
|
32
|
+
const line = this.rl.line ?? "";
|
|
33
|
+
const cursor = this.rl.cursor ?? 0;
|
|
34
|
+
this.items = this.getItems(line, cursor);
|
|
35
|
+
if (this.items.length > 0) {
|
|
36
|
+
this.index = Math.min(this.index, this.items.length - 1);
|
|
37
|
+
this.render();
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
this.index = -1;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
/** Render the current items to the dropdown. */
|
|
44
|
+
render() {
|
|
45
|
+
const lines = this.items.map((item, i) => i === this.index ? this.formatHighlighted(item) : this.formatNormal(item));
|
|
46
|
+
this.dropdown.render(lines);
|
|
47
|
+
}
|
|
48
|
+
/** Clear items and dropdown. */
|
|
49
|
+
clear() {
|
|
50
|
+
this.dropdown.clear();
|
|
51
|
+
this.items = [];
|
|
52
|
+
this.index = -1;
|
|
53
|
+
}
|
|
54
|
+
/** Move selection down. Returns true if handled. */
|
|
55
|
+
moveDown() {
|
|
56
|
+
if (this.items.length === 0)
|
|
57
|
+
return false;
|
|
58
|
+
this.index = Math.min(this.index + 1, this.items.length - 1);
|
|
59
|
+
this.render();
|
|
60
|
+
return true;
|
|
61
|
+
}
|
|
62
|
+
/** Move selection up. Returns true if handled. */
|
|
63
|
+
moveUp() {
|
|
64
|
+
if (this.items.length === 0)
|
|
65
|
+
return false;
|
|
66
|
+
this.index = Math.max(this.index - 1, -1);
|
|
67
|
+
this.render();
|
|
68
|
+
return true;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Accept the currently highlighted item.
|
|
72
|
+
* Sets the readline line to the item's completion text.
|
|
73
|
+
* Returns the accepted item, or null if nothing was selected.
|
|
74
|
+
*/
|
|
75
|
+
accept() {
|
|
76
|
+
if (this.index < 0 || this.index >= this.items.length)
|
|
77
|
+
return null;
|
|
78
|
+
const item = this.items[this.index];
|
|
79
|
+
this.clear();
|
|
80
|
+
this.rl.line = item.completion;
|
|
81
|
+
this.rl.cursor = item.completion.length;
|
|
82
|
+
this.rl._refreshLine();
|
|
83
|
+
// Recompute for next level of completion
|
|
84
|
+
this.update();
|
|
85
|
+
return item;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Handle a key event. Returns true if the key was consumed.
|
|
89
|
+
* Call this from your _ttyWrite override before passing to readline.
|
|
90
|
+
*/
|
|
91
|
+
handleKey(key) {
|
|
92
|
+
if (!key || this.items.length === 0)
|
|
93
|
+
return false;
|
|
94
|
+
if (key.name === "down") {
|
|
95
|
+
this.moveDown();
|
|
96
|
+
return true;
|
|
97
|
+
}
|
|
98
|
+
if (key.name === "up") {
|
|
99
|
+
this.moveUp();
|
|
100
|
+
return true;
|
|
101
|
+
}
|
|
102
|
+
if (key.name === "tab" && this.index >= 0) {
|
|
103
|
+
this.accept();
|
|
104
|
+
return true;
|
|
105
|
+
}
|
|
106
|
+
return false;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Handle Enter key — accepts highlighted item into the line
|
|
110
|
+
* but does NOT consume the key (caller should still pass to readline).
|
|
111
|
+
*/
|
|
112
|
+
handleEnter() {
|
|
113
|
+
if (this.items.length > 0 && this.index >= 0) {
|
|
114
|
+
const item = this.items[this.index];
|
|
115
|
+
if (item) {
|
|
116
|
+
this.rl.line = item.completion;
|
|
117
|
+
this.rl.cursor = item.completion.length;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
this.clear();
|
|
121
|
+
this.rl._refreshLine();
|
|
122
|
+
}
|
|
123
|
+
}
|
package/dist/dropdown.js
CHANGED
|
@@ -7,24 +7,7 @@
|
|
|
7
7
|
* 3. We adjust prevRows so the NEXT _refreshLine's moveCursor(0, -prevRows)
|
|
8
8
|
* moves the cursor back up past the dropdown lines to the prompt
|
|
9
9
|
*/
|
|
10
|
-
|
|
11
|
-
function truncateAnsi(str, max) {
|
|
12
|
-
let visible = 0;
|
|
13
|
-
let i = 0;
|
|
14
|
-
while (i < str.length && visible < max) {
|
|
15
|
-
if (str[i] === "\x1b") {
|
|
16
|
-
// Skip ANSI sequence
|
|
17
|
-
const end = str.indexOf("m", i);
|
|
18
|
-
if (end !== -1) {
|
|
19
|
-
i = end + 1;
|
|
20
|
-
continue;
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
visible++;
|
|
24
|
-
i++;
|
|
25
|
-
}
|
|
26
|
-
return str.slice(0, i);
|
|
27
|
-
}
|
|
10
|
+
import { esc, stripAnsi, truncateAnsi } from "@teammates/consolonia";
|
|
28
11
|
export class Dropdown {
|
|
29
12
|
rl;
|
|
30
13
|
lines = [];
|
|
@@ -62,15 +45,15 @@ export class Dropdown {
|
|
|
62
45
|
const cols = this.out.columns || 120;
|
|
63
46
|
let buf = "";
|
|
64
47
|
for (const line of this.lines) {
|
|
65
|
-
buf +=
|
|
48
|
+
buf += `\n${truncateAnsi(line, cols - 1)}`;
|
|
66
49
|
}
|
|
67
50
|
this.out.write(buf);
|
|
68
51
|
// 3. Move cursor back up to the prompt line and restore column.
|
|
69
52
|
// Don't touch prevRows — cursor IS on the prompt line after this.
|
|
70
53
|
const n = this.lines.length;
|
|
71
|
-
this.out.write(
|
|
54
|
+
this.out.write(esc.moveUp(n));
|
|
72
55
|
const promptText = this.rl._prompt ?? "";
|
|
73
|
-
const promptLen = promptText
|
|
56
|
+
const promptLen = stripAnsi(promptText).length;
|
|
74
57
|
const cursor = this.rl.cursor ?? 0;
|
|
75
58
|
this.out.write(`\x1b[${promptLen + cursor + 1}G`);
|
|
76
59
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
export type {
|
|
2
|
-
export type { AgentAdapter, RosterEntry, InstalledService } from "./adapter.js";
|
|
1
|
+
export type { AgentAdapter, InstalledService, RosterEntry } from "./adapter.js";
|
|
3
2
|
export { buildTeammatePrompt, formatHandoffContext } from "./adapter.js";
|
|
4
|
-
export {
|
|
5
|
-
export { Orchestrator, type OrchestratorConfig, type TeammateStatus, } from "./orchestrator.js";
|
|
3
|
+
export { type AgentPreset, CliProxyAdapter, type CliProxyOptions, PRESETS, } from "./adapters/cli-proxy.js";
|
|
6
4
|
export { EchoAdapter } from "./adapters/echo.js";
|
|
7
|
-
export {
|
|
5
|
+
export { Orchestrator, type OrchestratorConfig, type TeammateStatus, } from "./orchestrator.js";
|
|
6
|
+
export { Registry } from "./registry.js";
|
|
7
|
+
export type { DailyLog, HandoffEnvelope, OrchestratorEvent, OwnershipRules, SandboxLevel, TaskAssignment, TaskResult, TeammateConfig, } from "./types.js";
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Public API for @teammates/cli
|
|
2
2
|
export { buildTeammatePrompt, formatHandoffContext } from "./adapter.js";
|
|
3
|
-
export { Registry } from "./registry.js";
|
|
4
|
-
export { Orchestrator, } from "./orchestrator.js";
|
|
5
|
-
export { EchoAdapter } from "./adapters/echo.js";
|
|
6
3
|
export { CliProxyAdapter, PRESETS, } from "./adapters/cli-proxy.js";
|
|
4
|
+
export { EchoAdapter } from "./adapters/echo.js";
|
|
5
|
+
export { Orchestrator, } from "./orchestrator.js";
|
|
6
|
+
export { Registry } from "./registry.js";
|
package/dist/onboard.d.ts
CHANGED
|
@@ -12,6 +12,30 @@
|
|
|
12
12
|
* Returns the list of files that were copied.
|
|
13
13
|
*/
|
|
14
14
|
export declare function copyTemplateFiles(teammatesDir: string): Promise<string[]>;
|
|
15
|
+
/**
|
|
16
|
+
* Import teammates from another project's .teammates/ dir.
|
|
17
|
+
*
|
|
18
|
+
* Only copies SOUL.md and WISDOM.md per teammate (identity + wisdom carry over).
|
|
19
|
+
* Creates an empty memory/ dir for each (fresh start — no daily logs or typed memories).
|
|
20
|
+
* Also copies USER.md if present. Framework files (CROSS-TEAM.md, README.md, etc.)
|
|
21
|
+
* are project-specific and NOT copied — they get created fresh from the template.
|
|
22
|
+
*
|
|
23
|
+
* Skips teammates that already exist in the target (idempotent).
|
|
24
|
+
* Returns { teammates: string[], files: string[] }.
|
|
25
|
+
*/
|
|
26
|
+
export declare function importTeammates(sourceDir: string, targetDir: string): Promise<{
|
|
27
|
+
teammates: string[];
|
|
28
|
+
files: string[];
|
|
29
|
+
}>;
|
|
30
|
+
/**
|
|
31
|
+
* Build the adaptation prompt for a single imported teammate.
|
|
32
|
+
* Tells the agent to update ownership patterns, file paths, and boundaries
|
|
33
|
+
* for the new codebase while preserving identity, principles, and wisdom.
|
|
34
|
+
*
|
|
35
|
+
* @param teammatesDir - The .teammates/ directory in the target project
|
|
36
|
+
* @param teammateName - The name of the teammate to adapt
|
|
37
|
+
*/
|
|
38
|
+
export declare function buildAdaptationPrompt(teammatesDir: string, teammateName: string): Promise<string>;
|
|
15
39
|
/**
|
|
16
40
|
* Load ONBOARDING.md from the project dir, package root, or built-in fallback.
|
|
17
41
|
*/
|