@nowcrew/daemon 0.6.67 → 0.6.68

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 (61) hide show
  1. package/dist/agent-ability/materializer.js +1 -20
  2. package/dist/agent-ability/resolver.js +10 -7
  3. package/dist/agent-ability/runtime.js +0 -3
  4. package/dist/automatic-install-target.js +10 -15
  5. package/dist/computer-cli.js +1 -10
  6. package/dist/computer-service.js +1 -41
  7. package/dist/config.js +0 -44
  8. package/dist/daemon-migration-controller.js +18 -16
  9. package/dist/execution-protocol.js +1 -0
  10. package/dist/execution-runner.js +8 -5
  11. package/dist/local-execution-prompt.js +11 -15
  12. package/dist/local-executor.js +53 -93
  13. package/dist/machine-info.js +4 -3
  14. package/dist/main.js +0 -83
  15. package/dist/managed-service-lifecycle.js +2 -47
  16. package/dist/managed-service-startup.js +0 -2
  17. package/dist/profile-layout.js +4 -10
  18. package/dist/project-skills/controller.js +0 -2
  19. package/dist/prompt.js +1 -19
  20. package/dist/provider-env.js +21 -3
  21. package/dist/runner.js +2 -4
  22. package/dist/runtimes/codex-app-server-runner.js +23 -55
  23. package/dist/runtimes/codex-contract.js +5 -20
  24. package/dist/runtimes/codex-deepseek-config.js +17 -7
  25. package/dist/runtimes/codex.js +3 -4
  26. package/dist/self-training-workspace.js +15 -0
  27. package/dist/serve.js +3 -68
  28. package/dist/supervised-runtime.js +1 -3
  29. package/dist/workspace.js +14 -34
  30. package/package.json +1 -1
  31. package/dist/local-memory/index-budget.js +0 -74
  32. package/dist/local-memory/pending.js +0 -111
  33. package/dist/local-memory/runtime.js +0 -87
  34. package/dist/local-memory/types.js +0 -1
  35. package/dist/local-memory/write.js +0 -448
  36. package/dist/runtimes/codex-command-safety.js +0 -75
  37. package/dist/runtimes/codex-turn-retry.js +0 -69
  38. package/dist/storage-config.js +0 -175
  39. package/dist/storage-control.js +0 -193
  40. package/dist/storage-copy.js +0 -609
  41. package/dist/storage-credential-guard.js +0 -21
  42. package/dist/storage-doctor.js +0 -228
  43. package/dist/storage-identity.js +0 -29
  44. package/dist/storage-layout.js +0 -143
  45. package/dist/storage-manifest.js +0 -855
  46. package/dist/storage-migration-controller.js +0 -417
  47. package/dist/storage-migration-manifest.js +0 -105
  48. package/dist/storage-migration-policy.js +0 -100
  49. package/dist/storage-runtime-controller.js +0 -339
  50. package/dist/storage-runtime-readiness.js +0 -184
  51. package/dist/storage-runtime.js +0 -39
  52. package/dist/storage-safe-fs.js +0 -302
  53. package/dist/storage-serve-adapter.js +0 -65
  54. package/dist/storage-status-delivery.js +0 -209
  55. package/dist/storage-status-replay.js +0 -125
  56. package/dist/storage-target-confirmation.js +0 -129
  57. package/dist/storage-worker-command.js +0 -27
  58. package/dist/storage-worker-executor.js +0 -384
  59. package/dist/storage-worker-handoff.js +0 -151
  60. package/dist/storage-worker-operation.js +0 -284
  61. package/dist/storage-worker-status.js +0 -232
@@ -1,175 +0,0 @@
1
- import { readFile } from "node:fs/promises";
2
- import { posix, win32 } from "node:path";
3
- import { z } from "zod";
4
- import { atomicPrivateWrite } from "./atomic-private-write.js";
5
- import { resolveEnvTag, resolveNowworkHome, storageLayout, } from "./storage-layout.js";
6
- const UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/iu;
7
- const PROFILE = /^[a-z0-9][a-z0-9_-]{0,47}$/u;
8
- const PORTABLE_ABSOLUTE_PATH = z.string().min(1).max(32768).refine((value) => posix.isAbsolute(value) || win32.isAbsolute(value), "must be an absolute path");
9
- const ServerUrlSchema = z.string().url().max(2048).refine((value) => {
10
- const url = new URL(value);
11
- return (url.protocol === "http:" || url.protocol === "https:") && !url.username && !url.password;
12
- }, "serverUrl must be HTTP(S) without embedded credentials");
13
- const InstallationRecordSchema = z.object({
14
- version: z.literal(1),
15
- installationId: z.string().uuid(),
16
- profile: z.string().regex(PROFILE),
17
- serverUrl: ServerUrlSchema,
18
- environment: z.string().regex(/^[a-z0-9][a-z0-9_-]{0,31}$/u),
19
- workspaceId: z.string().uuid(),
20
- storageId: z.string().min(1).max(128).regex(/^[A-Za-z0-9_-]+$/u),
21
- nowworkHome: PORTABLE_ABSOLUTE_PATH,
22
- runtimeRoot: PORTABLE_ABSOLUTE_PATH,
23
- credentialRef: z.string().regex(/^profile:[a-z0-9][a-z0-9_-]{0,47}$/u),
24
- storageMigrationId: z.string().uuid().optional(),
25
- createdAt: z.string().datetime({ offset: true }),
26
- updatedAt: z.string().datetime({ offset: true }),
27
- }).strict();
28
- const InstallationRegistrySchema = z.object({
29
- version: z.literal(1),
30
- installations: z.array(InstallationRecordSchema).max(256),
31
- }).strict();
32
- export function findInstallationForProfile(records, profile) {
33
- if (!PROFILE.test(profile))
34
- throw new Error("profile name is invalid");
35
- const matches = records.filter((record) => record.profile === profile);
36
- if (matches.length > 1)
37
- throw new Error(`Multiple installations use profile '${profile}'`);
38
- return matches[0] ?? null;
39
- }
40
- const pathsFor = (platform) => platform === "win32" ? win32 : posix;
41
- function absoluteBase(value, fallback, platform, name) {
42
- const paths = pathsFor(platform);
43
- const selected = value ?? fallback;
44
- if (!paths.isAbsolute(selected) || selected.includes("\0") || selected.includes("\n") || selected.includes("\r")) {
45
- throw new Error(`${name} must be an absolute single-line path`);
46
- }
47
- return paths.normalize(selected);
48
- }
49
- export function resolveLocalStorageRoots(input) {
50
- const paths = pathsFor(input.platform);
51
- const userHome = absoluteBase(input.userHome, input.userHome, input.platform, "user home");
52
- if (input.platform === "win32") {
53
- const local = absoluteBase(input.environment.LOCALAPPDATA, paths.join(userHome, "AppData", "Local"), input.platform, "LOCALAPPDATA");
54
- const root = paths.join(local, "NowWork");
55
- return Object.freeze({
56
- configRoot: paths.join(root, "config"),
57
- runtimeBase: paths.join(root, "runtime"),
58
- cacheRoot: paths.join(root, "cache"),
59
- stateRoot: paths.join(root, "state"),
60
- backupsRoot: paths.join(root, "state", "backups"),
61
- runtimePackagesRoot: paths.join(root, "cache", "runtime-packages"),
62
- });
63
- }
64
- if (input.platform === "darwin") {
65
- const applicationSupport = paths.join(userHome, "Library", "Application Support", "NowWork");
66
- const cacheRoot = paths.join(userHome, "Library", "Caches", "NowWork");
67
- return Object.freeze({
68
- configRoot: paths.join(applicationSupport, "config"),
69
- runtimeBase: paths.join(cacheRoot, "runtime"),
70
- cacheRoot,
71
- stateRoot: paths.join(applicationSupport, "state"),
72
- backupsRoot: paths.join(applicationSupport, "state", "backups"),
73
- runtimePackagesRoot: paths.join(cacheRoot, "runtime-packages"),
74
- });
75
- }
76
- const configHome = absoluteBase(input.environment.XDG_CONFIG_HOME, paths.join(userHome, ".config"), input.platform, "XDG_CONFIG_HOME");
77
- const cacheHome = absoluteBase(input.environment.XDG_CACHE_HOME, paths.join(userHome, ".cache"), input.platform, "XDG_CACHE_HOME");
78
- const stateHome = absoluteBase(input.environment.XDG_STATE_HOME, paths.join(userHome, ".local", "state"), input.platform, "XDG_STATE_HOME");
79
- const runtimeHome = absoluteBase(input.environment.XDG_RUNTIME_DIR, paths.join(stateHome, "nowwork", "runtime"), input.platform, "XDG_RUNTIME_DIR");
80
- const stateRoot = paths.join(stateHome, "nowwork");
81
- const cacheRoot = paths.join(cacheHome, "nowwork");
82
- return Object.freeze({
83
- configRoot: paths.join(configHome, "nowwork"),
84
- runtimeBase: input.environment.XDG_RUNTIME_DIR === undefined ? runtimeHome : paths.join(runtimeHome, "nowwork"),
85
- cacheRoot,
86
- stateRoot,
87
- backupsRoot: paths.join(stateRoot, "backups"),
88
- runtimePackagesRoot: paths.join(cacheRoot, "runtime-packages"),
89
- });
90
- }
91
- export function buildStorageConfig(input) {
92
- if (!PROFILE.test(input.profile))
93
- throw new Error("profile name is invalid");
94
- if (!UUID.test(input.workspaceId))
95
- throw new Error("workspace id must be a UUID");
96
- const paths = pathsFor(input.platform);
97
- const local = resolveLocalStorageRoots(input);
98
- const home = resolveNowworkHome({
99
- ...(input.nowworkHome === undefined ? {} : { explicit: input.nowworkHome }),
100
- ...(input.environment.NOWWORK_HOME === undefined ? {} : { environment: input.environment.NOWWORK_HOME }),
101
- userHome: input.userHome,
102
- platform: input.platform,
103
- });
104
- const credentialRef = `profile:${input.profile}`;
105
- if (home.mode === "legacy") {
106
- return Object.freeze({
107
- mode: "legacy",
108
- profile: input.profile,
109
- workspaceId: input.workspaceId.toLowerCase(),
110
- credentialRef,
111
- daemonHome: input.legacyDaemonHome ?? paths.join(input.userHome, ".crew", "daemon"),
112
- agentsRoot: input.legacyAgentsRoot ?? paths.join(input.userHome, ".crew", "agents"),
113
- layout: null,
114
- local,
115
- diagnostics: Object.freeze(["legacy_storage_detected"]),
116
- });
117
- }
118
- const environment = resolveEnvTag({
119
- ...(input.envTag === undefined ? {} : { explicit: input.envTag }),
120
- ...(input.environment.NOWWORK_ENV_TAG === undefined ? {} : { environment: input.environment.NOWWORK_ENV_TAG }),
121
- }).environment;
122
- const layout = storageLayout({
123
- nowworkHome: home.root,
124
- environment,
125
- workspaceId: input.workspaceId,
126
- runtimeBase: local.runtimeBase,
127
- platform: input.platform,
128
- });
129
- return Object.freeze({
130
- mode: "standard",
131
- profile: input.profile,
132
- workspaceId: input.workspaceId.toLowerCase(),
133
- credentialRef,
134
- daemonHome: local.configRoot,
135
- agentsRoot: layout.agentItemsRoot,
136
- layout,
137
- local,
138
- diagnostics: Object.freeze([]),
139
- });
140
- }
141
- export function installationsPath(configRoot) {
142
- const paths = win32.isAbsolute(configRoot) && !posix.isAbsolute(configRoot) ? win32 : posix;
143
- return paths.join(configRoot, "installations.json");
144
- }
145
- export async function readInstallations(input) {
146
- const path = installationsPath(input.configRoot);
147
- try {
148
- const parsed = InstallationRegistrySchema.parse(JSON.parse(await readFile(path, "utf8")));
149
- return Object.freeze(parsed.installations.map((record) => Object.freeze(record)));
150
- }
151
- catch (error) {
152
- if (error.code === "ENOENT")
153
- return Object.freeze([]);
154
- throw new Error(`Invalid installation registry: ${path}`, { cause: error });
155
- }
156
- }
157
- export async function writeInstallations(records, input) {
158
- let parsed;
159
- try {
160
- parsed = InstallationRegistrySchema.parse({ version: 1, installations: records });
161
- const installationIds = new Set();
162
- const profiles = new Set();
163
- for (const record of parsed.installations) {
164
- if (installationIds.has(record.installationId) || profiles.has(record.profile)) {
165
- throw new Error("duplicate installation identity");
166
- }
167
- installationIds.add(record.installationId);
168
- profiles.add(record.profile);
169
- }
170
- }
171
- catch (error) {
172
- throw new Error("Invalid installation metadata", { cause: error });
173
- }
174
- await atomicPrivateWrite(installationsPath(input.configRoot), `${JSON.stringify(parsed, null, 2)}\n`);
175
- }
@@ -1,193 +0,0 @@
1
- import { z } from "zod";
2
- export const STORAGE_MIGRATION_CAPABILITY = "storage_migration_v1";
3
- export const STORAGE_MIGRATION_STATUS_CAPABILITY = "storage_migration_status_v1";
4
- const IdentitySchema = z.object({
5
- migrationId: z.string().uuid(),
6
- environment: z.string().regex(/^[a-z0-9][a-z0-9_-]{0,31}$/u),
7
- workspaceId: z.string().uuid(),
8
- });
9
- const DoctorRequestSchema = IdentitySchema.extend({ type: z.literal("daemon:storage-doctor") }).strict();
10
- const MigrateRequestSchema = IdentitySchema.extend({
11
- type: z.literal("daemon:storage-migrate"),
12
- manifestDigest: z.string().regex(/^[0-9a-f]{64}$/u),
13
- }).strict();
14
- const StatusSchema = z.enum([
15
- "preflight_running", "preflight_passed", "backing_up", "initial_sync", "quiescing", "final_sync", "verified",
16
- "service_switched", "hello_confirmed", "completed", "failed", "rollback_pending", "rolled_back",
17
- "rollback_failed",
18
- ]);
19
- const TOKEN = /(?:\bsk_(?:machine|user|agent)_[A-Za-z0-9_-]{4,}\b|\bbearer\s+[^\s]+|(?:password|secret|token)\s*[:=]\s*[^\s]+)/giu;
20
- const safeError = (error) => (error instanceof Error ? error.message : String(error))
21
- .replaceAll(TOKEN, "<redacted>").slice(0, 500) || "storage migration failed";
22
- const stableErrorCode = (candidate, fallback) => typeof candidate === "string" && /^[a-z0-9._-]{1,128}$/u.test(candidate) ? candidate : fallback;
23
- export function createStorageControlController(input) {
24
- const environment = z.string().regex(/^[a-z0-9][a-z0-9_-]{0,31}$/u).parse(input.environment);
25
- const workspaceId = z.string().uuid().parse(input.workspaceId);
26
- const profile = z.string().regex(/^[a-z0-9][a-z0-9_-]{0,47}$/u).parse(input.profile);
27
- const sourceStorageFingerprint = z.string().regex(/^sha256:[0-9a-f]{64}$/u).parse(input.sourceStorageFingerprint);
28
- const targetStorageFingerprint = z.string().regex(/^sha256:[0-9a-f]{64}$/u).parse(input.targetStorageFingerprint);
29
- const preflights = new Map();
30
- const preflightRuns = new Map();
31
- const appliedMigrationIds = new Set();
32
- let runningMigrationId = null;
33
- const preflightTimeoutMs = z.number().int().positive().max(24 * 60 * 60 * 1000)
34
- .parse(input.preflightTimeoutMs ?? 30 * 60 * 1000);
35
- const frame = (identity, status, extra = {}) => ({
36
- type: "daemon:storage-migration-status",
37
- migrationId: identity.migrationId,
38
- status,
39
- environment,
40
- workspaceId,
41
- profile,
42
- ...extra,
43
- });
44
- const failure = (identity, errorCode, error, reopenAdmission = false, extra = {}) => {
45
- input.sendStatus(frame(identity, "failed", {
46
- errorCode,
47
- ...extra,
48
- ...(error === undefined ? {} : { errorMessage: safeError(error) }),
49
- ...(reopenAdmission || error?.reopenAdmission === true
50
- ? { reopenAdmission: true }
51
- : {}),
52
- }));
53
- };
54
- const matchesIdentity = (identity) => identity.environment === environment && identity.workspaceId === workspaceId;
55
- const preflightKey = (identity) => `${identity.migrationId}\0${identity.environment}\0${identity.workspaceId}`;
56
- const runPreflight = (identity, failureFallback = "doctor_failed") => {
57
- const key = preflightKey(identity);
58
- const existing = preflightRuns.get(key);
59
- if (existing !== undefined)
60
- return existing;
61
- const controller = new AbortController();
62
- let scannedEntries = 0;
63
- let timedOut = false;
64
- input.sendStatus(frame(identity, "preflight_running", {
65
- progress: { state: "running", scannedEntries: 0 },
66
- }));
67
- const doctorPromise = Promise.resolve().then(() => input.runDoctor(identity.migrationId, {
68
- signal: controller.signal,
69
- onProgress: (progress) => {
70
- if (timedOut)
71
- return;
72
- scannedEntries = progress.scannedEntries;
73
- input.sendStatus(frame(identity, "preflight_running", {
74
- progress: { state: "running", scannedEntries },
75
- }));
76
- },
77
- }));
78
- let timeoutHandle;
79
- const timeout = new Promise((_, reject) => {
80
- timeoutHandle = setTimeout(() => {
81
- timedOut = true;
82
- controller.abort();
83
- reject(Object.assign(new Error("storage doctor preflight timed out"), {
84
- code: "preflight_stale",
85
- scannedEntries,
86
- }));
87
- }, preflightTimeoutMs);
88
- timeoutHandle.unref?.();
89
- });
90
- void doctorPromise.catch(() => undefined);
91
- let outcome;
92
- outcome = Promise.race([doctorPromise, timeout]).then((doctor) => {
93
- if (doctor.manifest.migrationId !== identity.migrationId
94
- || doctor.environment !== environment || doctor.workspaceId !== workspaceId
95
- || doctor.profile !== profile) {
96
- failure(identity, "storage_identity_mismatch", undefined, true);
97
- return null;
98
- }
99
- if (!doctor.applyAllowed) {
100
- failure(identity, doctor.blockers[0]?.code ?? "doctor_blocked", undefined, true);
101
- return null;
102
- }
103
- preflights.set(identity.migrationId, doctor);
104
- input.sendStatus(frame(identity, "preflight_passed", {
105
- sourceStorageFingerprint,
106
- targetStorageFingerprint,
107
- manifestDigest: doctor.manifestDigest,
108
- }));
109
- return doctor;
110
- }).catch((error) => {
111
- const code = error.code;
112
- if (code === "preflight_stale") {
113
- failure(identity, "preflight_stale", undefined, true, {
114
- retryable: true,
115
- progress: { state: "stale", scannedEntries: Number(error.scannedEntries) || scannedEntries },
116
- });
117
- }
118
- else if (code === "preflight_aborted") {
119
- failure(identity, "preflight_aborted", error, true, {
120
- retryable: true,
121
- progress: { state: "stale", scannedEntries },
122
- });
123
- }
124
- else {
125
- failure(identity, stableErrorCode(code, failureFallback), error, true);
126
- }
127
- return null;
128
- }).finally(() => {
129
- if (timeoutHandle !== undefined)
130
- clearTimeout(timeoutHandle);
131
- if (preflightRuns.get(key) === outcome)
132
- preflightRuns.delete(key);
133
- });
134
- preflightRuns.set(key, outcome);
135
- return outcome;
136
- };
137
- const handle = async (raw) => {
138
- const type = typeof raw === "object" && raw !== null && "type" in raw ? raw.type : null;
139
- if (type !== "daemon:storage-doctor" && type !== "daemon:storage-migrate")
140
- return false;
141
- const schema = type === "daemon:storage-doctor" ? DoctorRequestSchema : MigrateRequestSchema;
142
- const parsed = schema.safeParse(raw);
143
- if (!parsed.success)
144
- return true;
145
- const identity = parsed.data;
146
- if (!matchesIdentity(identity)) {
147
- failure(identity, "storage_identity_mismatch", undefined, true);
148
- return true;
149
- }
150
- if (type === "daemon:storage-doctor") {
151
- await runPreflight(identity);
152
- return true;
153
- }
154
- if (runningMigrationId !== null) {
155
- if (runningMigrationId !== identity.migrationId)
156
- failure(identity, "migration_active");
157
- return true;
158
- }
159
- const migrate = MigrateRequestSchema.parse(identity);
160
- if (appliedMigrationIds.has(identity.migrationId))
161
- return true;
162
- let doctor = preflights.get(identity.migrationId);
163
- if (doctor === undefined) {
164
- const rebuilt = await runPreflight(identity, "preflight_rebuild_failed");
165
- if (rebuilt === null)
166
- return true;
167
- doctor = rebuilt;
168
- }
169
- if (!doctor.applyAllowed || doctor.manifestDigest !== migrate.manifestDigest
170
- || doctor.manifest.migrationId !== identity.migrationId
171
- || doctor.environment !== environment || doctor.workspaceId !== workspaceId || doctor.profile !== profile) {
172
- failure(identity, "preflight_digest_mismatch", undefined, true);
173
- return true;
174
- }
175
- preflights.delete(identity.migrationId);
176
- runningMigrationId = identity.migrationId;
177
- try {
178
- await input.runMigration(doctor, (status) => {
179
- if (StatusSchema.safeParse(status).success)
180
- input.sendStatus(frame(identity, status));
181
- });
182
- appliedMigrationIds.add(identity.migrationId);
183
- }
184
- catch (error) {
185
- failure(identity, stableErrorCode(error.code, "storage_migration_failed"), error);
186
- }
187
- finally {
188
- runningMigrationId = null;
189
- }
190
- return true;
191
- };
192
- return Object.freeze({ handle });
193
- }