@lark-codem/codem-cli 0.1.252 → 0.1.253
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.
|
|
3
|
+
"version": "0.1.253",
|
|
4
4
|
"codemServiceManagementProtocol": 3,
|
|
5
5
|
"codemProfileProtocol": 1,
|
|
6
6
|
"type": "module",
|
|
@@ -29,17 +29,17 @@
|
|
|
29
29
|
"access": "public"
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@lark-codem/codem-core": "0.8.
|
|
32
|
+
"@lark-codem/codem-core": "0.8.79",
|
|
33
33
|
"zod": "3.25.76",
|
|
34
|
-
"@lark-codem/lark-cli": "0.1.1
|
|
34
|
+
"@lark-codem/lark-cli": "0.1.1"
|
|
35
35
|
},
|
|
36
36
|
"optionalDependencies": {
|
|
37
|
-
"@lark-codem/codem-cli-darwin-arm64": "0.1.
|
|
38
|
-
"@lark-codem/codem-cli-darwin-x64": "0.1.
|
|
39
|
-
"@lark-codem/codem-cli-linux-arm64": "0.1.
|
|
40
|
-
"@lark-codem/codem-cli-linux-x64": "0.1.
|
|
41
|
-
"@lark-codem/codem-cli-win32-arm64": "0.1.
|
|
42
|
-
"@lark-codem/codem-cli-win32-x64": "0.1.
|
|
37
|
+
"@lark-codem/codem-cli-darwin-arm64": "0.1.253",
|
|
38
|
+
"@lark-codem/codem-cli-darwin-x64": "0.1.253",
|
|
39
|
+
"@lark-codem/codem-cli-linux-arm64": "0.1.253",
|
|
40
|
+
"@lark-codem/codem-cli-linux-x64": "0.1.253",
|
|
41
|
+
"@lark-codem/codem-cli-win32-arm64": "0.1.253",
|
|
42
|
+
"@lark-codem/codem-cli-win32-x64": "0.1.253"
|
|
43
43
|
},
|
|
44
44
|
"engines": {
|
|
45
45
|
"node": ">=18"
|
|
@@ -30,5 +30,8 @@ export class CredentialStorageError extends Error {
|
|
|
30
30
|
|
|
31
31
|
export function isRecoverableCredentialState(error) {
|
|
32
32
|
return error?.code === "credential_storage_rotation_pending"
|
|
33
|
-
|| error?.code === "credential_storage_rotation_unknown"
|
|
33
|
+
|| error?.code === "credential_storage_rotation_unknown"
|
|
34
|
+
// A missing OAuth record permits reauthorization with the existing device,
|
|
35
|
+
// never use of its stale plaintext mirror or another credential kind.
|
|
36
|
+
|| (error?.code === "credential_storage_missing" && error.kind === "oauth");
|
|
34
37
|
}
|
package/profile/runtime-logs.js
CHANGED
|
@@ -10,7 +10,28 @@ const CAPACITY = 256;
|
|
|
10
10
|
const BATCH_SIZE = 32;
|
|
11
11
|
const INTERVAL_MS = 10_000;
|
|
12
12
|
const REQUEST_TIMEOUT_MS = 3_000;
|
|
13
|
+
const OBSERVATION_EVENTS = new Set(["command_delivery_observed", "command_admission", "runtime_capability_probe", "command_ack", "command_observation_closed", "diagnostic_reporter_health"]);
|
|
14
|
+
const OBSERVATION_DIMENSIONS = {
|
|
15
|
+
phase: ["resolve_binary", "build_env", "host_capabilities", "parse_capabilities", "strict_resume", "verify_binding", "prepare", "persist_state", "trusted_device", "request", "validate_response", "apply_response"],
|
|
16
|
+
reason: ["runtime_unavailable", "runtime_environment_failed", "capability_probe_failed", "runtime_binary_changed", "strict_resume_unsupported", "turn_context_unsupported", "active_run_protocol_mismatch", "trusted_device_blocked", "shutting_down_handoff", "handoff_target_not_active", "duplicate_inflight", "handler_inflight", "prepare_exception_unknown", "capacity", "stopped", "replaced", "scope_changed", "queue_removed", "local_rejected"],
|
|
17
|
+
command_type: ["agent.run", "agent.steer", "agent.stop", "task.assign", "task.stop", "artifact.relay.read", "artifact.convert_to_lark_resource", "artifact.download", "directory.list", "git.preview", "workflow.preview"],
|
|
18
|
+
actor_type: ["device", "sandbox"],
|
|
19
|
+
ack_status: ["accepted", "ignored_duplicate", "rejected"],
|
|
20
|
+
ack_outcome: ["accepted", "duplicate", "rejected", "conflicting"],
|
|
21
|
+
readback_scope: ["command", "delivery", "unmatched"],
|
|
22
|
+
timing_origin: ["observed", "restored_unknown"]
|
|
23
|
+
};
|
|
24
|
+
const OBSERVATION_METRICS = {
|
|
25
|
+
command_delivery_observed: ["attempt_delta", "suppressed_count"],
|
|
26
|
+
command_admission: ["attempt_delta", "suppressed_count", "deferred_age_ms", "deferred_duration_ms"],
|
|
27
|
+
runtime_capability_probe: ["probe_duration_ms"],
|
|
28
|
+
command_ack: ["attempt_delta", "suppressed_count", "ack_queue_wait_ms", "ack_settle_duration_ms", "pending_ack_age_ms", "pending_command_ack_count", "pending_ack_unknown_age_count"],
|
|
29
|
+
command_observation_closed: ["omitted_detail_count", "pending_command_ack_count", "deferred_count"],
|
|
30
|
+
diagnostic_reporter_health: ["dropped_delta", "upload_failure_delta", "pending_event_count"]
|
|
31
|
+
};
|
|
32
|
+
const EXTRA_FIELDS = ["observation_id", "runtime_client_instance_id", "command_id", "delivery_id", "probe_id", "sync_id", "transport_request_id"];
|
|
13
33
|
const STRING_FIELDS = new Set([
|
|
34
|
+
...EXTRA_FIELDS, "command_type", "ack_status", "ack_outcome", "readback_scope", "timing_origin", "required_capability",
|
|
14
35
|
"request_id", "command_id", "session_id", "task_id", "dispatch_id", "event_id", "sync_id",
|
|
15
36
|
"process_instance_id", "run_id", "stage", "phase", "status", "outcome", "reason", "action",
|
|
16
37
|
"error_class", "error_code", "error_kind", "error_type", "code", "signal", "stop_reason",
|
|
@@ -19,6 +40,7 @@ const STRING_FIELDS = new Set([
|
|
|
19
40
|
"failure_kind", "failure_impact", "failure_type", "failure_subtype", "failure_code", "failure_status", "delay_source", "mode", "provider", "name", "termination", "interaction_id", "interaction_kind", "owner_state", "artifact_id", "resource_type", "delivery_mode", "host", "scheme", "tool_call_id", "tool_name", "background_task_id", "model", "artifact_kind", "codem_user_id", "device_id", "operation", "foreground_error_code"
|
|
20
41
|
]);
|
|
21
42
|
const VALUE_FIELDS = new Set([
|
|
43
|
+
...new Set(Object.values(OBSERVATION_METRICS).flat()),
|
|
22
44
|
"pid", "exit_code", "duration_ms", "elapsed_ms", "wait_ms", "run_ms", "total_ms", "took_ms",
|
|
23
45
|
"attempt", "attempts", "attempt_count", "retryable", "http_status", "active_task_count",
|
|
24
46
|
"pending_event_count", "pending_command_ack_count", "next_retry_ms", "consecutive_failures",
|
|
@@ -40,6 +62,16 @@ function optional(read) {
|
|
|
40
62
|
try { return read(); } catch { return undefined; }
|
|
41
63
|
}
|
|
42
64
|
|
|
65
|
+
function metricProjection(event, fields = {}) {
|
|
66
|
+
return { count: 1, ...Object.fromEntries((OBSERVATION_METRICS[event] ?? [])
|
|
67
|
+
.filter(key => typeof fields?.[key] === "number" && Number.isFinite(fields[key]) && fields[key] >= 0)
|
|
68
|
+
.map(key => [key, fields[key]])) };
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function extraProjection(fields = {}) {
|
|
72
|
+
return Object.fromEntries(EXTRA_FIELDS.filter(key => token(fields?.[key])).map(key => [key, token(fields[key])]));
|
|
73
|
+
}
|
|
74
|
+
|
|
43
75
|
function projectFields(input) {
|
|
44
76
|
const result = {};
|
|
45
77
|
for (const [key, value] of Object.entries(input ?? {}).slice(0, 100)) {
|
|
@@ -52,6 +84,8 @@ function projectFields(input) {
|
|
|
52
84
|
}
|
|
53
85
|
}
|
|
54
86
|
const error = input?.error ?? input?.terminalError;
|
|
87
|
+
const fingerprint = input?.error_fingerprint ?? input?.errorFingerprint;
|
|
88
|
+
if (typeof fingerprint === "string" && /^[a-f0-9]{24}$/u.test(fingerprint)) result.error_fingerprint = fingerprint;
|
|
55
89
|
const terminal = input?.terminalError ?? error?.terminalError;
|
|
56
90
|
if (terminal && typeof terminal === "object") {
|
|
57
91
|
if (token(terminal.code)) result.error_code = token(terminal.code);
|
|
@@ -90,6 +124,10 @@ export class RuntimeLogReporter {
|
|
|
90
124
|
#timer;
|
|
91
125
|
#closed = false;
|
|
92
126
|
#dropped = 0;
|
|
127
|
+
#uploadFailures = 0;
|
|
128
|
+
#reportedDrops = 0;
|
|
129
|
+
#reportedFailures = 0;
|
|
130
|
+
#lastHealthAt = Date.now();
|
|
93
131
|
#send;
|
|
94
132
|
#role;
|
|
95
133
|
#version;
|
|
@@ -144,7 +182,7 @@ export class RuntimeLogReporter {
|
|
|
144
182
|
if (fs.lstatSync(file).isSymbolicLink() || fs.statSync(file).size > 65536) continue;
|
|
145
183
|
const entry = JSON.parse(fs.readFileSync(file, "utf8"));
|
|
146
184
|
if (entry?.record?.category?.reporter !== "codem_js" || entry?.record?.log_type !== "log" || !entry.header) continue;
|
|
147
|
-
this.#replay.queue.push({ header: entry.header, record: entry.record, attempts: 0, crashFile: file });
|
|
185
|
+
this.#replay.queue.push({ header: entry.header, record: entry.record, metrics: metricProjection(entry.record.category.event, entry.metrics), extra: extraProjection(entry.extra), attempts: 0, crashFile: file });
|
|
148
186
|
} catch { /* A partial crash write cannot prevent startup. */ }
|
|
149
187
|
}
|
|
150
188
|
} catch { /* First startup or unavailable storage. */ }
|
|
@@ -169,12 +207,14 @@ export class RuntimeLogReporter {
|
|
|
169
207
|
|
|
170
208
|
get pendingCount() { return this.#live.queue.length + this.#replay.queue.length; }
|
|
171
209
|
get droppedCount() { return this.#dropped; }
|
|
210
|
+
get identityKey() { return JSON.stringify([this.#instanceId, this.#role, this.#identity.deviceId, this.#identity.userId, this.#identity.tenantId]); }
|
|
172
211
|
|
|
173
212
|
record(level, component, event, fields = {}) {
|
|
174
213
|
try {
|
|
175
214
|
if (this.#closed) return false;
|
|
176
215
|
let safeFields;
|
|
177
216
|
try { safeFields = projectFields(fields); } catch { safeFields = {}; }
|
|
217
|
+
if (OBSERVATION_EVENTS.has(event)) safeFields.observation_id = randomUUID();
|
|
178
218
|
const severity = ["info", "warn", "error", "fatal"].includes(level) ? level : "info";
|
|
179
219
|
const identity = { ...this.#identity };
|
|
180
220
|
const category = {
|
|
@@ -186,6 +226,11 @@ export class RuntimeLogReporter {
|
|
|
186
226
|
...(identity.serverEnvironment ? { server_environment: identity.serverEnvironment } : {}),
|
|
187
227
|
...Object.fromEntries(["stage", "error_class", "error_code", "error_kind", "outcome"].filter((key) => safeFields[key]).map((key) => [key, safeFields[key]]))
|
|
188
228
|
};
|
|
229
|
+
if (OBSERVATION_EVENTS.has(category.event)) {
|
|
230
|
+
for (const [key, values] of Object.entries(OBSERVATION_DIMENSIONS)) {
|
|
231
|
+
if (safeFields[key]) category[key] = values.includes(safeFields[key]) ? safeFields[key] : "unknown";
|
|
232
|
+
}
|
|
233
|
+
}
|
|
189
234
|
const header = {
|
|
190
235
|
aid: SLARDAR_PC_AID,
|
|
191
236
|
device_id: identity.deviceId ?? this.#instanceId,
|
|
@@ -207,17 +252,39 @@ export class RuntimeLogReporter {
|
|
|
207
252
|
log_type: "log", log_level: severity === "fatal" ? "error" : severity,
|
|
208
253
|
log_content: `CodeM diagnostic ${severity} ${category.component}/${category.event}\n${JSON.stringify(payload)}`
|
|
209
254
|
};
|
|
255
|
+
const priority = severity === "fatal" ? 3 :
|
|
256
|
+
["resumed", "settled"].includes(safeFields.stage) || (severity === "error" && !safeFields.suppressed_count) ? 2 :
|
|
257
|
+
severity === "info" ? 0 : 1;
|
|
210
258
|
if (this.#live.queue.length >= CAPACITY) {
|
|
211
|
-
const
|
|
212
|
-
|
|
259
|
+
const minimum = Math.min(...this.#live.queue.map(entry => entry.priority ?? (entry.record.log_level === "info" ? 0 : 1)));
|
|
260
|
+
if (minimum > priority) { this.#dropped += 1; return false; }
|
|
261
|
+
const expendable = this.#live.queue.findIndex(entry => (entry.priority ?? (entry.record.log_level === "info" ? 0 : 1)) === minimum);
|
|
262
|
+
this.#live.queue.splice(expendable, 1);
|
|
213
263
|
this.#dropped += 1;
|
|
214
264
|
}
|
|
215
|
-
this.#live.queue.push({ header, record, attempts: 0 });
|
|
265
|
+
this.#live.queue.push({ header, record, metrics: metricProjection(category.event, safeFields), extra: extraProjection(safeFields), priority, attempts: 0 });
|
|
216
266
|
return true;
|
|
217
267
|
} catch { return false; }
|
|
218
268
|
}
|
|
219
269
|
|
|
220
270
|
async flush({ timeoutMs = REQUEST_TIMEOUT_MS } = {}) {
|
|
271
|
+
// Counters only in the failure path: never recursively log an upload error.
|
|
272
|
+
if (Date.now() - this.#lastHealthAt >= 60_000 && (this.#dropped !== this.#reportedDrops || this.#uploadFailures !== this.#reportedFailures)) {
|
|
273
|
+
this.#lastHealthAt = Date.now();
|
|
274
|
+
const dropped = this.#dropped;
|
|
275
|
+
const failures = this.#uploadFailures;
|
|
276
|
+
const queued = this.record("warn", "runtime-post", "diagnostic_reporter_health", {
|
|
277
|
+
dropped_delta: dropped - this.#reportedDrops,
|
|
278
|
+
upload_failure_delta: failures - this.#reportedFailures,
|
|
279
|
+
pending_event_count: this.pendingCount
|
|
280
|
+
});
|
|
281
|
+
// The health record can itself evict an entry or be refused by a full
|
|
282
|
+
// higher-priority queue. Neither loss has been included in this snapshot.
|
|
283
|
+
if (queued) {
|
|
284
|
+
this.#reportedDrops = dropped;
|
|
285
|
+
this.#reportedFailures = failures;
|
|
286
|
+
}
|
|
287
|
+
}
|
|
221
288
|
const deadline = Date.now() + timeoutMs;
|
|
222
289
|
const live = this.#flushLane(this.#live, timeoutMs).then(() => {
|
|
223
290
|
// Cover records added after drain's last queue check but before its
|
|
@@ -262,10 +329,10 @@ export class RuntimeLogReporter {
|
|
|
262
329
|
const key = JSON.stringify(first.header);
|
|
263
330
|
const batch = [];
|
|
264
331
|
while (batch.length < BATCH_SIZE && lane.queue.length && JSON.stringify(lane.queue[0].header) === key && Boolean(lane.queue[0].crashFile) === Boolean(first.crashFile)) batch.push(lane.queue.shift());
|
|
265
|
-
const data = batch.flatMap(({ record }) => [record, {
|
|
332
|
+
const data = batch.flatMap(({ record, metrics, extra }) => [record, {
|
|
266
333
|
app_version: record.app_version, app_minor_version: "", build_id: "",
|
|
267
334
|
process_type: record.process_type, session_id: "", timestamp: record.timestamp,
|
|
268
|
-
log_type: "flexible", event_name: "codem_runtime_diagnostic", category: record.category, metrics: { count: 1 }
|
|
335
|
+
log_type: "flexible", event_name: "codem_runtime_diagnostic", category: record.category, metrics: metrics ?? { count: 1 }, ...(extra ? { extra } : {})
|
|
269
336
|
}]);
|
|
270
337
|
try {
|
|
271
338
|
await Promise.race([Promise.resolve().then(() => this.#send({ header: first.header, data }, { signal: controller.signal })), deadline]);
|
|
@@ -273,6 +340,7 @@ export class RuntimeLogReporter {
|
|
|
273
340
|
if (entry.crashFile) { try { fs.unlinkSync(entry.crashFile); } catch { /* Replay may duplicate after a crash or concurrent startup. */ } }
|
|
274
341
|
}
|
|
275
342
|
} catch {
|
|
343
|
+
this.#uploadFailures += 1;
|
|
276
344
|
// One later retry, on the regular interval. Bound both memory and work;
|
|
277
345
|
// an unavailable collector must not create a retry loop or block exit.
|
|
278
346
|
for (const entry of batch) {
|
|
@@ -303,6 +371,9 @@ export class RuntimeLogReporter {
|
|
|
303
371
|
|
|
304
372
|
let active;
|
|
305
373
|
|
|
374
|
+
export function runtimeLogsEnabled() { return Boolean(active); }
|
|
375
|
+
export function runtimeLogIdentityKey() { return active?.identityKey; }
|
|
376
|
+
|
|
306
377
|
export function startRuntimeLogs({ role, version, env = process.env, send } = {}) {
|
|
307
378
|
try {
|
|
308
379
|
if (active || /^(1|true|yes)$/iu.test(env.CODEM_TELEMETRY_DISABLED ?? "") || env.NODE_TEST_CONTEXT) return;
|