@magpie-community/opencode-kiro-auth 0.1.7 → 0.1.8

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 (3) hide show
  1. package/README.md +3 -1
  2. package/index.mjs +41 -9
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -73,7 +73,9 @@ request:
73
73
  - The system prompt goes at the head of the first message.
74
74
  - Tool calls and results are paired: an unanswered call gets an error
75
75
  result, and a result longer than 250,000 characters is cut.
76
- - Tool ids Kiro wouldn't take are rewritten.
76
+ - Tool ids Kiro wouldn't take are rewritten. A tool name over 64
77
+ characters (an MCP plugin's, in Claude Code) is sent shortened with a
78
+ hash and its calls come back under the full name.
77
79
  - Only the latest images are sent.
78
80
  - Tools the history used but the request doesn't offer are declared.
79
81
  - It turns the AWS event stream Kiro answers with back into Messages'
package/index.mjs CHANGED
@@ -576,6 +576,36 @@ const TOOL_ID = /^[a-zA-Z0-9_.:-]{1,64}$/
576
576
  // one of Kiro's own, the same each time.
577
577
  const toolID = (id) => (TOOL_ID.test(id ?? "") ? id : "t_" + createHash("sha256").update(String(id ?? "")).digest("base64url").slice(0, 32))
578
578
 
579
+ // Kiro answers a tool named past 64 characters, or outside these, "Invalid
580
+ // tool use format." and won't raise the limit (kirodotdev/Kiro#7684), while
581
+ // MCP tools in Claude Code are named mcp__plugin_<plugin>_<server>__<tool>
582
+ // (yetone/magpie#1393).
583
+ const TOOL_NAME = /^[a-zA-Z0-9_-]{1,64}$/
584
+
585
+ // toolName is a tool's name as Kiro takes one: another is its head with a
586
+ // hash of the whole name, the same each time, so the conversation's later
587
+ // turns name it the same way. toolNames maps each such name back.
588
+ const toolName = (name) => {
589
+ const n = String(name ?? "")
590
+ if (TOOL_NAME.test(n)) return n
591
+ const hash = createHash("sha256").update(n).digest("hex").slice(0, 12)
592
+ return n.replace(/[^a-zA-Z0-9_-]/g, "_").slice(0, 64 - 1 - hash.length) + "_" + hash
593
+ }
594
+
595
+ // toolNames is the name the caller knows for each tool a request names
596
+ // that Kiro is sent under another name.
597
+ function toolNames(req) {
598
+ const names = new Map()
599
+ const add = (n) => {
600
+ if (typeof n !== "string" || !n) return
601
+ const k = toolName(n)
602
+ if (k !== n) names.set(k, n)
603
+ }
604
+ for (const t of req.tools ?? []) add(t?.name)
605
+ for (const m of req.messages ?? []) if (Array.isArray(m.content)) for (const p of m.content) if (p?.type === "tool_use") add(p.name)
606
+ return names
607
+ }
608
+
579
609
  function imageFormat(mediaType) {
580
610
  const t = String(mediaType ?? "").toLowerCase()
581
611
  const f = t.replace(/^image\//, "")
@@ -620,7 +650,7 @@ function buildKiro(req, model, profile, budget) {
620
650
  if (p?.type === "text" && p.text) texts.push(p.text)
621
651
  else if (p?.type === "tool_use") {
622
652
  const input = p.input && typeof p.input === "object" && !Array.isArray(p.input) ? p.input : {}
623
- a.toolUses.push({ name: p.name, toolUseId: toolID(p.id), input })
653
+ a.toolUses.push({ name: toolName(p.name), toolUseId: toolID(p.id), input })
624
654
  }
625
655
  }
626
656
  a.content = texts.join("\n\n")
@@ -719,8 +749,9 @@ function buildKiro(req, model, profile, budget) {
719
749
  const EMPTY = { type: "object", properties: {} }
720
750
  for (const t of req.tools ?? []) {
721
751
  if (!t?.name || (t.type && t.type !== "custom" && !t.input_schema)) continue // server tools Kiro hasn't
722
- offered.add(t.name)
723
- tools.push({ toolSpecification: { name: t.name, description: t.description || t.name, inputSchema: { json: t.input_schema ?? EMPTY } } })
752
+ const name = toolName(t.name)
753
+ offered.add(name)
754
+ tools.push({ toolSpecification: { name, description: t.description || t.name, inputSchema: { json: t.input_schema ?? EMPTY } } })
724
755
  }
725
756
  for (const e of entries)
726
757
  for (const c of e.assistantResponseMessage?.toolUses ?? [])
@@ -1047,8 +1078,9 @@ const QUOTA_WORDS = /quota|insufficient|balance|credit|billing|exceeded|rate.?li
1047
1078
  const failedBefore = (text) => errorResponse(QUOTA_WORDS.test(text) ? 429 : 502, text)
1048
1079
 
1049
1080
  // reply answers the Messages request from Kiro's events: a stream of
1050
- // Messages' events, or one message.
1051
- async function reply(it, model, stream) {
1081
+ // Messages' events, or one message. names gives back the caller's name of
1082
+ // a tool Kiro was sent under another (toolNames).
1083
+ async function reply(it, model, stream, names = new Map()) {
1052
1084
  const id = "msg_" + randomBytes(12).toString("hex")
1053
1085
  if (!stream) {
1054
1086
  const content = []
@@ -1066,7 +1098,7 @@ async function reply(it, model, stream) {
1066
1098
  else add({ type: "thinking", thinking: e.text, signature: "" })
1067
1099
  } else if (e.kind === "sig") {
1068
1100
  if (last?.type === "thinking") last.signature += e.text
1069
- } else if (e.kind === "toolStart") add({ type: "tool_use", id: e.id, name: e.name, input: "" })
1101
+ } else if (e.kind === "toolStart") add({ type: "tool_use", id: e.id, name: names.get(e.name) ?? e.name, input: "" })
1070
1102
  else if (e.kind === "toolArgs") {
1071
1103
  if (last?.type === "tool_use") last.input += e.text
1072
1104
  } else if (e.kind === "error") {
@@ -1127,7 +1159,7 @@ async function reply(it, model, stream) {
1127
1159
  if (open === "thinking") ctl.enqueue(sse("content_block_delta", { index, delta: { type: "signature_delta", signature: e.text } }))
1128
1160
  break
1129
1161
  case "toolStart":
1130
- begin("tool", { type: "tool_use", id: e.id, name: e.name, input: {} })
1162
+ begin("tool", { type: "tool_use", id: e.id, name: names.get(e.name) ?? e.name, input: {} })
1131
1163
  break
1132
1164
  case "toolArgs":
1133
1165
  if (open === "tool") ctl.enqueue(sse("content_block_delta", { index, delta: { type: "input_json_delta", partial_json: e.text } }))
@@ -1189,7 +1221,7 @@ async function generate(creds, auth, req, signal) {
1189
1221
  const f = failure(res.status, (await res.text()).slice(0, 1 << 20))
1190
1222
  return errorResponse(f.status, f.message)
1191
1223
  }
1192
- return kept(await reply(events(res.body, model, budget), model, req.stream === true))
1224
+ return kept(await reply(events(res.body, model, budget), model, req.stream === true, toolNames(req)))
1193
1225
  }
1194
1226
 
1195
1227
  // ---- signing in ----------------------------------------------------------------------
@@ -1453,4 +1485,4 @@ export async function KiroAuthPlugin({ client } = {}) {
1453
1485
  }
1454
1486
 
1455
1487
  // for tests
1456
- export const _internal = { generate, refresh, usageOf, buildKiro, events, reply, failure, toolID, thinking, readCLI, readIDE, regionOf, planName, frames }
1488
+ export const _internal = { generate, refresh, usageOf, buildKiro, events, reply, failure, toolID, toolName, toolNames, thinking, readCLI, readIDE, regionOf, planName, frames }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@magpie-community/opencode-kiro-auth",
3
- "version": "0.1.7",
3
+ "version": "0.1.8",
4
4
  "description": "Kiro subscriptions (Free, Pro, Pro+, Power) in OpenCode and magpie",
5
5
  "type": "module",
6
6
  "main": "./index.mjs",