zidane 6.2.14 → 6.2.18
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-DxYjSCQW.js → acp-CxE1-kHy.js} +2 -2
- package/dist/{acp-DxYjSCQW.js.map → acp-CxE1-kHy.js.map} +1 -1
- package/dist/acp-cli.js +4 -4
- package/dist/acp.d.ts +1 -1
- package/dist/acp.js +1 -1
- package/dist/{agent-DoEx_WD3.js → agent-DBfHPAgz.js} +81 -4
- package/dist/agent-DBfHPAgz.js.map +1 -0
- package/dist/agent.d.ts +1 -1
- package/dist/agent.js +1 -1
- package/dist/{anthropic-BYsc6qWj.js → anthropic-uKvj1yle.js} +76 -9
- package/dist/anthropic-uKvj1yle.js.map +1 -0
- package/dist/{auth-Bb479DFB.js → auth-CpdQebUy.js} +2 -2
- package/dist/{auth-Bb479DFB.js.map → auth-CpdQebUy.js.map} +1 -1
- package/dist/chat/pure.d.ts +3 -3
- package/dist/chat.d.ts +12 -6
- package/dist/chat.d.ts.map +1 -1
- package/dist/chat.js +3 -3
- package/dist/contexts/daytona.d.ts +1 -1
- package/dist/contexts/e2b.d.ts +1 -1
- package/dist/eval.d.ts +1 -1
- package/dist/extensions.d.ts +1 -1
- package/dist/extensions.js +1 -1
- package/dist/headless.d.ts +1 -1
- package/dist/headless.js +1 -1
- package/dist/{index-l0wehkWU.d.ts → index-CC0JD-0H.d.ts} +188 -138
- package/dist/index-CC0JD-0H.d.ts.map +1 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +4 -4
- package/dist/inline-autocomplete-BAwBcZtD.js.map +1 -1
- package/dist/{login-Clf-R27F.js → login-DreurRAq.js} +2 -2
- package/dist/{login-Clf-R27F.js.map → login-DreurRAq.js.map} +1 -1
- package/dist/{mcp-BCaN_Gyg.js → mcp-H6bqyM94.js} +24 -4
- package/dist/mcp-H6bqyM94.js.map +1 -0
- package/dist/mcp.d.ts +2 -2
- package/dist/mcp.js +2 -2
- package/dist/output/stream-json.d.ts +1 -1
- package/dist/output/terminal.d.ts +1 -1
- package/dist/presets.d.ts +1 -1
- package/dist/presets.js +1 -1
- package/dist/providers/anthropic.d.ts +1 -1
- package/dist/providers/anthropic.js +1 -1
- package/dist/providers/arcee.d.ts +1 -1
- package/dist/providers/baseten.d.ts +1 -1
- package/dist/providers/cerebras.d.ts +1 -1
- package/dist/providers/local.d.ts +1 -1
- package/dist/providers/openai-compat.d.ts +1 -1
- package/dist/providers/openai.d.ts +1 -1
- package/dist/providers/openrouter.d.ts +1 -1
- package/dist/providers/xai.d.ts +1 -1
- package/dist/providers.d.ts +1 -1
- package/dist/providers.js +1 -1
- package/dist/restate.d.ts +1 -1
- package/dist/session/sqlite.d.ts +1 -1
- package/dist/session.d.ts +1 -1
- package/dist/skills.d.ts +1 -1
- package/dist/{tool-formatters-DdgS-xE2.d.ts → tool-formatters-BD3oohVq.d.ts} +2 -2
- package/dist/{tool-formatters-DdgS-xE2.d.ts.map → tool-formatters-BD3oohVq.d.ts.map} +1 -1
- package/dist/tools/fetch-url.d.ts +1 -1
- package/dist/tools/web-search.d.ts +1 -1
- package/dist/tools.d.ts +1 -1
- package/dist/tools.js +1 -1
- package/dist/{transcript-anchors-DE6D0dNo.js → transcript-anchors-DUusSVpZ.js} +18 -9
- package/dist/transcript-anchors-DUusSVpZ.js.map +1 -0
- package/dist/{transcript-anchors-DKjXpQ0h.d.ts → transcript-anchors-DZYw3L1u.d.ts} +2 -2
- package/dist/{transcript-anchors-DKjXpQ0h.d.ts.map → transcript-anchors-DZYw3L1u.d.ts.map} +1 -1
- package/dist/tui.d.ts +19 -4
- package/dist/tui.d.ts.map +1 -1
- package/dist/tui.js +269 -39
- package/dist/tui.js.map +1 -1
- package/dist/{turn-operations-sE-Sli9H.d.ts → turn-operations-BcrzRAoE.d.ts} +3 -3
- package/dist/{turn-operations-sE-Sli9H.d.ts.map → turn-operations-BcrzRAoE.d.ts.map} +1 -1
- package/dist/types.d.ts +1 -1
- package/package.json +1 -1
- package/dist/agent-DoEx_WD3.js.map +0 -1
- package/dist/anthropic-BYsc6qWj.js.map +0 -1
- package/dist/index-l0wehkWU.d.ts.map +0 -1
- package/dist/mcp-BCaN_Gyg.js.map +0 -1
- package/dist/transcript-anchors-DE6D0dNo.js.map +0 -1
package/dist/tui.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { $ as
|
|
2
|
-
import { $ as composeExtensionPreset, B as ExtensionInstallError, Bt as ensureKeybindingsFile, Et as createModelSearchTool, H as installExtensionFromSpec, Ht as groupBindings, J as createExtensionHud, K as removeInstalledExtension, P as summaryToTurn, St as tailTruncate, Ut as keybindingsPath, Vt as formatBindingForDisplay, Wt as matchesBinding, X as discoverAndBuildExtensionRegistry, Y as registerExtensionHostModules, Yt as resolveExtensionKeybindings, _ as buildPostCompactAttachments, c as applyCompactSummaryCutoff, dn as sanitizeExtensionConfigActionPatch, en as inlineLoadedExtension, et as disposeExtensionRegistry, f as cleanupPersistedSession, g as resolveTasksDir, h as resolvePersistDir, hn as effectiveContextWindow, ht as isSpawnTool, it as createExtensionHostRuntimeBridge, lt as basic_default, m as resolveMcpWarningsDir, mn as OUTPUT_RESERVE_TOKENS, nn as parseExtensionScanPathEnv, on as coerceExtensionConfigInput, q as updateInstalledExtension, rn as scanExtensionDirectories, rt as partitionExtensionCatalog, t as createAgent, tt as filterExtensionRegistry, un as resolveExtensionConfigValue, wt as looksBinary, x as compactConversation, y as selectFilesFromSession, z as createExtensionPromptBridge, zt as KEYBINDING_KEY_COL_WIDTH } from "./agent-
|
|
1
|
+
import { $ as useMcpAuthDispatch, $n as buildBuildSystem, $t as providerKeySetChanged, A as runOAuthLogin, B as refreshMcpToolsCatalog, Ct as SETTINGS_CATEGORIES, D as formatPathForCwd, Dt as SettingsProvider, En as accentColor, Et as SETTINGS_TOGGLES, F as parseJsonTolerant, Gt as ConfigProvider, H as subscribeMcpToolsCache, Hn as useActiveTodos, Ht as DiscoveryProvider, J as parentServerName, Jt as resolveStoragePaths, K as buildVisibleMcpRows, Kt as useConfig, M as buildMcpServers, Mn as TODO_STATUS_GLYPHS, Mt as resolveChipColor, Nt as resolveTheme, O as fetchOAuthRedirect, Ot as clampFps, P as discoverProjectMcps, Q as McpAuthProvider, Qt as filterChainFallbacks, R as loadMcpToolsCache, St as DEFAULT_SETTINGS, T as suggestSafelistEntries, Tt as SETTINGS_INPUTS, Ut as useDiscovery, Vt as createDiscoverySlot, W as useMcpToolToggleMap, Wt as useDiscoveryOptional, Xt as chainPositionOf, Y as createFileMcpCredentialStore, Yt as buildRunModel, Zt as chainsEqual, _ as useSafeModeQueue, _n as chatAutoCompactBehavior, _t as truncateTrailing, a as useSurfaces, ar as compactSummaryEvent, at as PRESENT_PLAN_TOOL, b as getSafelist, br as updateToolEventOutcomes, bt as listProjectFiles, c as useStreamBuffer, cn as useUpdateCheck, cr as eventsFromTurns, d as discoverProjectSkills, dr as loadState, en as restoreChainFallbacks, er as buildPlanSystem, et as useMcpAuthState, fr as marginTopFor, ft as useInteractionsActions, g as useSafeModeActions, gr as sumRunCosts, gt as hintsLength, h as SafeModeProvider, hr as stripSpawnTokensLine, ht as clipHintsToWidth, i as useSelectStyle, in as tryOpenBrowser, it as InteractionsProvider, j as supportsOAuth, k as oauthUsesManualCodePaste, kt as useSettings, l as buildSkillsConfig, lr as lastContextSizeFromTurns, lt as makeRequestInteraction, m as writeSessionExport, mr as serverToolResultSummary, mt as EMPTY_HINTS, n as ThemeProvider, nn as toggleChainEntry, nr as chatReferenceTokensForPrompt, on as bootTick, ot as buildResumedToolResultsTurn, pt as useInteractionsQueue, q as indexOfServerRow, qt as resolveConfig, r as useColors, rn as useCompletion, rr as createChatTurnsReadTool, rt as ASK_USER_TOOL, s as useTheme, sn as buildUpdateHint, sr as deriveSessionTitle, st as createInteractionTools, t as computeTurnAnchors, tr as envSection, tt as getMcpAuthStatus, u as defaultSkillScanPaths, ur as listSessionMeta, ut as pendingInteractionsFromTurns, vn as discoverAgentsMd, vr as toolCallPreview, vt as buildHints, wt as SETTINGS_CHOICES, x as isOnSafelist, xr as usageByModel, xt as useEnabledToggleSet, y as addToSafelist, yr as toolResultText, z as mcpToolsCachePath } from "./transcript-anchors-DUusSVpZ.js";
|
|
2
|
+
import { $ as composeExtensionPreset, B as ExtensionInstallError, Bt as ensureKeybindingsFile, Et as createModelSearchTool, H as installExtensionFromSpec, Ht as groupBindings, J as createExtensionHud, K as removeInstalledExtension, P as summaryToTurn, St as tailTruncate, Ut as keybindingsPath, Vt as formatBindingForDisplay, Wt as matchesBinding, X as discoverAndBuildExtensionRegistry, Y as registerExtensionHostModules, Yt as resolveExtensionKeybindings, _ as buildPostCompactAttachments, c as applyCompactSummaryCutoff, dn as sanitizeExtensionConfigActionPatch, en as inlineLoadedExtension, et as disposeExtensionRegistry, f as cleanupPersistedSession, g as resolveTasksDir, h as resolvePersistDir, hn as effectiveContextWindow, ht as isSpawnTool, it as createExtensionHostRuntimeBridge, lt as basic_default, m as resolveMcpWarningsDir, mn as OUTPUT_RESERVE_TOKENS, nn as parseExtensionScanPathEnv, on as coerceExtensionConfigInput, q as updateInstalledExtension, rn as scanExtensionDirectories, rt as partitionExtensionCatalog, t as createAgent, tt as filterExtensionRegistry, un as resolveExtensionConfigValue, wt as looksBinary, x as compactConversation, y as selectFilesFromSession, z as createExtensionPromptBridge, zt as KEYBINDING_KEY_COL_WIDTH } from "./agent-DBfHPAgz.js";
|
|
3
3
|
import { a as formatDuration, c as previewLine, i as fmtTokens, l as shortId, n as compactPath, o as formatTaskStatus, r as fmtCost, s as formatTaskSummary, t as ageString } from "./format-BF745pLL.js";
|
|
4
4
|
import { n as appendCapped } from "./output-cap-kBUHBlnq.js";
|
|
5
5
|
import { i as killProcessGroup, n as SUPPORTS_PROCESS_GROUPS, r as createProcessContext } from "./contexts-A4ep-iJs.js";
|
|
@@ -7,16 +7,16 @@ import { l as errorMessage } from "./errors-DJUxZg9b.js";
|
|
|
7
7
|
import { M as findGitRoot, j as projectUserPaths } from "./resolve-HtxmBWs9.js";
|
|
8
8
|
import { a as createRingBufferSink, i as createLoggingHooks, l as logFileTimestamp, n as createFileSink, o as fanoutSink, r as createLogger, s as formatLogLine, t as consoleSink } from "./logger-DBX9uYOw.js";
|
|
9
9
|
import { i as sniffImageMediaType } from "./media-sniff-Bn76JxAu.js";
|
|
10
|
+
import { d as McpOAuthProvider, n as connectMcpServers, p as hasAuthorizationHeader } from "./mcp-H6bqyM94.js";
|
|
10
11
|
import { n as flattenTurns, r as formatTokenUsage, t as effectiveInputFromTurn } from "./stats-DAKBEKjc.js";
|
|
11
12
|
import { replaceDynamicSection } from "./prompt.js";
|
|
12
13
|
import { a as getExtensionSessionState, i as demoteStaleRunningStatus, o as loadSession, s as setExtensionSessionState, t as createSession } from "./session-DzrXKLw-.js";
|
|
13
14
|
import { o as withTimeout } from "./timeout-BDetbuN6.js";
|
|
14
|
-
import { n as connectMcpServers, u as McpOAuthProvider } from "./mcp-BCaN_Gyg.js";
|
|
15
15
|
import { a as generateStructuredData, c as shouldAutoGenerateTitle, f as commandBlockToEvent, g as parseCommandInvocation, h as executeCommand, n as patchInlineGhost, p as commandBlocksToContent, r as resolveInlineSuggestion, s as generateSessionTitle, t as createPathAutocompleteProvider } from "./inline-autocomplete-BAwBcZtD.js";
|
|
16
16
|
import { s as resolveCompletionSubmit } from "./completion-core-BRo86R_L.js";
|
|
17
17
|
import { i as installSkillFromSpec, r as SkillInstallError } from "./skills-DKWqoaYH.js";
|
|
18
|
-
import { i as ZIDANE_EXTENSION_SKILL_NAME, l as withZidaneExtensionSkill, o as extensionDirForCwd, r as EXTENSION_EDIT_METADATA_KEY, s as extensionScaffold, t as loginMcpServer } from "./login-
|
|
19
|
-
import { C as restoreModelOptions, S as piIdOf, _ as modelOptionsFor, m as getContextWindow, p as enabledModelOptions, s as setProviderCredential, t as detectAuth, v as modelSupportsReasoning } from "./auth-
|
|
18
|
+
import { i as ZIDANE_EXTENSION_SKILL_NAME, l as withZidaneExtensionSkill, o as extensionDirForCwd, r as EXTENSION_EDIT_METADATA_KEY, s as extensionScaffold, t as loginMcpServer } from "./login-DreurRAq.js";
|
|
19
|
+
import { C as restoreModelOptions, S as piIdOf, _ as modelOptionsFor, m as getContextWindow, p as enabledModelOptions, s as setProviderCredential, t as detectAuth, v as modelSupportsReasoning } from "./auth-CpdQebUy.js";
|
|
20
20
|
import { createDockerContext } from "./contexts/docker.js";
|
|
21
21
|
import { createTuiStore } from "./session/sqlite.js";
|
|
22
22
|
import { $ as extractEditPayload, B as isVisible, C as chunkMarkdownForRender, E as stripHtmlCommentsOutsideCode, F as BASH_CALL_ID_PREFIX, G as streamEventSearchText, H as promptHistoryFromEvents, I as EDIT_TOOL_NAMES, J as buildContextualDiff, K as turnSelectionOwnership, L as isEditErrorResult, N as blendHsl, O as createSkillsCompletionProvider, P as buildLinearRamp, R as isTurnHighlighted, T as splitMarkdownCodeBlocks, U as selectableTurnIds, V as isVisibleDuringSearch, W as selectionAfterTurnRemoval, X as clipDiffForRender, Y as buildUnifiedDiff, _ as turnContextSize, a as TOOL_DISPLAY, at as buildEditOutcomesAnnotation, b as filterModelCatalog, ct as parseEditOutcomesFromResult, d as finalizeStreamingMarkdown, dt as stripEditOutcomesAnnotation, et as filetypeFromPath, f as finalizeStreamingMarkdownForOwner, ft as summarizeOutcomes, g as revealEarlierTranscriptEvents, h as replaceTranscriptTurnEvents, ht as createChatsCompletionProvider, i as turnAsText, j as createFilesCompletionProvider, k as uniqueSkillNamesFromReferences, lt as resolveApprovalForPayload, n as deleteTurnSafely, o as displayNameFor, p as hiddenEarlierTranscriptCount, r as truncateTurnsAt, rt as summarizeEditPayload, s as formatToolCall, st as mergeApprovalAndBodyOutcomes, tt as previewEditPayload, u as capTranscriptEvents, ut as rewriteMultiEditHeader, v as splitPromptSegments, w as normalizeMarkdownCodeFences, y as buildModelCatalog, z as isUserBashEvent } from "./turn-operations-CokV32wf.js";
|
|
@@ -153,7 +153,7 @@ function upsertMcpServer(filePath, entry) {
|
|
|
153
153
|
action: "added"
|
|
154
154
|
};
|
|
155
155
|
}
|
|
156
|
-
const raw =
|
|
156
|
+
const raw = parseJsonTolerant(readFileSync(filePath, "utf8"));
|
|
157
157
|
if (Array.isArray(raw)) {
|
|
158
158
|
const idx = raw.findIndex((e) => isRecord(e) && e.name === entry.name);
|
|
159
159
|
const next = [...raw];
|
|
@@ -196,6 +196,41 @@ function upsertMcpServer(filePath, entry) {
|
|
|
196
196
|
}
|
|
197
197
|
throw new Error(`${filePath} is not a recognized mcps.json shape (array, map, or {"mcpServers": …}).`);
|
|
198
198
|
}
|
|
199
|
+
/**
|
|
200
|
+
* Remove the entry named `name` from the mcps config at `filePath`,
|
|
201
|
+
* preserving the file's shape and everything else in it — the removal
|
|
202
|
+
* counterpart of {@link upsertMcpServer}. Throws when the file is
|
|
203
|
+
* missing, malformed, an unrecognized shape, or has no entry of that
|
|
204
|
+
* name (the caller shows the message on the settings op line; silently
|
|
205
|
+
* "succeeding" on a no-op would lie about what happened).
|
|
206
|
+
*/
|
|
207
|
+
function removeMcpServer(filePath, name) {
|
|
208
|
+
if (!existsSync(filePath)) throw new Error(`${filePath} does not exist.`);
|
|
209
|
+
const raw = parseJsonTolerant(readFileSync(filePath, "utf8"));
|
|
210
|
+
if (Array.isArray(raw)) {
|
|
211
|
+
const next = raw.filter((e) => !(isRecord(e) && e.name === name));
|
|
212
|
+
if (next.length === raw.length) throw new Error(`no entry named "${name}" in ${filePath}.`);
|
|
213
|
+
writeFileSync(filePath, `${JSON.stringify(next, null, 2)}\n`);
|
|
214
|
+
return { path: filePath };
|
|
215
|
+
}
|
|
216
|
+
if (isRecord(raw)) {
|
|
217
|
+
if (isRecord(raw.mcpServers)) {
|
|
218
|
+
if (!(name in raw.mcpServers)) throw new Error(`no entry named "${name}" in ${filePath}.`);
|
|
219
|
+
const { [name]: _dropped, ...rest } = raw.mcpServers;
|
|
220
|
+
const next = {
|
|
221
|
+
...raw,
|
|
222
|
+
mcpServers: rest
|
|
223
|
+
};
|
|
224
|
+
writeFileSync(filePath, `${JSON.stringify(next, null, 2)}\n`);
|
|
225
|
+
return { path: filePath };
|
|
226
|
+
}
|
|
227
|
+
if (!(name in raw)) throw new Error(`no entry named "${name}" in ${filePath}.`);
|
|
228
|
+
const { [name]: _dropped, ...next } = raw;
|
|
229
|
+
writeFileSync(filePath, `${JSON.stringify(next, null, 2)}\n`);
|
|
230
|
+
return { path: filePath };
|
|
231
|
+
}
|
|
232
|
+
throw new Error(`${filePath} is not a recognized mcps.json shape (array, map, or {"mcpServers": …}).`);
|
|
233
|
+
}
|
|
199
234
|
/** Map-shaped files key entries by name — the inner object must not repeat it. */
|
|
200
235
|
function stripName(entry) {
|
|
201
236
|
const { name: _name, ...rest } = entry;
|
|
@@ -4915,6 +4950,39 @@ function DiscoveryShell({ children }) {
|
|
|
4915
4950
|
const [mcpsErrors, setMcpsErrors] = useState([]);
|
|
4916
4951
|
const [filesCatalog, setFilesCatalog] = useState([]);
|
|
4917
4952
|
const [mcpToolsByServer, setMcpToolsByServer] = useState(() => readToolsByServer(dataDir));
|
|
4953
|
+
/**
|
|
4954
|
+
* Seed MCP auth badges from the on-disk credential store so rows show
|
|
4955
|
+
* their auth state IMMEDIATELY (first paint, discovery refresh) instead
|
|
4956
|
+
* of waiting a bootstrap round-trip:
|
|
4957
|
+
* - `auth: 'oauth'` entries — `✓ authed` when tokens exist, else
|
|
4958
|
+
* `! needs login` (the flag says OAuth is required either way).
|
|
4959
|
+
* - flagless entries — `✓ authed` only when stored tokens exist
|
|
4960
|
+
* (tokens are proof the server is OAuth: the same rule the bootstrap
|
|
4961
|
+
* uses to attach the provider). No tokens → stay `idle`; most
|
|
4962
|
+
* flagless servers are plain stdio/http and "needs login" would lie.
|
|
4963
|
+
* - static-Authorization entries — untouched (the user owns auth).
|
|
4964
|
+
* The badge is a PREDICTION from disk state; bootstrap events
|
|
4965
|
+
* (connect / auth-required / auth-error) overwrite it with ground truth.
|
|
4966
|
+
*/
|
|
4967
|
+
const seedMcpAuthBadges = useCallback((servers) => {
|
|
4968
|
+
for (const entry of servers) {
|
|
4969
|
+
const explicitOauth = entry.config.auth === "oauth";
|
|
4970
|
+
if (!explicitOauth && hasAuthorizationHeader(entry.config.headers)) continue;
|
|
4971
|
+
const hasTokens = !!mcpCredentialStore.load(entry.config.name)?.tokens;
|
|
4972
|
+
if (explicitOauth) dispatchAuthRef.current(hasTokens ? {
|
|
4973
|
+
type: "auth-success",
|
|
4974
|
+
name: entry.config.name
|
|
4975
|
+
} : {
|
|
4976
|
+
type: "auth-required",
|
|
4977
|
+
name: entry.config.name,
|
|
4978
|
+
reason: "no-tokens"
|
|
4979
|
+
});
|
|
4980
|
+
else if (hasTokens) dispatchAuthRef.current({
|
|
4981
|
+
type: "auth-success",
|
|
4982
|
+
name: entry.config.name
|
|
4983
|
+
});
|
|
4984
|
+
}
|
|
4985
|
+
}, [mcpCredentialStore]);
|
|
4918
4986
|
const filesSlotRef = useRef(null);
|
|
4919
4987
|
const skillsSlotRef = useRef(null);
|
|
4920
4988
|
/** Last-published MCP discovery result — see the value-compare in `refreshMcps`. */
|
|
@@ -4967,18 +5035,7 @@ function DiscoveryShell({ children }) {
|
|
|
4967
5035
|
setMcpsCatalog(servers);
|
|
4968
5036
|
setMcpsErrors(errors);
|
|
4969
5037
|
bootTick(`discovery:mcps (${servers.length} servers, ${errors.length} parse errors)`);
|
|
4970
|
-
|
|
4971
|
-
if (entry.config.auth !== "oauth") continue;
|
|
4972
|
-
const hasTokens = !!mcpCredentialStore.load(entry.config.name)?.tokens;
|
|
4973
|
-
dispatchAuthRef.current(hasTokens ? {
|
|
4974
|
-
type: "auth-success",
|
|
4975
|
-
name: entry.config.name
|
|
4976
|
-
} : {
|
|
4977
|
-
type: "auth-required",
|
|
4978
|
-
name: entry.config.name,
|
|
4979
|
-
reason: "no-tokens"
|
|
4980
|
-
});
|
|
4981
|
-
}
|
|
5038
|
+
seedMcpAuthBadges(servers);
|
|
4982
5039
|
} catch (err) {
|
|
4983
5040
|
debugLog$1("discoverProjectMcps failed", err);
|
|
4984
5041
|
}
|
|
@@ -4989,7 +5046,7 @@ function DiscoveryShell({ children }) {
|
|
|
4989
5046
|
}, [
|
|
4990
5047
|
projectDir,
|
|
4991
5048
|
config.prefix,
|
|
4992
|
-
|
|
5049
|
+
seedMcpAuthBadges,
|
|
4993
5050
|
foreignAgents
|
|
4994
5051
|
]);
|
|
4995
5052
|
const ensureFiles = useCallback(() => filesSlotRef.current?.ensure() ?? Promise.resolve([]), []);
|
|
@@ -5007,30 +5064,20 @@ function DiscoveryShell({ children }) {
|
|
|
5007
5064
|
servers,
|
|
5008
5065
|
errors
|
|
5009
5066
|
});
|
|
5010
|
-
if (fingerprint === mcpsFingerprintRef.current) return Promise.resolve();
|
|
5067
|
+
if (fingerprint === mcpsFingerprintRef.current) return Promise.resolve(false);
|
|
5011
5068
|
mcpsFingerprintRef.current = fingerprint;
|
|
5012
5069
|
setMcpsCatalog(servers);
|
|
5013
5070
|
setMcpsErrors(errors);
|
|
5014
|
-
|
|
5015
|
-
if (entry.config.auth !== "oauth") continue;
|
|
5016
|
-
const hasTokens = !!mcpCredentialStore.load(entry.config.name)?.tokens;
|
|
5017
|
-
dispatchAuthRef.current(hasTokens ? {
|
|
5018
|
-
type: "auth-success",
|
|
5019
|
-
name: entry.config.name
|
|
5020
|
-
} : {
|
|
5021
|
-
type: "auth-required",
|
|
5022
|
-
name: entry.config.name,
|
|
5023
|
-
reason: "no-tokens"
|
|
5024
|
-
});
|
|
5025
|
-
}
|
|
5071
|
+
seedMcpAuthBadges(servers);
|
|
5026
5072
|
} catch (err) {
|
|
5027
5073
|
debugLog$1("refreshMcps failed", err);
|
|
5074
|
+
return Promise.resolve(false);
|
|
5028
5075
|
}
|
|
5029
|
-
return Promise.resolve();
|
|
5076
|
+
return Promise.resolve(true);
|
|
5030
5077
|
}, [
|
|
5031
5078
|
projectDir,
|
|
5032
5079
|
config.prefix,
|
|
5033
|
-
|
|
5080
|
+
seedMcpAuthBadges,
|
|
5034
5081
|
foreignAgents
|
|
5035
5082
|
]);
|
|
5036
5083
|
useEffect(() => {
|
|
@@ -13370,6 +13417,8 @@ function SettingsModal({ skillsCatalog: skillsCatalogProp, mcpsCatalog: mcpsCata
|
|
|
13370
13417
|
const [skillOp, setSkillOp] = useState(null);
|
|
13371
13418
|
const [mcpAdd, setMcpAdd] = useState(false);
|
|
13372
13419
|
const [mcpOp, setMcpOp] = useState(null);
|
|
13420
|
+
const [skillRemoveArmed, setSkillRemoveArmed] = useState(null);
|
|
13421
|
+
const [mcpRemoveArmed, setMcpRemoveArmed] = useState(null);
|
|
13373
13422
|
const [cursorByTab, setCursorByTab] = useState(() => Object.fromEntries(tabOrder.map((id) => [id, 0])));
|
|
13374
13423
|
const [query, setQuery] = useState("");
|
|
13375
13424
|
const [logsMinLevel, setLogsMinLevel] = useState("debug");
|
|
@@ -13792,6 +13841,13 @@ function SettingsModal({ skillsCatalog: skillsCatalogProp, mcpsCatalog: mcpsCata
|
|
|
13792
13841
|
useEffect(() => {
|
|
13793
13842
|
setRemoveArmed(null);
|
|
13794
13843
|
}, [focusedExtension?.name, activeTab]);
|
|
13844
|
+
const focusedSkill = activeTab === "skills" ? filteredSkills[cursor] : void 0;
|
|
13845
|
+
useEffect(() => {
|
|
13846
|
+
setSkillRemoveArmed(null);
|
|
13847
|
+
}, [focusedSkill?.name, activeTab]);
|
|
13848
|
+
useEffect(() => {
|
|
13849
|
+
setMcpRemoveArmed(null);
|
|
13850
|
+
}, [focusedMcp?.config.name, activeTab]);
|
|
13795
13851
|
const oauthPasteActive = activeTab === "mcps" && focusedMcpStatus?.kind === "authorizing" && !!focusedMcpStatus.url;
|
|
13796
13852
|
useEffect(() => {
|
|
13797
13853
|
if (!oauthPasteActive && !editingInputKey) inputRef.current?.focus();
|
|
@@ -13999,15 +14055,69 @@ function SettingsModal({ skillsCatalog: skillsCatalogProp, mcpsCatalog: mcpsCata
|
|
|
13999
14055
|
if (key.ctrl && key.name === "g" && activeTab === "skills" && actions?.onInstallSkill) {
|
|
14000
14056
|
key.preventDefault();
|
|
14001
14057
|
if (skillOp?.kind === "busy") return;
|
|
14058
|
+
setSkillRemoveArmed(null);
|
|
14002
14059
|
setSkillInstallOpen(true);
|
|
14003
14060
|
return;
|
|
14004
14061
|
}
|
|
14062
|
+
if (key.ctrl && key.name === "x" && activeTab === "skills" && actions?.onRemoveSkill) {
|
|
14063
|
+
key.preventDefault();
|
|
14064
|
+
const skill = focusedSkill;
|
|
14065
|
+
if (!skill || skillOp?.kind === "busy") return;
|
|
14066
|
+
if (skillRemoveArmed !== skill.name) {
|
|
14067
|
+
setSkillRemoveArmed(skill.name);
|
|
14068
|
+
setSkillOp({
|
|
14069
|
+
kind: "notice",
|
|
14070
|
+
text: `delete "${skill.name}" from disk? press ctrl+x again to confirm.`
|
|
14071
|
+
});
|
|
14072
|
+
return;
|
|
14073
|
+
}
|
|
14074
|
+
setSkillRemoveArmed(null);
|
|
14075
|
+
setSkillOp({
|
|
14076
|
+
kind: "busy",
|
|
14077
|
+
text: `deleting "${skill.name}"…`
|
|
14078
|
+
});
|
|
14079
|
+
actions.onRemoveSkill(skill).then((message) => setSkillOp({
|
|
14080
|
+
kind: "notice",
|
|
14081
|
+
text: message
|
|
14082
|
+
})).catch((err) => setSkillOp({
|
|
14083
|
+
kind: "error",
|
|
14084
|
+
text: errorMessage(err)
|
|
14085
|
+
}));
|
|
14086
|
+
return;
|
|
14087
|
+
}
|
|
14005
14088
|
if (key.ctrl && key.name === "g" && activeTab === "mcps" && actions?.onAddMcp) {
|
|
14006
14089
|
key.preventDefault();
|
|
14007
14090
|
if (mcpOp?.kind === "busy") return;
|
|
14091
|
+
setMcpRemoveArmed(null);
|
|
14008
14092
|
setMcpAdd(true);
|
|
14009
14093
|
return;
|
|
14010
14094
|
}
|
|
14095
|
+
if (key.ctrl && key.name === "x" && activeTab === "mcps" && actions?.onRemoveMcp) {
|
|
14096
|
+
key.preventDefault();
|
|
14097
|
+
if (focusedMcpRow?.kind !== "server" || !focusedMcp || mcpOp?.kind === "busy") return;
|
|
14098
|
+
const name = focusedMcp.config.name;
|
|
14099
|
+
if (mcpRemoveArmed !== name) {
|
|
14100
|
+
setMcpRemoveArmed(name);
|
|
14101
|
+
setMcpOp({
|
|
14102
|
+
kind: "notice",
|
|
14103
|
+
text: `remove "${name}" from ${displayPath$1(focusedMcp.path, homedir())}? press ctrl+x again to confirm.`
|
|
14104
|
+
});
|
|
14105
|
+
return;
|
|
14106
|
+
}
|
|
14107
|
+
setMcpRemoveArmed(null);
|
|
14108
|
+
setMcpOp({
|
|
14109
|
+
kind: "busy",
|
|
14110
|
+
text: `removing "${name}"…`
|
|
14111
|
+
});
|
|
14112
|
+
actions.onRemoveMcp(focusedMcp).then((message) => setMcpOp({
|
|
14113
|
+
kind: "notice",
|
|
14114
|
+
text: message
|
|
14115
|
+
})).catch((err) => setMcpOp({
|
|
14116
|
+
kind: "error",
|
|
14117
|
+
text: errorMessage(err)
|
|
14118
|
+
}));
|
|
14119
|
+
return;
|
|
14120
|
+
}
|
|
14011
14121
|
if (key.ctrl && key.name === "r") {
|
|
14012
14122
|
if (activeTab === "skills" && actions?.onRefreshSkills) {
|
|
14013
14123
|
actions.onRefreshSkills();
|
|
@@ -14271,6 +14381,8 @@ function SettingsModal({ skillsCatalog: skillsCatalogProp, mcpsCatalog: mcpsCata
|
|
|
14271
14381
|
canInstallExtension: !!actions?.onInstallExtension,
|
|
14272
14382
|
canInstallSkill: !!actions?.onInstallSkill,
|
|
14273
14383
|
canAddMcp: !!actions?.onAddMcp,
|
|
14384
|
+
canRemoveSkill: !!actions?.onRemoveSkill,
|
|
14385
|
+
canRemoveMcp: !!actions?.onRemoveMcp,
|
|
14274
14386
|
focusedExtensionExpandable: activeTab === "extensions" && extensionVisibleRows[cursor] !== void 0 && (() => {
|
|
14275
14387
|
const row = extensionVisibleRows[cursor];
|
|
14276
14388
|
return row.kind === "config" || row.kind === "extension" && row.hasConfig;
|
|
@@ -14934,6 +15046,7 @@ function SkillsList({ items, enabledSet, totalCount, cursor, highlightBg, query,
|
|
|
14934
15046
|
const bg = focused ? highlightBg : void 0;
|
|
14935
15047
|
const enabled = enabledSet.has(entry.name);
|
|
14936
15048
|
const description = truncateToCols(entry.description ?? "", descCols);
|
|
15049
|
+
const origin = skillOriginLabel(entry);
|
|
14937
15050
|
return /* @__PURE__ */ jsxs("box", {
|
|
14938
15051
|
id: anchorIdFor(i),
|
|
14939
15052
|
style: {
|
|
@@ -14957,6 +15070,10 @@ function SkillsList({ items, enabledSet, totalCount, cursor, highlightBg, query,
|
|
|
14957
15070
|
/* @__PURE__ */ jsx$1("span", {
|
|
14958
15071
|
fg: focused ? COLOR.brand : COLOR.dim,
|
|
14959
15072
|
children: entry.name
|
|
15073
|
+
}),
|
|
15074
|
+
origin && /* @__PURE__ */ jsxs("span", {
|
|
15075
|
+
fg: COLOR.mute,
|
|
15076
|
+
children: [" · ", origin]
|
|
14960
15077
|
})
|
|
14961
15078
|
]
|
|
14962
15079
|
}), /* @__PURE__ */ jsx$1("text", {
|
|
@@ -15642,7 +15759,7 @@ function renderMcpErrors(errors, home, warnColor) {
|
|
|
15642
15759
|
}, err.path))
|
|
15643
15760
|
});
|
|
15644
15761
|
}
|
|
15645
|
-
function Hints({ activeTab, focusedMcp, focusedMcpRow, focusedMcpStatus, canRefreshSkills, canRefreshMcps, canEditExtension, canCreateExtension, canUpdateExtension, canRemoveExtension, canInstallExtension, canInstallSkill, canAddMcp, focusedExtensionExpandable }) {
|
|
15762
|
+
function Hints({ activeTab, focusedMcp, focusedMcpRow, focusedMcpStatus, canRefreshSkills, canRefreshMcps, canEditExtension, canCreateExtension, canUpdateExtension, canRemoveExtension, canInstallExtension, canInstallSkill, canAddMcp, canRemoveSkill, canRemoveMcp, focusedExtensionExpandable }) {
|
|
15646
15763
|
const COLOR = useColors();
|
|
15647
15764
|
const onServerRow = focusedMcpRow?.kind === "server";
|
|
15648
15765
|
const showLogin = activeTab === "mcps" && onServerRow && !!focusedMcp && !!focusedMcpStatus && canLogin$1(focusedMcp, focusedMcpStatus);
|
|
@@ -15733,6 +15850,14 @@ function Hints({ activeTab, focusedMcp, focusedMcpRow, focusedMcpStatus, canRefr
|
|
|
15733
15850
|
}),
|
|
15734
15851
|
" install"
|
|
15735
15852
|
] }),
|
|
15853
|
+
activeTab === "skills" && canRemoveSkill && /* @__PURE__ */ jsxs("span", { children: [
|
|
15854
|
+
" · ",
|
|
15855
|
+
/* @__PURE__ */ jsx$1("span", {
|
|
15856
|
+
fg: COLOR.warn,
|
|
15857
|
+
children: "ctrl+x"
|
|
15858
|
+
}),
|
|
15859
|
+
" delete"
|
|
15860
|
+
] }),
|
|
15736
15861
|
activeTab === "mcps" && canAddMcp && /* @__PURE__ */ jsxs("span", { children: [
|
|
15737
15862
|
" · ",
|
|
15738
15863
|
/* @__PURE__ */ jsx$1("span", {
|
|
@@ -15741,6 +15866,14 @@ function Hints({ activeTab, focusedMcp, focusedMcpRow, focusedMcpStatus, canRefr
|
|
|
15741
15866
|
}),
|
|
15742
15867
|
" add server"
|
|
15743
15868
|
] }),
|
|
15869
|
+
activeTab === "mcps" && canRemoveMcp && onServerRow && /* @__PURE__ */ jsxs("span", { children: [
|
|
15870
|
+
" · ",
|
|
15871
|
+
/* @__PURE__ */ jsx$1("span", {
|
|
15872
|
+
fg: COLOR.warn,
|
|
15873
|
+
children: "ctrl+x"
|
|
15874
|
+
}),
|
|
15875
|
+
" remove"
|
|
15876
|
+
] }),
|
|
15744
15877
|
showLogin && /* @__PURE__ */ jsxs("span", { children: [
|
|
15745
15878
|
" · ",
|
|
15746
15879
|
/* @__PURE__ */ jsx$1("span", {
|
|
@@ -15789,7 +15922,22 @@ function generalCorpus(item) {
|
|
|
15789
15922
|
return parts.join(" ").toLowerCase();
|
|
15790
15923
|
}
|
|
15791
15924
|
function skillCorpus(s) {
|
|
15792
|
-
return `${s.name} ${s.description ?? ""}`.toLowerCase();
|
|
15925
|
+
return `${s.name} ${s.description ?? ""} ${skillOriginLabel(s)}`.toLowerCase();
|
|
15926
|
+
}
|
|
15927
|
+
/**
|
|
15928
|
+
* Short provenance chip for a skill row. Standard scan roots
|
|
15929
|
+
* (`.agents/skills`, `.{prefix}/skills` — project or user) are fully
|
|
15930
|
+
* described by the scope tag; a skill from a custom `skillsScanPaths`
|
|
15931
|
+
* entry shows the tilde-collapsed path itself so the user can tell
|
|
15932
|
+
* WHICH extra root contributed it. Inline / builtin skills (no
|
|
15933
|
+
* directory on disk) show their source tag.
|
|
15934
|
+
*/
|
|
15935
|
+
function skillOriginLabel(skill) {
|
|
15936
|
+
const dir = skill.baseDir ?? (skill.location ? dirname(skill.location) : void 0);
|
|
15937
|
+
if (!dir) return skill.source ?? "inline";
|
|
15938
|
+
const root = dirname(dir);
|
|
15939
|
+
if (/\/\.[^/]+\/skills$/.test(root)) return skill.source ?? "project";
|
|
15940
|
+
return truncateToCols(displayPath$1(root, homedir()), 36);
|
|
15793
15941
|
}
|
|
15794
15942
|
function extensionCorpus(e) {
|
|
15795
15943
|
return [
|
|
@@ -17082,6 +17230,8 @@ function AppShell() {
|
|
|
17082
17230
|
const dispatchAuth = useMcpAuthDispatch();
|
|
17083
17231
|
const dispatchAuthRef = useRef(dispatchAuth);
|
|
17084
17232
|
dispatchAuthRef.current = dispatchAuth;
|
|
17233
|
+
const pendingAutoLoginMcpRef = useRef(null);
|
|
17234
|
+
const onLoginMcpRef = useRef(null);
|
|
17085
17235
|
const skillsCatalogRef = useRef(skillsCatalog);
|
|
17086
17236
|
skillsCatalogRef.current = skillsCatalog;
|
|
17087
17237
|
const enabledSkillsRef = useRef(settings.enabledSkills);
|
|
@@ -18232,6 +18382,13 @@ function AppShell() {
|
|
|
18232
18382
|
name,
|
|
18233
18383
|
reason
|
|
18234
18384
|
});
|
|
18385
|
+
if (pendingAutoLoginMcpRef.current === name) {
|
|
18386
|
+
pendingAutoLoginMcpRef.current = null;
|
|
18387
|
+
onLoginMcpRef.current?.(name);
|
|
18388
|
+
}
|
|
18389
|
+
});
|
|
18390
|
+
agent.hooks.hook("mcp:bootstrap:settled", () => {
|
|
18391
|
+
pendingAutoLoginMcpRef.current = null;
|
|
18235
18392
|
});
|
|
18236
18393
|
agent.hooks.hook("mcp:bootstrap:end", (ctx) => {
|
|
18237
18394
|
if (ctx.ok) return;
|
|
@@ -18275,6 +18432,7 @@ function AppShell() {
|
|
|
18275
18432
|
type: "connected",
|
|
18276
18433
|
name
|
|
18277
18434
|
});
|
|
18435
|
+
if (pendingAutoLoginMcpRef.current === name) pendingAutoLoginMcpRef.current = null;
|
|
18278
18436
|
});
|
|
18279
18437
|
agent.hooks.hook("stream:thinking", ({ delta, turnId }) => stream.queueStreamDelta("thinking", delta, { turnId }));
|
|
18280
18438
|
agent.hooks.hook("stream:text", ({ delta, turnId }) => stream.queueStreamDelta("markdown", delta, { turnId }));
|
|
@@ -19243,9 +19401,73 @@ function AppShell() {
|
|
|
19243
19401
|
cwd: cwdRef.current,
|
|
19244
19402
|
prefix: config.prefix
|
|
19245
19403
|
}), entry);
|
|
19246
|
-
|
|
19404
|
+
pendingAutoLoginMcpRef.current = entry.name;
|
|
19405
|
+
if (!await onRefreshMcps() && pendingAutoLoginMcpRef.current === entry.name) pendingAutoLoginMcpRef.current = null;
|
|
19247
19406
|
return `${result.action} "${entry.name}" → ${compactPath(result.path, 64)}`;
|
|
19248
19407
|
}, [config.prefix, onRefreshMcps]);
|
|
19408
|
+
/**
|
|
19409
|
+
* Delete a discovered skill's directory (Settings → Skills → ctrl+x,
|
|
19410
|
+
* two-press confirm in the modal). Only skills that live on disk in a
|
|
19411
|
+
* root we can safely mutate qualify; the SKILL.md existence check
|
|
19412
|
+
* guards against ever recursively deleting a directory that isn't a
|
|
19413
|
+
* skill (e.g. a stale catalog entry pointing at a reused path).
|
|
19414
|
+
*
|
|
19415
|
+
* `.agents/skills/` entries ARE deletable — deliberately asymmetric
|
|
19416
|
+
* with `onRemoveMcp`'s ownership gate. An MCP removal edits a shared
|
|
19417
|
+
* multi-entry FILE other tools author (clobber risk); a skill is a
|
|
19418
|
+
* self-contained directory that is itself the install/uninstall unit,
|
|
19419
|
+
* and cross-tool installers (skills.sh, `ctrl+g` here) drop skills
|
|
19420
|
+
* into `.agents/skills/` expecting exactly this kind of removal.
|
|
19421
|
+
*/
|
|
19422
|
+
const onRemoveSkill = useCallback(async (skill) => {
|
|
19423
|
+
const dir = skill.baseDir ?? (skill.location ? dirname(skill.location) : void 0);
|
|
19424
|
+
if (!dir || skill.source === "inline" || skill.source === "builtin") throw new Error(`"${skill.name}" is ${skill.source ?? "inline"} — nothing on disk to delete.`);
|
|
19425
|
+
if (!existsSync(join(dir, "SKILL.md"))) throw new Error(`${compactPath(dir)} has no SKILL.md — refusing to delete.`);
|
|
19426
|
+
rmSync(dir, {
|
|
19427
|
+
recursive: true,
|
|
19428
|
+
force: true
|
|
19429
|
+
});
|
|
19430
|
+
const allow = enabledSkillsRef.current;
|
|
19431
|
+
if (allow?.includes(skill.name)) {
|
|
19432
|
+
const next = allow.filter((n) => n !== skill.name);
|
|
19433
|
+
enabledSkillsRef.current = next;
|
|
19434
|
+
setSetting("enabledSkills", next);
|
|
19435
|
+
}
|
|
19436
|
+
await onRefreshSkills();
|
|
19437
|
+
return `deleted "${skill.name}" (${compactPath(dir)})`;
|
|
19438
|
+
}, [setSetting, onRefreshSkills]);
|
|
19439
|
+
/**
|
|
19440
|
+
* Remove an MCP server from the config file that declared it
|
|
19441
|
+
* (Settings → MCPs → ctrl+x, two-press confirm in the modal).
|
|
19442
|
+
* Ownership-gated: only entries in a `.{prefix}/` file are removable —
|
|
19443
|
+
* `.agents/` siblings and imported foreign configs (Claude / Cursor /
|
|
19444
|
+
* VS Code) are cross-tool files we read but never rewrite, so the
|
|
19445
|
+
* error points the user at the declaring file instead.
|
|
19446
|
+
*/
|
|
19447
|
+
const onRemoveMcp = useCallback(async (entry) => {
|
|
19448
|
+
const name = entry.config.name;
|
|
19449
|
+
const prefix = (config.prefix ?? ".zidane").replace(/^\./, "");
|
|
19450
|
+
if (!entry.path.includes(`/.${prefix}/`)) throw new Error(`"${name}" is defined in ${compactPath(entry.path, 64)} — zidane doesn't edit that file; remove the entry there.`);
|
|
19451
|
+
removeMcpServer(entry.path, name);
|
|
19452
|
+
const enabled = enabledMcpsRef.current;
|
|
19453
|
+
if (enabled?.includes(name)) {
|
|
19454
|
+
const next = enabled.filter((n) => n !== name);
|
|
19455
|
+
enabledMcpsRef.current = next;
|
|
19456
|
+
setSetting("enabledMcps", next);
|
|
19457
|
+
}
|
|
19458
|
+
const deny = disabledMcpToolsRef.current;
|
|
19459
|
+
if (deny && name in deny) {
|
|
19460
|
+
const { [name]: _dropped, ...rest } = deny;
|
|
19461
|
+
disabledMcpToolsRef.current = rest;
|
|
19462
|
+
setSetting("disabledMcpTools", rest);
|
|
19463
|
+
}
|
|
19464
|
+
await onRefreshMcps();
|
|
19465
|
+
return `removed "${name}" from ${compactPath(entry.path, 64)}`;
|
|
19466
|
+
}, [
|
|
19467
|
+
config.prefix,
|
|
19468
|
+
setSetting,
|
|
19469
|
+
onRefreshMcps
|
|
19470
|
+
]);
|
|
19249
19471
|
const popupOpenRef = useRef(false);
|
|
19250
19472
|
const onPopupOpenChange = useCallback((open) => {
|
|
19251
19473
|
popupOpenRef.current = open;
|
|
@@ -19706,7 +19928,7 @@ function AppShell() {
|
|
|
19706
19928
|
* user runs comes from that same gate; each `runAgent` awaits its
|
|
19707
19929
|
* `agent.run` so the single-flight agent is never re-entered.
|
|
19708
19930
|
*/
|
|
19709
|
-
const runCommand = useCallback(async (invocation) => {
|
|
19931
|
+
const runCommand = useCallback(async (invocation, attachments = []) => {
|
|
19710
19932
|
const session = sessionRef.current;
|
|
19711
19933
|
const agent = agentRef.current;
|
|
19712
19934
|
if (!session) return;
|
|
@@ -19766,6 +19988,11 @@ function AppShell() {
|
|
|
19766
19988
|
const ctx = {
|
|
19767
19989
|
args: invocation.args,
|
|
19768
19990
|
argv: invocation.argv,
|
|
19991
|
+
...attachments.length > 0 ? { attachments: attachments.map((a) => ({
|
|
19992
|
+
name: a.name,
|
|
19993
|
+
mediaType: a.mediaType,
|
|
19994
|
+
data: a.content.toString("base64")
|
|
19995
|
+
})) } : {},
|
|
19769
19996
|
data: {},
|
|
19770
19997
|
emit: emitBlock,
|
|
19771
19998
|
runAgent: async (agentPrompt, agentOpts) => {
|
|
@@ -20142,7 +20369,7 @@ function AppShell() {
|
|
|
20142
20369
|
if (!opts?.wake) {
|
|
20143
20370
|
const invocation = parseCommandInvocation(prompt, commandsRef.current);
|
|
20144
20371
|
if (invocation) {
|
|
20145
|
-
await runCommand(invocation);
|
|
20372
|
+
await runCommand(invocation, attachments);
|
|
20146
20373
|
return;
|
|
20147
20374
|
}
|
|
20148
20375
|
const bashCommand = parseBashInvocation(prompt);
|
|
@@ -20518,6 +20745,7 @@ function AppShell() {
|
|
|
20518
20745
|
mcpCredentialStore,
|
|
20519
20746
|
rebuildActiveAgent
|
|
20520
20747
|
]);
|
|
20748
|
+
onLoginMcpRef.current = onLoginMcp;
|
|
20521
20749
|
const onLogoutMcp = useCallback((name) => {
|
|
20522
20750
|
mcpCredentialStore.delete(name);
|
|
20523
20751
|
const entry = mcpsCatalogRef.current.find((d) => d.config.name === name);
|
|
@@ -21199,6 +21427,8 @@ function AppShell() {
|
|
|
21199
21427
|
}),
|
|
21200
21428
|
onInstallSkill,
|
|
21201
21429
|
onAddMcp,
|
|
21430
|
+
onRemoveSkill,
|
|
21431
|
+
onRemoveMcp,
|
|
21202
21432
|
onPickCompactionModel
|
|
21203
21433
|
}
|
|
21204
21434
|
}));
|