@memberjunction/ng-realtime-channels 0.0.0 → 6.2.0-edge.4

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 ADDED
@@ -0,0 +1,183 @@
1
+ Business Source License 1.1
2
+
3
+ License text copyright (c) 2024 MariaDB plc, All Rights Reserved.
4
+ "Business Source License" is a trademark of MariaDB plc.
5
+
6
+ -----------------------------------------------------------------------------
7
+
8
+ Parameters
9
+
10
+ Licensor: Blue Cypress, Inc.
11
+
12
+ Licensed Work: MemberJunction.
13
+ The Licensed Work is (c) 2023-2026 Blue Cypress, Inc.
14
+
15
+ Additional Use Grant: Subject to the terms of this License, Licensor grants
16
+ you the following additional rights to make Production
17
+ Use of the Licensed Work.
18
+
19
+ 1. Internal Use
20
+
21
+ You may make production use of the Licensed Work for
22
+ your own internal business or organizational operations.
23
+
24
+ 2. Nonprofit Use
25
+
26
+ If you are a Nonprofit, you may make production use of
27
+ the Licensed Work for the operations and activities of
28
+ your Organizational Family.
29
+
30
+ 3. MemberJunction Certified Program Use
31
+
32
+ If you are authorized by Licensor under the
33
+ MemberJunction Certified Program to provide professional
34
+ services using the Licensed Work, you may make
35
+ production use of the Licensed Work in providing such
36
+ professional services to a client, provided that:
37
+
38
+ (a) the Licensed Work is deployed in, and the applicable
39
+ production use occurs within, an environment owned,
40
+ leased, licensed, subscribed to, or otherwise controlled
41
+ by that client; and
42
+
43
+ (b) the production use is for that client's own internal
44
+ business or organizational operations or is otherwise
45
+ independently permitted to that client under this
46
+ Additional Use Grant.
47
+
48
+ 4. Definitions Applicable to the Additional Use Grant
49
+
50
+ "Affiliate" means, with respect to a specified Person,
51
+ any other Person that directly or indirectly Controls,
52
+ is Controlled by, or is under common Control with such
53
+ specified Person.
54
+
55
+ "Control" (including the terms "Controls," "Controlled
56
+ by," and "under common Control with") means the direct
57
+ or indirect possession of the power to direct or cause
58
+ the direction of the management and policies of a
59
+ Person, whether through ownership of voting interests,
60
+ by contract, or otherwise.
61
+
62
+ "Organizational Family" means, with respect to a Person,
63
+ (a) such Person and its Affiliates, and (b) any
64
+ nonprofit organization, governmental entity, chapter,
65
+ division, local affiliate, regional affiliate, state
66
+ affiliate, national affiliate, or other entity that is
67
+ formally affiliated with such Person through governing
68
+ documents, a charter, bylaws, a membership agreement, or
69
+ another written organizational instrument, and is
70
+ recognized under such documents as part of the same
71
+ organizational structure.
72
+
73
+ "Nonprofit" means a Person recognized by the Internal
74
+ Revenue Service as exempt from federal income taxation
75
+ under Section 501(c)(3), 501(c)(4), 501(c)(5), or
76
+ 501(c)(6) of the Internal Revenue Code, or a foreign
77
+ organization recognized under substantially equivalent
78
+ laws.
79
+
80
+ A Person claiming eligibility as a Nonprofit shall, upon
81
+ Licensor's reasonable request, provide documentation
82
+ reasonably sufficient to demonstrate that it qualifies
83
+ as a Nonprofit. If such Person materially misrepresents,
84
+ or is unable to demonstrate, its qualification as a
85
+ Nonprofit, the rights granted to such Person under
86
+ Section 2 of this Additional Use Grant shall terminate.
87
+
88
+ "MemberJunction Certified Program" means Licensor's
89
+ then-current program for certifying and authorizing a
90
+ Person to provide professional services using the
91
+ Licensed Work.
92
+
93
+ "Person" means any individual, corporation, limited
94
+ liability company, partnership, association, nonprofit
95
+ organization, governmental entity, or other legal or
96
+ organizational entity.
97
+
98
+ Change Date: Four (4) years from the date the Licensed Work is first
99
+ made available.
100
+
101
+ Change License: MIT License.
102
+
103
+ For information about alternative licensing arrangements for the Licensed
104
+ Work, please contact Blue Cypress, Inc.
105
+
106
+ -----------------------------------------------------------------------------
107
+
108
+ Terms
109
+
110
+ The Licensor hereby grants you the right to copy, modify, create derivative
111
+ works, redistribute, and make non-production use of the Licensed Work. The
112
+ Licensor may make an Additional Use Grant, above, permitting limited
113
+ production use.
114
+
115
+ Effective on the Change Date, or the fourth anniversary of the first publicly
116
+ available distribution of a specific version of the Licensed Work under this
117
+ License, whichever comes first, the Licensor hereby grants you rights under
118
+ the terms of the Change License, and the rights granted in the paragraph
119
+ above terminate.
120
+
121
+ If your use of the Licensed Work does not comply with the requirements
122
+ currently in effect as described in this License, you must purchase a
123
+ commercial license from the Licensor, its affiliated entities, or authorized
124
+ resellers, or you must refrain from using the Licensed Work.
125
+
126
+ All copies of the original and modified Licensed Work, and derivative works
127
+ of the Licensed Work, are subject to this License. This License applies
128
+ separately for each version of the Licensed Work and the Change Date may vary
129
+ for each version of the Licensed Work released by Licensor.
130
+
131
+ You must conspicuously display this License on each original or modified copy
132
+ of the Licensed Work. If you receive the Licensed Work in original or
133
+ modified form from a third party, the terms and conditions set forth in this
134
+ License apply to your use of that work.
135
+
136
+ Any use of the Licensed Work in violation of this License will automatically
137
+ terminate your rights under this License for the current and all other
138
+ versions of the Licensed Work.
139
+
140
+ This License does not grant you any right in any trademark or logo of
141
+ Licensor or its affiliates (provided that you may use a trademark or logo of
142
+ Licensor as expressly required by this License).
143
+
144
+ TO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVIDED ON
145
+ AN "AS IS" BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS,
146
+ EXPRESS OR IMPLIED, INCLUDING (WITHOUT LIMITATION) WARRANTIES OF
147
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND
148
+ TITLE.
149
+
150
+ MariaDB hereby grants you permission to use this License's text to license
151
+ your works, and to refer to it using the trademark "Business Source License",
152
+ as long as you comply with the Covenants of Licensor below.
153
+
154
+ -----------------------------------------------------------------------------
155
+
156
+ Covenants of Licensor
157
+
158
+ In consideration of the right to use this License's text and the "Business
159
+ Source License" name and trademark, Licensor covenants to MariaDB, and to all
160
+ other recipients of the licensed work to be provided by Licensor:
161
+
162
+ 1. To specify as the Change License the GPL Version 2.0 or any later version,
163
+ or a license that is compatible with GPL Version 2.0 or a later version,
164
+ where "compatible" means that software provided under the Change License
165
+ can be included in a program with software provided under GPL Version 2.0
166
+ or a later version. Licensor may specify additional Change Licenses without
167
+ limitation.
168
+
169
+ 2. To either: (a) specify an additional grant of rights to use that does not
170
+ impose any additional restriction on the right granted in this License, as
171
+ the Additional Use Grant; or (b) insert the text "None".
172
+
173
+ 3. To specify a Change Date.
174
+
175
+ 4. Not to modify this License in any other way.
176
+
177
+ -----------------------------------------------------------------------------
178
+
179
+ Notice
180
+
181
+ The Business Source License (this document, or the "License") is not an Open
182
+ Source license. However, the Licensed Work will eventually be made available
183
+ under an Open Source License, as stated in this License.
package/README.md CHANGED
@@ -1,45 +1,59 @@
1
1
  # @memberjunction/ng-realtime-channels
2
2
 
3
- ## ⚠️ IMPORTANT NOTICE ⚠️
3
+ Build realtime-agent channels in Angular without the call overlay. A small package on purpose: it depends on the channel contract (`@memberjunction/realtime-runtime`, `@memberjunction/ai-core-plus`) and Angular's core, and nothing else of MemberJunction's UI (no overlay, no Explorer, no router), so an embed or an Open App can use it without pulling in the conversations stack.
4
4
 
5
- **This package is created solely for the purpose of setting up OIDC (OpenID Connect) trusted publishing with npm.**
5
+ The how-to is [`guides/REALTIME_CHANNELS_GUIDE.md`](../../../../guides/REALTIME_CHANNELS_GUIDE.md); a complete worked example is [`@memberjunction/ng-realtime-channel-examples`](../realtime-channel-examples/README.md).
6
6
 
7
- This is **NOT** a functional package and contains **NO** code or functionality beyond the OIDC setup configuration.
7
+ ## What is in it
8
8
 
9
- ## Purpose
9
+ | Export | Purpose |
10
+ |---|---|
11
+ | `AngularComponentChannel<TComponent>` | A base class that turns an **existing** Angular component into a realtime channel surface without rewriting it. You write a descriptor and a few binding functions; the adapter owns binding, perception, verbs, completion, persistence and pictures. |
12
+ | `ChannelSurfaceEvent` | What a component's output becomes: `{ Name, Payload?, Author?, Perceive? }`. |
13
+ | `EnableChannelFrameCapture(options?)` | Opts a host in to showing the model pictures of channel surfaces: registers a bounded `html-to-image` based rasterizer. Returns a function that removes it. |
14
+ | `CreateDomFrameCapturer(options?)`, `DomFrameCaptureOptions`, `DomRasterizer` | Build a capturer with different limits or a different rasterizer. |
15
+ | `ChannelFrameCapture`, `ElementFrameCapturer` | The singleton that holds the host's capturer (`Instance.Register(fn \| null)`, `Instance.Capturer`). |
10
16
 
11
- This package exists to:
12
- 1. Configure OIDC trusted publishing for the package name `@memberjunction/ng-realtime-channels`
13
- 2. Enable secure, token-less publishing from CI/CD workflows
14
- 3. Establish provenance for packages published under this name
17
+ ## `AngularComponentChannel`
15
18
 
16
- ## What is OIDC Trusted Publishing?
19
+ ```ts
20
+ @RegisterClass(BaseRealtimeChannelClient, 'SudokuChannel')
21
+ export class SudokuChannel extends AngularComponentChannel<SudokuComponent> {
22
+ protected readonly ComponentClass: Type<SudokuComponent> = SudokuComponent;
23
+ protected readonly Descriptor: RealtimeChannelDescriptor = { Key: 'Sudoku', /* ... for the model ... */ };
17
24
 
18
- OIDC trusted publishing allows package maintainers to publish packages directly from their CI/CD workflows without needing to manage npm access tokens. Instead, it uses OpenID Connect to establish trust between the CI/CD provider (like GitHub Actions) and npm.
25
+ protected ReadSurfaceState(c: SudokuComponent): JSONObject { return { board: c.Board, moves: c.MoveCount }; }
26
+ protected ApplySurfaceVerb(c: SudokuComponent, verb: string, args: JSONObject, actor: RealtimeChannelActor): RealtimeChannelVerbResult { /* ... */ }
27
+ protected SurfaceEvents(c: SudokuComponent): Observable<ChannelSurfaceEvent> { return c.CellChanged.pipe(map(/* ... */)); }
28
+ }
29
+ export function LoadSudokuChannel(): void {}
30
+ ```
19
31
 
20
- ## Setup Instructions
32
+ Required members: `ComponentClass`, `Descriptor`, `ReadSurfaceState`, `ApplySurfaceVerb`, `SurfaceEvents`. Optional: `OnSurfaceOpen` (apply `open` inputs), `SurfaceCompletion` (a stream that becomes `Complete(output)`), `OnSurfaceBound` (restore a component created again from the last state), `SurfaceElement` (the root element, so the model can be shown a picture). A subclass that overrides `OnInitialize` must call `super.OnInitialize()`.
21
33
 
22
- To properly configure OIDC trusted publishing for this package:
34
+ What the adapter does:
23
35
 
24
- 1. Go to [npmjs.com](https://www.npmjs.com/) and navigate to your package settings
25
- 2. Configure the trusted publisher (e.g., GitHub Actions)
26
- 3. Specify the repository and workflow that should be allowed to publish
27
- 4. Use the configured workflow to publish your actual package
36
+ * **Binding.** `BindSurface` subscribes to `SurfaceEvents` and `SurfaceCompletion`, restores the last state through `OnSurfaceBound`, applies `open` inputs that arrived early and releases waiting verbs. `UnbindSurface` keeps the last state and lets go. A collapsed-then-expanded panel creates a new component, so durable state belongs to the channel.
37
+ * **Perception.** Every event, and every successful verb, is recorded as a change: observers get a typed event and the model gets one coalesced delta note, gated by exposure policy. An event emitted while the adapter is running the agent's verb is attributed to the agent.
38
+ * **Verbs.** Resolved against the descriptor (case-insensitive), refused for the agent when exposure is below the verb's `ReturnsChannelData`, validated against the parameter schema, serialized, run on the component. A throw becomes a `verb_failed` result the model can read, and is logged.
39
+ * **A verb with no surface.** It waits, bounded (`SurfaceBindTimeoutMs`, 5 s), for the component to bind and runs against the real one; if it never binds the call fails with `surface_unavailable` and a message telling the agent to ask the user to open it. Not a hidden headless instance (it would hold state nobody is looking at) and not queue-and-acknowledge (the agent needs the real outcome).
40
+ * **A verb that never answers.** Each verb has a bounded execution time (`VerbTimeoutMs`, 15 s, overridable; a non-positive value turns it off). On timeout the call fails with `verb_timeout` ("The X didn't respond to \"play\" within 15s; try again or ask the user."), the queue is released and the timeout is logged once with the channel and verb. The adapter cannot cancel the promise: a late result is never delivered, a late failure is logged, and a late success (the component changed after the agent was told it had not) is recorded as a change so the next perception note shows the real state. Nothing is rolled back, so the component's own rules must reject a duplicate retry.
41
+ * **Persistence.** `SerializeState()` and `RestoreState()` carry the last state as JSON (a non-object is refused).
42
+ * **Pictures.** If `SurfaceElement` returns an element and the host called `EnableChannelFrameCapture`, the channel sources the model's video track and a frame is pushed after each user change, only while the effective exposure is `'pixels'` and a video track is established.
28
43
 
29
- ## DO NOT USE THIS PACKAGE
44
+ ## The rasterizer
30
45
 
31
- This package is a placeholder for OIDC configuration only. It:
32
- - Contains no executable code
33
- - Provides no functionality
34
- - Should not be installed as a dependency
35
- - Exists only for administrative purposes
46
+ Core ships no rasterizer: it is a heavy dependency every embed would pay for. A host that wants the model to see surfaces calls `EnableChannelFrameCapture()` once at startup, **before a session is minted** (Explorer does this in `ExplorerAppComponent`). The capturer is bounded (3000 nodes, 4 s, one capture at a time, a 1024 px longest edge, no web fonts) and fails soft: it costs the model a frame, never a call, and after three consecutive failures (or at once on one that cannot recover) turns itself off for the session and logs one reason.
36
47
 
37
- ## More Information
48
+ ## Layering
38
49
 
39
- For more details about npm's trusted publishing feature, see:
40
- - [npm Trusted Publishing Documentation](https://docs.npmjs.com/generating-provenance-statements)
41
- - [GitHub Actions OIDC Documentation](https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/about-security-hardening-with-openid-connect)
50
+ Layer **L1 (widgets)**: no router, no Explorer, no overlay. See [`guides/UI_LAYERING_GUIDE.md`](../../../../guides/UI_LAYERING_GUIDE.md).
42
51
 
43
- ---
52
+ ## Testing
44
53
 
45
- **Maintained for OIDC setup purposes only**
54
+ ```bash
55
+ cd packages/Angular/Generic/realtime-channels
56
+ pnpm test # node preset (adapter) + jsdom preset (rasterizer)
57
+ pnpm run test:types # typecheck the specs
58
+ pnpm run build
59
+ ```
@@ -0,0 +1,244 @@
1
+ /**
2
+ * @fileoverview {@link AngularComponentChannel}: turns an EXISTING Angular component into a realtime channel surface
3
+ * without rewriting it.
4
+ *
5
+ * A channel is what an agent and a user both operate during a call: the agent acts through verbs, perceives through
6
+ * state notes (and, if allowed, pictures), and the user acts directly on the surface. Writing one from scratch means
7
+ * writing the whole contract (descriptor, perception, verbs, binding the surface, completion). This base class owns the
8
+ * mechanics so a channel over a component you already have is a descriptor plus a few binding functions:
9
+ *
10
+ * ```ts
11
+ * @RegisterClass(BaseRealtimeChannelClient, 'SudokuChannel')
12
+ * export class SudokuChannel extends AngularComponentChannel<SudokuComponent> {
13
+ * protected readonly ComponentClass = SudokuComponent;
14
+ * protected readonly Descriptor: RealtimeChannelDescriptor = { Key: 'Sudoku', ... };
15
+ * protected ReadSurfaceState(c: SudokuComponent): JSONObject { return { board: c.Board, moves: c.MoveCount }; }
16
+ * protected ApplySurfaceVerb(c: SudokuComponent, verb: string, args: JSONObject): RealtimeChannelVerbResult { ... }
17
+ * protected SurfaceEvents(c: SudokuComponent): Observable<ChannelSurfaceEvent> { return c.CellChanged.pipe(map(...)); }
18
+ * }
19
+ * export function LoadSudokuChannel(): void {}
20
+ * ```
21
+ *
22
+ * ## What the adapter does for you
23
+ *
24
+ * - **Binding.** The overlay creates the component and hands it to {@link BindSurface}; the adapter subscribes to
25
+ * {@link SurfaceEvents}, applies anything that arrived early, and lets go cleanly on {@link UnbindSurface} (a host may
26
+ * create a NEW component instance for the same channel, e.g. when the overlay is recreated, so durable state belongs
27
+ * to the channel, see below).
28
+ * - **Perception.** Every event the component emits, and every verb the agent runs, is recorded as a change: observers
29
+ * see a typed event, and the model gets ONE coalesced structured note carrying a delta of {@link ReadSurfaceState}
30
+ * (see `RecordChange` in the base class). Exposure policy gates it like any channel.
31
+ * - **Verbs.** Parameters are validated against the descriptor's schema before your code runs; a verb the agent may not
32
+ * have (exposure) is refused by the dispatcher; the outcome is a structured result the model can recover from.
33
+ * - **Completion.** An optional {@link SurfaceCompletion} stream becomes `Complete(output)`.
34
+ * - **Pictures.** If you can name the component's root element ({@link SurfaceElement}) and the host registered a
35
+ * rasterizer (`EnableChannelFrameCapture`), the channel shows the model what the component looks like.
36
+ * - **Persistence.** The last state is saved as the channel's state of record and handed back to
37
+ * {@link OnSurfaceBound} when the surface is created again (collapse/expand, or a resumed session).
38
+ *
39
+ * ## When there is no surface
40
+ *
41
+ * A verb can arrive while no component is bound (the panel was just opened and the overlay is still creating the
42
+ * component). The adapter does NOT run the verb against a hidden second instance, and it does NOT acknowledge it and apply
43
+ * it later: the agent needs the real outcome (a move can be refused), and a second instance would hold state the user is
44
+ * not looking at. Instead the call WAITS, bounded ({@link SurfaceBindTimeoutMs}, 5 s), for the surface, runs once it
45
+ * binds (calls are serialized, so order is preserved), and fails with `'surface_unavailable'` and a message the agent can
46
+ * act on ("ask the user to open it") if it never binds. Seed inputs of `open` are different: there is nothing to report back
47
+ * but success, so they are applied when the surface binds. (A channel with no surface at all, a pure wire, does not need this
48
+ * class.)
49
+ *
50
+ * ## A verb that never answers
51
+ *
52
+ * Verbs run one at a time, so one that never settles would stall every later call. Each verb therefore has a bounded execution
53
+ * time ({@link VerbTimeoutMs}, 15 s). On timeout the call fails with `'verb_timeout'` and a message the agent can act on ("try
54
+ * again or ask the user"), the queue is released, and the timeout is logged once with the channel and verb. The adapter cannot
55
+ * cancel the promise your {@link ApplySurfaceVerb} returned, so what happens next is deliberately defined:
56
+ *
57
+ * - A **late result is never delivered**: the agent was already told the verb failed, and it is not told otherwise.
58
+ * - A late **failure** is logged and dropped.
59
+ * - A late **success** means the component DID change after the agent was told it had not. Nothing is rolled back (the
60
+ * component's own rules decide whether a retry is accepted, which is why they must live in the component), but the change is
61
+ * recorded like any other so the next perception note shows the model the real state.
62
+ * - The next queued verb may run while the late one is still pending, so a verb should not assume exclusive access to the
63
+ * component for longer than it takes to settle.
64
+ *
65
+ * @module @memberjunction/ng-realtime-channels
66
+ */
67
+ import type { Type } from '@angular/core';
68
+ import { Observable } from 'rxjs';
69
+ import type { JSONObject } from '@memberjunction/ai';
70
+ import { type RealtimeChannelActor, type RealtimeChannelDescriptor } from '@memberjunction/ai-core-plus';
71
+ import { BaseRealtimeChannelClient, type RealtimeChannelVerbResult } from '@memberjunction/realtime-runtime';
72
+ /**
73
+ * Something the wrapped component did that the channel should know about: a user's move, a selection, a state
74
+ * change worth telling the model about. Return these from {@link AngularComponentChannel.SurfaceEvents}.
75
+ */
76
+ export interface ChannelSurfaceEvent {
77
+ /** The event's name; declare it in the descriptor's `Events` so the agent knows it exists. */
78
+ Name: string;
79
+ /** The event's payload (JSON). */
80
+ Payload?: JSONObject;
81
+ /**
82
+ * Who caused it. Default `'user'`, except that an event emitted while the adapter is running an agent's verb is
83
+ * attributed to the agent (the component echoes the agent's own move through the same outputs the user's use).
84
+ */
85
+ Author?: RealtimeChannelActor | 'system';
86
+ /** Set `false` for an event observers should see but the model should not be told about. Default `true`. */
87
+ Perceive?: boolean;
88
+ }
89
+ /**
90
+ * Base class for a realtime channel whose surface is an existing Angular component. See the file comment for the model.
91
+ *
92
+ * @typeParam TComponent The component class the channel shows and operates.
93
+ */
94
+ export declare abstract class AngularComponentChannel<TComponent extends object> extends BaseRealtimeChannelClient<TComponent> {
95
+ /** The existing component to show as the channel's surface. The overlay creates it; the adapter binds to it. */
96
+ protected abstract readonly ComponentClass: Type<TComponent>;
97
+ /**
98
+ * The channel's self-description: what it is, what it holds (nouns), what it accepts (verbs with parameter schemas and
99
+ * `InvokableBy`), what it emits (events), how it opens (inputs) and what it hands back (output). Pure data, and the only
100
+ * thing an agent has to go on, so write `Instructions` and every description for the MODEL.
101
+ */
102
+ protected abstract readonly Descriptor: RealtimeChannelDescriptor;
103
+ /**
104
+ * The channel's state as the model should perceive it: one entry per noun in the descriptor, JSON only. Called whenever
105
+ * a perception note is built, so it must be a pure, cheap read of the component.
106
+ *
107
+ * @param component The bound component.
108
+ */
109
+ protected abstract ReadSurfaceState(component: TComponent): JSONObject;
110
+ /**
111
+ * Runs one verb on the component. The adapter has already resolved the verb against the descriptor and validated
112
+ * `args` against its schema, so trust the shape; check the GAME or DOCUMENT rules (is it the agent's turn? is the cell
113
+ * free?) and return a failure result with a message the model can act on rather than throwing.
114
+ *
115
+ * @param component The bound component.
116
+ * @param verb The verb's name, as declared in the descriptor.
117
+ * @param args The validated parameters.
118
+ * @param actor Who is acting: the agent, or the user acting through the same verb.
119
+ */
120
+ protected abstract ApplySurfaceVerb(component: TComponent, verb: string, args: JSONObject, actor: RealtimeChannelActor): RealtimeChannelVerbResult | Promise<RealtimeChannelVerbResult>;
121
+ /**
122
+ * What the component emits that the channel should react to, as a stream. Subscribed when the surface binds and
123
+ * unsubscribed when it unbinds. Merge the component's outputs here; map each to a {@link ChannelSurfaceEvent}.
124
+ *
125
+ * @param component The bound component.
126
+ */
127
+ protected abstract SurfaceEvents(component: TComponent): Observable<ChannelSurfaceEvent>;
128
+ /**
129
+ * Applies the seed inputs of `open` to the component (optional). Return a failure to refuse the open. Called when the
130
+ * surface is bound, immediately if it already is.
131
+ *
132
+ * @param component The bound component.
133
+ * @param inputs The validated open inputs.
134
+ */
135
+ protected OnSurfaceOpen?(component: TComponent, inputs: JSONObject): void | RealtimeChannelVerbResult | Promise<void | RealtimeChannelVerbResult>;
136
+ /**
137
+ * Emits when the component's job is done and it has something to hand back (a finished game, a submitted form):
138
+ * becomes `Complete(output)`, validated against the descriptor's `Output`. Optional.
139
+ *
140
+ * @param component The bound component.
141
+ */
142
+ protected SurfaceCompletion?(component: TComponent): Observable<JSONObject>;
143
+ /**
144
+ * Called each time a component is bound, with the last state the channel knew (this session's, or the saved one on a
145
+ * resumed session), so a component created fresh (a panel expanded again, a session resumed) can be restored to it.
146
+ * Optional; a component that keeps its own state elsewhere does not need it.
147
+ *
148
+ * @param component The newly bound component.
149
+ * @param lastState The last known state, or `null` when there is none.
150
+ */
151
+ protected OnSurfaceBound?(component: TComponent, lastState: JSONObject | null): void;
152
+ /**
153
+ * The component's root element, so the channel can show the model a picture of it. Optional: without it (or without a
154
+ * rasterizer registered by the host) the channel offers state only. A component can expose its host element by
155
+ * injecting `ElementRef`.
156
+ *
157
+ * @param component The bound component.
158
+ */
159
+ protected SurfaceElement?(component: TComponent): HTMLElement | null;
160
+ /** How long a verb waits for the surface to bind before failing with `'surface_unavailable'`, in ms. Override to change it. */
161
+ protected SurfaceBindTimeoutMs: number;
162
+ /**
163
+ * How long {@link ApplySurfaceVerb} may run before the call fails with `'verb_timeout'` and the queue is released, in ms
164
+ * (15 s by default; the surface bind wait is separate, see {@link SurfaceBindTimeoutMs}). Override it for a component whose
165
+ * verbs are legitimately slow; a value that is not a positive number turns the limit off, which is only safe for a verb that
166
+ * is guaranteed to settle. See the file comment for what happens to a verb that settles after the timeout.
167
+ */
168
+ protected VerbTimeoutMs: number;
169
+ get ChannelName(): string;
170
+ get TabTitle(): string;
171
+ GetDescriptor(): RealtimeChannelDescriptor;
172
+ /** The channel has no native tools: its verbs are reached through the `ContextTool` proxy. */
173
+ GetToolDefinitions(): never[];
174
+ GetSurfaceComponent(): Type<TComponent>;
175
+ private surface;
176
+ private surfaceSubscriptions;
177
+ private bindWaiters;
178
+ private lastState;
179
+ private pendingOpenInputs;
180
+ private verbChain;
181
+ private applyingActor;
182
+ /** The bound component, or `null` while no surface is up. */
183
+ protected get Surface(): TComponent | null;
184
+ /**
185
+ * Opts into pictures when the subclass can name the component's element and the host registered a rasterizer. Subclasses
186
+ * that override this MUST call `super.OnInitialize()`.
187
+ */
188
+ protected OnInitialize(): void;
189
+ /**
190
+ * The overlay created the component: bind to it. Subscribes to its events and completion, restores the last known
191
+ * state, applies any seed inputs that arrived before it existed, and releases verbs that were waiting for it.
192
+ */
193
+ BindSurface(component: TComponent): void;
194
+ /** The component is going away (the panel collapsed, or the session ended): keep its last state, let go of it. */
195
+ UnbindSurface(): void;
196
+ private unbindSubscriptions;
197
+ /** Resolves with the bound component, waiting (bounded) for it to bind; `null` when it never does. */
198
+ private whenSurfaceBound;
199
+ /**
200
+ * The channel's state: the live component's, or the last known when no component is bound (so a note built while the
201
+ * panel is collapsed still describes the channel truthfully).
202
+ */
203
+ GetState(): JSONObject;
204
+ /** Reads the component's state, logging and returning `null` if the subclass's reader throws (a perception note must never break a call). */
205
+ private safeReadState;
206
+ /** The state of record: the last known state as JSON, or `null` before there is any. */
207
+ SerializeState(): string | null;
208
+ /**
209
+ * A saved state came back (a resumed session): hold it, and hand it to {@link OnSurfaceBound} when the component is
210
+ * created. Returns `false` for anything that is not a JSON object.
211
+ */
212
+ RestoreState(stateJson: string): boolean;
213
+ /**
214
+ * Seeds the surface with the open inputs: now if the component is bound, otherwise when it binds (there is nothing to
215
+ * report back but success, so there is nothing to wait for).
216
+ */
217
+ protected OnOpen(inputs: JSONObject): Promise<void | RealtimeChannelVerbResult>;
218
+ private applyPendingOpen;
219
+ /**
220
+ * Runs one verb. Verbs are serialized (a second call waits for the first), wait (bounded) for the surface, and run
221
+ * against the real component, so the outcome the agent hears is the outcome the user sees.
222
+ */
223
+ ApplyVerb(verb: string, args: JSONObject, actor: RealtimeChannelActor): Promise<RealtimeChannelVerbResult>;
224
+ private runVerb;
225
+ private applyOnSurface;
226
+ /**
227
+ * Runs {@link ApplySurfaceVerb} with a bounded execution time. Settles with the verb's result, with `TimedOut` when it did
228
+ * not answer in time, or rejects with what it threw. Once it has timed out, whatever it later does is handled by
229
+ * {@link onLateVerbSettle} and never reaches the caller: the promise is already settled, so there is no second result.
230
+ */
231
+ private runWithTimeout;
232
+ /**
233
+ * A verb settled AFTER it timed out. The agent already has its answer (failure), so the late result is never delivered. A
234
+ * late failure is logged. A late success means the component changed after the agent was told it had not: it is recorded as
235
+ * a change (when the same component is still on screen) so the next perception note shows the model the real state.
236
+ */
237
+ private onLateVerbSettle;
238
+ /** The component emitted something: tell observers, and (unless told not to) record it as a change the model perceives. */
239
+ private onSurfaceEvent;
240
+ /** A picture of the component, or `null` when there is none to send (see the rules in the Interactive Component channel). */
241
+ private captureFrame;
242
+ Dispose(): void;
243
+ }
244
+ //# sourceMappingURL=angular-component-channel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"angular-component-channel.d.ts","sourceRoot":"","sources":["../../src/lib/angular-component-channel.ts"],"names":[],"mappings":"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"}