llui-agent 0.0.1 → 0.0.2
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/dist/bridge.d.ts.map +1 -1
- package/dist/bridge.js +8 -0
- package/dist/bridge.js.map +1 -1
- package/dist/tools.d.ts +15 -2
- package/dist/tools.d.ts.map +1 -1
- package/dist/tools.js +39 -9
- package/dist/tools.js.map +1 -1
- package/package.json +2 -2
package/dist/bridge.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bridge.d.ts","sourceRoot":"","sources":["../src/bridge.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,SAAS,EAAE,MAAM,2CAA2C,CAAA;AAQ/E,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AAKzC,MAAM,MAAM,UAAU,GAAG;IACvB,4BAA4B;IAC5B,KAAK,CAAC,EAAE,OAAO,KAAK,CAAA;IACpB,0GAA0G;IAC1G,SAAS,EAAE,MAAM,CAAA;IACjB,uDAAuD;IACvD,QAAQ,EAAE,UAAU,CAAA;IACpB,uDAAuD;IACvD,OAAO,EAAE,MAAM,CAAA;CAChB,CAAA;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,UAAU,GAAG,SAAS,
|
|
1
|
+
{"version":3,"file":"bridge.d.ts","sourceRoot":"","sources":["../src/bridge.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,SAAS,EAAE,MAAM,2CAA2C,CAAA;AAQ/E,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AAKzC,MAAM,MAAM,UAAU,GAAG;IACvB,4BAA4B;IAC5B,KAAK,CAAC,EAAE,OAAO,KAAK,CAAA;IACpB,0GAA0G;IAC1G,SAAS,EAAE,MAAM,CAAA;IACjB,uDAAuD;IACvD,QAAQ,EAAE,UAAU,CAAA;IACpB,uDAAuD;IACvD,OAAO,EAAE,MAAM,CAAA;CAChB,CAAA;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,UAAU,GAAG,SAAS,CAgF9D"}
|
package/dist/bridge.js
CHANGED
|
@@ -55,6 +55,14 @@ export function createBridgeServer(deps) {
|
|
|
55
55
|
if (name === 'describe_app') {
|
|
56
56
|
deps.bindings.setDescribe(deps.sessionId, res.body);
|
|
57
57
|
}
|
|
58
|
+
// observe returns description on every call; cache it so a later
|
|
59
|
+
// describe_app hit can serve from cache and short-circuit the LAP
|
|
60
|
+
// round-trip.
|
|
61
|
+
if (name === 'observe') {
|
|
62
|
+
const obs = res.body;
|
|
63
|
+
if (obs?.description)
|
|
64
|
+
deps.bindings.setDescribe(deps.sessionId, obs.description);
|
|
65
|
+
}
|
|
58
66
|
return okResult(res.body);
|
|
59
67
|
});
|
|
60
68
|
registerPrompts(server);
|
package/dist/bridge.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bridge.js","sourceRoot":"","sources":["../src/bridge.ts"],"names":[],"mappings":"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","sourcesContent":["import { Server as McpServer } from '@modelcontextprotocol/sdk/server/index.js'\nimport {\n CallToolRequestSchema,\n ListToolsRequestSchema,\n type CallToolResult,\n type ListToolsResult,\n} from '@modelcontextprotocol/sdk/types.js'\nimport { TOOLS, TOOL_TO_LAP_PATH } from './tools.js'\nimport { BindingMap } from './binding.js'\nimport { forwardLap } from './forwarder.js'\nimport type { LapDescribeResponse } from '@llui/agent/protocol'\nimport { registerPrompts } from './prompts.js'\n\nexport type BridgeDeps = {\n /** Injectable for tests. */\n fetch?: typeof fetch\n /** MCP session ID for this client. In stdio mode there's one session; derive from the Server instance. */\n sessionId: string\n /** Shared binding map (one BindingMap per process). */\n bindings: BindingMap\n /** Package version — set from package.json at boot. */\n version: string\n}\n\nexport function createBridgeServer(deps: BridgeDeps): McpServer {\n const server = new McpServer(\n { name: 'llui-agent', version: deps.version },\n { capabilities: { tools: {}, prompts: {} } },\n )\n\n server.setRequestHandler(\n ListToolsRequestSchema,\n async (): Promise<ListToolsResult> => ({\n tools: TOOLS,\n }),\n )\n\n server.setRequestHandler(CallToolRequestSchema, async (req): Promise<CallToolResult> => {\n const { name, arguments: args = {} } = req.params\n\n if (name === 'llui_connect_session') {\n const { url, token } = args as { url?: string; token?: string }\n if (typeof url !== 'string' || typeof token !== 'string') {\n return errorResult('invalid: url and token required')\n }\n deps.bindings.set(deps.sessionId, url, token)\n // Validate immediately by pinging /describe\n const res = await forwardLap(url, token, '/describe', {}, { fetch: deps.fetch })\n if (!res.ok) {\n deps.bindings.clear(deps.sessionId)\n return errorResult(`connect failed: ${JSON.stringify(res.error)}`)\n }\n const describe = res.body as LapDescribeResponse\n deps.bindings.setDescribe(deps.sessionId, describe)\n return okResult({\n appName: describe.name,\n appVersion: describe.version,\n status: 'connected',\n })\n }\n\n if (name === 'llui_disconnect_session') {\n deps.bindings.clear(deps.sessionId)\n return okResult({ status: 'disconnected' })\n }\n\n // Forwarded tools\n const binding = deps.bindings.get(deps.sessionId)\n if (!binding) {\n return errorResult('not bound — ask the user to run /llui-connect <url> <token> first')\n }\n\n // describe_app can serve from cache\n if (name === 'describe_app' && binding.describe) {\n return okResult(binding.describe)\n }\n\n const lapPath = TOOL_TO_LAP_PATH[name]\n if (!lapPath) return errorResult(`unknown tool: ${name}`)\n\n const res = await forwardLap(binding.url, binding.token, lapPath, args, { fetch: deps.fetch })\n if (!res.ok) {\n return errorResult(`LAP ${lapPath} failed: status=${res.status} ${JSON.stringify(res.error)}`)\n }\n\n // Cache describe_app responses after the first call too\n if (name === 'describe_app') {\n deps.bindings.setDescribe(deps.sessionId, res.body as LapDescribeResponse)\n }\n\n return okResult(res.body)\n })\n\n registerPrompts(server)\n\n return server\n}\n\nfunction okResult(body: unknown): CallToolResult {\n return {\n content: [{ type: 'text', text: JSON.stringify(body) }],\n }\n}\n\nfunction errorResult(msg: string): CallToolResult {\n return {\n content: [{ type: 'text', text: msg }],\n isError: true,\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"bridge.js","sourceRoot":"","sources":["../src/bridge.ts"],"names":[],"mappings":"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","sourcesContent":["import { Server as McpServer } from '@modelcontextprotocol/sdk/server/index.js'\nimport {\n CallToolRequestSchema,\n ListToolsRequestSchema,\n type CallToolResult,\n type ListToolsResult,\n} from '@modelcontextprotocol/sdk/types.js'\nimport { TOOLS, TOOL_TO_LAP_PATH } from './tools.js'\nimport { BindingMap } from './binding.js'\nimport { forwardLap } from './forwarder.js'\nimport type { LapDescribeResponse, LapObserveResponse } from '@llui/agent/protocol'\nimport { registerPrompts } from './prompts.js'\n\nexport type BridgeDeps = {\n /** Injectable for tests. */\n fetch?: typeof fetch\n /** MCP session ID for this client. In stdio mode there's one session; derive from the Server instance. */\n sessionId: string\n /** Shared binding map (one BindingMap per process). */\n bindings: BindingMap\n /** Package version — set from package.json at boot. */\n version: string\n}\n\nexport function createBridgeServer(deps: BridgeDeps): McpServer {\n const server = new McpServer(\n { name: 'llui-agent', version: deps.version },\n { capabilities: { tools: {}, prompts: {} } },\n )\n\n server.setRequestHandler(\n ListToolsRequestSchema,\n async (): Promise<ListToolsResult> => ({\n tools: TOOLS,\n }),\n )\n\n server.setRequestHandler(CallToolRequestSchema, async (req): Promise<CallToolResult> => {\n const { name, arguments: args = {} } = req.params\n\n if (name === 'llui_connect_session') {\n const { url, token } = args as { url?: string; token?: string }\n if (typeof url !== 'string' || typeof token !== 'string') {\n return errorResult('invalid: url and token required')\n }\n deps.bindings.set(deps.sessionId, url, token)\n // Validate immediately by pinging /describe\n const res = await forwardLap(url, token, '/describe', {}, { fetch: deps.fetch })\n if (!res.ok) {\n deps.bindings.clear(deps.sessionId)\n return errorResult(`connect failed: ${JSON.stringify(res.error)}`)\n }\n const describe = res.body as LapDescribeResponse\n deps.bindings.setDescribe(deps.sessionId, describe)\n return okResult({\n appName: describe.name,\n appVersion: describe.version,\n status: 'connected',\n })\n }\n\n if (name === 'llui_disconnect_session') {\n deps.bindings.clear(deps.sessionId)\n return okResult({ status: 'disconnected' })\n }\n\n // Forwarded tools\n const binding = deps.bindings.get(deps.sessionId)\n if (!binding) {\n return errorResult('not bound — ask the user to run /llui-connect <url> <token> first')\n }\n\n // describe_app can serve from cache\n if (name === 'describe_app' && binding.describe) {\n return okResult(binding.describe)\n }\n\n const lapPath = TOOL_TO_LAP_PATH[name]\n if (!lapPath) return errorResult(`unknown tool: ${name}`)\n\n const res = await forwardLap(binding.url, binding.token, lapPath, args, { fetch: deps.fetch })\n if (!res.ok) {\n return errorResult(`LAP ${lapPath} failed: status=${res.status} ${JSON.stringify(res.error)}`)\n }\n\n // Cache describe_app responses after the first call too\n if (name === 'describe_app') {\n deps.bindings.setDescribe(deps.sessionId, res.body as LapDescribeResponse)\n }\n\n // observe returns description on every call; cache it so a later\n // describe_app hit can serve from cache and short-circuit the LAP\n // round-trip.\n if (name === 'observe') {\n const obs = res.body as LapObserveResponse\n if (obs?.description) deps.bindings.setDescribe(deps.sessionId, obs.description)\n }\n\n return okResult(res.body)\n })\n\n registerPrompts(server)\n\n return server\n}\n\nfunction okResult(body: unknown): CallToolResult {\n return {\n content: [{ type: 'text', text: JSON.stringify(body) }],\n }\n}\n\nfunction errorResult(msg: string): CallToolResult {\n return {\n content: [{ type: 'text', text: msg }],\n isError: true,\n }\n}\n"]}
|
package/dist/tools.d.ts
CHANGED
|
@@ -1,7 +1,20 @@
|
|
|
1
1
|
import type { ListToolsResult } from '@modelcontextprotocol/sdk/types.js';
|
|
2
2
|
/**
|
|
3
|
-
* The
|
|
4
|
-
*
|
|
3
|
+
* The MCP tools Claude sees. Two tiers:
|
|
4
|
+
*
|
|
5
|
+
* - Efficient path (recommended): `observe` + `send_message`.
|
|
6
|
+
* `observe` returns state + actions + description + context in one
|
|
7
|
+
* call — replacing the old describe_app + get_state + list_actions
|
|
8
|
+
* trio. `send_message` defaults to `waitFor: 'drained'`, blocking
|
|
9
|
+
* until the message queue goes idle (http/delay/debounce round
|
|
10
|
+
* trips complete), then returns the new state + actions + drain
|
|
11
|
+
* meta. Together these cut the "check state → act → check state"
|
|
12
|
+
* loop from 5 round-trips to 2.
|
|
13
|
+
*
|
|
14
|
+
* - Legacy / specialized: `describe_app`, `get_state`, `list_actions`,
|
|
15
|
+
* `wait_for_change`. Kept for back-compat and niche uses (e.g.
|
|
16
|
+
* scoped state reads via JSON pointer, external state pushes). New
|
|
17
|
+
* integrations should prefer `observe`.
|
|
5
18
|
*
|
|
6
19
|
* Spec §8.
|
|
7
20
|
*/
|
package/dist/tools.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oCAAoC,CAAA;AAEzE
|
|
1
|
+
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oCAAoC,CAAA;AAEzE;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,KAAK,EAAE,eAAe,CAAC,OAAO,CAuI1C,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAWnD,CAAA"}
|
package/dist/tools.js
CHANGED
|
@@ -1,6 +1,19 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The
|
|
3
|
-
*
|
|
2
|
+
* The MCP tools Claude sees. Two tiers:
|
|
3
|
+
*
|
|
4
|
+
* - Efficient path (recommended): `observe` + `send_message`.
|
|
5
|
+
* `observe` returns state + actions + description + context in one
|
|
6
|
+
* call — replacing the old describe_app + get_state + list_actions
|
|
7
|
+
* trio. `send_message` defaults to `waitFor: 'drained'`, blocking
|
|
8
|
+
* until the message queue goes idle (http/delay/debounce round
|
|
9
|
+
* trips complete), then returns the new state + actions + drain
|
|
10
|
+
* meta. Together these cut the "check state → act → check state"
|
|
11
|
+
* loop from 5 round-trips to 2.
|
|
12
|
+
*
|
|
13
|
+
* - Legacy / specialized: `describe_app`, `get_state`, `list_actions`,
|
|
14
|
+
* `wait_for_change`. Kept for back-compat and niche uses (e.g.
|
|
15
|
+
* scoped state reads via JSON pointer, external state pushes). New
|
|
16
|
+
* integrations should prefer `observe`.
|
|
4
17
|
*
|
|
5
18
|
* Spec §8.
|
|
6
19
|
*/
|
|
@@ -25,14 +38,19 @@ export const TOOLS = [
|
|
|
25
38
|
description: 'Clear the binding for this Claude conversation. Subsequent LLui tool calls will fail until rebind.',
|
|
26
39
|
inputSchema: { type: 'object', properties: {} },
|
|
27
40
|
},
|
|
41
|
+
{
|
|
42
|
+
name: 'observe',
|
|
43
|
+
description: 'Unified snapshot — returns {state, actions, description, context} in one call. Use this as the default "what can I see, what can I do" read; prefer it over describe_app + get_state + list_actions. Typical flow: observe → send_message → (repeat). The response includes the static app description (name, version, msgSchema, docs) on every call so first-time callers do not need a separate describe_app.',
|
|
44
|
+
inputSchema: { type: 'object', properties: {} },
|
|
45
|
+
},
|
|
28
46
|
{
|
|
29
47
|
name: 'describe_app',
|
|
30
|
-
description: "Return the bound app's name, version, state/message schemas, annotations, and static docs.",
|
|
48
|
+
description: "Return the bound app's name, version, state/message schemas, annotations, and static docs. Legacy — prefer `observe`, which includes this as `description`.",
|
|
31
49
|
inputSchema: { type: 'object', properties: {} },
|
|
32
50
|
},
|
|
33
51
|
{
|
|
34
52
|
name: 'get_state',
|
|
35
|
-
description: 'Return the current app state. Optional `path` (JSON-pointer) to narrow the slice.',
|
|
53
|
+
description: 'Return the current app state. Optional `path` (JSON-pointer) to narrow the slice. Legacy for full-state reads — prefer `observe`. Still useful for scoped reads via JSON pointer.',
|
|
36
54
|
inputSchema: {
|
|
37
55
|
type: 'object',
|
|
38
56
|
properties: {
|
|
@@ -42,12 +60,12 @@ export const TOOLS = [
|
|
|
42
60
|
},
|
|
43
61
|
{
|
|
44
62
|
name: 'list_actions',
|
|
45
|
-
description: 'Return the currently-affordable actions: visible UI bindings plus agent-affordable registry entries, filtered by annotation gates.',
|
|
63
|
+
description: 'Return the currently-affordable actions: visible UI bindings plus agent-affordable registry entries, filtered by annotation gates. Legacy — prefer `observe`, which includes this as `actions`.',
|
|
46
64
|
inputSchema: { type: 'object', properties: {} },
|
|
47
65
|
},
|
|
48
66
|
{
|
|
49
67
|
name: 'send_message',
|
|
50
|
-
description: 'Dispatch a message to the app.
|
|
68
|
+
description: 'Dispatch a message to the app. Blocks by default until the message queue goes idle (drain semantics — captures http/delay/debounce round-trips that feed back as messages). Returns {status, stateAfter, actions, drain} on dispatched, {status: "pending-confirmation", confirmId} when the variant is @requiresConfirm, or {status: "rejected", reason} on validation failures. `drain.timedOut: true` means the 5s cap was hit while messages were still arriving — follow up with `observe` to resync. `actions` in the response reflects the new state, so you normally do not need a separate `observe` after a send.',
|
|
51
69
|
inputSchema: {
|
|
52
70
|
type: 'object',
|
|
53
71
|
properties: {
|
|
@@ -56,8 +74,19 @@ export const TOOLS = [
|
|
|
56
74
|
type: 'string',
|
|
57
75
|
description: 'User-facing rationale (required for confirm-gated variants)',
|
|
58
76
|
},
|
|
59
|
-
waitFor: {
|
|
60
|
-
|
|
77
|
+
waitFor: {
|
|
78
|
+
type: 'string',
|
|
79
|
+
enum: ['drained', 'idle', 'none'],
|
|
80
|
+
description: '"drained" (default) waits for the message queue to go idle; "idle" flushes the update cycle only (no async effects); "none" is fire-and-forget.',
|
|
81
|
+
},
|
|
82
|
+
drainQuietMs: {
|
|
83
|
+
type: 'number',
|
|
84
|
+
description: 'Quiescence window for waitFor:"drained". Drain completes when no commit fires for this many ms. Default 100.',
|
|
85
|
+
},
|
|
86
|
+
timeoutMs: {
|
|
87
|
+
type: 'number',
|
|
88
|
+
description: 'Hard cap on total wait. Default 5000. For waitFor:"drained", this bounds how long the drain loop runs; for pending-confirmation, how long to wait for user approval.',
|
|
89
|
+
},
|
|
61
90
|
},
|
|
62
91
|
required: ['msg'],
|
|
63
92
|
},
|
|
@@ -76,7 +105,7 @@ export const TOOLS = [
|
|
|
76
105
|
},
|
|
77
106
|
{
|
|
78
107
|
name: 'wait_for_change',
|
|
79
|
-
description: 'Long-poll for a state change. Returns changed / timeout.',
|
|
108
|
+
description: 'Long-poll for a state change. Returns changed / timeout. Specialized — use for external state pushes (WebSocket messages, timers) that arrive while Claude is idle. For the normal send-then-read loop, `send_message` with `waitFor:"drained"` already waits for effect round-trips.',
|
|
80
109
|
inputSchema: {
|
|
81
110
|
type: 'object',
|
|
82
111
|
properties: {
|
|
@@ -116,6 +145,7 @@ export const TOOLS = [
|
|
|
116
145
|
* Meta-tools handled separately in bridge.ts.
|
|
117
146
|
*/
|
|
118
147
|
export const TOOL_TO_LAP_PATH = {
|
|
148
|
+
observe: '/observe',
|
|
119
149
|
describe_app: '/describe',
|
|
120
150
|
get_state: '/state',
|
|
121
151
|
list_actions: '/actions',
|
package/dist/tools.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tools.js","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ListToolsResult } from '@modelcontextprotocol/sdk/types.js'\n\n/**\n * The 10 MCP tools Claude sees:\n * 2 meta-tools (bind/unbind) + 8 forwarded tools (1:1 with LAP endpoints).\n *\n * Spec §8.\n */\nexport const TOOLS: ListToolsResult['tools'] = [\n {\n name: 'llui_connect_session',\n description:\n 'Bind this Claude conversation to a specific LLui app. Call ONCE per chat when the user pastes /llui-connect <url> <token>. Subsequent LLui tool calls target the bound app.',\n inputSchema: {\n type: 'object',\n properties: {\n url: {\n type: 'string',\n description: 'LAP base URL (e.g. https://app.example/agent/lap/v1)',\n },\n token: { type: 'string', description: 'Bearer token for LAP calls' },\n },\n required: ['url', 'token'],\n },\n },\n {\n name: 'llui_disconnect_session',\n description:\n 'Clear the binding for this Claude conversation. Subsequent LLui tool calls will fail until rebind.',\n inputSchema: { type: 'object', properties: {} },\n },\n {\n name: 'describe_app',\n description:\n \"Return the bound app's name, version, state/message schemas, annotations, and static docs.\",\n inputSchema: { type: 'object', properties: {} },\n },\n {\n name: 'get_state',\n description:\n 'Return the current app state. Optional `path` (JSON-pointer) to narrow the slice.',\n inputSchema: {\n type: 'object',\n properties: {\n path: { type: 'string', description: 'Optional JSON-pointer, e.g. \"/user/name\"' },\n },\n },\n },\n {\n name: 'list_actions',\n description:\n 'Return the currently-affordable actions: visible UI bindings plus agent-affordable registry entries, filtered by annotation gates.',\n inputSchema: { type: 'object', properties: {} },\n },\n {\n name: 'send_message',\n description:\n 'Dispatch a message to the app. Auto-proposes a user confirmation when the message variant is @requiresConfirm. Returns dispatched / pending-confirmation / rejected.',\n inputSchema: {\n type: 'object',\n properties: {\n msg: { type: 'object', description: 'The message to dispatch; must have a `type` string' },\n reason: {\n type: 'string',\n description: 'User-facing rationale (required for confirm-gated variants)',\n },\n waitFor: { type: 'string', enum: ['idle', 'none'], description: 'default \"idle\"' },\n timeoutMs: { type: 'number' },\n },\n required: ['msg'],\n },\n },\n {\n name: 'get_confirm_result',\n description:\n 'Poll a pending-confirmation by confirmId. Returns confirmed / rejected / still-pending.',\n inputSchema: {\n type: 'object',\n properties: {\n confirmId: { type: 'string' },\n timeoutMs: { type: 'number' },\n },\n required: ['confirmId'],\n },\n },\n {\n name: 'wait_for_change',\n description: 'Long-poll for a state change. Returns changed / timeout.',\n inputSchema: {\n type: 'object',\n properties: {\n path: {\n type: 'string',\n description: 'Optional JSON-pointer to narrow which state changes trigger resolution',\n },\n timeoutMs: { type: 'number' },\n },\n },\n },\n {\n name: 'query_dom',\n description: 'Read elements tagged with data-agent=\"<name>\" in the rendered UI.',\n inputSchema: {\n type: 'object',\n properties: {\n name: { type: 'string' },\n multiple: { type: 'boolean' },\n },\n required: ['name'],\n },\n },\n {\n name: 'describe_visible_content',\n description: 'Return a structured outline of the currently-visible data-agent-tagged subtrees.',\n inputSchema: { type: 'object', properties: {} },\n },\n {\n name: 'describe_context',\n description:\n 'Return the current per-state narrative docs (agentContext) — what the user is trying to do right now.',\n inputSchema: { type: 'object', properties: {} },\n },\n]\n\n/**\n * Mapping from tool name → LAP path for the forwarded subset.\n * Meta-tools handled separately in bridge.ts.\n */\nexport const TOOL_TO_LAP_PATH: Record<string, string> = {\n describe_app: '/describe',\n get_state: '/state',\n list_actions: '/actions',\n send_message: '/message',\n get_confirm_result: '/confirm-result',\n wait_for_change: '/wait',\n query_dom: '/query-dom',\n describe_visible_content: '/describe-visible',\n describe_context: '/context',\n}\n"]}
|
|
1
|
+
{"version":3,"file":"tools.js","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ListToolsResult } from '@modelcontextprotocol/sdk/types.js'\n\n/**\n * The MCP tools Claude sees. Two tiers:\n *\n * - Efficient path (recommended): `observe` + `send_message`.\n * `observe` returns state + actions + description + context in one\n * call — replacing the old describe_app + get_state + list_actions\n * trio. `send_message` defaults to `waitFor: 'drained'`, blocking\n * until the message queue goes idle (http/delay/debounce round\n * trips complete), then returns the new state + actions + drain\n * meta. Together these cut the \"check state → act → check state\"\n * loop from 5 round-trips to 2.\n *\n * - Legacy / specialized: `describe_app`, `get_state`, `list_actions`,\n * `wait_for_change`. Kept for back-compat and niche uses (e.g.\n * scoped state reads via JSON pointer, external state pushes). New\n * integrations should prefer `observe`.\n *\n * Spec §8.\n */\nexport const TOOLS: ListToolsResult['tools'] = [\n {\n name: 'llui_connect_session',\n description:\n 'Bind this Claude conversation to a specific LLui app. Call ONCE per chat when the user pastes /llui-connect <url> <token>. Subsequent LLui tool calls target the bound app.',\n inputSchema: {\n type: 'object',\n properties: {\n url: {\n type: 'string',\n description: 'LAP base URL (e.g. https://app.example/agent/lap/v1)',\n },\n token: { type: 'string', description: 'Bearer token for LAP calls' },\n },\n required: ['url', 'token'],\n },\n },\n {\n name: 'llui_disconnect_session',\n description:\n 'Clear the binding for this Claude conversation. Subsequent LLui tool calls will fail until rebind.',\n inputSchema: { type: 'object', properties: {} },\n },\n {\n name: 'observe',\n description:\n 'Unified snapshot — returns {state, actions, description, context} in one call. Use this as the default \"what can I see, what can I do\" read; prefer it over describe_app + get_state + list_actions. Typical flow: observe → send_message → (repeat). The response includes the static app description (name, version, msgSchema, docs) on every call so first-time callers do not need a separate describe_app.',\n inputSchema: { type: 'object', properties: {} },\n },\n {\n name: 'describe_app',\n description:\n \"Return the bound app's name, version, state/message schemas, annotations, and static docs. Legacy — prefer `observe`, which includes this as `description`.\",\n inputSchema: { type: 'object', properties: {} },\n },\n {\n name: 'get_state',\n description:\n 'Return the current app state. Optional `path` (JSON-pointer) to narrow the slice. Legacy for full-state reads — prefer `observe`. Still useful for scoped reads via JSON pointer.',\n inputSchema: {\n type: 'object',\n properties: {\n path: { type: 'string', description: 'Optional JSON-pointer, e.g. \"/user/name\"' },\n },\n },\n },\n {\n name: 'list_actions',\n description:\n 'Return the currently-affordable actions: visible UI bindings plus agent-affordable registry entries, filtered by annotation gates. Legacy — prefer `observe`, which includes this as `actions`.',\n inputSchema: { type: 'object', properties: {} },\n },\n {\n name: 'send_message',\n description:\n 'Dispatch a message to the app. Blocks by default until the message queue goes idle (drain semantics — captures http/delay/debounce round-trips that feed back as messages). Returns {status, stateAfter, actions, drain} on dispatched, {status: \"pending-confirmation\", confirmId} when the variant is @requiresConfirm, or {status: \"rejected\", reason} on validation failures. `drain.timedOut: true` means the 5s cap was hit while messages were still arriving — follow up with `observe` to resync. `actions` in the response reflects the new state, so you normally do not need a separate `observe` after a send.',\n inputSchema: {\n type: 'object',\n properties: {\n msg: { type: 'object', description: 'The message to dispatch; must have a `type` string' },\n reason: {\n type: 'string',\n description: 'User-facing rationale (required for confirm-gated variants)',\n },\n waitFor: {\n type: 'string',\n enum: ['drained', 'idle', 'none'],\n description:\n '\"drained\" (default) waits for the message queue to go idle; \"idle\" flushes the update cycle only (no async effects); \"none\" is fire-and-forget.',\n },\n drainQuietMs: {\n type: 'number',\n description:\n 'Quiescence window for waitFor:\"drained\". Drain completes when no commit fires for this many ms. Default 100.',\n },\n timeoutMs: {\n type: 'number',\n description:\n 'Hard cap on total wait. Default 5000. For waitFor:\"drained\", this bounds how long the drain loop runs; for pending-confirmation, how long to wait for user approval.',\n },\n },\n required: ['msg'],\n },\n },\n {\n name: 'get_confirm_result',\n description:\n 'Poll a pending-confirmation by confirmId. Returns confirmed / rejected / still-pending.',\n inputSchema: {\n type: 'object',\n properties: {\n confirmId: { type: 'string' },\n timeoutMs: { type: 'number' },\n },\n required: ['confirmId'],\n },\n },\n {\n name: 'wait_for_change',\n description:\n 'Long-poll for a state change. Returns changed / timeout. Specialized — use for external state pushes (WebSocket messages, timers) that arrive while Claude is idle. For the normal send-then-read loop, `send_message` with `waitFor:\"drained\"` already waits for effect round-trips.',\n inputSchema: {\n type: 'object',\n properties: {\n path: {\n type: 'string',\n description: 'Optional JSON-pointer to narrow which state changes trigger resolution',\n },\n timeoutMs: { type: 'number' },\n },\n },\n },\n {\n name: 'query_dom',\n description: 'Read elements tagged with data-agent=\"<name>\" in the rendered UI.',\n inputSchema: {\n type: 'object',\n properties: {\n name: { type: 'string' },\n multiple: { type: 'boolean' },\n },\n required: ['name'],\n },\n },\n {\n name: 'describe_visible_content',\n description: 'Return a structured outline of the currently-visible data-agent-tagged subtrees.',\n inputSchema: { type: 'object', properties: {} },\n },\n {\n name: 'describe_context',\n description:\n 'Return the current per-state narrative docs (agentContext) — what the user is trying to do right now.',\n inputSchema: { type: 'object', properties: {} },\n },\n]\n\n/**\n * Mapping from tool name → LAP path for the forwarded subset.\n * Meta-tools handled separately in bridge.ts.\n */\nexport const TOOL_TO_LAP_PATH: Record<string, string> = {\n observe: '/observe',\n describe_app: '/describe',\n get_state: '/state',\n list_actions: '/actions',\n send_message: '/message',\n get_confirm_result: '/confirm-result',\n wait_for_change: '/wait',\n query_dom: '/query-dom',\n describe_visible_content: '/describe-visible',\n describe_context: '/context',\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "llui-agent",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"bin": {
|
|
6
6
|
"llui-agent": "./dist/cli.js"
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
],
|
|
21
21
|
"dependencies": {
|
|
22
22
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
23
|
-
"@llui/agent": "0.0.
|
|
23
|
+
"@llui/agent": "0.0.30"
|
|
24
24
|
},
|
|
25
25
|
"devDependencies": {
|
|
26
26
|
"@types/node": "^22.0.0"
|