@corenel/harness 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/compression.d.ts +11 -0
- package/dist/compression.d.ts.map +1 -0
- package/dist/compression.js +27 -0
- package/dist/compression.js.map +1 -0
- package/dist/conversation.d.ts +29 -0
- package/dist/conversation.d.ts.map +1 -0
- package/dist/conversation.js +25 -0
- package/dist/conversation.js.map +1 -0
- package/dist/core/loop.d.ts +31 -0
- package/dist/core/loop.d.ts.map +1 -0
- package/dist/core/loop.js +237 -0
- package/dist/core/loop.js.map +1 -0
- package/dist/dag/executeNode.d.ts +41 -0
- package/dist/dag/executeNode.d.ts.map +1 -0
- package/dist/dag/executeNode.js +81 -0
- package/dist/dag/executeNode.js.map +1 -0
- package/dist/fileSchema.d.ts +7 -0
- package/dist/fileSchema.d.ts.map +1 -0
- package/dist/fileSchema.js +40 -0
- package/dist/fileSchema.js.map +1 -0
- package/dist/guardrail/builtins.d.ts +9 -0
- package/dist/guardrail/builtins.d.ts.map +1 -0
- package/dist/guardrail/builtins.js +61 -0
- package/dist/guardrail/builtins.js.map +1 -0
- package/dist/guardrail/glob.d.ts +3 -0
- package/dist/guardrail/glob.d.ts.map +1 -0
- package/dist/guardrail/glob.js +33 -0
- package/dist/guardrail/glob.js.map +1 -0
- package/dist/guardrail/guardrail.d.ts +25 -0
- package/dist/guardrail/guardrail.d.ts.map +1 -0
- package/dist/guardrail/guardrail.js +67 -0
- package/dist/guardrail/guardrail.js.map +1 -0
- package/dist/guardrail/index.d.ts +9 -0
- package/dist/guardrail/index.d.ts.map +1 -0
- package/dist/guardrail/index.js +11 -0
- package/dist/guardrail/index.js.map +1 -0
- package/dist/guardrail/permission-service.d.ts +53 -0
- package/dist/guardrail/permission-service.d.ts.map +1 -0
- package/dist/guardrail/permission-service.js +147 -0
- package/dist/guardrail/permission-service.js.map +1 -0
- package/dist/guardrail/serialize.d.ts +9 -0
- package/dist/guardrail/serialize.d.ts.map +1 -0
- package/dist/guardrail/serialize.js +53 -0
- package/dist/guardrail/serialize.js.map +1 -0
- package/dist/guardrail/store.d.ts +26 -0
- package/dist/guardrail/store.d.ts.map +1 -0
- package/dist/guardrail/store.js +109 -0
- package/dist/guardrail/store.js.map +1 -0
- package/dist/guardrail/validate.d.ts +8 -0
- package/dist/guardrail/validate.d.ts.map +1 -0
- package/dist/guardrail/validate.js +105 -0
- package/dist/guardrail/validate.js.map +1 -0
- package/dist/guards.d.ts +37 -0
- package/dist/guards.d.ts.map +1 -0
- package/dist/guards.js +45 -0
- package/dist/guards.js.map +1 -0
- package/dist/log.d.ts +4 -0
- package/dist/log.d.ts.map +1 -0
- package/dist/log.js +22 -0
- package/dist/log.js.map +1 -0
- package/dist/promptCompiler.d.ts +18 -0
- package/dist/promptCompiler.d.ts.map +1 -0
- package/dist/promptCompiler.js +11 -0
- package/dist/promptCompiler.js.map +1 -0
- package/dist/prompts/config.d.ts +63 -0
- package/dist/prompts/config.d.ts.map +1 -0
- package/dist/prompts/config.js +268 -0
- package/dist/prompts/config.js.map +1 -0
- package/dist/prompts/host.d.ts +30 -0
- package/dist/prompts/host.d.ts.map +1 -0
- package/dist/prompts/host.js +11 -0
- package/dist/prompts/host.js.map +1 -0
- package/dist/prompts/index.d.ts +50 -0
- package/dist/prompts/index.d.ts.map +1 -0
- package/dist/prompts/index.js +105 -0
- package/dist/prompts/index.js.map +1 -0
- package/dist/prompts/library/defaults.generated.d.ts +2 -0
- package/dist/prompts/library/defaults.generated.d.ts.map +1 -0
- package/dist/prompts/library/defaults.generated.js +31 -0
- package/dist/prompts/library/defaults.generated.js.map +1 -0
- package/dist/prompts/library/index.d.ts +8 -0
- package/dist/prompts/library/index.d.ts.map +1 -0
- package/dist/prompts/library/index.js +28 -0
- package/dist/prompts/library/index.js.map +1 -0
- package/dist/providers/gateway.d.ts +58 -0
- package/dist/providers/gateway.d.ts.map +1 -0
- package/dist/providers/gateway.js +145 -0
- package/dist/providers/gateway.js.map +1 -0
- package/dist/services.d.ts +29 -0
- package/dist/services.d.ts.map +1 -0
- package/dist/services.js +22 -0
- package/dist/services.js.map +1 -0
- package/dist/sidecar/host.d.ts +69 -0
- package/dist/sidecar/host.d.ts.map +1 -0
- package/dist/sidecar/host.js +228 -0
- package/dist/sidecar/host.js.map +1 -0
- package/dist/sidecar/server.d.ts +42 -0
- package/dist/sidecar/server.d.ts.map +1 -0
- package/dist/sidecar/server.js +267 -0
- package/dist/sidecar/server.js.map +1 -0
- package/dist/skills.d.ts +39 -0
- package/dist/skills.d.ts.map +1 -0
- package/dist/skills.js +216 -0
- package/dist/skills.js.map +1 -0
- package/dist/systemParts.d.ts +10 -0
- package/dist/systemParts.d.ts.map +1 -0
- package/dist/systemParts.js +21 -0
- package/dist/systemParts.js.map +1 -0
- package/dist/todos.d.ts +34 -0
- package/dist/todos.d.ts.map +1 -0
- package/dist/todos.js +112 -0
- package/dist/todos.js.map +1 -0
- package/dist/tools/builtins.d.ts +20 -0
- package/dist/tools/builtins.d.ts.map +1 -0
- package/dist/tools/builtins.js +335 -0
- package/dist/tools/builtins.js.map +1 -0
- package/dist/tools/files.d.ts +11 -0
- package/dist/tools/files.d.ts.map +1 -0
- package/dist/tools/files.js +161 -0
- package/dist/tools/files.js.map +1 -0
- package/dist/tools/http.d.ts +3 -0
- package/dist/tools/http.d.ts.map +1 -0
- package/dist/tools/http.js +71 -0
- package/dist/tools/http.js.map +1 -0
- package/dist/tools/namespaces.d.ts +27 -0
- package/dist/tools/namespaces.d.ts.map +1 -0
- package/dist/tools/namespaces.js +83 -0
- package/dist/tools/namespaces.js.map +1 -0
- package/dist/tools/registry.d.ts +8 -0
- package/dist/tools/registry.d.ts.map +1 -0
- package/dist/tools/registry.js +14 -0
- package/dist/tools/registry.js.map +1 -0
- package/dist/tools/sessions.d.ts +3 -0
- package/dist/tools/sessions.d.ts.map +1 -0
- package/dist/tools/sessions.js +149 -0
- package/dist/tools/sessions.js.map +1 -0
- package/dist/tools/todo.d.ts +3 -0
- package/dist/tools/todo.d.ts.map +1 -0
- package/dist/tools/todo.js +38 -0
- package/dist/tools/todo.js.map +1 -0
- package/dist/tools/urlGuard.d.ts +9 -0
- package/dist/tools/urlGuard.d.ts.map +1 -0
- package/dist/tools/urlGuard.js +80 -0
- package/dist/tools/urlGuard.js.map +1 -0
- package/dist/tools/web.d.ts +3 -0
- package/dist/tools/web.d.ts.map +1 -0
- package/dist/tools/web.js +35 -0
- package/dist/tools/web.js.map +1 -0
- package/package.json +55 -0
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/* Shipped defaults for the Prompd-config workspace. The .md files in this folder
|
|
2
|
+
* are the source of truth; `defaults.generated.ts` inlines them as pure TS (run
|
|
3
|
+
* `node generate.mjs` after editing any .md) so this is node-runnable — no Vite
|
|
4
|
+
* `?raw` / import.meta.glob. CONFIG_DEFAULTS keys are config-workspace paths.
|
|
5
|
+
*
|
|
6
|
+
* `systems/system-<ext...>.md` are auto-mapped to per-filetype system prompts:
|
|
7
|
+
* drop one in systems/, regenerate, and (unless it's `system-base`) it registers
|
|
8
|
+
* for those extensions. See systemForFile. */
|
|
9
|
+
import { RAW_DEFAULTS } from './defaults.generated';
|
|
10
|
+
/** The single source of truth for seeding the config store + resetting a file. */
|
|
11
|
+
export const CONFIG_DEFAULTS = RAW_DEFAULTS;
|
|
12
|
+
/** Per-extension system prompt: file extension -> config path. Excludes base.
|
|
13
|
+
* Derived from the systems/system-*.md keys (pure — no bundler glob). */
|
|
14
|
+
export const SYSTEM_BY_EXT = {};
|
|
15
|
+
for (const configPath of Object.keys(CONFIG_DEFAULTS)) {
|
|
16
|
+
if (!configPath.startsWith('systems/system-'))
|
|
17
|
+
continue;
|
|
18
|
+
const file = configPath.split('/').pop(); // system-prmd-md.md
|
|
19
|
+
const stem = file.replace(/^system-/, '').replace(/\.md$/, ''); // prmd-md | pdflow | base
|
|
20
|
+
if (stem === 'base')
|
|
21
|
+
continue;
|
|
22
|
+
for (const ext of stem.split('-'))
|
|
23
|
+
if (ext)
|
|
24
|
+
SYSTEM_BY_EXT[ext] = configPath;
|
|
25
|
+
}
|
|
26
|
+
/** The default selected persona id (matches a personas/<id>.md key). */
|
|
27
|
+
export const DEFAULT_PERSONA = 'default';
|
|
28
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../prompts/library/index.ts"],"names":[],"mappings":"AAAA;;;;;;;8CAO8C;AAC9C,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAEpD,kFAAkF;AAClF,MAAM,CAAC,MAAM,eAAe,GAA2B,YAAY,CAAC;AAEpE;yEACyE;AACzE,MAAM,CAAC,MAAM,aAAa,GAA2B,EAAE,CAAC;AACxD,KAAK,MAAM,UAAU,IAAI,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC,EAAE,CAAC;IACtD,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,iBAAiB,CAAC;QAAE,SAAS;IACxD,MAAM,IAAI,GAAG,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAY,CAAC,CAAU,oBAAoB;IACjF,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC,0BAA0B;IAC1F,IAAI,IAAI,KAAK,MAAM;QAAE,SAAS;IAC9B,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC;QAAE,IAAI,GAAG;YAAE,aAAa,CAAC,GAAG,CAAC,GAAG,UAAU,CAAC;AAC9E,CAAC;AAED,wEAAwE;AACxE,MAAM,CAAC,MAAM,eAAe,GAAG,SAAS,CAAC"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import OpenAI from 'openai';
|
|
2
|
+
import type { ChatCompletionMessageParam, ChatCompletionTool } from 'openai/resources/chat/completions';
|
|
3
|
+
import type { IAuthTokenProvider, Usage } from '@corenel/protocol';
|
|
4
|
+
export declare function setGatewayBase(url: string): void;
|
|
5
|
+
export interface StreamCompletionParams {
|
|
6
|
+
model: string;
|
|
7
|
+
messages: ChatCompletionMessageParam[];
|
|
8
|
+
tools?: ChatCompletionTool[];
|
|
9
|
+
tool_choice?: 'auto' | 'none';
|
|
10
|
+
}
|
|
11
|
+
export interface AccumulatedToolCall {
|
|
12
|
+
id: string;
|
|
13
|
+
name: string;
|
|
14
|
+
arguments: string;
|
|
15
|
+
}
|
|
16
|
+
export interface StreamedCompletion {
|
|
17
|
+
content: string;
|
|
18
|
+
toolCalls: AccumulatedToolCall[];
|
|
19
|
+
usage: Usage;
|
|
20
|
+
finishReason: string;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Stream a completion and accumulate it: text deltas are surfaced via onText for
|
|
24
|
+
* live rendering; streamed tool-call deltas (indexed fragments) are reassembled
|
|
25
|
+
* into whole tool calls. Returns the finished message + usage.
|
|
26
|
+
*/
|
|
27
|
+
export declare function streamCompletion(client: OpenAI, params: StreamCompletionParams, signal: AbortSignal, onText?: (delta: string) => void): Promise<StreamedCompletion>;
|
|
28
|
+
export declare function createChatClient(auth: IAuthTokenProvider): OpenAI;
|
|
29
|
+
/** Host-injected model→custom-provider lookup. The kernel transport knows how to
|
|
30
|
+
* build a custom client but NOT how the host decides which model belongs to one
|
|
31
|
+
* (that lookup reads app storage) — so the app registers it at boot. Default:
|
|
32
|
+
* always the gateway. Keeps chat.ts free of any prompd/app import. */
|
|
33
|
+
export type CustomProviderResolver = (model: string) => {
|
|
34
|
+
baseURL: string;
|
|
35
|
+
apiKey: string;
|
|
36
|
+
} | null | undefined;
|
|
37
|
+
export declare function setCustomProviderResolver(fn: CustomProviderResolver): void;
|
|
38
|
+
/** Route a model to its client: a custom OpenAI-compatible provider's direct
|
|
39
|
+
* client when the host's resolver claims the model, else the caller's gateway.
|
|
40
|
+
* The single source of truth for model→client routing (workflow runner, test
|
|
41
|
+
* runner, …) so custom-provider handling can't drift between features.
|
|
42
|
+
* Main-thread only — the resolver reads localStorage. */
|
|
43
|
+
export declare function clientForModel(model: string, gateway: OpenAI): OpenAI;
|
|
44
|
+
/** Host-injected proxy for custom-provider fetches. Returns a Response (e.g. routed
|
|
45
|
+
* through a local sidecar so a loopback LLM dodges browser CORS) or null to fall
|
|
46
|
+
* back to a direct browser fetch. The kernel knows nothing about the sidecar — the
|
|
47
|
+
* app wires this; default is always-direct. */
|
|
48
|
+
export type LocalFetchProxy = (url: string, init: RequestInit) => Promise<Response> | null;
|
|
49
|
+
export declare function setLocalFetchProxy(fn: LocalFetchProxy): void;
|
|
50
|
+
/** A client for a custom OpenAI-compatible provider — calls its base URL directly
|
|
51
|
+
* with the user-supplied key (no gateway), UNLESS the injected local proxy handles
|
|
52
|
+
* it (loopback via the sidecar). Pure: the caller passes the provider config, so
|
|
53
|
+
* this stays Worker-safe (no localStorage). */
|
|
54
|
+
export declare function createCustomClient(p: {
|
|
55
|
+
baseURL: string;
|
|
56
|
+
apiKey: string;
|
|
57
|
+
}): OpenAI;
|
|
58
|
+
//# sourceMappingURL=gateway.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gateway.d.ts","sourceRoot":"","sources":["../../providers/gateway.ts"],"names":[],"mappings":"AAIA,OAAO,MAAM,MAAM,QAAQ,CAAC;AAC5B,OAAO,KAAK,EAAE,0BAA0B,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAC;AACxG,OAAO,KAAK,EAAE,kBAAkB,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAOnE,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAEhD;AAUD,MAAM,WAAW,sBAAsB;IACrC,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,0BAA0B,EAAE,CAAC;IACvC,KAAK,CAAC,EAAE,kBAAkB,EAAE,CAAC;IAC7B,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CAC/B;AAED,MAAM,WAAW,mBAAmB;IAAG,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE;AAEpF,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,mBAAmB,EAAE,CAAC;IACjC,KAAK,EAAE,KAAK,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;CACtB;AAED;;;;GAIG;AACH,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,sBAAsB,EAC9B,MAAM,EAAE,WAAW,EACnB,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,GAC/B,OAAO,CAAC,kBAAkB,CAAC,CA2D7B;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,kBAAkB,GAAG,MAAM,CAwBjE;AAED;;;sEAGsE;AACtE,MAAM,MAAM,sBAAsB,GAAG,CAAC,KAAK,EAAE,MAAM,KAAK;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,GAAG,SAAS,CAAC;AAE/G,wBAAgB,yBAAyB,CAAC,EAAE,EAAE,sBAAsB,GAAG,IAAI,CAE1E;AAED;;;;yDAIyD;AACzD,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAGrE;AAED;;;+CAG+C;AAC/C,MAAM,MAAM,eAAe,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,KAAK,OAAO,CAAC,QAAQ,CAAC,GAAG,IAAI,CAAC;AAE3F,wBAAgB,kBAAkB,CAAC,EAAE,EAAE,eAAe,GAAG,IAAI,CAA0B;AAEvF;;;+CAG+C;AAC/C,wBAAgB,kBAAkB,CAAC,CAAC,EAAE;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAUjF"}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
/* Chat transport: the official OpenAI SDK pointed at our same-origin gateway
|
|
2
|
+
* (/api/v1/chat/completions). The gateway holds the real provider key; the
|
|
3
|
+
* browser sends the short-lived Clerk token, injected per-request via a custom
|
|
4
|
+
* fetch (so token refresh is automatic and it works from a Worker later). */
|
|
5
|
+
import OpenAI from 'openai';
|
|
6
|
+
import { alog } from '../log';
|
|
7
|
+
// The gateway base. Injected by the host (the app wires VITE_API_BASE_URL; a node
|
|
8
|
+
// host passes an absolute endpoint like https://api.corenel.ai). Default '/api'
|
|
9
|
+
// (same-origin). The kernel stays env-agnostic — no import.meta.env here.
|
|
10
|
+
let apiBase = '/api';
|
|
11
|
+
export function setGatewayBase(url) {
|
|
12
|
+
apiBase = (url || '/api').replace(/\/$/, '');
|
|
13
|
+
}
|
|
14
|
+
function gatewayBaseURL() {
|
|
15
|
+
// The OpenAI SDK needs an absolute baseURL; it appends "/chat/completions".
|
|
16
|
+
// Use globalThis.location so this works on the main thread AND in a Worker.
|
|
17
|
+
const v1 = `${apiBase}/v1`;
|
|
18
|
+
if (/^https?:\/\//.test(v1))
|
|
19
|
+
return v1;
|
|
20
|
+
return `${globalThis.location.origin}${v1}`;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Stream a completion and accumulate it: text deltas are surfaced via onText for
|
|
24
|
+
* live rendering; streamed tool-call deltas (indexed fragments) are reassembled
|
|
25
|
+
* into whole tool calls. Returns the finished message + usage.
|
|
26
|
+
*/
|
|
27
|
+
export async function streamCompletion(client, params, signal, onText) {
|
|
28
|
+
alog('stream:create', { model: params.model, messages: params.messages.length, tools: params.tools?.length ?? 0 });
|
|
29
|
+
let stream;
|
|
30
|
+
try {
|
|
31
|
+
stream = await client.chat.completions.create({
|
|
32
|
+
model: params.model,
|
|
33
|
+
messages: params.messages,
|
|
34
|
+
tools: params.tools,
|
|
35
|
+
tool_choice: params.tool_choice,
|
|
36
|
+
stream: true,
|
|
37
|
+
stream_options: { include_usage: true },
|
|
38
|
+
}, { signal });
|
|
39
|
+
}
|
|
40
|
+
catch (e) {
|
|
41
|
+
// Surface the real gateway failure. The OpenAI SDK throws an APIError carrying
|
|
42
|
+
// the HTTP status + parsed body; collapse that into a clear message so it reads
|
|
43
|
+
// as "Gateway 500: <reason>" in the UI instead of an opaque "internal server
|
|
44
|
+
// error" (this string is what crosses the worker -> main-thread boundary).
|
|
45
|
+
const err = e;
|
|
46
|
+
const raw = err?.error;
|
|
47
|
+
const detail = (typeof raw === 'string' ? raw : raw?.error || raw?.message) || err?.message || String(e);
|
|
48
|
+
const msg = typeof err?.status === 'number' ? `Gateway ${err.status}: ${detail}` : detail;
|
|
49
|
+
alog('stream:create-error', msg);
|
|
50
|
+
throw new Error(msg);
|
|
51
|
+
}
|
|
52
|
+
alog('stream:open');
|
|
53
|
+
let content = '';
|
|
54
|
+
let finishReason = 'stop';
|
|
55
|
+
let chunkN = 0;
|
|
56
|
+
const usage = { promptTokens: 0, completionTokens: 0 };
|
|
57
|
+
const byIndex = new Map();
|
|
58
|
+
for await (const chunk of stream) {
|
|
59
|
+
if (chunkN++ === 0)
|
|
60
|
+
alog('stream:first-chunk');
|
|
61
|
+
const choice = chunk.choices?.[0];
|
|
62
|
+
if (choice?.delta?.content) {
|
|
63
|
+
content += choice.delta.content;
|
|
64
|
+
onText?.(choice.delta.content);
|
|
65
|
+
}
|
|
66
|
+
for (const tc of choice?.delta?.tool_calls ?? []) {
|
|
67
|
+
const cur = byIndex.get(tc.index) ?? { id: '', name: '', arguments: '' };
|
|
68
|
+
if (tc.id)
|
|
69
|
+
cur.id = tc.id;
|
|
70
|
+
if (tc.function?.name)
|
|
71
|
+
cur.name = tc.function.name;
|
|
72
|
+
if (tc.function?.arguments)
|
|
73
|
+
cur.arguments += tc.function.arguments;
|
|
74
|
+
byIndex.set(tc.index, cur);
|
|
75
|
+
}
|
|
76
|
+
if (choice?.finish_reason)
|
|
77
|
+
finishReason = choice.finish_reason;
|
|
78
|
+
if (chunk.usage) {
|
|
79
|
+
usage.promptTokens = chunk.usage.prompt_tokens || 0;
|
|
80
|
+
usage.completionTokens = chunk.usage.completion_tokens || 0;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
const toolCalls = [...byIndex.entries()].sort((a, b) => a[0] - b[0]).map(([, v]) => v);
|
|
84
|
+
alog('stream:end', { chunks: chunkN, contentLen: content.length, toolCalls: toolCalls.length, finishReason, usage });
|
|
85
|
+
return { content, toolCalls, usage, finishReason };
|
|
86
|
+
}
|
|
87
|
+
export function createChatClient(auth) {
|
|
88
|
+
return new OpenAI({
|
|
89
|
+
baseURL: gatewayBaseURL(),
|
|
90
|
+
// Real key lives server-side; this placeholder is replaced per-request by the
|
|
91
|
+
// Clerk token in the custom fetch below. The SDK requires a non-empty value.
|
|
92
|
+
apiKey: 'prompd-gateway',
|
|
93
|
+
dangerouslyAllowBrowser: true,
|
|
94
|
+
fetch: async (url, init) => {
|
|
95
|
+
const headers = new Headers(init?.headers);
|
|
96
|
+
alog('gateway:token-wait');
|
|
97
|
+
const token = await auth.getToken().catch(() => null);
|
|
98
|
+
if (token)
|
|
99
|
+
headers.set('Authorization', `Bearer ${token}`);
|
|
100
|
+
else
|
|
101
|
+
headers.delete('Authorization');
|
|
102
|
+
alog('gateway:fetch', { url: String(url), hasToken: !!token });
|
|
103
|
+
try {
|
|
104
|
+
const res = await fetch(url, { ...init, headers });
|
|
105
|
+
alog('gateway:status', res.status, res.statusText);
|
|
106
|
+
return res;
|
|
107
|
+
}
|
|
108
|
+
catch (e) {
|
|
109
|
+
alog('gateway:fetch-error', String(e?.message || e));
|
|
110
|
+
throw e;
|
|
111
|
+
}
|
|
112
|
+
},
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
let resolveCustomProvider = () => null;
|
|
116
|
+
export function setCustomProviderResolver(fn) {
|
|
117
|
+
resolveCustomProvider = fn;
|
|
118
|
+
}
|
|
119
|
+
/** Route a model to its client: a custom OpenAI-compatible provider's direct
|
|
120
|
+
* client when the host's resolver claims the model, else the caller's gateway.
|
|
121
|
+
* The single source of truth for model→client routing (workflow runner, test
|
|
122
|
+
* runner, …) so custom-provider handling can't drift between features.
|
|
123
|
+
* Main-thread only — the resolver reads localStorage. */
|
|
124
|
+
export function clientForModel(model, gateway) {
|
|
125
|
+
const cp = resolveCustomProvider(model);
|
|
126
|
+
return cp ? createCustomClient(cp) : gateway;
|
|
127
|
+
}
|
|
128
|
+
let localFetchProxy = () => null;
|
|
129
|
+
export function setLocalFetchProxy(fn) { localFetchProxy = fn; }
|
|
130
|
+
/** A client for a custom OpenAI-compatible provider — calls its base URL directly
|
|
131
|
+
* with the user-supplied key (no gateway), UNLESS the injected local proxy handles
|
|
132
|
+
* it (loopback via the sidecar). Pure: the caller passes the provider config, so
|
|
133
|
+
* this stays Worker-safe (no localStorage). */
|
|
134
|
+
export function createCustomClient(p) {
|
|
135
|
+
return new OpenAI({
|
|
136
|
+
baseURL: p.baseURL.replace(/\/$/, ''),
|
|
137
|
+
apiKey: p.apiKey || 'no-key',
|
|
138
|
+
dangerouslyAllowBrowser: true,
|
|
139
|
+
fetch: async (url, init) => {
|
|
140
|
+
const proxied = localFetchProxy(String(url), (init ?? {}));
|
|
141
|
+
return proxied ?? fetch(url, init);
|
|
142
|
+
},
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
//# sourceMappingURL=gateway.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gateway.js","sourceRoot":"","sources":["../../providers/gateway.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/** Result of a server-side compile (the browser can't resolve package refs/binary
|
|
2
|
+
* assets; the backend does). Only `output` is consumed here; the host impl may
|
|
3
|
+
* carry more. */
|
|
4
|
+
export interface BuildResult {
|
|
5
|
+
output: string;
|
|
6
|
+
}
|
|
7
|
+
/** Backend health-check result. */
|
|
8
|
+
export interface PingResult {
|
|
9
|
+
ok: boolean;
|
|
10
|
+
version?: string;
|
|
11
|
+
error?: string;
|
|
12
|
+
}
|
|
13
|
+
export interface HostServices {
|
|
14
|
+
/** Bearer token for the backend/gateway, or null when unauthenticated. */
|
|
15
|
+
getToken(): Promise<string | null>;
|
|
16
|
+
/** Base URL for the backend API (e.g. '/api' or an absolute origin). */
|
|
17
|
+
getApiBase(): string;
|
|
18
|
+
/** Server-side compile (resolves package refs + binary assets a browser can't). */
|
|
19
|
+
build(content: string, parameters: Record<string, unknown>, opts?: {
|
|
20
|
+
signal?: AbortSignal;
|
|
21
|
+
}): Promise<BuildResult>;
|
|
22
|
+
/** Reachability + version check for the backend. */
|
|
23
|
+
ping(): Promise<PingResult>;
|
|
24
|
+
}
|
|
25
|
+
/** Inject the host's backend access. Called once at boot (see the host's wiring). */
|
|
26
|
+
export declare function setHostServices(s: Partial<HostServices>): void;
|
|
27
|
+
/** The injected host services (defaults: no token, '/api'). */
|
|
28
|
+
export declare function hostServices(): HostServices;
|
|
29
|
+
//# sourceMappingURL=services.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"services.d.ts","sourceRoot":"","sources":["../services.ts"],"names":[],"mappings":"AAQA;;iBAEiB;AACjB,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,mCAAmC;AACnC,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,OAAO,CAAC;IACZ,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,YAAY;IAC3B,0EAA0E;IAC1E,QAAQ,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IACnC,wEAAwE;IACxE,UAAU,IAAI,MAAM,CAAC;IACrB,mFAAmF;IACnF,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IACnH,oDAAoD;IACpD,IAAI,IAAI,OAAO,CAAC,UAAU,CAAC,CAAC;CAC7B;AASD,qFAAqF;AACrF,wBAAgB,eAAe,CAAC,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,GAAG,IAAI,CAE9D;AAED,+DAA+D;AAC/D,wBAAgB,YAAY,IAAI,YAAY,CAE3C"}
|
package/dist/services.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/* HostServices — the seam by which a host supplies backend access (auth token +
|
|
2
|
+
* API base) to Corenel modules that are NOT React components (the runners, the
|
|
3
|
+
* agent assembly, the console), so they don't import the host's services/api
|
|
4
|
+
* directly. Mirrors setGatewayBase: the host injects once at boot; corenel code
|
|
5
|
+
* reads via hostServices(). The gateway has its own token/base injection
|
|
6
|
+
* (setGatewayBase + the per-client getToken); this covers the non-gateway uses
|
|
7
|
+
* (e.g. a runner attaching a bearer token to a direct fetch). */
|
|
8
|
+
let services = {
|
|
9
|
+
getToken: async () => null,
|
|
10
|
+
getApiBase: () => '/api',
|
|
11
|
+
build: async () => ({ output: '' }),
|
|
12
|
+
ping: async () => ({ ok: false, error: 'no backend configured' }),
|
|
13
|
+
};
|
|
14
|
+
/** Inject the host's backend access. Called once at boot (see the host's wiring). */
|
|
15
|
+
export function setHostServices(s) {
|
|
16
|
+
services = { ...services, ...s };
|
|
17
|
+
}
|
|
18
|
+
/** The injected host services (defaults: no token, '/api'). */
|
|
19
|
+
export function hostServices() {
|
|
20
|
+
return services;
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=services.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"services.js","sourceRoot":"","sources":["../services.ts"],"names":[],"mappings":"AAAA;;;;;;iEAMiE;AA2BjE,IAAI,QAAQ,GAAiB;IAC3B,QAAQ,EAAE,KAAK,IAAI,EAAE,CAAC,IAAI;IAC1B,UAAU,EAAE,GAAG,EAAE,CAAC,MAAM;IACxB,KAAK,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;IACnC,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,uBAAuB,EAAE,CAAC;CAClE,CAAC;AAEF,qFAAqF;AACrF,MAAM,UAAU,eAAe,CAAC,CAAwB;IACtD,QAAQ,GAAG,EAAE,GAAG,QAAQ,EAAE,GAAG,CAAC,EAAE,CAAC;AACnC,CAAC;AAED,+DAA+D;AAC/D,MAAM,UAAU,YAAY;IAC1B,OAAO,QAAQ,CAAC;AAClB,CAAC"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import type { AgentTool, IMemoryProvider, IKeyValueStore, ISearchProvider, ISessionStore, PermissionRequest, AskQuestion, AskAnswers } from '@corenel/protocol';
|
|
2
|
+
import type { FileService } from '@corenel/protocol';
|
|
3
|
+
import { type SidecarChannel } from '@corenel/protocol';
|
|
4
|
+
/** The host's live capabilities a connected sidecar may proxy into. Only the ones
|
|
5
|
+
* provided are reachable; a proxy call to a missing one is rejected. */
|
|
6
|
+
export interface HostProviders {
|
|
7
|
+
memory?: IMemoryProvider;
|
|
8
|
+
kv?: IKeyValueStore;
|
|
9
|
+
search?: ISearchProvider;
|
|
10
|
+
sessions?: ISessionStore;
|
|
11
|
+
/** The host's active file workspace (virtual or a real folder). */
|
|
12
|
+
files?: FileService;
|
|
13
|
+
/** Ask the user to approve a side-effecting action. */
|
|
14
|
+
confirm?: (req: PermissionRequest) => Promise<boolean>;
|
|
15
|
+
/** Ask the user one or more questions. */
|
|
16
|
+
ask?: (questions: AskQuestion[]) => Promise<AskAnswers | null>;
|
|
17
|
+
}
|
|
18
|
+
export interface SidecarHostOptions {
|
|
19
|
+
channel: SidecarChannel;
|
|
20
|
+
/** Pairing token presented to the sidecar (surface B — authenticates the
|
|
21
|
+
* connection; does NOT grant policy authority, which stays with the host). */
|
|
22
|
+
token: string;
|
|
23
|
+
/** The host's live stores. Only the ones provided are reachable; a proxy call
|
|
24
|
+
* to a missing provider is rejected. */
|
|
25
|
+
providers: HostProviders;
|
|
26
|
+
/** Register an imported proxy tool (wire to the kernel `registerTool`). */
|
|
27
|
+
registerTool: (tool: AgentTool) => void;
|
|
28
|
+
/** Remove a proxy tool on disconnect (wire to `unregisterTool`). */
|
|
29
|
+
unregisterTool?: (name: string) => void;
|
|
30
|
+
}
|
|
31
|
+
export declare class SidecarHost {
|
|
32
|
+
private readonly ch;
|
|
33
|
+
private readonly opts;
|
|
34
|
+
private invokeSeq;
|
|
35
|
+
private readonly invokePending;
|
|
36
|
+
private httpSeq;
|
|
37
|
+
private readonly httpPending;
|
|
38
|
+
private features;
|
|
39
|
+
private readonly imported;
|
|
40
|
+
private welcome;
|
|
41
|
+
constructor(opts: SidecarHostOptions);
|
|
42
|
+
/** Authenticate, then import the sidecar's tools. Resolves with their names,
|
|
43
|
+
* or rejects if the sidecar denies the token / protocol. */
|
|
44
|
+
connect(): Promise<string[]>;
|
|
45
|
+
/** Drop the connection: unregister imported tools and fail anything in flight. */
|
|
46
|
+
disconnect(reason?: string): void;
|
|
47
|
+
private onMessage;
|
|
48
|
+
/** Whether the connected sidecar advertised the loopback HTTP proxy. */
|
|
49
|
+
supportsHttpProxy(): boolean;
|
|
50
|
+
/** Fetch a (loopback) URL THROUGH the sidecar — a server-side fetch on the user's
|
|
51
|
+
* machine, so the browser dodges CORS. Returns a streaming Response: it resolves
|
|
52
|
+
* as soon as headers arrive (http-res) and the body streams in via http-chunk. */
|
|
53
|
+
httpFetch(req: {
|
|
54
|
+
method: string;
|
|
55
|
+
url: string;
|
|
56
|
+
headers: Record<string, string>;
|
|
57
|
+
body?: string;
|
|
58
|
+
}): Promise<Response>;
|
|
59
|
+
private invoke;
|
|
60
|
+
/** Answer a sidecar's proxy-provider call from the host's live store. The
|
|
61
|
+
* allowlist (HOST_METHODS) is the least-privilege boundary — a sidecar can
|
|
62
|
+
* never call an unlisted method, nor a provider the host didn't expose. */
|
|
63
|
+
private serveHostCall;
|
|
64
|
+
/** The dispatch object for a host-call: the stores/files expose their methods
|
|
65
|
+
* directly; confirm/ask are single functions wrapped so the method dispatch
|
|
66
|
+
* (`obj[method](...args)`) is uniform. */
|
|
67
|
+
private resolveProvider;
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=host.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"host.d.ts","sourceRoot":"","sources":["../../sidecar/host.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EACV,SAAS,EAAE,eAAe,EAAE,cAAc,EAAE,eAAe,EAAE,aAAa,EAC1E,iBAAiB,EAAE,WAAW,EAAE,UAAU,EAC3C,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAEL,KAAK,cAAc,EACpB,MAAM,mBAAmB,CAAC;AAE3B;wEACwE;AACxE,MAAM,WAAW,aAAa;IAC5B,MAAM,CAAC,EAAE,eAAe,CAAC;IACzB,EAAE,CAAC,EAAE,cAAc,CAAC;IACpB,MAAM,CAAC,EAAE,eAAe,CAAC;IACzB,QAAQ,CAAC,EAAE,aAAa,CAAC;IACzB,mEAAmE;IACnE,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,uDAAuD;IACvD,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,iBAAiB,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IACvD,0CAA0C;IAC1C,GAAG,CAAC,EAAE,CAAC,SAAS,EAAE,WAAW,EAAE,KAAK,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAAC;CAChE;AAED,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,cAAc,CAAC;IACxB;kFAC8E;IAC9E,KAAK,EAAE,MAAM,CAAC;IACd;4CACwC;IACxC,SAAS,EAAE,aAAa,CAAC;IACzB,2EAA2E;IAC3E,YAAY,EAAE,CAAC,IAAI,EAAE,SAAS,KAAK,IAAI,CAAC;IACxC,oEAAoE;IACpE,cAAc,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CACzC;AAkBD,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAiB;IACpC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAqB;IAC1C,OAAO,CAAC,SAAS,CAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,aAAa,CAA8B;IAC5D,OAAO,CAAC,OAAO,CAAK;IACpB,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAkC;IAC9D,OAAO,CAAC,QAAQ,CAAgB;IAChC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAgB;IACzC,OAAO,CAAC,OAAO,CAAmF;gBAEtF,IAAI,EAAE,kBAAkB;IAMpC;gEAC4D;IAC5D,OAAO,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IAO5B,kFAAkF;IAClF,UAAU,CAAC,MAAM,SAAiB,GAAG,IAAI;IAYzC,OAAO,CAAC,SAAS;IAsCjB,wEAAwE;IACxE,iBAAiB,IAAI,OAAO;IAE5B;;sFAEkF;IAClF,SAAS,CAAC,GAAG,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,QAAQ,CAAC;IAoBlH,OAAO,CAAC,MAAM;IAQd;;+EAE2E;YAC7D,aAAa;IAe3B;;8CAE0C;IAC1C,OAAO,CAAC,eAAe;CAWxB"}
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
import { SIDECAR_PROTOCOL, HOST_METHODS, errMessage, } from '@corenel/protocol';
|
|
2
|
+
/** Decode a base64 chunk to bytes (atob is available in the browser and Node 18+). */
|
|
3
|
+
function b64ToBytes(b64) {
|
|
4
|
+
const bin = atob(b64);
|
|
5
|
+
const out = new Uint8Array(bin.length);
|
|
6
|
+
for (let i = 0; i < bin.length; i++)
|
|
7
|
+
out[i] = bin.charCodeAt(i);
|
|
8
|
+
return out;
|
|
9
|
+
}
|
|
10
|
+
export class SidecarHost {
|
|
11
|
+
constructor(opts) {
|
|
12
|
+
Object.defineProperty(this, "ch", {
|
|
13
|
+
enumerable: true,
|
|
14
|
+
configurable: true,
|
|
15
|
+
writable: true,
|
|
16
|
+
value: void 0
|
|
17
|
+
});
|
|
18
|
+
Object.defineProperty(this, "opts", {
|
|
19
|
+
enumerable: true,
|
|
20
|
+
configurable: true,
|
|
21
|
+
writable: true,
|
|
22
|
+
value: void 0
|
|
23
|
+
});
|
|
24
|
+
Object.defineProperty(this, "invokeSeq", {
|
|
25
|
+
enumerable: true,
|
|
26
|
+
configurable: true,
|
|
27
|
+
writable: true,
|
|
28
|
+
value: 0
|
|
29
|
+
});
|
|
30
|
+
Object.defineProperty(this, "invokePending", {
|
|
31
|
+
enumerable: true,
|
|
32
|
+
configurable: true,
|
|
33
|
+
writable: true,
|
|
34
|
+
value: new Map()
|
|
35
|
+
});
|
|
36
|
+
Object.defineProperty(this, "httpSeq", {
|
|
37
|
+
enumerable: true,
|
|
38
|
+
configurable: true,
|
|
39
|
+
writable: true,
|
|
40
|
+
value: 0
|
|
41
|
+
});
|
|
42
|
+
Object.defineProperty(this, "httpPending", {
|
|
43
|
+
enumerable: true,
|
|
44
|
+
configurable: true,
|
|
45
|
+
writable: true,
|
|
46
|
+
value: new Map()
|
|
47
|
+
});
|
|
48
|
+
Object.defineProperty(this, "features", {
|
|
49
|
+
enumerable: true,
|
|
50
|
+
configurable: true,
|
|
51
|
+
writable: true,
|
|
52
|
+
value: []
|
|
53
|
+
});
|
|
54
|
+
Object.defineProperty(this, "imported", {
|
|
55
|
+
enumerable: true,
|
|
56
|
+
configurable: true,
|
|
57
|
+
writable: true,
|
|
58
|
+
value: []
|
|
59
|
+
});
|
|
60
|
+
Object.defineProperty(this, "welcome", {
|
|
61
|
+
enumerable: true,
|
|
62
|
+
configurable: true,
|
|
63
|
+
writable: true,
|
|
64
|
+
value: null
|
|
65
|
+
});
|
|
66
|
+
this.opts = opts;
|
|
67
|
+
this.ch = opts.channel;
|
|
68
|
+
this.ch.onMessage((m) => this.onMessage(m));
|
|
69
|
+
}
|
|
70
|
+
/** Authenticate, then import the sidecar's tools. Resolves with their names,
|
|
71
|
+
* or rejects if the sidecar denies the token / protocol. */
|
|
72
|
+
connect() {
|
|
73
|
+
return new Promise((resolve, reject) => {
|
|
74
|
+
this.welcome = { resolve, reject };
|
|
75
|
+
this.ch.send({ t: 'hello', protocol: SIDECAR_PROTOCOL, token: this.opts.token });
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
/** Drop the connection: unregister imported tools and fail anything in flight. */
|
|
79
|
+
disconnect(reason = 'disconnected') {
|
|
80
|
+
for (const name of this.imported)
|
|
81
|
+
this.opts.unregisterTool?.(name);
|
|
82
|
+
this.imported.length = 0;
|
|
83
|
+
for (const p of this.invokePending.values())
|
|
84
|
+
p.reject(new Error(reason));
|
|
85
|
+
this.invokePending.clear();
|
|
86
|
+
for (const p of this.httpPending.values())
|
|
87
|
+
p.onErr(reason);
|
|
88
|
+
this.httpPending.clear();
|
|
89
|
+
this.welcome?.reject(new Error(reason));
|
|
90
|
+
this.welcome = null;
|
|
91
|
+
this.ch.close();
|
|
92
|
+
}
|
|
93
|
+
onMessage(m) {
|
|
94
|
+
switch (m.t) {
|
|
95
|
+
case 'welcome': {
|
|
96
|
+
this.features = m.features ?? [];
|
|
97
|
+
for (const decl of m.tools) {
|
|
98
|
+
const tool = { ...decl, run: (args) => this.invoke(decl.name, args) };
|
|
99
|
+
this.opts.registerTool(tool);
|
|
100
|
+
this.imported.push(decl.name);
|
|
101
|
+
}
|
|
102
|
+
this.welcome?.resolve([...this.imported]);
|
|
103
|
+
this.welcome = null;
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
case 'denied': {
|
|
107
|
+
this.welcome?.reject(new Error(`sidecar denied connection: ${m.reason}`));
|
|
108
|
+
this.welcome = null;
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
case 'invoke-result': {
|
|
112
|
+
const p = this.invokePending.get(m.id);
|
|
113
|
+
if (!p)
|
|
114
|
+
return;
|
|
115
|
+
this.invokePending.delete(m.id);
|
|
116
|
+
if (m.ok)
|
|
117
|
+
p.resolve(m.result ?? '');
|
|
118
|
+
else
|
|
119
|
+
p.reject(new Error(m.error || 'sidecar tool failed'));
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
case 'host-call':
|
|
123
|
+
void this.serveHostCall(m);
|
|
124
|
+
return;
|
|
125
|
+
case 'http-res': {
|
|
126
|
+
this.httpPending.get(m.id)?.onRes(m.status, m.statusText, m.headers);
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
case 'http-chunk': {
|
|
130
|
+
this.httpPending.get(m.id)?.onChunk(b64ToBytes(m.b64));
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
case 'http-end': {
|
|
134
|
+
this.httpPending.get(m.id)?.onEnd();
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
case 'http-err': {
|
|
138
|
+
this.httpPending.get(m.id)?.onErr(m.error);
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
default:
|
|
142
|
+
return; // hello / invoke / host-call-result are handled on the sidecar side
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
/** Whether the connected sidecar advertised the loopback HTTP proxy. */
|
|
146
|
+
supportsHttpProxy() { return this.features.includes('http-proxy'); }
|
|
147
|
+
/** Fetch a (loopback) URL THROUGH the sidecar — a server-side fetch on the user's
|
|
148
|
+
* machine, so the browser dodges CORS. Returns a streaming Response: it resolves
|
|
149
|
+
* as soon as headers arrive (http-res) and the body streams in via http-chunk. */
|
|
150
|
+
httpFetch(req) {
|
|
151
|
+
const id = ++this.httpSeq;
|
|
152
|
+
return new Promise((resolve, reject) => {
|
|
153
|
+
let ctrl = null;
|
|
154
|
+
let settled = false;
|
|
155
|
+
const stream = new ReadableStream({ start(c) { ctrl = c; } });
|
|
156
|
+
this.httpPending.set(id, {
|
|
157
|
+
onRes: (status, statusText, headers) => { settled = true; resolve(new Response(stream, { status, statusText, headers })); },
|
|
158
|
+
onChunk: (bytes) => { try {
|
|
159
|
+
ctrl?.enqueue(bytes);
|
|
160
|
+
}
|
|
161
|
+
catch { /* stream already closed */ } },
|
|
162
|
+
onEnd: () => { this.httpPending.delete(id); try {
|
|
163
|
+
ctrl?.close();
|
|
164
|
+
}
|
|
165
|
+
catch { /* already closed */ } },
|
|
166
|
+
onErr: (msg) => {
|
|
167
|
+
this.httpPending.delete(id);
|
|
168
|
+
if (!settled)
|
|
169
|
+
reject(new Error(msg));
|
|
170
|
+
else
|
|
171
|
+
try {
|
|
172
|
+
ctrl?.error(new Error(msg));
|
|
173
|
+
}
|
|
174
|
+
catch { /* already closed */ }
|
|
175
|
+
},
|
|
176
|
+
});
|
|
177
|
+
this.ch.send({ t: 'http-req', id, method: req.method, url: req.url, headers: req.headers, body: req.body });
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
invoke(name, args) {
|
|
181
|
+
const id = ++this.invokeSeq;
|
|
182
|
+
return new Promise((resolve, reject) => {
|
|
183
|
+
this.invokePending.set(id, { resolve, reject });
|
|
184
|
+
this.ch.send({ t: 'invoke', id, name, args });
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
/** Answer a sidecar's proxy-provider call from the host's live store. The
|
|
188
|
+
* allowlist (HOST_METHODS) is the least-privilege boundary — a sidecar can
|
|
189
|
+
* never call an unlisted method, nor a provider the host didn't expose. */
|
|
190
|
+
async serveHostCall(m) {
|
|
191
|
+
try {
|
|
192
|
+
const provider = this.resolveProvider(m.provider);
|
|
193
|
+
if (!HOST_METHODS[m.provider].includes(m.method)) {
|
|
194
|
+
throw new Error(`method ${m.provider}.${m.method} is not permitted`);
|
|
195
|
+
}
|
|
196
|
+
const fn = provider[m.method];
|
|
197
|
+
if (typeof fn !== 'function')
|
|
198
|
+
throw new Error(`method ${m.provider}.${m.method} is unavailable`);
|
|
199
|
+
const result = await fn.apply(provider, m.args);
|
|
200
|
+
this.ch.send({ t: 'host-call-result', id: m.id, ok: true, result });
|
|
201
|
+
}
|
|
202
|
+
catch (e) {
|
|
203
|
+
this.ch.send({ t: 'host-call-result', id: m.id, ok: false, error: errMessage(e) });
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
/** The dispatch object for a host-call: the stores/files expose their methods
|
|
207
|
+
* directly; confirm/ask are single functions wrapped so the method dispatch
|
|
208
|
+
* (`obj[method](...args)`) is uniform. */
|
|
209
|
+
resolveProvider(p) {
|
|
210
|
+
const pv = this.opts.providers;
|
|
211
|
+
let found;
|
|
212
|
+
switch (p) {
|
|
213
|
+
case 'confirm':
|
|
214
|
+
found = pv.confirm ? { confirm: pv.confirm } : undefined;
|
|
215
|
+
break;
|
|
216
|
+
case 'ask':
|
|
217
|
+
found = pv.ask ? { ask: pv.ask } : undefined;
|
|
218
|
+
break;
|
|
219
|
+
default:
|
|
220
|
+
found = pv[p];
|
|
221
|
+
break;
|
|
222
|
+
}
|
|
223
|
+
if (!found)
|
|
224
|
+
throw new Error(`capability ${p} is not available on this host`);
|
|
225
|
+
return found;
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
//# sourceMappingURL=host.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"host.js","sourceRoot":"","sources":["../../sidecar/host.ts"],"names":[],"mappings":"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"}
|