@touchcastllc/napster-companion-api-dev 1.0.0-alpha.65 → 1.0.0-alpha.67

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.
@@ -0,0 +1,9 @@
1
+ import type { CompanionFunction } from "../../types";
2
+ import type { EdgeMcpApi } from "./edge-mcp-types";
3
+ /**
4
+ * Construct the `invokeCapability` function definition from a live Edge MCP
5
+ * api ref. Returns `null` when no capabilities are published — in that case
6
+ * there is nothing for the agent to call and the SDK should not register the
7
+ * function at all.
8
+ */
9
+ export declare function buildInvokeCapabilityFunction(api: EdgeMcpApi): CompanionFunction | null;
@@ -0,0 +1,95 @@
1
+ import type { EdgeMcpApi, FunctionCallEvent, SendCommand } from "./edge-mcp-types";
2
+ export interface EdgeMcpBridgeOptions {
3
+ /**
4
+ * The SDK's `sendCommand` method, bound to the live instance so the
5
+ * bridge can emit `send_message` (for state relays) and
6
+ * `function_call_output` (for invoke results).
7
+ */
8
+ sendCommand: SendCommand;
9
+ /**
10
+ * When true, the bridge logs attach status, every dispatched function
11
+ * call, and every state push relay to the developer console. Match the
12
+ * SDK's own `debug` flag.
13
+ *
14
+ * Default: `false`.
15
+ */
16
+ debug?: boolean;
17
+ /**
18
+ * How long `attach()` waits for a producer publication before giving up.
19
+ * The SDK is not blocked beyond this duration even when no Edge MCP
20
+ * exists in the page.
21
+ *
22
+ * Default: `1500` (ms).
23
+ */
24
+ attachTimeoutMs?: number;
25
+ /**
26
+ * When true, Edge MCP state pushes are forwarded to the agent as
27
+ * `role: 'system'` messages. Set false if the consuming application
28
+ * wants to control state delivery itself.
29
+ *
30
+ * Default: `true`.
31
+ */
32
+ relayStatePushes?: boolean;
33
+ }
34
+ export declare class EdgeMcpBridge {
35
+ private api;
36
+ private unsubStateChange;
37
+ private disposed;
38
+ private readonly options;
39
+ constructor(options: EdgeMcpBridgeOptions);
40
+ /**
41
+ * Discover an Edge MCP instance in the page and subscribe to state
42
+ * changes. Returns the discovered api ref, or `null` if no Edge MCP
43
+ * publishes within the timeout.
44
+ *
45
+ * Safe to await from the SDK's `init()` path. Failure is silent — the
46
+ * SDK continues to run exactly as it would without Edge MCP present.
47
+ */
48
+ attach(): Promise<EdgeMcpApi | null>;
49
+ /** True if `attach()` succeeded and the bridge has a live api ref. */
50
+ get isAttached(): boolean;
51
+ /**
52
+ * Direct access to the attached Edge MCP api ref, for callers that need
53
+ * to read `listCapabilities()` themselves (for example, to build the
54
+ * `invokeCapability` function definition for `set_settings.functions`).
55
+ *
56
+ * Returns `null` if not attached.
57
+ */
58
+ getApi(): EdgeMcpApi | null;
59
+ /**
60
+ * Dispatch an incoming function call from the agent. The SDK's
61
+ * data-channel message handler is responsible for normalizing the
62
+ * upstream event shape into `FunctionCallEvent` before calling this.
63
+ *
64
+ * Only the Edge MCP wrapper function (see
65
+ * `INVOKE_CAPABILITY_FUNCTION_NAMES`) is handled. Anything else is silently
66
+ * ignored so the bridge can coexist with other tool paths (vendor-registered
67
+ * tools, customer's own `onFunctionCall`, etc.).
68
+ *
69
+ * Always responds via `function_call_output` — success, validation
70
+ * failure, and unexpected error all produce a structured result the
71
+ * agent can read and narrate back to the user.
72
+ */
73
+ dispatchFunctionCall(event: FunctionCallEvent): Promise<void>;
74
+ /**
75
+ * Tear down subscriptions and drop the Edge MCP api ref. Call from the
76
+ * SDK's `destroy()` path. Idempotent.
77
+ */
78
+ dispose(): void;
79
+ /**
80
+ * Forward an Edge MCP state push to the agent as a system message.
81
+ *
82
+ * `role: 'system'` injects context without rendering to the user.
83
+ * `trigger_response: false` keeps the avatar from speaking on every
84
+ * state change. `delay: true` waits for the agent to finish its current
85
+ * speech before delivering, so it doesn't interrupt mid-sentence.
86
+ */
87
+ private relayStateChange;
88
+ /**
89
+ * Emit a `function_call_output` command carrying the bridge's result for
90
+ * a given `call_id`. The `output` field is a JSON-encoded string per the
91
+ * Realtime protocol convention.
92
+ */
93
+ private sendOutput;
94
+ private log;
95
+ }
@@ -0,0 +1,13 @@
1
+ import type { EdgeMcpApi } from "./edge-mcp-types";
2
+ /**
3
+ * Discover an Edge MCP instance published at the well-known global slot.
4
+ *
5
+ * Resolves with the api ref if found; resolves with `null` after the
6
+ * timeout if no Edge MCP shows up. Never rejects.
7
+ *
8
+ * @param timeoutMs How long to wait for a producer if none is published
9
+ * yet. Default: 1500ms — short enough not to delay the
10
+ * SDK noticeably, long enough to cover normal hydration
11
+ * ordering.
12
+ */
13
+ export declare function discoverEdgeMcp(timeoutMs?: number): Promise<EdgeMcpApi | null>;
@@ -0,0 +1,94 @@
1
+ /**
2
+ * Metadata exposed for one capability the agent can invoke.
3
+ * Returned by `EdgeMcpApi.listCapabilities()`.
4
+ */
5
+ export interface EdgeMcpCapabilityMeta {
6
+ /** Domain-named identifier, e.g. `'docs.search'` or `'cart.add'`. */
7
+ name: string;
8
+ /** One-sentence description used by the agent to decide WHEN to invoke. */
9
+ description: string;
10
+ /** JSON Schema describing valid arguments. Always present. */
11
+ inputSchema: Record<string, unknown>;
12
+ /** JSON Schema describing the return value, or `null`. */
13
+ outputSchema: Record<string, unknown> | null;
14
+ /** Governance tier — `'read' | 'reversible' | 'irreversible'`. */
15
+ sideEffect: "read" | "reversible" | "irreversible";
16
+ /** True if re-running with the same args is safe. */
17
+ idempotent: boolean;
18
+ }
19
+ /** Result returned by `EdgeMcpApi.invoke()`. */
20
+ export type EdgeMcpInvokeResult = {
21
+ ok: true;
22
+ result: unknown;
23
+ sideEffect: string;
24
+ } | {
25
+ ok: false;
26
+ error: string;
27
+ };
28
+ /** Payload delivered to `onStateChange` handlers. */
29
+ export interface EdgeMcpDelta {
30
+ name: string;
31
+ value: unknown;
32
+ }
33
+ /**
34
+ * The subset of the Edge MCP API this bridge consumes.
35
+ *
36
+ * The actual `EdgeMcp` interface defined in the `@napster/edge-mcp` package
37
+ * also includes `registerCapability` / `registerStateProvider` / `dispose`,
38
+ * but those are app-side concerns the SDK never calls. Keeping the shape
39
+ * minimal makes the structural type easier to satisfy for alternative
40
+ * implementations.
41
+ */
42
+ export interface EdgeMcpApi {
43
+ listCapabilities: () => EdgeMcpCapabilityMeta[];
44
+ invoke: (name: string, args?: unknown) => Promise<EdgeMcpInvokeResult>;
45
+ getState?: (name: string) => Promise<unknown>;
46
+ snapshot?: () => Promise<Record<string, unknown>>;
47
+ /**
48
+ * Optional — present in any v1-compliant implementation. The SDK uses it
49
+ * to relay state pushes to the agent as system messages.
50
+ */
51
+ onStateChange?: (handler: (delta: EdgeMcpDelta) => void) => () => void;
52
+ }
53
+ /**
54
+ * Shape of the object published to the well-known global slot.
55
+ * Defined in Edge MCP spec §4.2.
56
+ */
57
+ export interface PublishedEdgeMcp {
58
+ version: 1;
59
+ api: EdgeMcpApi;
60
+ }
61
+ /**
62
+ * Normalized shape of an incoming function-call event.
63
+ *
64
+ * The exact wire shape varies by upstream protocol (Azure OpenAI Realtime
65
+ * uses `response.function_call_arguments.done`); the SDK's data-channel
66
+ * handler is responsible for extracting these three fields before calling
67
+ * `EdgeMcpBridge.dispatchFunctionCall`.
68
+ */
69
+ export interface FunctionCallEvent {
70
+ /** The tool/function name the agent invoked. */
71
+ name: string;
72
+ /**
73
+ * The arguments the agent produced. The server's
74
+ * `function_implicitly_called` event delivers these as an already-parsed
75
+ * object (`{ tool_name, arguments }`); other protocols may deliver a
76
+ * JSON-encoded string. The bridge accepts both.
77
+ */
78
+ arguments: unknown;
79
+ /** Unique identifier the server uses to pair the call with its output. */
80
+ call_id: string;
81
+ }
82
+ /**
83
+ * Minimal `sendCommand` signature.
84
+ *
85
+ * Mirrors the existing `NapsterCompanionApiInstance.sendCommand` without
86
+ * coupling the bridge to the full `DataChannelCommand` union — the bridge
87
+ * only sends two command types:
88
+ * - `{ type: 'send_message', data: { role, text, trigger_response, delay } }`
89
+ * - `{ type: 'function_call_output', data: { call_id, output } }`
90
+ */
91
+ export type SendCommand = (command: {
92
+ type: string;
93
+ data: Record<string, unknown>;
94
+ }) => void;
@@ -0,0 +1,5 @@
1
+ export { EdgeMcpBridge } from "./edge-mcp-bridge";
2
+ export type { EdgeMcpBridgeOptions } from "./edge-mcp-bridge";
3
+ export { buildInvokeCapabilityFunction } from "./buildInvokeCapabilityFunction";
4
+ export { normalizeFunctionCallEvent } from "./normalizeFunctionCallEvent";
5
+ export type { EdgeMcpApi, EdgeMcpCapabilityMeta, EdgeMcpInvokeResult, EdgeMcpDelta, FunctionCallEvent, } from "./edge-mcp-types";
@@ -0,0 +1,11 @@
1
+ import type { FunctionCallEvent } from "./edge-mcp-types";
2
+ /**
3
+ * Returns a normalized `FunctionCallEvent` if `message` represents a function
4
+ * call, otherwise `null`. Callers route a non-null result to
5
+ * `EdgeMcpBridge.dispatchFunctionCall` and skip normal chat handling.
6
+ *
7
+ * Requires `name` and `call_id`. `arguments` is passed through as-is (object
8
+ * for `function_implicitly_called`, JSON string for realtime protocols, or
9
+ * absent for no-arg calls) — the bridge handles both shapes.
10
+ */
11
+ export declare function normalizeFunctionCallEvent(message: unknown): FunctionCallEvent | null;
@@ -66,7 +66,18 @@ export type StopVideoCommand = {
66
66
  type: DataChannelMessageType.STOP_VIDEO;
67
67
  data: null;
68
68
  };
69
- export type DataChannelCommand = SendMessageCommand | CancelCommand | SetSettingsCommand | StartVideoCommand | StopVideoCommand;
69
+ /** Result of an agent function call, paired with its originating `call_id`. */
70
+ export interface FunctionCallOutputData {
71
+ /** Identifier the server uses to pair the call with its output. */
72
+ call_id: string;
73
+ /** JSON-encoded string of the function result. */
74
+ output: string;
75
+ }
76
+ export type FunctionCallOutputCommand = {
77
+ type: DataChannelMessageType.FUNCTION_CALL_OUTPUT;
78
+ data: FunctionCallOutputData;
79
+ };
80
+ export type DataChannelCommand = SendMessageCommand | CancelCommand | SetSettingsCommand | StartVideoCommand | StopVideoCommand | FunctionCallOutputCommand;
70
81
  export declare const maxInactiveTimeoutDuration = 180000;
71
82
  export declare const defaultCountdownDuration = 30;
72
83
  export interface EventMessage {
@@ -42,6 +42,7 @@ export declare class InactiveOverlayManager {
42
42
  private currentTrigger;
43
43
  private isVisible;
44
44
  private readonly mountElement;
45
+ private pipTarget;
45
46
  private readonly callbacks;
46
47
  constructor(mountElement: HTMLElement, callbacks?: InactiveOverlayCallbacks);
47
48
  /**
@@ -62,6 +63,17 @@ export declare class InactiveOverlayManager {
62
63
  * Get the current trigger type if overlay is visible
63
64
  */
64
65
  getCurrentTrigger(): InactiveOverlayTrigger | null;
66
+ /**
67
+ * Set the PiP window body as the overlay target (or null when PiP closes).
68
+ * Relocates a visible overlay so it stays in front of the user.
69
+ */
70
+ setPipTarget(target: HTMLElement | null): void;
71
+ private getMountTarget;
72
+ /**
73
+ * Move a visible overlay into the current target document. The countdown
74
+ * keeps running since the same DOM node (and its timer) is preserved.
75
+ */
76
+ private relocate;
65
77
  /**
66
78
  * Handle continue button click
67
79
  */
@@ -17,4 +17,8 @@ export declare function createPiPManager(handlers: {
17
17
  onScreenShareToggle: () => void;
18
18
  isScreenShareSupported: () => boolean;
19
19
  onInteraction?: () => void;
20
+ /** PiP window opened — receives its body so callers can render into it. */
21
+ onOpen?: (pipBody: HTMLElement) => void;
22
+ /** PiP window closed (by user or programmatically). */
23
+ onClose?: () => void;
20
24
  }): PiPController;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@touchcastllc/napster-companion-api-dev",
3
- "version": "1.0.0-alpha.65",
3
+ "version": "1.0.0-alpha.67",
4
4
  "keywords": [
5
5
  "napster",
6
6
  "companion-api",