mu-agent 0.2.2 → 0.2.4
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/CHANGELOG.md +35 -0
- package/README.md +3 -7
- package/dist/bundle/chunks/anthropic.js +1 -1
- package/dist/bundle/chunks/{chunk-BK7M6BDT.js → chunk-C4L65EFW.js} +6 -6
- package/dist/bundle/chunks/chunk-VPSGIO2O.js +2 -0
- package/dist/bundle/chunks/openai-chatgpt.js +1 -1
- package/dist/bundle/chunks/openai-codex.js +2 -2
- package/dist/bundle/chunks/{openai-completions-UOA7MELD.js → openai-completions-WALPQ6HP.js} +4 -2
- package/dist/bundle/chunks/openrouter.js +1 -1
- package/dist/bundle/chunks/radius.js +1 -1
- package/dist/bundle/chunks/{virtual-modules-U6MRV5BC.js → virtual-modules-4BSUQTRT.js} +1 -1
- package/dist/bundle/cli-runtime.js +1 -1
- package/dist/bundle/index.js +1 -1
- package/dist/bundle/rpc-entry.js +1 -1
- package/docs/models-configuration.md +5 -5
- package/docs/models.md +23 -1
- package/judge/dist/auth.js +66 -19
- package/judge/dist/mude.js +624 -117
- package/judge/dist/setup.js +275 -146
- package/judge/manifest.json +14 -15
- package/judge/mu/{chunk-6XRUK3PM.js → chunk-JK2OO2CN.js} +5 -4
- package/judge/mu/{cloud-code-XR7SZMJC.js → cloud-code-K5ONKXO7.js} +1 -1
- package/judge/mu/index.js +65 -28
- package/kyrn/bin/kyrn-doctor +0 -1
- package/kyrn/bin/kyrn-ledger +0 -2
- package/kyrn/bin/mu.mjs +50 -16
- package/package.json +2 -2
- package/dist/bundle/chunks/chunk-AN7MSYCK.js +0 -2
package/dist/bundle/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { createRequire as __piCreateRequire } from "node:module"; const require = __piCreateRequire(import.meta.url);
|
|
2
|
-
import{ShowImagesSelectorComponent,ThemeSelectorComponent}from"./chunks/chunk-
|
|
2
|
+
import{ShowImagesSelectorComponent,ThemeSelectorComponent}from"./chunks/chunk-VPSGIO2O.js";import{AgentSession,AgentSessionRuntime,AssistantMessageComponent,BashExecutionComponent,BorderedLoader,BranchSummaryMessageComponent,CURRENT_SESSION_VERSION,CompactionSummaryMessageComponent,CredentialSynchronizationError,CustomEditor,CustomMessageComponent,DEFAULT_COMPACTION_SETTINGS,DefaultPackageManager,DefaultResourceLoader,DynamicBorder,ExtensionEditorComponent,ExtensionInputComponent,ExtensionRunner,ExtensionSelectorComponent,FileModelsStore,FooterComponent,InteractiveMode,LoginDialogComponent,MCP_CONNECTION_EVENT,ModelRegistry,ModelRuntime,ModelSelectorComponent,OAuthSelectorComponent,RpcClient,SessionManager,SessionSelectorComponent,SettingsManager,SettingsSelectorComponent,SkillInvocationMessageComponent,ThinkingSelectorComponent,ToolExecutionComponent,TreeSelectorComponent,UserMessageComponent,UserMessageSelectorComponent,VIRTUAL_MODEL_STATE_ENTRY,applyHttpProxySettings,buildContextEntries,buildSessionContext,buildSessionProjection,calculateContextTokens,collectEntriesForBranchSummary,compact,configureHttpDispatcher,convertToLlm,convertToPng,copyToClipboard,createAgentSession,createAgentSessionFromServices,createAgentSessionRuntime,createAgentSessionServices,createBashTool,createBashToolDefinition,createCodemodeExtension,createCodingTools,createEditTool,createEditToolDefinition,createEventBus,createExtensionRuntime,createFindTool,createFindToolDefinition,createGrepTool,createGrepToolDefinition,createLocalBashOperations,createLocalPowerShellOperations,createLsTool,createLsToolDefinition,createMcpExtension,createPowerShellTool,createPowerShellToolDefinition,createReadOnlyTools,createReadTool,createReadToolDefinition,createSyntheticSourceInfo,createToolSearchExtension,createWriteTool,createWriteToolDefinition,defaultModelPerProvider,defineTool,detectSupportedImageMimeTypeFromFile,discoverAndLoadExtensions,estimateTokens,findCutPoint,findTurnStartIndex,formatDimensionNote,formatSkillsForPrompt,generateBranchSummary,generateDiffString,generateSummary,generateSummaryWithUsage,generateUnifiedPatch,getLastAssistantUsage,getLatestCompactionEntry,isBashToolResult,isEditToolResult,isFindToolResult,isGrepToolResult,isLsToolResult,isPowerShellToolResult,isReadToolResult,isToolCallEventType,isWriteToolResult,loadProjectContextFiles,loadSkills,loadSkillsFromDir,main,migrateSessionEntries,parseArgs,parseFrontmatter,parseSessionEntries,parseSkillBlock,prepareBranchEntries,renderDiff,resizeImage,resolveCliModel,resolveModelScopeWithDiagnostics,runPrintMode,runRpcMode,serializeConversation,sessionEntryToContextMessages,setupCli,shouldCompact,stdioRpcTransport,stripFrontmatter,withFileMutationQueue,wrapRegisteredTool,wrapRegisteredTools}from"./chunks/chunk-C4L65EFW.js";import{DEFAULT_MAX_BYTES,DEFAULT_MAX_LINES,formatReadLineRange,formatSize,truncateHead,truncateLine,truncateTail,truncateToVisualLines}from"./chunks/chunk-DYTENXHX.js";import{ArminComponent}from"./chunks/chunk-FLHKNMLQ.js";import{Theme,getLanguageFromPath,getMarkdownTheme,getSelectListTheme,getSettingsListTheme,highlightCode,initTheme,keyHint,keyText,rawKeyHint}from"./chunks/chunk-LT2C56HV.js";import{ProjectTrustStore,hasTrustRequiringProjectResources,loadMcpConfig}from"./chunks/chunk-6Z2347ML.js";import{readStoredCredential}from"./chunks/chunk-MF3VB62R.js";import{getPowerShellConfig,getShellConfig}from"./chunks/chunk-URBBMV3M.js";import"./chunks/chunk-6QGV3IWD.js";import{CONFIG_DIR_NAME,VERSION,getAgentDir,getDocsPath,getExamplesPath,getPackageDir,getReadmePath}from"./chunks/chunk-LHRPMXVI.js";import"./chunks/chunk-USJZMAIR.js";import"./chunks/chunk-5AGIVGSV.js";import"./chunks/chunk-UKVNB6C4.js";import"./chunks/chunk-TMTOQ7H7.js";import"./chunks/chunk-7DDKXS2Q.js";import"./chunks/chunk-3V45WARH.js";import"./chunks/chunk-WCGU75WO.js";import"./chunks/chunk-LPXNMA2W.js";import"./chunks/chunk-JXWJOIH4.js";export{AgentSession,AgentSessionRuntime,ArminComponent,AssistantMessageComponent,BashExecutionComponent,BorderedLoader,BranchSummaryMessageComponent,CONFIG_DIR_NAME,CURRENT_SESSION_VERSION,CompactionSummaryMessageComponent,CredentialSynchronizationError,CustomEditor,CustomMessageComponent,DEFAULT_COMPACTION_SETTINGS,DEFAULT_MAX_BYTES,DEFAULT_MAX_LINES,DefaultPackageManager,DefaultResourceLoader,DynamicBorder,ExtensionEditorComponent,ExtensionInputComponent,ExtensionRunner,ExtensionSelectorComponent,FileModelsStore,FooterComponent,InteractiveMode,LoginDialogComponent,MCP_CONNECTION_EVENT,ModelRegistry,ModelRuntime,ModelSelectorComponent,OAuthSelectorComponent,ProjectTrustStore,RpcClient,SessionManager,SessionSelectorComponent,SettingsManager,SettingsSelectorComponent,ShowImagesSelectorComponent,SkillInvocationMessageComponent,Theme,ThemeSelectorComponent,ThinkingSelectorComponent,ToolExecutionComponent,TreeSelectorComponent,UserMessageComponent,UserMessageSelectorComponent,VERSION,VIRTUAL_MODEL_STATE_ENTRY,applyHttpProxySettings,buildContextEntries,buildSessionContext,buildSessionProjection,calculateContextTokens,collectEntriesForBranchSummary,compact,configureHttpDispatcher,convertToLlm,convertToPng,copyToClipboard,createAgentSession,createAgentSessionFromServices,createAgentSessionRuntime,createAgentSessionServices,createBashTool,createBashToolDefinition,createCodemodeExtension,createCodingTools,createEditTool,createEditToolDefinition,createEventBus,createExtensionRuntime,createFindTool,createFindToolDefinition,createGrepTool,createGrepToolDefinition,createLocalBashOperations,createLocalPowerShellOperations,createLsTool,createLsToolDefinition,createMcpExtension,createPowerShellTool,createPowerShellToolDefinition,createReadOnlyTools,createReadTool,createReadToolDefinition,createSyntheticSourceInfo,createToolSearchExtension,createWriteTool,createWriteToolDefinition,defaultModelPerProvider,defineTool,detectSupportedImageMimeTypeFromFile,discoverAndLoadExtensions,estimateTokens,findCutPoint,findTurnStartIndex,formatDimensionNote,formatReadLineRange,formatSize,formatSkillsForPrompt,generateBranchSummary,generateDiffString,generateSummary,generateSummaryWithUsage,generateUnifiedPatch,getAgentDir,getDocsPath,getExamplesPath,getLanguageFromPath,getLastAssistantUsage,getLatestCompactionEntry,getMarkdownTheme,getPackageDir,getPowerShellConfig,getReadmePath,getSelectListTheme,getSettingsListTheme,getShellConfig,hasTrustRequiringProjectResources,highlightCode,initTheme,isBashToolResult,isEditToolResult,isFindToolResult,isGrepToolResult,isLsToolResult,isPowerShellToolResult,isReadToolResult,isToolCallEventType,isWriteToolResult,keyHint,keyText,loadMcpConfig,loadProjectContextFiles,loadSkills,loadSkillsFromDir,main,migrateSessionEntries,parseArgs,parseFrontmatter,parseSessionEntries,parseSkillBlock,prepareBranchEntries,rawKeyHint,readStoredCredential,renderDiff,resizeImage,resolveCliModel,resolveModelScopeWithDiagnostics,runPrintMode,runRpcMode,serializeConversation,sessionEntryToContextMessages,setupCli,shouldCompact,stdioRpcTransport,stripFrontmatter,truncateHead,truncateLine,truncateTail,truncateToVisualLines,withFileMutationQueue,wrapRegisteredTool,wrapRegisteredTools};
|
package/dist/bundle/rpc-entry.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire as __piCreateRequire } from "node:module"; const require = __piCreateRequire(import.meta.url);
|
|
3
|
-
import{configureHttpDispatcher,main,nameProcess}from"./chunks/chunk-
|
|
3
|
+
import{configureHttpDispatcher,main,nameProcess}from"./chunks/chunk-C4L65EFW.js";import"./chunks/chunk-DYTENXHX.js";import"./chunks/chunk-FLHKNMLQ.js";import"./chunks/chunk-LT2C56HV.js";import"./chunks/chunk-6Z2347ML.js";import"./chunks/chunk-MF3VB62R.js";import"./chunks/chunk-URBBMV3M.js";import"./chunks/chunk-6QGV3IWD.js";import{APP_NAME}from"./chunks/chunk-LHRPMXVI.js";import"./chunks/chunk-USJZMAIR.js";import"./chunks/chunk-5AGIVGSV.js";import"./chunks/chunk-UKVNB6C4.js";import"./chunks/chunk-TMTOQ7H7.js";import"./chunks/chunk-7DDKXS2Q.js";import"./chunks/chunk-3V45WARH.js";import"./chunks/chunk-WCGU75WO.js";import"./chunks/chunk-LPXNMA2W.js";import"./chunks/chunk-JXWJOIH4.js";nameProcess(`${APP_NAME}-rpc`);process.env.PI_CODING_AGENT="true";process.env.AI_AGENT="pi";process.emitWarning=(()=>{});configureHttpDispatcher();main(["--mode","rpc",...process.argv.slice(2)]);
|
|
@@ -110,12 +110,12 @@ See [Describe model input and caching](models.md#describe-model-input-and-cachin
|
|
|
110
110
|
|
|
111
111
|
| Field | Type | Default | Description |
|
|
112
112
|
|---|---|---|---|
|
|
113
|
-
| `supportsStore` | boolean | | Whether the provider supports the store field. Default:
|
|
114
|
-
| `supportsDeveloperRole` | boolean | | Whether the provider supports the developer role instead of system. Default:
|
|
115
|
-
| `supportsReasoningEffort` | boolean | | Whether the provider supports reasoning_effort. Default: auto-detected from URL. |
|
|
116
|
-
| `supportsUsageInStreaming` | boolean | `true` | Whether the provider supports stream_options.include_usage for token usage in streaming responses. |
|
|
113
|
+
| `supportsStore` | boolean | | Whether the provider supports the store field. Default: true for api.openai.com and Azure OpenAI, false for other endpoints. |
|
|
114
|
+
| `supportsDeveloperRole` | boolean | | Whether the provider supports the developer role instead of system for reasoning models. Default: true for api.openai.com, Azure OpenAI, and Xiaomi MiMo, false for other endpoints. When an endpoint rejects the developer role, Pi sends the request again with system and keeps using system for that model until it restarts. |
|
|
115
|
+
| `supportsReasoningEffort` | boolean | | Whether the provider supports reasoning_effort. Default: auto-detected from URL. When an endpoint rejects reasoning_effort as an unknown field, Pi sends the request again without it. |
|
|
116
|
+
| `supportsUsageInStreaming` | boolean | `true` | Whether the provider supports stream_options.include_usage for token usage in streaming responses. When an endpoint rejects stream_options as an unknown field, Pi sends the request again without it. |
|
|
117
117
|
| `supportsFinishReason` | boolean | `true` | Whether streamed responses include finish_reason. When false, pi infers stop or toolUse when the stream ends. |
|
|
118
|
-
| `maxTokensField` | `"max_completion_tokens" \| "max_tokens"` | | Which field to use for max tokens. Default:
|
|
118
|
+
| `maxTokensField` | `"max_completion_tokens" \| "max_tokens"` | | Which field to use for max tokens. Default: max_completion_tokens for api.openai.com, Azure OpenAI, and Xiaomi MiMo, max_tokens for other endpoints. When an endpoint rejects the field, Pi sends the request again with the other one. |
|
|
119
119
|
| `requiresToolResultName` | boolean | | Whether tool results require the name field. Default: auto-detected from URL. |
|
|
120
120
|
| `requiresAssistantAfterToolResult` | boolean | | Whether a user message after tool results requires an assistant message in between. Default: auto-detected from URL. |
|
|
121
121
|
| `requiresThinkingAsText` | boolean | | Whether thinking blocks must be converted to text blocks with <thinking> delimiters. Default: auto-detected from URL. |
|
package/docs/models.md
CHANGED
|
@@ -78,6 +78,28 @@ To route a built-in provider through a proxy, set only its `baseUrl`. Its models
|
|
|
78
78
|
|
|
79
79
|
[Models Configuration](models-configuration.md) lists every field.
|
|
80
80
|
|
|
81
|
+
### Third-party OpenAI-compatible endpoints
|
|
82
|
+
|
|
83
|
+
With `"api": "openai-completions"`, Pi sends OpenAI's newer request shape only to endpoints documented to take it: `api.openai.com`, Azure OpenAI, and Xiaomi MiMo. There, a reasoning model's system prompt goes as a `developer` message and the output limit as `max_completion_tokens`, with `store: false` on OpenAI and Azure. Every other endpoint, including a relay or gateway, gets the shape all OpenAI-compatible servers accept: a `system` message, `max_tokens`, and no `store`.
|
|
84
|
+
|
|
85
|
+
If an endpoint still rejects part of a request, for example with `unknown role developer` or `Unrecognized request argument supplied: max_completion_tokens`, Pi sends the request again with that part changed before any reply appears, and keeps the change for that model until Pi restarts. This covers the `developer` role, the max tokens field, `reasoning_effort`, `stream_options`, `store`, and the prompt cache fields, each changed at most once per request. A rejection of a value, such as a `max_tokens` above the model's limit, is shown as it is. Requests to `api.openai.com` are never changed this way.
|
|
86
|
+
|
|
87
|
+
To choose yourself, set `compat` on the provider or a model. A relay in front of OpenAI's reasoning models can take OpenAI's shape:
|
|
88
|
+
|
|
89
|
+
```json
|
|
90
|
+
{
|
|
91
|
+
"providers": {
|
|
92
|
+
"my-relay": {
|
|
93
|
+
"baseUrl": "https://relay.example.com/v1",
|
|
94
|
+
"api": "openai-completions",
|
|
95
|
+
"apiKey": "$MY_RELAY_KEY",
|
|
96
|
+
"compat": { "supportsDeveloperRole": true, "maxTokensField": "max_completion_tokens" },
|
|
97
|
+
"models": [{ "id": "gpt-5.5", "reasoning": true }]
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
```
|
|
102
|
+
|
|
81
103
|
### Describe model input and caching
|
|
82
104
|
|
|
83
105
|
Use `inputLimits.images.resize` to control how Pi encodes new image attachments, `read` results, and tool-result images before storing them in conversation history:
|
|
@@ -218,4 +240,4 @@ Complete the provider's headless authentication flow when available. Some provid
|
|
|
218
240
|
|
|
219
241
|
### A compatible endpoint rejects requests
|
|
220
242
|
|
|
221
|
-
Check its API type and compatibility settings in `models.json`. The upstream server must support the corresponding request fields and behavior.
|
|
243
|
+
Check its API type and compatibility settings in `models.json`. The upstream server must support the corresponding request fields and behavior. Pi already resends a request whose `developer` role or optional field an OpenAI-compatible endpoint rejects; see [Third-party OpenAI-compatible endpoints](#third-party-openai-compatible-endpoints). For any other field the error names, set the matching `compat` field from [Models Configuration](models-configuration.md#openai-completions).
|
package/judge/dist/auth.js
CHANGED
|
@@ -21,7 +21,12 @@ var init_cloud_code = __esm({
|
|
|
21
21
|
import { constants } from "node:os";
|
|
22
22
|
import { join as join3 } from "node:path";
|
|
23
23
|
import { createInterface } from "node:readline";
|
|
24
|
-
import {
|
|
24
|
+
import {
|
|
25
|
+
defaultModelPerProvider,
|
|
26
|
+
FileModelsStore,
|
|
27
|
+
ModelRuntime,
|
|
28
|
+
SettingsManager
|
|
29
|
+
} from "../../dist/bundle/index.js";
|
|
25
30
|
|
|
26
31
|
// packages/kyrn-judge/src/config.ts
|
|
27
32
|
import { readFileSync } from "node:fs";
|
|
@@ -57,8 +62,9 @@ var DEFAULT_CONFIG = {
|
|
|
57
62
|
"capability.disclosure": "off",
|
|
58
63
|
// Its rules deliver what matters; in single-prompt runs a "next_turn" verdict never reached anyone.
|
|
59
64
|
"notify.routing": "shadow",
|
|
60
|
-
//
|
|
61
|
-
|
|
65
|
+
// input.interjection follows the default: mu, not the key that sent it, decides when a message sent mid-run
|
|
66
|
+
// reaches the work. A message waits for its verdict for at most 1.5 s (`features.interjection.waitMs`), and goes
|
|
67
|
+
// as sent without one. A built-in "active" here would keep it acting under a default of shadow.
|
|
62
68
|
// Its steers were mostly wrong where it flagged anything at all, so it only records until it is reworked.
|
|
63
69
|
"turn.drift": "shadow"
|
|
64
70
|
},
|
|
@@ -740,7 +746,8 @@ var ANTIGRAVITY_ENDPOINTS = [
|
|
|
740
746
|
"https://autopush-cloudcode-pa.sandbox.googleapis.com",
|
|
741
747
|
CLOUD_CODE_ENDPOINT
|
|
742
748
|
];
|
|
743
|
-
var
|
|
749
|
+
var ANTIGRAVITY_CLI_VERSION = "1.4.0";
|
|
750
|
+
var antigravityUserAgent = (env = (name) => process.env[name]) => `antigravity/cli/${env("MU_ANTIGRAVITY_VERSION") || env("PI_AI_ANTIGRAVITY_VERSION") || ANTIGRAVITY_CLI_VERSION}`;
|
|
744
751
|
|
|
745
752
|
// packages/kyrn-judge/src/google-login/oauth.ts
|
|
746
753
|
import { createServer } from "node:http";
|
|
@@ -1130,7 +1137,7 @@ var FLASH_LEVELS = {
|
|
|
1130
1137
|
max: null
|
|
1131
1138
|
};
|
|
1132
1139
|
var PRO_LEVELS = { ...FLASH_LEVELS, minimal: null };
|
|
1133
|
-
var levelsOf = (id) => /^gemini-3(?:\.\d+)?-pro/.test(id) ? PRO_LEVELS : /^gemini-3(?:\.\d+)?-flash/.test(id) ? FLASH_LEVELS : void 0;
|
|
1140
|
+
var levelsOf = (id) => /^gemini-3(?:\.\d+)?-pro|^gemini-4/.test(id) ? PRO_LEVELS : /^gemini-3(?:\.\d+)?-flash/.test(id) ? FLASH_LEVELS : void 0;
|
|
1134
1141
|
var OPUS = { input: 5, output: 25, cacheRead: 0.5, cacheWrite: 6.25 };
|
|
1135
1142
|
var SONNET = { input: 3, output: 15, cacheRead: 0.3, cacheWrite: 3.75 };
|
|
1136
1143
|
var GEMINI_PRO = { input: 2, output: 12, cacheRead: 0.2, cacheWrite: 2.375 };
|
|
@@ -1182,7 +1189,8 @@ function antigravityModelsFrom(body) {
|
|
|
1182
1189
|
const models = /* @__PURE__ */ new Map();
|
|
1183
1190
|
for (const [raw, info] of entries) {
|
|
1184
1191
|
const id = raw.trim();
|
|
1185
|
-
if (!SERVED.test(id) || /image/.test(id) || models.has(id))
|
|
1192
|
+
if (!SERVED.test(id) || /image/.test(id) || /-disabled$/.test(id) || info.disabled === true || models.has(id))
|
|
1193
|
+
continue;
|
|
1186
1194
|
const known = baseline.get(id);
|
|
1187
1195
|
if (known) {
|
|
1188
1196
|
models.set(id, known);
|
|
@@ -1198,7 +1206,7 @@ function antigravityModelsFrom(body) {
|
|
|
1198
1206
|
reasoning,
|
|
1199
1207
|
input: images ? TEXT_AND_IMAGE : ["text"],
|
|
1200
1208
|
cost: FREE,
|
|
1201
|
-
contextWindow: family === "gemini" ? 1048576 : family === "claude" ? 2e5 : 131072,
|
|
1209
|
+
contextWindow: positive(info.maxTokens) ?? (family === "gemini" ? 1048576 : family === "claude" ? 2e5 : 131072),
|
|
1202
1210
|
maxTokens: positive(info.maxOutputTokens) ?? (family === "gemini" ? 65535 : family === "claude" ? 64e3 : 32768)
|
|
1203
1211
|
})
|
|
1204
1212
|
);
|
|
@@ -1284,7 +1292,8 @@ var LEGACY_PROVIDERS = ["openai-codex", "anthropic"];
|
|
|
1284
1292
|
var LISTED_BY_ACCOUNT = /* @__PURE__ */ new Set(["google-antigravity"]);
|
|
1285
1293
|
var MODELS_READ_MS = 2e4;
|
|
1286
1294
|
var BROWSER_METHOD = "browser";
|
|
1287
|
-
var USAGE = "usage: mu auth status | mu auth login <provider> | mu auth logout <provider>";
|
|
1295
|
+
var USAGE = "usage: mu auth status | mu auth login <provider> [--paste] | mu auth logout <provider>";
|
|
1296
|
+
var ERROR_CODES = ["port_in_use", "login_taken_over"];
|
|
1288
1297
|
var AUTH_COMMANDS = ["status", "login", "logout"];
|
|
1289
1298
|
function modelsOf(runtime, provider, preferred) {
|
|
1290
1299
|
const models = runtime.getModels(provider).map((model) => ({ id: model.id, name: model.name || model.id }));
|
|
@@ -1300,16 +1309,42 @@ function shown(prompt) {
|
|
|
1300
1309
|
options: prompt.type === "select" ? prompt.options : void 0
|
|
1301
1310
|
};
|
|
1302
1311
|
}
|
|
1312
|
+
function errorLine(error) {
|
|
1313
|
+
const line = {
|
|
1314
|
+
type: "error",
|
|
1315
|
+
message: error instanceof Error ? error.message : String(error)
|
|
1316
|
+
};
|
|
1317
|
+
if (!(error instanceof Error)) return line;
|
|
1318
|
+
const { code, port, holder } = error;
|
|
1319
|
+
if (typeof code !== "string" || !ERROR_CODES.includes(code)) return line;
|
|
1320
|
+
line.code = code;
|
|
1321
|
+
if (code !== "port_in_use") return line;
|
|
1322
|
+
if (typeof port === "number") line.port = port;
|
|
1323
|
+
if (holder && typeof holder === "object") {
|
|
1324
|
+
const { pid, command, pi } = holder;
|
|
1325
|
+
line.holder = {
|
|
1326
|
+
...typeof pid === "number" ? { pid } : {},
|
|
1327
|
+
...typeof command === "string" ? { command } : {},
|
|
1328
|
+
...pi === true ? { pi } : {}
|
|
1329
|
+
};
|
|
1330
|
+
}
|
|
1331
|
+
return line;
|
|
1332
|
+
}
|
|
1303
1333
|
async function runAuth(argv, options) {
|
|
1304
1334
|
const { runtime, preferred, io } = options;
|
|
1305
1335
|
try {
|
|
1306
|
-
const
|
|
1336
|
+
const flags = argv.filter((arg) => arg.startsWith("--"));
|
|
1337
|
+
const [mode, provider, ...extra] = argv.filter((arg) => !arg.startsWith("--"));
|
|
1307
1338
|
if (!AUTH_COMMANDS.includes(mode ?? "")) throw new Error(USAGE);
|
|
1308
|
-
|
|
1339
|
+
const paste = flags.includes("--paste");
|
|
1340
|
+
if (extra.length > 0 || flags.some((flag) => flag !== "--paste") || paste && mode !== "login") {
|
|
1341
|
+
throw new Error(USAGE);
|
|
1342
|
+
}
|
|
1343
|
+
for (const extra2 of options.extra) runtime.registerNativeProvider(extra2);
|
|
1309
1344
|
if (options.extra.length > 0) {
|
|
1310
|
-
await runtime.refresh({ allowNetwork: false, providers: options.extra.map((
|
|
1345
|
+
await runtime.refresh({ allowNetwork: false, providers: options.extra.map((extra2) => extra2.id) });
|
|
1311
1346
|
}
|
|
1312
|
-
const offered = [...BUILT_IN_PROVIDERS, ...options.extra.map((
|
|
1347
|
+
const offered = [...BUILT_IN_PROVIDERS, ...options.extra.map((extra2) => extra2.id)];
|
|
1313
1348
|
const known = [...offered, ...LEGACY_PROVIDERS];
|
|
1314
1349
|
const status = async () => ({
|
|
1315
1350
|
type: "status",
|
|
@@ -1329,19 +1364,24 @@ async function runAuth(argv, options) {
|
|
|
1329
1364
|
}
|
|
1330
1365
|
if (mode === "logout") {
|
|
1331
1366
|
const stored = (await runtime.listCredentials()).find((credential) => credential.providerId === provider);
|
|
1332
|
-
if (stored?.type === "oauth")
|
|
1367
|
+
if (stored?.type === "oauth") {
|
|
1368
|
+
await runtime.logout(provider);
|
|
1369
|
+
if (LISTED_BY_ACCOUNT.has(provider)) await options.forgetModels?.(provider);
|
|
1370
|
+
}
|
|
1333
1371
|
io.say(await status());
|
|
1334
1372
|
return 0;
|
|
1335
1373
|
}
|
|
1336
|
-
await signIn(provider, options);
|
|
1374
|
+
await signIn(provider, paste ? { ...options, login: { ...options.login, pasteOnly: true } } : options);
|
|
1337
1375
|
return 0;
|
|
1338
1376
|
} catch (error) {
|
|
1339
|
-
io.say(
|
|
1377
|
+
io.say(errorLine(error));
|
|
1340
1378
|
return 1;
|
|
1341
1379
|
}
|
|
1342
1380
|
}
|
|
1343
|
-
async function signIn(provider, { runtime, preferred, io, modelsReadMs, login: login2 }) {
|
|
1381
|
+
async function signIn(provider, { runtime, preferred, io, modelsReadMs, login: login2, signal: ending2 }) {
|
|
1344
1382
|
const controller = new AbortController();
|
|
1383
|
+
ending2?.addEventListener("abort", () => controller.abort(), { once: true });
|
|
1384
|
+
if (ending2?.aborted) controller.abort();
|
|
1345
1385
|
let pending;
|
|
1346
1386
|
io.listen(
|
|
1347
1387
|
(line) => {
|
|
@@ -1402,6 +1442,7 @@ var authPath = join3(agentDir, "auth.json");
|
|
|
1402
1442
|
var modelsStorePath = join3(agentDir, "models-store.json");
|
|
1403
1443
|
var say = (message) => process.stdout.write(`${JSON.stringify(message)}
|
|
1404
1444
|
`);
|
|
1445
|
+
var ending = new AbortController();
|
|
1405
1446
|
function googleProviders() {
|
|
1406
1447
|
try {
|
|
1407
1448
|
const loaded = loadConfig({ dir: agentDir, env: process.env });
|
|
@@ -1421,16 +1462,18 @@ function googleProviders() {
|
|
|
1421
1462
|
}
|
|
1422
1463
|
}
|
|
1423
1464
|
async function main() {
|
|
1465
|
+
const modelsStore = new FileModelsStore(modelsStorePath);
|
|
1424
1466
|
const runtime = await ModelRuntime.create({
|
|
1425
1467
|
authPath,
|
|
1426
1468
|
modelsPath: join3(agentDir, "models.json"),
|
|
1427
|
-
|
|
1469
|
+
modelsStore,
|
|
1428
1470
|
refreshOnCreate: false
|
|
1429
1471
|
});
|
|
1430
1472
|
return runAuth(process.argv.slice(2), {
|
|
1431
1473
|
runtime,
|
|
1432
1474
|
preferred: defaultModelPerProvider,
|
|
1433
1475
|
extra: googleProviders(),
|
|
1476
|
+
forgetModels: (providerId) => modelsStore.delete(providerId),
|
|
1434
1477
|
login: {
|
|
1435
1478
|
agentName: "mu",
|
|
1436
1479
|
// The id pi keeps in settings.json for this installation: the same one a /login in the terminal sends.
|
|
@@ -1443,7 +1486,8 @@ async function main() {
|
|
|
1443
1486
|
lines.on("line", line);
|
|
1444
1487
|
lines.on("close", end);
|
|
1445
1488
|
}
|
|
1446
|
-
}
|
|
1489
|
+
},
|
|
1490
|
+
signal: ending.signal
|
|
1447
1491
|
});
|
|
1448
1492
|
}
|
|
1449
1493
|
var leaving = false;
|
|
@@ -1453,7 +1497,10 @@ var leave = (code) => {
|
|
|
1453
1497
|
void exitWhenUnlocked(code, [authPath, modelsStorePath], (exitCode) => process.exit(exitCode));
|
|
1454
1498
|
};
|
|
1455
1499
|
for (const signal of ["SIGTERM", "SIGINT", "SIGHUP"])
|
|
1456
|
-
process.on(signal, () =>
|
|
1500
|
+
process.on(signal, () => {
|
|
1501
|
+
ending.abort();
|
|
1502
|
+
leave(128 + constants.signals[signal]);
|
|
1503
|
+
});
|
|
1457
1504
|
main().then(leave, (error) => {
|
|
1458
1505
|
say({ type: "error", message: error instanceof Error ? error.message : String(error) });
|
|
1459
1506
|
leave(1);
|