@magpie-community/opencode-zen-free-auth 0.1.0 → 0.1.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.
package/README.md CHANGED
@@ -31,6 +31,9 @@ Requests go to `https://opencode.ai/zen/v1` using each model's native
31
31
  Chat Completions, Responses or Anthropic Messages API. Streaming and
32
32
  ordinary JSON replies are supported.
33
33
 
34
- The agent's tools are preserved. If Zen calls an added tool, its name is
35
- mapped to the agent's unique case-insensitive match (`bash` to `Bash`).
36
- A call with no matching tool returns an error. Tools run in the agent.
34
+ The agent's tools are preserved. Zen's models often call OpenCode's own
35
+ tool names; such a call is given the agent's tool whose name differs only
36
+ in case (`bash` to `Bash`), or else only in case and `_`/`-` (`todowrite`
37
+ to `todo_write`, `webfetch` to `web_fetch`), when exactly one does. A
38
+ call with no such tool returns an error that names it. Tools run in the
39
+ agent.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@magpie-community/opencode-zen-free-auth",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "OpenCode Zen free models through the public credential, with native streaming protocols",
5
5
  "type": "module",
6
6
  "main": "./index.mjs",
package/tool-response.mjs CHANGED
@@ -30,20 +30,35 @@ function list(value) {
30
30
  return value;
31
31
  }
32
32
 
33
- function nameGuard(policy) {
34
- const declared = new Set(policy.declared);
35
- const injected = new Set(policy.injected);
33
+ // OpenCode's own models call OpenCode's tool names (bash, todowrite,
34
+ // webfetch) whatever the agent declared. A call is given the agent's tool
35
+ // whose name differs only in case, or else only in case and separators
36
+ // (todowrite → todo_write, webfetch → web_fetch), when exactly one does; a
37
+ // name two of the agent's tools fold to is never guessed between.
38
+ const separators = /[\s_.-]/g;
39
+ function foldsTo(declared, key) {
36
40
  const folded = new Map();
37
41
  for (const name of declared) {
38
- const key = name.toLowerCase();
39
- folded.set(key, folded.has(key) ? null : name);
42
+ const k = key(name);
43
+ folded.set(k, folded.has(k) ? null : name);
40
44
  }
45
+ return folded;
46
+ }
47
+
48
+ function nameGuard(policy) {
49
+ const declared = new Set(policy.declared);
50
+ const lower = (name) => name.toLowerCase();
51
+ const bare = (name) => name.toLowerCase().replace(separators, "");
52
+ const byCase = foldsTo(declared, lower);
53
+ const byShape = foldsTo(declared, bare);
41
54
  return (name) => {
42
55
  if (typeof name !== "string" || !name) throw new GuardError("Missing upstream tool name");
43
56
  if (declared.has(name)) return name;
44
- const match = injected.has(name) && folded.get(name.toLowerCase());
57
+ const match = byCase.get(lower(name)) ?? (byCase.has(lower(name)) ? null : byShape.get(bare(name)));
45
58
  if (match) return match;
46
- throw new GuardError("Upstream called a tool not declared by the client");
59
+ throw new GuardError(
60
+ `Upstream called a tool not declared by the client: ${JSON.stringify(name.slice(0, 128))}`,
61
+ );
47
62
  };
48
63
  }
49
64