@nowcrew/daemon 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
@@ -105,10 +105,8 @@ CREW_DAEMON_HOME="$HOME/.crew/daemon-dev" crew-daemon doctor --profile dev
105
105
  CREW_DAEMON_HOME="$HOME/.crew/daemon-dev" crew-daemon status --profile dev
106
106
  ```
107
107
 
108
- If the target descriptor has drifted or the profile is stopped, the daemon fails closed and remains
109
- manually upgradeable. On macOS, another unregistered legacy LaunchAgent may coexist only when its plist
110
- exactly matches a generated NowCrew service and resolves to a different npm prefix. An unverifiable or
111
- same-prefix descriptor still fails closed.
108
+ If the descriptor has drifted, the profile is stopped, or another host descriptor is not registered, the
109
+ daemon fails closed and remains manually upgradeable.
112
110
 
113
111
  The daemon advertises `daemon_update_v1` only when all of these conditions hold:
114
112
 
@@ -117,7 +115,7 @@ The daemon advertises `daemon_update_v1` only when all of these conditions hold:
117
115
  | Platform | macOS LaunchAgent or Linux systemd user service |
118
116
  | Entrypoint | global `@nowcrew/daemon/dist/main.js`, not npx or source/tsx |
119
117
  | Startup | `crew-daemon serve --profile <name>` through the installed service |
120
- | Registry | registered descriptors remain conflict-free; the exact target legacy descriptor may be adopted once; an exact macOS legacy descriptor on another npm prefix may coexist |
118
+ | Registry | every other NowCrew descriptor on the OS user account is registered and conflict-free; the exact target legacy descriptor may be adopted once |
121
119
  | Identity | service ID, descriptor, daemon home, Agent root, entrypoint, package root, and npm prefix match |
122
120
  | Service | the selected profile is running and holds the installation lease |
123
121
  | Install root | a standard writable Unix global npm prefix can be derived from the running entrypoint |
@@ -6,7 +6,6 @@ import { builtDaemonEntry } from "./computer-cli.js";
6
6
  import { buildServiceSpec, readServiceDescriptor, serviceStatus, } from "./computer-service.js";
7
7
  import { daemonGlobalInstallation } from "./daemon-installation.js";
8
8
  import { daemonInstallationLeaseHeld } from "./daemon-installation-lease.js";
9
- import { inspectLegacyServiceInstallation } from "./legacy-service-installation.js";
10
9
  import { assertRegistryCoversDescriptors, listManagedServiceDescriptorPaths, managedServiceIdentityMatches, readManagedServiceRegistry, serviceDescriptorSha256, } from "./managed-service-registry.js";
11
10
  function defaults() {
12
11
  return {
@@ -23,25 +22,8 @@ function defaults() {
23
22
  serviceStatus,
24
23
  assertWritable: (path) => access(path, constants.W_OK),
25
24
  installationLeaseHeld: daemonInstallationLeaseHeld,
26
- inspectLegacyDescriptorInstallation: (descriptorPath) => inspectLegacyServiceInstallation(descriptorPath, process.platform, homedir(), process.getuid?.()),
27
25
  };
28
26
  }
29
- async function registryCoversUpdateScope(services, descriptorPaths, targetDescriptorPath, npmPrefix, inspectLegacyDescriptorInstallation) {
30
- for (const descriptorPath of descriptorPaths) {
31
- if (descriptorPath === targetDescriptorPath)
32
- continue;
33
- try {
34
- assertRegistryCoversDescriptors(services, [descriptorPath]);
35
- continue;
36
- }
37
- catch {
38
- const legacy = await inspectLegacyDescriptorInstallation(descriptorPath).catch(() => null);
39
- if (legacy === null || legacy.npmPrefix === npmPrefix)
40
- return false;
41
- }
42
- }
43
- return true;
44
- }
45
27
  export async function detectDaemonUpdateEligibility(profileName, overrides = {}) {
46
28
  const deps = { ...defaults(), ...overrides };
47
29
  if (deps.platform !== "darwin" && deps.platform !== "linux") {
@@ -83,7 +65,10 @@ export async function detectDaemonUpdateEligibility(profileName, overrides = {})
83
65
  const registered = services.find((record) => record.serviceId === spec.id
84
66
  || (record.daemonHome === deps.profileHome && record.profile === profileName));
85
67
  if (registered !== undefined) {
86
- if (!await registryCoversUpdateScope(services, await deps.listManagedDescriptorPaths(), spec.descriptorPath, installation.npmPrefix, deps.inspectLegacyDescriptorInstallation)) {
68
+ try {
69
+ assertRegistryCoversDescriptors(services, await deps.listManagedDescriptorPaths());
70
+ }
71
+ catch {
87
72
  return { eligible: false, reason: "managed_service_registry_incomplete" };
88
73
  }
89
74
  const descriptor = await deps.readServiceDescriptor(spec).catch(() => null);
@@ -124,7 +109,12 @@ export async function detectDaemonUpdateEligibility(profileName, overrides = {})
124
109
  if (legacyDescriptor !== legacySpec.descriptor) {
125
110
  return { eligible: false, reason: "managed_service_not_registered" };
126
111
  }
127
- if (!await registryCoversUpdateScope(services, await deps.listManagedDescriptorPaths(), legacySpec.descriptorPath, installation.npmPrefix, deps.inspectLegacyDescriptorInstallation)) {
112
+ try {
113
+ const descriptorPaths = await deps.listManagedDescriptorPaths();
114
+ const targetPath = legacySpec.descriptorPath;
115
+ assertRegistryCoversDescriptors(services, descriptorPaths.filter((descriptorPath) => descriptorPath !== targetPath));
116
+ }
117
+ catch {
128
118
  return { eligible: false, reason: "managed_service_registry_incomplete" };
129
119
  }
130
120
  status = await deps.serviceStatus(legacySpec);
package/dist/main.js CHANGED
File without changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nowcrew/daemon",
3
- "version": "0.5.42",
3
+ "version": "0.5.44",
4
4
  "type": "module",
5
5
  "description": "crew daemon — 运行在用户机器:拉起/管理 agent 进程,注入 crew CLI,归一化 runtime 事件",
6
6
  "license": "Apache-2.0",
@@ -16,6 +16,13 @@
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
+ "prepublishOnly": "pnpm build && node ../scripts/daemon-release-artifact.mjs --strict-registry",
23
+ "test": "vitest run",
24
+ "typecheck": "tsc --noEmit"
25
+ },
19
26
  "dependencies": {
20
27
  "@agentclientprotocol/sdk": "1.2.1",
21
28
  "@nowcrew/cli": "^0.4.13",
@@ -33,11 +40,5 @@
33
40
  "tsx": "^4.19.0",
34
41
  "typescript": "^5.6.0",
35
42
  "vitest": "^2.1.0"
36
- },
37
- "scripts": {
38
- "daemon": "pnpm --filter @nowcrew/cli build && tsx src/main.ts",
39
- "build": "tsc -p tsconfig.json",
40
- "test": "vitest run",
41
- "typecheck": "tsc --noEmit"
42
43
  }
43
- }
44
+ }