@agent-native/core 0.19.0 → 0.19.3
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/dist/a2a/caller-auth.d.ts +1 -0
- package/dist/a2a/caller-auth.d.ts.map +1 -1
- package/dist/a2a/caller-auth.js +1 -1
- package/dist/a2a/caller-auth.js.map +1 -1
- package/dist/agent/production-agent.d.ts +1 -1
- package/dist/agent/production-agent.d.ts.map +1 -1
- package/dist/agent/production-agent.js +34 -2
- package/dist/agent/production-agent.js.map +1 -1
- package/dist/cli/code-agent-executor.d.ts.map +1 -1
- package/dist/cli/code-agent-executor.js +47 -256
- package/dist/cli/code-agent-executor.js.map +1 -1
- package/dist/cli/connect.d.ts +3 -2
- package/dist/cli/connect.d.ts.map +1 -1
- package/dist/cli/connect.js +12 -8
- package/dist/cli/connect.js.map +1 -1
- package/dist/cli/mcp-config-writers.d.ts +3 -3
- package/dist/cli/mcp-config-writers.d.ts.map +1 -1
- package/dist/cli/mcp-config-writers.js +19 -8
- package/dist/cli/mcp-config-writers.js.map +1 -1
- package/dist/client/AgentPanel.d.ts +3 -1
- package/dist/client/AgentPanel.d.ts.map +1 -1
- package/dist/client/AgentPanel.js +4 -4
- package/dist/client/AgentPanel.js.map +1 -1
- package/dist/client/AssistantChat.d.ts +3 -0
- package/dist/client/AssistantChat.d.ts.map +1 -1
- package/dist/client/AssistantChat.js +11 -3
- package/dist/client/AssistantChat.js.map +1 -1
- package/dist/client/MultiTabAssistantChat.d.ts.map +1 -1
- package/dist/client/MultiTabAssistantChat.js +4 -1
- package/dist/client/MultiTabAssistantChat.js.map +1 -1
- package/dist/client/dynamic-suggestions.d.ts +43 -0
- package/dist/client/dynamic-suggestions.d.ts.map +1 -0
- package/dist/client/dynamic-suggestions.js +344 -0
- package/dist/client/dynamic-suggestions.js.map +1 -0
- package/dist/client/index.d.ts +1 -0
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +1 -0
- package/dist/client/index.js.map +1 -1
- package/dist/client/settings/SettingsPanel.js +2 -2
- package/dist/client/settings/SettingsPanel.js.map +1 -1
- package/dist/coding-tools/index.d.ts +31 -0
- package/dist/coding-tools/index.d.ts.map +1 -0
- package/dist/coding-tools/index.js +411 -0
- package/dist/coding-tools/index.js.map +1 -0
- package/dist/mcp/build-server.d.ts +33 -1
- package/dist/mcp/build-server.d.ts.map +1 -1
- package/dist/mcp/build-server.js +33 -10
- package/dist/mcp/build-server.js.map +1 -1
- package/dist/mcp/builtin-tools.d.ts +3 -1
- package/dist/mcp/builtin-tools.d.ts.map +1 -1
- package/dist/mcp/builtin-tools.js +115 -26
- package/dist/mcp/builtin-tools.js.map +1 -1
- package/dist/mcp/connect-route.d.ts.map +1 -1
- package/dist/mcp/connect-route.js +382 -74
- package/dist/mcp/connect-route.js.map +1 -1
- package/dist/mcp/org-directory.d.ts +83 -0
- package/dist/mcp/org-directory.d.ts.map +1 -0
- package/dist/mcp/org-directory.js +201 -0
- package/dist/mcp/org-directory.js.map +1 -0
- package/dist/mcp/server.d.ts +38 -1
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +222 -77
- package/dist/mcp/server.js.map +1 -1
- package/dist/scripts/dev/index.d.ts +6 -4
- package/dist/scripts/dev/index.d.ts.map +1 -1
- package/dist/scripts/dev/index.js +28 -13
- package/dist/scripts/dev/index.js.map +1 -1
- package/dist/server/agent-chat-plugin.d.ts +6 -6
- package/dist/server/agent-chat-plugin.d.ts.map +1 -1
- package/dist/server/agent-chat-plugin.js +65 -32
- package/dist/server/agent-chat-plugin.js.map +1 -1
- package/dist/server/agent-teams.js +2 -2
- package/dist/server/agent-teams.js.map +1 -1
- package/dist/server/agents-bundle.d.ts +3 -3
- package/dist/server/agents-bundle.js +5 -5
- package/dist/server/agents-bundle.js.map +1 -1
- package/dist/server/auth.d.ts +8 -0
- package/dist/server/auth.d.ts.map +1 -1
- package/dist/server/auth.js +8 -1
- package/dist/server/auth.js.map +1 -1
- package/dist/server/sentry.d.ts.map +1 -1
- package/dist/server/sentry.js +17 -2
- package/dist/server/sentry.js.map +1 -1
- package/dist/vite/client.d.ts.map +1 -1
- package/dist/vite/client.js +1 -0
- package/dist/vite/client.js.map +1 -1
- package/docs/content/client.md +15 -0
- package/docs/content/code-agents-ui.md +11 -1
- package/docs/content/drop-in-agent.md +3 -1
- package/docs/content/external-agents.md +27 -6
- package/docs/content/frames.md +1 -1
- package/docs/content/mcp-clients.md +2 -0
- package/docs/content/mcp-protocol.md +4 -2
- package/docs/content/migration-workbench.md +5 -0
- package/package.json +1 -1
|
@@ -28,11 +28,15 @@ export const CLIENTS = [
|
|
|
28
28
|
"cowork",
|
|
29
29
|
];
|
|
30
30
|
/** Build the HTTP MCP server entry for a deployed agent-native app. */
|
|
31
|
-
export function buildHttpMcpEntry(mcpUrl, token) {
|
|
31
|
+
export function buildHttpMcpEntry(mcpUrl, token, headers) {
|
|
32
|
+
const mergedHeaders = {
|
|
33
|
+
...(headers ?? {}),
|
|
34
|
+
...(token ? { Authorization: `Bearer ${token}` } : {}),
|
|
35
|
+
};
|
|
32
36
|
return {
|
|
33
37
|
type: "http",
|
|
34
38
|
url: mcpUrl,
|
|
35
|
-
...(
|
|
39
|
+
...(Object.keys(mergedHeaders).length ? { headers: mergedHeaders } : {}),
|
|
36
40
|
};
|
|
37
41
|
}
|
|
38
42
|
// ---------------------------------------------------------------------------
|
|
@@ -123,11 +127,18 @@ function legacyCodexMcpHeader(name) {
|
|
|
123
127
|
return /^[A-Za-z0-9_-]+$/.test(name) ? `[mcp_servers.${name}]` : null;
|
|
124
128
|
}
|
|
125
129
|
/** Build a `[mcp_servers.<name>]` block for an HTTP-type MCP server. */
|
|
126
|
-
export function buildCodexHttpBlock(name, mcpUrl, token) {
|
|
130
|
+
export function buildCodexHttpBlock(name, mcpUrl, token, headers) {
|
|
127
131
|
const lines = [codexMcpHeader(name)];
|
|
128
132
|
lines.push(`url = ${tomlQuote(mcpUrl)}`);
|
|
129
|
-
|
|
130
|
-
|
|
133
|
+
const mergedHeaders = {
|
|
134
|
+
...(headers ?? {}),
|
|
135
|
+
...(token ? { Authorization: `Bearer ${token}` } : {}),
|
|
136
|
+
};
|
|
137
|
+
const headerEntries = Object.entries(mergedHeaders);
|
|
138
|
+
if (headerEntries.length) {
|
|
139
|
+
lines.push(`http_headers = { ${headerEntries
|
|
140
|
+
.map(([key, value]) => `${tomlQuote(key)} = ${tomlQuote(value)}`)
|
|
141
|
+
.join(", ")} }`);
|
|
131
142
|
}
|
|
132
143
|
return lines.join("\n") + "\n";
|
|
133
144
|
}
|
|
@@ -197,13 +208,13 @@ export function codexHasBlock(file, name) {
|
|
|
197
208
|
* given client's config file and return the file path that was written.
|
|
198
209
|
* Re-running replaces the same named entry — never duplicates.
|
|
199
210
|
*/
|
|
200
|
-
export function writeHttpEntryForClient(client, serverName, mcpUrl, token, baseDir, scope) {
|
|
211
|
+
export function writeHttpEntryForClient(client, serverName, mcpUrl, token, baseDir, scope, headers) {
|
|
201
212
|
const file = configPathFor(client, baseDir, scope);
|
|
202
213
|
if (client === "codex") {
|
|
203
|
-
writeCodexBlock(file, serverName, buildCodexHttpBlock(serverName, mcpUrl, token));
|
|
214
|
+
writeCodexBlock(file, serverName, buildCodexHttpBlock(serverName, mcpUrl, token, headers));
|
|
204
215
|
}
|
|
205
216
|
else {
|
|
206
|
-
writeJsonMcpEntry(file, serverName, buildHttpMcpEntry(mcpUrl, token));
|
|
217
|
+
writeJsonMcpEntry(file, serverName, buildHttpMcpEntry(mcpUrl, token, headers));
|
|
207
218
|
}
|
|
208
219
|
return file;
|
|
209
220
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mcp-config-writers.js","sourceRoot":"","sources":["../../src/cli/mcp-config-writers.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Shared MCP client-config writers.\n *\n * Extracted so both `agent-native mcp install` (see `mcp.ts`) and\n * `agent-native connect` (see `connect.ts`) write the EXACT same on-disk\n * config file targets and formats for every supported client. `mcp.ts`\n * intentionally keeps its own hand-rolled copies of these writers (its\n * external behavior is unchanged); new code should import from here so the\n * formats never diverge.\n *\n * Supported clients and their config files:\n * - claude-code / claude-code-cli → `.mcp.json` (project) or\n * `~/.claude.json` (user). JSON `mcpServers[name] = entry`.\n * - cowork → `~/.cowork/mcp.json`. Same JSON shape.\n * - codex → `~/.codex/config.toml`.\n * `[mcp_servers.<name>]` block.\n *\n * Node-only. No new npm deps — hand-rolled JSON merge + minimal TOML block\n * merge, mirroring `mcp.ts`.\n */\n\nimport fs from \"node:fs\";\nimport os from \"node:os\";\nimport path from \"node:path\";\n\nexport type ClientId = \"claude-code\" | \"claude-code-cli\" | \"codex\" | \"cowork\";\n\nexport const CLIENTS: ClientId[] = [\n \"claude-code\",\n \"claude-code-cli\",\n \"codex\",\n \"cowork\",\n];\n\n/** The HTTP MCP server entry written into a JSON client config. */\nexport interface HttpMcpEntry {\n type: \"http\";\n url: string;\n headers?: Record<string, string>;\n}\n\n/** Build the HTTP MCP server entry for a deployed agent-native app. */\nexport function buildHttpMcpEntry(\n mcpUrl: string,\n token?: string,\n): HttpMcpEntry {\n return {\n type: \"http\",\n url: mcpUrl,\n ...(token ? { headers: { Authorization: `Bearer ${token}` } } : {}),\n };\n}\n\n// ---------------------------------------------------------------------------\n// Config file locations — kept identical to `mcp.ts`.\n// ---------------------------------------------------------------------------\n\n/**\n * Cowork consumes MCP exactly like Claude Code (same JSON server-entry\n * shape). Resolved lazily so `os.homedir()` reflects the current `$HOME`.\n */\nexport function coworkConfigPath(): string {\n return path.join(os.homedir(), \".cowork\", \"mcp.json\");\n}\n\nexport function claudeCodeProjectConfig(baseDir: string): string {\n return path.join(baseDir, \".mcp.json\");\n}\n\nexport function claudeCodeUserConfig(): string {\n return path.join(os.homedir(), \".claude.json\");\n}\n\nexport function codexConfigPath(): string {\n return path.join(os.homedir(), \".codex\", \"config.toml\");\n}\n\n/**\n * Resolve the on-disk config path for a client.\n *\n * `scope` only affects Claude Code / Claude Code CLI: `\"user\"` → the global\n * `~/.claude.json`, anything else → the project-local `.mcp.json` rooted at\n * `baseDir`.\n */\nexport function configPathFor(\n client: ClientId,\n baseDir: string,\n scope: string | undefined,\n): string {\n switch (client) {\n case \"claude-code\":\n case \"claude-code-cli\":\n return scope === \"user\"\n ? claudeCodeUserConfig()\n : claudeCodeProjectConfig(baseDir);\n case \"cowork\":\n return coworkConfigPath();\n case \"codex\":\n return codexConfigPath();\n }\n}\n\n// ---------------------------------------------------------------------------\n// JSON client configs (Claude Code, Claude Code CLI, Cowork)\n// ---------------------------------------------------------------------------\n\nfunction readJsonFile(file: string): Record<string, any> {\n try {\n const raw = fs.readFileSync(file, \"utf-8\");\n const parsed = JSON.parse(raw);\n return parsed && typeof parsed === \"object\" ? parsed : {};\n } catch {\n return {};\n }\n}\n\n/**\n * Idempotently write `mcpServers[name] = entry` into a JSON config file.\n * Pass `entry === null` to delete the named entry. Re-running with the same\n * name replaces the existing entry in place — never duplicates.\n */\nexport function writeJsonMcpEntry(\n file: string,\n name: string,\n entry: Record<string, unknown> | null,\n): void {\n const config = readJsonFile(file);\n if (!config.mcpServers || typeof config.mcpServers !== \"object\") {\n config.mcpServers = {};\n }\n if (entry === null) {\n delete config.mcpServers[name];\n } else {\n config.mcpServers[name] = entry;\n }\n fs.mkdirSync(path.dirname(file), { recursive: true });\n fs.writeFileSync(file, JSON.stringify(config, null, 2) + \"\\n\", \"utf-8\");\n}\n\nexport function hasJsonMcpEntry(file: string, name: string): boolean {\n const config = readJsonFile(file);\n return !!config?.mcpServers && name in config.mcpServers;\n}\n\n// ---------------------------------------------------------------------------\n// Codex TOML (hand-rolled minimal block merge, no new dep)\n// ---------------------------------------------------------------------------\n\nfunction tomlQuote(s: string): string {\n return `\"${s.replace(/\\\\/g, \"\\\\\\\\\").replace(/\"/g, '\\\\\"')}\"`;\n}\n\nfunction codexMcpHeader(name: string): string {\n return `[mcp_servers.${tomlQuote(name)}]`;\n}\n\nfunction legacyCodexMcpHeader(name: string): string | null {\n return /^[A-Za-z0-9_-]+$/.test(name) ? `[mcp_servers.${name}]` : null;\n}\n\n/** Build a `[mcp_servers.<name>]` block for an HTTP-type MCP server. */\nexport function buildCodexHttpBlock(\n name: string,\n mcpUrl: string,\n token?: string,\n): string {\n const lines: string[] = [codexMcpHeader(name)];\n lines.push(`url = ${tomlQuote(mcpUrl)}`);\n if (token) {\n lines.push(\n `http_headers = { Authorization = ${tomlQuote(`Bearer ${token}`)} }`,\n );\n }\n return lines.join(\"\\n\") + \"\\n\";\n}\n\n/**\n * Replace (or append) the `[mcp_servers.<name>]` block in a TOML file\n * without disturbing other content. A block is the header line plus every\n * following line until the next top-level `[` table header or EOF. Pass\n * `block === null` to remove the block. Identical algorithm to `mcp.ts`'s\n * `writeCodexBlock` so the two never diverge.\n */\nexport function writeCodexBlock(\n file: string,\n name: string,\n block: string | null,\n): void {\n let content = \"\";\n try {\n content = fs.readFileSync(file, \"utf-8\");\n } catch {\n content = \"\";\n }\n\n const headers = new Set(\n [codexMcpHeader(name), legacyCodexMcpHeader(name)].filter(\n Boolean,\n ) as string[],\n );\n const lines = content.split(/\\r?\\n/);\n const out: string[] = [];\n let i = 0;\n let removed = false;\n while (i < lines.length) {\n const line = lines[i];\n if (headers.has(line.trim())) {\n // Skip this block entirely (header + body until next table header).\n removed = true;\n i++;\n while (i < lines.length && !/^\\s*\\[/.test(lines[i])) i++;\n continue;\n }\n out.push(line);\n i++;\n }\n\n let next = out\n .join(\"\\n\")\n .replace(/\\n{3,}/g, \"\\n\\n\")\n .replace(/\\n*$/, \"\\n\");\n if (block !== null) {\n next = next.replace(/\\n*$/, \"\\n\");\n if (next.trim().length) next += \"\\n\";\n next += block;\n }\n if (block === null && !removed) return; // nothing to do\n\n fs.mkdirSync(path.dirname(file), { recursive: true });\n fs.writeFileSync(file, next, \"utf-8\");\n}\n\nexport function codexHasBlock(file: string, name: string): boolean {\n try {\n const content = fs.readFileSync(file, \"utf-8\");\n const headers = new Set(\n [codexMcpHeader(name), legacyCodexMcpHeader(name)].filter(\n Boolean,\n ) as string[],\n );\n return content.split(/\\r?\\n/).some((line) => headers.has(line.trim()));\n } catch {\n return false;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Unified write helper\n// ---------------------------------------------------------------------------\n\n/**\n * Idempotently write the HTTP MCP server entry for `serverName` into the\n * given client's config file and return the file path that was written.\n * Re-running replaces the same named entry — never duplicates.\n */\nexport function writeHttpEntryForClient(\n client: ClientId,\n serverName: string,\n mcpUrl: string,\n token: string | undefined,\n baseDir: string,\n scope: string | undefined,\n): string {\n const file = configPathFor(client, baseDir, scope);\n if (client === \"codex\") {\n writeCodexBlock(\n file,\n serverName,\n buildCodexHttpBlock(serverName, mcpUrl, token),\n );\n } else {\n writeJsonMcpEntry(\n file,\n serverName,\n buildHttpMcpEntry(mcpUrl, token) as unknown as Record<string, unknown>,\n );\n }\n return file;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"mcp-config-writers.js","sourceRoot":"","sources":["../../src/cli/mcp-config-writers.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Shared MCP client-config writers.\n *\n * Extracted so both `agent-native mcp install` (see `mcp.ts`) and\n * `agent-native connect` (see `connect.ts`) write the EXACT same on-disk\n * config file targets and formats for every supported client. `mcp.ts`\n * intentionally keeps its own hand-rolled copies of these writers (its\n * external behavior is unchanged); new code should import from here so the\n * formats never diverge.\n *\n * Supported clients and their config files:\n * - claude-code / claude-code-cli → `.mcp.json` (project) or\n * `~/.claude.json` (user). JSON `mcpServers[name] = entry`.\n * - cowork → `~/.cowork/mcp.json`. Same JSON shape.\n * - codex → `~/.codex/config.toml`.\n * `[mcp_servers.<name>]` block.\n *\n * Node-only. No new npm deps — hand-rolled JSON merge + minimal TOML block\n * merge, mirroring `mcp.ts`.\n */\n\nimport fs from \"node:fs\";\nimport os from \"node:os\";\nimport path from \"node:path\";\n\nexport type ClientId = \"claude-code\" | \"claude-code-cli\" | \"codex\" | \"cowork\";\n\nexport const CLIENTS: ClientId[] = [\n \"claude-code\",\n \"claude-code-cli\",\n \"codex\",\n \"cowork\",\n];\n\n/** The HTTP MCP server entry written into a JSON client config. */\nexport interface HttpMcpEntry {\n type: \"http\";\n url: string;\n headers?: Record<string, string>;\n}\n\n/** Build the HTTP MCP server entry for a deployed agent-native app. */\nexport function buildHttpMcpEntry(\n mcpUrl: string,\n token?: string,\n headers?: Record<string, string>,\n): HttpMcpEntry {\n const mergedHeaders = {\n ...(headers ?? {}),\n ...(token ? { Authorization: `Bearer ${token}` } : {}),\n };\n return {\n type: \"http\",\n url: mcpUrl,\n ...(Object.keys(mergedHeaders).length ? { headers: mergedHeaders } : {}),\n };\n}\n\n// ---------------------------------------------------------------------------\n// Config file locations — kept identical to `mcp.ts`.\n// ---------------------------------------------------------------------------\n\n/**\n * Cowork consumes MCP exactly like Claude Code (same JSON server-entry\n * shape). Resolved lazily so `os.homedir()` reflects the current `$HOME`.\n */\nexport function coworkConfigPath(): string {\n return path.join(os.homedir(), \".cowork\", \"mcp.json\");\n}\n\nexport function claudeCodeProjectConfig(baseDir: string): string {\n return path.join(baseDir, \".mcp.json\");\n}\n\nexport function claudeCodeUserConfig(): string {\n return path.join(os.homedir(), \".claude.json\");\n}\n\nexport function codexConfigPath(): string {\n return path.join(os.homedir(), \".codex\", \"config.toml\");\n}\n\n/**\n * Resolve the on-disk config path for a client.\n *\n * `scope` only affects Claude Code / Claude Code CLI: `\"user\"` → the global\n * `~/.claude.json`, anything else → the project-local `.mcp.json` rooted at\n * `baseDir`.\n */\nexport function configPathFor(\n client: ClientId,\n baseDir: string,\n scope: string | undefined,\n): string {\n switch (client) {\n case \"claude-code\":\n case \"claude-code-cli\":\n return scope === \"user\"\n ? claudeCodeUserConfig()\n : claudeCodeProjectConfig(baseDir);\n case \"cowork\":\n return coworkConfigPath();\n case \"codex\":\n return codexConfigPath();\n }\n}\n\n// ---------------------------------------------------------------------------\n// JSON client configs (Claude Code, Claude Code CLI, Cowork)\n// ---------------------------------------------------------------------------\n\nfunction readJsonFile(file: string): Record<string, any> {\n try {\n const raw = fs.readFileSync(file, \"utf-8\");\n const parsed = JSON.parse(raw);\n return parsed && typeof parsed === \"object\" ? parsed : {};\n } catch {\n return {};\n }\n}\n\n/**\n * Idempotently write `mcpServers[name] = entry` into a JSON config file.\n * Pass `entry === null` to delete the named entry. Re-running with the same\n * name replaces the existing entry in place — never duplicates.\n */\nexport function writeJsonMcpEntry(\n file: string,\n name: string,\n entry: Record<string, unknown> | null,\n): void {\n const config = readJsonFile(file);\n if (!config.mcpServers || typeof config.mcpServers !== \"object\") {\n config.mcpServers = {};\n }\n if (entry === null) {\n delete config.mcpServers[name];\n } else {\n config.mcpServers[name] = entry;\n }\n fs.mkdirSync(path.dirname(file), { recursive: true });\n fs.writeFileSync(file, JSON.stringify(config, null, 2) + \"\\n\", \"utf-8\");\n}\n\nexport function hasJsonMcpEntry(file: string, name: string): boolean {\n const config = readJsonFile(file);\n return !!config?.mcpServers && name in config.mcpServers;\n}\n\n// ---------------------------------------------------------------------------\n// Codex TOML (hand-rolled minimal block merge, no new dep)\n// ---------------------------------------------------------------------------\n\nfunction tomlQuote(s: string): string {\n return `\"${s.replace(/\\\\/g, \"\\\\\\\\\").replace(/\"/g, '\\\\\"')}\"`;\n}\n\nfunction codexMcpHeader(name: string): string {\n return `[mcp_servers.${tomlQuote(name)}]`;\n}\n\nfunction legacyCodexMcpHeader(name: string): string | null {\n return /^[A-Za-z0-9_-]+$/.test(name) ? `[mcp_servers.${name}]` : null;\n}\n\n/** Build a `[mcp_servers.<name>]` block for an HTTP-type MCP server. */\nexport function buildCodexHttpBlock(\n name: string,\n mcpUrl: string,\n token?: string,\n headers?: Record<string, string>,\n): string {\n const lines: string[] = [codexMcpHeader(name)];\n lines.push(`url = ${tomlQuote(mcpUrl)}`);\n const mergedHeaders = {\n ...(headers ?? {}),\n ...(token ? { Authorization: `Bearer ${token}` } : {}),\n };\n const headerEntries = Object.entries(mergedHeaders);\n if (headerEntries.length) {\n lines.push(\n `http_headers = { ${headerEntries\n .map(([key, value]) => `${tomlQuote(key)} = ${tomlQuote(value)}`)\n .join(\", \")} }`,\n );\n }\n return lines.join(\"\\n\") + \"\\n\";\n}\n\n/**\n * Replace (or append) the `[mcp_servers.<name>]` block in a TOML file\n * without disturbing other content. A block is the header line plus every\n * following line until the next top-level `[` table header or EOF. Pass\n * `block === null` to remove the block. Identical algorithm to `mcp.ts`'s\n * `writeCodexBlock` so the two never diverge.\n */\nexport function writeCodexBlock(\n file: string,\n name: string,\n block: string | null,\n): void {\n let content = \"\";\n try {\n content = fs.readFileSync(file, \"utf-8\");\n } catch {\n content = \"\";\n }\n\n const headers = new Set(\n [codexMcpHeader(name), legacyCodexMcpHeader(name)].filter(\n Boolean,\n ) as string[],\n );\n const lines = content.split(/\\r?\\n/);\n const out: string[] = [];\n let i = 0;\n let removed = false;\n while (i < lines.length) {\n const line = lines[i];\n if (headers.has(line.trim())) {\n // Skip this block entirely (header + body until next table header).\n removed = true;\n i++;\n while (i < lines.length && !/^\\s*\\[/.test(lines[i])) i++;\n continue;\n }\n out.push(line);\n i++;\n }\n\n let next = out\n .join(\"\\n\")\n .replace(/\\n{3,}/g, \"\\n\\n\")\n .replace(/\\n*$/, \"\\n\");\n if (block !== null) {\n next = next.replace(/\\n*$/, \"\\n\");\n if (next.trim().length) next += \"\\n\";\n next += block;\n }\n if (block === null && !removed) return; // nothing to do\n\n fs.mkdirSync(path.dirname(file), { recursive: true });\n fs.writeFileSync(file, next, \"utf-8\");\n}\n\nexport function codexHasBlock(file: string, name: string): boolean {\n try {\n const content = fs.readFileSync(file, \"utf-8\");\n const headers = new Set(\n [codexMcpHeader(name), legacyCodexMcpHeader(name)].filter(\n Boolean,\n ) as string[],\n );\n return content.split(/\\r?\\n/).some((line) => headers.has(line.trim()));\n } catch {\n return false;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Unified write helper\n// ---------------------------------------------------------------------------\n\n/**\n * Idempotently write the HTTP MCP server entry for `serverName` into the\n * given client's config file and return the file path that was written.\n * Re-running replaces the same named entry — never duplicates.\n */\nexport function writeHttpEntryForClient(\n client: ClientId,\n serverName: string,\n mcpUrl: string,\n token: string | undefined,\n baseDir: string,\n scope: string | undefined,\n headers?: Record<string, string>,\n): string {\n const file = configPathFor(client, baseDir, scope);\n if (client === \"codex\") {\n writeCodexBlock(\n file,\n serverName,\n buildCodexHttpBlock(serverName, mcpUrl, token, headers),\n );\n } else {\n writeJsonMcpEntry(\n file,\n serverName,\n buildHttpMcpEntry(mcpUrl, token, headers) as unknown as Record<\n string,\n unknown\n >,\n );\n }\n return file;\n}\n"]}
|
|
@@ -94,6 +94,8 @@ export interface AgentSidebarProps {
|
|
|
94
94
|
emptyStateText?: string;
|
|
95
95
|
/** Suggestion prompts shown when no messages */
|
|
96
96
|
suggestions?: string[];
|
|
97
|
+
/** Context-aware suggestions merged with `suggestions`. Enabled by default. */
|
|
98
|
+
dynamicSuggestions?: AssistantChatProps["dynamicSuggestions"];
|
|
97
99
|
/** Initial sidebar width in pixels. Mount-only; user resize and a saved
|
|
98
100
|
* localStorage value override this. Default: 380 */
|
|
99
101
|
defaultSidebarWidth?: number;
|
|
@@ -119,7 +121,7 @@ export interface AgentSidebarProps {
|
|
|
119
121
|
* Wraps app content with a toggleable agent sidebar.
|
|
120
122
|
* Use AgentToggleButton in your header to open/close it.
|
|
121
123
|
*/
|
|
122
|
-
export declare function AgentSidebar({ children, emptyStateText, suggestions, defaultSidebarWidth, sidebarWidth, position, defaultOpen, animateMobile, scope, browserTabId, }: AgentSidebarProps): import("react/jsx-runtime").JSX.Element;
|
|
124
|
+
export declare function AgentSidebar({ children, emptyStateText, suggestions, dynamicSuggestions, defaultSidebarWidth, sidebarWidth, position, defaultOpen, animateMobile, scope, browserTabId, }: AgentSidebarProps): import("react/jsx-runtime").JSX.Element;
|
|
123
125
|
/**
|
|
124
126
|
* Focus the agent chat composer input.
|
|
125
127
|
* Opens the sidebar if closed, then focuses the text input.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AgentPanel.d.ts","sourceRoot":"","sources":["../../src/client/AgentPanel.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,KASN,MAAM,OAAO,CAAC;AAwCf,OAAO,EAEL,KAAK,kBAAkB,EACxB,MAAM,oBAAoB,CAAC;AAiK5B,MAAM,WAAW,oBAAoB;IACnC,0EAA0E;IAC1E,OAAO,EAAE,OAAO,CAAC;IACjB,qDAAqD;IACrD,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,yDAAyD;IACzD,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,oDAAoD;IACpD,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,kDAAkD;IAClD,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,4EAA4E;IAC5E,4BAA4B,CAAC,EAAE,MAAM,CAAC;IACtC,mEAAmE;IACnE,2BAA2B,CAAC,EAAE,MAAM,CAAC;IACrC,wEAAwE;IACxE,8BAA8B,CAAC,EAAE,MAAM,CAAC;CACzC;AAgGD,MAAM,WAAW,eAAgB,SAAQ,IAAI,CAC3C,kBAAkB,EAClB,eAAe,CAChB;IACC,oCAAoC;IACpC,WAAW,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC;IAC7B,wCAAwC;IACxC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,6GAA6G;IAC7G,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;IACxB,iFAAiF;IACjF,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,6HAA6H;IAC7H,kBAAkB,CAAC,EAAE,MAAM,IAAI,CAAC;IAChC,iGAAiG;IACjG,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,yFAAyF;IACzF,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;;;;OAMG;IACH,KAAK,CAAC,EAAE,OAAO,uBAAuB,EAAE,eAAe,GAAG,IAAI,CAAC;IAC/D,mEAAmE;IACnE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gFAAgF;IAChF,UAAU,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC7B,uDAAuD;IACvD,UAAU,CAAC,EAAE,oBAAoB,CAAC;CACnC;
|
|
1
|
+
{"version":3,"file":"AgentPanel.d.ts","sourceRoot":"","sources":["../../src/client/AgentPanel.tsx"],"names":[],"mappings":"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"}
|
|
@@ -244,7 +244,7 @@ function CodeAccessUnavailablePanel({ title, description, ctaLabel, ctaHref, sec
|
|
|
244
244
|
});
|
|
245
245
|
}, className: "inline-flex items-center gap-1.5 rounded-md border border-border bg-background px-3 py-1.5 text-xs font-medium text-foreground hover:bg-accent", children: [secondaryCtaLabel, _jsx(IconExternalLink, { className: "h-3 w-3" })] })] })] }));
|
|
246
246
|
}
|
|
247
|
-
function AgentPanelInner({ defaultMode = "chat", className, apiUrl, emptyStateText, emptyStateAddon, suggestions, showHeader = true, onCollapse, isFullscreen, onToggleFullscreen, devAppUrl, storageKey, scope, browserTabId, chatNotice, codeAccess, }) {
|
|
247
|
+
function AgentPanelInner({ defaultMode = "chat", className, apiUrl, emptyStateText, emptyStateAddon, suggestions, dynamicSuggestions, showHeader = true, onCollapse, isFullscreen, onToggleFullscreen, devAppUrl, storageKey, scope, browserTabId, chatNotice, codeAccess, }) {
|
|
248
248
|
const mounted = useClientOnly();
|
|
249
249
|
const keyPrefix = storageKey ? `:${storageKey}` : "";
|
|
250
250
|
const execModeKey = `${EXEC_MODE_KEY}${keyPrefix}`;
|
|
@@ -562,7 +562,7 @@ function AgentPanelInner({ defaultMode = "chat", className, apiUrl, emptyStateTe
|
|
|
562
562
|
`[data-agent-fullscreen='true'] .agent-composer-area{` +
|
|
563
563
|
`max-width:${FULLSCREEN_CONTENT_MAX_PX}px;` +
|
|
564
564
|
`margin-left:auto;margin-right:auto;width:100%;}`,
|
|
565
|
-
} }), SHOW_ONBOARDING && mounted && canUseCodeTools && (_jsx(Suspense, { fallback: null, children: _jsx(OnboardingPanel, {}) })), _jsx("div", { className: cn("flex flex-col min-h-0", mode === "chat" ? "flex-1" : "shrink-0"), children: mounted && (_jsx(MultiTabAssistantChat, { apiUrl: apiUrl, showHeader: false, renderHeader: showHeader ? renderChatHeader : undefined, renderOverlay: undefined, contentHidden: mode !== "chat", emptyStateText: emptyStateText, emptyStateAddon: emptyStateAddon, suggestions: suggestions, onSwitchToCli: () => switchMode("cli"), execMode: execMode, onExecModeChange: switchExecMode, storageKey: storageKey, scope: scope, browserTabId: browserTabId })) }), canUseCodeTools
|
|
565
|
+
} }), SHOW_ONBOARDING && mounted && canUseCodeTools && (_jsx(Suspense, { fallback: null, children: _jsx(OnboardingPanel, {}) })), _jsx("div", { className: cn("flex flex-col min-h-0", mode === "chat" ? "flex-1" : "shrink-0"), children: mounted && (_jsx(MultiTabAssistantChat, { apiUrl: apiUrl, showHeader: false, renderHeader: showHeader ? renderChatHeader : undefined, renderOverlay: undefined, contentHidden: mode !== "chat", emptyStateText: emptyStateText, emptyStateAddon: emptyStateAddon, suggestions: suggestions, dynamicSuggestions: dynamicSuggestions, onSwitchToCli: () => switchMode("cli"), execMode: execMode, onExecModeChange: switchExecMode, storageKey: storageKey, scope: scope, browserTabId: browserTabId })) }), canUseCodeTools
|
|
566
566
|
? mode === "cli" &&
|
|
567
567
|
cliTabs.map((id) => (_jsx("div", { className: "min-h-0 relative flex-1", style: {
|
|
568
568
|
display: id === activeCliTab ? undefined : "none",
|
|
@@ -943,7 +943,7 @@ export function AgentChatSurface({ mode = "panel", className, defaultMode = "cha
|
|
|
943
943
|
* Wraps app content with a toggleable agent sidebar.
|
|
944
944
|
* Use AgentToggleButton in your header to open/close it.
|
|
945
945
|
*/
|
|
946
|
-
export function AgentSidebar({ children, emptyStateText = "How can I help you?", suggestions, defaultSidebarWidth, sidebarWidth, position = "right", defaultOpen = false, animateMobile = false, scope, browserTabId, }) {
|
|
946
|
+
export function AgentSidebar({ children, emptyStateText = "How can I help you?", suggestions, dynamicSuggestions, defaultSidebarWidth, sidebarWidth, position = "right", defaultOpen = false, animateMobile = false, scope, browserTabId, }) {
|
|
947
947
|
const initialWidth = defaultSidebarWidth ?? sidebarWidth ?? 380;
|
|
948
948
|
const [open, setOpen] = useState(() => getInitialAgentSidebarOpen(defaultOpen));
|
|
949
949
|
const [presentationMode, setPresentationMode] = useState(false);
|
|
@@ -1243,7 +1243,7 @@ export function AgentSidebar({ children, emptyStateText = "How can I help you?",
|
|
|
1243
1243
|
// any in-progress or completed conversations.
|
|
1244
1244
|
const sidebar = (_jsxs(_Fragment, { children: [showResizeHandle && !isLeft && (_jsx(ResizeHandle, { position: position, onDrag: handleDrag })), _jsx("div", { className: cn("agent-sidebar-panel flex shrink-0 flex-col overflow-hidden text-[13px] leading-[1.2] antialiased", animateMobile &&
|
|
1245
1245
|
isMobile &&
|
|
1246
|
-
"shadow-2xl transition-transform duration-[260ms] ease-[cubic-bezier(0.32,0.72,0,1)] motion-reduce:transition-none"), style: panelStyle, inert: isMobile && !open ? true : undefined, "aria-hidden": isMobile && !open ? true : undefined, children: _jsx(AgentPanel, { emptyStateText: emptyStateText, suggestions: suggestions, onCollapse: () => setOpenPersisted(false), isFullscreen: effectiveFullscreen, onToggleFullscreen: isMobile ? undefined : toggleFullscreen, scope: scope, browserTabId: browserTabId }) }), showResizeHandle && isLeft && (_jsx(ResizeHandle, { position: position, onDrag: handleDrag }))] }));
|
|
1246
|
+
"shadow-2xl transition-transform duration-[260ms] ease-[cubic-bezier(0.32,0.72,0,1)] motion-reduce:transition-none"), style: panelStyle, inert: isMobile && !open ? true : undefined, "aria-hidden": isMobile && !open ? true : undefined, children: _jsx(AgentPanel, { emptyStateText: emptyStateText, suggestions: suggestions, dynamicSuggestions: dynamicSuggestions, onCollapse: () => setOpenPersisted(false), isFullscreen: effectiveFullscreen, onToggleFullscreen: isMobile ? undefined : toggleFullscreen, scope: scope, browserTabId: browserTabId }) }), showResizeHandle && isLeft && (_jsx(ResizeHandle, { position: position, onDrag: handleDrag }))] }));
|
|
1247
1247
|
return (_jsxs("div", { className: "flex min-w-0 flex-1 h-screen overflow-hidden", children: [isMobile && !presentationMode && (animateMobile || open) && (_jsx("div", { className: cn("fixed inset-0 bg-black/40", animateMobile &&
|
|
1248
1248
|
"transition-opacity duration-200 motion-reduce:transition-none", animateMobile && !open && "pointer-events-none opacity-0", animateMobile && open && "opacity-100"), style: { zIndex: SIDEBAR_OVERLAY_Z_INDEX - 1 }, onClick: () => setOpenPersisted(false) })), _jsx(URLSync, { browserTabId: browserTabId }), isLeft && !presentationMode ? sidebar : null, _jsx("div", { className: "flex flex-1 flex-col overflow-auto min-w-0", children: _jsx(ScreenRefreshBoundary, { children: children }) }), !isLeft && !presentationMode ? sidebar : null] }));
|
|
1249
1249
|
}
|