runwork 0.8.4 → 0.9.1
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/agents/__tests__/claude-code-stats.test.js +173 -2
- package/dist/agents/__tests__/codex-stats.test.js +93 -0
- package/dist/agents/claude-code.js +140 -19
- package/dist/agents/claude-desktop.d.ts +2 -1
- package/dist/agents/claude-desktop.js +57 -0
- package/dist/agents/codex.d.ts +28 -1
- package/dist/agents/codex.js +213 -2
- package/dist/agents/detect.js +2 -1
- package/dist/agents/detection.d.ts +17 -0
- package/dist/agents/detection.js +89 -0
- package/dist/agents/generic-adapter.js +3 -13
- package/dist/agents/registry-data.d.ts +126 -0
- package/dist/agents/registry-data.js +436 -0
- package/dist/agents/registry.d.ts +8 -48
- package/dist/agents/registry.js +9 -192
- package/dist/agents/types.d.ts +12 -0
- package/dist/auth/store.js +12 -1
- package/dist/commands/init.js +4 -0
- package/dist/commands/sync.js +21 -1
- package/dist/generated/version.d.ts +1 -1
- package/dist/generated/version.js +1 -1
- package/dist/utils/which.d.ts +8 -0
- package/dist/utils/which.js +29 -0
- package/package.json +1 -1
package/dist/agents/registry.js
CHANGED
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* CLI-side agent registry entry point.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
4
|
+
* The data and browser-safe types / lookups live in `./registry-data.ts` so
|
|
5
|
+
* that the desktop package can import them without pulling in Node-only
|
|
6
|
+
* modules. This file keeps the existing public surface for CLI callers by
|
|
7
|
+
* re-exporting everything from the data module and adding the Node-only path
|
|
8
|
+
* resolvers used by the generic adapter and `sync` command.
|
|
9
9
|
*/
|
|
10
10
|
import { platform, homedir } from 'os';
|
|
11
11
|
import { join } from 'path';
|
|
12
|
+
// Re-export types, data, and browser-safe lookups so every existing CLI
|
|
13
|
+
// caller keeps working unchanged (`import { getRegistryAgent, ... } from './registry.js'`).
|
|
14
|
+
export * from './registry-data.js';
|
|
12
15
|
function getNodePlatform() {
|
|
13
16
|
const p = platform();
|
|
14
17
|
if (p === 'darwin')
|
|
@@ -31,189 +34,3 @@ export function resolveToAbsolute(ps, scope) {
|
|
|
31
34
|
? join(homedir(), resolved)
|
|
32
35
|
: join(process.cwd(), resolved);
|
|
33
36
|
}
|
|
34
|
-
// ---------------------------------------------------------------------------
|
|
35
|
-
// Registry
|
|
36
|
-
// ---------------------------------------------------------------------------
|
|
37
|
-
const AGENT_REGISTRY = [
|
|
38
|
-
// === First-class agents (have custom adapters in CLI) ===
|
|
39
|
-
{
|
|
40
|
-
slug: 'claude-code',
|
|
41
|
-
name: 'Claude Code',
|
|
42
|
-
description: "Anthropic's AI coding agent for the terminal",
|
|
43
|
-
category: 'cli',
|
|
44
|
-
detection: { method: 'binary', target: 'claude' },
|
|
45
|
-
skillsPaths: { global: '.claude/skills', project: '.claude/skills' },
|
|
46
|
-
mcpConfigPath: '.claude/settings.json',
|
|
47
|
-
instructionFile: { global: '.claude/CLAUDE.md', project: '.claude/CLAUDE.md' },
|
|
48
|
-
mcpConfigKey: 'mcpServers',
|
|
49
|
-
firstClass: true,
|
|
50
|
-
},
|
|
51
|
-
{
|
|
52
|
-
slug: 'claude-desktop',
|
|
53
|
-
name: 'Claude Desktop',
|
|
54
|
-
aliases: ['Claude Desktop (Cowork)', 'Cowork'],
|
|
55
|
-
description: 'Claude as a desktop application',
|
|
56
|
-
category: 'desktop',
|
|
57
|
-
detection: {
|
|
58
|
-
method: 'path',
|
|
59
|
-
target: {
|
|
60
|
-
macos: 'Library/Application Support/Claude/claude_desktop_config.json',
|
|
61
|
-
windows: 'AppData/Roaming/Claude/claude_desktop_config.json',
|
|
62
|
-
linux: '.config/Claude/claude_desktop_config.json',
|
|
63
|
-
},
|
|
64
|
-
},
|
|
65
|
-
skillsPaths: { global: '.claude/skills', project: '.claude/skills' },
|
|
66
|
-
mcpConfigPath: {
|
|
67
|
-
macos: 'Library/Application Support/Claude/claude_desktop_config.json',
|
|
68
|
-
windows: 'AppData/Roaming/Claude/claude_desktop_config.json',
|
|
69
|
-
linux: '.config/Claude/claude_desktop_config.json',
|
|
70
|
-
},
|
|
71
|
-
mcpConfigKey: 'mcpServers',
|
|
72
|
-
firstClass: true,
|
|
73
|
-
},
|
|
74
|
-
{
|
|
75
|
-
slug: 'cursor',
|
|
76
|
-
name: 'Cursor',
|
|
77
|
-
description: 'AI-powered code editor',
|
|
78
|
-
category: 'ide',
|
|
79
|
-
detection: { method: 'binary', target: 'cursor' },
|
|
80
|
-
skillsPaths: { global: '.cursor/skills', project: '.cursor/skills' },
|
|
81
|
-
mcpConfigPath: '.cursor/mcp.json',
|
|
82
|
-
instructionFile: { project: '.cursor/rules/runwork.mdc' },
|
|
83
|
-
mcpConfigKey: 'mcpServers',
|
|
84
|
-
skillFormat: 'mdc',
|
|
85
|
-
firstClass: true,
|
|
86
|
-
},
|
|
87
|
-
{
|
|
88
|
-
slug: 'codex',
|
|
89
|
-
name: 'Codex CLI',
|
|
90
|
-
description: "OpenAI's AI coding agent for the terminal",
|
|
91
|
-
category: 'cli',
|
|
92
|
-
detection: { method: 'binary', target: 'codex' },
|
|
93
|
-
skillsPaths: { global: '.codex/skills', project: '.agents/skills' },
|
|
94
|
-
instructionFile: { global: '.codex/instructions.md', project: 'AGENTS.md' },
|
|
95
|
-
firstClass: true,
|
|
96
|
-
},
|
|
97
|
-
{
|
|
98
|
-
slug: 'windsurf',
|
|
99
|
-
name: 'Windsurf',
|
|
100
|
-
description: 'AI-powered code editor by Codeium',
|
|
101
|
-
category: 'ide',
|
|
102
|
-
detection: { method: 'binary', target: 'windsurf' },
|
|
103
|
-
skillsPaths: { global: '.codeium/windsurf/skills', project: '.windsurf/skills' },
|
|
104
|
-
mcpConfigPath: '.codeium/windsurf/mcp_config.json',
|
|
105
|
-
instructionFile: { global: '.codeium/windsurf/rules/runwork.md', project: '.windsurf/rules/runwork.md' },
|
|
106
|
-
mcpConfigKey: 'mcpServers',
|
|
107
|
-
skillFormat: 'windsurf-md',
|
|
108
|
-
firstClass: true,
|
|
109
|
-
},
|
|
110
|
-
{
|
|
111
|
-
slug: 'gemini',
|
|
112
|
-
name: 'Gemini CLI',
|
|
113
|
-
description: "Google's AI coding agent for the terminal",
|
|
114
|
-
category: 'cli',
|
|
115
|
-
detection: { method: 'binary', target: 'gemini' },
|
|
116
|
-
skillsPaths: { global: '.gemini/skills', project: '.gemini/skills' },
|
|
117
|
-
mcpConfigPath: '.gemini/settings.json',
|
|
118
|
-
instructionFile: { global: '.gemini/GEMINI.md', project: 'GEMINI.md' },
|
|
119
|
-
mcpConfigKey: 'mcpServers',
|
|
120
|
-
firstClass: true,
|
|
121
|
-
},
|
|
122
|
-
// === Additional agents with some custom handling ===
|
|
123
|
-
{
|
|
124
|
-
slug: 'copilot-vscode',
|
|
125
|
-
name: 'GitHub Copilot (VS Code)',
|
|
126
|
-
description: "GitHub's AI pair programmer in VS Code",
|
|
127
|
-
category: 'extension',
|
|
128
|
-
detection: { method: 'binary', target: 'code' },
|
|
129
|
-
skillsPaths: { global: '.copilot/skills', project: '.github/skills' },
|
|
130
|
-
mcpConfigPath: '.vscode/mcp.json',
|
|
131
|
-
mcpConfigKey: 'servers',
|
|
132
|
-
},
|
|
133
|
-
{
|
|
134
|
-
slug: 'cline',
|
|
135
|
-
name: 'Cline',
|
|
136
|
-
description: 'Autonomous AI coding agent for VS Code',
|
|
137
|
-
category: 'extension',
|
|
138
|
-
detection: { method: 'binary', target: 'cline' },
|
|
139
|
-
skillsPaths: { global: '.agents/skills', project: '.agents/skills' },
|
|
140
|
-
},
|
|
141
|
-
{
|
|
142
|
-
slug: 'copilot-cli',
|
|
143
|
-
name: 'GitHub Copilot CLI',
|
|
144
|
-
description: 'GitHub Copilot in the terminal',
|
|
145
|
-
category: 'cli',
|
|
146
|
-
detection: { method: 'binary', target: 'gh' },
|
|
147
|
-
skillsPaths: { global: '.copilot/skills', project: '.github/skills' },
|
|
148
|
-
mcpConfigPath: '.copilot/mcp-config.json',
|
|
149
|
-
mcpConfigKey: 'mcpServers',
|
|
150
|
-
},
|
|
151
|
-
// === Community agents (from skillshare targets.yaml) ===
|
|
152
|
-
{ slug: 'antigravity', name: 'Antigravity', description: "Google's Antigravity AI agent", category: 'cli', detection: { method: 'binary', target: 'antigravity' }, skillsPaths: { global: '.gemini/antigravity/skills', project: '.agent/skills' } },
|
|
153
|
-
{ slug: 'amp', name: 'Amp', description: 'AI coding agent by Sourcegraph', category: 'cli', detection: { method: 'binary', target: 'amp' }, skillsPaths: { global: '.config/agents/skills', project: '.agents/skills' } },
|
|
154
|
-
{ slug: 'adal', name: 'AdaL', description: 'AI coding agent', category: 'cli', detection: { method: 'binary', target: 'adal' }, skillsPaths: { global: '.adal/skills', project: '.adal/skills' } },
|
|
155
|
-
{ slug: 'astrbot', name: 'AstrBot', description: 'AI coding agent', category: 'cli', detection: { method: 'binary', target: 'astrbot' }, skillsPaths: { global: '.astrbot/data/skills', project: 'data/skills' } },
|
|
156
|
-
{ slug: 'augment', name: 'Augment', description: 'AI coding assistant', category: 'ide', detection: { method: 'binary', target: 'augment' }, skillsPaths: { global: '.augment/skills', project: '.augment/skills' } },
|
|
157
|
-
{ slug: 'bob', name: 'Bob', description: 'AI coding agent', category: 'cli', detection: { method: 'binary', target: 'bob' }, skillsPaths: { global: '.bob/skills', project: '.bob/skills' } },
|
|
158
|
-
{ slug: 'codebuddy', name: 'CodeBuddy', description: 'AI coding assistant', category: 'cli', detection: { method: 'binary', target: 'codebuddy' }, skillsPaths: { global: '.codebuddy/skills', project: '.codebuddy/skills' } },
|
|
159
|
-
{ slug: 'comate', name: 'Comate', description: 'AI coding agent', category: 'cli', detection: { method: 'binary', target: 'comate' }, skillsPaths: { global: '.comate/skills', project: '.comate/skills' } },
|
|
160
|
-
{ slug: 'commandcode', name: 'Command Code', description: 'AI coding agent', category: 'cli', detection: { method: 'binary', target: 'commandcode' }, skillsPaths: { global: '.commandcode/skills', project: '.commandcode/skills' } },
|
|
161
|
-
{ slug: 'continue', name: 'Continue', description: 'Open-source AI code assistant', category: 'extension', detection: { method: 'binary', target: 'continue' }, skillsPaths: { global: '.continue/skills', project: '.continue/skills' } },
|
|
162
|
-
{ slug: 'cortex', name: 'Cortex', description: "Snowflake's AI coding agent", category: 'cli', detection: { method: 'binary', target: 'cortex' }, skillsPaths: { global: '.snowflake/cortex/skills', project: '.cortex/skills' } },
|
|
163
|
-
{ slug: 'crush', name: 'Crush', description: 'AI agent by Charm', category: 'cli', detection: { method: 'binary', target: 'crush' }, skillsPaths: { global: '.config/crush/skills', project: '.crush/skills' } },
|
|
164
|
-
{ slug: 'deepagents', name: 'Deep Agents', description: 'AI coding agent', category: 'cli', detection: { method: 'binary', target: 'deepagents' }, skillsPaths: { global: '.deepagents/agent/skills', project: '.deepagents/skills' } },
|
|
165
|
-
{ slug: 'droid', name: 'Droid', description: "Factory AI's coding agent", category: 'cli', detection: { method: 'binary', target: 'droid' }, skillsPaths: { global: '.factory/skills', project: '.factory/skills' } },
|
|
166
|
-
{ slug: 'firebender', name: 'Firebender', description: 'AI coding agent', category: 'cli', detection: { method: 'binary', target: 'firebender' }, skillsPaths: { global: '.firebender/skills', project: '.firebender/skills' } },
|
|
167
|
-
{ slug: 'goose', name: 'Goose', description: 'AI coding agent by Block', category: 'cli', detection: { method: 'binary', target: 'goose' }, skillsPaths: { global: '.config/goose/skills', project: '.goose/skills' } },
|
|
168
|
-
{ slug: 'hermes', name: 'Hermes', description: 'AI coding agent', category: 'cli', detection: { method: 'binary', target: 'hermes' }, skillsPaths: { global: '.hermes/skills', project: '.hermes/skills' } },
|
|
169
|
-
{ slug: 'iflow', name: 'iFlow CLI', description: 'AI coding agent', category: 'cli', detection: { method: 'binary', target: 'iflow' }, skillsPaths: { global: '.iflow/skills', project: '.iflow/skills' } },
|
|
170
|
-
{ slug: 'junie', name: 'Junie', description: 'JetBrains AI coding agent', category: 'ide', detection: { method: 'binary', target: 'junie' }, skillsPaths: { global: '.junie/skills', project: '.junie/skills' } },
|
|
171
|
-
{ slug: 'kilocode', name: 'Kilo Code', description: 'AI coding agent', category: 'extension', detection: { method: 'binary', target: 'kilocode' }, skillsPaths: { global: '.kilocode/skills', project: '.kilocode/skills' } },
|
|
172
|
-
{ slug: 'kimi', name: 'Kimi Code CLI', description: "Moonshot AI's coding agent", category: 'cli', detection: { method: 'binary', target: 'kimi' }, skillsPaths: { global: '.config/agents/skills', project: '.agents/skills' } },
|
|
173
|
-
{ slug: 'kiro', name: 'Kiro', description: "AWS's AI coding agent", category: 'ide', detection: { method: 'binary', target: 'kiro' }, skillsPaths: { global: '.kiro/skills', project: '.kiro/skills' } },
|
|
174
|
-
{ slug: 'kode', name: 'Kode', description: 'AI coding agent', category: 'cli', detection: { method: 'binary', target: 'kode' }, skillsPaths: { global: '.kode/skills', project: '.kode/skills' } },
|
|
175
|
-
{ slug: 'letta', name: 'Letta', description: 'AI coding agent', category: 'cli', detection: { method: 'binary', target: 'letta' }, skillsPaths: { global: '.letta/skills', project: '.skills' } },
|
|
176
|
-
{ slug: 'lingma', name: 'Lingma', description: 'AI coding agent', category: 'cli', detection: { method: 'binary', target: 'lingma' }, skillsPaths: { global: '.lingma/skills', project: '.lingma/skills' } },
|
|
177
|
-
{ slug: 'mcpjam', name: 'MCPJam', description: 'MCP-based AI agent', category: 'cli', detection: { method: 'binary', target: 'mcpjam' }, skillsPaths: { global: '.mcpjam/skills', project: '.mcpjam/skills' } },
|
|
178
|
-
{ slug: 'mux', name: 'Mux', description: 'AI coding agent', category: 'cli', detection: { method: 'binary', target: 'mux' }, skillsPaths: { global: '.mux/skills', project: '.mux/skills' } },
|
|
179
|
-
{ slug: 'neovate', name: 'Neovate', description: 'AI coding agent for Neovim', category: 'extension', detection: { method: 'binary', target: 'neovate' }, skillsPaths: { global: '.neovate/skills', project: '.neovate/skills' } },
|
|
180
|
-
{ slug: 'omp', name: 'Oh My Pi', description: 'AI coding agent', category: 'cli', detection: { method: 'binary', target: 'omp' }, skillsPaths: { global: '.omp/agent/skills', project: '.omp/skills' } },
|
|
181
|
-
{ slug: 'openclaw', name: 'OpenClaw', description: 'AI coding agent', category: 'cli', detection: { method: 'binary', target: 'openclaw' }, skillsPaths: { global: '.openclaw/skills', project: 'skills' } },
|
|
182
|
-
{ slug: 'opencode', name: 'OpenCode', description: 'Open-source AI coding agent', category: 'cli', detection: { method: 'binary', target: 'opencode' }, skillsPaths: { global: '.config/opencode/skills', project: '.opencode/skills' } },
|
|
183
|
-
{ slug: 'openhands', name: 'OpenHands', description: 'Open-source AI coding agent', category: 'cli', detection: { method: 'binary', target: 'openhands' }, skillsPaths: { global: '.openhands/skills', project: '.openhands/skills' } },
|
|
184
|
-
{ slug: 'pi', name: 'Pi', description: 'AI coding agent', category: 'cli', detection: { method: 'binary', target: 'pi' }, skillsPaths: { global: '.pi/agent/skills', project: '.pi/skills' } },
|
|
185
|
-
{ slug: 'pochi', name: 'Pochi', description: 'AI coding agent', category: 'cli', detection: { method: 'binary', target: 'pochi' }, skillsPaths: { global: '.pochi/skills', project: '.pochi/skills' } },
|
|
186
|
-
{ slug: 'purecode', name: 'PureCode AI', description: 'AI coding agent', category: 'cli', detection: { method: 'binary', target: 'purecode' }, skillsPaths: { global: '.purecode/skills', project: '.agents/skills' } },
|
|
187
|
-
{ slug: 'qoder', name: 'Qoder', description: 'AI coding agent', category: 'cli', detection: { method: 'binary', target: 'qoder' }, skillsPaths: { global: '.qoder/skills', project: '.qoder/skills' } },
|
|
188
|
-
{ slug: 'qwen', name: 'Qwen Code', description: "Alibaba's AI coding agent", category: 'cli', detection: { method: 'binary', target: 'qwen' }, skillsPaths: { global: '.qwen/skills', project: '.qwen/skills' } },
|
|
189
|
-
{ slug: 'roo', name: 'Roo Code', description: 'AI coding agent', category: 'extension', detection: { method: 'binary', target: 'roo' }, skillsPaths: { global: '.roo/skills', project: '.roo/skills' } },
|
|
190
|
-
{ slug: 'trae', name: 'Trae', description: 'ByteDance AI coding IDE', category: 'ide', detection: { method: 'binary', target: 'trae' }, skillsPaths: { global: '.trae/skills', project: '.trae/skills' } },
|
|
191
|
-
{ slug: 'mistral-vibe', name: 'Mistral Vibe', description: "Mistral's AI coding agent", category: 'cli', detection: { method: 'binary', target: 'vibe' }, skillsPaths: { global: '.vibe/skills', project: '.vibe/skills' } },
|
|
192
|
-
{ slug: 'verdent', name: 'Verdent', description: 'AI coding agent', category: 'cli', detection: { method: 'binary', target: 'verdent' }, skillsPaths: { global: '.verdent/skills', project: '.verdent/skills' } },
|
|
193
|
-
{ slug: 'warp', name: 'Warp AI', description: 'AI-powered terminal', category: 'cli', detection: { method: 'path', target: { macos: '/Applications/Warp.app', linux: '/usr/bin/warp-terminal' } }, skillsPaths: { global: '.agents/skills', project: '.agents/skills' } },
|
|
194
|
-
{ slug: 'witsy', name: 'Witsy', description: 'AI coding agent', category: 'cli', detection: { method: 'binary', target: 'witsy' }, skillsPaths: { global: '.agents/skills', project: '.agents/skills' } },
|
|
195
|
-
{ slug: 'zencoder', name: 'Zencoder', description: 'AI coding agent', category: 'cli', detection: { method: 'binary', target: 'zencoder' }, skillsPaths: { global: '.zencoder/skills', project: '.zencoder/skills' } },
|
|
196
|
-
{ slug: 'replit', name: 'Replit', description: 'AI-powered coding platform', category: 'ide', detection: { method: 'binary', target: 'replit' }, skillsPaths: { global: '.config/agents/skills', project: '.agents/skills' } },
|
|
197
|
-
];
|
|
198
|
-
// ---------------------------------------------------------------------------
|
|
199
|
-
// Index (built once)
|
|
200
|
-
// ---------------------------------------------------------------------------
|
|
201
|
-
const slugIndex = new Map();
|
|
202
|
-
for (const agent of AGENT_REGISTRY) {
|
|
203
|
-
slugIndex.set(agent.slug, agent);
|
|
204
|
-
}
|
|
205
|
-
// ---------------------------------------------------------------------------
|
|
206
|
-
// Public API
|
|
207
|
-
// ---------------------------------------------------------------------------
|
|
208
|
-
export function getRegistryAgent(slug) {
|
|
209
|
-
return slugIndex.get(slug);
|
|
210
|
-
}
|
|
211
|
-
export function getRegistryAgents() {
|
|
212
|
-
return AGENT_REGISTRY;
|
|
213
|
-
}
|
|
214
|
-
export function getFirstClassSlugs() {
|
|
215
|
-
return AGENT_REGISTRY.filter(a => a.firstClass).map(a => a.slug);
|
|
216
|
-
}
|
|
217
|
-
export function getCustomAdapterSlugs() {
|
|
218
|
-
return new Set(['claude-code', 'claude-desktop', 'cursor', 'windsurf', 'codex', 'cline', 'gemini']);
|
|
219
|
-
}
|
package/dist/agents/types.d.ts
CHANGED
|
@@ -75,6 +75,18 @@ export interface AgentConfigOverride {
|
|
|
75
75
|
};
|
|
76
76
|
/** Domains to allowlist in the agent's sandbox/network config (e.g. for Cursor CLI sandbox) */
|
|
77
77
|
networkAllowlist?: string[];
|
|
78
|
+
/**
|
|
79
|
+
* Minimum permission levels required for Runwork tools to function.
|
|
80
|
+
* Adapters should only UPGRADE restrictive settings, never downgrade
|
|
81
|
+
* more permissive ones. Keys are agent-specific config field names,
|
|
82
|
+
* values are ordered arrays from most restrictive to least, plus
|
|
83
|
+
* the minimum required value.
|
|
84
|
+
*/
|
|
85
|
+
minimumPermissions?: Array<{
|
|
86
|
+
field: string;
|
|
87
|
+
order: string[];
|
|
88
|
+
minimum: string;
|
|
89
|
+
}>;
|
|
78
90
|
}
|
|
79
91
|
export interface AgentUsageStats {
|
|
80
92
|
hasNewActivity: boolean;
|
package/dist/auth/store.js
CHANGED
|
@@ -44,7 +44,18 @@ export function clearCredentials() {
|
|
|
44
44
|
export function requireAuth() {
|
|
45
45
|
const creds = getCredentials();
|
|
46
46
|
if (!creds) {
|
|
47
|
-
|
|
47
|
+
const isTTY = process.stdin.isTTY;
|
|
48
|
+
if (isTTY) {
|
|
49
|
+
console.error('Not logged in. Run `runwork login` first.');
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
// Headless / sandbox / AI agent environment: provide actionable guidance
|
|
53
|
+
console.error('Not logged in. In a sandbox or headless environment, authenticate using one of:\n' +
|
|
54
|
+
' 1. Call the get_cli_setup MCP tool, then write the returned credentials to ~/.runwork/.credentials\n' +
|
|
55
|
+
' 2. Set the RUNWORK_API_KEY environment variable\n' +
|
|
56
|
+
' 3. Run: runwork login --api-key <your-api-key>\n' +
|
|
57
|
+
' 4. Run: runwork login --no-open --print-only (prints a URL for browser auth)');
|
|
58
|
+
}
|
|
48
59
|
process.exit(1);
|
|
49
60
|
}
|
|
50
61
|
return creds;
|
package/dist/commands/init.js
CHANGED
|
@@ -107,6 +107,10 @@ export async function runCreateFlow(name, workspaceFlag, options = {}) {
|
|
|
107
107
|
if (workspaceFlag) {
|
|
108
108
|
workspace = await resolveWorkspace(client, workspaceFlag);
|
|
109
109
|
}
|
|
110
|
+
else if (creds.defaultWorkspaceId) {
|
|
111
|
+
// Auto-select default workspace from credentials (set during login/onboarding)
|
|
112
|
+
workspace = { id: creds.defaultWorkspaceId, name: creds.defaultWorkspaceName || creds.defaultWorkspaceId };
|
|
113
|
+
}
|
|
110
114
|
else {
|
|
111
115
|
const workspaces = await client.listWorkspaces();
|
|
112
116
|
if (workspaces.length === 0) {
|
package/dist/commands/sync.js
CHANGED
|
@@ -5,6 +5,7 @@ import { homedir } from 'os';
|
|
|
5
5
|
import { requireAuth } from '../auth/store.js';
|
|
6
6
|
import { ApiClient } from '../api/client.js';
|
|
7
7
|
import { getAdapterBySlug } from '../agents/detect.js';
|
|
8
|
+
import { CodexAdapter } from '../agents/codex.js';
|
|
8
9
|
import { RUNWORK_MCP_PREFIX, RUNWORK_WORKSPACE_MCP_NAME } from '../agents/types.js';
|
|
9
10
|
import { collectTelemetryEvents, printTelemetryVerbose, summarizeTelemetryForDryRun, } from './sync-telemetry.js';
|
|
10
11
|
import { generateIntroSkill, generateInstructionHint, buildAppSkillDescription } from '../agents/intro-skill.js';
|
|
@@ -360,12 +361,31 @@ export async function syncFromState(state, statePath, credentials, opts) {
|
|
|
360
361
|
if (!adapter.writeAgentConfig)
|
|
361
362
|
continue;
|
|
362
363
|
try {
|
|
363
|
-
await adapter.writeAgentConfig({
|
|
364
|
+
await adapter.writeAgentConfig({
|
|
365
|
+
networkAllowlist: networkDomains,
|
|
366
|
+
minimumPermissions: [
|
|
367
|
+
{ field: 'approval_policy', order: ['always', 'untrusted', 'on-request', 'never'], minimum: 'on-request' },
|
|
368
|
+
{ field: 'sandbox_mode', order: ['full', 'read-only', 'workspace-write', 'off'], minimum: 'workspace-write' },
|
|
369
|
+
],
|
|
370
|
+
}, 'user');
|
|
364
371
|
}
|
|
365
372
|
catch {
|
|
366
373
|
// Best-effort
|
|
367
374
|
}
|
|
368
375
|
}
|
|
376
|
+
// Register ~/.runwork as a project in the Codex desktop app (best-effort).
|
|
377
|
+
// Only attempts when Codex adapter is configured and the desktop app is closed.
|
|
378
|
+
for (const adapter of adapters) {
|
|
379
|
+
if (adapter instanceof CodexAdapter) {
|
|
380
|
+
const runworkDir = join(homedir(), '.runwork');
|
|
381
|
+
const result = adapter.registerDesktopWorkspace(runworkDir, 'Runwork');
|
|
382
|
+
if (result === 'written') {
|
|
383
|
+
console.log(` [${adapter.name}] Registered workspace in Codex desktop app`);
|
|
384
|
+
}
|
|
385
|
+
// 'app_running' and 'already_registered' are silently skipped
|
|
386
|
+
break;
|
|
387
|
+
}
|
|
388
|
+
}
|
|
369
389
|
// Update state
|
|
370
390
|
state.lastSyncAt = new Date().toISOString();
|
|
371
391
|
state.mcpServers = mcpEntries.map(e => e.name);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const VERSION = "0.
|
|
1
|
+
export declare const VERSION = "0.9.1";
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// Auto-generated by scripts/embed-types.ts -- do not edit
|
|
2
|
-
export const VERSION = "0.
|
|
2
|
+
export const VERSION = "0.9.1";
|
package/dist/utils/which.d.ts
CHANGED
|
@@ -4,3 +4,11 @@
|
|
|
4
4
|
* Returns the resolved path on success, null if not found.
|
|
5
5
|
*/
|
|
6
6
|
export declare function whichBinary(name: string): string | null;
|
|
7
|
+
/**
|
|
8
|
+
* Check if a desktop app is currently running by process name.
|
|
9
|
+
* On macOS: checks for the .app bundle process via pgrep.
|
|
10
|
+
* On Windows: uses tasklist to find the .exe.
|
|
11
|
+
* On Linux: uses pgrep for the binary name.
|
|
12
|
+
* Returns true if the process is found, false otherwise.
|
|
13
|
+
*/
|
|
14
|
+
export declare function isAppRunning(appName: string): boolean;
|
package/dist/utils/which.js
CHANGED
|
@@ -16,3 +16,32 @@ export function whichBinary(name) {
|
|
|
16
16
|
return null;
|
|
17
17
|
}
|
|
18
18
|
}
|
|
19
|
+
/**
|
|
20
|
+
* Check if a desktop app is currently running by process name.
|
|
21
|
+
* On macOS: checks for the .app bundle process via pgrep.
|
|
22
|
+
* On Windows: uses tasklist to find the .exe.
|
|
23
|
+
* On Linux: uses pgrep for the binary name.
|
|
24
|
+
* Returns true if the process is found, false otherwise.
|
|
25
|
+
*/
|
|
26
|
+
export function isAppRunning(appName) {
|
|
27
|
+
try {
|
|
28
|
+
const os = platform();
|
|
29
|
+
if (os === 'darwin') {
|
|
30
|
+
// pgrep -f matches against the full command line, catching Electron apps
|
|
31
|
+
execFileSync('pgrep', ['-f', `${appName}.app`], { stdio: 'pipe' });
|
|
32
|
+
return true;
|
|
33
|
+
}
|
|
34
|
+
else if (os === 'win32') {
|
|
35
|
+
const result = execFileSync('tasklist', ['/FI', `IMAGENAME eq ${appName}.exe`, '/NH'], { stdio: 'pipe' }).toString();
|
|
36
|
+
return result.includes(`${appName}.exe`);
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
execFileSync('pgrep', ['-x', appName.toLowerCase()], { stdio: 'pipe' });
|
|
40
|
+
return true;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
// pgrep exits non-zero when no processes match
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
}
|
package/package.json
CHANGED