@shwfed/config 1.0.0 → 1.0.1

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 (47) hide show
  1. package/dist/module.json +1 -1
  2. package/dist/module.mjs +117 -23
  3. package/dist/runtime/components/config/footer.vue +0 -2
  4. package/dist/runtime/components/config/index.vue +13 -3
  5. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.daterange/config.d.vue.ts +2 -2
  6. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.daterange/config.vue +85 -10
  7. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.daterange/config.vue.d.ts +2 -2
  8. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.daterange/runtime.vue +18 -6
  9. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.daterange/schema.d.ts +1 -1
  10. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.daterange/schema.js +11 -4
  11. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.datetimerange/config.d.vue.ts +2 -2
  12. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.datetimerange/config.vue +85 -10
  13. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.datetimerange/config.vue.d.ts +2 -2
  14. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.datetimerange/runtime.vue +18 -6
  15. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.datetimerange/schema.d.ts +1 -1
  16. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.datetimerange/schema.js +11 -4
  17. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.timerange/config.d.vue.ts +2 -2
  18. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.timerange/config.vue +87 -11
  19. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.timerange/config.vue.d.ts +2 -2
  20. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.timerange/runtime.vue +18 -6
  21. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.timerange/schema.d.ts +1 -1
  22. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.timerange/schema.js +11 -4
  23. package/dist/runtime/components/form/fields/2026-05-12/com.shwfed.form.field.upload/config.vue +3 -0
  24. package/dist/runtime/components/form/fields/2026-05-12/com.shwfed.form.field.upload/runtime.vue +8 -0
  25. package/dist/runtime/components/form/index.vue +2 -2
  26. package/dist/runtime/components/table/ai/columns-button.vue +91 -98
  27. package/dist/runtime/components/table/ai/data-source-button.vue +88 -95
  28. package/dist/runtime/components/table/index.vue +5 -7
  29. package/dist/runtime/plugins/ai/index.d.ts +1 -5
  30. package/dist/runtime/plugins/ai/index.js +185 -441
  31. package/dist/runtime/plugins/cel/index.js +7 -0
  32. package/dist/runtime/vendor/cel-js/PROMPT.md +8 -0
  33. package/package.json +4 -4
  34. package/dist/chunks/index.mjs +0 -212742
  35. package/dist/runtime/components/ai/byok-button.d.vue.ts +0 -3
  36. package/dist/runtime/components/ai/byok-button.vue +0 -48
  37. package/dist/runtime/components/ai/byok-button.vue.d.ts +0 -3
  38. package/dist/runtime/components/ai/byok-settings.d.vue.ts +0 -3
  39. package/dist/runtime/components/ai/byok-settings.vue +0 -282
  40. package/dist/runtime/components/ai/byok-settings.vue.d.ts +0 -3
  41. package/dist/runtime/plugins/ai/gate.d.ts +0 -1
  42. package/dist/runtime/plugins/ai/gate.js +0 -8
  43. package/dist/runtime/plugins/ai/settings-state.d.ts +0 -1
  44. package/dist/runtime/plugins/ai/settings-state.js +0 -2
  45. package/dist/runtime/plugins/ai/store.d.ts +0 -17
  46. package/dist/runtime/plugins/ai/store.js +0 -40
  47. package/dist/shared/config.DW2OtAXe.mjs +0 -86529
@@ -1,13 +1,10 @@
1
1
  import { defineNuxtPlugin } from "#app";
2
2
  import { computed } from "vue";
3
3
  import { JSONSchema, Schema } from "effect";
4
- import { isByokAllowed } from "./gate.js";
5
- import { createConfigRef, DEFAULT_MAX_TOKENS as CONFIG_DEFAULT_MAX_TOKENS } from "./store.js";
6
- import { settingsOpen } from "./settings-state.js";
7
- const DEFAULT_ANTHROPIC_MODEL = "claude-sonnet-4-5-20250929";
8
- const DEFAULT_ANTHROPIC_ENDPOINT = "https://api.anthropic.com/v1/messages";
9
- const DEFAULT_OPENAI_MODEL = "gpt-4o-mini";
10
- const DEFAULT_OPENAI_ENDPOINT = "https://api.openai.com/v1/chat/completions";
4
+ const ENDPOINT = "http://192.168.168.10/anthropic/v1/messages";
5
+ const MODEL = "MiniMax-M2.7";
6
+ const ANTHROPIC_VERSION = "2023-06-01";
7
+ const DEFAULT_MAX_TOKENS = 8192;
11
8
  export class StructuredOutputDecodeError extends Error {
12
9
  rawOutput;
13
10
  constructor(rawOutput, cause) {
@@ -51,467 +48,214 @@ async function* readSSE(res) {
51
48
  }
52
49
  }
53
50
  }
54
- function buildAnthropicClient(cfg) {
55
- const endpoint = cfg.endpoint ?? DEFAULT_ANTHROPIC_ENDPOINT;
56
- const model = cfg.model ?? DEFAULT_ANTHROPIC_MODEL;
57
- const configuredMaxTokens = cfg.maxTokens ?? CONFIG_DEFAULT_MAX_TOKENS;
58
- const RETRY_TOOL_USE_ID = "retry_call_0";
59
- function buildBody(messages, options) {
60
- return {
61
- model,
62
- max_tokens: options.maxTokens ?? configuredMaxTokens,
63
- messages,
64
- ...options.system !== void 0 ? { system: options.system } : {},
65
- ...options.tools !== void 0 ? { tools: options.tools } : {},
66
- ...options.toolChoice !== void 0 ? { tool_choice: options.toolChoice } : {}
67
- };
68
- }
69
- function buildInitialMessages(prompt, retry) {
70
- const messages = [{ role: "user", content: prompt }];
71
- if (retry) {
72
- messages.push({
73
- role: "assistant",
74
- content: [{
75
- type: "tool_use",
76
- id: RETRY_TOOL_USE_ID,
77
- name: retry.toolName,
78
- input: retry.previousOutput
79
- }]
80
- });
81
- messages.push({
82
- role: "user",
83
- content: [{
84
- type: "tool_result",
85
- tool_use_id: RETRY_TOOL_USE_ID,
86
- content: retry.feedback
87
- }]
88
- });
89
- }
90
- return messages;
91
- }
92
- function buildInit(body, signal) {
93
- return {
94
- method: "POST",
95
- headers: {
96
- "content-type": "application/json",
97
- "x-api-key": cfg.apiKey,
98
- "anthropic-version": "2023-06-01",
99
- // CORS opt-in for browser-direct calls. The name is deliberately
100
- // scary — keys live in localStorage on dev/beta only, gated by gate.ts.
101
- "anthropic-dangerous-direct-browser-access": "true"
102
- },
103
- body: JSON.stringify(body),
104
- ...signal ? { signal } : {}
105
- };
51
+ function buildBody(messages, system, options) {
52
+ return {
53
+ model: MODEL,
54
+ messages,
55
+ max_tokens: options.maxTokens ?? DEFAULT_MAX_TOKENS,
56
+ ...system !== void 0 ? { system } : {},
57
+ ...options.tools !== void 0 ? { tools: options.tools } : {},
58
+ ...options.toolChoice !== void 0 ? { tool_choice: options.toolChoice } : {}
59
+ };
60
+ }
61
+ function buildInit(body, signal) {
62
+ return {
63
+ method: "POST",
64
+ headers: {
65
+ "content-type": "application/json",
66
+ "anthropic-version": ANTHROPIC_VERSION,
67
+ "anthropic-dangerous-direct-browser-access": "true"
68
+ },
69
+ body: JSON.stringify(body),
70
+ ...signal ? { signal } : {}
71
+ };
72
+ }
73
+ async function call(messages, system, options, signal) {
74
+ const res = await fetch(ENDPOINT, buildInit(buildBody(messages, system, options), signal));
75
+ if (!res.ok) {
76
+ throw new Error(`Anthropic ${res.status}: ${await readError(res) || res.statusText}`);
106
77
  }
107
- async function call(messages, options, signal) {
108
- const res = await fetch(endpoint, buildInit(buildBody(messages, options), signal));
109
- if (!res.ok) {
110
- throw new Error(`Anthropic ${res.status}: ${await readError(res) || res.statusText}`);
111
- }
112
- return await res.json();
78
+ return await res.json();
79
+ }
80
+ async function callStream(messages, system, options, signal, onProgress) {
81
+ const body = { ...buildBody(messages, system, options), stream: true };
82
+ const res = await fetch(ENDPOINT, buildInit(body, signal));
83
+ if (!res.ok) {
84
+ throw new Error(`Anthropic ${res.status}: ${await readError(res) || res.statusText}`);
113
85
  }
114
- async function callStream(messages, options, signal, onProgress) {
115
- const body = { ...buildBody(messages, options), stream: true };
116
- const res = await fetch(endpoint, buildInit(body, signal));
117
- if (!res.ok) {
118
- throw new Error(`Anthropic ${res.status}: ${await readError(res) || res.statusText}`);
86
+ const blocks = /* @__PURE__ */ new Map();
87
+ let stopReason;
88
+ for await (const ev of readSSE(res)) {
89
+ if (!ev.event || !ev.data) continue;
90
+ let payload;
91
+ try {
92
+ payload = JSON.parse(ev.data);
93
+ } catch {
94
+ continue;
119
95
  }
120
- const blocks = /* @__PURE__ */ new Map();
121
- for await (const ev of readSSE(res)) {
122
- if (ev.event === "content_block_start") {
123
- const data = JSON.parse(ev.data);
124
- blocks.set(data.index, {
125
- type: data.content_block.type,
126
- id: data.content_block.id,
127
- name: data.content_block.name,
128
- text: "",
129
- inputJson: ""
130
- });
131
- } else if (ev.event === "content_block_delta") {
132
- const data = JSON.parse(ev.data);
133
- const block = blocks.get(data.index);
134
- if (!block) continue;
135
- if (data.delta.type === "text_delta" && data.delta.text) {
136
- block.text += data.delta.text;
137
- onProgress();
138
- } else if (data.delta.type === "input_json_delta" && data.delta.partial_json) {
139
- block.inputJson += data.delta.partial_json;
140
- onProgress();
141
- }
96
+ const p = payload;
97
+ if (p.type === "content_block_start" && typeof p.index === "number" && p.content_block) {
98
+ const cb = p.content_block;
99
+ blocks.set(p.index, {
100
+ type: cb.type === "tool_use" ? "tool_use" : "text",
101
+ text: "",
102
+ toolId: cb.id,
103
+ toolName: cb.name,
104
+ inputJson: ""
105
+ });
106
+ } else if (p.type === "content_block_delta" && typeof p.index === "number" && p.delta) {
107
+ const cur = blocks.get(p.index);
108
+ if (!cur) continue;
109
+ if (p.delta.type === "text_delta" && p.delta.text) {
110
+ cur.text += p.delta.text;
111
+ onProgress();
112
+ } else if (p.delta.type === "input_json_delta" && p.delta.partial_json) {
113
+ cur.inputJson += p.delta.partial_json;
114
+ onProgress();
142
115
  }
116
+ } else if (p.type === "message_delta" && p.delta?.stop_reason) {
117
+ stopReason = p.delta.stop_reason;
118
+ } else if (p.type === "message_stop") {
119
+ break;
143
120
  }
144
- const ordered = [...blocks.entries()].sort(([a], [b]) => a - b);
145
- const content = ordered.map(([, block]) => {
146
- if (block.type === "text") return { type: "text", text: block.text };
147
- if (block.type === "tool_use") {
148
- let input = {};
149
- if (block.inputJson) {
150
- try {
151
- input = JSON.parse(block.inputJson);
152
- } catch {
153
- }
154
- }
155
- return {
156
- type: "tool_use",
157
- id: block.id ?? "",
158
- name: block.name ?? "",
159
- input
160
- };
161
- }
162
- return { type: block.type };
163
- });
164
- return { content };
165
121
  }
166
- function extractText(response) {
167
- return response.content.filter((b) => b.type === "text").map((b) => b.text).join("");
168
- }
169
- return {
170
- async generateText(input) {
171
- const opts = {
172
- ...input.system !== void 0 ? { system: input.system } : {},
173
- ...input.maxTokens !== void 0 ? { maxTokens: input.maxTokens } : {}
174
- };
175
- const messages = [{ role: "user", content: input.prompt }];
176
- const response = input.onProgress ? await callStream(messages, opts, input.signal, input.onProgress) : await call(messages, opts, input.signal);
177
- return extractText(response);
178
- },
179
- async generateObject(input) {
180
- const toolName = input.objectName ?? "structured_output";
181
- const structuredSchema = JSONSchema.make(input.schema);
182
- const helperTools = input.tools ?? [];
183
- const helperByName = new Map(helperTools.map((t) => [t.name, t]));
184
- const tools = [
185
- ...helperTools.map((t) => ({
186
- name: t.name,
187
- description: t.description,
188
- input_schema: t.inputJsonSchema
189
- })),
190
- {
191
- name: toolName,
192
- description: "Return the structured output as the tool input.",
193
- input_schema: structuredSchema
194
- }
195
- ];
196
- const toolChoice = helperTools.length > 0 ? { type: "any" } : { type: "tool", name: toolName };
197
- const optsBase = {
198
- ...input.system !== void 0 ? { system: input.system } : {},
199
- ...input.maxTokens !== void 0 ? { maxTokens: input.maxTokens } : {},
200
- tools,
201
- toolChoice
202
- };
203
- const messages = buildInitialMessages(
204
- input.prompt,
205
- input.retry !== void 0 ? { ...input.retry, toolName } : void 0
206
- );
207
- const decode = (raw) => {
122
+ const content = [...blocks.entries()].sort(([a], [b]) => a - b).map(([, v]) => {
123
+ if (v.type === "tool_use") {
124
+ let input = {};
125
+ if (v.inputJson) {
208
126
  try {
209
- return Schema.decodeUnknownSync(input.schema)(raw);
210
- } catch (cause) {
211
- throw new StructuredOutputDecodeError(raw, cause);
212
- }
213
- };
214
- for (; ; ) {
215
- const response = input.onProgress ? await callStream(messages, optsBase, input.signal, input.onProgress) : await call(messages, optsBase, input.signal);
216
- const structured = response.content.find(
217
- (b) => b.type === "tool_use" && b.name === toolName
218
- );
219
- if (structured) return decode(structured.input);
220
- const helperCalls = response.content.filter(
221
- (b) => b.type === "tool_use"
222
- );
223
- if (helperCalls.length === 0) {
224
- const text = response.content.filter((b) => b.type === "text").map((b) => b.text).join("");
225
- throw new Error(`\u6A21\u578B\u672A\u8FD4\u56DE\u7ED3\u6784\u5316\u8F93\u51FA${text ? `: ${text.slice(0, 200)}` : ""}`);
226
- }
227
- const toolResults = [];
228
- for (const callBlock of helperCalls) {
229
- const tool = helperByName.get(callBlock.name);
230
- if (!tool) {
231
- toolResults.push({
232
- type: "tool_result",
233
- tool_use_id: callBlock.id,
234
- content: `Unknown tool: ${callBlock.name}`,
235
- is_error: true
236
- });
237
- continue;
238
- }
239
- try {
240
- const result = await tool.execute(callBlock.input);
241
- toolResults.push({
242
- type: "tool_result",
243
- tool_use_id: callBlock.id,
244
- content: typeof result === "string" ? result : JSON.stringify(result)
245
- });
246
- } catch (err) {
247
- toolResults.push({
248
- type: "tool_result",
249
- tool_use_id: callBlock.id,
250
- content: err instanceof Error ? err.message : String(err),
251
- is_error: true
252
- });
253
- }
127
+ input = JSON.parse(v.inputJson);
128
+ } catch {
129
+ input = {};
254
130
  }
255
- messages.push({ role: "assistant", content: response.content });
256
- messages.push({ role: "user", content: toolResults });
257
131
  }
132
+ return {
133
+ type: "tool_use",
134
+ id: v.toolId ?? "",
135
+ name: v.toolName ?? "",
136
+ input
137
+ };
258
138
  }
259
- };
139
+ return { type: "text", text: v.text };
140
+ });
141
+ return { content, stop_reason: stopReason };
260
142
  }
261
- function buildOpenAIClient(cfg) {
262
- const endpoint = cfg.endpoint ?? DEFAULT_OPENAI_ENDPOINT;
263
- const model = cfg.model ?? DEFAULT_OPENAI_MODEL;
264
- const configuredMaxTokens = cfg.maxTokens ?? CONFIG_DEFAULT_MAX_TOKENS;
265
- function buildBody(messages, options) {
266
- return {
267
- model,
268
- messages,
269
- max_tokens: options.maxTokens ?? configuredMaxTokens,
270
- ...options.tools !== void 0 ? { tools: options.tools } : {},
271
- ...options.toolChoice !== void 0 ? { tool_choice: options.toolChoice } : {}
272
- };
273
- }
274
- function buildInit(body, signal) {
275
- return {
276
- method: "POST",
277
- headers: {
278
- "content-type": "application/json",
279
- "authorization": `Bearer ${cfg.apiKey}`
280
- },
281
- body: JSON.stringify(body),
282
- ...signal ? { signal } : {}
283
- };
284
- }
285
- async function call(messages, options, signal) {
286
- const res = await fetch(endpoint, buildInit(buildBody(messages, options), signal));
287
- if (!res.ok) {
288
- throw new Error(`OpenAI ${res.status}: ${await readError(res) || res.statusText}`);
143
+ const RETRY_TOOL_USE_ID = "retry_call_0";
144
+ function buildUserMessages(prompt) {
145
+ return [{ role: "user", content: prompt }];
146
+ }
147
+ function appendRetry(messages, retry, toolName) {
148
+ messages.push({
149
+ role: "assistant",
150
+ content: [{
151
+ type: "tool_use",
152
+ id: RETRY_TOOL_USE_ID,
153
+ name: toolName,
154
+ input: retry.previousOutput
155
+ }]
156
+ });
157
+ messages.push({
158
+ role: "user",
159
+ content: [{
160
+ type: "tool_result",
161
+ tool_use_id: RETRY_TOOL_USE_ID,
162
+ content: retry.feedback
163
+ }]
164
+ });
165
+ }
166
+ async function generateText(input) {
167
+ const messages = buildUserMessages(input.prompt);
168
+ const opts = input.maxTokens !== void 0 ? { maxTokens: input.maxTokens } : {};
169
+ const response = input.onProgress ? await callStream(messages, input.system, opts, input.signal, input.onProgress) : await call(messages, input.system, opts, input.signal);
170
+ return response.content.filter((b) => b.type === "text").map((b) => b.text).join("");
171
+ }
172
+ async function generateObject(input) {
173
+ const toolName = input.objectName ?? "structured_output";
174
+ const structuredParams = JSONSchema.make(input.schema);
175
+ const helperTools = input.tools ?? [];
176
+ const helperByName = new Map(helperTools.map((t) => [t.name, t]));
177
+ const tools = [
178
+ ...helperTools.map((t) => ({
179
+ name: t.name,
180
+ description: t.description,
181
+ input_schema: t.inputJsonSchema
182
+ })),
183
+ {
184
+ name: toolName,
185
+ description: "Return the structured output as the tool input.",
186
+ input_schema: structuredParams
289
187
  }
290
- return await res.json();
291
- }
292
- async function callStream(messages, options, signal, onProgress) {
293
- const body = { ...buildBody(messages, options), stream: true };
294
- const res = await fetch(endpoint, buildInit(body, signal));
295
- if (!res.ok) {
296
- throw new Error(`OpenAI ${res.status}: ${await readError(res) || res.statusText}`);
188
+ ];
189
+ const toolChoice = helperTools.length > 0 ? { type: "any" } : { type: "tool", name: toolName };
190
+ const messages = buildUserMessages(input.prompt);
191
+ if (input.retry) appendRetry(messages, input.retry, toolName);
192
+ const opts = {
193
+ tools,
194
+ toolChoice,
195
+ ...input.maxTokens !== void 0 ? { maxTokens: input.maxTokens } : {}
196
+ };
197
+ const decode = (raw) => {
198
+ try {
199
+ return Schema.decodeUnknownSync(input.schema)(raw);
200
+ } catch (cause) {
201
+ throw new StructuredOutputDecodeError(raw, cause);
297
202
  }
298
- let content = "";
299
- const tools = /* @__PURE__ */ new Map();
300
- let finishReason;
301
- for await (const ev of readSSE(res)) {
302
- if (ev.data === "[DONE]") break;
303
- let chunk;
304
- try {
305
- chunk = JSON.parse(ev.data);
306
- } catch {
307
- continue;
308
- }
309
- const choice = chunk.choices?.[0];
310
- if (!choice) continue;
311
- if (choice.finish_reason) finishReason = choice.finish_reason;
312
- const delta = choice.delta;
313
- if (!delta) continue;
314
- if (delta.content) {
315
- content += delta.content;
316
- onProgress();
317
- }
318
- if (delta.tool_calls) {
319
- for (const tc of delta.tool_calls) {
320
- const idx = tc.index ?? 0;
321
- const cur = tools.get(idx) ?? { arguments: "" };
322
- if (tc.id) cur.id = tc.id;
323
- if (tc.function?.name) cur.name = tc.function.name;
324
- if (tc.function?.arguments) {
325
- cur.arguments += tc.function.arguments;
326
- onProgress();
327
- }
328
- tools.set(idx, cur);
329
- }
203
+ };
204
+ for (; ; ) {
205
+ const response = input.onProgress ? await callStream(messages, input.system, opts, input.signal, input.onProgress) : await call(messages, input.system, opts, input.signal);
206
+ const toolUses = response.content.filter(
207
+ (b) => b.type === "tool_use"
208
+ );
209
+ const structured = toolUses.find((c) => c.name === toolName);
210
+ if (structured) {
211
+ return decode(structured.input);
212
+ }
213
+ if (toolUses.length === 0) {
214
+ if (response.stop_reason === "max_tokens") {
215
+ throw new Error("\u6A21\u578B\u5728\u4EA7\u51FA\u7ED3\u6784\u5316\u7ED3\u679C\u524D\u7528\u5C3D\u4E86 token \u9884\u7B97\uFF08stop_reason=max_tokens\uFF09\u3002\u8BF7\u63D0\u9AD8 maxTokens\uFF0C\u6216\u6362\u7528\u975E\u63A8\u7406\u6A21\u578B\u3002");
330
216
  }
217
+ const text = response.content.filter((b) => b.type === "text").map((b) => b.text).join("");
218
+ const reason = response.stop_reason ? `\uFF08stop_reason=${response.stop_reason}\uFF09` : "";
219
+ throw new Error(`\u6A21\u578B\u672A\u8FD4\u56DE\u7ED3\u6784\u5316\u8F93\u51FA${reason}${text ? `: ${text.slice(0, 200)}` : ""}`);
331
220
  }
332
- const toolCalls = [...tools.entries()].sort(([a], [b]) => a - b).map(([, v]) => ({
333
- id: v.id ?? "",
334
- type: "function",
335
- function: { name: v.name ?? "", arguments: v.arguments }
336
- }));
337
- return {
338
- choices: [{
339
- finish_reason: finishReason,
340
- message: {
341
- content: content || null,
342
- ...toolCalls.length > 0 ? { tool_calls: toolCalls } : {}
343
- }
344
- }]
345
- };
346
- }
347
- const RETRY_TOOL_CALL_ID = "retry_call_0";
348
- function buildMessages(prompt, system) {
349
- const messages = [];
350
- if (system !== void 0) messages.push({ role: "system", content: system });
351
- messages.push({ role: "user", content: prompt });
352
- return messages;
353
- }
354
- function appendRetry(messages, retry, toolName) {
355
221
  messages.push({
356
222
  role: "assistant",
357
- content: null,
358
- tool_calls: [{
359
- id: RETRY_TOOL_CALL_ID,
360
- type: "function",
361
- function: { name: toolName, arguments: JSON.stringify(retry.previousOutput) }
362
- }]
363
- });
364
- messages.push({
365
- role: "tool",
366
- tool_call_id: RETRY_TOOL_CALL_ID,
367
- content: retry.feedback
223
+ content: toolUses
368
224
  });
369
- }
370
- return {
371
- async generateText(input) {
372
- const messages = buildMessages(input.prompt, input.system);
373
- const opts = input.maxTokens !== void 0 ? { maxTokens: input.maxTokens } : {};
374
- const response = input.onProgress ? await callStream(messages, opts, input.signal, input.onProgress) : await call(messages, opts, input.signal);
375
- return response.choices[0]?.message.content ?? "";
376
- },
377
- async generateObject(input) {
378
- const toolName = input.objectName ?? "structured_output";
379
- const structuredParams = JSONSchema.make(input.schema);
380
- const helperTools = input.tools ?? [];
381
- const helperByName = new Map(helperTools.map((t) => [t.name, t]));
382
- const tools = [
383
- ...helperTools.map((t) => ({
384
- type: "function",
385
- function: {
386
- name: t.name,
387
- description: t.description,
388
- parameters: t.inputJsonSchema
389
- }
390
- })),
391
- {
392
- type: "function",
393
- function: {
394
- name: toolName,
395
- description: "Return the structured output as the function arguments.",
396
- parameters: structuredParams
397
- }
398
- }
399
- ];
400
- const toolChoice = helperTools.length > 0 ? "required" : { type: "function", function: { name: toolName } };
401
- const messages = buildMessages(input.prompt, input.system);
402
- if (input.retry) appendRetry(messages, input.retry, toolName);
403
- const opts = {
404
- tools,
405
- toolChoice,
406
- ...input.maxTokens !== void 0 ? { maxTokens: input.maxTokens } : {}
407
- };
408
- const decodeArgs = (raw) => {
409
- try {
410
- return JSON.parse(raw);
411
- } catch (err) {
412
- const message = err instanceof Error ? err.message : String(err);
413
- throw new Error(`\u65E0\u6CD5\u89E3\u6790\u6A21\u578B\u8FD4\u56DE\u7684\u7ED3\u6784\u5316\u6570\u636E: ${message}`);
414
- }
415
- };
416
- const decode = (raw) => {
417
- try {
418
- return Schema.decodeUnknownSync(input.schema)(raw);
419
- } catch (cause) {
420
- throw new StructuredOutputDecodeError(raw, cause);
421
- }
422
- };
423
- for (; ; ) {
424
- const response = input.onProgress ? await callStream(messages, opts, input.signal, input.onProgress) : await call(messages, opts, input.signal);
425
- const choice = response.choices[0];
426
- const structured = choice?.message.tool_calls?.find((c) => c.function.name === toolName);
427
- if (structured) {
428
- return decode(decodeArgs(structured.function.arguments));
429
- }
430
- const helperCalls = choice?.message.tool_calls ?? [];
431
- if (helperCalls.length === 0) {
432
- if (choice?.finish_reason === "length") {
433
- throw new Error("\u6A21\u578B\u5728\u4EA7\u51FA\u7ED3\u6784\u5316\u7ED3\u679C\u524D\u7528\u5C3D\u4E86 token \u9884\u7B97\uFF08finish_reason=length\uFF09\u3002\u8BF7\u63D0\u9AD8 maxTokens\uFF0C\u6216\u6362\u7528\u975E\u63A8\u7406\u6A21\u578B\u3002");
434
- }
435
- const text = choice?.message.content ?? "";
436
- const reason = choice?.finish_reason ? `\uFF08finish_reason=${choice.finish_reason}\uFF09` : "";
437
- throw new Error(`\u6A21\u578B\u672A\u8FD4\u56DE\u7ED3\u6784\u5316\u8F93\u51FA${reason}${text ? `: ${text.slice(0, 200)}` : ""}`);
438
- }
439
- messages.push({
440
- role: "assistant",
441
- content: null,
442
- tool_calls: helperCalls
225
+ const results = [];
226
+ for (const useBlock of toolUses) {
227
+ const tool = helperByName.get(useBlock.name);
228
+ if (!tool) {
229
+ results.push({
230
+ type: "tool_result",
231
+ tool_use_id: useBlock.id,
232
+ content: `Unknown tool: ${useBlock.name}`
233
+ });
234
+ continue;
235
+ }
236
+ try {
237
+ const result = await tool.execute(useBlock.input ?? {});
238
+ results.push({
239
+ type: "tool_result",
240
+ tool_use_id: useBlock.id,
241
+ content: typeof result === "string" ? result : JSON.stringify(result)
242
+ });
243
+ } catch (err) {
244
+ results.push({
245
+ type: "tool_result",
246
+ tool_use_id: useBlock.id,
247
+ content: err instanceof Error ? err.message : String(err)
443
248
  });
444
- for (const callBlock of helperCalls) {
445
- const tool = helperByName.get(callBlock.function.name);
446
- if (!tool) {
447
- messages.push({
448
- role: "tool",
449
- tool_call_id: callBlock.id,
450
- content: `Unknown tool: ${callBlock.function.name}`
451
- });
452
- continue;
453
- }
454
- let parsedInput = {};
455
- try {
456
- parsedInput = callBlock.function.arguments ? JSON.parse(callBlock.function.arguments) : {};
457
- } catch {
458
- }
459
- try {
460
- const result = await tool.execute(parsedInput);
461
- messages.push({
462
- role: "tool",
463
- tool_call_id: callBlock.id,
464
- content: typeof result === "string" ? result : JSON.stringify(result)
465
- });
466
- } catch (err) {
467
- messages.push({
468
- role: "tool",
469
- tool_call_id: callBlock.id,
470
- content: err instanceof Error ? err.message : String(err)
471
- });
472
- }
473
- }
474
249
  }
475
250
  }
476
- };
477
- }
478
- function buildClient(cfg) {
479
- switch (cfg.provider) {
480
- case "anthropic":
481
- return buildAnthropicClient(cfg);
482
- case "openai":
483
- return buildOpenAIClient(cfg);
484
- default:
485
- throw new Error(`unsupported AI provider: ${cfg.provider}`);
251
+ messages.push({ role: "user", content: results });
486
252
  }
487
253
  }
488
254
  export default defineNuxtPlugin({
489
255
  name: "shwfed:ai",
490
256
  setup: () => {
491
- const config = createConfigRef();
492
- const allowed = isByokAllowed();
493
- const available = computed(() => allowed && config.value !== null);
494
- function setConfig(next) {
495
- config.value = next;
496
- }
497
- function openSettings() {
498
- settingsOpen.value = true;
499
- }
500
- async function generateText(input) {
501
- const cfg = config.value;
502
- if (!cfg) throw new Error("AI \u672A\u914D\u7F6E");
503
- return buildClient(cfg).generateText(input);
504
- }
505
- async function generateObject(input) {
506
- const cfg = config.value;
507
- if (!cfg) throw new Error("AI \u672A\u914D\u7F6E");
508
- return buildClient(cfg).generateObject(input);
509
- }
510
257
  const ai = {
511
- available,
512
- config,
513
- setConfig,
514
- openSettings,
258
+ available: computed(() => true),
515
259
  generateText,
516
260
  generateObject
517
261
  };