@nowcrew/daemon 0.6.11 → 0.6.13
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 +6 -3
- package/dist/agent-ability/materializer.js +4 -3
- package/dist/agent-ability/resolver.js +13 -3
- package/dist/agent-ability/types.js +11 -7
- package/dist/config.js +4 -2
- package/dist/execution-runner.js +4 -1
- package/dist/host-execution-coordinator.js +3 -3
- package/dist/main.js +0 -0
- package/dist/memory-prune-diagnostics.js +6 -0
- package/dist/remote/claude-bridge.js +558 -0
- package/dist/remote/claude-channel.js +164 -0
- package/dist/remote/codex-client.js +451 -0
- package/dist/remote/codex-runtime.js +77 -0
- package/dist/remote/config.js +135 -0
- package/dist/remote/gateway.js +879 -0
- package/dist/remote/identity.js +39 -0
- package/dist/remote/owner.js +77 -0
- package/dist/remote/protocol.js +211 -0
- package/dist/remote/remote-cli.js +254 -0
- package/dist/remote/runtime-probe.js +182 -0
- package/dist/remote/session-discovery.js +249 -0
- package/dist/remote/wrapper.js +40 -0
- package/dist/remote-web/assets/index-B_6VM_tw.js +94 -0
- package/dist/remote-web/assets/index-L6EiQbJn.css +1 -0
- package/dist/remote-web/assets/inter-cyrillic-ext-wght-normal-BOeWTOD4.woff2 +0 -0
- package/dist/remote-web/assets/inter-cyrillic-wght-normal-DqGufNeO.woff2 +0 -0
- package/dist/remote-web/assets/inter-greek-ext-wght-normal-DlzME5K_.woff2 +0 -0
- package/dist/remote-web/assets/inter-greek-wght-normal-CkhJZR-_.woff2 +0 -0
- package/dist/remote-web/assets/inter-latin-ext-wght-normal-DO1Apj_S.woff2 +0 -0
- package/dist/remote-web/assets/inter-latin-wght-normal-Dx4kXJAl.woff2 +0 -0
- package/dist/remote-web/assets/inter-vietnamese-wght-normal-CBcvBZtf.woff2 +0 -0
- package/dist/remote-web/icons/nowwork-192.png +0 -0
- package/dist/remote-web/icons/nowwork-512.png +0 -0
- package/dist/remote-web/icons/nowwork.svg +7 -0
- package/dist/remote-web/index.html +20 -0
- package/dist/remote-web/manifest.webmanifest +13 -0
- package/dist/remote-web/sw.js +12 -0
- package/dist/serve.js +9 -3
- package/dist/shared-execution-slots.js +17 -9
- package/dist/slog.js +11 -0
- package/dist/workspace.js +18 -17
- package/package.json +9 -10
package/README.md
CHANGED
|
@@ -371,9 +371,10 @@ CREW_RUNTIME_SAFE=1
|
|
|
371
371
|
CREW_EXECUTION_MAX_PROMPT_BYTES=256000
|
|
372
372
|
CREW_EXECUTION_MAX_TIMEOUT_MS=10800000
|
|
373
373
|
CREW_EXECUTION_MAX_EVENT_BYTES=64000
|
|
374
|
-
CREW_MAX_PARALLEL=
|
|
374
|
+
CREW_MAX_PARALLEL=10
|
|
375
|
+
CREW_SCHEDULED_MAX_PARALLEL=4
|
|
375
376
|
CREW_EXECUTION_MAX_QUEUED_PER_AGENT=32
|
|
376
|
-
CREW_EXECUTION_MAX_PARALLEL_TOTAL=
|
|
377
|
+
CREW_EXECUTION_MAX_PARALLEL_TOTAL=10
|
|
377
378
|
CREW_EXECUTION_MAX_QUEUED_TOTAL=128
|
|
378
379
|
CREW_EXECUTION_MAX_STARTING_TOTAL=1
|
|
379
380
|
CREW_EXECUTION_MAX_STARTING_PER_RUNTIME=1
|
|
@@ -381,7 +382,9 @@ CREW_EXECUTION_START_GAP_MS=3000
|
|
|
381
382
|
CREW_EXECUTION_STARTUP_TIMEOUT_MS=120000
|
|
382
383
|
```
|
|
383
384
|
|
|
384
|
-
`
|
|
385
|
+
`CREW_MAX_PARALLEL` limits normal executions per Agent. `CREW_SCHEDULED_MAX_PARALLEL` separately
|
|
386
|
+
limits scheduled executions per Agent. `MAX_PARALLEL_TOTAL` is the machine-wide process cap shared by
|
|
387
|
+
protocol-v1 and legacy work.
|
|
385
388
|
Runtime startup is a separate FIFO gate: by default only one Claude, Codex, or Kimi process may be
|
|
386
389
|
initializing at a time, and launches are spaced by three seconds. A process leaves the startup gate
|
|
387
390
|
only after its runtime-specific ready event; startup timeout cancels the owned process tree.
|
|
@@ -440,8 +440,6 @@ const materializeWorkspaceTraining = async (agentsRoot, handle, ability) => {
|
|
|
440
440
|
for (const mount of mounts) {
|
|
441
441
|
const sources = verified.files.filter((file) => file.path.endsWith(".md")
|
|
442
442
|
&& (file.path === mount.path || file.path.startsWith(`${mount.path}/`)));
|
|
443
|
-
if (sources.length === 0)
|
|
444
|
-
throw new Error(`ability_memory_mount_empty:${mount.path}`);
|
|
445
443
|
for (const source of sources) {
|
|
446
444
|
const relativePath = source.path === mount.path
|
|
447
445
|
? source.path.split("/").at(-1)
|
|
@@ -467,7 +465,10 @@ const materializeWorkspaceTraining = async (agentsRoot, handle, ability) => {
|
|
|
467
465
|
: join(sourceRoot, asset.source);
|
|
468
466
|
await cp(source, target, { recursive: true, preserveTimestamps: true });
|
|
469
467
|
}
|
|
470
|
-
const evalPaths = [
|
|
468
|
+
const evalPaths = [
|
|
469
|
+
...(verified.manifest.spec.evals.policy === undefined ? [] : [verified.manifest.spec.evals.policy]),
|
|
470
|
+
...verified.manifest.spec.evals.cases,
|
|
471
|
+
];
|
|
471
472
|
for (const path of evalPaths) {
|
|
472
473
|
const target = join(staging, "evals", layerRelativePath(path, "evals"));
|
|
473
474
|
await mkdir(dirname(target), { recursive: true });
|
|
@@ -253,9 +253,19 @@ const scan = (files, manifest) => {
|
|
|
253
253
|
if (executable.has(extname(file.path).toLowerCase()))
|
|
254
254
|
findings.push({ code: "executable_asset", path: file.path });
|
|
255
255
|
}
|
|
256
|
-
const required = new Set(["instructions"
|
|
256
|
+
const required = new Set(["instructions"]);
|
|
257
257
|
if (manifest.spec.skills.length > 0)
|
|
258
258
|
required.add("skills");
|
|
259
|
+
if (manifest.spec.memory.policy.length > 0)
|
|
260
|
+
required.add("memory-policy");
|
|
261
|
+
if (manifest.spec.memory.seeds.length > 0)
|
|
262
|
+
required.add("memory-seed");
|
|
263
|
+
if (manifest.spec.workspace.assets.length > 0)
|
|
264
|
+
required.add("workspace");
|
|
265
|
+
if (manifest.spec.evals.policy !== undefined)
|
|
266
|
+
required.add("eval-policy");
|
|
267
|
+
if (manifest.spec.evals.cases.length > 0)
|
|
268
|
+
required.add("eval-cases");
|
|
259
269
|
return { findings, required };
|
|
260
270
|
};
|
|
261
271
|
const lockedManifestPaths = (manifest) => [
|
|
@@ -264,7 +274,7 @@ const lockedManifestPaths = (manifest) => [
|
|
|
264
274
|
...manifest.spec.memory.policy.map((entry) => entry.path),
|
|
265
275
|
...manifest.spec.memory.seeds.map((entry) => entry.path),
|
|
266
276
|
...manifest.spec.workspace.assets.map((entry) => entry.source),
|
|
267
|
-
manifest.spec.evals.policy,
|
|
277
|
+
...(manifest.spec.evals.policy === undefined ? [] : [manifest.spec.evals.policy]),
|
|
268
278
|
...manifest.spec.evals.cases,
|
|
269
279
|
];
|
|
270
280
|
export const evaluateAbilityCases = (files, manifest, lock, memory) => {
|
|
@@ -367,7 +377,7 @@ export async function resolveAbilityRelease(agentsRoot, command) {
|
|
|
367
377
|
const assertions = [
|
|
368
378
|
{ name: "manifest_lock_verified", passed: true },
|
|
369
379
|
{ name: "manifest_asset_paths_locked", passed: lockedManifestPaths(manifest).every((path) => lockedPaths.has(path)) },
|
|
370
|
-
{ name: "
|
|
380
|
+
{ name: "declared_layers_resolvable", passed: [...security.required].every((kind) => kind === "skills" ? kinds.has(kind) || (manifest.spec.skills.length > 0 && lock.dependencies.length > 0) : kinds.has(kind)) },
|
|
371
381
|
{ name: "dependencies_pinned", passed: lock.dependencies.every((dependency) => /^[a-f0-9]{40}$/u.test(dependency.commit)) },
|
|
372
382
|
{ name: "security_scan_clear", passed: security.findings.length === 0 },
|
|
373
383
|
...evaluateAbilityCases(files, manifest, lock, memory),
|
|
@@ -61,16 +61,20 @@ export const DaemonAbilityManifestSchema = z.object({
|
|
|
61
61
|
skills: z.array(z.object({
|
|
62
62
|
name: z.string().min(1).max(128), source: z.union([LocalSkillSchema, GitSkillSchema]),
|
|
63
63
|
mount: SafeAbilityPathSchema, mode: ModeSchema, trust: z.string().max(128).optional(),
|
|
64
|
-
}).strict()).max(500),
|
|
64
|
+
}).strict()).max(500).default([]),
|
|
65
65
|
memory: z.object({
|
|
66
|
-
policy: z.array(z.object({ path: SafeAbilityPathSchema, mode: ModeSchema, mergeKey: z.string().optional() }).strict()).max(100),
|
|
67
|
-
seeds: z.array(z.object({ path: SafeAbilityPathSchema, mode: ModeSchema, mergeKey: z.string().optional() }).strict()).max(1_000),
|
|
68
|
-
runtime: z.object({ store: z.literal("nowcrew-managed"), promotion: z.literal("pull-request"), retentionDays: z.number().int().positive().optional() }).strict()
|
|
69
|
-
|
|
66
|
+
policy: z.array(z.object({ path: SafeAbilityPathSchema, mode: ModeSchema, mergeKey: z.string().optional() }).strict()).max(100).default([]),
|
|
67
|
+
seeds: z.array(z.object({ path: SafeAbilityPathSchema, mode: ModeSchema, mergeKey: z.string().optional() }).strict()).max(1_000).default([]),
|
|
68
|
+
runtime: z.object({ store: z.literal("nowcrew-managed"), promotion: z.literal("pull-request"), retentionDays: z.number().int().positive().optional() }).strict()
|
|
69
|
+
.default({ store: "nowcrew-managed", promotion: "pull-request" }),
|
|
70
|
+
}).strict().default({ policy: [], seeds: [], runtime: { store: "nowcrew-managed", promotion: "pull-request" } }),
|
|
70
71
|
workspace: z.object({ assets: z.array(z.object({
|
|
71
72
|
source: SafeAbilityPathSchema, target: WorkspaceAbilityTargetSchema, mode: ModeSchema,
|
|
72
|
-
}).strict()).max(1_000) }).strict(),
|
|
73
|
-
evals: z.object({
|
|
73
|
+
}).strict()).max(1_000).default([]) }).strict().default({ assets: [] }),
|
|
74
|
+
evals: z.object({
|
|
75
|
+
policy: SafeAbilityPathSchema.optional(),
|
|
76
|
+
cases: z.array(SafeAbilityPathSchema).max(1_000).default([]),
|
|
77
|
+
}).strict().default({ cases: [] }),
|
|
74
78
|
compatibility: z.object({
|
|
75
79
|
providers: z.array(z.enum(["claude", "codex", "kimi", "hermes", "opencode", "deepseek-harness"])).min(1),
|
|
76
80
|
minNowCrewVersion: z.string().regex(/^\d+\.\d+\.\d+$/u),
|
package/dist/config.js
CHANGED
|
@@ -10,9 +10,10 @@ export const DEFAULT_EXECUTION_LIMITS = Object.freeze({
|
|
|
10
10
|
maxPromptBytes: 256_000,
|
|
11
11
|
maxTimeoutMs: 3 * 60 * 60_000,
|
|
12
12
|
maxEventBytes: 64_000,
|
|
13
|
-
maxParallelPerAgent:
|
|
13
|
+
maxParallelPerAgent: 10,
|
|
14
|
+
maxParallelScheduledPerAgent: 4,
|
|
14
15
|
maxQueuedPerAgent: 32,
|
|
15
|
-
maxParallelTotal:
|
|
16
|
+
maxParallelTotal: 10,
|
|
16
17
|
maxQueuedTotal: 128,
|
|
17
18
|
maxStartingTotal: 1,
|
|
18
19
|
maxStartingPerRuntime: 1,
|
|
@@ -68,6 +69,7 @@ export function loadConfig(env = process.env) {
|
|
|
68
69
|
maxTimeoutMs: integerEnvAtMost(env, "CREW_EXECUTION_MAX_TIMEOUT_MS", DEFAULT_EXECUTION_LIMITS.maxTimeoutMs, MAX_EXECUTION_TIMEOUT_MS),
|
|
69
70
|
maxEventBytes: integerEnvAtLeast(env, "CREW_EXECUTION_MAX_EVENT_BYTES", DEFAULT_EXECUTION_LIMITS.maxEventBytes, MIN_EXECUTION_EVENT_BYTES),
|
|
70
71
|
maxParallelPerAgent: positiveIntegerEnv(env, "CREW_MAX_PARALLEL", DEFAULT_EXECUTION_LIMITS.maxParallelPerAgent),
|
|
72
|
+
maxParallelScheduledPerAgent: positiveIntegerEnv(env, "CREW_SCHEDULED_MAX_PARALLEL", DEFAULT_EXECUTION_LIMITS.maxParallelScheduledPerAgent),
|
|
71
73
|
maxQueuedPerAgent: positiveIntegerEnv(env, "CREW_EXECUTION_MAX_QUEUED_PER_AGENT", DEFAULT_EXECUTION_LIMITS.maxQueuedPerAgent),
|
|
72
74
|
maxParallelTotal: positiveIntegerEnv(env, "CREW_EXECUTION_MAX_PARALLEL_TOTAL", DEFAULT_EXECUTION_LIMITS.maxParallelTotal),
|
|
73
75
|
maxQueuedTotal: positiveIntegerEnv(env, "CREW_EXECUTION_MAX_QUEUED_TOTAL", DEFAULT_EXECUTION_LIMITS.maxQueuedTotal),
|
package/dist/execution-runner.js
CHANGED
|
@@ -231,7 +231,10 @@ function admission(spec, config, dependencies, at) {
|
|
|
231
231
|
|| dependencies.facts.queuedTotal < 0) {
|
|
232
232
|
return { rejected: rejection(spec.executionId, "invalid_spec", "Invalid local resource facts", at) };
|
|
233
233
|
}
|
|
234
|
-
const
|
|
234
|
+
const maxParallelForAgent = spec.context.scheduledRunId === undefined
|
|
235
|
+
? config.executionLimits.maxParallelPerAgent
|
|
236
|
+
: config.executionLimits.maxParallelScheduledPerAgent;
|
|
237
|
+
const agentAtCapacity = dependencies.facts.activeForAgent >= maxParallelForAgent;
|
|
235
238
|
const machineAtCapacity = dependencies.facts.activeTotal >= config.executionLimits.maxParallelTotal;
|
|
236
239
|
const slotInvalid = dependencies.slot?.state === "ready"
|
|
237
240
|
? agentAtCapacity || machineAtCapacity
|
|
@@ -4,7 +4,7 @@ import { mkdir, open, readFile, rename, rm, writeFile } from "node:fs/promises";
|
|
|
4
4
|
import { randomUUID } from "node:crypto";
|
|
5
5
|
import { defaultProcessController } from "./execution-journal.js";
|
|
6
6
|
import { createJournalLease, createJournalLeaseRegistry, JournalLockedError, } from "./execution-journal-lock.js";
|
|
7
|
-
const HOST_EXECUTION_SLOT_COUNT =
|
|
7
|
+
const HOST_EXECUTION_SLOT_COUNT = 10;
|
|
8
8
|
const HOST_STARTUP_GAP_MS = 3_000;
|
|
9
9
|
const RETRY_MS = 50;
|
|
10
10
|
export function defaultHostExecutionCoordinatorRoot(userHome = homedir()) {
|
|
@@ -215,8 +215,8 @@ export function createHostExecutionCoordinator(options = {}) {
|
|
|
215
215
|
}
|
|
216
216
|
export function hostCoordinatedSlotManager(local, host) {
|
|
217
217
|
return {
|
|
218
|
-
reserve: (handle, kind) => {
|
|
219
|
-
const localReservation = local.reserve(handle, kind);
|
|
218
|
+
reserve: (handle, kind, executionClass) => {
|
|
219
|
+
const localReservation = local.reserve(handle, kind, executionClass);
|
|
220
220
|
if (!localReservation.accepted)
|
|
221
221
|
return localReservation;
|
|
222
222
|
const hostReservation = host.reserveExecution(localReservation.ready);
|
package/dist/main.js
CHANGED
|
File without changes
|
|
@@ -372,6 +372,10 @@ export function evaluateMemoryPrunePostcondition(before, after, execution) {
|
|
|
372
372
|
outcome = "source_work_log_empty";
|
|
373
373
|
else if (!facts.work_log_cleared)
|
|
374
374
|
outcome = "work_log_not_cleared";
|
|
375
|
+
else if (!after.memory.exists)
|
|
376
|
+
outcome = "shared_memory_missing_after";
|
|
377
|
+
else if ((after.memory.size ?? 0) === 0)
|
|
378
|
+
outcome = "shared_memory_empty_after";
|
|
375
379
|
else if (facts.lessons_changed && facts.shared_memory_has_lessons_reference) {
|
|
376
380
|
outcome = "promoted_and_indexed";
|
|
377
381
|
}
|
|
@@ -381,6 +385,8 @@ export function evaluateMemoryPrunePostcondition(before, after, execution) {
|
|
|
381
385
|
}
|
|
382
386
|
else if (facts.lessons_changed)
|
|
383
387
|
outcome = "promoted_without_index_change";
|
|
388
|
+
else if (facts.shared_memory_changed)
|
|
389
|
+
outcome = "shared_memory_updated";
|
|
384
390
|
else
|
|
385
391
|
outcome = "no_files_changed";
|
|
386
392
|
return { outcome, ...facts };
|