@neotx/core 0.1.0-alpha.2 → 0.1.0-alpha.4

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.
@@ -828,13 +846,14 @@ declare class Orchestrator extends NeoEventEmitter {
828
846
  private readonly idempotencyCache;
829
847
  private readonly abortControllers;
830
848
  private readonly repoIndex;
831
- private readonly createdRunDirs;
849
+ private readonly runStore;
832
850
  private readonly journalDir;
833
851
  private readonly builtInWorkflowDir;
834
852
  private readonly customWorkflowDir;
835
853
  private costJournal;
836
854
  private eventJournal;
837
855
  private webhookDispatcher;
856
+ private memoryStore;
838
857
  private _paused;
839
858
  private _costToday;
840
859
  private _startedAt;
@@ -870,12 +889,14 @@ declare class Orchestrator extends NeoEventEmitter {
870
889
  private buildDispatchContext;
871
890
  private executeStep;
872
891
  /**
873
- * Push the branch, then remove the worktree.
892
+ * Push the branch (writable only), then remove the session clone.
874
893
  * Runs in `finally` so it executes on both success and failure.
875
894
  */
876
- private finalizeWorktree;
895
+ private finalizeSession;
877
896
  private runAgentSession;
878
897
  private finalizeDispatch;
898
+ private getMemoryStore;
899
+ private loadMemoryContext;
879
900
  private emitCostEvents;
880
901
  private emitSessionComplete;
881
902
  private emitSessionFail;
@@ -885,8 +906,10 @@ declare class Orchestrator extends NeoEventEmitter {
885
906
  private getFirstStep;
886
907
  private resolveStepAgent;
887
908
  private resolveRepo;
888
- private buildMiddlewareContext;
889
909
  private computeBudgetRemainingPct;
910
+ private resolveMcpServers;
911
+ /** Discover running supervisor daemons and return webhook configs for their endpoints. */
912
+ private discoverSupervisorWebhooks;
890
913
  private persistRun;
891
914
  private recoverOrphanedRuns;
892
915
  }
@@ -930,7 +953,6 @@ declare function getSupervisorDir(name: string): string;
930
953
  * Path to a supervisor state file: ~/.neo/supervisors/<name>/state.json
931
954
  */
932
955
  declare function getSupervisorStatePath(name: string): string;
933
- declare function getSupervisorMemoryPath(name: string): string;
934
956
  declare function getSupervisorActivityPath(name: string): string;
935
957
  declare function getSupervisorInboxPath(name: string): string;
936
958
  declare function getSupervisorEventsPath(name: string): string;
@@ -940,9 +962,12 @@ interface ParsedOutput {
940
962
  rawOutput: string;
941
963
  output?: unknown;
942
964
  parseError?: string;
965
+ prUrl?: string;
966
+ prNumber?: number;
943
967
  }
944
968
  /**
945
969
  * Parse agent output, optionally validating against a Zod schema.
970
+ * Also extracts structured markers like PR_URL from the output.
946
971
  *
947
972
  * - If no schema: returns rawOutput only
948
973
  * - If schema provided: extracts JSON from output, validates with schema
@@ -954,10 +979,11 @@ interface SessionOptions {
954
979
  agent: ResolvedAgent;
955
980
  prompt: string;
956
981
  repoPath?: string;
957
- worktreePath?: string;
982
+ sessionPath?: string;
958
983
  sandboxConfig: SandboxConfig;
959
984
  hooks?: Record<string, unknown>;
960
- mcpServers?: McpServerConfig[];
985
+ mcpServers?: Record<string, McpServerConfig>;
986
+ env?: Record<string, string>;
961
987
  initTimeoutMs: number;
962
988
  maxDurationMs: number;
963
989
  resumeSessionId?: string | undefined;
@@ -1007,6 +1033,78 @@ interface RecoveryOptions extends SessionOptions {
1007
1033
  */
1008
1034
  declare function runWithRecovery(options: RecoveryOptions): Promise<SessionResult>;
1009
1035
 
1036
+ interface SessionExecutionInput {
1037
+ runId: string;
1038
+ sessionId: string;
1039
+ agent: ResolvedAgent;
1040
+ stepDef: WorkflowStepDef;
1041
+ repoConfig: RepoConfig;
1042
+ repoPath: string;
1043
+ prompt: string;
1044
+ branch?: string | undefined;
1045
+ gitStrategy: GitStrategy;
1046
+ sessionPath?: string | undefined;
1047
+ metadata?: Record<string, unknown> | undefined;
1048
+ startedAt: string;
1049
+ }
1050
+ interface SessionExecutionConfig {
1051
+ initTimeoutMs: number;
1052
+ maxDurationMs: number;
1053
+ maxRetries: number;
1054
+ backoffBaseMs: number;
1055
+ }
1056
+ interface SessionExecutionDeps {
1057
+ middleware: Middleware[];
1058
+ mcpServers?: Record<string, McpServerConfig> | undefined;
1059
+ memoryContext?: string | undefined;
1060
+ onAttempt?: (attempt: number, strategy: string) => void;
1061
+ }
1062
+ interface SessionExecutionResult extends StepResult {
1063
+ parsed: ParsedOutput;
1064
+ }
1065
+ declare function loadRepoInstructions(repoPath: string): Promise<string | undefined>;
1066
+ declare function buildGitStrategyInstructions(strategy: GitStrategy, agent: ResolvedAgent, branch: string, baseBranch: string, remote: string, metadata?: Record<string, unknown>): string | null;
1067
+ declare function buildReportingInstructions(_runId: string): string;
1068
+ declare function buildFullPrompt(agentPrompt: string | undefined, repoInstructions: string | undefined, gitInstructions: string | null, taskPrompt: string, memoryContext?: string | undefined, cwdInstructions?: string | undefined, reportingInstructions?: string | undefined): string;
1069
+ /**
1070
+ * Encapsulates session execution logic: prompt building, SDK calls, and response processing.
1071
+ * Extracted from Orchestrator for better testability and separation of concerns.
1072
+ */
1073
+ declare class SessionExecutor {
1074
+ private readonly config;
1075
+ private readonly getContextValue;
1076
+ constructor(config: SessionExecutionConfig, getContextValue: (key: string) => unknown);
1077
+ /**
1078
+ * Execute an agent session with the given input and dependencies.
1079
+ * Handles prompt building, SDK invocation via recovery wrapper, and output parsing.
1080
+ */
1081
+ execute(input: SessionExecutionInput, deps: SessionExecutionDeps): Promise<SessionExecutionResult>;
1082
+ }
1083
+
1084
+ /**
1085
+ * Checks whether a process with the given PID is currently running.
1086
+ *
1087
+ * Uses the POSIX signal 0 trick: `process.kill(pid, 0)` doesn't actually
1088
+ * send a signal but checks whether the process exists and the current
1089
+ * process has permission to signal it. If the process doesn't exist,
1090
+ * an ESRCH error is thrown.
1091
+ *
1092
+ * @param pid - The process ID to check. Must be a positive integer.
1093
+ * @returns `true` if the process is alive and accessible, `false` otherwise.
1094
+ *
1095
+ * @example
1096
+ * ```ts
1097
+ * import { isProcessAlive } from "@/shared/process";
1098
+ *
1099
+ * // Check if current process is alive (always true)
1100
+ * isProcessAlive(process.pid); // => true
1101
+ *
1102
+ * // Check if a non-existent process is alive
1103
+ * isProcessAlive(999999); // => false
1104
+ * ```
1105
+ */
1106
+ declare function isProcessAlive(pid: number): boolean;
1107
+
1010
1108
  declare const supervisorDaemonStateSchema: z.ZodObject<{
1011
1109
  pid: z.ZodNumber;
1012
1110
  sessionId: z.ZodString;
@@ -1019,11 +1117,21 @@ declare const supervisorDaemonStateSchema: z.ZodObject<{
1019
1117
  todayCostUsd: z.ZodDefault<z.ZodNumber>;
1020
1118
  costResetDate: z.ZodOptional<z.ZodString>;
1021
1119
  idleSkipCount: z.ZodDefault<z.ZodNumber>;
1120
+ activeWorkSkipCount: z.ZodDefault<z.ZodNumber>;
1022
1121
  status: z.ZodDefault<z.ZodEnum<{
1023
1122
  running: "running";
1024
1123
  draining: "draining";
1025
1124
  stopped: "stopped";
1026
1125
  }>>;
1126
+ lastConsolidationHeartbeat: z.ZodDefault<z.ZodNumber>;
1127
+ lastCompactionHeartbeat: z.ZodDefault<z.ZodNumber>;
1128
+ lastConsolidationTimestamp: z.ZodOptional<z.ZodString>;
1129
+ wakeReason: z.ZodOptional<z.ZodEnum<{
1130
+ events: "events";
1131
+ timer: "timer";
1132
+ active_runs: "active_runs";
1133
+ forced: "forced";
1134
+ }>>;
1027
1135
  }, z.core.$strip>;
1028
1136
  type SupervisorDaemonState = z.infer<typeof supervisorDaemonStateSchema>;
1029
1137
  declare const webhookIncomingEventSchema: z.ZodObject<{
@@ -1038,6 +1146,7 @@ type WebhookIncomingEvent = z.infer<typeof webhookIncomingEventSchema>;
1038
1146
  declare const inboxMessageSchema: z.ZodObject<{
1039
1147
  id: z.ZodString;
1040
1148
  from: z.ZodEnum<{
1149
+ agent: "agent";
1041
1150
  tui: "tui";
1042
1151
  api: "api";
1043
1152
  external: "external";
@@ -1053,19 +1162,47 @@ declare const activityEntrySchema: z.ZodObject<{
1053
1162
  error: "error";
1054
1163
  message: "message";
1055
1164
  decision: "decision";
1165
+ tool_use: "tool_use";
1056
1166
  event: "event";
1057
1167
  heartbeat: "heartbeat";
1058
1168
  action: "action";
1059
1169
  thinking: "thinking";
1060
1170
  plan: "plan";
1061
1171
  dispatch: "dispatch";
1062
- tool_use: "tool_use";
1063
1172
  }>;
1064
1173
  summary: z.ZodString;
1065
1174
  detail: z.ZodOptional<z.ZodUnknown>;
1066
1175
  timestamp: z.ZodString;
1067
1176
  }, z.core.$strip>;
1068
1177
  type ActivityEntry = z.infer<typeof activityEntrySchema>;
1178
+ declare const logBufferEntrySchema: z.ZodObject<{
1179
+ id: z.ZodString;
1180
+ type: z.ZodEnum<{
1181
+ decision: "decision";
1182
+ action: "action";
1183
+ progress: "progress";
1184
+ blocker: "blocker";
1185
+ milestone: "milestone";
1186
+ discovery: "discovery";
1187
+ }>;
1188
+ message: z.ZodString;
1189
+ agent: z.ZodOptional<z.ZodString>;
1190
+ runId: z.ZodOptional<z.ZodString>;
1191
+ repo: z.ZodOptional<z.ZodString>;
1192
+ target: z.ZodEnum<{
1193
+ memory: "memory";
1194
+ knowledge: "knowledge";
1195
+ digest: "digest";
1196
+ }>;
1197
+ timestamp: z.ZodString;
1198
+ consolidatedAt: z.ZodOptional<z.ZodString>;
1199
+ }, z.core.$strip>;
1200
+ type LogBufferEntry = z.infer<typeof logBufferEntrySchema>;
1201
+ declare const internalEventKindSchema: z.ZodEnum<{
1202
+ consolidation_timer: "consolidation_timer";
1203
+ active_run_check: "active_run_check";
1204
+ }>;
1205
+ type InternalEventKind = z.infer<typeof internalEventKindSchema>;
1069
1206
  type QueuedEvent = {
1070
1207
  kind: "webhook";
1071
1208
  data: WebhookIncomingEvent;
@@ -1076,6 +1213,10 @@ type QueuedEvent = {
1076
1213
  kind: "run_complete";
1077
1214
  runId: string;
1078
1215
  timestamp: string;
1216
+ } | {
1217
+ kind: "internal";
1218
+ eventKind: InternalEventKind;
1219
+ timestamp: string;
1079
1220
  };
1080
1221
 
1081
1222
  declare class ActivityLog {
@@ -1101,6 +1242,8 @@ declare class ActivityLog {
1101
1242
  interface SupervisorDaemonOptions {
1102
1243
  name: string;
1103
1244
  config: GlobalConfig;
1245
+ /** Path to bundled default SUPERVISOR.md (e.g. from @neotx/agents) */
1246
+ defaultInstructionsPath?: string | undefined;
1104
1247
  }
1105
1248
  /**
1106
1249
  * Orchestrates all supervisor components: webhook server, event queue,
@@ -1110,6 +1253,7 @@ declare class SupervisorDaemon {
1110
1253
  private readonly name;
1111
1254
  private readonly config;
1112
1255
  private readonly dir;
1256
+ private readonly defaultInstructionsPath;
1113
1257
  private webhookServer;
1114
1258
  private eventQueue;
1115
1259
  private heartbeatLoop;
@@ -1122,7 +1266,6 @@ declare class SupervisorDaemon {
1122
1266
  private readState;
1123
1267
  private writeState;
1124
1268
  private readLockPid;
1125
- private isProcessAlive;
1126
1269
  }
1127
1270
 
1128
1271
  interface EventQueueOptions {
@@ -1178,7 +1321,7 @@ declare class EventQueue {
1178
1321
  * Start watching inbox.jsonl and events.jsonl for new entries.
1179
1322
  * New lines are parsed and pushed into the queue.
1180
1323
  */
1181
- startWatching(inboxPath: string, eventsPath: string): void;
1324
+ startWatching(inboxPath: string, eventsPath: string): Promise<void>;
1182
1325
  stopWatching(): void;
1183
1326
  /**
1184
1327
  * Replay unprocessed events from disk on startup.
@@ -1210,15 +1353,20 @@ interface HeartbeatLoopOptions {
1210
1353
  sessionId: string;
1211
1354
  eventQueue: EventQueue;
1212
1355
  activityLog: ActivityLog;
1356
+ /** Path to bundled default SUPERVISOR.md (e.g. from @neotx/agents) */
1357
+ defaultInstructionsPath?: string | undefined;
1358
+ memoryDbPath?: string | undefined;
1213
1359
  }
1214
1360
  /**
1215
1361
  * The core autonomous loop. At each iteration:
1216
1362
  * 1. Drain events from the queue
1217
- * 2. Build a prompt with context + memory + events
1218
- * 3. Call sdk.query() for Claude to reason and act
1219
- * 4. Extract and save updated memory
1220
- * 5. Log activity
1221
- * 6. Wait for the next event or idle timeout
1363
+ * 2. Read log buffer entries
1364
+ * 3. Determine standard vs consolidation mode
1365
+ * 4. Build the appropriate prompt
1366
+ * 5. Call sdk.query() for Claude to reason and act
1367
+ * 6. Mark entries consolidated and compact log buffer (consolidation only)
1368
+ * 7. Log activity
1369
+ * 8. Wait for the next event or idle timeout
1222
1370
  */
1223
1371
  declare class HeartbeatLoop {
1224
1372
  private stopping;
@@ -1231,17 +1379,48 @@ declare class HeartbeatLoop {
1231
1379
  private readonly eventQueue;
1232
1380
  private readonly activityLog;
1233
1381
  private customInstructions;
1382
+ private readonly defaultInstructionsPath;
1383
+ private memoryStore;
1384
+ private readonly memoryDbPath;
1234
1385
  constructor(options: HeartbeatLoopOptions);
1386
+ private getMemoryStore;
1235
1387
  start(): Promise<void>;
1236
1388
  stop(): void;
1237
1389
  private runHeartbeat;
1390
+ /**
1391
+ * Check if supervisor daily budget is exceeded.
1392
+ */
1393
+ private checkBudgetExceeded;
1394
+ /**
1395
+ * Handle skip logic for idle and active-work scenarios.
1396
+ */
1397
+ private handleSkipLogic;
1398
+ /**
1399
+ * Determine heartbeat mode: compaction > consolidation > standard.
1400
+ */
1401
+ private determineHeartbeatMode;
1402
+ /**
1403
+ * Build the state update object after heartbeat completion.
1404
+ */
1405
+ private buildStateUpdate;
1406
+ /**
1407
+ * Build the prompt for the current heartbeat mode.
1408
+ */
1409
+ private buildHeartbeatModePrompt;
1410
+ /**
1411
+ * Call the Claude SDK and stream results.
1412
+ */
1413
+ private callSdk;
1238
1414
  private readState;
1239
1415
  private updateState;
1416
+ /** Read persisted run files and return summaries of active (running/paused) runs. */
1417
+ private getActiveRuns;
1240
1418
  /**
1241
1419
  * Load custom instructions from SUPERVISOR.md.
1242
1420
  * Resolution order:
1243
1421
  * 1. Explicit path via `supervisor.instructions` in config
1244
- * 2. Default: ~/.neo/SUPERVISOR.md
1422
+ * 2. User default: ~/.neo/SUPERVISOR.md
1423
+ * 3. Bundled default from @neotx/agents (if path provided)
1245
1424
  */
1246
1425
  private loadInstructions;
1247
1426
  /** Route a single SDK stream message to the appropriate log handler. */
@@ -1256,50 +1435,115 @@ declare class HeartbeatLoop {
1256
1435
  }
1257
1436
 
1258
1437
  /**
1259
- * Load the supervisor memory from disk.
1260
- * Migrates from legacy memory.md if needed.
1261
- */
1262
- declare function loadMemory(dir: string): Promise<string>;
1263
- /**
1264
- * Save the supervisor memory to disk (full overwrite).
1265
- * Automatically compacts if needed.
1266
- */
1267
- declare function saveMemory(dir: string, content: string): Promise<void>;
1268
- /**
1269
- * Extract memory content from Claude's response using <memory>...</memory> tags.
1438
+ * Append a single entry to the log buffer file.
1270
1439
  */
1271
- declare function extractMemoryFromResponse(response: string): string | null;
1272
- /**
1273
- * Check if memory content exceeds the recommended size limit.
1274
- */
1275
- declare function checkMemorySize(content: string): {
1276
- ok: boolean;
1277
- sizeKB: number;
1278
- };
1440
+ declare function appendLogBuffer(dir: string, entry: LogBufferEntry): Promise<void>;
1279
1441
 
1280
- interface HeartbeatPromptOptions {
1281
- repos: RepoConfig[];
1282
- memory: string;
1283
- knowledge: string;
1284
- memorySizeKB: number;
1285
- grouped: GroupedEvents;
1286
- budgetStatus: {
1287
- todayUsd: number;
1288
- capUsd: number;
1289
- remainingPct: number;
1290
- };
1291
- activeRuns: string[];
1292
- heartbeatCount: number;
1293
- mcpServerNames: string[];
1294
- customInstructions?: string | undefined;
1442
+ interface Embedder {
1443
+ embed(texts: string[]): Promise<number[][]>;
1444
+ readonly dimensions: number;
1445
+ }
1446
+ declare class LocalEmbedder implements Embedder {
1447
+ readonly dimensions = 384;
1448
+ embed(texts: string[]): Promise<number[][]>;
1449
+ }
1450
+
1451
+ declare const memoryTypeSchema: z.ZodEnum<{
1452
+ fact: "fact";
1453
+ procedure: "procedure";
1454
+ episode: "episode";
1455
+ focus: "focus";
1456
+ feedback: "feedback";
1457
+ task: "task";
1458
+ }>;
1459
+ type MemoryType = z.infer<typeof memoryTypeSchema>;
1460
+ declare const memoryEntrySchema: z.ZodObject<{
1461
+ id: z.ZodString;
1462
+ type: z.ZodEnum<{
1463
+ fact: "fact";
1464
+ procedure: "procedure";
1465
+ episode: "episode";
1466
+ focus: "focus";
1467
+ feedback: "feedback";
1468
+ task: "task";
1469
+ }>;
1470
+ scope: z.ZodString;
1471
+ content: z.ZodString;
1472
+ source: z.ZodString;
1473
+ tags: z.ZodDefault<z.ZodArray<z.ZodString>>;
1474
+ createdAt: z.ZodString;
1475
+ lastAccessedAt: z.ZodString;
1476
+ accessCount: z.ZodDefault<z.ZodNumber>;
1477
+ expiresAt: z.ZodOptional<z.ZodString>;
1478
+ outcome: z.ZodOptional<z.ZodString>;
1479
+ runId: z.ZodOptional<z.ZodString>;
1480
+ category: z.ZodOptional<z.ZodString>;
1481
+ severity: z.ZodOptional<z.ZodString>;
1482
+ supersedes: z.ZodOptional<z.ZodString>;
1483
+ }, z.core.$strip>;
1484
+ type MemoryEntry = z.infer<typeof memoryEntrySchema>;
1485
+ declare const memoryWriteInputSchema: z.ZodObject<{
1486
+ type: z.ZodEnum<{
1487
+ fact: "fact";
1488
+ procedure: "procedure";
1489
+ episode: "episode";
1490
+ focus: "focus";
1491
+ feedback: "feedback";
1492
+ task: "task";
1493
+ }>;
1494
+ scope: z.ZodDefault<z.ZodString>;
1495
+ content: z.ZodString;
1496
+ source: z.ZodDefault<z.ZodString>;
1497
+ tags: z.ZodDefault<z.ZodArray<z.ZodString>>;
1498
+ expiresAt: z.ZodOptional<z.ZodString>;
1499
+ outcome: z.ZodOptional<z.ZodString>;
1500
+ runId: z.ZodOptional<z.ZodString>;
1501
+ category: z.ZodOptional<z.ZodString>;
1502
+ severity: z.ZodOptional<z.ZodString>;
1503
+ supersedes: z.ZodOptional<z.ZodString>;
1504
+ }, z.core.$strip>;
1505
+ type MemoryWriteInput = z.input<typeof memoryWriteInputSchema>;
1506
+ interface MemoryQuery {
1507
+ scope?: string;
1508
+ types?: MemoryType[];
1509
+ since?: string;
1510
+ limit?: number;
1511
+ sortBy?: "relevance" | "createdAt" | "accessCount";
1512
+ tags?: string[];
1513
+ }
1514
+ interface MemoryStats {
1515
+ total: number;
1516
+ byType: Record<string, number>;
1517
+ byScope: Record<string, number>;
1518
+ }
1519
+
1520
+ declare class MemoryStore {
1521
+ private db;
1522
+ private embedder;
1523
+ private hasVec;
1524
+ constructor(dbPath: string, embedder?: Embedder | null);
1525
+ private initSchema;
1526
+ /**
1527
+ * Migrate existing tables whose CHECK constraint predates the 'task' type.
1528
+ * SQLite doesn't allow ALTER CHECK, so we recreate the table if needed.
1529
+ */
1530
+ private migrateCheckConstraint;
1531
+ write(input: MemoryWriteInput): Promise<string>;
1532
+ update(id: string, content: string): void;
1533
+ updateFields(id: string, fields: {
1534
+ content?: string;
1535
+ outcome?: string;
1536
+ runId?: string;
1537
+ }): void;
1538
+ forget(id: string): void;
1539
+ query(opts?: MemoryQuery): MemoryEntry[];
1540
+ search(text: string, opts?: MemoryQuery): Promise<MemoryEntry[]>;
1541
+ markAccessed(ids: string[]): void;
1542
+ decay(maxAgeDays?: number, minAccessCount?: number): number;
1543
+ expireEphemeral(): number;
1544
+ stats(): MemoryStats;
1545
+ close(): void;
1295
1546
  }
1296
- /**
1297
- * Build the prompt sent to Claude at each heartbeat.
1298
- *
1299
- * Includes: role definition, current memory, pending events,
1300
- * budget status, active runs, and available integrations.
1301
- */
1302
- declare function buildHeartbeatPrompt(opts: HeartbeatPromptOptions): string;
1303
1547
 
1304
1548
  interface WebhookServerOptions {
1305
1549
  port: number;
@@ -1378,4 +1622,4 @@ declare class WorkflowRegistry {
1378
1622
 
1379
1623
  declare const VERSION = "0.1.0";
1380
1624
 
1381
- 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 };
1625
+ 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 };