omnara 0.2.3 → 0.3.0
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/bin/omnara.js +5 -0
- package/dist/auth/auth-provider.d.ts +2 -0
- package/dist/auth/credential-manager.d.ts +5 -1
- package/dist/auth/credentials-store.d.ts +2 -1
- package/dist/auth/supabase-client.d.ts +1 -1
- package/dist/cli.js +5886 -6382
- package/dist/cli.js.map +4 -4
- package/dist/commands/index.d.ts +1 -0
- package/dist/commands/kill.d.ts +2 -0
- package/dist/daemon/daemon-launcher.d.ts +7 -0
- package/dist/daemon/paths.d.ts +7 -0
- package/dist/daemon/session-runner.d.ts +1 -1
- package/dist/env/env-mode.d.ts +2 -0
- package/dist/http/api-client.d.ts +0 -5
- package/dist/orchestrator/agent-orchestrator.d.ts +39 -44
- package/dist/orchestrator/ai-client.d.ts +7 -6
- package/dist/orchestrator/orchestrator-types.d.ts +3 -2
- package/dist/orchestrator/session.d.ts +59 -38
- package/dist/orchestrator/tools/worker-tools.d.ts +2 -0
- package/dist/orchestrator/utils/envelope-utils.d.ts +13 -0
- package/dist/orchestrator/utils/index.d.ts +1 -2
- package/dist/orchestrator/utils/worker-events.d.ts +7 -0
- package/dist/orchestrator/utils/worktree-manager.d.ts +21 -146
- package/dist/orchestrator/worker-manager.d.ts +44 -99
- package/dist/orchestrator/worker-types.d.ts +23 -0
- package/dist/relay/relay-bridge.d.ts +2 -10
- package/dist/utils/logger.d.ts +15 -0
- package/instrument.mjs +14 -0
- package/package.json +6 -2
- package/scripts/test-preinstall.js +0 -1
- package/dist/daemon/file-logger.d.ts +0 -24
- package/dist/daemon/session-log-manager.d.ts +0 -10
- package/dist/orchestrator/tools/worker-status-tool.d.ts +0 -7
- package/dist/orchestrator/utils/async-queue.d.ts +0 -26
|
@@ -1,121 +1,66 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import
|
|
3
|
-
import type { AgentClient } from './ai-client.js';
|
|
4
|
-
import { AsyncQueue } from './utils/async-queue.js';
|
|
1
|
+
import type { McpServerConfig } from '@anthropic-ai/claude-agent-sdk';
|
|
2
|
+
import { type AgentClient } from './ai-client.js';
|
|
5
3
|
import { WorktreeManager } from './utils/worktree-manager.js';
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
}
|
|
11
|
-
export interface WorkerRecord {
|
|
12
|
-
id: string;
|
|
13
|
-
task: string;
|
|
14
|
-
prompt: string;
|
|
15
|
-
sessionId: string;
|
|
16
|
-
sdkSessionId?: string | null;
|
|
17
|
-
status: WorkerStatus;
|
|
18
|
-
startedAt: number;
|
|
19
|
-
lastUpdateAt: number;
|
|
20
|
-
originSessionId?: string;
|
|
21
|
-
progress: WorkerProgressEntry[];
|
|
22
|
-
result?: string;
|
|
23
|
-
error?: string;
|
|
24
|
-
metadata?: Record<string, unknown>;
|
|
25
|
-
messageQueue: AsyncQueue<SDKUserMessage>;
|
|
26
|
-
worktreePath?: string;
|
|
27
|
-
branchName?: string;
|
|
28
|
-
work_context?: string;
|
|
29
|
-
worktree_name?: string;
|
|
30
|
-
}
|
|
31
|
-
export interface WorkerMessageEvent {
|
|
32
|
-
record: WorkerRecord;
|
|
33
|
-
messageType: 'assistant_text' | 'assistant_complete' | 'tool_call' | 'tool_result';
|
|
34
|
-
text?: string;
|
|
35
|
-
success?: boolean;
|
|
36
|
-
toolName?: string;
|
|
37
|
-
toolUseId?: string;
|
|
38
|
-
toolInput?: unknown;
|
|
39
|
-
toolContent?: unknown;
|
|
40
|
-
isError?: boolean;
|
|
41
|
-
}
|
|
4
|
+
import { Session, type CompleteMessageEnvelope } from './session.js';
|
|
5
|
+
import type { WorkerStatus } from './worker-types.js';
|
|
6
|
+
import type { MessageEnvelope } from '@omnara/shared-js/schemas';
|
|
7
|
+
export type { WorkerStatus, WorkerRecord, WorkerSessionMessageEvent } from './worker-types.js';
|
|
42
8
|
interface LaunchWorkerOptions {
|
|
43
9
|
task: string;
|
|
44
10
|
prompt: string;
|
|
45
11
|
work_context: string;
|
|
46
12
|
worktree_name: string;
|
|
47
|
-
originSessionId
|
|
13
|
+
originSessionId: string;
|
|
48
14
|
metadata?: Record<string, unknown>;
|
|
49
15
|
}
|
|
50
16
|
interface WorkerManagerOptions {
|
|
51
17
|
createClient: (mcpServers?: Record<string, McpServerConfig>, cwd?: string) => AgentClient;
|
|
52
|
-
|
|
18
|
+
broadcastMessage: (msg: MessageEnvelope) => Promise<void> | void;
|
|
19
|
+
broadcastComplete: (complete: CompleteMessageEnvelope) => Promise<void> | void;
|
|
20
|
+
announceWorkerSession?: (info: {
|
|
21
|
+
sessionId: string;
|
|
22
|
+
parentSessionId?: string;
|
|
23
|
+
metadata?: Record<string, unknown>;
|
|
24
|
+
}) => Promise<void> | void;
|
|
53
25
|
repoPath: string;
|
|
54
|
-
worktreesEnabled: boolean;
|
|
55
|
-
worktreesBaseRef?: string;
|
|
56
26
|
}
|
|
57
|
-
|
|
27
|
+
type Worker = {
|
|
28
|
+
status: WorkerStatus;
|
|
29
|
+
session: Session;
|
|
30
|
+
ai: AgentClient;
|
|
31
|
+
task: string;
|
|
32
|
+
parentSessionId: string;
|
|
33
|
+
worktreeName?: string;
|
|
34
|
+
directory: string;
|
|
35
|
+
startedAt: number;
|
|
36
|
+
lastUpdateAt: number;
|
|
37
|
+
};
|
|
38
|
+
export declare class WorkerManager {
|
|
58
39
|
private readonly options;
|
|
59
|
-
private
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
40
|
+
private workers;
|
|
41
|
+
worktreeManager: WorktreeManager;
|
|
42
|
+
broadcastMessage: (msg: MessageEnvelope) => Promise<void> | void;
|
|
43
|
+
broadcastComplete: (complete: CompleteMessageEnvelope) => Promise<void> | void;
|
|
44
|
+
readonly repoPath: string;
|
|
45
|
+
private readonly announceWorkerSession?;
|
|
63
46
|
constructor(options: WorkerManagerOptions);
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
* Get a formatted summary of all current worker statuses for inclusion in system prompts.
|
|
70
|
-
* Returns a string describing all active workers and their current state.
|
|
71
|
-
*/
|
|
72
|
-
getWorkerStatusSummary(): string;
|
|
73
|
-
launchWorker({ task, prompt, work_context, worktree_name, originSessionId, metadata }: LaunchWorkerOptions, toolUseId?: string): WorkerRecord;
|
|
74
|
-
private createWorktreeAndRun;
|
|
75
|
-
cancelWorker(id: string): boolean;
|
|
47
|
+
listWorkers(): Worker[];
|
|
48
|
+
getWorker(id: string): Worker | undefined;
|
|
49
|
+
getWorkerByTask(task: string): Worker | undefined;
|
|
50
|
+
cancelWorker(id: string): Promise<boolean>;
|
|
51
|
+
launchWorker({ task, prompt, worktree_name, originSessionId, }: LaunchWorkerOptions): Promise<Worker>;
|
|
76
52
|
/**
|
|
77
53
|
* Route a user message to a worker by session ID.
|
|
78
|
-
*
|
|
79
|
-
*
|
|
80
|
-
* @param sessionId - The session ID of the worker
|
|
81
|
-
* @param message - The message content to send
|
|
82
|
-
* @returns true if message was sent, false if worker not found
|
|
54
|
+
* Thin wrapper around enqueueMessage.
|
|
83
55
|
*/
|
|
84
|
-
|
|
56
|
+
userMessageWorker(sessionId: string, userId: string, message: string): Promise<boolean>;
|
|
85
57
|
/**
|
|
86
58
|
* Send a message to a worker (running or completed).
|
|
87
|
-
*
|
|
88
|
-
* @param task - The task name of the worker to message
|
|
89
|
-
* @param message - The message content to send
|
|
90
|
-
* @param interrupt - If true, interrupt current generation; if false, queue for next turn
|
|
91
|
-
* @param toolUseId - Optional tool use ID to track this operation for relay forwarding
|
|
92
|
-
* @returns true if message was sent, false if worker not found or message queue is closed
|
|
93
|
-
*/
|
|
94
|
-
messageWorker(task: string, message: string, interrupt: boolean, toolUseId?: string): Promise<boolean>;
|
|
95
|
-
private emitUpdate;
|
|
96
|
-
private emitCompleted;
|
|
97
|
-
private handleStatusUpdate;
|
|
98
|
-
/**
|
|
99
|
-
* Create an async iterable stream of user messages for the worker.
|
|
100
|
-
* Yields the initial prompt, then streams any additional messages from the queue.
|
|
101
|
-
* If initialPrompt is empty, skips the initial yield and only consumes from the queue.
|
|
102
|
-
*/
|
|
103
|
-
private createMessageStream;
|
|
104
|
-
private runWorker;
|
|
105
|
-
private handleMessage;
|
|
106
|
-
private extractAssistantText;
|
|
107
|
-
private extractDeltaText;
|
|
108
|
-
private extractError;
|
|
109
|
-
private wrapPrompt;
|
|
110
|
-
/**
|
|
111
|
-
* Shutdown the worker manager and cleanup all resources
|
|
112
|
-
* This should be called during application shutdown to ensure all worktrees are cleaned up
|
|
59
|
+
* Thin wrapper around enqueueMessage.
|
|
113
60
|
*/
|
|
61
|
+
toolMessageWorker(task: string, message: string): Promise<boolean>;
|
|
114
62
|
shutdown(): Promise<void>;
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
*/
|
|
119
|
-
getWorktreeManager(): WorktreeManager;
|
|
63
|
+
private onComplete;
|
|
64
|
+
onMessage(id: string, msg: MessageEnvelope): Promise<void>;
|
|
65
|
+
private commitWorkerChanges;
|
|
120
66
|
}
|
|
121
|
-
export {};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { MessageEnvelope } from '@omnara/shared-js/schemas';
|
|
2
|
+
import type { Session } from './session.js';
|
|
3
|
+
export type WorkerStatus = 'running' | 'completed' | 'error' | 'canceled';
|
|
4
|
+
export interface WorkerRecord {
|
|
5
|
+
id: string;
|
|
6
|
+
task: string;
|
|
7
|
+
prompt: string;
|
|
8
|
+
sdkSessionId?: string | null;
|
|
9
|
+
status: WorkerStatus;
|
|
10
|
+
startedAt: number;
|
|
11
|
+
lastUpdateAt: number;
|
|
12
|
+
originSessionId?: string;
|
|
13
|
+
result?: string;
|
|
14
|
+
error?: string;
|
|
15
|
+
metadata?: Record<string, unknown>;
|
|
16
|
+
session?: Session;
|
|
17
|
+
worktreePath?: string;
|
|
18
|
+
worktreeName?: string;
|
|
19
|
+
}
|
|
20
|
+
export interface WorkerSessionMessageEvent {
|
|
21
|
+
record: WorkerRecord;
|
|
22
|
+
message: MessageEnvelope;
|
|
23
|
+
}
|
|
@@ -39,10 +39,9 @@ export declare class RelayBridge extends EventEmitter {
|
|
|
39
39
|
private ensureUserSession;
|
|
40
40
|
private sendPrimarySessionInit;
|
|
41
41
|
private sendFrame;
|
|
42
|
+
private handleOutboundControl;
|
|
42
43
|
private handleWebsocketLifecycle;
|
|
43
|
-
private handleOutbound;
|
|
44
44
|
private handleInbound;
|
|
45
|
-
private toRelayFrame;
|
|
46
45
|
private tryHandleControlMessage;
|
|
47
46
|
private tryHandleMessageEnvelope;
|
|
48
47
|
private handleSessionBootstrap;
|
|
@@ -54,16 +53,9 @@ export declare class RelayBridge extends EventEmitter {
|
|
|
54
53
|
private handleRelayRequest;
|
|
55
54
|
private handleMessageEnvelope;
|
|
56
55
|
private isTextContent;
|
|
57
|
-
private buildUserTextEnvelope;
|
|
58
|
-
private buildTextEnvelope;
|
|
59
|
-
private buildToolCallEnvelope;
|
|
60
|
-
private normalizeToolArguments;
|
|
61
|
-
private buildToolResultEnvelope;
|
|
62
|
-
private buildAgentCompleteEnvelope;
|
|
63
|
-
private buildProgressEnvelope;
|
|
64
|
-
private buildEnvelope;
|
|
65
56
|
private isMessageEnvelope;
|
|
66
57
|
private enqueue;
|
|
58
|
+
private sendSessionInitControl;
|
|
67
59
|
private flushQueue;
|
|
68
60
|
private startPingTimer;
|
|
69
61
|
private clearLoginWait;
|
package/dist/utils/logger.d.ts
CHANGED
|
@@ -32,18 +32,28 @@ export declare function getLogLevel(): LogLevel;
|
|
|
32
32
|
export interface Logger extends Console {
|
|
33
33
|
important(...args: unknown[]): void;
|
|
34
34
|
success(...args: unknown[]): void;
|
|
35
|
+
close?(): Promise<void>;
|
|
35
36
|
}
|
|
36
37
|
/**
|
|
37
38
|
* Creates a controlled logger instance
|
|
38
39
|
*/
|
|
40
|
+
type LogSink = (entry: {
|
|
41
|
+
line: string;
|
|
42
|
+
raw: unknown[];
|
|
43
|
+
}) => void;
|
|
39
44
|
export declare class ControlledLogger implements Logger {
|
|
40
45
|
private logLevel;
|
|
41
46
|
private forceOutput;
|
|
42
47
|
private _console;
|
|
48
|
+
private sinks;
|
|
49
|
+
private closers;
|
|
50
|
+
private formatLine;
|
|
43
51
|
Console: typeof console.Console;
|
|
44
52
|
constructor(options?: {
|
|
45
53
|
logLevel?: LogLevel;
|
|
46
54
|
forceOutput?: boolean;
|
|
55
|
+
sinks?: LogSink[];
|
|
56
|
+
closers?: Array<() => Promise<void> | void>;
|
|
47
57
|
});
|
|
48
58
|
/**
|
|
49
59
|
* Standard log output (INFO level)
|
|
@@ -78,10 +88,12 @@ export declare class ControlledLogger implements Logger {
|
|
|
78
88
|
* Success messages that should typically be shown
|
|
79
89
|
*/
|
|
80
90
|
success(...args: unknown[]): void;
|
|
91
|
+
close(): Promise<void>;
|
|
81
92
|
/**
|
|
82
93
|
* Check if a message should be logged at the given level
|
|
83
94
|
*/
|
|
84
95
|
private shouldLog;
|
|
96
|
+
private write;
|
|
85
97
|
/**
|
|
86
98
|
* Update the log level dynamically
|
|
87
99
|
*/
|
|
@@ -117,6 +129,8 @@ export declare const logger: ControlledLogger;
|
|
|
117
129
|
export declare function createLogger(componentName?: string, options?: {
|
|
118
130
|
logLevel?: LogLevel;
|
|
119
131
|
forceOutput?: boolean;
|
|
132
|
+
sinks?: LogSink[];
|
|
133
|
+
closers?: Array<() => Promise<void> | void>;
|
|
120
134
|
}): Logger;
|
|
121
135
|
/**
|
|
122
136
|
* Helper to extract error messages consistently
|
|
@@ -126,3 +140,4 @@ export declare function extractErrorMessage(error: unknown): string;
|
|
|
126
140
|
* Print current logger configuration (useful for debugging)
|
|
127
141
|
*/
|
|
128
142
|
export declare function printLoggerConfig(): void;
|
|
143
|
+
export {};
|
package/instrument.mjs
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import * as Sentry from '@sentry/node';
|
|
2
|
+
|
|
3
|
+
const DEFAULT_DSN =
|
|
4
|
+
'https://ad24dca67a2ab987c433aba53f738743@o4509630021828608.ingest.us.sentry.io/4510413097467904';
|
|
5
|
+
|
|
6
|
+
const dsn = process.env.OMNARA_SENTRY_DSN ?? process.env.SENTRY_DSN ?? DEFAULT_DSN;
|
|
7
|
+
|
|
8
|
+
if (dsn) {
|
|
9
|
+
Sentry.init({
|
|
10
|
+
dsn,
|
|
11
|
+
environment: process.env.OMNARA_ENV ?? process.env.NODE_ENV ?? 'production',
|
|
12
|
+
sendDefaultPii: false,
|
|
13
|
+
});
|
|
14
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "omnara",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Command-line interface for Omnara.",
|
|
6
6
|
"main": "dist/cli.js",
|
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
"files": [
|
|
24
24
|
"dist",
|
|
25
25
|
"bin",
|
|
26
|
+
"instrument.mjs",
|
|
26
27
|
"scripts",
|
|
27
28
|
"README.md"
|
|
28
29
|
],
|
|
@@ -30,6 +31,7 @@
|
|
|
30
31
|
"@anthropic-ai/claude-agent-sdk": "^0.1.42",
|
|
31
32
|
"@anthropic-ai/sdk": "^0.67.0",
|
|
32
33
|
"@modelcontextprotocol/sdk": "^1.20.1",
|
|
34
|
+
"@sentry/node": "^10.26.0",
|
|
33
35
|
"@supabase/supabase-js": "^2.76.1",
|
|
34
36
|
"@types/glob": "^8.1.0",
|
|
35
37
|
"ajv": "^8.17.1",
|
|
@@ -48,6 +50,7 @@
|
|
|
48
50
|
"@types/ws": "^8.18.1",
|
|
49
51
|
"@typescript-eslint/eslint-plugin": "^8.46.2",
|
|
50
52
|
"@typescript-eslint/parser": "^8.46.2",
|
|
53
|
+
"@vitest/ui": "^2.1.8",
|
|
51
54
|
"esbuild": "^0.25.12",
|
|
52
55
|
"eslint": "^9.38.0",
|
|
53
56
|
"eslint-formatter-unix": "^8.40.0",
|
|
@@ -55,7 +58,8 @@
|
|
|
55
58
|
"prettier": "^3.6.2",
|
|
56
59
|
"tsx": "^4.7.0",
|
|
57
60
|
"typescript": "^5.4.0",
|
|
58
|
-
"typescript-eslint": "^8.46.2"
|
|
61
|
+
"typescript-eslint": "^8.46.2",
|
|
62
|
+
"vitest": "^2.1.8"
|
|
59
63
|
},
|
|
60
64
|
"engines": {
|
|
61
65
|
"node": ">=20"
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import fs from 'node:fs';
|
|
2
|
-
import { ControlledLogger, LogLevel } from '../utils/logger.js';
|
|
3
|
-
export declare class FileBackedLogger extends ControlledLogger {
|
|
4
|
-
private readonly stream;
|
|
5
|
-
private closed;
|
|
6
|
-
constructor(stream: fs.WriteStream, options?: {
|
|
7
|
-
logLevel?: LogLevel;
|
|
8
|
-
forceOutput?: boolean;
|
|
9
|
-
});
|
|
10
|
-
log(...args: unknown[]): void;
|
|
11
|
-
info(...args: unknown[]): void;
|
|
12
|
-
debug(...args: unknown[]): void;
|
|
13
|
-
warn(...args: unknown[]): void;
|
|
14
|
-
error(...args: unknown[]): void;
|
|
15
|
-
trace(...args: unknown[]): void;
|
|
16
|
-
important(...args: unknown[]): void;
|
|
17
|
-
success(...args: unknown[]): void;
|
|
18
|
-
close(): Promise<void>;
|
|
19
|
-
private writeLine;
|
|
20
|
-
}
|
|
21
|
-
export declare function createDaemonFileLogger(): Promise<{
|
|
22
|
-
logger: FileBackedLogger;
|
|
23
|
-
logPath: string;
|
|
24
|
-
}>;
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import fs from 'node:fs';
|
|
2
|
-
export interface SessionLogHandle {
|
|
3
|
-
stream: fs.WriteStream;
|
|
4
|
-
logPath: string;
|
|
5
|
-
}
|
|
6
|
-
export declare function createSessionLog(handle: {
|
|
7
|
-
workspaceId: string;
|
|
8
|
-
launchId: string;
|
|
9
|
-
}): Promise<SessionLogHandle>;
|
|
10
|
-
export declare function writeSessionLog(stream: fs.WriteStream, level: string, args: unknown[]): void;
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
export interface StatusUpdateEvent {
|
|
2
|
-
message: string;
|
|
3
|
-
metadata?: Record<string, unknown>;
|
|
4
|
-
timestamp: number;
|
|
5
|
-
}
|
|
6
|
-
export type StatusUpdateCallback = (event: StatusUpdateEvent) => void;
|
|
7
|
-
export declare function createWorkerStatusMcpServer(onStatusUpdate: StatusUpdateCallback): import("@anthropic-ai/claude-agent-sdk").McpSdkServerConfigWithInstance;
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* A simple async queue for streaming messages to workers.
|
|
3
|
-
* Allows pushing messages and consuming them via async iteration.
|
|
4
|
-
*/
|
|
5
|
-
export declare class AsyncQueue<T> {
|
|
6
|
-
private queue;
|
|
7
|
-
private resolvers;
|
|
8
|
-
private closed;
|
|
9
|
-
/**
|
|
10
|
-
* Push a new item to the queue.
|
|
11
|
-
* If there are waiting consumers, resolve them immediately.
|
|
12
|
-
*/
|
|
13
|
-
push(item: T): void;
|
|
14
|
-
/**
|
|
15
|
-
* Close the queue, signaling that no more items will be added.
|
|
16
|
-
*/
|
|
17
|
-
close(): void;
|
|
18
|
-
/**
|
|
19
|
-
* Check if the queue is closed.
|
|
20
|
-
*/
|
|
21
|
-
isClosed(): boolean;
|
|
22
|
-
/**
|
|
23
|
-
* Async iterator implementation for consuming items from the queue.
|
|
24
|
-
*/
|
|
25
|
-
[Symbol.asyncIterator](): AsyncIterator<T>;
|
|
26
|
-
}
|