agent-trellis 0.6.3 → 0.8.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 +97 -38
- package/dist/adapters/claude-code.js +3 -2
- package/dist/adapters/codex.js +3 -2
- package/dist/adapters/jsonMcp.d.ts +3 -1
- package/dist/adapters/jsonMcp.js +18 -4
- package/dist/adapters/kimi-code.d.ts +21 -0
- package/dist/adapters/kimi-code.js +107 -0
- package/dist/adapters/kiro.js +3 -2
- package/dist/adapters/mcpPlan.d.ts +26 -2
- package/dist/adapters/mcpPlan.js +135 -15
- package/dist/adapters/pi.js +22 -3
- package/dist/adapters/symlinkPlan.d.ts +7 -0
- package/dist/adapters/symlinkPlan.js +16 -7
- package/dist/cli.js +129 -20
- package/dist/commands/doctor.d.ts +7 -2
- package/dist/commands/doctor.js +38 -2
- package/dist/commands/init.d.ts +4 -2
- package/dist/commands/init.js +26 -13
- package/dist/commands/kimi.d.ts +16 -0
- package/dist/commands/kimi.js +64 -0
- package/dist/commands/manage.d.ts +39 -0
- package/dist/commands/manage.js +126 -0
- package/dist/commands/mcp.d.ts +22 -1
- package/dist/commands/mcp.js +65 -2
- package/dist/commands/mcpGateway.d.ts +6 -0
- package/dist/commands/mcpGateway.js +34 -14
- package/dist/commands/mcpImport.d.ts +27 -0
- package/dist/commands/mcpImport.js +336 -0
- package/dist/commands/memory.d.ts +5 -3
- package/dist/commands/memory.js +12 -8
- package/dist/commands/migrate.d.ts +37 -7
- package/dist/commands/migrate.js +253 -27
- package/dist/commands/onboard.d.ts +74 -2
- package/dist/commands/onboard.js +463 -72
- package/dist/commands/onboardVerdict.js +20 -7
- package/dist/commands/rollback.js +4 -1
- package/dist/commands/secretsAudit.d.ts +21 -12
- package/dist/commands/secretsAudit.js +39 -10
- package/dist/commands/skill.d.ts +17 -0
- package/dist/commands/skill.js +47 -2
- package/dist/commands/sync.js +2 -0
- package/dist/core/canonical.d.ts +58 -4
- package/dist/core/canonical.js +183 -11
- package/dist/core/capabilitySelection.d.ts +45 -0
- package/dist/core/capabilitySelection.js +124 -0
- package/dist/core/types.d.ts +25 -2
- package/dist/core/types.js +7 -0
- package/dist/lib/backup.d.ts +2 -0
- package/dist/lib/backup.js +4 -0
- package/dist/lib/builtinSkills.d.ts +2 -0
- package/dist/lib/builtinSkills.js +4 -0
- package/dist/lib/cliMetadata.d.ts +1 -0
- package/dist/lib/cliMetadata.js +14 -0
- package/dist/lib/gatewayBackend.d.ts +28 -0
- package/dist/lib/gatewayBackend.js +72 -1
- package/dist/lib/installAgent.d.ts +7 -5
- package/dist/lib/installAgent.js +4 -3
- package/dist/lib/mcpConnect.js +5 -1
- package/dist/lib/mcpMigrateRead.d.ts +1 -0
- package/dist/lib/mcpMigrateRead.js +3 -0
- package/dist/lib/mcpRuntime.d.ts +46 -0
- package/dist/lib/mcpRuntime.js +185 -0
- package/dist/lib/mcpStatusProvider.d.ts +10 -0
- package/dist/lib/mcpStatusProvider.js +25 -0
- package/dist/lib/mcpToolRegistry.d.ts +18 -0
- package/dist/lib/mcpToolRegistry.js +107 -14
- package/dist/lib/memoryGraph.d.ts +1 -1
- package/dist/lib/memoryGraph.js +9 -3
- package/dist/lib/memoryProvider.d.ts +58 -0
- package/dist/lib/memoryProvider.js +175 -0
- package/dist/lib/memoryStatus.d.ts +17 -0
- package/dist/lib/memoryStatus.js +88 -0
- package/dist/lib/nativeMemory.d.ts +19 -0
- package/dist/lib/nativeMemory.js +129 -0
- package/dist/lib/runtimeControlProvider.d.ts +16 -0
- package/dist/lib/runtimeControlProvider.js +168 -0
- package/dist/lib/secretEnv.d.ts +17 -0
- package/dist/lib/secretEnv.js +31 -1
- package/dist/lib/skillProvider.d.ts +13 -0
- package/dist/lib/skillProvider.js +210 -0
- package/dist/lib/taskProvider.d.ts +7 -0
- package/dist/lib/taskProvider.js +43 -0
- package/dist/lib/taskStore.d.ts +46 -0
- package/dist/lib/taskStore.js +156 -0
- package/dist/lib/terminalPicker.d.ts +23 -28
- package/dist/lib/terminalPicker.js +54 -164
- package/dist/pi-bridge/bundle.js +493 -51
- package/dist/pi-bridge/index.js +42 -21
- package/dist/pi-bridge/schemaTranslate.d.ts +4 -8
- package/dist/pi-bridge/schemaTranslate.js +4 -8
- package/dist/probes/kimi-code.d.ts +12 -0
- package/dist/probes/kimi-code.js +55 -0
- package/dist/sdk.d.ts +1 -1
- package/docs/architecture.md +224 -26
- package/docs/assets/agent-trellis-architecture-horizontal.svg +80 -0
- package/docs/assets/agent-trellis-architecture-vertical.svg +82 -0
- package/docs/assets/trellis-mark.svg +12 -0
- package/docs/getting-started.md +403 -35
- package/docs/overview.md +131 -0
- package/docs/overview.zh-CN.md +100 -0
- package/docs/research.md +59 -0
- package/docs/roadmap.md +10 -5
- package/package.json +5 -3
- package/schema/builtin-skills/trellis-runtime/SKILL.md +117 -0
- package/schema/capability-selection.example.yaml +23 -0
- package/schema/scope.example.yaml +1 -1
- package/schema/servers.example.yaml +15 -1
|
@@ -1,193 +1,83 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
* (trellis-onboard-interactive-picker design.md D1) — the interaction
|
|
4
|
-
* surface `trellis onboard`'s two prompts need (at most four rows, no
|
|
5
|
-
* search, no pagination) doesn't need a full prompt library; this
|
|
6
|
-
* hand-rolls just enough raw-mode key handling and ANSI rendering for
|
|
7
|
-
* that bounded case, matching the project's existing narrow-dependency
|
|
8
|
-
* precedent (src/lib/envVarNames.ts, src/lib/secretEnv.ts).
|
|
2
|
+
* Styled interactive prompts used by `trellis onboard`.
|
|
9
3
|
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
4
|
+
* The onboarding orchestration depends on semantic values (an index or a set
|
|
5
|
+
* of indices), not on a particular terminal renderer. Clack owns raw-mode
|
|
6
|
+
* handling, color, wrapping, cursor cleanup, and cancellation; the injected
|
|
7
|
+
* streams keep the prompt loop testable without a real terminal.
|
|
14
8
|
*/
|
|
9
|
+
import { CANCEL_SYMBOL, autocompleteMultiselect, isCancel, multiselect, select } from "@clack/prompts";
|
|
15
10
|
function defaultStreams() {
|
|
16
|
-
return { input: process.stdin, output: process.
|
|
11
|
+
return { input: process.stdin, output: process.stderr };
|
|
17
12
|
}
|
|
18
13
|
/**
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
* (design.md D2). A stream lacking `setRawMode` (piped input, some
|
|
22
|
-
* minimal TTYs) always falls back, never hangs or guesses.
|
|
14
|
+
* Clack is only started for a real interactive terminal. Piped input keeps
|
|
15
|
+
* the existing numbered fallback in onboard instead of hanging in raw mode.
|
|
23
16
|
*/
|
|
24
17
|
export function canUseInteractivePicker(streams = defaultStreams()) {
|
|
25
18
|
const input = streams.input;
|
|
26
19
|
const output = streams.output;
|
|
27
20
|
return Boolean(input.isTTY && output.isTTY && typeof input.setRawMode === "function");
|
|
28
21
|
}
|
|
29
|
-
/** Wrapping index navigation
|
|
22
|
+
/** Wrapping index navigation retained as a small public utility for callers/tests. */
|
|
30
23
|
export function nextIndex(current, delta, length) {
|
|
31
24
|
return ((current + delta) % length + length) % length;
|
|
32
25
|
}
|
|
33
|
-
/** Pure single-index toggle
|
|
26
|
+
/** Pure single-index toggle retained for callers/tests. */
|
|
34
27
|
export function toggled(checked, index) {
|
|
35
28
|
const next = [...checked];
|
|
36
29
|
next[index] = !next[index];
|
|
37
30
|
return next;
|
|
38
31
|
}
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
const HIDE_CURSOR = `${ESC}[?25l`;
|
|
42
|
-
const SHOW_CURSOR = `${ESC}[?25h`;
|
|
43
|
-
/** Parses one raw input chunk into a single logical key — arrow escape
|
|
44
|
-
* sequences, j/k, space, enter, or Ctrl+C. Anything else is ignored. */
|
|
45
|
-
function parseKey(chunk) {
|
|
46
|
-
if (chunk === CTRL_C)
|
|
47
|
-
return "cancel";
|
|
48
|
-
if (chunk === "\r" || chunk === "\n")
|
|
49
|
-
return "confirm";
|
|
50
|
-
if (chunk === " ")
|
|
51
|
-
return "toggle";
|
|
52
|
-
if (chunk === `${ESC}[A` || chunk === "k")
|
|
53
|
-
return "up";
|
|
54
|
-
if (chunk === `${ESC}[B` || chunk === "j")
|
|
55
|
-
return "down";
|
|
56
|
-
return null;
|
|
57
|
-
}
|
|
58
|
-
function withRawMode(streams, body) {
|
|
59
|
-
const input = streams.input;
|
|
60
|
-
const output = streams.output;
|
|
61
|
-
const canSetRawMode = typeof input.setRawMode === "function";
|
|
62
|
-
if (canSetRawMode)
|
|
63
|
-
input.setRawMode(true);
|
|
64
|
-
input.resume();
|
|
65
|
-
input.setEncoding("utf-8");
|
|
66
|
-
output.write(HIDE_CURSOR);
|
|
67
|
-
const restore = () => {
|
|
68
|
-
output.write(SHOW_CURSOR);
|
|
69
|
-
if (canSetRawMode)
|
|
70
|
-
input.setRawMode(false);
|
|
71
|
-
input.pause();
|
|
72
|
-
};
|
|
73
|
-
// Second-layer safety net (design.md D6): a thrown error the caller's
|
|
74
|
-
// own try/finally doesn't get a chance to run for (process killed
|
|
75
|
-
// externally) must still not leave the terminal in raw mode/cursor
|
|
76
|
-
// hidden.
|
|
77
|
-
process.once("exit", restore);
|
|
78
|
-
return body().finally(() => {
|
|
79
|
-
restore();
|
|
80
|
-
process.removeListener("exit", restore);
|
|
81
|
-
});
|
|
82
|
-
}
|
|
83
|
-
function moveCursorUp(output, lines) {
|
|
84
|
-
if (lines > 0)
|
|
85
|
-
output.write(`${ESC}[${lines}A`);
|
|
86
|
-
}
|
|
87
|
-
function clearLines(output, lines) {
|
|
88
|
-
for (let i = 0; i < lines; i++) {
|
|
89
|
-
output.write(`${ESC}[2K`);
|
|
90
|
-
if (i < lines - 1)
|
|
91
|
-
output.write(`${ESC}[1B`);
|
|
92
|
-
}
|
|
93
|
-
moveCursorUp(output, lines - 1);
|
|
94
|
-
}
|
|
95
|
-
function renderRows(output, rows, previousRowCount) {
|
|
96
|
-
if (previousRowCount > 0) {
|
|
97
|
-
clearLines(output, previousRowCount);
|
|
98
|
-
}
|
|
99
|
-
for (const row of rows) {
|
|
100
|
-
output.write(`${row}\n`);
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
function highlightRow(text, isHighlighted) {
|
|
104
|
-
return isHighlighted ? `> ${ESC}[7m${text}${ESC}[0m` : ` ${text}`;
|
|
32
|
+
function wasCancelled(value) {
|
|
33
|
+
return value === CANCEL_SYMBOL || isCancel(value);
|
|
105
34
|
}
|
|
106
35
|
/**
|
|
107
|
-
* Single-select
|
|
108
|
-
*
|
|
109
|
-
* must have already confirmed `canUseInteractivePicker()` — this function
|
|
110
|
-
* does not re-check, and assumes `streams.input` genuinely supports raw
|
|
111
|
-
* mode.
|
|
36
|
+
* Single-select prompt. The returned number is the original item index, so
|
|
37
|
+
* callers do not depend on display labels or prompt-library values.
|
|
112
38
|
*/
|
|
113
|
-
export async function runSingleSelectPicker(items, streams = defaultStreams()) {
|
|
114
|
-
const
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
draw();
|
|
125
|
-
const onData = (chunk) => {
|
|
126
|
-
const key = parseKey(chunk.toString("utf-8"));
|
|
127
|
-
if (key === "up") {
|
|
128
|
-
highlighted = nextIndex(highlighted, -1, items.length);
|
|
129
|
-
draw();
|
|
130
|
-
}
|
|
131
|
-
else if (key === "down") {
|
|
132
|
-
highlighted = nextIndex(highlighted, 1, items.length);
|
|
133
|
-
draw();
|
|
134
|
-
}
|
|
135
|
-
else if (key === "confirm") {
|
|
136
|
-
input.removeListener("data", onData);
|
|
137
|
-
resolve(highlighted);
|
|
138
|
-
}
|
|
139
|
-
else if (key === "cancel") {
|
|
140
|
-
input.removeListener("data", onData);
|
|
141
|
-
resolve(null);
|
|
142
|
-
}
|
|
143
|
-
};
|
|
144
|
-
input.on("data", onData);
|
|
145
|
-
});
|
|
39
|
+
export async function runSingleSelectPicker(items, streams = defaultStreams(), message = "请选择一个迁移来源") {
|
|
40
|
+
const result = await select({
|
|
41
|
+
message,
|
|
42
|
+
options: items.map((item, value) => ({
|
|
43
|
+
label: typeof item === "string" ? item : item.label,
|
|
44
|
+
value,
|
|
45
|
+
...(typeof item === "string" || item.disabled === undefined ? {} : { disabled: item.disabled }),
|
|
46
|
+
})),
|
|
47
|
+
input: streams.input,
|
|
48
|
+
output: streams.output,
|
|
49
|
+
showInstructions: true,
|
|
146
50
|
});
|
|
51
|
+
return wasCancelled(result) ? null : result;
|
|
147
52
|
}
|
|
148
53
|
/**
|
|
149
|
-
*
|
|
150
|
-
*
|
|
151
|
-
* confirm time, or `null` on Ctrl+C cancel. Same precondition as
|
|
152
|
-
* `runSingleSelectPicker`.
|
|
54
|
+
* Checkbox prompt. The returned indices preserve the existing onboard
|
|
55
|
+
* contract, while Clack handles checked state, wrapping, colors, and cleanup.
|
|
153
56
|
*/
|
|
154
|
-
export async function runMultiSelectPicker(items, initiallyChecked, streams = defaultStreams()) {
|
|
155
|
-
const
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
checked = toggled(checked, highlighted);
|
|
179
|
-
draw();
|
|
180
|
-
}
|
|
181
|
-
else if (key === "confirm") {
|
|
182
|
-
input.removeListener("data", onData);
|
|
183
|
-
resolve(checked.flatMap((isChecked, i) => (isChecked ? [i] : [])));
|
|
184
|
-
}
|
|
185
|
-
else if (key === "cancel") {
|
|
186
|
-
input.removeListener("data", onData);
|
|
187
|
-
resolve(null);
|
|
188
|
-
}
|
|
189
|
-
};
|
|
190
|
-
input.on("data", onData);
|
|
191
|
-
});
|
|
57
|
+
export async function runMultiSelectPicker(items, initiallyChecked, streams = defaultStreams(), message = "请选择要启用的项目") {
|
|
58
|
+
const result = await multiselect({
|
|
59
|
+
message,
|
|
60
|
+
options: items.map((label, value) => ({ label, value })),
|
|
61
|
+
initialValues: items.flatMap((_, index) => (initiallyChecked[index] ? [index] : [])),
|
|
62
|
+
input: streams.input,
|
|
63
|
+
output: streams.output,
|
|
64
|
+
required: false,
|
|
65
|
+
showInstructions: true,
|
|
66
|
+
});
|
|
67
|
+
return wasCancelled(result) ? null : [...result].sort((left, right) => left - right);
|
|
68
|
+
}
|
|
69
|
+
/** Searchable multiselect for large skill/MCP inventories. It returns the
|
|
70
|
+
* selected labels as stable names, preserving the semantic adapter contract
|
|
71
|
+
* while avoiding a wall of dozens of rows in the onboarding terminal. */
|
|
72
|
+
export async function runSearchMultiSelectPicker(items, streams = defaultStreams(), message = "选择要迁移的项目") {
|
|
73
|
+
const result = await autocompleteMultiselect({
|
|
74
|
+
message,
|
|
75
|
+
placeholder: "输入关键词筛选",
|
|
76
|
+
options: items.map((value) => ({ label: value, value })),
|
|
77
|
+
initialValues: [...items],
|
|
78
|
+
input: streams.input,
|
|
79
|
+
output: streams.output,
|
|
80
|
+
required: false,
|
|
192
81
|
});
|
|
82
|
+
return wasCancelled(result) ? null : result;
|
|
193
83
|
}
|