@doriandev/devcc 0.1.2 → 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/README.md +589 -389
- package/bin/devcc.mjs +50 -23
- package/dist/devcc/agents/agents.d.ts +119 -0
- package/dist/devcc/agents/agents.d.ts.map +1 -0
- package/dist/devcc/agents/agents.js +182 -0
- package/dist/devcc/agents/agents.js.map +1 -0
- package/dist/devcc/app/App.d.ts +23 -0
- package/dist/devcc/app/App.d.ts.map +1 -1
- package/dist/devcc/app/App.js +451 -19
- package/dist/devcc/app/App.js.map +1 -1
- package/dist/devcc/app/controlPlaneCommands.d.ts +14 -0
- package/dist/devcc/app/controlPlaneCommands.d.ts.map +1 -0
- package/dist/devcc/app/controlPlaneCommands.js +204 -0
- package/dist/devcc/app/controlPlaneCommands.js.map +1 -0
- package/dist/devcc/app/keymap.d.ts.map +1 -1
- package/dist/devcc/app/keymap.js +25 -3
- package/dist/devcc/app/keymap.js.map +1 -1
- package/dist/devcc/automation.d.ts +52 -0
- package/dist/devcc/automation.d.ts.map +1 -0
- package/dist/devcc/automation.js +339 -0
- package/dist/devcc/automation.js.map +1 -0
- package/dist/devcc/cli.d.ts.map +1 -1
- package/dist/devcc/cli.js +73 -3
- package/dist/devcc/cli.js.map +1 -1
- package/dist/devcc/components/Sidebar.d.ts.map +1 -1
- package/dist/devcc/components/Sidebar.js +1 -0
- package/dist/devcc/components/Sidebar.js.map +1 -1
- package/dist/devcc/components/primitives.d.ts.map +1 -1
- package/dist/devcc/components/primitives.js +3 -0
- package/dist/devcc/components/primitives.js.map +1 -1
- package/dist/devcc/core/commands.d.ts +33 -0
- package/dist/devcc/core/commands.d.ts.map +1 -1
- package/dist/devcc/core/commands.js.map +1 -1
- package/dist/devcc/core/config.d.ts +71 -3
- package/dist/devcc/core/config.d.ts.map +1 -1
- package/dist/devcc/core/config.js +189 -5
- package/dist/devcc/core/config.js.map +1 -1
- package/dist/devcc/core/state.d.ts +19 -1
- package/dist/devcc/core/state.d.ts.map +1 -1
- package/dist/devcc/core/state.js +6 -0
- package/dist/devcc/core/state.js.map +1 -1
- package/dist/devcc/environment/EnvironmentService.d.ts +58 -0
- package/dist/devcc/environment/EnvironmentService.d.ts.map +1 -0
- package/dist/devcc/environment/EnvironmentService.js +159 -0
- package/dist/devcc/environment/EnvironmentService.js.map +1 -0
- package/dist/devcc/environment/integrations.d.ts +52 -0
- package/dist/devcc/environment/integrations.d.ts.map +1 -0
- package/dist/devcc/environment/integrations.js +94 -0
- package/dist/devcc/environment/integrations.js.map +1 -0
- package/dist/devcc/environment/tools.d.ts +51 -0
- package/dist/devcc/environment/tools.d.ts.map +1 -0
- package/dist/devcc/environment/tools.js +99 -0
- package/dist/devcc/environment/tools.js.map +1 -0
- package/dist/devcc/git/GitService.d.ts +26 -0
- package/dist/devcc/git/GitService.d.ts.map +1 -1
- package/dist/devcc/git/GitService.js +71 -2
- package/dist/devcc/git/GitService.js.map +1 -1
- package/dist/devcc/git/worktrees.d.ts +88 -0
- package/dist/devcc/git/worktrees.d.ts.map +1 -0
- package/dist/devcc/git/worktrees.js +226 -0
- package/dist/devcc/git/worktrees.js.map +1 -0
- package/dist/devcc/index.d.ts +15 -3
- package/dist/devcc/index.d.ts.map +1 -1
- package/dist/devcc/index.js +14 -2
- package/dist/devcc/index.js.map +1 -1
- package/dist/devcc/init/detect.d.ts +55 -0
- package/dist/devcc/init/detect.d.ts.map +1 -0
- package/dist/devcc/init/detect.js +207 -0
- package/dist/devcc/init/detect.js.map +1 -0
- package/dist/devcc/init/prompt.d.ts +25 -0
- package/dist/devcc/init/prompt.d.ts.map +1 -0
- package/dist/devcc/init/prompt.js +156 -0
- package/dist/devcc/init/prompt.js.map +1 -0
- package/dist/devcc/platform/launch.d.ts +30 -0
- package/dist/devcc/platform/launch.d.ts.map +1 -0
- package/dist/devcc/platform/launch.js +93 -0
- package/dist/devcc/platform/launch.js.map +1 -0
- package/dist/devcc/services/ServiceManager.d.ts +10 -2
- package/dist/devcc/services/ServiceManager.d.ts.map +1 -1
- package/dist/devcc/services/ServiceManager.js +18 -4
- package/dist/devcc/services/ServiceManager.js.map +1 -1
- package/dist/devcc/services/node.d.ts +11 -0
- package/dist/devcc/services/node.d.ts.map +1 -1
- package/dist/devcc/services/node.js +20 -18
- package/dist/devcc/services/node.js.map +1 -1
- package/dist/devcc/services/ollama.d.ts +64 -5
- package/dist/devcc/services/ollama.d.ts.map +1 -1
- package/dist/devcc/services/ollama.js +118 -17
- package/dist/devcc/services/ollama.js.map +1 -1
- package/dist/devcc/services/remote.d.ts +90 -0
- package/dist/devcc/services/remote.d.ts.map +1 -0
- package/dist/devcc/services/remote.js +233 -0
- package/dist/devcc/services/remote.js.map +1 -0
- package/dist/devcc/services/types.d.ts +8 -1
- package/dist/devcc/services/types.d.ts.map +1 -1
- package/dist/devcc/services/types.js.map +1 -1
- package/dist/devcc/utils/exec.d.ts +6 -0
- package/dist/devcc/utils/exec.d.ts.map +1 -1
- package/dist/devcc/utils/exec.js +12 -2
- package/dist/devcc/utils/exec.js.map +1 -1
- package/dist/devcc/verify/verify.d.ts +107 -0
- package/dist/devcc/verify/verify.d.ts.map +1 -0
- package/dist/devcc/verify/verify.js +203 -0
- package/dist/devcc/verify/verify.js.map +1 -0
- package/dist/devcc/views/OverviewView.d.ts.map +1 -1
- package/dist/devcc/views/OverviewView.js +58 -2
- package/dist/devcc/views/OverviewView.js.map +1 -1
- package/dist/devcc/views/ServicesView.d.ts +2 -0
- package/dist/devcc/views/ServicesView.d.ts.map +1 -1
- package/dist/devcc/views/ServicesView.js +15 -0
- package/dist/devcc/views/ServicesView.js.map +1 -1
- package/dist/devcc/views/SystemView.d.ts +10 -1
- package/dist/devcc/views/SystemView.d.ts.map +1 -1
- package/dist/devcc/views/SystemView.js +127 -19
- package/dist/devcc/views/SystemView.js.map +1 -1
- package/dist/devcc/views/WorktreesView.d.ts +48 -0
- package/dist/devcc/views/WorktreesView.d.ts.map +1 -0
- package/dist/devcc/views/WorktreesView.js +235 -0
- package/dist/devcc/views/WorktreesView.js.map +1 -0
- package/package.json +1 -1
- package/src/devcc/agents/agents.ts +292 -0
- package/src/devcc/app/App.ts +529 -22
- package/src/devcc/app/controlPlaneCommands.ts +227 -0
- package/src/devcc/app/keymap.ts +25 -3
- package/src/devcc/automation.ts +409 -0
- package/src/devcc/cli.ts +77 -3
- package/src/devcc/components/Sidebar.ts +1 -0
- package/src/devcc/components/primitives.ts +3 -0
- package/src/devcc/core/commands.ts +34 -0
- package/src/devcc/core/config.ts +275 -11
- package/src/devcc/core/state.ts +25 -0
- package/src/devcc/environment/EnvironmentService.ts +215 -0
- package/src/devcc/environment/integrations.ts +133 -0
- package/src/devcc/environment/tools.ts +151 -0
- package/src/devcc/git/GitService.ts +104 -2
- package/src/devcc/git/worktrees.ts +256 -0
- package/src/devcc/index.ts +66 -2
- package/src/devcc/init/detect.ts +268 -0
- package/src/devcc/init/prompt.ts +179 -0
- package/src/devcc/platform/launch.ts +125 -0
- package/src/devcc/services/ServiceManager.ts +15 -3
- package/src/devcc/services/node.ts +17 -14
- package/src/devcc/services/ollama.ts +162 -19
- package/src/devcc/services/remote.ts +306 -0
- package/src/devcc/services/types.ts +9 -1
- package/src/devcc/utils/exec.ts +26 -2
- package/src/devcc/verify/verify.ts +316 -0
- package/src/devcc/views/OverviewView.ts +84 -2
- package/src/devcc/views/ServicesView.ts +17 -0
- package/src/devcc/views/SystemView.ts +144 -22
- package/src/devcc/views/WorktreesView.ts +270 -0
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
import { existsSync } from "node:fs"
|
|
2
|
+
import { isAbsolute } from "node:path"
|
|
3
|
+
import { isActive, type ProcessDefinition, type ProcessStatus } from "../processes/ManagedProcess.js"
|
|
4
|
+
import type { ProcessManager } from "../processes/ProcessManager.js"
|
|
5
|
+
import { DevccError } from "../utils/errors.js"
|
|
6
|
+
import { exec, type ExecOptions, type ExecResult } from "../utils/exec.js"
|
|
7
|
+
import type { ScopedLogger } from "../utils/logger.js"
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* AI coding agents (Claude Code, Codex, ...).
|
|
11
|
+
*
|
|
12
|
+
* An agent is not a new kind of process: an adapter only describes how to run
|
|
13
|
+
* the agent's CLI non-interactively, and `AgentManager` hands the result to the
|
|
14
|
+
* project's `ProcessManager`. Status, PID, logs, stop and cleanup on quit all
|
|
15
|
+
* come from the existing process infrastructure.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
export interface AgentLaunchOptions {
|
|
19
|
+
/** Working directory - the selected worktree. Must be absolute. */
|
|
20
|
+
cwd: string
|
|
21
|
+
/** The task for the agent. */
|
|
22
|
+
prompt: string
|
|
23
|
+
/** Branch of the worktree, for display. */
|
|
24
|
+
branch?: string
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export interface AgentAdapter {
|
|
28
|
+
id: string
|
|
29
|
+
name: string
|
|
30
|
+
/** Executable, overridable per machine through config. */
|
|
31
|
+
command: string
|
|
32
|
+
/** Whether the CLI is installed and runnable. */
|
|
33
|
+
detect: () => Promise<boolean>
|
|
34
|
+
/** argv for a non-interactive run of `prompt`. */
|
|
35
|
+
args: (prompt: string) => string[]
|
|
36
|
+
/**
|
|
37
|
+
* True when `args` puts `--` before the prompt, so a task starting with `-`
|
|
38
|
+
* cannot be read as an option. Tasks starting with `-` are refused otherwise.
|
|
39
|
+
*/
|
|
40
|
+
separatesPrompt: boolean
|
|
41
|
+
/**
|
|
42
|
+
* argv to start the agent's interactive session with `prompt` as the first
|
|
43
|
+
* message. Only for agents known to support it (the built-ins).
|
|
44
|
+
*/
|
|
45
|
+
interactiveArgs?: (prompt: string) => string[]
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export interface AgentConfig {
|
|
49
|
+
/** Display name (defaults per built-in, or to the id). */
|
|
50
|
+
name?: string
|
|
51
|
+
/** Executable name or path. */
|
|
52
|
+
command?: string
|
|
53
|
+
/** Extra arguments placed before the prompt, e.g. `["--permission-mode", "acceptEdits"]`. */
|
|
54
|
+
args?: string[]
|
|
55
|
+
/** Set false to hide a built-in agent. */
|
|
56
|
+
enabled?: boolean
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export interface AgentSession {
|
|
60
|
+
/** Process id in the ProcessManager, also the log source id. */
|
|
61
|
+
id: string
|
|
62
|
+
agentId: string
|
|
63
|
+
agentName: string
|
|
64
|
+
cwd: string
|
|
65
|
+
branch?: string
|
|
66
|
+
/** First line of the prompt, for display. */
|
|
67
|
+
task: string
|
|
68
|
+
status: ProcessStatus
|
|
69
|
+
pid?: number
|
|
70
|
+
startedAt: Date
|
|
71
|
+
exitCode?: number
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
type Exec = (command: string, args: readonly string[], options?: ExecOptions) => Promise<ExecResult>
|
|
75
|
+
|
|
76
|
+
interface BuiltinAgent {
|
|
77
|
+
name: string
|
|
78
|
+
command: string
|
|
79
|
+
/** Where the prompt goes relative to the user's extra args. */
|
|
80
|
+
args: (extra: string[], prompt: string) => string[]
|
|
81
|
+
/** Interactive session opened with `prompt` as the first message. */
|
|
82
|
+
interactiveArgs: (extra: string[], prompt: string) => string[]
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Non-interactive invocations: `claude -p -- <prompt>` and `codex exec -- <prompt>`.
|
|
87
|
+
* The `--` matters: without it a task like `--dangerously-skip-permissions`
|
|
88
|
+
* would be parsed as a flag.
|
|
89
|
+
*/
|
|
90
|
+
export const BUILTIN_AGENTS: Readonly<Record<string, BuiltinAgent>> = {
|
|
91
|
+
claude: {
|
|
92
|
+
name: "Claude Code",
|
|
93
|
+
command: "claude",
|
|
94
|
+
args: (extra, prompt) => [...extra, "-p", "--", prompt],
|
|
95
|
+
interactiveArgs: (extra, prompt) => [...extra, "--", prompt],
|
|
96
|
+
},
|
|
97
|
+
codex: {
|
|
98
|
+
name: "Codex",
|
|
99
|
+
command: "codex",
|
|
100
|
+
args: (extra, prompt) => ["exec", ...extra, "--", prompt],
|
|
101
|
+
interactiveArgs: (extra, prompt) => [...extra, "--", prompt],
|
|
102
|
+
},
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Build adapters from config. Built-ins are always present unless disabled;
|
|
107
|
+
* any other key defines a custom agent whose prompt is the last argument.
|
|
108
|
+
*/
|
|
109
|
+
export function createAgentAdapters(
|
|
110
|
+
config: Readonly<Record<string, AgentConfig>> = {},
|
|
111
|
+
run: Exec = exec,
|
|
112
|
+
): AgentAdapter[] {
|
|
113
|
+
const ids = [...new Set([...Object.keys(BUILTIN_AGENTS), ...Object.keys(config)])]
|
|
114
|
+
const adapters: AgentAdapter[] = []
|
|
115
|
+
|
|
116
|
+
for (const id of ids) {
|
|
117
|
+
const entry = config[id] ?? {}
|
|
118
|
+
if (entry.enabled === false) continue
|
|
119
|
+
const builtin = BUILTIN_AGENTS[id]
|
|
120
|
+
const command = entry.command ?? builtin?.command
|
|
121
|
+
if (!command) continue
|
|
122
|
+
|
|
123
|
+
const extra = entry.args ?? []
|
|
124
|
+
adapters.push({
|
|
125
|
+
id,
|
|
126
|
+
name: entry.name ?? builtin?.name ?? id,
|
|
127
|
+
command,
|
|
128
|
+
detect: async () => {
|
|
129
|
+
const result = await run(command, ["--version"], { timeoutMs: 3_000 })
|
|
130
|
+
return result.ok
|
|
131
|
+
},
|
|
132
|
+
// Custom agents keep the prompt as the literal last argument (it may be an
|
|
133
|
+
// option's value, e.g. `--message`), so they cannot take a `--` guard.
|
|
134
|
+
args: (prompt) => (builtin ? builtin.args(extra, prompt) : [...extra, prompt]),
|
|
135
|
+
separatesPrompt: builtin !== undefined,
|
|
136
|
+
interactiveArgs: builtin ? (prompt) => builtin.interactiveArgs(extra, prompt) : undefined,
|
|
137
|
+
})
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
return adapters
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
export interface AgentManagerOptions {
|
|
144
|
+
processes: ProcessManager
|
|
145
|
+
adapters: readonly AgentAdapter[]
|
|
146
|
+
logger?: ScopedLogger
|
|
147
|
+
/** Injected for tests. */
|
|
148
|
+
exists?: (path: string) => boolean
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
interface SessionMeta {
|
|
152
|
+
agentId: string
|
|
153
|
+
agentName: string
|
|
154
|
+
cwd: string
|
|
155
|
+
branch?: string
|
|
156
|
+
task: string
|
|
157
|
+
startedAt: Date
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
export const AGENT_PROCESS_PREFIX = "agent:"
|
|
161
|
+
|
|
162
|
+
export class AgentManager {
|
|
163
|
+
private readonly adapters: Map<string, AgentAdapter>
|
|
164
|
+
private readonly meta = new Map<string, SessionMeta>()
|
|
165
|
+
/** Detection results, cached for the session: installing a CLI mid-session is rare. */
|
|
166
|
+
private readonly detected = new Map<string, Promise<boolean>>()
|
|
167
|
+
private sequence = 0
|
|
168
|
+
|
|
169
|
+
constructor(private readonly options: AgentManagerOptions) {
|
|
170
|
+
this.adapters = new Map(options.adapters.map((adapter) => [adapter.id, adapter]))
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
list(): AgentAdapter[] {
|
|
174
|
+
return [...this.adapters.values()]
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
get(id: string): AgentAdapter | undefined {
|
|
178
|
+
return this.adapters.get(id)
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/** Whether an agent's CLI is installed. `refresh` re-runs the probe. */
|
|
182
|
+
detect(id: string, refresh = false): Promise<boolean> {
|
|
183
|
+
const adapter = this.adapters.get(id)
|
|
184
|
+
if (!adapter) return Promise.resolve(false)
|
|
185
|
+
let pending = refresh ? undefined : this.detected.get(id)
|
|
186
|
+
if (!pending) {
|
|
187
|
+
pending = adapter.detect().catch(() => false)
|
|
188
|
+
this.detected.set(id, pending)
|
|
189
|
+
}
|
|
190
|
+
return pending
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Start an agent in `options.cwd` as a managed task. Throws a `DevccError`
|
|
195
|
+
* with an actionable message when the agent is unknown, not installed, or
|
|
196
|
+
* the directory is missing.
|
|
197
|
+
*/
|
|
198
|
+
async launch(agentId: string, options: AgentLaunchOptions): Promise<AgentSession> {
|
|
199
|
+
const adapter = this.adapters.get(agentId)
|
|
200
|
+
if (!adapter) throw new DevccError({ scope: "process", message: `Unknown agent "${agentId}"` })
|
|
201
|
+
|
|
202
|
+
const prompt = options.prompt.trim()
|
|
203
|
+
if (prompt === "") throw new DevccError({ scope: "process", message: `${adapter.name} needs a task` })
|
|
204
|
+
if (prompt.startsWith("-") && !adapter.separatesPrompt) {
|
|
205
|
+
throw new DevccError({
|
|
206
|
+
scope: "process",
|
|
207
|
+
message: `${adapter.name}: a task cannot start with "-" (it would be read as an option)`,
|
|
208
|
+
})
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
const exists = this.options.exists ?? existsSync
|
|
212
|
+
if (!isAbsolute(options.cwd) || !exists(options.cwd)) {
|
|
213
|
+
throw new DevccError({ scope: "process", message: `Working directory does not exist: ${options.cwd}` })
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
if (!(await this.detect(agentId, true))) {
|
|
217
|
+
throw new DevccError({
|
|
218
|
+
scope: "process",
|
|
219
|
+
message: `${adapter.name} is not installed (\`${adapter.command}\` was not found)`,
|
|
220
|
+
detail: `Install it, or point devcc at it with agents.${agentId}.command in .devcc.ts.`,
|
|
221
|
+
})
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
this.sequence += 1
|
|
225
|
+
const id = `${AGENT_PROCESS_PREFIX}${agentId}:${this.sequence}`
|
|
226
|
+
const where = options.branch ?? options.cwd
|
|
227
|
+
const definition: ProcessDefinition = {
|
|
228
|
+
id,
|
|
229
|
+
name: `${adapter.name} · ${where}`,
|
|
230
|
+
command: adapter.command,
|
|
231
|
+
args: adapter.args(prompt),
|
|
232
|
+
cwd: options.cwd,
|
|
233
|
+
kind: "task",
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
this.meta.set(id, {
|
|
237
|
+
agentId,
|
|
238
|
+
agentName: adapter.name,
|
|
239
|
+
cwd: options.cwd,
|
|
240
|
+
branch: options.branch,
|
|
241
|
+
task: prompt.split("\n")[0] ?? prompt,
|
|
242
|
+
startedAt: new Date(),
|
|
243
|
+
})
|
|
244
|
+
|
|
245
|
+
this.options.processes.register(definition)
|
|
246
|
+
this.options.logger?.info("agent launch", { agent: agentId, cwd: options.cwd })
|
|
247
|
+
try {
|
|
248
|
+
await this.options.processes.start(id)
|
|
249
|
+
} catch (error) {
|
|
250
|
+
this.options.logger?.warn("agent launch failed", { agent: agentId, cwd: options.cwd })
|
|
251
|
+
throw error
|
|
252
|
+
}
|
|
253
|
+
return this.session(id) as AgentSession
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
/** Every agent session this manager started, newest first. */
|
|
257
|
+
sessions(): AgentSession[] {
|
|
258
|
+
return [...this.meta.keys()]
|
|
259
|
+
.map((id) => this.session(id))
|
|
260
|
+
.filter((session): session is AgentSession => session !== undefined)
|
|
261
|
+
.reverse()
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
async stop(sessionId: string): Promise<void> {
|
|
265
|
+
await this.options.processes.stop(sessionId)
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
/** Directories where an agent is still running; worktree removal refuses these. */
|
|
269
|
+
busyPaths(): string[] {
|
|
270
|
+
return this.sessions()
|
|
271
|
+
.filter((session) => isActive(session.status))
|
|
272
|
+
.map((session) => session.cwd)
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
private session(id: string): AgentSession | undefined {
|
|
276
|
+
const meta = this.meta.get(id)
|
|
277
|
+
const process = this.options.processes.get(id)
|
|
278
|
+
if (!meta || !process) return undefined
|
|
279
|
+
return {
|
|
280
|
+
id,
|
|
281
|
+
agentId: meta.agentId,
|
|
282
|
+
agentName: meta.agentName,
|
|
283
|
+
cwd: meta.cwd,
|
|
284
|
+
branch: meta.branch,
|
|
285
|
+
task: meta.task,
|
|
286
|
+
status: process.status,
|
|
287
|
+
pid: process.pid,
|
|
288
|
+
startedAt: process.startedAt ?? meta.startedAt,
|
|
289
|
+
exitCode: process.exitCode,
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
}
|