@thenavidm/slipway 0.1.15 → 0.1.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,14 @@
2
2
 
3
3
  What changed in Slipway, newest first.
4
4
 
5
+ ## 0.1.17, 2026-10-05: what Google Photos needed
6
+
7
+ - **`which` reads an argument by its own words, not through a synonym.** Since 0.1.14 a tool's argument names count toward finding it, and a synonym reached them too. Google Photos says "photos" means media, so `get_media_item`, which takes a `media_item_id`, drew level with the photo picker for "let me choose photos" and was listed first. An argument now counts only for the words it is made of, so the picker is first again. Buffer's "schedule a post to a channel" still reads `channelId` and `schedulingType`, and the first answer to every task measured on the other servers is unchanged.
8
+
9
+ ## 0.1.16, 2026-10-05: what Flodesk needed
10
+
11
+ - **`which` says a title once.** Each answer line printed a tool's title and then the first sentence of its description, and many descriptions open with the title itself: 24 of Flodesk's 32 tools, 10 of Firefly's 14, and nearly every tool on Beehiiv, Calendly and Circle. Where the sentence opens with the title's words, the line now prints the sentence alone. Flodesk's answer to `which add a subscriber to a segment` goes from 52 tokens to 36 and Firefly's to `which image model 5` from 90 to 77, and an agent carries that answer through each step after it. A description that adds something new still follows its title.
12
+
5
13
  ## 0.1.15, 2026-10-05: what Adobe Firefly needed
6
14
 
7
15
  - **The general help counts the tuning settings instead of naming them.** An agent reads `--help` first and carries it through every later step, so its length is paid again on each one. Firefly's help named 14 settings on its last line, and with only 14 commands its whole command list was shorter; its Codex CLI task cost 370 more input tokens on Slipway than on its own 2.x CLI. The line now says how many more settings there are and that `agent-context` describes each, the `--http` settings join that count, and the safety switches and the settings an app marks as setup are still named. Every server's help is shorter by the names it had on that line.
@@ -14,5 +14,5 @@ export declare function renderList(app: App, tools: readonly Tool[], bin: string
14
14
  export declare function exampleCommand(bin: string, tool: Tool, args: Record<string, unknown>): string;
15
15
  export declare function renderToolHelp(tool: Tool, bin: string, aliases?: Readonly<Record<string, string>>): string;
16
16
  export declare function renderGeneralHelp(app: App, bin: string): string;
17
- /** One line per tool, for search results and listings. */
17
+ /** One line per tool, for search results: the title, then what the description adds to it. */
18
18
  export declare function toolLine(tool: Tool): string;
package/dist/cli/help.js CHANGED
@@ -293,7 +293,15 @@ export function renderGeneralHelp(app, bin) {
293
293
  lines.push(app.definition.links.repository, ``);
294
294
  return lines.join("\n");
295
295
  }
296
- /** One line per tool, for search results and listings. */
296
+ /** One line per tool, for search results: the title, then what the description adds to it. */
297
297
  export function toolLine(tool) {
298
- return `${riskMark(tool)} ${tool.command} ${tool.title}: ${firstSentence(tool.description, 80)}`;
298
+ const sentence = firstSentence(tool.description, 80);
299
+ // Many descriptions open by saying the title again, which an agent would read twice.
300
+ const what = !sentence ? tool.title : restates(sentence, tool.title) ? sentence : `${tool.title}: ${sentence}`;
301
+ return `${riskMark(tool)} ${tool.command} ${what}`;
302
+ }
303
+ /** Whether a sentence opens with a title's words, whatever the case and punctuation. */
304
+ function restates(sentence, title) {
305
+ const words = (text) => text.toLowerCase().replace(/[^\p{L}\p{N}]+/gu, " ").trim();
306
+ return words(sentence).startsWith(words(title));
299
307
  }
package/dist/search.js CHANGED
@@ -94,12 +94,14 @@ export function searchTools(tools, query, limit = 10, synonyms = {}) {
94
94
  const tags = tool.tags.flatMap(words);
95
95
  const description = words(tool.description);
96
96
  // What a tool takes says what it is for: `channelId` and `schedulingType` find the post tool for "schedule a post to a channel".
97
+ // Only the words themselves count there. Through a synonym, Google Photos' "photos" read as `media_item_id`
98
+ // and put get_media_item level with the picker for "let me choose photos".
97
99
  const args = Object.keys(tool.jsonSchema.properties ?? {}).filter((key) => key !== "confirm").flatMap(words);
98
100
  let score = 0;
99
101
  let matched = 0;
100
102
  for (const term of terms) {
101
103
  // A term that is the tool's name is not a hint, it is the answer.
102
- const got = (named(tool, term) ? 20 : 0) + hits(term, name, extra) * 5 + hits(term, title, extra) * 4 + hits(term, tags, extra) * 3 + hits(term, args, extra) * 2 + hits(term, description, extra);
104
+ const got = (named(tool, term) ? 20 : 0) + hits(term, name, extra) * 5 + hits(term, title, extra) * 4 + hits(term, tags, extra) * 3 + exact(term, args) * 2 + hits(term, description, extra);
103
105
  if (got > 0)
104
106
  matched++;
105
107
  score += got;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thenavidm/slipway",
3
- "version": "0.1.15",
3
+ "version": "0.1.17",
4
4
  "description": "Slipway, the TypeScript framework for MCP servers and agent-native CLIs. One tool definition ships an MCP server and a CLI, with write safety, typed results and release checks built in.",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",