omnara 0.6.0 → 1.0.0-beta.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/package.json +14 -57
- package/src/bin.ts +34 -0
- package/src/browser.ts +16 -0
- package/src/config.ts +185 -0
- package/src/factory.ts +396 -0
- package/src/flags.ts +174 -0
- package/src/format.ts +45 -0
- package/src/interactive.ts +56 -0
- package/src/login.test.ts +131 -0
- package/src/login.ts +204 -0
- package/src/manifest.ts +702 -0
- package/src/mcp-add.ts +299 -0
- package/src/mcp-oauth.ts +175 -0
- package/src/output.ts +239 -0
- package/src/reporter.ts +73 -0
- package/src/skill-archive.ts +58 -0
- package/src/slack-integration.ts +225 -0
- package/tsconfig.json +7 -0
- package/README.md +0 -20
- package/bin/omnara.js +0 -26
- package/dist/auth/auth-provider.d.ts +0 -26
- package/dist/auth/cli-auth-service.d.ts +0 -26
- package/dist/auth/credential-manager.d.ts +0 -13
- package/dist/auth/credentials-store.d.ts +0 -20
- package/dist/auth/ensure-cli-credentials.d.ts +0 -8
- package/dist/auth/login-flow.d.ts +0 -11
- package/dist/auth/loopback-listener.d.ts +0 -20
- package/dist/auth/pkce.d.ts +0 -6
- package/dist/cli.d.ts +0 -3
- package/dist/cli.js +0 -19479
- package/dist/cli.js.map +0 -7
- package/dist/commands/agent.d.ts +0 -9
- package/dist/commands/auth.d.ts +0 -2
- package/dist/commands/daemon.d.ts +0 -2
- package/dist/commands/index.d.ts +0 -4
- package/dist/commands/kill.d.ts +0 -2
- package/dist/config/omnara-config.d.ts +0 -19
- package/dist/daemon/config-store.d.ts +0 -37
- package/dist/daemon/daemon-client.d.ts +0 -27
- package/dist/daemon/daemon-launcher.d.ts +0 -39
- package/dist/daemon/daemon-service.d.ts +0 -30
- package/dist/daemon/directory-registry.d.ts +0 -17
- package/dist/daemon/local-control-server.d.ts +0 -38
- package/dist/daemon/machine-supervisor.d.ts +0 -63
- package/dist/daemon/paths.d.ts +0 -16
- package/dist/daemon/run-daemon.d.ts +0 -1
- package/dist/daemon/session-pid-registry.d.ts +0 -11
- package/dist/daemon/session-runner.d.ts +0 -38
- package/dist/daemon/state-store.d.ts +0 -14
- package/dist/env/env-mode.d.ts +0 -2
- package/dist/http/api-client.d.ts +0 -19
- package/dist/http/machines.d.ts +0 -3
- package/dist/http/user-sessions.d.ts +0 -16
- package/dist/http/workspaces.d.ts +0 -4
- package/dist/index.d.ts +0 -1
- package/dist/orchestrator/agent-orchestrator.d.ts +0 -103
- package/dist/orchestrator/ai-client.d.ts +0 -33
- package/dist/orchestrator/orchestrator-prompt.d.ts +0 -8
- package/dist/orchestrator/orchestrator-prompt.md +0 -222
- package/dist/orchestrator/orchestrator-types.d.ts +0 -168
- package/dist/orchestrator/session.d.ts +0 -83
- package/dist/orchestrator/tools/worker-tools.d.ts +0 -10
- package/dist/orchestrator/utils/completions-manager.d.ts +0 -8
- package/dist/orchestrator/utils/envelope-utils.d.ts +0 -13
- package/dist/orchestrator/utils/index.d.ts +0 -2
- package/dist/orchestrator/utils/session-logger.d.ts +0 -7
- package/dist/orchestrator/utils/worker-events.d.ts +0 -7
- package/dist/orchestrator/utils/worktree-manager.d.ts +0 -51
- package/dist/orchestrator/worker-manager.d.ts +0 -81
- package/dist/orchestrator/worker-types.d.ts +0 -23
- package/dist/orchestrator-prompt.md +0 -222
- package/dist/package-info.d.ts +0 -12
- package/dist/relay/relay-bridge.d.ts +0 -65
- package/dist/relay/relay-service.d.ts +0 -19
- package/dist/schemas/index.d.ts +0 -2
- package/dist/utils/backoff.d.ts +0 -6
- package/dist/utils/browser.d.ts +0 -1
- package/dist/utils/claude-code-check.d.ts +0 -19
- package/dist/utils/executable.d.ts +0 -53
- package/dist/utils/logger.d.ts +0 -143
- package/dist/utils/prompt.d.ts +0 -1
- package/dist/utils/version-check.d.ts +0 -43
- package/dist/utils/websocket.d.ts +0 -5
- package/instrument.mjs +0 -14
- package/scripts/build-executable.ts +0 -244
- package/scripts/copy-assets.mjs +0 -41
- package/scripts/generate-release-json.ts +0 -136
- package/scripts/preinstall.js +0 -141
- package/scripts/test-preinstall.js +0 -124
- package/scripts/upload-release.ts +0 -388
package/package.json
CHANGED
|
@@ -1,69 +1,26 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "omnara",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.0-beta.0",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"description": "Command-line interface for Omnara.",
|
|
6
|
-
"main": "dist/cli.js",
|
|
7
|
-
"types": "dist/cli.d.ts",
|
|
8
5
|
"bin": {
|
|
9
|
-
"omnara": "./bin
|
|
6
|
+
"omnara": "./src/bin.ts"
|
|
10
7
|
},
|
|
11
8
|
"scripts": {
|
|
12
|
-
"
|
|
13
|
-
"
|
|
14
|
-
"
|
|
15
|
-
"build:exe:all": "bun run scripts/build-executable.ts --all",
|
|
16
|
-
"build:release": "bun run scripts/build-executable.ts --all && bun run scripts/generate-release-json.ts",
|
|
17
|
-
"copy-assets": "node scripts/copy-assets.mjs",
|
|
18
|
-
"preinstall": "node scripts/preinstall.js"
|
|
9
|
+
"omnara": "tsx src/bin.ts",
|
|
10
|
+
"test": "vitest run",
|
|
11
|
+
"typecheck": "tsc --noEmit -p tsconfig.json"
|
|
19
12
|
},
|
|
20
|
-
"keywords": [
|
|
21
|
-
"omnara",
|
|
22
|
-
"cli"
|
|
23
|
-
],
|
|
24
|
-
"author": "Omnara",
|
|
25
|
-
"license": "UNLICENSED",
|
|
26
|
-
"files": [
|
|
27
|
-
"dist",
|
|
28
|
-
"bin",
|
|
29
|
-
"instrument.mjs",
|
|
30
|
-
"scripts",
|
|
31
|
-
"README.md"
|
|
32
|
-
],
|
|
33
13
|
"dependencies": {
|
|
34
|
-
"@
|
|
35
|
-
"@
|
|
36
|
-
"
|
|
37
|
-
"
|
|
38
|
-
"
|
|
39
|
-
"ajv": "^8.17.1",
|
|
40
|
-
"ajv-formats": "^2.1.1",
|
|
41
|
-
"chalk": "^4.1.2",
|
|
42
|
-
"commander": "^11.1.0",
|
|
43
|
-
"glob": "^9.3.5",
|
|
44
|
-
"jsonc-parser": "^3.3.1",
|
|
45
|
-
"simple-git": "^3.30.0",
|
|
46
|
-
"ws": "^8.18.3",
|
|
47
|
-
"zod": "^3.25.76"
|
|
14
|
+
"@clack/prompts": "^1.7.0",
|
|
15
|
+
"@omnara/sdk": "workspace:*",
|
|
16
|
+
"commander": "^14.0.0",
|
|
17
|
+
"tar": "^7.5.22",
|
|
18
|
+
"zod": "^4.4.3"
|
|
48
19
|
},
|
|
49
20
|
"devDependencies": {
|
|
50
|
-
"@
|
|
51
|
-
"
|
|
52
|
-
"
|
|
53
|
-
"
|
|
54
|
-
"@typescript-eslint/parser": "^8.46.2",
|
|
55
|
-
"@vitest/ui": "^2.1.8",
|
|
56
|
-
"esbuild": "^0.25.12",
|
|
57
|
-
"eslint": "^9.38.0",
|
|
58
|
-
"eslint-formatter-unix": "^8.40.0",
|
|
59
|
-
"json-schema-to-typescript": "^14.0.1",
|
|
60
|
-
"prettier": "^3.6.2",
|
|
61
|
-
"tsx": "^4.7.0",
|
|
62
|
-
"typescript": "^5.4.0",
|
|
63
|
-
"typescript-eslint": "^8.46.2",
|
|
64
|
-
"vitest": "^2.1.8"
|
|
65
|
-
},
|
|
66
|
-
"engines": {
|
|
67
|
-
"node": ">=20"
|
|
21
|
+
"@types/node": "^22.10.0",
|
|
22
|
+
"tsx": "^4.19.0",
|
|
23
|
+
"typescript": "^5.6.0",
|
|
24
|
+
"vitest": "4.1.9"
|
|
68
25
|
}
|
|
69
26
|
}
|
package/src/bin.ts
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
#!/usr/bin/env tsx
|
|
2
|
+
import { Command } from 'commander'
|
|
3
|
+
|
|
4
|
+
import { loadConfig, registerConfigCommand } from './config.ts'
|
|
5
|
+
import { registerGroup, registerOperation } from './factory.ts'
|
|
6
|
+
import { registerLoginCommand } from './login.ts'
|
|
7
|
+
import { commandGroups, topLevelOperations } from './manifest.ts'
|
|
8
|
+
|
|
9
|
+
process.stdout.on('error', (error: NodeJS.ErrnoException) => {
|
|
10
|
+
if (error.code === 'EPIPE') process.exit(0)
|
|
11
|
+
throw error
|
|
12
|
+
})
|
|
13
|
+
|
|
14
|
+
const program = new Command('omnara').description('Interact with the Omnara API')
|
|
15
|
+
program.configureHelp({
|
|
16
|
+
subcommandTerm: (cmd) => {
|
|
17
|
+
const args = cmd.registeredArguments
|
|
18
|
+
.map((arg) =>
|
|
19
|
+
arg.required
|
|
20
|
+
? `<${arg.name()}${arg.variadic ? '...' : ''}>`
|
|
21
|
+
: `[${arg.name()}${arg.variadic ? '...' : ''}]`,
|
|
22
|
+
)
|
|
23
|
+
.join(' ')
|
|
24
|
+
return [cmd.name(), cmd.options.length > 0 ? '[options]' : '', args]
|
|
25
|
+
.filter((part) => part !== '')
|
|
26
|
+
.join(' ')
|
|
27
|
+
},
|
|
28
|
+
})
|
|
29
|
+
const config = loadConfig()
|
|
30
|
+
for (const group of commandGroups) registerGroup(program, config, group)
|
|
31
|
+
for (const operation of topLevelOperations) registerOperation(program, config, operation)
|
|
32
|
+
registerLoginCommand(program, config)
|
|
33
|
+
registerConfigCommand(program, config)
|
|
34
|
+
await program.parseAsync()
|
package/src/browser.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { spawn } from 'node:child_process'
|
|
2
|
+
|
|
3
|
+
function browserCommand(url: string): { command: string; args: string[] } {
|
|
4
|
+
if (process.platform === 'darwin') return { command: 'open', args: [url] }
|
|
5
|
+
if (process.platform === 'win32') return { command: 'cmd', args: ['/c', 'start', '', url] }
|
|
6
|
+
return { command: 'xdg-open', args: [url] }
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function openInBrowser(url: string, onError: (message: string) => void): void {
|
|
10
|
+
const { command, args } = browserCommand(url)
|
|
11
|
+
const child = spawn(command, args, { stdio: 'ignore', detached: true })
|
|
12
|
+
child.once('error', () => {
|
|
13
|
+
onError('could not open a browser; use the URL above')
|
|
14
|
+
})
|
|
15
|
+
child.unref()
|
|
16
|
+
}
|
package/src/config.ts
ADDED
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import { chmodSync, existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'
|
|
2
|
+
import { homedir } from 'node:os'
|
|
3
|
+
import { dirname, join } from 'node:path'
|
|
4
|
+
|
|
5
|
+
import { bearerToken, createOmnaraClient, type OmnaraClient } from '@omnara/sdk'
|
|
6
|
+
import { zOrganizationId, zProjectId } from '@omnara/sdk/zod'
|
|
7
|
+
import type { Command } from 'commander'
|
|
8
|
+
import * as z from 'zod'
|
|
9
|
+
|
|
10
|
+
import {
|
|
11
|
+
canPromptInteractively,
|
|
12
|
+
promptOrgSelection,
|
|
13
|
+
promptProjectSelection,
|
|
14
|
+
} from './interactive.ts'
|
|
15
|
+
import { CliInputError, runCliAction } from './output.ts'
|
|
16
|
+
|
|
17
|
+
export const DEFAULT_BASE_URL = 'https://app.omnara.com'
|
|
18
|
+
|
|
19
|
+
const zConfigFile = z.looseObject({
|
|
20
|
+
base_url: z.url().optional(),
|
|
21
|
+
token: z.string().min(1).optional(),
|
|
22
|
+
org_id: zOrganizationId.optional(),
|
|
23
|
+
project_id: zProjectId.optional(),
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
export type ConfigFile = z.infer<typeof zConfigFile>
|
|
27
|
+
|
|
28
|
+
export interface CliConfig {
|
|
29
|
+
client: OmnaraClient
|
|
30
|
+
baseUrl: string
|
|
31
|
+
defaultOrgId?: string
|
|
32
|
+
defaultProjectId?: string
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function configFilePath(): string {
|
|
36
|
+
return join(homedir(), '.config', 'omnara', 'config.json')
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
let warnedAboutConfig = false
|
|
40
|
+
|
|
41
|
+
function warnConfigIgnored(message: string): void {
|
|
42
|
+
if (warnedAboutConfig) return
|
|
43
|
+
warnedAboutConfig = true
|
|
44
|
+
console.error(message)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const zConfigContents = z
|
|
48
|
+
.string()
|
|
49
|
+
.transform((raw, ctx): unknown => {
|
|
50
|
+
try {
|
|
51
|
+
return JSON.parse(raw)
|
|
52
|
+
} catch (error) {
|
|
53
|
+
ctx.addIssue(error instanceof Error ? error.message : String(error))
|
|
54
|
+
return z.NEVER
|
|
55
|
+
}
|
|
56
|
+
})
|
|
57
|
+
.pipe(zConfigFile)
|
|
58
|
+
|
|
59
|
+
function loadConfigFile(): z.ZodSafeParseResult<ConfigFile> {
|
|
60
|
+
const path = configFilePath()
|
|
61
|
+
if (!existsSync(path)) return { success: true, data: {} }
|
|
62
|
+
return zConfigContents.safeParse(readFileSync(path, 'utf8'))
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export function readConfigFile(): ConfigFile {
|
|
66
|
+
const result = loadConfigFile()
|
|
67
|
+
if (result.success) return result.data
|
|
68
|
+
warnConfigIgnored(
|
|
69
|
+
`warning: ignoring unreadable config at ${configFilePath()}: ${z.prettifyError(result.error)}`,
|
|
70
|
+
)
|
|
71
|
+
return {}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export function readConfigFileForUpdate(): ConfigFile {
|
|
75
|
+
const result = loadConfigFile()
|
|
76
|
+
if (result.success) return result.data
|
|
77
|
+
throw new CliInputError(
|
|
78
|
+
`refusing to modify unreadable config at ${configFilePath()} (fix or delete it first): ${z.prettifyError(result.error)}`,
|
|
79
|
+
)
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export function updateConfigFile(patch: Partial<ConfigFile>): ConfigFile {
|
|
83
|
+
const merged = Object.fromEntries(
|
|
84
|
+
Object.entries({ ...readConfigFileForUpdate(), ...patch }).filter(
|
|
85
|
+
([, value]) => value !== undefined,
|
|
86
|
+
),
|
|
87
|
+
)
|
|
88
|
+
const result = zConfigFile.safeParse(merged)
|
|
89
|
+
if (!result.success) {
|
|
90
|
+
throw new CliInputError(`refusing to save invalid config:\n${z.prettifyError(result.error)}`)
|
|
91
|
+
}
|
|
92
|
+
mkdirSync(dirname(configFilePath()), { recursive: true, mode: 0o700 })
|
|
93
|
+
writeFileSync(configFilePath(), `${JSON.stringify(result.data, null, 2)}\n`, { mode: 0o600 })
|
|
94
|
+
chmodSync(configFilePath(), 0o600)
|
|
95
|
+
return result.data
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export function loadConfig(): CliConfig {
|
|
99
|
+
const file = readConfigFile()
|
|
100
|
+
const baseUrl = process.env.OMNARA_BASE_URL ?? file.base_url ?? DEFAULT_BASE_URL
|
|
101
|
+
const token = process.env.OMNARA_API_KEY ?? file.token
|
|
102
|
+
const client = createOmnaraClient({
|
|
103
|
+
baseUrl,
|
|
104
|
+
auth: token ? bearerToken(token) : undefined,
|
|
105
|
+
})
|
|
106
|
+
return {
|
|
107
|
+
client,
|
|
108
|
+
baseUrl,
|
|
109
|
+
defaultOrgId: process.env.OMNARA_ORG_ID ?? file.org_id,
|
|
110
|
+
defaultProjectId: process.env.OMNARA_PROJECT_ID ?? file.project_id,
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
interface ConfigOptions {
|
|
115
|
+
org?: string
|
|
116
|
+
project?: string
|
|
117
|
+
baseUrl?: string
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function describeValue(
|
|
121
|
+
envName: string,
|
|
122
|
+
fileValue: string | undefined,
|
|
123
|
+
defaultValue?: string,
|
|
124
|
+
): string {
|
|
125
|
+
const envValue = process.env[envName]
|
|
126
|
+
if (envValue !== undefined) {
|
|
127
|
+
const shadowed = fileValue !== undefined ? ` (config has ${fileValue})` : ''
|
|
128
|
+
return `${envValue} [from ${envName}${shadowed}]`
|
|
129
|
+
}
|
|
130
|
+
if (fileValue !== undefined) return `${fileValue} [from config file]`
|
|
131
|
+
if (defaultValue !== undefined) return `${defaultValue} [default]`
|
|
132
|
+
return '(not set)'
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function printConfig(): void {
|
|
136
|
+
const file = readConfigFile()
|
|
137
|
+
console.log(`config file ${configFilePath()}`)
|
|
138
|
+
console.log(`org_id ${describeValue('OMNARA_ORG_ID', file.org_id)}`)
|
|
139
|
+
console.log(`project_id ${describeValue('OMNARA_PROJECT_ID', file.project_id)}`)
|
|
140
|
+
console.log(`base_url ${describeValue('OMNARA_BASE_URL', file.base_url, DEFAULT_BASE_URL)}`)
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
export function registerConfigCommand(program: Command, cli: CliConfig): void {
|
|
144
|
+
const config = program
|
|
145
|
+
.command('config')
|
|
146
|
+
.description('Show or set the default organization and project')
|
|
147
|
+
.option('--org <org-id>', 'save this organization ID as the default')
|
|
148
|
+
.option('--project <project-id>', 'save this project ID as the default')
|
|
149
|
+
.option('--base-url <url>', 'save this API base URL as the default')
|
|
150
|
+
.action(async (options: ConfigOptions) => {
|
|
151
|
+
await runCliAction(() => {
|
|
152
|
+
if (
|
|
153
|
+
options.org !== undefined ||
|
|
154
|
+
options.project !== undefined ||
|
|
155
|
+
options.baseUrl !== undefined
|
|
156
|
+
) {
|
|
157
|
+
const clearStaleProject = options.org !== undefined && options.project === undefined
|
|
158
|
+
updateConfigFile({
|
|
159
|
+
...(options.org !== undefined ? { org_id: options.org } : {}),
|
|
160
|
+
...(clearStaleProject
|
|
161
|
+
? { project_id: undefined }
|
|
162
|
+
: options.project !== undefined
|
|
163
|
+
? { project_id: options.project }
|
|
164
|
+
: {}),
|
|
165
|
+
...(options.baseUrl !== undefined ? { base_url: options.baseUrl } : {}),
|
|
166
|
+
})
|
|
167
|
+
}
|
|
168
|
+
printConfig()
|
|
169
|
+
})
|
|
170
|
+
})
|
|
171
|
+
config
|
|
172
|
+
.command('select')
|
|
173
|
+
.description('Interactively choose the default organization and project')
|
|
174
|
+
.action(async () => {
|
|
175
|
+
await runCliAction(async () => {
|
|
176
|
+
if (!canPromptInteractively()) {
|
|
177
|
+
throw new CliInputError('interactive selection needs a terminal')
|
|
178
|
+
}
|
|
179
|
+
const orgId = await promptOrgSelection(cli.client)
|
|
180
|
+
const projectId = await promptProjectSelection(cli.client, orgId)
|
|
181
|
+
updateConfigFile({ org_id: orgId, project_id: projectId })
|
|
182
|
+
printConfig()
|
|
183
|
+
})
|
|
184
|
+
})
|
|
185
|
+
}
|