@zhongqian97-code/ecode 0.5.42 → 0.5.44

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 CHANGED
@@ -53,6 +53,31 @@ Priority: **env vars > config file > defaults**
53
53
 
54
54
  **`dangerousPatterns`** — list of command prefixes that require double confirmation. Setting this field replaces the entire default list.
55
55
 
56
+ ### Multi-provider config
57
+
58
+ Configure multiple providers and switch between them:
59
+
60
+ ```json
61
+ {
62
+ "defaultProvider": "anthropic",
63
+ "providers": {
64
+ "anthropic": {
65
+ "baseUrl": "https://api.anthropic.com",
66
+ "apiKey": "sk-ant-...",
67
+ "model": "claude-sonnet-4-6",
68
+ "apiFormat": "anthropic"
69
+ },
70
+ "deepseek": {
71
+ "baseUrl": "https://api.deepseek.com/v1",
72
+ "apiKey": "sk-...",
73
+ "model": "deepseek-chat"
74
+ }
75
+ }
76
+ }
77
+ ```
78
+
79
+ **`apiFormat`** — set to `"anthropic"` to use the native Anthropic Messages API. Auto-detected when `baseUrl` contains `"anthropic"`; required for Anthropic-compatible endpoints with custom URLs.
80
+
56
81
  ### Using with other providers
57
82
 
58
83
  ```bash
@@ -62,8 +87,8 @@ export ECODE_API_KEY=sk-...
62
87
  export ECODE_MODEL=deepseek-chat
63
88
  ecode
64
89
 
65
- # Anthropic Claude (via proxy or compatible gateway)
66
- export ECODE_BASE_URL=https://your-openai-proxy/v1
90
+ # Anthropic Claude (native API no proxy needed)
91
+ export ECODE_BASE_URL=https://api.anthropic.com
67
92
  export ECODE_API_KEY=sk-ant-...
68
93
  export ECODE_MODEL=claude-sonnet-4-6
69
94
  ecode
@@ -279,7 +279,7 @@ function createAnthropicProvider(profile) {
279
279
  }
280
280
  async function* streamAnthropicResponse(profile, messages, tools, signal) {
281
281
  const { system, anthropicMessages } = convertMessagesToAnthropic(messages);
282
- const endpointUrl = new URL2(`${profile.baseUrl.replace(/\/$/, "")}/v1/messages`);
282
+ const endpointUrl = new URL2(`${profile.baseUrl.replace(/\/v1\/?$/, "").replace(/\/$/, "")}/v1/messages`);
283
283
  const requestBody = {
284
284
  model: profile.model,
285
285
  max_tokens: 8192,
@@ -1203,6 +1203,19 @@ async function webFetch(params) {
1203
1203
  // src/logger.ts
1204
1204
  import * as fs4 from "fs";
1205
1205
  import * as path3 from "path";
1206
+ function createLoggerAtPath(filePath) {
1207
+ return {
1208
+ filePath,
1209
+ append(entry) {
1210
+ try {
1211
+ fs4.appendFileSync(filePath, JSON.stringify(entry) + "\n");
1212
+ } catch (err) {
1213
+ process.stderr.write(`[logger] Failed to write log entry: ${err}
1214
+ `);
1215
+ }
1216
+ }
1217
+ };
1218
+ }
1206
1219
  function createLogger(logDir, sessionStart) {
1207
1220
  fs4.mkdirSync(logDir, { recursive: true });
1208
1221
  const filename = sessionStart.toISOString().replace(/:/g, "-").replace(/\..+/, "") + ".jsonl";
@@ -2152,6 +2165,7 @@ export {
2152
2165
  grepFiles,
2153
2166
  WEB_FETCH_TOOL,
2154
2167
  webFetch,
2168
+ createLoggerAtPath,
2155
2169
  createLogger,
2156
2170
  DEFAULT_SYSTEM_PROMPT,
2157
2171
  classifyCommand,
package/dist/index.js CHANGED
@@ -22,6 +22,7 @@ import {
22
22
  applyPatch,
23
23
  classifyCommand,
24
24
  createLogger,
25
+ createLoggerAtPath,
25
26
  createProvider,
26
27
  editFile,
27
28
  executeBash,
@@ -34,7 +35,7 @@ import {
34
35
  todo,
35
36
  webFetch,
36
37
  writeFile
37
- } from "./chunk-7RQ4D4K6.js";
38
+ } from "./chunk-I4VLKL2I.js";
38
39
  import {
39
40
  createSessionMetadata,
40
41
  generateTitle,
@@ -335,7 +336,9 @@ var SessionRuntime = class {
335
336
  this.llm = opts.llm ?? createProvider(resolveActiveProfile(config2));
336
337
  this.model = config2.model;
337
338
  this.autoApproveNormal = opts.autoApproveNormal ?? false;
338
- if (config2.logDir) {
339
+ if (opts.logFilePath) {
340
+ this.logger = createLoggerAtPath(opts.logFilePath);
341
+ } else if (config2.logDir) {
339
342
  this.logger = createLogger(config2.logDir, /* @__PURE__ */ new Date());
340
343
  const meta = createSessionMetadata(this.logger.filePath, this.model, this.id);
341
344
  writeSessionMetadata(this.logger.filePath, meta);
@@ -811,7 +814,7 @@ if (rawArgs[0] === "web") {
811
814
  webAutoApprove = true;
812
815
  }
813
816
  }
814
- const { buildServer, generateAccessToken } = await import("./web-YRH6C6ID.js");
817
+ const { buildServer, generateAccessToken } = await import("./web-ONRJYFTB.js");
815
818
  const token = finalConfig.webToken ?? generateAccessToken();
816
819
  const manager = new SessionManager(finalConfig);
817
820
  const __webDirname = dirname(fileURLToPath(import.meta.url));
@@ -920,6 +923,6 @@ Node.js 16/18 \u8BF7\u4F7F\u7528 --web \u6216 --pipe \u6A21\u5F0F\u3002
920
923
  );
921
924
  process.exit(1);
922
925
  }
923
- const { App, React, render } = await import("./ui-FGG6SNSS.js");
926
+ const { App, React, render } = await import("./ui-3K5WAFNO.js");
924
927
  render(React.createElement(App, { config: finalConfig, version: VERSION, autoMode, registry, trustedSkillDirs, initialMessages }));
925
928
  }
@@ -26,7 +26,7 @@ import {
26
26
  todo,
27
27
  webFetch,
28
28
  writeFile
29
- } from "./chunk-7RQ4D4K6.js";
29
+ } from "./chunk-I4VLKL2I.js";
30
30
  import {
31
31
  handleSkillInput,
32
32
  loadJobs,
@@ -1681,7 +1681,7 @@ async function chatRoutes(app, opts) {
1681
1681
  const logFilePath = join2(opts.config.logDir, session.logFile);
1682
1682
  const initialMessages = loadMessagesFromJsonl(logFilePath);
1683
1683
  try {
1684
- await manager.createSession({ sessionId: id, initialMessages });
1684
+ await manager.createSession({ sessionId: id, initialMessages, logFilePath });
1685
1685
  return reply.send({ success: true, resumed: true });
1686
1686
  } catch (err) {
1687
1687
  const msg = err instanceof Error ? err.message : String(err);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zhongqian97-code/ecode",
3
- "version": "0.5.42",
3
+ "version": "0.5.44",
4
4
  "description": "A minimal Claude Code clone with REPL interface and bash tool calling",
5
5
  "type": "module",
6
6
  "author": "zhongqian97-code",