Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 7f780f0642 | |||
| 33e0d9a705 |
@@ -1,6 +1,9 @@
|
|||||||
{
|
{
|
||||||
"name": "nerve",
|
"name": "nerve",
|
||||||
"private": true,
|
"private": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">=22.5.0"
|
||||||
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "pnpm -r run build",
|
"build": "pnpm -r run build",
|
||||||
"check": "biome check .",
|
"check": "biome check .",
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
{
|
{
|
||||||
"name": "@uncaged/nerve-cli",
|
"name": "@uncaged/nerve-cli",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=22.5.0"
|
||||||
|
},
|
||||||
"version": "0.1.8",
|
"version": "0.1.8",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"bin": {
|
"bin": {
|
||||||
@@ -23,7 +26,6 @@
|
|||||||
"citty": "^0.1.6"
|
"citty": "^0.1.6"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/better-sqlite3": "^7.6.13",
|
|
||||||
"@types/node": "^22.0.0",
|
"@types/node": "^22.0.0",
|
||||||
"@uncaged/nerve-daemon": "workspace:*",
|
"@uncaged/nerve-daemon": "workspace:*",
|
||||||
"vitest": "^4.1.5"
|
"vitest": "^4.1.5"
|
||||||
|
|||||||
@@ -3,6 +3,10 @@
|
|||||||
"version": "0.1.4",
|
"version": "0.1.4",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
|
"files": ["dist"],
|
||||||
|
"publishConfig": {
|
||||||
|
"access": "public"
|
||||||
|
},
|
||||||
"types": "dist/index.d.ts",
|
"types": "dist/index.d.ts",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"prepublishOnly": "bash ../../scripts/prepublish-check.sh",
|
"prepublishOnly": "bash ../../scripts/prepublish-check.sh",
|
||||||
|
|||||||
@@ -89,10 +89,11 @@ function makeLogStore(
|
|||||||
}
|
}
|
||||||
return activeRuns;
|
return activeRuns;
|
||||||
}),
|
}),
|
||||||
getTriggerPayload: vi.fn(() => ({ value: 42 })),
|
getTriggerPayload: vi.fn((): unknown => ({ value: 42 })),
|
||||||
getThreadEvents: vi.fn(() => [{ type: "thread_start", triggerPayload: {} }]),
|
getThreadEvents: vi.fn((): Array<{ type: string; [key: string]: unknown }> => [{ type: "thread_start", triggerPayload: {} }]),
|
||||||
archiveLogs: vi.fn(() => ({ days: [], vacuumed: false })),
|
archiveLogs: vi.fn(() => ({ days: [], vacuumed: false })),
|
||||||
close: vi.fn(),
|
close: vi.fn(),
|
||||||
|
getAllWorkflowRuns: vi.fn(() => []),
|
||||||
};
|
};
|
||||||
return store;
|
return store;
|
||||||
}
|
}
|
||||||
@@ -127,7 +128,7 @@ describe("WorkflowManager — crash recovery (Phase 3)", () => {
|
|||||||
child.emit("exit", 1, null);
|
child.emit("exit", 1, null);
|
||||||
|
|
||||||
const crashedCalls = logStore.upsertWorkflowRun.mock.calls.filter(
|
const crashedCalls = logStore.upsertWorkflowRun.mock.calls.filter(
|
||||||
([entry]: [{ type: string }]) => entry.type === "crashed",
|
(args: any[]) => (args[0] as { type: string }).type === "crashed",
|
||||||
);
|
);
|
||||||
expect(crashedCalls).toHaveLength(2);
|
expect(crashedCalls).toHaveLength(2);
|
||||||
|
|
||||||
@@ -216,10 +217,10 @@ describe("WorkflowManager — crash recovery (Phase 3)", () => {
|
|||||||
|
|
||||||
// resume-thread should have been sent
|
// resume-thread should have been sent
|
||||||
const resumeCalls = (secondChild.send as ReturnType<typeof vi.fn>).mock.calls.filter(
|
const resumeCalls = (secondChild.send as ReturnType<typeof vi.fn>).mock.calls.filter(
|
||||||
([msg]: [unknown]) =>
|
(args: any[]) =>
|
||||||
msg !== null &&
|
args[0] !== null &&
|
||||||
typeof msg === "object" &&
|
typeof args[0] === "object" &&
|
||||||
(msg as Record<string, unknown>).type === "resume-thread",
|
(args[0] as Record<string, unknown>).type === "resume-thread",
|
||||||
);
|
);
|
||||||
expect(resumeCalls).toHaveLength(1);
|
expect(resumeCalls).toHaveLength(1);
|
||||||
expect(resumeCalls[0][0]).toMatchObject({
|
expect(resumeCalls[0][0]).toMatchObject({
|
||||||
@@ -286,7 +287,7 @@ describe("WorkflowManager — crash recovery (Phase 3)", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const appendCalls = logStore.append.mock.calls.filter(
|
const appendCalls = logStore.append.mock.calls.filter(
|
||||||
([entry]: [{ type: string }]) => entry.type === "thread_command_event",
|
(args: any[]) => (args[0] as { type: string }).type === "thread_command_event",
|
||||||
);
|
);
|
||||||
expect(appendCalls).toHaveLength(1);
|
expect(appendCalls).toHaveLength(1);
|
||||||
expect(appendCalls[0][0]).toMatchObject({
|
expect(appendCalls[0][0]).toMatchObject({
|
||||||
@@ -313,7 +314,7 @@ describe("WorkflowManager — crash recovery (Phase 3)", () => {
|
|||||||
mgr.startWorkflow("my-wf", payload);
|
mgr.startWorkflow("my-wf", payload);
|
||||||
|
|
||||||
const startedCall = logStore.upsertWorkflowRun.mock.calls.find(
|
const startedCall = logStore.upsertWorkflowRun.mock.calls.find(
|
||||||
([entry]: [{ type: string }]) => entry.type === "started",
|
(args: any[]) => (args[0] as { type: string }).type === "started",
|
||||||
);
|
);
|
||||||
expect(startedCall).toBeDefined();
|
expect(startedCall).toBeDefined();
|
||||||
const logEntry = startedCall?.[0] as { payload: string | null };
|
const logEntry = startedCall?.[0] as { payload: string | null };
|
||||||
|
|||||||
@@ -79,6 +79,7 @@ function makeLogStore() {
|
|||||||
getThreadEvents: vi.fn(() => []),
|
getThreadEvents: vi.fn(() => []),
|
||||||
archiveLogs: vi.fn(() => ({ days: [], vacuumed: false })),
|
archiveLogs: vi.fn(() => ({ days: [], vacuumed: false })),
|
||||||
close: vi.fn(),
|
close: vi.fn(),
|
||||||
|
getAllWorkflowRuns: vi.fn(() => []),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -126,7 +127,7 @@ describe("WorkflowManager — drainAndRespawn (Phase 3 hot reload)", () => {
|
|||||||
await drainPromise;
|
await drainPromise;
|
||||||
|
|
||||||
const interruptedCalls = logStore.upsertWorkflowRun.mock.calls.filter(
|
const interruptedCalls = logStore.upsertWorkflowRun.mock.calls.filter(
|
||||||
([entry]: [{ type: string }]) => entry.type === "interrupted",
|
(args: any[]) => (args[0] as { type: string }).type === "interrupted",
|
||||||
);
|
);
|
||||||
expect(interruptedCalls).toHaveLength(2);
|
expect(interruptedCalls).toHaveLength(2);
|
||||||
|
|
||||||
@@ -190,10 +191,10 @@ describe("WorkflowManager — drainAndRespawn (Phase 3 hot reload)", () => {
|
|||||||
|
|
||||||
const newChild = mockChildren[1];
|
const newChild = mockChildren[1];
|
||||||
const resumeCalls = (newChild.send as ReturnType<typeof vi.fn>).mock.calls.filter(
|
const resumeCalls = (newChild.send as ReturnType<typeof vi.fn>).mock.calls.filter(
|
||||||
([msg]: [unknown]) =>
|
(args: any[]) =>
|
||||||
msg !== null &&
|
args[0] !== null &&
|
||||||
typeof msg === "object" &&
|
typeof args[0] === "object" &&
|
||||||
(msg as Record<string, unknown>).type === "resume-thread",
|
(args[0] as Record<string, unknown>).type === "resume-thread",
|
||||||
);
|
);
|
||||||
expect(resumeCalls).toHaveLength(0);
|
expect(resumeCalls).toHaveLength(0);
|
||||||
|
|
||||||
@@ -218,10 +219,10 @@ describe("WorkflowManager — drainAndRespawn (Phase 3 hot reload)", () => {
|
|||||||
|
|
||||||
const newChild = mockChildren[1];
|
const newChild = mockChildren[1];
|
||||||
const startCalls = (newChild.send as ReturnType<typeof vi.fn>).mock.calls.filter(
|
const startCalls = (newChild.send as ReturnType<typeof vi.fn>).mock.calls.filter(
|
||||||
([msg]: [unknown]) =>
|
(args: any[]) =>
|
||||||
msg !== null &&
|
args[0] !== null &&
|
||||||
typeof msg === "object" &&
|
typeof args[0] === "object" &&
|
||||||
(msg as Record<string, unknown>).type === "start-thread",
|
(args[0] as Record<string, unknown>).type === "start-thread",
|
||||||
);
|
);
|
||||||
expect(startCalls).toHaveLength(1);
|
expect(startCalls).toHaveLength(1);
|
||||||
|
|
||||||
@@ -266,7 +267,7 @@ describe("Kernel — workflow hot reload via file-watcher (Phase 3)", () => {
|
|||||||
// Kernel's handleWorkflowFileChange should log a workflow_reload event
|
// Kernel's handleWorkflowFileChange should log a workflow_reload event
|
||||||
// We test this via the kernel itself
|
// We test this via the kernel itself
|
||||||
const appendCalls = logStore.append.mock.calls;
|
const appendCalls = logStore.append.mock.calls;
|
||||||
const startCall = appendCalls.find(([e]: [{ type: string }]) => e.type === "start");
|
const startCall = appendCalls.find((args: any[]) => (args[0] as { type: string }).type === "start");
|
||||||
expect(startCall).toBeDefined();
|
expect(startCall).toBeDefined();
|
||||||
|
|
||||||
const stopPromise = kernel.stop();
|
const stopPromise = kernel.stop();
|
||||||
|
|||||||
@@ -78,6 +78,7 @@ function makeLogStore() {
|
|||||||
appendWithWorkflowUpdate: vi.fn(),
|
appendWithWorkflowUpdate: vi.fn(),
|
||||||
getWorkflowRun: vi.fn(() => null),
|
getWorkflowRun: vi.fn(() => null),
|
||||||
getActiveWorkflowRuns: vi.fn(() => []),
|
getActiveWorkflowRuns: vi.fn(() => []),
|
||||||
|
getAllWorkflowRuns: vi.fn(() => []),
|
||||||
getTriggerPayload: vi.fn(() => null),
|
getTriggerPayload: vi.fn(() => null),
|
||||||
getThreadEvents: vi.fn(() => []),
|
getThreadEvents: vi.fn(() => []),
|
||||||
archiveLogs: vi.fn(() => ({ days: [], vacuumed: false })),
|
archiveLogs: vi.fn(() => ({ days: [], vacuumed: false })),
|
||||||
@@ -137,10 +138,10 @@ describe("kernel + workflowManager integration", () => {
|
|||||||
// We need to check that a start-thread message was sent to the workflow worker
|
// We need to check that a start-thread message was sent to the workflow worker
|
||||||
const workflowWorker = mockChildren.find((c) =>
|
const workflowWorker = mockChildren.find((c) =>
|
||||||
(c.send as ReturnType<typeof vi.fn>).mock.calls.some(
|
(c.send as ReturnType<typeof vi.fn>).mock.calls.some(
|
||||||
([msg]: [unknown]) =>
|
(args: unknown[]) =>
|
||||||
msg !== null &&
|
args[0] !== null &&
|
||||||
typeof msg === "object" &&
|
typeof args[0] === "object" &&
|
||||||
(msg as Record<string, unknown>).type === "start-thread",
|
(args[0] as Record<string, unknown>).type === "start-thread",
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
expect(workflowWorker).toBeDefined();
|
expect(workflowWorker).toBeDefined();
|
||||||
@@ -212,10 +213,10 @@ describe("kernel + workflowManager integration", () => {
|
|||||||
// No workflow worker should have been spawned (only the sense group worker)
|
// No workflow worker should have been spawned (only the sense group worker)
|
||||||
const workflowWorkerSpawned = mockChildren.some((c) =>
|
const workflowWorkerSpawned = mockChildren.some((c) =>
|
||||||
(c.send as ReturnType<typeof vi.fn>).mock.calls.some(
|
(c.send as ReturnType<typeof vi.fn>).mock.calls.some(
|
||||||
([msg]: [unknown]) =>
|
(args: unknown[]) =>
|
||||||
msg !== null &&
|
args[0] !== null &&
|
||||||
typeof msg === "object" &&
|
typeof args[0] === "object" &&
|
||||||
(msg as Record<string, unknown>).type === "start-thread",
|
(args[0] as Record<string, unknown>).type === "start-thread",
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
expect(workflowWorkerSpawned).toBe(false);
|
expect(workflowWorkerSpawned).toBe(false);
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import { describe, expect, it } from "vitest";
|
|||||||
import { createBlobStore } from "../blob-store.js";
|
import { createBlobStore } from "../blob-store.js";
|
||||||
import { parseParentMessage } from "../ipc.js";
|
import { parseParentMessage } from "../ipc.js";
|
||||||
import { executeCompute, openPeerDb, openSenseDb, runMigrations } from "../sense-runtime.js";
|
import { executeCompute, openPeerDb, openSenseDb, runMigrations } from "../sense-runtime.js";
|
||||||
import type { DrizzleDB, PeerMap, SenseRuntime } from "../sense-runtime.js";
|
import type { ComputeFn, DrizzleDB, PeerMap, SenseRuntime } from "../sense-runtime.js";
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// Helpers
|
// Helpers
|
||||||
@@ -168,7 +168,7 @@ describe("openPeerDb", () => {
|
|||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
describe("executeCompute", () => {
|
describe("executeCompute", () => {
|
||||||
function makeRuntime(computeFn: (db: DrizzleDB, peers: PeerMap) => Promise<unknown | null>): {
|
function makeRuntime(computeFn: ComputeFn): {
|
||||||
runtime: SenseRuntime;
|
runtime: SenseRuntime;
|
||||||
sqlite: Database.Database;
|
sqlite: Database.Database;
|
||||||
} {
|
} {
|
||||||
|
|||||||
@@ -76,6 +76,7 @@ function makeLogStore() {
|
|||||||
getThreadEvents: vi.fn(() => []),
|
getThreadEvents: vi.fn(() => []),
|
||||||
archiveLogs: vi.fn(() => ({ days: [], vacuumed: false })),
|
archiveLogs: vi.fn(() => ({ days: [], vacuumed: false })),
|
||||||
close: vi.fn(),
|
close: vi.fn(),
|
||||||
|
getAllWorkflowRuns: vi.fn(() => []),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Generated
-3
@@ -27,9 +27,6 @@ importers:
|
|||||||
specifier: ^0.1.6
|
specifier: ^0.1.6
|
||||||
version: 0.1.6
|
version: 0.1.6
|
||||||
devDependencies:
|
devDependencies:
|
||||||
'@types/better-sqlite3':
|
|
||||||
specifier: ^7.6.13
|
|
||||||
version: 7.6.13
|
|
||||||
'@types/node':
|
'@types/node':
|
||||||
specifier: ^22.0.0
|
specifier: ^22.0.0
|
||||||
version: 22.19.17
|
version: 22.19.17
|
||||||
|
|||||||
Reference in New Issue
Block a user