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.
Files changed (90) hide show
  1. package/package.json +14 -57
  2. package/src/bin.ts +34 -0
  3. package/src/browser.ts +16 -0
  4. package/src/config.ts +185 -0
  5. package/src/factory.ts +396 -0
  6. package/src/flags.ts +174 -0
  7. package/src/format.ts +45 -0
  8. package/src/interactive.ts +56 -0
  9. package/src/login.test.ts +131 -0
  10. package/src/login.ts +204 -0
  11. package/src/manifest.ts +702 -0
  12. package/src/mcp-add.ts +299 -0
  13. package/src/mcp-oauth.ts +175 -0
  14. package/src/output.ts +239 -0
  15. package/src/reporter.ts +73 -0
  16. package/src/skill-archive.ts +58 -0
  17. package/src/slack-integration.ts +225 -0
  18. package/tsconfig.json +7 -0
  19. package/README.md +0 -20
  20. package/bin/omnara.js +0 -26
  21. package/dist/auth/auth-provider.d.ts +0 -26
  22. package/dist/auth/cli-auth-service.d.ts +0 -26
  23. package/dist/auth/credential-manager.d.ts +0 -13
  24. package/dist/auth/credentials-store.d.ts +0 -20
  25. package/dist/auth/ensure-cli-credentials.d.ts +0 -8
  26. package/dist/auth/login-flow.d.ts +0 -11
  27. package/dist/auth/loopback-listener.d.ts +0 -20
  28. package/dist/auth/pkce.d.ts +0 -6
  29. package/dist/cli.d.ts +0 -3
  30. package/dist/cli.js +0 -19479
  31. package/dist/cli.js.map +0 -7
  32. package/dist/commands/agent.d.ts +0 -9
  33. package/dist/commands/auth.d.ts +0 -2
  34. package/dist/commands/daemon.d.ts +0 -2
  35. package/dist/commands/index.d.ts +0 -4
  36. package/dist/commands/kill.d.ts +0 -2
  37. package/dist/config/omnara-config.d.ts +0 -19
  38. package/dist/daemon/config-store.d.ts +0 -37
  39. package/dist/daemon/daemon-client.d.ts +0 -27
  40. package/dist/daemon/daemon-launcher.d.ts +0 -39
  41. package/dist/daemon/daemon-service.d.ts +0 -30
  42. package/dist/daemon/directory-registry.d.ts +0 -17
  43. package/dist/daemon/local-control-server.d.ts +0 -38
  44. package/dist/daemon/machine-supervisor.d.ts +0 -63
  45. package/dist/daemon/paths.d.ts +0 -16
  46. package/dist/daemon/run-daemon.d.ts +0 -1
  47. package/dist/daemon/session-pid-registry.d.ts +0 -11
  48. package/dist/daemon/session-runner.d.ts +0 -38
  49. package/dist/daemon/state-store.d.ts +0 -14
  50. package/dist/env/env-mode.d.ts +0 -2
  51. package/dist/http/api-client.d.ts +0 -19
  52. package/dist/http/machines.d.ts +0 -3
  53. package/dist/http/user-sessions.d.ts +0 -16
  54. package/dist/http/workspaces.d.ts +0 -4
  55. package/dist/index.d.ts +0 -1
  56. package/dist/orchestrator/agent-orchestrator.d.ts +0 -103
  57. package/dist/orchestrator/ai-client.d.ts +0 -33
  58. package/dist/orchestrator/orchestrator-prompt.d.ts +0 -8
  59. package/dist/orchestrator/orchestrator-prompt.md +0 -222
  60. package/dist/orchestrator/orchestrator-types.d.ts +0 -168
  61. package/dist/orchestrator/session.d.ts +0 -83
  62. package/dist/orchestrator/tools/worker-tools.d.ts +0 -10
  63. package/dist/orchestrator/utils/completions-manager.d.ts +0 -8
  64. package/dist/orchestrator/utils/envelope-utils.d.ts +0 -13
  65. package/dist/orchestrator/utils/index.d.ts +0 -2
  66. package/dist/orchestrator/utils/session-logger.d.ts +0 -7
  67. package/dist/orchestrator/utils/worker-events.d.ts +0 -7
  68. package/dist/orchestrator/utils/worktree-manager.d.ts +0 -51
  69. package/dist/orchestrator/worker-manager.d.ts +0 -81
  70. package/dist/orchestrator/worker-types.d.ts +0 -23
  71. package/dist/orchestrator-prompt.md +0 -222
  72. package/dist/package-info.d.ts +0 -12
  73. package/dist/relay/relay-bridge.d.ts +0 -65
  74. package/dist/relay/relay-service.d.ts +0 -19
  75. package/dist/schemas/index.d.ts +0 -2
  76. package/dist/utils/backoff.d.ts +0 -6
  77. package/dist/utils/browser.d.ts +0 -1
  78. package/dist/utils/claude-code-check.d.ts +0 -19
  79. package/dist/utils/executable.d.ts +0 -53
  80. package/dist/utils/logger.d.ts +0 -143
  81. package/dist/utils/prompt.d.ts +0 -1
  82. package/dist/utils/version-check.d.ts +0 -43
  83. package/dist/utils/websocket.d.ts +0 -5
  84. package/instrument.mjs +0 -14
  85. package/scripts/build-executable.ts +0 -244
  86. package/scripts/copy-assets.mjs +0 -41
  87. package/scripts/generate-release-json.ts +0 -136
  88. package/scripts/preinstall.js +0 -141
  89. package/scripts/test-preinstall.js +0 -124
  90. package/scripts/upload-release.ts +0 -388
package/package.json CHANGED
@@ -1,69 +1,26 @@
1
1
  {
2
2
  "name": "omnara",
3
- "version": "0.6.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/omnara.js"
6
+ "omnara": "./src/bin.ts"
10
7
  },
11
8
  "scripts": {
12
- "build": "npm run build:types && node build.mjs && npm run copy-assets",
13
- "build:types": "tsc --emitDeclarationOnly --project tsconfig.json",
14
- "build:exe": "bun run scripts/build-executable.ts",
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
- "@anthropic-ai/claude-agent-sdk": "^0.1.42",
35
- "@anthropic-ai/sdk": "^0.67.0",
36
- "@modelcontextprotocol/sdk": "^1.20.1",
37
- "@sentry/node": "^10.28.0",
38
- "@types/glob": "^8.1.0",
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
- "@omnara/shared-js": "file:../shared-js",
51
- "@types/node": "^20.11.30",
52
- "@types/ws": "^8.18.1",
53
- "@typescript-eslint/eslint-plugin": "^8.46.2",
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
+ }