@poncho-ai/cli 0.17.0 → 0.18.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/.turbo/turbo-build.log +7 -7
- package/CHANGELOG.md +16 -0
- package/dist/{chunk-GDB5X2OS.js → chunk-ETZ3YKFP.js} +102 -13
- package/dist/cli.js +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -1
- package/dist/{run-interactive-ink-B6JJ33SN.js → run-interactive-ink-VSO7GB3Y.js} +1 -1
- package/package.json +4 -4
- package/src/index.ts +36 -5
- package/src/web-ui-client.ts +71 -6
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
> @poncho-ai/cli@0.
|
|
2
|
+
> @poncho-ai/cli@0.18.0 build /home/runner/work/poncho-ai/poncho-ai/packages/cli
|
|
3
3
|
> tsup src/index.ts src/cli.ts --format esm --dts
|
|
4
4
|
|
|
5
5
|
[34mCLI[39m Building entry: src/cli.ts, src/index.ts
|
|
@@ -7,12 +7,12 @@
|
|
|
7
7
|
[34mCLI[39m tsup v8.5.1
|
|
8
8
|
[34mCLI[39m Target: es2022
|
|
9
9
|
[34mESM[39m Build start
|
|
10
|
-
[32mESM[39m [1mdist/index.js [22m[32m857.00 B[39m
|
|
11
|
-
[32mESM[39m [1mdist/run-interactive-ink-B6JJ33SN.js [22m[32m55.30 KB[39m
|
|
12
10
|
[32mESM[39m [1mdist/cli.js [22m[32m94.00 B[39m
|
|
13
|
-
[32mESM[39m [1mdist/
|
|
14
|
-
[32mESM[39m
|
|
11
|
+
[32mESM[39m [1mdist/index.js [22m[32m857.00 B[39m
|
|
12
|
+
[32mESM[39m [1mdist/run-interactive-ink-VSO7GB3Y.js [22m[32m55.30 KB[39m
|
|
13
|
+
[32mESM[39m [1mdist/chunk-ETZ3YKFP.js [22m[32m372.58 KB[39m
|
|
14
|
+
[32mESM[39m ⚡️ Build success in 72ms
|
|
15
15
|
[34mDTS[39m Build start
|
|
16
|
-
[32mDTS[39m ⚡️ Build success in
|
|
16
|
+
[32mDTS[39m ⚡️ Build success in 3995ms
|
|
17
17
|
[32mDTS[39m [1mdist/cli.d.ts [22m[32m20.00 B[39m
|
|
18
|
-
[32mDTS[39m [1mdist/index.d.ts [22m[32m3.
|
|
18
|
+
[32mDTS[39m [1mdist/index.d.ts [22m[32m3.59 KB[39m
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
# @poncho-ai/cli
|
|
2
2
|
|
|
3
|
+
## 0.18.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [`cd6ccd7`](https://github.com/cesr/poncho-ai/commit/cd6ccd7846e16fbaf17167617666796320ec29ce) Thanks [@cesr](https://github.com/cesr)! - Add MCP custom headers support, tool:generating streaming feedback, and cross-owner subagent recovery
|
|
8
|
+
- **MCP custom headers**: `poncho mcp add --header "Name: value"` and `headers` config field let servers like Arcade receive extra HTTP headers alongside bearer auth.
|
|
9
|
+
- **tool:generating event**: the harness now emits `tool:generating` events when the model begins writing tool-call arguments, so the web UI shows real-time "preparing <tool>" feedback instead of appearing stuck during large tool calls.
|
|
10
|
+
- **Subagent recovery**: `list`/`listSummaries` accept optional `ownerId` so stale-subagent recovery on server restart scans across all owners.
|
|
11
|
+
|
|
12
|
+
### Patch Changes
|
|
13
|
+
|
|
14
|
+
- Updated dependencies [[`cd6ccd7`](https://github.com/cesr/poncho-ai/commit/cd6ccd7846e16fbaf17167617666796320ec29ce)]:
|
|
15
|
+
- @poncho-ai/sdk@1.3.0
|
|
16
|
+
- @poncho-ai/harness@0.18.0
|
|
17
|
+
- @poncho-ai/messaging@0.2.6
|
|
18
|
+
|
|
3
19
|
## 0.17.0
|
|
4
20
|
|
|
5
21
|
### Minor Changes
|
|
@@ -2547,8 +2547,32 @@ var getWebUiClientScript = (markedSource2) => `
|
|
|
2547
2547
|
updateContextRing();
|
|
2548
2548
|
}
|
|
2549
2549
|
}
|
|
2550
|
+
if (eventName === "tool:generating") {
|
|
2551
|
+
const toolName = payload.tool || "tool";
|
|
2552
|
+
if (!Array.isArray(assistantMessage._activeActivities)) {
|
|
2553
|
+
assistantMessage._activeActivities = [];
|
|
2554
|
+
}
|
|
2555
|
+
assistantMessage._activeActivities.push({
|
|
2556
|
+
kind: "generating",
|
|
2557
|
+
tool: toolName,
|
|
2558
|
+
label: "Preparing " + toolName,
|
|
2559
|
+
});
|
|
2560
|
+
if (assistantMessage._currentText.length > 0) {
|
|
2561
|
+
assistantMessage._sections.push({
|
|
2562
|
+
type: "text",
|
|
2563
|
+
content: assistantMessage._currentText,
|
|
2564
|
+
});
|
|
2565
|
+
assistantMessage._currentText = "";
|
|
2566
|
+
}
|
|
2567
|
+
const prepText =
|
|
2568
|
+
"- preparing \\x60" + toolName + "\\x60";
|
|
2569
|
+
assistantMessage._currentTools.push(prepText);
|
|
2570
|
+
assistantMessage.metadata.toolActivity.push(prepText);
|
|
2571
|
+
renderIfActiveConversation(true);
|
|
2572
|
+
}
|
|
2550
2573
|
if (eventName === "tool:started") {
|
|
2551
2574
|
const toolName = payload.tool || "tool";
|
|
2575
|
+
removeActiveActivityForTool(assistantMessage, toolName);
|
|
2552
2576
|
const startedActivity = addActiveActivityFromToolStart(
|
|
2553
2577
|
assistantMessage,
|
|
2554
2578
|
payload,
|
|
@@ -2560,14 +2584,24 @@ var getWebUiClientScript = (markedSource2) => `
|
|
|
2560
2584
|
});
|
|
2561
2585
|
assistantMessage._currentText = "";
|
|
2562
2586
|
}
|
|
2587
|
+
const tick = "\\x60";
|
|
2588
|
+
const prepPrefix = "- preparing " + tick + toolName + tick;
|
|
2589
|
+
const prepToolIdx = assistantMessage._currentTools.indexOf(prepPrefix);
|
|
2590
|
+
if (prepToolIdx >= 0) {
|
|
2591
|
+
assistantMessage._currentTools.splice(prepToolIdx, 1);
|
|
2592
|
+
}
|
|
2593
|
+
const prepMetaIdx = assistantMessage.metadata.toolActivity.indexOf(prepPrefix);
|
|
2594
|
+
if (prepMetaIdx >= 0) {
|
|
2595
|
+
assistantMessage.metadata.toolActivity.splice(prepMetaIdx, 1);
|
|
2596
|
+
}
|
|
2563
2597
|
const detail =
|
|
2564
2598
|
startedActivity && typeof startedActivity.detail === "string"
|
|
2565
2599
|
? startedActivity.detail.trim()
|
|
2566
2600
|
: "";
|
|
2567
2601
|
const toolText =
|
|
2568
|
-
"- start
|
|
2602
|
+
"- start " + tick +
|
|
2569
2603
|
toolName +
|
|
2570
|
-
|
|
2604
|
+
tick +
|
|
2571
2605
|
(detail ? " (" + detail + ")" : "");
|
|
2572
2606
|
assistantMessage._currentTools.push(toolText);
|
|
2573
2607
|
assistantMessage.metadata.toolActivity.push(toolText);
|
|
@@ -3290,26 +3324,57 @@ var getWebUiClientScript = (markedSource2) => `
|
|
|
3290
3324
|
updateContextRing();
|
|
3291
3325
|
}
|
|
3292
3326
|
}
|
|
3327
|
+
if (eventName === "tool:generating") {
|
|
3328
|
+
const toolName = payload.tool || "tool";
|
|
3329
|
+
if (!Array.isArray(assistantMessage._activeActivities)) {
|
|
3330
|
+
assistantMessage._activeActivities = [];
|
|
3331
|
+
}
|
|
3332
|
+
assistantMessage._activeActivities.push({
|
|
3333
|
+
kind: "generating",
|
|
3334
|
+
tool: toolName,
|
|
3335
|
+
label: "Preparing " + toolName,
|
|
3336
|
+
});
|
|
3337
|
+
if (assistantMessage._currentText.length > 0) {
|
|
3338
|
+
assistantMessage._sections.push({ type: "text", content: assistantMessage._currentText });
|
|
3339
|
+
assistantMessage._currentText = "";
|
|
3340
|
+
}
|
|
3341
|
+
if (!assistantMessage.metadata) assistantMessage.metadata = {};
|
|
3342
|
+
if (!assistantMessage.metadata.toolActivity) assistantMessage.metadata.toolActivity = [];
|
|
3343
|
+
const prepText = "- preparing \\x60" + toolName + "\\x60";
|
|
3344
|
+
assistantMessage._currentTools.push(prepText);
|
|
3345
|
+
assistantMessage.metadata.toolActivity.push(prepText);
|
|
3346
|
+
renderIfActiveConversation(true);
|
|
3347
|
+
}
|
|
3293
3348
|
if (eventName === "tool:started") {
|
|
3294
3349
|
const toolName = payload.tool || "tool";
|
|
3350
|
+
removeActiveActivityForTool(assistantMessage, toolName);
|
|
3295
3351
|
const startedActivity = addActiveActivityFromToolStart(
|
|
3296
3352
|
assistantMessage,
|
|
3297
3353
|
payload,
|
|
3298
3354
|
);
|
|
3299
|
-
// If we have text accumulated, push it as a text section
|
|
3300
3355
|
if (assistantMessage._currentText.length > 0) {
|
|
3301
3356
|
assistantMessage._sections.push({ type: "text", content: assistantMessage._currentText });
|
|
3302
3357
|
assistantMessage._currentText = "";
|
|
3303
3358
|
}
|
|
3359
|
+
if (!assistantMessage.metadata) assistantMessage.metadata = {};
|
|
3360
|
+
if (!assistantMessage.metadata.toolActivity) assistantMessage.metadata.toolActivity = [];
|
|
3361
|
+
const tick = "\\x60";
|
|
3362
|
+
const prepPrefix = "- preparing " + tick + toolName + tick;
|
|
3363
|
+
const prepToolIdx = assistantMessage._currentTools.indexOf(prepPrefix);
|
|
3364
|
+
if (prepToolIdx >= 0) {
|
|
3365
|
+
assistantMessage._currentTools.splice(prepToolIdx, 1);
|
|
3366
|
+
}
|
|
3367
|
+
const prepMetaIdx = assistantMessage.metadata.toolActivity.indexOf(prepPrefix);
|
|
3368
|
+
if (prepMetaIdx >= 0) {
|
|
3369
|
+
assistantMessage.metadata.toolActivity.splice(prepMetaIdx, 1);
|
|
3370
|
+
}
|
|
3304
3371
|
const detail =
|
|
3305
3372
|
startedActivity && typeof startedActivity.detail === "string"
|
|
3306
3373
|
? startedActivity.detail.trim()
|
|
3307
3374
|
: "";
|
|
3308
3375
|
const toolText =
|
|
3309
|
-
"- start
|
|
3376
|
+
"- start " + tick + toolName + tick + (detail ? " (" + detail + ")" : "");
|
|
3310
3377
|
assistantMessage._currentTools.push(toolText);
|
|
3311
|
-
if (!assistantMessage.metadata) assistantMessage.metadata = {};
|
|
3312
|
-
if (!assistantMessage.metadata.toolActivity) assistantMessage.metadata.toolActivity = [];
|
|
3313
3378
|
assistantMessage.metadata.toolActivity.push(toolText);
|
|
3314
3379
|
renderIfActiveConversation(true);
|
|
3315
3380
|
}
|
|
@@ -6150,6 +6215,10 @@ Connect remote MCP servers and expose their tools to the agent:
|
|
|
6150
6215
|
# Add remote MCP server
|
|
6151
6216
|
poncho mcp add --url https://mcp.example.com/github --name github --auth-bearer-env GITHUB_TOKEN
|
|
6152
6217
|
|
|
6218
|
+
# Server with custom headers (e.g. Arcade)
|
|
6219
|
+
poncho mcp add --url https://mcp.arcade.dev --name arcade \\
|
|
6220
|
+
--auth-bearer-env ARCADE_API_KEY --header "Arcade-User-ID: user@example.com"
|
|
6221
|
+
|
|
6153
6222
|
# List configured servers
|
|
6154
6223
|
poncho mcp list
|
|
6155
6224
|
|
|
@@ -6231,6 +6300,8 @@ export default {
|
|
|
6231
6300
|
url: "https://mcp.example.com/github",
|
|
6232
6301
|
auth: { type: "bearer", tokenEnv: "GITHUB_TOKEN" },
|
|
6233
6302
|
},
|
|
6303
|
+
// Custom headers for servers that require them (e.g. Arcade)
|
|
6304
|
+
// { name: "arcade", url: "https://mcp.arcade.dev", auth: { type: "bearer", tokenEnv: "ARCADE_API_KEY" }, headers: { "Arcade-User-ID": "user@example.com" } },
|
|
6234
6305
|
],
|
|
6235
6306
|
// Tool access: true (available), false (disabled), 'approval' (requires human approval)
|
|
6236
6307
|
tools: {
|
|
@@ -9065,9 +9136,11 @@ data: ${JSON.stringify(data)}
|
|
|
9065
9136
|
handler._cronJobs = cronJobs;
|
|
9066
9137
|
handler._conversationStore = conversationStore;
|
|
9067
9138
|
try {
|
|
9068
|
-
const
|
|
9069
|
-
|
|
9070
|
-
|
|
9139
|
+
const allSummaries = await conversationStore.listSummaries();
|
|
9140
|
+
const subagentSummaries = allSummaries.filter((s) => s.parentConversationId);
|
|
9141
|
+
for (const s of subagentSummaries) {
|
|
9142
|
+
const conv = await conversationStore.get(s.conversationId);
|
|
9143
|
+
if (conv?.subagentMeta?.status === "running") {
|
|
9071
9144
|
conv.subagentMeta.status = "stopped";
|
|
9072
9145
|
conv.subagentMeta.error = { code: "SERVER_RESTART", message: "Interrupted by server restart" };
|
|
9073
9146
|
conv.updatedAt = Date.now();
|
|
@@ -9299,7 +9372,7 @@ var runInteractive = async (workingDir, params) => {
|
|
|
9299
9372
|
await harness.initialize();
|
|
9300
9373
|
const identity = await ensureAgentIdentity2(workingDir);
|
|
9301
9374
|
try {
|
|
9302
|
-
const { runInteractiveInk } = await import("./run-interactive-ink-
|
|
9375
|
+
const { runInteractiveInk } = await import("./run-interactive-ink-VSO7GB3Y.js");
|
|
9303
9376
|
await runInteractiveInk({
|
|
9304
9377
|
harness,
|
|
9305
9378
|
params,
|
|
@@ -9680,6 +9753,15 @@ var mcpAdd = async (workingDir, options) => {
|
|
|
9680
9753
|
if (!options.url.startsWith("http://") && !options.url.startsWith("https://")) {
|
|
9681
9754
|
throw new Error("Invalid MCP URL. Expected http:// or https://.");
|
|
9682
9755
|
}
|
|
9756
|
+
const parsedHeaders = options.headers && options.headers.length > 0 ? Object.fromEntries(
|
|
9757
|
+
options.headers.map((h) => {
|
|
9758
|
+
const idx = h.indexOf(":");
|
|
9759
|
+
if (idx < 1) {
|
|
9760
|
+
throw new Error(`Invalid header format "${h}". Expected "Name: value".`);
|
|
9761
|
+
}
|
|
9762
|
+
return [h.slice(0, idx).trim(), h.slice(idx + 1).trim()];
|
|
9763
|
+
})
|
|
9764
|
+
) : void 0;
|
|
9683
9765
|
const serverName = options.name ?? normalizeMcpName({ url: options.url });
|
|
9684
9766
|
mcp.push({
|
|
9685
9767
|
name: serverName,
|
|
@@ -9688,7 +9770,8 @@ var mcpAdd = async (workingDir, options) => {
|
|
|
9688
9770
|
auth: options.authBearerEnv ? {
|
|
9689
9771
|
type: "bearer",
|
|
9690
9772
|
tokenEnv: options.authBearerEnv
|
|
9691
|
-
} : void 0
|
|
9773
|
+
} : void 0,
|
|
9774
|
+
headers: parsedHeaders
|
|
9692
9775
|
});
|
|
9693
9776
|
await writeConfigFile(workingDir, { ...config, mcp });
|
|
9694
9777
|
let envSeedMessage;
|
|
@@ -9732,8 +9815,10 @@ var mcpList = async (workingDir) => {
|
|
|
9732
9815
|
process.stdout.write("Configured MCP servers:\n");
|
|
9733
9816
|
for (const entry of mcp) {
|
|
9734
9817
|
const auth = entry.auth?.type === "bearer" ? `auth=bearer:${entry.auth.tokenEnv}` : "auth=none";
|
|
9818
|
+
const headerKeys = entry.headers ? Object.keys(entry.headers) : [];
|
|
9819
|
+
const headerInfo = headerKeys.length > 0 ? `, headers=${headerKeys.join(",")}` : "";
|
|
9735
9820
|
process.stdout.write(
|
|
9736
|
-
`- ${entry.name ?? entry.url} (remote: ${entry.url}, ${auth})
|
|
9821
|
+
`- ${entry.name ?? entry.url} (remote: ${entry.url}, ${auth}${headerInfo})
|
|
9737
9822
|
`
|
|
9738
9823
|
);
|
|
9739
9824
|
}
|
|
@@ -9937,13 +10022,17 @@ var buildCli = () => {
|
|
|
9937
10022
|
).option("--env <name>", "env variable (repeatable)", (value, all) => {
|
|
9938
10023
|
all.push(value);
|
|
9939
10024
|
return all;
|
|
10025
|
+
}, []).option("--header <header>", "custom header as 'Name: value' (repeatable)", (value, all) => {
|
|
10026
|
+
all.push(value);
|
|
10027
|
+
return all;
|
|
9940
10028
|
}, []).action(
|
|
9941
10029
|
async (options) => {
|
|
9942
10030
|
await mcpAdd(process.cwd(), {
|
|
9943
10031
|
url: options.url,
|
|
9944
10032
|
name: options.name,
|
|
9945
10033
|
envVars: options.env,
|
|
9946
|
-
authBearerEnv: options.authBearerEnv
|
|
10034
|
+
authBearerEnv: options.authBearerEnv,
|
|
10035
|
+
headers: options.header
|
|
9947
10036
|
});
|
|
9948
10037
|
}
|
|
9949
10038
|
);
|
package/dist/cli.js
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -66,6 +66,7 @@ declare const mcpAdd: (workingDir: string, options: {
|
|
|
66
66
|
name?: string;
|
|
67
67
|
envVars?: string[];
|
|
68
68
|
authBearerEnv?: string;
|
|
69
|
+
headers?: string[];
|
|
69
70
|
}) => Promise<void>;
|
|
70
71
|
declare const mcpList: (workingDir: string) => Promise<void>;
|
|
71
72
|
declare const mcpRemove: (workingDir: string, name: string) => Promise<void>;
|
package/dist/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@poncho-ai/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.18.0",
|
|
4
4
|
"description": "CLI for building and deploying AI agents",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -27,9 +27,9 @@
|
|
|
27
27
|
"react": "^19.2.4",
|
|
28
28
|
"react-devtools-core": "^6.1.5",
|
|
29
29
|
"yaml": "^2.8.1",
|
|
30
|
-
"@poncho-ai/harness": "0.
|
|
31
|
-
"@poncho-ai/messaging": "0.2.
|
|
32
|
-
"@poncho-ai/sdk": "1.
|
|
30
|
+
"@poncho-ai/harness": "0.18.0",
|
|
31
|
+
"@poncho-ai/messaging": "0.2.6",
|
|
32
|
+
"@poncho-ai/sdk": "1.3.0"
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
35
35
|
"@types/busboy": "^1.5.4",
|
package/src/index.ts
CHANGED
|
@@ -455,6 +455,10 @@ Connect remote MCP servers and expose their tools to the agent:
|
|
|
455
455
|
# Add remote MCP server
|
|
456
456
|
poncho mcp add --url https://mcp.example.com/github --name github --auth-bearer-env GITHUB_TOKEN
|
|
457
457
|
|
|
458
|
+
# Server with custom headers (e.g. Arcade)
|
|
459
|
+
poncho mcp add --url https://mcp.arcade.dev --name arcade \\
|
|
460
|
+
--auth-bearer-env ARCADE_API_KEY --header "Arcade-User-ID: user@example.com"
|
|
461
|
+
|
|
458
462
|
# List configured servers
|
|
459
463
|
poncho mcp list
|
|
460
464
|
|
|
@@ -536,6 +540,8 @@ export default {
|
|
|
536
540
|
url: "https://mcp.example.com/github",
|
|
537
541
|
auth: { type: "bearer", tokenEnv: "GITHUB_TOKEN" },
|
|
538
542
|
},
|
|
543
|
+
// Custom headers for servers that require them (e.g. Arcade)
|
|
544
|
+
// { name: "arcade", url: "https://mcp.arcade.dev", auth: { type: "bearer", tokenEnv: "ARCADE_API_KEY" }, headers: { "Arcade-User-ID": "user@example.com" } },
|
|
539
545
|
],
|
|
540
546
|
// Tool access: true (available), false (disabled), 'approval' (requires human approval)
|
|
541
547
|
tools: {
|
|
@@ -3753,11 +3759,14 @@ export const createRequestHandler = async (options?: {
|
|
|
3753
3759
|
handler._cronJobs = cronJobs;
|
|
3754
3760
|
handler._conversationStore = conversationStore;
|
|
3755
3761
|
|
|
3756
|
-
// Recover stale subagent runs that were "running" when the server last stopped
|
|
3762
|
+
// Recover stale subagent runs that were "running" when the server last stopped.
|
|
3763
|
+
// Pass no ownerId so we scan across all owners (not just "local-owner").
|
|
3757
3764
|
try {
|
|
3758
|
-
const
|
|
3759
|
-
|
|
3760
|
-
|
|
3765
|
+
const allSummaries = await conversationStore.listSummaries();
|
|
3766
|
+
const subagentSummaries = allSummaries.filter((s) => s.parentConversationId);
|
|
3767
|
+
for (const s of subagentSummaries) {
|
|
3768
|
+
const conv = await conversationStore.get(s.conversationId);
|
|
3769
|
+
if (conv?.subagentMeta?.status === "running") {
|
|
3761
3770
|
conv.subagentMeta.status = "stopped";
|
|
3762
3771
|
conv.subagentMeta.error = { code: "SERVER_RESTART", message: "Interrupted by server restart" };
|
|
3763
3772
|
conv.updatedAt = Date.now();
|
|
@@ -4535,6 +4544,7 @@ export const mcpAdd = async (
|
|
|
4535
4544
|
name?: string;
|
|
4536
4545
|
envVars?: string[];
|
|
4537
4546
|
authBearerEnv?: string;
|
|
4547
|
+
headers?: string[];
|
|
4538
4548
|
},
|
|
4539
4549
|
): Promise<void> => {
|
|
4540
4550
|
const config = (await loadPonchoConfig(workingDir)) ?? { mcp: [] };
|
|
@@ -4548,6 +4558,18 @@ export const mcpAdd = async (
|
|
|
4548
4558
|
if (!options.url.startsWith("http://") && !options.url.startsWith("https://")) {
|
|
4549
4559
|
throw new Error("Invalid MCP URL. Expected http:// or https://.");
|
|
4550
4560
|
}
|
|
4561
|
+
const parsedHeaders: Record<string, string> | undefined =
|
|
4562
|
+
options.headers && options.headers.length > 0
|
|
4563
|
+
? Object.fromEntries(
|
|
4564
|
+
options.headers.map((h) => {
|
|
4565
|
+
const idx = h.indexOf(":");
|
|
4566
|
+
if (idx < 1) {
|
|
4567
|
+
throw new Error(`Invalid header format "${h}". Expected "Name: value".`);
|
|
4568
|
+
}
|
|
4569
|
+
return [h.slice(0, idx).trim(), h.slice(idx + 1).trim()];
|
|
4570
|
+
}),
|
|
4571
|
+
)
|
|
4572
|
+
: undefined;
|
|
4551
4573
|
const serverName = options.name ?? normalizeMcpName({ url: options.url });
|
|
4552
4574
|
mcp.push({
|
|
4553
4575
|
name: serverName,
|
|
@@ -4559,6 +4581,7 @@ export const mcpAdd = async (
|
|
|
4559
4581
|
tokenEnv: options.authBearerEnv,
|
|
4560
4582
|
}
|
|
4561
4583
|
: undefined,
|
|
4584
|
+
headers: parsedHeaders,
|
|
4562
4585
|
});
|
|
4563
4586
|
|
|
4564
4587
|
await writeConfigFile(workingDir, { ...config, mcp });
|
|
@@ -4605,8 +4628,10 @@ export const mcpList = async (workingDir: string): Promise<void> => {
|
|
|
4605
4628
|
for (const entry of mcp) {
|
|
4606
4629
|
const auth =
|
|
4607
4630
|
entry.auth?.type === "bearer" ? `auth=bearer:${entry.auth.tokenEnv}` : "auth=none";
|
|
4631
|
+
const headerKeys = entry.headers ? Object.keys(entry.headers) : [];
|
|
4632
|
+
const headerInfo = headerKeys.length > 0 ? `, headers=${headerKeys.join(",")}` : "";
|
|
4608
4633
|
process.stdout.write(
|
|
4609
|
-
`- ${entry.name ?? entry.url} (remote: ${entry.url}, ${auth})\n`,
|
|
4634
|
+
`- ${entry.name ?? entry.url} (remote: ${entry.url}, ${auth}${headerInfo})\n`,
|
|
4610
4635
|
);
|
|
4611
4636
|
}
|
|
4612
4637
|
};
|
|
@@ -4933,6 +4958,10 @@ export const buildCli = (): Command => {
|
|
|
4933
4958
|
all.push(value);
|
|
4934
4959
|
return all;
|
|
4935
4960
|
}, [] as string[])
|
|
4961
|
+
.option("--header <header>", "custom header as 'Name: value' (repeatable)", (value, all: string[]) => {
|
|
4962
|
+
all.push(value);
|
|
4963
|
+
return all;
|
|
4964
|
+
}, [] as string[])
|
|
4936
4965
|
.action(
|
|
4937
4966
|
async (
|
|
4938
4967
|
options: {
|
|
@@ -4940,6 +4969,7 @@ export const buildCli = (): Command => {
|
|
|
4940
4969
|
name?: string;
|
|
4941
4970
|
authBearerEnv?: string;
|
|
4942
4971
|
env: string[];
|
|
4972
|
+
header: string[];
|
|
4943
4973
|
},
|
|
4944
4974
|
) => {
|
|
4945
4975
|
await mcpAdd(process.cwd(), {
|
|
@@ -4947,6 +4977,7 @@ export const buildCli = (): Command => {
|
|
|
4947
4977
|
name: options.name,
|
|
4948
4978
|
envVars: options.env,
|
|
4949
4979
|
authBearerEnv: options.authBearerEnv,
|
|
4980
|
+
headers: options.header,
|
|
4950
4981
|
});
|
|
4951
4982
|
},
|
|
4952
4983
|
);
|
package/src/web-ui-client.ts
CHANGED
|
@@ -1062,8 +1062,32 @@ export const getWebUiClientScript = (markedSource: string): string => `
|
|
|
1062
1062
|
updateContextRing();
|
|
1063
1063
|
}
|
|
1064
1064
|
}
|
|
1065
|
+
if (eventName === "tool:generating") {
|
|
1066
|
+
const toolName = payload.tool || "tool";
|
|
1067
|
+
if (!Array.isArray(assistantMessage._activeActivities)) {
|
|
1068
|
+
assistantMessage._activeActivities = [];
|
|
1069
|
+
}
|
|
1070
|
+
assistantMessage._activeActivities.push({
|
|
1071
|
+
kind: "generating",
|
|
1072
|
+
tool: toolName,
|
|
1073
|
+
label: "Preparing " + toolName,
|
|
1074
|
+
});
|
|
1075
|
+
if (assistantMessage._currentText.length > 0) {
|
|
1076
|
+
assistantMessage._sections.push({
|
|
1077
|
+
type: "text",
|
|
1078
|
+
content: assistantMessage._currentText,
|
|
1079
|
+
});
|
|
1080
|
+
assistantMessage._currentText = "";
|
|
1081
|
+
}
|
|
1082
|
+
const prepText =
|
|
1083
|
+
"- preparing \\x60" + toolName + "\\x60";
|
|
1084
|
+
assistantMessage._currentTools.push(prepText);
|
|
1085
|
+
assistantMessage.metadata.toolActivity.push(prepText);
|
|
1086
|
+
renderIfActiveConversation(true);
|
|
1087
|
+
}
|
|
1065
1088
|
if (eventName === "tool:started") {
|
|
1066
1089
|
const toolName = payload.tool || "tool";
|
|
1090
|
+
removeActiveActivityForTool(assistantMessage, toolName);
|
|
1067
1091
|
const startedActivity = addActiveActivityFromToolStart(
|
|
1068
1092
|
assistantMessage,
|
|
1069
1093
|
payload,
|
|
@@ -1075,14 +1099,24 @@ export const getWebUiClientScript = (markedSource: string): string => `
|
|
|
1075
1099
|
});
|
|
1076
1100
|
assistantMessage._currentText = "";
|
|
1077
1101
|
}
|
|
1102
|
+
const tick = "\\x60";
|
|
1103
|
+
const prepPrefix = "- preparing " + tick + toolName + tick;
|
|
1104
|
+
const prepToolIdx = assistantMessage._currentTools.indexOf(prepPrefix);
|
|
1105
|
+
if (prepToolIdx >= 0) {
|
|
1106
|
+
assistantMessage._currentTools.splice(prepToolIdx, 1);
|
|
1107
|
+
}
|
|
1108
|
+
const prepMetaIdx = assistantMessage.metadata.toolActivity.indexOf(prepPrefix);
|
|
1109
|
+
if (prepMetaIdx >= 0) {
|
|
1110
|
+
assistantMessage.metadata.toolActivity.splice(prepMetaIdx, 1);
|
|
1111
|
+
}
|
|
1078
1112
|
const detail =
|
|
1079
1113
|
startedActivity && typeof startedActivity.detail === "string"
|
|
1080
1114
|
? startedActivity.detail.trim()
|
|
1081
1115
|
: "";
|
|
1082
1116
|
const toolText =
|
|
1083
|
-
"- start
|
|
1117
|
+
"- start " + tick +
|
|
1084
1118
|
toolName +
|
|
1085
|
-
|
|
1119
|
+
tick +
|
|
1086
1120
|
(detail ? " (" + detail + ")" : "");
|
|
1087
1121
|
assistantMessage._currentTools.push(toolText);
|
|
1088
1122
|
assistantMessage.metadata.toolActivity.push(toolText);
|
|
@@ -1805,26 +1839,57 @@ export const getWebUiClientScript = (markedSource: string): string => `
|
|
|
1805
1839
|
updateContextRing();
|
|
1806
1840
|
}
|
|
1807
1841
|
}
|
|
1842
|
+
if (eventName === "tool:generating") {
|
|
1843
|
+
const toolName = payload.tool || "tool";
|
|
1844
|
+
if (!Array.isArray(assistantMessage._activeActivities)) {
|
|
1845
|
+
assistantMessage._activeActivities = [];
|
|
1846
|
+
}
|
|
1847
|
+
assistantMessage._activeActivities.push({
|
|
1848
|
+
kind: "generating",
|
|
1849
|
+
tool: toolName,
|
|
1850
|
+
label: "Preparing " + toolName,
|
|
1851
|
+
});
|
|
1852
|
+
if (assistantMessage._currentText.length > 0) {
|
|
1853
|
+
assistantMessage._sections.push({ type: "text", content: assistantMessage._currentText });
|
|
1854
|
+
assistantMessage._currentText = "";
|
|
1855
|
+
}
|
|
1856
|
+
if (!assistantMessage.metadata) assistantMessage.metadata = {};
|
|
1857
|
+
if (!assistantMessage.metadata.toolActivity) assistantMessage.metadata.toolActivity = [];
|
|
1858
|
+
const prepText = "- preparing \\x60" + toolName + "\\x60";
|
|
1859
|
+
assistantMessage._currentTools.push(prepText);
|
|
1860
|
+
assistantMessage.metadata.toolActivity.push(prepText);
|
|
1861
|
+
renderIfActiveConversation(true);
|
|
1862
|
+
}
|
|
1808
1863
|
if (eventName === "tool:started") {
|
|
1809
1864
|
const toolName = payload.tool || "tool";
|
|
1865
|
+
removeActiveActivityForTool(assistantMessage, toolName);
|
|
1810
1866
|
const startedActivity = addActiveActivityFromToolStart(
|
|
1811
1867
|
assistantMessage,
|
|
1812
1868
|
payload,
|
|
1813
1869
|
);
|
|
1814
|
-
// If we have text accumulated, push it as a text section
|
|
1815
1870
|
if (assistantMessage._currentText.length > 0) {
|
|
1816
1871
|
assistantMessage._sections.push({ type: "text", content: assistantMessage._currentText });
|
|
1817
1872
|
assistantMessage._currentText = "";
|
|
1818
1873
|
}
|
|
1874
|
+
if (!assistantMessage.metadata) assistantMessage.metadata = {};
|
|
1875
|
+
if (!assistantMessage.metadata.toolActivity) assistantMessage.metadata.toolActivity = [];
|
|
1876
|
+
const tick = "\\x60";
|
|
1877
|
+
const prepPrefix = "- preparing " + tick + toolName + tick;
|
|
1878
|
+
const prepToolIdx = assistantMessage._currentTools.indexOf(prepPrefix);
|
|
1879
|
+
if (prepToolIdx >= 0) {
|
|
1880
|
+
assistantMessage._currentTools.splice(prepToolIdx, 1);
|
|
1881
|
+
}
|
|
1882
|
+
const prepMetaIdx = assistantMessage.metadata.toolActivity.indexOf(prepPrefix);
|
|
1883
|
+
if (prepMetaIdx >= 0) {
|
|
1884
|
+
assistantMessage.metadata.toolActivity.splice(prepMetaIdx, 1);
|
|
1885
|
+
}
|
|
1819
1886
|
const detail =
|
|
1820
1887
|
startedActivity && typeof startedActivity.detail === "string"
|
|
1821
1888
|
? startedActivity.detail.trim()
|
|
1822
1889
|
: "";
|
|
1823
1890
|
const toolText =
|
|
1824
|
-
"- start
|
|
1891
|
+
"- start " + tick + toolName + tick + (detail ? " (" + detail + ")" : "");
|
|
1825
1892
|
assistantMessage._currentTools.push(toolText);
|
|
1826
|
-
if (!assistantMessage.metadata) assistantMessage.metadata = {};
|
|
1827
|
-
if (!assistantMessage.metadata.toolActivity) assistantMessage.metadata.toolActivity = [];
|
|
1828
1893
|
assistantMessage.metadata.toolActivity.push(toolText);
|
|
1829
1894
|
renderIfActiveConversation(true);
|
|
1830
1895
|
}
|