@kehto/shell 0.25.0 → 0.26.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -2
- package/dist/index.d.ts +49 -1
- package/dist/index.js +64 -1
- package/dist/index.js.map +1 -1
- package/package.json +6 -6
package/README.md
CHANGED
|
@@ -14,8 +14,10 @@ pnpm add @kehto/shell
|
|
|
14
14
|
|
|
15
15
|
## Published Napplet Compatibility
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
`>=0.32.0 <0.
|
|
17
|
+
Peers admit `@napplet/core` `>=0.32.0 <0.37.0` and `@napplet/nap`
|
|
18
|
+
`>=0.32.0 <0.36.0`, so the nap 0.35.x line that ships the `llm` subpath (and the
|
|
19
|
+
core 0.36.x line nap 0.35.1 requires) installs without peer conflicts; development
|
|
20
|
+
and tests stay on the baseline 0.32.0 line. The installed core 0.32.0 / nap 0.32.0 contracts follow
|
|
19
21
|
NAP-INTENT authority `5ac0490461ca6fec2f0d2e45b4835cf9bc08de24`, napplet/web#199
|
|
20
22
|
source `3037200c932488f14f7f369b8583c39c9c16510a` / merge
|
|
21
23
|
`b3f0007867eac109fa4917fac9c285d3b7cc6155`, and Version Packages #198 release
|
|
@@ -305,6 +307,10 @@ for outer URL encoding, review, routing, and verified launcher behavior.
|
|
|
305
307
|
|
|
306
308
|
This non-normative guidance defers to the living [NAP-GAMEPAD](https://github.com/napplet/naps/pull/108). Services export `createGamepadService` and `browserGamepadOptions`; shell exports `denyNappletControllerAccess`. Paja and the playground register one host reader and deny native gamepad/HID/USB paths before frame execution. Source-bound subscriptions receive immediate full snapshots; only the visible host's input owner gets live controls. Focus loss supplies neutral controls and timestamp zero; unsubscribe, window destruction, and service removal release polling. Non-browser or denied native readers report the proposal's unavailable reasons. See [Controller input](https://github.com/kehto/web/blob/main/docs/gamepad.md).
|
|
307
309
|
|
|
310
|
+
## LLM integration
|
|
311
|
+
|
|
312
|
+
This non-normative guidance defers to the living [NAP-LLM](https://github.com/napplet/naps/pull/134) (checked at `3e10939`). Services export `createLlmService`, `LlmServiceError`, the provider mappers and `LLM_PROVIDER_PRESETS`; shell exports `getShellDomainState` and the `LlmHooks` adapter field; acl exports `llm:generate`. The runtime routes `llm.*` to one registered service and answers every sanctioned request with exactly one `llm.<op>.result`, shaping missing-service and ACL failures as `{ code: 'unsupported' }`. Hosts implement `LlmConnectionHost`; the service enforces schema, handle ownership, consent before submission, duplicate ids, cancellation and deadline races, ordered deltas and safe errors. Advertisement stays binary on the wire while hosts report a third `unconfigured` state until the user adds a connection. See [Language models](https://github.com/kehto/web/blob/main/docs/llm.md).
|
|
313
|
+
|
|
308
314
|
## UUID support on HTTP origins
|
|
309
315
|
|
|
310
316
|
Shell event injection, cache queries, and source-session registration use native
|
package/dist/index.d.ts
CHANGED
|
@@ -243,6 +243,30 @@ interface WebrtcHooks {
|
|
|
243
243
|
/** True when the host has shell-mediated WebRTC sessions wired. */
|
|
244
244
|
isAvailable(): boolean;
|
|
245
245
|
}
|
|
246
|
+
/**
|
|
247
|
+
* Host wiring behind the NAP-LLM `llm` domain.
|
|
248
|
+
*
|
|
249
|
+
* NAP-LLM support is not binary: a host may have the runtime and service wired
|
|
250
|
+
* while the user has not yet configured any model connection. `isAvailable()`
|
|
251
|
+
* decides whether the domain is advertised at all; `isConfigured()` reports
|
|
252
|
+
* whether a connection exists so host UIs can show an "unconfigured" state and
|
|
253
|
+
* prompt for setup when a napplet first calls `llm.select`.
|
|
254
|
+
*/
|
|
255
|
+
interface LlmHooks {
|
|
256
|
+
/** True when the host can route `llm.*` to a registered service. */
|
|
257
|
+
isAvailable(): boolean;
|
|
258
|
+
/** True when at least one model connection is configured. Omitted means configured. */
|
|
259
|
+
isConfigured?(): boolean;
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* Host-facing advertisement state of one NAP domain.
|
|
263
|
+
*
|
|
264
|
+
* - `supported`: advertised to napplets and ready to serve requests.
|
|
265
|
+
* - `unconfigured`: advertised, but the host still needs user configuration
|
|
266
|
+
* (for example an LLM connection); the first request prompts for setup.
|
|
267
|
+
* - `disabled`: not advertised; the host disabled it or its backend is not live.
|
|
268
|
+
*/
|
|
269
|
+
type ShellDomainState = 'supported' | 'unconfigured' | 'disabled';
|
|
246
270
|
/**
|
|
247
271
|
* Optional host override for the static shell.init capability handshake.
|
|
248
272
|
*
|
|
@@ -417,6 +441,12 @@ interface ShellAdapter {
|
|
|
417
441
|
* registers the concrete service via `registerService('webrtc')`.
|
|
418
442
|
*/
|
|
419
443
|
webrtc?: WebrtcHooks;
|
|
444
|
+
/**
|
|
445
|
+
* Optional NAP-LLM wiring state. When omitted, a registered `llm` service is
|
|
446
|
+
* advertised as supported; when present, `isAvailable()` gates advertisement
|
|
447
|
+
* and `isConfigured()` feeds the host's unconfigured indicator.
|
|
448
|
+
*/
|
|
449
|
+
llm?: LlmHooks;
|
|
420
450
|
/**
|
|
421
451
|
* Optional capability advertisement override. Omitted by production hosts.
|
|
422
452
|
*/
|
|
@@ -982,6 +1012,24 @@ declare function buildShellCapabilities(hooks: ShellAdapter): ShellCapabilities;
|
|
|
982
1012
|
* @returns A fresh immutable environment whose entries are exact live subsets.
|
|
983
1013
|
*/
|
|
984
1014
|
declare function resolveShellEnvironment(hooks: ShellAdapter, identity: OriginIdentity): ShellEnvironment;
|
|
1015
|
+
/**
|
|
1016
|
+
* Report the host-facing advertisement state of one bare NAP domain.
|
|
1017
|
+
*
|
|
1018
|
+
* Advertisement itself stays binary on the wire (NIP-5D domain presence), but a
|
|
1019
|
+
* host UI needs the third state: the domain is advertised while the user has not
|
|
1020
|
+
* configured its backend yet. Only hooks that expose `isConfigured()` (today
|
|
1021
|
+
* `llm`) can report `unconfigured`; every other advertised domain is
|
|
1022
|
+
* `supported`, and anything not advertised is `disabled`.
|
|
1023
|
+
*
|
|
1024
|
+
* @param hooks - The ShellAdapter provided by the host app.
|
|
1025
|
+
* @param domain - Bare NAP domain name such as `llm`.
|
|
1026
|
+
* @returns `supported`, `unconfigured` or `disabled`.
|
|
1027
|
+
* @example
|
|
1028
|
+
* ```ts
|
|
1029
|
+
* getShellDomainState(hooks, 'llm'); // 'unconfigured' until a connection is saved
|
|
1030
|
+
* ```
|
|
1031
|
+
*/
|
|
1032
|
+
declare function getShellDomainState(hooks: ShellAdapter, domain: string): ShellDomainState;
|
|
985
1033
|
|
|
986
1034
|
/**
|
|
987
1035
|
* identity-proxy.ts — Shell-side per-domain proxy for identity.* envelopes.
|
|
@@ -1568,4 +1616,4 @@ type ResourceInbound = ResourceInfoRequest | ResourceBytesRequest | ResourceByte
|
|
|
1568
1616
|
*/
|
|
1569
1617
|
type ResourceOutbound = ResourceInfoResult | ResourceInfoError | ResourceBytesResult | ResourceBytesError | ResourceBytesManyResult | ResourceBytesManyError;
|
|
1570
1618
|
|
|
1571
|
-
export { type AclCheckEvent, type AclEntry, type AclStore, type AudioManager, type AudioSource, type AuthHooks, type BleHooks, type BrowserDeps, type CapabilityHooks, type CommonHooks, type ConfigHooks, type CryptoHooks, type DmHooks, type HotkeyHooks, type IdentityProxy, type IdentityProxyDeps, type IntentHooks, type KeysProxy, type KeysProxyDeps, type LinkHooks, type ListsHooks, type ManifestCache, type ManifestCacheEntry, type MediaProxy, type MediaProxyDeps, type NappletCspDirective, type NappletCspDirectives, type NappletCspOptions, type NappletNamespacePreludeOptions, type NappletSrcdocOptions, type NormalizedIntentUri, type NotifyProxy, type NotifyProxyDeps, type OriginIdentity, type OriginRegistry, type ProxyOriginRegistry, type RelayConfigHooks, type RelayPoolHooks, type RelayPoolLike, type ResourceBytesError, type ResourceBytesManyError, type ResourceBytesManyItem, type ResourceBytesManyRequest, type ResourceBytesManyResult, type ResourceBytesRequest, type ResourceBytesResult, type ResourceCancelRequest, type ResourceErrorCode, type ResourceInbound, type ResourceInfoError, type ResourceInfoRequest, type ResourceInfoResult, type ResourceOutbound, type ResourceRequestId, type SerialHooks, type SessionRegistry, type ShellAdapter, type ShellBridge, type ShellCapabilities, type ShellEnvironment, type ThemeProxy, type ThemeProxyDeps, type UnroutedMessageInfo, type UploadBackendLike, type UploadHooks, type WebrtcHooks, type WindowManagerHooks, type WorkerRelayHooks, type WorkerRelayLike, adaptHooks, audioManager, buildNappletCsp, buildShellCapabilities, createIdentityProxy, createKeysProxy, createMediaProxy, createNotifyProxy, createShellBridge, createThemeProxy, denyNappletControllerAccess, injectNappletCsp, injectNappletNamespacePrelude, manifestCache, nappKeyRegistry, normalizeIntentUri, originRegistry, prepareNappletSrcdoc, renderNappletCspMeta, renderNappletNamespacePrelude, resolveShellEnvironment, sessionRegistry };
|
|
1619
|
+
export { type AclCheckEvent, type AclEntry, type AclStore, type AudioManager, type AudioSource, type AuthHooks, type BleHooks, type BrowserDeps, type CapabilityHooks, type CommonHooks, type ConfigHooks, type CryptoHooks, type DmHooks, type HotkeyHooks, type IdentityProxy, type IdentityProxyDeps, type IntentHooks, type KeysProxy, type KeysProxyDeps, type LinkHooks, type ListsHooks, type LlmHooks, type ManifestCache, type ManifestCacheEntry, type MediaProxy, type MediaProxyDeps, type NappletCspDirective, type NappletCspDirectives, type NappletCspOptions, type NappletNamespacePreludeOptions, type NappletSrcdocOptions, type NormalizedIntentUri, type NotifyProxy, type NotifyProxyDeps, type OriginIdentity, type OriginRegistry, type ProxyOriginRegistry, type RelayConfigHooks, type RelayPoolHooks, type RelayPoolLike, type ResourceBytesError, type ResourceBytesManyError, type ResourceBytesManyItem, type ResourceBytesManyRequest, type ResourceBytesManyResult, type ResourceBytesRequest, type ResourceBytesResult, type ResourceCancelRequest, type ResourceErrorCode, type ResourceInbound, type ResourceInfoError, type ResourceInfoRequest, type ResourceInfoResult, type ResourceOutbound, type ResourceRequestId, type SerialHooks, type SessionRegistry, type ShellAdapter, type ShellBridge, type ShellCapabilities, type ShellDomainState, type ShellEnvironment, type ThemeProxy, type ThemeProxyDeps, type UnroutedMessageInfo, type UploadBackendLike, type UploadHooks, type WebrtcHooks, type WindowManagerHooks, type WorkerRelayHooks, type WorkerRelayLike, adaptHooks, audioManager, buildNappletCsp, buildShellCapabilities, createIdentityProxy, createKeysProxy, createMediaProxy, createNotifyProxy, createShellBridge, createThemeProxy, denyNappletControllerAccess, getShellDomainState, injectNappletCsp, injectNappletNamespacePrelude, manifestCache, nappKeyRegistry, normalizeIntentUri, originRegistry, prepareNappletSrcdoc, renderNappletCspMeta, renderNappletNamespacePrelude, resolveShellEnvironment, sessionRegistry };
|
package/dist/index.js
CHANGED
|
@@ -1013,7 +1013,8 @@ var SERVICE_ONLY_DOMAINS = [
|
|
|
1013
1013
|
"dm",
|
|
1014
1014
|
"count",
|
|
1015
1015
|
"fs",
|
|
1016
|
-
"gamepad"
|
|
1016
|
+
"gamepad",
|
|
1017
|
+
"llm"
|
|
1017
1018
|
];
|
|
1018
1019
|
function buildShellCapabilities(hooks) {
|
|
1019
1020
|
const disabled = new Set(hooks.capabilities?.disabledDomains ?? []);
|
|
@@ -1060,10 +1061,18 @@ function isServiceDomainLive(hooks, domain) {
|
|
|
1060
1061
|
return hooks.ble?.isAvailable() === true;
|
|
1061
1062
|
case "webrtc":
|
|
1062
1063
|
return hooks.webrtc?.isAvailable() === true;
|
|
1064
|
+
case "llm":
|
|
1065
|
+
return hooks.llm ? hooks.llm.isAvailable() : true;
|
|
1063
1066
|
default:
|
|
1064
1067
|
return true;
|
|
1065
1068
|
}
|
|
1066
1069
|
}
|
|
1070
|
+
function getShellDomainState(hooks, domain) {
|
|
1071
|
+
if (!buildShellCapabilities(hooks).domains.includes(domain)) return "disabled";
|
|
1072
|
+
const configurable = Reflect.get(hooks, domain);
|
|
1073
|
+
const isConfigured = configurable && typeof configurable === "object" ? configurable.isConfigured : void 0;
|
|
1074
|
+
return typeof isConfigured === "function" && !isConfigured.call(configurable) ? "unconfigured" : "supported";
|
|
1075
|
+
}
|
|
1067
1076
|
function getLiveServices(hooks, domains, disabled) {
|
|
1068
1077
|
const liveDomains = new Set(domains);
|
|
1069
1078
|
return Object.keys(hooks.services ?? {}).filter((name) => {
|
|
@@ -2907,6 +2916,57 @@ function nappletNamespacePrelude(domains, normalizeIntentUri2) {
|
|
|
2907
2916
|
onChanged: (callback) => domainEventHandle("fs.changed", callback, (msg) => msg.change)
|
|
2908
2917
|
};
|
|
2909
2918
|
}
|
|
2919
|
+
function makeLlm() {
|
|
2920
|
+
const asFailure = (value) => {
|
|
2921
|
+
if (!value || typeof value !== "object") return null;
|
|
2922
|
+
const { code, message } = value;
|
|
2923
|
+
return typeof code === "string" && typeof message === "string" ? { code, message } : null;
|
|
2924
|
+
};
|
|
2925
|
+
const failure = (entry) => Object.assign(new Error(entry.message), { code: entry.code });
|
|
2926
|
+
function call(type, payload, field, options = {}) {
|
|
2927
|
+
const requestId = id();
|
|
2928
|
+
const promise = new Promise((resolve, reject) => {
|
|
2929
|
+
let nextSequence = 0;
|
|
2930
|
+
const onAbort = () => {
|
|
2931
|
+
post({ type: "llm.cancel", id: id(), requestId });
|
|
2932
|
+
};
|
|
2933
|
+
const off = listen((event) => {
|
|
2934
|
+
if (!isParentMessage(event)) return;
|
|
2935
|
+
const msg = event.data;
|
|
2936
|
+
if (typeof msg !== "object" || msg === null) return;
|
|
2937
|
+
if (type === "llm.generate" && msg.type === "llm.delta" && msg.requestId === requestId) {
|
|
2938
|
+
if (msg.sequence !== nextSequence || typeof msg.text !== "string") return;
|
|
2939
|
+
nextSequence += 1;
|
|
2940
|
+
options.onDelta?.({ requestId, sequence: msg.sequence, text: msg.text });
|
|
2941
|
+
return;
|
|
2942
|
+
}
|
|
2943
|
+
if (msg.type !== `${type}.result` || msg.id !== requestId) return;
|
|
2944
|
+
off();
|
|
2945
|
+
options.signal?.removeEventListener("abort", onAbort);
|
|
2946
|
+
const error = asFailure(msg.error);
|
|
2947
|
+
if (error) {
|
|
2948
|
+
reject(failure(error));
|
|
2949
|
+
return;
|
|
2950
|
+
}
|
|
2951
|
+
if (!Object.prototype.hasOwnProperty.call(msg, field)) {
|
|
2952
|
+
reject(failure({ code: "provider-error", message: `${type}.result missing ${field}` }));
|
|
2953
|
+
return;
|
|
2954
|
+
}
|
|
2955
|
+
resolve(msg[field]);
|
|
2956
|
+
});
|
|
2957
|
+
post({ type, id: requestId, ...payload });
|
|
2958
|
+
if (options.signal?.aborted) onAbort();
|
|
2959
|
+
else options.signal?.addEventListener("abort", onAbort, { once: true });
|
|
2960
|
+
});
|
|
2961
|
+
return Object.assign(promise, { requestId });
|
|
2962
|
+
}
|
|
2963
|
+
return {
|
|
2964
|
+
select: (requirements) => call("llm.select", requirements === void 0 ? {} : { requirements }, "model"),
|
|
2965
|
+
describe: (handle) => call("llm.describe", { handle }, "model"),
|
|
2966
|
+
generate: (request2, options) => call("llm.generate", { request: request2 }, "result", options ?? {}),
|
|
2967
|
+
cancel: (requestId) => call("llm.cancel", { requestId }, "cancelled")
|
|
2968
|
+
};
|
|
2969
|
+
}
|
|
2910
2970
|
const intentDelivery = allowed.has("intent") ? makeIntentDelivery() : void 0;
|
|
2911
2971
|
const shell = allowed.has("shell") ? makeShell() : void 0;
|
|
2912
2972
|
let gamepad;
|
|
@@ -2981,6 +3041,8 @@ function nappletNamespacePrelude(domains, normalizeIntentUri2) {
|
|
|
2981
3041
|
return makeDm();
|
|
2982
3042
|
case "fs":
|
|
2983
3043
|
return makeFs();
|
|
3044
|
+
case "llm":
|
|
3045
|
+
return makeLlm();
|
|
2984
3046
|
default:
|
|
2985
3047
|
return {};
|
|
2986
3048
|
}
|
|
@@ -3251,6 +3313,7 @@ export {
|
|
|
3251
3313
|
createThemeProxy,
|
|
3252
3314
|
denyNappletControllerAccess,
|
|
3253
3315
|
formatDenialReason,
|
|
3316
|
+
getShellDomainState,
|
|
3254
3317
|
injectNappletCsp,
|
|
3255
3318
|
injectNappletNamespacePrelude,
|
|
3256
3319
|
manifestCache,
|