@lark-codem/codem-cli 0.1.239 → 0.1.240

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lark-codem/codem-cli",
3
- "version": "0.1.239",
3
+ "version": "0.1.240",
4
4
  "codemServiceManagementProtocol": 3,
5
5
  "codemProfileProtocol": 1,
6
6
  "type": "module",
@@ -29,16 +29,16 @@
29
29
  "access": "public"
30
30
  },
31
31
  "dependencies": {
32
- "@lark-codem/codem-core": "0.8.71",
32
+ "@lark-codem/codem-core": "0.8.72",
33
33
  "zod": "3.25.76"
34
34
  },
35
35
  "optionalDependencies": {
36
- "@lark-codem/codem-cli-darwin-arm64": "0.1.239",
37
- "@lark-codem/codem-cli-darwin-x64": "0.1.239",
38
- "@lark-codem/codem-cli-linux-arm64": "0.1.239",
39
- "@lark-codem/codem-cli-linux-x64": "0.1.239",
40
- "@lark-codem/codem-cli-win32-arm64": "0.1.239",
41
- "@lark-codem/codem-cli-win32-x64": "0.1.239"
36
+ "@lark-codem/codem-cli-darwin-arm64": "0.1.240",
37
+ "@lark-codem/codem-cli-darwin-x64": "0.1.240",
38
+ "@lark-codem/codem-cli-linux-arm64": "0.1.240",
39
+ "@lark-codem/codem-cli-linux-x64": "0.1.240",
40
+ "@lark-codem/codem-cli-win32-arm64": "0.1.240",
41
+ "@lark-codem/codem-cli-win32-x64": "0.1.240"
42
42
  },
43
43
  "engines": {
44
44
  "node": ">=18"
@@ -11,10 +11,17 @@ export function credentialStorageRecovery(errorCode) {
11
11
  };
12
12
  }
13
13
 
14
+ // An interrupted rotation keeps its fence until the user explicitly re-logs in.
15
+ // Name that action wherever the raw error can still reach a terminal or log.
16
+ export const OAUTH_REAUTHORIZATION_HINT =
17
+ "上次 OAuth 刷新被中断,本机登录凭据需要重新建立。请运行 codem login 重新登录(设备身份会保留)";
18
+
14
19
  export class CredentialStorageError extends Error {
15
20
  constructor(code, kind = null) {
16
21
  const recovery = credentialStorageRecovery(code);
17
- super(`Credential storage ${code}${kind ? ` (${kind})` : ""}${recovery ? `。${recovery.message}。${recovery.hint}` : ""}`);
22
+ const rotation = kind === "oauth" && (code === "rotation_pending" || code === "rotation_unknown");
23
+ const suffix = recovery ? `。${recovery.message}。${recovery.hint}` : rotation ? `。${OAUTH_REAUTHORIZATION_HINT}。` : "";
24
+ super(`Credential storage ${code}${kind ? ` (${kind})` : ""}${suffix}`);
18
25
  this.name = "CredentialStorageError";
19
26
  this.code = `credential_storage_${code}`;
20
27
  this.kind = kind;
@@ -115,16 +115,25 @@ export class RuntimeLogReporter {
115
115
 
116
116
  // Crash files hold already-projected records and the identity at failure time.
117
117
  // Never await network IO in uncaughtExceptionMonitor. Replay is at-least-once.
118
- persistCrash(component, event, fields = {}) {
118
+ // deliverNow also queues the record for this process's next flush. A
119
+ // successful send deletes its file; otherwise the next process replays it.
120
+ persistCrash(component, event, fields = {}, { deliverNow = false } = {}) {
121
+ let entry;
122
+ let crashFile;
119
123
  try {
120
- if (!this.#crashDirectory || this.#closed) return;
124
+ if (this.#closed || (!this.#crashDirectory && !deliverNow)) return;
121
125
  if (!this.record("fatal", component, event, fields)) return;
122
- const entry = this.#live.queue.pop();
126
+ entry = this.#live.queue.pop();
127
+ if (!this.#crashDirectory) return;
123
128
  fs.mkdirSync(this.#crashDirectory, { recursive: true, mode: 0o700 });
124
129
  const names = fs.readdirSync(this.#crashDirectory).filter(name => /^js-[a-f0-9-]+\.json$/u.test(name));
125
130
  if (names.length >= 32) return;
126
- fs.writeFileSync(path.join(this.#crashDirectory, `js-${randomUUID()}.json`), JSON.stringify(entry), { flag: "wx", mode: 0o600 });
127
- } catch { /* Crash diagnostics must preserve the original exit behavior. */ }
131
+ const file = path.join(this.#crashDirectory, `js-${randomUUID()}.json`);
132
+ fs.writeFileSync(file, JSON.stringify(entry), { flag: "wx", mode: 0o600 });
133
+ crashFile = file;
134
+ } catch { /* Crash diagnostics must preserve the original exit behavior. */ } finally {
135
+ if (deliverNow && entry) this.#replay.queue.push({ ...entry, attempts: 0, ...(crashFile ? { crashFile } : {}) });
136
+ }
128
137
  }
129
138
 
130
139
  #restoreCrashes() {
@@ -318,6 +327,13 @@ export function persistRuntimeCrash(component, event, fields) {
318
327
  try { active?.persistCrash(component, event, fields); } catch { /* best effort */ }
319
328
  }
320
329
 
330
+ // A failure that ends a short-lived process: persist first, then try to deliver
331
+ // within one upload budget, so an immediate exit cannot lose the count.
332
+ export async function reportRuntimeFailure(component, event, fields = {}, budgetMs = 3_000) {
333
+ try { active?.persistCrash(component, event, fields, { deliverNow: true }); } catch { /* best effort */ }
334
+ await flushRuntimeLogs(budgetMs);
335
+ }
336
+
321
337
  export async function flushRuntimeLogs(budgetMs = 200) {
322
338
  if (!active) return;
323
339
  let timeout;