diff --git a/SANDBOX.md b/SANDBOX.md index 3a95024..42baf58 100644 --- a/SANDBOX.md +++ b/SANDBOX.md @@ -240,7 +240,7 @@ export function createBashTool(googleAuthId) { | Consideration | Ephemeral (`docker run --rm`) | Persistent Container (`docker exec`) | | :--- | :--- | :--- | -| **Startup Overhead** | ~200–400ms per command | ~20–50ms per command | +| **Startup Overhead** | ~200-400ms per command | ~20-50ms per command | | **State Cleanliness** | Completely fresh OS environment every call | Processes/background jobs remain running | | **Lifecycle Complexity** | None. Docker handles lifecycle and cleanup | Requires container pool management and reaper | | **Failure Recovery** | Automatic | If container crashes, must be recreated | diff --git a/docs/api/routes/pos/client.md b/docs/api/routes/pos/client.md index 666755b..f27a5b5 100644 --- a/docs/api/routes/pos/client.md +++ b/docs/api/routes/pos/client.md @@ -5,7 +5,7 @@ Public. No cookie required. POS discovery and pairing Special API for POS bind and sync. -- Step 1 (Discovery): `authCode` length 1–4. Returns certificate fingerprints, serial number, and mandantId. +- Step 1 (Discovery): `authCode` length 1-4. Returns certificate fingerprints, serial number, and mandantId. - Step 2 (Pairing): `authCode` length 6 (pairingpin from posterminal). Verifies the pairingpin, sets token, paired_at, and clientserial, revokes the pairingpin, and returns device credentials and company metadata. diff --git a/mcp.md b/mcp.md index 462faaa..224f856 100644 --- a/mcp.md +++ b/mcp.md @@ -226,7 +226,7 @@ server.registerTool('search-articles', { searchquery: z.string().nullable().optional().describe('Keywords matching name, brand, EAN, SKU, or supplier SKU (AND logic).'), excludewords: z.string().nullable().optional().describe('Keywords to exclude (AND logic).'), offset: z.number().int().min(0).nullable().optional().describe('Pagination offset (default 0).'), - limit: z.number().int().min(1).max(20).nullable().optional().describe('Window size 1–20 (default 3).'), + limit: z.number().int().min(1).max(20).nullable().optional().describe('Window size 1-20 (default 3).'), }, }, async ({ searchquery, excludewords, offset, limit }) => { ... }); ``` diff --git a/src/api/routes/mcp.js b/src/api/routes/mcp.js index c2b82c2..7a3383d 100644 --- a/src/api/routes/mcp.js +++ b/src/api/routes/mcp.js @@ -115,8 +115,8 @@ const tokenVerifier = { const scopes = typeof decoded.scope === 'string' ? decoded.scope.split(' ') : Array.isArray(decoded.scope) - ? decoded.scope - : ['mcp:tools']; + ? decoded.scope + : ['mcp:tools']; return { token, @@ -237,7 +237,7 @@ function createDashbackMcpServer({ user }) { searchquery: z.string().nullable().optional().describe(TOOL_PARAMETER_DESCRIPTIONS.search_articles?.searchquery || 'Keywords matching name, brand, EAN, SKU, or supplier SKU (AND logic).'), excludewords: z.string().nullable().optional().describe(TOOL_PARAMETER_DESCRIPTIONS.search_articles?.excludewords || 'Keywords to exclude (AND logic).'), offset: z.number().int().min(0).nullable().optional().describe(TOOL_PARAMETER_DESCRIPTIONS.search_articles?.offset || 'Pagination offset (default 0).'), - limit: z.number().int().min(1).max(20).nullable().optional().describe(TOOL_PARAMETER_DESCRIPTIONS.search_articles?.limit || 'Window size 1–20 (default 3).'), + limit: z.number().int().min(1).max(20).nullable().optional().describe(TOOL_PARAMETER_DESCRIPTIONS.search_articles?.limit || 'Window size 1-20 (default 3).'), }, }, async ({ searchquery = '', excludewords = '', offset = 0, limit = 3 } = {}) => { diff --git a/src/defaultApplets/category-inventory.applet.js b/src/defaultApplets/category-inventory.applet.js index 8203ddb..9d6b48d 100644 --- a/src/defaultApplets/category-inventory.applet.js +++ b/src/defaultApplets/category-inventory.applet.js @@ -1,4 +1,4 @@ -// @applet-input-schema {"type":"object","properties":{"query":{"type":"string","title":"Category name contains","default":"","description":"Case-insensitive substring match on the category name. Leave empty to include every category."},"limit":{"type":"integer","title":"Max rows","default":100,"minimum":1,"maximum":500},"sortBy":{"type":"string","title":"Sort by","default":"articles","enum":["articles","name","depth"],"description":"articles = most articles first, name = A–Z, depth = tree depth then name."}}} +// @applet-input-schema {"type":"object","properties":{"query":{"type":"string","title":"Category name contains","default":"","description":"Case-insensitive substring match on the category name. Leave empty to include every category."},"limit":{"type":"integer","title":"Max rows","default":100,"minimum":1,"maximum":500},"sortBy":{"type":"string","title":"Sort by","default":"articles","enum":["articles","name","depth"],"description":"articles = most articles first, name = A-Z, depth = tree depth then name."}}} // @applet-output-schema id:integer;name:string;depth:integer;articles:integer;children:integer // @applet-description "Category inventory — every category with its article count and child count." // diff --git a/src/tools/analyze-image.js b/src/tools/analyze-image.js index 431c98a..5f231f9 100644 --- a/src/tools/analyze-image.js +++ b/src/tools/analyze-image.js @@ -21,7 +21,7 @@ import { * call with the image attached. This tool is that bridge: * * - 1 image → resized to fit 400×400 and sent as a single WebP. - * - 2–9 → composited into a labelled grid (2x1/3x1/2x2/3x2/3x3) with the file name + * - 2-9 → composited into a labelled grid (2x1/3x1/2x2/3x2/3x3) with the file name * printed under each cell, so one cheap call can compare many candidates. * - Database images are addressed as `image/` and fetched from `/image/:hash`. * @@ -314,7 +314,7 @@ export function createAnalyzeImageTool({ googleAuthId, model }) { const inputs = extractImageInputs({ paths }); if (inputs.length === 0) { throw new ToolError( - 'analyze_image requires "paths": an array of 1–9 VFS paths (e.g. ["images/a-1.avif"]) ' + + 'analyze_image requires "paths": an array of 1-9 VFS paths (e.g. ["images/a-1.avif"]) ' + 'or database paths (e.g. ["image/"]). Get candidates from search_images first.' ); } diff --git a/src/tools/prompts.js b/src/tools/prompts.js index 6a3e6ea..a929d85 100644 --- a/src/tools/prompts.js +++ b/src/tools/prompts.js @@ -173,7 +173,7 @@ export const TOOL_PARAMETER_DESCRIPTIONS = { analyze_image: { note: NOTE_DESC, - paths: '1–9 VFS paths or DB paths ("image/").', + paths: '1-9 VFS paths or DB paths ("image/").', prompt: 'Inspection criteria or question.', grid: 'Grid layout or null for auto.', }, @@ -216,7 +216,7 @@ export const TOOL_PARAMETER_DESCRIPTIONS = { searchquery: 'Keywords matching name, brand, EAN, SKU, or supplier SKU (AND logic).', excludewords: 'Keywords to exclude (AND logic).', offset: 'Pagination offset (default 0).', - limit: 'Window size 1–20 (default 3).', + limit: 'Window size 1-20 (default 3).', }, edit_image: { @@ -243,7 +243,7 @@ export const TOOL_PARAMETER_DESCRIPTIONS = { taxRate: 'VAT percentage (default 19).', amount: 'Price amount when paired with "from".', from: '"gross" (default) or "net".', - precision: 'Net price API decimal precision 2–8 (default 6).', + precision: 'Net price API decimal precision 2-8 (default 6).', items: 'Array of prices or calculation objects for batch processing.', }, diff --git a/src/v1/routes/client.js b/src/v1/routes/client.js index 1c95973..e59abd6 100644 --- a/src/v1/routes/client.js +++ b/src/v1/routes/client.js @@ -64,7 +64,7 @@ export function buildClientStep2(authCode, config) { * summary: POS discovery and pairing * description: | * Special API for POS bind and sync. - * - Step 1 (Discovery): `authCode` length 1–4. Returns certificate fingerprints, serial number, and mandantId. + * - Step 1 (Discovery): `authCode` length 1-4. Returns certificate fingerprints, serial number, and mandantId. * - Step 2 (Pairing): `authCode` length 6 (pairingpin from posterminal). Verifies the pairingpin, sets token, paired_at, and clientserial, revokes the pairingpin, and returns device credentials and company metadata. * security: [] * x-markdown: pos/client.md