@cairnvibe/sdk 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/LICENSE +21 -0
- package/dist/cairn-widget.js +228 -0
- package/dist/context-collector.d.ts +1 -0
- package/dist/context-collector.js +23 -0
- package/dist/dashboard-sqlite.d.ts +8 -0
- package/dist/dashboard-sqlite.js +50 -0
- package/dist/dashboard.d.ts +39 -0
- package/dist/dashboard.js +60 -0
- package/dist/element-ladder.d.ts +7 -0
- package/dist/element-ladder.js +60 -0
- package/dist/index.d.ts +31 -0
- package/dist/index.js +1069 -0
- package/dist/key-rotator.d.ts +7 -0
- package/dist/key-rotator.js +31 -0
- package/dist/package.json +1 -0
- package/dist/realtime-cli.d.ts +2 -0
- package/dist/realtime-cli.js +59 -0
- package/dist/realtime-server.d.ts +10 -0
- package/dist/realtime-server.js +291 -0
- package/dist/server.d.ts +95 -0
- package/dist/server.js +298 -0
- package/dist/speak-server.d.ts +16 -0
- package/dist/speak-server.js +41 -0
- package/dist/transcribe-server.d.ts +14 -0
- package/dist/transcribe-server.js +47 -0
- package/dist/tts-stream.d.ts +33 -0
- package/dist/tts-stream.js +124 -0
- package/dist/verb-executor.d.ts +17 -0
- package/dist/verb-executor.js +67 -0
- package/package.json +56 -0
- package/src/context-collector.ts +21 -0
- package/src/dashboard-sqlite.ts +52 -0
- package/src/dashboard.ts +82 -0
- package/src/element-ladder.ts +67 -0
- package/src/index.tsx +1250 -0
- package/src/key-rotator.ts +29 -0
- package/src/realtime-cli.ts +62 -0
- package/src/realtime-server.ts +342 -0
- package/src/server.ts +386 -0
- package/src/speak-server.ts +56 -0
- package/src/transcribe-server.ts +68 -0
- package/src/tts-stream.ts +140 -0
- package/src/verb-executor.ts +84 -0
- package/src/web-component.ts +1252 -0
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
// Turns a raw server response into a UI action — or, on anything that fails
|
|
2
|
+
// validation, into a plain explain. This is the client-side half of
|
|
3
|
+
// BUILD_PLAN.md invariant #1 ("the LLM never emits code or selectors, only a
|
|
4
|
+
// verb from a fixed list") and invariant #3 ("any lookup failure degrades to
|
|
5
|
+
// explain — never guess, never wrong-click"). The server (`server.ts`)
|
|
6
|
+
// enforces the same schema independently — never trust the client alone.
|
|
7
|
+
|
|
8
|
+
import { VerbResponseSchema, type TourStep, type VerbResponse } from "@cairnvibe/core";
|
|
9
|
+
import { findElement, highlightElement, logMiss, type MissContext } from "./element-ladder";
|
|
10
|
+
|
|
11
|
+
export interface VerbExecutorOptions {
|
|
12
|
+
onExplain: (text: string) => void;
|
|
13
|
+
onNavigate?: (route: string) => void;
|
|
14
|
+
onDo?: (action: string, target?: string) => void;
|
|
15
|
+
onMiss?: (context: MissContext) => void;
|
|
16
|
+
/**
|
|
17
|
+
* A multi-step guided walkthrough (2-6 steps). Highlighting/timing/speech
|
|
18
|
+
* is NOT done here — this just hands the raw steps to the caller, which
|
|
19
|
+
* owns the UI (progress display) and, for voice, the TTS sequencing.
|
|
20
|
+
*/
|
|
21
|
+
onTour?: (steps: TourStep[]) => void;
|
|
22
|
+
/** Action ids the customer has actually wired up. "do" is rejected for anything else. */
|
|
23
|
+
registeredActions?: string[];
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const FALLBACK_TEXT = "I'm not sure — I couldn't understand that response. Try rephrasing your question.";
|
|
27
|
+
|
|
28
|
+
export function executeVerbResponse(raw: unknown, route: string, options: VerbExecutorOptions): void {
|
|
29
|
+
const parsed = VerbResponseSchema.safeParse(raw);
|
|
30
|
+
if (!parsed.success) {
|
|
31
|
+
options.onExplain(FALLBACK_TEXT);
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
dispatchVerb(parsed.data, route, options);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function dispatchVerb(verb: VerbResponse, route: string, options: VerbExecutorOptions): void {
|
|
39
|
+
switch (verb.verb) {
|
|
40
|
+
case "explain":
|
|
41
|
+
options.onExplain(verb.text);
|
|
42
|
+
return;
|
|
43
|
+
|
|
44
|
+
case "highlight":
|
|
45
|
+
case "open": {
|
|
46
|
+
const el = findElement(verb.target);
|
|
47
|
+
if (!el) {
|
|
48
|
+
(options.onMiss ?? logMiss)({ attempted: verb.target, route });
|
|
49
|
+
options.onExplain(verb.text ?? "I know what you need, but I can't find it on this page right now.");
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
highlightElement(el);
|
|
53
|
+
if (verb.text) options.onExplain(verb.text);
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
case "navigate":
|
|
58
|
+
options.onNavigate?.(verb.route);
|
|
59
|
+
if (verb.text) options.onExplain(verb.text);
|
|
60
|
+
return;
|
|
61
|
+
|
|
62
|
+
case "do": {
|
|
63
|
+
const allowed = options.registeredActions ?? [];
|
|
64
|
+
if (!allowed.includes(verb.action)) {
|
|
65
|
+
options.onExplain("That action isn't available here.");
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
options.onDo?.(verb.action, verb.target);
|
|
69
|
+
if (verb.text) options.onExplain(verb.text);
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
case "tour":
|
|
74
|
+
if (options.onTour) {
|
|
75
|
+
options.onTour(verb.steps);
|
|
76
|
+
} else {
|
|
77
|
+
// Caller doesn't support tours (e.g. an older host app) — degrade
|
|
78
|
+
// to reading the steps out as one explanation rather than dropping
|
|
79
|
+
// the reply silently.
|
|
80
|
+
options.onExplain(verb.steps.map((s) => s.text).join(" "));
|
|
81
|
+
}
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
}
|