@neotx/core 0.1.0-alpha.1 → 0.1.0-alpha.10

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/dist/index.d.ts CHANGED
@@ -86,14 +86,21 @@ declare const mcpServerConfigSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
86
86
  args: z.ZodOptional<z.ZodArray<z.ZodString>>;
87
87
  env: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
88
88
  }, z.core.$strip>], "type">;
89
+ declare const gitStrategySchema: z.ZodDefault<z.ZodEnum<{
90
+ pr: "pr";
91
+ branch: "branch";
92
+ }>>;
93
+ type GitStrategy = z.infer<typeof gitStrategySchema>;
89
94
  declare const repoConfigSchema: z.ZodObject<{
90
95
  path: z.ZodString;
91
96
  name: z.ZodOptional<z.ZodString>;
92
97
  defaultBranch: z.ZodDefault<z.ZodString>;
93
98
  branchPrefix: z.ZodDefault<z.ZodString>;
94
99
  pushRemote: z.ZodDefault<z.ZodString>;
95
- autoCreatePr: z.ZodDefault<z.ZodBoolean>;
96
- prBaseBranch: z.ZodOptional<z.ZodString>;
100
+ gitStrategy: z.ZodDefault<z.ZodEnum<{
101
+ pr: "pr";
102
+ branch: "branch";
103
+ }>>;
97
104
  }, z.core.$strip>;
98
105
  declare const globalConfigSchema: z.ZodObject<{
99
106
  repos: z.ZodDefault<z.ZodArray<z.ZodObject<{
@@ -102,8 +109,10 @@ declare const globalConfigSchema: z.ZodObject<{
102
109
  defaultBranch: z.ZodDefault<z.ZodString>;
103
110
  branchPrefix: z.ZodDefault<z.ZodString>;
104
111
  pushRemote: z.ZodDefault<z.ZodString>;
105
- autoCreatePr: z.ZodDefault<z.ZodBoolean>;
106
- prBaseBranch: z.ZodOptional<z.ZodString>;
112
+ gitStrategy: z.ZodDefault<z.ZodEnum<{
113
+ pr: "pr";
114
+ branch: "branch";
115
+ }>>;
107
116
  }, z.core.$strip>>>;
108
117
  concurrency: z.ZodDefault<z.ZodObject<{
109
118
  maxSessions: z.ZodDefault<z.ZodNumber>;
@@ -121,6 +130,7 @@ declare const globalConfigSchema: z.ZodObject<{
121
130
  sessions: z.ZodDefault<z.ZodObject<{
122
131
  initTimeoutMs: z.ZodDefault<z.ZodNumber>;
123
132
  maxDurationMs: z.ZodDefault<z.ZodNumber>;
133
+ dir: z.ZodDefault<z.ZodString>;
124
134
  }, z.core.$strip>>;
125
135
  webhooks: z.ZodDefault<z.ZodArray<z.ZodObject<{
126
136
  url: z.ZodString;
@@ -131,14 +141,18 @@ declare const globalConfigSchema: z.ZodObject<{
131
141
  supervisor: z.ZodDefault<z.ZodObject<{
132
142
  port: z.ZodDefault<z.ZodNumber>;
133
143
  secret: z.ZodOptional<z.ZodString>;
134
- idleIntervalMs: z.ZodDefault<z.ZodNumber>;
135
- idleSkipMax: z.ZodDefault<z.ZodNumber>;
136
144
  heartbeatTimeoutMs: z.ZodDefault<z.ZodNumber>;
137
145
  maxConsecutiveFailures: z.ZodDefault<z.ZodNumber>;
138
146
  maxEventsPerSec: z.ZodDefault<z.ZodNumber>;
139
147
  dailyCapUsd: z.ZodDefault<z.ZodNumber>;
148
+ consolidationIntervalMs: z.ZodDefault<z.ZodNumber>;
149
+ compactionIntervalMs: z.ZodDefault<z.ZodNumber>;
150
+ eventTimeoutMs: z.ZodDefault<z.ZodNumber>;
140
151
  instructions: z.ZodOptional<z.ZodString>;
141
152
  }, z.core.$strip>>;
153
+ memory: z.ZodDefault<z.ZodObject<{
154
+ embeddings: z.ZodDefault<z.ZodBoolean>;
155
+ }, z.core.$strip>>;
142
156
  mcpServers: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodDiscriminatedUnion<[z.ZodObject<{
143
157
  type: z.ZodLiteral<"http">;
144
158
  url: z.ZodString;
@@ -166,8 +180,10 @@ declare const neoConfigSchema: z.ZodObject<{
166
180
  defaultBranch: z.ZodDefault<z.ZodString>;
167
181
  branchPrefix: z.ZodDefault<z.ZodString>;
168
182
  pushRemote: z.ZodDefault<z.ZodString>;
169
- autoCreatePr: z.ZodDefault<z.ZodBoolean>;
170
- prBaseBranch: z.ZodOptional<z.ZodString>;
183
+ gitStrategy: z.ZodDefault<z.ZodEnum<{
184
+ pr: "pr";
185
+ branch: "branch";
186
+ }>>;
171
187
  }, z.core.$strip>>>;
172
188
  concurrency: z.ZodDefault<z.ZodObject<{
173
189
  maxSessions: z.ZodDefault<z.ZodNumber>;
@@ -185,6 +201,7 @@ declare const neoConfigSchema: z.ZodObject<{
185
201
  sessions: z.ZodDefault<z.ZodObject<{
186
202
  initTimeoutMs: z.ZodDefault<z.ZodNumber>;
187
203
  maxDurationMs: z.ZodDefault<z.ZodNumber>;
204
+ dir: z.ZodDefault<z.ZodString>;
188
205
  }, z.core.$strip>>;
189
206
  webhooks: z.ZodDefault<z.ZodArray<z.ZodObject<{
190
207
  url: z.ZodString;
@@ -195,14 +212,18 @@ declare const neoConfigSchema: z.ZodObject<{
195
212
  supervisor: z.ZodDefault<z.ZodObject<{
196
213
  port: z.ZodDefault<z.ZodNumber>;
197
214
  secret: z.ZodOptional<z.ZodString>;
198
- idleIntervalMs: z.ZodDefault<z.ZodNumber>;
199
- idleSkipMax: z.ZodDefault<z.ZodNumber>;
200
215
  heartbeatTimeoutMs: z.ZodDefault<z.ZodNumber>;
201
216
  maxConsecutiveFailures: z.ZodDefault<z.ZodNumber>;
202
217
  maxEventsPerSec: z.ZodDefault<z.ZodNumber>;
203
218
  dailyCapUsd: z.ZodDefault<z.ZodNumber>;
219
+ consolidationIntervalMs: z.ZodDefault<z.ZodNumber>;
220
+ compactionIntervalMs: z.ZodDefault<z.ZodNumber>;
221
+ eventTimeoutMs: z.ZodDefault<z.ZodNumber>;
204
222
  instructions: z.ZodOptional<z.ZodString>;
205
223
  }, z.core.$strip>>;
224
+ memory: z.ZodDefault<z.ZodObject<{
225
+ embeddings: z.ZodDefault<z.ZodBoolean>;
226
+ }, z.core.$strip>>;
206
227
  mcpServers: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodDiscriminatedUnion<[z.ZodObject<{
207
228
  type: z.ZodLiteral<"http">;
208
229
  url: z.ZodString;
@@ -255,6 +276,7 @@ interface AgentDefinition {
255
276
  prompt: string;
256
277
  tools: string[];
257
278
  model: string;
279
+ mcpServers?: string[] | undefined;
258
280
  }
259
281
  interface ResolvedAgent {
260
282
  name: string;
@@ -295,7 +317,7 @@ interface PersistedRun {
295
317
  repo: string;
296
318
  prompt: string;
297
319
  branch?: string | undefined;
298
- worktreePath?: string | undefined;
320
+ sessionPath?: string | undefined;
299
321
  pid?: number | undefined;
300
322
  status: "running" | "paused" | "completed" | "failed";
301
323
  steps: Record<string, StepResult>;
@@ -308,6 +330,8 @@ interface StepResult {
308
330
  sessionId?: string | undefined;
309
331
  output?: unknown;
310
332
  rawOutput?: string | undefined;
333
+ prUrl?: string | undefined;
334
+ prNumber?: number | undefined;
311
335
  costUsd: number;
312
336
  durationMs: number;
313
337
  agent: string;
@@ -322,10 +346,12 @@ interface DispatchInput {
322
346
  repo: string;
323
347
  prompt: string;
324
348
  runId?: string | undefined;
349
+ branch?: string | undefined;
325
350
  step?: string | undefined;
326
351
  from?: string | undefined;
327
352
  retry?: string | undefined;
328
353
  priority?: Priority | undefined;
354
+ gitStrategy?: "pr" | "branch" | undefined;
329
355
  overrides?: {
330
356
  agents?: Record<string, string> | undefined;
331
357
  maxTurns?: number | undefined;
@@ -357,7 +383,7 @@ interface ActiveSession {
357
383
  repo: string;
358
384
  status: "running" | "queued" | "waiting_gate";
359
385
  startedAt: string;
360
- worktreePath?: string | undefined;
386
+ sessionPath?: string | undefined;
361
387
  }
362
388
  interface OrchestratorStatus {
363
389
  paused: boolean;
@@ -611,15 +637,13 @@ declare class Semaphore {
611
637
  */
612
638
  declare class CostJournal {
613
639
  private readonly dir;
614
- private dirCreated;
640
+ private readonly dirCache;
615
641
  private dayCache;
616
642
  constructor(options: {
617
643
  dir: string;
618
644
  });
619
645
  append(entry: CostEntry): Promise<void>;
620
646
  getDayTotal(date?: Date): Promise<number>;
621
- private fileForDate;
622
- private ensureDir;
623
647
  }
624
648
 
625
649
  /**
@@ -646,28 +670,31 @@ declare class NeoEventEmitter {
646
670
  */
647
671
  declare class EventJournal {
648
672
  private readonly dir;
649
- private dirCreated;
673
+ private readonly dirCache;
650
674
  constructor(options: {
651
675
  dir: string;
652
676
  });
653
677
  append(event: NeoEvent): Promise<void>;
654
- private fileForDate;
655
- private ensureDir;
656
678
  }
657
679
 
658
680
  type WebhookConfig = NeoConfig["webhooks"][number];
659
681
  /**
660
- * Fire-and-forget webhook dispatcher for NeoEvents.
682
+ * Webhook dispatcher for NeoEvents.
661
683
  *
662
684
  * - Matches events against per-webhook filters (exact or wildcard like "session:*")
663
685
  * - Excludes gate:waiting events (contain non-serializable callbacks)
664
686
  * - Signs payloads with HMAC-SHA256 when a secret is configured
665
- * - Never throws errors are silently swallowed (consistent with EventJournal)
687
+ * - Terminal events (session:complete, session:fail, budget:alert) are retried
688
+ * with exponential backoff on failure
689
+ * - Non-terminal events remain fire-and-forget
666
690
  */
667
691
  declare class WebhookDispatcher {
668
692
  private readonly webhooks;
693
+ private readonly pending;
669
694
  constructor(webhooks: WebhookConfig[]);
670
695
  dispatch(event: NeoEvent): void;
696
+ /** Wait for all pending terminal webhook deliveries to complete. */
697
+ flush(): Promise<void>;
671
698
  }
672
699
  /**
673
700
  * Check if an event type matches a filter list.
@@ -676,27 +703,48 @@ declare class WebhookDispatcher {
676
703
  */
677
704
  declare function matchesFilter(eventType: string, filters?: string[]): boolean;
678
705
 
706
+ interface SessionCloneInfo {
707
+ path: string;
708
+ branch: string;
709
+ repoPath: string;
710
+ }
711
+ /**
712
+ * Create an isolated git clone for an agent session.
713
+ * Uses `git clone --local` to hardlink objects (fast, no network).
714
+ * Then checks out the target branch (existing or new).
715
+ */
716
+ declare function createSessionClone(options: {
717
+ repoPath: string;
718
+ branch: string;
719
+ baseBranch: string;
720
+ sessionDir: string;
721
+ }): Promise<SessionCloneInfo>;
722
+ /**
723
+ * Remove a session clone directory.
724
+ * Idempotent — does not throw if the directory is already gone.
725
+ */
726
+ declare function removeSessionClone(sessionPath: string): Promise<void>;
727
+ /**
728
+ * List all session clones under a base directory.
729
+ */
730
+ declare function listSessionClones(sessionsBaseDir: string): Promise<SessionCloneInfo[]>;
731
+
679
732
  declare function createBranch(repoPath: string, branch: string, baseBranch: string): Promise<void>;
680
733
  declare function pushBranch(repoPath: string, branch: string, remote: string): Promise<void>;
681
734
  declare function fetchRemote(repoPath: string, remote: string): Promise<void>;
682
735
  declare function deleteBranch(repoPath: string, branch: string): Promise<void>;
683
736
  declare function getCurrentBranch(repoPath: string): Promise<string>;
684
737
  /**
685
- * Generate a deterministic branch name for a run.
686
- * Uses the repo's branchPrefix (default "feat") and the runId.
687
- */
688
- declare function getBranchName(config: RepoConfig, runId: string): string;
689
-
690
- /**
691
- * Per-repository in-memory mutex to serialise git operations.
692
- * Concurrent git commands on the same repo corrupt the index — this prevents that.
738
+ * Resolve the branch name for a run.
739
+ * If an explicit branch is provided, use it as-is.
740
+ * Otherwise, generate a deterministic name from the repo's branchPrefix and runId.
693
741
  */
742
+ declare function getBranchName(config: RepoConfig, runId: string, branch?: string): string;
694
743
  /**
695
- * Execute `fn` while holding an exclusive lock for `repoPath`.
696
- * Concurrent calls for the same repo are queued and executed serially.
697
- * Operations on different repos run in parallel.
744
+ * Push a branch from a session clone to a remote. Silently succeeds if
745
+ * the branch has no new commits to push.
698
746
  */
699
- declare function withGitLock<T>(repoPath: string, fn: () => Promise<T>): Promise<T>;
747
+ declare function pushSessionBranch(sessionPath: string, branch: string, remote: string): Promise<void>;
700
748
 
701
749
  /**
702
750
  * SDK-compatible sandbox configuration.
@@ -715,40 +763,10 @@ interface SandboxConfig {
715
763
  /**
716
764
  * Build an SDK-compatible sandbox configuration for an agent.
717
765
  *
718
- * - Writable agents: all their tools are allowed, write paths include the worktree
766
+ * - Writable agents: all their tools are allowed, write paths include the session clone
719
767
  * - Readonly agents: write tools are filtered out, no writable paths
720
768
  */
721
- declare function buildSandboxConfig(agent: ResolvedAgent, worktreePath?: string): SandboxConfig;
722
-
723
- interface WorktreeInfo {
724
- path: string;
725
- branch: string;
726
- repoPath: string;
727
- }
728
- /**
729
- * Create a new git worktree with an associated branch.
730
- * Creates the branch from baseBranch, then adds the worktree at worktreeDir.
731
- */
732
- declare function createWorktree(options: {
733
- repoPath: string;
734
- branch: string;
735
- baseBranch: string;
736
- worktreeDir: string;
737
- }): Promise<WorktreeInfo>;
738
- /**
739
- * Remove a worktree. Does NOT delete the branch (branch stays for the PR).
740
- * Idempotent — does not throw if the worktree is already gone.
741
- */
742
- declare function removeWorktree(worktreePath: string): Promise<void>;
743
- /**
744
- * List all worktrees for a repository.
745
- */
746
- declare function listWorktrees(repoPath: string): Promise<WorktreeInfo[]>;
747
- /**
748
- * Clean up worktrees under worktreeBaseDir that no longer have a matching run.
749
- * Removes any subdirectory that is a git worktree.
750
- */
751
- declare function cleanupOrphanedWorktrees(worktreeBaseDir: string): Promise<void>;
769
+ declare function buildSandboxConfig(agent: ResolvedAgent, sessionPath?: string): SandboxConfig;
752
770
 
753
771
  /**
754
772
  * Audit log middleware.
@@ -817,6 +835,8 @@ interface OrchestratorOptions {
817
835
  journalDir?: string | undefined;
818
836
  builtInWorkflowDir?: string | undefined;
819
837
  customWorkflowDir?: string | undefined;
838
+ /** Skip orphan recovery on start — workers should set this to true to avoid false orphan detection on concurrent launches. */
839
+ skipOrphanRecovery?: boolean | undefined;
820
840
  }
821
841
  declare class Orchestrator extends NeoEventEmitter {
822
842
  private readonly config;
@@ -828,17 +848,19 @@ declare class Orchestrator extends NeoEventEmitter {
828
848
  private readonly idempotencyCache;
829
849
  private readonly abortControllers;
830
850
  private readonly repoIndex;
831
- private readonly createdRunDirs;
851
+ private readonly runStore;
832
852
  private readonly journalDir;
833
853
  private readonly builtInWorkflowDir;
834
854
  private readonly customWorkflowDir;
835
855
  private costJournal;
836
856
  private eventJournal;
837
857
  private webhookDispatcher;
858
+ private memoryStore;
838
859
  private _paused;
839
860
  private _costToday;
840
861
  private _startedAt;
841
862
  private _drainResolve;
863
+ private readonly skipOrphanRecovery;
842
864
  constructor(config: NeoConfig, options?: OrchestratorOptions);
843
865
  registerWorkflow(definition: WorkflowDefinition): void;
844
866
  registerAgent(agent: ResolvedAgent): void;
@@ -870,12 +892,14 @@ declare class Orchestrator extends NeoEventEmitter {
870
892
  private buildDispatchContext;
871
893
  private executeStep;
872
894
  /**
873
- * Push the branch, then remove the worktree.
895
+ * Push the branch (writable only), then remove the session clone.
874
896
  * Runs in `finally` so it executes on both success and failure.
875
897
  */
876
- private finalizeWorktree;
898
+ private finalizeSession;
877
899
  private runAgentSession;
878
900
  private finalizeDispatch;
901
+ private getMemoryStore;
902
+ private loadMemoryContext;
879
903
  private emitCostEvents;
880
904
  private emitSessionComplete;
881
905
  private emitSessionFail;
@@ -885,8 +909,10 @@ declare class Orchestrator extends NeoEventEmitter {
885
909
  private getFirstStep;
886
910
  private resolveStepAgent;
887
911
  private resolveRepo;
888
- private buildMiddlewareContext;
889
912
  private computeBudgetRemainingPct;
913
+ private resolveMcpServers;
914
+ /** Discover running supervisor daemons and return webhook configs for their endpoints. */
915
+ private discoverSupervisorWebhooks;
890
916
  private persistRun;
891
917
  private recoverOrphanedRuns;
892
918
  }
@@ -930,7 +956,6 @@ declare function getSupervisorDir(name: string): string;
930
956
  * Path to a supervisor state file: ~/.neo/supervisors/<name>/state.json
931
957
  */
932
958
  declare function getSupervisorStatePath(name: string): string;
933
- declare function getSupervisorMemoryPath(name: string): string;
934
959
  declare function getSupervisorActivityPath(name: string): string;
935
960
  declare function getSupervisorInboxPath(name: string): string;
936
961
  declare function getSupervisorEventsPath(name: string): string;
@@ -940,9 +965,12 @@ interface ParsedOutput {
940
965
  rawOutput: string;
941
966
  output?: unknown;
942
967
  parseError?: string;
968
+ prUrl?: string;
969
+ prNumber?: number;
943
970
  }
944
971
  /**
945
972
  * Parse agent output, optionally validating against a Zod schema.
973
+ * Also extracts structured markers like PR_URL from the output.
946
974
  *
947
975
  * - If no schema: returns rawOutput only
948
976
  * - If schema provided: extracts JSON from output, validates with schema
@@ -954,10 +982,11 @@ interface SessionOptions {
954
982
  agent: ResolvedAgent;
955
983
  prompt: string;
956
984
  repoPath?: string;
957
- worktreePath?: string;
985
+ sessionPath?: string;
958
986
  sandboxConfig: SandboxConfig;
959
987
  hooks?: Record<string, unknown>;
960
- mcpServers?: McpServerConfig[];
988
+ mcpServers?: Record<string, McpServerConfig>;
989
+ env?: Record<string, string>;
961
990
  initTimeoutMs: number;
962
991
  maxDurationMs: number;
963
992
  resumeSessionId?: string | undefined;
@@ -1007,9 +1036,80 @@ interface RecoveryOptions extends SessionOptions {
1007
1036
  */
1008
1037
  declare function runWithRecovery(options: RecoveryOptions): Promise<SessionResult>;
1009
1038
 
1039
+ interface SessionExecutionInput {
1040
+ runId: string;
1041
+ sessionId: string;
1042
+ agent: ResolvedAgent;
1043
+ stepDef: WorkflowStepDef;
1044
+ repoConfig: RepoConfig;
1045
+ repoPath: string;
1046
+ prompt: string;
1047
+ branch?: string | undefined;
1048
+ gitStrategy: GitStrategy;
1049
+ sessionPath?: string | undefined;
1050
+ metadata?: Record<string, unknown> | undefined;
1051
+ startedAt: string;
1052
+ }
1053
+ interface SessionExecutionConfig {
1054
+ initTimeoutMs: number;
1055
+ maxDurationMs: number;
1056
+ maxRetries: number;
1057
+ backoffBaseMs: number;
1058
+ }
1059
+ interface SessionExecutionDeps {
1060
+ middleware: Middleware[];
1061
+ mcpServers?: Record<string, McpServerConfig> | undefined;
1062
+ memoryContext?: string | undefined;
1063
+ onAttempt?: (attempt: number, strategy: string) => void;
1064
+ }
1065
+ interface SessionExecutionResult extends StepResult {
1066
+ parsed: ParsedOutput;
1067
+ }
1068
+ declare function loadRepoInstructions(repoPath: string): Promise<string | undefined>;
1069
+ declare function buildGitStrategyInstructions(strategy: GitStrategy, agent: ResolvedAgent, branch: string, baseBranch: string, remote: string, metadata?: Record<string, unknown>): string | null;
1070
+ declare function buildReportingInstructions(_runId: string): string;
1071
+ declare function buildFullPrompt(agentPrompt: string | undefined, repoInstructions: string | undefined, gitInstructions: string | null, taskPrompt: string, memoryContext?: string | undefined, cwdInstructions?: string | undefined, reportingInstructions?: string | undefined): string;
1072
+ /**
1073
+ * Encapsulates session execution logic: prompt building, SDK calls, and response processing.
1074
+ * Extracted from Orchestrator for better testability and separation of concerns.
1075
+ */
1076
+ declare class SessionExecutor {
1077
+ private readonly config;
1078
+ private readonly getContextValue;
1079
+ constructor(config: SessionExecutionConfig, getContextValue: (key: string) => unknown);
1080
+ /**
1081
+ * Execute an agent session with the given input and dependencies.
1082
+ * Handles prompt building, SDK invocation via recovery wrapper, and output parsing.
1083
+ */
1084
+ execute(input: SessionExecutionInput, deps: SessionExecutionDeps): Promise<SessionExecutionResult>;
1085
+ }
1086
+
1087
+ /**
1088
+ * Checks whether a process with the given PID is currently running.
1089
+ *
1090
+ * Uses the POSIX signal 0 trick: `process.kill(pid, 0)` doesn't actually
1091
+ * send a signal but checks whether the process exists and the current
1092
+ * process has permission to signal it. If the process doesn't exist,
1093
+ * an ESRCH error is thrown.
1094
+ *
1095
+ * @param pid - The process ID to check. Must be a positive integer.
1096
+ * @returns `true` if the process is alive and accessible, `false` otherwise.
1097
+ *
1098
+ * @example
1099
+ * ```ts
1100
+ * import { isProcessAlive } from "@/shared/process";
1101
+ *
1102
+ * // Check if current process is alive (always true)
1103
+ * isProcessAlive(process.pid); // => true
1104
+ *
1105
+ * // Check if a non-existent process is alive
1106
+ * isProcessAlive(999999); // => false
1107
+ * ```
1108
+ */
1109
+ declare function isProcessAlive(pid: number): boolean;
1110
+
1010
1111
  declare const supervisorDaemonStateSchema: z.ZodObject<{
1011
1112
  pid: z.ZodNumber;
1012
- tmuxSession: z.ZodString;
1013
1113
  sessionId: z.ZodString;
1014
1114
  port: z.ZodNumber;
1015
1115
  cwd: z.ZodString;
@@ -1020,11 +1120,21 @@ declare const supervisorDaemonStateSchema: z.ZodObject<{
1020
1120
  todayCostUsd: z.ZodDefault<z.ZodNumber>;
1021
1121
  costResetDate: z.ZodOptional<z.ZodString>;
1022
1122
  idleSkipCount: z.ZodDefault<z.ZodNumber>;
1123
+ activeWorkSkipCount: z.ZodDefault<z.ZodNumber>;
1023
1124
  status: z.ZodDefault<z.ZodEnum<{
1024
1125
  running: "running";
1025
1126
  draining: "draining";
1026
1127
  stopped: "stopped";
1027
1128
  }>>;
1129
+ lastConsolidationHeartbeat: z.ZodDefault<z.ZodNumber>;
1130
+ lastCompactionHeartbeat: z.ZodDefault<z.ZodNumber>;
1131
+ lastConsolidationTimestamp: z.ZodOptional<z.ZodString>;
1132
+ wakeReason: z.ZodOptional<z.ZodEnum<{
1133
+ events: "events";
1134
+ timer: "timer";
1135
+ active_runs: "active_runs";
1136
+ forced: "forced";
1137
+ }>>;
1028
1138
  }, z.core.$strip>;
1029
1139
  type SupervisorDaemonState = z.infer<typeof supervisorDaemonStateSchema>;
1030
1140
  declare const webhookIncomingEventSchema: z.ZodObject<{
@@ -1039,6 +1149,7 @@ type WebhookIncomingEvent = z.infer<typeof webhookIncomingEventSchema>;
1039
1149
  declare const inboxMessageSchema: z.ZodObject<{
1040
1150
  id: z.ZodString;
1041
1151
  from: z.ZodEnum<{
1152
+ agent: "agent";
1042
1153
  tui: "tui";
1043
1154
  api: "api";
1044
1155
  external: "external";
@@ -1054,19 +1165,47 @@ declare const activityEntrySchema: z.ZodObject<{
1054
1165
  error: "error";
1055
1166
  message: "message";
1056
1167
  decision: "decision";
1168
+ tool_use: "tool_use";
1057
1169
  event: "event";
1058
1170
  heartbeat: "heartbeat";
1059
1171
  action: "action";
1060
1172
  thinking: "thinking";
1061
1173
  plan: "plan";
1062
1174
  dispatch: "dispatch";
1063
- tool_use: "tool_use";
1064
1175
  }>;
1065
1176
  summary: z.ZodString;
1066
1177
  detail: z.ZodOptional<z.ZodUnknown>;
1067
1178
  timestamp: z.ZodString;
1068
1179
  }, z.core.$strip>;
1069
1180
  type ActivityEntry = z.infer<typeof activityEntrySchema>;
1181
+ declare const logBufferEntrySchema: z.ZodObject<{
1182
+ id: z.ZodString;
1183
+ type: z.ZodEnum<{
1184
+ decision: "decision";
1185
+ action: "action";
1186
+ progress: "progress";
1187
+ blocker: "blocker";
1188
+ milestone: "milestone";
1189
+ discovery: "discovery";
1190
+ }>;
1191
+ message: z.ZodString;
1192
+ agent: z.ZodOptional<z.ZodString>;
1193
+ runId: z.ZodOptional<z.ZodString>;
1194
+ repo: z.ZodOptional<z.ZodString>;
1195
+ target: z.ZodEnum<{
1196
+ memory: "memory";
1197
+ knowledge: "knowledge";
1198
+ digest: "digest";
1199
+ }>;
1200
+ timestamp: z.ZodString;
1201
+ consolidatedAt: z.ZodOptional<z.ZodString>;
1202
+ }, z.core.$strip>;
1203
+ type LogBufferEntry = z.infer<typeof logBufferEntrySchema>;
1204
+ declare const internalEventKindSchema: z.ZodEnum<{
1205
+ consolidation_timer: "consolidation_timer";
1206
+ active_run_check: "active_run_check";
1207
+ }>;
1208
+ type InternalEventKind = z.infer<typeof internalEventKindSchema>;
1070
1209
  type QueuedEvent = {
1071
1210
  kind: "webhook";
1072
1211
  data: WebhookIncomingEvent;
@@ -1077,6 +1216,10 @@ type QueuedEvent = {
1077
1216
  kind: "run_complete";
1078
1217
  runId: string;
1079
1218
  timestamp: string;
1219
+ } | {
1220
+ kind: "internal";
1221
+ eventKind: InternalEventKind;
1222
+ timestamp: string;
1080
1223
  };
1081
1224
 
1082
1225
  declare class ActivityLog {
@@ -1102,6 +1245,8 @@ declare class ActivityLog {
1102
1245
  interface SupervisorDaemonOptions {
1103
1246
  name: string;
1104
1247
  config: GlobalConfig;
1248
+ /** Path to bundled default SUPERVISOR.md (e.g. from @neotx/agents) */
1249
+ defaultInstructionsPath?: string | undefined;
1105
1250
  }
1106
1251
  /**
1107
1252
  * Orchestrates all supervisor components: webhook server, event queue,
@@ -1111,6 +1256,7 @@ declare class SupervisorDaemon {
1111
1256
  private readonly name;
1112
1257
  private readonly config;
1113
1258
  private readonly dir;
1259
+ private readonly defaultInstructionsPath;
1114
1260
  private webhookServer;
1115
1261
  private eventQueue;
1116
1262
  private heartbeatLoop;
@@ -1123,7 +1269,6 @@ declare class SupervisorDaemon {
1123
1269
  private readState;
1124
1270
  private writeState;
1125
1271
  private readLockPid;
1126
- private isProcessAlive;
1127
1272
  }
1128
1273
 
1129
1274
  interface EventQueueOptions {
@@ -1179,7 +1324,7 @@ declare class EventQueue {
1179
1324
  * Start watching inbox.jsonl and events.jsonl for new entries.
1180
1325
  * New lines are parsed and pushed into the queue.
1181
1326
  */
1182
- startWatching(inboxPath: string, eventsPath: string): void;
1327
+ startWatching(inboxPath: string, eventsPath: string): Promise<void>;
1183
1328
  stopWatching(): void;
1184
1329
  /**
1185
1330
  * Replay unprocessed events from disk on startup.
@@ -1211,15 +1356,20 @@ interface HeartbeatLoopOptions {
1211
1356
  sessionId: string;
1212
1357
  eventQueue: EventQueue;
1213
1358
  activityLog: ActivityLog;
1359
+ /** Path to bundled default SUPERVISOR.md (e.g. from @neotx/agents) */
1360
+ defaultInstructionsPath?: string | undefined;
1361
+ memoryDbPath?: string | undefined;
1214
1362
  }
1215
1363
  /**
1216
1364
  * The core autonomous loop. At each iteration:
1217
1365
  * 1. Drain events from the queue
1218
- * 2. Build a prompt with context + memory + events
1219
- * 3. Call sdk.query() for Claude to reason and act
1220
- * 4. Extract and save updated memory
1221
- * 5. Log activity
1222
- * 6. Wait for the next event or idle timeout
1366
+ * 2. Read log buffer entries
1367
+ * 3. Determine standard vs consolidation mode
1368
+ * 4. Build the appropriate prompt
1369
+ * 5. Call sdk.query() for Claude to reason and act
1370
+ * 6. Mark entries consolidated and compact log buffer (consolidation only)
1371
+ * 7. Log activity
1372
+ * 8. Wait for the next event or idle timeout
1223
1373
  */
1224
1374
  declare class HeartbeatLoop {
1225
1375
  private stopping;
@@ -1232,17 +1382,48 @@ declare class HeartbeatLoop {
1232
1382
  private readonly eventQueue;
1233
1383
  private readonly activityLog;
1234
1384
  private customInstructions;
1385
+ private readonly defaultInstructionsPath;
1386
+ private memoryStore;
1387
+ private readonly memoryDbPath;
1235
1388
  constructor(options: HeartbeatLoopOptions);
1389
+ private getMemoryStore;
1236
1390
  start(): Promise<void>;
1237
1391
  stop(): void;
1238
1392
  private runHeartbeat;
1393
+ /**
1394
+ * Check if supervisor daily budget is exceeded.
1395
+ */
1396
+ private checkBudgetExceeded;
1397
+ /**
1398
+ * Handle skip logic for idle and active-work scenarios.
1399
+ */
1400
+ private handleSkipLogic;
1401
+ /**
1402
+ * Determine heartbeat mode: compaction > consolidation > standard.
1403
+ */
1404
+ private determineHeartbeatMode;
1405
+ /**
1406
+ * Build the state update object after heartbeat completion.
1407
+ */
1408
+ private buildStateUpdate;
1409
+ /**
1410
+ * Build the prompt for the current heartbeat mode.
1411
+ */
1412
+ private buildHeartbeatModePrompt;
1413
+ /**
1414
+ * Call the Claude SDK and stream results.
1415
+ */
1416
+ private callSdk;
1239
1417
  private readState;
1240
1418
  private updateState;
1419
+ /** Read persisted run files and return summaries of active (running/paused) runs. */
1420
+ private getActiveRuns;
1241
1421
  /**
1242
1422
  * Load custom instructions from SUPERVISOR.md.
1243
1423
  * Resolution order:
1244
1424
  * 1. Explicit path via `supervisor.instructions` in config
1245
- * 2. Default: ~/.neo/SUPERVISOR.md
1425
+ * 2. User default: ~/.neo/SUPERVISOR.md
1426
+ * 3. Bundled default from @neotx/agents (if path provided)
1246
1427
  */
1247
1428
  private loadInstructions;
1248
1429
  /** Route a single SDK stream message to the appropriate log handler. */
@@ -1257,50 +1438,115 @@ declare class HeartbeatLoop {
1257
1438
  }
1258
1439
 
1259
1440
  /**
1260
- * Load the supervisor memory from disk.
1261
- * Migrates from legacy memory.md if needed.
1262
- */
1263
- declare function loadMemory(dir: string): Promise<string>;
1264
- /**
1265
- * Save the supervisor memory to disk (full overwrite).
1266
- * Automatically compacts if needed.
1267
- */
1268
- declare function saveMemory(dir: string, content: string): Promise<void>;
1269
- /**
1270
- * Extract memory content from Claude's response using <memory>...</memory> tags.
1441
+ * Append a single entry to the log buffer file.
1271
1442
  */
1272
- declare function extractMemoryFromResponse(response: string): string | null;
1273
- /**
1274
- * Check if memory content exceeds the recommended size limit.
1275
- */
1276
- declare function checkMemorySize(content: string): {
1277
- ok: boolean;
1278
- sizeKB: number;
1279
- };
1443
+ declare function appendLogBuffer(dir: string, entry: LogBufferEntry): Promise<void>;
1280
1444
 
1281
- interface HeartbeatPromptOptions {
1282
- repos: RepoConfig[];
1283
- memory: string;
1284
- knowledge: string;
1285
- memorySizeKB: number;
1286
- grouped: GroupedEvents;
1287
- budgetStatus: {
1288
- todayUsd: number;
1289
- capUsd: number;
1290
- remainingPct: number;
1291
- };
1292
- activeRuns: string[];
1293
- heartbeatCount: number;
1294
- mcpServerNames: string[];
1295
- customInstructions?: string | undefined;
1445
+ interface Embedder {
1446
+ embed(texts: string[]): Promise<number[][]>;
1447
+ readonly dimensions: number;
1448
+ }
1449
+ declare class LocalEmbedder implements Embedder {
1450
+ readonly dimensions = 384;
1451
+ embed(texts: string[]): Promise<number[][]>;
1452
+ }
1453
+
1454
+ declare const memoryTypeSchema: z.ZodEnum<{
1455
+ fact: "fact";
1456
+ procedure: "procedure";
1457
+ episode: "episode";
1458
+ focus: "focus";
1459
+ feedback: "feedback";
1460
+ task: "task";
1461
+ }>;
1462
+ type MemoryType = z.infer<typeof memoryTypeSchema>;
1463
+ declare const memoryEntrySchema: z.ZodObject<{
1464
+ id: z.ZodString;
1465
+ type: z.ZodEnum<{
1466
+ fact: "fact";
1467
+ procedure: "procedure";
1468
+ episode: "episode";
1469
+ focus: "focus";
1470
+ feedback: "feedback";
1471
+ task: "task";
1472
+ }>;
1473
+ scope: z.ZodString;
1474
+ content: z.ZodString;
1475
+ source: z.ZodString;
1476
+ tags: z.ZodDefault<z.ZodArray<z.ZodString>>;
1477
+ createdAt: z.ZodString;
1478
+ lastAccessedAt: z.ZodString;
1479
+ accessCount: z.ZodDefault<z.ZodNumber>;
1480
+ expiresAt: z.ZodOptional<z.ZodString>;
1481
+ outcome: z.ZodOptional<z.ZodString>;
1482
+ runId: z.ZodOptional<z.ZodString>;
1483
+ category: z.ZodOptional<z.ZodString>;
1484
+ severity: z.ZodOptional<z.ZodString>;
1485
+ supersedes: z.ZodOptional<z.ZodString>;
1486
+ }, z.core.$strip>;
1487
+ type MemoryEntry = z.infer<typeof memoryEntrySchema>;
1488
+ declare const memoryWriteInputSchema: z.ZodObject<{
1489
+ type: z.ZodEnum<{
1490
+ fact: "fact";
1491
+ procedure: "procedure";
1492
+ episode: "episode";
1493
+ focus: "focus";
1494
+ feedback: "feedback";
1495
+ task: "task";
1496
+ }>;
1497
+ scope: z.ZodDefault<z.ZodString>;
1498
+ content: z.ZodString;
1499
+ source: z.ZodDefault<z.ZodString>;
1500
+ tags: z.ZodDefault<z.ZodArray<z.ZodString>>;
1501
+ expiresAt: z.ZodOptional<z.ZodString>;
1502
+ outcome: z.ZodOptional<z.ZodString>;
1503
+ runId: z.ZodOptional<z.ZodString>;
1504
+ category: z.ZodOptional<z.ZodString>;
1505
+ severity: z.ZodOptional<z.ZodString>;
1506
+ supersedes: z.ZodOptional<z.ZodString>;
1507
+ }, z.core.$strip>;
1508
+ type MemoryWriteInput = z.input<typeof memoryWriteInputSchema>;
1509
+ interface MemoryQuery {
1510
+ scope?: string;
1511
+ types?: MemoryType[];
1512
+ since?: string;
1513
+ limit?: number;
1514
+ sortBy?: "relevance" | "createdAt" | "accessCount";
1515
+ tags?: string[];
1516
+ }
1517
+ interface MemoryStats {
1518
+ total: number;
1519
+ byType: Record<string, number>;
1520
+ byScope: Record<string, number>;
1521
+ }
1522
+
1523
+ declare class MemoryStore {
1524
+ private db;
1525
+ private embedder;
1526
+ private hasVec;
1527
+ constructor(dbPath: string, embedder?: Embedder | null);
1528
+ private initSchema;
1529
+ /**
1530
+ * Migrate existing tables whose CHECK constraint predates the 'task' type.
1531
+ * SQLite doesn't allow ALTER CHECK, so we recreate the table if needed.
1532
+ */
1533
+ private migrateCheckConstraint;
1534
+ write(input: MemoryWriteInput): Promise<string>;
1535
+ update(id: string, content: string): void;
1536
+ updateFields(id: string, fields: {
1537
+ content?: string;
1538
+ outcome?: string;
1539
+ runId?: string;
1540
+ }): void;
1541
+ forget(id: string): void;
1542
+ query(opts?: MemoryQuery): MemoryEntry[];
1543
+ search(text: string, opts?: MemoryQuery): Promise<MemoryEntry[]>;
1544
+ markAccessed(ids: string[]): void;
1545
+ decay(maxAgeDays?: number, minAccessCount?: number): number;
1546
+ expireEphemeral(): number;
1547
+ stats(): MemoryStats;
1548
+ close(): void;
1296
1549
  }
1297
- /**
1298
- * Build the prompt sent to Claude at each heartbeat.
1299
- *
1300
- * Includes: role definition, current memory, pending events,
1301
- * budget status, active runs, and available integrations.
1302
- */
1303
- declare function buildHeartbeatPrompt(opts: HeartbeatPromptOptions): string;
1304
1550
 
1305
1551
  interface WebhookServerOptions {
1306
1552
  port: number;
@@ -1379,4 +1625,4 @@ declare class WorkflowRegistry {
1379
1625
 
1380
1626
  declare const VERSION = "0.1.0";
1381
1627
 
1382
- export { type ActiveSession, type ActivityEntry, ActivityLog, type AgentConfig, type AgentDefinition, type AgentMessageEvent, type AgentModel, AgentRegistry, type AgentTool, type AgentToolEntry, type AgentToolUseEvent, type AuditLogMiddleware, type BudgetAlertEvent, type CostEntry, CostJournal, type CostUpdateEvent, type DispatchInput, EventJournal, EventQueue, type GateWaitingEvent, type GlobalConfig, HeartbeatLoop, type HeartbeatLoopOptions, type HeartbeatPromptOptions, type HookEvent, type InboxMessage, type LoopDetectionMiddleware, type McpServerConfig, type Middleware, type MiddlewareChain, type MiddlewareContext, type MiddlewareContextMap, type MiddlewareEvent, type MiddlewareHandler, type MiddlewareResult, type NeoConfig, type NeoEvent, NeoEventEmitter, Orchestrator, type OrchestratorOptions, type OrchestratorShutdownEvent, type OrchestratorStatus, type ParsedOutput, type PersistedRun, type Priority, type QueueDequeueEvent, type QueueEnqueueEvent, type QueuedEvent, type RecoveryOptions, type RepoConfig, type RepoConfigInput, type ResolvedAgent, type SDKHooks, type SandboxConfig, Semaphore, type SemaphoreCallbacks, type SemaphoreConfig, type SessionCompleteEvent, SessionError, type SessionEvent, type SessionFailEvent, type SessionOptions, type SessionResult, type SessionStartEvent, type StepResult, SupervisorDaemon, type SupervisorDaemonOptions, type SupervisorDaemonState, type SupervisorDaemonState as SupervisorState, type TaskResult, VERSION, WebhookDispatcher, type WebhookIncomingEvent, WebhookServer, type WorkflowContext, type WorkflowDefinition, type WorkflowGateDef, WorkflowRegistry, type WorkflowStepCompleteEvent, type WorkflowStepDef, type WorkflowStepStartEvent, type WorktreeInfo, activityEntrySchema, addRepoToGlobalConfig, agentConfigSchema, agentModelSchema, agentSandboxSchema, agentToolEntrySchema, agentToolSchema, auditLog, budgetGuard, buildHeartbeatPrompt, buildMiddlewareChain, buildSDKHooks, buildSandboxConfig, checkMemorySize, cleanupOrphanedWorktrees, createBranch, createWorktree, deleteBranch, extractMemoryFromResponse, fetchRemote, getBranchName, getCurrentBranch, getDataDir, getJournalsDir, getRepoRunsDir, getRunDispatchPath, getRunLogPath, getRunsDir, getSupervisorActivityPath, getSupervisorDir, getSupervisorEventsPath, getSupervisorInboxPath, getSupervisorLockPath, getSupervisorMemoryPath, getSupervisorStatePath, getSupervisorsDir, globalConfigSchema, inboxMessageSchema, listReposFromGlobalConfig, listWorktrees, loadAgentFile, loadConfig, loadGlobalConfig, loadMemory, loadWorkflow, loopDetection, matchesFilter, mcpServerConfigSchema, neoConfigSchema, parseOutput, pushBranch, removeRepoFromGlobalConfig, removeWorktree, repoConfigSchema, resolveAgent, runSession, runWithRecovery, saveMemory, supervisorDaemonStateSchema, supervisorDaemonStateSchema as supervisorStateSchema, toRepoSlug, webhookIncomingEventSchema, withGitLock, workflowGateDefSchema, workflowStepDefSchema };
1628
+ export { type ActiveSession, type ActivityEntry, ActivityLog, type AgentConfig, type AgentDefinition, type AgentMessageEvent, type AgentModel, AgentRegistry, type AgentTool, type AgentToolEntry, type AgentToolUseEvent, type AuditLogMiddleware, type BudgetAlertEvent, type CostEntry, CostJournal, type CostUpdateEvent, type DispatchInput, type Embedder, EventJournal, EventQueue, type GateWaitingEvent, type GitStrategy, type GlobalConfig, HeartbeatLoop, type HeartbeatLoopOptions, type HookEvent, type InboxMessage, LocalEmbedder, type LoopDetectionMiddleware, type McpServerConfig, type MemoryEntry, type MemoryQuery, type MemoryStats, MemoryStore, type MemoryType, type MemoryWriteInput, type Middleware, type MiddlewareChain, type MiddlewareContext, type MiddlewareContextMap, type MiddlewareEvent, type MiddlewareHandler, type MiddlewareResult, type NeoConfig, type NeoEvent, NeoEventEmitter, Orchestrator, type OrchestratorOptions, type OrchestratorShutdownEvent, type OrchestratorStatus, type ParsedOutput, type PersistedRun, type Priority, type QueueDequeueEvent, type QueueEnqueueEvent, type QueuedEvent, type RecoveryOptions, type RepoConfig, type RepoConfigInput, type ResolvedAgent, type SDKHooks, type SandboxConfig, Semaphore, type SemaphoreCallbacks, type SemaphoreConfig, type SessionCloneInfo, type SessionCompleteEvent, SessionError, type SessionEvent, type SessionExecutionConfig, type SessionExecutionDeps, type SessionExecutionInput, type SessionExecutionResult, SessionExecutor, type SessionFailEvent, type SessionOptions, type SessionResult, type SessionStartEvent, type StepResult, SupervisorDaemon, type SupervisorDaemonOptions, type SupervisorDaemonState, type SupervisorDaemonState as SupervisorState, type TaskResult, VERSION, WebhookDispatcher, type WebhookIncomingEvent, WebhookServer, type WorkflowContext, type WorkflowDefinition, type WorkflowGateDef, WorkflowRegistry, type WorkflowStepCompleteEvent, type WorkflowStepDef, type WorkflowStepStartEvent, activityEntrySchema, addRepoToGlobalConfig, agentConfigSchema, agentModelSchema, agentSandboxSchema, agentToolEntrySchema, agentToolSchema, appendLogBuffer, auditLog, budgetGuard, buildFullPrompt, buildGitStrategyInstructions, buildMiddlewareChain, buildReportingInstructions, buildSDKHooks, buildSandboxConfig, createBranch, createSessionClone, deleteBranch, fetchRemote, getBranchName, getCurrentBranch, getDataDir, getJournalsDir, getRepoRunsDir, getRunDispatchPath, getRunLogPath, getRunsDir, getSupervisorActivityPath, getSupervisorDir, getSupervisorEventsPath, getSupervisorInboxPath, getSupervisorLockPath, getSupervisorStatePath, getSupervisorsDir, globalConfigSchema, inboxMessageSchema, isProcessAlive, listReposFromGlobalConfig, listSessionClones, loadAgentFile, loadConfig, loadGlobalConfig, loadRepoInstructions, loadWorkflow, loopDetection, matchesFilter, mcpServerConfigSchema, neoConfigSchema, parseOutput, pushBranch, pushSessionBranch, removeRepoFromGlobalConfig, removeSessionClone, repoConfigSchema, resolveAgent, runSession, runWithRecovery, supervisorDaemonStateSchema, supervisorDaemonStateSchema as supervisorStateSchema, toRepoSlug, webhookIncomingEventSchema, workflowGateDefSchema, workflowStepDefSchema };