larkway 0.3.25 → 0.3.26
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 +1 -1
- package/README.zh.md +1 -1
- package/dist/main.js +89 -53
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
You @ the bot in a Feishu thread. It runs on your machine — reading your real codebase, executing commands, opening MRs — and posts the result back. You define what the agent knows and what it can do. Larkway just carries the messages.
|
|
10
10
|
|
|
11
|
-
**Current release: v0.3.
|
|
11
|
+
**Current release: v0.3.26**
|
|
12
12
|
|
|
13
13
|
---
|
|
14
14
|
|
package/README.zh.md
CHANGED
package/dist/main.js
CHANGED
|
@@ -117684,12 +117684,14 @@ var AnswerChannelExtractor = class {
|
|
|
117684
117684
|
mode = "waiting";
|
|
117685
117685
|
buffer = "";
|
|
117686
117686
|
visibleText = "";
|
|
117687
|
+
lastSnapshotText = "";
|
|
117687
117688
|
ingestDelta(text, raw) {
|
|
117688
117689
|
if (!text || this.mode === "closed") return [];
|
|
117689
117690
|
this.buffer += text;
|
|
117690
117691
|
return this.drain(raw);
|
|
117691
117692
|
}
|
|
117692
117693
|
ingestSnapshot(text, raw) {
|
|
117694
|
+
this.lastSnapshotText = text;
|
|
117693
117695
|
const events = splitAnswerChannelText(text, raw);
|
|
117694
117696
|
const out = [];
|
|
117695
117697
|
for (const event of events) {
|
|
@@ -117697,13 +117699,30 @@ var AnswerChannelExtractor = class {
|
|
|
117697
117699
|
out.push(event);
|
|
117698
117700
|
continue;
|
|
117699
117701
|
}
|
|
117700
|
-
if (event.text === this.visibleText)
|
|
117702
|
+
if (event.text === this.visibleText) {
|
|
117703
|
+
if (text.includes(ANSWER_END_MARKER)) this.mode = "closed";
|
|
117704
|
+
continue;
|
|
117705
|
+
}
|
|
117701
117706
|
this.visibleText = event.text;
|
|
117702
117707
|
out.push(event);
|
|
117703
117708
|
if (text.includes(ANSWER_END_MARKER)) this.mode = "closed";
|
|
117704
117709
|
}
|
|
117705
117710
|
return out;
|
|
117706
117711
|
}
|
|
117712
|
+
ingestGrowingSnapshot(text, raw) {
|
|
117713
|
+
if (!text || this.mode === "closed") return [];
|
|
117714
|
+
if (this.lastSnapshotText && text.startsWith(this.lastSnapshotText)) {
|
|
117715
|
+
const delta = text.slice(this.lastSnapshotText.length);
|
|
117716
|
+
this.lastSnapshotText = text;
|
|
117717
|
+
return delta ? this.ingestDelta(delta, raw) : [];
|
|
117718
|
+
}
|
|
117719
|
+
if (this.lastSnapshotText === "") {
|
|
117720
|
+
this.lastSnapshotText = text;
|
|
117721
|
+
return this.ingestDelta(text, raw);
|
|
117722
|
+
}
|
|
117723
|
+
this.lastSnapshotText = text;
|
|
117724
|
+
return this.ingestSnapshot(text, raw);
|
|
117725
|
+
}
|
|
117707
117726
|
drain(raw) {
|
|
117708
117727
|
const events = [];
|
|
117709
117728
|
if (this.mode === "waiting") {
|
|
@@ -125748,7 +125767,7 @@ function* parseLinesMulti(line, answerExtractor = new AnswerChannelExtractor())
|
|
|
125748
125767
|
if (typeof item !== "object" || item === null) continue;
|
|
125749
125768
|
const block = item;
|
|
125750
125769
|
if (block["type"] === "text" && typeof block["text"] === "string") {
|
|
125751
|
-
yield* answerExtractor.
|
|
125770
|
+
yield* answerExtractor.ingestGrowingSnapshot(block["text"], obj);
|
|
125752
125771
|
emitted = true;
|
|
125753
125772
|
} else if (block["type"] === "tool_use") {
|
|
125754
125773
|
yield {
|
|
@@ -126060,64 +126079,80 @@ function buildCodexCommand(opts, codexBinPath = "codex") {
|
|
|
126060
126079
|
const freshFlags = opts.cwd != null ? ["-C", opts.cwd, ...commonFlags] : commonFlags;
|
|
126061
126080
|
return [codexBinPath, ["exec", ...freshFlags]];
|
|
126062
126081
|
}
|
|
126063
|
-
|
|
126064
|
-
|
|
126065
|
-
|
|
126066
|
-
|
|
126067
|
-
|
|
126068
|
-
obj
|
|
126069
|
-
|
|
126070
|
-
|
|
126071
|
-
|
|
126072
|
-
|
|
126073
|
-
|
|
126074
|
-
|
|
126075
|
-
|
|
126076
|
-
|
|
126077
|
-
|
|
126078
|
-
|
|
126079
|
-
|
|
126080
|
-
|
|
126081
|
-
|
|
126082
|
-
|
|
126083
|
-
|
|
126084
|
-
|
|
126085
|
-
|
|
126086
|
-
|
|
126087
|
-
|
|
126088
|
-
|
|
126089
|
-
|
|
126090
|
-
|
|
126091
|
-
if (
|
|
126092
|
-
yield
|
|
126093
|
-
type: "tool_use",
|
|
126094
|
-
toolName: "shell",
|
|
126095
|
-
toolInput: { command: itemRecord["command"] },
|
|
126096
|
-
raw: obj
|
|
126097
|
-
};
|
|
126082
|
+
var CodexLineParser = class {
|
|
126083
|
+
answerExtractor = new AnswerChannelExtractor();
|
|
126084
|
+
*parseLine(line) {
|
|
126085
|
+
const trimmed = line.trim();
|
|
126086
|
+
if (trimmed === "") return;
|
|
126087
|
+
let obj;
|
|
126088
|
+
try {
|
|
126089
|
+
obj = JSON.parse(trimmed);
|
|
126090
|
+
} catch {
|
|
126091
|
+
yield { type: "raw", raw: trimmed };
|
|
126092
|
+
return;
|
|
126093
|
+
}
|
|
126094
|
+
if (typeof obj !== "object" || obj === null) {
|
|
126095
|
+
yield { type: "raw", raw: obj };
|
|
126096
|
+
return;
|
|
126097
|
+
}
|
|
126098
|
+
const record = obj;
|
|
126099
|
+
const topType = record["type"];
|
|
126100
|
+
if (topType === "thread.started" && typeof record["thread_id"] === "string") {
|
|
126101
|
+
yield { type: "system_init", sessionId: record["thread_id"], raw: obj };
|
|
126102
|
+
return;
|
|
126103
|
+
}
|
|
126104
|
+
if (topType === "turn.completed") {
|
|
126105
|
+
yield { type: "result", stopReason: "end_turn", raw: obj };
|
|
126106
|
+
return;
|
|
126107
|
+
}
|
|
126108
|
+
const agentMessageText = agentMessageTextFrom(record);
|
|
126109
|
+
if (agentMessageText !== void 0) {
|
|
126110
|
+
if (topType === "item.completed") {
|
|
126111
|
+
yield* this.answerExtractor.ingestSnapshot(agentMessageText, obj);
|
|
126098
126112
|
return;
|
|
126099
126113
|
}
|
|
126114
|
+
yield* this.answerExtractor.ingestGrowingSnapshot(agentMessageText, obj);
|
|
126115
|
+
return;
|
|
126100
126116
|
}
|
|
126101
|
-
|
|
126102
|
-
|
|
126103
|
-
|
|
126104
|
-
|
|
126105
|
-
|
|
126106
|
-
|
|
126107
|
-
|
|
126108
|
-
|
|
126109
|
-
|
|
126110
|
-
|
|
126117
|
+
if (topType === "item.started") {
|
|
126118
|
+
const item = record["item"];
|
|
126119
|
+
if (typeof item === "object" && item !== null) {
|
|
126120
|
+
const itemRecord = item;
|
|
126121
|
+
if (itemRecord["type"] === "command_execution" && typeof itemRecord["command"] === "string") {
|
|
126122
|
+
yield {
|
|
126123
|
+
type: "tool_use",
|
|
126124
|
+
toolName: "shell",
|
|
126125
|
+
toolInput: { command: itemRecord["command"] },
|
|
126126
|
+
raw: obj
|
|
126127
|
+
};
|
|
126128
|
+
return;
|
|
126129
|
+
}
|
|
126111
126130
|
}
|
|
126112
|
-
|
|
126113
|
-
|
|
126114
|
-
|
|
126131
|
+
yield { type: "raw", raw: obj };
|
|
126132
|
+
return;
|
|
126133
|
+
}
|
|
126134
|
+
if (topType === "item.completed") {
|
|
126135
|
+
const item = record["item"];
|
|
126136
|
+
if (typeof item === "object" && item !== null) {
|
|
126137
|
+
const itemRecord = item;
|
|
126138
|
+
if (itemRecord["type"] === "command_execution") {
|
|
126139
|
+
yield { type: "tool_result", raw: obj };
|
|
126140
|
+
return;
|
|
126141
|
+
}
|
|
126115
126142
|
}
|
|
126143
|
+
yield { type: "raw", raw: obj };
|
|
126144
|
+
return;
|
|
126116
126145
|
}
|
|
126117
126146
|
yield { type: "raw", raw: obj };
|
|
126118
|
-
return;
|
|
126119
126147
|
}
|
|
126120
|
-
|
|
126148
|
+
};
|
|
126149
|
+
function agentMessageTextFrom(record) {
|
|
126150
|
+
const item = record["item"];
|
|
126151
|
+
if (typeof item !== "object" || item === null) return void 0;
|
|
126152
|
+
const itemRecord = item;
|
|
126153
|
+
if (itemRecord["type"] !== "agent_message") return void 0;
|
|
126154
|
+
const text = itemRecord["text"];
|
|
126155
|
+
return typeof text === "string" ? text : void 0;
|
|
126121
126156
|
}
|
|
126122
126157
|
function runCodex(opts, codexBinPath = "codex") {
|
|
126123
126158
|
const timeoutMs = opts.timeoutMs ?? 15 * 60 * 1e3;
|
|
@@ -126242,9 +126277,10 @@ stderr: ${stderr}` : "")
|
|
|
126242
126277
|
crlfDelay: Infinity,
|
|
126243
126278
|
signal: rlAbortController.signal
|
|
126244
126279
|
});
|
|
126280
|
+
const parser = new CodexLineParser();
|
|
126245
126281
|
try {
|
|
126246
126282
|
for await (const line of rl) {
|
|
126247
|
-
for (const event of
|
|
126283
|
+
for (const event of parser.parseLine(line)) {
|
|
126248
126284
|
if (event.type === "system_init") {
|
|
126249
126285
|
discoveredSessionId = event.sessionId;
|
|
126250
126286
|
}
|