@fased/fased 0.1.57 → 0.1.59
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/agents/anthropic-payload-policy.js +188 -0
- package/dist/agents/anthropic-transport-stream.js +736 -0
- package/dist/agents/copilot-dynamic-headers.js +1 -1
- package/dist/agents/current-model-catalog.js +5 -2
- package/dist/agents/custom-api-registry.js +21 -0
- package/dist/agents/google-transport-stream.js +543 -0
- package/dist/agents/model-catalog-status.js +6 -1
- package/dist/agents/models-config.js +2 -1
- package/dist/agents/openai-completions-compat.js +49 -0
- package/dist/agents/openai-responses-payload-policy.js +100 -0
- package/dist/agents/openai-tool-schema.js +130 -0
- package/dist/agents/openai-transport-stream.js +1040 -0
- package/dist/agents/pi-embedded-runner/compact.js +9 -0
- package/dist/agents/pi-embedded-runner/run/attempt.js +9 -0
- package/dist/agents/pi-embedded-runner/session-manager-init.js +5 -20
- package/dist/agents/provider-extension-catalog-manifest.js +2 -2
- package/dist/agents/provider-request-config.js +1 -1
- package/dist/agents/provider-stream.js +29 -0
- package/dist/agents/provider-transport-fetch.js +89 -0
- package/dist/agents/provider-transport-stream.js +72 -0
- package/dist/agents/system-prompt-cache-boundary.js +1 -1
- package/dist/agents/system-prompt.js +1 -1
- package/dist/agents/transport-message-transform.js +143 -0
- package/dist/agents/transport-stream-shared.js +81 -0
- package/dist/brand.js +1 -1
- package/dist/build-info.json +3 -3
- package/dist/canvas-host/a2ui/.bundle.hash +1 -1
- package/dist/channels/delivery.js +78 -0
- package/dist/channels/plugins/catalog.js +10 -5
- package/dist/cli/components-cli.js +16 -13
- package/dist/cli/program/register.subclis.js +9 -0
- package/dist/cli/providers-cli.js +79 -6
- package/dist/cli/services-cli.js +28 -0
- package/dist/commands/auth-choice.js +1 -1
- package/dist/commands/models/list.auth-overview.js +12 -0
- package/dist/commands/onboard-channels.js +5 -0
- package/dist/commands/onboard-helpers.js +1 -1
- package/dist/commands/vllm-setup.js +12 -3
- package/dist/control-ui/assets/{app-DltSyY4Y.js → app-S_jg-ADS.js} +1706 -1675
- package/dist/control-ui/assets/{index-D5JlBp7f.js → index-C22rDOFm.js} +3 -3
- package/dist/control-ui/assets/{providers-Cc89iMdx.js → providers-QMn4w2_f.js} +3 -3
- package/dist/control-ui/index.html +1 -1
- package/dist/control-ui/version.json +1 -1
- package/dist/gateway/control-reply-text.js +10 -1
- package/dist/gateway/method-scopes.js +2 -0
- package/dist/gateway/protocol/schema/agents-models-skills.js +1 -0
- package/dist/gateway/server-chat.js +3 -3
- package/dist/gateway/server-methods/channels.js +10 -2
- package/dist/gateway/server-methods/chat.js +19 -12
- package/dist/gateway/server-methods/models.js +4 -0
- package/dist/gateway/server-methods/services.js +47 -2
- package/dist/gateway/server-methods-list.js +2 -0
- package/dist/gateway/session-event-payloads.js +20 -9
- package/dist/infra/google-api-base-url.js +29 -0
- package/dist/plugin-sdk/{accounts-CmMwe9Dt.js → accounts-DxblobYM.js} +1 -1
- package/dist/plugin-sdk/{actions-DYViFQiX.js → actions-D4UNimWa.js} +2 -2
- package/dist/plugin-sdk/{active-listener-DVbpcisf.js → active-listener-CFuy106s.js} +1 -1
- package/dist/plugin-sdk/{audio-preflight-D-Mfay8i.js → audio-preflight-CxZixyhW.js} +25 -25
- package/dist/plugin-sdk/{audit-JImYFOzJ.js → audit-Cs0K7LBp.js} +1 -1
- package/dist/plugin-sdk/{channel-access-cxCK2mci.js → channel-access-D5aHoTY8.js} +1 -1
- package/dist/plugin-sdk/{channel-access-configure-B_qYjml8.js → channel-access-configure-Dvch9mMQ.js} +1 -1
- package/dist/plugin-sdk/channel-plugin-common.d.ts +2 -2
- package/dist/plugin-sdk/channel-plugin-common.js +4 -4
- package/dist/plugin-sdk/{chunk-CF8nvZNj.js → chunk-B0FUGc5A.js} +1 -1
- package/dist/plugin-sdk/{chunk-items-yLFoO571.js → chunk-items-Cy9a3X7x.js} +1 -1
- package/dist/plugin-sdk/command-status.js +25 -25
- package/dist/plugin-sdk/{commands-registry-CK4KmMG0.js → commands-registry-DmDRhRAU.js} +2 -2
- package/dist/plugin-sdk/{common-Cky4hpqr.js → common-CfUOowOp.js} +1 -1
- package/dist/plugin-sdk/{config-Dbxj_jUP.js → config-mxULv0fQ.js} +4 -1
- package/dist/plugin-sdk/{config-schema-aKPMn6ML.js → config-schema-D8E0LX8X.js} +4422 -486
- package/dist/plugin-sdk/device-pair.d.ts +1 -1
- package/dist/plugin-sdk/discord.d.ts +4 -4
- package/dist/plugin-sdk/discord.js +19 -19
- package/dist/plugin-sdk/{handle-action-BSNDD2Vc.js → handle-action-DbVCF9HZ.js} +13 -13
- package/dist/plugin-sdk/{helpers-CDo2XBSr.js → helpers-BXbdgs5H.js} +1 -1
- package/dist/plugin-sdk/{image-ops-DbeBxbn4.js → image-ops-D7jPxaph.js} +1 -1
- package/dist/plugin-sdk/index.d.ts +15 -15
- package/dist/plugin-sdk/index.js +27 -27
- package/dist/plugin-sdk/{login-CWXvFTd8.js → login-BRxww6nv.js} +3 -3
- package/dist/plugin-sdk/{login-qr-CJB2zjmM.js → login-qr-DJXsk9XH.js} +3 -3
- package/dist/plugin-sdk/{manager-CbiFFLKS.js → manager-Y2S_5IlI.js} +2 -2
- package/dist/plugin-sdk/{markdown-tables-Bskt9r8i.js → markdown-tables-DHLFQqaF.js} +1 -1
- package/dist/plugin-sdk/{media-B3aAg5rh.js → media-Czo4carg.js} +2 -2
- package/dist/plugin-sdk/{monitor-BYGbTI5V.js → monitor-CFHFAUOj.js} +32 -32
- package/dist/plugin-sdk/{monitor-BJs6z7AT.js → monitor-xS9A8Upr.js} +29 -29
- package/dist/plugin-sdk/ollama-runtime.js +970 -0
- package/dist/plugin-sdk/{openresponses-http-BGCl2dS2.js → openresponses-http-BcUbeVV6.js} +25 -25
- package/dist/plugin-sdk/{optional-runtime-dependency-BlTVkcAg.js → optional-runtime-dependency-DdMbxS24.js} +1 -1
- package/dist/plugin-sdk/{outbound-CIemga5_.js → outbound-Db8mRN6P.js} +6 -6
- package/dist/plugin-sdk/{outbound-attachment-2RckWqrk.js → outbound-attachment-BqFjcypb.js} +2 -2
- package/dist/plugin-sdk/{pairing-message-r-VQfhFB.js → pairing-message-B3GC_7CD.js} +1 -1
- package/dist/plugin-sdk/{pairing-message-C403mq4K.d.ts → pairing-message-CxonJmwM.d.ts} +1 -1
- package/dist/plugin-sdk/{pairing-store-uPnLfGgB.js → pairing-store-CQikgIbw.js} +2 -2
- package/dist/plugin-sdk/{pi-model-discovery-BpEilAym.js → pi-model-discovery-CY3m5zJP.js} +1 -1
- package/dist/plugin-sdk/{pi-model-discovery-runtime-DwNdFaz-.js → pi-model-discovery-runtime-DSh1T2pn.js} +2 -2
- package/dist/plugin-sdk/provider-web-search-config-contract.d.ts +1 -1
- package/dist/plugin-sdk/{pw-ai-H7UgunQQ.js → pw-ai-AFUqn-tQ.js} +3 -3
- package/dist/plugin-sdk/{replies-CKMwkH4G.js → replies-Fzh9PhXl.js} +2 -2
- package/dist/plugin-sdk/{resolve-outbound-target-B68fSoGi.js → resolve-outbound-target-KpF3co6T.js} +1 -1
- package/dist/plugin-sdk/{resolve-route-B8fOfihG.js → resolve-route-CDl74O19.js} +1 -1
- package/dist/plugin-sdk/{retry-policy-B6GQldxB.js → retry-policy-D4uiqUOG.js} +1 -1
- package/dist/plugin-sdk/{runtime-nVJl3PlS.js → runtime-Bb6KRnCC.js} +6 -4
- package/dist/plugin-sdk/{runtime-dependency-DlqVSsSs.js → runtime-dependency-DLDmB94f.js} +11 -11
- package/dist/plugin-sdk/sat-runtime.d.ts +2 -2
- package/dist/plugin-sdk/sat-runtime.js +25 -25
- package/dist/plugin-sdk/{send-CPK_HlYW.js → send-5nFktR1n.js} +5 -5
- package/dist/plugin-sdk/{send-hSu1HWms.js → send-Bfzf11VY.js} +7 -7
- package/dist/plugin-sdk/{send-D3DQOg2a.js → send-C4k4JuJN.js} +6 -6
- package/dist/plugin-sdk/{send-BHokB4TR.js → send-D-uDKGIq.js} +6 -6
- package/dist/plugin-sdk/{send-BCJ4hi3t.js → send-Du8ykP1k.js} +8 -8
- package/dist/plugin-sdk/{session-DQ4Dr-mf.js → session-CS-Td9EM.js} +2 -2
- package/dist/plugin-sdk/{skill-commands-CmdoKLh_.js → skill-commands-CFAlXWHk.js} +2 -2
- package/dist/plugin-sdk/{slack-B70NHpMF.js → slack-DXYGbizH.js} +37 -37
- package/dist/plugin-sdk/{slack-actions-fSmP981b.js → slack-actions-BcMkNv1Z.js} +11 -11
- package/dist/plugin-sdk/slack.d.ts +4 -4
- package/dist/plugin-sdk/slack.js +9 -9
- package/dist/plugin-sdk/{sticker-cache-B4dG2sKU.js → sticker-cache-Dr3rYfU1.js} +3 -3
- package/dist/plugin-sdk/{tables-EX4Hy-a-.js → tables-bFXyRpkx.js} +1 -1
- package/dist/plugin-sdk/{targets-BeGUCGWK.js → targets-DH7a9lKB.js} +1 -1
- package/dist/plugin-sdk/{telegram-actions-CM8SJgc9.js → telegram-actions-Besbw_Hg.js} +28 -28
- package/dist/plugin-sdk/telegram.d.ts +4 -4
- package/dist/plugin-sdk/telegram.js +8 -8
- package/dist/plugin-sdk/{thread-bindings.lifecycle-tHK_1mvp.js → thread-bindings.lifecycle-CgOvvdw8.js} +3 -3
- package/dist/plugin-sdk/{thread-bindings.state-D7xG1GHu.js → thread-bindings.state-CQpk44Hq.js} +2 -2
- package/dist/plugin-sdk/{tmp-fased-dir-Ouj58axY.d.ts → tmp-fased-dir-DQ00xQ5D.d.ts} +1 -1
- package/dist/plugin-sdk/{types-B4hj6HgR.d.ts → types-B6zx-Dl2.d.ts} +1 -1
- package/dist/plugin-sdk/{types-dWZFX1fk.d.ts → types-eUM7hcDz.d.ts} +1 -1
- package/dist/plugin-sdk/{web-BFolfZ3i.js → web-Q1-G--JH.js} +30 -30
- package/dist/plugin-sdk/{whatsapp-actions-CYmleHCz.js → whatsapp-actions-BtSc2CBv.js} +13 -13
- package/dist/plugin-sdk/{whatsapp-heartbeat-BEwm4GK3.js → whatsapp-heartbeat-Bg9TuYzl.js} +2 -2
- package/dist/plugin-sdk/whatsapp.d.ts +9 -9
- package/dist/plugin-sdk/whatsapp.js +12 -12
- package/dist/plugin-sdk/{wsl-BtMDzMv5.js → wsl-C4DGFkOd.js} +3 -3
- package/dist/plugin-sdk/{zod-schema.providers-core-FaYR6KdD.d.ts → zod-schema.providers-core-CIzCjXH9.d.ts} +61 -61
- package/dist/plugins/provider-runtime.js +79 -0
- package/dist/providers/refresh.js +14 -0
- package/extensions/acpx/package.json +1 -1
- package/extensions/bluebubbles/package.json +1 -1
- package/extensions/copilot-proxy/package.json +1 -1
- package/extensions/diagnostics-otel/package.json +1 -1
- package/extensions/fased-federation/package.json +1 -1
- package/extensions/google-gemini-cli-auth/package.json +1 -1
- package/extensions/imessage/package.json +1 -1
- package/extensions/irc/package.json +1 -1
- package/extensions/line/package.json +1 -1
- package/extensions/llm-task/package.json +1 -1
- package/extensions/lobster/package.json +1 -1
- package/extensions/matrix/CHANGELOG.md +12 -0
- package/extensions/matrix/package.json +1 -1
- package/extensions/mattermost/package.json +1 -1
- package/extensions/memory-core/package.json +2 -2
- package/extensions/memory-lancedb/package.json +1 -1
- package/extensions/minimax-portal-auth/package.json +1 -1
- package/extensions/msteams/CHANGELOG.md +12 -0
- package/extensions/msteams/package.json +1 -1
- package/extensions/nextcloud-talk/package.json +1 -1
- package/extensions/nostr/CHANGELOG.md +12 -0
- package/extensions/nostr/package.json +1 -1
- package/extensions/open-prose/package.json +1 -1
- package/extensions/sat-mining/package.json +1 -1
- package/extensions/signal/package.json +1 -1
- package/extensions/synology-chat/package.json +1 -1
- package/extensions/tlon/package.json +1 -1
- package/extensions/twitch/CHANGELOG.md +12 -0
- package/extensions/twitch/package.json +1 -1
- package/extensions/voice-call/CHANGELOG.md +12 -0
- package/extensions/voice-call/package.json +1 -1
- package/extensions/zalo/CHANGELOG.md +12 -0
- package/extensions/zalo/package.json +1 -1
- package/extensions/zalouser/CHANGELOG.md +12 -0
- package/extensions/zalouser/package.json +1 -1
- package/package.json +1 -1
|
@@ -2,6 +2,7 @@ import { CONFIG_DIR, isRecord, resolveUserPath } from "../../utils.js";
|
|
|
2
2
|
import { resolveFasedAgentPackageRootSync } from "../../infra/fased-root.js";
|
|
3
3
|
import { getPackageManifestMetadata } from "../../plugins/manifest.js";
|
|
4
4
|
import { discoverFasedAgentPlugins } from "../../plugins/discovery.js";
|
|
5
|
+
import { channelDeliveryAllowsInstall, getChannelDelivery } from "../delivery.js";
|
|
5
6
|
import fs from "node:fs";
|
|
6
7
|
import path from "node:path";
|
|
7
8
|
|
|
@@ -152,20 +153,22 @@ function buildCatalogEntry(candidate) {
|
|
|
152
153
|
if (!meta) {
|
|
153
154
|
return null;
|
|
154
155
|
}
|
|
156
|
+
const delivery = candidate.catalogSource === "official-catalog" ? "official-addon" : getChannelDelivery(id);
|
|
155
157
|
const install = resolveInstallInfo({
|
|
156
158
|
manifest,
|
|
157
159
|
packageName: candidate.packageName,
|
|
158
160
|
packageDir: candidate.packageDir,
|
|
159
161
|
workspaceDir: candidate.workspaceDir
|
|
160
162
|
});
|
|
161
|
-
if (!install) {
|
|
163
|
+
if (!install && channelDeliveryAllowsInstall(delivery)) {
|
|
162
164
|
return null;
|
|
163
165
|
}
|
|
164
166
|
return {
|
|
165
167
|
id,
|
|
166
168
|
meta,
|
|
169
|
+
delivery,
|
|
167
170
|
catalogSource: candidate.catalogSource,
|
|
168
|
-
install
|
|
171
|
+
install: channelDeliveryAllowsInstall(delivery) ? install ?? {} : {}
|
|
169
172
|
};
|
|
170
173
|
}
|
|
171
174
|
function buildExternalCatalogEntry(entry, catalogSource) {
|
|
@@ -201,7 +204,7 @@ function formatChannelPluginCatalogSource(source) {
|
|
|
201
204
|
}
|
|
202
205
|
}
|
|
203
206
|
function formatChannelPluginCatalogInstallBits(entry) {
|
|
204
|
-
const bits = [formatChannelPluginCatalogSource(entry.catalogSource)];
|
|
207
|
+
const bits = [entry.delivery, formatChannelPluginCatalogSource(entry.catalogSource)];
|
|
205
208
|
if (entry.install.expectedIntegrity) {
|
|
206
209
|
bits.push("integrity pinned");
|
|
207
210
|
}
|
|
@@ -211,10 +214,12 @@ function formatChannelPluginCatalogInstallBits(entry) {
|
|
|
211
214
|
return bits;
|
|
212
215
|
}
|
|
213
216
|
function formatChannelPluginCatalogSelectionHint(entry) {
|
|
214
|
-
|
|
217
|
+
const action = entry.delivery === "official-addon" ? "install" : entry.delivery === "bundled" ? "enable bundled" : "docs required";
|
|
218
|
+
return [...formatChannelPluginCatalogInstallBits(entry), action].join(" · ");
|
|
215
219
|
}
|
|
216
220
|
function formatChannelPluginCatalogStatusLine(entry) {
|
|
217
|
-
|
|
221
|
+
const next = entry.delivery === "official-addon" ? "install add-on to enable" : entry.delivery === "bundled" ? "enable bundled integration" : `follow ${entry.meta.docsPath}`;
|
|
222
|
+
return `${entry.meta.label}: ${formatChannelPluginCatalogInstallBits(entry).join(", ")}, ${next}`;
|
|
218
223
|
}
|
|
219
224
|
function buildChannelUiCatalog(plugins) {
|
|
220
225
|
const entries = plugins.map((plugin) => {
|
|
@@ -16,20 +16,23 @@ function registerComponentsCli(program) {
|
|
|
16
16
|
renderComponentReport(options);
|
|
17
17
|
});
|
|
18
18
|
components.command("install").description("Install a cataloged optional component").argument("<id>", "Component id from `fased components`").action(async (id) => {
|
|
19
|
-
|
|
20
|
-
id,
|
|
21
|
-
config: loadConfig()
|
|
22
|
-
});
|
|
23
|
-
await writeConfigFile(result.config);
|
|
24
|
-
for (const warning of result.slotWarnings) {
|
|
25
|
-
defaultRuntime.log(theme.warn(warning));
|
|
26
|
-
}
|
|
27
|
-
defaultRuntime.log(`Installed component: ${result.entry.label} (${result.entry.packageName})`);
|
|
28
|
-
if (result.entry.restartRequired !== false) {
|
|
29
|
-
defaultRuntime.log("Restart the gateway to apply the component.");
|
|
30
|
-
}
|
|
19
|
+
await installComponentCommand(id);
|
|
31
20
|
});
|
|
32
21
|
}
|
|
22
|
+
async function installComponentCommand(id) {
|
|
23
|
+
const result = await installCapabilityComponent({
|
|
24
|
+
id,
|
|
25
|
+
config: loadConfig()
|
|
26
|
+
});
|
|
27
|
+
await writeConfigFile(result.config);
|
|
28
|
+
for (const warning of result.slotWarnings) {
|
|
29
|
+
defaultRuntime.log(theme.warn(warning));
|
|
30
|
+
}
|
|
31
|
+
defaultRuntime.log(`Installed component: ${result.entry.label} (${result.entry.packageName})`);
|
|
32
|
+
if (result.entry.restartRequired !== false) {
|
|
33
|
+
defaultRuntime.log("Restart the gateway to apply the component.");
|
|
34
|
+
}
|
|
35
|
+
}
|
|
33
36
|
function renderComponentReport(options) {
|
|
34
37
|
const report = buildCapabilityReadinessReport();
|
|
35
38
|
if (options.json) {
|
|
@@ -80,4 +83,4 @@ function renderComponentReport(options) {
|
|
|
80
83
|
}
|
|
81
84
|
|
|
82
85
|
//#endregion
|
|
83
|
-
export { registerComponentsCli };
|
|
86
|
+
export { installComponentCommand, registerComponentsCli, renderComponentReport };
|
|
@@ -327,6 +327,15 @@ const entries = [
|
|
|
327
327
|
mod.registerComponentsCli(program);
|
|
328
328
|
}
|
|
329
329
|
},
|
|
330
|
+
{
|
|
331
|
+
name: "services",
|
|
332
|
+
description: "Inspect and connect optional services and runtimes",
|
|
333
|
+
hasSubcommands: true,
|
|
334
|
+
register: async (program) => {
|
|
335
|
+
const mod = await import("../services-cli.js");
|
|
336
|
+
mod.registerServicesCli(program);
|
|
337
|
+
}
|
|
338
|
+
},
|
|
330
339
|
{
|
|
331
340
|
name: "update",
|
|
332
341
|
description: "Update FasedAgent and inspect update channel status",
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import { theme } from "../terminal/theme.js";
|
|
2
|
-
import {
|
|
2
|
+
import { defaultRuntime } from "../runtime.js";
|
|
3
|
+
import { listAgentIds, resolveAgentDir, resolveDefaultAgentId } from "../agents/agent-scope.js";
|
|
3
4
|
import { getProviderBrandManifestForRoute } from "../providers/registry.js";
|
|
4
|
-
import { loadAuthProfileStoreForRuntime } from "../agents/auth-profiles/store.js";
|
|
5
|
+
import { ensureAuthProfileStore, loadAuthProfileStoreForRuntime } from "../agents/auth-profiles/store.js";
|
|
5
6
|
import { loadConfig, writeConfigFile } from "../config/io.js";
|
|
6
7
|
import "../config/config.js";
|
|
7
8
|
import "../agents/auth-profiles.js";
|
|
9
|
+
import { ensureFasedModelsJson } from "../agents/models-config.js";
|
|
8
10
|
import { applyProviderRefreshToRegistrySource, buildProviderCapabilityOverridesSource, buildProviderRefreshEnvFromCredentials, buildProviderRefreshReport, buildProviderRegistryReviewPatch, fetchOfficialProviderRefreshSnapshot, loadProviderRefreshSnapshotFromFile } from "../providers/refresh.js";
|
|
11
|
+
import { buildAuthChoiceGroups } from "../commands/auth-choice-options.js";
|
|
9
12
|
import { createClackPrompter } from "../wizard/clack-prompter.js";
|
|
10
13
|
import path from "node:path";
|
|
11
14
|
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
@@ -106,11 +109,13 @@ async function providersModelsAddCommand(options) {
|
|
|
106
109
|
...options.api?.trim() ? { api: options.api.trim() } : {},
|
|
107
110
|
models: nextModels
|
|
108
111
|
};
|
|
109
|
-
|
|
112
|
+
const nextConfig = upsertProviderModelConfig({
|
|
110
113
|
cfg,
|
|
111
114
|
providerId,
|
|
112
115
|
providerConfig: nextProvider
|
|
113
|
-
})
|
|
116
|
+
});
|
|
117
|
+
await writeConfigFile(nextConfig);
|
|
118
|
+
await ensureFasedModelsJson(nextConfig);
|
|
114
119
|
console.log(`${theme.success("Model saved:")} ${providerId}/${model.id}`);
|
|
115
120
|
}
|
|
116
121
|
async function providersModelsRemoveCommand(options) {
|
|
@@ -125,14 +130,16 @@ async function providersModelsRemoveCommand(options) {
|
|
|
125
130
|
if (nextModels.length === (existing.models ?? []).length) {
|
|
126
131
|
throw new Error(`Model "${providerId}/${modelId}" is not configured.`);
|
|
127
132
|
}
|
|
128
|
-
|
|
133
|
+
const nextConfig = upsertProviderModelConfig({
|
|
129
134
|
cfg,
|
|
130
135
|
providerId,
|
|
131
136
|
providerConfig: {
|
|
132
137
|
...existing,
|
|
133
138
|
models: nextModels
|
|
134
139
|
}
|
|
135
|
-
})
|
|
140
|
+
});
|
|
141
|
+
await writeConfigFile(nextConfig);
|
|
142
|
+
await ensureFasedModelsJson(nextConfig);
|
|
136
143
|
console.log(`${theme.success("Model removed:")} ${providerId}/${modelId}`);
|
|
137
144
|
}
|
|
138
145
|
async function providersModelsListCommand(options) {
|
|
@@ -353,6 +360,13 @@ async function providersRefreshCommand(options) {
|
|
|
353
360
|
}
|
|
354
361
|
function registerProvidersCli(program) {
|
|
355
362
|
const providers = program.command("providers").description("Review provider manifests and model catalogs");
|
|
363
|
+
providers.command("connect").description("Connect a model provider using the same auth flow as onboarding and the UI").argument("[provider]", "Public provider id, for example openai or anthropic").option("--method <id>", "Credential method id").option("--set-default", "Apply the provider's recommended default model", false).action(async (provider, options) => {
|
|
364
|
+
await providersConnectCommand({
|
|
365
|
+
provider,
|
|
366
|
+
method: options.method,
|
|
367
|
+
setDefault: options.setDefault === true
|
|
368
|
+
});
|
|
369
|
+
});
|
|
356
370
|
providers.command("refresh").description("Compare provider registry against official/source catalogs").option("--from-file <path>", "Use a provider refresh snapshot JSON file").option("--json", "Output JSON", false).option("--write-review [path]", "Write a review patch instead of applying changes").option("--apply", "Apply model-list updates to src/providers/registry.ts", false).option("--wizard", "Choose report/review/apply from an interactive wizard", false).option("--no-network", "Do not fetch official provider docs; report local registry only").action(async (opts) => {
|
|
357
371
|
await providersRefreshCommand({
|
|
358
372
|
fromFile: opts.fromFile,
|
|
@@ -392,6 +406,65 @@ function registerProvidersCli(program) {
|
|
|
392
406
|
});
|
|
393
407
|
});
|
|
394
408
|
}
|
|
409
|
+
async function providersConnectCommand(options) {
|
|
410
|
+
if (!process.stdin.isTTY) {
|
|
411
|
+
throw new Error("providers connect requires an interactive TTY.");
|
|
412
|
+
}
|
|
413
|
+
const config = loadConfig();
|
|
414
|
+
const [{ applyAuthChoice }, { openUrl }] = await Promise.all([import("../commands/auth-choice.js"), import("../commands/onboard-helpers.js")]);
|
|
415
|
+
const agentId = resolveDefaultAgentId(config);
|
|
416
|
+
const agentDir = resolveAgentDir(config, agentId);
|
|
417
|
+
const store = ensureAuthProfileStore(agentDir, { allowKeychainPrompt: false });
|
|
418
|
+
const { groups } = buildAuthChoiceGroups({
|
|
419
|
+
store,
|
|
420
|
+
includeSkip: false
|
|
421
|
+
});
|
|
422
|
+
const requestedProvider = options.provider?.trim().toLowerCase();
|
|
423
|
+
const prompter = createClackPrompter();
|
|
424
|
+
let selectedGroup = requestedProvider ? groups.find((candidate) => String(candidate.value).toLowerCase() === requestedProvider || candidate.label.toLowerCase() === requestedProvider) : undefined;
|
|
425
|
+
if (!requestedProvider) {
|
|
426
|
+
const selectedProvider = await prompter.select({
|
|
427
|
+
message: "Model provider",
|
|
428
|
+
options: groups.map((candidate) => ({
|
|
429
|
+
value: candidate.value,
|
|
430
|
+
label: candidate.label,
|
|
431
|
+
hint: candidate.hint
|
|
432
|
+
}))
|
|
433
|
+
});
|
|
434
|
+
selectedGroup = groups.find((candidate) => String(candidate.value) === String(selectedProvider));
|
|
435
|
+
}
|
|
436
|
+
if (!selectedGroup) {
|
|
437
|
+
throw new Error(`Unknown provider: ${options.provider}. Run \`fased providers connect\` to choose.`);
|
|
438
|
+
}
|
|
439
|
+
const requestedMethod = options.method?.trim();
|
|
440
|
+
let method = requestedMethod ? selectedGroup.options.find((candidate) => String(candidate.value) === requestedMethod) : selectedGroup.options.length === 1 ? selectedGroup.options[0] : undefined;
|
|
441
|
+
if (!requestedMethod && selectedGroup.options.length > 1) {
|
|
442
|
+
const selectedMethod = await prompter.select({
|
|
443
|
+
message: `${selectedGroup.label} auth method`,
|
|
444
|
+
options: selectedGroup.options
|
|
445
|
+
});
|
|
446
|
+
method = selectedGroup.options.find((candidate) => String(candidate.value) === String(selectedMethod));
|
|
447
|
+
}
|
|
448
|
+
if (!method) {
|
|
449
|
+
throw new Error(`Unknown auth method for ${selectedGroup.label}: ${options.method ?? "(none)"}`);
|
|
450
|
+
}
|
|
451
|
+
const result = await applyAuthChoice({
|
|
452
|
+
authChoice: method.value,
|
|
453
|
+
config,
|
|
454
|
+
prompter,
|
|
455
|
+
runtime: defaultRuntime,
|
|
456
|
+
openUrl: async (url) => {
|
|
457
|
+
await openUrl(url);
|
|
458
|
+
},
|
|
459
|
+
agentDir,
|
|
460
|
+
agentId,
|
|
461
|
+
setDefaultModel: options.setDefault === true,
|
|
462
|
+
opts: {}
|
|
463
|
+
});
|
|
464
|
+
await writeConfigFile(result.config);
|
|
465
|
+
await ensureFasedModelsJson(result.config, agentDir);
|
|
466
|
+
defaultRuntime.log(`${theme.success("Provider connected:")} ${selectedGroup.label}`);
|
|
467
|
+
}
|
|
395
468
|
|
|
396
469
|
//#endregion
|
|
397
470
|
export { registerProvidersCli };
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { theme } from "../terminal/theme.js";
|
|
2
|
+
import { defaultRuntime } from "../runtime.js";
|
|
3
|
+
import { formatDocsLink } from "../terminal/links.js";
|
|
4
|
+
import { buildCapabilityReadinessReport } from "../capabilities/catalog.js";
|
|
5
|
+
import { installComponentCommand, renderComponentReport } from "./components-cli.js";
|
|
6
|
+
|
|
7
|
+
//#region src/cli/services-cli.ts
|
|
8
|
+
function registerServicesCli(program) {
|
|
9
|
+
const services = program.command("services").description("Inspect and connect optional services and runtimes");
|
|
10
|
+
services.command("status").description("Show service and component readiness").option("--json", "Output JSON", false).action((options) => renderComponentReport(options));
|
|
11
|
+
services.command("install").description("Install an official optional component").argument("<id>", "Component id from `fased services status`").action(async (id) => installComponentCommand(id));
|
|
12
|
+
services.command("connect").description("Install when supported, or show the canonical connection surface").argument("<id>", "Component id from `fased services status`").action(async (id) => {
|
|
13
|
+
const entry = buildCapabilityReadinessReport().entries.find((candidate) => candidate.id === id.trim());
|
|
14
|
+
if (!entry) {
|
|
15
|
+
throw new Error(`Unknown service component: ${id}. Run \`fased services status\`.`);
|
|
16
|
+
}
|
|
17
|
+
if (entry.delivery === "npm-addon" && entry.state === "not-installed") {
|
|
18
|
+
await installComponentCommand(entry.id);
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
defaultRuntime.log(`${theme.heading(entry.label)}: ${entry.detail}`);
|
|
22
|
+
defaultRuntime.log(`Connect from: ${entry.surface}`);
|
|
23
|
+
defaultRuntime.log(`Docs: ${formatDocsLink(entry.docsPath, `docs.fased.ai${entry.docsPath}`)}`);
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
//#endregion
|
|
28
|
+
export { registerServicesCli };
|
|
@@ -2,4 +2,4 @@ import { applyAuthChoice } from "./auth-choice.apply.js";
|
|
|
2
2
|
import { warnIfModelConfigLooksOff } from "./auth-choice.model-check.js";
|
|
3
3
|
import { resolvePreferredProviderForAuthChoice } from "./auth-choice.preferred-provider.js";
|
|
4
4
|
|
|
5
|
-
export {
|
|
5
|
+
export { applyAuthChoice, resolvePreferredProviderForAuthChoice, warnIfModelConfigLooksOff };
|
|
@@ -10,6 +10,11 @@ import { formatRemainingShort } from "../../agents/auth-health.js";
|
|
|
10
10
|
import "./list.format.js";
|
|
11
11
|
|
|
12
12
|
//#region src/commands/models/list.auth-overview.ts
|
|
13
|
+
const LOCAL_PROVIDER_IDS = new Set([
|
|
14
|
+
"ollama",
|
|
15
|
+
"lmstudio",
|
|
16
|
+
"vllm"
|
|
17
|
+
]);
|
|
13
18
|
function formatProfileSecretLabel(params) {
|
|
14
19
|
const value = typeof params.value === "string" ? params.value.trim() : "";
|
|
15
20
|
if (value) {
|
|
@@ -69,6 +74,13 @@ function resolveProviderAuthOverview(params) {
|
|
|
69
74
|
const envKey = resolveEnvApiKey(provider);
|
|
70
75
|
const customKey = getCustomProviderApiKey(cfg, provider);
|
|
71
76
|
const effective = (() => {
|
|
77
|
+
const providerConfig = cfg.models?.providers?.[provider];
|
|
78
|
+
if (LOCAL_PROVIDER_IDS.has(provider) && providerConfig?.baseUrl?.trim()) {
|
|
79
|
+
return {
|
|
80
|
+
kind: "local",
|
|
81
|
+
detail: providerConfig.baseUrl.trim()
|
|
82
|
+
};
|
|
83
|
+
}
|
|
72
84
|
if (profiles.length > 0) {
|
|
73
85
|
return {
|
|
74
86
|
kind: "profiles",
|
|
@@ -6,6 +6,7 @@ import { getChannelPlugin, listChannelPlugins } from "../channels/plugins/index.
|
|
|
6
6
|
import { formatChannelPrimerLine, formatChannelSelectionLine, listChatChannels } from "../channels/registry.js";
|
|
7
7
|
import { enablePluginInConfig } from "../plugins/enable.js";
|
|
8
8
|
import { formatDocsLink } from "../terminal/links.js";
|
|
9
|
+
import { channelDeliveryAllowsInstall, formatChannelDelivery } from "../channels/delivery.js";
|
|
9
10
|
import { formatChannelPluginCatalogSelectionHint, formatChannelPluginCatalogStatusLine, listChannelPluginCatalogEntries } from "../channels/plugins/catalog.js";
|
|
10
11
|
import { isChannelConfigured } from "../config/plugin-auto-enable.js";
|
|
11
12
|
import { resolveChannelDefaultAccountId } from "../channels/plugins/helpers.js";
|
|
@@ -492,6 +493,10 @@ async function setupChannels(cfg, runtime, prompter, options) {
|
|
|
492
493
|
const { catalogById } = getChannelEntries();
|
|
493
494
|
const catalogEntry = catalogById.get(channel);
|
|
494
495
|
if (catalogEntry) {
|
|
496
|
+
if (!channelDeliveryAllowsInstall(catalogEntry.delivery)) {
|
|
497
|
+
await prompter.note(`${catalogEntry.meta.label} is ${formatChannelDelivery(catalogEntry.delivery).toLowerCase()}. Follow ${catalogEntry.meta.docsPath}; onboarding cannot install it from npm.`, "Channel delivery");
|
|
498
|
+
return;
|
|
499
|
+
}
|
|
495
500
|
const workspaceDir = resolveAgentWorkspaceDir(next, resolveDefaultAgentId(next));
|
|
496
501
|
const result = await ensureOnboardingPluginInstalled({
|
|
497
502
|
cfg: next,
|
|
@@ -460,4 +460,4 @@ function resolveControlUiLinks(params) {
|
|
|
460
460
|
}
|
|
461
461
|
|
|
462
462
|
//#endregion
|
|
463
|
-
export { DEFAULT_WORKSPACE, applyWizardMetadata, detectBinary, detectBrowserOpenSupport, ensureWorkspaceAndSessions, formatControlUiSshHint, guardCancel, handleOnboardingRepair, handleReset, moveToTrash, normalizeGatewayTokenInput, openUrl, printWizardHeader, probeGatewayReachable, randomToken, resolveControlUiLinks, resolveNodeManagerOptions, summarizeExistingConfig, validateGatewayPasswordInput, waitForGatewayReachable };
|
|
463
|
+
export { DEFAULT_WORKSPACE, applyWizardMetadata, detectBinary, detectBrowserOpenSupport, ensureWorkspaceAndSessions, formatControlUiSshHint, guardCancel, handleOnboardingRepair, handleReset, moveToTrash, normalizeGatewayTokenInput, openUrl, openUrlInBackground, printWizardHeader, probeGatewayReachable, randomToken, resolveBrowserOpenCommand, resolveControlUiLinks, resolveNodeManagerOptions, summarizeExistingConfig, validateGatewayPasswordInput, waitForGatewayReachable };
|
|
@@ -20,6 +20,15 @@ function resolveLmStudioBaseUrl(value) {
|
|
|
20
20
|
const trimmed = value.trim().replace(/\/+$/, "");
|
|
21
21
|
return /\/v1$/i.test(trimmed) ? trimmed : `${trimmed}/v1`;
|
|
22
22
|
}
|
|
23
|
+
function normalizeLocalProviderModelId(provider, value) {
|
|
24
|
+
const normalizedProvider = provider.trim().toLowerCase();
|
|
25
|
+
let modelId = value.trim();
|
|
26
|
+
const prefix = `${normalizedProvider}/`;
|
|
27
|
+
while (normalizedProvider && modelId.toLowerCase().startsWith(prefix)) {
|
|
28
|
+
modelId = modelId.slice(prefix.length).trim();
|
|
29
|
+
}
|
|
30
|
+
return modelId;
|
|
31
|
+
}
|
|
23
32
|
function localModelDefinition(params) {
|
|
24
33
|
const modelId = params.id.trim();
|
|
25
34
|
const lower = modelId.toLowerCase();
|
|
@@ -37,7 +46,7 @@ function localModelDefinition(params) {
|
|
|
37
46
|
async function configureVllmProvider(params) {
|
|
38
47
|
const baseUrl = params.baseUrl.trim().replace(/\/+$/, "");
|
|
39
48
|
const apiKey = params.apiKey.trim();
|
|
40
|
-
const modelId = params.modelId
|
|
49
|
+
const modelId = normalizeLocalProviderModelId("vllm", params.modelId);
|
|
41
50
|
if (!baseUrl || !apiKey || !modelId) {
|
|
42
51
|
throw new Error("vLLM setup requires base URL, API key or placeholder, and model ID.");
|
|
43
52
|
}
|
|
@@ -77,7 +86,7 @@ async function configureVllmProvider(params) {
|
|
|
77
86
|
async function configureOllamaProvider(params) {
|
|
78
87
|
const baseUrl = resolveOllamaBaseUrl(params.baseUrl || OLLAMA_DEFAULT_BASE_URL);
|
|
79
88
|
const apiKey = params.apiKey?.trim() || "ollama-local";
|
|
80
|
-
const modelId = params.modelId
|
|
89
|
+
const modelId = normalizeLocalProviderModelId("ollama", params.modelId);
|
|
81
90
|
if (!baseUrl || !modelId) {
|
|
82
91
|
throw new Error("Ollama setup requires base URL and model ID.");
|
|
83
92
|
}
|
|
@@ -117,7 +126,7 @@ async function configureOllamaProvider(params) {
|
|
|
117
126
|
async function configureLmStudioProvider(params) {
|
|
118
127
|
const baseUrl = resolveLmStudioBaseUrl(params.baseUrl || LMSTUDIO_DEFAULT_BASE_URL);
|
|
119
128
|
const apiKey = params.apiKey?.trim() || "lmstudio-local";
|
|
120
|
-
const modelId = params.modelId
|
|
129
|
+
const modelId = normalizeLocalProviderModelId("lmstudio", params.modelId);
|
|
121
130
|
if (!baseUrl || !modelId) {
|
|
122
131
|
throw new Error("LM Studio setup requires base URL and model ID.");
|
|
123
132
|
}
|