@zhongqian97-code/ecode 0.5.4 → 0.5.5

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/dist/index.js +38 -11
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -149,14 +149,10 @@ function createOpenAIProvider(profile) {
149
149
  return {
150
150
  [Symbol.asyncIterator]: async function* () {
151
151
  let thinkPhase = "pre";
152
- let afterReasoningDetails = false;
152
+ let scanningForClose = false;
153
+ let closeSearchBuffer = "";
153
154
  function processContent(raw) {
154
155
  if (!raw) return { text: "", thinking: "" };
155
- if (afterReasoningDetails) {
156
- afterReasoningDetails = false;
157
- thinkPhase = "post";
158
- return { text: raw.startsWith("</think>") ? raw.slice(8) : raw, thinking: "" };
159
- }
160
156
  if (thinkPhase === "post") return { text: raw, thinking: "" };
161
157
  if (thinkPhase === "pre") {
162
158
  if (raw.startsWith("<think>")) {
@@ -197,7 +193,7 @@ function createOpenAIProvider(profile) {
197
193
  reasoningAccumulator += delta.reasoning_content;
198
194
  }
199
195
  if (delta.reasoning_details && delta.reasoning_details.length > 0) {
200
- afterReasoningDetails = true;
196
+ scanningForClose = true;
201
197
  for (const rd of delta.reasoning_details) {
202
198
  const id = rd.id ?? "";
203
199
  const text = rd.text ?? "";
@@ -233,8 +229,29 @@ function createOpenAIProvider(profile) {
233
229
  }
234
230
  }
235
231
  const isLast = choice.finish_reason != null;
236
- const raw = delta.reasoning_details && delta.reasoning_details.length > 0 ? "" : delta.content ?? "";
237
- const { text: filteredText, thinking: thinkContent } = processContent(raw);
232
+ let rawToProcess;
233
+ if (delta.reasoning_details && delta.reasoning_details.length > 0) {
234
+ rawToProcess = "";
235
+ } else if (scanningForClose) {
236
+ closeSearchBuffer += delta.content ?? "";
237
+ const closeIdx = closeSearchBuffer.indexOf("</think>");
238
+ if (closeIdx !== -1) {
239
+ rawToProcess = closeSearchBuffer.slice(closeIdx + 8);
240
+ scanningForClose = false;
241
+ closeSearchBuffer = "";
242
+ thinkPhase = "post";
243
+ } else if (isLast) {
244
+ rawToProcess = closeSearchBuffer;
245
+ scanningForClose = false;
246
+ closeSearchBuffer = "";
247
+ thinkPhase = "post";
248
+ } else {
249
+ rawToProcess = "";
250
+ }
251
+ } else {
252
+ rawToProcess = delta.content ?? "";
253
+ }
254
+ const { text: filteredText, thinking: thinkContent } = processContent(rawToProcess);
238
255
  if (thinkContent) {
239
256
  reasoningAccumulator += thinkContent;
240
257
  }
@@ -3522,6 +3539,7 @@ var SkillRegistry = class {
3522
3539
  };
3523
3540
 
3524
3541
  // src/pipe.ts
3542
+ var PIPE_SYSTEM_PROMPT = "You are a helpful assistant running in headless pipe mode. You have access to read-only file tools (read, glob, grep). Answer concisely and accurately.";
3525
3543
  var PIPE_TOOLS = [READ_TOOL, GLOB_TOOL, GREP_TOOL];
3526
3544
  function emit(out, event) {
3527
3545
  out.write(JSON.stringify(event) + "\n");
@@ -3542,10 +3560,15 @@ async function executeToolCall(name, args) {
3542
3560
  return `Unknown tool: ${name}`;
3543
3561
  }
3544
3562
  async function runPipe(prompt, llm, out = process.stdout) {
3545
- const messages = [{ role: "user", content: prompt }];
3563
+ const messages = [
3564
+ { role: "system", content: PIPE_SYSTEM_PROMPT },
3565
+ { role: "user", content: prompt }
3566
+ ];
3546
3567
  while (true) {
3547
3568
  let assistantText = "";
3548
3569
  let lastUsage;
3570
+ let lastReasoning;
3571
+ let lastReasoningDetails;
3549
3572
  const toolCalls = [];
3550
3573
  for await (const chunk of llm.stream(messages, PIPE_TOOLS)) {
3551
3574
  if (chunk.text) {
@@ -3558,6 +3581,8 @@ async function runPipe(prompt, llm, out = process.stdout) {
3558
3581
  if (chunk.done) {
3559
3582
  if (chunk.toolCalls) toolCalls.push(...chunk.toolCalls);
3560
3583
  if (chunk.usage) lastUsage = chunk.usage;
3584
+ if (chunk.reasoning) lastReasoning = chunk.reasoning;
3585
+ if (chunk.reasoningDetails) lastReasoningDetails = chunk.reasoningDetails;
3561
3586
  }
3562
3587
  }
3563
3588
  if (toolCalls.length > 0) {
@@ -3568,7 +3593,9 @@ async function runPipe(prompt, llm, out = process.stdout) {
3568
3593
  id: tc.id,
3569
3594
  type: "function",
3570
3595
  function: { name: tc.name, arguments: tc.arguments }
3571
- }))
3596
+ })),
3597
+ ...lastReasoning ? { reasoning_content: lastReasoning } : {},
3598
+ ...lastReasoningDetails ? { reasoning_details: lastReasoningDetails } : {}
3572
3599
  });
3573
3600
  for (const tc of toolCalls) {
3574
3601
  emit(out, { type: "tool_call", id: tc.id, name: tc.name, arguments: tc.arguments });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zhongqian97-code/ecode",
3
- "version": "0.5.4",
3
+ "version": "0.5.5",
4
4
  "description": "A minimal Claude Code clone with REPL interface and bash tool calling",
5
5
  "type": "module",
6
6
  "author": "zhongqian97-code",