@nowcrew/daemon 0.6.87-beta.3 → 0.6.87

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.
Files changed (28) hide show
  1. package/dist/external-output.js +154 -68
  2. package/dist/main.js +6 -2
  3. package/dist/serve.js +17 -11
  4. package/dist/storage-identity.js +4 -1
  5. package/dist/storage-ownership.js +93 -5
  6. package/dist/storage-runtime-controller.js +40 -20
  7. package/dist/storage-runtime.js +38 -2
  8. package/dist/storage-serve-adapter.js +22 -5
  9. package/package.json +9 -10
  10. package/dist/project-skills/capability.js +0 -109
  11. package/dist/project-skills/controller-convergence.js +0 -57
  12. package/dist/project-skills/projection-set-switch.js +0 -419
  13. package/dist/project-skills/projection-state-domain.js +0 -170
  14. package/dist/project-skills/projection-state-store.js +0 -842
  15. package/dist/project-skills/projection-state-transaction.js +0 -322
  16. package/dist/project-skills/projection-state.js +0 -3
  17. package/dist/project-skills/runtime-root-bootstrap.js +0 -47
  18. package/dist/project-skills/runtime-root-domain.js +0 -268
  19. package/dist/project-skills/runtime-root-gc.js +0 -293
  20. package/dist/project-skills/runtime-root-lease-artifact.js +0 -46
  21. package/dist/project-skills/runtime-root-leases.js +0 -487
  22. package/dist/project-skills/runtime-root-source-identity.js +0 -60
  23. package/dist/project-skills/runtime-root-startup.js +0 -49
  24. package/dist/project-skills/runtime-root-state-artifact-domain.js +0 -143
  25. package/dist/project-skills/runtime-root-state-index.js +0 -356
  26. package/dist/project-skills/runtime-root-store.js +0 -722
  27. package/dist/project-skills/serve-capability.js +0 -28
  28. package/dist/project-skills/serve-startup.js +0 -37
@@ -1,7 +1,7 @@
1
1
  import { findInstallationForProfile, readInstallations, resolveLocalStorageRoots, } from "./storage-config.js";
2
2
  import { storageHelloIdentity } from "./storage-identity.js";
3
3
  import { storageLayout } from "./storage-layout.js";
4
- import { readStorageOwnershipClaim } from "./storage-ownership.js";
4
+ import { readStorageOwnershipClaim, resolveWorkspaceStorageOwnershipClaim, } from "./storage-ownership.js";
5
5
  const canonicalServerUrl = (value) => value.replace(/\/+$/u, "");
6
6
  export function resolveStorageRuntime(input) {
7
7
  const installation = findInstallationForProfile(input.records, input.profile);
@@ -45,7 +45,7 @@ export async function loadStorageRuntime(input) {
45
45
  return null;
46
46
  let ownership;
47
47
  try {
48
- ownership = await readStorageOwnershipClaim(baseline.layout.persistentRoot);
48
+ ownership = await readStorageOwnershipClaim(baseline.layout.persistentRoot, baseline.layout.workspaceId);
49
49
  }
50
50
  catch (error) {
51
51
  if (error.code !== "ENOENT")
@@ -53,3 +53,39 @@ export async function loadStorageRuntime(input) {
53
53
  }
54
54
  return ownership === undefined ? baseline : resolveStorageRuntime({ ...input, records, ownership });
55
55
  }
56
+ export async function bindStorageRuntimeOwnership(runtime, server) {
57
+ const workspaceId = server.workspaceId.toLowerCase();
58
+ const machineId = server.machineId.toLowerCase();
59
+ if (runtime.installation.workspaceId !== workspaceId) {
60
+ throw new Error("Storage runtime server workspace identity changed");
61
+ }
62
+ const existing = runtime.identity.storageOwnership;
63
+ if (existing !== undefined) {
64
+ if (existing.machineId !== machineId)
65
+ throw new Error("Storage runtime server machine identity changed");
66
+ return runtime;
67
+ }
68
+ const ownership = await resolveWorkspaceStorageOwnershipClaim({
69
+ nowworkHome: runtime.layout.persistentRoot,
70
+ machineId,
71
+ workspaceId,
72
+ environment: runtime.installation.environment,
73
+ workspaceRootFingerprint: runtime.identity.workspaceRootFingerprint,
74
+ });
75
+ return Object.freeze({
76
+ ...runtime,
77
+ identity: storageHelloIdentity({ installation: runtime.installation, layout: runtime.layout, ownership }),
78
+ });
79
+ }
80
+ export function createStorageRuntimeOwnershipBinding(initial) {
81
+ let runtime = initial;
82
+ let bindTail = Promise.resolve();
83
+ const bind = (server) => {
84
+ const current = bindTail.then(async () => {
85
+ runtime = await bindStorageRuntimeOwnership(runtime, server);
86
+ });
87
+ bindTail = current.catch(() => undefined);
88
+ return current;
89
+ };
90
+ return Object.freeze({ identity: () => runtime.identity, bind });
91
+ }
@@ -9,6 +9,15 @@ export function storageMigrationCapabilities(configured, options) {
9
9
  ...(options.ready ? [STORAGE_MIGRATION_CAPABILITY] : []),
10
10
  ])]);
11
11
  }
12
+ export function bindStorageMigrationServerIdentity(options, identity, callbacks) {
13
+ const bind = options?.bindServerIdentity;
14
+ if (bind === undefined) {
15
+ if (options?.ready === true)
16
+ callbacks.onBound();
17
+ return;
18
+ }
19
+ void Promise.resolve().then(() => bind(identity)).then(callbacks.onBound).catch(callbacks.onError);
20
+ }
12
21
  export function createServeStorageStatusDelivery(options, dependencies) {
13
22
  return createStorageStatusDelivery({
14
23
  ...(options?.statusOutboxPath === undefined ? {} : { outboxPath: options.statusOutboxPath }),
@@ -17,28 +26,36 @@ export function createServeStorageStatusDelivery(options, dependencies) {
17
26
  });
18
27
  }
19
28
  export function attachStorageMigrationRuntime(options, dependencies) {
20
- let admissionClosed = false;
29
+ let migrationAdmissionClosed = false;
30
+ let identityAdmissionClosed = options?.bindServerIdentity !== undefined;
21
31
  if (options?.ready === true) {
22
32
  options.attach?.({
23
33
  gate: {
24
34
  isBusy: dependencies.isBusy,
25
35
  closeAndFlush: async () => {
26
- admissionClosed = true;
36
+ migrationAdmissionClosed = true;
27
37
  await dependencies.waitForExecutionFrames();
28
38
  if (dependencies.isBusy()) {
29
- admissionClosed = false;
39
+ migrationAdmissionClosed = false;
30
40
  throw Object.assign(new Error("active execution entered before storage migration quiesce"), {
31
41
  code: "runtime_busy",
32
42
  });
33
43
  }
34
44
  await dependencies.flushLocalState();
35
45
  },
36
- reopen: () => { admissionClosed = false; },
46
+ reopen: () => { migrationAdmissionClosed = false; },
37
47
  },
38
48
  sendStatus: dependencies.sendStatus,
39
49
  });
40
50
  }
41
- return Object.freeze({ isAdmissionClosed: () => admissionClosed });
51
+ return Object.freeze({
52
+ isAdmissionClosed: () => migrationAdmissionClosed || identityAdmissionClosed,
53
+ beginIdentityBinding: () => {
54
+ if (options?.bindServerIdentity !== undefined)
55
+ identityAdmissionClosed = true;
56
+ },
57
+ completeIdentityBinding: () => { identityAdmissionClosed = false; },
58
+ });
42
59
  }
43
60
  export function replayStorageMigrationStatus(options, socket, isCurrent, onError, deliver) {
44
61
  return options?.replayStatus?.((frame) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nowcrew/daemon",
3
- "version": "0.6.87-beta.3",
3
+ "version": "0.6.87",
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",
@@ -44,5 +36,12 @@
44
36
  "tsx": "^4.19.0",
45
37
  "typescript": "^5.6.0",
46
38
  "vitest": "^2.1.0"
39
+ },
40
+ "scripts": {
41
+ "daemon": "pnpm --filter @nowcrew/cli build && tsx src/main.ts",
42
+ "build": "tsc -p tsconfig.json",
43
+ "codex-home:migrate": "tsx src/runtimes/codex-home-migration-cli.ts",
44
+ "test": "vitest run",
45
+ "typecheck": "tsc --noEmit"
47
46
  }
48
- }
47
+ }
@@ -1,109 +0,0 @@
1
- import { PROJECT_SKILLS_CAPABILITY, PROJECT_SKILL_PROJECTION_V2_CAPABILITY, } from "./types.js";
2
- export function projectSkillV2RolloutReady(platform, readiness) {
3
- const platformReady = platform === "darwin"
4
- || platform === "linux"
5
- || (platform === "win32" && readiness.nativeWindowsSmokePassed);
6
- return platformReady
7
- && readiness.runtimeRootStorePrimitiveReady
8
- && readiness.runtimeRootStoreRecoveryReady
9
- && readiness.leaseRecoveryReady
10
- && readiness.controllerReady
11
- && readiness.executionHandlerReady
12
- && readiness.codexAdapterReady
13
- && readiness.claudeAdapterReady;
14
- }
15
- export function effectiveProjectSkillCapabilities(capabilities, projectSkillsReady, projectSkillV2Ready) {
16
- const projectSkillCapabilitiesReady = projectSkillsReady && projectSkillV2Ready;
17
- if (!projectSkillCapabilitiesReady
18
- && !capabilities.includes(PROJECT_SKILLS_CAPABILITY)
19
- && !capabilities.includes(PROJECT_SKILL_PROJECTION_V2_CAPABILITY)
20
- && Object.isFrozen(capabilities))
21
- return capabilities;
22
- const filtered = capabilities.filter((capability) => capability !== PROJECT_SKILL_PROJECTION_V2_CAPABILITY
23
- && (projectSkillCapabilitiesReady || capability !== PROJECT_SKILLS_CAPABILITY));
24
- if (!projectSkillCapabilitiesReady || !filtered.includes(PROJECT_SKILLS_CAPABILITY)) {
25
- return Object.freeze(filtered);
26
- }
27
- const v1Index = filtered.indexOf(PROJECT_SKILLS_CAPABILITY);
28
- return Object.freeze([
29
- ...filtered.slice(0, v1Index + 1),
30
- PROJECT_SKILL_PROJECTION_V2_CAPABILITY,
31
- ...filtered.slice(v1Index + 1),
32
- ]);
33
- }
34
- export function withProjectSkillCapabilityStatus(value, status) {
35
- return {
36
- ...value,
37
- projectSkillsStatus: status,
38
- capabilities: status === "ready"
39
- ? value.capabilities
40
- : effectiveProjectSkillCapabilities(value.capabilities, false, false),
41
- };
42
- }
43
- const settleReadinessGate = async (operation) => {
44
- try {
45
- return await operation() === true;
46
- }
47
- catch {
48
- return false;
49
- }
50
- };
51
- export async function createProjectSkillConnectionCapabilitySnapshot(input) {
52
- const runtimeRootStorePrimitiveReady = await settleReadinessGate(input.probeRuntimeRootStorePrimitive);
53
- const controllerReady = await settleReadinessGate(input.initializeController);
54
- const recoveryReady = await settleReadinessGate(input.recoverRuntimeRootsAndLeases);
55
- const readiness = Object.freeze({
56
- runtimeRootStorePrimitiveReady,
57
- runtimeRootStoreRecoveryReady: recoveryReady,
58
- leaseRecoveryReady: recoveryReady,
59
- controllerReady,
60
- executionHandlerReady: true,
61
- codexAdapterReady: true,
62
- claudeAdapterReady: true,
63
- nativeWindowsSmokePassed: false,
64
- });
65
- const projectSkillsReady = projectSkillV2RolloutReady(input.platform, readiness);
66
- return Object.freeze({
67
- capabilities: effectiveProjectSkillCapabilities(input.baseCapabilities, projectSkillsReady, projectSkillsReady),
68
- projectSkillsReady,
69
- readiness,
70
- });
71
- }
72
- export async function prepareProjectSkillConnectionCapabilities(input) {
73
- const snapshot = await createProjectSkillConnectionCapabilitySnapshot({
74
- ...input,
75
- baseCapabilities: [...input.baseCapabilities, ...await input.additionalCapabilities()],
76
- });
77
- input.applyReadiness(snapshot.projectSkillsReady);
78
- return snapshot.capabilities;
79
- }
80
- export function createProjectSkillControllerReadiness(input) {
81
- let status = "initializing";
82
- let initialization = null;
83
- const ensure = () => {
84
- if (status === "ready")
85
- return Promise.resolve(true);
86
- if (initialization !== null)
87
- return initialization;
88
- status = "initializing";
89
- const attempt = input.initialize().then(() => {
90
- status = "ready";
91
- return true;
92
- }, (error) => {
93
- status = "unavailable";
94
- input.onUnavailable(error);
95
- return false;
96
- }).finally(() => {
97
- if (initialization === attempt)
98
- initialization = null;
99
- input.onSettled();
100
- });
101
- initialization = attempt;
102
- return attempt;
103
- };
104
- return Object.freeze({
105
- status: () => status,
106
- ensure,
107
- applyPreflight: (ready) => { status = ready ? "ready" : "unavailable"; },
108
- });
109
- }
@@ -1,57 +0,0 @@
1
- import { ProjectProjectionError, } from "./reconciler.js";
2
- export const MAX_REMEMBERED_PROJECT_SKILL_AGENTS = 64;
3
- const compareBinary = (left, right) => {
4
- if (left < right)
5
- return -1;
6
- if (left > right)
7
- return 1;
8
- return 0;
9
- };
10
- const copySnapshot = (snapshot) => Object.freeze({
11
- bindings: Object.freeze(snapshot.bindings.map((binding) => Object.freeze({ ...binding }))),
12
- generation: snapshot.generation,
13
- });
14
- export function createProjectSkillSnapshotEpoch(maxEntries = MAX_REMEMBERED_PROJECT_SKILL_AGENTS) {
15
- if (!Number.isSafeInteger(maxEntries) || maxEntries < 1) {
16
- throw new ProjectProjectionError("skill_projection_failed");
17
- }
18
- const snapshots = new Map();
19
- return Object.freeze({
20
- begin() {
21
- snapshots.clear();
22
- },
23
- remember(handle, snapshot) {
24
- const previous = snapshots.get(handle);
25
- if (previous !== undefined && snapshot.generation < previous.generation)
26
- return;
27
- if (previous === undefined && snapshots.size >= maxEntries) {
28
- throw new ProjectProjectionError("skill_projection_failed");
29
- }
30
- snapshots.set(handle, copySnapshot(snapshot));
31
- },
32
- forget(handle) {
33
- snapshots.delete(handle);
34
- },
35
- entries() {
36
- return Object.freeze([...snapshots.entries()]
37
- .sort(([left], [right]) => compareBinary(left, right))
38
- .map(([handle, snapshot]) => Object.freeze([handle, copySnapshot(snapshot)])));
39
- },
40
- });
41
- }
42
- const stableErrorCode = (reason) => reason?.code === "skill_projection_snapshot_corrupt"
43
- ? "skill_projection_snapshot_corrupt"
44
- : "skill_projection_failed";
45
- export function toPathPrivateConvergenceResults(entries, results) {
46
- return Object.freeze(entries.map(([handle], index) => {
47
- const result = results[index];
48
- if (result?.status === "fulfilled") {
49
- return Object.freeze({ handle, status: "fulfilled" });
50
- }
51
- return Object.freeze({
52
- handle,
53
- status: "rejected",
54
- errorCode: stableErrorCode(result?.reason),
55
- });
56
- }));
57
- }