@pinecall/dot 0.11.24 → 0.11.25

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.
Files changed (120) hide show
  1. package/README.md +135 -59
  2. package/dist/agent/index.d.ts +3 -2
  3. package/dist/agent/index.d.ts.map +1 -1
  4. package/dist/agent/index.js +2 -1
  5. package/dist/agent/index.js.map +1 -1
  6. package/dist/agent/tutor.d.ts +8 -10
  7. package/dist/agent/tutor.d.ts.map +1 -1
  8. package/dist/agent/tutor.js +71 -74
  9. package/dist/agent/tutor.js.map +1 -1
  10. package/dist/agent/walks.d.ts +19 -0
  11. package/dist/agent/walks.d.ts.map +1 -0
  12. package/dist/agent/walks.js +89 -0
  13. package/dist/agent/walks.js.map +1 -0
  14. package/dist/page/page.d.ts +2 -2
  15. package/dist/page/page.d.ts.map +1 -1
  16. package/dist/page/page.js +5 -5
  17. package/dist/page/page.js.map +1 -1
  18. package/dist/page/roles.d.ts +2 -0
  19. package/dist/page/roles.d.ts.map +1 -1
  20. package/dist/page/roles.js +21 -2
  21. package/dist/page/roles.js.map +1 -1
  22. package/dist/pointer/asking.d.ts +25 -0
  23. package/dist/pointer/asking.d.ts.map +1 -0
  24. package/dist/pointer/asking.js +82 -0
  25. package/dist/pointer/asking.js.map +1 -0
  26. package/dist/pointer/flight.d.ts +28 -0
  27. package/dist/pointer/flight.d.ts.map +1 -1
  28. package/dist/pointer/flight.js +93 -7
  29. package/dist/pointer/flight.js.map +1 -1
  30. package/dist/pointer/frames.d.ts +28 -0
  31. package/dist/pointer/frames.d.ts.map +1 -0
  32. package/dist/pointer/frames.js +66 -0
  33. package/dist/pointer/frames.js.map +1 -0
  34. package/dist/pointer/icons.d.ts +8 -0
  35. package/dist/pointer/icons.d.ts.map +1 -0
  36. package/dist/pointer/icons.js +15 -0
  37. package/dist/pointer/icons.js.map +1 -0
  38. package/dist/pointer/menu.d.ts +3 -0
  39. package/dist/pointer/menu.d.ts.map +1 -1
  40. package/dist/pointer/menu.js +26 -6
  41. package/dist/pointer/menu.js.map +1 -1
  42. package/dist/pointer/person.d.ts +13 -2
  43. package/dist/pointer/person.d.ts.map +1 -1
  44. package/dist/pointer/person.js +47 -41
  45. package/dist/pointer/person.js.map +1 -1
  46. package/dist/pointer/pressing.d.ts +6 -0
  47. package/dist/pointer/pressing.d.ts.map +1 -0
  48. package/dist/pointer/pressing.js +32 -0
  49. package/dist/pointer/pressing.js.map +1 -0
  50. package/dist/pointer/typing.d.ts +5 -3
  51. package/dist/pointer/typing.d.ts.map +1 -1
  52. package/dist/pointer/typing.js +46 -15
  53. package/dist/pointer/typing.js.map +1 -1
  54. package/dist/server/index.d.ts +34 -0
  55. package/dist/server/index.d.ts.map +1 -0
  56. package/dist/server/index.js +108 -0
  57. package/dist/server/index.js.map +1 -0
  58. package/dist/server/questions.d.ts +30 -0
  59. package/dist/server/questions.d.ts.map +1 -0
  60. package/dist/server/questions.js +136 -0
  61. package/dist/server/questions.js.map +1 -0
  62. package/dist/server/saying.d.ts +31 -0
  63. package/dist/server/saying.d.ts.map +1 -0
  64. package/dist/server/saying.js +124 -0
  65. package/dist/server/saying.js.map +1 -0
  66. package/dist/tutor/acting.d.ts +42 -0
  67. package/dist/tutor/acting.d.ts.map +1 -0
  68. package/dist/tutor/acting.js +180 -0
  69. package/dist/tutor/acting.js.map +1 -0
  70. package/dist/tutor/aloud.d.ts +50 -0
  71. package/dist/tutor/aloud.d.ts.map +1 -0
  72. package/dist/tutor/aloud.js +288 -0
  73. package/dist/tutor/aloud.js.map +1 -0
  74. package/dist/tutor/ask.d.ts +49 -0
  75. package/dist/tutor/ask.d.ts.map +1 -0
  76. package/dist/tutor/ask.js +47 -0
  77. package/dist/tutor/ask.js.map +1 -0
  78. package/dist/tutor/listening.d.ts +17 -0
  79. package/dist/tutor/listening.d.ts.map +1 -0
  80. package/dist/tutor/listening.js +66 -0
  81. package/dist/tutor/listening.js.map +1 -0
  82. package/dist/tutor/options.d.ts +37 -1
  83. package/dist/tutor/options.d.ts.map +1 -1
  84. package/dist/tutor/options.js +1 -1
  85. package/dist/tutor/options.js.map +1 -1
  86. package/dist/tutor/reading.d.ts +58 -0
  87. package/dist/tutor/reading.d.ts.map +1 -0
  88. package/dist/tutor/reading.js +193 -0
  89. package/dist/tutor/reading.js.map +1 -0
  90. package/dist/tutor/text.d.ts +16 -0
  91. package/dist/tutor/text.d.ts.map +1 -0
  92. package/dist/tutor/text.js +119 -0
  93. package/dist/tutor/text.js.map +1 -0
  94. package/dist/tutor/tutor.d.ts +2 -9
  95. package/dist/tutor/tutor.d.ts.map +1 -1
  96. package/dist/tutor/tutor.js +109 -87
  97. package/dist/tutor/tutor.js.map +1 -1
  98. package/dist/tutor/walking.d.ts +20 -6
  99. package/dist/tutor/walking.d.ts.map +1 -1
  100. package/dist/tutor/walking.js +125 -25
  101. package/dist/tutor/walking.js.map +1 -1
  102. package/dist/tutor/walks.d.ts +33 -0
  103. package/dist/tutor/walks.d.ts.map +1 -1
  104. package/dist/tutor/walks.js +116 -10
  105. package/dist/tutor/walks.js.map +1 -1
  106. package/dist/wire/acts.d.ts +60 -0
  107. package/dist/wire/acts.d.ts.map +1 -0
  108. package/dist/wire/acts.js +120 -0
  109. package/dist/wire/acts.js.map +1 -0
  110. package/dist/wire/ask.d.ts +132 -0
  111. package/dist/wire/ask.d.ts.map +1 -0
  112. package/dist/wire/ask.js +102 -0
  113. package/dist/wire/ask.js.map +1 -0
  114. package/dist/wire/index.d.ts +26 -8
  115. package/dist/wire/index.d.ts.map +1 -1
  116. package/dist/wire/index.js +62 -11
  117. package/dist/wire/index.js.map +1 -1
  118. package/docs/macros.md +53 -3
  119. package/docs/write-a-tutor.md +26 -2
  120. package/package.json +8 -4
@@ -0,0 +1,50 @@
1
+ /** One reading under way: each part recorded as it is reached, the examples pressed, typed and talked to, the outputs explained; and what a reading takes from the tutor. */
2
+ import { type ExplainRequest, type NextLine, type NextRequest, type Note } from "../wire/ask.js";
3
+ import type { RecordedStep } from "../wire/index.js";
4
+ import type { Acting } from "./acting.js";
5
+ import { type Reading } from "./reading.js";
6
+ /** What reading a page takes from the tutor. */
7
+ export interface ReadingOptions {
8
+ /** A text recorded in the agent's voice, by the site's door; null when it was not. */
9
+ record: (text: string) => Promise<RecordedStep | null>;
10
+ /** The part being read lit and pointed at, the rest dimmed; null puts the light out. */
11
+ light: (element: Element | null) => void;
12
+ /** An example pressed, and what it controls waited on until it answered. */
13
+ press: (element: Element) => Promise<void>;
14
+ /** The page's own example typed into a field, the pointer on it; paced to `ms`, the recording said meanwhile. */
15
+ type?: ((element: Element, text: string, ms?: number) => Promise<void>) | undefined;
16
+ /** An output explained by the site's door: notes on its lines; none when the door gives none. */
17
+ explain?: ((request: ExplainRequest) => Promise<Note[]>) | undefined;
18
+ /** The dot's next line on a chat it talks to for a goal, by the site's door; null when it gives none. */
19
+ next?: ((request: NextRequest) => Promise<NextLine | null>) | undefined;
20
+ /** A chat talked to opened before its first line: its field focused, and its output waited on while it says it is busy (a greeting coming). */
21
+ open?: ((field: Element, output: Element) => Promise<void>) | undefined;
22
+ /** A spoken call's output waited on while it says it is busy: the agent answering what the dot said into it. */
23
+ settle?: ((output: Element) => Promise<void>) | undefined;
24
+ }
25
+ /** One reading under way: each part recorded when it is reached, the next one asked for while one plays. */
26
+ export declare class ReadAloud {
27
+ #private;
28
+ readonly reading: Reading;
29
+ constructor(reading: Reading, options: ReadingOptions);
30
+ /** The `at`th step recorded, and the next sentence asked for, so it is there when this one ends; a note whose line is not in the output, none. */
31
+ voice(at: number): Promise<RecordedStep | null>;
32
+ /** The `at`th step, an example: typed into a field; a turn of a talk; or pressed, waited on, and its output explained by the door when the page notes nothing on it. */
33
+ act(at: number): Promise<void>;
34
+ /** The `at`th step starts: its part lit and pointed at, an output's line by its note; -1, the reading is over. */
35
+ shows(at: number): void;
36
+ }
37
+ /** How long a part that could not be recorded waits before it is asked again, each time, in ms: a door that just came up (a machine booting) answers within these. */
38
+ export declare const RECORD_AGAIN_MS: number[];
39
+ /**
40
+ * What a reading takes, from the tutor's acts and moves: each part recorded by the site's door, the part read
41
+ * lit and pointed at (`light`), and an example pressed, then what it controls (its output) waited on until it
42
+ * answered and is not busy.
43
+ */
44
+ export declare function readingWith(title: string, acting: Acting, moves: {
45
+ light: (element: Element | null) => void;
46
+ queued: <T>(work: () => Promise<T>) => Promise<T>;
47
+ }): {
48
+ title: string;
49
+ } & ReadingOptions;
50
+ //# sourceMappingURL=aloud.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"aloud.d.ts","sourceRoot":"","sources":["../../src/tutor/aloud.ts"],"names":[],"mappings":"AAAA,6KAA6K;AAG7K,OAAO,EAAc,KAAK,cAAc,EAAc,KAAK,QAAQ,EAAE,KAAK,WAAW,EAAE,KAAK,IAAI,EAAE,MAAM,gBAAgB,CAAC;AACzH,OAAO,KAAK,EAAE,YAAY,EAAY,MAAM,kBAAkB,CAAC;AAC/D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAuJ,KAAK,OAAO,EAAE,MAAM,cAAc,CAAC;AASjM,gDAAgD;AAChD,MAAM,WAAW,cAAc;IAC7B,sFAAsF;IACtF,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAAC;IACvD,wFAAwF;IACxF,KAAK,EAAE,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,KAAK,IAAI,CAAC;IACzC,4EAA4E;IAC5E,KAAK,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3C,iHAAiH;IACjH,IAAI,CAAC,EAAE,CAAC,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,SAAS,CAAC;IACpF,iGAAiG;IACjG,OAAO,CAAC,EAAE,CAAC,CAAC,OAAO,EAAE,cAAc,KAAK,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,GAAG,SAAS,CAAC;IACrE,yGAAyG;IACzG,IAAI,CAAC,EAAE,CAAC,CAAC,OAAO,EAAE,WAAW,KAAK,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,CAAC,GAAG,SAAS,CAAC;IACxE,+IAA+I;IAC/I,IAAI,CAAC,EAAE,CAAC,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,SAAS,CAAC;IACxE,gHAAgH;IAChH,MAAM,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,SAAS,CAAC;CAC3D;AAED,4GAA4G;AAC5G,qBAAa,SAAS;;IACpB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAkB1B,YAAY,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,cAAc,EAGpD;IAED,kJAAkJ;IAClJ,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAU9C;IAED,wKAAwK;IAClK,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAwBnC;IAqGD,kHAAkH;IAClH,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CA4BtB;CAiBF;AAKD,sKAAsK;AACtK,eAAO,MAAM,eAAe,UAAoB,CAAC;AAkBjD;;;;GAIG;AACH,wBAAgB,WAAW,CACzB,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,KAAK,EAAE;IAAE,KAAK,EAAE,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,KAAK,IAAI,CAAC;IAAC,MAAM,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,CAAA;CAAE,GACrG;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG,cAAc,CA2BpC"}
@@ -0,0 +1,288 @@
1
+ /** One reading under way: each part recorded as it is reached, the examples pressed, typed and talked to, the outputs explained; and what a reading takes from the tutor. */
2
+ import { notPressable } from "../pointer/pressing.js";
3
+ import { MOST_HEARD } from "../wire/ask.js";
4
+ import { EXPLAIN_ATTRIBUTE, HEARD_ATTRIBUTE, READING_ATTRIBUTE, SAID_ATTRIBUTE, SAY_ATTRIBUTE, SAYING_EVENT, labelOf, languageOf, outputOf } from "./reading.js";
5
+ import { lineIn, piecesOf, seen, textOf, wordsOf } from "./text.js";
6
+ /** The most turns of its own a talk takes: the gateway's own ceiling on a caller's, whatever the goal. */
7
+ const MOST_TURNS = 40;
8
+ /** One reading under way: each part recorded when it is reached, the next one asked for while one plays. */
9
+ export class ReadAloud {
10
+ reading;
11
+ #options;
12
+ #asked = new Map();
13
+ /** The output whose notes are being read, marked for the site to widen it. */
14
+ #open = null;
15
+ /** The chats talked to that were opened already. */
16
+ #opened = new WeakSet();
17
+ /** The agent's answers read aloud already, on a chat talked to. */
18
+ #heard = new WeakSet();
19
+ /** The chats the dot said goodbye on. */
20
+ #bye = new WeakSet();
21
+ /** The presses of a talk's turns: read as the talk goes, never explained after. */
22
+ #turns = new WeakSet();
23
+ /** Each step's recording, once recorded: what a typing is paced to, and what a call is told. */
24
+ #recorded = new Map();
25
+ /** The steps whose typing, or telling, started. */
26
+ #begun = new WeakSet();
27
+ constructor(reading, options) {
28
+ this.reading = reading;
29
+ this.#options = options;
30
+ }
31
+ /** The `at`th step recorded, and the next sentence asked for, so it is there when this one ends; a note whose line is not in the output, none. */
32
+ voice(at) {
33
+ const about = this.reading.outputs[at];
34
+ if (about !== undefined && about.find !== null && lineIn(about.output, about.find) === null)
35
+ return Promise.resolve(null);
36
+ const recording = this.#record(at).then((step) => {
37
+ if (step !== null)
38
+ this.#recorded.set(at, step);
39
+ return step;
40
+ });
41
+ const next = this.reading.walk.steps.findIndex((step, index) => index > at && "live" in step);
42
+ if (next !== -1)
43
+ void this.#record(next);
44
+ return recording;
45
+ }
46
+ /** The `at`th step, an example: typed into a field; a turn of a talk; or pressed, waited on, and its output explained by the door when the page notes nothing on it. */
47
+ async act(at) {
48
+ const element = this.reading.at[at];
49
+ const step = this.reading.walk.steps[at];
50
+ if (element === undefined || step === undefined)
51
+ return;
52
+ const goal = this.reading.goals.get(step);
53
+ if (goal !== undefined)
54
+ return this.#talk(at, element, goal);
55
+ this.#options.light(element);
56
+ if ("fill" in step) {
57
+ await this.#options.type?.(element, step.with);
58
+ return;
59
+ }
60
+ await this.#options.press(element);
61
+ if (this.#turns.has(step))
62
+ return;
63
+ // Its own output, by what it controls: a press the page says nothing after has no step about it.
64
+ const output = outputOf(element);
65
+ // What the agent answered in a chat is read as it came, pointing at it, before anything is said of it.
66
+ let after = at;
67
+ for (const turn of this.#unheard(output)) {
68
+ const said = this.#say(turn.getAttribute(SAY_ATTRIBUTE) ?? wordsOf(turn), turn);
69
+ this.#insert(after, said);
70
+ after += said.length;
71
+ }
72
+ const noted = this.reading.outputs.some((about) => about !== undefined && about.output === output && about.find !== null);
73
+ if (!noted)
74
+ await this.#explain(after, output, element.getAttribute(EXPLAIN_ATTRIBUTE));
75
+ }
76
+ /** The turns of a chat not read aloud yet, in order, the agent's and the tools it used: all but the caller's; each counted as read. On a spoken call the agent is heard, not read: its turns and its tools are counted and left out, and only the call's end is said. */
77
+ #unheard(output) {
78
+ const turns = [...output.querySelectorAll(`[${SAID_ATTRIBUTE}]:not([${SAID_ATTRIBUTE}="caller"])`)].filter((turn) => seen(turn) && !this.#heard.has(turn));
79
+ for (const turn of turns)
80
+ this.#heard.add(turn);
81
+ return output.hasAttribute(HEARD_ATTRIBUTE) ? turns.filter((turn) => HEARD_ON_A_CALL.has(turn.getAttribute(SAID_ATTRIBUTE) ?? "") === false) : turns;
82
+ }
83
+ /** A text said pointing at `element`, a recording at a time. */
84
+ #say(text, element) {
85
+ return piecesOf(text).map((piece) => [{ say: piece, beats: [], live: true }, element, undefined]);
86
+ }
87
+ /** The output explained by the door: its notes after step `at`, in the place of the page's line on it (kept when the model gave none). */
88
+ async #explain(at, output, command) {
89
+ if (command === null || this.#options.explain === undefined)
90
+ return;
91
+ const text = textOf(output);
92
+ if (text === "")
93
+ return;
94
+ const notes = await this.#options.explain({ output: text, command: command || undefined, language: languageOf(output) }).catch(() => []);
95
+ const { steps } = this.reading.walk;
96
+ const { at: where, outputs } = this.reading;
97
+ if (notes.length > 0) {
98
+ for (let index = outputs.length - 1; index > at; index -= 1) {
99
+ if (outputs[index]?.output !== output || outputs[index]?.find !== null)
100
+ continue;
101
+ steps.splice(index, 1);
102
+ where.splice(index, 1);
103
+ outputs.splice(index, 1);
104
+ }
105
+ }
106
+ this.#insert(at, notes.map((note) => [{ say: note.say, beats: [], live: true }, output, { output, find: note.find }]));
107
+ }
108
+ /**
109
+ * One turn of a talk, at the step that marks it: the chat opened first, if it was not; what the agent said since
110
+ * (and the tools it used) read aloud, pointing at each; then the dot's next line asked of the door, said, typed
111
+ * and sent, and the turn after it marked. A button in no form is a spoken call: the button opens it, the agent is
112
+ * heard and not read, and the dot's lines are said into the call (`SAYING_EVENT`) with nothing to send. The talk
113
+ * ends when the dot said goodbye, the chat ended (a turn marked `end`, a send button disabled), the door gives no
114
+ * line or the turns run out; the page then goes on, the chat having been read as it went.
115
+ */
116
+ async #talk(at, button, goal) {
117
+ const output = outputOf(button);
118
+ // A call is spoken when its output says the agent is heard there, whatever form its button sits in (a console's
119
+ // composer holds the call button beside the box one types into); a chat is typed into its form's field.
120
+ const field = output.hasAttribute(HEARD_ATTRIBUTE) ? null : (button.closest("form")?.querySelector("input:not([type=hidden]), textarea") ?? null);
121
+ const spoken = field === null;
122
+ if (!this.#opened.has(output)) {
123
+ this.#opened.add(output);
124
+ // A call is opened by its button, its greeting waited on; a chat opens as its field is focused.
125
+ if (spoken)
126
+ await this.#options.press(button);
127
+ else
128
+ await this.#options.open?.(field, output);
129
+ }
130
+ else if (spoken) {
131
+ // The agent answering what was said into the call: waited on while the output says it is busy.
132
+ await this.#options.settle?.(output);
133
+ }
134
+ const marker = () => {
135
+ const step = { press: labelOf(button) };
136
+ this.reading.goals.set(step, goal);
137
+ return [step, button, undefined];
138
+ };
139
+ const unheard = this.#unheard(output);
140
+ if (unheard.length > 0) {
141
+ this.#insert(at, [...unheard.flatMap((turn) => this.#say(turn.getAttribute(SAY_ATTRIBUTE) ?? wordsOf(turn), turn)), marker()]);
142
+ return;
143
+ }
144
+ const turns = [...output.querySelectorAll(`[${SAID_ATTRIBUTE}="agent"], [${SAID_ATTRIBUTE}="caller"]`)].filter(seen);
145
+ const heard = turns.map((turn) => ({ who: turn.getAttribute(SAID_ATTRIBUTE) === "agent" ? "agent" : "caller", said: wordsOf(turn) })).slice(-MOST_HEARD);
146
+ const mine = heard.filter((turn) => turn.who === "caller").length;
147
+ const ended = output.querySelector(`[${SAID_ATTRIBUTE}="end"]`) !== null;
148
+ const over = ended || this.#bye.has(output) || mine >= MOST_TURNS || (field !== null && notPressable(button, true) !== null);
149
+ const next = over || this.#options.next === undefined ? null : await this.#options.next({ goal, heard, language: languageOf(output) }).catch(() => null);
150
+ if (next === null)
151
+ return;
152
+ if (next.hangup)
153
+ this.#bye.add(output);
154
+ if (field === null) {
155
+ // Said pointing at the call, and into it: each piece told to the output as it starts playing.
156
+ const said = this.#say(next.say, output);
157
+ for (const [step] of said)
158
+ this.reading.spoken.set(step, output);
159
+ this.#insert(at, [...said, marker()]);
160
+ return;
161
+ }
162
+ const press = { press: labelOf(button) };
163
+ this.#turns.add(press);
164
+ const said = this.#say(next.say, field);
165
+ if (said[0] !== undefined)
166
+ this.reading.typed.set(said[0][0], { field, text: next.say });
167
+ this.#insert(at, [...said, [press, button, undefined], marker()]);
168
+ }
169
+ /** Steps put after the `at`th; what was asked for ahead stands on the old numbering, so it is asked again. */
170
+ #insert(at, added) {
171
+ const { steps } = this.reading.walk;
172
+ const { at: where, outputs } = this.reading;
173
+ for (const [offset, [step, element, about]] of added.entries()) {
174
+ steps.splice(at + 1 + offset, 0, step);
175
+ where.splice(at + 1 + offset, 0, element);
176
+ outputs.splice(at + 1 + offset, 0, about);
177
+ }
178
+ for (const index of [...this.#asked.keys()])
179
+ if (index > at)
180
+ this.#asked.delete(index);
181
+ for (const index of [...this.#recorded.keys()])
182
+ if (index > at)
183
+ this.#recorded.delete(index);
184
+ }
185
+ /** The `at`th step starts: its part lit and pointed at, an output's line by its note; -1, the reading is over. */
186
+ shows(at) {
187
+ const about = at < 0 ? undefined : this.reading.outputs[at];
188
+ const output = about?.output ?? null;
189
+ if (this.#open !== output) {
190
+ this.#open?.removeAttribute(READING_ATTRIBUTE);
191
+ output?.setAttribute(READING_ATTRIBUTE, "");
192
+ this.#open = output;
193
+ }
194
+ const element = at < 0 ? null : (this.reading.at[at] ?? null);
195
+ const step = at < 0 ? undefined : this.reading.walk.steps[at];
196
+ // A talk's steps light nothing: a line said into a call goes into the call, and the button that opened it is
197
+ // gone once pressed (a hang-up stands where it was); there is nothing on the page to point at meanwhile.
198
+ const into = step === undefined ? undefined : this.reading.spoken.get(step);
199
+ const talking = (into !== undefined && into.hasAttribute(HEARD_ATTRIBUTE)) || (step !== undefined && this.reading.goals.has(step));
200
+ this.#options.light(talking ? null : about === undefined || about.find === null ? element : (lineIn(about.output, about.find) ?? element));
201
+ // A sentence typed as it is said: the typing starts with it, paced to its recording.
202
+ const typing = step === undefined ? undefined : this.reading.typed.get(step);
203
+ if (step !== undefined && typing !== undefined && !this.#begun.has(step)) {
204
+ this.#begun.add(step);
205
+ void this.#options.type?.(typing.field, typing.text, this.#recorded.get(at)?.durationMs);
206
+ }
207
+ // A sentence said into a call: the call's page is told it as it starts, with its recording, to play it in.
208
+ const recorded = this.#recorded.get(at);
209
+ if (step !== undefined && into !== undefined && recorded !== undefined && !this.#begun.has(step)) {
210
+ this.#begun.add(step);
211
+ const detail = { text: recorded.say, audio: recorded.audio, durationMs: recorded.durationMs };
212
+ into.dispatchEvent(new CustomEvent(SAYING_EVENT, { bubbles: true, detail }));
213
+ }
214
+ }
215
+ #record(at) {
216
+ const step = this.reading.walk.steps[at];
217
+ if (step === undefined || !("live" in step))
218
+ return Promise.resolve(null);
219
+ let recording = this.#asked.get(at);
220
+ if (recording === undefined) {
221
+ const asked = recordedAgain(() => this.#options.record(step.say));
222
+ // One that could not be recorded is not kept: reached again, it is asked again.
223
+ recording = asked.then((recorded) => {
224
+ if (recorded === null && this.#asked.get(at) === recording)
225
+ this.#asked.delete(at);
226
+ return recorded;
227
+ });
228
+ this.#asked.set(at, recording);
229
+ }
230
+ return recording;
231
+ }
232
+ }
233
+ /** What is heard on a spoken call and so not read: the agent's words, and the tools it used meanwhile. */
234
+ const HEARD_ON_A_CALL = new Set(["agent", "tool"]);
235
+ /** How long a part that could not be recorded waits before it is asked again, each time, in ms: a door that just came up (a machine booting) answers within these. */
236
+ export const RECORD_AGAIN_MS = [600, 1500, 3000];
237
+ /** A part recorded, asked again after each wait while the door fails; null once every try failed. */
238
+ async function recordedAgain(record) {
239
+ for (let tried = 0;; tried += 1) {
240
+ const recorded = await record().catch(() => null);
241
+ const wait = RECORD_AGAIN_MS[tried];
242
+ if (recorded !== null || wait === undefined)
243
+ return recorded;
244
+ await new Promise((done) => setTimeout(done, wait));
245
+ }
246
+ }
247
+ /** How long a reading waits for an example it pressed to answer, in ms. */
248
+ const EXAMPLE_MS = 60_000;
249
+ /** Whether `output`, or something in it, says it is busy. */
250
+ const isBusy = (output) => output.closest("[aria-busy=true]") !== null || output.querySelector("[aria-busy=true]") !== null;
251
+ /**
252
+ * What a reading takes, from the tutor's acts and moves: each part recorded by the site's door, the part read
253
+ * lit and pointed at (`light`), and an example pressed, then what it controls (its output) waited on until it
254
+ * answered and is not busy.
255
+ */
256
+ export function readingWith(title, acting, moves) {
257
+ return {
258
+ title,
259
+ record: (text) => acting.read(text),
260
+ explain: (request) => acting.explain(request),
261
+ next: (request) => acting.next(request),
262
+ // Focused, a chat may open and greet: waited on only while it says it is busy.
263
+ open: async (field, output) => {
264
+ await moves.queued(async () => field.focus({ preventScroll: true }));
265
+ if (isBusy(output))
266
+ await acting.wait(() => output, EXAMPLE_MS);
267
+ },
268
+ // A spoken call's output, busy while the agent answers what was said into it: waited on only then.
269
+ settle: async (output) => {
270
+ if (isBusy(output))
271
+ await acting.wait(() => output, EXAMPLE_MS);
272
+ },
273
+ light: moves.light,
274
+ type: (element, text, ms) => moves.queued(async () => void (await acting.type(element, text, ms))),
275
+ // The page's own example: its button pressed in any form. The wait after it holds no move: the pointer and
276
+ // the light go on (a visitor skipping ahead) while the output is waited on.
277
+ press: async (element) => {
278
+ if ((await moves.queued(() => acting.press(element, true))) !== null)
279
+ return;
280
+ // What it controls is on its own page: a chat in a frame of the site's own answers there.
281
+ const controls = element.getAttribute("aria-controls");
282
+ const output = controls === null ? null : element.ownerDocument.getElementById(controls);
283
+ if (output !== null)
284
+ await acting.wait(() => output, EXAMPLE_MS);
285
+ },
286
+ };
287
+ }
288
+ //# sourceMappingURL=aloud.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"aloud.js","sourceRoot":"","sources":["../../src/tutor/aloud.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,49 @@
1
+ /** What the tutor does with what the visitor typed: the site's server decides, and it plays a walk, shows one thing, or offers the agent. */
2
+ import type { Page } from "../page/page.js";
3
+ import { type AskRequest, type Decision, type DoorRequest } from "../wire/ask.js";
4
+ import type { Values } from "../wire/acts.js";
5
+ /** What the tutor says around a decision; the site's own words in its language. */
6
+ export interface AskWords {
7
+ /** Beside the face while the server decides: "Looking…". */
8
+ looking: string;
9
+ /** Under the field when the page has nothing for it: "I can't find that on this page." */
10
+ notHere: string;
11
+ /** Under the field for a question a person answers: "That one is a question for the agent." */
12
+ forAgent: string;
13
+ /** The button that takes it to the agent: "Ask the agent". */
14
+ agent: string;
15
+ }
16
+ /** The words, from the site's or in English. */
17
+ export declare function askWords(words?: {
18
+ looking?: string | undefined;
19
+ notHere?: string | undefined;
20
+ forAgent?: string | undefined;
21
+ askAgent?: string | undefined;
22
+ }): AskWords;
23
+ /** What doing it takes, from the tutor. */
24
+ export interface Asked {
25
+ /** The site's door. */
26
+ ask: (request: DoorRequest) => Promise<unknown>;
27
+ page: Page;
28
+ path: () => string;
29
+ walks: () => AskRequest["walks"];
30
+ /** Play a walk called with the values picked out of what was typed. */
31
+ play: (walk: string, values: Values, message: string) => void;
32
+ /** Let a walk play once the door answers: called inside the visitor's submit. */
33
+ unlock: () => void;
34
+ /** Light and point at a thing, its name beside the face. */
35
+ show: (element: Element, role: string, name: string) => void;
36
+ /** Words beside the face for a moment; null takes them away. */
37
+ note: (text: string | null) => void;
38
+ /** A line under the field, with a button when there is somewhere to take it. */
39
+ offer: (text: string, action?: {
40
+ label: string;
41
+ onClick: () => void;
42
+ }) => void;
43
+ /** Take what they typed to the agent: a call, with it written in. None, no button. */
44
+ talk?: ((message: string) => void) | undefined;
45
+ words: AskWords;
46
+ }
47
+ /** Ask, and do the one thing decided; answers the decision, or null when the server gave none. */
48
+ export declare function act(message: string, on: Asked): Promise<Decision | null>;
49
+ //# sourceMappingURL=ask.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ask.d.ts","sourceRoot":"","sources":["../../src/tutor/ask.ts"],"names":[],"mappings":"AAAA,6IAA6I;AAM7I,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAuB,KAAK,UAAU,EAAE,KAAK,QAAQ,EAAE,KAAK,WAAW,EAAE,MAAM,gBAAgB,CAAC;AACvG,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAE9C,mFAAmF;AACnF,MAAM,WAAW,QAAQ;IACvB,4DAA4D;IAC5D,OAAO,EAAE,MAAM,CAAC;IAChB,0FAA0F;IAC1F,OAAO,EAAE,MAAM,CAAC;IAChB,+FAA+F;IAC/F,QAAQ,EAAE,MAAM,CAAC;IACjB,8DAA8D;IAC9D,KAAK,EAAE,MAAM,CAAC;CACf;AAED,gDAAgD;AAChD,wBAAgB,QAAQ,CAAC,KAAK,GAAE;IAAE,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CAAO,GAAG,QAAQ,CAO3K;AAED,2CAA2C;AAC3C,MAAM,WAAW,KAAK;IACpB,uBAAuB;IACvB,GAAG,EAAE,CAAC,OAAO,EAAE,WAAW,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAChD,IAAI,EAAE,IAAI,CAAC;IACX,IAAI,EAAE,MAAM,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,UAAU,CAAC,OAAO,CAAC,CAAC;IACjC,uEAAuE;IACvE,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9D,iFAAiF;IACjF,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,4DAA4D;IAC5D,IAAI,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7D,gEAAgE;IAChE,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;IACpC,gFAAgF;IAChF,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,IAAI,CAAA;KAAE,KAAK,IAAI,CAAC;IAC/E,sFAAsF;IACtF,IAAI,CAAC,EAAE,CAAC,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;IAC/C,KAAK,EAAE,QAAQ,CAAC;CACjB;AAED,kGAAkG;AAClG,wBAAsB,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,KAAK,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,CA4B9E"}
@@ -0,0 +1,47 @@
1
+ /** What the tutor does with what the visitor typed: the site's server decides, and it plays a walk, shows one thing, or offers the agent. */
2
+ //
3
+ // No call and no voice: a walk plays its recording, a thing is lit and pointed at with its name beside the
4
+ // face. Anything the page cannot show (a question a person answers, something not here, a server that
5
+ // did not answer) is never answered in words of the tutor's: the field says so, with the agent one click away.
6
+ import { decisionOf, namedIn } from "../wire/ask.js";
7
+ /** The words, from the site's or in English. */
8
+ export function askWords(words = {}) {
9
+ return {
10
+ looking: words.looking ?? "Looking…",
11
+ notHere: words.notHere ?? "I can't find that on this page.",
12
+ forAgent: words.forAgent ?? "That one is a question for the agent.",
13
+ agent: words.askAgent ?? "Ask the agent",
14
+ };
15
+ }
16
+ /** Ask, and do the one thing decided; answers the decision, or null when the server gave none. */
17
+ export async function act(message, on) {
18
+ on.unlock();
19
+ on.note(on.words.looking);
20
+ const seen = on.page.seen();
21
+ let decision;
22
+ try {
23
+ decision = decisionOf(await on.ask({ decide: { message, path: on.path(), page: seen.text, walks: on.walks() } }));
24
+ }
25
+ catch {
26
+ decision = null;
27
+ }
28
+ on.note(null);
29
+ const talk = on.talk;
30
+ const agent = talk === undefined ? undefined : { label: on.words.agent, onClick: () => talk(message) };
31
+ if (decision?.do === "walk") {
32
+ on.play(decision.walk, decision.params ?? {}, message);
33
+ return decision;
34
+ }
35
+ if (decision?.do === "show") {
36
+ const target = decision.target;
37
+ const element = on.page.element(target);
38
+ const thing = namedIn(seen.text).find((one) => one.ref === target);
39
+ if (element !== null && thing !== undefined) {
40
+ on.show(element, thing.role, thing.name);
41
+ return decision;
42
+ }
43
+ }
44
+ on.offer(decision?.do === "talk" ? on.words.forAgent : on.words.notHere, agent);
45
+ return decision;
46
+ }
47
+ //# sourceMappingURL=ask.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ask.js","sourceRoot":"","sources":["../../src/tutor/ask.ts"],"names":[],"mappings":"AAAA,6IAA6I;AAC7I,EAAE;AACF,2GAA2G;AAC3G,sGAAsG;AACtG,+GAA+G;AAG/G,OAAO,EAAE,UAAU,EAAE,OAAO,EAAoD,MAAM,gBAAgB,CAAC;AAevG,gDAAgD;AAChD,MAAM,UAAU,QAAQ,CAAC,KAAK,GAAiI,EAAE;IAC/J,OAAO;QACL,OAAO,EAAE,KAAK,CAAC,OAAO,IAAI,UAAU;QACpC,OAAO,EAAE,KAAK,CAAC,OAAO,IAAI,iCAAiC;QAC3D,QAAQ,EAAE,KAAK,CAAC,QAAQ,IAAI,uCAAuC;QACnE,KAAK,EAAE,KAAK,CAAC,QAAQ,IAAI,eAAe;KACzC,CAAC;AACJ,CAAC;AAwBD,kGAAkG;AAClG,MAAM,CAAC,KAAK,UAAU,GAAG,CAAC,OAAe,EAAE,EAAS;IAClD,EAAE,CAAC,MAAM,EAAE,CAAC;IACZ,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAC1B,MAAM,IAAI,GAAG,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;IAC5B,IAAI,QAAyB,CAAC;IAC9B,IAAI,CAAC;QACH,QAAQ,GAAG,UAAU,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;IACpH,CAAC;IAAC,MAAM,CAAC;QACP,QAAQ,GAAG,IAAI,CAAC;IAClB,CAAC;IACD,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACd,MAAM,IAAI,GAAG,EAAE,CAAC,IAAI,CAAC;IACrB,MAAM,KAAK,GAAG,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;IACvG,IAAI,QAAQ,EAAE,EAAE,KAAK,MAAM,EAAE,CAAC;QAC5B,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC,MAAM,IAAI,EAAE,EAAE,OAAO,CAAC,CAAC;QACvD,OAAO,QAAQ,CAAC;IAClB,CAAC;IACD,IAAI,QAAQ,EAAE,EAAE,KAAK,MAAM,EAAE,CAAC;QAC5B,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC;QAC/B,MAAM,OAAO,GAAG,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QACxC,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,GAAG,KAAK,MAAM,CAAC,CAAC;QACnE,IAAI,OAAO,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YAC5C,EAAE,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;YACzC,OAAO,QAAQ,CAAC;QAClB,CAAC;IACH,CAAC;IACD,EAAE,CAAC,KAAK,CAAC,QAAQ,EAAE,EAAE,KAAK,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;IAChF,OAAO,QAAQ,CAAC;AAClB,CAAC"}
@@ -0,0 +1,17 @@
1
+ /** What the tutor hears of the page: a scroll, a resize, a toggle, a field typed in, the page changing, a click, and the mouse over a thing with a line. */
2
+ /** What makes the page worth looking at again. */
3
+ export type Why = "scroll" | "resize" | "dom" | "toggle";
4
+ export interface Heard {
5
+ /** The page changed for `why`: look again once it settles. */
6
+ soon: (why: Why) => void;
7
+ /** The visitor clicked something a person names: a link, a button, a field. */
8
+ clicked: (element: Element) => void;
9
+ }
10
+ export interface Listening {
11
+ /** The thing with a line under the visitor's mouse now, or a moment ago. */
12
+ offered(): Element | null;
13
+ close(): void;
14
+ }
15
+ /** Listen to the page until `close()`. */
16
+ export declare function listen(document: Document, view: Window, heard: Heard): Listening;
17
+ //# sourceMappingURL=listening.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"listening.d.ts","sourceRoot":"","sources":["../../src/tutor/listening.ts"],"names":[],"mappings":"AAAA,4JAA4J;AAM5J,kDAAkD;AAClD,MAAM,MAAM,GAAG,GAAG,QAAQ,GAAG,QAAQ,GAAG,KAAK,GAAG,QAAQ,CAAC;AAEzD,MAAM,WAAW,KAAK;IACpB,8DAA8D;IAC9D,IAAI,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,IAAI,CAAC;IACzB,+EAA+E;IAC/E,OAAO,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;CACrC;AAED,MAAM,WAAW,SAAS;IACxB,4EAA4E;IAC5E,OAAO,IAAI,OAAO,GAAG,IAAI,CAAC;IAC1B,KAAK,IAAI,IAAI,CAAC;CACf;AAED,0CAA0C;AAC1C,wBAAgB,MAAM,CAAC,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,GAAG,SAAS,CAqDhF"}
@@ -0,0 +1,66 @@
1
+ /** What the tutor hears of the page: a scroll, a resize, a toggle, a field typed in, the page changing, a click, and the mouse over a thing with a line. */
2
+ //
3
+ // Everything the tutor's own layer does (`data-pinecall-skip`) is left out, so its moves never read as
4
+ // the visitor's. The thing with a line under the mouse is kept a moment after the mouse leaves it, so
5
+ // its ▶ can be reached.
6
+ /** Listen to the page until `close()`. */
7
+ export function listen(document, view, heard) {
8
+ let offered = null;
9
+ let leaving;
10
+ const ours = (target) => target instanceof Element && target.closest("[data-pinecall-skip]") !== null;
11
+ const onScroll = () => heard.soon("scroll");
12
+ const onResize = () => heard.soon("resize");
13
+ const onToggle = () => heard.soon("toggle");
14
+ // What the visitor types reaches the agent as the page's next look, as their scroll does.
15
+ const onInput = (event) => {
16
+ if (event.target instanceof Element && !ours(event.target))
17
+ heard.soon("dom");
18
+ };
19
+ // Over the ▶ itself (the tutor's own layer) it stays; off an element with a line it goes a moment later.
20
+ const onOver = (event) => {
21
+ const target = event.target instanceof Element ? event.target : null;
22
+ clearTimeout(leaving);
23
+ if (ours(target))
24
+ return;
25
+ const marked = target?.closest("[data-pinecall-say]") ?? null;
26
+ if (marked !== null)
27
+ offered = marked;
28
+ else
29
+ leaving = setTimeout(() => (offered = null), 400);
30
+ };
31
+ const onClick = (event) => {
32
+ const target = event.target instanceof Element ? event.target : null;
33
+ if (target === null || ours(target))
34
+ return;
35
+ const clicked = target.closest("a, button, summary, input, select, textarea, [role=button], [role=link]");
36
+ if (clicked !== null)
37
+ heard.clicked(clicked);
38
+ };
39
+ const changes = new MutationObserver((records) => {
40
+ if (records.every((record) => ours(record.target instanceof Element ? record.target : record.target.parentElement)))
41
+ return;
42
+ heard.soon("dom");
43
+ });
44
+ // Captured on the document: a page whose content scrolls in a box of its own is heard scrolling too.
45
+ document.addEventListener("scroll", onScroll, { capture: true, passive: true });
46
+ view.addEventListener("resize", onResize);
47
+ document.addEventListener("toggle", onToggle, true);
48
+ document.addEventListener("click", onClick, true);
49
+ document.addEventListener("input", onInput, true);
50
+ document.addEventListener("pointerover", onOver, true);
51
+ changes.observe(document.body, { subtree: true, childList: true, characterData: true, attributes: true, attributeFilter: ["open", "hidden", "aria-expanded", "aria-selected", "class"] });
52
+ return {
53
+ offered: () => (offered?.isConnected === true ? offered : null),
54
+ close() {
55
+ clearTimeout(leaving);
56
+ changes.disconnect();
57
+ document.removeEventListener("scroll", onScroll, true);
58
+ view.removeEventListener("resize", onResize);
59
+ document.removeEventListener("toggle", onToggle, true);
60
+ document.removeEventListener("click", onClick, true);
61
+ document.removeEventListener("input", onInput, true);
62
+ document.removeEventListener("pointerover", onOver, true);
63
+ },
64
+ };
65
+ }
66
+ //# sourceMappingURL=listening.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"listening.js","sourceRoot":"","sources":["../../src/tutor/listening.ts"],"names":[],"mappings":"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"}