@unclick/mcp-server 0.2.5 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (142) hide show
  1. package/README.md +160 -139
  2. package/dist/abn-tool.js +1 -1
  3. package/dist/bgg-tool.js +1 -1
  4. package/dist/carboninterface-tool.js +1 -1
  5. package/dist/cards/card.d.ts +9 -0
  6. package/dist/cards/card.d.ts.map +1 -0
  7. package/dist/cards/card.js +4 -0
  8. package/dist/cards/card.js.map +1 -0
  9. package/dist/cards/search-memory-card.d.ts +11 -0
  10. package/dist/cards/search-memory-card.d.ts.map +1 -0
  11. package/dist/cards/search-memory-card.js +75 -0
  12. package/dist/cards/search-memory-card.js.map +1 -0
  13. package/dist/cards/search-memory-card.test.d.ts +2 -0
  14. package/dist/cards/search-memory-card.test.d.ts.map +1 -0
  15. package/dist/cards/search-memory-card.test.js +59 -0
  16. package/dist/cards/search-memory-card.test.js.map +1 -0
  17. package/dist/catalog.d.ts.map +1 -1
  18. package/dist/catalog.js +265 -4
  19. package/dist/catalog.js.map +1 -1
  20. package/dist/client.d.ts.map +1 -1
  21. package/dist/client.js +96 -6
  22. package/dist/client.js.map +1 -1
  23. package/dist/converter-tools.js +1 -1
  24. package/dist/crews-tool.d.ts +12 -0
  25. package/dist/crews-tool.d.ts.map +1 -0
  26. package/dist/crews-tool.js +125 -0
  27. package/dist/crews-tool.js.map +1 -0
  28. package/dist/gdelt-tool.js +4 -4
  29. package/dist/hackernews-tool.js +1 -1
  30. package/dist/index.js +0 -0
  31. package/dist/keychain-secure-input.js +42 -42
  32. package/dist/line-tool.js +1 -1
  33. package/dist/linear-tool.js +73 -73
  34. package/dist/local-catalog-handlers.js +1 -1
  35. package/dist/local-catalog-handlers.js.map +1 -1
  36. package/dist/local-tools.js +7 -7
  37. package/dist/local-tools.js.map +1 -1
  38. package/dist/memory/__tests__/bitemporal.test.d.ts +8 -0
  39. package/dist/memory/__tests__/bitemporal.test.d.ts.map +1 -0
  40. package/dist/memory/__tests__/bitemporal.test.js +148 -0
  41. package/dist/memory/__tests__/bitemporal.test.js.map +1 -0
  42. package/dist/memory/__tests__/hybrid-search.test.d.ts +14 -0
  43. package/dist/memory/__tests__/hybrid-search.test.d.ts.map +1 -0
  44. package/dist/memory/__tests__/hybrid-search.test.js +304 -0
  45. package/dist/memory/__tests__/hybrid-search.test.js.map +1 -0
  46. package/dist/memory/agent.d.ts +34 -0
  47. package/dist/memory/agent.d.ts.map +1 -0
  48. package/dist/memory/agent.js +69 -0
  49. package/dist/memory/agent.js.map +1 -0
  50. package/dist/memory/conflicts.d.ts +48 -0
  51. package/dist/memory/conflicts.d.ts.map +1 -0
  52. package/dist/memory/conflicts.js +209 -0
  53. package/dist/memory/conflicts.js.map +1 -0
  54. package/dist/memory/db.d.ts +25 -0
  55. package/dist/memory/db.d.ts.map +1 -0
  56. package/dist/memory/db.js +144 -0
  57. package/dist/memory/db.js.map +1 -0
  58. package/dist/memory/device.d.ts +20 -0
  59. package/dist/memory/device.d.ts.map +1 -0
  60. package/dist/memory/device.js +48 -0
  61. package/dist/memory/device.js.map +1 -0
  62. package/dist/memory/embeddings.d.ts +10 -0
  63. package/dist/memory/embeddings.d.ts.map +1 -0
  64. package/dist/memory/embeddings.js +40 -0
  65. package/dist/memory/embeddings.js.map +1 -0
  66. package/dist/memory/handlers.d.ts +11 -0
  67. package/dist/memory/handlers.d.ts.map +1 -0
  68. package/dist/memory/handlers.js +219 -0
  69. package/dist/memory/handlers.js.map +1 -0
  70. package/dist/memory/instrumentation.d.ts +38 -0
  71. package/dist/memory/instrumentation.d.ts.map +1 -0
  72. package/dist/memory/instrumentation.js +97 -0
  73. package/dist/memory/instrumentation.js.map +1 -0
  74. package/dist/memory/load-events.d.ts +18 -0
  75. package/dist/memory/load-events.d.ts.map +1 -0
  76. package/dist/memory/load-events.js +61 -0
  77. package/dist/memory/load-events.js.map +1 -0
  78. package/dist/memory/local.d.ts +40 -0
  79. package/dist/memory/local.d.ts.map +1 -0
  80. package/dist/memory/local.js +400 -0
  81. package/dist/memory/local.js.map +1 -0
  82. package/dist/memory/session-state.d.ts +37 -0
  83. package/dist/memory/session-state.d.ts.map +1 -0
  84. package/dist/memory/session-state.js +82 -0
  85. package/dist/memory/session-state.js.map +1 -0
  86. package/dist/memory/supabase.d.ts +104 -0
  87. package/dist/memory/supabase.d.ts.map +1 -0
  88. package/dist/memory/supabase.js +710 -0
  89. package/dist/memory/supabase.js.map +1 -0
  90. package/dist/memory/tenant-settings.d.ts +33 -0
  91. package/dist/memory/tenant-settings.d.ts.map +1 -0
  92. package/dist/memory/tenant-settings.js +79 -0
  93. package/dist/memory/tenant-settings.js.map +1 -0
  94. package/dist/memory/tool-awareness.d.ts +66 -0
  95. package/dist/memory/tool-awareness.d.ts.map +1 -0
  96. package/dist/memory/tool-awareness.js +307 -0
  97. package/dist/memory/tool-awareness.js.map +1 -0
  98. package/dist/memory/types.d.ts +97 -0
  99. package/dist/memory/types.d.ts.map +1 -0
  100. package/dist/memory/types.js +5 -0
  101. package/dist/memory/types.js.map +1 -0
  102. package/dist/monday-tool.js +46 -46
  103. package/dist/musicbrainz-tool.js +1 -1
  104. package/dist/musicbrainz-tool.js.map +1 -1
  105. package/dist/numbers-tool.js +2 -2
  106. package/dist/openfoodfacts-tool.js +1 -1
  107. package/dist/openmeteo-tool.js +1 -1
  108. package/dist/radiobrowser-tool.js +2 -2
  109. package/dist/server.d.ts.map +1 -1
  110. package/dist/server.js +838 -15
  111. package/dist/server.js.map +1 -1
  112. package/dist/signals/emit.d.ts +11 -0
  113. package/dist/signals/emit.d.ts.map +1 -0
  114. package/dist/signals/emit.js +26 -0
  115. package/dist/signals/emit.js.map +1 -0
  116. package/dist/testpass-tool.d.ts +12 -0
  117. package/dist/testpass-tool.d.ts.map +1 -0
  118. package/dist/testpass-tool.js +121 -0
  119. package/dist/testpass-tool.js.map +1 -0
  120. package/dist/toilets-tool.js +2 -2
  121. package/dist/tool-wiring.d.ts +320 -4
  122. package/dist/tool-wiring.d.ts.map +1 -1
  123. package/dist/tool-wiring.js +246 -5
  124. package/dist/tool-wiring.js.map +1 -1
  125. package/dist/trivia-tool.js +5 -5
  126. package/dist/usgs-tool.js +1 -1
  127. package/dist/uxpass-tool.d.ts +24 -0
  128. package/dist/uxpass-tool.d.ts.map +1 -0
  129. package/dist/uxpass-tool.js +165 -0
  130. package/dist/uxpass-tool.js.map +1 -0
  131. package/dist/vault-bridge.js +7 -7
  132. package/dist/vercel-tool.d.ts +3 -0
  133. package/dist/vercel-tool.d.ts.map +1 -1
  134. package/dist/vercel-tool.js +198 -7
  135. package/dist/vercel-tool.js.map +1 -1
  136. package/dist/web-tools.d.ts +62 -0
  137. package/dist/web-tools.d.ts.map +1 -0
  138. package/dist/web-tools.js +271 -0
  139. package/dist/web-tools.js.map +1 -0
  140. package/package.json +69 -65
  141. package/public/icon.svg +15 -15
  142. package/server.json +37 -37
package/README.md CHANGED
@@ -1,139 +1,160 @@
1
- # @unclick/mcp-server
2
-
3
- **MCP server for the [UnClick](https://unclick.world) tool marketplace.**
4
-
5
- Lets any MCP-compatible AI agent (Claude, Cursor, etc.) discover and use every tool in the UnClick marketplace — URL shortening, QR codes, image processing, hashing, CSV/JSON, regex, cron, color utilities, key-value storage, and more.
6
-
7
- ## Quick Start
8
-
9
- ### Claude Desktop
10
-
11
- Add to `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) or `%APPDATA%\Claude\claude_desktop_config.json` (Windows):
12
-
13
- ```json
14
- {
15
- "mcpServers": {
16
- "unclick": {
17
- "command": "npx",
18
- "args": ["-y", "@unclick/mcp-server"],
19
- "env": {
20
- "UNCLICK_API_KEY": "your_api_key_here"
21
- }
22
- }
23
- }
24
- }
25
- ```
26
-
27
- Get your API key at [unclick.world](https://unclick.world).
28
-
29
- ### Local / Development
30
-
31
- ```bash
32
- UNCLICK_API_KEY=unck_... npx @unclick/mcp-server
33
- ```
34
-
35
- ## Configuration
36
-
37
- | Environment Variable | Default | Description |
38
- |---|---|---|
39
- | `UNCLICK_API_KEY` | *(required)* | Your UnClick API key |
40
- | `UNCLICK_BASE_URL` | `https://api.unclick.world` | Override API base URL (for self-hosted) |
41
-
42
- ## Tools Exposed
43
-
44
- ### Discovery (Meta Tools)
45
-
46
- These tools let agents explore the full marketplace dynamically.
47
-
48
- | Tool | Description |
49
- |---|---|
50
- | `unclick_search` | Search for tools by keyword. "I need to resize an image" → returns the image tool with endpoints and schemas. |
51
- | `unclick_browse` | Browse all tools, optionally filtered by category (text, data, media, time, network, generation, storage). |
52
- | `unclick_tool_info` | Get full details on a specific tool: all endpoints, required params, and response shapes. |
53
- | `unclick_call` | Universal caller — specify any `endpoint_id` and `params`, the server routes the call. |
54
-
55
- **Discovery flow for an agent:**
56
- 1. `unclick_search` → "what tool handles X?"
57
- 2. `unclick_tool_info` "what are the exact params for that tool?"
58
- 3. `unclick_call` → call it
59
-
60
- ### Direct Tools (Zero Friction)
61
-
62
- The most-used tools are exposed as first-class MCP tools for immediate use without discovery:
63
-
64
- | Tool | What it does |
65
- |---|---|
66
- | `unclick_shorten_url` | Shorten a URL |
67
- | `unclick_generate_qr` | Generate a QR code (PNG/SVG) |
68
- | `unclick_hash` | Hash text with MD5/SHA1/SHA256/SHA512 |
69
- | `unclick_transform_text` | Change text case (camel, snake, kebab, title, etc.) |
70
- | `unclick_validate_email` | Validate an email address |
71
- | `unclick_validate_url` | Validate a URL (+ optional reachability check) |
72
- | `unclick_resize_image` | Resize a base64-encoded image |
73
- | `unclick_parse_csv` | Parse CSV to JSON |
74
- | `unclick_json_format` | Pretty-print JSON |
75
- | `unclick_encode` | Encode/decode base64, URL, HTML, or hex |
76
- | `unclick_generate_uuid` | Generate UUIDs |
77
- | `unclick_random_password` | Generate a secure password |
78
- | `unclick_cron_parse` | Parse a cron expression + show next occurrences |
79
- | `unclick_ip_parse` | Parse an IP address |
80
- | `unclick_color_convert` | Convert color between hex/RGB/HSL/HSV |
81
- | `unclick_regex_test` | Test a regex and get all matches |
82
- | `unclick_timestamp_convert` | Convert timestamps between formats |
83
- | `unclick_diff_text` | Line-by-line diff of two strings |
84
- | `unclick_kv_set` | Store a value in the key-value store |
85
- | `unclick_kv_get` | Retrieve a value from the key-value store |
86
-
87
- ## Full Tool Catalog
88
-
89
- The marketplace currently includes 23 tool groups spanning:
90
-
91
- - **Text** transform (case, slug, count), encode/decode (base64, URL, HTML, hex), hash/HMAC, regex, markdown, diff
92
- - **Data** JSON utilities, CSV processing, input validation (email, URL, phone, credit card, IP, color)
93
- - **Media** image processing (resize, convert, crop, rotate, compress, grayscale), QR code generation, color utilities
94
- - **Time** timestamp conversion, cron parsing/building
95
- - **Network** URL shortening, IP utilities (parse, subnet, CIDR)
96
- - **Generation** UUID v4, random (numbers, strings, passwords, picks, shuffles, colors)
97
- - **Storage** key-value store (with TTL), webhook bins
98
-
99
- All tools are accessible via `unclick_call` with the appropriate `endpoint_id`.
100
-
101
- ## Example Usage
102
-
103
- **Agent discovers and uses a tool:**
104
- ```
105
- Agent: I need to hash a password before storing it.
106
-
107
- 1. unclick_search({ query: "hash password" })
108
- Returns: hash tool (slug: hash, endpoints: hash.compute, hash.verify, hash.hmac)
109
-
110
- 2. unclick_call({ endpoint_id: "hash.compute", params: { text: "my-secret", algorithm: "sha256" } })
111
- → { algorithm: "sha256", hash: "abc123...", length: 64 }
112
- ```
113
-
114
- **Direct tool usage:**
115
- ```
116
- Agent: unclick_generate_qr({ text: "https://example.com", format: "png", size: 400 })
117
- { binary: true, content_type: "image/png", data: "<base64>" }
118
- ```
119
-
120
- ## Development
121
-
122
- ```bash
123
- # Run locally with tsx (no build step)
124
- UNCLICK_API_KEY=unck_... npm run dev
125
-
126
- # Build
127
- npm run build
128
-
129
- # Run built output
130
- npm start
131
- ```
132
-
133
- ## MCP Registry
134
-
135
- This server is published to npm as `@unclick/mcp-server` and can be added to any MCP registry that supports npx-based servers.
136
-
137
- ## License
138
-
139
- MIT
1
+ # @unclick/mcp-server
2
+
3
+ **MCP server for the [UnClick](https://unclick.world) tool marketplace.**
4
+
5
+ One install gives any MCP-compatible AI agent (Claude, Cursor, etc.) access to:
6
+ - **450+ callable endpoints** across 60+ integrations (social, e-commerce, accounting, messaging, and more)
7
+ - **Persistent cross-session memory** — the agent remembers you across sessions, zero config
8
+
9
+ ## Quick Start
10
+
11
+ ### Claude Desktop / Claude Code
12
+
13
+ Add to your MCP config (Claude Desktop: `~/Library/Application Support/Claude/claude_desktop_config.json`, or run `claude mcp add` in Claude Code):
14
+
15
+ ```json
16
+ {
17
+ "mcpServers": {
18
+ "unclick": {
19
+ "command": "npx",
20
+ "args": ["-y", "@unclick/mcp-server"],
21
+ "env": {
22
+ "UNCLICK_API_KEY": "your_api_key_here"
23
+ }
24
+ }
25
+ }
26
+ }
27
+ ```
28
+
29
+ Get your API key at [unclick.world](https://unclick.world).
30
+
31
+ > **Install codes.** The `UNCLICK_API_KEY` can also be a short-lived install code like `unclick-ember-falcon-2847` (good for 24 hours). On first boot the server exchanges it for the real key and caches it at `~/.unclick/credentials.json`. This means install snippets shared in chat look like project slugs rather than credentials.
32
+
33
+ ### Cursor
34
+
35
+ Same config snippet as above — Cursor uses the same MCP format.
36
+
37
+ ### Local / Development
38
+
39
+ ```bash
40
+ UNCLICK_API_KEY=unck_... npx @unclick/mcp-server
41
+ ```
42
+
43
+ ## Memory (built in, zero config)
44
+
45
+ Memory works out of the box. No setup needed — data is stored as JSON files in `~/.unclick/memory/`.
46
+
47
+ **Want cross-machine sync?** Add Supabase env vars to your config:
48
+
49
+ ```json
50
+ "env": {
51
+ "UNCLICK_API_KEY": "your_api_key_here",
52
+ "SUPABASE_URL": "https://your-project.supabase.co",
53
+ "SUPABASE_SERVICE_ROLE_KEY": "your_service_role_key"
54
+ }
55
+ ```
56
+
57
+ Memory tools exposed at session level: `load_memory`, `save_session`, `save_fact`, `search_memory`, `save_identity`. Full 17 operations available via `unclick_call` with `endpoint_id: "memory.*"`. The prior names (`get_startup_context`, `write_session_summary`, `add_fact`, `set_business_context`) still work as backward-compatible aliases.
58
+
59
+ ## Configuration
60
+
61
+ | Environment Variable | Default | Description |
62
+ |---|---|---|
63
+ | `UNCLICK_API_KEY` | *(required)* | Your UnClick API key |
64
+ | `UNCLICK_BASE_URL` | `https://api.unclick.world` | Override API base URL (for self-hosted) |
65
+
66
+ ## Tools Exposed
67
+
68
+ ### Discovery
69
+
70
+ | Tool | Description |
71
+ |---|---|
72
+ | `unclick_search` | Search for tools by keyword. "I need to resize an image" returns the image tool with endpoints and schemas. |
73
+
74
+ `unclick_browse`, `unclick_tool_info`, and `unclick_call` remain callable for backward compatibility but are hidden from the advertised tool list so end users are not shown internal machinery.
75
+
76
+ **Discovery flow for an agent:**
77
+ 1. `unclick_search` to find relevant tools
78
+ 2. Inspect the returned endpoint schemas
79
+ 3. Invoke the matching endpoint via the raw call interface
80
+
81
+ ### Direct Tools (Zero Friction)
82
+
83
+ The most-used tools are exposed as first-class MCP tools for immediate use without discovery:
84
+
85
+ | Tool | What it does |
86
+ |---|---|
87
+ | `unclick_shorten_url` | Shorten a URL |
88
+ | `unclick_generate_qr` | Generate a QR code (PNG/SVG) |
89
+ | `unclick_hash` | Hash text with MD5/SHA1/SHA256/SHA512 |
90
+ | `unclick_transform_text` | Change text case (camel, snake, kebab, title, etc.) |
91
+ | `unclick_validate_email` | Validate an email address |
92
+ | `unclick_validate_url` | Validate a URL (+ optional reachability check) |
93
+ | `unclick_resize_image` | Resize a base64-encoded image |
94
+ | `unclick_parse_csv` | Parse CSV to JSON |
95
+ | `unclick_json_format` | Pretty-print JSON |
96
+ | `unclick_encode` | Encode/decode base64, URL, HTML, or hex |
97
+ | `unclick_generate_uuid` | Generate UUIDs |
98
+ | `unclick_random_password` | Generate a secure password |
99
+ | `unclick_cron_parse` | Parse a cron expression + show next occurrences |
100
+ | `unclick_ip_parse` | Parse an IP address |
101
+ | `unclick_color_convert` | Convert color between hex/RGB/HSL/HSV |
102
+ | `unclick_regex_test` | Test a regex and get all matches |
103
+ | `unclick_timestamp_convert` | Convert timestamps between formats |
104
+ | `unclick_diff_text` | Line-by-line diff of two strings |
105
+ | `unclick_kv_set` | Store a value in the key-value store |
106
+ | `unclick_kv_get` | Retrieve a value from the key-value store |
107
+
108
+ ## Full Tool Catalog
109
+
110
+ The marketplace currently includes 23 tool groups spanning:
111
+
112
+ - **Text** — transform (case, slug, count), encode/decode (base64, URL, HTML, hex), hash/HMAC, regex, markdown, diff
113
+ - **Data** — JSON utilities, CSV processing, input validation (email, URL, phone, credit card, IP, color)
114
+ - **Media** image processing (resize, convert, crop, rotate, compress, grayscale), QR code generation, color utilities
115
+ - **Time** — timestamp conversion, cron parsing/building
116
+ - **Network** URL shortening, IP utilities (parse, subnet, CIDR)
117
+ - **Generation** UUID v4, random (numbers, strings, passwords, picks, shuffles, colors)
118
+ - **Storage** — key-value store (with TTL), webhook bins
119
+
120
+ All tools are accessible via `unclick_call` with the appropriate `endpoint_id`.
121
+
122
+ ## Example Usage
123
+
124
+ **Agent discovers and uses a tool:**
125
+ ```
126
+ Agent: I need to hash a password before storing it.
127
+
128
+ 1. unclick_search({ query: "hash password" })
129
+ Returns: hash tool (slug: hash, endpoints: hash.compute, hash.verify, hash.hmac)
130
+
131
+ 2. unclick_call({ endpoint_id: "hash.compute", params: { text: "my-secret", algorithm: "sha256" } })
132
+ → { algorithm: "sha256", hash: "abc123...", length: 64 }
133
+ ```
134
+
135
+ **Direct tool usage:**
136
+ ```
137
+ Agent: unclick_generate_qr({ text: "https://example.com", format: "png", size: 400 })
138
+ → { binary: true, content_type: "image/png", data: "<base64>" }
139
+ ```
140
+
141
+ ## Development
142
+
143
+ ```bash
144
+ # Run locally with tsx (no build step)
145
+ UNCLICK_API_KEY=unck_... npm run dev
146
+
147
+ # Build
148
+ npm run build
149
+
150
+ # Run built output
151
+ npm start
152
+ ```
153
+
154
+ ## MCP Registry
155
+
156
+ This server is published to npm as `@unclick/mcp-server` and can be added to any MCP registry that supports npx-based servers.
157
+
158
+ ## License
159
+
160
+ MIT
package/dist/abn-tool.js CHANGED
@@ -1,5 +1,5 @@
1
1
  // Australian Business Registry (ABN Lookup) integration.
2
- // Uses the free ABR JSONP API no authentication required.
2
+ // Uses the free ABR JSONP API - no authentication required.
3
3
  // Base URL: https://abr.business.gov.au/json/
4
4
  const ABN_BASE = "https://abr.business.gov.au/json";
5
5
  // ─── JSONP helper ─────────────────────────────────────────────────────────────
package/dist/bgg-tool.js CHANGED
@@ -187,7 +187,7 @@ export async function bggUserCollection(args) {
187
187
  };
188
188
  }
189
189
  // ─── bgg_top_games ────────────────────────────────────────────────────────────
190
- // GET /hot?type=boardgame returns BGG's "Hotness" list (top 50)
190
+ // GET /hot?type=boardgame - returns BGG's "Hotness" list (top 50)
191
191
  export async function bggTopGames(args) {
192
192
  const limit = Math.min(Number(args.limit ?? 20), 50);
193
193
  const data = await bggFetch("/hot?type=boardgame");
@@ -34,7 +34,7 @@ export async function estimateFlightEmissions(args) {
34
34
  const legs = args.legs;
35
35
  const passengers = Number(args.passengers ?? 1);
36
36
  if (!Array.isArray(legs) || legs.length === 0) {
37
- throw new Error("legs is required array of { departure_airport, destination_airport } " +
37
+ throw new Error("legs is required - array of { departure_airport, destination_airport } " +
38
38
  "(IATA codes, e.g. [{departure_airport:'SFO', destination_airport:'LAX'}]).");
39
39
  }
40
40
  const mappedLegs = legs.map((leg) => {
@@ -0,0 +1,9 @@
1
+ export interface ConversationalCard {
2
+ headline: string;
3
+ summary: string;
4
+ keyFacts: string[];
5
+ nextActions: string[];
6
+ deepLink?: string;
7
+ }
8
+ export declare function buildCard(fields: ConversationalCard): ConversationalCard;
9
+ //# sourceMappingURL=card.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"card.d.ts","sourceRoot":"","sources":["../../src/cards/card.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,wBAAgB,SAAS,CAAC,MAAM,EAAE,kBAAkB,GAAG,kBAAkB,CAExE"}
@@ -0,0 +1,4 @@
1
+ export function buildCard(fields) {
2
+ return fields;
3
+ }
4
+ //# sourceMappingURL=card.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"card.js","sourceRoot":"","sources":["../../src/cards/card.ts"],"names":[],"mappings":"AAQA,MAAM,UAAU,SAAS,CAAC,MAA0B;IAClD,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Phase 1 example wrap. Builds a ConversationalCard summarising a
3
+ * search_memory result list. Only invoked when the caller opts in via
4
+ * include_card=true on search_memory; the legacy raw-array response is the
5
+ * default so existing agents keep working unchanged.
6
+ *
7
+ * Type imported from the new @unclick/wizard package (Phase 1 deliverable).
8
+ */
9
+ import type { ConversationalCard } from "@unclick/wizard";
10
+ export declare function buildSearchMemoryCard(query: string, results: unknown): ConversationalCard;
11
+ //# sourceMappingURL=search-memory-card.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search-memory-card.d.ts","sourceRoot":"","sources":["../../src/cards/search-memory-card.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAqB1D,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,OAAO,GACf,kBAAkB,CA6DpB"}
@@ -0,0 +1,75 @@
1
+ /**
2
+ * Phase 1 example wrap. Builds a ConversationalCard summarising a
3
+ * search_memory result list. Only invoked when the caller opts in via
4
+ * include_card=true on search_memory; the legacy raw-array response is the
5
+ * default so existing agents keep working unchanged.
6
+ *
7
+ * Type imported from the new @unclick/wizard package (Phase 1 deliverable).
8
+ */
9
+ const MAX_PREVIEW_RESULTS = 5;
10
+ const MAX_PREVIEW_LENGTH = 140;
11
+ function rowText(row) {
12
+ const raw = row.fact ?? row.content ?? "";
13
+ const trimmed = raw.replace(/\s+/g, " ").trim();
14
+ if (trimmed.length <= MAX_PREVIEW_LENGTH)
15
+ return trimmed;
16
+ return `${trimmed.slice(0, MAX_PREVIEW_LENGTH - 1)}…`;
17
+ }
18
+ export function buildSearchMemoryCard(query, results) {
19
+ const rows = Array.isArray(results) ? results : [];
20
+ const total = rows.length;
21
+ const safeQuery = query.trim() || "(empty query)";
22
+ if (total === 0) {
23
+ return {
24
+ title: `No memories found for "${safeQuery}"`,
25
+ summary: "Memory was searched but nothing matched. Try a broader query or save a new fact if this is novel context.",
26
+ severity: "info",
27
+ followUps: [
28
+ { label: "Refine the search query and try again" },
29
+ {
30
+ label: "Save this as a new fact",
31
+ action: {
32
+ tool: "save_fact",
33
+ args: { fact: "", category: "general" },
34
+ confirmation: "confirm",
35
+ },
36
+ },
37
+ ],
38
+ meta: { tool: "search_memory", query: safeQuery, result_count: 0 },
39
+ };
40
+ }
41
+ const preview = rows.slice(0, MAX_PREVIEW_RESULTS).map(rowText).filter(Boolean);
42
+ const shownCount = preview.length;
43
+ const hiddenCount = Math.max(0, total - shownCount);
44
+ return {
45
+ title: `Found ${total} memor${total === 1 ? "y" : "ies"} matching "${safeQuery}"`,
46
+ summary: hiddenCount > 0
47
+ ? `Showing the top ${shownCount} of ${total}. The rest are in the raw results payload.`
48
+ : `Showing all ${total}.`,
49
+ severity: "success",
50
+ body: [
51
+ {
52
+ kind: "list",
53
+ heading: "Top matches",
54
+ items: preview,
55
+ },
56
+ ],
57
+ followUps: [
58
+ { label: "Refine the search query and try again" },
59
+ {
60
+ label: "Save a new fact related to this query",
61
+ action: {
62
+ tool: "save_fact",
63
+ args: { fact: "", category: "general" },
64
+ confirmation: "confirm",
65
+ },
66
+ },
67
+ ],
68
+ meta: {
69
+ tool: "search_memory",
70
+ query: safeQuery,
71
+ result_count: total,
72
+ },
73
+ };
74
+ }
75
+ //# sourceMappingURL=search-memory-card.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search-memory-card.js","sourceRoot":"","sources":["../../src/cards/search-memory-card.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,MAAM,mBAAmB,GAAG,CAAC,CAAC;AAC9B,MAAM,kBAAkB,GAAG,GAAG,CAAC;AAW/B,SAAS,OAAO,CAAC,GAAkB;IACjC,MAAM,GAAG,GAAG,GAAG,CAAC,IAAI,IAAI,GAAG,CAAC,OAAO,IAAI,EAAE,CAAC;IAC1C,MAAM,OAAO,GAAG,GAAG,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;IAChD,IAAI,OAAO,CAAC,MAAM,IAAI,kBAAkB;QAAE,OAAO,OAAO,CAAC;IACzD,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,kBAAkB,GAAG,CAAC,CAAC,GAAG,CAAC;AACxD,CAAC;AAED,MAAM,UAAU,qBAAqB,CACnC,KAAa,EACb,OAAgB;IAEhB,MAAM,IAAI,GAAG,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAE,OAA2B,CAAC,CAAC,CAAC,EAAE,CAAC;IACxE,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC;IAC1B,MAAM,SAAS,GAAG,KAAK,CAAC,IAAI,EAAE,IAAI,eAAe,CAAC;IAElD,IAAI,KAAK,KAAK,CAAC,EAAE,CAAC;QAChB,OAAO;YACL,KAAK,EAAE,0BAA0B,SAAS,GAAG;YAC7C,OAAO,EACL,2GAA2G;YAC7G,QAAQ,EAAE,MAAM;YAChB,SAAS,EAAE;gBACT,EAAE,KAAK,EAAE,uCAAuC,EAAE;gBAClD;oBACE,KAAK,EAAE,yBAAyB;oBAChC,MAAM,EAAE;wBACN,IAAI,EAAE,WAAW;wBACjB,IAAI,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,QAAQ,EAAE,SAAS,EAAE;wBACvC,YAAY,EAAE,SAAS;qBACxB;iBACF;aACF;YACD,IAAI,EAAE,EAAE,IAAI,EAAE,eAAe,EAAE,KAAK,EAAE,SAAS,EAAE,YAAY,EAAE,CAAC,EAAE;SACnE,CAAC;IACJ,CAAC;IAED,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,mBAAmB,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAChF,MAAM,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC;IAClC,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,GAAG,UAAU,CAAC,CAAC;IAEpD,OAAO;QACL,KAAK,EAAE,SAAS,KAAK,SAAS,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,cAAc,SAAS,GAAG;QACjF,OAAO,EACL,WAAW,GAAG,CAAC;YACb,CAAC,CAAC,mBAAmB,UAAU,OAAO,KAAK,4CAA4C;YACvF,CAAC,CAAC,eAAe,KAAK,GAAG;QAC7B,QAAQ,EAAE,SAAS;QACnB,IAAI,EAAE;YACJ;gBACE,IAAI,EAAE,MAAM;gBACZ,OAAO,EAAE,aAAa;gBACtB,KAAK,EAAE,OAAO;aACf;SACF;QACD,SAAS,EAAE;YACT,EAAE,KAAK,EAAE,uCAAuC,EAAE;YAClD;gBACE,KAAK,EAAE,uCAAuC;gBAC9C,MAAM,EAAE;oBACN,IAAI,EAAE,WAAW;oBACjB,IAAI,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,QAAQ,EAAE,SAAS,EAAE;oBACvC,YAAY,EAAE,SAAS;iBACxB;aACF;SACF;QACD,IAAI,EAAE;YACJ,IAAI,EAAE,eAAe;YACrB,KAAK,EAAE,SAAS;YAChB,YAAY,EAAE,KAAK;SACpB;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=search-memory-card.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search-memory-card.test.d.ts","sourceRoot":"","sources":["../../src/cards/search-memory-card.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,59 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { buildSearchMemoryCard } from "./search-memory-card.js";
3
+ describe("buildSearchMemoryCard - Phase 1 Wizard wrap", () => {
4
+ it("renders an empty-state card when no results match", () => {
5
+ const card = buildSearchMemoryCard("functional programming", []);
6
+ expect(card.title).toContain("No memories found");
7
+ expect(card.title).toContain("functional programming");
8
+ expect(card.severity).toBe("info");
9
+ expect(card.followUps?.length ?? 0).toBeGreaterThanOrEqual(2);
10
+ expect(card.meta?.result_count).toBe(0);
11
+ });
12
+ it("renders a results card with truncated previews when matches exist", () => {
13
+ const results = [
14
+ { id: "1", fact: "Chris prefers TypeScript over JavaScript", confidence: 0.95 },
15
+ { id: "2", fact: "Chris's timezone is Australia/Melbourne", confidence: 0.9 },
16
+ { id: "3", fact: "Bailey reviews and merges Phase 1 wizard PRs", confidence: 0.85 },
17
+ ];
18
+ const card = buildSearchMemoryCard("Chris", results);
19
+ expect(card.title).toBe('Found 3 memories matching "Chris"');
20
+ expect(card.severity).toBe("success");
21
+ expect(card.body?.[0]?.kind).toBe("list");
22
+ if (card.body?.[0]?.kind === "list") {
23
+ expect(card.body[0].items).toHaveLength(3);
24
+ expect(card.body[0].items[0]).toContain("TypeScript");
25
+ }
26
+ expect(card.meta?.result_count).toBe(3);
27
+ });
28
+ it("singular wording when exactly one match is returned", () => {
29
+ const card = buildSearchMemoryCard("timezone", [{ fact: "Australia/Melbourne" }]);
30
+ expect(card.title).toBe('Found 1 memory matching "timezone"');
31
+ });
32
+ it("truncates long fact previews to keep cards renderable", () => {
33
+ const longFact = "x".repeat(500);
34
+ const card = buildSearchMemoryCard("noisy", [{ fact: longFact }]);
35
+ if (card.body?.[0]?.kind === "list") {
36
+ expect(card.body[0].items[0].length).toBeLessThanOrEqual(140);
37
+ expect(card.body[0].items[0].endsWith("…")).toBe(true);
38
+ }
39
+ else {
40
+ throw new Error("expected list section");
41
+ }
42
+ });
43
+ it("caps the preview list at five entries even with more matches", () => {
44
+ const results = Array.from({ length: 12 }, (_, i) => ({ fact: `fact ${i}` }));
45
+ const card = buildSearchMemoryCard("many", results);
46
+ expect(card.title).toBe('Found 12 memories matching "many"');
47
+ expect(card.summary).toContain("Showing the top 5 of 12");
48
+ if (card.body?.[0]?.kind === "list") {
49
+ expect(card.body[0].items).toHaveLength(5);
50
+ }
51
+ });
52
+ it("includes a save_fact follow-up wired with confirmation", () => {
53
+ const card = buildSearchMemoryCard("anything", [{ fact: "x" }]);
54
+ const saveFollowUp = card.followUps?.find((f) => f.action?.tool === "save_fact");
55
+ expect(saveFollowUp).toBeDefined();
56
+ expect(saveFollowUp?.action?.confirmation).toBe("confirm");
57
+ });
58
+ });
59
+ //# sourceMappingURL=search-memory-card.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search-memory-card.test.js","sourceRoot":"","sources":["../../src/cards/search-memory-card.test.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../src/catalog.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,KAAK,GAAG,MAAM,GAAG,QAAQ,GAAG,OAAO,CAAC;IAC5C,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,OAAO,CAAC;IACtB,8CAA8C;IAC9C,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACtC;AAED,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,WAAW,EAAE,CAAC;CAC1B;AAED,eAAO,MAAM,UAAU,4FASb,CAAC;AAEX,eAAO,MAAM,OAAO,EAAE,OAAO,EAi1D5B,CAAC;AAEF,qDAAqD;AACrD,eAAO,MAAM,YAAY;UAA2B,OAAO;cAAY,WAAW;EAAK,CAAC;AAOxF,iCAAiC;AACjC,eAAO,MAAM,QAAQ,sBAEpB,CAAC"}
1
+ {"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../src/catalog.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,KAAK,GAAG,MAAM,GAAG,QAAQ,GAAG,OAAO,CAAC;IAC5C,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,OAAO,CAAC;IACtB,8CAA8C;IAC9C,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACtC;AAED,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,WAAW,EAAE,CAAC;CAC1B;AAED,eAAO,MAAM,UAAU,4FASb,CAAC;AAEX,eAAO,MAAM,OAAO,EAAE,OAAO,EAulE5B,CAAC;AAEF,qDAAqD;AACrD,eAAO,MAAM,YAAY;UAA2B,OAAO;cAAY,WAAW;EAAK,CAAC;AAOxF,iCAAiC;AACjC,eAAO,MAAM,QAAQ,sBAEpB,CAAC"}