@mastra/code-sdk 0.0.0-polyester-catcher-20261002131924 → 0.0.0-react-sdk-20261005160725
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/acp/agent.d.ts +3 -3
- package/dist/acp/agent.d.ts.map +1 -1
- package/dist/acp/agent.js +88 -17
- package/dist/acp/agent.js.map +1 -1
- package/dist/acp/runtime.d.ts.map +1 -1
- package/dist/acp/runtime.js +18 -10
- package/dist/acp/runtime.js.map +1 -1
- package/dist/agents/model.js +2 -2
- package/dist/agents/prompts/agent-instructions.js +1 -1
- package/dist/auth/account-rotation-processor.js +1 -1
- package/dist/auth/providers/kimi-coding.js +2 -1
- package/dist/auth/providers/kimi-coding.js.map +1 -1
- package/dist/auth/providers/xai.js +2 -1
- package/dist/auth/providers/xai.js.map +1 -1
- package/dist/auth/storage.js +1 -1
- package/dist/auth/types.d.ts +1 -0
- package/dist/auth/types.d.ts.map +1 -1
- package/dist/clipboard/index.js +1 -1
- package/dist/headless/cli.d.ts.map +1 -1
- package/dist/headless/cli.js +5 -3
- package/dist/headless/cli.js.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -5
- package/dist/index.js.map +1 -1
- package/dist/lsp/server.js +1 -1
- package/dist/onboarding/om-settings.d.ts +1 -0
- package/dist/onboarding/om-settings.d.ts.map +1 -1
- package/dist/onboarding/om-settings.js +10 -1
- package/dist/onboarding/om-settings.js.map +1 -1
- package/dist/onboarding/settings.js +2 -2
- package/dist/providers/openai-codex.js +1 -1
- package/dist/schedules/run-script.js +1 -1
- package/dist/schema.js +1 -1
- package/dist/utils/open-url.d.ts +10 -0
- package/dist/utils/open-url.d.ts.map +1 -0
- package/dist/utils/open-url.js +30 -0
- package/dist/utils/open-url.js.map +1 -0
- package/dist/utils/project.js +2 -2
- package/dist/utils/signals-pubsub.d.ts +32 -4
- package/dist/utils/signals-pubsub.d.ts.map +1 -1
- package/dist/utils/signals-pubsub.js +207 -28
- package/dist/utils/signals-pubsub.js.map +1 -1
- package/dist/utils/slash-command-processor.js +1 -1
- package/dist/utils/update-check.js +1 -1
- package/package.json +15 -15
package/dist/acp/agent.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Agent, AgentSideConnection, InitializeRequest, InitializeResponse, NewSessionRequest, NewSessionResponse, PromptRequest, PromptResponse, CancelNotification, ContentBlock, SetSessionConfigOptionRequest, SetSessionConfigOptionResponse } from '@agentclientprotocol/sdk';
|
|
1
|
+
import type { Agent, AgentSideConnection, AuthenticateRequest, InitializeRequest, InitializeResponse, NewSessionRequest, NewSessionResponse, PromptRequest, PromptResponse, CancelNotification, ContentBlock, SetSessionConfigOptionRequest, SetSessionConfigOptionResponse } from '@agentclientprotocol/sdk';
|
|
2
2
|
import type { AgentController, AgentControllerMode, Session } from '@mastra/core/agent-controller';
|
|
3
3
|
import type { ThinkingLevelSetting } from '../thinking.js';
|
|
4
4
|
import type { AcpSkills } from './skills.js';
|
|
@@ -24,8 +24,8 @@ export declare class MastraCodeAcpAgent implements Agent {
|
|
|
24
24
|
private getSession;
|
|
25
25
|
private enqueue;
|
|
26
26
|
dispose(): Promise<void>;
|
|
27
|
-
initialize(
|
|
28
|
-
authenticate(): Promise<void>;
|
|
27
|
+
initialize({ clientCapabilities }: InitializeRequest): Promise<InitializeResponse>;
|
|
28
|
+
authenticate({ methodId }: AuthenticateRequest): Promise<void>;
|
|
29
29
|
newSession(request: NewSessionRequest): Promise<NewSessionResponse>;
|
|
30
30
|
private createNewSession;
|
|
31
31
|
private refreshCommands;
|
package/dist/acp/agent.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../src/acp/agent.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,KAAK,EACL,mBAAmB,EACnB,iBAAiB,EACjB,kBAAkB,EAClB,iBAAiB,EACjB,kBAAkB,EAClB,aAAa,EACb,cAAc,EACd,kBAAkB,EAClB,YAAY,EAEZ,6BAA6B,EAC7B,8BAA8B,EAE/B,MAAM,0BAA0B,CAAC;AAClC,OAAO,KAAK,EAAE,eAAe,EAAE,mBAAmB,EAAE,OAAO,EAAE,MAAM,+BAA+B,CAAC;
|
|
1
|
+
{"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../src/acp/agent.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,KAAK,EACL,mBAAmB,EACnB,mBAAmB,EAEnB,iBAAiB,EACjB,kBAAkB,EAClB,iBAAiB,EACjB,kBAAkB,EAClB,aAAa,EACb,cAAc,EACd,kBAAkB,EAClB,YAAY,EAEZ,6BAA6B,EAC7B,8BAA8B,EAE/B,MAAM,0BAA0B,CAAC;AAClC,OAAO,KAAK,EAAE,eAAe,EAAE,mBAAmB,EAAE,OAAO,EAAE,MAAM,+BAA+B,CAAC;AAInG,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAO3D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAE7C,MAAM,WAAW,iBAAiB;IAChC,UAAU,EAAE,eAAe,CAAC;IAC5B,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,mBAAmB,EAAE,CAAC;IAC7B,gBAAgB,CAAC,EAAE,MAAM,oBAAoB,CAAC;IAC9C,SAAS,CAAC,EAAE,MAAM,OAAO,CAAC,SAAS,GAAG,SAAS,CAAC,CAAC;IACjD,OAAO,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC/B;AAED,MAAM,MAAM,iBAAiB,GAAG,CAAC,OAAO,EAAE,iBAAiB,KAAK,OAAO,CAAC,iBAAiB,CAAC,CAAC;AA6E3F,yFAAyF;AACzF,qBAAa,kBAAmB,YAAW,KAAK;IAQ5C,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,QAAQ,CAAC,aAAa;IARhC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAmC;IAC5D,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAA0C;IAC3E,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAAiB;IACxD,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,QAAQ,CAAC,CAAgB;gBAGd,UAAU,EAAE,mBAAmB,EAC/B,aAAa,EAAE,iBAAiB;IAGnD,OAAO,CAAC,UAAU;IAMlB,OAAO,CAAC,OAAO;IASf,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAgClB,UAAU,CAAC,EAAE,kBAAkB,EAAE,EAAE,iBAAiB,GAAG,OAAO,CAAC,kBAAkB,CAAC;IASlF,YAAY,CAAC,EAAE,QAAQ,EAAE,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC;IA4BpE,UAAU,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,kBAAkB,CAAC;YAUrD,gBAAgB;YAkGhB,eAAe;IAa7B,OAAO,CAAC,aAAa;IAqCrB,OAAO,CAAC,aAAa;IAMf,sBAAsB,CAAC,MAAM,EAAE,6BAA6B,GAAG,OAAO,CAAC,8BAA8B,CAAC;IA0BtG,MAAM,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,cAAc,CAAC;IA2DvD,MAAM,CAAC,YAAY,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC;IA0BvD,cAAc,CAAC,MAAM,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAU5E,wBAAwB,CAAC,MAAM,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;CAiB9F;AASD,wBAAgB,4BAA4B,CAAC,MAAM,EAAE,YAAY,EAAE,GAAG,MAAM,CAiB3E;AAED,wBAAgB,aAAa,CAC3B,MAAM,EAAE,UAAU,GAAG,SAAS,GAAG,OAAO,GAAG,WAAW,GACrD,UAAU,GAAG,WAAW,GAAG,YAAY,GAAG,mBAAmB,GAAG,SAAS,CAW3E"}
|
package/dist/acp/agent.js
CHANGED
|
@@ -1,11 +1,63 @@
|
|
|
1
|
-
import { getAvailableThinkingLevelsForModel, isThinkingLevelSetting } from "../thinking.js";
|
|
2
1
|
import { getCurrentVersion } from "../utils/update-check.js";
|
|
2
|
+
import { AuthStorage, PROVIDER_DEFAULT_MODELS, getOAuthProviders } from "../auth/storage.js";
|
|
3
|
+
import { getAvailableThinkingLevelsForModel, isThinkingLevelSetting } from "../thinking.js";
|
|
4
|
+
import { seedProviderOMDefault } from "../onboarding/om-settings.js";
|
|
5
|
+
import { openUrlInBrowser } from "../utils/open-url.js";
|
|
3
6
|
import { withCleanupFailure } from "./errors.js";
|
|
4
7
|
import { handleAgentControllerEvent } from "./event-mapper.js";
|
|
5
8
|
import { expandSkillCommand, listSkillCommands } from "./skills.js";
|
|
6
9
|
import { isAbsolute } from "path";
|
|
7
10
|
import { PROTOCOL_VERSION, RequestError } from "@agentclientprotocol/sdk";
|
|
8
11
|
//#region src/acp/agent.ts
|
|
12
|
+
const TERMINAL_LOGIN_METHOD_ID = "mastracode-login";
|
|
13
|
+
const BROWSER_LOGIN_PROVIDER_IDS = [
|
|
14
|
+
"openai-codex",
|
|
15
|
+
"kimi-for-coding",
|
|
16
|
+
"xai"
|
|
17
|
+
];
|
|
18
|
+
const TERMINAL_LOGIN_PROVIDER_IDS = ["anthropic", "github-copilot"];
|
|
19
|
+
function terminalLogin(id, name, description, loginArgs) {
|
|
20
|
+
return {
|
|
21
|
+
id,
|
|
22
|
+
name,
|
|
23
|
+
description,
|
|
24
|
+
type: "terminal",
|
|
25
|
+
args: loginArgs,
|
|
26
|
+
_meta: { "terminal-auth": {
|
|
27
|
+
command: process.execPath,
|
|
28
|
+
args: [...process.argv.slice(1, 2), ...loginArgs],
|
|
29
|
+
label: name
|
|
30
|
+
} }
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
function listAuthMethods({ auth, _meta } = {}) {
|
|
34
|
+
const providers = getOAuthProviders();
|
|
35
|
+
const methods = providers.filter((provider) => BROWSER_LOGIN_PROVIDER_IDS.includes(provider.id)).map((provider) => ({
|
|
36
|
+
id: provider.id,
|
|
37
|
+
name: `Log in with ${provider.name}`,
|
|
38
|
+
description: "Opens your browser to sign in"
|
|
39
|
+
}));
|
|
40
|
+
if (!auth?.terminal && _meta?.["terminal-auth"] !== true) return methods;
|
|
41
|
+
return [
|
|
42
|
+
...methods,
|
|
43
|
+
...providers.filter((provider) => TERMINAL_LOGIN_PROVIDER_IDS.includes(provider.id)).map((provider) => terminalLogin(provider.id, `Log in with ${provider.name}`, "Sign in from a terminal", [
|
|
44
|
+
"login",
|
|
45
|
+
"--provider",
|
|
46
|
+
provider.id
|
|
47
|
+
])),
|
|
48
|
+
terminalLogin(TERMINAL_LOGIN_METHOD_ID, "Log in with Mastra Code", "Sign in to another provider or add an API key from a terminal", ["login"])
|
|
49
|
+
];
|
|
50
|
+
}
|
|
51
|
+
function hasUsableModel(available, currentModelId) {
|
|
52
|
+
if (available.some((model) => model.hasApiKey)) return true;
|
|
53
|
+
return currentModelId !== "" && !available.some((model) => model.id === currentModelId);
|
|
54
|
+
}
|
|
55
|
+
function credentialedDefaultModel(available, currentModelId) {
|
|
56
|
+
const current = available.find((model) => model.id === currentModelId);
|
|
57
|
+
if (!current || current.hasApiKey) return void 0;
|
|
58
|
+
const credentialed = new Set(available.filter((model) => model.hasApiKey).map((model) => model.id));
|
|
59
|
+
return Object.values(PROVIDER_DEFAULT_MODELS).find((modelId) => credentialed.has(modelId));
|
|
60
|
+
}
|
|
9
61
|
/** One ACP connection, with an independent Mastra Code runtime for each conversation. */
|
|
10
62
|
var MastraCodeAcpAgent = class {
|
|
11
63
|
connection;
|
|
@@ -54,7 +106,7 @@ var MastraCodeAcpAgent = class {
|
|
|
54
106
|
});
|
|
55
107
|
return this.disposal;
|
|
56
108
|
}
|
|
57
|
-
async initialize(
|
|
109
|
+
async initialize({ clientCapabilities }) {
|
|
58
110
|
return {
|
|
59
111
|
protocolVersion: PROTOCOL_VERSION,
|
|
60
112
|
agentInfo: {
|
|
@@ -68,11 +120,30 @@ var MastraCodeAcpAgent = class {
|
|
|
68
120
|
http: true,
|
|
69
121
|
sse: false
|
|
70
122
|
}
|
|
71
|
-
}
|
|
123
|
+
},
|
|
124
|
+
authMethods: listAuthMethods(clientCapabilities)
|
|
72
125
|
};
|
|
73
126
|
}
|
|
74
|
-
async authenticate() {
|
|
75
|
-
|
|
127
|
+
async authenticate({ methodId }) {
|
|
128
|
+
if (methodId === TERMINAL_LOGIN_METHOD_ID || TERMINAL_LOGIN_PROVIDER_IDS.includes(methodId)) return;
|
|
129
|
+
if (!BROWSER_LOGIN_PROVIDER_IDS.includes(methodId)) throw RequestError.invalidParams(void 0, `Unknown authentication method: ${methodId}`);
|
|
130
|
+
const needsTerminal = () => RequestError.internalError(void 0, "Browser sign-in can't finish on its own. Run `mastracode login` in a terminal to sign in.");
|
|
131
|
+
await new AuthStorage().login(methodId, {
|
|
132
|
+
authMode: "browser",
|
|
133
|
+
onAuth: ({ url, userCode }) => {
|
|
134
|
+
if (userCode && !url.includes(userCode)) throw needsTerminal();
|
|
135
|
+
process.stderr.write(`Open ${url} to sign in\n`);
|
|
136
|
+
openUrlInBrowser(url);
|
|
137
|
+
},
|
|
138
|
+
onPrompt: async () => {
|
|
139
|
+
throw needsTerminal();
|
|
140
|
+
}
|
|
141
|
+
});
|
|
142
|
+
try {
|
|
143
|
+
seedProviderOMDefault(methodId);
|
|
144
|
+
} catch (error) {
|
|
145
|
+
process.stderr.write(`[acp] memory model unchanged after sign-in: ${error}\n`);
|
|
146
|
+
}
|
|
76
147
|
}
|
|
77
148
|
newSession(request) {
|
|
78
149
|
const creating = Promise.resolve().then(() => this.createNewSession(request));
|
|
@@ -86,23 +157,23 @@ var MastraCodeAcpAgent = class {
|
|
|
86
157
|
const runtime = await this.createSession(request);
|
|
87
158
|
try {
|
|
88
159
|
if (this.disposed) throw RequestError.internalError(void 0, "ACP connection is closed");
|
|
160
|
+
const available = await runtime.controller.listAvailableModels();
|
|
161
|
+
if (!hasUsableModel(available, runtime.session.model.get() ?? "")) throw RequestError.authRequired(void 0, "Sign in to a model provider or add an API key to use Mastra Code");
|
|
89
162
|
const thread = await runtime.session.thread.create();
|
|
90
163
|
await runtime.session.thread.switch({ threadId: thread.id });
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
};
|
|
101
|
-
} catch {}
|
|
164
|
+
const defaultModelId = credentialedDefaultModel(available, runtime.session.model.get() ?? "");
|
|
165
|
+
if (defaultModelId) await runtime.session.model.switch({ modelId: defaultModelId });
|
|
166
|
+
const models = {
|
|
167
|
+
currentModelId: runtime.session.model.get() ?? "",
|
|
168
|
+
availableModels: includeCurrentModel([...new Map(available.filter((model) => model.hasApiKey || model.id === runtime.session.model.get()).map((model) => [model.id, {
|
|
169
|
+
modelId: model.id,
|
|
170
|
+
name: model.hasApiKey ? model.id : `${model.id} (provider not configured)`
|
|
171
|
+
}])).values()], runtime.session.model.get() ?? "")
|
|
172
|
+
};
|
|
102
173
|
if (this.disposed) throw RequestError.internalError(void 0, "ACP connection is closed");
|
|
103
174
|
const entry = {
|
|
104
175
|
...runtime,
|
|
105
|
-
models: models
|
|
176
|
+
models: models.availableModels,
|
|
106
177
|
state: null,
|
|
107
178
|
queue: Promise.resolve(),
|
|
108
179
|
turns: /* @__PURE__ */ new Set(),
|
package/dist/acp/agent.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent.js","names":[],"sources":["../../src/acp/agent.ts"],"sourcesContent":["import { isAbsolute } from 'node:path';\nimport { PROTOCOL_VERSION, RequestError } from '@agentclientprotocol/sdk';\nimport type {\n Agent,\n AgentSideConnection,\n InitializeRequest,\n InitializeResponse,\n NewSessionRequest,\n NewSessionResponse,\n PromptRequest,\n PromptResponse,\n CancelNotification,\n ContentBlock,\n SessionConfigOption,\n SetSessionConfigOptionRequest,\n SetSessionConfigOptionResponse,\n AvailableCommand,\n} from '@agentclientprotocol/sdk';\nimport type { AgentController, AgentControllerMode, Session } from '@mastra/core/agent-controller';\nimport { getAvailableThinkingLevelsForModel, isThinkingLevelSetting } from '../thinking.js';\nimport type { ThinkingLevelSetting } from '../thinking.js';\nimport { getCurrentVersion } from '../utils/update-check.js';\nimport { withCleanupFailure } from './errors.js';\nimport { handleAgentControllerEvent } from './event-mapper.js';\nimport type { PromptState } from './event-mapper.js';\nimport { expandSkillCommand, listSkillCommands } from './skills.js';\nimport type { AcpSkills } from './skills.js';\n\nexport interface AcpSessionRuntime {\n controller: AgentController;\n session: Session;\n modes: AgentControllerMode[];\n getThinkingLevel?: () => ThinkingLevelSetting;\n getSkills?: () => Promise<AcpSkills | undefined>;\n cleanup?: () => Promise<void>;\n}\n\nexport type AcpSessionFactory = (request: NewSessionRequest) => Promise<AcpSessionRuntime>;\n\ninterface SessionEntry extends AcpSessionRuntime {\n models: { modelId: string; name: string }[];\n state: PromptState | null;\n queue: Promise<void>;\n turns: Set<{ cancelled: boolean }>;\n unsubscribe: () => void;\n commands?: AvailableCommand[];\n}\n\n/** One ACP connection, with an independent Mastra Code runtime for each conversation. */\nexport class MastraCodeAcpAgent implements Agent {\n private readonly sessions = new Map<string, SessionEntry>();\n private readonly pendingCreations = new Set<Promise<NewSessionResponse>>();\n private readonly startupCleanupFailures: unknown[] = [];\n private disposed = false;\n private disposal?: Promise<void>;\n\n constructor(\n private readonly connection: AgentSideConnection,\n private readonly createSession: AcpSessionFactory,\n ) {}\n\n private getSession(sessionId: string): SessionEntry {\n const entry = this.sessions.get(sessionId);\n if (!entry || this.disposed) throw RequestError.invalidParams({ sessionId }, 'Unknown ACP session');\n return entry;\n }\n\n private enqueue<T>(entry: SessionEntry, operation: () => Promise<T>): Promise<T> {\n const result = entry.queue.then(operation);\n entry.queue = result.then(\n () => {},\n () => {},\n );\n return result;\n }\n\n dispose(): Promise<void> {\n if (this.disposal) return this.disposal;\n this.disposed = true;\n const entries = [...this.sessions.values()];\n this.sessions.clear();\n const cleanup = Promise.allSettled([\n // A runtime under construction owns its cleanup until it joins sessions.\n Promise.allSettled([...this.pendingCreations]),\n ...entries.map(async entry => {\n for (const turn of entry.turns) turn.cancelled = true;\n if (entry.state) {\n entry.state.cancelled = true;\n entry.session.abort();\n entry.state?.resolve('aborted');\n }\n entry.unsubscribe();\n await entry.cleanup?.();\n }),\n ]).then(results => {\n const failures = results.filter(result => result.status === 'rejected').map(result => result.reason);\n failures.push(...this.startupCleanupFailures);\n if (failures.length) throw new AggregateError(failures, 'ACP session cleanup failed');\n });\n // A provider or MCP startup can stall. Keep its cleanup ownership, but let\n // the host terminate the connection if shutdown cannot finish in time.\n this.disposal = new Promise<void>((resolve, reject) => {\n const timeout = setTimeout(() => reject(new Error('ACP shutdown timed out after 10 seconds')), 10_000);\n void cleanup.then(resolve, reject).finally(() => clearTimeout(timeout));\n });\n return this.disposal;\n }\n\n async initialize(_request: InitializeRequest): Promise<InitializeResponse> {\n return {\n protocolVersion: PROTOCOL_VERSION,\n agentInfo: { name: 'mastracode', title: 'Mastra Code', version: getCurrentVersion() },\n agentCapabilities: { loadSession: false, mcpCapabilities: { http: true, sse: false } },\n };\n }\n\n async authenticate(): Promise<void> {\n throw RequestError.invalidParams(undefined, 'Configure authentication through Mastra Code before starting ACP');\n }\n\n newSession(request: NewSessionRequest): Promise<NewSessionResponse> {\n const creating = Promise.resolve().then(() => this.createNewSession(request));\n this.pendingCreations.add(creating);\n void creating.then(\n () => this.pendingCreations.delete(creating),\n () => this.pendingCreations.delete(creating),\n );\n return creating;\n }\n\n private async createNewSession(request: NewSessionRequest): Promise<NewSessionResponse> {\n if (this.disposed) throw RequestError.internalError(undefined, 'ACP connection is closed');\n if (!isAbsolute(request.cwd)) throw RequestError.invalidParams(undefined, 'cwd must be an absolute path');\n const runtime = await this.createSession(request);\n try {\n if (this.disposed) throw RequestError.internalError(undefined, 'ACP connection is closed');\n const thread = await runtime.session.thread.create();\n await runtime.session.thread.switch({ threadId: thread.id });\n let models: NewSessionResponse['models'];\n try {\n const available = await runtime.controller.listAvailableModels();\n models = {\n currentModelId: runtime.session.model.get() ?? '',\n availableModels: includeCurrentModel(\n [\n ...new Map(\n available\n .filter(model => model.hasApiKey || model.id === runtime.session.model.get())\n .map(\n model =>\n [\n model.id,\n {\n modelId: model.id,\n name: model.hasApiKey ? model.id : `${model.id} (provider not configured)`,\n },\n ] as const,\n ),\n ).values(),\n ],\n runtime.session.model.get() ?? '',\n ),\n };\n } catch {\n // Discovery may be unavailable before provider authentication.\n }\n if (this.disposed) throw RequestError.internalError(undefined, 'ACP connection is closed');\n const entry: SessionEntry = {\n ...runtime,\n models: models?.availableModels ?? [],\n state: null,\n queue: Promise.resolve(),\n turns: new Set(),\n unsubscribe: () => {},\n commands: [],\n };\n if (this.disposed) throw RequestError.internalError(undefined, 'ACP connection is closed');\n entry.unsubscribe = runtime.session.subscribe(event => {\n handleAgentControllerEvent(event, entry.state, this.connection, entry.session);\n if (event.type === 'mode_changed') {\n void this.connection\n .sessionUpdate({\n sessionId: thread.id,\n update: { sessionUpdate: 'current_mode_update', currentModeId: entry.session.mode.get() },\n })\n .catch(error => process.stderr.write(`[acp] mode update failed: ${error}\\n`));\n }\n if (\n event.type === 'mode_changed' ||\n event.type === 'model_changed' ||\n (event.type === 'state_changed' && event.changedKeys.includes('thinkingLevel'))\n ) {\n void this.connection\n .sessionUpdate({\n sessionId: thread.id,\n update: { sessionUpdate: 'config_option_update', configOptions: this.configOptions(entry) },\n })\n .catch(error => process.stderr.write(`[acp] configuration update failed: ${error}\\n`));\n }\n });\n const response: NewSessionResponse = {\n sessionId: thread.id,\n modes: {\n currentModeId: runtime.session.mode.get(),\n availableModes: runtime.modes.map(mode => ({ id: mode.id, name: mode.name ?? mode.id })),\n },\n models,\n configOptions: this.configOptions(entry),\n };\n this.sessions.set(thread.id, entry);\n // Let the SDK send session/new before clients receive updates for this ID.\n setImmediate(() => {\n void this.enqueue(entry, async () => {\n if (!this.disposed) await this.refreshCommands(thread.id, entry);\n }).catch(error => process.stderr.write(`[acp] command discovery failed: ${error}\\n`));\n });\n return response;\n } catch (error) {\n try {\n await runtime.cleanup?.();\n } catch (cleanupError) {\n if (this.disposed) this.startupCleanupFailures.push(cleanupError);\n throw withCleanupFailure(error, cleanupError);\n }\n throw error;\n }\n }\n\n private async refreshCommands(sessionId: string, entry: SessionEntry): Promise<AcpSkills | undefined> {\n const skills = await entry.getSkills?.();\n const commands = await listSkillCommands(skills);\n if (JSON.stringify(commands) !== JSON.stringify(entry.commands)) {\n await this.connection.sessionUpdate({\n sessionId,\n update: { sessionUpdate: 'available_commands_update', availableCommands: commands },\n });\n entry.commands = commands;\n }\n return skills;\n }\n\n private configOptions(entry: SessionEntry): SessionConfigOption[] {\n const modelId = entry.session.model.get() ?? '';\n const options: SessionConfigOption[] = [];\n const models = includeCurrentModel(entry.models, modelId);\n if (models.length)\n options.push({\n id: 'model',\n name: 'Model',\n category: 'model',\n type: 'select',\n currentValue: modelId,\n options: models.map(model => ({ value: model.modelId, name: model.name })),\n });\n options.push({\n id: 'mode',\n name: 'Mode',\n category: 'mode',\n type: 'select',\n currentValue: entry.session.mode.get(),\n options: entry.modes.map(mode => ({ value: mode.id, name: mode.name ?? mode.id })),\n });\n if (entry.getThinkingLevel)\n options.push({\n id: 'thought_level',\n name: 'Reasoning effort',\n category: 'thought_level',\n type: 'select',\n description: 'Requested reasoning level. The provider may adjust it for the selected model.',\n currentValue: this.thinkingLevel(entry),\n options: getAvailableThinkingLevelsForModel(modelId).map(value => ({\n value,\n name: value[0]!.toUpperCase() + value.slice(1),\n })),\n });\n return options;\n }\n\n private thinkingLevel(entry: SessionEntry): ThinkingLevelSetting {\n const level = entry.getThinkingLevel?.() ?? 'off';\n const levels = getAvailableThinkingLevelsForModel(entry.session.model.get() ?? '');\n return levels.includes(level) ? level : 'xhigh';\n }\n\n async setSessionConfigOption(params: SetSessionConfigOptionRequest): Promise<SetSessionConfigOptionResponse> {\n const entry = this.getSession(params.sessionId);\n return this.enqueue(entry, async () => {\n this.getSession(params.sessionId);\n const option = this.configOptions(entry).find(option => option.id === params.configId);\n if (\n !option ||\n option.type !== 'select' ||\n !option.options.some(item => 'value' in item && item.value === params.value)\n ) {\n throw RequestError.invalidParams(undefined, 'Unknown session configuration selection');\n }\n if (params.configId === 'model') {\n await entry.session.model.switch({ modelId: String(params.value) });\n } else if (params.configId === 'mode') {\n await entry.session.mode.switch({ modeId: String(params.value) });\n } else if (isThinkingLevelSetting(params.value)) {\n await entry.session.state.set({ thinkingLevel: params.value });\n }\n if (entry.getThinkingLevel && entry.getThinkingLevel() !== this.thinkingLevel(entry)) {\n await entry.session.state.set({ thinkingLevel: this.thinkingLevel(entry) });\n }\n return { configOptions: this.configOptions(entry) };\n });\n }\n\n async prompt(request: PromptRequest): Promise<PromptResponse> {\n const entry = this.getSession(request.sessionId);\n const content = extractTextFromContentBlocks(request.prompt);\n const turn = { cancelled: false };\n entry.turns.add(turn);\n try {\n return await this.enqueue(entry, async () => {\n if (turn.cancelled || this.disposed) return { stopReason: 'cancelled' };\n const usage: PromptState['usage'] = { promptTokens: 0, completionTokens: 0, totalTokens: 0 };\n let complete!: PromptState['resolve'];\n const completion = new Promise<Parameters<PromptState['resolve']>[0]>(resolve => {\n complete = resolve;\n });\n const state: PromptState = {\n sessionId: request.sessionId,\n usage,\n resolve: reason => {\n state.finished = true;\n complete(reason);\n },\n };\n entry.state = state;\n try {\n const skills = await this.refreshCommands(request.sessionId, entry);\n const expanded = await expandSkillCommand(content, skills, entry.commands ?? []);\n if (turn.cancelled || this.disposed) return { stopReason: 'cancelled' };\n await entry.session.sendMessage({ content: expanded });\n const reason = await completion;\n if (reason === 'error' && !state.cancelled && !state.stopReason) {\n throw RequestError.internalError(undefined, state.error?.message ?? 'Mastra Code turn failed');\n }\n return {\n stopReason: state.cancelled ? 'cancelled' : (state.stopReason ?? mapStopReason(reason)),\n usage: {\n inputTokens: usage.promptTokens,\n outputTokens: usage.completionTokens,\n totalTokens: usage.totalTokens,\n thoughtTokens: usage.reasoningTokens,\n cachedReadTokens: usage.cachedInputTokens,\n cachedWriteTokens: usage.cacheCreationInputTokens,\n },\n };\n } catch (error) {\n if (state.cancelled) return { stopReason: 'cancelled' };\n if (error instanceof RequestError) throw error;\n throw RequestError.internalError(\n undefined,\n error instanceof Error ? error.message : 'Mastra Code turn failed',\n );\n } finally {\n state.finished = true;\n if (entry.state === state) entry.state = null;\n }\n });\n } finally {\n entry.turns.delete(turn);\n }\n }\n\n async cancel(notification: CancelNotification): Promise<void> {\n const entry = this.sessions.get(notification.sessionId);\n if (!entry) return;\n for (const turn of entry.turns) turn.cancelled = true;\n if (entry.state && !entry.state.finished && !entry.state.cancelled) {\n const state = entry.state;\n state.cancelled = true;\n // Persist denial before aborting, otherwise a parked snapshot can replay on the next turn.\n for (const deny of state.cancelSuspensions?.values() ?? []) {\n try {\n await deny();\n } catch {\n /* Still abort if the suspended run is no longer available. */\n }\n }\n state.cancelSuspensions?.clear();\n if (entry.state !== state) return;\n entry.session.abort();\n // A suspended run has already ended and will not emit another agent_end.\n if (entry.state?.suspended) {\n entry.session.stream.detach();\n entry.state.resolve('aborted');\n }\n }\n }\n\n async setSessionMode(params: { sessionId: string; modeId: string }): Promise<void> {\n const entry = this.getSession(params.sessionId);\n if (!entry.modes.some(mode => mode.id === params.modeId))\n throw RequestError.invalidParams(undefined, 'Unknown mode');\n await this.enqueue(entry, async () => {\n if (this.disposed) return;\n await entry.session.mode.switch({ modeId: params.modeId });\n });\n }\n\n async unstable_setSessionModel(params: { sessionId: string; modelId: string }): Promise<void> {\n const entry = this.getSession(params.sessionId);\n await this.enqueue(entry, async () => {\n if (this.disposed) return;\n if (\n !includeCurrentModel(entry.models, entry.session.model.get() ?? '').some(\n model => model.modelId === params.modelId,\n )\n ) {\n throw RequestError.invalidParams(\n undefined,\n 'Model is unavailable or its provider is not configured. Refresh the model list.',\n );\n }\n await entry.session.model.switch({ modelId: params.modelId });\n });\n }\n}\n\nfunction includeCurrentModel(models: SessionEntry['models'], currentModelId: string): SessionEntry['models'] {\n // Saved/custom model IDs may work even when discovery only returns a gateway-qualified alias.\n return currentModelId && !models.some(model => model.modelId === currentModelId)\n ? [{ modelId: currentModelId, name: currentModelId }, ...models]\n : models;\n}\n\nexport function extractTextFromContentBlocks(blocks: ContentBlock[]): string {\n const parts: string[] = [];\n for (const block of blocks) {\n if (block.type === 'text') {\n parts.push(block.text);\n } else if (block.type === 'resource_link') {\n parts.push(`[resource: ${block.uri}]`);\n } else if (block.type === 'resource') {\n parts.push(`[resource: ${block.resource.uri}]`);\n if (!('text' in block.resource))\n throw RequestError.invalidParams(undefined, 'Binary prompt resources are not supported');\n parts.push(block.resource.text);\n } else {\n throw RequestError.invalidParams(undefined, `Unsupported prompt content: ${block.type}`);\n }\n }\n return parts.join('\\n');\n}\n\nexport function mapStopReason(\n reason: 'complete' | 'aborted' | 'error' | 'suspended',\n): 'end_turn' | 'cancelled' | 'max_tokens' | 'max_turn_requests' | 'refusal' {\n switch (reason) {\n case 'complete':\n return 'end_turn';\n case 'aborted':\n return 'cancelled';\n case 'error':\n throw RequestError.internalError(undefined, 'Mastra Code turn failed');\n case 'suspended':\n return 'end_turn';\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"agent.js","names":[],"sources":["../../src/acp/agent.ts"],"sourcesContent":["import { isAbsolute } from 'node:path';\nimport { PROTOCOL_VERSION, RequestError } from '@agentclientprotocol/sdk';\nimport type {\n Agent,\n AgentSideConnection,\n AuthenticateRequest,\n AuthMethod,\n InitializeRequest,\n InitializeResponse,\n NewSessionRequest,\n NewSessionResponse,\n PromptRequest,\n PromptResponse,\n CancelNotification,\n ContentBlock,\n SessionConfigOption,\n SetSessionConfigOptionRequest,\n SetSessionConfigOptionResponse,\n AvailableCommand,\n} from '@agentclientprotocol/sdk';\nimport type { AgentController, AgentControllerMode, Session } from '@mastra/core/agent-controller';\nimport { AuthStorage, getOAuthProviders, PROVIDER_DEFAULT_MODELS } from '../auth/storage.js';\nimport { seedProviderOMDefault } from '../onboarding/om-settings.js';\nimport { getAvailableThinkingLevelsForModel, isThinkingLevelSetting } from '../thinking.js';\nimport type { ThinkingLevelSetting } from '../thinking.js';\nimport { openUrlInBrowser } from '../utils/open-url.js';\nimport { getCurrentVersion } from '../utils/update-check.js';\nimport { withCleanupFailure } from './errors.js';\nimport { handleAgentControllerEvent } from './event-mapper.js';\nimport type { PromptState } from './event-mapper.js';\nimport { expandSkillCommand, listSkillCommands } from './skills.js';\nimport type { AcpSkills } from './skills.js';\n\nexport interface AcpSessionRuntime {\n controller: AgentController;\n session: Session;\n modes: AgentControllerMode[];\n getThinkingLevel?: () => ThinkingLevelSetting;\n getSkills?: () => Promise<AcpSkills | undefined>;\n cleanup?: () => Promise<void>;\n}\n\nexport type AcpSessionFactory = (request: NewSessionRequest) => Promise<AcpSessionRuntime>;\n\ninterface SessionEntry extends AcpSessionRuntime {\n models: { modelId: string; name: string }[];\n state: PromptState | null;\n queue: Promise<void>;\n turns: Set<{ cancelled: boolean }>;\n unsubscribe: () => void;\n commands?: AvailableCommand[];\n}\n\nconst TERMINAL_LOGIN_METHOD_ID = 'mastracode-login';\nconst BROWSER_LOGIN_PROVIDER_IDS = ['openai-codex', 'kimi-for-coding', 'xai'];\nconst TERMINAL_LOGIN_PROVIDER_IDS = ['anthropic', 'github-copilot'];\n\nfunction terminalLogin(id: string, name: string, description: string, loginArgs: string[]): AuthMethod {\n return {\n id,\n name,\n description,\n type: 'terminal',\n args: loginArgs,\n _meta: {\n 'terminal-auth': {\n command: process.execPath,\n args: [...process.argv.slice(1, 2), ...loginArgs],\n label: name,\n },\n },\n };\n}\n\nfunction listAuthMethods({ auth, _meta }: InitializeRequest['clientCapabilities'] = {}): AuthMethod[] {\n const providers = getOAuthProviders();\n const methods: AuthMethod[] = providers\n .filter(provider => BROWSER_LOGIN_PROVIDER_IDS.includes(provider.id))\n .map(provider => ({\n id: provider.id,\n name: `Log in with ${provider.name}`,\n description: 'Opens your browser to sign in',\n }));\n if (!auth?.terminal && _meta?.['terminal-auth'] !== true) return methods;\n return [\n ...methods,\n ...providers\n .filter(provider => TERMINAL_LOGIN_PROVIDER_IDS.includes(provider.id))\n .map(provider =>\n terminalLogin(provider.id, `Log in with ${provider.name}`, 'Sign in from a terminal', [\n 'login',\n '--provider',\n provider.id,\n ]),\n ),\n terminalLogin(\n TERMINAL_LOGIN_METHOD_ID,\n 'Log in with Mastra Code',\n 'Sign in to another provider or add an API key from a terminal',\n ['login'],\n ),\n ];\n}\n\nfunction hasUsableModel(available: { id: string; hasApiKey: boolean }[], currentModelId: string): boolean {\n if (available.some(model => model.hasApiKey)) return true;\n return currentModelId !== '' && !available.some(model => model.id === currentModelId);\n}\n\nfunction credentialedDefaultModel(\n available: { id: string; hasApiKey: boolean }[],\n currentModelId: string,\n): string | undefined {\n const current = available.find(model => model.id === currentModelId);\n if (!current || current.hasApiKey) return undefined;\n const credentialed = new Set(available.filter(model => model.hasApiKey).map(model => model.id));\n return Object.values(PROVIDER_DEFAULT_MODELS).find(modelId => credentialed.has(modelId));\n}\n\n/** One ACP connection, with an independent Mastra Code runtime for each conversation. */\nexport class MastraCodeAcpAgent implements Agent {\n private readonly sessions = new Map<string, SessionEntry>();\n private readonly pendingCreations = new Set<Promise<NewSessionResponse>>();\n private readonly startupCleanupFailures: unknown[] = [];\n private disposed = false;\n private disposal?: Promise<void>;\n\n constructor(\n private readonly connection: AgentSideConnection,\n private readonly createSession: AcpSessionFactory,\n ) {}\n\n private getSession(sessionId: string): SessionEntry {\n const entry = this.sessions.get(sessionId);\n if (!entry || this.disposed) throw RequestError.invalidParams({ sessionId }, 'Unknown ACP session');\n return entry;\n }\n\n private enqueue<T>(entry: SessionEntry, operation: () => Promise<T>): Promise<T> {\n const result = entry.queue.then(operation);\n entry.queue = result.then(\n () => {},\n () => {},\n );\n return result;\n }\n\n dispose(): Promise<void> {\n if (this.disposal) return this.disposal;\n this.disposed = true;\n const entries = [...this.sessions.values()];\n this.sessions.clear();\n const cleanup = Promise.allSettled([\n // A runtime under construction owns its cleanup until it joins sessions.\n Promise.allSettled([...this.pendingCreations]),\n ...entries.map(async entry => {\n for (const turn of entry.turns) turn.cancelled = true;\n if (entry.state) {\n entry.state.cancelled = true;\n entry.session.abort();\n entry.state?.resolve('aborted');\n }\n entry.unsubscribe();\n await entry.cleanup?.();\n }),\n ]).then(results => {\n const failures = results.filter(result => result.status === 'rejected').map(result => result.reason);\n failures.push(...this.startupCleanupFailures);\n if (failures.length) throw new AggregateError(failures, 'ACP session cleanup failed');\n });\n // A provider or MCP startup can stall. Keep its cleanup ownership, but let\n // the host terminate the connection if shutdown cannot finish in time.\n this.disposal = new Promise<void>((resolve, reject) => {\n const timeout = setTimeout(() => reject(new Error('ACP shutdown timed out after 10 seconds')), 10_000);\n void cleanup.then(resolve, reject).finally(() => clearTimeout(timeout));\n });\n return this.disposal;\n }\n\n async initialize({ clientCapabilities }: InitializeRequest): Promise<InitializeResponse> {\n return {\n protocolVersion: PROTOCOL_VERSION,\n agentInfo: { name: 'mastracode', title: 'Mastra Code', version: getCurrentVersion() },\n agentCapabilities: { loadSession: false, mcpCapabilities: { http: true, sse: false } },\n authMethods: listAuthMethods(clientCapabilities),\n };\n }\n\n async authenticate({ methodId }: AuthenticateRequest): Promise<void> {\n if (methodId === TERMINAL_LOGIN_METHOD_ID || TERMINAL_LOGIN_PROVIDER_IDS.includes(methodId)) return;\n if (!BROWSER_LOGIN_PROVIDER_IDS.includes(methodId)) {\n throw RequestError.invalidParams(undefined, `Unknown authentication method: ${methodId}`);\n }\n const needsTerminal = () =>\n RequestError.internalError(\n undefined,\n \"Browser sign-in can't finish on its own. Run `mastracode login` in a terminal to sign in.\",\n );\n await new AuthStorage().login(methodId, {\n authMode: 'browser',\n onAuth: ({ url, userCode }) => {\n if (userCode && !url.includes(userCode)) throw needsTerminal();\n process.stderr.write(`Open ${url} to sign in\\n`);\n openUrlInBrowser(url);\n },\n onPrompt: async () => {\n throw needsTerminal();\n },\n });\n try {\n seedProviderOMDefault(methodId);\n } catch (error) {\n process.stderr.write(`[acp] memory model unchanged after sign-in: ${error}\\n`);\n }\n }\n\n newSession(request: NewSessionRequest): Promise<NewSessionResponse> {\n const creating = Promise.resolve().then(() => this.createNewSession(request));\n this.pendingCreations.add(creating);\n void creating.then(\n () => this.pendingCreations.delete(creating),\n () => this.pendingCreations.delete(creating),\n );\n return creating;\n }\n\n private async createNewSession(request: NewSessionRequest): Promise<NewSessionResponse> {\n if (this.disposed) throw RequestError.internalError(undefined, 'ACP connection is closed');\n if (!isAbsolute(request.cwd)) throw RequestError.invalidParams(undefined, 'cwd must be an absolute path');\n const runtime = await this.createSession(request);\n try {\n if (this.disposed) throw RequestError.internalError(undefined, 'ACP connection is closed');\n const available = await runtime.controller.listAvailableModels();\n if (!hasUsableModel(available, runtime.session.model.get() ?? '')) {\n throw RequestError.authRequired(undefined, 'Sign in to a model provider or add an API key to use Mastra Code');\n }\n const thread = await runtime.session.thread.create();\n await runtime.session.thread.switch({ threadId: thread.id });\n const defaultModelId = credentialedDefaultModel(available, runtime.session.model.get() ?? '');\n if (defaultModelId) await runtime.session.model.switch({ modelId: defaultModelId });\n const models: NewSessionResponse['models'] = {\n currentModelId: runtime.session.model.get() ?? '',\n availableModels: includeCurrentModel(\n [\n ...new Map(\n available\n .filter(model => model.hasApiKey || model.id === runtime.session.model.get())\n .map(\n model =>\n [\n model.id,\n {\n modelId: model.id,\n name: model.hasApiKey ? model.id : `${model.id} (provider not configured)`,\n },\n ] as const,\n ),\n ).values(),\n ],\n runtime.session.model.get() ?? '',\n ),\n };\n if (this.disposed) throw RequestError.internalError(undefined, 'ACP connection is closed');\n const entry: SessionEntry = {\n ...runtime,\n models: models.availableModels,\n state: null,\n queue: Promise.resolve(),\n turns: new Set(),\n unsubscribe: () => {},\n commands: [],\n };\n if (this.disposed) throw RequestError.internalError(undefined, 'ACP connection is closed');\n entry.unsubscribe = runtime.session.subscribe(event => {\n handleAgentControllerEvent(event, entry.state, this.connection, entry.session);\n if (event.type === 'mode_changed') {\n void this.connection\n .sessionUpdate({\n sessionId: thread.id,\n update: { sessionUpdate: 'current_mode_update', currentModeId: entry.session.mode.get() },\n })\n .catch(error => process.stderr.write(`[acp] mode update failed: ${error}\\n`));\n }\n if (\n event.type === 'mode_changed' ||\n event.type === 'model_changed' ||\n (event.type === 'state_changed' && event.changedKeys.includes('thinkingLevel'))\n ) {\n void this.connection\n .sessionUpdate({\n sessionId: thread.id,\n update: { sessionUpdate: 'config_option_update', configOptions: this.configOptions(entry) },\n })\n .catch(error => process.stderr.write(`[acp] configuration update failed: ${error}\\n`));\n }\n });\n const response: NewSessionResponse = {\n sessionId: thread.id,\n modes: {\n currentModeId: runtime.session.mode.get(),\n availableModes: runtime.modes.map(mode => ({ id: mode.id, name: mode.name ?? mode.id })),\n },\n models,\n configOptions: this.configOptions(entry),\n };\n this.sessions.set(thread.id, entry);\n // Let the SDK send session/new before clients receive updates for this ID.\n setImmediate(() => {\n void this.enqueue(entry, async () => {\n if (!this.disposed) await this.refreshCommands(thread.id, entry);\n }).catch(error => process.stderr.write(`[acp] command discovery failed: ${error}\\n`));\n });\n return response;\n } catch (error) {\n try {\n await runtime.cleanup?.();\n } catch (cleanupError) {\n if (this.disposed) this.startupCleanupFailures.push(cleanupError);\n throw withCleanupFailure(error, cleanupError);\n }\n throw error;\n }\n }\n\n private async refreshCommands(sessionId: string, entry: SessionEntry): Promise<AcpSkills | undefined> {\n const skills = await entry.getSkills?.();\n const commands = await listSkillCommands(skills);\n if (JSON.stringify(commands) !== JSON.stringify(entry.commands)) {\n await this.connection.sessionUpdate({\n sessionId,\n update: { sessionUpdate: 'available_commands_update', availableCommands: commands },\n });\n entry.commands = commands;\n }\n return skills;\n }\n\n private configOptions(entry: SessionEntry): SessionConfigOption[] {\n const modelId = entry.session.model.get() ?? '';\n const options: SessionConfigOption[] = [];\n const models = includeCurrentModel(entry.models, modelId);\n if (models.length)\n options.push({\n id: 'model',\n name: 'Model',\n category: 'model',\n type: 'select',\n currentValue: modelId,\n options: models.map(model => ({ value: model.modelId, name: model.name })),\n });\n options.push({\n id: 'mode',\n name: 'Mode',\n category: 'mode',\n type: 'select',\n currentValue: entry.session.mode.get(),\n options: entry.modes.map(mode => ({ value: mode.id, name: mode.name ?? mode.id })),\n });\n if (entry.getThinkingLevel)\n options.push({\n id: 'thought_level',\n name: 'Reasoning effort',\n category: 'thought_level',\n type: 'select',\n description: 'Requested reasoning level. The provider may adjust it for the selected model.',\n currentValue: this.thinkingLevel(entry),\n options: getAvailableThinkingLevelsForModel(modelId).map(value => ({\n value,\n name: value[0]!.toUpperCase() + value.slice(1),\n })),\n });\n return options;\n }\n\n private thinkingLevel(entry: SessionEntry): ThinkingLevelSetting {\n const level = entry.getThinkingLevel?.() ?? 'off';\n const levels = getAvailableThinkingLevelsForModel(entry.session.model.get() ?? '');\n return levels.includes(level) ? level : 'xhigh';\n }\n\n async setSessionConfigOption(params: SetSessionConfigOptionRequest): Promise<SetSessionConfigOptionResponse> {\n const entry = this.getSession(params.sessionId);\n return this.enqueue(entry, async () => {\n this.getSession(params.sessionId);\n const option = this.configOptions(entry).find(option => option.id === params.configId);\n if (\n !option ||\n option.type !== 'select' ||\n !option.options.some(item => 'value' in item && item.value === params.value)\n ) {\n throw RequestError.invalidParams(undefined, 'Unknown session configuration selection');\n }\n if (params.configId === 'model') {\n await entry.session.model.switch({ modelId: String(params.value) });\n } else if (params.configId === 'mode') {\n await entry.session.mode.switch({ modeId: String(params.value) });\n } else if (isThinkingLevelSetting(params.value)) {\n await entry.session.state.set({ thinkingLevel: params.value });\n }\n if (entry.getThinkingLevel && entry.getThinkingLevel() !== this.thinkingLevel(entry)) {\n await entry.session.state.set({ thinkingLevel: this.thinkingLevel(entry) });\n }\n return { configOptions: this.configOptions(entry) };\n });\n }\n\n async prompt(request: PromptRequest): Promise<PromptResponse> {\n const entry = this.getSession(request.sessionId);\n const content = extractTextFromContentBlocks(request.prompt);\n const turn = { cancelled: false };\n entry.turns.add(turn);\n try {\n return await this.enqueue(entry, async () => {\n if (turn.cancelled || this.disposed) return { stopReason: 'cancelled' };\n const usage: PromptState['usage'] = { promptTokens: 0, completionTokens: 0, totalTokens: 0 };\n let complete!: PromptState['resolve'];\n const completion = new Promise<Parameters<PromptState['resolve']>[0]>(resolve => {\n complete = resolve;\n });\n const state: PromptState = {\n sessionId: request.sessionId,\n usage,\n resolve: reason => {\n state.finished = true;\n complete(reason);\n },\n };\n entry.state = state;\n try {\n const skills = await this.refreshCommands(request.sessionId, entry);\n const expanded = await expandSkillCommand(content, skills, entry.commands ?? []);\n if (turn.cancelled || this.disposed) return { stopReason: 'cancelled' };\n await entry.session.sendMessage({ content: expanded });\n const reason = await completion;\n if (reason === 'error' && !state.cancelled && !state.stopReason) {\n throw RequestError.internalError(undefined, state.error?.message ?? 'Mastra Code turn failed');\n }\n return {\n stopReason: state.cancelled ? 'cancelled' : (state.stopReason ?? mapStopReason(reason)),\n usage: {\n inputTokens: usage.promptTokens,\n outputTokens: usage.completionTokens,\n totalTokens: usage.totalTokens,\n thoughtTokens: usage.reasoningTokens,\n cachedReadTokens: usage.cachedInputTokens,\n cachedWriteTokens: usage.cacheCreationInputTokens,\n },\n };\n } catch (error) {\n if (state.cancelled) return { stopReason: 'cancelled' };\n if (error instanceof RequestError) throw error;\n throw RequestError.internalError(\n undefined,\n error instanceof Error ? error.message : 'Mastra Code turn failed',\n );\n } finally {\n state.finished = true;\n if (entry.state === state) entry.state = null;\n }\n });\n } finally {\n entry.turns.delete(turn);\n }\n }\n\n async cancel(notification: CancelNotification): Promise<void> {\n const entry = this.sessions.get(notification.sessionId);\n if (!entry) return;\n for (const turn of entry.turns) turn.cancelled = true;\n if (entry.state && !entry.state.finished && !entry.state.cancelled) {\n const state = entry.state;\n state.cancelled = true;\n // Persist denial before aborting, otherwise a parked snapshot can replay on the next turn.\n for (const deny of state.cancelSuspensions?.values() ?? []) {\n try {\n await deny();\n } catch {\n /* Still abort if the suspended run is no longer available. */\n }\n }\n state.cancelSuspensions?.clear();\n if (entry.state !== state) return;\n entry.session.abort();\n // A suspended run has already ended and will not emit another agent_end.\n if (entry.state?.suspended) {\n entry.session.stream.detach();\n entry.state.resolve('aborted');\n }\n }\n }\n\n async setSessionMode(params: { sessionId: string; modeId: string }): Promise<void> {\n const entry = this.getSession(params.sessionId);\n if (!entry.modes.some(mode => mode.id === params.modeId))\n throw RequestError.invalidParams(undefined, 'Unknown mode');\n await this.enqueue(entry, async () => {\n if (this.disposed) return;\n await entry.session.mode.switch({ modeId: params.modeId });\n });\n }\n\n async unstable_setSessionModel(params: { sessionId: string; modelId: string }): Promise<void> {\n const entry = this.getSession(params.sessionId);\n await this.enqueue(entry, async () => {\n if (this.disposed) return;\n if (\n !includeCurrentModel(entry.models, entry.session.model.get() ?? '').some(\n model => model.modelId === params.modelId,\n )\n ) {\n throw RequestError.invalidParams(\n undefined,\n 'Model is unavailable or its provider is not configured. Refresh the model list.',\n );\n }\n await entry.session.model.switch({ modelId: params.modelId });\n });\n }\n}\n\nfunction includeCurrentModel(models: SessionEntry['models'], currentModelId: string): SessionEntry['models'] {\n // Saved/custom model IDs may work even when discovery only returns a gateway-qualified alias.\n return currentModelId && !models.some(model => model.modelId === currentModelId)\n ? [{ modelId: currentModelId, name: currentModelId }, ...models]\n : models;\n}\n\nexport function extractTextFromContentBlocks(blocks: ContentBlock[]): string {\n const parts: string[] = [];\n for (const block of blocks) {\n if (block.type === 'text') {\n parts.push(block.text);\n } else if (block.type === 'resource_link') {\n parts.push(`[resource: ${block.uri}]`);\n } else if (block.type === 'resource') {\n parts.push(`[resource: ${block.resource.uri}]`);\n if (!('text' in block.resource))\n throw RequestError.invalidParams(undefined, 'Binary prompt resources are not supported');\n parts.push(block.resource.text);\n } else {\n throw RequestError.invalidParams(undefined, `Unsupported prompt content: ${block.type}`);\n }\n }\n return parts.join('\\n');\n}\n\nexport function mapStopReason(\n reason: 'complete' | 'aborted' | 'error' | 'suspended',\n): 'end_turn' | 'cancelled' | 'max_tokens' | 'max_turn_requests' | 'refusal' {\n switch (reason) {\n case 'complete':\n return 'end_turn';\n case 'aborted':\n return 'cancelled';\n case 'error':\n throw RequestError.internalError(undefined, 'Mastra Code turn failed');\n case 'suspended':\n return 'end_turn';\n }\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../src/acp/runtime.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAElE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAGpD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAGpD,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,iBAAiB,EAC1B,OAAO,GAAE,IAAI,CAAC,gBAAgB,EAAE,UAAU,CAAM,GAC/C,OAAO,CAAC,iBAAiB,CAAC,
|
|
1
|
+
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../src/acp/runtime.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAElE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAGpD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAGpD,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,iBAAiB,EAC1B,OAAO,GAAE,IAAI,CAAC,gBAAgB,EAAE,UAAU,CAAM,GAC/C,OAAO,CAAC,iBAAiB,CAAC,CAiG5B"}
|
package/dist/acp/runtime.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { withCleanupFailure } from "./errors.js";
|
|
2
1
|
import { loadSettings, resolveDefaultThinkingLevel } from "../onboarding/settings.js";
|
|
2
|
+
import { withCleanupFailure } from "./errors.js";
|
|
3
3
|
import { createMastraCode } from "../index.js";
|
|
4
4
|
import { RequestError } from "@agentclientprotocol/sdk";
|
|
5
5
|
//#region src/acp/runtime.ts
|
|
@@ -47,17 +47,25 @@ async function createAcpSession(request, options = {}) {
|
|
|
47
47
|
getSkills: async () => (await result.controller.resolveWorkspace({ session: result.session }))?.skills,
|
|
48
48
|
getThinkingLevel: () => result.session.state.get().thinkingLevel ?? resolveDefaultThinkingLevel(settings, result.session.mode.get()).level,
|
|
49
49
|
cleanup: () => cleanupPromise ??= (async () => {
|
|
50
|
-
result.session.abort();
|
|
51
|
-
result.session.thread.detachFromCurrent();
|
|
52
|
-
result.stopPluginSignalProviders();
|
|
53
|
-
result.githubSignals?.stopAllPolling();
|
|
54
50
|
await Promise.allSettled([
|
|
55
|
-
result.session.
|
|
56
|
-
result.
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
result.
|
|
51
|
+
Promise.resolve().then(() => result.session.abort()),
|
|
52
|
+
Promise.resolve().then(() => result.session.thread.detachFromCurrent()),
|
|
53
|
+
Promise.resolve().then(() => result.stopPluginSignalProviders()),
|
|
54
|
+
Promise.resolve().then(() => result.githubSignals?.stopAllPolling()),
|
|
55
|
+
Promise.resolve().then(() => result.threadScheduler.stop())
|
|
56
|
+
]);
|
|
57
|
+
let dispatchTimeout;
|
|
58
|
+
await Promise.race([Promise.resolve().then(() => result.stopNotificationDispatch()).catch(() => {}), new Promise((resolve) => {
|
|
59
|
+
dispatchTimeout = setTimeout(resolve, 2e3);
|
|
60
|
+
dispatchTimeout.unref();
|
|
61
|
+
})]).finally(() => clearTimeout(dispatchTimeout));
|
|
62
|
+
await Promise.allSettled([
|
|
63
|
+
Promise.resolve().then(() => result.session.thread.clearAndReleaseLock()),
|
|
64
|
+
Promise.resolve().then(() => result.mcpManager?.disconnect()),
|
|
65
|
+
Promise.resolve().then(() => result.controller.getMastra()?.stopWorkers()),
|
|
66
|
+
Promise.resolve().then(() => result.controller.stopIntervals())
|
|
60
67
|
]);
|
|
68
|
+
await Promise.resolve().then(() => result.signalsPubSub?.close?.()).catch(() => {});
|
|
61
69
|
await result.storage.close();
|
|
62
70
|
})()
|
|
63
71
|
};
|
package/dist/acp/runtime.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtime.js","names":[],"sources":["../../src/acp/runtime.ts"],"sourcesContent":["import { RequestError } from '@agentclientprotocol/sdk';\nimport type { NewSessionRequest } from '@agentclientprotocol/sdk';\nimport { createMastraCode } from '../index.js';\nimport type { MastraCodeConfig } from '../index.js';\nimport type { McpServerConfig } from '../mcp/types.js';\nimport { loadSettings, resolveDefaultThinkingLevel } from '../onboarding/settings.js';\nimport type { AcpSessionRuntime } from './agent.js';\nimport { withCleanupFailure } from './errors.js';\n\nexport async function createAcpSession(\n request: NewSessionRequest,\n options: Pick<MastraCodeConfig, 'coAuthor'> = {},\n): Promise<AcpSessionRuntime> {\n const names = new Set<string>();\n const servers = request.mcpServers.map(server => {\n if ('type' in server && server.type === 'sse')\n throw RequestError.invalidParams(undefined, 'Legacy SSE MCP servers are unsupported; use HTTP or stdio');\n if (names.has(server.name))\n throw RequestError.invalidParams(undefined, `Duplicate MCP server name: ${server.name}`);\n names.add(server.name);\n const config: McpServerConfig =\n 'command' in server\n ? {\n command: server.command,\n args: server.args,\n env: Object.fromEntries(server.env.map(item => [item.name, item.value])),\n cwd: request.cwd,\n }\n : { url: server.url, headers: Object.fromEntries(server.headers.map(item => [item.name, item.value])) };\n return [server.name, config] as const;\n });\n const result = await createMastraCode({\n coAuthor: options.coAuthor,\n cwd: request.cwd,\n initialState: {\n projectPath: request.cwd,\n yolo: false,\n permissionRules: { categories: {}, tools: { ask_user: 'deny' } },\n },\n mcpServers: Object.fromEntries(servers),\n // ACP clients can answer permission requests, but have no free-text tool response method.\n disabledTools: ['ask_user'],\n unixSocketPubSub: false,\n disableMcp: false,\n disableHooks: false,\n // Project environment files must not mutate other ACP sessions.\n disableEnvFile: true,\n });\n const settings = loadSettings();\n let cleanupPromise: Promise<void> | undefined;\n const runtime: AcpSessionRuntime = {\n controller: result.controller,\n session: result.session,\n modes: result.controller.listModes(),\n getSkills: async () => (await result.controller.resolveWorkspace({ session: result.session }))?.skills,\n getThinkingLevel: () =>\n result.session.state.get().thinkingLevel ??\n resolveDefaultThinkingLevel(settings, result.session.mode.get()).level,\n cleanup: () =>\n (cleanupPromise ??= (async () => {\n result.session.abort()
|
|
1
|
+
{"version":3,"file":"runtime.js","names":[],"sources":["../../src/acp/runtime.ts"],"sourcesContent":["import { RequestError } from '@agentclientprotocol/sdk';\nimport type { NewSessionRequest } from '@agentclientprotocol/sdk';\nimport { createMastraCode } from '../index.js';\nimport type { MastraCodeConfig } from '../index.js';\nimport type { McpServerConfig } from '../mcp/types.js';\nimport { loadSettings, resolveDefaultThinkingLevel } from '../onboarding/settings.js';\nimport type { AcpSessionRuntime } from './agent.js';\nimport { withCleanupFailure } from './errors.js';\n\nexport async function createAcpSession(\n request: NewSessionRequest,\n options: Pick<MastraCodeConfig, 'coAuthor'> = {},\n): Promise<AcpSessionRuntime> {\n const names = new Set<string>();\n const servers = request.mcpServers.map(server => {\n if ('type' in server && server.type === 'sse')\n throw RequestError.invalidParams(undefined, 'Legacy SSE MCP servers are unsupported; use HTTP or stdio');\n if (names.has(server.name))\n throw RequestError.invalidParams(undefined, `Duplicate MCP server name: ${server.name}`);\n names.add(server.name);\n const config: McpServerConfig =\n 'command' in server\n ? {\n command: server.command,\n args: server.args,\n env: Object.fromEntries(server.env.map(item => [item.name, item.value])),\n cwd: request.cwd,\n }\n : { url: server.url, headers: Object.fromEntries(server.headers.map(item => [item.name, item.value])) };\n return [server.name, config] as const;\n });\n const result = await createMastraCode({\n coAuthor: options.coAuthor,\n cwd: request.cwd,\n initialState: {\n projectPath: request.cwd,\n yolo: false,\n permissionRules: { categories: {}, tools: { ask_user: 'deny' } },\n },\n mcpServers: Object.fromEntries(servers),\n // ACP clients can answer permission requests, but have no free-text tool response method.\n disabledTools: ['ask_user'],\n unixSocketPubSub: false,\n disableMcp: false,\n disableHooks: false,\n // Project environment files must not mutate other ACP sessions.\n disableEnvFile: true,\n });\n const settings = loadSettings();\n let cleanupPromise: Promise<void> | undefined;\n const runtime: AcpSessionRuntime = {\n controller: result.controller,\n session: result.session,\n modes: result.controller.listModes(),\n getSkills: async () => (await result.controller.resolveWorkspace({ session: result.session }))?.skills,\n getThinkingLevel: () =>\n result.session.state.get().thinkingLevel ??\n resolveDefaultThinkingLevel(settings, result.session.mode.get()).level,\n cleanup: () =>\n (cleanupPromise ??= (async () => {\n await Promise.allSettled([\n Promise.resolve().then(() => result.session.abort()),\n Promise.resolve().then(() => result.session.thread.detachFromCurrent()),\n Promise.resolve().then(() => result.stopPluginSignalProviders()),\n Promise.resolve().then(() => result.githubSignals?.stopAllPolling()),\n Promise.resolve().then(() => result.threadScheduler.stop()),\n ]);\n // Leave time for the other cleanup phases within ACP's shared 10-second cap.\n // A timed-out dispatch may still finish later; this grace is not cancellation.\n let dispatchTimeout: ReturnType<typeof setTimeout> | undefined;\n await Promise.race([\n Promise.resolve()\n .then(() => result.stopNotificationDispatch())\n .catch(() => {}),\n new Promise<void>(resolve => {\n dispatchTimeout = setTimeout(resolve, 2_000);\n dispatchTimeout.unref();\n }),\n ]).finally(() => clearTimeout(dispatchTimeout));\n await Promise.allSettled([\n Promise.resolve().then(() => result.session.thread.clearAndReleaseLock()),\n Promise.resolve().then(() => result.mcpManager?.disconnect()),\n Promise.resolve().then(() => result.controller.getMastra()?.stopWorkers()),\n Promise.resolve().then(() => result.controller.stopIntervals()),\n ]);\n await Promise.resolve()\n .then(() => (result.signalsPubSub as { close?: () => void | Promise<void> } | undefined)?.close?.())\n .catch(() => {});\n await result.storage.close();\n })()),\n };\n try {\n const status = await result.mcpManager?.initInBackground();\n const failed = status?.failed.filter(server => names.has(server.name)) ?? [];\n if (failed.length)\n throw RequestError.internalError(\n undefined,\n failed.map(server => `MCP server ${server.name}: ${server.error ?? 'connection failed'}`).join('; '),\n );\n\n return runtime;\n } catch (error) {\n try {\n await runtime.cleanup?.();\n } catch (cleanupError) {\n throw withCleanupFailure(error, cleanupError);\n }\n throw error;\n }\n}\n"],"mappings":"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"}
|
package/dist/agents/model.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { listBuiltinModePacks, resolveModePackFallbackChain } from "../onboarding/packs.js";
|
|
2
2
|
import { MASTRA_GATEWAY_PREFIX, remapOpenAIModelForCodexOAuth, stripMastraGatewayPrefix } from "../providers/model-ids.js";
|
|
3
3
|
import { ProviderAuthRequiredError } from "../auth/provider-auth-error.js";
|
|
4
|
-
import {
|
|
4
|
+
import { isThinkingLevelSetting } from "../thinking.js";
|
|
5
5
|
import { findModePackForModel, loadSettings, resolveDefaultThinkingLevel, resolveModePackModels, stripMastraCodeCustomProviderPrefix } from "../onboarding/settings.js";
|
|
6
6
|
import { hasCredentialStoreProvider, resolveCredentialStore, resolveTenantFromRequestContext, setCredentialStoreProvider } from "./credential-resolver.js";
|
|
7
7
|
import { getRequestAccountSelection, isRequestAccountRoutingExhausted } from "../auth/account-routing-context.js";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { DEFAULT_CONFIG_DIR } from "../../constants.js";
|
|
2
2
|
import { dirname, isAbsolute, join, normalize, relative, resolve, sep } from "path";
|
|
3
|
-
import { execFileSync } from "child_process";
|
|
4
3
|
import { existsSync, readFileSync, realpathSync, statSync } from "fs";
|
|
4
|
+
import { execFileSync } from "child_process";
|
|
5
5
|
import { homedir } from "os";
|
|
6
6
|
//#region src/agents/prompts/agent-instructions.ts
|
|
7
7
|
/**
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { getOAuthProviders } from "./storage.js";
|
|
2
|
-
import { ProviderAuthRequiredError } from "./provider-auth-error.js";
|
|
3
2
|
import { resolveModePackFallbackChain } from "../onboarding/packs.js";
|
|
3
|
+
import { ProviderAuthRequiredError } from "./provider-auth-error.js";
|
|
4
4
|
import { findModePackForModel, loadSettings, resolveModePackModels } from "../onboarding/settings.js";
|
|
5
5
|
import { resolveCredentialStore } from "../agents/credential-resolver.js";
|
|
6
6
|
import { getRequestAccountSelection, isRequestAccountRoutingExhausted, markRequestAccountRoutingExhausted, setRequestAccountSelection } from "./account-routing-context.js";
|
|
@@ -170,7 +170,8 @@ async function loginKimiCoding(callbacks) {
|
|
|
170
170
|
const pending = await startKimiCodingDeviceLogin({ signal: callbacks.signal });
|
|
171
171
|
callbacks.onAuth({
|
|
172
172
|
url: pending.url,
|
|
173
|
-
instructions: pending.instructions
|
|
173
|
+
instructions: pending.instructions,
|
|
174
|
+
userCode: pending.userCode
|
|
174
175
|
});
|
|
175
176
|
callbacks.onProgress?.("Waiting for Kimi For Coding device authorization...");
|
|
176
177
|
return pollDeviceCodeUntilComplete({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"kimi-coding.js","names":[],"sources":["../../../src/auth/providers/kimi-coding.ts"],"sourcesContent":["import { arch, hostname, platform, release } from 'node:os';\nimport { getCurrentVersion } from '../../utils/update-check.js';\nimport {\n abortableSleep,\n createDeviceCodePollState,\n pollDeviceCodeUntilComplete,\n stepDeviceCodePoll,\n} from '../device-code.js';\nimport type { DeviceCodePollOutcome, DeviceCodePollState } from '../device-code.js';\nimport type { OAuthCredentials, OAuthLoginCallbacks, OAuthProviderInterface } from '../types.js';\n\nconst CLIENT_ID = '17e5f671-d194-4dfb-9706-5516cb48c098';\nconst OAUTH_HOST = 'https://auth.kimi.com';\nconst DEVICE_ID_PATTERN = /^[0-9a-f]{32}$/;\nconst DEFAULT_EXPIRES_IN_SECONDS = 15 * 60;\nconst DEFAULT_POLL_INTERVAL_SECONDS = 5;\nconst REQUEST_TIMEOUT_MS = 30_000;\nconst REFRESH_MAX_RETRIES = 3;\n\nfunction asciiHeaderValue(value: string): string {\n const sanitized = value.replace(/[^\\x20-\\x7E]/g, '').trim();\n return sanitized || 'unknown';\n}\n\nconst KIMI_DEVICE_DETAILS = {\n 'X-Msh-Platform': 'mastracode',\n 'X-Msh-Version': asciiHeaderValue(getCurrentVersion()),\n 'X-Msh-Device-Name': asciiHeaderValue(hostname()),\n 'X-Msh-Device-Model': asciiHeaderValue(`${platform()} ${arch()}`),\n 'X-Msh-Os-Version': asciiHeaderValue(release()),\n};\n\nexport function createKimiCodingDeviceId(): string {\n return globalThis.crypto.randomUUID().replaceAll('-', '');\n}\n\nexport function isKimiCodingDeviceId(value: unknown): value is string {\n return typeof value === 'string' && DEVICE_ID_PATTERN.test(value);\n}\n\nexport function getKimiCodingDeviceHeaders(deviceId: string): Record<string, string> {\n if (!isKimiCodingDeviceId(deviceId)) {\n throw new Error('Kimi For Coding credentials have an invalid device ID. Please reconnect the account.');\n }\n return { ...KIMI_DEVICE_DETAILS, 'X-Msh-Device-Id': deviceId };\n}\n\nfunction requestSignal(signal?: AbortSignal): AbortSignal {\n const timeout = AbortSignal.timeout(REQUEST_TIMEOUT_MS);\n return signal ? AbortSignal.any([timeout, signal]) : timeout;\n}\n\nfunction trustedHttpUrl(value: unknown): string | null {\n if (typeof value !== 'string' || !value) return null;\n try {\n const url = new URL(value);\n return url.protocol === 'https:' ? url.href : null;\n } catch {\n return null;\n }\n}\n\nasync function readJson(response: Response): Promise<Record<string, unknown> | null> {\n try {\n const value = (await response.json()) as unknown;\n return value && typeof value === 'object' ? (value as Record<string, unknown>) : null;\n } catch {\n return null;\n }\n}\n\nfunction credentialsFromTokenResponse(value: unknown, operation: string, deviceId: string): OAuthCredentials {\n const data = (value ?? {}) as Record<string, unknown>;\n const access = data.access_token;\n const refresh = data.refresh_token;\n const expiresIn = data.expires_in;\n if (\n typeof access !== 'string' ||\n !access ||\n typeof refresh !== 'string' ||\n !refresh ||\n typeof expiresIn !== 'number' ||\n !Number.isFinite(expiresIn) ||\n expiresIn <= 0\n ) {\n throw new Error(`Kimi For Coding token ${operation} response missing fields`);\n }\n return { access, refresh, expires: Date.now() + expiresIn * 1000, deviceId };\n}\n\nexport interface KimiCodingDeviceLoginPending {\n clientId: string;\n deviceId: string;\n deviceCode: string;\n userCode: string;\n url: string;\n instructions: string;\n state: DeviceCodePollState;\n}\n\nexport type KimiCodingDevicePollResult =\n | { status: 'complete'; credentials: OAuthCredentials }\n | { status: 'pending'; nextPollMs: number; pending: KimiCodingDeviceLoginPending }\n | { status: 'failed'; error: string };\n\nexport async function startKimiCodingDeviceLogin(options?: {\n signal?: AbortSignal;\n}): Promise<KimiCodingDeviceLoginPending> {\n const clientId = CLIENT_ID;\n const deviceId = createKimiCodingDeviceId();\n const response = await fetch(`${OAUTH_HOST}/api/oauth/device_authorization`, {\n method: 'POST',\n headers: {\n ...getKimiCodingDeviceHeaders(deviceId),\n 'Content-Type': 'application/x-www-form-urlencoded',\n Accept: 'application/json',\n },\n body: new URLSearchParams({ client_id: clientId }).toString(),\n signal: requestSignal(options?.signal),\n });\n if (!response.ok) {\n throw new Error(`Kimi For Coding device authorization failed: ${response.status}`);\n }\n\n const data = await readJson(response);\n const deviceCode = data?.device_code;\n const userCode = data?.user_code;\n const verificationUri = trustedHttpUrl(data?.verification_uri);\n const verificationUriComplete = trustedHttpUrl(data?.verification_uri_complete);\n if (\n typeof deviceCode !== 'string' ||\n !deviceCode ||\n typeof userCode !== 'string' ||\n !userCode ||\n !verificationUri ||\n !verificationUriComplete\n ) {\n throw new Error('Invalid Kimi For Coding device authorization response');\n }\n\n const interval = data?.interval;\n const expiresIn = data?.expires_in;\n return {\n clientId,\n deviceId,\n deviceCode,\n userCode,\n url: verificationUriComplete,\n instructions: `Enter code: ${userCode}`,\n state: createDeviceCodePollState({\n intervalSeconds:\n typeof interval === 'number' && Number.isFinite(interval) && interval > 0\n ? interval\n : DEFAULT_POLL_INTERVAL_SECONDS,\n expiresInSeconds:\n typeof expiresIn === 'number' && Number.isFinite(expiresIn) && expiresIn > 0\n ? expiresIn\n : DEFAULT_EXPIRES_IN_SECONDS,\n }),\n };\n}\n\nasync function pollKimiCodingTokenOnce(\n pending: KimiCodingDeviceLoginPending,\n signal?: AbortSignal,\n): Promise<DeviceCodePollOutcome<OAuthCredentials>> {\n const response = await fetch(`${OAUTH_HOST}/api/oauth/token`, {\n method: 'POST',\n headers: {\n ...getKimiCodingDeviceHeaders(pending.deviceId),\n 'Content-Type': 'application/x-www-form-urlencoded',\n Accept: 'application/json',\n },\n body: new URLSearchParams({\n client_id: pending.clientId,\n device_code: pending.deviceCode,\n grant_type: 'urn:ietf:params:oauth:grant-type:device_code',\n }).toString(),\n signal: requestSignal(signal),\n });\n const data = await readJson(response);\n if (response.ok && typeof data?.access_token === 'string') {\n try {\n return { status: 'complete', result: credentialsFromTokenResponse(data, 'poll', pending.deviceId) };\n } catch (error) {\n return { status: 'failed', error: error instanceof Error ? error.message : String(error) };\n }\n }\n\n const error = data?.error;\n if (error === 'authorization_pending') return { status: 'pending' };\n if (error === 'slow_down') {\n return {\n status: 'slow_down',\n intervalSeconds: typeof data?.interval === 'number' && data.interval > 0 ? data.interval : undefined,\n };\n }\n if (error === 'expired_token') {\n return { status: 'failed', error: 'Kimi For Coding authorization expired. Please restart login.' };\n }\n if (error === 'access_denied') return { status: 'failed', error: 'Kimi For Coding login was denied.' };\n return {\n status: 'failed',\n error: `Kimi For Coding token request failed: ${response.status}`,\n };\n}\n\nexport async function pollKimiCodingDeviceLogin(\n pending: KimiCodingDeviceLoginPending,\n options?: { signal?: AbortSignal },\n): Promise<KimiCodingDevicePollResult> {\n const step = await stepDeviceCodePoll(pending.state, () => pollKimiCodingTokenOnce(pending, options?.signal));\n if (step.status === 'complete') return { status: 'complete', credentials: step.result };\n if (step.status === 'failed') return { status: 'failed', error: step.error };\n return {\n status: 'pending',\n nextPollMs: step.nextPollMs,\n pending: { ...pending, state: step.state },\n };\n}\n\nexport async function loginKimiCoding(callbacks: OAuthLoginCallbacks): Promise<OAuthCredentials> {\n const pending = await startKimiCodingDeviceLogin({ signal: callbacks.signal });\n callbacks.onAuth({ url: pending.url, instructions: pending.instructions });\n callbacks.onProgress?.('Waiting for Kimi For Coding device authorization...');\n return pollDeviceCodeUntilComplete({\n state: pending.state,\n pollOnce: () => pollKimiCodingTokenOnce(pending, callbacks.signal),\n signal: callbacks.signal,\n });\n}\n\nexport async function refreshKimiCodingToken(\n refreshToken: string,\n options: { signal?: AbortSignal; deviceId: string },\n): Promise<OAuthCredentials> {\n const clientId = CLIENT_ID;\n const deviceHeaders = getKimiCodingDeviceHeaders(options.deviceId);\n let lastError: Error | undefined;\n for (let attempt = 0; attempt <= REFRESH_MAX_RETRIES; attempt++) {\n if (attempt > 0) await abortableSleep(1000 * 2 ** (attempt - 1), options.signal);\n let response: Response;\n try {\n response = await fetch(`${OAUTH_HOST}/api/oauth/token`, {\n method: 'POST',\n headers: {\n ...deviceHeaders,\n 'Content-Type': 'application/x-www-form-urlencoded',\n Accept: 'application/json',\n },\n body: new URLSearchParams({\n client_id: clientId,\n grant_type: 'refresh_token',\n refresh_token: refreshToken,\n }).toString(),\n signal: requestSignal(options.signal),\n });\n } catch (error) {\n lastError = error instanceof Error ? error : new Error(String(error));\n if (attempt === REFRESH_MAX_RETRIES) throw lastError;\n continue;\n }\n const data = await readJson(response);\n if (response.ok) return credentialsFromTokenResponse(data, 'refresh', options.deviceId);\n\n const error = typeof data?.error === 'string' ? ` ${data.error}` : '';\n lastError = new Error(`Kimi For Coding token refresh failed: ${response.status}${error}`);\n const retryable = response.status === 429 || response.status >= 500;\n if (!retryable || attempt === REFRESH_MAX_RETRIES) throw lastError;\n }\n throw lastError ?? new Error('Kimi For Coding token refresh failed');\n}\n\nexport const kimiCodingOAuthProvider: OAuthProviderInterface = {\n id: 'kimi-for-coding',\n name: 'Kimi For Coding',\n login: loginKimiCoding,\n refreshToken: credentials =>\n refreshKimiCodingToken(credentials.refresh, {\n deviceId: typeof credentials.deviceId === 'string' ? credentials.deviceId : '',\n }),\n getApiKey: credentials => credentials.access,\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"kimi-coding.js","names":[],"sources":["../../../src/auth/providers/kimi-coding.ts"],"sourcesContent":["import { arch, hostname, platform, release } from 'node:os';\nimport { getCurrentVersion } from '../../utils/update-check.js';\nimport {\n abortableSleep,\n createDeviceCodePollState,\n pollDeviceCodeUntilComplete,\n stepDeviceCodePoll,\n} from '../device-code.js';\nimport type { DeviceCodePollOutcome, DeviceCodePollState } from '../device-code.js';\nimport type { OAuthCredentials, OAuthLoginCallbacks, OAuthProviderInterface } from '../types.js';\n\nconst CLIENT_ID = '17e5f671-d194-4dfb-9706-5516cb48c098';\nconst OAUTH_HOST = 'https://auth.kimi.com';\nconst DEVICE_ID_PATTERN = /^[0-9a-f]{32}$/;\nconst DEFAULT_EXPIRES_IN_SECONDS = 15 * 60;\nconst DEFAULT_POLL_INTERVAL_SECONDS = 5;\nconst REQUEST_TIMEOUT_MS = 30_000;\nconst REFRESH_MAX_RETRIES = 3;\n\nfunction asciiHeaderValue(value: string): string {\n const sanitized = value.replace(/[^\\x20-\\x7E]/g, '').trim();\n return sanitized || 'unknown';\n}\n\nconst KIMI_DEVICE_DETAILS = {\n 'X-Msh-Platform': 'mastracode',\n 'X-Msh-Version': asciiHeaderValue(getCurrentVersion()),\n 'X-Msh-Device-Name': asciiHeaderValue(hostname()),\n 'X-Msh-Device-Model': asciiHeaderValue(`${platform()} ${arch()}`),\n 'X-Msh-Os-Version': asciiHeaderValue(release()),\n};\n\nexport function createKimiCodingDeviceId(): string {\n return globalThis.crypto.randomUUID().replaceAll('-', '');\n}\n\nexport function isKimiCodingDeviceId(value: unknown): value is string {\n return typeof value === 'string' && DEVICE_ID_PATTERN.test(value);\n}\n\nexport function getKimiCodingDeviceHeaders(deviceId: string): Record<string, string> {\n if (!isKimiCodingDeviceId(deviceId)) {\n throw new Error('Kimi For Coding credentials have an invalid device ID. Please reconnect the account.');\n }\n return { ...KIMI_DEVICE_DETAILS, 'X-Msh-Device-Id': deviceId };\n}\n\nfunction requestSignal(signal?: AbortSignal): AbortSignal {\n const timeout = AbortSignal.timeout(REQUEST_TIMEOUT_MS);\n return signal ? AbortSignal.any([timeout, signal]) : timeout;\n}\n\nfunction trustedHttpUrl(value: unknown): string | null {\n if (typeof value !== 'string' || !value) return null;\n try {\n const url = new URL(value);\n return url.protocol === 'https:' ? url.href : null;\n } catch {\n return null;\n }\n}\n\nasync function readJson(response: Response): Promise<Record<string, unknown> | null> {\n try {\n const value = (await response.json()) as unknown;\n return value && typeof value === 'object' ? (value as Record<string, unknown>) : null;\n } catch {\n return null;\n }\n}\n\nfunction credentialsFromTokenResponse(value: unknown, operation: string, deviceId: string): OAuthCredentials {\n const data = (value ?? {}) as Record<string, unknown>;\n const access = data.access_token;\n const refresh = data.refresh_token;\n const expiresIn = data.expires_in;\n if (\n typeof access !== 'string' ||\n !access ||\n typeof refresh !== 'string' ||\n !refresh ||\n typeof expiresIn !== 'number' ||\n !Number.isFinite(expiresIn) ||\n expiresIn <= 0\n ) {\n throw new Error(`Kimi For Coding token ${operation} response missing fields`);\n }\n return { access, refresh, expires: Date.now() + expiresIn * 1000, deviceId };\n}\n\nexport interface KimiCodingDeviceLoginPending {\n clientId: string;\n deviceId: string;\n deviceCode: string;\n userCode: string;\n url: string;\n instructions: string;\n state: DeviceCodePollState;\n}\n\nexport type KimiCodingDevicePollResult =\n | { status: 'complete'; credentials: OAuthCredentials }\n | { status: 'pending'; nextPollMs: number; pending: KimiCodingDeviceLoginPending }\n | { status: 'failed'; error: string };\n\nexport async function startKimiCodingDeviceLogin(options?: {\n signal?: AbortSignal;\n}): Promise<KimiCodingDeviceLoginPending> {\n const clientId = CLIENT_ID;\n const deviceId = createKimiCodingDeviceId();\n const response = await fetch(`${OAUTH_HOST}/api/oauth/device_authorization`, {\n method: 'POST',\n headers: {\n ...getKimiCodingDeviceHeaders(deviceId),\n 'Content-Type': 'application/x-www-form-urlencoded',\n Accept: 'application/json',\n },\n body: new URLSearchParams({ client_id: clientId }).toString(),\n signal: requestSignal(options?.signal),\n });\n if (!response.ok) {\n throw new Error(`Kimi For Coding device authorization failed: ${response.status}`);\n }\n\n const data = await readJson(response);\n const deviceCode = data?.device_code;\n const userCode = data?.user_code;\n const verificationUri = trustedHttpUrl(data?.verification_uri);\n const verificationUriComplete = trustedHttpUrl(data?.verification_uri_complete);\n if (\n typeof deviceCode !== 'string' ||\n !deviceCode ||\n typeof userCode !== 'string' ||\n !userCode ||\n !verificationUri ||\n !verificationUriComplete\n ) {\n throw new Error('Invalid Kimi For Coding device authorization response');\n }\n\n const interval = data?.interval;\n const expiresIn = data?.expires_in;\n return {\n clientId,\n deviceId,\n deviceCode,\n userCode,\n url: verificationUriComplete,\n instructions: `Enter code: ${userCode}`,\n state: createDeviceCodePollState({\n intervalSeconds:\n typeof interval === 'number' && Number.isFinite(interval) && interval > 0\n ? interval\n : DEFAULT_POLL_INTERVAL_SECONDS,\n expiresInSeconds:\n typeof expiresIn === 'number' && Number.isFinite(expiresIn) && expiresIn > 0\n ? expiresIn\n : DEFAULT_EXPIRES_IN_SECONDS,\n }),\n };\n}\n\nasync function pollKimiCodingTokenOnce(\n pending: KimiCodingDeviceLoginPending,\n signal?: AbortSignal,\n): Promise<DeviceCodePollOutcome<OAuthCredentials>> {\n const response = await fetch(`${OAUTH_HOST}/api/oauth/token`, {\n method: 'POST',\n headers: {\n ...getKimiCodingDeviceHeaders(pending.deviceId),\n 'Content-Type': 'application/x-www-form-urlencoded',\n Accept: 'application/json',\n },\n body: new URLSearchParams({\n client_id: pending.clientId,\n device_code: pending.deviceCode,\n grant_type: 'urn:ietf:params:oauth:grant-type:device_code',\n }).toString(),\n signal: requestSignal(signal),\n });\n const data = await readJson(response);\n if (response.ok && typeof data?.access_token === 'string') {\n try {\n return { status: 'complete', result: credentialsFromTokenResponse(data, 'poll', pending.deviceId) };\n } catch (error) {\n return { status: 'failed', error: error instanceof Error ? error.message : String(error) };\n }\n }\n\n const error = data?.error;\n if (error === 'authorization_pending') return { status: 'pending' };\n if (error === 'slow_down') {\n return {\n status: 'slow_down',\n intervalSeconds: typeof data?.interval === 'number' && data.interval > 0 ? data.interval : undefined,\n };\n }\n if (error === 'expired_token') {\n return { status: 'failed', error: 'Kimi For Coding authorization expired. Please restart login.' };\n }\n if (error === 'access_denied') return { status: 'failed', error: 'Kimi For Coding login was denied.' };\n return {\n status: 'failed',\n error: `Kimi For Coding token request failed: ${response.status}`,\n };\n}\n\nexport async function pollKimiCodingDeviceLogin(\n pending: KimiCodingDeviceLoginPending,\n options?: { signal?: AbortSignal },\n): Promise<KimiCodingDevicePollResult> {\n const step = await stepDeviceCodePoll(pending.state, () => pollKimiCodingTokenOnce(pending, options?.signal));\n if (step.status === 'complete') return { status: 'complete', credentials: step.result };\n if (step.status === 'failed') return { status: 'failed', error: step.error };\n return {\n status: 'pending',\n nextPollMs: step.nextPollMs,\n pending: { ...pending, state: step.state },\n };\n}\n\nexport async function loginKimiCoding(callbacks: OAuthLoginCallbacks): Promise<OAuthCredentials> {\n const pending = await startKimiCodingDeviceLogin({ signal: callbacks.signal });\n callbacks.onAuth({ url: pending.url, instructions: pending.instructions, userCode: pending.userCode });\n callbacks.onProgress?.('Waiting for Kimi For Coding device authorization...');\n return pollDeviceCodeUntilComplete({\n state: pending.state,\n pollOnce: () => pollKimiCodingTokenOnce(pending, callbacks.signal),\n signal: callbacks.signal,\n });\n}\n\nexport async function refreshKimiCodingToken(\n refreshToken: string,\n options: { signal?: AbortSignal; deviceId: string },\n): Promise<OAuthCredentials> {\n const clientId = CLIENT_ID;\n const deviceHeaders = getKimiCodingDeviceHeaders(options.deviceId);\n let lastError: Error | undefined;\n for (let attempt = 0; attempt <= REFRESH_MAX_RETRIES; attempt++) {\n if (attempt > 0) await abortableSleep(1000 * 2 ** (attempt - 1), options.signal);\n let response: Response;\n try {\n response = await fetch(`${OAUTH_HOST}/api/oauth/token`, {\n method: 'POST',\n headers: {\n ...deviceHeaders,\n 'Content-Type': 'application/x-www-form-urlencoded',\n Accept: 'application/json',\n },\n body: new URLSearchParams({\n client_id: clientId,\n grant_type: 'refresh_token',\n refresh_token: refreshToken,\n }).toString(),\n signal: requestSignal(options.signal),\n });\n } catch (error) {\n lastError = error instanceof Error ? error : new Error(String(error));\n if (attempt === REFRESH_MAX_RETRIES) throw lastError;\n continue;\n }\n const data = await readJson(response);\n if (response.ok) return credentialsFromTokenResponse(data, 'refresh', options.deviceId);\n\n const error = typeof data?.error === 'string' ? ` ${data.error}` : '';\n lastError = new Error(`Kimi For Coding token refresh failed: ${response.status}${error}`);\n const retryable = response.status === 429 || response.status >= 500;\n if (!retryable || attempt === REFRESH_MAX_RETRIES) throw lastError;\n }\n throw lastError ?? new Error('Kimi For Coding token refresh failed');\n}\n\nexport const kimiCodingOAuthProvider: OAuthProviderInterface = {\n id: 'kimi-for-coding',\n name: 'Kimi For Coding',\n login: loginKimiCoding,\n refreshToken: credentials =>\n refreshKimiCodingToken(credentials.refresh, {\n deviceId: typeof credentials.deviceId === 'string' ? credentials.deviceId : '',\n }),\n getApiKey: credentials => credentials.access,\n};\n"],"mappings":"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"}
|
|
@@ -162,7 +162,8 @@ async function loginXAI(callbacks) {
|
|
|
162
162
|
const pending = await startXAIDeviceLogin({ signal: callbacks.signal });
|
|
163
163
|
callbacks.onAuth({
|
|
164
164
|
url: pending.url,
|
|
165
|
-
instructions: pending.instructions
|
|
165
|
+
instructions: pending.instructions,
|
|
166
|
+
userCode: pending.userCode
|
|
166
167
|
});
|
|
167
168
|
callbacks.onProgress?.("Waiting for xAI device authorization...");
|
|
168
169
|
return pollDeviceCodeUntilComplete({
|