@fungi.computer/nacre 0.1.4 → 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/dist/website-channels.d.ts +102 -0
- package/dist/website-channels.js +119 -0
- package/docs/api/README.md +1 -0
- package/docs/api/command-host.md +40 -3
- package/docs/api/index.md +33 -2
- package/docs/api/keys.md +1 -1
- package/docs/api/shell-module.md +61 -0
- package/docs/api/website-channels.md +382 -0
- package/docs/api/window-manager.md +44 -1
- package/package.json +5 -1
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What a host's owner settings read about a website chat channel: the web
|
|
3
|
+
* origin grammar both the Oyster and Hub enforce and the Settings form checks,
|
|
4
|
+
* and the wire shapes of a website, its conversations and a transcript.
|
|
5
|
+
*/
|
|
6
|
+
import { z } from "zod";
|
|
7
|
+
/** One refused-origin reason, keyed for callers that name it to a person. */
|
|
8
|
+
export type WebOriginProblem = "tooLong" | "notUrl" | "insecure" | "credentials" | "path" | "notAllowed";
|
|
9
|
+
/** The reason a refused origin's first issue names. */
|
|
10
|
+
export declare function webOriginProblem(error: z.ZodError): WebOriginProblem;
|
|
11
|
+
/**
|
|
12
|
+
* Parse one allowed embed origin: exact `https://host[:port]`, one leading
|
|
13
|
+
* `*.` subdomain level, or `http` only on loopback for development. Paths,
|
|
14
|
+
* credentials, queries and bare wildcards are rejected. The Hub stores and
|
|
15
|
+
* enforces these; Settings runs the same schema before it sends one.
|
|
16
|
+
*/
|
|
17
|
+
export declare const webOriginSchema: z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>;
|
|
18
|
+
/** How a website is found and where it may appear. */
|
|
19
|
+
export type WebsiteSelector = {
|
|
20
|
+
/** Websites are the web provider's bindings. */
|
|
21
|
+
provider: "web";
|
|
22
|
+
/** The public key in the pasted snippet. */
|
|
23
|
+
siteKey: string;
|
|
24
|
+
/** The origins allowed to embed the chat. */
|
|
25
|
+
origins: string[];
|
|
26
|
+
/** The owner's accent colour, `#rrggbb`. */
|
|
27
|
+
accent?: string | undefined;
|
|
28
|
+
/** Visitors must pass Cloudflare Turnstile before they can chat. */
|
|
29
|
+
turnstile?: boolean | undefined;
|
|
30
|
+
};
|
|
31
|
+
/** One website as an owner's Settings read it. */
|
|
32
|
+
export type WebsiteSite = {
|
|
33
|
+
/** The binding's identity on its host. */
|
|
34
|
+
bindingId: string;
|
|
35
|
+
/** The Agent visitors chat with, named by its id in the host's directory. */
|
|
36
|
+
agentId: string;
|
|
37
|
+
/** How the embed finds the website and where it may appear. */
|
|
38
|
+
selector: WebsiteSelector;
|
|
39
|
+
/** Whether visitors can chat now. */
|
|
40
|
+
lifecycle: "active" | "suspended";
|
|
41
|
+
/** The version an edit must name; it advances on every edit. */
|
|
42
|
+
authorityVersion: number;
|
|
43
|
+
/** The owner's brief for this website; visitors never see it. */
|
|
44
|
+
persona: string;
|
|
45
|
+
};
|
|
46
|
+
/** One website as an owner's Settings read it. */
|
|
47
|
+
export declare const websiteSiteSchema: z.ZodType<WebsiteSite>;
|
|
48
|
+
/** One conversation of a website, newest first. */
|
|
49
|
+
export type WebsiteConversation = {
|
|
50
|
+
/** The conversation's Session on the website's Agent. */
|
|
51
|
+
sessionId: string;
|
|
52
|
+
/** A short label for the visitor. */
|
|
53
|
+
label: string;
|
|
54
|
+
/** When the visitor or the Agent last wrote, in epoch milliseconds. */
|
|
55
|
+
lastEventAt: number;
|
|
56
|
+
};
|
|
57
|
+
/** One conversation of a website. */
|
|
58
|
+
export declare const websiteConversationSchema: z.ZodType<WebsiteConversation>;
|
|
59
|
+
/** One line of a website conversation as its owner reads it. */
|
|
60
|
+
export type TranscriptLine = {
|
|
61
|
+
/** Who wrote the line. */
|
|
62
|
+
role: "visitor" | "agent";
|
|
63
|
+
/** What was written. */
|
|
64
|
+
text: string;
|
|
65
|
+
};
|
|
66
|
+
/** An owner's read of one website conversation. */
|
|
67
|
+
export type WebsiteTranscript = {
|
|
68
|
+
/** The conversation's Session on the website's Agent. */
|
|
69
|
+
sessionId: string;
|
|
70
|
+
/** A short label for the visitor. */
|
|
71
|
+
label: string;
|
|
72
|
+
/** What visitor and Agent said, oldest first. */
|
|
73
|
+
lines: TranscriptLine[];
|
|
74
|
+
};
|
|
75
|
+
/** An owner's read of one website conversation. */
|
|
76
|
+
export declare const websiteTranscriptSchema: z.ZodType<WebsiteTranscript>;
|
|
77
|
+
/** One content part of a message; only text parts are read. */
|
|
78
|
+
export type TranscriptPart = {
|
|
79
|
+
/** The part's kind; `text` parts carry the words. */
|
|
80
|
+
type: string;
|
|
81
|
+
/** The words of a text part. */
|
|
82
|
+
text?: string | undefined;
|
|
83
|
+
};
|
|
84
|
+
/**
|
|
85
|
+
* The part of a Session message a transcript reads: who said it and what the
|
|
86
|
+
* content holds. A Shiitake message satisfies it without this package knowing
|
|
87
|
+
* Shiitake.
|
|
88
|
+
*/
|
|
89
|
+
export type TranscriptMessage = {
|
|
90
|
+
/** The model message. */
|
|
91
|
+
value: {
|
|
92
|
+
/** `user` for a visitor's prompt, `assistant` for the Agent's reply. */
|
|
93
|
+
role: string;
|
|
94
|
+
/** Plain text, or content parts of which only text parts are read. */
|
|
95
|
+
content: string | readonly TranscriptPart[];
|
|
96
|
+
};
|
|
97
|
+
};
|
|
98
|
+
/**
|
|
99
|
+
* The visible line of one message: a visitor's prompt or the Agent's reply.
|
|
100
|
+
* Tool traffic and empty turns are not conversation, so they have no line.
|
|
101
|
+
*/
|
|
102
|
+
export declare function transcriptLine(message: TranscriptMessage): TranscriptLine | null;
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What a host's owner settings read about a website chat channel: the web
|
|
3
|
+
* origin grammar both the Oyster and Hub enforce and the Settings form checks,
|
|
4
|
+
* and the wire shapes of a website, its conversations and a transcript.
|
|
5
|
+
*/
|
|
6
|
+
import { z } from "zod";
|
|
7
|
+
const loopbackHosts = new Set(["localhost", "127.0.0.1", "[::1]"]);
|
|
8
|
+
const webOriginProblems = {
|
|
9
|
+
tooLong: "Origin is too long",
|
|
10
|
+
notUrl: "Origin is not a URL",
|
|
11
|
+
insecure: "Origin must use https",
|
|
12
|
+
credentials: "Origin must not carry credentials",
|
|
13
|
+
path: "Origin must not carry a path, query or fragment",
|
|
14
|
+
notAllowed: "Origin is not allowed",
|
|
15
|
+
};
|
|
16
|
+
const webOriginProblemNames = [
|
|
17
|
+
"tooLong",
|
|
18
|
+
"notUrl",
|
|
19
|
+
"insecure",
|
|
20
|
+
"credentials",
|
|
21
|
+
"path",
|
|
22
|
+
"notAllowed",
|
|
23
|
+
];
|
|
24
|
+
/** The reason a refused origin's first issue names. */
|
|
25
|
+
export function webOriginProblem(error) {
|
|
26
|
+
const message = error.issues[0]?.message;
|
|
27
|
+
return (webOriginProblemNames.find((problem) => webOriginProblems[problem] === message) ?? "notAllowed");
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Parse one allowed embed origin: exact `https://host[:port]`, one leading
|
|
31
|
+
* `*.` subdomain level, or `http` only on loopback for development. Paths,
|
|
32
|
+
* credentials, queries and bare wildcards are rejected. The Hub stores and
|
|
33
|
+
* enforces these; Settings runs the same schema before it sends one.
|
|
34
|
+
*/
|
|
35
|
+
export const webOriginSchema = z
|
|
36
|
+
.string()
|
|
37
|
+
.max(253, webOriginProblems.tooLong)
|
|
38
|
+
.transform((value, context) => {
|
|
39
|
+
const refuse = (problem) => {
|
|
40
|
+
context.addIssue({ code: "custom", message: webOriginProblems[problem] });
|
|
41
|
+
return z.NEVER;
|
|
42
|
+
};
|
|
43
|
+
const wildcard = value.startsWith("https://*.");
|
|
44
|
+
const candidate = wildcard ? value.replace("*.", "") : value;
|
|
45
|
+
let url;
|
|
46
|
+
try {
|
|
47
|
+
url = new URL(candidate);
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
return refuse("notUrl");
|
|
51
|
+
}
|
|
52
|
+
const secure = url.protocol === "https:" ||
|
|
53
|
+
(url.protocol === "http:" &&
|
|
54
|
+
!wildcard &&
|
|
55
|
+
loopbackHosts.has(url.hostname));
|
|
56
|
+
if (!secure)
|
|
57
|
+
return refuse("insecure");
|
|
58
|
+
if (url.username !== "" || url.password !== "")
|
|
59
|
+
return refuse("credentials");
|
|
60
|
+
if (url.pathname !== "/" || url.search !== "" || url.hash !== "")
|
|
61
|
+
return refuse("path");
|
|
62
|
+
if (url.origin !== candidate.toLowerCase() ||
|
|
63
|
+
url.hostname.includes("*") ||
|
|
64
|
+
(wildcard && url.hostname.split(".").length < 2))
|
|
65
|
+
return refuse("notAllowed");
|
|
66
|
+
return wildcard ? `https://*.${url.host}` : url.origin;
|
|
67
|
+
});
|
|
68
|
+
const identity = z.string().min(1).max(256);
|
|
69
|
+
/** One website as an owner's Settings read it. */
|
|
70
|
+
export const websiteSiteSchema = z.object({
|
|
71
|
+
bindingId: identity,
|
|
72
|
+
agentId: identity,
|
|
73
|
+
selector: z.object({
|
|
74
|
+
provider: z.literal("web"),
|
|
75
|
+
siteKey: identity,
|
|
76
|
+
origins: z.array(z.string()).min(1).max(16),
|
|
77
|
+
accent: z.string().optional(),
|
|
78
|
+
turnstile: z.boolean().optional(),
|
|
79
|
+
}),
|
|
80
|
+
lifecycle: z.enum(["active", "suspended"]),
|
|
81
|
+
authorityVersion: z.number().int().positive(),
|
|
82
|
+
persona: z.string().max(4_000),
|
|
83
|
+
});
|
|
84
|
+
/** One conversation of a website. */
|
|
85
|
+
export const websiteConversationSchema = z.object({
|
|
86
|
+
sessionId: identity,
|
|
87
|
+
label: z.string(),
|
|
88
|
+
lastEventAt: z.number().int().nonnegative(),
|
|
89
|
+
});
|
|
90
|
+
/** An owner's read of one website conversation. */
|
|
91
|
+
export const websiteTranscriptSchema = z.strictObject({
|
|
92
|
+
sessionId: identity,
|
|
93
|
+
label: z.string(),
|
|
94
|
+
lines: z.array(z.strictObject({
|
|
95
|
+
role: z.enum(["visitor", "agent"]),
|
|
96
|
+
text: z.string(),
|
|
97
|
+
})),
|
|
98
|
+
});
|
|
99
|
+
/**
|
|
100
|
+
* The visible line of one message: a visitor's prompt or the Agent's reply.
|
|
101
|
+
* Tool traffic and empty turns are not conversation, so they have no line.
|
|
102
|
+
*/
|
|
103
|
+
export function transcriptLine(message) {
|
|
104
|
+
const { role, content } = message.value;
|
|
105
|
+
if (role !== "user" && role !== "assistant")
|
|
106
|
+
return null;
|
|
107
|
+
const text = hasParts(content)
|
|
108
|
+
? content
|
|
109
|
+
.flatMap((part) => (part.type === "text" ? [part.text ?? ""] : []))
|
|
110
|
+
.join("")
|
|
111
|
+
: content;
|
|
112
|
+
if (text.trim() === "")
|
|
113
|
+
return null;
|
|
114
|
+
return { role: role === "user" ? "visitor" : "agent", text };
|
|
115
|
+
}
|
|
116
|
+
/** `Array.isArray` does not narrow a readonly array out of the union. */
|
|
117
|
+
function hasParts(content) {
|
|
118
|
+
return Array.isArray(content);
|
|
119
|
+
}
|
package/docs/api/README.md
CHANGED
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
| [index](index.md) | - |
|
|
17
17
|
| [keys](keys.md) | - |
|
|
18
18
|
| [shell-module](shell-module.md) | - |
|
|
19
|
+
| [website-channels](website-channels.md) | - |
|
|
19
20
|
| [window-manager](window-manager.md) | - |
|
|
20
21
|
| [workbench-directory](workbench-directory.md) | - |
|
|
21
22
|
| [workbench](workbench.md) | - |
|
package/docs/api/command-host.md
CHANGED
|
@@ -80,6 +80,19 @@ grammar stays with its owner, which hands rows of this shape.
|
|
|
80
80
|
|
|
81
81
|
---
|
|
82
82
|
|
|
83
|
+
### AppCommandTarget
|
|
84
|
+
|
|
85
|
+
```ts
|
|
86
|
+
type AppCommandTarget = Readonly<{
|
|
87
|
+
surfaceId: string;
|
|
88
|
+
commandId: string;
|
|
89
|
+
}>;
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
One App command, named by its surface and its declared command id.
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
83
96
|
### AppSurfaceCommandMount
|
|
84
97
|
|
|
85
98
|
```ts
|
|
@@ -98,8 +111,8 @@ The command side of one mounted App's host handlers.
|
|
|
98
111
|
|
|
99
112
|
```ts
|
|
100
113
|
type PaneCommands = Readonly<{
|
|
101
|
-
|
|
102
|
-
contribute: (commands) => WhistleContributionLease;
|
|
114
|
+
command: (id, group?) => WhistleCommandKey;
|
|
115
|
+
contribute: (commands, group?) => WhistleContributionLease;
|
|
103
116
|
execute: WhistleRuntime["execute"];
|
|
104
117
|
snapshot: WhistleRuntime["snapshot"];
|
|
105
118
|
subscribe: WhistleRuntime["subscribe"];
|
|
@@ -133,9 +146,10 @@ type AppSurfaceCommandHost = Readonly<{
|
|
|
133
146
|
focus: (mountId) => void;
|
|
134
147
|
registerShellCommands: (commands) => () => void;
|
|
135
148
|
registerDirectoryCommands: (commands, run) => () => void;
|
|
149
|
+
appCommand: (row) => AppCommandTarget | undefined;
|
|
136
150
|
menu: () => readonly WhistleMenuProjection[];
|
|
137
151
|
active: () => WhistleSnapshot;
|
|
138
|
-
execute: (
|
|
152
|
+
execute: (command, input) => Promise<WhistleExecutionOutcome>;
|
|
139
153
|
snapshot: () => WhistleSnapshot;
|
|
140
154
|
subscribe: (listener) => () => void;
|
|
141
155
|
dispose: () => void;
|
|
@@ -198,6 +212,29 @@ Select the shell command-palette chord from the embedding browser user agent.
|
|
|
198
212
|
|
|
199
213
|
---
|
|
200
214
|
|
|
215
|
+
### appSurfaceCommandKey()
|
|
216
|
+
|
|
217
|
+
```ts
|
|
218
|
+
function appSurfaceCommandKey(target): WhistleCommandKey;
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
The typed Whistle identity of a command a mounted App surface contributed: each
|
|
222
|
+
mounted surface owns the Whistle namespace named by its surface id.
|
|
223
|
+
|
|
224
|
+
#### Parameters
|
|
225
|
+
|
|
226
|
+
| Parameter | Type | Description |
|
|
227
|
+
| --------- | --------------------------------------- | -------------------------------------------- |
|
|
228
|
+
| `target` | [`AppCommandTarget`](#appcommandtarget) | The App surface and its declared command id. |
|
|
229
|
+
|
|
230
|
+
#### Returns
|
|
231
|
+
|
|
232
|
+
`WhistleCommandKey`
|
|
233
|
+
|
|
234
|
+
The key every snapshot row of that command carries as `command`.
|
|
235
|
+
|
|
236
|
+
---
|
|
237
|
+
|
|
201
238
|
### createAppSurfaceCommandHost()
|
|
202
239
|
|
|
203
240
|
```ts
|
package/docs/api/index.md
CHANGED
|
@@ -418,7 +418,8 @@ The shell unmounted: stop notifying its callbacks.
|
|
|
418
418
|
mount(
|
|
419
419
|
container,
|
|
420
420
|
input,
|
|
421
|
-
events
|
|
421
|
+
events,
|
|
422
|
+
signal
|
|
422
423
|
): Promise<WorkbenchChildHandle>;
|
|
423
424
|
```
|
|
424
425
|
|
|
@@ -433,6 +434,7 @@ slot in that App's window. The host never moves the child: the shell keeps
|
|
|
433
434
|
| `container` | `HTMLElement` |
|
|
434
435
|
| `input` | [`WorkbenchChildLaunch`](#workbenchchildlaunch) |
|
|
435
436
|
| `events` | [`TeamWorkbenchChildEvents`](#teamworkbenchchildevents) |
|
|
437
|
+
| `signal` | `AbortSignal` |
|
|
436
438
|
|
|
437
439
|
###### Returns
|
|
438
440
|
|
|
@@ -476,6 +478,7 @@ TeamWorkbenchHostHandle.reportAgentSessionSelection;
|
|
|
476
478
|
```ts
|
|
477
479
|
type TeamWorkbenchChildEvents = WorkbenchChildEvents &
|
|
478
480
|
Readonly<{
|
|
481
|
+
onDeliveryPending?: () => void;
|
|
479
482
|
onAgentSessionSelection: (selection) => Promise<void>;
|
|
480
483
|
}>;
|
|
481
484
|
```
|
|
@@ -662,7 +665,8 @@ while covered.
|
|
|
662
665
|
mount(
|
|
663
666
|
container,
|
|
664
667
|
input,
|
|
665
|
-
events
|
|
668
|
+
events,
|
|
669
|
+
signal
|
|
666
670
|
): Promise<WorkbenchChildHandle>;
|
|
667
671
|
```
|
|
668
672
|
|
|
@@ -677,6 +681,7 @@ slot in that App's window. The host never moves the child: the shell keeps
|
|
|
677
681
|
| `container` | `HTMLElement` |
|
|
678
682
|
| `input` | [`WorkbenchChildLaunch`](#workbenchchildlaunch) |
|
|
679
683
|
| `events` | [`TeamWorkbenchChildEvents`](#teamworkbenchchildevents) |
|
|
684
|
+
| `signal` | `AbortSignal` |
|
|
680
685
|
|
|
681
686
|
###### Returns
|
|
682
687
|
|
|
@@ -1606,6 +1611,18 @@ Re-exports
|
|
|
1606
1611
|
|
|
1607
1612
|
---
|
|
1608
1613
|
|
|
1614
|
+
### AppCommandTarget
|
|
1615
|
+
|
|
1616
|
+
Re-exports [AppCommandTarget](command-host.md#appcommandtarget)
|
|
1617
|
+
|
|
1618
|
+
---
|
|
1619
|
+
|
|
1620
|
+
### appSurfaceCommandKey
|
|
1621
|
+
|
|
1622
|
+
Re-exports [appSurfaceCommandKey](command-host.md#appsurfacecommandkey)
|
|
1623
|
+
|
|
1624
|
+
---
|
|
1625
|
+
|
|
1609
1626
|
### appDirectorySourceId
|
|
1610
1627
|
|
|
1611
1628
|
Re-exports [appDirectorySourceId](command-host.md#appdirectorysourceid)
|
|
@@ -1795,6 +1812,20 @@ Re-exports [installShellKeys](keys.md#installshellkeys)
|
|
|
1795
1812
|
|
|
1796
1813
|
---
|
|
1797
1814
|
|
|
1815
|
+
### APP\_SURFACE\_DOCUMENT\_TIMEOUT\_MS
|
|
1816
|
+
|
|
1817
|
+
Re-exports
|
|
1818
|
+
[APP_SURFACE_DOCUMENT_TIMEOUT_MS](window-manager.md#app_surface_document_timeout_ms)
|
|
1819
|
+
|
|
1820
|
+
---
|
|
1821
|
+
|
|
1822
|
+
### prepareWithDeliveryRetry
|
|
1823
|
+
|
|
1824
|
+
Re-exports
|
|
1825
|
+
[prepareWithDeliveryRetry](window-manager.md#preparewithdeliveryretry)
|
|
1826
|
+
|
|
1827
|
+
---
|
|
1828
|
+
|
|
1798
1829
|
### WindowLaunch
|
|
1799
1830
|
|
|
1800
1831
|
Re-exports [WindowLaunch](window-manager.md#windowlaunch)
|
package/docs/api/keys.md
CHANGED
|
@@ -58,7 +58,7 @@ One key offered after the leader chord, with the command it runs.
|
|
|
58
58
|
type ShellKeyHost = Readonly<{
|
|
59
59
|
active: () => WhistleSnapshot;
|
|
60
60
|
subscribe: (listener) => () => void;
|
|
61
|
-
execute: (
|
|
61
|
+
execute: (command, input) => Promise<WhistleExecutionOutcome>;
|
|
62
62
|
}>;
|
|
63
63
|
```
|
|
64
64
|
|
package/docs/api/shell-module.md
CHANGED
|
@@ -81,6 +81,67 @@ Always ShellModuleError.
|
|
|
81
81
|
Error.name;
|
|
82
82
|
```
|
|
83
83
|
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
### ShellModuleUnavailable
|
|
87
|
+
|
|
88
|
+
The picked shell's module could not be fetched or evaluated. A browser keeps a
|
|
89
|
+
failed module fetch for the life of the document, so only loading the page again
|
|
90
|
+
can recover it.
|
|
91
|
+
|
|
92
|
+
#### Extends
|
|
93
|
+
|
|
94
|
+
- `Error`
|
|
95
|
+
|
|
96
|
+
#### Constructors
|
|
97
|
+
|
|
98
|
+
##### Constructor
|
|
99
|
+
|
|
100
|
+
```ts
|
|
101
|
+
new ShellModuleUnavailable(moduleUrl, options): ShellModuleUnavailable;
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
###### Parameters
|
|
105
|
+
|
|
106
|
+
| Parameter | Type | Description |
|
|
107
|
+
| ----------- | -------------- | ----------------------------------- |
|
|
108
|
+
| `moduleUrl` | `string` | The module URL that could not load. |
|
|
109
|
+
| `options` | `ErrorOptions` | - |
|
|
110
|
+
|
|
111
|
+
###### Returns
|
|
112
|
+
|
|
113
|
+
[`ShellModuleUnavailable`](#shellmoduleunavailable)
|
|
114
|
+
|
|
115
|
+
###### Overrides
|
|
116
|
+
|
|
117
|
+
```ts
|
|
118
|
+
Error.constructor;
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
#### Properties
|
|
122
|
+
|
|
123
|
+
##### name
|
|
124
|
+
|
|
125
|
+
```ts
|
|
126
|
+
readonly name: "ShellModuleUnavailable" = "ShellModuleUnavailable";
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
Always ShellModuleUnavailable.
|
|
130
|
+
|
|
131
|
+
###### Overrides
|
|
132
|
+
|
|
133
|
+
```ts
|
|
134
|
+
Error.name;
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
##### moduleUrl
|
|
138
|
+
|
|
139
|
+
```ts
|
|
140
|
+
readonly moduleUrl: string;
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
The module URL that could not load.
|
|
144
|
+
|
|
84
145
|
## Type Aliases
|
|
85
146
|
|
|
86
147
|
### ShellMountInput
|
|
@@ -0,0 +1,382 @@
|
|
|
1
|
+
<!-- Generated by Botanical API docs (TypeDoc + typedoc-plugin-markdown). Do not edit. -->
|
|
2
|
+
|
|
3
|
+
[**@fungi.computer/nacre**](README.md)
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
[@fungi.computer/nacre](README.md) / website-channels
|
|
8
|
+
|
|
9
|
+
# website-channels
|
|
10
|
+
|
|
11
|
+
## Type Aliases
|
|
12
|
+
|
|
13
|
+
### WebOriginProblem
|
|
14
|
+
|
|
15
|
+
```ts
|
|
16
|
+
type WebOriginProblem =
|
|
17
|
+
"tooLong" | "notUrl" | "insecure" | "credentials" | "path" | "notAllowed";
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
One refused-origin reason, keyed for callers that name it to a person.
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
### WebsiteSelector
|
|
25
|
+
|
|
26
|
+
```ts
|
|
27
|
+
type WebsiteSelector = object;
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
How a website is found and where it may appear.
|
|
31
|
+
|
|
32
|
+
#### Properties
|
|
33
|
+
|
|
34
|
+
##### provider
|
|
35
|
+
|
|
36
|
+
```ts
|
|
37
|
+
provider: "web";
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Websites are the web provider's bindings.
|
|
41
|
+
|
|
42
|
+
##### siteKey
|
|
43
|
+
|
|
44
|
+
```ts
|
|
45
|
+
siteKey: string;
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
The public key in the pasted snippet.
|
|
49
|
+
|
|
50
|
+
##### origins
|
|
51
|
+
|
|
52
|
+
```ts
|
|
53
|
+
origins: string[];
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
The origins allowed to embed the chat.
|
|
57
|
+
|
|
58
|
+
##### accent?
|
|
59
|
+
|
|
60
|
+
```ts
|
|
61
|
+
optional accent?: string;
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
The owner's accent colour, `#rrggbb`.
|
|
65
|
+
|
|
66
|
+
##### turnstile?
|
|
67
|
+
|
|
68
|
+
```ts
|
|
69
|
+
optional turnstile?: boolean;
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Visitors must pass Cloudflare Turnstile before they can chat.
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
### WebsiteSite
|
|
77
|
+
|
|
78
|
+
```ts
|
|
79
|
+
type WebsiteSite = object;
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
One website as an owner's Settings read it.
|
|
83
|
+
|
|
84
|
+
#### Properties
|
|
85
|
+
|
|
86
|
+
##### bindingId
|
|
87
|
+
|
|
88
|
+
```ts
|
|
89
|
+
bindingId: string;
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
The binding's identity on its host.
|
|
93
|
+
|
|
94
|
+
##### agentId
|
|
95
|
+
|
|
96
|
+
```ts
|
|
97
|
+
agentId: string;
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
The Agent visitors chat with, named by its id in the host's directory.
|
|
101
|
+
|
|
102
|
+
##### selector
|
|
103
|
+
|
|
104
|
+
```ts
|
|
105
|
+
selector: WebsiteSelector;
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
How the embed finds the website and where it may appear.
|
|
109
|
+
|
|
110
|
+
##### lifecycle
|
|
111
|
+
|
|
112
|
+
```ts
|
|
113
|
+
lifecycle: "active" | "suspended";
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
Whether visitors can chat now.
|
|
117
|
+
|
|
118
|
+
##### authorityVersion
|
|
119
|
+
|
|
120
|
+
```ts
|
|
121
|
+
authorityVersion: number;
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
The version an edit must name; it advances on every edit.
|
|
125
|
+
|
|
126
|
+
##### persona
|
|
127
|
+
|
|
128
|
+
```ts
|
|
129
|
+
persona: string;
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
The owner's brief for this website; visitors never see it.
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
### WebsiteConversation
|
|
137
|
+
|
|
138
|
+
```ts
|
|
139
|
+
type WebsiteConversation = object;
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
One conversation of a website, newest first.
|
|
143
|
+
|
|
144
|
+
#### Properties
|
|
145
|
+
|
|
146
|
+
##### sessionId
|
|
147
|
+
|
|
148
|
+
```ts
|
|
149
|
+
sessionId: string;
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
The conversation's Session on the website's Agent.
|
|
153
|
+
|
|
154
|
+
##### label
|
|
155
|
+
|
|
156
|
+
```ts
|
|
157
|
+
label: string;
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
A short label for the visitor.
|
|
161
|
+
|
|
162
|
+
##### lastEventAt
|
|
163
|
+
|
|
164
|
+
```ts
|
|
165
|
+
lastEventAt: number;
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
When the visitor or the Agent last wrote, in epoch milliseconds.
|
|
169
|
+
|
|
170
|
+
---
|
|
171
|
+
|
|
172
|
+
### TranscriptLine
|
|
173
|
+
|
|
174
|
+
```ts
|
|
175
|
+
type TranscriptLine = object;
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
One line of a website conversation as its owner reads it.
|
|
179
|
+
|
|
180
|
+
#### Properties
|
|
181
|
+
|
|
182
|
+
##### role
|
|
183
|
+
|
|
184
|
+
```ts
|
|
185
|
+
role: "visitor" | "agent";
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
Who wrote the line.
|
|
189
|
+
|
|
190
|
+
##### text
|
|
191
|
+
|
|
192
|
+
```ts
|
|
193
|
+
text: string;
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
What was written.
|
|
197
|
+
|
|
198
|
+
---
|
|
199
|
+
|
|
200
|
+
### WebsiteTranscript
|
|
201
|
+
|
|
202
|
+
```ts
|
|
203
|
+
type WebsiteTranscript = object;
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
An owner's read of one website conversation.
|
|
207
|
+
|
|
208
|
+
#### Properties
|
|
209
|
+
|
|
210
|
+
##### sessionId
|
|
211
|
+
|
|
212
|
+
```ts
|
|
213
|
+
sessionId: string;
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
The conversation's Session on the website's Agent.
|
|
217
|
+
|
|
218
|
+
##### label
|
|
219
|
+
|
|
220
|
+
```ts
|
|
221
|
+
label: string;
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
A short label for the visitor.
|
|
225
|
+
|
|
226
|
+
##### lines
|
|
227
|
+
|
|
228
|
+
```ts
|
|
229
|
+
lines: TranscriptLine[];
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
What visitor and Agent said, oldest first.
|
|
233
|
+
|
|
234
|
+
---
|
|
235
|
+
|
|
236
|
+
### TranscriptPart
|
|
237
|
+
|
|
238
|
+
```ts
|
|
239
|
+
type TranscriptPart = object;
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
One content part of a message; only text parts are read.
|
|
243
|
+
|
|
244
|
+
#### Properties
|
|
245
|
+
|
|
246
|
+
##### type
|
|
247
|
+
|
|
248
|
+
```ts
|
|
249
|
+
type: string;
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
The part's kind; `text` parts carry the words.
|
|
253
|
+
|
|
254
|
+
##### text?
|
|
255
|
+
|
|
256
|
+
```ts
|
|
257
|
+
optional text?: string;
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
The words of a text part.
|
|
261
|
+
|
|
262
|
+
---
|
|
263
|
+
|
|
264
|
+
### TranscriptMessage
|
|
265
|
+
|
|
266
|
+
```ts
|
|
267
|
+
type TranscriptMessage = object;
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
The part of a Session message a transcript reads: who said it and what the
|
|
271
|
+
content holds. A Shiitake message satisfies it without this package knowing
|
|
272
|
+
Shiitake.
|
|
273
|
+
|
|
274
|
+
#### Properties
|
|
275
|
+
|
|
276
|
+
##### value
|
|
277
|
+
|
|
278
|
+
```ts
|
|
279
|
+
value: object;
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
The model message.
|
|
283
|
+
|
|
284
|
+
###### role
|
|
285
|
+
|
|
286
|
+
```ts
|
|
287
|
+
role: string;
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
`user` for a visitor's prompt, `assistant` for the Agent's reply.
|
|
291
|
+
|
|
292
|
+
###### content
|
|
293
|
+
|
|
294
|
+
```ts
|
|
295
|
+
content: string | readonly TranscriptPart[];
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
Plain text, or content parts of which only text parts are read.
|
|
299
|
+
|
|
300
|
+
## Variables
|
|
301
|
+
|
|
302
|
+
### webOriginSchema
|
|
303
|
+
|
|
304
|
+
```ts
|
|
305
|
+
const webOriginSchema: ZodPipe<ZodString, ZodTransform<string, string>>;
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
Parse one allowed embed origin: exact `https://host[:port]`, one leading `*.`
|
|
309
|
+
subdomain level, or `http` only on loopback for development. Paths, credentials,
|
|
310
|
+
queries and bare wildcards are rejected. The Hub stores and enforces these;
|
|
311
|
+
Settings runs the same schema before it sends one.
|
|
312
|
+
|
|
313
|
+
---
|
|
314
|
+
|
|
315
|
+
### websiteSiteSchema
|
|
316
|
+
|
|
317
|
+
```ts
|
|
318
|
+
const websiteSiteSchema: z.ZodType<WebsiteSite>;
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
One website as an owner's Settings read it.
|
|
322
|
+
|
|
323
|
+
---
|
|
324
|
+
|
|
325
|
+
### websiteConversationSchema
|
|
326
|
+
|
|
327
|
+
```ts
|
|
328
|
+
const websiteConversationSchema: z.ZodType<WebsiteConversation>;
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
One conversation of a website.
|
|
332
|
+
|
|
333
|
+
---
|
|
334
|
+
|
|
335
|
+
### websiteTranscriptSchema
|
|
336
|
+
|
|
337
|
+
```ts
|
|
338
|
+
const websiteTranscriptSchema: z.ZodType<WebsiteTranscript>;
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
An owner's read of one website conversation.
|
|
342
|
+
|
|
343
|
+
## Functions
|
|
344
|
+
|
|
345
|
+
### webOriginProblem()
|
|
346
|
+
|
|
347
|
+
```ts
|
|
348
|
+
function webOriginProblem(error): WebOriginProblem;
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
The reason a refused origin's first issue names.
|
|
352
|
+
|
|
353
|
+
#### Parameters
|
|
354
|
+
|
|
355
|
+
| Parameter | Type |
|
|
356
|
+
| --------- | ---------- |
|
|
357
|
+
| `error` | `ZodError` |
|
|
358
|
+
|
|
359
|
+
#### Returns
|
|
360
|
+
|
|
361
|
+
[`WebOriginProblem`](#weboriginproblem)
|
|
362
|
+
|
|
363
|
+
---
|
|
364
|
+
|
|
365
|
+
### transcriptLine()
|
|
366
|
+
|
|
367
|
+
```ts
|
|
368
|
+
function transcriptLine(message): TranscriptLine | null;
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
The visible line of one message: a visitor's prompt or the Agent's reply. Tool
|
|
372
|
+
traffic and empty turns are not conversation, so they have no line.
|
|
373
|
+
|
|
374
|
+
#### Parameters
|
|
375
|
+
|
|
376
|
+
| Parameter | Type |
|
|
377
|
+
| --------- | ----------------------------------------- |
|
|
378
|
+
| `message` | [`TranscriptMessage`](#transcriptmessage) |
|
|
379
|
+
|
|
380
|
+
#### Returns
|
|
381
|
+
|
|
382
|
+
[`TranscriptLine`](#transcriptline) \| `null`
|
|
@@ -25,7 +25,8 @@ Minimum identity required to own a window across mount generations.
|
|
|
25
25
|
### WindowStatus
|
|
26
26
|
|
|
27
27
|
```ts
|
|
28
|
-
type WindowStatus =
|
|
28
|
+
type WindowStatus =
|
|
29
|
+
"loading" | "getting-ready" | "ready" | "minimized" | "error";
|
|
29
30
|
```
|
|
30
31
|
|
|
31
32
|
Current presentation state of a managed window.
|
|
@@ -61,6 +62,7 @@ with it.
|
|
|
61
62
|
|
|
62
63
|
```ts
|
|
63
64
|
type WindowEvents = Readonly<{
|
|
65
|
+
onDeliveryPending?: () => void;
|
|
64
66
|
onComputerChoice: () => Promise<void>;
|
|
65
67
|
onNavigationState: (state) => void;
|
|
66
68
|
onStatusItems: (items) => void;
|
|
@@ -211,8 +213,49 @@ Host adapters used to create, attach and validate window mounts.
|
|
|
211
213
|
| `Launch` _extends_ [`WindowLaunch`](#windowlaunch) |
|
|
212
214
|
| `Container` |
|
|
213
215
|
|
|
216
|
+
## Variables
|
|
217
|
+
|
|
218
|
+
### APP\_SURFACE\_DOCUMENT\_TIMEOUT\_MS
|
|
219
|
+
|
|
220
|
+
```ts
|
|
221
|
+
const APP_SURFACE_DOCUMENT_TIMEOUT_MS: 30000 = 30_000;
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
Existing cold-document bound, also used as one total preparation budget.
|
|
225
|
+
|
|
214
226
|
## Functions
|
|
215
227
|
|
|
228
|
+
### prepareWithDeliveryRetry()
|
|
229
|
+
|
|
230
|
+
```ts
|
|
231
|
+
function prepareWithDeliveryRetry<A>(prepare, signal, onPending): Promise<A>;
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
Shell-only preparation retry. No document, connection or mounted operation
|
|
235
|
+
belongs inside `prepare`. Each fetch receives the interruptible attempt's
|
|
236
|
+
signal; the absolute budget covers both requests and backoff, never resets, and
|
|
237
|
+
is released as soon as preparation succeeds.
|
|
238
|
+
|
|
239
|
+
#### Type Parameters
|
|
240
|
+
|
|
241
|
+
| Type Parameter |
|
|
242
|
+
| -------------- |
|
|
243
|
+
| `A` |
|
|
244
|
+
|
|
245
|
+
#### Parameters
|
|
246
|
+
|
|
247
|
+
| Parameter | Type |
|
|
248
|
+
| ----------- | ------------------------------ |
|
|
249
|
+
| `prepare` | (`signal`) => `Promise`\<`A`\> |
|
|
250
|
+
| `signal` | `AbortSignal` |
|
|
251
|
+
| `onPending` | () => `void` |
|
|
252
|
+
|
|
253
|
+
#### Returns
|
|
254
|
+
|
|
255
|
+
`Promise`\<`A`\>
|
|
256
|
+
|
|
257
|
+
---
|
|
258
|
+
|
|
216
259
|
### hasVisibleWindows()
|
|
217
260
|
|
|
218
261
|
```ts
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fungi.computer/nacre",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"author": "Levi <levi@technomancy.dev>",
|
|
5
5
|
"description": "The shell client for hosting Apps: workbench, command host, keys, commands, window manager and App directory rows",
|
|
6
6
|
"type": "module",
|
|
@@ -43,6 +43,10 @@
|
|
|
43
43
|
"./workbench-directory": {
|
|
44
44
|
"types": "./dist/workbench-directory.d.ts",
|
|
45
45
|
"import": "./dist/workbench-directory.js"
|
|
46
|
+
},
|
|
47
|
+
"./website-channels": {
|
|
48
|
+
"types": "./dist/website-channels.d.ts",
|
|
49
|
+
"import": "./dist/website-channels.js"
|
|
46
50
|
}
|
|
47
51
|
},
|
|
48
52
|
"files": [
|