refactor: MCP server improvements
This commit is contained in:
parent
f330cce386
commit
4bbdb4e20c
391
mcp/README.md
391
mcp/README.md
|
|
@ -1,12 +1,11 @@
|
|||
# Honcho MCP Server
|
||||
|
||||
## Quickstart: Use the Hosted MCP Server
|
||||
A Cloudflare Worker that implements the [Model Context Protocol (MCP)](https://modelcontextprotocol.io/) for [Honcho](https://honcho.dev), providing AI memory and personalization tools to LLM clients like Claude Desktop.
|
||||
|
||||
Go to <https://app.honcho.dev> and get an API key. Then go to Claude Desktop and navigate to custom MCP servers.
|
||||
## Quickstart: Use the Hosted Server
|
||||
|
||||
If you don't have node/bun installed you will need to do that. You can also use npm if you already have that installed. If not, Claude Desktop or Claude Code can help!
|
||||
|
||||
Add Honcho to your Claude desktop config. You must provide a username for Honcho to refer to you as -- preferably what you want Claude to actually call you.
|
||||
1. Get an API key at <https://app.honcho.dev>
|
||||
2. Add Honcho to your Claude Desktop config:
|
||||
|
||||
```json
|
||||
{
|
||||
|
|
@ -30,356 +29,90 @@ Add Honcho to your Claude desktop config. You must provide a username for Honcho
|
|||
}
|
||||
```
|
||||
|
||||
You may customize your assistant name and/or workspace ID. Both are optional.
|
||||
### Optional Headers
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"honcho": {
|
||||
"command": "bunx",
|
||||
"args": [
|
||||
"mcp-remote",
|
||||
"https://mcp.honcho.dev",
|
||||
"--header",
|
||||
"Authorization:${AUTH_HEADER}",
|
||||
"--header",
|
||||
"X-Honcho-User-Name:${USER_NAME}",
|
||||
"--header",
|
||||
"X-Honcho-Assistant-Name:${ASSISTANT_NAME}",
|
||||
"--header",
|
||||
"X-Honcho-Workspace-ID:${WORKSPACE_ID}"
|
||||
],
|
||||
"env": {
|
||||
"AUTH_HEADER": "Bearer <your-honcho-key>",
|
||||
"USER_NAME": "<your-name>",
|
||||
"ASSISTANT_NAME": "<your-assistant-name>",
|
||||
"WORKSPACE_ID": "<your-custom-workspace-id>"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
| Header | Default | Description |
|
||||
| --- | --- | --- |
|
||||
| `X-Honcho-Assistant-Name` | `"Assistant"` | Name for the assistant peer |
|
||||
| `X-Honcho-Workspace-ID` | `"default"` | Workspace to operate in |
|
||||
| `X-Honcho-Base-URL` | `https://api.honcho.dev` | Custom API base URL |
|
||||
|
||||
## Available Tools
|
||||
|
||||
### start_conversation
|
||||
### Bespoke Flow (Simple)
|
||||
|
||||
Start a new conversation session with Honcho. This initializes a session for tracking conversation history and context.
|
||||
| Tool | Description |
|
||||
| --- | --- |
|
||||
| `start_conversation` | Start a new conversation, returns a session ID |
|
||||
| `get_personalization_insights` | Ask Honcho about the user for personalized responses |
|
||||
| `add_turn` | Record user + assistant messages |
|
||||
|
||||
**Returns:** A session ID that you must store and use for all subsequent interactions in this conversation.
|
||||
### General Tools
|
||||
|
||||
### add_turn
|
||||
**Workspace:** `search_workspace`, `get_workspace_metadata`, `set_workspace_metadata`
|
||||
|
||||
Add a conversation turn (user and assistant messages) to the current session. This stores the conversation in Honcho for context tracking.
|
||||
**Peers:** `create_peer`, `list_peers`, `chat`, `get_peer_card`, `set_peer_card`, `get_peer_context`, `get_representation`, `get_peer_metadata`, `set_peer_metadata`, `search_peer_messages`
|
||||
|
||||
**Parameters:**
|
||||
**Sessions:** `create_session`, `list_sessions`, `delete_session`, `clone_session`, `add_peers_to_session`, `remove_peers_from_session`, `get_session_peers`, `add_messages_to_session`, `get_session_messages`, `search_session_messages`, `get_session_context`, `get_session_representation`, `get_session_metadata`, `set_session_metadata`
|
||||
|
||||
- `session_id`: The ID of the session to add the turn to
|
||||
- `messages`: Array of message objects with `role` ("user" or "assistant") and `content`
|
||||
**Conclusions:** `list_conclusions`, `query_conclusions`, `create_conclusions`, `delete_conclusion`
|
||||
|
||||
**Example usage:**
|
||||
**System:** `schedule_dream`, `get_queue_status`
|
||||
|
||||
```json
|
||||
{
|
||||
"session_id": "session-uuid",
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "Hello, how are you?"
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "I'm doing well, thank you!"
|
||||
}
|
||||
]
|
||||
}
|
||||
## Architecture
|
||||
|
||||
```
|
||||
src/
|
||||
index.ts # Worker entry point — parse config, delegate to MCP handler
|
||||
server.ts # createServer() — registers all tools on an McpServer
|
||||
config.ts # HonchoConfig, parseConfig(), createClient()
|
||||
types.ts # ToolContext, result helpers
|
||||
tools/
|
||||
bespoke.ts # start_conversation, add_turn, get_personalization_insights
|
||||
workspace.ts # search, metadata
|
||||
peers.ts # CRUD, chat, card, context, representation, search
|
||||
sessions.ts # CRUD, peers, messages, context, representation, clone
|
||||
conclusions.ts # list, query, create, delete
|
||||
system.ts # dream, queue status
|
||||
```
|
||||
|
||||
### get_personalization_insights
|
||||
Built on:
|
||||
|
||||
Get personalization insights from Honcho based on conversation history. This queries the user's conversation context to provide personalized responses.
|
||||
- **[agents](https://www.npmjs.com/package/agents)** — `createMcpHandler` for Cloudflare Workers
|
||||
- **[@modelcontextprotocol/sdk](https://www.npmjs.com/package/@modelcontextprotocol/sdk)** — `McpServer` for tool registration
|
||||
- **[@honcho-ai/sdk](https://www.npmjs.com/package/@honcho-ai/sdk)** v2 — Honcho TypeScript SDK
|
||||
|
||||
**Parameters:**
|
||||
## Development
|
||||
|
||||
- `session_id`: The ID of the session for context
|
||||
- `query`: The question about the user's preferences, habits, etc.
|
||||
|
||||
**Example queries:**
|
||||
|
||||
- "What does this message reveal about the user's communication preferences?"
|
||||
- "How formal or casual should I be with the user based on our history?"
|
||||
- "What emotional state might the user be in right now?"
|
||||
|
||||
### search_workspace
|
||||
|
||||
Search for messages across the entire workspace.
|
||||
|
||||
**Parameters:**
|
||||
|
||||
- `query`: The search query to use
|
||||
|
||||
### get_workspace_metadata
|
||||
|
||||
Get metadata for the current workspace.
|
||||
|
||||
**Parameters:** None
|
||||
|
||||
### set_workspace_metadata
|
||||
|
||||
Set metadata for the current workspace.
|
||||
|
||||
**Parameters:**
|
||||
|
||||
- `metadata`: A dictionary of metadata to associate with the workspace
|
||||
|
||||
### create_peer
|
||||
|
||||
Create or get a peer with the specified ID and optional configuration.
|
||||
|
||||
**Parameters:**
|
||||
|
||||
- `peer_id`: Unique identifier for the peer
|
||||
- `config`: Optional configuration dictionary for the peer
|
||||
|
||||
### get_peer_metadata
|
||||
|
||||
Get metadata for a specific peer.
|
||||
|
||||
**Parameters:**
|
||||
|
||||
- `peer_id`: The ID of the peer to get metadata for
|
||||
|
||||
### set_peer_metadata
|
||||
|
||||
Set metadata for a specific peer.
|
||||
|
||||
**Parameters:**
|
||||
|
||||
- `peer_id`: The ID of the peer to set metadata for
|
||||
- `metadata`: A dictionary of metadata to associate with the peer
|
||||
|
||||
### search_peer_messages
|
||||
|
||||
Search for messages sent by a peer.
|
||||
|
||||
**Parameters:**
|
||||
|
||||
- `peer_id`: The ID of the peer to search messages for
|
||||
- `query`: The search query to use
|
||||
|
||||
### chat
|
||||
|
||||
Query a peer's representation with natural language questions.
|
||||
|
||||
**Parameters:**
|
||||
|
||||
- `peer_id`: The ID of the peer to query
|
||||
- `query`: The natural language question to ask
|
||||
- `target_peer_id`: Optional target peer ID for local representation queries
|
||||
- `session_id`: Optional session ID to scope the query to a specific session
|
||||
|
||||
### list_peers
|
||||
|
||||
Get all peers in the current workspace.
|
||||
|
||||
**Parameters:** None
|
||||
|
||||
### create_session
|
||||
|
||||
Create or get a session with the specified ID and optional configuration.
|
||||
|
||||
**Parameters:**
|
||||
|
||||
- `session_id`: Unique identifier for the session
|
||||
- `config`: Optional configuration dictionary for the session
|
||||
|
||||
### get_session_metadata
|
||||
|
||||
Get metadata for a specific session.
|
||||
|
||||
**Parameters:**
|
||||
|
||||
- `session_id`: The ID of the session to get metadata for
|
||||
|
||||
### set_session_metadata
|
||||
|
||||
Set metadata for a specific session.
|
||||
|
||||
**Parameters:**
|
||||
|
||||
- `session_id`: The ID of the session to set metadata for
|
||||
- `metadata`: A dictionary of metadata to associate with the session
|
||||
|
||||
### add_peers_to_session
|
||||
|
||||
Add peers to a session.
|
||||
|
||||
**Parameters:**
|
||||
|
||||
- `session_id`: The ID of the session to add peers to
|
||||
- `peer_ids`: List of peer IDs to add to the session
|
||||
|
||||
### remove_peers_from_session
|
||||
|
||||
Remove peers from a session.
|
||||
|
||||
**Parameters:**
|
||||
|
||||
- `session_id`: The ID of the session to remove peers from
|
||||
- `peer_ids`: List of peer IDs to remove from the session
|
||||
|
||||
### get_session_peers
|
||||
|
||||
Get all peer IDs in a session.
|
||||
|
||||
**Parameters:**
|
||||
|
||||
- `session_id`: The ID of the session to get peers from
|
||||
|
||||
### add_messages_to_session
|
||||
|
||||
Add messages to a session.
|
||||
|
||||
**Parameters:**
|
||||
|
||||
- `session_id`: The ID of the session to add messages to
|
||||
- `messages`: List of message dictionaries with `peer_id`, `content`, and optional `metadata`
|
||||
|
||||
### get_session_messages
|
||||
|
||||
Get messages from a session with optional filtering.
|
||||
|
||||
**Parameters:**
|
||||
|
||||
- `session_id`: The ID of the session to get messages from
|
||||
- `filters`: Optional dictionary of filter criteria
|
||||
|
||||
### get_session_context
|
||||
|
||||
Get optimized context for a session within a token limit.
|
||||
|
||||
**Parameters:**
|
||||
|
||||
- `session_id`: The ID of the session to get context for
|
||||
- `summary`: Whether to include summary information (default: true)
|
||||
- `tokens`: Maximum number of tokens to include in the context
|
||||
|
||||
### search_session_messages
|
||||
|
||||
Search for messages in a specific session.
|
||||
|
||||
**Parameters:**
|
||||
|
||||
- `session_id`: The ID of the session to search messages in
|
||||
- `query`: The search query to use
|
||||
|
||||
### get_working_representation
|
||||
|
||||
Get the current working representation of a peer in a session.
|
||||
|
||||
**Parameters:**
|
||||
|
||||
- `session_id`: The ID of the session
|
||||
- `peer_id`: The ID of the peer to get the working representation of
|
||||
- `target_peer_id`: Optional target peer ID to get the representation of what peer_id knows about target_peer_id
|
||||
|
||||
### list_sessions
|
||||
|
||||
Get all sessions in the current workspace.
|
||||
|
||||
**Parameters:** None
|
||||
|
||||
## Contributing or Self Hosting
|
||||
|
||||
A Cloudflare Worker that implements the Model Context Protocol (MCP) to provide Honcho functionality as tools for AI assistants like Claude Desktop.
|
||||
|
||||
### Deploy MCP Worker
|
||||
|
||||
1. **Install dependencies:**
|
||||
|
||||
```bash
|
||||
bun i
|
||||
```
|
||||
|
||||
2. **Login to Cloudflare (if not already done):**
|
||||
|
||||
```bash
|
||||
bun wrangler login
|
||||
```
|
||||
|
||||
3. **Configure your worker name in `wrangler.toml`:**
|
||||
- Update the `name` field to your desired worker name
|
||||
- Update the worker names in the `[env.production]` and `[env.staging]` sections
|
||||
|
||||
4. **Test locally:**
|
||||
|
||||
```bash
|
||||
bun dev
|
||||
```
|
||||
|
||||
5. **Deploy to production:**
|
||||
|
||||
```bash
|
||||
bun run deploy
|
||||
```
|
||||
|
||||
### Configuration Options
|
||||
|
||||
You can customize the behavior using HTTP headers:
|
||||
|
||||
**Available Configuration:**
|
||||
|
||||
- `apiKey`: Your Honcho API key
|
||||
- `baseUrl`: Custom Honcho API base URL (default: <https://api.honcho.dev>)
|
||||
- `workspaceId`: Workspace ID (default: "default")
|
||||
- `userName`: User identifier (default: "User")
|
||||
- `assistantName`: Assistant identifier (default: "Assistant")
|
||||
|
||||
#### Using HTTP Headers
|
||||
|
||||
Pass configuration to mcp-remote via custom headers:
|
||||
### Setup
|
||||
|
||||
```bash
|
||||
bunx mcp-remote https://YOUR_WORKER_NAME.YOUR_SUBDOMAIN.workers.dev \
|
||||
--header "Authorization:Bearer YOUR_HONCHO_API_KEY" \
|
||||
--header "X-Honcho-Workspace-ID:my-workspace" \
|
||||
--header "X-Honcho-User-Name:john" \
|
||||
--header "X-Honcho-Assistant-Name:Claude" \
|
||||
--header "X-Honcho-Base-URL:https://custom.honcho.dev"
|
||||
bun install
|
||||
```
|
||||
|
||||
**Supported Custom Headers:**
|
||||
|
||||
- `Authorization: Bearer YOUR_API_KEY` - Your Honcho API key
|
||||
- `X-Honcho-Base-URL` - Custom Honcho API base URL
|
||||
- `X-Honcho-Workspace-ID` - Workspace identifier
|
||||
- `X-Honcho-User-Name` - User identifier
|
||||
- `X-Honcho-Assistant-Name` - Assistant identifier
|
||||
|
||||
### Authentication
|
||||
|
||||
The MCP server requires a valid Honcho API key provided via the Authorization header.
|
||||
|
||||
### Testing
|
||||
|
||||
You can test the MCP server using `mcp-remote` with the local URL:
|
||||
### Local dev
|
||||
|
||||
```bash
|
||||
bunx mcp-remote http://localhost:8787 --header "Authorization:Bearer your-api-key"
|
||||
bun dev
|
||||
```
|
||||
|
||||
### Error Handling
|
||||
### Type-check
|
||||
|
||||
The server provides proper JSON-RPC 2.0 error responses:
|
||||
```bash
|
||||
bun run tsc --noEmit
|
||||
```
|
||||
|
||||
- `-32700`: Parse error
|
||||
- `-32600`: Invalid Request
|
||||
- `-32601`: Method not found
|
||||
- `-32602`: Invalid params
|
||||
- `-32603`: Internal error
|
||||
### Test locally
|
||||
|
||||
Common issues:
|
||||
```bash
|
||||
bunx mcp-remote http://localhost:8787 \
|
||||
--header "Authorization:Bearer <key>" \
|
||||
--header "X-Honcho-User-Name:test"
|
||||
```
|
||||
|
||||
- **Missing API key**: Ensure you provide a valid Honcho API key via header or URL parameter
|
||||
- **Invalid tool parameters**: Check that required parameters are provided and properly formatted
|
||||
- **Network errors**: Verify the worker is deployed and accessible
|
||||
### Deploy
|
||||
|
||||
```bash
|
||||
bun run deploy # production
|
||||
bun run deploy:staging # staging
|
||||
```
|
||||
|
|
|
|||
279
mcp/bun.lock
279
mcp/bun.lock
|
|
@ -4,7 +4,10 @@
|
|||
"": {
|
||||
"name": "honcho-mcp-proxy",
|
||||
"dependencies": {
|
||||
"@honcho-ai/sdk": "^1.6.0",
|
||||
"@honcho-ai/sdk": "^2.0.0",
|
||||
"@modelcontextprotocol/sdk": "^1.26.0",
|
||||
"agents": "^0.4.0",
|
||||
"zod": "^4.3.6",
|
||||
},
|
||||
"devDependencies": {
|
||||
"@cloudflare/workers-types": "^4.20241002.0",
|
||||
|
|
@ -14,6 +17,24 @@
|
|||
},
|
||||
},
|
||||
"packages": {
|
||||
"@ai-sdk/gateway": ["@ai-sdk/gateway@3.0.39", "", { "dependencies": { "@ai-sdk/provider": "3.0.8", "@ai-sdk/provider-utils": "4.0.14", "@vercel/oidc": "3.1.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-SeCZBAdDNbWpVUXiYgOAqis22p5MEYfrjRw0hiBa5hM+7sDGYQpMinUjkM8kbPXMkY+AhKLrHleBl+SuqpzlgA=="],
|
||||
|
||||
"@ai-sdk/provider": ["@ai-sdk/provider@3.0.8", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-oGMAgGoQdBXbZqNG0Ze56CHjDZ1IDYOwGYxYjO5KLSlz5HiNQ9udIXsPZ61VWaHGZ5XW/jyjmr6t2xz2jGVwbQ=="],
|
||||
|
||||
"@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@4.0.14", "", { "dependencies": { "@ai-sdk/provider": "3.0.8", "@standard-schema/spec": "^1.1.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-7bzKd9lgiDeXM7O4U4nQ8iTxguAOkg8LZGD9AfDVZYjO5cKYRwBPwVjboFcVrxncRHu0tYxZtXZtiLKpG4pEng=="],
|
||||
|
||||
"@apidevtools/json-schema-ref-parser": ["@apidevtools/json-schema-ref-parser@11.9.3", "", { "dependencies": { "@jsdevtools/ono": "^7.1.3", "@types/json-schema": "^7.0.15", "js-yaml": "^4.1.0" } }, "sha512-60vepv88RwcJtSHrD6MjIL6Ta3SOYbgfnkHb+ppAVK+o9mXprRtulx7VlRl3lN3bbvysAfCS7WMVfhUYemB0IQ=="],
|
||||
|
||||
"@babel/runtime": ["@babel/runtime@7.28.6", "", {}, "sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA=="],
|
||||
|
||||
"@babel/runtime-corejs3": ["@babel/runtime-corejs3@7.29.0", "", { "dependencies": { "core-js-pure": "^3.48.0" } }, "sha512-TgUkdp71C9pIbBcHudc+gXZnihEDOjUAmXO1VO4HHGES7QLZcShR0stfKIxLSNIYx2fqhmJChOjm/wkF8wv4gA=="],
|
||||
|
||||
"@cfworker/json-schema": ["@cfworker/json-schema@4.1.1", "", {}, "sha512-gAmrUZSGtKc3AiBL71iNWxDsyUC5uMaKKGdvzYsBoTW/xi42JQHl7eKV2OYzCUqvc+D2RCcf7EXY2iCyFIk6og=="],
|
||||
|
||||
"@cloudflare/ai-chat": ["@cloudflare/ai-chat@0.0.7", "", { "peerDependencies": { "agents": "^0.4.0", "ai": "^6.0.0", "react": "^19.0.0", "zod": "^3.25.0 || ^4.0.0" } }, "sha512-yjRoM8AIFJccgSWvR7LZdf435E63oYXquyh2VpFpXsgYO3okYL1ONTIHG6QBDAnJrMf213/z6Vy47V7Py9slYw=="],
|
||||
|
||||
"@cloudflare/codemode": ["@cloudflare/codemode@0.0.7", "", { "dependencies": { "zod-to-ts": "^2.0.0" }, "peerDependencies": { "agents": "^0.4.0", "ai": "^6.0.0", "zod": "^3.25.0 || ^4.0.0" } }, "sha512-hzT8WWMel7CaCtEuFG1jtw1jRb6tBpIqQje5DG/dtAWobFnh+UGplGqSyLFEqD8BLknHYrMT/qxdguR94d03dg=="],
|
||||
|
||||
"@cloudflare/kv-asset-handler": ["@cloudflare/kv-asset-handler@0.4.0", "", { "dependencies": { "mime": "^3.0.0" } }, "sha512-+tv3z+SPp+gqTIcImN9o0hqE9xyfQjI1XD9pL6NuKjua9B1y7mNYv0S9cP+QEbA4ppVgGZEmKOvHX5G5Ei1CVA=="],
|
||||
|
||||
"@cloudflare/unenv-preset": ["@cloudflare/unenv-preset@2.4.1", "", { "peerDependencies": { "unenv": "2.0.0-rc.17", "workerd": "^1.20250521.0" }, "optionalPeers": ["workerd"] }, "sha512-70mk5GPv+ozJ5XcIhFpq4ps7HvQYu+As7vwasUy9LcBadsTcWA2iFis/7aFJmQehfKerDwVOHfMYpgTTC+u24Q=="],
|
||||
|
|
@ -84,9 +105,9 @@
|
|||
|
||||
"@esbuild/win32-x64": ["@esbuild/win32-x64@0.25.4", "", { "os": "win32", "cpu": "x64" }, "sha512-nOT2vZNw6hJ+z43oP1SPea/G/6AbN6X+bGNhNuq8NtRHy4wsMhw765IKLNmnjek7GvjWBYQ8Q5VBoYTFg9y1UQ=="],
|
||||
|
||||
"@honcho-ai/core": ["@honcho-ai/core@1.8.0", "", { "dependencies": { "@types/node": "^18.11.18", "@types/node-fetch": "^2.6.4", "abort-controller": "^3.0.0", "agentkeepalive": "^4.2.1", "form-data-encoder": "1.7.2", "formdata-node": "^4.3.2", "node-fetch": "^2.6.7" } }, "sha512-qxBNoXLezH8yx4iBoz4Bsxkm9zp4Gm1fNwuP8gHRdSelxhR0dXpvLffx8B5V0XFWsx+SfPaJFyaKw0X2sYMwLA=="],
|
||||
"@honcho-ai/sdk": ["@honcho-ai/sdk@2.0.1", "", { "dependencies": { "@types/node": "^24.0.1", "zod": "4.0.0" } }, "sha512-y/Wk49C0N1miI9BZTNWFIbzdUkMZfP4Do/EJ1q4lEIK+FAOKxQgces/zET3kPKV3zF9sOUl2pXrFb/XKYayeYw=="],
|
||||
|
||||
"@honcho-ai/sdk": ["@honcho-ai/sdk@1.6.0", "", { "dependencies": { "@honcho-ai/core": "^1.6.1", "@types/node": "^24.0.1", "zod": "4.0.0" } }, "sha512-6HSjTidVwchEWw18p5Gqp4e2/I1Um0EppTZYZ22+hG1UemKRcJX+VDRvlu5ja8inD/WWYTEOJ/HBSdT8OC9biw=="],
|
||||
"@hono/node-server": ["@hono/node-server@1.19.9", "", { "peerDependencies": { "hono": "^4" } }, "sha512-vHL6w3ecZsky+8P5MD+eFfaGTyCeOHUIFYMGpQGbrBTSmNNoxv0if69rEZ5giu36weC5saFuznL411gRX7bJDw=="],
|
||||
|
||||
"@img/sharp-darwin-arm64": ["@img/sharp-darwin-arm64@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-arm64": "1.0.4" }, "os": "darwin", "cpu": "arm64" }, "sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ=="],
|
||||
|
||||
|
|
@ -132,6 +153,12 @@
|
|||
|
||||
"@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.9", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.0.3", "@jridgewell/sourcemap-codec": "^1.4.10" } }, "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ=="],
|
||||
|
||||
"@jsdevtools/ono": ["@jsdevtools/ono@7.1.3", "", {}, "sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg=="],
|
||||
|
||||
"@modelcontextprotocol/sdk": ["@modelcontextprotocol/sdk@1.26.0", "", { "dependencies": { "@hono/node-server": "^1.19.9", "ajv": "^8.17.1", "ajv-formats": "^3.0.1", "content-type": "^1.0.5", "cors": "^2.8.5", "cross-spawn": "^7.0.5", "eventsource": "^3.0.2", "eventsource-parser": "^3.0.0", "express": "^5.2.1", "express-rate-limit": "^8.2.1", "hono": "^4.11.4", "jose": "^6.1.3", "json-schema-typed": "^8.0.2", "pkce-challenge": "^5.0.0", "raw-body": "^3.0.0", "zod": "^3.25 || ^4.0", "zod-to-json-schema": "^3.25.1" }, "peerDependencies": { "@cfworker/json-schema": "^4.1.1" }, "optionalPeers": ["@cfworker/json-schema"] }, "sha512-Y5RmPncpiDtTXDbLKswIJzTqu2hyBKxTNsgKqKclDbhIgg1wgtf1fRuvxgTnRfcnxtvvgbIEcqUOzZrJ6iSReg=="],
|
||||
|
||||
"@opentelemetry/api": ["@opentelemetry/api@1.9.0", "", {}, "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg=="],
|
||||
|
||||
"@poppinss/colors": ["@poppinss/colors@4.1.5", "", { "dependencies": { "kleur": "^4.1.5" } }, "sha512-FvdDqtcRCtz6hThExcFOgW0cWX+xwSMWcRuQe5ZEb2m7cVQOAVZOIMt+/v9RxGiD9/OY16qJBXK4CVKWAPalBw=="],
|
||||
|
||||
"@poppinss/dumper": ["@poppinss/dumper@0.6.4", "", { "dependencies": { "@poppinss/colors": "^4.1.5", "@sindresorhus/is": "^7.0.2", "supports-color": "^10.0.0" } }, "sha512-iG0TIdqv8xJ3Lt9O8DrPRxw1MRLjNpoqiSGU03P/wNLP/s0ra0udPJ1J2Tx5M0J3H/cVyEgpbn8xUKRY9j59kQ=="],
|
||||
|
|
@ -142,24 +169,48 @@
|
|||
|
||||
"@speed-highlight/core": ["@speed-highlight/core@1.2.7", "", {}, "sha512-0dxmVj4gxg3Jg879kvFS/msl4s9F3T9UXC1InxgOf7t5NvcPD97u/WTA5vL/IxWHMn7qSxBozqrnnE2wvl1m8g=="],
|
||||
|
||||
"@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="],
|
||||
|
||||
"@types/json-schema": ["@types/json-schema@7.0.15", "", {}, "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA=="],
|
||||
|
||||
"@types/lodash": ["@types/lodash@4.17.23", "", {}, "sha512-RDvF6wTulMPjrNdCoYRC8gNR880JNGT8uB+REUpC2Ns4pRqQJhGz90wh7rgdXDPpCczF3VGktDuFGVnz8zP7HA=="],
|
||||
|
||||
"@types/node": ["@types/node@24.1.0", "", { "dependencies": { "undici-types": "~7.8.0" } }, "sha512-ut5FthK5moxFKH2T1CUOC6ctR67rQRvvHdFLCD2Ql6KXmMuCrjsSsRI9UsLCm9M18BMwClv4pn327UvB7eeO1w=="],
|
||||
|
||||
"@types/node-fetch": ["@types/node-fetch@2.6.12", "", { "dependencies": { "@types/node": "*", "form-data": "^4.0.0" } }, "sha512-8nneRWKCg3rMtF69nLQJnOYUcbafYeFSjqkw3jCRLsqkWFlHaoQrr5mXmofFGOx3DKn7UfmBMyov8ySvLRVldA=="],
|
||||
"@vercel/oidc": ["@vercel/oidc@3.1.0", "", {}, "sha512-Fw28YZpRnA3cAHHDlkt7xQHiJ0fcL+NRcIqsocZQUSmbzeIKRpwttJjik5ZGanXP+vlA4SbTg+AbA3bP363l+w=="],
|
||||
|
||||
"abort-controller": ["abort-controller@3.0.0", "", { "dependencies": { "event-target-shim": "^5.0.0" } }, "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg=="],
|
||||
"accepts": ["accepts@2.0.0", "", { "dependencies": { "mime-types": "^3.0.0", "negotiator": "^1.0.0" } }, "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng=="],
|
||||
|
||||
"acorn": ["acorn@8.14.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA=="],
|
||||
|
||||
"acorn-walk": ["acorn-walk@8.3.2", "", {}, "sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A=="],
|
||||
|
||||
"agentkeepalive": ["agentkeepalive@4.6.0", "", { "dependencies": { "humanize-ms": "^1.2.1" } }, "sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ=="],
|
||||
"agents": ["agents@0.4.0", "", { "dependencies": { "@cfworker/json-schema": "^4.1.1", "@modelcontextprotocol/sdk": "1.26.0", "cron-schedule": "^6.0.0", "escape-html": "^1.0.3", "json-schema": "^0.4.0", "json-schema-to-typescript": "^15.0.4", "mimetext": "^3.0.28", "nanoid": "^5.1.6", "partyserver": "^0.1.4", "partysocket": "1.1.13", "yargs": "^18.0.0" }, "peerDependencies": { "@ai-sdk/openai": "^3.0.0", "@ai-sdk/react": "^3.0.0", "@cloudflare/ai-chat": "^0.0.7", "@cloudflare/codemode": "^0.0.7", "@x402/core": "^2.0.0", "@x402/evm": "^2.0.0", "ai": "^6.0.0", "react": "^19.0.0", "viem": ">=2.0.0", "zod": "^3.25.0 || ^4.0.0" }, "optionalPeers": ["@ai-sdk/openai", "@ai-sdk/react", "@x402/core", "@x402/evm", "viem"], "bin": { "agents": "dist/cli/index.js" } }, "sha512-YZPNCpO9KxHsyE1HyGFHPKs2MrRiOaQ6GJ9R8uPGqjmsfGZ0WWB7mayiQDgSx7tezwckrX4ShtGGftffDCMx0Q=="],
|
||||
|
||||
"asynckit": ["asynckit@0.4.0", "", {}, "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="],
|
||||
"ai": ["ai@6.0.78", "", { "dependencies": { "@ai-sdk/gateway": "3.0.39", "@ai-sdk/provider": "3.0.8", "@ai-sdk/provider-utils": "4.0.14", "@opentelemetry/api": "1.9.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-eriIX/NLWfWNDeE/OJy8wmIp9fyaH7gnxTOCPT5bp0MNkvORstp1TwRUql9au8XjXzH7o2WApqbwgxJDDV0Rbw=="],
|
||||
|
||||
"ajv": ["ajv@8.17.1", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2" } }, "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g=="],
|
||||
|
||||
"ajv-formats": ["ajv-formats@3.0.1", "", { "dependencies": { "ajv": "^8.0.0" } }, "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ=="],
|
||||
|
||||
"ansi-regex": ["ansi-regex@6.2.2", "", {}, "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg=="],
|
||||
|
||||
"ansi-styles": ["ansi-styles@6.2.3", "", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="],
|
||||
|
||||
"argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="],
|
||||
|
||||
"blake3-wasm": ["blake3-wasm@2.1.5", "", {}, "sha512-F1+K8EbfOZE49dtoPtmxUQrpXaBIl3ICvasLh+nJta0xkz+9kF/7uet9fLnwKqhDrmj6g+6K3Tw9yQPUg2ka5g=="],
|
||||
|
||||
"body-parser": ["body-parser@2.2.2", "", { "dependencies": { "bytes": "^3.1.2", "content-type": "^1.0.5", "debug": "^4.4.3", "http-errors": "^2.0.0", "iconv-lite": "^0.7.0", "on-finished": "^2.4.1", "qs": "^6.14.1", "raw-body": "^3.0.1", "type-is": "^2.0.1" } }, "sha512-oP5VkATKlNwcgvxi0vM0p/D3n2C3EReYVX+DNYs5TjZFn/oQt2j+4sVJtSMr18pdRr8wjTcBl6LoV+FUwzPmNA=="],
|
||||
|
||||
"bytes": ["bytes@3.1.2", "", {}, "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg=="],
|
||||
|
||||
"call-bind-apply-helpers": ["call-bind-apply-helpers@1.0.2", "", { "dependencies": { "es-errors": "^1.3.0", "function-bind": "^1.1.2" } }, "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ=="],
|
||||
|
||||
"call-bound": ["call-bound@1.0.4", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "get-intrinsic": "^1.3.0" } }, "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg=="],
|
||||
|
||||
"cliui": ["cliui@9.0.1", "", { "dependencies": { "string-width": "^7.2.0", "strip-ansi": "^7.1.0", "wrap-ansi": "^9.0.0" } }, "sha512-k7ndgKhwoQveBL+/1tqGJYNz097I7WOvwbmmU2AR5+magtbjPWQTS1C5vzGkBC8Ym8UWRzfKUzUUqFLypY4Q+w=="],
|
||||
|
||||
"color": ["color@4.2.3", "", { "dependencies": { "color-convert": "^2.0.1", "color-string": "^1.9.0" } }, "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A=="],
|
||||
|
||||
"color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="],
|
||||
|
|
@ -168,18 +219,38 @@
|
|||
|
||||
"color-string": ["color-string@1.9.1", "", { "dependencies": { "color-name": "^1.0.0", "simple-swizzle": "^0.2.2" } }, "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg=="],
|
||||
|
||||
"combined-stream": ["combined-stream@1.0.8", "", { "dependencies": { "delayed-stream": "~1.0.0" } }, "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg=="],
|
||||
"content-disposition": ["content-disposition@1.0.1", "", {}, "sha512-oIXISMynqSqm241k6kcQ5UwttDILMK4BiurCfGEREw6+X9jkkpEe5T9FZaApyLGGOnFuyMWZpdolTXMtvEJ08Q=="],
|
||||
|
||||
"cookie": ["cookie@1.0.2", "", {}, "sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA=="],
|
||||
"content-type": ["content-type@1.0.5", "", {}, "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA=="],
|
||||
|
||||
"cookie": ["cookie@0.7.2", "", {}, "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w=="],
|
||||
|
||||
"cookie-signature": ["cookie-signature@1.2.2", "", {}, "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg=="],
|
||||
|
||||
"core-js-pure": ["core-js-pure@3.48.0", "", {}, "sha512-1slJgk89tWC51HQ1AEqG+s2VuwpTRr8ocu4n20QUcH1v9lAN0RXen0Q0AABa/DK1I7RrNWLucplOHMx8hfTGTw=="],
|
||||
|
||||
"cors": ["cors@2.8.6", "", { "dependencies": { "object-assign": "^4", "vary": "^1" } }, "sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw=="],
|
||||
|
||||
"cron-schedule": ["cron-schedule@6.0.0", "", {}, "sha512-BoZaseYGXOo5j5HUwTaegIog3JJbuH4BbrY9A1ArLjXpy+RWb3mV28F/9Gv1dDA7E2L8kngWva4NWisnLTyfgQ=="],
|
||||
|
||||
"cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="],
|
||||
|
||||
"debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="],
|
||||
|
||||
"defu": ["defu@6.1.4", "", {}, "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg=="],
|
||||
|
||||
"delayed-stream": ["delayed-stream@1.0.0", "", {}, "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ=="],
|
||||
"depd": ["depd@2.0.0", "", {}, "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw=="],
|
||||
|
||||
"detect-libc": ["detect-libc@2.0.4", "", {}, "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA=="],
|
||||
|
||||
"dunder-proto": ["dunder-proto@1.0.1", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.1", "es-errors": "^1.3.0", "gopd": "^1.2.0" } }, "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A=="],
|
||||
|
||||
"ee-first": ["ee-first@1.1.1", "", {}, "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="],
|
||||
|
||||
"emoji-regex": ["emoji-regex@10.6.0", "", {}, "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A=="],
|
||||
|
||||
"encodeurl": ["encodeurl@2.0.0", "", {}, "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg=="],
|
||||
|
||||
"error-stack-parser-es": ["error-stack-parser-es@1.0.5", "", {}, "sha512-5qucVt2XcuGMcEGgWI7i+yZpmpByQ8J1lHhcL7PwqCwu9FPP3VUXzT4ltHe5i2z9dePwEHcDVOAfSnHsOlCXRA=="],
|
||||
|
||||
"es-define-property": ["es-define-property@1.0.1", "", {}, "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g=="],
|
||||
|
|
@ -188,26 +259,48 @@
|
|||
|
||||
"es-object-atoms": ["es-object-atoms@1.1.1", "", { "dependencies": { "es-errors": "^1.3.0" } }, "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA=="],
|
||||
|
||||
"es-set-tostringtag": ["es-set-tostringtag@2.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6", "has-tostringtag": "^1.0.2", "hasown": "^2.0.2" } }, "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA=="],
|
||||
|
||||
"esbuild": ["esbuild@0.25.4", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.4", "@esbuild/android-arm": "0.25.4", "@esbuild/android-arm64": "0.25.4", "@esbuild/android-x64": "0.25.4", "@esbuild/darwin-arm64": "0.25.4", "@esbuild/darwin-x64": "0.25.4", "@esbuild/freebsd-arm64": "0.25.4", "@esbuild/freebsd-x64": "0.25.4", "@esbuild/linux-arm": "0.25.4", "@esbuild/linux-arm64": "0.25.4", "@esbuild/linux-ia32": "0.25.4", "@esbuild/linux-loong64": "0.25.4", "@esbuild/linux-mips64el": "0.25.4", "@esbuild/linux-ppc64": "0.25.4", "@esbuild/linux-riscv64": "0.25.4", "@esbuild/linux-s390x": "0.25.4", "@esbuild/linux-x64": "0.25.4", "@esbuild/netbsd-arm64": "0.25.4", "@esbuild/netbsd-x64": "0.25.4", "@esbuild/openbsd-arm64": "0.25.4", "@esbuild/openbsd-x64": "0.25.4", "@esbuild/sunos-x64": "0.25.4", "@esbuild/win32-arm64": "0.25.4", "@esbuild/win32-ia32": "0.25.4", "@esbuild/win32-x64": "0.25.4" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-8pgjLUcUjcgDg+2Q4NYXnPbo/vncAY4UmyaCm0jZevERqCHZIaWwdJHkf8XQtu4AxSKCdvrUbT0XUr1IdZzI8Q=="],
|
||||
|
||||
"event-target-shim": ["event-target-shim@5.0.1", "", {}, "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ=="],
|
||||
"escalade": ["escalade@3.2.0", "", {}, "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA=="],
|
||||
|
||||
"escape-html": ["escape-html@1.0.3", "", {}, "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow=="],
|
||||
|
||||
"etag": ["etag@1.8.1", "", {}, "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg=="],
|
||||
|
||||
"event-target-polyfill": ["event-target-polyfill@0.0.4", "", {}, "sha512-Gs6RLjzlLRdT8X9ZipJdIZI/Y6/HhRLyq9RdDlCsnpxr/+Nn6bU2EFGuC94GjxqhM+Nmij2Vcq98yoHrU8uNFQ=="],
|
||||
|
||||
"eventsource": ["eventsource@3.0.7", "", { "dependencies": { "eventsource-parser": "^3.0.1" } }, "sha512-CRT1WTyuQoD771GW56XEZFQ/ZoSfWid1alKGDYMmkt2yl8UXrVR4pspqWNEcqKvVIzg6PAltWjxcSSPrboA4iA=="],
|
||||
|
||||
"eventsource-parser": ["eventsource-parser@3.0.6", "", {}, "sha512-Vo1ab+QXPzZ4tCa8SwIHJFaSzy4R6SHf7BY79rFBDf0idraZWAkYrDjDj8uWaSm3S2TK+hJ7/t1CEmZ7jXw+pg=="],
|
||||
|
||||
"exit-hook": ["exit-hook@2.2.1", "", {}, "sha512-eNTPlAD67BmP31LDINZ3U7HSF8l57TxOY2PmBJ1shpCvpnxBF93mWCE8YHBnXs8qiUZJc9WDcWIeC3a2HIAMfw=="],
|
||||
|
||||
"express": ["express@5.2.1", "", { "dependencies": { "accepts": "^2.0.0", "body-parser": "^2.2.1", "content-disposition": "^1.0.0", "content-type": "^1.0.5", "cookie": "^0.7.1", "cookie-signature": "^1.2.1", "debug": "^4.4.0", "depd": "^2.0.0", "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "etag": "^1.8.1", "finalhandler": "^2.1.0", "fresh": "^2.0.0", "http-errors": "^2.0.0", "merge-descriptors": "^2.0.0", "mime-types": "^3.0.0", "on-finished": "^2.4.1", "once": "^1.4.0", "parseurl": "^1.3.3", "proxy-addr": "^2.0.7", "qs": "^6.14.0", "range-parser": "^1.2.1", "router": "^2.2.0", "send": "^1.1.0", "serve-static": "^2.2.0", "statuses": "^2.0.1", "type-is": "^2.0.1", "vary": "^1.1.2" } }, "sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw=="],
|
||||
|
||||
"express-rate-limit": ["express-rate-limit@8.2.1", "", { "dependencies": { "ip-address": "10.0.1" }, "peerDependencies": { "express": ">= 4.11" } }, "sha512-PCZEIEIxqwhzw4KF0n7QF4QqruVTcF73O5kFKUnGOyjbCCgizBBiFaYpd/fnBLUMPw/BWw9OsiN7GgrNYr7j6g=="],
|
||||
|
||||
"exsolve": ["exsolve@1.0.7", "", {}, "sha512-VO5fQUzZtI6C+vx4w/4BWJpg3s/5l+6pRQEHzFRM8WFi4XffSP1Z+4qi7GbjWbvRQEbdIco5mIMq+zX4rPuLrw=="],
|
||||
|
||||
"form-data": ["form-data@4.0.4", "", { "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", "hasown": "^2.0.2", "mime-types": "^2.1.12" } }, "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow=="],
|
||||
"fast-deep-equal": ["fast-deep-equal@3.1.3", "", {}, "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="],
|
||||
|
||||
"form-data-encoder": ["form-data-encoder@1.7.2", "", {}, "sha512-qfqtYan3rxrnCk1VYaA4H+Ms9xdpPqvLZa6xmMgFvhO32x7/3J/ExcTd6qpxM0vH2GdMI+poehyBZvqfMTto8A=="],
|
||||
"fast-uri": ["fast-uri@3.1.0", "", {}, "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA=="],
|
||||
|
||||
"formdata-node": ["formdata-node@4.4.1", "", { "dependencies": { "node-domexception": "1.0.0", "web-streams-polyfill": "4.0.0-beta.3" } }, "sha512-0iirZp3uVDjVGt9p49aTaqjk84TrglENEDuqfdlZQ1roC9CWlPk6Avf8EEnZNcAqPonwkG35x4n3ww/1THYAeQ=="],
|
||||
"fdir": ["fdir@6.5.0", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="],
|
||||
|
||||
"finalhandler": ["finalhandler@2.1.1", "", { "dependencies": { "debug": "^4.4.0", "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "on-finished": "^2.4.1", "parseurl": "^1.3.3", "statuses": "^2.0.1" } }, "sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA=="],
|
||||
|
||||
"forwarded": ["forwarded@0.2.0", "", {}, "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow=="],
|
||||
|
||||
"fresh": ["fresh@2.0.0", "", {}, "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A=="],
|
||||
|
||||
"fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="],
|
||||
|
||||
"function-bind": ["function-bind@1.1.2", "", {}, "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="],
|
||||
|
||||
"get-caller-file": ["get-caller-file@2.0.5", "", {}, "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg=="],
|
||||
|
||||
"get-east-asian-width": ["get-east-asian-width@1.4.0", "", {}, "sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q=="],
|
||||
|
||||
"get-intrinsic": ["get-intrinsic@1.3.0", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.1.1", "function-bind": "^1.1.2", "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-symbols": "^1.1.0", "hasown": "^2.0.2", "math-intrinsics": "^1.1.0" } }, "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ=="],
|
||||
|
||||
"get-proto": ["get-proto@1.0.1", "", { "dependencies": { "dunder-proto": "^1.0.1", "es-object-atoms": "^1.0.0" } }, "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g=="],
|
||||
|
|
@ -218,52 +311,158 @@
|
|||
|
||||
"has-symbols": ["has-symbols@1.1.0", "", {}, "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ=="],
|
||||
|
||||
"has-tostringtag": ["has-tostringtag@1.0.2", "", { "dependencies": { "has-symbols": "^1.0.3" } }, "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw=="],
|
||||
|
||||
"hasown": ["hasown@2.0.2", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ=="],
|
||||
|
||||
"humanize-ms": ["humanize-ms@1.2.1", "", { "dependencies": { "ms": "^2.0.0" } }, "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ=="],
|
||||
"hono": ["hono@4.11.9", "", {}, "sha512-Eaw2YTGM6WOxA6CXbckaEvslr2Ne4NFsKrvc0v97JD5awbmeBLO5w9Ho9L9kmKonrwF9RJlW6BxT1PVv/agBHQ=="],
|
||||
|
||||
"http-errors": ["http-errors@2.0.1", "", { "dependencies": { "depd": "~2.0.0", "inherits": "~2.0.4", "setprototypeof": "~1.2.0", "statuses": "~2.0.2", "toidentifier": "~1.0.1" } }, "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ=="],
|
||||
|
||||
"iconv-lite": ["iconv-lite@0.7.2", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw=="],
|
||||
|
||||
"inherits": ["inherits@2.0.4", "", {}, "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="],
|
||||
|
||||
"ip-address": ["ip-address@10.0.1", "", {}, "sha512-NWv9YLW4PoW2B7xtzaS3NCot75m6nK7Icdv0o3lfMceJVRfSoQwqD4wEH5rLwoKJwUiZ/rfpiVBhnaF0FK4HoA=="],
|
||||
|
||||
"ipaddr.js": ["ipaddr.js@1.9.1", "", {}, "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g=="],
|
||||
|
||||
"is-arrayish": ["is-arrayish@0.3.2", "", {}, "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ=="],
|
||||
|
||||
"is-extglob": ["is-extglob@2.1.1", "", {}, "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="],
|
||||
|
||||
"is-glob": ["is-glob@4.0.3", "", { "dependencies": { "is-extglob": "^2.1.1" } }, "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg=="],
|
||||
|
||||
"is-promise": ["is-promise@4.0.0", "", {}, "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ=="],
|
||||
|
||||
"isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="],
|
||||
|
||||
"jose": ["jose@6.1.3", "", {}, "sha512-0TpaTfihd4QMNwrz/ob2Bp7X04yuxJkjRGi4aKmOqwhov54i6u79oCv7T+C7lo70MKH6BesI3vscD1yb/yzKXQ=="],
|
||||
|
||||
"js-base64": ["js-base64@3.7.8", "", {}, "sha512-hNngCeKxIUQiEUN3GPJOkz4wF/YvdUdbNL9hsBcMQTkKzboD7T/q3OYOuuPZLUE6dBxSGpwhk5mwuDud7JVAow=="],
|
||||
|
||||
"js-yaml": ["js-yaml@4.1.1", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA=="],
|
||||
|
||||
"json-schema": ["json-schema@0.4.0", "", {}, "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA=="],
|
||||
|
||||
"json-schema-to-typescript": ["json-schema-to-typescript@15.0.4", "", { "dependencies": { "@apidevtools/json-schema-ref-parser": "^11.5.5", "@types/json-schema": "^7.0.15", "@types/lodash": "^4.17.7", "is-glob": "^4.0.3", "js-yaml": "^4.1.0", "lodash": "^4.17.21", "minimist": "^1.2.8", "prettier": "^3.2.5", "tinyglobby": "^0.2.9" }, "bin": { "json2ts": "dist/src/cli.js" } }, "sha512-Su9oK8DR4xCmDsLlyvadkXzX6+GGXJpbhwoLtOGArAG61dvbW4YQmSEno2y66ahpIdmLMg6YUf/QHLgiwvkrHQ=="],
|
||||
|
||||
"json-schema-traverse": ["json-schema-traverse@1.0.0", "", {}, "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="],
|
||||
|
||||
"json-schema-typed": ["json-schema-typed@8.0.2", "", {}, "sha512-fQhoXdcvc3V28x7C7BMs4P5+kNlgUURe2jmUT1T//oBRMDrqy1QPelJimwZGo7Hg9VPV3EQV5Bnq4hbFy2vetA=="],
|
||||
|
||||
"kleur": ["kleur@4.1.5", "", {}, "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ=="],
|
||||
|
||||
"lodash": ["lodash@4.17.23", "", {}, "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w=="],
|
||||
|
||||
"math-intrinsics": ["math-intrinsics@1.1.0", "", {}, "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g=="],
|
||||
|
||||
"media-typer": ["media-typer@1.1.0", "", {}, "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw=="],
|
||||
|
||||
"merge-descriptors": ["merge-descriptors@2.0.0", "", {}, "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g=="],
|
||||
|
||||
"mime": ["mime@3.0.0", "", { "bin": { "mime": "cli.js" } }, "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A=="],
|
||||
|
||||
"mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="],
|
||||
"mime-db": ["mime-db@1.54.0", "", {}, "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ=="],
|
||||
|
||||
"mime-types": ["mime-types@2.1.35", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="],
|
||||
"mime-types": ["mime-types@3.0.2", "", { "dependencies": { "mime-db": "^1.54.0" } }, "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A=="],
|
||||
|
||||
"mimetext": ["mimetext@3.0.28", "", { "dependencies": { "@babel/runtime": "^7.26.0", "@babel/runtime-corejs3": "^7.26.0", "js-base64": "^3.7.7", "mime-types": "^2.1.35" } }, "sha512-eQXpbNrtxLCjUtiVbR/qR09dbPgZ2o+KR1uA7QKqGhbn8QV7HIL16mXXsobBL4/8TqoYh1us31kfz+dNfCev9g=="],
|
||||
|
||||
"miniflare": ["miniflare@4.20250712.2", "", { "dependencies": { "@cspotcode/source-map-support": "0.8.1", "acorn": "8.14.0", "acorn-walk": "8.3.2", "exit-hook": "2.2.1", "glob-to-regexp": "0.4.1", "sharp": "^0.33.5", "stoppable": "1.1.0", "undici": "^7.10.0", "workerd": "1.20250712.0", "ws": "8.18.0", "youch": "4.1.0-beta.10", "zod": "3.22.3" }, "bin": { "miniflare": "bootstrap.js" } }, "sha512-cZ8WyQBwqfjYLjd61fDR4/j0nAVbjB3Wxbun/brL9S5FAi4RlTR0LyMTKsIVA0s+nL4Pg9VjVMki4M/Jk2cz+Q=="],
|
||||
|
||||
"minimist": ["minimist@1.2.8", "", {}, "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA=="],
|
||||
|
||||
"ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="],
|
||||
|
||||
"node-domexception": ["node-domexception@1.0.0", "", {}, "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ=="],
|
||||
"nanoid": ["nanoid@5.1.6", "", { "bin": { "nanoid": "bin/nanoid.js" } }, "sha512-c7+7RQ+dMB5dPwwCp4ee1/iV/q2P6aK1mTZcfr1BTuVlyW9hJYiMPybJCcnBlQtuSmTIWNeazm/zqNoZSSElBg=="],
|
||||
|
||||
"node-fetch": ["node-fetch@2.7.0", "", { "dependencies": { "whatwg-url": "^5.0.0" }, "peerDependencies": { "encoding": "^0.1.0" }, "optionalPeers": ["encoding"] }, "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A=="],
|
||||
"negotiator": ["negotiator@1.0.0", "", {}, "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg=="],
|
||||
|
||||
"object-assign": ["object-assign@4.1.1", "", {}, "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="],
|
||||
|
||||
"object-inspect": ["object-inspect@1.13.4", "", {}, "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew=="],
|
||||
|
||||
"ohash": ["ohash@2.0.11", "", {}, "sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ=="],
|
||||
|
||||
"on-finished": ["on-finished@2.4.1", "", { "dependencies": { "ee-first": "1.1.1" } }, "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg=="],
|
||||
|
||||
"once": ["once@1.4.0", "", { "dependencies": { "wrappy": "1" } }, "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w=="],
|
||||
|
||||
"parseurl": ["parseurl@1.3.3", "", {}, "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ=="],
|
||||
|
||||
"partyserver": ["partyserver@0.1.5", "", { "dependencies": { "nanoid": "^5.1.6" }, "peerDependencies": { "@cloudflare/workers-types": "^4.20240729.0" } }, "sha512-kaE3GYaYWFc70EJQDQEhyYbO2Wczz/NgsFXerfjRo0t2s7ZxL1XggWT+HkMrdEyqbZOv3b66CV93WG0Lcg/ThQ=="],
|
||||
|
||||
"partysocket": ["partysocket@1.1.13", "", { "dependencies": { "event-target-polyfill": "^0.0.4" } }, "sha512-RNXGzc6j0NISGE84+VTHHtbPwmnzZuOYJm9XZ+en+aZlIA2vC4AfwPlYxAHmGGGko3pQF7xRNhoe7bu1Brej4Q=="],
|
||||
|
||||
"path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="],
|
||||
|
||||
"path-to-regexp": ["path-to-regexp@6.3.0", "", {}, "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ=="],
|
||||
|
||||
"pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="],
|
||||
|
||||
"picomatch": ["picomatch@4.0.3", "", {}, "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="],
|
||||
|
||||
"pkce-challenge": ["pkce-challenge@5.0.1", "", {}, "sha512-wQ0b/W4Fr01qtpHlqSqspcj3EhBvimsdh0KlHhH8HRZnMsEa0ea2fTULOXOS9ccQr3om+GcGRk4e+isrZWV8qQ=="],
|
||||
|
||||
"prettier": ["prettier@3.8.1", "", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg=="],
|
||||
|
||||
"proxy-addr": ["proxy-addr@2.0.7", "", { "dependencies": { "forwarded": "0.2.0", "ipaddr.js": "1.9.1" } }, "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg=="],
|
||||
|
||||
"qs": ["qs@6.14.1", "", { "dependencies": { "side-channel": "^1.1.0" } }, "sha512-4EK3+xJl8Ts67nLYNwqw/dsFVnCf+qR7RgXSK9jEEm9unao3njwMDdmsdvoKBKHzxd7tCYz5e5M+SnMjdtXGQQ=="],
|
||||
|
||||
"range-parser": ["range-parser@1.2.1", "", {}, "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg=="],
|
||||
|
||||
"raw-body": ["raw-body@3.0.2", "", { "dependencies": { "bytes": "~3.1.2", "http-errors": "~2.0.1", "iconv-lite": "~0.7.0", "unpipe": "~1.0.0" } }, "sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA=="],
|
||||
|
||||
"react": ["react@19.2.4", "", {}, "sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ=="],
|
||||
|
||||
"require-from-string": ["require-from-string@2.0.2", "", {}, "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw=="],
|
||||
|
||||
"router": ["router@2.2.0", "", { "dependencies": { "debug": "^4.4.0", "depd": "^2.0.0", "is-promise": "^4.0.0", "parseurl": "^1.3.3", "path-to-regexp": "^8.0.0" } }, "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ=="],
|
||||
|
||||
"safer-buffer": ["safer-buffer@2.1.2", "", {}, "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="],
|
||||
|
||||
"semver": ["semver@7.7.2", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA=="],
|
||||
|
||||
"send": ["send@1.2.1", "", { "dependencies": { "debug": "^4.4.3", "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "etag": "^1.8.1", "fresh": "^2.0.0", "http-errors": "^2.0.1", "mime-types": "^3.0.2", "ms": "^2.1.3", "on-finished": "^2.4.1", "range-parser": "^1.2.1", "statuses": "^2.0.2" } }, "sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ=="],
|
||||
|
||||
"serve-static": ["serve-static@2.2.1", "", { "dependencies": { "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "parseurl": "^1.3.3", "send": "^1.2.0" } }, "sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw=="],
|
||||
|
||||
"setprototypeof": ["setprototypeof@1.2.0", "", {}, "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="],
|
||||
|
||||
"sharp": ["sharp@0.33.5", "", { "dependencies": { "color": "^4.2.3", "detect-libc": "^2.0.3", "semver": "^7.6.3" }, "optionalDependencies": { "@img/sharp-darwin-arm64": "0.33.5", "@img/sharp-darwin-x64": "0.33.5", "@img/sharp-libvips-darwin-arm64": "1.0.4", "@img/sharp-libvips-darwin-x64": "1.0.4", "@img/sharp-libvips-linux-arm": "1.0.5", "@img/sharp-libvips-linux-arm64": "1.0.4", "@img/sharp-libvips-linux-s390x": "1.0.4", "@img/sharp-libvips-linux-x64": "1.0.4", "@img/sharp-libvips-linuxmusl-arm64": "1.0.4", "@img/sharp-libvips-linuxmusl-x64": "1.0.4", "@img/sharp-linux-arm": "0.33.5", "@img/sharp-linux-arm64": "0.33.5", "@img/sharp-linux-s390x": "0.33.5", "@img/sharp-linux-x64": "0.33.5", "@img/sharp-linuxmusl-arm64": "0.33.5", "@img/sharp-linuxmusl-x64": "0.33.5", "@img/sharp-wasm32": "0.33.5", "@img/sharp-win32-ia32": "0.33.5", "@img/sharp-win32-x64": "0.33.5" } }, "sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw=="],
|
||||
|
||||
"shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="],
|
||||
|
||||
"shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="],
|
||||
|
||||
"side-channel": ["side-channel@1.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.3", "side-channel-list": "^1.0.0", "side-channel-map": "^1.0.1", "side-channel-weakmap": "^1.0.2" } }, "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw=="],
|
||||
|
||||
"side-channel-list": ["side-channel-list@1.0.0", "", { "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.3" } }, "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA=="],
|
||||
|
||||
"side-channel-map": ["side-channel-map@1.0.1", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.5", "object-inspect": "^1.13.3" } }, "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA=="],
|
||||
|
||||
"side-channel-weakmap": ["side-channel-weakmap@1.0.2", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.5", "object-inspect": "^1.13.3", "side-channel-map": "^1.0.1" } }, "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A=="],
|
||||
|
||||
"simple-swizzle": ["simple-swizzle@0.2.2", "", { "dependencies": { "is-arrayish": "^0.3.1" } }, "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg=="],
|
||||
|
||||
"statuses": ["statuses@2.0.2", "", {}, "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw=="],
|
||||
|
||||
"stoppable": ["stoppable@1.1.0", "", {}, "sha512-KXDYZ9dszj6bzvnEMRYvxgeTHU74QBFL54XKtP3nyMuJ81CFYtABZ3bAzL2EdFUaEwJOBOgENyFj3R7oTzDyyw=="],
|
||||
|
||||
"string-width": ["string-width@7.2.0", "", { "dependencies": { "emoji-regex": "^10.3.0", "get-east-asian-width": "^1.0.0", "strip-ansi": "^7.1.0" } }, "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ=="],
|
||||
|
||||
"strip-ansi": ["strip-ansi@7.1.2", "", { "dependencies": { "ansi-regex": "^6.0.1" } }, "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA=="],
|
||||
|
||||
"supports-color": ["supports-color@10.0.0", "", {}, "sha512-HRVVSbCCMbj7/kdWF9Q+bbckjBHLtHMEoJWlkmYzzdwhYMkjkOwubLM6t7NbWKjgKamGDrWL1++KrjUO1t9oAQ=="],
|
||||
|
||||
"tr46": ["tr46@0.0.3", "", {}, "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="],
|
||||
"tinyglobby": ["tinyglobby@0.2.15", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.3" } }, "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ=="],
|
||||
|
||||
"toidentifier": ["toidentifier@1.0.1", "", {}, "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA=="],
|
||||
|
||||
"tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
|
||||
|
||||
"type-is": ["type-is@2.0.1", "", { "dependencies": { "content-type": "^1.0.5", "media-typer": "^1.1.0", "mime-types": "^3.0.0" } }, "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw=="],
|
||||
|
||||
"typescript": ["typescript@5.8.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ=="],
|
||||
|
||||
"ufo": ["ufo@1.6.1", "", {}, "sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA=="],
|
||||
|
|
@ -274,28 +473,48 @@
|
|||
|
||||
"unenv": ["unenv@2.0.0-rc.17", "", { "dependencies": { "defu": "^6.1.4", "exsolve": "^1.0.4", "ohash": "^2.0.11", "pathe": "^2.0.3", "ufo": "^1.6.1" } }, "sha512-B06u0wXkEd+o5gOCMl/ZHl5cfpYbDZKAT+HWTL+Hws6jWu7dCiqBBXXXzMFcFVJb8D4ytAnYmxJA83uwOQRSsg=="],
|
||||
|
||||
"web-streams-polyfill": ["web-streams-polyfill@4.0.0-beta.3", "", {}, "sha512-QW95TCTaHmsYfHDybGMwO5IJIM93I/6vTRk+daHTWFPhwh+C8Cg7j7XyKrwrj8Ib6vYXe0ocYNrmzY4xAAN6ug=="],
|
||||
"unpipe": ["unpipe@1.0.0", "", {}, "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ=="],
|
||||
|
||||
"webidl-conversions": ["webidl-conversions@3.0.1", "", {}, "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="],
|
||||
"vary": ["vary@1.1.2", "", {}, "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg=="],
|
||||
|
||||
"whatwg-url": ["whatwg-url@5.0.0", "", { "dependencies": { "tr46": "~0.0.3", "webidl-conversions": "^3.0.0" } }, "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw=="],
|
||||
"which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="],
|
||||
|
||||
"workerd": ["workerd@1.20250712.0", "", { "optionalDependencies": { "@cloudflare/workerd-darwin-64": "1.20250712.0", "@cloudflare/workerd-darwin-arm64": "1.20250712.0", "@cloudflare/workerd-linux-64": "1.20250712.0", "@cloudflare/workerd-linux-arm64": "1.20250712.0", "@cloudflare/workerd-windows-64": "1.20250712.0" }, "bin": { "workerd": "bin/workerd" } }, "sha512-7h+k1OxREpiZW0849g0uQNexRWMcs5i5gUGhJzCY8nIx6Tv4D/ndlXJ47lEFj7/LQdp165IL9dM2D5uDiedZrg=="],
|
||||
|
||||
"wrangler": ["wrangler@4.26.0", "", { "dependencies": { "@cloudflare/kv-asset-handler": "0.4.0", "@cloudflare/unenv-preset": "2.4.1", "blake3-wasm": "2.1.5", "esbuild": "0.25.4", "miniflare": "4.20250712.2", "path-to-regexp": "6.3.0", "unenv": "2.0.0-rc.17", "workerd": "1.20250712.0" }, "optionalDependencies": { "fsevents": "~2.3.2" }, "peerDependencies": { "@cloudflare/workers-types": "^4.20250712.0" }, "optionalPeers": ["@cloudflare/workers-types"], "bin": { "wrangler": "bin/wrangler.js", "wrangler2": "bin/wrangler.js" } }, "sha512-EXuwyWlgYQZv6GJlyE0lVGk9hHqASssuECECT1XC5aIijTwNLQhsj/TOZ0hKSFlMbVr1E+OAdevAxd0kaF4ovA=="],
|
||||
|
||||
"wrap-ansi": ["wrap-ansi@9.0.2", "", { "dependencies": { "ansi-styles": "^6.2.1", "string-width": "^7.0.0", "strip-ansi": "^7.1.0" } }, "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww=="],
|
||||
|
||||
"wrappy": ["wrappy@1.0.2", "", {}, "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="],
|
||||
|
||||
"ws": ["ws@8.18.0", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw=="],
|
||||
|
||||
"y18n": ["y18n@5.0.8", "", {}, "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA=="],
|
||||
|
||||
"yargs": ["yargs@18.0.0", "", { "dependencies": { "cliui": "^9.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "string-width": "^7.2.0", "y18n": "^5.0.5", "yargs-parser": "^22.0.0" } }, "sha512-4UEqdc2RYGHZc7Doyqkrqiln3p9X2DZVxaGbwhn2pi7MrRagKaOcIKe8L3OxYcbhXLgLFUS3zAYuQjKBQgmuNg=="],
|
||||
|
||||
"yargs-parser": ["yargs-parser@22.0.0", "", {}, "sha512-rwu/ClNdSMpkSrUb+d6BRsSkLUq1fmfsY6TOpYzTwvwkg1/NRG85KBy3kq++A8LKQwX6lsu+aWad+2khvuXrqw=="],
|
||||
|
||||
"youch": ["youch@4.1.0-beta.10", "", { "dependencies": { "@poppinss/colors": "^4.1.5", "@poppinss/dumper": "^0.6.4", "@speed-highlight/core": "^1.2.7", "cookie": "^1.0.2", "youch-core": "^0.3.3" } }, "sha512-rLfVLB4FgQneDr0dv1oddCVZmKjcJ6yX6mS4pU82Mq/Dt9a3cLZQ62pDBL4AUO+uVrCvtWz3ZFUL2HFAFJ/BXQ=="],
|
||||
|
||||
"youch-core": ["youch-core@0.3.3", "", { "dependencies": { "@poppinss/exception": "^1.2.2", "error-stack-parser-es": "^1.0.5" } }, "sha512-ho7XuGjLaJ2hWHoK8yFnsUGy2Y5uDpqSTq1FkHLK4/oqKtyUU1AFbOOxY4IpC9f0fTLjwYbslUz0Po5BpD1wrA=="],
|
||||
|
||||
"zod": ["zod@4.0.0", "", {}, "sha512-9diLdTPc/L7w/5jI4C3gHYNiGHDV9IZYxo1e5LSD8cabi65WVTWWb+g2BGPEpUUCOxR4D+6O5B0AzyMdUAXwrw=="],
|
||||
"zod": ["zod@4.3.6", "", {}, "sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg=="],
|
||||
|
||||
"@honcho-ai/core/@types/node": ["@types/node@18.19.120", "", { "dependencies": { "undici-types": "~5.26.4" } }, "sha512-WtCGHFXnVI8WHLxDAt5TbnCM4eSE+nI0QN2NJtwzcgMhht2eNz6V9evJrk+lwC8bCY8OWV5Ym8Jz7ZEyGnKnMA=="],
|
||||
"zod-to-json-schema": ["zod-to-json-schema@3.25.1", "", { "peerDependencies": { "zod": "^3.25 || ^4" } }, "sha512-pM/SU9d3YAggzi6MtR4h7ruuQlqKtad8e9S0fmxcMi+ueAK5Korys/aWcV9LIIHTVbj01NdzxcnXSN+O74ZIVA=="],
|
||||
|
||||
"zod-to-ts": ["zod-to-ts@2.0.0", "", { "peerDependencies": { "typescript": "^5.0.0", "zod": "^3.25.0 || ^4.0.0" } }, "sha512-aHsUgIl+CQutKAxtRNeZslLCLXoeuSq+j5HU7q3kvi/c2KIAo6q4YjT7/lwFfACxLB923ELHYMkHmlxiqFy4lw=="],
|
||||
|
||||
"@honcho-ai/sdk/zod": ["zod@4.0.0", "", {}, "sha512-9diLdTPc/L7w/5jI4C3gHYNiGHDV9IZYxo1e5LSD8cabi65WVTWWb+g2BGPEpUUCOxR4D+6O5B0AzyMdUAXwrw=="],
|
||||
|
||||
"mimetext/mime-types": ["mime-types@2.1.35", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="],
|
||||
|
||||
"miniflare/zod": ["zod@3.22.3", "", {}, "sha512-EjIevzuJRiRPbVH4mGc8nApb/lVLKVpmUhAaR5R5doKGfAnGJ6Gr3CViAVjP+4FWSxCsybeWQdcgCtbX+7oZug=="],
|
||||
|
||||
"@honcho-ai/core/@types/node/undici-types": ["undici-types@5.26.5", "", {}, "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA=="],
|
||||
"router/path-to-regexp": ["path-to-regexp@8.3.0", "", {}, "sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA=="],
|
||||
|
||||
"youch/cookie": ["cookie@1.0.2", "", {}, "sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA=="],
|
||||
|
||||
"mimetext/mime-types/mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="],
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,156 +1,137 @@
|
|||
# Comprehensive Honcho MCP Integration Instructions
|
||||
# Honcho MCP Server — Instructions
|
||||
|
||||
## What is Honcho?
|
||||
## Quick Start: Bespoke Flow
|
||||
|
||||
Honcho is an infrastructure layer for building AI agents with memory and social cognition. It enables personalized AI interactions by building coherent models of user psychology over time. The Honcho MCP server simplifies the integration to just 3 essential functions. Here's how to use them:
|
||||
The simplest way to use Honcho is the **bespoke flow** — three tools that handle everything for a standard user/assistant conversation.
|
||||
|
||||
### Step 1: Start New Conversation (First Message Only)
|
||||
### 1. Start a conversation (once per conversation)
|
||||
|
||||
When a user begins a new conversation, always call `start_conversation`:
|
||||
|
||||
```text
|
||||
```
|
||||
start_conversation
|
||||
```
|
||||
|
||||
**Returns**: A session ID that you must store and use for all subsequent interactions in this conversation.
|
||||
Returns a `session_id`. Store it for the rest of this conversation.
|
||||
|
||||
### Step 2: Get Personalized Insights (When Helpful)
|
||||
### 2. Get personalization insights (before responding, when helpful)
|
||||
|
||||
Before responding to any user message, you can query for personalization insights:
|
||||
|
||||
```text
|
||||
```
|
||||
get_personalization_insights
|
||||
session_id: [SESSION_ID_FROM_STEP_1]
|
||||
query: [YOUR_QUESTION]
|
||||
session_id: "<session_id>"
|
||||
query: "What communication style does this user prefer?"
|
||||
```
|
||||
|
||||
This query takes a bit of time, so it's best to only perform it when you need personalized insights. If the query can be responded to effectively using what you already know about the user, just go ahead and answer it. However, the insights endpoint is extremely perceptive. It has the capability to reveal aspects of the user's personality, historical use of the application you are operating in, and more.
|
||||
This calls Honcho's reasoning system to answer your question about the user, grounded in everything Honcho has learned across all their conversations. It takes a few seconds, so use it when personalization would genuinely improve your response.
|
||||
|
||||
**Returns**: Personalized insights about the user based on accumulated knowledge.
|
||||
|
||||
**Example Queries**:
|
||||
**Good queries:**
|
||||
|
||||
- "What does this message reveal about the user's communication preferences?"
|
||||
- "How formal or casual should I be with the user based on our history?"
|
||||
- "What is the user really asking for beyond her explicit question?"
|
||||
- "How formal or casual should I be?"
|
||||
- "What is the user really asking for beyond their explicit question?"
|
||||
- "What emotional state might the user be in right now?"
|
||||
- "How can I best help the user with her current request?"
|
||||
|
||||
### Step 3: Respond to User
|
||||
### 3. Record the turn (after every exchange)
|
||||
|
||||
Craft your response using any insights gained from Step 2.
|
||||
|
||||
### Step 4: Store the Conversation Turn (After Each Exchange)
|
||||
|
||||
**CRITICAL**: Always store both the user's message AND your response using `add_turn`:
|
||||
|
||||
```text
|
||||
```
|
||||
add_turn
|
||||
session_id: [SESSION_ID_FROM_STEP_1]
|
||||
messages: [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "[USER'S_EXACT_MESSAGE]"
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "[YOUR_EXACT_RESPONSE]"
|
||||
}
|
||||
]
|
||||
session_id: "<session_id>"
|
||||
messages:
|
||||
- role: "user"
|
||||
content: "<exact user message>"
|
||||
- role: "assistant"
|
||||
content: "<your exact response>"
|
||||
```
|
||||
|
||||
## Complete Example Flow
|
||||
**Always** call this after responding so Honcho can learn from the conversation.
|
||||
|
||||
Here's exactly what to do for a new conversation:
|
||||
---
|
||||
|
||||
1. **User says**: "Hi Claude! My name is Sarah and I'm feeling overwhelmed with work"
|
||||
## General Tools
|
||||
|
||||
2. **Start conversation**:
|
||||
Beyond the bespoke flow, Honcho exposes the full API for advanced use cases.
|
||||
|
||||
```text
|
||||
start_conversation
|
||||
```
|
||||
### Workspace Tools
|
||||
|
||||
→ Returns: `session_abc123`
|
||||
| Tool | When to use |
|
||||
| --- | --- |
|
||||
| `search_workspace` | Find messages across all sessions and peers |
|
||||
| `get_workspace_metadata` | Read workspace-level settings |
|
||||
| `set_workspace_metadata` | Store workspace-level settings |
|
||||
|
||||
3. **Get insights** (optional but recommended):
|
||||
### Peer Tools
|
||||
|
||||
```text
|
||||
get_personalization_insights
|
||||
session_id: "session_abc123"
|
||||
query: "What does the user's message about feeling overwhelmed tell me about her current state and how should I respond?"
|
||||
```
|
||||
| Tool | When to use |
|
||||
| --- | --- |
|
||||
| `create_peer` | Register a new participant (user or agent) |
|
||||
| `list_peers` | See all participants in the workspace |
|
||||
| `chat` | Ask Honcho what it knows about any peer. Accepts optional `reasoning_level` (`minimal`–`max`) to control depth vs. speed. |
|
||||
| `get_peer_card` | Get compact biographical facts about a peer |
|
||||
| `set_peer_card` | Manually set/correct facts about a peer |
|
||||
| `get_peer_context` | Get full context (representation + peer card) |
|
||||
| `get_representation` | Get the textual representation from conclusions |
|
||||
| `get_peer_metadata` / `set_peer_metadata` | Custom attributes on a peer |
|
||||
| `search_peer_messages` | Find messages by a specific peer |
|
||||
|
||||
→ Returns insights about Sarah's emotional state and preferred communication style
|
||||
### Session Tools
|
||||
|
||||
4. **Respond to Sarah**: "Hi Sarah! I can hear that you're feeling overwhelmed with work right now..."
|
||||
| Tool | When to use |
|
||||
| --- | --- |
|
||||
| `create_session` | Create a raw session (use `start_conversation` for the simple flow) |
|
||||
| `list_sessions` | Discover existing conversations |
|
||||
| `delete_session` | Permanently remove a session |
|
||||
| `clone_session` | Fork a conversation (optionally up to a specific message) |
|
||||
| `add_peers_to_session` / `remove_peers_from_session` | Manage session participants |
|
||||
| `get_session_peers` | See who is in a session |
|
||||
| `add_messages_to_session` | Add messages from specific peers |
|
||||
| `get_session_messages` | Read conversation history |
|
||||
| `search_session_messages` | Semantic search within a session |
|
||||
| `get_session_context` | Get LLM-ready context (messages + summary) |
|
||||
| `get_session_representation` | Get a peer's session-scoped representation |
|
||||
| `get_session_metadata` / `set_session_metadata` | Custom attributes on a session |
|
||||
|
||||
5. **Store the turn**:
|
||||
### Conclusion Tools
|
||||
|
||||
```text
|
||||
add_turn
|
||||
session_id: "session_abc123"
|
||||
messages: [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "Hi Claude! My name is Sarah and I'm feeling overwhelmed with work"
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "Hi Sarah! I can hear that you're feeling overwhelmed with work right now..."
|
||||
}
|
||||
]
|
||||
```
|
||||
| Tool | When to use |
|
||||
| --- | --- |
|
||||
| `list_conclusions` | See what Honcho has derived about a peer |
|
||||
| `query_conclusions` | Semantic search across derived facts |
|
||||
| `create_conclusions` | Inject facts manually |
|
||||
| `delete_conclusion` | Remove incorrect or outdated facts |
|
||||
|
||||
## Continuing an Existing Conversation
|
||||
### System Tools
|
||||
|
||||
For subsequent messages in the same conversation:
|
||||
| Tool | When to use |
|
||||
| --- | --- |
|
||||
| `schedule_dream` | Trigger memory consolidation for better insights |
|
||||
| `get_queue_status` | Check if background processing is complete |
|
||||
|
||||
1. **User says**: "Thanks for listening. Can you help me prioritize my tasks?"
|
||||
---
|
||||
|
||||
2. **Respond**: "Based on our conversation, I can see you value..."
|
||||
## Key Concepts
|
||||
|
||||
3. **Store the turn**:
|
||||
### Peers
|
||||
|
||||
```text
|
||||
add_turn
|
||||
session_id: "session_abc123"
|
||||
messages: [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "Thanks for listening. Can you help me prioritize my tasks?"
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "Based on our conversation, I can see you value..."
|
||||
}
|
||||
]
|
||||
```
|
||||
A **peer** is any participant — human or AI. Each peer has a unique ID within the workspace.
|
||||
|
||||
## Best Practices for Personalization Queries
|
||||
### Sessions
|
||||
|
||||
Ask questions that reveal:
|
||||
A **session** is a conversation context. Sessions track message history, manage which peers participate, and provide context retrieval for LLMs.
|
||||
|
||||
**Communication Style**: "How formal/casual should I be?" "What does this reveal about their preferences?"
|
||||
### Conclusions
|
||||
|
||||
**User Needs**: "What are they really asking for?" "What emotional state are they in?"
|
||||
**Conclusions** are facts and observations that Honcho derives from conversations. They power the representation — Honcho's understanding of a peer.
|
||||
|
||||
**Relationship**: "How can I build rapport?" "What engages them most?"
|
||||
### Representations
|
||||
|
||||
**Task Approach**: "How do they prefer problem-solving?" "What detail level do they want?"
|
||||
A **representation** is a formatted text summary built from a peer's conclusions. Query it with `get_representation` or `chat`.
|
||||
|
||||
## Error Handling
|
||||
### Peer Cards
|
||||
|
||||
- **Authorization Errors and Timeouts**: Make sure user has configured API key and URL for Honcho
|
||||
- **ValueError**: Messages were incorrectly formatted, make sure to include role and content
|
||||
- **"No personalization insights found"**: Normal when there's limited history with the user
|
||||
- **Session management**: The MCP server handles all session persistence automatically
|
||||
A **peer card** is a compact list of biographical facts about a peer, automatically maintained by Honcho (or manually via `set_peer_card`).
|
||||
|
||||
## Key Principles
|
||||
### Reasoning Level
|
||||
|
||||
1. **Always start with `start_conversation` for new conversations**
|
||||
2. **Store every message exchange with `add_turn`**
|
||||
3. **Use `get_personalization_insights` strategically for better responses**
|
||||
4. **Ask thoughtful questions about `peer` representation**
|
||||
5. **Never expose technical details to the user**
|
||||
6. **The system maintains context automatically between sessions**
|
||||
Several tools accept an optional `reasoning_level` parameter (`minimal`, `low`, `medium`, `high`, `max`). Higher levels produce more thorough answers but take longer and cost more. Default is `low`. Use `minimal` for the fastest lookups; use `high` or `max` when depth matters.
|
||||
|
||||
### Dreams
|
||||
|
||||
A **dream** is a background memory-consolidation process. It reviews conclusions, merges redundancies, and generates higher-level insights. Schedule one with `schedule_dream` after long conversations.
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
{
|
||||
"name": "honcho-mcp-proxy",
|
||||
"version": "1.0.0",
|
||||
"description": "Cloudflare Worker proxy for Honcho MCP Server",
|
||||
"main": "worker.ts",
|
||||
"name": "honcho-mcp",
|
||||
"version": "3.0.0",
|
||||
"description": "Honcho MCP Server — Cloudflare Worker",
|
||||
"main": "src/index.ts",
|
||||
"packageManager": "bun@1.2.0",
|
||||
"engines": {
|
||||
"node": ">=18.0.0",
|
||||
|
|
@ -15,7 +15,10 @@
|
|||
"deploy:staging": "wrangler deploy --env staging"
|
||||
},
|
||||
"dependencies": {
|
||||
"@honcho-ai/sdk": "^2.0.0"
|
||||
"@honcho-ai/sdk": "^2.0.0",
|
||||
"@modelcontextprotocol/sdk": "^1.26.0",
|
||||
"agents": "^0.4.0",
|
||||
"zod": "^4.3.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@cloudflare/workers-types": "^4.20241002.0",
|
||||
|
|
|
|||
|
|
@ -0,0 +1,51 @@
|
|||
import { Honcho } from "@honcho-ai/sdk";
|
||||
|
||||
export interface HonchoConfig {
|
||||
apiKey: string;
|
||||
userName: string;
|
||||
baseUrl: string;
|
||||
workspaceId: string;
|
||||
assistantName: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse configuration from request headers.
|
||||
* Throws on missing required fields so callers get clear errors.
|
||||
*/
|
||||
export function parseConfig(request: Request): HonchoConfig {
|
||||
const authHeader = request.headers.get("Authorization");
|
||||
if (!authHeader?.startsWith("Bearer ")) {
|
||||
throw new Error(
|
||||
"Missing Authorization header. Provide 'Authorization: Bearer <your-honcho-key>'.",
|
||||
);
|
||||
}
|
||||
const apiKey = authHeader.substring(7);
|
||||
if (!apiKey) {
|
||||
throw new Error("Authorization header is empty after 'Bearer '.");
|
||||
}
|
||||
|
||||
const userName = request.headers.get("X-Honcho-User-Name");
|
||||
if (!userName) {
|
||||
throw new Error(
|
||||
"Missing X-Honcho-User-Name header. Provide 'X-Honcho-User-Name: <your-name>'.",
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
apiKey,
|
||||
userName,
|
||||
baseUrl:
|
||||
request.headers.get("X-Honcho-Base-URL") || "https://api.honcho.dev",
|
||||
workspaceId: request.headers.get("X-Honcho-Workspace-ID") || "default",
|
||||
assistantName:
|
||||
request.headers.get("X-Honcho-Assistant-Name") || "Assistant",
|
||||
};
|
||||
}
|
||||
|
||||
export function createClient(config: HonchoConfig): Honcho {
|
||||
return new Honcho({
|
||||
apiKey: config.apiKey,
|
||||
baseURL: config.baseUrl,
|
||||
workspaceId: config.workspaceId,
|
||||
});
|
||||
}
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
import { createMcpHandler } from "agents/mcp";
|
||||
import { parseConfig, createClient } from "./config.js";
|
||||
import { createServer } from "./server.js";
|
||||
|
||||
const CORS_ORIGIN = "*";
|
||||
const CORS_METHODS = "GET, POST, DELETE, OPTIONS";
|
||||
const CORS_ALLOWED_HEADERS =
|
||||
"Content-Type, Authorization, X-Honcho-User-Name, X-Honcho-Base-URL, X-Honcho-Workspace-ID, X-Honcho-Assistant-Name";
|
||||
|
||||
const CORS_HEADERS = {
|
||||
"Access-Control-Allow-Origin": CORS_ORIGIN,
|
||||
"Access-Control-Allow-Methods": CORS_METHODS,
|
||||
"Access-Control-Allow-Headers": CORS_ALLOWED_HEADERS,
|
||||
};
|
||||
|
||||
export default {
|
||||
async fetch(
|
||||
request: Request,
|
||||
env: unknown,
|
||||
executionCtx: ExecutionContext,
|
||||
): Promise<Response> {
|
||||
let config;
|
||||
try {
|
||||
config = parseConfig(request);
|
||||
} catch (e) {
|
||||
const message =
|
||||
e instanceof Error ? e.message : "Invalid request";
|
||||
return new Response(JSON.stringify({ error: message }), {
|
||||
status: 401,
|
||||
headers: { "Content-Type": "application/json", ...CORS_HEADERS },
|
||||
});
|
||||
}
|
||||
|
||||
try {
|
||||
const honcho = createClient(config);
|
||||
const server = createServer({ honcho, config });
|
||||
const handler = createMcpHandler(server, {
|
||||
corsOptions: {
|
||||
origin: CORS_ORIGIN,
|
||||
methods: CORS_METHODS,
|
||||
headers: CORS_ALLOWED_HEADERS,
|
||||
},
|
||||
});
|
||||
return handler(request, env, executionCtx);
|
||||
} catch (e) {
|
||||
const message =
|
||||
e instanceof Error ? e.message : "Internal server error";
|
||||
return new Response(JSON.stringify({ error: message }), {
|
||||
status: 500,
|
||||
headers: { "Content-Type": "application/json", ...CORS_HEADERS },
|
||||
});
|
||||
}
|
||||
},
|
||||
};
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
||||
import type { ToolContext } from "./types.js";
|
||||
import { register as registerBespokeTools } from "./tools/bespoke.js";
|
||||
import { register as registerWorkspaceTools } from "./tools/workspace.js";
|
||||
import { register as registerPeerTools } from "./tools/peers.js";
|
||||
import { register as registerSessionTools } from "./tools/sessions.js";
|
||||
import { register as registerConclusionTools } from "./tools/conclusions.js";
|
||||
import { register as registerSystemTools } from "./tools/system.js";
|
||||
|
||||
export function createServer(ctx: ToolContext): McpServer {
|
||||
const server = new McpServer({
|
||||
name: "Honcho MCP Server",
|
||||
version: "3.0.0",
|
||||
});
|
||||
|
||||
registerBespokeTools(server, ctx);
|
||||
registerWorkspaceTools(server, ctx);
|
||||
registerPeerTools(server, ctx);
|
||||
registerSessionTools(server, ctx);
|
||||
registerConclusionTools(server, ctx);
|
||||
registerSystemTools(server, ctx);
|
||||
|
||||
return server;
|
||||
}
|
||||
|
|
@ -0,0 +1,135 @@
|
|||
import { z } from "zod";
|
||||
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
||||
import type { ToolContext } from "../types.js";
|
||||
import { textResult, errorResult } from "../types.js";
|
||||
|
||||
export function register(server: McpServer, ctx: ToolContext) {
|
||||
// ── start_conversation ──────────────────────────────────────────────
|
||||
server.registerTool(
|
||||
"start_conversation",
|
||||
{
|
||||
description: [
|
||||
"Start a new conversation for the current user.",
|
||||
"Call this once at the beginning of every new conversation.",
|
||||
"Returns a session_id you must pass to add_turn and get_personalization_insights for the rest of this conversation.",
|
||||
].join("\n"),
|
||||
inputSchema: {},
|
||||
},
|
||||
async () => {
|
||||
try {
|
||||
const userPeer = await ctx.honcho.peer(ctx.config.userName);
|
||||
const assistantPeer = await ctx.honcho.peer(
|
||||
ctx.config.assistantName,
|
||||
{ configuration: { observeMe: false } },
|
||||
);
|
||||
|
||||
const sessionId = crypto.randomUUID();
|
||||
const session = await ctx.honcho.session(sessionId, { metadata: {} });
|
||||
|
||||
await session.addPeers([
|
||||
userPeer,
|
||||
[assistantPeer, { observeMe: null, observeOthers: false }],
|
||||
]);
|
||||
|
||||
return textResult(sessionId);
|
||||
} catch (e) {
|
||||
return errorResult(
|
||||
`Failed to start conversation: ${e instanceof Error ? e.message : String(e)}`,
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
// ── add_turn ────────────────────────────────────────────────────────
|
||||
server.registerTool(
|
||||
"add_turn",
|
||||
{
|
||||
description: [
|
||||
"Record a user–assistant exchange in the current conversation.",
|
||||
"Call this after every assistant response so Honcho can learn from the conversation.",
|
||||
"Pass the full messages array containing both the user's message and your response.",
|
||||
].join("\n"),
|
||||
inputSchema: {
|
||||
session_id: z.string().describe("Session ID from start_conversation."),
|
||||
messages: z
|
||||
.array(
|
||||
z.object({
|
||||
role: z
|
||||
.enum(["user", "assistant"])
|
||||
.describe("Who sent the message."),
|
||||
content: z.string().describe("Message text."),
|
||||
metadata: z
|
||||
.record(z.string(), z.unknown())
|
||||
.optional()
|
||||
.describe("Optional metadata."),
|
||||
}),
|
||||
)
|
||||
.describe("Ordered list of messages in this turn."),
|
||||
},
|
||||
},
|
||||
async ({ session_id, messages }) => {
|
||||
try {
|
||||
const session = await ctx.honcho.session(session_id);
|
||||
const userPeer = await ctx.honcho.peer(ctx.config.userName);
|
||||
const assistantPeer = await ctx.honcho.peer(ctx.config.assistantName);
|
||||
|
||||
const sessionMessages = messages.map((msg) => {
|
||||
const peer = msg.role === "user" ? userPeer : assistantPeer;
|
||||
return msg.metadata
|
||||
? peer.message(msg.content, { metadata: msg.metadata })
|
||||
: peer.message(msg.content);
|
||||
});
|
||||
|
||||
await session.addMessages(sessionMessages);
|
||||
return textResult("Turn added successfully");
|
||||
} catch (e) {
|
||||
return errorResult(
|
||||
`Failed to add turn: ${e instanceof Error ? e.message : String(e)}`,
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
// ── get_personalization_insights ────────────────────────────────────
|
||||
server.registerTool(
|
||||
"get_personalization_insights",
|
||||
{
|
||||
description: [
|
||||
"Ask Honcho a natural-language question about the user and get a personalized answer",
|
||||
"grounded in everything Honcho has learned across all of the user's conversations.",
|
||||
"Use this before responding when personalization would genuinely improve your response — it takes a few seconds.",
|
||||
"Returns a natural-language answer.",
|
||||
].join("\n"),
|
||||
inputSchema: {
|
||||
session_id: z
|
||||
.string()
|
||||
.describe("Session ID from start_conversation, for context."),
|
||||
query: z
|
||||
.string()
|
||||
.describe(
|
||||
"Natural-language question about the user (e.g. 'What communication style does this user prefer?').",
|
||||
),
|
||||
reasoning_level: z
|
||||
.enum(["minimal", "low", "medium", "high", "max"])
|
||||
.optional()
|
||||
.describe(
|
||||
"How much reasoning effort to use. Higher = more detailed but slower. Default: 'low'.",
|
||||
),
|
||||
},
|
||||
},
|
||||
async ({ session_id, query, reasoning_level }) => {
|
||||
try {
|
||||
const userPeer = await ctx.honcho.peer(ctx.config.userName);
|
||||
const result = await userPeer.chat(query, {
|
||||
session: session_id,
|
||||
reasoningLevel: reasoning_level,
|
||||
});
|
||||
return textResult(result ?? "No personalization insights found.");
|
||||
} catch (e) {
|
||||
return errorResult(
|
||||
`Failed to get insights: ${e instanceof Error ? e.message : String(e)}`,
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,175 @@
|
|||
import { z } from "zod";
|
||||
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
||||
import type { ToolContext } from "../types.js";
|
||||
import { textResult, errorResult } from "../types.js";
|
||||
|
||||
export function register(server: McpServer, ctx: ToolContext) {
|
||||
// ── list_conclusions ────────────────────────────────────────────────
|
||||
server.registerTool(
|
||||
"list_conclusions",
|
||||
{
|
||||
description: [
|
||||
"List conclusions (facts and observations) that Honcho has derived about a peer.",
|
||||
"Use this to see what Honcho has learned. If no target is given, returns self-conclusions.",
|
||||
"Returns an array of conclusion objects with id, content, observer/observed IDs, and timestamps.",
|
||||
].join("\n"),
|
||||
inputSchema: {
|
||||
peer_id: z.string().describe("The observer peer."),
|
||||
target_peer_id: z
|
||||
.string()
|
||||
.optional()
|
||||
.describe(
|
||||
"Optional: list conclusions about this target. Omit for self-conclusions.",
|
||||
),
|
||||
},
|
||||
},
|
||||
async ({ peer_id, target_peer_id }) => {
|
||||
try {
|
||||
const peer = await ctx.honcho.peer(peer_id);
|
||||
const scope = target_peer_id
|
||||
? peer.conclusionsOf(target_peer_id)
|
||||
: peer.conclusions;
|
||||
const page = await scope.list();
|
||||
const conclusions: Record<string, unknown>[] = [];
|
||||
for await (const c of page) {
|
||||
conclusions.push({
|
||||
id: c.id,
|
||||
content: c.content,
|
||||
observer_id: c.observerId,
|
||||
observed_id: c.observedId,
|
||||
session_id: c.sessionId,
|
||||
created_at: c.createdAt,
|
||||
});
|
||||
}
|
||||
return textResult(conclusions);
|
||||
} catch (e) {
|
||||
return errorResult(
|
||||
`Failed to list conclusions: ${e instanceof Error ? e.message : String(e)}`,
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
// ── query_conclusions ───────────────────────────────────────────────
|
||||
server.registerTool(
|
||||
"query_conclusions",
|
||||
{
|
||||
description: [
|
||||
"Semantic search across a peer's conclusions.",
|
||||
"Use this to find specific knowledge Honcho has derived — more targeted than list_conclusions.",
|
||||
"Returns an array of matching conclusions ranked by relevance.",
|
||||
].join("\n"),
|
||||
inputSchema: {
|
||||
peer_id: z.string().describe("The observer peer."),
|
||||
query: z.string().describe("Semantic search query."),
|
||||
target_peer_id: z
|
||||
.string()
|
||||
.optional()
|
||||
.describe("Optional: search conclusions about this target."),
|
||||
top_k: z
|
||||
.number()
|
||||
.optional()
|
||||
.describe("Max results to return."),
|
||||
},
|
||||
},
|
||||
async ({ peer_id, query, target_peer_id, top_k }) => {
|
||||
try {
|
||||
const peer = await ctx.honcho.peer(peer_id);
|
||||
const scope = target_peer_id
|
||||
? peer.conclusionsOf(target_peer_id)
|
||||
: peer.conclusions;
|
||||
const conclusions = await scope.query(query, top_k);
|
||||
return textResult(
|
||||
conclusions.map((c) => ({
|
||||
id: c.id,
|
||||
content: c.content,
|
||||
observer_id: c.observerId,
|
||||
observed_id: c.observedId,
|
||||
session_id: c.sessionId,
|
||||
created_at: c.createdAt,
|
||||
})),
|
||||
);
|
||||
} catch (e) {
|
||||
return errorResult(
|
||||
`Query failed: ${e instanceof Error ? e.message : String(e)}`,
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
// ── create_conclusions ──────────────────────────────────────────────
|
||||
server.registerTool(
|
||||
"create_conclusions",
|
||||
{
|
||||
description: [
|
||||
"Manually create conclusions (facts/observations) about a peer.",
|
||||
"Use this to inject knowledge into Honcho that wasn't derived from conversation.",
|
||||
"Returns the number of conclusions created.",
|
||||
].join("\n"),
|
||||
inputSchema: {
|
||||
peer_id: z.string().describe("The observer peer."),
|
||||
target_peer_id: z
|
||||
.string()
|
||||
.describe("The peer the conclusions are about."),
|
||||
conclusions: z
|
||||
.array(z.string())
|
||||
.describe("Conclusion content strings to create."),
|
||||
session_id: z
|
||||
.string()
|
||||
.optional()
|
||||
.describe(
|
||||
"Optional: associate conclusions with a session. Omit for global conclusions.",
|
||||
),
|
||||
},
|
||||
},
|
||||
async ({ peer_id, target_peer_id, conclusions, session_id }) => {
|
||||
try {
|
||||
const peer = await ctx.honcho.peer(peer_id);
|
||||
const scope = peer.conclusionsOf(target_peer_id);
|
||||
const params = conclusions.map((content) => ({
|
||||
content,
|
||||
sessionId: session_id,
|
||||
}));
|
||||
await scope.create(params);
|
||||
return textResult(
|
||||
`Created ${conclusions.length} conclusion${conclusions.length === 1 ? "" : "s"} successfully`,
|
||||
);
|
||||
} catch (e) {
|
||||
return errorResult(
|
||||
`Failed to create conclusions: ${e instanceof Error ? e.message : String(e)}`,
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
// ── delete_conclusion ───────────────────────────────────────────────
|
||||
server.registerTool(
|
||||
"delete_conclusion",
|
||||
{
|
||||
description: [
|
||||
"Delete a specific conclusion by ID.",
|
||||
"Use this to remove incorrect or outdated knowledge.",
|
||||
"Returns a confirmation message.",
|
||||
].join("\n"),
|
||||
inputSchema: {
|
||||
peer_id: z.string().describe("The observer peer."),
|
||||
target_peer_id: z
|
||||
.string()
|
||||
.describe("The peer the conclusion is about."),
|
||||
conclusion_id: z.string().describe("The conclusion to delete."),
|
||||
},
|
||||
},
|
||||
async ({ peer_id, target_peer_id, conclusion_id }) => {
|
||||
try {
|
||||
const peer = await ctx.honcho.peer(peer_id);
|
||||
const scope = peer.conclusionsOf(target_peer_id);
|
||||
await scope.delete(conclusion_id);
|
||||
return textResult("Conclusion deleted successfully");
|
||||
} catch (e) {
|
||||
return errorResult(
|
||||
`Failed to delete conclusion: ${e instanceof Error ? e.message : String(e)}`,
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,360 @@
|
|||
import { z } from "zod";
|
||||
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
||||
import type { ToolContext } from "../types.js";
|
||||
import { textResult, errorResult, formatMessages } from "../types.js";
|
||||
|
||||
export function register(server: McpServer, ctx: ToolContext) {
|
||||
// ── create_peer ─────────────────────────────────────────────────────
|
||||
server.registerTool(
|
||||
"create_peer",
|
||||
{
|
||||
description: [
|
||||
"Get or create a peer with the given ID.",
|
||||
"Use this to register a new participant (user or agent) in the workspace.",
|
||||
"Returns the peer ID and any configuration that was set.",
|
||||
].join("\n"),
|
||||
inputSchema: {
|
||||
peer_id: z.string().describe("Unique identifier for the peer."),
|
||||
configuration: z
|
||||
.object({
|
||||
observeMe: z.boolean().nullable().optional().describe(
|
||||
"Whether derivation tasks should be created for this peer's messages. Default: true.",
|
||||
),
|
||||
})
|
||||
.optional()
|
||||
.describe("Optional peer configuration."),
|
||||
},
|
||||
},
|
||||
async ({ peer_id, configuration }) => {
|
||||
try {
|
||||
const peer = await ctx.honcho.peer(peer_id, { configuration });
|
||||
return textResult({ peer_id: peer.id, configuration: peer.configuration });
|
||||
} catch (e) {
|
||||
return errorResult(
|
||||
`Failed to create peer: ${e instanceof Error ? e.message : String(e)}`,
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
// ── list_peers ──────────────────────────────────────────────────────
|
||||
server.registerTool(
|
||||
"list_peers",
|
||||
{
|
||||
description: [
|
||||
"List all peers in the current workspace.",
|
||||
"Use this to discover which users and agents exist.",
|
||||
"Returns an array of peer IDs.",
|
||||
].join("\n"),
|
||||
inputSchema: {},
|
||||
},
|
||||
async () => {
|
||||
try {
|
||||
const page = await ctx.honcho.peers();
|
||||
const peers: { id: string }[] = [];
|
||||
for await (const peer of page) {
|
||||
peers.push({ id: peer.id });
|
||||
}
|
||||
return textResult(peers);
|
||||
} catch (e) {
|
||||
return errorResult(
|
||||
`Failed to list peers: ${e instanceof Error ? e.message : String(e)}`,
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
// ── chat ────────────────────────────────────────────────────────────
|
||||
server.registerTool(
|
||||
"chat",
|
||||
{
|
||||
description: [
|
||||
"Ask a natural-language question about a peer's knowledge and get an answer from Honcho's reasoning system.",
|
||||
"Use this to query what Honcho knows about any peer — their preferences, history, personality, etc.",
|
||||
"Returns a natural-language answer, or 'None' if no relevant information exists.",
|
||||
].join("\n"),
|
||||
inputSchema: {
|
||||
peer_id: z.string().describe("The peer to query about."),
|
||||
query: z.string().describe("Natural-language question."),
|
||||
target_peer_id: z
|
||||
.string()
|
||||
.optional()
|
||||
.describe(
|
||||
"Optional: query what peer_id knows about this target peer instead of their global representation.",
|
||||
),
|
||||
session_id: z
|
||||
.string()
|
||||
.optional()
|
||||
.describe("Optional: scope the query to a specific session."),
|
||||
reasoning_level: z
|
||||
.enum(["minimal", "low", "medium", "high", "max"])
|
||||
.optional()
|
||||
.describe("Reasoning effort. Higher = more detailed but slower."),
|
||||
},
|
||||
},
|
||||
async ({ peer_id, query, target_peer_id, session_id, reasoning_level }) => {
|
||||
try {
|
||||
const peer = await ctx.honcho.peer(peer_id);
|
||||
const result = await peer.chat(query, {
|
||||
target: target_peer_id,
|
||||
session: session_id,
|
||||
reasoningLevel: reasoning_level,
|
||||
});
|
||||
return textResult(result ?? "None");
|
||||
} catch (e) {
|
||||
return errorResult(
|
||||
`Chat failed: ${e instanceof Error ? e.message : String(e)}`,
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
// ── get_peer_card ───────────────────────────────────────────────────
|
||||
server.registerTool(
|
||||
"get_peer_card",
|
||||
{
|
||||
description: [
|
||||
"Get the peer card — a compact set of biographical facts about a peer.",
|
||||
"Use this when you need a quick summary of who someone is.",
|
||||
"Returns an array of fact strings, or null if no card exists yet.",
|
||||
].join("\n"),
|
||||
inputSchema: {
|
||||
peer_id: z.string().describe("The observer peer."),
|
||||
target_peer_id: z
|
||||
.string()
|
||||
.optional()
|
||||
.describe(
|
||||
"Optional: get this peer's card about the target instead of their own.",
|
||||
),
|
||||
},
|
||||
},
|
||||
async ({ peer_id, target_peer_id }) => {
|
||||
try {
|
||||
const peer = await ctx.honcho.peer(peer_id);
|
||||
const card = await peer.getCard(target_peer_id);
|
||||
return textResult(card ?? "No peer card found.");
|
||||
} catch (e) {
|
||||
return errorResult(
|
||||
`Failed to get peer card: ${e instanceof Error ? e.message : String(e)}`,
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
// ── set_peer_card ───────────────────────────────────────────────────
|
||||
server.registerTool(
|
||||
"set_peer_card",
|
||||
{
|
||||
description: [
|
||||
"Set or update the peer card — a list of biographical facts about a peer.",
|
||||
"Use this to manually establish or correct facts about a peer.",
|
||||
"Returns the updated peer card.",
|
||||
].join("\n"),
|
||||
inputSchema: {
|
||||
peer_id: z.string().describe("The observer peer."),
|
||||
peer_card: z
|
||||
.array(z.string())
|
||||
.describe("Array of fact strings to set as the peer card."),
|
||||
target_peer_id: z
|
||||
.string()
|
||||
.optional()
|
||||
.describe(
|
||||
"Optional: set this peer's card about the target instead of their own.",
|
||||
),
|
||||
},
|
||||
},
|
||||
async ({ peer_id, peer_card, target_peer_id }) => {
|
||||
try {
|
||||
const peer = await ctx.honcho.peer(peer_id);
|
||||
const result = await peer.setCard(peer_card, target_peer_id);
|
||||
return textResult(result ?? "Peer card set successfully");
|
||||
} catch (e) {
|
||||
return errorResult(
|
||||
`Failed to set peer card: ${e instanceof Error ? e.message : String(e)}`,
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
// ── get_peer_context ────────────────────────────────────────────────
|
||||
server.registerTool(
|
||||
"get_peer_context",
|
||||
{
|
||||
description: [
|
||||
"Get comprehensive context for a peer — combines their representation (conclusions) and peer card.",
|
||||
"Use this when you need the full picture of what Honcho knows about someone.",
|
||||
"Returns an object with representation, peer_card, peer_id, and target_id.",
|
||||
].join("\n"),
|
||||
inputSchema: {
|
||||
peer_id: z.string().describe("The observer peer."),
|
||||
target_peer_id: z
|
||||
.string()
|
||||
.optional()
|
||||
.describe("Optional: get context about this target peer."),
|
||||
search_query: z
|
||||
.string()
|
||||
.optional()
|
||||
.describe("Optional: semantic search to filter relevant conclusions."),
|
||||
max_conclusions: z
|
||||
.number()
|
||||
.optional()
|
||||
.describe("Optional: max number of conclusions to include."),
|
||||
},
|
||||
},
|
||||
async ({ peer_id, target_peer_id, search_query, max_conclusions }) => {
|
||||
try {
|
||||
const peer = await ctx.honcho.peer(peer_id);
|
||||
const context = await peer.context({
|
||||
target: target_peer_id,
|
||||
searchQuery: search_query,
|
||||
maxConclusions: max_conclusions,
|
||||
});
|
||||
return textResult({
|
||||
peer_id: context.peerId,
|
||||
target_id: context.targetId,
|
||||
representation: context.representation,
|
||||
peer_card: context.peerCard,
|
||||
});
|
||||
} catch (e) {
|
||||
return errorResult(
|
||||
`Failed to get peer context: ${e instanceof Error ? e.message : String(e)}`,
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
// ── get_representation ──────────────────────────────────────────────
|
||||
server.registerTool(
|
||||
"get_representation",
|
||||
{
|
||||
description: [
|
||||
"Get the formatted representation for a peer — a text summary built from their conclusions.",
|
||||
"Use this when you want the textual representation without the peer card.",
|
||||
"Returns a formatted string of conclusions.",
|
||||
].join("\n"),
|
||||
inputSchema: {
|
||||
peer_id: z.string().describe("The observer peer."),
|
||||
target_peer_id: z
|
||||
.string()
|
||||
.optional()
|
||||
.describe("Optional: get representation about this target peer."),
|
||||
session_id: z
|
||||
.string()
|
||||
.optional()
|
||||
.describe("Optional: scope to a specific session."),
|
||||
search_query: z
|
||||
.string()
|
||||
.optional()
|
||||
.describe("Optional: semantic search to filter conclusions."),
|
||||
max_conclusions: z
|
||||
.number()
|
||||
.optional()
|
||||
.describe("Optional: max number of conclusions."),
|
||||
},
|
||||
},
|
||||
async ({
|
||||
peer_id,
|
||||
target_peer_id,
|
||||
session_id,
|
||||
search_query,
|
||||
max_conclusions,
|
||||
}) => {
|
||||
try {
|
||||
const peer = await ctx.honcho.peer(peer_id);
|
||||
const rep = await peer.representation({
|
||||
target: target_peer_id,
|
||||
session: session_id,
|
||||
searchQuery: search_query,
|
||||
maxConclusions: max_conclusions,
|
||||
});
|
||||
return textResult(rep);
|
||||
} catch (e) {
|
||||
return errorResult(
|
||||
`Failed to get representation: ${e instanceof Error ? e.message : String(e)}`,
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
// ── get_peer_metadata ───────────────────────────────────────────────
|
||||
server.registerTool(
|
||||
"get_peer_metadata",
|
||||
{
|
||||
description: [
|
||||
"Get the metadata dictionary for a peer.",
|
||||
"Use this to read custom attributes stored on a peer.",
|
||||
"Returns a JSON object of key-value pairs.",
|
||||
].join("\n"),
|
||||
inputSchema: {
|
||||
peer_id: z.string().describe("The peer to get metadata for."),
|
||||
},
|
||||
},
|
||||
async ({ peer_id }) => {
|
||||
try {
|
||||
const peer = await ctx.honcho.peer(peer_id);
|
||||
const metadata = await peer.getMetadata();
|
||||
return textResult(metadata);
|
||||
} catch (e) {
|
||||
return errorResult(
|
||||
`Failed to get peer metadata: ${e instanceof Error ? e.message : String(e)}`,
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
// ── set_peer_metadata ───────────────────────────────────────────────
|
||||
server.registerTool(
|
||||
"set_peer_metadata",
|
||||
{
|
||||
description: [
|
||||
"Set metadata for a peer (overwrites existing metadata).",
|
||||
"Use this to store custom attributes on a peer.",
|
||||
"Returns a confirmation message.",
|
||||
].join("\n"),
|
||||
inputSchema: {
|
||||
peer_id: z.string().describe("The peer to set metadata for."),
|
||||
metadata: z
|
||||
.record(z.string(), z.unknown())
|
||||
.describe("Key-value pairs to set."),
|
||||
},
|
||||
},
|
||||
async ({ peer_id, metadata }) => {
|
||||
try {
|
||||
const peer = await ctx.honcho.peer(peer_id);
|
||||
await peer.setMetadata(metadata);
|
||||
return textResult("Peer metadata set successfully");
|
||||
} catch (e) {
|
||||
return errorResult(
|
||||
`Failed to set peer metadata: ${e instanceof Error ? e.message : String(e)}`,
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
// ── search_peer_messages ────────────────────────────────────────────
|
||||
server.registerTool(
|
||||
"search_peer_messages",
|
||||
{
|
||||
description: [
|
||||
"Semantic search across all messages authored by a specific peer.",
|
||||
"Use this to find what a particular peer has said across all sessions.",
|
||||
"Returns an array of matching messages.",
|
||||
].join("\n"),
|
||||
inputSchema: {
|
||||
peer_id: z.string().describe("The peer whose messages to search."),
|
||||
query: z.string().describe("Search query."),
|
||||
},
|
||||
},
|
||||
async ({ peer_id, query }) => {
|
||||
try {
|
||||
const peer = await ctx.honcho.peer(peer_id);
|
||||
const messages = await peer.search(query);
|
||||
return textResult(formatMessages(messages));
|
||||
} catch (e) {
|
||||
return errorResult(
|
||||
`Search failed: ${e instanceof Error ? e.message : String(e)}`,
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,477 @@
|
|||
import { z } from "zod";
|
||||
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
||||
import type { ToolContext } from "../types.js";
|
||||
import { textResult, errorResult, formatMessages } from "../types.js";
|
||||
|
||||
export function register(server: McpServer, ctx: ToolContext) {
|
||||
// ── create_session ──────────────────────────────────────────────────
|
||||
server.registerTool(
|
||||
"create_session",
|
||||
{
|
||||
description: [
|
||||
"Get or create a session with the given ID.",
|
||||
"Use this when you need a raw session (for the bespoke flow, use start_conversation instead).",
|
||||
"Returns the session ID.",
|
||||
].join("\n"),
|
||||
inputSchema: {
|
||||
session_id: z.string().describe("Unique identifier for the session."),
|
||||
},
|
||||
},
|
||||
async ({ session_id }) => {
|
||||
try {
|
||||
const session = await ctx.honcho.session(session_id, { metadata: {} });
|
||||
return textResult({ session_id: session.id });
|
||||
} catch (e) {
|
||||
return errorResult(
|
||||
`Failed to create session: ${e instanceof Error ? e.message : String(e)}`,
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
// ── list_sessions ───────────────────────────────────────────────────
|
||||
server.registerTool(
|
||||
"list_sessions",
|
||||
{
|
||||
description: [
|
||||
"List all sessions in the current workspace.",
|
||||
"Use this to discover existing conversations.",
|
||||
"Returns an array of session IDs.",
|
||||
].join("\n"),
|
||||
inputSchema: {},
|
||||
},
|
||||
async () => {
|
||||
try {
|
||||
const page = await ctx.honcho.sessions();
|
||||
const sessions: { id: string }[] = [];
|
||||
for await (const session of page) {
|
||||
sessions.push({ id: session.id });
|
||||
}
|
||||
return textResult(sessions);
|
||||
} catch (e) {
|
||||
return errorResult(
|
||||
`Failed to list sessions: ${e instanceof Error ? e.message : String(e)}`,
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
// ── delete_session ──────────────────────────────────────────────────
|
||||
server.registerTool(
|
||||
"delete_session",
|
||||
{
|
||||
description: [
|
||||
"Permanently delete a session and all its messages.",
|
||||
"Use this to clean up conversations that are no longer needed. This cannot be undone.",
|
||||
"Returns a confirmation message.",
|
||||
].join("\n"),
|
||||
inputSchema: {
|
||||
session_id: z.string().describe("The session to delete."),
|
||||
},
|
||||
},
|
||||
async ({ session_id }) => {
|
||||
try {
|
||||
const session = await ctx.honcho.session(session_id);
|
||||
await session.delete();
|
||||
return textResult("Session deleted successfully");
|
||||
} catch (e) {
|
||||
return errorResult(
|
||||
`Failed to delete session: ${e instanceof Error ? e.message : String(e)}`,
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
// ── clone_session ───────────────────────────────────────────────────
|
||||
server.registerTool(
|
||||
"clone_session",
|
||||
{
|
||||
description: [
|
||||
"Clone a session, optionally up to a specific message.",
|
||||
"Use this to fork a conversation — e.g. to explore a different branch.",
|
||||
"Returns the new cloned session ID.",
|
||||
].join("\n"),
|
||||
inputSchema: {
|
||||
session_id: z.string().describe("The session to clone."),
|
||||
message_id: z
|
||||
.string()
|
||||
.optional()
|
||||
.describe(
|
||||
"Optional: clone only up to and including this message. Omit to clone everything.",
|
||||
),
|
||||
},
|
||||
},
|
||||
async ({ session_id, message_id }) => {
|
||||
try {
|
||||
const session = await ctx.honcho.session(session_id);
|
||||
const cloned = await session.clone(message_id);
|
||||
return textResult({ session_id: cloned.id });
|
||||
} catch (e) {
|
||||
return errorResult(
|
||||
`Failed to clone session: ${e instanceof Error ? e.message : String(e)}`,
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
// ── add_peers_to_session ────────────────────────────────────────────
|
||||
server.registerTool(
|
||||
"add_peers_to_session",
|
||||
{
|
||||
description: [
|
||||
"Add one or more peers to a session.",
|
||||
"Use this to bring participants into a conversation.",
|
||||
"Returns a confirmation message.",
|
||||
].join("\n"),
|
||||
inputSchema: {
|
||||
session_id: z.string().describe("The session to add peers to."),
|
||||
peers: z
|
||||
.array(
|
||||
z.union([
|
||||
z.string().describe("Peer ID with default config."),
|
||||
z.object({
|
||||
peer_id: z.string().describe("Peer ID."),
|
||||
observe_me: z
|
||||
.boolean()
|
||||
.nullable()
|
||||
.optional()
|
||||
.describe("Whether this peer's messages trigger derivation in this session."),
|
||||
observe_others: z
|
||||
.boolean()
|
||||
.nullable()
|
||||
.optional()
|
||||
.describe("Whether this peer observes other peers' messages in this session."),
|
||||
}).describe("Peer with per-session config."),
|
||||
]),
|
||||
)
|
||||
.describe("Peers to add — plain IDs or objects with per-session config."),
|
||||
},
|
||||
},
|
||||
async ({ session_id, peers }) => {
|
||||
try {
|
||||
const session = await ctx.honcho.session(session_id);
|
||||
const additions = peers.map((p) => {
|
||||
if (typeof p === "string") return p;
|
||||
const config: { observeMe?: boolean | null; observeOthers?: boolean | null } = {};
|
||||
if (p.observe_me !== undefined) config.observeMe = p.observe_me;
|
||||
if (p.observe_others !== undefined) config.observeOthers = p.observe_others;
|
||||
return Object.keys(config).length > 0
|
||||
? [p.peer_id, config] as [string, typeof config]
|
||||
: p.peer_id;
|
||||
});
|
||||
await session.addPeers(additions);
|
||||
return textResult("Peers added to session successfully");
|
||||
} catch (e) {
|
||||
return errorResult(
|
||||
`Failed to add peers: ${e instanceof Error ? e.message : String(e)}`,
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
// ── remove_peers_from_session ───────────────────────────────────────
|
||||
server.registerTool(
|
||||
"remove_peers_from_session",
|
||||
{
|
||||
description: [
|
||||
"Remove one or more peers from a session.",
|
||||
"Use this to remove participants from a conversation.",
|
||||
"Returns a confirmation message.",
|
||||
].join("\n"),
|
||||
inputSchema: {
|
||||
session_id: z.string().describe("The session to remove peers from."),
|
||||
peer_ids: z
|
||||
.array(z.string())
|
||||
.describe("Peer IDs to remove."),
|
||||
},
|
||||
},
|
||||
async ({ session_id, peer_ids }) => {
|
||||
try {
|
||||
const session = await ctx.honcho.session(session_id);
|
||||
await session.removePeers(peer_ids);
|
||||
return textResult("Peers removed from session successfully");
|
||||
} catch (e) {
|
||||
return errorResult(
|
||||
`Failed to remove peers: ${e instanceof Error ? e.message : String(e)}`,
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
// ── get_session_peers ───────────────────────────────────────────────
|
||||
server.registerTool(
|
||||
"get_session_peers",
|
||||
{
|
||||
description: [
|
||||
"Get all peers participating in a session.",
|
||||
"Use this to see who is in a conversation.",
|
||||
"Returns an array of peer IDs.",
|
||||
].join("\n"),
|
||||
inputSchema: {
|
||||
session_id: z.string().describe("The session to query."),
|
||||
},
|
||||
},
|
||||
async ({ session_id }) => {
|
||||
try {
|
||||
const session = await ctx.honcho.session(session_id);
|
||||
const peers = await session.peers();
|
||||
return textResult(peers.map((p) => p.id));
|
||||
} catch (e) {
|
||||
return errorResult(
|
||||
`Failed to get session peers: ${e instanceof Error ? e.message : String(e)}`,
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
// ── add_messages_to_session ─────────────────────────────────────────
|
||||
server.registerTool(
|
||||
"add_messages_to_session",
|
||||
{
|
||||
description: [
|
||||
"Add messages to a session from specific peers.",
|
||||
"Use this for multi-peer conversations where you need to attribute messages to specific peers.",
|
||||
"For the simple user/assistant flow, use add_turn instead.",
|
||||
"Returns a confirmation message.",
|
||||
].join("\n"),
|
||||
inputSchema: {
|
||||
session_id: z.string().describe("The session to add messages to."),
|
||||
messages: z
|
||||
.array(
|
||||
z.object({
|
||||
peer_id: z.string().describe("Peer ID authoring this message."),
|
||||
content: z.string().describe("Message text."),
|
||||
metadata: z
|
||||
.record(z.string(), z.unknown())
|
||||
.optional()
|
||||
.describe("Optional metadata."),
|
||||
}),
|
||||
)
|
||||
.describe("Messages to add."),
|
||||
},
|
||||
},
|
||||
async ({ session_id, messages }) => {
|
||||
try {
|
||||
const session = await ctx.honcho.session(session_id);
|
||||
const peerCache = new Map<string, Awaited<ReturnType<typeof ctx.honcho.peer>>>();
|
||||
const sessionMessages = [];
|
||||
for (const msg of messages) {
|
||||
let peer = peerCache.get(msg.peer_id);
|
||||
if (!peer) {
|
||||
peer = await ctx.honcho.peer(msg.peer_id);
|
||||
peerCache.set(msg.peer_id, peer);
|
||||
}
|
||||
sessionMessages.push(
|
||||
msg.metadata
|
||||
? peer.message(msg.content, { metadata: msg.metadata })
|
||||
: peer.message(msg.content),
|
||||
);
|
||||
}
|
||||
await session.addMessages(sessionMessages);
|
||||
return textResult("Messages added to session successfully");
|
||||
} catch (e) {
|
||||
return errorResult(
|
||||
`Failed to add messages: ${e instanceof Error ? e.message : String(e)}`,
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
// ── get_session_messages ────────────────────────────────────────────
|
||||
server.registerTool(
|
||||
"get_session_messages",
|
||||
{
|
||||
description: [
|
||||
"Get all messages from a session, with optional metadata filtering.",
|
||||
"Use this to read the conversation history.",
|
||||
"Returns a paginated array of messages.",
|
||||
].join("\n"),
|
||||
inputSchema: {
|
||||
session_id: z.string().describe("The session to get messages from."),
|
||||
filters: z
|
||||
.record(z.string(), z.unknown())
|
||||
.optional()
|
||||
.describe("Optional metadata filter criteria."),
|
||||
},
|
||||
},
|
||||
async ({ session_id, filters }) => {
|
||||
try {
|
||||
const session = await ctx.honcho.session(session_id);
|
||||
const page = await session.messages(filters);
|
||||
const messages = [];
|
||||
for await (const msg of page) {
|
||||
messages.push(msg);
|
||||
}
|
||||
return textResult(formatMessages(messages));
|
||||
} catch (e) {
|
||||
return errorResult(
|
||||
`Failed to get messages: ${e instanceof Error ? e.message : String(e)}`,
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
// ── search_session_messages ─────────────────────────────────────────
|
||||
server.registerTool(
|
||||
"search_session_messages",
|
||||
{
|
||||
description: [
|
||||
"Semantic search across messages in a specific session.",
|
||||
"Use this to find relevant messages within a single conversation.",
|
||||
"Returns an array of matching messages.",
|
||||
].join("\n"),
|
||||
inputSchema: {
|
||||
session_id: z.string().describe("The session to search in."),
|
||||
query: z.string().describe("Search query."),
|
||||
},
|
||||
},
|
||||
async ({ session_id, query }) => {
|
||||
try {
|
||||
const session = await ctx.honcho.session(session_id);
|
||||
const messages = await session.search(query);
|
||||
return textResult(formatMessages(messages));
|
||||
} catch (e) {
|
||||
return errorResult(
|
||||
`Search failed: ${e instanceof Error ? e.message : String(e)}`,
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
// ── get_session_context ─────────────────────────────────────────────
|
||||
server.registerTool(
|
||||
"get_session_context",
|
||||
{
|
||||
description: [
|
||||
"Get optimized context for a session, suitable for LLM prompts.",
|
||||
"Includes recent messages and an optional summary of older ones.",
|
||||
"Use this to build a context window for the next LLM call.",
|
||||
"Returns messages, summary, and session ID.",
|
||||
].join("\n"),
|
||||
inputSchema: {
|
||||
session_id: z.string().describe("The session to get context for."),
|
||||
summary: z
|
||||
.boolean()
|
||||
.optional()
|
||||
.describe("Include a summary of older messages? Default: true."),
|
||||
tokens: z
|
||||
.number()
|
||||
.optional()
|
||||
.describe("Target token budget for the context window."),
|
||||
},
|
||||
},
|
||||
async ({ session_id, summary, tokens }) => {
|
||||
try {
|
||||
const session = await ctx.honcho.session(session_id);
|
||||
const context = await session.context({ summary, tokens });
|
||||
return textResult({
|
||||
session_id: context.sessionId,
|
||||
summary: context.summary,
|
||||
messages: context.messages.map((msg) => ({
|
||||
id: msg.id,
|
||||
content: msg.content,
|
||||
peer_id: msg.peerId,
|
||||
metadata: msg.metadata,
|
||||
created_at: msg.createdAt,
|
||||
})),
|
||||
});
|
||||
} catch (e) {
|
||||
return errorResult(
|
||||
`Failed to get context: ${e instanceof Error ? e.message : String(e)}`,
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
// ── get_session_representation ──────────────────────────────────────
|
||||
server.registerTool(
|
||||
"get_session_representation",
|
||||
{
|
||||
description: [
|
||||
"Get a peer's representation scoped to a specific session.",
|
||||
"Use this to see what Honcho has learned about a peer from a single conversation.",
|
||||
"Returns a formatted string of session-scoped conclusions.",
|
||||
].join("\n"),
|
||||
inputSchema: {
|
||||
session_id: z.string().describe("The session to scope to."),
|
||||
peer_id: z
|
||||
.string()
|
||||
.describe("The peer to get the representation for."),
|
||||
target_peer_id: z
|
||||
.string()
|
||||
.optional()
|
||||
.describe(
|
||||
"Optional: get what peer_id knows about target_peer_id in this session.",
|
||||
),
|
||||
},
|
||||
},
|
||||
async ({ session_id, peer_id, target_peer_id }) => {
|
||||
try {
|
||||
const session = await ctx.honcho.session(session_id);
|
||||
const rep = await session.representation(peer_id, {
|
||||
target: target_peer_id,
|
||||
});
|
||||
return textResult(rep);
|
||||
} catch (e) {
|
||||
return errorResult(
|
||||
`Failed to get representation: ${e instanceof Error ? e.message : String(e)}`,
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
// ── get_session_metadata ────────────────────────────────────────────
|
||||
server.registerTool(
|
||||
"get_session_metadata",
|
||||
{
|
||||
description: [
|
||||
"Get the metadata dictionary for a session.",
|
||||
"Use this to read custom attributes stored on a session.",
|
||||
"Returns a JSON object.",
|
||||
].join("\n"),
|
||||
inputSchema: {
|
||||
session_id: z.string().describe("The session to get metadata for."),
|
||||
},
|
||||
},
|
||||
async ({ session_id }) => {
|
||||
try {
|
||||
const session = await ctx.honcho.session(session_id);
|
||||
const metadata = await session.getMetadata();
|
||||
return textResult(metadata);
|
||||
} catch (e) {
|
||||
return errorResult(
|
||||
`Failed to get session metadata: ${e instanceof Error ? e.message : String(e)}`,
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
// ── set_session_metadata ────────────────────────────────────────────
|
||||
server.registerTool(
|
||||
"set_session_metadata",
|
||||
{
|
||||
description: [
|
||||
"Set metadata for a session (overwrites existing metadata).",
|
||||
"Use this to store custom attributes on a session.",
|
||||
"Returns a confirmation message.",
|
||||
].join("\n"),
|
||||
inputSchema: {
|
||||
session_id: z.string().describe("The session to set metadata for."),
|
||||
metadata: z
|
||||
.record(z.string(), z.unknown())
|
||||
.describe("Key-value pairs to set."),
|
||||
},
|
||||
},
|
||||
async ({ session_id, metadata }) => {
|
||||
try {
|
||||
const session = await ctx.honcho.session(session_id);
|
||||
await session.setMetadata(metadata);
|
||||
return textResult("Session metadata set successfully");
|
||||
} catch (e) {
|
||||
return errorResult(
|
||||
`Failed to set session metadata: ${e instanceof Error ? e.message : String(e)}`,
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
import { z } from "zod";
|
||||
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
||||
import type { ToolContext } from "../types.js";
|
||||
import { textResult, errorResult } from "../types.js";
|
||||
|
||||
export function register(server: McpServer, ctx: ToolContext) {
|
||||
// ── schedule_dream ──────────────────────────────────────────────────
|
||||
server.registerTool(
|
||||
"schedule_dream",
|
||||
{
|
||||
description: [
|
||||
"Schedule a dream — a background memory-consolidation task for a peer.",
|
||||
"Dreams consolidate observations into higher-level insights and update peer cards.",
|
||||
"Use this after a long conversation to improve Honcho's memory quality.",
|
||||
"Returns a confirmation message.",
|
||||
].join("\n"),
|
||||
inputSchema: {
|
||||
peer_id: z.string().describe("The observer peer to dream for."),
|
||||
target_peer_id: z
|
||||
.string()
|
||||
.optional()
|
||||
.describe(
|
||||
"Optional: dream about this target peer. Omit for self-reflection.",
|
||||
),
|
||||
session_id: z
|
||||
.string()
|
||||
.optional()
|
||||
.describe("Optional: scope the dream to a session."),
|
||||
},
|
||||
},
|
||||
async ({ peer_id, target_peer_id, session_id }) => {
|
||||
try {
|
||||
await ctx.honcho.scheduleDream({
|
||||
observer: peer_id,
|
||||
observed: target_peer_id,
|
||||
session: session_id,
|
||||
});
|
||||
return textResult("Dream scheduled successfully");
|
||||
} catch (e) {
|
||||
return errorResult(
|
||||
`Failed to schedule dream: ${e instanceof Error ? e.message : String(e)}`,
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
// ── get_queue_status ────────────────────────────────────────────────
|
||||
server.registerTool(
|
||||
"get_queue_status",
|
||||
{
|
||||
description: [
|
||||
"Get the current processing queue status for background tasks (message derivation, dreams).",
|
||||
"Use this to check if Honcho is still processing messages before querying for insights.",
|
||||
"Returns work unit counts: total, completed, in-progress, and pending.",
|
||||
].join("\n"),
|
||||
inputSchema: {},
|
||||
},
|
||||
async () => {
|
||||
try {
|
||||
const status = await ctx.honcho.queueStatus();
|
||||
return textResult(status);
|
||||
} catch (e) {
|
||||
return errorResult(
|
||||
`Failed to get queue status: ${e instanceof Error ? e.message : String(e)}`,
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,81 @@
|
|||
import { z } from "zod";
|
||||
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
||||
import type { ToolContext } from "../types.js";
|
||||
import { textResult, errorResult, formatMessages } from "../types.js";
|
||||
|
||||
export function register(server: McpServer, ctx: ToolContext) {
|
||||
// ── search_workspace ────────────────────────────────────────────────
|
||||
server.registerTool(
|
||||
"search_workspace",
|
||||
{
|
||||
description: [
|
||||
"Semantic search across all messages in the workspace.",
|
||||
"Use this to find past conversations or messages from any peer/session.",
|
||||
"Returns an array of matching messages with their content, peer, and session info.",
|
||||
].join("\n"),
|
||||
inputSchema: {
|
||||
query: z.string().describe("Search query."),
|
||||
},
|
||||
},
|
||||
async ({ query }) => {
|
||||
try {
|
||||
const messages = await ctx.honcho.search(query);
|
||||
return textResult(formatMessages(messages));
|
||||
} catch (e) {
|
||||
return errorResult(
|
||||
`Search failed: ${e instanceof Error ? e.message : String(e)}`,
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
// ── get_workspace_metadata ──────────────────────────────────────────
|
||||
server.registerTool(
|
||||
"get_workspace_metadata",
|
||||
{
|
||||
description: [
|
||||
"Get the metadata dictionary for the current workspace.",
|
||||
"Use this to read workspace-level settings or custom attributes.",
|
||||
"Returns a JSON object of key-value pairs.",
|
||||
].join("\n"),
|
||||
inputSchema: {},
|
||||
},
|
||||
async () => {
|
||||
try {
|
||||
const metadata = await ctx.honcho.getMetadata();
|
||||
return textResult(metadata);
|
||||
} catch (e) {
|
||||
return errorResult(
|
||||
`Failed to get metadata: ${e instanceof Error ? e.message : String(e)}`,
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
// ── set_workspace_metadata ──────────────────────────────────────────
|
||||
server.registerTool(
|
||||
"set_workspace_metadata",
|
||||
{
|
||||
description: [
|
||||
"Set metadata for the current workspace (overwrites existing metadata).",
|
||||
"Use this to store workspace-level settings or custom attributes.",
|
||||
"Returns a confirmation message.",
|
||||
].join("\n"),
|
||||
inputSchema: {
|
||||
metadata: z
|
||||
.record(z.string(), z.unknown())
|
||||
.describe("Key-value pairs to set as workspace metadata."),
|
||||
},
|
||||
},
|
||||
async ({ metadata }) => {
|
||||
try {
|
||||
await ctx.honcho.setMetadata(metadata);
|
||||
return textResult("Workspace metadata set successfully");
|
||||
} catch (e) {
|
||||
return errorResult(
|
||||
`Failed to set metadata: ${e instanceof Error ? e.message : String(e)}`,
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
import type { Honcho, Message } from "@honcho-ai/sdk";
|
||||
import type { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
|
||||
import type { HonchoConfig } from "./config.js";
|
||||
|
||||
export interface ToolContext {
|
||||
honcho: Honcho;
|
||||
config: HonchoConfig;
|
||||
}
|
||||
|
||||
export function textResult(
|
||||
data: string | object | unknown[],
|
||||
): CallToolResult {
|
||||
const text = typeof data === "string" ? data : JSON.stringify(data);
|
||||
return { content: [{ type: "text", text }] };
|
||||
}
|
||||
|
||||
export function errorResult(msg: string): CallToolResult {
|
||||
return { content: [{ type: "text", text: msg }], isError: true };
|
||||
}
|
||||
|
||||
/** Serialize a Message[] to a plain JSON-safe array. */
|
||||
export function formatMessages(messages: Message[]) {
|
||||
return messages.map((m) => ({
|
||||
id: m.id,
|
||||
content: m.content,
|
||||
peer_id: m.peerId,
|
||||
session_id: m.sessionId,
|
||||
metadata: m.metadata,
|
||||
created_at: m.createdAt,
|
||||
}));
|
||||
}
|
||||
|
|
@ -9,6 +9,6 @@
|
|||
"skipLibCheck": true,
|
||||
"types": ["@cloudflare/workers-types"]
|
||||
},
|
||||
"include": ["**/*.ts"],
|
||||
"include": ["src/**/*.ts"],
|
||||
"exclude": ["node_modules"]
|
||||
}
|
||||
|
|
|
|||
2245
mcp/worker.ts
2245
mcp/worker.ts
File diff suppressed because it is too large
Load Diff
|
|
@ -1,5 +1,5 @@
|
|||
name = "honcho-mcp"
|
||||
main = "worker.ts"
|
||||
main = "src/index.ts"
|
||||
compatibility_date = "2024-12-09"
|
||||
compatibility_flags = ["nodejs_compat"]
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue