sakuraai 0.0.3 → 0.0.4
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/dist/index.js +65 -21
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -379,16 +379,16 @@ function findFile(sessionId) {
|
|
|
379
379
|
}
|
|
380
380
|
function readMessages(file) {
|
|
381
381
|
const msgs = [];
|
|
382
|
-
let
|
|
382
|
+
let lastUserSecs = null;
|
|
383
383
|
for (const entry of jsonlEntries(file)) {
|
|
384
384
|
if (entry?.isSidechain === true) continue;
|
|
385
385
|
const tsStr = entry?.timestamp ?? "";
|
|
386
386
|
const tsSecs = parseIsoUnix(tsStr);
|
|
387
|
-
if (startSecs == null) startSecs = tsSecs;
|
|
388
387
|
if (entry?.type === "user") {
|
|
389
388
|
if (entry?.userType !== "external") continue;
|
|
390
389
|
const text = extractTextFromContent(entry?.message?.content);
|
|
391
390
|
if (text) {
|
|
391
|
+
lastUserSecs = tsSecs;
|
|
392
392
|
msgs.push({
|
|
393
393
|
id: entry?.uuid ?? "",
|
|
394
394
|
role: "user",
|
|
@@ -400,15 +400,16 @@ function readMessages(file) {
|
|
|
400
400
|
} else if (entry?.type === "assistant") {
|
|
401
401
|
const { text, hasTools } = extractAssistantText(entry?.message?.content);
|
|
402
402
|
if (!text) continue;
|
|
403
|
-
const
|
|
404
|
-
const
|
|
403
|
+
const u = entry?.message?.usage;
|
|
404
|
+
const total = (u?.input_tokens ?? 0) + (u?.cache_read_input_tokens ?? 0) + (u?.cache_creation_input_tokens ?? 0);
|
|
405
|
+
const elapsed = lastUserSecs != null && tsSecs != null ? Math.max(0, tsSecs - lastUserSecs) : void 0;
|
|
405
406
|
msgs.push({
|
|
406
407
|
id: entry?.uuid ?? "",
|
|
407
408
|
role: "assistant",
|
|
408
409
|
content: text,
|
|
409
410
|
timestamp: tsStr,
|
|
410
411
|
hasToolUse: hasTools,
|
|
411
|
-
inputTokens:
|
|
412
|
+
inputTokens: total > 0 ? total : void 0,
|
|
412
413
|
elapsedSecs: elapsed
|
|
413
414
|
});
|
|
414
415
|
}
|
|
@@ -431,31 +432,62 @@ function send(sessionId, message, onData) {
|
|
|
431
432
|
return new Promise((resolve) => {
|
|
432
433
|
const bin = process.env.CLAUDE_BIN || "claude";
|
|
433
434
|
const cwd = sessionCwd(sessionId);
|
|
434
|
-
const child = spawn(
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
435
|
+
const child = spawn(
|
|
436
|
+
bin,
|
|
437
|
+
[
|
|
438
|
+
"--resume",
|
|
439
|
+
sessionId,
|
|
440
|
+
"-p",
|
|
441
|
+
message,
|
|
442
|
+
"--output-format",
|
|
443
|
+
"stream-json",
|
|
444
|
+
"--include-partial-messages",
|
|
445
|
+
"--verbose"
|
|
446
|
+
],
|
|
447
|
+
{
|
|
448
|
+
cwd: cwd && fs3.existsSync(cwd) ? cwd : void 0,
|
|
449
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
450
|
+
}
|
|
451
|
+
);
|
|
452
|
+
let buf = "";
|
|
453
|
+
let finalText = "";
|
|
439
454
|
let err = "";
|
|
440
455
|
child.stdout.on("data", (d) => {
|
|
441
|
-
|
|
442
|
-
|
|
456
|
+
buf += d.toString();
|
|
457
|
+
let nl;
|
|
458
|
+
while ((nl = buf.indexOf("\n")) >= 0) {
|
|
459
|
+
const line = buf.slice(0, nl);
|
|
460
|
+
buf = buf.slice(nl + 1);
|
|
461
|
+
if (!line.trim()) continue;
|
|
462
|
+
try {
|
|
463
|
+
const delta = textDelta(JSON.parse(line));
|
|
464
|
+
if (delta) {
|
|
465
|
+
finalText += delta;
|
|
466
|
+
onData?.(delta);
|
|
467
|
+
}
|
|
468
|
+
} catch {
|
|
469
|
+
}
|
|
470
|
+
}
|
|
443
471
|
});
|
|
444
472
|
child.stderr.on("data", (d) => err += d.toString());
|
|
445
|
-
child.on(
|
|
446
|
-
"error",
|
|
447
|
-
(e) => resolve({ ok: false, output: "", error: e.message })
|
|
448
|
-
);
|
|
473
|
+
child.on("error", (e) => resolve({ ok: false, output: "", error: e.message }));
|
|
449
474
|
child.on(
|
|
450
475
|
"close",
|
|
451
476
|
(code) => resolve({
|
|
452
477
|
ok: code === 0,
|
|
453
|
-
output:
|
|
478
|
+
output: finalText.trim(),
|
|
454
479
|
error: code === 0 ? void 0 : err.trim() || `exited ${code}`
|
|
455
480
|
})
|
|
456
481
|
);
|
|
457
482
|
});
|
|
458
483
|
}
|
|
484
|
+
function textDelta(ev) {
|
|
485
|
+
const obj = ev?.type === "stream_event" ? ev.event : ev;
|
|
486
|
+
if (obj?.type === "content_block_delta" && obj?.delta?.type === "text_delta") {
|
|
487
|
+
return obj.delta.text ?? null;
|
|
488
|
+
}
|
|
489
|
+
return null;
|
|
490
|
+
}
|
|
459
491
|
var PROJECTS_DIR;
|
|
460
492
|
var init_claude = __esm({
|
|
461
493
|
"src/runtime/claude.ts"() {
|
|
@@ -540,6 +572,7 @@ function readMessages2(file) {
|
|
|
540
572
|
return [];
|
|
541
573
|
}
|
|
542
574
|
const msgs = [];
|
|
575
|
+
let lastUserSecs = null;
|
|
543
576
|
for (const line of content.split("\n")) {
|
|
544
577
|
if (!line.trim()) continue;
|
|
545
578
|
let entry;
|
|
@@ -559,7 +592,16 @@ function readMessages2(file) {
|
|
|
559
592
|
const text = part?.text ?? "";
|
|
560
593
|
if (!text) continue;
|
|
561
594
|
const ts = entry?.timestamp ?? "";
|
|
562
|
-
|
|
595
|
+
const tsSecs = parseIsoUnix(ts);
|
|
596
|
+
if (role === "user") lastUserSecs = tsSecs;
|
|
597
|
+
msgs.push({
|
|
598
|
+
id: ts,
|
|
599
|
+
role,
|
|
600
|
+
content: text,
|
|
601
|
+
timestamp: ts,
|
|
602
|
+
hasToolUse: false,
|
|
603
|
+
elapsedSecs: role === "assistant" && lastUserSecs != null && tsSecs != null ? Math.max(0, tsSecs - lastUserSecs) : void 0
|
|
604
|
+
});
|
|
563
605
|
}
|
|
564
606
|
return msgs;
|
|
565
607
|
}
|
|
@@ -683,8 +725,8 @@ async function messages3(sessionId) {
|
|
|
683
725
|
} catch {
|
|
684
726
|
}
|
|
685
727
|
}
|
|
686
|
-
const startMs = msgRows[0]?.time_created ?? 0;
|
|
687
728
|
const out = [];
|
|
729
|
+
let lastUserMs = null;
|
|
688
730
|
for (const m of msgRows) {
|
|
689
731
|
let v;
|
|
690
732
|
try {
|
|
@@ -697,13 +739,15 @@ async function messages3(sessionId) {
|
|
|
697
739
|
const text = (partsMap.get(m.id) ?? []).join("");
|
|
698
740
|
if (!text) continue;
|
|
699
741
|
const mtime = Math.floor(m.time_created / 1e3);
|
|
742
|
+
if (role === "user") lastUserMs = m.time_created;
|
|
700
743
|
out.push({
|
|
701
744
|
id: m.id,
|
|
702
745
|
role,
|
|
703
746
|
content: text,
|
|
704
747
|
timestamp: chronoIso(mtime),
|
|
705
748
|
hasToolUse: false,
|
|
706
|
-
|
|
749
|
+
// Per-turn duration: assistant time − the user msg that started it.
|
|
750
|
+
elapsedSecs: role === "assistant" && lastUserMs != null ? Math.max(0, Math.floor((m.time_created - lastUserMs) / 1e3)) : void 0
|
|
707
751
|
});
|
|
708
752
|
}
|
|
709
753
|
return out;
|
|
@@ -1746,7 +1790,7 @@ var init_pair = __esm({
|
|
|
1746
1790
|
import { Command } from "commander";
|
|
1747
1791
|
|
|
1748
1792
|
// src/version.ts
|
|
1749
|
-
var VERSION = "0.0.
|
|
1793
|
+
var VERSION = "0.0.4";
|
|
1750
1794
|
|
|
1751
1795
|
// src/index.ts
|
|
1752
1796
|
init_config();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sakuraai",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.4",
|
|
4
4
|
"description": "Sakura Agent CLI + local runtime for managing AI coding sessions (Claude Code, Codex, OpenCode) and reaching them privately from the Sakura mobile app over Tailscale",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|