@shwfed/config 1.0.0 → 1.1.0

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.
Files changed (48) hide show
  1. package/README.md +1 -0
  2. package/dist/module.json +1 -1
  3. package/dist/module.mjs +169 -23
  4. package/dist/runtime/components/config/footer.vue +0 -2
  5. package/dist/runtime/components/config/index.vue +13 -3
  6. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.daterange/config.d.vue.ts +2 -2
  7. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.daterange/config.vue +85 -10
  8. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.daterange/config.vue.d.ts +2 -2
  9. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.daterange/runtime.vue +18 -6
  10. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.daterange/schema.d.ts +1 -1
  11. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.daterange/schema.js +11 -4
  12. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.datetimerange/config.d.vue.ts +2 -2
  13. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.datetimerange/config.vue +85 -10
  14. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.datetimerange/config.vue.d.ts +2 -2
  15. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.datetimerange/runtime.vue +18 -6
  16. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.datetimerange/schema.d.ts +1 -1
  17. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.datetimerange/schema.js +11 -4
  18. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.timerange/config.d.vue.ts +2 -2
  19. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.timerange/config.vue +87 -11
  20. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.timerange/config.vue.d.ts +2 -2
  21. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.timerange/runtime.vue +18 -6
  22. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.timerange/schema.d.ts +1 -1
  23. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.timerange/schema.js +11 -4
  24. package/dist/runtime/components/form/fields/2026-05-12/com.shwfed.form.field.upload/config.vue +3 -0
  25. package/dist/runtime/components/form/fields/2026-05-12/com.shwfed.form.field.upload/runtime.vue +8 -0
  26. package/dist/runtime/components/form/index.vue +2 -2
  27. package/dist/runtime/components/table/ai/columns-button.vue +91 -98
  28. package/dist/runtime/components/table/ai/data-source-button.vue +88 -95
  29. package/dist/runtime/components/table/index.vue +5 -7
  30. package/dist/runtime/plugins/ai/index.d.ts +1 -5
  31. package/dist/runtime/plugins/ai/index.js +185 -441
  32. package/dist/runtime/plugins/cel/index.js +7 -0
  33. package/dist/runtime/vendor/cel-js/PROMPT.md +8 -0
  34. package/package.json +4 -4
  35. package/dist/chunks/index.mjs +0 -212742
  36. package/dist/runtime/components/ai/byok-button.d.vue.ts +0 -3
  37. package/dist/runtime/components/ai/byok-button.vue +0 -48
  38. package/dist/runtime/components/ai/byok-button.vue.d.ts +0 -3
  39. package/dist/runtime/components/ai/byok-settings.d.vue.ts +0 -3
  40. package/dist/runtime/components/ai/byok-settings.vue +0 -282
  41. package/dist/runtime/components/ai/byok-settings.vue.d.ts +0 -3
  42. package/dist/runtime/plugins/ai/gate.d.ts +0 -1
  43. package/dist/runtime/plugins/ai/gate.js +0 -8
  44. package/dist/runtime/plugins/ai/settings-state.d.ts +0 -1
  45. package/dist/runtime/plugins/ai/settings-state.js +0 -2
  46. package/dist/runtime/plugins/ai/store.d.ts +0 -17
  47. package/dist/runtime/plugins/ai/store.js +0 -40
  48. package/dist/shared/config.DW2OtAXe.mjs +0 -86529
@@ -1,3 +0,0 @@
1
- declare const __VLS_export: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
2
- declare const _default: typeof __VLS_export;
3
- export default _default;
@@ -1,48 +0,0 @@
1
- <script setup>
2
- import { useNuxtApp } from "#app";
3
- import { Icon } from "@iconify/vue";
4
- import { computed } from "vue";
5
- import { isByokAllowed } from "../../plugins/ai/gate";
6
- import { settingsOpen } from "../../plugins/ai/settings-state";
7
- import ByokSettings from "./byok-settings.vue";
8
- defineOptions({ name: "ShwfedAiByokButton" });
9
- const { $ai } = useNuxtApp();
10
- const allowed = isByokAllowed();
11
- const status = computed(() => {
12
- const c = $ai.config.value;
13
- if (!c) {
14
- return {
15
- icon: "fluent:sparkle-20-regular",
16
- label: "AI \u672A\u914D\u7F6E",
17
- hint: "\u70B9\u51FB\u914D\u7F6E BYOK \u5BC6\u94A5"
18
- };
19
- }
20
- return {
21
- icon: "fluent:magic-wand-20-regular",
22
- label: "AI",
23
- hint: c.model ?? "\u9ED8\u8BA4\u6A21\u578B"
24
- };
25
- });
26
- </script>
27
-
28
- <template>
29
- <template v-if="allowed">
30
- <button
31
- type="button"
32
- class="byok-button"
33
- :title="status.hint"
34
- @click="settingsOpen = true"
35
- >
36
- <Icon
37
- :icon="status.icon"
38
- class="size-4 shrink-0"
39
- />
40
- <span class="truncate">{{ status.label }}</span>
41
- </button>
42
- <ByokSettings />
43
- </template>
44
- </template>
45
-
46
- <style scoped>
47
- .byok-button{align-items:center;border-radius:.25rem;color:#71717a;display:inline-flex;font-size:.75rem;gap:.375rem;padding-block:.25rem;padding-inline:.5rem;transition:background-color .1s ease,color .1s ease}.byok-button:hover{background-color:#f4f4f5;color:#3f3f46}
48
- </style>
@@ -1,3 +0,0 @@
1
- declare const __VLS_export: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
2
- declare const _default: typeof __VLS_export;
3
- export default _default;
@@ -1,3 +0,0 @@
1
- declare const __VLS_export: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
2
- declare const _default: typeof __VLS_export;
3
- export default _default;
@@ -1,282 +0,0 @@
1
- <script setup>
2
- import { useNuxtApp } from "#app";
3
- import { Icon } from "@iconify/vue";
4
- import { computed, ref, watch } from "vue";
5
- import { toast } from "vue-sonner";
6
- import ShwfedModal from "../modal.vue";
7
- import { Button } from "../ui/button";
8
- import { Field, FieldLabel, FieldDescription } from "../ui/field";
9
- import { Input } from "../ui/input";
10
- import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "../ui/select";
11
- import { settingsOpen } from "../../plugins/ai/settings-state";
12
- import { DEFAULT_MAX_TOKENS, PROVIDER_DEFAULTS } from "../../plugins/ai/store";
13
- const ANTHROPIC_ENTRY = { value: "anthropic", label: "Anthropic \u517C\u5BB9", icon: "simple-icons:anthropic" };
14
- const OPENAI_ENTRY = { value: "openai", label: "OpenAI \u517C\u5BB9", icon: "simple-icons:openai" };
15
- const PROVIDER_ENTRIES = [ANTHROPIC_ENTRY, OPENAI_ENTRY];
16
- defineOptions({ name: "ShwfedAiByokSettings" });
17
- const { $ai } = useNuxtApp();
18
- const provider = ref("anthropic");
19
- const apiKey = ref("");
20
- const showKey = ref(false);
21
- const advanced = ref(false);
22
- const model = ref("");
23
- const endpoint = ref("");
24
- const maxTokens = ref(void 0);
25
- const testing = ref(false);
26
- watch(settingsOpen, (open) => {
27
- if (!open) return;
28
- const c = $ai.config.value;
29
- if (c) {
30
- provider.value = c.provider;
31
- apiKey.value = c.apiKey;
32
- model.value = c.model ?? "";
33
- endpoint.value = c.endpoint ?? "";
34
- maxTokens.value = c.maxTokens;
35
- advanced.value = !!(c.model || c.endpoint || c.maxTokens);
36
- } else {
37
- provider.value = "anthropic";
38
- apiKey.value = "";
39
- model.value = "";
40
- endpoint.value = "";
41
- maxTokens.value = void 0;
42
- advanced.value = false;
43
- }
44
- showKey.value = false;
45
- });
46
- const placeholder = computed(() => PROVIDER_DEFAULTS[provider.value]);
47
- const apiKeyPlaceholder = computed(() => provider.value === "anthropic" ? "sk-ant-..." : "sk-...");
48
- function buildConfig() {
49
- if (!apiKey.value.trim()) return null;
50
- const mt = maxTokens.value;
51
- return {
52
- provider: provider.value,
53
- apiKey: apiKey.value.trim(),
54
- model: advanced.value && model.value.trim() ? model.value.trim() : void 0,
55
- endpoint: advanced.value && endpoint.value.trim() ? endpoint.value.trim() : void 0,
56
- maxTokens: advanced.value && typeof mt === "number" && Number.isFinite(mt) && mt > 0 ? Math.floor(mt) : void 0
57
- };
58
- }
59
- const canSave = computed(() => !!apiKey.value.trim());
60
- function onSave() {
61
- const next = buildConfig();
62
- if (!next) return;
63
- $ai.setConfig(next);
64
- toast.success("AI \u914D\u7F6E\u5DF2\u4FDD\u5B58");
65
- settingsOpen.value = false;
66
- }
67
- function onClear() {
68
- $ai.setConfig(null);
69
- apiKey.value = "";
70
- model.value = "";
71
- endpoint.value = "";
72
- maxTokens.value = void 0;
73
- toast.success("AI \u914D\u7F6E\u5DF2\u6E05\u9664");
74
- settingsOpen.value = false;
75
- }
76
- async function onTest() {
77
- const draft = buildConfig();
78
- if (!draft) {
79
- toast.error("\u8BF7\u5148\u586B\u5199 API Key");
80
- return;
81
- }
82
- const previous = $ai.config.value;
83
- $ai.setConfig(draft);
84
- testing.value = true;
85
- try {
86
- const out = await $ai.generateText({ prompt: "ping" });
87
- toast.success("\u8FDE\u63A5\u6210\u529F", { description: out.slice(0, 80) });
88
- } catch (err) {
89
- $ai.setConfig(previous);
90
- const message = err instanceof Error ? err.message : String(err);
91
- toast.error("\u8FDE\u63A5\u5931\u8D25", { description: message });
92
- } finally {
93
- testing.value = false;
94
- }
95
- }
96
- </script>
97
-
98
- <template>
99
- <ShwfedModal
100
- v-model:open="settingsOpen"
101
- content-width="32rem"
102
- :dismissible="!testing"
103
- >
104
- <template #title>
105
- <span class="flex items-center gap-2">
106
- <Icon
107
- icon="fluent:sparkle-20-regular"
108
- class="size-5"
109
- />
110
- AI 配置 (BYOK)
111
- </span>
112
- </template>
113
- <template #description>
114
- 使用您自己的 API Key 直接调用模型。仅本地有效,密钥保存在浏览器中,不会上传。
115
- </template>
116
-
117
- <form
118
- class="flex flex-col gap-4 py-2"
119
- autocomplete="off"
120
- @submit.prevent="onSave"
121
- >
122
- <Field orientation="vertical">
123
- <FieldLabel class="text-xs text-zinc-500">
124
- 供应商
125
- </FieldLabel>
126
- <Select
127
- :model-value="provider"
128
- @update:model-value="(v) => provider = v"
129
- >
130
- <SelectTrigger class="w-full">
131
- <SelectValue />
132
- </SelectTrigger>
133
- <SelectContent>
134
- <SelectItem
135
- v-for="entry in PROVIDER_ENTRIES"
136
- :key="entry.value"
137
- :value="entry.value"
138
- >
139
- <span class="inline-flex items-center gap-2">
140
- <Icon
141
- :icon="entry.icon"
142
- class="size-4 shrink-0"
143
- />
144
- <span>{{ entry.label }}</span>
145
- </span>
146
- </SelectItem>
147
- </SelectContent>
148
- </Select>
149
- </Field>
150
-
151
- <Field orientation="vertical">
152
- <FieldLabel class="text-xs text-zinc-500">
153
- API Key
154
- </FieldLabel>
155
- <div class="relative">
156
- <Input
157
- v-model="apiKey"
158
- :type="showKey ? 'text' : 'password'"
159
- :placeholder="apiKeyPlaceholder"
160
- autocomplete="off"
161
- class="pr-10"
162
- />
163
- <button
164
- type="button"
165
- class="absolute right-2 top-1/2 -translate-y-1/2 text-zinc-400 hover:text-zinc-600"
166
- @click="showKey = !showKey"
167
- >
168
- <Icon
169
- :icon="showKey ? 'fluent:eye-off-20-regular' : 'fluent:eye-20-regular'"
170
- class="size-4"
171
- />
172
- </button>
173
- </div>
174
- </Field>
175
-
176
- <button
177
- type="button"
178
- class="flex w-fit items-center gap-1 text-xs text-zinc-500 hover:text-zinc-700"
179
- @click="advanced = !advanced"
180
- >
181
- <Icon
182
- :icon="advanced ? 'fluent:chevron-down-20-regular' : 'fluent:chevron-right-20-regular'"
183
- class="size-3.5"
184
- />
185
- 高级
186
- </button>
187
-
188
- <div
189
- v-if="advanced"
190
- class="flex flex-col gap-4 rounded border border-zinc-100 bg-zinc-50/40 p-3"
191
- >
192
- <Field orientation="vertical">
193
- <FieldLabel class="text-xs text-zinc-500">
194
- 模型
195
- </FieldLabel>
196
- <FieldDescription class="text-xs text-zinc-400">
197
- 留空使用默认:{{ placeholder.model }}
198
- </FieldDescription>
199
- <Input
200
- v-model="model"
201
- :placeholder="placeholder.model"
202
- />
203
- </Field>
204
- <Field orientation="vertical">
205
- <FieldLabel class="text-xs text-zinc-500">
206
- 端点
207
- </FieldLabel>
208
- <FieldDescription class="text-xs text-zinc-400">
209
- 完整请求 URL,将被原样使用(如 OpenRouter 或后端代理)。留空使用默认:{{ placeholder.endpoint }}
210
- </FieldDescription>
211
- <Input
212
- v-model="endpoint"
213
- :placeholder="placeholder.endpoint"
214
- />
215
- </Field>
216
- <Field orientation="vertical">
217
- <FieldLabel class="text-xs text-zinc-500">
218
- 最大输出 token
219
- </FieldLabel>
220
- <FieldDescription class="text-xs text-zinc-400">
221
- 单次响应可生成的最大 token 数;推理模型需要更高额度以容纳隐式思考。留空使用默认:{{ DEFAULT_MAX_TOKENS }}
222
- </FieldDescription>
223
- <Input
224
- :model-value="maxTokens ?? ''"
225
- type="number"
226
- min="1"
227
- :placeholder="String(DEFAULT_MAX_TOKENS)"
228
- @update:model-value="(v) => {
229
- const n = typeof v === 'number' ? v : Number(v);
230
- maxTokens = Number.isFinite(n) && n > 0 ? Math.floor(n) : void 0;
231
- }"
232
- />
233
- </Field>
234
- </div>
235
- </form>
236
-
237
- <template #footer>
238
- <div class="flex items-center justify-between gap-3">
239
- <Button
240
- v-if="$ai.config.value"
241
- type="button"
242
- variant="ghost"
243
- size="sm"
244
- :disabled="testing"
245
- @click="onClear"
246
- >
247
- <Icon icon="fluent:delete-20-regular" />
248
- 清除
249
- </Button>
250
- <span
251
- v-else
252
- class="flex-1"
253
- />
254
- <div class="flex items-center gap-2">
255
- <Button
256
- type="button"
257
- variant="default"
258
- size="sm"
259
- :disabled="!canSave || testing"
260
- @click="onTest"
261
- >
262
- <Icon
263
- :icon="testing ? 'fluent:arrow-sync-20-regular' : 'fluent:flash-20-regular'"
264
- :class="testing ? 'animate-spin' : ''"
265
- />
266
- 测试
267
- </Button>
268
- <Button
269
- type="button"
270
- variant="primary"
271
- size="sm"
272
- :disabled="!canSave || testing"
273
- @click="onSave"
274
- >
275
- <Icon icon="fluent:checkmark-20-regular" />
276
- 保存
277
- </Button>
278
- </div>
279
- </div>
280
- </template>
281
- </ShwfedModal>
282
- </template>
@@ -1,3 +0,0 @@
1
- declare const __VLS_export: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
2
- declare const _default: typeof __VLS_export;
3
- export default _default;
@@ -1 +0,0 @@
1
- export declare function isByokAllowed(): boolean;
@@ -1,8 +0,0 @@
1
- export function isByokAllowed() {
2
- if (typeof window === "undefined") return false;
3
- const h = window.location.hostname;
4
- if (h === "localhost" || h === "127.0.0.1") return true;
5
- if (h.startsWith("beta.")) return true;
6
- if (h.includes(".beta.")) return true;
7
- return false;
8
- }
@@ -1 +0,0 @@
1
- export declare const settingsOpen: import("vue").Ref<boolean, boolean>;
@@ -1,2 +0,0 @@
1
- import { ref } from "vue";
2
- export const settingsOpen = ref(false);
@@ -1,17 +0,0 @@
1
- import { type Ref } from 'vue';
2
- export type AiProvider = 'anthropic' | 'openai';
3
- export interface AiConfig {
4
- provider: AiProvider;
5
- apiKey: string;
6
- model?: string;
7
- endpoint?: string;
8
- maxTokens?: number;
9
- }
10
- export declare const DEFAULT_MAX_TOKENS = 8192;
11
- export declare function loadConfig(): AiConfig | null;
12
- export declare function saveConfig(config: AiConfig | null): void;
13
- export declare function createConfigRef(): Ref<AiConfig | null>;
14
- export declare const PROVIDER_DEFAULTS: Record<AiProvider, {
15
- model: string;
16
- endpoint: string;
17
- }>;
@@ -1,40 +0,0 @@
1
- import { ref, watch } from "vue";
2
- export const DEFAULT_MAX_TOKENS = 8192;
3
- const STORAGE_KEY = "shwfed:ai:byok";
4
- function isProvider(v) {
5
- return v === "anthropic" || v === "openai";
6
- }
7
- export function loadConfig() {
8
- if (typeof window === "undefined") return null;
9
- try {
10
- const raw = window.localStorage.getItem(STORAGE_KEY);
11
- if (!raw) return null;
12
- const parsed = JSON.parse(raw);
13
- if (!parsed || typeof parsed !== "object") return null;
14
- if (typeof parsed.apiKey !== "string" || parsed.apiKey.length === 0) return null;
15
- if (!isProvider(parsed.provider)) return null;
16
- return {
17
- provider: parsed.provider,
18
- apiKey: parsed.apiKey,
19
- model: typeof parsed.model === "string" && parsed.model ? parsed.model : void 0,
20
- endpoint: typeof parsed.endpoint === "string" && parsed.endpoint ? parsed.endpoint : void 0,
21
- maxTokens: typeof parsed.maxTokens === "number" && Number.isFinite(parsed.maxTokens) && parsed.maxTokens > 0 ? Math.floor(parsed.maxTokens) : void 0
22
- };
23
- } catch {
24
- return null;
25
- }
26
- }
27
- export function saveConfig(config) {
28
- if (typeof window === "undefined") return;
29
- if (config === null) window.localStorage.removeItem(STORAGE_KEY);
30
- else window.localStorage.setItem(STORAGE_KEY, JSON.stringify(config));
31
- }
32
- export function createConfigRef() {
33
- const r = ref(loadConfig());
34
- watch(r, (next) => saveConfig(next), { deep: true });
35
- return r;
36
- }
37
- export const PROVIDER_DEFAULTS = {
38
- anthropic: { model: "claude-sonnet-4-5-20250929", endpoint: "https://api.anthropic.com/v1/messages" },
39
- openai: { model: "gpt-4o-mini", endpoint: "https://api.openai.com/v1/chat/completions" }
40
- };