@alneas/eaos-server 0.1.0 → 0.2.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.
- package/CHANGELOG.md +20 -0
- package/README.ja.md +28 -18
- package/README.md +8 -2
- package/dist/agentic/agent-jobs.d.ts +5 -1
- package/dist/agentic/autonomous-worker.d.ts +30 -3
- package/dist/agentic/autonomous-worker.js +2 -1
- package/dist/agentic/event-bridge.d.ts +6 -0
- package/dist/agentic/index.d.ts +7 -3
- package/dist/agentic/index.js +2 -1
- package/dist/agentic/local-runner.d.ts +6 -2
- package/dist/chunk-4BARRLJR.js +180 -0
- package/dist/chunk-4BARRLJR.js.map +1 -0
- package/dist/{chunk-THYUY5ZZ.js → chunk-F2J6IQ6I.js} +68 -25
- package/dist/chunk-F2J6IQ6I.js.map +1 -0
- package/dist/{chunk-6KV5CJBW.js → chunk-F4IITPGX.js} +5 -5
- package/dist/{chunk-DHQGNP4T.js → chunk-SDJNYPYK.js} +2 -2
- package/dist/{chunk-DHQGNP4T.js.map → chunk-SDJNYPYK.js.map} +1 -1
- package/dist/chunk-YMHVRBUU.js +199 -0
- package/dist/chunk-YMHVRBUU.js.map +1 -0
- package/dist/db-package/index.js +3 -3
- package/dist/engine.js +2 -2
- package/dist/execution/chat.d.ts +7 -0
- package/dist/execution/chat.js +7 -0
- package/dist/execution/chat.js.map +1 -0
- package/dist/execution/index.d.ts +294 -2
- package/dist/execution/index.js +10 -1
- package/dist/execution/index.js.map +1 -1
- package/dist/execution/tool-agent.d.ts +7 -0
- package/dist/execution/tool-agent.js +8 -0
- package/dist/execution/tool-agent.js.map +1 -0
- package/dist/index.d.ts +5 -1
- package/dist/index.js +4 -3
- package/dist/lifecycle-engine/backend-migration.js +1 -1
- package/dist/lifecycle-engine/baseline.js +1 -1
- package/dist/lifecycle-engine/index.js +1 -1
- package/dist/lifecycle-engine/platform/index.js +8 -8
- package/dist/sql-lifecycle/index.d.ts +1 -1
- package/docs/api.md +809 -2
- package/docs/guide.md +44 -0
- package/docs/index.md +6 -2
- package/package.json +12 -3
- package/dist/chunk-THYUY5ZZ.js.map +0 -1
- /package/dist/{chunk-6KV5CJBW.js.map → chunk-F4IITPGX.js.map} +0 -0
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
// src/execution/chat.ts
|
|
2
|
+
function createChatClient(options) {
|
|
3
|
+
const adapter = options.adapter, authorize = options.authorize, tools = options.tools;
|
|
4
|
+
const parameters = structuredClone(options.parameters), governance = options.governance, registry = options.modelRegistry;
|
|
5
|
+
const modelAdapters = Object.freeze(Object.fromEntries(Object.entries(options.modelAdapters ?? {}).map(([model, transport]) => {
|
|
6
|
+
if (typeof transport?.stream !== "function") throw new Error("Invalid AI model adapter binding");
|
|
7
|
+
return [model, Object.freeze({ id: transport.id, capabilities: Object.freeze({ ...transport.capabilities }), stream: transport.stream.bind(transport) })];
|
|
8
|
+
})));
|
|
9
|
+
if (registry && !options.modelAdapters) throw new Error("AI model adapter bindings required");
|
|
10
|
+
if (parameters !== void 0 && (!parameters || typeof parameters !== "object" || Array.isArray(parameters) || Object.keys(parameters).some((key) => ["model", "messages", "tools", "stream"].includes(key)))) throw new Error("Invalid or reserved chat parameters");
|
|
11
|
+
const timeout = options.timeoutMs ?? 3e4, maxInput = options.maxInputChars ?? 2e5, maxOutput = options.maxOutputChars ?? 1e5, maxEvents = options.maxEvents ?? 1e4;
|
|
12
|
+
for (const [value, max] of [[timeout, 36e5], [maxInput, 7e6], [maxOutput, 1e7], [maxEvents, 1e5]]) if (!Number.isSafeInteger(value) || value < 1 || value > max) throw new Error("Invalid chat limit");
|
|
13
|
+
if (typeof adapter?.stream !== "function" || typeof authorize !== "function" || tools !== void 0 && typeof tools !== "function") throw new Error("Chat adapter and authorization required");
|
|
14
|
+
return {
|
|
15
|
+
/**
|
|
16
|
+
* Request one bounded completion for the current actor.
|
|
17
|
+
* @param principal - Verified nonblank tenant/user identity; copied before invoking host callbacks.
|
|
18
|
+
* @param input - One to 1000 messages, optional cancellation, and explicit none/catalog tool disclosure.
|
|
19
|
+
* @returns Assistant data only after final live authorization; tools remain unexecuted requests.
|
|
20
|
+
* @throws Rejects invalid requests, governance/provider failure, revocation, limits or cancellation.
|
|
21
|
+
* @example
|
|
22
|
+
* ```typescript
|
|
23
|
+
* import { createChatClient } from '@alneas/eaos-server/execution/chat';
|
|
24
|
+
* export function complete(client: ReturnType<typeof createChatClient>, ...args: Parameters<typeof client.complete>) {
|
|
25
|
+
* return client.complete(...args);
|
|
26
|
+
* }
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
async complete(principal, input) {
|
|
30
|
+
const p = structuredClone(principal);
|
|
31
|
+
if (!p || [p.tenantId, p.userId].some((v) => typeof v !== "string" || !v.trim())) throw new Error("Chat access denied");
|
|
32
|
+
if (!Array.isArray(input?.messages) || !input.messages.length || input.messages.length > 1e3 || Object.keys(input).some((k) => !["messages", "signal", "tools"].includes(k)) || input.tools !== void 0 && !["none", "catalog"].includes(input.tools)) throw new Error("Invalid chat history or options");
|
|
33
|
+
let messages = structuredClone(input.messages);
|
|
34
|
+
const toolMode = input.tools, traceId = crypto.randomUUID();
|
|
35
|
+
let sensitivityLevel, usage, selectedModelId;
|
|
36
|
+
let attemptStarted = false, usageRecord;
|
|
37
|
+
const context = () => ({ tenantId: p.tenantId, userId: p.userId, operation: governance?.operation ?? "model:chat", traceId, ...governance?.sessionId ? { sessionId: governance.sessionId } : {}, ...selectedModelId ?? governance?.model ? { model: selectedModelId ?? governance?.model } : {}, ...sensitivityLevel ? { sensitivityLevel } : {} });
|
|
38
|
+
const observe = async (phase, extra = {}) => {
|
|
39
|
+
try {
|
|
40
|
+
await governance?.observability?.record({ phase, context: context(), ...extra });
|
|
41
|
+
} catch {
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
const controller = new AbortController();
|
|
45
|
+
let iterator, timer;
|
|
46
|
+
const abort = () => controller.abort();
|
|
47
|
+
input.signal?.addEventListener("abort", abort, { once: true });
|
|
48
|
+
if (input.signal?.aborted) abort();
|
|
49
|
+
const check = () => {
|
|
50
|
+
if (controller.signal.aborted) throw new Error("Chat cancelled or timed out");
|
|
51
|
+
};
|
|
52
|
+
const allow = async () => {
|
|
53
|
+
check();
|
|
54
|
+
if (await authorize(structuredClone(p), "model:chat") !== true) throw new Error("Chat access denied");
|
|
55
|
+
check();
|
|
56
|
+
};
|
|
57
|
+
const recordAttemptUsage = () => {
|
|
58
|
+
if (!attemptStarted || !governance?.budget?.recordUsage) return Promise.resolve();
|
|
59
|
+
return usageRecord ??= Promise.resolve().then(() => governance.budget.recordUsage({ context: context(), usage: usage && structuredClone(usage) }));
|
|
60
|
+
};
|
|
61
|
+
const work = async () => {
|
|
62
|
+
await allow();
|
|
63
|
+
const catalog = toolMode === "catalog" ? structuredClone(await tools?.(structuredClone(p)) ?? []) : [];
|
|
64
|
+
await allow();
|
|
65
|
+
if (catalog.length > 100 || new Set(catalog.map((t) => t.name)).size !== catalog.length) throw new Error("Invalid chat tool catalog");
|
|
66
|
+
if (JSON.stringify({ messages, tools: catalog, parameters }).length > maxInput) throw new Error("Chat input limit");
|
|
67
|
+
if (governance?.guard?.before) {
|
|
68
|
+
const guarded = await governance.guard.before({ context: context(), messages, toolNames: catalog.map((tool) => tool.name) });
|
|
69
|
+
if (!guarded.allowed) throw new Error(`Chat blocked${guarded.reason ? `: ${guarded.reason}` : ""}`);
|
|
70
|
+
if (guarded.messages !== void 0) messages = structuredClone(guarded.messages);
|
|
71
|
+
sensitivityLevel = guarded.sensitivityLevel;
|
|
72
|
+
}
|
|
73
|
+
await allow();
|
|
74
|
+
const route = registry?.resolve({ context: context(), capability: "chat", ...governance?.model ? { modelId: governance.model } : {}, ...sensitivityLevel ? { sensitivityLevel } : {} });
|
|
75
|
+
let selectedAdapter = adapter;
|
|
76
|
+
if (route) {
|
|
77
|
+
selectedModelId = route.modelId;
|
|
78
|
+
if (!Object.hasOwn(modelAdapters, route.modelId) || typeof modelAdapters[route.modelId]?.stream !== "function") throw new Error("AI model adapter binding missing");
|
|
79
|
+
selectedAdapter = modelAdapters[route.modelId];
|
|
80
|
+
if (selectedAdapter.id !== route.adapterId) throw new Error("AI model adapter does not match the approved route");
|
|
81
|
+
if (toolMode === "catalog" && !route.capabilities.includes("tools")) throw new Error("AI model route does not support tools");
|
|
82
|
+
}
|
|
83
|
+
if (catalog.length && !selectedAdapter.capabilities.tools) throw new Error("Invalid chat tool catalog");
|
|
84
|
+
const inputLimit = Math.min(maxInput, route?.maxInputChars ?? maxInput), outputLimit = Math.min(maxOutput, route?.maxOutputChars ?? maxOutput);
|
|
85
|
+
if (JSON.stringify({ messages, tools: catalog, parameters }).length > inputLimit) throw new Error("Chat input limit");
|
|
86
|
+
await allow();
|
|
87
|
+
if (governance?.budget) {
|
|
88
|
+
const decision = await governance.budget.authorize({ context: context() });
|
|
89
|
+
if (!decision.allowed) throw new Error(`Chat budget denied${decision.reason ? `: ${decision.reason}` : ""}`);
|
|
90
|
+
}
|
|
91
|
+
await allow();
|
|
92
|
+
await observe("started", { input: { messageCount: messages.length, toolCount: catalog.length }, metadata: { adapter: selectedAdapter.id, ...route ? { modelId: route.modelId } : {} } });
|
|
93
|
+
await allow();
|
|
94
|
+
attemptStarted = true;
|
|
95
|
+
iterator = selectedAdapter.stream({ messages, ...catalog.length ? { tools: catalog } : {}, parameters: structuredClone(parameters), signal: controller.signal })[Symbol.asyncIterator]();
|
|
96
|
+
const parts = [], calls = /* @__PURE__ */ new Set(), names = new Set(catalog.map((t) => t.name));
|
|
97
|
+
let size = 0, events = 0;
|
|
98
|
+
while (true) {
|
|
99
|
+
check();
|
|
100
|
+
const next = await iterator.next();
|
|
101
|
+
check();
|
|
102
|
+
if (next.done) throw new Error("Chat stream ended without completion");
|
|
103
|
+
await allow();
|
|
104
|
+
const event = next.value;
|
|
105
|
+
await observe("event", { eventType: event.type });
|
|
106
|
+
if (++events > maxEvents || (size += JSON.stringify(event).length) > outputLimit) throw new Error("Chat output limit");
|
|
107
|
+
if (event.type === "metadata") usage = mergeUsage(usage, readUsage(event.metadata));
|
|
108
|
+
if (event.type === "finish") {
|
|
109
|
+
if (!["stop", "tool-calls"].includes(event.reason) || event.reason === "tool-calls" !== calls.size > 0) throw new Error("Chat response incomplete or inconsistent");
|
|
110
|
+
let message = { id: crypto.randomUUID(), role: "assistant", parts };
|
|
111
|
+
if (governance?.guard?.after) {
|
|
112
|
+
const guarded = await governance.guard.after({ context: context(), message });
|
|
113
|
+
if (!guarded.allowed) throw new Error(`Chat output blocked${guarded.reason ? `: ${guarded.reason}` : ""}`);
|
|
114
|
+
if (guarded.messages !== void 0) {
|
|
115
|
+
if (guarded.messages.length !== 1) throw new Error("Chat output guard returned invalid message count");
|
|
116
|
+
message = structuredClone(guarded.messages[0]);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
if (JSON.stringify(message).length > outputLimit) throw new Error("Chat output limit after guard");
|
|
120
|
+
await allow();
|
|
121
|
+
return { message, finishReason: event.reason, traceId, usage, sensitivityLevel };
|
|
122
|
+
}
|
|
123
|
+
if (event.type === "text-delta") {
|
|
124
|
+
if (typeof event.text !== "string") throw new Error("Invalid chat text");
|
|
125
|
+
const previous = parts.at(-1);
|
|
126
|
+
if (previous?.type === "text") parts[parts.length - 1] = { type: "text", text: previous.text + event.text };
|
|
127
|
+
else parts.push({ type: "text", text: event.text });
|
|
128
|
+
} else if (event.type === "tool-call") {
|
|
129
|
+
if (!names.has(event.name) || typeof event.callId !== "string" || !event.callId.trim() || calls.has(event.callId) || calls.size >= 100 || !event.input || typeof event.input !== "object" || Array.isArray(event.input)) throw new Error("Invalid or unregistered chat tool call");
|
|
130
|
+
calls.add(event.callId);
|
|
131
|
+
parts.push(structuredClone(event));
|
|
132
|
+
} else if (event.type === "data") parts.push(structuredClone(event));
|
|
133
|
+
else if (event.type !== "metadata") throw new Error("Unexpected chat event");
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
let rejectAbort;
|
|
137
|
+
const stopped = new Promise((_resolve, reject) => {
|
|
138
|
+
rejectAbort = () => reject(new Error("Chat cancelled or timed out"));
|
|
139
|
+
controller.signal.addEventListener("abort", rejectAbort, { once: true });
|
|
140
|
+
if (controller.signal.aborted) rejectAbort();
|
|
141
|
+
timer = setTimeout(abort, timeout);
|
|
142
|
+
});
|
|
143
|
+
const accountedWork = async () => {
|
|
144
|
+
let result;
|
|
145
|
+
try {
|
|
146
|
+
result = await work();
|
|
147
|
+
} catch (error) {
|
|
148
|
+
await recordAttemptUsage();
|
|
149
|
+
throw error;
|
|
150
|
+
}
|
|
151
|
+
await recordAttemptUsage();
|
|
152
|
+
await allow();
|
|
153
|
+
await observe("completed", { output: result.message, usage });
|
|
154
|
+
await allow();
|
|
155
|
+
return result;
|
|
156
|
+
};
|
|
157
|
+
try {
|
|
158
|
+
return await Promise.race([accountedWork(), stopped]);
|
|
159
|
+
} catch (error) {
|
|
160
|
+
let failure = error;
|
|
161
|
+
try {
|
|
162
|
+
await Promise.race([recordAttemptUsage(), stopped]);
|
|
163
|
+
} catch (accountingError) {
|
|
164
|
+
if (!controller.signal.aborted) failure = accountingError;
|
|
165
|
+
}
|
|
166
|
+
void observe("failed", { error: failure instanceof Error ? failure.message : String(failure), usage });
|
|
167
|
+
throw failure;
|
|
168
|
+
} finally {
|
|
169
|
+
clearTimeout(timer);
|
|
170
|
+
input.signal?.removeEventListener("abort", abort);
|
|
171
|
+
if (rejectAbort) controller.signal.removeEventListener("abort", rejectAbort);
|
|
172
|
+
controller.abort();
|
|
173
|
+
try {
|
|
174
|
+
void Promise.resolve(iterator?.return?.()).catch(() => {
|
|
175
|
+
});
|
|
176
|
+
} catch {
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
function readUsage(value) {
|
|
183
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
|
|
184
|
+
const record = value, raw = record.usage && typeof record.usage === "object" && !Array.isArray(record.usage) ? record.usage : record;
|
|
185
|
+
const inputTokens = number(raw.inputTokens ?? raw.promptTokens ?? raw.input_tokens), outputTokens = number(raw.outputTokens ?? raw.completionTokens ?? raw.output_tokens), totalTokens = number(raw.totalTokens ?? raw.total_tokens), cost = number(raw.cost), currency = typeof raw.currency === "string" ? raw.currency : void 0;
|
|
186
|
+
if (inputTokens === void 0 && outputTokens === void 0 && totalTokens === void 0 && cost === void 0) return void 0;
|
|
187
|
+
return { ...inputTokens === void 0 ? {} : { inputTokens }, ...outputTokens === void 0 ? {} : { outputTokens }, ...totalTokens === void 0 ? {} : { totalTokens }, ...cost === void 0 ? {} : { cost }, ...currency ? { currency } : {} };
|
|
188
|
+
}
|
|
189
|
+
function number(value) {
|
|
190
|
+
return typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : void 0;
|
|
191
|
+
}
|
|
192
|
+
function mergeUsage(previous, next) {
|
|
193
|
+
return next ? { ...previous ?? {}, ...next } : previous;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
export {
|
|
197
|
+
createChatClient
|
|
198
|
+
};
|
|
199
|
+
//# sourceMappingURL=chunk-YMHVRBUU.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/execution/chat.ts"],"sourcesContent":["import type { AIChatAdapter, AIChatMessage, AIChatPart, AIChatEvent } from '@alneas/appkit-core/ai/ai-chat'\nimport type { ActionToolDescriptor, ActionToolObject } from '@alneas/appkit-core/ai/action'\nimport type { AIBudgetGate, AIGuard, AIExecutionContext, AIModelRegistry, AIObservabilitySink, AIUsage } from '@alneas/eaos-core'\nimport type { ExecutionPolicy, ExecutionPrincipal } from './index'\n\n/** Host-injected model guards, usage budgets and telemetry.\n * @see createChatClient\n */\nexport interface ChatGovernanceOptions {\n /** Optional pre-input and post-output checks; replacement messages remain host-owned. */\n guard?: AIGuard\n /** Optional request admission and once-per-started-attempt accounting; accounting failures propagate. */\n budget?: AIBudgetGate\n /** Awaited started/event/completed telemetry within the deadline; sink errors are ignored. */\n observability?: AIObservabilitySink\n /** Telemetry operation label; authorization always checks model:chat. */\n operation?: string\n /** Host-selected registry model ID; without a registry this is metadata, not provider selection. */\n model?: string\n /** Optional host session identity recorded in governance context. */\n sessionId?: string\n}\n/** Host-configured adapter, current admission and bounded chat policy.\n * @see createChatClient\n */\nexport interface ChatClientOptions extends ExecutionPolicy {\n /** Existing Appkit transport configured with the host endpoint, model and credentials. */\n adapter: AIChatAdapter\n /** Host-owned provider parameters cloned at creation; model/messages/tools/stream keys are reserved and rejected. */\n parameters?: ActionToolObject\n /**\n * Resolve descriptors only when the caller explicitly requests tools: catalog.\n * @param principal - Copied verified actor whose current disclosure permission the host must check.\n * @returns At most 100 unique descriptors; omission advertises no tools.\n * @throws Host resolution failures reject completion before the provider starts.\n * @example\n * ```typescript\n * import type { ChatClientOptions } from '@alneas/eaos-server/execution/chat';\n * export function disclosedTools(resolve: NonNullable<ChatClientOptions['tools']>) { return resolve; }\n * ```\n */\n tools?(principal: ExecutionPrincipal): Promise<readonly ActionToolDescriptor[]>\n /** Positive integer deadline in milliseconds; default 30000, maximum 3600000. */\n timeoutMs?: number\n /** Serialized request character ceiling; default 200000, maximum 7000000. */\n maxInputChars?: number\n /** Serialized event and final assistant-message character ceiling; default 100000, maximum 10000000. */\n maxOutputChars?: number\n /** Maximum stream event count; default 10000, maximum 100000. */\n maxEvents?: number\n /** Host-approved route registry; requests cannot select a model or bypass sensitivity limits. */\n modelRegistry?: AIModelRegistry\n /** Required with modelRegistry: host-approved logical model to configured adapter bindings, snapshotted at creation. */\n modelAdapters?: Readonly<Record<string, AIChatAdapter>>\n /** Optional host guards, budgets and telemetry; final current authorization follows their completion. */\n governance?: ChatGovernanceOptions\n}\n/** Completed assistant message and optional host-governance metadata.\n * @see createChatClient\n */\nexport interface ChatCompletion {\n /** Detached assistant response; tool-call parts are unexecuted requests. */\n message: AIChatMessage\n /** Successful provider finish reason; truncated or inconsistent streams reject. */\n finishReason: 'stop' | 'tool-calls'\n /** Unique request trace identity generated before governance callbacks. */\n traceId?: string\n /** Recognized nonnegative adapter metadata; undefined means unknown, including Appkit OpenAI SSE without usage events. */\n usage?: AIUsage\n /** Sensitivity label supplied by the input guard. */\n sensitivityLevel?: AIExecutionContext['sensitivityLevel']\n}\n/**\n * Complete scoped chat through the existing Appkit adapter with live admission and host governance.\n * @param options - Trusted adapter, current authorization, optional routes/governance and bounded limits.\n * @returns A client whose complete method returns detached, finally authorized assistant data.\n * @throws Rejects invalid limits or missing adapter/policy during construction. Completion rejects\n * invalid histories/catalogs, denied or revoked admission, guard/budget/route denial, provider failures,\n * incomplete streams, exceeded limits, cancellation, deadline expiry and host accounting failure. Telemetry errors are ignored.\n * @remarks Every completion authorizes model:chat before disclosure, between events and after awaited\n * output guard, usage recording and completion telemetry. This client never executes model tool calls.\n * The host must configure real endpoint credentials in the Appkit adapter. Abort is cooperative for a\n * custom transport; the request promise remains bounded even if its iterator ignores cancellation.\n * With modelRegistry, provide modelAdapters mapping each approved logical model to its host-configured\n * Appkit adapter; generic adapter IDs alone do not select or prove the provider model. Binding entries\n * and stream methods are snapshotted at creation. Reserved transport parameters are rejected in 0.2.\n * Accounting runs once after each started adapter attempt, including output blocks, revocation and provider\n * failure. Unknown usage is passed as undefined, never zero. Appkit's OpenAI SSE adapter currently emits\n * no usage metadata event even for provider include_usage chunks; hosts must reconcile measured usage\n * through their existing accounting port using trace/session context. Accounting callback errors reject\n * completion in 0.2; a stalled callback remains bounded by the request deadline.\n * @example\n * ```typescript\n * import { createChatClient, type ChatClientOptions } from '@alneas/eaos-server/execution/chat';\n * export function connectChat(options: ChatClientOptions) { return createChatClient(options); }\n * ```\n */\nexport function createChatClient(options: ChatClientOptions) {\n const adapter = options.adapter, authorize = options.authorize, tools = options.tools\n const parameters = structuredClone(options.parameters), governance = options.governance, registry = options.modelRegistry\n const modelAdapters = Object.freeze(Object.fromEntries(Object.entries(options.modelAdapters ?? {}).map(([model,transport]) => {\n if (typeof transport?.stream !== 'function') throw new Error('Invalid AI model adapter binding')\n return [model,Object.freeze({id:transport.id,capabilities:Object.freeze({...transport.capabilities}),stream:transport.stream.bind(transport)})]\n })))\n if (registry && !options.modelAdapters) throw new Error('AI model adapter bindings required')\n if (parameters !== undefined && (!parameters || typeof parameters !== 'object' || Array.isArray(parameters) || Object.keys(parameters).some(key => ['model','messages','tools','stream'].includes(key)))) throw new Error('Invalid or reserved chat parameters')\n const timeout = options.timeoutMs ?? 30000, maxInput = options.maxInputChars ?? 200000, maxOutput = options.maxOutputChars ?? 100000, maxEvents = options.maxEvents ?? 10000\n for (const [value, max] of [[timeout,3600000],[maxInput,7000000],[maxOutput,10000000],[maxEvents,100000]] as const) if (!Number.isSafeInteger(value) || value < 1 || value > max) throw new Error('Invalid chat limit')\n if (typeof adapter?.stream !== 'function' || typeof authorize !== 'function' || tools !== undefined && typeof tools !== 'function') throw new Error('Chat adapter and authorization required')\n return {\n /**\n * Request one bounded completion for the current actor.\n * @param principal - Verified nonblank tenant/user identity; copied before invoking host callbacks.\n * @param input - One to 1000 messages, optional cancellation, and explicit none/catalog tool disclosure.\n * @returns Assistant data only after final live authorization; tools remain unexecuted requests.\n * @throws Rejects invalid requests, governance/provider failure, revocation, limits or cancellation.\n * @example\n * ```typescript\n * import { createChatClient } from '@alneas/eaos-server/execution/chat';\n * export function complete(client: ReturnType<typeof createChatClient>, ...args: Parameters<typeof client.complete>) {\n * return client.complete(...args);\n * }\n * ```\n */\n async complete(principal: ExecutionPrincipal, input: { messages: readonly AIChatMessage[]; signal?: AbortSignal; tools?: 'none' | 'catalog' }): Promise<ChatCompletion> {\n const p = structuredClone(principal)\n if (!p || [p.tenantId,p.userId].some(v => typeof v !== 'string' || !v.trim())) throw new Error('Chat access denied')\n if (!Array.isArray(input?.messages) || !input.messages.length || input.messages.length > 1000 || Object.keys(input).some(k => !['messages','signal','tools'].includes(k)) || input.tools !== undefined && !['none','catalog'].includes(input.tools)) throw new Error('Invalid chat history or options')\n let messages: AIChatMessage[] = structuredClone(input.messages) as AIChatMessage[]\n const toolMode = input.tools, traceId = crypto.randomUUID()\n let sensitivityLevel: AIExecutionContext['sensitivityLevel'], usage: AIUsage | undefined, selectedModelId: string | undefined\n let attemptStarted = false, usageRecord: Promise<void> | undefined\n const context = (): AIExecutionContext => ({ tenantId: p.tenantId, userId: p.userId, operation: governance?.operation ?? 'model:chat', traceId, ...(governance?.sessionId ? { sessionId: governance.sessionId } : {}), ...((selectedModelId ?? governance?.model) ? { model: selectedModelId ?? governance?.model } : {}), ...(sensitivityLevel ? { sensitivityLevel } : {}) })\n const observe = async (phase: Parameters<AIObservabilitySink['record']>[0]['phase'], extra: Omit<Parameters<AIObservabilitySink['record']>[0], 'phase' | 'context'> = {}) => {\n try { await governance?.observability?.record({ phase, context: context(), ...extra }) } catch { /* Telemetry is best-effort within the request deadline. */ }\n }\n const controller = new AbortController(); let iterator: AsyncIterator<AIChatEvent> | undefined, timer: ReturnType<typeof setTimeout> | undefined\n const abort = () => controller.abort()\n input.signal?.addEventListener('abort', abort, { once: true })\n if (input.signal?.aborted) abort()\n const check = () => { if (controller.signal.aborted) throw new Error('Chat cancelled or timed out') }\n const allow = async () => { check(); if (await authorize(structuredClone(p), 'model:chat') !== true) throw new Error('Chat access denied'); check() }\n const recordAttemptUsage = (): Promise<void> => {\n if (!attemptStarted || !governance?.budget?.recordUsage) return Promise.resolve()\n return usageRecord ??= Promise.resolve().then(() => governance.budget!.recordUsage!({context:context(),usage:usage && structuredClone(usage)}))\n }\n const work = async (): Promise<ChatCompletion> => {\n await allow()\n const catalog = toolMode === 'catalog' ? structuredClone(await tools?.(structuredClone(p)) ?? []) : []\n await allow()\n if (catalog.length > 100 || new Set(catalog.map(t => t.name)).size !== catalog.length) throw new Error('Invalid chat tool catalog')\n if (JSON.stringify({ messages, tools: catalog, parameters }).length > maxInput) throw new Error('Chat input limit')\n if (governance?.guard?.before) {\n const guarded = await governance.guard.before({ context: context(), messages, toolNames: catalog.map(tool => tool.name) })\n if (!guarded.allowed) throw new Error(`Chat blocked${guarded.reason ? `: ${guarded.reason}` : ''}`)\n if (guarded.messages !== undefined) messages = structuredClone(guarded.messages) as AIChatMessage[]\n sensitivityLevel = guarded.sensitivityLevel\n }\n await allow()\n const route = registry?.resolve({ context: context(), capability: 'chat', ...(governance?.model ? { modelId: governance.model } : {}), ...(sensitivityLevel ? { sensitivityLevel } : {}) })\n let selectedAdapter = adapter\n if (route) {\n selectedModelId = route.modelId\n if (!Object.hasOwn(modelAdapters,route.modelId) || typeof modelAdapters[route.modelId]?.stream !== 'function') throw new Error('AI model adapter binding missing')\n selectedAdapter = modelAdapters[route.modelId]\n if (selectedAdapter.id !== route.adapterId) throw new Error('AI model adapter does not match the approved route')\n if (toolMode === 'catalog' && !route.capabilities.includes('tools')) throw new Error('AI model route does not support tools')\n }\n if (catalog.length && !selectedAdapter.capabilities.tools) throw new Error('Invalid chat tool catalog')\n const inputLimit = Math.min(maxInput, route?.maxInputChars ?? maxInput), outputLimit = Math.min(maxOutput, route?.maxOutputChars ?? maxOutput)\n if (JSON.stringify({ messages, tools: catalog, parameters }).length > inputLimit) throw new Error('Chat input limit')\n await allow()\n if (governance?.budget) {\n const decision = await governance.budget.authorize({ context: context() })\n if (!decision.allowed) throw new Error(`Chat budget denied${decision.reason ? `: ${decision.reason}` : ''}`)\n }\n await allow()\n await observe('started', { input: { messageCount: messages.length, toolCount: catalog.length }, metadata: { adapter: selectedAdapter.id, ...(route ? { modelId: route.modelId } : {}) } })\n await allow()\n attemptStarted = true\n iterator = selectedAdapter.stream({ messages, ...(catalog.length ? { tools: catalog } : {}), parameters: structuredClone(parameters), signal: controller.signal })[Symbol.asyncIterator]()\n const parts: AIChatPart[] = [], calls = new Set<string>(), names = new Set(catalog.map(t => t.name))\n let size = 0, events = 0\n while (true) {\n check()\n const next = await iterator.next(); check()\n if (next.done) throw new Error('Chat stream ended without completion')\n await allow()\n const event = next.value\n await observe('event', { eventType: event.type })\n if (++events > maxEvents || (size += JSON.stringify(event).length) > outputLimit) throw new Error('Chat output limit')\n if (event.type === 'metadata') usage = mergeUsage(usage, readUsage(event.metadata))\n if (event.type === 'finish') {\n if (!['stop','tool-calls'].includes(event.reason) || (event.reason === 'tool-calls') !== (calls.size > 0)) throw new Error('Chat response incomplete or inconsistent')\n let message: AIChatMessage = { id: crypto.randomUUID(), role: 'assistant', parts }\n if (governance?.guard?.after) {\n const guarded = await governance.guard.after({ context: context(), message })\n if (!guarded.allowed) throw new Error(`Chat output blocked${guarded.reason ? `: ${guarded.reason}` : ''}`)\n if (guarded.messages !== undefined) {\n if (guarded.messages.length !== 1) throw new Error('Chat output guard returned invalid message count')\n message = structuredClone(guarded.messages[0])\n }\n }\n if (JSON.stringify(message).length > outputLimit) throw new Error('Chat output limit after guard')\n await allow()\n return { message, finishReason: event.reason as ChatCompletion['finishReason'], traceId, usage, sensitivityLevel }\n }\n if (event.type === 'text-delta') {\n if (typeof event.text !== 'string') throw new Error('Invalid chat text')\n const previous = parts.at(-1)\n if (previous?.type === 'text') parts[parts.length - 1] = { type: 'text', text: previous.text + event.text }\n else parts.push({ type: 'text', text: event.text })\n } else if (event.type === 'tool-call') {\n if (!names.has(event.name) || typeof event.callId !== 'string' || !event.callId.trim() || calls.has(event.callId) || calls.size >= 100 || !event.input || typeof event.input !== 'object' || Array.isArray(event.input)) throw new Error('Invalid or unregistered chat tool call')\n calls.add(event.callId); parts.push(structuredClone(event))\n } else if (event.type === 'data') parts.push(structuredClone(event))\n else if (event.type !== 'metadata') throw new Error('Unexpected chat event')\n }\n }\n let rejectAbort: (() => void) | undefined\n const stopped = new Promise<never>((_resolve, reject) => {\n rejectAbort = () => reject(new Error('Chat cancelled or timed out'))\n controller.signal.addEventListener('abort', rejectAbort, { once: true })\n if (controller.signal.aborted) rejectAbort()\n timer = setTimeout(abort, timeout)\n })\n const accountedWork = async () => {\n let result: ChatCompletion\n try { result = await work() }\n catch (error) { await recordAttemptUsage(); throw error }\n await recordAttemptUsage()\n await allow()\n await observe('completed', {output:result.message,usage})\n await allow()\n return result\n }\n try { return await Promise.race([accountedWork(), stopped]) }\n catch (error) {\n let failure = error\n // A deadline can win while a started provider/output guard is pending. Account that attempt once.\n try { await Promise.race([recordAttemptUsage(),stopped]) }\n catch (accountingError) { if (!controller.signal.aborted) failure = accountingError }\n void observe('failed', { error: failure instanceof Error ? failure.message : String(failure), usage })\n throw failure\n }\n finally {\n clearTimeout(timer); input.signal?.removeEventListener('abort', abort)\n if (rejectAbort) controller.signal.removeEventListener('abort', rejectAbort)\n controller.abort()\n try { void Promise.resolve(iterator?.return?.()).catch(() => {}) } catch { /* Preserve the original outcome. */ }\n }\n },\n }\n}\n\nfunction readUsage(value: unknown): AIUsage | undefined {\n if (!value || typeof value !== 'object' || Array.isArray(value)) return undefined\n const record = value as Record<string, unknown>, raw = record.usage && typeof record.usage === 'object' && !Array.isArray(record.usage) ? record.usage as Record<string, unknown> : record\n const inputTokens = number(raw.inputTokens ?? raw.promptTokens ?? raw.input_tokens), outputTokens = number(raw.outputTokens ?? raw.completionTokens ?? raw.output_tokens), totalTokens = number(raw.totalTokens ?? raw.total_tokens), cost = number(raw.cost), currency = typeof raw.currency === 'string' ? raw.currency : undefined\n if (inputTokens === undefined && outputTokens === undefined && totalTokens === undefined && cost === undefined) return undefined\n return { ...(inputTokens === undefined ? {} : { inputTokens }), ...(outputTokens === undefined ? {} : { outputTokens }), ...(totalTokens === undefined ? {} : { totalTokens }), ...(cost === undefined ? {} : { cost }), ...(currency ? { currency } : {}) }\n}\n\nfunction number(value: unknown): number | undefined { return typeof value === 'number' && Number.isFinite(value) && value >= 0 ? value : undefined }\nfunction mergeUsage(previous: AIUsage | undefined, next: AIUsage | undefined): AIUsage | undefined { return next ? { ...(previous ?? {}), ...next } : previous }\n"],"mappings":";AAiGO,SAAS,iBAAiB,SAA4B;AAC5D,QAAM,UAAU,QAAQ,SAAS,YAAY,QAAQ,WAAW,QAAQ,QAAQ;AAChF,QAAM,aAAa,gBAAgB,QAAQ,UAAU,GAAG,aAAa,QAAQ,YAAY,WAAW,QAAQ;AAC5G,QAAM,gBAAgB,OAAO,OAAO,OAAO,YAAY,OAAO,QAAQ,QAAQ,iBAAiB,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,OAAM,SAAS,MAAM;AAC7H,QAAI,OAAO,WAAW,WAAW,WAAY,OAAM,IAAI,MAAM,kCAAkC;AAC/F,WAAO,CAAC,OAAM,OAAO,OAAO,EAAC,IAAG,UAAU,IAAG,cAAa,OAAO,OAAO,EAAC,GAAG,UAAU,aAAY,CAAC,GAAE,QAAO,UAAU,OAAO,KAAK,SAAS,EAAC,CAAC,CAAC;AAAA,EAC/I,CAAC,CAAC,CAAC;AACH,MAAI,YAAY,CAAC,QAAQ,cAAe,OAAM,IAAI,MAAM,oCAAoC;AAC5F,MAAI,eAAe,WAAc,CAAC,cAAc,OAAO,eAAe,YAAY,MAAM,QAAQ,UAAU,KAAK,OAAO,KAAK,UAAU,EAAE,KAAK,SAAO,CAAC,SAAQ,YAAW,SAAQ,QAAQ,EAAE,SAAS,GAAG,CAAC,GAAI,OAAM,IAAI,MAAM,qCAAqC;AAC/P,QAAM,UAAU,QAAQ,aAAa,KAAO,WAAW,QAAQ,iBAAiB,KAAQ,YAAY,QAAQ,kBAAkB,KAAQ,YAAY,QAAQ,aAAa;AACvK,aAAW,CAAC,OAAO,GAAG,KAAK,CAAC,CAAC,SAAQ,IAAO,GAAE,CAAC,UAAS,GAAO,GAAE,CAAC,WAAU,GAAQ,GAAE,CAAC,WAAU,GAAM,CAAC,EAAY,KAAI,CAAC,OAAO,cAAc,KAAK,KAAK,QAAQ,KAAK,QAAQ,IAAK,OAAM,IAAI,MAAM,oBAAoB;AACtN,MAAI,OAAO,SAAS,WAAW,cAAc,OAAO,cAAc,cAAc,UAAU,UAAa,OAAO,UAAU,WAAY,OAAM,IAAI,MAAM,yCAAyC;AAC7L,SAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAeN,MAAM,SAAS,WAA+B,OAA0H;AACvK,YAAM,IAAI,gBAAgB,SAAS;AACnC,UAAI,CAAC,KAAK,CAAC,EAAE,UAAS,EAAE,MAAM,EAAE,KAAK,OAAK,OAAO,MAAM,YAAY,CAAC,EAAE,KAAK,CAAC,EAAG,OAAM,IAAI,MAAM,oBAAoB;AACnH,UAAI,CAAC,MAAM,QAAQ,OAAO,QAAQ,KAAK,CAAC,MAAM,SAAS,UAAU,MAAM,SAAS,SAAS,OAAQ,OAAO,KAAK,KAAK,EAAE,KAAK,OAAK,CAAC,CAAC,YAAW,UAAS,OAAO,EAAE,SAAS,CAAC,CAAC,KAAK,MAAM,UAAU,UAAa,CAAC,CAAC,QAAO,SAAS,EAAE,SAAS,MAAM,KAAK,EAAG,OAAM,IAAI,MAAM,iCAAiC;AACtS,UAAI,WAA4B,gBAAgB,MAAM,QAAQ;AAC9D,YAAM,WAAW,MAAM,OAAO,UAAU,OAAO,WAAW;AAC1D,UAAI,kBAA0D,OAA4B;AAC1F,UAAI,iBAAiB,OAAO;AAC5B,YAAM,UAAU,OAA2B,EAAE,UAAU,EAAE,UAAU,QAAQ,EAAE,QAAQ,WAAW,YAAY,aAAa,cAAc,SAAS,GAAI,YAAY,YAAY,EAAE,WAAW,WAAW,UAAU,IAAI,CAAC,GAAI,GAAK,mBAAmB,YAAY,QAAS,EAAE,OAAO,mBAAmB,YAAY,MAAM,IAAI,CAAC,GAAI,GAAI,mBAAmB,EAAE,iBAAiB,IAAI,CAAC,EAAG;AAC7W,YAAM,UAAU,OAAO,OAA8D,QAAiF,CAAC,MAAM;AAC5K,YAAI;AAAE,gBAAM,YAAY,eAAe,OAAO,EAAE,OAAO,SAAS,QAAQ,GAAG,GAAG,MAAM,CAAC;AAAA,QAAE,QAAQ;AAAA,QAA8D;AAAA,MAC9J;AACA,YAAM,aAAa,IAAI,gBAAgB;AAAG,UAAI,UAAkD;AAChG,YAAM,QAAQ,MAAM,WAAW,MAAM;AACrC,YAAM,QAAQ,iBAAiB,SAAS,OAAO,EAAE,MAAM,KAAK,CAAC;AAC7D,UAAI,MAAM,QAAQ,QAAS,OAAM;AACjC,YAAM,QAAQ,MAAM;AAAE,YAAI,WAAW,OAAO,QAAS,OAAM,IAAI,MAAM,6BAA6B;AAAA,MAAE;AACpG,YAAM,QAAQ,YAAY;AAAE,cAAM;AAAG,YAAI,MAAM,UAAU,gBAAgB,CAAC,GAAG,YAAY,MAAM,KAAM,OAAM,IAAI,MAAM,oBAAoB;AAAG,cAAM;AAAA,MAAE;AACpJ,YAAM,qBAAqB,MAAqB;AAC/C,YAAI,CAAC,kBAAkB,CAAC,YAAY,QAAQ,YAAa,QAAO,QAAQ,QAAQ;AAChF,eAAO,gBAAgB,QAAQ,QAAQ,EAAE,KAAK,MAAM,WAAW,OAAQ,YAAa,EAAC,SAAQ,QAAQ,GAAE,OAAM,SAAS,gBAAgB,KAAK,EAAC,CAAC,CAAC;AAAA,MAC/I;AACA,YAAM,OAAO,YAAqC;AACjD,cAAM,MAAM;AACZ,cAAM,UAAU,aAAa,YAAY,gBAAgB,MAAM,QAAQ,gBAAgB,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC;AACrG,cAAM,MAAM;AACZ,YAAI,QAAQ,SAAS,OAAO,IAAI,IAAI,QAAQ,IAAI,OAAK,EAAE,IAAI,CAAC,EAAE,SAAS,QAAQ,OAAQ,OAAM,IAAI,MAAM,2BAA2B;AAClI,YAAI,KAAK,UAAU,EAAE,UAAU,OAAO,SAAS,WAAW,CAAC,EAAE,SAAS,SAAU,OAAM,IAAI,MAAM,kBAAkB;AAClH,YAAI,YAAY,OAAO,QAAQ;AAC9B,gBAAM,UAAU,MAAM,WAAW,MAAM,OAAO,EAAE,SAAS,QAAQ,GAAG,UAAU,WAAW,QAAQ,IAAI,UAAQ,KAAK,IAAI,EAAE,CAAC;AACzH,cAAI,CAAC,QAAQ,QAAS,OAAM,IAAI,MAAM,eAAe,QAAQ,SAAS,KAAK,QAAQ,MAAM,KAAK,EAAE,EAAE;AACnG,cAAI,QAAQ,aAAa,OAAW,YAAW,gBAAgB,QAAQ,QAAQ;AAC/E,6BAAmB,QAAQ;AAAA,QAC5B;AACC,cAAM,MAAM;AACZ,cAAM,QAAQ,UAAU,QAAQ,EAAE,SAAS,QAAQ,GAAG,YAAY,QAAQ,GAAI,YAAY,QAAQ,EAAE,SAAS,WAAW,MAAM,IAAI,CAAC,GAAI,GAAI,mBAAmB,EAAE,iBAAiB,IAAI,CAAC,EAAG,CAAC;AAC1L,YAAI,kBAAkB;AACtB,YAAI,OAAO;AACV,4BAAkB,MAAM;AACxB,cAAI,CAAC,OAAO,OAAO,eAAc,MAAM,OAAO,KAAK,OAAO,cAAc,MAAM,OAAO,GAAG,WAAW,WAAY,OAAM,IAAI,MAAM,kCAAkC;AACjK,4BAAkB,cAAc,MAAM,OAAO;AAC7C,cAAI,gBAAgB,OAAO,MAAM,UAAW,OAAM,IAAI,MAAM,oDAAoD;AAChH,cAAI,aAAa,aAAa,CAAC,MAAM,aAAa,SAAS,OAAO,EAAG,OAAM,IAAI,MAAM,uCAAuC;AAAA,QAC7H;AACA,YAAI,QAAQ,UAAU,CAAC,gBAAgB,aAAa,MAAO,OAAM,IAAI,MAAM,2BAA2B;AACtG,cAAM,aAAa,KAAK,IAAI,UAAU,OAAO,iBAAiB,QAAQ,GAAG,cAAc,KAAK,IAAI,WAAW,OAAO,kBAAkB,SAAS;AAC7I,YAAI,KAAK,UAAU,EAAE,UAAU,OAAO,SAAS,WAAW,CAAC,EAAE,SAAS,WAAY,OAAM,IAAI,MAAM,kBAAkB;AACpH,cAAM,MAAM;AACZ,YAAI,YAAY,QAAQ;AACvB,gBAAM,WAAW,MAAM,WAAW,OAAO,UAAU,EAAE,SAAS,QAAQ,EAAE,CAAC;AACzE,cAAI,CAAC,SAAS,QAAS,OAAM,IAAI,MAAM,qBAAqB,SAAS,SAAS,KAAK,SAAS,MAAM,KAAK,EAAE,EAAE;AAAA,QAC5G;AACA,cAAM,MAAM;AACZ,cAAM,QAAQ,WAAW,EAAE,OAAO,EAAE,cAAc,SAAS,QAAQ,WAAW,QAAQ,OAAO,GAAG,UAAU,EAAE,SAAS,gBAAgB,IAAI,GAAI,QAAQ,EAAE,SAAS,MAAM,QAAQ,IAAI,CAAC,EAAG,EAAE,CAAC;AACzL,cAAM,MAAM;AACZ,yBAAiB;AACjB,mBAAW,gBAAgB,OAAO,EAAE,UAAU,GAAI,QAAQ,SAAS,EAAE,OAAO,QAAQ,IAAI,CAAC,GAAI,YAAY,gBAAgB,UAAU,GAAG,QAAQ,WAAW,OAAO,CAAC,EAAE,OAAO,aAAa,EAAE;AACzL,cAAM,QAAsB,CAAC,GAAG,QAAQ,oBAAI,IAAY,GAAG,QAAQ,IAAI,IAAI,QAAQ,IAAI,OAAK,EAAE,IAAI,CAAC;AACnG,YAAI,OAAO,GAAG,SAAS;AACvB,eAAO,MAAM;AACZ,gBAAM;AACN,gBAAM,OAAO,MAAM,SAAS,KAAK;AAAG,gBAAM;AAC1C,cAAI,KAAK,KAAM,OAAM,IAAI,MAAM,sCAAsC;AACrE,gBAAM,MAAM;AACZ,gBAAM,QAAQ,KAAK;AACnB,gBAAM,QAAQ,SAAS,EAAE,WAAW,MAAM,KAAK,CAAC;AAChD,cAAI,EAAE,SAAS,cAAc,QAAQ,KAAK,UAAU,KAAK,EAAE,UAAU,YAAa,OAAM,IAAI,MAAM,mBAAmB;AACrH,cAAI,MAAM,SAAS,WAAY,SAAQ,WAAW,OAAO,UAAU,MAAM,QAAQ,CAAC;AAClF,cAAI,MAAM,SAAS,UAAU;AAC5B,gBAAI,CAAC,CAAC,QAAO,YAAY,EAAE,SAAS,MAAM,MAAM,KAAM,MAAM,WAAW,iBAAmB,MAAM,OAAO,EAAI,OAAM,IAAI,MAAM,0CAA0C;AACrK,gBAAI,UAAyB,EAAE,IAAI,OAAO,WAAW,GAAG,MAAM,aAAa,MAAM;AACjF,gBAAI,YAAY,OAAO,OAAO;AAC7B,oBAAM,UAAU,MAAM,WAAW,MAAM,MAAM,EAAE,SAAS,QAAQ,GAAG,QAAQ,CAAC;AAC5E,kBAAI,CAAC,QAAQ,QAAS,OAAM,IAAI,MAAM,sBAAsB,QAAQ,SAAS,KAAK,QAAQ,MAAM,KAAK,EAAE,EAAE;AACzG,kBAAI,QAAQ,aAAa,QAAW;AACnC,oBAAI,QAAQ,SAAS,WAAW,EAAG,OAAM,IAAI,MAAM,kDAAkD;AACrG,0BAAU,gBAAgB,QAAQ,SAAS,CAAC,CAAC;AAAA,cAC9C;AAAA,YACD;AACA,gBAAI,KAAK,UAAU,OAAO,EAAE,SAAS,YAAa,OAAM,IAAI,MAAM,+BAA+B;AACjG,kBAAM,MAAM;AACZ,mBAAO,EAAE,SAAS,cAAc,MAAM,QAA0C,SAAS,OAAO,iBAAiB;AAAA,UAClH;AACA,cAAI,MAAM,SAAS,cAAc;AAChC,gBAAI,OAAO,MAAM,SAAS,SAAU,OAAM,IAAI,MAAM,mBAAmB;AACvE,kBAAM,WAAW,MAAM,GAAG,EAAE;AAC5B,gBAAI,UAAU,SAAS,OAAQ,OAAM,MAAM,SAAS,CAAC,IAAI,EAAE,MAAM,QAAQ,MAAM,SAAS,OAAO,MAAM,KAAK;AAAA,gBACrG,OAAM,KAAK,EAAE,MAAM,QAAQ,MAAM,MAAM,KAAK,CAAC;AAAA,UACnD,WAAW,MAAM,SAAS,aAAa;AACtC,gBAAI,CAAC,MAAM,IAAI,MAAM,IAAI,KAAK,OAAO,MAAM,WAAW,YAAY,CAAC,MAAM,OAAO,KAAK,KAAK,MAAM,IAAI,MAAM,MAAM,KAAK,MAAM,QAAQ,OAAO,CAAC,MAAM,SAAS,OAAO,MAAM,UAAU,YAAY,MAAM,QAAQ,MAAM,KAAK,EAAG,OAAM,IAAI,MAAM,wCAAwC;AACjR,kBAAM,IAAI,MAAM,MAAM;AAAG,kBAAM,KAAK,gBAAgB,KAAK,CAAC;AAAA,UAC3D,WAAW,MAAM,SAAS,OAAQ,OAAM,KAAK,gBAAgB,KAAK,CAAC;AAAA,mBAC1D,MAAM,SAAS,WAAY,OAAM,IAAI,MAAM,uBAAuB;AAAA,QAC5E;AAAA,MACD;AACA,UAAI;AACJ,YAAM,UAAU,IAAI,QAAe,CAAC,UAAU,WAAW;AACxD,sBAAc,MAAM,OAAO,IAAI,MAAM,6BAA6B,CAAC;AACnE,mBAAW,OAAO,iBAAiB,SAAS,aAAa,EAAE,MAAM,KAAK,CAAC;AACvE,YAAI,WAAW,OAAO,QAAS,aAAY;AAC3C,gBAAQ,WAAW,OAAO,OAAO;AAAA,MAClC,CAAC;AACD,YAAM,gBAAgB,YAAY;AACjC,YAAI;AACJ,YAAI;AAAE,mBAAS,MAAM,KAAK;AAAA,QAAE,SACrB,OAAO;AAAE,gBAAM,mBAAmB;AAAG,gBAAM;AAAA,QAAM;AACxD,cAAM,mBAAmB;AACzB,cAAM,MAAM;AACZ,cAAM,QAAQ,aAAa,EAAC,QAAO,OAAO,SAAQ,MAAK,CAAC;AACxD,cAAM,MAAM;AACZ,eAAO;AAAA,MACR;AACA,UAAI;AAAE,eAAO,MAAM,QAAQ,KAAK,CAAC,cAAc,GAAG,OAAO,CAAC;AAAA,MAAE,SACrD,OAAO;AACb,YAAI,UAAU;AAEd,YAAI;AAAE,gBAAM,QAAQ,KAAK,CAAC,mBAAmB,GAAE,OAAO,CAAC;AAAA,QAAE,SAClD,iBAAiB;AAAE,cAAI,CAAC,WAAW,OAAO,QAAS,WAAU;AAAA,QAAgB;AACpF,aAAK,QAAQ,UAAU,EAAE,OAAO,mBAAmB,QAAQ,QAAQ,UAAU,OAAO,OAAO,GAAG,MAAM,CAAC;AACrG,cAAM;AAAA,MACP,UACA;AACC,qBAAa,KAAK;AAAG,cAAM,QAAQ,oBAAoB,SAAS,KAAK;AACrE,YAAI,YAAa,YAAW,OAAO,oBAAoB,SAAS,WAAW;AAC3E,mBAAW,MAAM;AACjB,YAAI;AAAE,eAAK,QAAQ,QAAQ,UAAU,SAAS,CAAC,EAAE,MAAM,MAAM;AAAA,UAAC,CAAC;AAAA,QAAE,QAAQ;AAAA,QAAuC;AAAA,MACjH;AAAA,IACD;AAAA,EACD;AACD;AAEA,SAAS,UAAU,OAAqC;AACvD,MAAI,CAAC,SAAS,OAAO,UAAU,YAAY,MAAM,QAAQ,KAAK,EAAG,QAAO;AACxE,QAAM,SAAS,OAAkC,MAAM,OAAO,SAAS,OAAO,OAAO,UAAU,YAAY,CAAC,MAAM,QAAQ,OAAO,KAAK,IAAI,OAAO,QAAmC;AACpL,QAAM,cAAc,OAAO,IAAI,eAAe,IAAI,gBAAgB,IAAI,YAAY,GAAG,eAAe,OAAO,IAAI,gBAAgB,IAAI,oBAAoB,IAAI,aAAa,GAAG,cAAc,OAAO,IAAI,eAAe,IAAI,YAAY,GAAG,OAAO,OAAO,IAAI,IAAI,GAAG,WAAW,OAAO,IAAI,aAAa,WAAW,IAAI,WAAW;AAC5T,MAAI,gBAAgB,UAAa,iBAAiB,UAAa,gBAAgB,UAAa,SAAS,OAAW,QAAO;AACvH,SAAO,EAAE,GAAI,gBAAgB,SAAY,CAAC,IAAI,EAAE,YAAY,GAAI,GAAI,iBAAiB,SAAY,CAAC,IAAI,EAAE,aAAa,GAAI,GAAI,gBAAgB,SAAY,CAAC,IAAI,EAAE,YAAY,GAAI,GAAI,SAAS,SAAY,CAAC,IAAI,EAAE,KAAK,GAAI,GAAI,WAAW,EAAE,SAAS,IAAI,CAAC,EAAG;AAC5P;AAEA,SAAS,OAAO,OAAoC;AAAE,SAAO,OAAO,UAAU,YAAY,OAAO,SAAS,KAAK,KAAK,SAAS,IAAI,QAAQ;AAAU;AACnJ,SAAS,WAAW,UAA+B,MAAgD;AAAE,SAAO,OAAO,EAAE,GAAI,YAAY,CAAC,GAAI,GAAG,KAAK,IAAI;AAAS;","names":[]}
|
package/dist/db-package/index.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
LocalFirstSqliteAdapter
|
|
3
|
-
} from "../chunk-VISRDVTK.js";
|
|
4
1
|
import "../chunk-JT6BRGQM.js";
|
|
5
2
|
import {
|
|
6
3
|
MigrationAggregator
|
|
7
4
|
} from "../chunk-5WOZWPZA.js";
|
|
5
|
+
import {
|
|
6
|
+
LocalFirstSqliteAdapter
|
|
7
|
+
} from "../chunk-VISRDVTK.js";
|
|
8
8
|
|
|
9
9
|
// src/db-package/index.ts
|
|
10
10
|
export * from "@alneas/eaos-core/contracts/data-contracts";
|
package/dist/engine.js
CHANGED
|
@@ -2,12 +2,12 @@ import {
|
|
|
2
2
|
ErpEngine,
|
|
3
3
|
createErpEngine,
|
|
4
4
|
defineConfig
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-F4IITPGX.js";
|
|
6
|
+
import "./chunk-L6PMAEMB.js";
|
|
6
7
|
import "./chunk-XIEY2OF4.js";
|
|
7
8
|
import "./chunk-AVDMLTPF.js";
|
|
8
9
|
import "./chunk-VC2PCK2S.js";
|
|
9
10
|
import "./chunk-R4ADP2DC.js";
|
|
10
|
-
import "./chunk-L6PMAEMB.js";
|
|
11
11
|
import "./chunk-VF5YDZJC.js";
|
|
12
12
|
import "./chunk-46UWPEW2.js";
|
|
13
13
|
import "./chunk-INCHXAFK.js";
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import '@alneas/appkit-core/ai/ai-chat';
|
|
2
|
+
import '@alneas/appkit-core/ai/action';
|
|
3
|
+
import '@alneas/eaos-core';
|
|
4
|
+
export { ChatClientOptions, ChatCompletion, ChatGovernanceOptions, createChatClient } from './index.js';
|
|
5
|
+
import 'hono/types';
|
|
6
|
+
import 'hono';
|
|
7
|
+
import '@alneas/appkit-core/ai';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -1,5 +1,160 @@
|
|
|
1
|
+
import { AIChatMessage, AIChatAdapter } from '@alneas/appkit-core/ai/ai-chat';
|
|
2
|
+
import { ActionToolBinding, ActionRegistry, ActionToolCall, ActionToolObject, ActionToolDescriptor } from '@alneas/appkit-core/ai/action';
|
|
3
|
+
import { AIModelRegistry, AIGuard, AIBudgetGate, AIObservabilitySink, AIUsage, AIExecutionContext } from '@alneas/eaos-core';
|
|
1
4
|
import * as hono_types from 'hono/types';
|
|
2
5
|
import { Context, Hono } from 'hono';
|
|
6
|
+
import * as _alneas_appkit_core_ai from '@alneas/appkit-core/ai';
|
|
7
|
+
|
|
8
|
+
/** Host-registered Action binding and explicit automatic-execution policy.
|
|
9
|
+
* @see createToolAgent
|
|
10
|
+
*/
|
|
11
|
+
interface AgentTool {
|
|
12
|
+
/** Existing Appkit Action/command binding; registration and input/output schemas remain Appkit-owned. */
|
|
13
|
+
binding: ActionToolBinding;
|
|
14
|
+
/** Only host-verified read-only actions may run automatically; handoffs remain unexecuted. */
|
|
15
|
+
mode: 'read' | 'handoff';
|
|
16
|
+
}
|
|
17
|
+
/** Current host policies and limits for a single-flight Appkit execution session.
|
|
18
|
+
* @see createToolAgent
|
|
19
|
+
*/
|
|
20
|
+
interface ToolAgentOptions extends Omit<ChatClientOptions, 'tools'> {
|
|
21
|
+
/**
|
|
22
|
+
* Resolve the current host registry and explicit tool execution policy.
|
|
23
|
+
* @param principal - Copied verified tenant/user identity.
|
|
24
|
+
* @returns Existing Action registry and at most 100 read/handoff bindings.
|
|
25
|
+
* @throws Rejects missing host session or registry resolution failures.
|
|
26
|
+
* @example
|
|
27
|
+
* ```typescript
|
|
28
|
+
* import type { ToolAgentOptions } from '@alneas/eaos-server/execution/tool-agent';
|
|
29
|
+
* export function agentSession(resolve: ToolAgentOptions['session']) { return resolve; }
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
session(principal: ExecutionPrincipal): Promise<{
|
|
33
|
+
/** Existing host-owned Appkit Action registry for this authorized session. */
|
|
34
|
+
registry: ActionRegistry;
|
|
35
|
+
/** Explicit read/handoff policy for every disclosed binding. */
|
|
36
|
+
tools: readonly AgentTool[];
|
|
37
|
+
}>;
|
|
38
|
+
/**
|
|
39
|
+
* Check current permission to disclose a tool descriptor or result to the model.
|
|
40
|
+
* @param principal - Copied verified actor.
|
|
41
|
+
* @param name - Host-registered tool name.
|
|
42
|
+
* @returns Exactly true permits disclosure; other results deny it.
|
|
43
|
+
* @throws Host policy errors propagate into the execution outcome.
|
|
44
|
+
* @example
|
|
45
|
+
* ```typescript
|
|
46
|
+
* import type { ToolAgentOptions } from '@alneas/eaos-server/execution/tool-agent';
|
|
47
|
+
* export function disclosurePolicy(policy: ToolAgentOptions['disclose']) { return policy; }
|
|
48
|
+
* ```
|
|
49
|
+
*/
|
|
50
|
+
disclose(principal: ExecutionPrincipal, name: string): Promise<boolean>;
|
|
51
|
+
/**
|
|
52
|
+
* Check exact resource/input permission before execution and before result disclosure.
|
|
53
|
+
* @param principal - Copied verified actor; callback mutation cannot change the trusted identity.
|
|
54
|
+
* @param call - Untrusted model request with correlated ID, name and arguments.
|
|
55
|
+
* @returns Exactly true admits the call; it does not approve a handoff for execution.
|
|
56
|
+
* @throws Host policy errors propagate into the execution outcome.
|
|
57
|
+
* @example
|
|
58
|
+
* ```typescript
|
|
59
|
+
* import type { ToolAgentOptions } from '@alneas/eaos-server/execution/tool-agent';
|
|
60
|
+
* export function callPolicy(policy: ToolAgentOptions['authorizeCall']) { return policy; }
|
|
61
|
+
* ```
|
|
62
|
+
*/
|
|
63
|
+
authorizeCall(principal: ExecutionPrincipal, call: ActionToolCall): Promise<boolean>;
|
|
64
|
+
/** Maximum model rounds; default 6, allowed integers 1–20. */
|
|
65
|
+
maxRounds?: number;
|
|
66
|
+
/** Maximum automatic Action calls per run; default 10, allowed integers 1–100. */
|
|
67
|
+
maxCalls?: number;
|
|
68
|
+
}
|
|
69
|
+
/** Final in-memory conversational outcome, separate from Appkit execution status.
|
|
70
|
+
* @see createToolAgent
|
|
71
|
+
*/
|
|
72
|
+
interface ToolAgentResult {
|
|
73
|
+
/** Completed chat, unexecuted handoff, bounded stop, or an Action validation/execution failure. */
|
|
74
|
+
status: 'completed' | 'handoff' | 'limited' | 'tool-error';
|
|
75
|
+
/** Detached correlated chat history, including only authorized projected tool results. */
|
|
76
|
+
messages: AIChatMessage[];
|
|
77
|
+
/** Unexecuted requests; the host must validate them through its existing Action/Proposal review path. */
|
|
78
|
+
pending: ActionToolCall[];
|
|
79
|
+
/** Number of attempted automatic Action calls, including a returned Action failure. */
|
|
80
|
+
callsExecuted: number;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Orchestrate bounded model rounds through existing Appkit Action/Execution and scoped EAOS chat.
|
|
84
|
+
* @param options - Current session/disclosure/call policies, Appkit adapter and chat/round/call limits.
|
|
85
|
+
* @returns Single-flight run, cancel, close and summary subscription methods backed by Appkit ExecutionSession.
|
|
86
|
+
* @throws Invalid policies or round/call limits reject construction. Concurrent/closed runs reject through
|
|
87
|
+
* Appkit; asynchronous authorization/provider failures become failed execution outcomes. Cancellation is
|
|
88
|
+
* cooperative and does not roll back previously completed Action effects.
|
|
89
|
+
* @remarks Only explicitly host-verified read tools execute automatically. A batch containing any handoff
|
|
90
|
+
* returns all its calls without executing them. No durable command engine, approval grant or transaction
|
|
91
|
+
* is created; retained tool-call/result history and descriptors are reauthorized at the exact adapter
|
|
92
|
+
* boundary after chat governance, including caller-supplied history and guard substitutions. Approved writes belong to the host's existing proposal/approval and owning command service.
|
|
93
|
+
* @example
|
|
94
|
+
* ```typescript
|
|
95
|
+
* import { createToolAgent, type ToolAgentOptions } from '@alneas/eaos-server/execution/tool-agent';
|
|
96
|
+
* export function connectAgent(options: ToolAgentOptions) { return createToolAgent(options); }
|
|
97
|
+
* ```
|
|
98
|
+
*/
|
|
99
|
+
declare function createToolAgent(options: ToolAgentOptions): {
|
|
100
|
+
/**
|
|
101
|
+
* Request cooperative cancellation of the current Appkit execution.
|
|
102
|
+
* @returns No value; Appkit marks active work cancelling without rolling back completed effects.
|
|
103
|
+
* @example
|
|
104
|
+
* ```typescript
|
|
105
|
+
* import { createToolAgent } from '@alneas/eaos-server/execution/tool-agent';
|
|
106
|
+
* export function cancel(agent: ReturnType<typeof createToolAgent>) { return agent.cancel(); }
|
|
107
|
+
* ```
|
|
108
|
+
*/
|
|
109
|
+
cancel: () => void;
|
|
110
|
+
/**
|
|
111
|
+
* Read Appkit's summary-only in-memory execution history.
|
|
112
|
+
* @returns Appkit execution summaries; raw model inputs/results are not stored in these summaries.
|
|
113
|
+
* @example
|
|
114
|
+
* ```typescript
|
|
115
|
+
* import { createToolAgent } from '@alneas/eaos-server/execution/tool-agent';
|
|
116
|
+
* export function snapshot(agent: ReturnType<typeof createToolAgent>) { return agent.getSnapshot(); }
|
|
117
|
+
* ```
|
|
118
|
+
*/
|
|
119
|
+
getSnapshot: () => readonly _alneas_appkit_core_ai.ExecutionRecord[];
|
|
120
|
+
/**
|
|
121
|
+
* Subscribe to Appkit execution summary changes.
|
|
122
|
+
* @param listener - Callback notified when execution state changes; do not expose raw secrets in UI callbacks.
|
|
123
|
+
* @returns Unsubscribe function owned by the subscribing host.
|
|
124
|
+
* @example
|
|
125
|
+
* ```typescript
|
|
126
|
+
* import { createToolAgent } from '@alneas/eaos-server/execution/tool-agent';
|
|
127
|
+
* export function observe(agent: ReturnType<typeof createToolAgent>, listener: () => void) { return agent.subscribe(listener); }
|
|
128
|
+
* ```
|
|
129
|
+
*/
|
|
130
|
+
subscribe: (listener: () => void) => () => void;
|
|
131
|
+
/**
|
|
132
|
+
* Close the Appkit session and request cooperative cancellation.
|
|
133
|
+
* @returns No value; the session no longer admits new runs.
|
|
134
|
+
* @example
|
|
135
|
+
* ```typescript
|
|
136
|
+
* import { createToolAgent } from '@alneas/eaos-server/execution/tool-agent';
|
|
137
|
+
* export function close(agent: ReturnType<typeof createToolAgent>) { agent.close(); }
|
|
138
|
+
* ```
|
|
139
|
+
*/
|
|
140
|
+
close: () => void;
|
|
141
|
+
/**
|
|
142
|
+
* Run a single authorized model/Action conversation.
|
|
143
|
+
* @param principal - Verified current tenant/user identity, copied before host callbacks.
|
|
144
|
+
* @param input - Detached initial messages and optional cooperative cancellation signal.
|
|
145
|
+
* @returns Appkit execution outcome containing a ToolAgentResult on success; failed/cancelled outcomes omit it.
|
|
146
|
+
* @throws Appkit rejects concurrent or closed session admission; run failures otherwise become outcomes.
|
|
147
|
+
* @example
|
|
148
|
+
* ```typescript
|
|
149
|
+
* import { createToolAgent } from '@alneas/eaos-server/execution/tool-agent';
|
|
150
|
+
* export function run(agent: ReturnType<typeof createToolAgent>, ...args: Parameters<typeof agent.run>) { return agent.run(...args); }
|
|
151
|
+
* ```
|
|
152
|
+
*/
|
|
153
|
+
run(principal: ExecutionPrincipal, input: {
|
|
154
|
+
messages: readonly AIChatMessage[];
|
|
155
|
+
signal?: AbortSignal;
|
|
156
|
+
}): Promise<_alneas_appkit_core_ai.ExecutionOutcome<ToolAgentResult>>;
|
|
157
|
+
};
|
|
3
158
|
|
|
4
159
|
/**
|
|
5
160
|
* Authenticated host identity supplied to {@link createPluginExecutionRouter}.
|
|
@@ -45,6 +200,143 @@ declare function createPluginExecutionRouter(options: {
|
|
|
45
200
|
*/
|
|
46
201
|
allowedOrigins?: string[];
|
|
47
202
|
}): Hono<hono_types.BlankEnv, hono_types.BlankSchema, "/">;
|
|
203
|
+
/** Verified generic execution identity; policy checks remain host-owned.
|
|
204
|
+
* @see createChatClient
|
|
205
|
+
*/
|
|
206
|
+
type ExecutionPrincipal = ExecutionIdentity;
|
|
207
|
+
/** Current admission policy used by model and action orchestration.
|
|
208
|
+
* @see createChatClient
|
|
209
|
+
*/
|
|
210
|
+
interface ExecutionPolicy {
|
|
211
|
+
/**
|
|
212
|
+
* Check current membership, activation and operation permission.
|
|
213
|
+
* @param principal - Trusted tenant/user identity copied before calling the host.
|
|
214
|
+
* @param operation - Host operation identity; chat uses model:chat.
|
|
215
|
+
* @returns Exactly true to admit; any other value denies execution.
|
|
216
|
+
* @throws Host policy failures propagate to the caller.
|
|
217
|
+
* @example
|
|
218
|
+
* ```typescript
|
|
219
|
+
* import type { ExecutionPolicy } from '@alneas/eaos-server/execution';
|
|
220
|
+
* export function currentPolicy(policy: ExecutionPolicy) { return policy; }
|
|
221
|
+
* ```
|
|
222
|
+
* @see createChatClient
|
|
223
|
+
*/
|
|
224
|
+
authorize(principal: ExecutionPrincipal, operation: string): Promise<boolean>;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/** Host-injected model guards, usage budgets and telemetry.
|
|
228
|
+
* @see createChatClient
|
|
229
|
+
*/
|
|
230
|
+
interface ChatGovernanceOptions {
|
|
231
|
+
/** Optional pre-input and post-output checks; replacement messages remain host-owned. */
|
|
232
|
+
guard?: AIGuard;
|
|
233
|
+
/** Optional request admission and once-per-started-attempt accounting; accounting failures propagate. */
|
|
234
|
+
budget?: AIBudgetGate;
|
|
235
|
+
/** Awaited started/event/completed telemetry within the deadline; sink errors are ignored. */
|
|
236
|
+
observability?: AIObservabilitySink;
|
|
237
|
+
/** Telemetry operation label; authorization always checks model:chat. */
|
|
238
|
+
operation?: string;
|
|
239
|
+
/** Host-selected registry model ID; without a registry this is metadata, not provider selection. */
|
|
240
|
+
model?: string;
|
|
241
|
+
/** Optional host session identity recorded in governance context. */
|
|
242
|
+
sessionId?: string;
|
|
243
|
+
}
|
|
244
|
+
/** Host-configured adapter, current admission and bounded chat policy.
|
|
245
|
+
* @see createChatClient
|
|
246
|
+
*/
|
|
247
|
+
interface ChatClientOptions extends ExecutionPolicy {
|
|
248
|
+
/** Existing Appkit transport configured with the host endpoint, model and credentials. */
|
|
249
|
+
adapter: AIChatAdapter;
|
|
250
|
+
/** Host-owned provider parameters cloned at creation; model/messages/tools/stream keys are reserved and rejected. */
|
|
251
|
+
parameters?: ActionToolObject;
|
|
252
|
+
/**
|
|
253
|
+
* Resolve descriptors only when the caller explicitly requests tools: catalog.
|
|
254
|
+
* @param principal - Copied verified actor whose current disclosure permission the host must check.
|
|
255
|
+
* @returns At most 100 unique descriptors; omission advertises no tools.
|
|
256
|
+
* @throws Host resolution failures reject completion before the provider starts.
|
|
257
|
+
* @example
|
|
258
|
+
* ```typescript
|
|
259
|
+
* import type { ChatClientOptions } from '@alneas/eaos-server/execution/chat';
|
|
260
|
+
* export function disclosedTools(resolve: NonNullable<ChatClientOptions['tools']>) { return resolve; }
|
|
261
|
+
* ```
|
|
262
|
+
*/
|
|
263
|
+
tools?(principal: ExecutionPrincipal): Promise<readonly ActionToolDescriptor[]>;
|
|
264
|
+
/** Positive integer deadline in milliseconds; default 30000, maximum 3600000. */
|
|
265
|
+
timeoutMs?: number;
|
|
266
|
+
/** Serialized request character ceiling; default 200000, maximum 7000000. */
|
|
267
|
+
maxInputChars?: number;
|
|
268
|
+
/** Serialized event and final assistant-message character ceiling; default 100000, maximum 10000000. */
|
|
269
|
+
maxOutputChars?: number;
|
|
270
|
+
/** Maximum stream event count; default 10000, maximum 100000. */
|
|
271
|
+
maxEvents?: number;
|
|
272
|
+
/** Host-approved route registry; requests cannot select a model or bypass sensitivity limits. */
|
|
273
|
+
modelRegistry?: AIModelRegistry;
|
|
274
|
+
/** Required with modelRegistry: host-approved logical model to configured adapter bindings, snapshotted at creation. */
|
|
275
|
+
modelAdapters?: Readonly<Record<string, AIChatAdapter>>;
|
|
276
|
+
/** Optional host guards, budgets and telemetry; final current authorization follows their completion. */
|
|
277
|
+
governance?: ChatGovernanceOptions;
|
|
278
|
+
}
|
|
279
|
+
/** Completed assistant message and optional host-governance metadata.
|
|
280
|
+
* @see createChatClient
|
|
281
|
+
*/
|
|
282
|
+
interface ChatCompletion {
|
|
283
|
+
/** Detached assistant response; tool-call parts are unexecuted requests. */
|
|
284
|
+
message: AIChatMessage;
|
|
285
|
+
/** Successful provider finish reason; truncated or inconsistent streams reject. */
|
|
286
|
+
finishReason: 'stop' | 'tool-calls';
|
|
287
|
+
/** Unique request trace identity generated before governance callbacks. */
|
|
288
|
+
traceId?: string;
|
|
289
|
+
/** Recognized nonnegative adapter metadata; undefined means unknown, including Appkit OpenAI SSE without usage events. */
|
|
290
|
+
usage?: AIUsage;
|
|
291
|
+
/** Sensitivity label supplied by the input guard. */
|
|
292
|
+
sensitivityLevel?: AIExecutionContext['sensitivityLevel'];
|
|
293
|
+
}
|
|
294
|
+
/**
|
|
295
|
+
* Complete scoped chat through the existing Appkit adapter with live admission and host governance.
|
|
296
|
+
* @param options - Trusted adapter, current authorization, optional routes/governance and bounded limits.
|
|
297
|
+
* @returns A client whose complete method returns detached, finally authorized assistant data.
|
|
298
|
+
* @throws Rejects invalid limits or missing adapter/policy during construction. Completion rejects
|
|
299
|
+
* invalid histories/catalogs, denied or revoked admission, guard/budget/route denial, provider failures,
|
|
300
|
+
* incomplete streams, exceeded limits, cancellation, deadline expiry and host accounting failure. Telemetry errors are ignored.
|
|
301
|
+
* @remarks Every completion authorizes model:chat before disclosure, between events and after awaited
|
|
302
|
+
* output guard, usage recording and completion telemetry. This client never executes model tool calls.
|
|
303
|
+
* The host must configure real endpoint credentials in the Appkit adapter. Abort is cooperative for a
|
|
304
|
+
* custom transport; the request promise remains bounded even if its iterator ignores cancellation.
|
|
305
|
+
* With modelRegistry, provide modelAdapters mapping each approved logical model to its host-configured
|
|
306
|
+
* Appkit adapter; generic adapter IDs alone do not select or prove the provider model. Binding entries
|
|
307
|
+
* and stream methods are snapshotted at creation. Reserved transport parameters are rejected in 0.2.
|
|
308
|
+
* Accounting runs once after each started adapter attempt, including output blocks, revocation and provider
|
|
309
|
+
* failure. Unknown usage is passed as undefined, never zero. Appkit's OpenAI SSE adapter currently emits
|
|
310
|
+
* no usage metadata event even for provider include_usage chunks; hosts must reconcile measured usage
|
|
311
|
+
* through their existing accounting port using trace/session context. Accounting callback errors reject
|
|
312
|
+
* completion in 0.2; a stalled callback remains bounded by the request deadline.
|
|
313
|
+
* @example
|
|
314
|
+
* ```typescript
|
|
315
|
+
* import { createChatClient, type ChatClientOptions } from '@alneas/eaos-server/execution/chat';
|
|
316
|
+
* export function connectChat(options: ChatClientOptions) { return createChatClient(options); }
|
|
317
|
+
* ```
|
|
318
|
+
*/
|
|
319
|
+
declare function createChatClient(options: ChatClientOptions): {
|
|
320
|
+
/**
|
|
321
|
+
* Request one bounded completion for the current actor.
|
|
322
|
+
* @param principal - Verified nonblank tenant/user identity; copied before invoking host callbacks.
|
|
323
|
+
* @param input - One to 1000 messages, optional cancellation, and explicit none/catalog tool disclosure.
|
|
324
|
+
* @returns Assistant data only after final live authorization; tools remain unexecuted requests.
|
|
325
|
+
* @throws Rejects invalid requests, governance/provider failure, revocation, limits or cancellation.
|
|
326
|
+
* @example
|
|
327
|
+
* ```typescript
|
|
328
|
+
* import { createChatClient } from '@alneas/eaos-server/execution/chat';
|
|
329
|
+
* export function complete(client: ReturnType<typeof createChatClient>, ...args: Parameters<typeof client.complete>) {
|
|
330
|
+
* return client.complete(...args);
|
|
331
|
+
* }
|
|
332
|
+
* ```
|
|
333
|
+
*/
|
|
334
|
+
complete(principal: ExecutionPrincipal, input: {
|
|
335
|
+
messages: readonly AIChatMessage[];
|
|
336
|
+
signal?: AbortSignal;
|
|
337
|
+
tools?: "none" | "catalog";
|
|
338
|
+
}): Promise<ChatCompletion>;
|
|
339
|
+
};
|
|
48
340
|
|
|
49
|
-
export { createPluginExecutionRouter };
|
|
50
|
-
export type { ExecutionIdentity };
|
|
341
|
+
export { createChatClient, createPluginExecutionRouter, createToolAgent };
|
|
342
|
+
export type { AgentTool, ChatClientOptions, ChatCompletion, ChatGovernanceOptions, ExecutionIdentity, ExecutionPolicy, ExecutionPrincipal, ToolAgentOptions, ToolAgentResult };
|
package/dist/execution/index.js
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createToolAgent
|
|
3
|
+
} from "../chunk-4BARRLJR.js";
|
|
4
|
+
import {
|
|
5
|
+
createChatClient
|
|
6
|
+
} from "../chunk-YMHVRBUU.js";
|
|
7
|
+
|
|
1
8
|
// src/execution/index.ts
|
|
2
9
|
import { Hono } from "hono";
|
|
3
10
|
function createPluginExecutionRouter(options) {
|
|
@@ -52,6 +59,8 @@ function createPluginExecutionRouter(options) {
|
|
|
52
59
|
return router;
|
|
53
60
|
}
|
|
54
61
|
export {
|
|
55
|
-
|
|
62
|
+
createChatClient,
|
|
63
|
+
createPluginExecutionRouter,
|
|
64
|
+
createToolAgent
|
|
56
65
|
};
|
|
57
66
|
//# sourceMappingURL=index.js.map
|