@touchcastllc/napster-companion-api-dev 1.0.0-alpha.71 → 1.0.0-alpha.73

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.
@@ -1,56 +1,88 @@
1
- import type { EdgeMcpApi, FunctionCallEvent, SendCommand } from "./edge-mcp-types";
1
+ import type { FunctionCallEvent, SendCommand, EdgeMcpModelContext } from "./edge-mcp-types";
2
2
  export interface EdgeMcpBridgeOptions {
3
3
  /**
4
4
  * The SDK's `sendCommand`, bound to the live instance so the bridge can emit
5
- * `send_message` (state relays) and `send_function_output` (invoke results).
5
+ * `send_message` (state relays) and `send_function_output` (tool results).
6
6
  */
7
7
  sendCommand: SendCommand;
8
8
  /** Mirror the SDK's `debug` flag. Default: `false`. */
9
9
  debug?: boolean;
10
- /** How long `attach()` waits for an Edge MCP to publish. Default: `1500` ms. */
10
+ /** How long `attach()` polls for `document.modelContext`. Default: `1500` ms. */
11
11
  attachTimeoutMs?: number;
12
12
  /**
13
- * Forward Edge MCP state pushes to the agent as `role: 'system'` messages.
14
- * Set false to control state delivery yourself. Default: `true`.
13
+ * Forward toolkit state pushes (`resourceupdated`) to the agent as
14
+ * `role: 'system'` messages. Set false to handle state yourself. Default: `true`.
15
15
  */
16
16
  relayStatePushes?: boolean;
17
+ /**
18
+ * Register the page's WebMCP tools with the agent mid-session by pushing them
19
+ * as `set_settings.inline_functions` on attach and on every `toolchange`. Set
20
+ * false to manage the agent's function list yourself. Default: `true`.
21
+ */
22
+ registerInlineFunctions?: boolean;
17
23
  }
18
24
  export declare class EdgeMcpBridge {
19
- private api;
20
- private unsubStateChange;
25
+ private mc;
26
+ private tools;
27
+ private onToolChange;
28
+ private onResourceUpdated;
29
+ private lastInlineSig;
30
+ private sessionReady;
21
31
  private disposed;
22
32
  private readonly options;
23
33
  constructor(options: EdgeMcpBridgeOptions);
24
34
  /**
25
- * Discover an Edge MCP in the page and subscribe to its state changes.
26
- * Returns the api ref, or `null` if none publishes within the timeout.
27
- * Safe to fire from `init()` — failure is silent and non-fatal.
35
+ * Discover `document.modelContext` in the page, cache its tools, and wire up
36
+ * the `toolchange` / `resourceupdated` listeners. Returns the model context,
37
+ * or `null` if none appears within the timeout. Safe to fire from `init()` —
38
+ * failure is silent and non-fatal.
39
+ */
40
+ attach(): Promise<EdgeMcpModelContext | null>;
41
+ /** Attach to a known model context: cache tools and subscribe to events. */
42
+ private bind;
43
+ /** Re-read the tool catalog from the model context. */
44
+ private refreshTools;
45
+ /** Map the current WebMCP tools to `set_settings.inline_functions` definitions. */
46
+ private buildInlineFunctions;
47
+ /**
48
+ * Called by the SDK when the session reaches the "ready" state
49
+ * (`avatar_state_changed` → `state: "ready"`). This is the only safe moment to
50
+ * register tools — the realtime session silently drops `inline_functions` sent
51
+ * before it's ready (e.g. on data-channel open). Marks the session ready,
52
+ * resets the dedupe, and pushes the current tools. Re-fires on reconnect (a
53
+ * fresh "ready").
54
+ */
55
+ onSessionReady(): void;
56
+ /**
57
+ * Register the page's WebMCP tools with the agent by sending the complete
58
+ * current catalog as `set_settings.inline_functions`. Called on attach, on
59
+ * every toolchange, and on data-channel open, so tools registered mid-session
60
+ * reach the agent. No-op when not attached, when `registerInlineFunctions` is
61
+ * disabled, or when the catalog is unchanged since the last successful push.
28
62
  */
29
- attach(): Promise<EdgeMcpApi | null>;
30
- /** True if `attach()` succeeded and the bridge has a live api ref. */
63
+ private pushInlineFunctions;
64
+ /** True if `attach()` succeeded and the bridge has a live model context. */
31
65
  get isAttached(): boolean;
32
- /** The attached Edge MCP api ref, or `null` if not attached. */
33
- getApi(): EdgeMcpApi | null;
34
66
  /**
35
67
  * Dispatch a normalized agent function call. Handles it only when the name
36
- * matches a capability the attached Edge MCP currently exposes. The name can
37
- * arrive as the top-level `event.name` (direct call, args in
38
- * `event.arguments`) or nested in a wrapper tool's `tool_name` (args under
39
- * `arguments`/`args`). Anything else is ignored so the bridge coexists with
40
- * other tool paths. Matched calls always reply via `send_function_output`.
68
+ * matches a tool the page currently exposes. The name can arrive as the
69
+ * top-level `event.name` (direct call, args in `event.arguments`) or nested in
70
+ * a wrapper tool's `tool_name` (args under `arguments`/`args`). Anything else
71
+ * is ignored so the bridge coexists with other tool paths. Matched calls
72
+ * always reply via `send_function_output`.
41
73
  */
42
74
  dispatchFunctionCall(event: FunctionCallEvent): Promise<void>;
43
- /** Tear down subscriptions and drop the api ref. Idempotent. */
75
+ /** Tear down listeners and drop the model-context ref. Idempotent. */
44
76
  dispose(): void;
45
77
  /**
46
- * Forward an Edge MCP state push to the agent as a system message.
78
+ * Forward a toolkit resource update to the agent as a system message.
47
79
  * `trigger_response: false` keeps the avatar from speaking on every change;
48
80
  * `delay: true` waits for it to finish its current speech first.
49
81
  */
50
- private relayStateChange;
82
+ private relayResourceUpdate;
51
83
  /**
52
- * Emit a `send_function_output` for a `call_id`. `output` is JSON-encoded per
53
- * the Realtime protocol convention.
84
+ * Emit a `send_function_output` for a `call_id`. When `raw` is true the
85
+ * payload is already the output string; otherwise it is JSON-encoded.
54
86
  */
55
87
  private sendOutput;
56
88
  private log;
@@ -1,13 +1,14 @@
1
- import type { EdgeMcpApi } from "./edge-mcp-types";
1
+ import type { EdgeMcpModelContext } from "./edge-mcp-types";
2
+ /** Read `document.modelContext`, falling back to the deprecated navigator alias. */
3
+ export declare function getModelContext(): EdgeMcpModelContext | null;
2
4
  /**
3
- * Discover an Edge MCP instance published at the well-known global slot.
5
+ * Discover `document.modelContext`, polling briefly if it is not present yet.
4
6
  *
5
- * Resolves with the api ref if found; resolves with `null` after the
6
- * timeout if no Edge MCP shows up. Never rejects.
7
+ * Resolves with the model context if found, or `null` after `timeoutMs` if no
8
+ * WebMCP surface shows up. Never rejects.
7
9
  *
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.
10
+ * @param timeoutMs How long to wait for a late-installing polyfill. Default
11
+ * 1500ms — long enough to cover normal hydration ordering,
12
+ * short enough not to delay the SDK noticeably.
12
13
  */
13
- export declare function discoverEdgeMcp(timeoutMs?: number): Promise<EdgeMcpApi | null>;
14
+ export declare function discoverModelContext(timeoutMs?: number): Promise<EdgeMcpModelContext | null>;
@@ -1,94 +1,76 @@
1
- /**
2
- * Metadata exposed for one capability the agent can invoke.
3
- * Returned by `EdgeMcpApi.listCapabilities()`.
4
- */
5
- export interface EdgeMcpCapabilityMeta {
1
+ /** Tool metadata as returned by `document.modelContext.getTools()`. */
2
+ export interface EdgeMcpToolInfo {
6
3
  /** Domain-named identifier, e.g. `'docs.search'` or `'cart.add'`. */
7
4
  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;
5
+ /** One-sentence description the agent uses to decide WHEN to invoke. */
6
+ description?: string;
7
+ /**
8
+ * JSON Schema describing valid arguments. NOTE: the WebMCP polyfill returns
9
+ * this as a JSON **string** (per the spec's `ModelContextToolInfo`); a native
10
+ * implementation may return an object. Callers must handle both.
11
+ */
12
+ inputSchema?: Record<string, unknown> | string;
13
+ /** Optional human-readable label. */
14
+ title?: string;
32
15
  }
33
16
  /**
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.
17
+ * Payload of the toolkit's `resourceupdated` event (live-state extension).
18
+ * Mirrors MCP's `notifications/resources/updated`, but carries the value
19
+ * inline so the SDK can relay it without a follow-up read.
41
20
  */
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;
21
+ export interface EdgeMcpResourceUpdate {
22
+ uri: string;
23
+ value: unknown;
52
24
  }
53
25
  /**
54
- * Shape of the object published to the well-known global slot.
55
- * Defined in Edge MCP spec §4.2.
26
+ * The subset of `document.modelContext` this bridge consumes.
27
+ *
28
+ * `getTools()` / `executeTool()` are the standard read/invoke methods (named in
29
+ * the WebMCP spec; implemented by the polyfill and Chrome). The `resource*`
30
+ * members are the Napster toolkit's live-state extension and are OPTIONAL — a
31
+ * bare WebMCP site won't have them, so the bridge feature-detects before use.
32
+ * `document.modelContext` is an `EventTarget`: it dispatches `toolchange` when
33
+ * the tool list changes and (with the toolkit) `resourceupdated` on state push.
56
34
  */
57
- export interface PublishedEdgeMcp {
58
- version: 1;
59
- api: EdgeMcpApi;
35
+ export interface EdgeMcpModelContext extends EventTarget {
36
+ getTools(): Promise<EdgeMcpToolInfo[]>;
37
+ executeTool(tool: EdgeMcpToolInfo, inputArgsJson: string, options?: {
38
+ signal?: AbortSignal;
39
+ }): Promise<string | null>;
40
+ getResources?: () => Array<{
41
+ uri: string;
42
+ name: string;
43
+ }>;
44
+ readResource?: (uri: string) => Promise<unknown>;
45
+ subscribeResource?: (uri: string, handler: (update: EdgeMcpResourceUpdate) => void) => () => void;
60
46
  }
61
47
  /**
62
48
  * Normalized shape of an incoming function-call event.
63
49
  *
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`.
50
+ * The server signals an agent tool call with a `function_implicitly_called`
51
+ * event; the SDK's data-channel handler extracts these three fields before
52
+ * calling `EdgeMcpBridge.dispatchFunctionCall`.
68
53
  */
69
54
  export interface FunctionCallEvent {
70
55
  /** The tool/function name the agent invoked. */
71
56
  name: string;
72
57
  /**
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.
58
+ * The arguments the agent produced — an already-parsed object for
59
+ * `function_implicitly_called`, a JSON string for realtime protocols, or
60
+ * absent for no-arg calls. The bridge accepts all three.
77
61
  */
78
62
  arguments: unknown;
79
63
  /** Unique identifier the server uses to pair the call with its output. */
80
64
  call_id: string;
81
65
  }
82
66
  /**
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:
67
+ * Minimal `sendCommand` signature. Mirrors
68
+ * `NapsterCompanionApiInstance.sendCommand` without coupling the bridge to the
69
+ * full `DataChannelCommand` union — the bridge only sends two command types:
88
70
  * - `{ type: 'send_message', data: { role, text, trigger_response, delay } }`
89
71
  * - `{ type: 'send_function_output', data: { call_id, output } }`
90
72
  */
91
73
  export type SendCommand = (command: {
92
74
  type: string;
93
75
  data: Record<string, unknown>;
94
- }) => void;
76
+ }) => boolean | void;
@@ -1,5 +1,5 @@
1
1
  export { EdgeMcpBridge } from "./edge-mcp-bridge";
2
2
  export type { EdgeMcpBridgeOptions } from "./edge-mcp-bridge";
3
- export { buildInvokeCapabilityFunction } from "./buildInvokeCapabilityFunction";
4
3
  export { normalizeFunctionCallEvent } from "./normalizeFunctionCallEvent";
5
- export type { EdgeMcpApi, EdgeMcpCapabilityMeta, EdgeMcpInvokeResult, EdgeMcpDelta, FunctionCallEvent, } from "./edge-mcp-types";
4
+ export { getModelContext, discoverModelContext } from "./edge-mcp-discovery";
5
+ export type { EdgeMcpModelContext, EdgeMcpToolInfo, EdgeMcpResourceUpdate, FunctionCallEvent, SendCommand, } from "./edge-mcp-types";
@@ -30,6 +30,34 @@ export interface CompanionFunction {
30
30
  /** JSON-Schema style parameter definitions. */
31
31
  parameters?: Record<string, unknown>;
32
32
  }
33
+ /**
34
+ * A full function definition registered inline at runtime via
35
+ * `set_settings.inline_functions`. Mirrors the backend's function record: a
36
+ * top-level `id` and `flow`, with name/description/parameters nested under
37
+ * `data`. Used to register tools MID-SESSION (the WebMCP bridge maps the page's
38
+ * live `document.modelContext` tools to this shape).
39
+ */
40
+ export interface InlineFunction {
41
+ /** Unique identifier for the function record. */
42
+ id: string;
43
+ /**
44
+ * Invocation mode. `"implicit"` = invoked client-side (the client returns the
45
+ * result); `"explicit"` = server-handled. WebMCP tools are `"implicit"`.
46
+ */
47
+ flow: "implicit" | "explicit";
48
+ /**
49
+ * The connection modality the function operates in (e.g. `"video"`). Required
50
+ * so the server doesn't reject the WebRTC connection with "Modalities other
51
+ * than video are not supported".
52
+ */
53
+ modality?: string;
54
+ /** The function definition, same fields as a registered function. */
55
+ data: {
56
+ name: string;
57
+ description?: string;
58
+ parameters?: Record<string, unknown>;
59
+ };
60
+ }
33
61
  export interface SendMessageData {
34
62
  /** The text message to send */
35
63
  text: string;
@@ -55,7 +83,18 @@ export type CancelCommand = {
55
83
  export type SetSettingsCommand = {
56
84
  type: DataChannelMessageType.SET_SETTINGS;
57
85
  data: {
58
- functions: CompanionFunction[];
86
+ /** Session/connection modality (e.g. `"video"` for the avatar connection). */
87
+ modality?: string;
88
+ /** Functions configured at session start. */
89
+ functions?: CompanionFunction[];
90
+ /**
91
+ * Full function definitions provided inline at runtime. Used to register
92
+ * tools MID-SESSION — e.g. the WebMCP bridge pushes the page's live
93
+ * `document.modelContext` tools here, and re-pushes whenever the tool
94
+ * catalog changes. Merged with existing settings: send the complete current
95
+ * list each time.
96
+ */
97
+ inline_functions?: InlineFunction[];
59
98
  };
60
99
  };
61
100
  export type StartVideoCommand = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@touchcastllc/napster-companion-api-dev",
3
- "version": "1.0.0-alpha.71",
3
+ "version": "1.0.0-alpha.73",
4
4
  "keywords": [
5
5
  "napster",
6
6
  "companion-api",
@@ -1,9 +0,0 @@
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;