@trops/dash-core 0.1.611 → 0.1.613
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/electron/index.js +173 -6
- package/dist/electron/index.js.map +1 -1
- package/dist/index.esm.js +195 -23
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +195 -23
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -46051,6 +46051,55 @@ var NewProviderPicker = function NewProviderPicker(_ref2) {
|
|
|
46051
46051
|
});
|
|
46052
46052
|
};
|
|
46053
46053
|
|
|
46054
|
+
/**
|
|
46055
|
+
* providerType.js
|
|
46056
|
+
*
|
|
46057
|
+
* Helpers for assigning a stable, UNIQUE `type` to a provider.
|
|
46058
|
+
*
|
|
46059
|
+
* A provider's identity in the widget system is its `type` string (widgets
|
|
46060
|
+
* declare `requiredProviders: [{ type }]`, runtime resolves by type). Catalog
|
|
46061
|
+
* providers each carry a unique type (`slack`, `github`, …). Hand-rolled
|
|
46062
|
+
* custom MCP servers historically all shared `type: "custom"`, which conflates
|
|
46063
|
+
* multiple customs at binding/runtime. These helpers give each NEW custom
|
|
46064
|
+
* provider a unique slug derived from its name so it behaves like a catalog
|
|
46065
|
+
* provider.
|
|
46066
|
+
*
|
|
46067
|
+
* Forward-only: existing providers are never renamed here (that would break
|
|
46068
|
+
* widgets already built against their type). Only the create path uses this.
|
|
46069
|
+
*/
|
|
46070
|
+
|
|
46071
|
+
/**
|
|
46072
|
+
* Convert a provider name into a kebab-case type slug.
|
|
46073
|
+
* "My Granola Server" → "my-granola-server". Falls back to a sane default
|
|
46074
|
+
* when the name has no slug-able characters.
|
|
46075
|
+
*/
|
|
46076
|
+
function slugifyProviderType(name) {
|
|
46077
|
+
var slug = String(name || "").toLowerCase().trim().replace(/[^\w\s-]/g, "") // drop punctuation/symbols
|
|
46078
|
+
.replace(/[\s_]+/g, "-") // whitespace/underscores → hyphen
|
|
46079
|
+
.replace(/-+/g, "-") // collapse repeats
|
|
46080
|
+
.replace(/^-+|-+$/g, ""); // trim hyphens
|
|
46081
|
+
return slug || "custom-provider";
|
|
46082
|
+
}
|
|
46083
|
+
|
|
46084
|
+
/**
|
|
46085
|
+
* Produce a slug type unique against the already-configured provider types.
|
|
46086
|
+
* Appends `-2`, `-3`, … on collision so two providers can never share a type.
|
|
46087
|
+
*
|
|
46088
|
+
* @param {string} name provider instance name
|
|
46089
|
+
* @param {Iterable<string>} existingTypes types already in use (e.g.
|
|
46090
|
+
* Object.values(providers).map(p => p.type))
|
|
46091
|
+
* @returns {string}
|
|
46092
|
+
*/
|
|
46093
|
+
function uniqueProviderType(name) {
|
|
46094
|
+
var existingTypes = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
|
|
46095
|
+
var base = slugifyProviderType(name);
|
|
46096
|
+
var taken = new Set(existingTypes || []);
|
|
46097
|
+
if (!taken.has(base)) return base;
|
|
46098
|
+
var i = 2;
|
|
46099
|
+
while (taken.has("".concat(base, "-").concat(i))) i++;
|
|
46100
|
+
return "".concat(base, "-").concat(i);
|
|
46101
|
+
}
|
|
46102
|
+
|
|
46054
46103
|
var ProvidersSection = function ProvidersSection(_ref) {
|
|
46055
46104
|
var _ref$dashApi = _ref.dashApi,
|
|
46056
46105
|
dashApi = _ref$dashApi === void 0 ? null : _ref$dashApi,
|
|
@@ -46275,8 +46324,21 @@ var ProvidersSection = function ProvidersSection(_ref) {
|
|
|
46275
46324
|
function handleMcpSave(providerName, providerType, mcpCredentials, mcpConfig) {
|
|
46276
46325
|
var allowedTools = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : null;
|
|
46277
46326
|
if (!dashApi || !appId) return;
|
|
46327
|
+
// Forward-only unique types: a hand-rolled custom MCP server arrives with
|
|
46328
|
+
// the generic default type "custom", which conflates multiple customs at
|
|
46329
|
+
// widget-binding/runtime time. Give each NEW one a unique slug so it has a
|
|
46330
|
+
// distinct identity like catalog providers. Catalog installs pass a real
|
|
46331
|
+
// id (not "custom") and are untouched; the edit path preserves type, so no
|
|
46332
|
+
// existing provider is ever renamed.
|
|
46333
|
+
var resolvedType = providerType;
|
|
46334
|
+
if (resolvedType === "custom") {
|
|
46335
|
+
var existingTypes = Object.values(providers || {}).map(function (p) {
|
|
46336
|
+
return p.type;
|
|
46337
|
+
});
|
|
46338
|
+
resolvedType = uniqueProviderType(providerName, existingTypes);
|
|
46339
|
+
}
|
|
46278
46340
|
dashApi.saveProvider(appId, providerName, {
|
|
46279
|
-
providerType:
|
|
46341
|
+
providerType: resolvedType,
|
|
46280
46342
|
credentials: mcpCredentials,
|
|
46281
46343
|
providerClass: "mcp",
|
|
46282
46344
|
mcpConfig: mcpConfig,
|
|
@@ -52196,18 +52258,35 @@ var McpServerSection = function McpServerSection() {
|
|
|
52196
52258
|
});
|
|
52197
52259
|
};
|
|
52198
52260
|
|
|
52261
|
+
/**
|
|
52262
|
+
* modelMigration.js (renderer mirror)
|
|
52263
|
+
*
|
|
52264
|
+
* Mirrors the retired-model map + default from the main-process provider
|
|
52265
|
+
* registry (electron/llm/modelProviders.js) so the Settings UI can detect a
|
|
52266
|
+
* stale saved selection, auto-migrate it, and show a notice — without an IPC
|
|
52267
|
+
* round-trip. KEEP IN SYNC with modelProviders.js (anthropic provider).
|
|
52268
|
+
*/
|
|
52269
|
+
var DEFAULT_MODEL = "claude-opus-4-8";
|
|
52270
|
+
var RETIRED_MODEL_MAP = {
|
|
52271
|
+
"claude-sonnet-4-20250514": "claude-sonnet-4-6",
|
|
52272
|
+
"claude-opus-4-20250514": "claude-opus-4-8",
|
|
52273
|
+
"claude-opus-4-1-20250805": "claude-opus-4-8",
|
|
52274
|
+
"claude-3-7-sonnet-20250219": "claude-sonnet-4-6",
|
|
52275
|
+
"claude-3-5-sonnet-20241022": "claude-sonnet-4-6",
|
|
52276
|
+
"claude-3-5-sonnet-20240620": "claude-sonnet-4-6",
|
|
52277
|
+
"claude-3-5-haiku-20241022": "claude-haiku-4-5",
|
|
52278
|
+
"claude-3-opus-20240229": "claude-opus-4-8"
|
|
52279
|
+
};
|
|
52280
|
+
function isRetiredModel(id) {
|
|
52281
|
+
return !!RETIRED_MODEL_MAP[id];
|
|
52282
|
+
}
|
|
52283
|
+
function migrateModelId(id) {
|
|
52284
|
+
if (!id) return DEFAULT_MODEL;
|
|
52285
|
+
return RETIRED_MODEL_MAP[id] || id;
|
|
52286
|
+
}
|
|
52287
|
+
|
|
52199
52288
|
function ownKeys$m(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
52200
52289
|
function _objectSpread$m(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys$m(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys$m(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
52201
|
-
var MODELS = [{
|
|
52202
|
-
value: "claude-sonnet-4-20250514",
|
|
52203
|
-
label: "Claude Sonnet 4"
|
|
52204
|
-
}, {
|
|
52205
|
-
value: "claude-opus-4-20250514",
|
|
52206
|
-
label: "Claude Opus 4"
|
|
52207
|
-
}, {
|
|
52208
|
-
value: "claude-haiku-4-5-20251001",
|
|
52209
|
-
label: "Claude Haiku 4.5"
|
|
52210
|
-
}];
|
|
52211
52290
|
var BACKENDS = [{
|
|
52212
52291
|
value: "claude-code",
|
|
52213
52292
|
label: "Claude Code CLI"
|
|
@@ -52216,6 +52295,7 @@ var BACKENDS = [{
|
|
|
52216
52295
|
label: "Anthropic API"
|
|
52217
52296
|
}];
|
|
52218
52297
|
var AiAssistantSection = function AiAssistantSection() {
|
|
52298
|
+
var _anthropicProvider$;
|
|
52219
52299
|
var appContext = React.useContext(AppContext);
|
|
52220
52300
|
var settings = (appContext === null || appContext === void 0 ? void 0 : appContext.settings) || {};
|
|
52221
52301
|
var providers = (appContext === null || appContext === void 0 ? void 0 : appContext.providers) || {};
|
|
@@ -52233,7 +52313,7 @@ var AiAssistantSection = function AiAssistantSection() {
|
|
|
52233
52313
|
_useState4 = _slicedToArray(_useState3, 2),
|
|
52234
52314
|
preferredBackend = _useState4[0],
|
|
52235
52315
|
setPreferredBackend = _useState4[1];
|
|
52236
|
-
var _useState5 = React.useState(aiSettings.model ||
|
|
52316
|
+
var _useState5 = React.useState(aiSettings.model || DEFAULT_MODEL),
|
|
52237
52317
|
_useState6 = _slicedToArray(_useState5, 2),
|
|
52238
52318
|
selectedModel = _useState6[0],
|
|
52239
52319
|
setSelectedModel = _useState6[1];
|
|
@@ -52250,6 +52330,21 @@ var AiAssistantSection = function AiAssistantSection() {
|
|
|
52250
52330
|
saveKeyStatus = _useState10[0],
|
|
52251
52331
|
setSaveKeyStatus = _useState10[1];
|
|
52252
52332
|
|
|
52333
|
+
// Provider-pluggable model discovery (live fetch + curated fallback)
|
|
52334
|
+
var _useState11 = React.useState([]),
|
|
52335
|
+
_useState12 = _slicedToArray(_useState11, 2),
|
|
52336
|
+
availableModels = _useState12[0],
|
|
52337
|
+
setAvailableModels = _useState12[1];
|
|
52338
|
+
var _useState13 = React.useState(false),
|
|
52339
|
+
_useState14 = _slicedToArray(_useState13, 2),
|
|
52340
|
+
modelsLoading = _useState14[0],
|
|
52341
|
+
setModelsLoading = _useState14[1];
|
|
52342
|
+
// One-time notice when a retired saved model was auto-migrated
|
|
52343
|
+
var _useState15 = React.useState(null),
|
|
52344
|
+
_useState16 = _slicedToArray(_useState15, 2),
|
|
52345
|
+
migrationNotice = _useState16[0],
|
|
52346
|
+
setMigrationNotice = _useState16[1];
|
|
52347
|
+
|
|
52253
52348
|
// Find existing Anthropic provider
|
|
52254
52349
|
var anthropicProvider = Object.entries(providers).find(function (_ref) {
|
|
52255
52350
|
var _ref2 = _slicedToArray(_ref, 2),
|
|
@@ -52258,6 +52353,9 @@ var AiAssistantSection = function AiAssistantSection() {
|
|
|
52258
52353
|
});
|
|
52259
52354
|
var hasAnthropicProvider = !!anthropicProvider;
|
|
52260
52355
|
var anthropicProviderName = anthropicProvider === null || anthropicProvider === void 0 ? void 0 : anthropicProvider[0];
|
|
52356
|
+
// Decrypted key (when AppContext exposes it) enables the live Models API
|
|
52357
|
+
// fetch; without it, listModels returns the curated fallback list.
|
|
52358
|
+
var anthropicApiKey = (anthropicProvider === null || anthropicProvider === void 0 || (_anthropicProvider$ = anthropicProvider[1]) === null || _anthropicProvider$ === void 0 || (_anthropicProvider$ = _anthropicProvider$.credentials) === null || _anthropicProvider$ === void 0 ? void 0 : _anthropicProvider$.apiKey) || null;
|
|
52261
52359
|
|
|
52262
52360
|
// Check CLI availability on mount
|
|
52263
52361
|
React.useEffect(function () {
|
|
@@ -52279,6 +52377,28 @@ var AiAssistantSection = function AiAssistantSection() {
|
|
|
52279
52377
|
}
|
|
52280
52378
|
}, []);
|
|
52281
52379
|
|
|
52380
|
+
// Fetch selectable models for the current provider. With an API key the
|
|
52381
|
+
// main process does a live Anthropic Models API fetch; otherwise it returns
|
|
52382
|
+
// the curated fallback. Provider is "anthropic" for both current backends.
|
|
52383
|
+
var fetchModels = React.useCallback(function () {
|
|
52384
|
+
var _window$mainApi2;
|
|
52385
|
+
if (!((_window$mainApi2 = window.mainApi) !== null && _window$mainApi2 !== void 0 && (_window$mainApi2 = _window$mainApi2.llm) !== null && _window$mainApi2 !== void 0 && _window$mainApi2.listModels)) return;
|
|
52386
|
+
setModelsLoading(true);
|
|
52387
|
+
window.mainApi.llm.listModels("anthropic", anthropicApiKey).then(function (res) {
|
|
52388
|
+
return setAvailableModels(res && res.models || []);
|
|
52389
|
+
})["catch"](function () {
|
|
52390
|
+
return setAvailableModels([]);
|
|
52391
|
+
})["finally"](function () {
|
|
52392
|
+
return setModelsLoading(false);
|
|
52393
|
+
});
|
|
52394
|
+
}, [anthropicApiKey]);
|
|
52395
|
+
|
|
52396
|
+
// Load models on mount and whenever the available API key changes (so the
|
|
52397
|
+
// list upgrades from curated → live once a key is configured).
|
|
52398
|
+
React.useEffect(function () {
|
|
52399
|
+
fetchModels();
|
|
52400
|
+
}, [fetchModels]);
|
|
52401
|
+
|
|
52282
52402
|
// Save AI settings to app settings
|
|
52283
52403
|
var saveAiSettings = React.useCallback(function (updates) {
|
|
52284
52404
|
if (appContext !== null && appContext !== void 0 && appContext.changeSettings) {
|
|
@@ -52289,6 +52409,24 @@ var AiAssistantSection = function AiAssistantSection() {
|
|
|
52289
52409
|
}));
|
|
52290
52410
|
}
|
|
52291
52411
|
}, [appContext]);
|
|
52412
|
+
|
|
52413
|
+
// Auto-migrate a retired saved model to its current replacement (one-time,
|
|
52414
|
+
// on mount) so an old selection can't 404 the assistant. Shows a notice.
|
|
52415
|
+
React.useEffect(function () {
|
|
52416
|
+
var saved = aiSettings.model;
|
|
52417
|
+
if (saved && isRetiredModel(saved)) {
|
|
52418
|
+
var replacement = migrateModelId(saved);
|
|
52419
|
+
setSelectedModel(replacement);
|
|
52420
|
+
saveAiSettings({
|
|
52421
|
+
model: replacement
|
|
52422
|
+
});
|
|
52423
|
+
setMigrationNotice({
|
|
52424
|
+
from: saved,
|
|
52425
|
+
to: replacement
|
|
52426
|
+
});
|
|
52427
|
+
}
|
|
52428
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
52429
|
+
}, []);
|
|
52292
52430
|
function handleBackendChange(e) {
|
|
52293
52431
|
var value = e.target.value;
|
|
52294
52432
|
setPreferredBackend(value);
|
|
@@ -52332,6 +52470,15 @@ var AiAssistantSection = function AiAssistantSection() {
|
|
|
52332
52470
|
});
|
|
52333
52471
|
}
|
|
52334
52472
|
|
|
52473
|
+
// Model dropdown options — keep the current selection selectable even if it
|
|
52474
|
+
// isn't in the fetched list (e.g. a pinned/custom id).
|
|
52475
|
+
var modelOptions = selectedModel && !availableModels.some(function (m) {
|
|
52476
|
+
return m.value === selectedModel;
|
|
52477
|
+
}) ? [{
|
|
52478
|
+
value: selectedModel,
|
|
52479
|
+
label: selectedModel
|
|
52480
|
+
}].concat(_toConsumableArray(availableModels)) : availableModels;
|
|
52481
|
+
|
|
52335
52482
|
// Determine effective backend (what will actually be used)
|
|
52336
52483
|
var effectiveBackend = preferredBackend === "claude-code" && cliStatus !== null && cliStatus !== void 0 && cliStatus.available ? "claude-code" : preferredBackend === "anthropic" && hasAnthropicProvider ? "anthropic" : cliStatus !== null && cliStatus !== void 0 && cliStatus.available ? "claude-code" : hasAnthropicProvider ? "anthropic" : null;
|
|
52337
52484
|
return /*#__PURE__*/jsxRuntime.jsxs("div", {
|
|
@@ -52428,6 +52575,18 @@ var AiAssistantSection = function AiAssistantSection() {
|
|
|
52428
52575
|
}, b.value);
|
|
52429
52576
|
})
|
|
52430
52577
|
})]
|
|
52578
|
+
}), migrationNotice && /*#__PURE__*/jsxRuntime.jsxs("div", {
|
|
52579
|
+
className: "flex items-start gap-2 rounded-lg bg-yellow-900/30 border border-yellow-700 px-3 py-2 text-xs text-yellow-300",
|
|
52580
|
+
children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.FontAwesomeIcon, {
|
|
52581
|
+
icon: "exclamation-triangle",
|
|
52582
|
+
className: "h-3.5 w-3.5 mt-0.5"
|
|
52583
|
+
}), /*#__PURE__*/jsxRuntime.jsxs("span", {
|
|
52584
|
+
children: ["Your previously selected model (", /*#__PURE__*/jsxRuntime.jsx("code", {
|
|
52585
|
+
children: migrationNotice.from
|
|
52586
|
+
}), ") is no longer available. Switched to ", /*#__PURE__*/jsxRuntime.jsx("code", {
|
|
52587
|
+
children: migrationNotice.to
|
|
52588
|
+
}), "."]
|
|
52589
|
+
})]
|
|
52431
52590
|
}), /*#__PURE__*/jsxRuntime.jsxs("div", {
|
|
52432
52591
|
className: "flex flex-row items-center justify-between py-1",
|
|
52433
52592
|
children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
|
|
@@ -52437,18 +52596,31 @@ var AiAssistantSection = function AiAssistantSection() {
|
|
|
52437
52596
|
children: "Model"
|
|
52438
52597
|
}), /*#__PURE__*/jsxRuntime.jsx("span", {
|
|
52439
52598
|
className: "text-xs opacity-50",
|
|
52440
|
-
children: "
|
|
52599
|
+
children: "Model for AI Assistant conversations"
|
|
52600
|
+
})]
|
|
52601
|
+
}), /*#__PURE__*/jsxRuntime.jsxs("div", {
|
|
52602
|
+
className: "flex items-center gap-2",
|
|
52603
|
+
children: [/*#__PURE__*/jsxRuntime.jsx("select", {
|
|
52604
|
+
value: selectedModel,
|
|
52605
|
+
onChange: handleModelChange,
|
|
52606
|
+
className: "bg-white/10 border border-white/10 rounded-md px-3 py-1.5 text-sm text-gray-200 focus:outline-none focus:ring-1 focus:ring-blue-500",
|
|
52607
|
+
children: modelOptions.map(function (m) {
|
|
52608
|
+
return /*#__PURE__*/jsxRuntime.jsx("option", {
|
|
52609
|
+
value: m.value,
|
|
52610
|
+
children: m.label
|
|
52611
|
+
}, m.value);
|
|
52612
|
+
})
|
|
52613
|
+
}), /*#__PURE__*/jsxRuntime.jsx("button", {
|
|
52614
|
+
type: "button",
|
|
52615
|
+
onClick: fetchModels,
|
|
52616
|
+
disabled: modelsLoading,
|
|
52617
|
+
title: "Refresh available models",
|
|
52618
|
+
className: "text-gray-400 hover:text-gray-200 disabled:opacity-40 transition-colors p-1.5",
|
|
52619
|
+
children: /*#__PURE__*/jsxRuntime.jsx(DashReact.FontAwesomeIcon, {
|
|
52620
|
+
icon: "rotate",
|
|
52621
|
+
className: "h-3.5 w-3.5 ".concat(modelsLoading ? "animate-spin" : "")
|
|
52622
|
+
})
|
|
52441
52623
|
})]
|
|
52442
|
-
}), /*#__PURE__*/jsxRuntime.jsx("select", {
|
|
52443
|
-
value: selectedModel,
|
|
52444
|
-
onChange: handleModelChange,
|
|
52445
|
-
className: "bg-white/10 border border-white/10 rounded-md px-3 py-1.5 text-sm text-gray-200 focus:outline-none focus:ring-1 focus:ring-blue-500",
|
|
52446
|
-
children: MODELS.map(function (m) {
|
|
52447
|
-
return /*#__PURE__*/jsxRuntime.jsx("option", {
|
|
52448
|
-
value: m.value,
|
|
52449
|
-
children: m.label
|
|
52450
|
-
}, m.value);
|
|
52451
|
-
})
|
|
52452
52624
|
})]
|
|
52453
52625
|
})]
|
|
52454
52626
|
}), !hasAnthropicProvider && /*#__PURE__*/jsxRuntime.jsxs("div", {
|