@jini-ai/ui 0.4.4 → 0.4.6
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 +10 -0
- package/README.md +20 -0
- package/dist/core/theme/default.d.ts +4 -0
- package/dist/core/theme/default.js +11 -0
- package/dist/core/theme/stylesheet.d.ts +8 -0
- package/dist/core/theme/stylesheet.js +14 -0
- package/dist/core/theme/types.d.ts +39 -0
- package/dist/core/theme/types.js +2 -0
- package/dist/core/theme/validation.d.ts +15 -0
- package/dist/core/theme/validation.js +55 -0
- package/dist/features/admin-widgets/components/Select/Select.d.ts +11 -3
- package/dist/features/admin-widgets/components/Select/Select.hooks.d.ts +8 -13
- package/dist/features/admin-widgets/components/Select/Select.hooks.js +37 -215
- package/dist/features/admin-widgets/components/Select/Select.js +4 -3
- package/dist/features/appearance/constants.js +1 -1
- package/dist/features/connectors/rules.d.ts +1 -6
- package/dist/features/connectors/types.d.ts +1 -6
- package/dist/features/connectors/types.js +1 -6
- package/dist/features/execution/http-adapter.d.ts +111 -0
- package/dist/features/execution/http-adapter.js +160 -0
- package/dist/features/execution/index.d.ts +4 -0
- package/dist/features/execution/index.js +2 -0
- package/dist/features/execution/react/hooks/use-execution-credential.hooks.d.ts +232 -0
- package/dist/features/execution/react/hooks/use-execution-credential.hooks.js +217 -0
- package/dist/features/html-editor/canvas-style.d.ts +1 -1
- package/dist/features/html-editor/canvas-style.js +2 -2
- package/dist/features/i18n/dictionaries/settings-dialog.ar.js +2 -0
- package/dist/features/i18n/dictionaries/settings-dialog.bn.js +2 -0
- package/dist/features/i18n/dictionaries/settings-dialog.de.js +2 -0
- package/dist/features/i18n/dictionaries/settings-dialog.en.js +2 -0
- package/dist/features/i18n/dictionaries/settings-dialog.es.js +2 -0
- package/dist/features/i18n/dictionaries/settings-dialog.fa.js +2 -0
- package/dist/features/i18n/dictionaries/settings-dialog.fr.js +2 -0
- package/dist/features/i18n/dictionaries/settings-dialog.hi.js +2 -0
- package/dist/features/i18n/dictionaries/settings-dialog.hu.js +2 -0
- package/dist/features/i18n/dictionaries/settings-dialog.id.js +2 -0
- package/dist/features/i18n/dictionaries/settings-dialog.it.js +2 -0
- package/dist/features/i18n/dictionaries/settings-dialog.ja.js +2 -0
- package/dist/features/i18n/dictionaries/settings-dialog.ko.js +2 -0
- package/dist/features/i18n/dictionaries/settings-dialog.pl.js +2 -0
- package/dist/features/i18n/dictionaries/settings-dialog.pt-BR.js +2 -0
- package/dist/features/i18n/dictionaries/settings-dialog.ru.js +2 -0
- package/dist/features/i18n/dictionaries/settings-dialog.th.js +2 -0
- package/dist/features/i18n/dictionaries/settings-dialog.tr.js +2 -0
- package/dist/features/i18n/dictionaries/settings-dialog.uk.js +2 -0
- package/dist/features/i18n/dictionaries/settings-dialog.ur.js +2 -0
- package/dist/features/i18n/dictionaries/settings-dialog.zh-CN.js +2 -0
- package/dist/features/i18n/dictionaries/settings-dialog.zh-TW.js +2 -0
- package/dist/features/i18n/dictionary-translator.d.ts +5 -2
- package/dist/features/i18n/dictionary-translator.js +1 -1
- package/dist/features/i18n/index.d.ts +1 -1
- package/dist/features/i18n/index.js +1 -1
- package/dist/features/i18n/template-i18n.d.ts +11 -0
- package/dist/features/i18n/template-i18n.js +12 -0
- package/dist/features/interactive-ui/providers/recharts/chart-tokens.d.ts +1 -1
- package/dist/features/interactive-ui/providers/recharts/chart-tokens.js +1 -1
- package/dist/features/lexical-rich-text-editor/deserialize.d.ts +0 -5
- package/dist/features/lexical-rich-text-editor/deserialize.js +0 -5
- package/dist/features/lexical-rich-text-editor/mention-node.d.ts +5 -17
- package/dist/features/lexical-rich-text-editor/mention-node.js +5 -17
- package/dist/features/lexical-rich-text-editor/mention-parser.d.ts +2 -4
- package/dist/features/lexical-rich-text-editor/serialize.d.ts +0 -4
- package/dist/features/lexical-rich-text-editor/serialize.js +0 -4
- package/dist/features/lexical-rich-text-editor/types.d.ts +3 -13
- package/dist/features/lexical-rich-text-editor/types.js +3 -13
- package/dist/features/mcp-ui/early-message-buffer.d.ts +1 -2
- package/dist/features/mcp-ui/early-message-buffer.js +1 -2
- package/dist/features/mcp-ui/escape.d.ts +4 -0
- package/dist/features/mcp-ui/escape.js +2 -9
- package/dist/features/mcp-ui/index.d.ts +1 -0
- package/dist/features/mcp-ui/index.js +1 -0
- package/dist/features/mcp-ui/protocol.d.ts +2 -5
- package/dist/features/mcp-ui/protocol.js +2 -5
- package/dist/features/mcp-ui/resource.d.ts +47 -7
- package/dist/features/mcp-ui/resource.js +5 -8
- package/dist/features/mcp-ui/secret-card.d.ts +115 -0
- package/dist/features/mcp-ui/secret-card.js +137 -0
- package/dist/features/mcp-ui/surfaces/confirmation.js +5 -0
- package/dist/features/mcp-ui/surfaces/fields.d.ts +5 -2
- package/dist/features/mcp-ui/surfaces/fields.js +3 -1
- package/dist/features/mcp-ui/surfaces/form.d.ts +4 -1
- package/dist/features/mcp-ui/surfaces/form.js +65 -3
- package/dist/features/mcp-ui/surfaces/outcome.d.ts +2 -0
- package/dist/features/mcp-ui/surfaces/text-input.d.ts +14 -6
- package/dist/features/mcp-ui/surfaces/text-input.js +16 -2
- package/dist/features/mcp-ui/surfaces/tokens.js +1 -1
- package/dist/features/memory/react/components/MemoryConnectedPanel.d.ts +1 -1
- package/dist/features/memory/react/components/MemoryConnectedPanel.js +0 -1
- package/dist/features/panel-kit/helpers/format-timestamp.d.ts +5 -3
- package/dist/features/panel-kit/helpers/format-timestamp.js +13 -4
- package/dist/features/panel-kit/helpers/permissions.js +2 -0
- package/dist/features/panel-kit/helpers/resolve-active-tab-id.js +2 -0
- package/dist/features/panel-kit/helpers/standing-draft-local-backup.d.ts +51 -0
- package/dist/features/panel-kit/helpers/standing-draft-local-backup.js +77 -0
- package/dist/features/panel-kit/helpers/standing-draft-recovery-message.d.ts +8 -0
- package/dist/features/panel-kit/helpers/standing-draft-recovery-message.js +10 -0
- package/dist/features/panel-kit/hooks/use-async-action.hooks.d.ts +1 -0
- package/dist/features/panel-kit/hooks/use-dirty-guard.hooks.d.ts +1 -0
- package/dist/features/panel-kit/hooks/use-dirty-guard.hooks.js +1 -0
- package/dist/features/panel-kit/hooks/use-serial-writes.hooks.d.ts +8 -0
- package/dist/features/panel-kit/hooks/use-serial-writes.hooks.js +3 -0
- package/dist/features/panel-kit/hooks/use-settings-slice.hooks.d.ts +211 -0
- package/dist/features/panel-kit/hooks/use-settings-slice.hooks.js +382 -0
- package/dist/features/panel-kit/hooks/use-standing-draft-autosave.hooks.d.ts +179 -0
- package/dist/features/panel-kit/hooks/use-standing-draft-autosave.hooks.js +300 -0
- package/dist/features/panel-kit/index.d.ts +7 -1
- package/dist/features/panel-kit/index.js +5 -1
- package/dist/features/resource-dashboard/types.d.ts +8 -41
- package/dist/features/resource-dashboard/types.js +3 -26
- package/dist/features/tab-strip/constants.d.ts +3 -4
- package/dist/features/tab-strip/constants.js +3 -4
- package/dist/features/tab-strip/dependencies.d.ts +1 -6
- package/dist/features/tab-strip/dependencies.js +1 -6
- package/dist/features/tab-strip/react/components/TabBar.d.ts +33 -1
- package/dist/features/tab-strip/react/components/TabBar.hooks.d.ts +57 -5
- package/dist/features/tab-strip/react/components/TabBar.hooks.js +63 -5
- package/dist/features/tab-strip/react/components/TabBar.js +12 -1
- package/dist/features/tab-strip/rules.d.ts +4 -17
- package/dist/features/tab-strip/rules.js +4 -17
- package/dist/features/tab-strip/types.d.ts +2 -13
- package/dist/icon-name.d.ts +1 -1
- package/dist/icon-name.js +1 -0
- package/dist/index.d.ts +42 -417
- package/dist/index.js +42 -430
- package/dist/react/components/CustomSelect.d.ts +6 -2
- package/dist/react/components/CustomSelect.js +20 -91
- package/dist/react/components/Icon.d.ts +6 -0
- package/dist/react/components/Icon.js +12 -0
- package/dist/react/components/select-popover.d.ts +106 -0
- package/dist/react/components/select-popover.js +210 -0
- package/dist/renderers/sandbox-scripts.d.ts +29 -0
- package/dist/renderers/sandbox-scripts.js +127 -0
- package/dist/renderers/sandboxed-document.js +3 -86
- package/dist/renderers/srcdoc/build.d.ts +10 -17
- package/dist/renderers/srcdoc/build.js +31 -234
- package/dist/styles/variables.css +2 -2
- package/dist/theme/apply.d.ts +1 -1
- package/dist/theme/apply.js +2 -2
- package/dist/theme/color-scheme.d.ts +1 -1
- package/dist/theme/default.d.ts +1 -3
- package/dist/theme/default.js +2 -10
- package/dist/theme/index.d.ts +3 -3
- package/dist/theme/index.js +2 -2
- package/dist/theme/stylesheet.d.ts +1 -7
- package/dist/theme/stylesheet.js +2 -13
- package/dist/theme/types.d.ts +1 -38
- package/dist/theme/types.js +2 -1
- package/dist/theme/validation.d.ts +1 -14
- package/dist/theme/validation.js +2 -54
- package/dist/utils/endpoint-policy.d.ts +21 -39
- package/dist/utils/endpoint-policy.js +19 -107
- package/dist/utils/file-system-errors.d.ts +1 -2
- package/dist/utils/file-system-errors.js +1 -2
- package/dist/utils/ime-composing.d.ts +0 -3
- package/dist/utils/ime-composing.js +0 -3
- package/dist/utils/platform.d.ts +1 -4
- package/dist/utils/platform.js +1 -4
- package/dist/utils/smooth-scroll-to-top.d.ts +1 -3
- package/dist/utils/smooth-scroll-to-top.js +3 -13
- package/dist/utils/timezone.js +1 -5
- package/dist/utils/uuid.d.ts +0 -3
- package/dist/utils/uuid.js +0 -3
- package/dist/utils/visual-stability.d.ts +1 -3
- package/dist/utils/visual-stability.js +1 -3
- package/package.json +74 -15
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
import { useEffect, useRef, useState } from "react";
|
|
2
|
+
import { useSerialWrites } from "../../../panel-kit/hooks/use-serial-writes.hooks.js";
|
|
3
|
+
import { useSettlementGeneration } from "../../../panel-kit/hooks/use-settlement-generation.hooks.js";
|
|
4
|
+
/**
|
|
5
|
+
* @complexity Time: O(1) per call — one GET on mount, one PUT per explicit save/migrate. Space:
|
|
6
|
+
* O(1) — no caller-controlled collections.
|
|
7
|
+
*/
|
|
8
|
+
export function useExecutionCredential({ byok, onByokChange, locale, port, effects }, _options = {}) {
|
|
9
|
+
const [stored, setStored] = useState(null);
|
|
10
|
+
const [saveState, setSaveState] = useState({ status: "idle" });
|
|
11
|
+
const [settingsSaveState, setSettingsSaveState] = useState({ status: "idle" });
|
|
12
|
+
const [legacyKey, setLegacyKey] = useState(null);
|
|
13
|
+
const [legacyDismissed, setLegacyDismissed] = useState(false);
|
|
14
|
+
// The operator's latest `byok`/`onByokChange`, read back by `saveKey` AFTER its await — never the
|
|
15
|
+
// `byok` its own closure captured at button-press time. Without this, a provider chip click, a
|
|
16
|
+
// model edit, or a newly typed key made while a key save was in flight was reverted to the
|
|
17
|
+
// click-time config the instant the response landed, and the ledger slice then autosaved that
|
|
18
|
+
// revert (S1). Assigning a ref during render is the same idiom `use-visitor-credential-
|
|
19
|
+
// form.hooks.ts`'s `apiRef` uses for the identical reason.
|
|
20
|
+
const inputRef = useRef({ byok, onByokChange });
|
|
21
|
+
inputRef.current = { byok, onByokChange };
|
|
22
|
+
// The server rebuilds every write from the row it read when the request arrived
|
|
23
|
+
// (`execution-credential-store.ts`'s `setExecutionCredential`: read -> seal -> upsert the WHOLE
|
|
24
|
+
// merged record), so a key save, a settings save and a migration in flight together each merge
|
|
25
|
+
// over the same stale row and the later upsert reverts the other's fields — both still answer
|
|
26
|
+
// 200. Chained, each write reads what the one before it actually wrote. Tab-local only: two tabs,
|
|
27
|
+
// or the Settings and AI Assistant mounts in two different browser windows, can still race — that
|
|
28
|
+
// needs a server-side concurrency check (see the plan's "Needs owner decision" section). Same
|
|
29
|
+
// shared lane `use-visitor-credential-form.hooks.ts` (`8ac256353`) and
|
|
30
|
+
// `use-other-credentials.hooks.ts` queue their own credential writes through.
|
|
31
|
+
const writes = useSerialWrites();
|
|
32
|
+
// Guards `setStored` against an out-of-order read: the mount GET, the post-save refresh GET, and
|
|
33
|
+
// each write's own response are all independent round trips with no ordering between them. A slow
|
|
34
|
+
// mount GET that resolves after a save (or after the save's own refresh) must not overwrite the
|
|
35
|
+
// fresher view those already installed — see F2 in plan-components.md (2026-09-20). Only `setStored`
|
|
36
|
+
// is guarded; `setSaveState`/`setSettingsSaveState`, `clearLegacyLocalCredential`, `setLegacyKey`
|
|
37
|
+
// and `publishSettingsRefresh` all belong to the button that called them and the write really did
|
|
38
|
+
// happen, so none of those are stale just because a later call also started.
|
|
39
|
+
const storedSettlement = useSettlementGeneration();
|
|
40
|
+
// A write's own response is the freshest view of the row this mount has at the instant it lands,
|
|
41
|
+
// so it mints its generation THEN — after the await, and only on success — superseding any read
|
|
42
|
+
// still in flight, and installs unconditionally. Minting before the PUT instead let a FAILED
|
|
43
|
+
// write (which learned nothing about the row) strand a slower read that was still coming back:
|
|
44
|
+
// `stored` then stayed at its pre-load value until some unrelated refresh ran. Unlike
|
|
45
|
+
// `useSerialWrites`' own "mint before `run`" rule, this generation orders RESPONSES by arrival,
|
|
46
|
+
// not button presses by intent — nothing here is a "which click owns the UI" decision.
|
|
47
|
+
function installWrittenView(view) {
|
|
48
|
+
storedSettlement.next();
|
|
49
|
+
setStored(view);
|
|
50
|
+
}
|
|
51
|
+
// Hydrate the stored view, on mount AND whenever another mount (or `AssistantDock`'s own separate
|
|
52
|
+
// copy) publishes a change to this same server row — see this file's "Cross-mount staleness" doc
|
|
53
|
+
// above. Silent on failure, same posture `use-visitor-credential-form.hooks.ts` takes for its own
|
|
54
|
+
// GET: a failed read must not put an error next to a key field the operator has not touched yet,
|
|
55
|
+
// and the only visible consequence is that the "already stored" affordances stay at whatever they
|
|
56
|
+
// last held until a refresh works.
|
|
57
|
+
useEffect(() => {
|
|
58
|
+
let cancelled = false;
|
|
59
|
+
const refresh = () => {
|
|
60
|
+
const generation = storedSettlement.next();
|
|
61
|
+
port
|
|
62
|
+
.loadAdminExecutionCredential({}, {})
|
|
63
|
+
.then((view) => {
|
|
64
|
+
if (!cancelled && storedSettlement.isCurrent({ generation }))
|
|
65
|
+
setStored(view);
|
|
66
|
+
})
|
|
67
|
+
.catch(() => undefined);
|
|
68
|
+
};
|
|
69
|
+
refresh();
|
|
70
|
+
// `scope` is `null` ("refresh everything") or the list of namespaces a publisher named — narrow
|
|
71
|
+
// to this credential's own namespace so an unrelated slice's save does not trigger a pointless
|
|
72
|
+
// refetch here, matching `useSettingsSlice`'s identical narrowing.
|
|
73
|
+
const unsubscribe = effects.refreshPort.subscribe({ listener: (scope) => {
|
|
74
|
+
if (scope && !scope.includes(effects.namespace))
|
|
75
|
+
return;
|
|
76
|
+
refresh();
|
|
77
|
+
} }, {});
|
|
78
|
+
return () => {
|
|
79
|
+
cancelled = true;
|
|
80
|
+
unsubscribe();
|
|
81
|
+
};
|
|
82
|
+
// `port` is referentially stable in production (`useWiredAdminExecutionCredential` always passes
|
|
83
|
+
// the same module-level singleton), so adding it changes nothing about when this effect re-runs —
|
|
84
|
+
// it is here only because it is now a function-scoped value ESLint's exhaustive-deps rule can see,
|
|
85
|
+
// where the old `loadAdminExecutionCredential` import was invisible to that rule.
|
|
86
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
87
|
+
}, [port, effects]);
|
|
88
|
+
// Offer the migration prompt only once the server's own state is known AND nothing is already
|
|
89
|
+
// stored there — an admin who already has a server-side credential (migrated earlier, or just
|
|
90
|
+
// saved fresh this session) gets no benefit from being asked to migrate a now-superseded local
|
|
91
|
+
// value, and re-asking would read as the screen not noticing its own save.
|
|
92
|
+
useEffect(() => {
|
|
93
|
+
if (stored === null)
|
|
94
|
+
return;
|
|
95
|
+
setLegacyKey(stored.isSet ? null : effects.readLegacyCredential({}, {}));
|
|
96
|
+
}, [stored, effects]);
|
|
97
|
+
function saveKey() {
|
|
98
|
+
const apiKey = byok.apiKey.trim();
|
|
99
|
+
// The BUTTON's rule, applied again here so a blank field cannot reach the server even through a
|
|
100
|
+
// direct call. Deliberately NOT `hasUsableAdminKey`: a stored key makes the credential usable,
|
|
101
|
+
// not the empty field writable. See `hasTypedAdminKey`'s own doc for the bug that distinction fixes.
|
|
102
|
+
// OUTSIDE the write chain on purpose: a no-op call must never queue a link that would only hold
|
|
103
|
+
// up the migrate/settings writes behind it for nothing.
|
|
104
|
+
if (!effects.hasTypedKey({ apiKey }, {}))
|
|
105
|
+
return Promise.resolve(); // nothing typed — there is no key to write
|
|
106
|
+
// Set synchronously, at call time, so a press queued behind another write shows "Saving…"
|
|
107
|
+
// immediately rather than sitting at "idle" until its turn on the chain arrives.
|
|
108
|
+
setSaveState({ status: "saving" });
|
|
109
|
+
return writes.run({ task: async () => {
|
|
110
|
+
try {
|
|
111
|
+
// The key ALONE. Every other field is `saveSettings`'s, and building the patch from one
|
|
112
|
+
// literal (rather than spreading `byok` and deleting) is what makes that readable at a glance
|
|
113
|
+
// — there is no branch here that could let another field through.
|
|
114
|
+
const patch = { apiKey };
|
|
115
|
+
const view = await port.saveAdminExecutionCredential({ patch }, {});
|
|
116
|
+
installWrittenView(view);
|
|
117
|
+
setSaveState({ status: "saved" });
|
|
118
|
+
// Tells every other mounted copy of this credential (the other settings screen, the dock) to
|
|
119
|
+
// re-read — see this file's "Cross-mount staleness" doc above.
|
|
120
|
+
effects.refreshPort.publish({ namespaces: [effects.namespace] }, {});
|
|
121
|
+
// Clear the field once the key is safely stored — see this file's `onByokChange` doc. Reads
|
|
122
|
+
// the LATEST input, not the `byok`/`onByokChange` this closure captured at button-press time
|
|
123
|
+
// (S1 above), and only actually clears when the field still holds exactly the key that was
|
|
124
|
+
// just saved — otherwise the operator has since typed something new, and clearing it would
|
|
125
|
+
// discard that unsaved edit instead of the key this save actually persisted.
|
|
126
|
+
const latestInput = inputRef.current;
|
|
127
|
+
if (latestInput.byok.apiKey.trim() === apiKey) {
|
|
128
|
+
latestInput.onByokChange({ ...latestInput.byok, apiKey: "" });
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
catch (error) {
|
|
132
|
+
setSaveState({ status: "error", message: effects.describeError({ error, fallback: "failed to save the key" }, {}) });
|
|
133
|
+
}
|
|
134
|
+
} });
|
|
135
|
+
}
|
|
136
|
+
function saveSettings() {
|
|
137
|
+
setSettingsSaveState({ status: "saving" });
|
|
138
|
+
return writes.run({ task: async () => {
|
|
139
|
+
try {
|
|
140
|
+
// No `apiKey` key at all, under any condition — see this controller's `saveSettings` doc. The
|
|
141
|
+
// field's contents are not consulted here, so there is no state of the form in which this
|
|
142
|
+
// patch can grow one.
|
|
143
|
+
const patch = {
|
|
144
|
+
protocol: byok.protocol,
|
|
145
|
+
providerId: byok.providerId,
|
|
146
|
+
baseUrl: byok.baseUrl,
|
|
147
|
+
model: byok.model,
|
|
148
|
+
...(byok.maxTokens !== undefined ? { maxTokens: byok.maxTokens } : {}),
|
|
149
|
+
};
|
|
150
|
+
const view = await port.saveAdminExecutionCredential({ patch }, {});
|
|
151
|
+
installWrittenView(view);
|
|
152
|
+
setSettingsSaveState({ status: "saved" });
|
|
153
|
+
effects.refreshPort.publish({ namespaces: [effects.namespace] }, {});
|
|
154
|
+
}
|
|
155
|
+
catch (error) {
|
|
156
|
+
setSettingsSaveState({
|
|
157
|
+
status: "error",
|
|
158
|
+
message: effects.describeError({ error, fallback: "failed to save the settings" }, {}),
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
} });
|
|
162
|
+
}
|
|
163
|
+
function migrateLegacyKey() {
|
|
164
|
+
if (!legacyKey)
|
|
165
|
+
return Promise.resolve();
|
|
166
|
+
setSaveState({ status: "saving" });
|
|
167
|
+
return writes.run({ task: async () => {
|
|
168
|
+
try {
|
|
169
|
+
const patch = {
|
|
170
|
+
apiKey: legacyKey,
|
|
171
|
+
protocol: byok.protocol,
|
|
172
|
+
providerId: byok.providerId,
|
|
173
|
+
baseUrl: byok.baseUrl,
|
|
174
|
+
model: byok.model,
|
|
175
|
+
...(byok.maxTokens !== undefined ? { maxTokens: byok.maxTokens } : {}),
|
|
176
|
+
};
|
|
177
|
+
const view = await port.saveAdminExecutionCredential({ patch }, {});
|
|
178
|
+
// Clear the local copy ONLY after the PUT above has actually resolved successfully — the
|
|
179
|
+
// design's explicit ordering requirement (§6: "only after that PUT succeeds does the code
|
|
180
|
+
// clear the localStorage entry"). A throw above skips every line from here down, so a failed
|
|
181
|
+
// migration leaves both the local key AND `legacyKey` state untouched — the prompt stays up
|
|
182
|
+
// and the admin can retry or decline.
|
|
183
|
+
effects.clearLegacyCredential({}, {});
|
|
184
|
+
installWrittenView(view);
|
|
185
|
+
setLegacyKey(null);
|
|
186
|
+
setSaveState({ status: "saved" });
|
|
187
|
+
// Same cross-mount notification `saveKey` above sends — a migration is a write to the same row.
|
|
188
|
+
effects.refreshPort.publish({ namespaces: [effects.namespace] }, {});
|
|
189
|
+
}
|
|
190
|
+
catch (error) {
|
|
191
|
+
setSaveState({ status: "error", message: effects.describeError({ error, fallback: "failed to save the migrated key" }, {}) });
|
|
192
|
+
}
|
|
193
|
+
} });
|
|
194
|
+
}
|
|
195
|
+
function dismissLegacyPrompt() {
|
|
196
|
+
setLegacyDismissed(true);
|
|
197
|
+
}
|
|
198
|
+
// All three read the form's CURRENT endpoint, so they follow a provider switch on the same render.
|
|
199
|
+
const storedKeyIsForOtherEndpoint = effects.storedKeyIsForOtherEndpoint({ stored, baseUrl: byok.baseUrl }, {});
|
|
200
|
+
const apiKeyPlaceholder = effects.credentialHint({ stored, storedKeyIsForOtherEndpoint }, { locale });
|
|
201
|
+
return {
|
|
202
|
+
stored,
|
|
203
|
+
apiKeyStoredExternally: effects.hasUsableKey({ apiKey: byok.apiKey, stored, baseUrl: byok.baseUrl }, {}),
|
|
204
|
+
apiKeyPlaceholder,
|
|
205
|
+
storedKeyIsForOtherEndpoint,
|
|
206
|
+
canDiscoverModels: !effects.storedKeyBlocksProbe({ apiKey: byok.apiKey, stored, baseUrl: byok.baseUrl }, {}),
|
|
207
|
+
saveState,
|
|
208
|
+
settingsSaveState,
|
|
209
|
+
canSaveKey: effects.hasTypedKey({ apiKey: byok.apiKey }, {}),
|
|
210
|
+
saveKey,
|
|
211
|
+
saveSettings,
|
|
212
|
+
legacyKey: legacyDismissed ? null : legacyKey,
|
|
213
|
+
migrateLegacyKey,
|
|
214
|
+
dismissLegacyPrompt,
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
//# sourceMappingURL=use-execution-credential.hooks.js.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AdminTheme, ColorScheme } from '../../theme/types.js';
|
|
1
|
+
import type { AdminTheme, ColorScheme } from '../../core/theme/types.js';
|
|
2
2
|
/**
|
|
3
3
|
* @file Builds the `canvas.frameStyle` GrapesJS injects into its editing canvas, so a host that
|
|
4
4
|
* supplies its own canvas styling is not silently overruled by GrapesJS's own defaults.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { defaultAdminTheme } from '../../theme/default.js';
|
|
2
|
-
import { renderAdminThemeVariables } from '../../theme/stylesheet.js';
|
|
1
|
+
import { defaultAdminTheme } from '../../core/theme/default.js';
|
|
2
|
+
import { renderAdminThemeVariables } from '../../core/theme/stylesheet.js';
|
|
3
3
|
/** GrapesJS's own default scrollbar chrome for the canvas, restated verbatim from its
|
|
4
4
|
* `canvas.frameStyle` default so overriding that option does not silently drop it. */
|
|
5
5
|
const CANVAS_SCROLLBAR_STYLE = [
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
export const SETTINGS_DIALOG_AR = {
|
|
2
|
+
"I removed what looked like a key from your message. If it was real, rotate it. Use the secure form to save it.": "أزلت من رسالتك ما بدا كمفتاح. إن كان حقيقيًا، فاستبدله. استخدم النموذج الآمن لحفظه.",
|
|
3
|
+
"Use the secure form to save keys, tokens, passwords, and secrets. Chat answers are sent to the assistant.": "استخدم النموذج الآمن لحفظ المفاتيح والرموز وكلمات المرور والأسرار. تُرسل إجابات الدردشة إلى المساعد.",
|
|
2
4
|
'# My skill\n\n1. Explain the workflow.\n2. Describe the inputs and outputs.': '# مهارتي\n\n1. اشرح سير العمل.\n2. صف المدخلات والمخرجات.',
|
|
3
5
|
'A custom path override did not work, so this used the automatically detected binary instead.': 'لم يعمل مسار مخصص بديل، لذلك استُخدم الملف التنفيذي الذي تم اكتشافه تلقائيًا بدلاً منه.',
|
|
4
6
|
'API key': 'مفتاح API',
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
export const SETTINGS_DIALOG_BN = {
|
|
2
|
+
"I removed what looked like a key from your message. If it was real, rotate it. Use the secure form to save it.": "আপনার বার্তা থেকে কী বলে মনে হওয়া অংশটি সরিয়ে দিয়েছি। সেটি আসল হলে বদলে ফেলুন। সংরক্ষণ করতে নিরাপদ ফর্ম ব্যবহার করুন।",
|
|
3
|
+
"Use the secure form to save keys, tokens, passwords, and secrets. Chat answers are sent to the assistant.": "কী, টোকেন, পাসওয়ার্ড ও গোপন তথ্য সংরক্ষণ করতে নিরাপদ ফর্ম ব্যবহার করুন। চ্যাটের উত্তর সহকারীকে পাঠানো হয়।",
|
|
2
4
|
'# My skill\n\n1. Explain the workflow.\n2. Describe the inputs and outputs.': '# আমার স্কিল\n\n1. ওয়ার্কফ্লো ব্যাখ্যা করুন।\n2. ইনপুট এবং আউটপুট বর্ণনা করুন।',
|
|
3
5
|
'A custom path override did not work, so this used the automatically detected binary instead.': 'একটি কাস্টম পাথ ওভাররাইড কাজ করেনি, তাই এর পরিবর্তে স্বয়ংক্রিয়ভাবে শনাক্ত করা বাইনারি ব্যবহার করা হয়েছে।',
|
|
4
6
|
'API key': 'API কী',
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
export const SETTINGS_DIALOG_DE = {
|
|
2
|
+
"I removed what looked like a key from your message. If it was real, rotate it. Use the secure form to save it.": "Ich habe aus deiner Nachricht entfernt, was wie ein Schlüssel aussah. Falls er echt war, ersetze ihn. Speichere ihn über das sichere Formular.",
|
|
3
|
+
"Use the secure form to save keys, tokens, passwords, and secrets. Chat answers are sent to the assistant.": "Speichere Schlüssel, Tokens, Passwörter und Geheimnisse über das sichere Formular. Chatantworten werden an den Assistenten gesendet.",
|
|
2
4
|
'# My skill\n\n1. Explain the workflow.\n2. Describe the inputs and outputs.': '# Meine Skill\n\n1. Erkläre den Workflow.\n2. Beschreibe die Eingaben und Ausgaben.',
|
|
3
5
|
'A custom path override did not work, so this used the automatically detected binary instead.': 'Eine benutzerdefinierte Pfadüberschreibung hat nicht funktioniert, daher wurde stattdessen die automatisch erkannte Binärdatei verwendet.',
|
|
4
6
|
'API key': 'API-Schlüssel',
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
export const SETTINGS_DIALOG_EN = {
|
|
2
|
+
"I removed what looked like a key from your message. If it was real, rotate it. Use the secure form to save it.": "I removed what looked like a key from your message. If it was real, rotate it. Use the secure form to save it.",
|
|
3
|
+
"Use the secure form to save keys, tokens, passwords, and secrets. Chat answers are sent to the assistant.": "Use the secure form to save keys, tokens, passwords, and secrets. Chat answers are sent to the assistant.",
|
|
2
4
|
'# My skill\n\n1. Explain the workflow.\n2. Describe the inputs and outputs.': '# My skill\n\n1. Explain the workflow.\n2. Describe the inputs and outputs.',
|
|
3
5
|
'A custom path override did not work, so this used the automatically detected binary instead.': 'A custom path override did not work, so this used the automatically detected binary instead.',
|
|
4
6
|
'API key': 'API key',
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
export const SETTINGS_DIALOG_ES = {
|
|
2
|
+
"I removed what looked like a key from your message. If it was real, rotate it. Use the secure form to save it.": "He eliminado de tu mensaje lo que parecía una clave. Si era real, cámbiala. Usa el formulario seguro para guardarla.",
|
|
3
|
+
"Use the secure form to save keys, tokens, passwords, and secrets. Chat answers are sent to the assistant.": "Usa el formulario seguro para guardar claves, tokens, contraseñas y secretos. Las respuestas del chat se envían al asistente.",
|
|
2
4
|
'# My skill\n\n1. Explain the workflow.\n2. Describe the inputs and outputs.': '# Mi skill\n\n1. Explica el flujo de trabajo.\n2. Describe las entradas y salidas.',
|
|
3
5
|
'A custom path override did not work, so this used the automatically detected binary instead.': 'Una ruta personalizada no funcionó, así que se usó en su lugar el binario detectado automáticamente.',
|
|
4
6
|
'API key': 'Clave de API',
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
export const SETTINGS_DIALOG_FA = {
|
|
2
|
+
"I removed what looked like a key from your message. If it was real, rotate it. Use the secure form to save it.": "متنی را که شبیه کلید بود از پیامتان حذف کردم. اگر واقعی بود، آن را تعویض کنید. برای ذخیره از فرم امن استفاده کنید.",
|
|
3
|
+
"Use the secure form to save keys, tokens, passwords, and secrets. Chat answers are sent to the assistant.": "برای ذخیره کلیدها، توکنها، گذرواژهها و اطلاعات محرمانه از فرم امن استفاده کنید. پاسخهای گفتگو به دستیار فرستاده میشوند.",
|
|
2
4
|
'# My skill\n\n1. Explain the workflow.\n2. Describe the inputs and outputs.': '# مهارت من\n\n1. گردش کار را توضیح دهید.\n2. ورودیها و خروجیها را شرح دهید.',
|
|
3
5
|
'A custom path override did not work, so this used the automatically detected binary instead.': 'مسیر سفارشی جایگزین کار نکرد، بنابراین بهجای آن از فایل اجرایی شناساییشده بهطور خودکار استفاده شد.',
|
|
4
6
|
'API key': 'کلید API',
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
export const SETTINGS_DIALOG_FR = {
|
|
2
|
+
"I removed what looked like a key from your message. If it was real, rotate it. Use the secure form to save it.": "J’ai supprimé de votre message ce qui ressemblait à une clé. Si elle était réelle, remplacez-la. Utilisez le formulaire sécurisé pour l’enregistrer.",
|
|
3
|
+
"Use the secure form to save keys, tokens, passwords, and secrets. Chat answers are sent to the assistant.": "Utilisez le formulaire sécurisé pour enregistrer les clés, jetons, mots de passe et secrets. Les réponses du chat sont envoyées à l’assistant.",
|
|
2
4
|
'# My skill\n\n1. Explain the workflow.\n2. Describe the inputs and outputs.': '# Ma compétence\n\n1. Expliquez le déroulement.\n2. Décrivez les entrées et sorties.',
|
|
3
5
|
'A custom path override did not work, so this used the automatically detected binary instead.': 'Le chemin personnalisé n\'a pas fonctionné ; le binaire détecté automatiquement a donc été utilisé à la place.',
|
|
4
6
|
'API key': 'Clé API',
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
export const SETTINGS_DIALOG_HI = {
|
|
2
|
+
"I removed what looked like a key from your message. If it was real, rotate it. Use the secure form to save it.": "मैंने आपके संदेश से कुंजी जैसा दिखने वाला हिस्सा हटा दिया है। अगर वह असली कुंजी थी, तो उसे बदलें। उसे सहेजने के लिए सुरक्षित फ़ॉर्म का उपयोग करें।",
|
|
3
|
+
"Use the secure form to save keys, tokens, passwords, and secrets. Chat answers are sent to the assistant.": "कुंजियाँ, टोकन, पासवर्ड और गोपनीय जानकारी सहेजने के लिए सुरक्षित फ़ॉर्म का उपयोग करें। चैट के उत्तर सहायक को भेजे जाते हैं।",
|
|
2
4
|
'# My skill\n\n1. Explain the workflow.\n2. Describe the inputs and outputs.': '# मेरी स्किल\n\n1. वर्कफ़्लो के बारे में बताएं।\n2. इनपुट और आउटपुट के बारे में बताएं।',
|
|
3
5
|
'A custom path override did not work, so this used the automatically detected binary instead.': 'एक कस्टम पाथ ओवरराइड काम नहीं कर सका, इसलिए इसके बजाय स्वचालित रूप से पहचानी गई बाइनरी का उपयोग किया गया।',
|
|
4
6
|
'API key': 'API कुंजी',
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
export const SETTINGS_DIALOG_HU = {
|
|
2
|
+
"I removed what looked like a key from your message. If it was real, rotate it. Use the secure form to save it.": "Eltávolítottam az üzenetedből azt, ami kulcsnak tűnt. Ha valódi volt, cseréld le. A biztonságos űrlapon mentsd el.",
|
|
3
|
+
"Use the secure form to save keys, tokens, passwords, and secrets. Chat answers are sent to the assistant.": "A kulcsokat, tokeneket, jelszavakat és titkokat a biztonságos űrlapon mentsd el. A chatválaszokat elküldjük az asszisztensnek.",
|
|
2
4
|
'# My skill\n\n1. Explain the workflow.\n2. Describe the inputs and outputs.': '# Saját képességem\n\n1. Írd le a munkafolyamatot.\n2. Írd le a bemeneteket és a kimeneteket.',
|
|
3
5
|
'A custom path override did not work, so this used the automatically detected binary instead.': 'Az egyéni útvonal felülbírálása nem működött, ezért ez az automatikusan felismert binárist használta helyette.',
|
|
4
6
|
'API key': 'API-kulcs',
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
export const SETTINGS_DIALOG_ID = {
|
|
2
|
+
"I removed what looked like a key from your message. If it was real, rotate it. Use the secure form to save it.": "Saya menghapus teks yang tampak seperti kunci dari pesan Anda. Jika itu kunci asli, gantilah. Gunakan formulir aman untuk menyimpannya.",
|
|
3
|
+
"Use the secure form to save keys, tokens, passwords, and secrets. Chat answers are sent to the assistant.": "Gunakan formulir aman untuk menyimpan kunci, token, kata sandi, dan rahasia. Jawaban chat dikirim ke asisten.",
|
|
2
4
|
'# My skill\n\n1. Explain the workflow.\n2. Describe the inputs and outputs.': '# Skill saya\n\n1. Jelaskan alur kerjanya.\n2. Jelaskan input dan outputnya.',
|
|
3
5
|
'A custom path override did not work, so this used the automatically detected binary instead.': 'Penggantian jalur kustom tidak berhasil, jadi ini menggunakan biner yang terdeteksi otomatis sebagai gantinya.',
|
|
4
6
|
'API key': 'Kunci API',
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
export const SETTINGS_DIALOG_IT = {
|
|
2
|
+
"I removed what looked like a key from your message. If it was real, rotate it. Use the secure form to save it.": "Ho rimosso dal messaggio ciò che sembrava una chiave. Se era reale, sostituiscila. Usa il modulo sicuro per salvarla.",
|
|
3
|
+
"Use the secure form to save keys, tokens, passwords, and secrets. Chat answers are sent to the assistant.": "Usa il modulo sicuro per salvare chiavi, token, password e segreti. Le risposte nella chat vengono inviate all’assistente.",
|
|
2
4
|
'# My skill\n\n1. Explain the workflow.\n2. Describe the inputs and outputs.': '# La mia competenza\n\n1. Spiega il flusso di lavoro.\n2. Descrivi gli input e gli output.',
|
|
3
5
|
'A custom path override did not work, so this used the automatically detected binary instead.': 'Il percorso personalizzato specificato non ha funzionato, quindi è stato usato il binario rilevato automaticamente.',
|
|
4
6
|
'API key': 'Chiave API',
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
export const SETTINGS_DIALOG_JA = {
|
|
2
|
+
"I removed what looked like a key from your message. If it was real, rotate it. Use the secure form to save it.": "メッセージからキーと思われる文字列を削除しました。本物のキーだった場合は再発行してください。保存には安全なフォームを使ってください。",
|
|
3
|
+
"Use the secure form to save keys, tokens, passwords, and secrets. Chat answers are sent to the assistant.": "キー、トークン、パスワード、シークレットの保存には安全なフォームを使ってください。チャットの回答はアシスタントに送信されます。",
|
|
2
4
|
'# My skill\n\n1. Explain the workflow.\n2. Describe the inputs and outputs.': '# マイスキル\n\n1. ワークフローを説明してください。\n2. 入力と出力を説明してください。',
|
|
3
5
|
'A custom path override did not work, so this used the automatically detected binary instead.': 'カスタムパスの上書きが機能しなかったため、自動検出されたバイナリを代わりに使用しました。',
|
|
4
6
|
'API key': 'APIキー',
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
export const SETTINGS_DIALOG_KO = {
|
|
2
|
+
"I removed what looked like a key from your message. If it was real, rotate it. Use the secure form to save it.": "메시지에서 키로 보이는 내용을 제거했습니다. 실제 키였다면 교체하세요. 저장하려면 보안 양식을 사용하세요.",
|
|
3
|
+
"Use the secure form to save keys, tokens, passwords, and secrets. Chat answers are sent to the assistant.": "키, 토큰, 비밀번호, 비밀 정보를 저장하려면 보안 양식을 사용하세요. 채팅 답변은 어시스턴트에게 전송됩니다.",
|
|
2
4
|
'# My skill\n\n1. Explain the workflow.\n2. Describe the inputs and outputs.': '# 내 스킬\n\n1. 워크플로를 설명하세요.\n2. 입력과 출력을 설명하세요.',
|
|
3
5
|
'A custom path override did not work, so this used the automatically detected binary instead.': '사용자 지정 경로 재정의가 작동하지 않아 자동으로 감지된 바이너리를 대신 사용했습니다.',
|
|
4
6
|
'API key': 'API 키',
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
export const SETTINGS_DIALOG_PL = {
|
|
2
|
+
"I removed what looked like a key from your message. If it was real, rotate it. Use the secure form to save it.": "Usunąłem z wiadomości tekst, który wyglądał jak klucz. Jeśli był prawdziwy, wymień go. Zapisz go za pomocą bezpiecznego formularza.",
|
|
3
|
+
"Use the secure form to save keys, tokens, passwords, and secrets. Chat answers are sent to the assistant.": "Użyj bezpiecznego formularza do zapisywania kluczy, tokenów, haseł i sekretów. Odpowiedzi na czacie są wysyłane do asystenta.",
|
|
2
4
|
'# My skill\n\n1. Explain the workflow.\n2. Describe the inputs and outputs.': '# Moja umiejętność\n\n1. Opisz przebieg pracy.\n2. Opisz dane wejściowe i wyjściowe.',
|
|
3
5
|
'A custom path override did not work, so this used the automatically detected binary instead.': 'Niestandardowa ścieżka nie zadziałała, więc użyto automatycznie wykrytego pliku binarnego.',
|
|
4
6
|
'API key': 'Klucz API',
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
export const SETTINGS_DIALOG_PT_BR = {
|
|
2
|
+
"I removed what looked like a key from your message. If it was real, rotate it. Use the secure form to save it.": "Removi da sua mensagem o que parecia ser uma chave. Se era real, substitua-a. Use o formulário seguro para salvá-la.",
|
|
3
|
+
"Use the secure form to save keys, tokens, passwords, and secrets. Chat answers are sent to the assistant.": "Use o formulário seguro para salvar chaves, tokens, senhas e segredos. As respostas do chat são enviadas ao assistente.",
|
|
2
4
|
'# My skill\n\n1. Explain the workflow.\n2. Describe the inputs and outputs.': '# Minha skill\n\n1. Explique o fluxo de trabalho.\n2. Descreva as entradas e saídas.',
|
|
3
5
|
'A custom path override did not work, so this used the automatically detected binary instead.': 'Uma substituição de caminho personalizado não funcionou, então foi usado o binário detectado automaticamente.',
|
|
4
6
|
'API key': 'Chave de API',
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
export const SETTINGS_DIALOG_RU = {
|
|
2
|
+
"I removed what looked like a key from your message. If it was real, rotate it. Use the secure form to save it.": "Я удалил из сообщения то, что было похоже на ключ. Если он настоящий, замените его. Сохраните его через защищённую форму.",
|
|
3
|
+
"Use the secure form to save keys, tokens, passwords, and secrets. Chat answers are sent to the assistant.": "Используйте защищённую форму для сохранения ключей, токенов, паролей и секретов. Ответы в чате отправляются ассистенту.",
|
|
2
4
|
'# My skill\n\n1. Explain the workflow.\n2. Describe the inputs and outputs.': '# Мой навык\n\n1. Опишите рабочий процесс.\n2. Опишите входные и выходные данные.',
|
|
3
5
|
'A custom path override did not work, so this used the automatically detected binary instead.': 'Переопределение пользовательского пути не сработало, поэтому был использован автоматически обнаруженный бинарный файл.',
|
|
4
6
|
'API key': 'Ключ API',
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
export const SETTINGS_DIALOG_TH = {
|
|
2
|
+
"I removed what looked like a key from your message. If it was real, rotate it. Use the secure form to save it.": "ฉันลบข้อความที่ดูเหมือนคีย์ออกจากข้อความของคุณแล้ว หากเป็นคีย์จริง ให้เปลี่ยนคีย์ใหม่ ใช้แบบฟอร์มที่ปลอดภัยเพื่อบันทึก",
|
|
3
|
+
"Use the secure form to save keys, tokens, passwords, and secrets. Chat answers are sent to the assistant.": "ใช้แบบฟอร์มที่ปลอดภัยเพื่อบันทึกคีย์ โทเค็น รหัสผ่าน และข้อมูลลับ คำตอบในแชตจะถูกส่งไปยังผู้ช่วย",
|
|
2
4
|
'# My skill\n\n1. Explain the workflow.\n2. Describe the inputs and outputs.': '# ทักษะของฉัน\n\n1. อธิบายขั้นตอนการทำงาน\n2. อธิบายข้อมูลนำเข้าและผลลัพธ์',
|
|
3
5
|
'A custom path override did not work, so this used the automatically detected binary instead.': 'การกำหนดพาธที่กำหนดเองไม่สำเร็จ จึงใช้ไบนารีที่ตรวจพบโดยอัตโนมัติแทน',
|
|
4
6
|
'API key': 'คีย์ API',
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
export const SETTINGS_DIALOG_TR = {
|
|
2
|
+
"I removed what looked like a key from your message. If it was real, rotate it. Use the secure form to save it.": "Mesajınızdan anahtara benzeyen metni kaldırdım. Gerçekse yenileyin. Kaydetmek için güvenli formu kullanın.",
|
|
3
|
+
"Use the secure form to save keys, tokens, passwords, and secrets. Chat answers are sent to the assistant.": "Anahtarları, tokenları, parolaları ve gizli bilgileri kaydetmek için güvenli formu kullanın. Sohbet yanıtları asistana gönderilir.",
|
|
2
4
|
'# My skill\n\n1. Explain the workflow.\n2. Describe the inputs and outputs.': '# Becerim\n\n1. İş akışını açıkla.\n2. Girdileri ve çıktıları tanımla.',
|
|
3
5
|
'A custom path override did not work, so this used the automatically detected binary instead.': 'Özel bir yol geçersiz kılması işe yaramadı, bu yüzden bunun yerine otomatik olarak algılanan ikili dosya kullanıldı.',
|
|
4
6
|
'API key': 'API anahtarı',
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
export const SETTINGS_DIALOG_UK = {
|
|
2
|
+
"I removed what looked like a key from your message. If it was real, rotate it. Use the secure form to save it.": "Я видалив із повідомлення те, що було схоже на ключ. Якщо він справжній, замініть його. Збережіть його через захищену форму.",
|
|
3
|
+
"Use the secure form to save keys, tokens, passwords, and secrets. Chat answers are sent to the assistant.": "Використовуйте захищену форму для збереження ключів, токенів, паролів і секретів. Відповіді в чаті надсилаються асистенту.",
|
|
2
4
|
'# My skill\n\n1. Explain the workflow.\n2. Describe the inputs and outputs.': '# Моя навичка\n\n1. Опишіть робочий процес.\n2. Опишіть вхідні та вихідні дані.',
|
|
3
5
|
'A custom path override did not work, so this used the automatically detected binary instead.': 'Користувацький шлях не спрацював, тому натомість було використано автоматично визначений виконуваний файл.',
|
|
4
6
|
'API key': 'Ключ API',
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
export const SETTINGS_DIALOG_UR = {
|
|
2
|
+
"I removed what looked like a key from your message. If it was real, rotate it. Use the secure form to save it.": "میں نے آپ کے پیغام سے وہ متن ہٹا دیا جو کلید جیسا لگ رہا تھا۔ اگر وہ حقیقی تھی تو اسے تبدیل کریں۔ محفوظ کرنے کے لیے محفوظ فارم استعمال کریں۔",
|
|
3
|
+
"Use the secure form to save keys, tokens, passwords, and secrets. Chat answers are sent to the assistant.": "کلیدیں، ٹوکن، پاس ورڈ اور راز محفوظ کرنے کے لیے محفوظ فارم استعمال کریں۔ چیٹ کے جوابات اسسٹنٹ کو بھیجے جاتے ہیں۔",
|
|
2
4
|
'# My skill\n\n1. Explain the workflow.\n2. Describe the inputs and outputs.': '# میری اسکل\n\n1. ورک فلو کی وضاحت کریں۔\n2. ان پٹس اور آؤٹ پٹس بیان کریں۔',
|
|
3
5
|
'A custom path override did not work, so this used the automatically detected binary instead.': 'ایک کسٹم پاتھ اوور رائیڈ کام نہیں کر سکا، اس لیے اس کے بجائے خودکار طور پر شناخت شدہ بائنری استعمال کی گئی۔',
|
|
4
6
|
'API key': 'API کلید',
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
export const SETTINGS_DIALOG_ZH_CN = {
|
|
2
|
+
"I removed what looked like a key from your message. If it was real, rotate it. Use the secure form to save it.": "我已从你的消息中移除疑似密钥的内容。如果是真实密钥,请更换它。请使用安全表单保存。",
|
|
3
|
+
"Use the secure form to save keys, tokens, passwords, and secrets. Chat answers are sent to the assistant.": "请使用安全表单保存密钥、令牌、密码和机密信息。聊天回答会发送给助手。",
|
|
2
4
|
'# My skill\n\n1. Explain the workflow.\n2. Describe the inputs and outputs.': '# 我的技能\n\n1. 说明工作流程。\n2. 描述输入和输出。',
|
|
3
5
|
'A custom path override did not work, so this used the automatically detected binary instead.': '自定义路径覆盖未生效,因此改用自动检测到的二进制文件。',
|
|
4
6
|
'API key': 'API 密钥',
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
export const SETTINGS_DIALOG_ZH_TW = {
|
|
2
|
+
"I removed what looked like a key from your message. If it was real, rotate it. Use the secure form to save it.": "我已從你的訊息中移除疑似金鑰的內容。如果是真實金鑰,請更換它。請使用安全表單儲存。",
|
|
3
|
+
"Use the secure form to save keys, tokens, passwords, and secrets. Chat answers are sent to the assistant.": "請使用安全表單儲存金鑰、權杖、密碼和機密資訊。聊天回答會傳送給助理。",
|
|
2
4
|
'# My skill\n\n1. Explain the workflow.\n2. Describe the inputs and outputs.': '# 我的技能\n\n1. 說明工作流程。\n2. 描述輸入與輸出。',
|
|
3
5
|
'A custom path override did not work, so this used the automatically detected binary instead.': '自訂路徑覆寫未生效,因此改用自動偵測到的二進位檔。',
|
|
4
6
|
'API key': 'API 金鑰',
|
|
@@ -2,10 +2,13 @@
|
|
|
2
2
|
export type LocaleDictionary = Readonly<Record<string, Readonly<Record<string, string>>>>;
|
|
3
3
|
/** Locale-bound translation injected into a widget or panel hook. */
|
|
4
4
|
export type Translate = (key: string) => string;
|
|
5
|
-
export type DictionaryTranslator = (required: {
|
|
5
|
+
export type DictionaryTranslator = ((required: {
|
|
6
6
|
locale: string;
|
|
7
7
|
key: string;
|
|
8
|
-
}) => string
|
|
8
|
+
}) => string) & {
|
|
9
|
+
/** Expose caller-owned copy so translation audits can detect untranslated locales despite fallback. */
|
|
10
|
+
readonly dictionary: LocaleDictionary;
|
|
11
|
+
};
|
|
9
12
|
/** Feature copy wins over the host's common copy, then falls back to the source key.
|
|
10
13
|
* No locale context or product dictionary is installed by this helper. */
|
|
11
14
|
export declare function createDictionaryTranslator({ featureDictionary }: {
|
|
@@ -9,6 +9,6 @@ function lookup(dictionary, locale, key) {
|
|
|
9
9
|
/** Feature copy wins over the host's common copy, then falls back to the source key.
|
|
10
10
|
* No locale context or product dictionary is installed by this helper. */
|
|
11
11
|
export function createDictionaryTranslator({ featureDictionary }, { commonDictionary = {} } = {}) {
|
|
12
|
-
return ({ locale, key }) => lookup(featureDictionary, locale, key) ?? lookup(commonDictionary, locale, key) ?? key;
|
|
12
|
+
return Object.assign(({ locale, key }) => lookup(featureDictionary, locale, key) ?? lookup(commonDictionary, locale, key) ?? key, { dictionary: featureDictionary });
|
|
13
13
|
}
|
|
14
14
|
//# sourceMappingURL=dictionary-translator.js.map
|
|
@@ -7,5 +7,5 @@ export { SETTINGS_DIALOG_EN, SETTINGS_DIALOG_ES, SETTINGS_DIALOG_DICTIONARIES, }
|
|
|
7
7
|
export type { SettingsDialogDict } from './dictionaries/index.js';
|
|
8
8
|
export { createDictionaryTranslator } from './dictionary-translator.js';
|
|
9
9
|
export type { Translate, DictionaryTranslator, LocaleDictionary } from './dictionary-translator.js';
|
|
10
|
-
export { interpolate, splitOnPlaceholders, pickPlural } from './template-i18n.js';
|
|
10
|
+
export { interpolate, splitOnPlaceholders, pickPlural, localeEntry } from './template-i18n.js';
|
|
11
11
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -2,5 +2,5 @@ export { detectInitialLocale, resolveSystemLocale, defaultDetectSystemLocale, }
|
|
|
2
2
|
export { I18nProvider, useI18n, useT } from './context.js';
|
|
3
3
|
export { SETTINGS_DIALOG_EN, SETTINGS_DIALOG_ES, SETTINGS_DIALOG_DICTIONARIES, } from './dictionaries/index.js';
|
|
4
4
|
export { createDictionaryTranslator } from './dictionary-translator.js';
|
|
5
|
-
export { interpolate, splitOnPlaceholders, pickPlural } from './template-i18n.js';
|
|
5
|
+
export { interpolate, splitOnPlaceholders, pickPlural, localeEntry } from './template-i18n.js';
|
|
6
6
|
//# sourceMappingURL=index.js.map
|
|
@@ -10,6 +10,7 @@ export declare function interpolate({ template, vars }: {
|
|
|
10
10
|
* Missing/mistyped locale tokens collapse the remaining text into one segment, followed by
|
|
11
11
|
* empty segments, so a translation defect does not crash its dialog.
|
|
12
12
|
*/
|
|
13
|
+
/** Returns tokens.length + 1 segments in token order; callers interleave their node values. */
|
|
13
14
|
export declare function splitOnPlaceholders({ template, tokens }: {
|
|
14
15
|
template: string;
|
|
15
16
|
tokens: readonly string[];
|
|
@@ -23,4 +24,14 @@ export declare function pickPlural({ count, forms }: {
|
|
|
23
24
|
other: string;
|
|
24
25
|
};
|
|
25
26
|
}): string;
|
|
27
|
+
/** Resolve caller-owned locale data, defaulting to English or an explicit fallback.
|
|
28
|
+
* Own-property lookup prevents constructor/toString/__proto__ locale names from returning
|
|
29
|
+
* prototype objects, which would throw when passed to a string interpolator.
|
|
30
|
+
* @throws When neither the requested entry nor a fallback is defined. */
|
|
31
|
+
export declare function localeEntry<T>({ table, locale }: {
|
|
32
|
+
table: Readonly<Record<string, T>>;
|
|
33
|
+
locale: string;
|
|
34
|
+
}, { fallback }?: {
|
|
35
|
+
fallback?: T;
|
|
36
|
+
}): T;
|
|
26
37
|
//# sourceMappingURL=template-i18n.d.ts.map
|
|
@@ -11,6 +11,7 @@ export function interpolate({ template, vars }) {
|
|
|
11
11
|
* Missing/mistyped locale tokens collapse the remaining text into one segment, followed by
|
|
12
12
|
* empty segments, so a translation defect does not crash its dialog.
|
|
13
13
|
*/
|
|
14
|
+
/** Returns tokens.length + 1 segments in token order; callers interleave their node values. */
|
|
14
15
|
export function splitOnPlaceholders({ template, tokens }) {
|
|
15
16
|
const segments = [];
|
|
16
17
|
let rest = template;
|
|
@@ -33,4 +34,15 @@ export function splitOnPlaceholders({ template, tokens }) {
|
|
|
33
34
|
export function pickPlural({ count, forms }) {
|
|
34
35
|
return count === 1 ? forms.one : forms.other;
|
|
35
36
|
}
|
|
37
|
+
/** Resolve caller-owned locale data, defaulting to English or an explicit fallback.
|
|
38
|
+
* Own-property lookup prevents constructor/toString/__proto__ locale names from returning
|
|
39
|
+
* prototype objects, which would throw when passed to a string interpolator.
|
|
40
|
+
* @throws When neither the requested entry nor a fallback is defined. */
|
|
41
|
+
export function localeEntry({ table, locale }, { fallback = table.en } = {}) {
|
|
42
|
+
const entry = Object.hasOwn(table, locale) ? (table[locale] ?? fallback) : fallback;
|
|
43
|
+
if (entry === undefined) {
|
|
44
|
+
throw new Error(`No locale entry for "${locale}" and no English or explicit fallback`);
|
|
45
|
+
}
|
|
46
|
+
return entry;
|
|
47
|
+
}
|
|
36
48
|
//# sourceMappingURL=template-i18n.js.map
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* The CSS variables every recharts provider paints with — the host's theme owns the colors.
|
|
5
5
|
*
|
|
6
6
|
* Why `--jini-chart-*` with fallbacks rather than bare `--jini-primary`: a host that styles its own
|
|
7
|
-
* chrome and never maps Jini's base tokens (
|
|
7
|
+
* chrome and never maps Jini's base tokens (an adopting admin shell) got Jini's near-black default bars, in
|
|
8
8
|
* dark mode too ("the color is ugly", demo V3, 2026-10-05). A host sets `--jini-chart-1`..`-6`,
|
|
9
9
|
* `--jini-chart-grid`, `--jini-chart-axis`, `--jini-chart-cursor`, `--jini-chart-surface` and
|
|
10
10
|
* `--jini-chart-text` in its own CSS; a host that sets none keeps the base-token look for the
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* The CSS variables every recharts provider paints with — the host's theme owns the colors.
|
|
5
5
|
*
|
|
6
6
|
* Why `--jini-chart-*` with fallbacks rather than bare `--jini-primary`: a host that styles its own
|
|
7
|
-
* chrome and never maps Jini's base tokens (
|
|
7
|
+
* chrome and never maps Jini's base tokens (an adopting admin shell) got Jini's near-black default bars, in
|
|
8
8
|
* dark mode too ("the color is ugly", demo V3, 2026-10-05). A host sets `--jini-chart-1`..`-6`,
|
|
9
9
|
* `--jini-chart-grid`, `--jini-chart-axis`, `--jini-chart-cursor`, `--jini-chart-surface` and
|
|
10
10
|
* `--jini-chart-text` in its own CSS; a host that sets none keeps the base-token look for the
|
|
@@ -1,8 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Origin: `apps/web/src/components/composer/deserialize.ts`. Ported
|
|
3
|
-
* verbatim, except `buildInlineMentionParts` → `parseMentionParts` (this
|
|
4
|
-
* package's generalized mention parser, see `mention-parser.ts`).
|
|
5
|
-
*/
|
|
6
1
|
import { type LexicalEditor } from 'lexical';
|
|
7
2
|
import type { MentionEntity } from './types.js';
|
|
8
3
|
export declare function setRichTextFromPlainText(editor: LexicalEditor, text: string, knownMentions: MentionEntity[]): void;
|
|
@@ -1,8 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Origin: `apps/web/src/components/composer/deserialize.ts`. Ported
|
|
3
|
-
* verbatim, except `buildInlineMentionParts` → `parseMentionParts` (this
|
|
4
|
-
* package's generalized mention parser, see `mention-parser.ts`).
|
|
5
|
-
*/
|
|
6
1
|
import { $createLineBreakNode, $createParagraphNode, $createTextNode, $getRoot, } from 'lexical';
|
|
7
2
|
import { $createMentionNode } from './mention-node.js';
|
|
8
3
|
import { parseMentionParts } from './mention-parser.js';
|
|
@@ -1,21 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* Origin: `apps/web/src/components/composer/MentionNode.ts`. The origin
|
|
9
|
-
* imported OD's `connectorBrandColor`/`resolveBrandTheme` directly to color
|
|
10
|
-
* a `connector`-kind pill's `--m-hue` CSS custom property, and installed a
|
|
11
|
-
* document-wide `MutationObserver` to re-stamp every mounted pill on a live
|
|
12
|
-
* theme flip. Both are dropped from this node entirely — no per-instance
|
|
13
|
-
* color logic and no global observer belong on a generic Lexical node class.
|
|
14
|
-
* A host that wants per-kind/per-entity coloring supplies a
|
|
15
|
-
* `resolveMentionColor` callback to `RichTextInput`, applied by
|
|
16
|
-
* `react/hooks/useMentionColorStamping.ts` via Lexical's own
|
|
17
|
-
* `registerMutationListener` (scoped to that one editor instance, not the
|
|
18
|
-
* whole document) — see that file for the replacement mechanism.
|
|
2
|
+
* Atomic @mention extends TextNode so getTextContent preserves the wire token. Token mode deletes
|
|
3
|
+
* one entity but still permits character-level caret movement; rules.ts normalizes arrow navigation.
|
|
4
|
+
* Generic nodes own no brand resolution or document-wide observer. Host colors enter through
|
|
5
|
+
* RichTextInput.resolveMentionColor and an editor-scoped Lexical mutation listener; see
|
|
6
|
+
* react/hooks/useMentionColorStamping.ts.
|
|
19
7
|
*/
|
|
20
8
|
import { TextNode, type EditorConfig, type LexicalNode, type NodeKey, type SerializedTextNode, type Spread } from 'lexical';
|
|
21
9
|
import type { MentionEntity } from './types.js';
|