@nowcrew/daemon 0.6.71 → 0.6.72

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/dist/main.js CHANGED
File without changes
@@ -42,7 +42,7 @@ export function createStorageControlController(input) {
42
42
  ...extra,
43
43
  });
44
44
  const failure = (identity, errorCode, error, reopenAdmission = false, extra = {}) => {
45
- input.sendStatus(frame(identity, "failed", {
45
+ reportStatus(frame(identity, "failed", {
46
46
  errorCode,
47
47
  ...extra,
48
48
  ...(error === undefined ? {} : { errorMessage: safeError(error) }),
@@ -51,6 +51,14 @@ export function createStorageControlController(input) {
51
51
  : {}),
52
52
  }));
53
53
  };
54
+ const reportStatus = (statusFrame) => {
55
+ try {
56
+ input.sendStatus(statusFrame);
57
+ }
58
+ catch (error) {
59
+ input.onStatusError?.(error, statusFrame);
60
+ }
61
+ };
54
62
  const matchesIdentity = (identity) => identity.environment === environment && identity.workspaceId === workspaceId;
55
63
  const preflightKey = (identity) => `${identity.migrationId}\0${identity.environment}\0${identity.workspaceId}`;
56
64
  const runPreflight = (identity, failureFallback = "doctor_failed") => {
@@ -61,7 +69,7 @@ export function createStorageControlController(input) {
61
69
  const controller = new AbortController();
62
70
  let scannedEntries = 0;
63
71
  let timedOut = false;
64
- input.sendStatus(frame(identity, "preflight_running", {
72
+ reportStatus(frame(identity, "preflight_running", {
65
73
  progress: { state: "running", scannedEntries: 0 },
66
74
  }));
67
75
  const doctorPromise = Promise.resolve().then(() => input.runDoctor(identity.migrationId, {
@@ -70,7 +78,7 @@ export function createStorageControlController(input) {
70
78
  if (timedOut)
71
79
  return;
72
80
  scannedEntries = progress.scannedEntries;
73
- input.sendStatus(frame(identity, "preflight_running", {
81
+ reportStatus(frame(identity, "preflight_running", {
74
82
  progress: { state: "running", scannedEntries },
75
83
  }));
76
84
  },
@@ -101,7 +109,7 @@ export function createStorageControlController(input) {
101
109
  return null;
102
110
  }
103
111
  preflights.set(identity.migrationId, doctor);
104
- input.sendStatus(frame(identity, "preflight_passed", {
112
+ reportStatus(frame(identity, "preflight_passed", {
105
113
  sourceStorageFingerprint,
106
114
  targetStorageFingerprint,
107
115
  manifestDigest: doctor.manifestDigest,
@@ -177,7 +185,7 @@ export function createStorageControlController(input) {
177
185
  try {
178
186
  await input.runMigration(doctor, (status) => {
179
187
  if (StatusSchema.safeParse(status).success)
180
- input.sendStatus(frame(identity, status));
188
+ reportStatus(frame(identity, status));
181
189
  });
182
190
  appliedMigrationIds.add(identity.migrationId);
183
191
  }
@@ -121,6 +121,10 @@ function loadOutbox(path) {
121
121
  if (storageStatusEventId(delivered) !== delivered.eventId) {
122
122
  throw new Error("storage status outbox event identity mismatch");
123
123
  }
124
+ // Progress is telemetry, not a durable obligation. Older versions could
125
+ // leave hundreds of progress frames behind and starve terminal statuses.
126
+ if (delivered.status === "preflight_running")
127
+ continue;
124
128
  pending.set(delivered.eventId, delivered);
125
129
  }
126
130
  return pending;
@@ -157,6 +161,13 @@ export function createStorageStatusDelivery(input) {
157
161
  const eventId = frame.eventId ?? storageStatusEventId(frame);
158
162
  EventIdSchema.parse(eventId);
159
163
  const delivered = deliveredFrame({ ...frame, eventId });
164
+ // A large manifest can emit thousands of progress updates. Send the
165
+ // latest telemetry opportunistically without putting it in the bounded
166
+ // durable outbox; terminal states remain durable and replayable.
167
+ if (delivered.status === "preflight_running") {
168
+ input.transmit(delivered);
169
+ return;
170
+ }
160
171
  const existing = pending.get(eventId);
161
172
  if (existing === undefined && pending.size >= 256) {
162
173
  throw new Error("storage migration status outbox limit exceeded");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nowcrew/daemon",
3
- "version": "0.6.71",
3
+ "version": "0.6.72",
4
4
  "type": "module",
5
5
  "description": "crew daemon — 运行在用户机器:拉起/管理 agent 进程,注入 crew CLI,归一化 runtime 事件",
6
6
  "license": "Apache-2.0",
@@ -16,14 +16,6 @@
16
16
  "publishConfig": {
17
17
  "access": "public"
18
18
  },
19
- "scripts": {
20
- "daemon": "pnpm --filter @nowcrew/cli build && tsx src/main.ts",
21
- "build": "tsc -p tsconfig.json",
22
- "codex-home:migrate": "tsx src/runtimes/codex-home-migration-cli.ts",
23
- "prepublishOnly": "pnpm build && node ../scripts/daemon-release-artifact.mjs --strict-registry",
24
- "test": "vitest run",
25
- "typecheck": "tsc --noEmit"
26
- },
27
19
  "dependencies": {
28
20
  "@agentclientprotocol/sdk": "1.2.1",
29
21
  "@nowcrew/cli": "^0.4.13",
@@ -42,5 +34,12 @@
42
34
  "tsx": "^4.19.0",
43
35
  "typescript": "^5.6.0",
44
36
  "vitest": "^2.1.0"
37
+ },
38
+ "scripts": {
39
+ "daemon": "pnpm --filter @nowcrew/cli build && tsx src/main.ts",
40
+ "build": "tsc -p tsconfig.json",
41
+ "codex-home:migrate": "tsx src/runtimes/codex-home-migration-cli.ts",
42
+ "test": "vitest run",
43
+ "typecheck": "tsc --noEmit"
45
44
  }
46
- }
45
+ }