@7n/tauri-components 0.10.1 → 0.11.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 (64) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/package.json +1 -4
  3. package/src/components/AgentDialog.vue +21 -46
  4. package/src/components/AuditDialog.vue +9 -17
  5. package/src/components/BaseDialog.vue +2 -6
  6. package/src/components/DialogActions.vue +2 -3
  7. package/src/components/RequestView.vue +2 -3
  8. package/src/components/StatePill.vue +1 -1
  9. package/src/components/docs/AgentDialog.md +4 -4
  10. package/src/components/docs/AuditDialog.md +4 -4
  11. package/src/components/docs/BaseDialog.md +4 -4
  12. package/src/components/docs/DialogActions.md +4 -4
  13. package/src/components/docs/RequestView.md +4 -4
  14. package/src/components/docs/StatePill.md +4 -4
  15. package/src/components/docs/index.md +4 -4
  16. package/src/components/docs/status.md +4 -4
  17. package/src/components/index.js +2 -2
  18. package/src/components/status.js +1 -1
  19. package/src/core/acp-agent-presets.js +2 -2
  20. package/src/core/acp-agent.js +21 -15
  21. package/src/core/acp-kit.js +79 -30
  22. package/src/core/dispatch.js +3 -3
  23. package/src/core/docs/acp-agent-presets.md +4 -4
  24. package/src/core/docs/acp-agent.md +4 -4
  25. package/src/core/docs/acp-kit.md +4 -4
  26. package/src/core/docs/dispatch.md +4 -4
  27. package/src/core/docs/manifest.md +4 -4
  28. package/src/core/manifest.js +10 -8
  29. package/src/docs/index.md +4 -4
  30. package/src/index.js +3 -8
  31. package/src/testing/docs/quasar.md +4 -4
  32. package/src/testing/quasar.js +2 -2
  33. package/src/vue/docs/index.md +4 -4
  34. package/src/vue/docs/journal-store-tauri.md +4 -4
  35. package/src/vue/docs/use-acp-agent.md +4 -4
  36. package/src/vue/docs/use-updater.md +4 -4
  37. package/src/vue/index.js +4 -6
  38. package/src/vue/journal-store-tauri.js +2 -2
  39. package/src/vue/use-acp-agent.js +22 -14
  40. package/src/vue/use-updater.js +4 -6
  41. package/types/core/dispatch.d.ts +5 -2
  42. package/types/core/manifest.d.ts +14 -9
  43. package/types/core/scope.d.ts +24 -11
  44. package/types/core/tools.d.ts +1 -1
  45. package/types/index.d.ts +4 -9
  46. package/src/core/agent-handler.js +0 -171
  47. package/src/core/agent-kit.js +0 -43
  48. package/src/core/docs/agent-handler.md +0 -31
  49. package/src/core/docs/agent-kit.md +0 -25
  50. package/src/core/docs/llm.md +0 -29
  51. package/src/core/docs/omlx-models.md +0 -30
  52. package/src/core/docs/resolve-omlx-base-url.md +0 -40
  53. package/src/core/llm.js +0 -90
  54. package/src/core/omlx-models.js +0 -34
  55. package/src/core/resolve-omlx-base-url.js +0 -84
  56. package/src/vue/docs/use-agent.md +0 -29
  57. package/src/vue/docs/use-omlx.md +0 -30
  58. package/src/vue/use-agent.js +0 -60
  59. package/src/vue/use-omlx.js +0 -102
  60. package/types/core/agent-handler.d.ts +0 -43
  61. package/types/core/agent-kit.d.ts +0 -30
  62. package/types/core/llm.d.ts +0 -52
  63. package/types/core/omlx-models.d.ts +0 -17
  64. package/types/core/resolve-omlx-base-url.d.ts +0 -42
@@ -45,14 +45,13 @@ export function useUpdater() {
45
45
  message: `Версія ${update.version} готова. Встановити зараз?`,
46
46
  cancel: { label: 'Пізніше', flat: true },
47
47
  ok: { label: 'Встановити', color: 'primary' },
48
- persistent: true,
48
+ persistent: true
49
49
  })
50
50
  .onOk(() => installAndRelaunch(update))
51
51
  .onCancel(() => {
52
52
  busy = false
53
53
  })
54
- }
55
- catch (error) {
54
+ } catch (error) {
56
55
  // No network, or the updater isn't configured/permitted — don't bother
57
56
  // the user, but leave a trace for diagnosis.
58
57
  console.error('[updater] check failed:', error)
@@ -94,10 +93,9 @@ export function useUpdater() {
94
93
  message: `Перезапустити зараз, щоб перейти на версію ${update.version}?`,
95
94
  cancel: { label: 'Пізніше', flat: true },
96
95
  ok: { label: 'Перезапустити', color: 'primary' },
97
- persistent: true,
96
+ persistent: true
98
97
  }).onOk(() => relaunch())
99
- }
100
- catch (error) {
98
+ } catch (error) {
101
99
  dismiss()
102
100
  busy = false
103
101
  console.error('[updater] install failed:', error)
@@ -4,11 +4,14 @@
4
4
  * @param {object} [input] candidate input
5
5
  * @returns {string|null} error message, or null when valid
6
6
  */
7
- export function validateInput(tool: object, input?: object): string | null;
7
+ export function validateInput(tool: object, input?: object): string | null
8
8
  /**
9
9
  * Build a dispatch function bound to a catalog and a transport.
10
10
  * @param {object[]} catalog tool definitions
11
11
  * @param {(tool: object, input: object) => unknown} transport runs the tool's backend call
12
12
  * @returns {(name: string, input?: object) => Promise<object>} dispatch returning an envelope
13
13
  */
14
- export function createDispatch(catalog: object[], transport: (tool: object, input: object) => unknown): (name: string, input?: object) => Promise<object>;
14
+ export function createDispatch(
15
+ catalog: object[],
16
+ transport: (tool: object, input: object) => unknown
17
+ ): (name: string, input?: object) => Promise<object>
@@ -3,24 +3,29 @@
3
3
  * @param {Record<string, {type: string, required?: boolean, description?: string}>} input tool input spec
4
4
  * @returns {object} JSON Schema for the parameters object
5
5
  */
6
- export function toJsonSchema(input: Record<string, {
7
- type: string;
8
- required?: boolean;
9
- description?: string;
10
- }>): object;
6
+ export function toJsonSchema(
7
+ input: Record<
8
+ string,
9
+ {
10
+ type: string
11
+ required?: boolean
12
+ description?: string
13
+ }
14
+ >
15
+ ): object
11
16
  /**
12
17
  * OpenAI function-calling tool definitions, optionally filtered (e.g. by scope).
13
18
  * @param {object[]} catalog tool definitions
14
19
  * @param {(tool: object) => boolean} [allow] predicate; default includes all tools
15
20
  * @returns {object[]} OpenAI `tools` array
16
21
  */
17
- export function toolManifest(catalog: object[], allow?: (tool: object) => boolean): object[];
22
+ export function toolManifest(catalog: object[], allow?: (tool: object) => boolean): object[]
18
23
  /**
19
24
  * Compact catalog listing (name + summary).
20
25
  * @param {object[]} catalog tool definitions
21
26
  * @returns {{name: string, summary: string}[]} tool list
22
27
  */
23
28
  export function listTools(catalog: object[]): {
24
- name: string;
25
- summary: string;
26
- }[];
29
+ name: string
30
+ summary: string
31
+ }[]
@@ -6,9 +6,14 @@
6
6
  * @param {string} toolName tool name
7
7
  * @returns {'allow'|'approval'|'deny'} decision
8
8
  */
9
- export function classify(catalog: object[], actorTiers: Record<string, number> | undefined, actor: {
10
- kind?: string;
11
- }, toolName: string): "allow" | "approval" | "deny";
9
+ export function classify(
10
+ catalog: object[],
11
+ actorTiers: Record<string, number> | undefined,
12
+ actor: {
13
+ kind?: string
14
+ },
15
+ toolName: string
16
+ ): 'allow' | 'approval' | 'deny'
12
17
  /**
13
18
  * LLM tool manifest visible to the actor (everything it may run OR request approval for).
14
19
  * @param {object[]} catalog tool definitions
@@ -16,9 +21,13 @@ export function classify(catalog: object[], actorTiers: Record<string, number> |
16
21
  * @param {{ kind?: string }} actor caller identity
17
22
  * @returns {object[]} OpenAI tools array
18
23
  */
19
- export function scopedManifest(catalog: object[], actorTiers: Record<string, number> | undefined, actor: {
20
- kind?: string;
21
- }): object[];
24
+ export function scopedManifest(
25
+ catalog: object[],
26
+ actorTiers: Record<string, number> | undefined,
27
+ actor: {
28
+ kind?: string
29
+ }
30
+ ): object[]
22
31
  /**
23
32
  * Tool names visible to the actor.
24
33
  * @param {object[]} catalog tool definitions
@@ -26,10 +35,14 @@ export function scopedManifest(catalog: object[], actorTiers: Record<string, num
26
35
  * @param {{ kind?: string }} actor caller identity
27
36
  * @returns {string[]} visible tool names
28
37
  */
29
- export function scopedToolNames(catalog: object[], actorTiers: Record<string, number> | undefined, actor: {
30
- kind?: string;
31
- }): string[];
38
+ export function scopedToolNames(
39
+ catalog: object[],
40
+ actorTiers: Record<string, number> | undefined,
41
+ actor: {
42
+ kind?: string
43
+ }
44
+ ): string[]
32
45
  export namespace DEFAULT_ACTOR_TIERS {
33
- let human: number;
34
- let agent: number;
46
+ let human: number
47
+ let agent: number
35
48
  }
@@ -4,4 +4,4 @@
4
4
  * @param {string} name tool name
5
5
  * @returns {object|null} the tool definition, or null if unknown
6
6
  */
7
- export function getTool(catalog: object[], name: string): object | null;
7
+ export function getTool(catalog: object[], name: string): object | null
package/types/index.d.ts CHANGED
@@ -1,9 +1,4 @@
1
- export { createAgentKit } from "./core/agent-kit.js";
2
- export { getTool } from "./core/tools.js";
3
- export { handleApprove, handleRequest, handleRespond } from "./core/agent-handler.js";
4
- export { createDispatch, validateInput } from "./core/dispatch.js";
5
- export { createOpenAiChat, runAgent } from "./core/llm.js";
6
- export { listOmlxModels, resolveModel } from "./core/omlx-models.js";
7
- export { DIRECT_OMLX_BASE_URL, isDirectOmlxUrl, PROXY_OMLX_BASE_URL, resolveOmlxBaseUrl, resolveOmlxBaseUrlCached } from "./core/resolve-omlx-base-url.js";
8
- export { listTools, toJsonSchema, toolManifest } from "./core/manifest.js";
9
- export { classify, DEFAULT_ACTOR_TIERS, scopedManifest, scopedToolNames } from "./core/scope.js";
1
+ export { getTool } from './core/tools.js'
2
+ export { createDispatch, validateInput } from './core/dispatch.js'
3
+ export { listTools, toJsonSchema, toolManifest } from './core/manifest.js'
4
+ export { classify, DEFAULT_ACTOR_TIERS, scopedManifest, scopedToolNames } from './core/scope.js'
@@ -1,171 +0,0 @@
1
- import { runAgent } from './llm.js'
2
-
3
- // Agent-gateway handlers — start / resume / approve the agent loop on behalf of a
4
- // caller (human via UI or agent via MCP). They own the journal lifecycle and
5
- // return a structured result contract.
6
- //
7
- // All collaborators are injected (no module-level singletons): `dispatch`,
8
- // `journal`, the scoped `tools` manifest, the `gate` decision fn, `buildSystem`
9
- // (turns optional grounding context into a system prompt) and `grounding` (an
10
- // optional read tool whose output grounds the prompt). createAgentKit wires
11
- // these from an app catalog; tests pass fakes.
12
- //
13
- // Trust: destructive tool calls from an agent pause as `needs_approval` (the
14
- // loop never executes them); a human approves later via handleApprove.
15
-
16
- const QUESTION_RE = /\?\s*$/
17
-
18
- /**
19
- * @param {string} text candidate text
20
- * @returns {boolean} true when text ends with a question mark
21
- */
22
- function isQuestion(text) {
23
- return typeof text === 'string' && QUESTION_RE.test(text.trim())
24
- }
25
-
26
- /**
27
- * Derive the structured result fields from a runAgent result.
28
- * @param {object} result runAgent result
29
- * @returns {{ status: string, summary: string|null, question: string|null, pendingApproval: object|null }} fields
30
- */
31
- function finalize(result) {
32
- const question = isQuestion(result.content) ? result.content : null
33
- let status = 'done'
34
- if (result.stopped === 'needs_approval') status = 'needs_approval'
35
- else if (result.stopped === 'max_steps') status = 'partial'
36
- else if (question) status = 'needs_clarification'
37
- return {
38
- status,
39
- summary: question ? null : (result.content || null),
40
- question,
41
- pendingApproval: result.pendingApproval ?? null,
42
- }
43
- }
44
-
45
- /**
46
- * Run the loop (fresh or resumed), persist to the journal, return the envelope.
47
- * @param {{ requestId: string, runArgs: object, baseActions: object[], journal: object }} ctx run context
48
- * @returns {Promise<object>} structured result envelope
49
- */
50
- async function runAndJournal({ requestId, runArgs, baseActions, journal }) {
51
- let result
52
- try {
53
- result = await runAgent(runArgs)
54
- }
55
- catch (error) {
56
- await journal.update(requestId, { status: 'failed', error: String(error?.message ?? error) })
57
- return { requestId, status: 'failed', summary: null, actions: baseActions, question: null, pendingApproval: null }
58
- }
59
-
60
- const fields = finalize(result)
61
- const actions = [...baseActions, ...result.trace]
62
- await journal.update(requestId, { ...fields, messages: result.messages, actions })
63
- return { requestId, ...fields, actions }
64
- }
65
-
66
- /**
67
- * Fetch optional grounding context via a read tool; {} when not configured / on failure.
68
- * @param {Function} dispatch tool dispatcher
69
- * @param {{ tool: string, key?: string, fallback?: unknown }} [grounding] grounding config
70
- * @returns {Promise<object>} context object keyed by grounding.key (default "grounding")
71
- */
72
- async function groundingContext(dispatch, grounding) {
73
- if (!grounding?.tool) return {}
74
- const key = grounding.key ?? 'grounding'
75
- const fallback = grounding.fallback ?? []
76
- try {
77
- const res = await dispatch(grounding.tool, {})
78
- return { [key]: res?.ok ? res.output : fallback }
79
- }
80
- catch {
81
- return { [key]: fallback }
82
- }
83
- }
84
-
85
- /**
86
- * Start a new agent request.
87
- * @param {{ intent: string, actor: object, chat: Function, dispatch: Function, journal: object, tools: object[], gate: Function, buildSystem?: Function, grounding?: object }} opts request parameters
88
- * @returns {Promise<object>} structured result envelope
89
- */
90
- export async function handleRequest({ intent, actor, chat, dispatch, journal, tools, gate, buildSystem, grounding }) {
91
- const id = await journal.create({ intent, actor })
92
- await journal.update(id, { status: 'running' })
93
- const ctx = await groundingContext(dispatch, grounding)
94
- const system = buildSystem ? buildSystem(ctx) : undefined
95
- return runAndJournal({
96
- requestId: id,
97
- baseActions: [],
98
- journal,
99
- runArgs: { system, prompt: intent, chat, dispatch, tools, gate },
100
- })
101
- }
102
-
103
- /**
104
- * Resume a conversation with a follow-up / clarification answer.
105
- * @param {{ requestId: string, message: string, actor: object, chat: Function, dispatch: Function, journal: object, tools: object[], gate: Function }} opts resume parameters
106
- * @returns {Promise<object>} updated result envelope
107
- */
108
- export async function handleRespond({ requestId, message, chat, dispatch, journal, tools, gate }) {
109
- let record
110
- try {
111
- record = await journal.load(requestId)
112
- }
113
- catch {
114
- return { requestId, status: 'failed', summary: null, actions: [], question: 'Request not found.', pendingApproval: null }
115
- }
116
-
117
- if (record.status === 'running' || !Array.isArray(record.messages) || record.messages.length === 0) {
118
- return { requestId, status: record.status, summary: record.summary, actions: record.actions, question: null, pendingApproval: record.pendingApproval ?? null }
119
- }
120
-
121
- await journal.update(requestId, { status: 'running' })
122
- return runAndJournal({
123
- requestId,
124
- baseActions: record.actions ?? [],
125
- journal,
126
- runArgs: { messages: [...record.messages, { role: 'user', content: message }], chat, dispatch, tools, gate },
127
- })
128
- }
129
-
130
- /**
131
- * Approve (or reject) a pending destructive action. Executes with the approver's
132
- * (human) authority via the injected dispatch — no gate.
133
- * @param {{ requestId: string, approve: boolean, dispatch: Function, journal: object }} opts approval parameters
134
- * @returns {Promise<object>} updated result envelope
135
- */
136
- export async function handleApprove({ requestId, approve, dispatch, journal }) {
137
- let record
138
- try {
139
- record = await journal.load(requestId)
140
- }
141
- catch {
142
- return { requestId, status: 'failed', summary: null, actions: [], question: 'Request not found.', pendingApproval: null }
143
- }
144
-
145
- if (record.status !== 'needs_approval' || !record.pendingApproval) {
146
- return { requestId, status: record.status, summary: record.summary, actions: record.actions ?? [], question: null, pendingApproval: null }
147
- }
148
-
149
- if (!approve) {
150
- const fields = { status: 'rejected', summary: 'Rejected by human.', pendingApproval: null }
151
- await journal.update(requestId, fields)
152
- return { requestId, ...fields, actions: record.actions ?? [], question: null }
153
- }
154
-
155
- const { tool, input } = record.pendingApproval
156
- await journal.update(requestId, { status: 'running' })
157
- const envelope = await dispatch(tool, input)
158
- const actions = [...(record.actions ?? []), { tool, input, envelope }]
159
-
160
- if (!envelope.ok) {
161
- // Execution failed (e.g. transient) — stay needs_approval so the human can
162
- // retry after fixing; keep pendingApproval, record the error and the attempt.
163
- const error = envelope.error?.message ?? 'execution failed'
164
- await journal.update(requestId, { status: 'needs_approval', actions, error })
165
- return { requestId, status: 'needs_approval', summary: null, actions, error, question: null, pendingApproval: record.pendingApproval }
166
- }
167
-
168
- const summary = `Approved: ${tool} executed.`
169
- await journal.update(requestId, { status: 'done', actions, summary, error: null, pendingApproval: null })
170
- return { requestId, status: 'done', summary, actions, question: null, pendingApproval: null }
171
- }
@@ -1,43 +0,0 @@
1
- import { handleApprove, handleRequest, handleRespond } from './agent-handler.js'
2
- import { createDispatch } from './dispatch.js'
3
- import { toolManifest } from './manifest.js'
4
- import { classify, DEFAULT_ACTOR_TIERS, scopedManifest } from './scope.js'
5
-
6
- // createAgentKit binds the generic agent machinery to ONE app's tool catalog.
7
- // It is the single integration seam: an app supplies its catalog, a domain
8
- // system prompt, a transport (Tauri invoke / CLI spawn / fetch), a journal store
9
- // and optional grounding, and gets back request/respond/approve plus the derived
10
- // manifest + scope helpers — all pre-bound, so callers never re-thread the
11
- // catalog. The `chat` fn stays per-call (its config can change between requests).
12
-
13
- /**
14
- * @param {object} config kit configuration
15
- * @param {object[]} config.catalog tool definitions (required)
16
- * @param {string|((ctx: object) => string)} [config.systemPrompt] domain system prompt (or builder from grounding ctx)
17
- * @param {(tool: object, input: object) => unknown} [config.transport] backend runner; omit to build the kit without dispatch (manifest/scope only)
18
- * @param {object} [config.journal] journal store { create, load, update, list }
19
- * @param {Record<string, number>} [config.actorTiers] max executable tier rank per actor kind
20
- * @param {{ tool: string, key?: string, fallback?: unknown }} [config.grounding] optional read tool to ground the prompt
21
- * @returns {{ dispatch: Function|null, classify: Function, scopedManifest: Function, toolManifest: Function, request: Function, respond: Function, approve: Function }} bound kit
22
- */
23
- export function createAgentKit({ catalog, systemPrompt = '', transport, journal, actorTiers = DEFAULT_ACTOR_TIERS, grounding } = {}) {
24
- if (!Array.isArray(catalog)) throw new Error('createAgentKit: catalog (array) is required')
25
-
26
- const dispatch = transport ? createDispatch(catalog, transport) : null
27
- const buildSystem = typeof systemPrompt === 'function' ? systemPrompt : () => systemPrompt
28
- const toolsFor = actor => scopedManifest(catalog, actorTiers, actor)
29
- const gateFor = actor => name => classify(catalog, actorTiers, actor, name)
30
-
31
- return {
32
- dispatch,
33
- classify: (actor, name) => classify(catalog, actorTiers, actor, name),
34
- scopedManifest: actor => toolsFor(actor),
35
- toolManifest: allow => toolManifest(catalog, allow),
36
- request: ({ intent, actor, chat }) =>
37
- handleRequest({ intent, actor, chat, dispatch, journal, tools: toolsFor(actor), gate: gateFor(actor), buildSystem, grounding }),
38
- respond: ({ requestId, message, actor, chat }) =>
39
- handleRespond({ requestId, message, actor, chat, dispatch, journal, tools: toolsFor(actor), gate: gateFor(actor) }),
40
- approve: ({ requestId, approve }) =>
41
- handleApprove({ requestId, approve, dispatch, journal }),
42
- }
43
- }
@@ -1,31 +0,0 @@
1
- ---
2
- docgen:
3
- source: npm/src/core/agent-handler.js
4
- crc: 8ef1230c
5
- model: omlx/gemma-4-e4b-it-OptiQ-4bit
6
- score: 100
7
- issues: judge:inaccurate:0.97
8
- judgeModel: openai-codex/gpt-5.4-mini
9
- ---
10
-
11
- # agent-handler.js
12
-
13
- ## Огляд
14
-
15
- Модуль керує життєвим циклом агентського запиту. Він ініціює запит через `handleRequest`, підтримує діалог з користувачем через `handleRespond` та реалізує логіку схвалення через `handleApprove`.
16
-
17
- ## Поведінка
18
-
19
- handleRequest ініціює новий агентський запит, створює запис у журналі та запускає цикл агента.
20
- handleRespond продовжує розмову, використовуючи попередній стан запису та нове повідомлення користувача.
21
- handleApprove виконує або відхиляє заплановану деструктивну дію, якщо запис перебуває у стані очікування схвалення.
22
-
23
- ## Публічний API
24
-
25
- handleRequest — Ініціює новий запит до агента.
26
- handleRespond — Продовжує діалог, надаючи відповідь або уточнення.
27
- handleApprove — Підтверджує (або відхиляє) заплановану руйнівну дію, виконуючи її з дозволу користувача.
28
-
29
- ## Гарантії поведінки
30
-
31
- - Перехоплює помилки і не пропускає винятків назовні (fail-safe).
@@ -1,25 +0,0 @@
1
- ---
2
- docgen:
3
- source: npm/src/core/agent-kit.js
4
- crc: 27461b4b
5
- model: omlx/gemma-4-e4b-it-OptiQ-4bit
6
- score: 100
7
- judgeModel: openai-codex/gpt-5.4-mini
8
- ---
9
-
10
- # agent-kit.js
11
-
12
- ## Огляд
13
-
14
- Цей модуль відповідає за ініціалізацію та конфігурування набору інструментів для агента. Функція `createAgentKit` створює об'єкт, що містить необхідні методи та механізми для роботи агента, забезпечуючи його доступ до інструментів та системних налаштувань.
15
-
16
- ## Поведінка
17
-
18
- 1. Викликати `createAgentKit` для створення набору інструментів агента.
19
- 2. Надати `createAgentKit` каталог інструментів.
20
- 3. За бажанням надати системний підказку, транспортний механізм, сховище журналу, рівні акторів та інструмент для заземлення.
21
- 4. Отримати об'єкт набору інструментів, що містить функції для диспетчеризації, класифікації, отримання маніфесту інструментів, створення запитів, відповідей та схвалення.
22
-
23
- ## Гарантії поведінки
24
-
25
- - (специфічних машинно-виведених гарантій немає)
@@ -1,29 +0,0 @@
1
- ---
2
- docgen:
3
- source: npm/src/core/llm.js
4
- crc: 2f379651
5
- model: omlx/gemma-4-e4b-it-OptiQ-4bit
6
- score: 100
7
- issues: judge:inaccurate:0.98
8
- judgeModel: openai-codex/gpt-5.4-mini
9
- ---
10
-
11
- # llm.js
12
-
13
- ## Огляд
14
-
15
- Модуль дозволяє ініціювати сеанс чату з мовною моделлю через мережевий ендпоінт <http://127.0.0.1:10240/v1>. Функціонал реалізується через публічні функції `runAgent` та `createOpenAiChat`. Код виконує виклик API та керує циклом виклику інструментів у контексті агента, доки модель не надасть фінальну відповідь або не буде перевищено ліміт кроків. Робота залежить від конфігурації, описаної у `response.json`.
16
-
17
- ## Поведінка
18
-
19
- runAgent виконує цикл виклику інструментів, поки модель не надасть відповідь без виклику інструменту, або доки не буде досягнуто максимальної кількості кроків.
20
- createOpenAiChat створює функцію, яка викликає мережевий ендпоінт OpenAI-сумісного API (наприклад, <http://127.0.0.1:10240/v1>) для отримання відповіді моделі.
21
-
22
- ## Публічний API
23
-
24
- runAgent — Запускає цикл виклику інструментів до моменту, коли модель надає відповідь без виклику інструменту. Може використовувати новий запит або продовжувати сесію на основі існуючої історії повідомлень.
25
- createOpenAiChat — Створює функцію для взаємодії з кінцевою точкою, сумісною з OpenAI (omlx).
26
-
27
- ## Гарантії поведінки
28
-
29
- - Read-only: не виконує операцій запису (ФС/БД).
@@ -1,30 +0,0 @@
1
- ---
2
- docgen:
3
- source: npm/src/core/omlx-models.js
4
- crc: 81a5dc3a
5
- model: omlx/gemma-4-e4b-it-OptiQ-4bit
6
- score: 100
7
- issues: judge:inaccurate:0.97
8
- judgeModel: openai-codex/gpt-5.4-mini
9
- ---
10
-
11
- # omlx-models.js
12
-
13
- ## Огляд
14
-
15
- Модуль надає публічні механізми для взаємодії з локально завантаженими моделями. Він дозволяє отримати повний список доступних моделей та вибрати конкретну модель із цього списку. Функціонал працює в режимі, що перехоплює помилки (fail-safe), і не здійснює запису у файлову систему чи бази даних. Робота модуля залежить від конфігурацій, зокрема `response.json`.
16
-
17
- ## Поведінка
18
-
19
- listOmlxModels отримує список ідентифікаторів моделей, завантажених локальним сервером, або повертає порожній масив у разі будь-якої помилки.
20
- resolveModel обирає модель з наданого списку, надаючи пріоритет обраній моделі, або повертає першу доступну модель, якщо пріоритетна відсутня.
21
-
22
- ## Публічний API
23
-
24
- listOmlxModels — отримує список доступних моделей.
25
- resolveModel — вибирає модель: обрану, якщо вона завантажена, інакше першу доступну, або порожній рядок.
26
-
27
- ## Гарантії поведінки
28
-
29
- - Read-only: не виконує операцій запису (ФС/БД).
30
- - Перехоплює помилки і не пропускає винятків назовні (fail-safe).
@@ -1,40 +0,0 @@
1
- ---
2
- docgen:
3
- source: npm/src/core/resolve-omlx-base-url.js
4
- crc: 36c282c7
5
- model: omlx/gemma-4-e4b-it-OptiQ-4bit
6
- score: 100
7
- issues: judge:inaccurate:0.99
8
- judgeModel: openai-codex/gpt-5.4-mini
9
- ---
10
-
11
- # resolve-omlx-base-url.js
12
-
13
- ## Огляд
14
-
15
- Модуль визначає та надає базові URL для взаємодії з серверами omlx. Він експортує константи: DIRECT_OMLX_BASE_URL="<http://127.0.0.1:8000/v1>" для прямого доступу та PROXY_OMLX_BASE_URL="<http://127.0.0.1:8088/v1>" для проксі-доступу. Модуль звертається до мережі для визначення робочого URL, перевіряючи доступність проксі-сервера. Вибір URL кешується у межах прогону. При помилках мережевого доступу модуль перехоплює їх (fail-safe) і повертає порожнє значення замість кидання винятків. Модуль є лише для читання (не виконує операцій з ФС/БД).
16
-
17
- ## Поведінка
18
-
19
- DIRECT_OMLX_BASE_URL: Надає базовий URL для прямого доступу до сервера omlx, який є <http://127.0.0.1:8000/v1>.
20
- PROXY_OMLX_BASE_URL: Надає базовий URL для доступу через проксі-сервер omlx, який є <http://127.0.0.1:8088/v1>.
21
- isDirectOmlxUrl: Перевіряє, чи вказаний URL є стандартним локальним сервером omlx (<http://127.0.0.1:8000> або localhost:8000).
22
- resolveOmlxBaseUrl: Визначає ефективний базовий URL omlx, перевіряючи доступність проксі-сервера через зондування `/health`; у разі успіху повертає URL проксі, інакше — прямий URL.
23
- resolveOmlxBaseUrlCached: Визначає ефективний базовий URL omlx, використовуючи кешування для уникнення повторних зондувань протягом заданого часу життя (TTL).
24
- __resetOmlxBaseUrlCache: Очищає кеш результатів зондування базового URL omlx.
25
-
26
- ## Публічний API
27
-
28
- DIRECT_OMLX_BASE_URL — Базовий URL для прямого доступу до локального OMLX сервера, що вказує на <http://127.0.0.1:8000/v1>.
29
- PROXY_OMLX_BASE_URL — Базовий URL для проксі-доступу до OMLX сервера, що вказує на <http://127.0.0.1:8088/v1>.
30
- isDirectOmlxUrl — Визначає, чи є URL основним локальним сервером OMLX, який не повинен бути перенаправлений через проксі.
31
- resolveOmlxBaseUrl — Перевіряє доступність проксі-сервера шляхом виконання GET-запиту до <http://127.0.0.1:8088/v1>; якщо відповідь успішна, використовується проксі, інакше — прямий URL.
32
- resolveOmlxBaseUrlCached — Виконує перевірку доступності проксі-сервера з кешуванням, щоб уникнути повторних перевірок при кожному виклику LLM.
33
- __resetOmlxBaseUrlCache — Очищає всі збережені результати перевірки доступності базового URL OMLX.
34
-
35
- ## Гарантії поведінки
36
-
37
- - Read-only: не виконує операцій запису (ФС/БД).
38
- - Перехоплює помилки і не пропускає винятків назовні (fail-safe).
39
- - За певних помилок повертає порожнє значення (напр. `null`) замість винятку.
40
- - Кешує результати в межах одного прогону.
package/src/core/llm.js DELETED
@@ -1,90 +0,0 @@
1
- // The tool-calling loop and an OpenAI-compatible chat adapter. Both are
2
- // stateless and domain-agnostic: the system prompt and tool manifest are passed
3
- // in by the caller (an app builds them from its catalog — see agent-kit.js).
4
-
5
- const DEFAULT_SYSTEM = 'You are a tool-using assistant. Call one tool at a time and wait for its result. If the request is ambiguous, ask a clarifying question with no tool call. When done, reply with a plain-text summary and no tool call.'
6
-
7
- /**
8
- * Run the tool-calling loop until the model answers without a tool call.
9
- * Accepts either a fresh prompt or an existing messages[] for sessional resume.
10
- * @param {object} params loop parameters
11
- * @param {string} [params.prompt] user request (fresh start)
12
- * @param {object[]} [params.messages] existing conversation to resume (takes priority over prompt)
13
- * @param {(name: string, input: object) => Promise<object>} params.dispatch tool dispatcher returning an envelope
14
- * @param {(req: {messages: object[], tools: object[]}) => Promise<object>} params.chat model call returning an assistant message
15
- * @param {number} [params.maxSteps] safety cap on loop iterations
16
- * @param {string} [params.system] system prompt (only used when building fresh from prompt)
17
- * @param {object[]} [params.tools] LLM tool manifest (pass a scoped manifest to restrict)
18
- * @param {(name: string) => 'allow'|'approval'|'deny'} [params.gate] per-call decision (default: allow)
19
- * @returns {Promise<{content: string, steps: number, trace: object[], messages: object[], stopped?: string, pendingApproval?: object}>} loop result
20
- */
21
- export async function runAgent({ prompt, messages: initialMessages, dispatch, chat, maxSteps = 6, system = DEFAULT_SYSTEM, tools = [], gate = () => 'allow' }) {
22
- const messages = initialMessages
23
- ? [...initialMessages]
24
- : [
25
- { role: 'system', content: system },
26
- { role: 'user', content: prompt },
27
- ]
28
- const trace = []
29
-
30
- for (let step = 0; step < maxSteps; step++) {
31
- const reply = await chat({ messages, tools })
32
- messages.push(reply)
33
-
34
- const calls = reply.tool_calls ?? []
35
- if (calls.length === 0) {
36
- return { content: reply.content ?? '', steps: step + 1, trace, messages }
37
- }
38
-
39
- for (const call of calls) {
40
- let input = {}
41
- try {
42
- input = call.function.arguments ? JSON.parse(call.function.arguments) : {}
43
- }
44
- catch {
45
- // leave input empty — dispatch's schema validation reports the problem
46
- }
47
-
48
- const decision = gate(call.function.name)
49
- if (decision === 'approval') {
50
- // Destructive request from a non-human: pause for human approval.
51
- return { content: reply.content ?? '', steps: step + 1, trace, messages, stopped: 'needs_approval', pendingApproval: { tool: call.function.name, input } }
52
- }
53
-
54
- const envelope = decision === 'deny'
55
- ? { ok: false, error: { code: 'forbidden', message: `Tool "${call.function.name}" is not allowed.` } }
56
- : await dispatch(call.function.name, input)
57
- trace.push({ tool: call.function.name, input, envelope })
58
- messages.push({ role: 'tool', tool_call_id: call.id, content: JSON.stringify(envelope) })
59
- }
60
- }
61
-
62
- return { content: '', steps: maxSteps, trace, messages, stopped: 'max_steps' }
63
- }
64
-
65
- /**
66
- * Build a `chat` function that calls an OpenAI-compatible endpoint (omlx).
67
- * @param {object} params config
68
- * @param {string} params.baseUrl base URL incl. /v1 (e.g. http://127.0.0.1:10240/v1)
69
- * @param {string} params.model served model id
70
- * @param {string} [params.apiKey] optional bearer token
71
- * @param {typeof fetch} [params.fetchFn] fetch implementation (injectable for tests / tauri-http)
72
- * @returns {(req: {messages: object[], tools: object[]}) => Promise<object>} chat function
73
- */
74
- export function createOpenAiChat({ baseUrl, model, apiKey, fetchFn = fetch }) {
75
- return async function chat({ messages, tools }) {
76
- const response = await fetchFn(`${baseUrl}/chat/completions`, {
77
- method: 'POST',
78
- headers: {
79
- 'content-type': 'application/json',
80
- ...(apiKey ? { authorization: `Bearer ${apiKey}` } : {}),
81
- },
82
- body: JSON.stringify({ model, messages, tools, tool_choice: 'auto' }),
83
- })
84
- if (!response.ok) {
85
- throw new Error(`omlx ${response.status}: ${await response.text()}`)
86
- }
87
- const data = await response.json()
88
- return data.choices[0].message
89
- }
90
- }