@magpie-community/opencode-kiro-auth 0.1.8 → 0.1.10
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 +2 -0
- package/index.mjs +34 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -76,6 +76,8 @@ request:
|
|
|
76
76
|
- Tool ids Kiro wouldn't take are rewritten. A tool name over 64
|
|
77
77
|
characters (an MCP plugin's, in Claude Code) is sent shortened with a
|
|
78
78
|
hash and its calls come back under the full name.
|
|
79
|
+
- A tool's images (a screenshot, Codex's view_image) go with the
|
|
80
|
+
message that answers the call, as Kiro's tool results hold text alone.
|
|
79
81
|
- Only the latest images are sent.
|
|
80
82
|
- Tools the history used but the request doesn't offer are declared.
|
|
81
83
|
- It turns the AWS event stream Kiro answers with back into Messages'
|
package/index.mjs
CHANGED
|
@@ -614,6 +614,12 @@ function imageFormat(mediaType) {
|
|
|
614
614
|
return f
|
|
615
615
|
}
|
|
616
616
|
|
|
617
|
+
// addImage puts an Anthropic image block in images as Kiro takes it: the
|
|
618
|
+
// bytes inline. One named only by a URL has no bytes to send and is left out.
|
|
619
|
+
function addImage(images, p) {
|
|
620
|
+
if (p.source?.type === "base64" && p.source.data) images.push({ format: imageFormat(p.source.media_type), source: { bytes: p.source.data } })
|
|
621
|
+
}
|
|
622
|
+
|
|
617
623
|
const textOf = (c) =>
|
|
618
624
|
typeof c === "string" ? c : Array.isArray(c) ? c.filter((p) => p?.type === "text").map((p) => p.text ?? "").join("\n\n") : ""
|
|
619
625
|
const joinNonEmpty = (a, b) => (a && b ? a + "\n\n" + b : a + b)
|
|
@@ -640,6 +646,12 @@ function thinking(req, model) {
|
|
|
640
646
|
// buildKiro is the body of a generateAssistantResponse call.
|
|
641
647
|
function buildKiro(req, model, profile, budget) {
|
|
642
648
|
const entries = []
|
|
649
|
+
// the messages the caller marked for its prompt cache (cache_control),
|
|
650
|
+
// which go to Kiro as a cachePoint on the message they end up in (#110)
|
|
651
|
+
const marked = new WeakSet()
|
|
652
|
+
const mark = (msg, parts) => {
|
|
653
|
+
if (parts.some((p) => p?.cache_control)) marked.add(msg)
|
|
654
|
+
}
|
|
643
655
|
const user = () => ({ content: "", modelId: model, origin: "KIRO_CLI" })
|
|
644
656
|
for (const m of req.messages ?? []) {
|
|
645
657
|
const parts = typeof m.content === "string" ? [{ type: "text", text: m.content }] : m.content ?? []
|
|
@@ -660,6 +672,7 @@ function buildKiro(req, model, profile, budget) {
|
|
|
660
672
|
prev.content = joinNonEmpty(prev.content, a.content)
|
|
661
673
|
prev.toolUses.push(...a.toolUses)
|
|
662
674
|
} else entries.push({ assistantResponseMessage: a })
|
|
675
|
+
mark(prev ?? a, parts)
|
|
663
676
|
continue
|
|
664
677
|
}
|
|
665
678
|
const u = user()
|
|
@@ -669,12 +682,14 @@ function buildKiro(req, model, profile, budget) {
|
|
|
669
682
|
if (p?.type === "text") {
|
|
670
683
|
if (p.text) texts.push(p.text)
|
|
671
684
|
} else if (p?.type === "document") texts.push(documentText(p))
|
|
672
|
-
else if (p?.type === "image")
|
|
673
|
-
|
|
674
|
-
} else if (p?.type === "tool_result") {
|
|
685
|
+
else if (p?.type === "image") addImage(u.images, p)
|
|
686
|
+
else if (p?.type === "tool_result") {
|
|
675
687
|
let out = textOf(p.content)
|
|
676
688
|
if (out.length > RESULT_LIMIT) out = out.slice(0, RESULT_LIMIT) + "\n… (cut)"
|
|
677
689
|
results.push({ toolUseId: toolID(p.tool_use_id), status: p.is_error ? "error" : "success", content: [{ text: out || "(no output)" }] })
|
|
690
|
+
// a tool's images (a screenshot, Codex's view_image) go with the
|
|
691
|
+
// message, as Kiro's tool results carry text alone (magpie #369, #1861)
|
|
692
|
+
if (Array.isArray(p.content)) for (const c of p.content) if (c?.type === "image") addImage(u.images, c)
|
|
678
693
|
}
|
|
679
694
|
}
|
|
680
695
|
u.content = texts.join("\n\n")
|
|
@@ -685,6 +700,7 @@ function buildKiro(req, model, profile, budget) {
|
|
|
685
700
|
prev.images.push(...u.images)
|
|
686
701
|
if (results.length) (prev.userInputMessageContext ??= { toolResults: [] }).toolResults.push(...results)
|
|
687
702
|
} else entries.push({ userInputMessage: u })
|
|
703
|
+
mark(prev ?? u, parts)
|
|
688
704
|
}
|
|
689
705
|
// the conversation opens with something the user said: tool results with
|
|
690
706
|
// no call before them go, and a reply the caller began with
|
|
@@ -740,6 +756,7 @@ function buildKiro(req, model, profile, budget) {
|
|
|
740
756
|
let system = typeof req.system === "string" ? req.system : textOf(req.system)
|
|
741
757
|
if (budget) system = `<thinking_mode>enabled</thinking_mode><max_thinking_length>${budget}</max_thinking_length>` + (system ? "\n" + system : "")
|
|
742
758
|
if (system) entries[0].userInputMessage.content = system + "\n\n" + entries[0].userInputMessage.content
|
|
759
|
+
if (Array.isArray(req.system)) mark(entries[0].userInputMessage, req.system)
|
|
743
760
|
|
|
744
761
|
// the caller's tools, and any the conversation used that it no longer
|
|
745
762
|
// offers — Kiro rejects a history naming a tool it wasn't given
|
|
@@ -752,6 +769,7 @@ function buildKiro(req, model, profile, budget) {
|
|
|
752
769
|
const name = toolName(t.name)
|
|
753
770
|
offered.add(name)
|
|
754
771
|
tools.push({ toolSpecification: { name, description: t.description || t.name, inputSchema: { json: t.input_schema ?? EMPTY } } })
|
|
772
|
+
if (t.cache_control) tools.push({ cachePoint: { type: "default" } })
|
|
755
773
|
}
|
|
756
774
|
for (const e of entries)
|
|
757
775
|
for (const c of e.assistantResponseMessage?.toolUses ?? [])
|
|
@@ -760,6 +778,19 @@ function buildKiro(req, model, profile, budget) {
|
|
|
760
778
|
tools.push({ toolSpecification: { name: c.name, description: "Tool", inputSchema: { json: EMPTY } } })
|
|
761
779
|
}
|
|
762
780
|
if (tools.length) (current.userInputMessageContext ??= {}).tools = tools
|
|
781
|
+
// Kiro's cachePoint is Bedrock's: it caches the prompt up to the point,
|
|
782
|
+
// and a request may hold 4 at most, as Anthropic's cache_control; past
|
|
783
|
+
// that the last ones are kept, the most of the prompt they cover
|
|
784
|
+
const points = []
|
|
785
|
+
for (const t of tools) if (t.cachePoint) points.push(() => tools.splice(tools.indexOf(t), 1))
|
|
786
|
+
for (const e of entries) {
|
|
787
|
+
const msg = e.userInputMessage ?? e.assistantResponseMessage
|
|
788
|
+
if (marked.has(msg)) {
|
|
789
|
+
msg.cachePoint = { type: "default" }
|
|
790
|
+
points.push(() => delete msg.cachePoint)
|
|
791
|
+
}
|
|
792
|
+
}
|
|
793
|
+
for (const drop of points.slice(0, Math.max(0, points.length - 4))) drop()
|
|
763
794
|
|
|
764
795
|
const state = { chatTriggerType: "MANUAL", agentTaskType: "vibe", conversationId: randomUUID(), currentMessage: { userInputMessage: current } }
|
|
765
796
|
if (entries.length > 1) state.history = entries.slice(0, -1)
|