@agent-native/core 0.51.15 → 0.53.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 +42 -96
- package/blueprints/action/crud.md +98 -0
- package/blueprints/channel/discord.md +74 -0
- package/blueprints/provider/stripe.md +87 -0
- package/blueprints/sandbox/docker.md +78 -0
- package/dist/action.d.ts +24 -0
- package/dist/action.d.ts.map +1 -1
- package/dist/action.js +4 -0
- package/dist/action.js.map +1 -1
- package/dist/agent/observational-memory/compactor.d.ts +43 -0
- package/dist/agent/observational-memory/compactor.d.ts.map +1 -0
- package/dist/agent/observational-memory/compactor.js +50 -0
- package/dist/agent/observational-memory/compactor.js.map +1 -0
- package/dist/agent/observational-memory/config.d.ts +37 -0
- package/dist/agent/observational-memory/config.d.ts.map +1 -0
- package/dist/agent/observational-memory/config.js +48 -0
- package/dist/agent/observational-memory/config.js.map +1 -0
- package/dist/agent/observational-memory/index.d.ts +26 -0
- package/dist/agent/observational-memory/index.d.ts.map +1 -0
- package/dist/agent/observational-memory/index.js +25 -0
- package/dist/agent/observational-memory/index.js.map +1 -0
- package/dist/agent/observational-memory/internal-run.d.ts +37 -0
- package/dist/agent/observational-memory/internal-run.d.ts.map +1 -0
- package/dist/agent/observational-memory/internal-run.js +59 -0
- package/dist/agent/observational-memory/internal-run.js.map +1 -0
- package/dist/agent/observational-memory/message-text.d.ts +13 -0
- package/dist/agent/observational-memory/message-text.d.ts.map +1 -0
- package/dist/agent/observational-memory/message-text.js +46 -0
- package/dist/agent/observational-memory/message-text.js.map +1 -0
- package/dist/agent/observational-memory/migrations.d.ts +13 -0
- package/dist/agent/observational-memory/migrations.d.ts.map +1 -0
- package/dist/agent/observational-memory/migrations.js +43 -0
- package/dist/agent/observational-memory/migrations.js.map +1 -0
- package/dist/agent/observational-memory/observer.d.ts +37 -0
- package/dist/agent/observational-memory/observer.d.ts.map +1 -0
- package/dist/agent/observational-memory/observer.js +82 -0
- package/dist/agent/observational-memory/observer.js.map +1 -0
- package/dist/agent/observational-memory/plugin.d.ts +16 -0
- package/dist/agent/observational-memory/plugin.d.ts.map +1 -0
- package/dist/agent/observational-memory/plugin.js +26 -0
- package/dist/agent/observational-memory/plugin.js.map +1 -0
- package/dist/agent/observational-memory/prompts.d.ts +27 -0
- package/dist/agent/observational-memory/prompts.d.ts.map +1 -0
- package/dist/agent/observational-memory/prompts.js +42 -0
- package/dist/agent/observational-memory/prompts.js.map +1 -0
- package/dist/agent/observational-memory/read.d.ts +47 -0
- package/dist/agent/observational-memory/read.d.ts.map +1 -0
- package/dist/agent/observational-memory/read.js +99 -0
- package/dist/agent/observational-memory/read.js.map +1 -0
- package/dist/agent/observational-memory/reflector.d.ts +31 -0
- package/dist/agent/observational-memory/reflector.d.ts.map +1 -0
- package/dist/agent/observational-memory/reflector.js +76 -0
- package/dist/agent/observational-memory/reflector.js.map +1 -0
- package/dist/agent/observational-memory/schema.d.ts +267 -0
- package/dist/agent/observational-memory/schema.d.ts.map +1 -0
- package/dist/agent/observational-memory/schema.js +48 -0
- package/dist/agent/observational-memory/schema.js.map +1 -0
- package/dist/agent/observational-memory/store.d.ts +52 -0
- package/dist/agent/observational-memory/store.d.ts.map +1 -0
- package/dist/agent/observational-memory/store.js +197 -0
- package/dist/agent/observational-memory/store.js.map +1 -0
- package/dist/agent/observational-memory/types.d.ts +61 -0
- package/dist/agent/observational-memory/types.d.ts.map +1 -0
- package/dist/agent/observational-memory/types.js +9 -0
- package/dist/agent/observational-memory/types.js.map +1 -0
- package/dist/agent/production-agent.d.ts +15 -0
- package/dist/agent/production-agent.d.ts.map +1 -1
- package/dist/agent/production-agent.js +240 -1
- package/dist/agent/production-agent.js.map +1 -1
- package/dist/agent/run-loop-with-resume.d.ts.map +1 -1
- package/dist/agent/run-loop-with-resume.js +49 -0
- package/dist/agent/run-loop-with-resume.js.map +1 -1
- package/dist/agent/run-store.d.ts +17 -0
- package/dist/agent/run-store.d.ts.map +1 -1
- package/dist/agent/run-store.js +55 -0
- package/dist/agent/run-store.js.map +1 -1
- package/dist/agent/runtime-context.d.ts +30 -0
- package/dist/agent/runtime-context.d.ts.map +1 -1
- package/dist/agent/runtime-context.js +54 -1
- package/dist/agent/runtime-context.js.map +1 -1
- package/dist/agent/tool-call-journal.d.ts +101 -0
- package/dist/agent/tool-call-journal.d.ts.map +1 -0
- package/dist/agent/tool-call-journal.js +214 -0
- package/dist/agent/tool-call-journal.js.map +1 -0
- package/dist/agent/types.d.ts +24 -0
- package/dist/agent/types.d.ts.map +1 -1
- package/dist/agent/types.js.map +1 -1
- package/dist/cli/add.d.ts +109 -0
- package/dist/cli/add.d.ts.map +1 -0
- package/dist/cli/add.js +352 -0
- package/dist/cli/add.js.map +1 -0
- package/dist/cli/connect.d.ts +5 -4
- package/dist/cli/connect.d.ts.map +1 -1
- package/dist/cli/connect.js +157 -48
- package/dist/cli/connect.js.map +1 -1
- package/dist/cli/eval.d.ts +17 -0
- package/dist/cli/eval.d.ts.map +1 -0
- package/dist/cli/eval.js +121 -0
- package/dist/cli/eval.js.map +1 -0
- package/dist/cli/index.js +44 -3
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/mcp-config-writers.d.ts +20 -13
- package/dist/cli/mcp-config-writers.d.ts.map +1 -1
- package/dist/cli/mcp-config-writers.js +152 -13
- package/dist/cli/mcp-config-writers.js.map +1 -1
- package/dist/cli/mcp.d.ts +2 -2
- package/dist/cli/mcp.d.ts.map +1 -1
- package/dist/cli/mcp.js +50 -196
- package/dist/cli/mcp.js.map +1 -1
- package/dist/cli/plan-local.d.ts +69 -6
- package/dist/cli/plan-local.d.ts.map +1 -1
- package/dist/cli/plan-local.js +517 -23
- package/dist/cli/plan-local.js.map +1 -1
- package/dist/cli/recap.d.ts.map +1 -1
- package/dist/cli/recap.js +1 -1
- package/dist/cli/recap.js.map +1 -1
- package/dist/cli/skills.d.ts +13 -6
- package/dist/cli/skills.d.ts.map +1 -1
- package/dist/cli/skills.js +287 -111
- package/dist/cli/skills.js.map +1 -1
- package/dist/client/AssistantChat.d.ts.map +1 -1
- package/dist/client/AssistantChat.js +118 -92
- package/dist/client/AssistantChat.js.map +1 -1
- package/dist/client/agent-chat-adapter.d.ts.map +1 -1
- package/dist/client/agent-chat-adapter.js +16 -0
- package/dist/client/agent-chat-adapter.js.map +1 -1
- package/dist/client/agent-engine-key.d.ts +6 -4
- package/dist/client/agent-engine-key.d.ts.map +1 -1
- package/dist/client/agent-engine-key.js +9 -6
- package/dist/client/agent-engine-key.js.map +1 -1
- package/dist/client/chat/run-recovery.js +1 -1
- package/dist/client/chat/run-recovery.js.map +1 -1
- package/dist/client/chat/tool-call-display.d.ts +20 -1
- package/dist/client/chat/tool-call-display.d.ts.map +1 -1
- package/dist/client/chat/tool-call-display.js +32 -7
- package/dist/client/chat/tool-call-display.js.map +1 -1
- package/dist/client/settings/SettingsPanel.d.ts.map +1 -1
- package/dist/client/settings/SettingsPanel.js +7 -14
- package/dist/client/settings/SettingsPanel.js.map +1 -1
- package/dist/client/sse-event-processor.d.ts +13 -0
- package/dist/client/sse-event-processor.d.ts.map +1 -1
- package/dist/client/sse-event-processor.js +21 -0
- package/dist/client/sse-event-processor.js.map +1 -1
- package/dist/coding-tools/run-code.d.ts +7 -0
- package/dist/coding-tools/run-code.d.ts.map +1 -1
- package/dist/coding-tools/run-code.js +21 -106
- package/dist/coding-tools/run-code.js.map +1 -1
- package/dist/coding-tools/sandbox/adapter.d.ts +79 -0
- package/dist/coding-tools/sandbox/adapter.d.ts.map +1 -0
- package/dist/coding-tools/sandbox/adapter.js +24 -0
- package/dist/coding-tools/sandbox/adapter.js.map +1 -0
- package/dist/coding-tools/sandbox/index.d.ts +51 -0
- package/dist/coding-tools/sandbox/index.d.ts.map +1 -0
- package/dist/coding-tools/sandbox/index.js +79 -0
- package/dist/coding-tools/sandbox/index.js.map +1 -0
- package/dist/coding-tools/sandbox/local-child-process-adapter.d.ts +24 -0
- package/dist/coding-tools/sandbox/local-child-process-adapter.d.ts.map +1 -0
- package/dist/coding-tools/sandbox/local-child-process-adapter.js +141 -0
- package/dist/coding-tools/sandbox/local-child-process-adapter.js.map +1 -0
- package/dist/db/client.d.ts +4 -2
- package/dist/db/client.d.ts.map +1 -1
- package/dist/db/client.js +6 -4
- package/dist/db/client.js.map +1 -1
- package/dist/deploy/route-discovery.d.ts.map +1 -1
- package/dist/deploy/route-discovery.js +1 -0
- package/dist/deploy/route-discovery.js.map +1 -1
- package/dist/eval/agent-runner.d.ts +63 -0
- package/dist/eval/agent-runner.d.ts.map +1 -0
- package/dist/eval/agent-runner.js +142 -0
- package/dist/eval/agent-runner.js.map +1 -0
- package/dist/eval/define-eval.d.ts +29 -0
- package/dist/eval/define-eval.d.ts.map +1 -0
- package/dist/eval/define-eval.js +43 -0
- package/dist/eval/define-eval.js.map +1 -0
- package/dist/eval/index.d.ts +18 -0
- package/dist/eval/index.d.ts.map +1 -0
- package/dist/eval/index.js +17 -0
- package/dist/eval/index.js.map +1 -0
- package/dist/eval/report.d.ts +8 -0
- package/dist/eval/report.d.ts.map +1 -0
- package/dist/eval/report.js +44 -0
- package/dist/eval/report.js.map +1 -0
- package/dist/eval/runner.d.ts +67 -0
- package/dist/eval/runner.d.ts.map +1 -0
- package/dist/eval/runner.js +256 -0
- package/dist/eval/runner.js.map +1 -0
- package/dist/eval/scorer.d.ts +83 -0
- package/dist/eval/scorer.d.ts.map +1 -0
- package/dist/eval/scorer.js +195 -0
- package/dist/eval/scorer.js.map +1 -0
- package/dist/eval/types.d.ts +162 -0
- package/dist/eval/types.d.ts.map +1 -0
- package/dist/eval/types.js +20 -0
- package/dist/eval/types.js.map +1 -0
- package/dist/observability/traces.d.ts.map +1 -1
- package/dist/observability/traces.js +100 -1
- package/dist/observability/traces.js.map +1 -1
- package/dist/observability/tracing.d.ts +73 -0
- package/dist/observability/tracing.d.ts.map +1 -0
- package/dist/observability/tracing.js +126 -0
- package/dist/observability/tracing.js.map +1 -0
- package/dist/onboarding/default-steps.d.ts.map +1 -1
- package/dist/onboarding/default-steps.js +4 -1
- package/dist/onboarding/default-steps.js.map +1 -1
- package/dist/provider-api/actions/query-staged-dataset.d.ts +1 -1
- package/dist/scripts/agent-engines/list-agent-engines.d.ts.map +1 -1
- package/dist/scripts/agent-engines/list-agent-engines.js +10 -3
- package/dist/scripts/agent-engines/list-agent-engines.js.map +1 -1
- package/dist/server/action-discovery.d.ts.map +1 -1
- package/dist/server/action-discovery.js +4 -0
- package/dist/server/action-discovery.js.map +1 -1
- package/dist/server/agent-chat-plugin.d.ts +9 -0
- package/dist/server/agent-chat-plugin.d.ts.map +1 -1
- package/dist/server/agent-chat-plugin.js +118 -110
- package/dist/server/agent-chat-plugin.js.map +1 -1
- package/dist/server/agent-engine-api-key-route.d.ts +37 -0
- package/dist/server/agent-engine-api-key-route.d.ts.map +1 -0
- package/dist/server/agent-engine-api-key-route.js +105 -0
- package/dist/server/agent-engine-api-key-route.js.map +1 -0
- package/dist/server/agent-teams.d.ts +62 -0
- package/dist/server/agent-teams.d.ts.map +1 -1
- package/dist/server/agent-teams.js +99 -2
- package/dist/server/agent-teams.js.map +1 -1
- package/dist/server/core-routes-plugin.d.ts.map +1 -1
- package/dist/server/core-routes-plugin.js +17 -10
- package/dist/server/core-routes-plugin.js.map +1 -1
- package/dist/server/create-server.js +1 -1
- package/dist/server/create-server.js.map +1 -1
- package/dist/server/credential-provider.d.ts.map +1 -1
- package/dist/server/credential-provider.js +2 -0
- package/dist/server/credential-provider.js.map +1 -1
- package/dist/server/framework-request-handler.d.ts.map +1 -1
- package/dist/server/framework-request-handler.js +33 -1
- package/dist/server/framework-request-handler.js.map +1 -1
- package/dist/server/index.d.ts +1 -0
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +1 -0
- package/dist/server/index.js.map +1 -1
- package/dist/templates/workspace-core/.agents/skills/external-agents/SKILL.md +17 -4
- package/dist/templates/workspace-core/.agents/skills/harness-agents/SKILL.md +20 -0
- package/dist/templates/workspace-core/.agents/skills/observability/SKILL.md +20 -0
- package/docs/content/agent-teams.md +32 -0
- package/docs/content/blueprint-installer.md +73 -0
- package/docs/content/evals.md +141 -0
- package/docs/content/pr-visual-recap.md +7 -4
- package/docs/content/sandbox-adapters.md +134 -0
- package/docs/content/template-plan.md +20 -8
- package/package.json +5 -1
- package/src/templates/workspace-core/.agents/skills/external-agents/SKILL.md +17 -4
- package/src/templates/workspace-core/.agents/skills/harness-agents/SKILL.md +20 -0
- package/src/templates/workspace-core/.agents/skills/observability/SKILL.md +20 -0
package/dist/cli/connect.js
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* `agent-native connect <url>` — wire your local
|
|
2
|
+
* `agent-native connect <url>` — wire your local MCP-capable coding agent
|
|
3
3
|
* to a DEPLOYED agent-native app. OAuth-capable clients receive a standard
|
|
4
4
|
* remote MCP URL entry and authenticate in the host. Fallback clients use the
|
|
5
5
|
* browser device-code flow: open the verification URL, approve in the browser,
|
|
6
6
|
* and the minted HTTP MCP server entry is written idempotently.
|
|
7
7
|
*
|
|
8
|
-
* agent-native connect <url> [--client all|claude-code|
|
|
9
|
-
* codex|cowork
|
|
8
|
+
* agent-native connect <url> [--client all|claude-code|
|
|
9
|
+
* codex|cowork|cursor|opencode|github-copilot]
|
|
10
|
+
* [--scope user|project]
|
|
10
11
|
* [--name <serverName>]
|
|
11
12
|
* agent-native reconnect [<url>] [--client ...] [--name <serverName>]
|
|
12
13
|
* agent-native connect <url> --token <token> (no-browser fallback)
|
|
@@ -33,7 +34,7 @@ import os from "node:os";
|
|
|
33
34
|
import { spawn } from "node:child_process";
|
|
34
35
|
import path from "node:path";
|
|
35
36
|
import { findWorkspaceRoot } from "../mcp/workspace-resolve.js";
|
|
36
|
-
import { CLIENTS, configPathFor, removeSameUrlDuplicatesForClient, writeCodexBlock, writeHttpEntryForClient,
|
|
37
|
+
import { CLIENTS, configPathFor, jsonMcpConfigKeyForClient, removeSameUrlDuplicatesForClient, writeCodexBlock, writeHttpEntryForClient, writeJsonMcpEntryForClient, } from "./mcp-config-writers.js";
|
|
37
38
|
import { isFirstPartyPlanHost, writePlanPublishAuth, } from "./plan-publish-store.js";
|
|
38
39
|
import { TEMPLATES, visibleTemplates } from "./templates-meta.js";
|
|
39
40
|
const DEVICE_START_PATH = "/_agent-native/mcp/connect/device/start";
|
|
@@ -66,16 +67,25 @@ const CLIENT_LABELS = {
|
|
|
66
67
|
"claude-code-cli": "Claude Code CLI",
|
|
67
68
|
codex: "Codex",
|
|
68
69
|
cowork: "Claude Cowork",
|
|
70
|
+
cursor: "Cursor",
|
|
71
|
+
opencode: "OpenCode",
|
|
72
|
+
"github-copilot": "GitHub Copilot / VS Code",
|
|
69
73
|
};
|
|
70
74
|
const CLIENT_HINTS = {
|
|
71
75
|
"claude-code": ".mcp.json or ~/.claude.json",
|
|
72
76
|
"claude-code-cli": ".mcp.json or ~/.claude.json",
|
|
73
77
|
codex: "$CODEX_HOME/config.toml or ~/.codex/config.toml",
|
|
74
78
|
cowork: "~/.cowork/mcp.json",
|
|
79
|
+
cursor: ".cursor/mcp.json or ~/.cursor/mcp.json",
|
|
80
|
+
opencode: "opencode.json or ~/.config/opencode/opencode.json",
|
|
81
|
+
"github-copilot": ".vscode/mcp.json or VS Code user mcp.json",
|
|
75
82
|
};
|
|
76
83
|
const REMOTE_MCP_OAUTH_CLIENTS = new Set([
|
|
77
84
|
"claude-code",
|
|
78
85
|
"claude-code-cli",
|
|
86
|
+
"cursor",
|
|
87
|
+
"opencode",
|
|
88
|
+
"github-copilot",
|
|
79
89
|
]);
|
|
80
90
|
let logOutImpl = (msg) => process.stdout.write(`${msg}\n`);
|
|
81
91
|
let logErrImpl = (msg) => process.stderr.write(`${msg}\n`);
|
|
@@ -175,11 +185,15 @@ export function normalizeUrl(raw) {
|
|
|
175
185
|
const base = `${parsed.origin}${parsed.pathname}`.replace(/\/+$/, "");
|
|
176
186
|
return base;
|
|
177
187
|
}
|
|
188
|
+
// Clients offered in the interactive picker and expanded by "all". Excludes
|
|
189
|
+
// the `claude-code-cli` alias so users only ever see a single "Claude Code"
|
|
190
|
+
// option (it still works if passed explicitly via --client).
|
|
191
|
+
const SELECTABLE_CLIENTS = CLIENTS.filter((c) => c !== "claude-code-cli");
|
|
178
192
|
/** Resolve the requested clients list. "all" → every supported client. */
|
|
179
193
|
export function resolveClients(client) {
|
|
180
|
-
const c = (client ?? "all")
|
|
194
|
+
const c = normalizeClientAlias(client ?? "all");
|
|
181
195
|
if (c === "all" || c === "")
|
|
182
|
-
return [...
|
|
196
|
+
return [...SELECTABLE_CLIENTS];
|
|
183
197
|
if (c.includes(",")) {
|
|
184
198
|
const clients = normalizeClientIds(c.split(",").map((part) => part.trim()));
|
|
185
199
|
if (clients.length > 0)
|
|
@@ -189,6 +203,20 @@ export function resolveClients(client) {
|
|
|
189
203
|
return [c];
|
|
190
204
|
throw new Error(`Unknown --client "${client}". Use: all, ${CLIENTS.join(", ")}`);
|
|
191
205
|
}
|
|
206
|
+
function normalizeClientAlias(value) {
|
|
207
|
+
const id = value.trim().toLowerCase();
|
|
208
|
+
// The Claude Code CLI and desktop share ~/.claude.json, so they are one
|
|
209
|
+
// client. `claude-code-cli` stays accepted for back-compat but collapses to
|
|
210
|
+
// the single "Claude Code" option everywhere it surfaces.
|
|
211
|
+
if (id === "claude" ||
|
|
212
|
+
id === "claude-code-desktop" ||
|
|
213
|
+
id === "claude-code-cli")
|
|
214
|
+
return "claude-code";
|
|
215
|
+
if (id === "copilot" || id === "vscode" || id === "vs-code") {
|
|
216
|
+
return "github-copilot";
|
|
217
|
+
}
|
|
218
|
+
return id;
|
|
219
|
+
}
|
|
192
220
|
export function connectPreferencesPath() {
|
|
193
221
|
return path.join(os.homedir(), ".agent-native", "connect.json");
|
|
194
222
|
}
|
|
@@ -200,7 +228,7 @@ function normalizeClientIds(values) {
|
|
|
200
228
|
for (const value of values) {
|
|
201
229
|
if (typeof value !== "string")
|
|
202
230
|
continue;
|
|
203
|
-
const id = value
|
|
231
|
+
const id = normalizeClientAlias(value);
|
|
204
232
|
if (!CLIENTS.includes(id))
|
|
205
233
|
continue;
|
|
206
234
|
const client = id;
|
|
@@ -233,7 +261,7 @@ export function writeConnectClientPreferences(clients, file = connectPreferences
|
|
|
233
261
|
}, null, 2) + "\n", "utf-8");
|
|
234
262
|
}
|
|
235
263
|
function clientPromptOptions() {
|
|
236
|
-
return
|
|
264
|
+
return SELECTABLE_CLIENTS.map((client) => ({
|
|
237
265
|
value: client,
|
|
238
266
|
label: CLIENT_LABELS[client],
|
|
239
267
|
hint: CLIENT_HINTS[client],
|
|
@@ -361,6 +389,22 @@ function sentenceClientLabelList(clients) {
|
|
|
361
389
|
return `${labels[0]} and ${labels[1]}`;
|
|
362
390
|
return `${labels.slice(0, -1).join(", ")}, and ${labels[labels.length - 1]}`;
|
|
363
391
|
}
|
|
392
|
+
function oauthNextStepsForClients(clients, serverName) {
|
|
393
|
+
const lines = [];
|
|
394
|
+
if (clients.includes("claude-code") || clients.includes("claude-code-cli")) {
|
|
395
|
+
lines.push("Claude Code: restart Claude Code, run /mcp, and choose Authenticate.");
|
|
396
|
+
}
|
|
397
|
+
if (clients.includes("cursor")) {
|
|
398
|
+
lines.push("Cursor: restart or reload Cursor, then authenticate the MCP server from Cursor MCP settings if prompted.");
|
|
399
|
+
}
|
|
400
|
+
if (clients.includes("opencode")) {
|
|
401
|
+
lines.push(`OpenCode: run opencode mcp auth ${serverName ?? "<server-name>"} or authenticate on first use.`);
|
|
402
|
+
}
|
|
403
|
+
if (clients.includes("github-copilot")) {
|
|
404
|
+
lines.push("GitHub Copilot / VS Code: reload VS Code, open the MCP config, and use the Auth action above the server if prompted.");
|
|
405
|
+
}
|
|
406
|
+
return lines;
|
|
407
|
+
}
|
|
364
408
|
function clientsNotIn(requestedClients, effectiveClients) {
|
|
365
409
|
const effective = new Set(effectiveClients);
|
|
366
410
|
return requestedClients.filter((client) => !effective.has(client));
|
|
@@ -379,7 +423,7 @@ async function showReconnectSuccessOutro({ serverName, clients, }) {
|
|
|
379
423
|
}
|
|
380
424
|
const oauthClients = clients.filter((client) => supportsRemoteMcpOAuth(client));
|
|
381
425
|
if (oauthClients.length > 0) {
|
|
382
|
-
lines.push(
|
|
426
|
+
lines.push(...oauthNextStepsForClients(oauthClients, serverName));
|
|
383
427
|
}
|
|
384
428
|
if (!clients.includes("codex") && oauthClients.length === 0) {
|
|
385
429
|
lines.push(`Restart or reload ${sentenceClientLabelList(clients)} before using the MCP tools.`);
|
|
@@ -556,26 +600,43 @@ export async function runDeviceFlow(baseUrl, appSlug, clientArg, deps = {}, opti
|
|
|
556
600
|
const sleep = deps.sleep ?? realSleep;
|
|
557
601
|
const open = deps.openBrowser ?? openInBrowser;
|
|
558
602
|
const now = deps.now ?? (() => Date.now());
|
|
559
|
-
let start;
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
603
|
+
let start = null;
|
|
604
|
+
// A cold/propagating Plan instance can briefly 404/5xx before its connect
|
|
605
|
+
// route is registered (async plugin init). Retry a few times so a recoverable
|
|
606
|
+
// blip doesn't kill the connect before polling even begins.
|
|
607
|
+
const START_ATTEMPTS = 4;
|
|
608
|
+
for (let attempt = 0; attempt < START_ATTEMPTS; attempt++) {
|
|
609
|
+
try {
|
|
610
|
+
const { status, json } = await postJson(fetchImpl, `${baseUrl}${DEVICE_START_PATH}`, {
|
|
611
|
+
client: clientArg,
|
|
612
|
+
app: appSlug,
|
|
613
|
+
...(options.fullCatalog ? { fullCatalog: true } : {}),
|
|
614
|
+
});
|
|
615
|
+
if (status >= 200 && status < 300 && json?.device_code) {
|
|
616
|
+
start = json;
|
|
617
|
+
break;
|
|
618
|
+
}
|
|
619
|
+
if ((status === 404 || status >= 500) && attempt < START_ATTEMPTS - 1) {
|
|
620
|
+
await sleep(1000 * (attempt + 1));
|
|
621
|
+
continue;
|
|
622
|
+
}
|
|
567
623
|
logErr(` Could not start the connect flow on ${baseUrl} ` +
|
|
568
624
|
`(HTTP ${status}). Is this an agent-native app, and is it ` +
|
|
569
625
|
`deployed with the connect endpoint enabled?`);
|
|
570
626
|
return null;
|
|
571
627
|
}
|
|
572
|
-
|
|
628
|
+
catch (err) {
|
|
629
|
+
if (attempt < START_ATTEMPTS - 1) {
|
|
630
|
+
await sleep(1000 * (attempt + 1));
|
|
631
|
+
continue;
|
|
632
|
+
}
|
|
633
|
+
logErr(` Could not reach ${baseUrl} (${err?.message ?? err}). ` +
|
|
634
|
+
`Check the URL and your network.`);
|
|
635
|
+
return null;
|
|
636
|
+
}
|
|
573
637
|
}
|
|
574
|
-
|
|
575
|
-
logErr(` Could not reach ${baseUrl} (${err?.message ?? err}). ` +
|
|
576
|
-
`Check the URL and your network.`);
|
|
638
|
+
if (!start)
|
|
577
639
|
return null;
|
|
578
|
-
}
|
|
579
640
|
const interval = Math.max(1, Number(start.interval) || 5);
|
|
580
641
|
const expiresIn = Math.max(interval, Number(start.expires_in) || 600);
|
|
581
642
|
const deadline = now() + expiresIn * 1000;
|
|
@@ -588,23 +649,59 @@ export async function runDeviceFlow(baseUrl, appSlug, clientArg, deps = {}, opti
|
|
|
588
649
|
logOut(" Approve in the browser to finish. Opening it now…");
|
|
589
650
|
open(start.verification_uri_complete);
|
|
590
651
|
let spin = 0;
|
|
652
|
+
let transientStreak = 0;
|
|
653
|
+
// Ride out brief cold-instance blips, but don't poll a persistently-dead
|
|
654
|
+
// endpoint forever: give up after this many consecutive transient (404/5xx
|
|
655
|
+
// or network-error) polls. Reset as soon as one poll responds normally.
|
|
656
|
+
const MAX_TRANSIENT_POLLS = 20;
|
|
591
657
|
const isTTY = !!process.stdout.isTTY;
|
|
592
658
|
while (now() < deadline) {
|
|
593
659
|
let poll;
|
|
660
|
+
let transient = false;
|
|
594
661
|
try {
|
|
595
662
|
const { status, json } = await postJson(fetchImpl, `${baseUrl}${DEVICE_POLL_PATH}`, { device_code: start.device_code });
|
|
596
663
|
if (status < 200 || status >= 300) {
|
|
664
|
+
if (isTerminalPollBody(json)) {
|
|
665
|
+
poll = json;
|
|
666
|
+
}
|
|
667
|
+
else if (status === 404 || status >= 500) {
|
|
668
|
+
// Transient: a cold/propagating Plan instance can briefly serve a
|
|
669
|
+
// bare 404 (the MCP route isn't registered until async plugin init
|
|
670
|
+
// settles) or a 5xx before it's healthy. The next poll usually lands
|
|
671
|
+
// on a warm instance, so keep polling until the deadline instead of
|
|
672
|
+
// hard-failing the whole connect on a recoverable blip. (This is the
|
|
673
|
+
// recurring "Cannot find any route matching [POST] .../mcp" case.)
|
|
674
|
+
poll = { status: "pending" };
|
|
675
|
+
transient = true;
|
|
676
|
+
}
|
|
677
|
+
else {
|
|
678
|
+
if (isTTY)
|
|
679
|
+
process.stdout.write("\r\x1b[K");
|
|
680
|
+
logErr(` Connect polling failed (HTTP ${status}): ` +
|
|
681
|
+
responseMessage(json, "server returned an error."));
|
|
682
|
+
return null;
|
|
683
|
+
}
|
|
684
|
+
}
|
|
685
|
+
else {
|
|
686
|
+
poll = (json ?? { status: "pending" });
|
|
687
|
+
}
|
|
688
|
+
}
|
|
689
|
+
catch {
|
|
690
|
+
// Transient network error — keep polling.
|
|
691
|
+
poll = { status: "pending" };
|
|
692
|
+
transient = true;
|
|
693
|
+
}
|
|
694
|
+
if (transient) {
|
|
695
|
+
if (++transientStreak > MAX_TRANSIENT_POLLS) {
|
|
597
696
|
if (isTTY)
|
|
598
697
|
process.stdout.write("\r\x1b[K");
|
|
599
|
-
logErr(
|
|
600
|
-
|
|
698
|
+
logErr(" Connect endpoint is not responding (repeated 404/5xx). It may be " +
|
|
699
|
+
"mid-deploy — wait a minute and run the command again.");
|
|
601
700
|
return null;
|
|
602
701
|
}
|
|
603
|
-
poll = (json ?? { status: "pending" });
|
|
604
702
|
}
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
poll = { status: "pending" };
|
|
703
|
+
else {
|
|
704
|
+
transientStreak = 0;
|
|
608
705
|
}
|
|
609
706
|
if (poll.status === "approved") {
|
|
610
707
|
if (isTTY)
|
|
@@ -652,6 +749,12 @@ export async function runDeviceFlow(baseUrl, appSlug, clientArg, deps = {}, opti
|
|
|
652
749
|
logErr(" Timed out waiting for approval. Run the command again to retry.");
|
|
653
750
|
return null;
|
|
654
751
|
}
|
|
752
|
+
function isTerminalPollBody(json) {
|
|
753
|
+
return (json?.status === "not_found" ||
|
|
754
|
+
json?.status === "error" ||
|
|
755
|
+
json?.status === "expired" ||
|
|
756
|
+
json?.status === "consumed");
|
|
757
|
+
}
|
|
655
758
|
// ---------------------------------------------------------------------------
|
|
656
759
|
// Writing config(s)
|
|
657
760
|
// ---------------------------------------------------------------------------
|
|
@@ -707,10 +810,10 @@ function setSavedProfileEntry(profiles, serverName, client, file, entry) {
|
|
|
707
810
|
profiles.prodEntries[serverName][client] ??= {};
|
|
708
811
|
profiles.prodEntries[serverName][client][file] = entry;
|
|
709
812
|
}
|
|
710
|
-
function readJsonMcpServerEntry(file, serverName) {
|
|
813
|
+
function readJsonMcpServerEntry(client, file, serverName) {
|
|
711
814
|
try {
|
|
712
815
|
const parsed = JSON.parse(fs.readFileSync(file, "utf-8"));
|
|
713
|
-
const entry = parsed?.
|
|
816
|
+
const entry = parsed?.[jsonMcpConfigKeyForClient(client)]?.[serverName];
|
|
714
817
|
return entry && typeof entry === "object" ? entry : undefined;
|
|
715
818
|
}
|
|
716
819
|
catch {
|
|
@@ -760,7 +863,7 @@ function readCurrentMcpEntry(client, serverName, baseDir, scope) {
|
|
|
760
863
|
: undefined,
|
|
761
864
|
};
|
|
762
865
|
}
|
|
763
|
-
const entry = readJsonMcpServerEntry(file, serverName);
|
|
866
|
+
const entry = readJsonMcpServerEntry(client, file, serverName);
|
|
764
867
|
return {
|
|
765
868
|
file,
|
|
766
869
|
saved: entry
|
|
@@ -777,7 +880,7 @@ function writeSavedMcpEntry(client, file, serverName, saved) {
|
|
|
777
880
|
}
|
|
778
881
|
if (saved.kind !== "json")
|
|
779
882
|
return;
|
|
780
|
-
|
|
883
|
+
writeJsonMcpEntryForClient(client, file, serverName, saved.entry);
|
|
781
884
|
}
|
|
782
885
|
function unescapeTomlString(value) {
|
|
783
886
|
return value.replace(/\\"/g, '"').replace(/\\\\/g, "\\");
|
|
@@ -808,10 +911,10 @@ function savedEntryUrl(saved) {
|
|
|
808
911
|
const match = saved.block.match(/^\s*url\s*=\s*"((?:\\.|[^"])*)"/m);
|
|
809
912
|
return match ? unescapeTomlString(match[1]) : undefined;
|
|
810
913
|
}
|
|
811
|
-
function readJsonMcpServerEntries(file) {
|
|
914
|
+
function readJsonMcpServerEntries(client, file) {
|
|
812
915
|
try {
|
|
813
916
|
const parsed = JSON.parse(fs.readFileSync(file, "utf-8"));
|
|
814
|
-
const servers = parsed?.
|
|
917
|
+
const servers = parsed?.[jsonMcpConfigKeyForClient(client)];
|
|
815
918
|
if (!servers || typeof servers !== "object" || Array.isArray(servers)) {
|
|
816
919
|
return [];
|
|
817
920
|
}
|
|
@@ -881,7 +984,7 @@ function readExistingMcpEntries(clients, baseDir, scope) {
|
|
|
881
984
|
const file = configPathFor(client, baseDir, scope);
|
|
882
985
|
const rawEntries = client === "codex"
|
|
883
986
|
? readCodexMcpServerEntries(file)
|
|
884
|
-
: readJsonMcpServerEntries(file);
|
|
987
|
+
: readJsonMcpServerEntries(client, file);
|
|
885
988
|
for (const { serverName, saved } of rawEntries) {
|
|
886
989
|
const url = savedEntryUrl(saved);
|
|
887
990
|
if (!url)
|
|
@@ -912,7 +1015,12 @@ function savedEntryHeaders(saved) {
|
|
|
912
1015
|
if (!saved)
|
|
913
1016
|
return {};
|
|
914
1017
|
if (saved.kind === "json") {
|
|
915
|
-
const headers = saved.entry.headers
|
|
1018
|
+
const headers = saved.entry.headers ??
|
|
1019
|
+
(saved.entry.requestInit &&
|
|
1020
|
+
typeof saved.entry.requestInit === "object" &&
|
|
1021
|
+
!Array.isArray(saved.entry.requestInit)
|
|
1022
|
+
? saved.entry.requestInit.headers
|
|
1023
|
+
: undefined);
|
|
916
1024
|
return headers && typeof headers === "object"
|
|
917
1025
|
? Object.fromEntries(Object.entries(headers)
|
|
918
1026
|
.filter((entry) => {
|
|
@@ -1526,12 +1634,11 @@ async function connectOne(rawUrl, parsed, clients, deps) {
|
|
|
1526
1634
|
// ADDITIONAL write alongside the per-client MCP config; Best-effort and
|
|
1527
1635
|
// merge-not-clobber — never fails the connect.
|
|
1528
1636
|
//
|
|
1529
|
-
// OAuth clients
|
|
1530
|
-
//
|
|
1531
|
-
//
|
|
1532
|
-
//
|
|
1533
|
-
//
|
|
1534
|
-
// connect` right after they just ran it.
|
|
1637
|
+
// OAuth clients authenticate in-host via standard MCP OAuth, so they never
|
|
1638
|
+
// mint a local bearer token. To still populate the publish store for them, we
|
|
1639
|
+
// run a supplemental device-flow mint using a non-OAuth client arg so the
|
|
1640
|
+
// Plans server gets a usable token and `publish-visual-plan` doesn't send the
|
|
1641
|
+
// user back to `agent-native connect` right after they just ran it.
|
|
1535
1642
|
let publishToken = token;
|
|
1536
1643
|
if (!publishToken &&
|
|
1537
1644
|
oauthClients.length > 0 &&
|
|
@@ -1579,7 +1686,9 @@ async function connectOne(rawUrl, parsed, clients, deps) {
|
|
|
1579
1686
|
logOut(` Replaced legacy bearer headers for ${clientLabelList(oauthMigrations)}; it will reconnect with standard MCP OAuth.`);
|
|
1580
1687
|
}
|
|
1581
1688
|
logOut(` ${clientLabelList(oauthClients)}: wrote URL-only MCP config (no bearer headers).`);
|
|
1582
|
-
|
|
1689
|
+
for (const line of oauthNextStepsForClients(oauthClients, serverName)) {
|
|
1690
|
+
logOut(` Next: ${line}`);
|
|
1691
|
+
}
|
|
1583
1692
|
}
|
|
1584
1693
|
logOut("");
|
|
1585
1694
|
logOut(` Restart or reload ${sentenceClientLabelList(clients)} to pick up the new MCP server.`);
|
|
@@ -1762,16 +1871,16 @@ Usage:
|
|
|
1762
1871
|
|
|
1763
1872
|
npx @agent-native/core@latest connect <url> [--client <c>] [--scope user|project] [--name <n>]
|
|
1764
1873
|
Writes the HTTP MCP entry into your selected client config(s). Claude
|
|
1765
|
-
Code /
|
|
1766
|
-
|
|
1874
|
+
Code, Cursor, OpenCode, and GitHub Copilot / VS Code use standard remote
|
|
1875
|
+
MCP OAuth and get URL-only config. Codex / Cowork use the browser
|
|
1767
1876
|
device-code fallback: the command prints a code, opens the verification
|
|
1768
1877
|
URL, polls until approved, then writes bearer headers. With no --client,
|
|
1769
1878
|
opens a brief picker preselected from ~/.agent-native/connect.json, or
|
|
1770
1879
|
all clients on first run. Idempotent — re-running replaces the same entry.
|
|
1771
1880
|
Auth is stored per client config/session; restart or reload each selected
|
|
1772
1881
|
client before expecting new tools to appear.
|
|
1773
|
-
Re-running over an older
|
|
1774
|
-
OAuth config and prompts you to authenticate
|
|
1882
|
+
Re-running over an older OAuth-capable bearer entry upgrades it to
|
|
1883
|
+
URL-only OAuth config and prompts you to authenticate in that host.
|
|
1775
1884
|
|
|
1776
1885
|
For cross-app access, prefer the unified Dispatch gateway:
|
|
1777
1886
|
npx @agent-native/core@latest connect https://dispatch.agent-native.com
|
|
@@ -1808,7 +1917,7 @@ Developer:
|
|
|
1808
1917
|
npx @agent-native/core@latest connect prod [--apps mail,calendar] [--client <c>]
|
|
1809
1918
|
Restore production MCP entries saved before the dev switch.
|
|
1810
1919
|
|
|
1811
|
-
Clients: all (default), claude-code,
|
|
1920
|
+
Clients: all (default), claude-code, codex, cowork, cursor, opencode, github-copilot
|
|
1812
1921
|
Scope: user (default, ~/.claude.json) or project (.mcp.json)`;
|
|
1813
1922
|
/**
|
|
1814
1923
|
* `agent-native connect` entry point. `deps` is injectable for tests; the
|