@magpie-community/opencode-trae-auth 0.1.9 → 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.
Files changed (2) hide show
  1. package/index.mjs +63 -6
  2. package/package.json +1 -1
package/index.mjs CHANGED
@@ -551,8 +551,8 @@ class TextTools {
551
551
  text += this.buf.slice(0, i)
552
552
  const raw = this.buf.slice(i + OPEN.length, j).trim()
553
553
  this.buf = this.buf.slice(j + CLOSE.length)
554
- const v = parseJSON(raw)
555
- if (v.name) calls.push({ name: String(v.name), arguments: typeof v.arguments === "string" ? v.arguments : JSON.stringify(v.arguments ?? v.input ?? v.parameters ?? {}) })
554
+ const v = looseJSON(raw) ?? {}
555
+ if (v.name) calls.push({ name: String(v.name), arguments: callArgs(v) })
556
556
  else text += OPEN + raw + CLOSE
557
557
  }
558
558
  if (end) {
@@ -570,14 +570,62 @@ class TextTools {
570
570
  }
571
571
  }
572
572
 
573
+ // looseJSON reads a JSON object as a model writes one: a string holding a
574
+ // raw newline or tab (a file's content written out, #799) is read as if
575
+ // they were escaped. null when it isn't one even so.
576
+ function looseJSON(s) {
577
+ for (const t of [s, escapeRaw(s)]) {
578
+ try {
579
+ const v = JSON.parse(t)
580
+ if (v && typeof v === "object" && !Array.isArray(v)) return v
581
+ } catch {}
582
+ }
583
+ return null
584
+ }
585
+
586
+ // escapeRaw escapes the control characters inside JSON strings
587
+ function escapeRaw(s) {
588
+ let out = ""
589
+ let str = false
590
+ let esc = false
591
+ for (const ch of String(s ?? "")) {
592
+ if (str && !esc && ch < " ") {
593
+ out += ch === "\n" ? "\\n" : ch === "\r" ? "\\r" : ch === "\t" ? "\\t" : "\\u" + ch.charCodeAt(0).toString(16).padStart(4, "0")
594
+ continue
595
+ }
596
+ if (str && ch === "\\" && !esc) esc = true
597
+ else {
598
+ if (ch === '"' && !esc) str = !str
599
+ esc = false
600
+ }
601
+ out += ch
602
+ }
603
+ return out
604
+ }
605
+
606
+ // callArgs is a tagged block's arguments as JSON: under arguments (an
607
+ // object, or a string of one), input or parameters, else the block's other
608
+ // keys, as a model that writes them beside the name means them (#799: a
609
+ // write that went out as {})
610
+ function callArgs(v) {
611
+ let a = v.arguments ?? v.input ?? v.parameters
612
+ if (a === undefined) {
613
+ const { name, type, id, ...rest } = v
614
+ a = rest
615
+ }
616
+ if (typeof a === "string") return a.trim() ? (looseJSON(a) ? JSON.stringify(looseJSON(a)) : a) : "{}"
617
+ return JSON.stringify(a ?? {})
618
+ }
619
+
573
620
  // nativeCall is a tool call as Trae's events carry one
574
621
  function nativeCall(tc) {
575
622
  const f = tc?.function ?? tc?.function_call ?? tc
576
623
  const name = f?.name ?? tc?.tool_name ?? ""
577
624
  const index = Number.isInteger(tc?.index) ? tc.index : null
578
- if (!name && index === null && !tc?.id) return null
579
625
  const a = f?.arguments ?? f?.args ?? tc?.params ?? tc?.input ?? tc?.parameters ?? ""
580
- return { id: tc?.id || tc?.tool_call_id || "", index, name: String(name), arguments: typeof a === "string" ? a : JSON.stringify(a) }
626
+ const args = typeof a === "string" ? a : JSON.stringify(a)
627
+ if (!name && index === null && !tc?.id && !args) return null
628
+ return { id: tc?.id || tc?.tool_call_id || "", index, name: String(name), arguments: args }
581
629
  }
582
630
 
583
631
  // NativeCalls puts together the tool calls Trae streams: a call comes in
@@ -594,6 +642,12 @@ class NativeCalls {
594
642
  let o = this.calls.find((x) => (c.id && x.id === c.id) || (!c.id && c.index !== null && x.index === c.index))
595
643
  if (!o && !c.id && c.index === null)
596
644
  o = this.calls.findLast((x) => x.name === c.name && (x.arguments === c.arguments || (!done(x.arguments) && c.arguments.startsWith(x.arguments))))
645
+ // a piece with nothing to say whose it is (or an index its call's
646
+ // first event didn't give) belongs to the call still being written
647
+ if (!o && !c.name && !c.id) {
648
+ o = this.calls.findLast((x) => !done(x.arguments))
649
+ if (o && c.index !== null && o.index !== null && o.index !== c.index) o = null
650
+ }
597
651
  if (!o) {
598
652
  if (!c.name) return
599
653
  this.calls.push({ ...c })
@@ -608,7 +662,10 @@ class NativeCalls {
608
662
  else o.arguments = prev + next // a piece
609
663
  }
610
664
  take() {
611
- return this.calls.filter((c) => c.name).map(({ id, name, arguments: a }) => ({ id: id || callId(), name, arguments: a || "{}" }))
665
+ return this.calls.filter((c) => c.name).map(({ id, name, arguments: a }) => {
666
+ const v = a && !done(a) ? looseJSON(a) : null
667
+ return { id: id || callId(), name, arguments: v ? JSON.stringify(v) : a || "{}" }
668
+ })
612
669
  }
613
670
  }
614
671
 
@@ -1154,4 +1211,4 @@ export const TraeCNAuthPlugin = async ({ client }) => {
1154
1211
  }
1155
1212
 
1156
1213
  // for tests
1157
- export const _internal = { HOSTS, MODELS, TextTools, traeMessages, chatBody, credits, whenOf, newDevice }
1214
+ export const _internal = { HOSTS, MODELS, TextTools, NativeCalls, looseJSON, traeMessages, chatBody, credits, whenOf, newDevice }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@magpie-community/opencode-trae-auth",
3
- "version": "0.1.9",
3
+ "version": "0.1.10",
4
4
  "description": "OpenCode provider plugin for Trae CN (trae.cn): your Trae CN account's models, free tier included, with Trae's own browser sign-in",
5
5
  "type": "module",
6
6
  "main": "./index.mjs",