@nodeint/migent 0.0.0-stage → 0.1.2
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/LICENSE +21 -0
- package/README.md +206 -2
- package/dist/commands/agent.d.ts +14 -0
- package/dist/commands/agent.js +97 -0
- package/dist/commands/config.d.ts +35 -0
- package/dist/commands/config.js +613 -0
- package/dist/commands/doctor.d.ts +5 -0
- package/dist/commands/doctor.js +26 -0
- package/dist/commands/execute.d.ts +12 -0
- package/dist/commands/execute.js +39 -0
- package/dist/commands/init.d.ts +26 -0
- package/dist/commands/init.js +311 -0
- package/dist/commands/service.d.ts +11 -0
- package/dist/commands/service.js +60 -0
- package/dist/commands/sessions.d.ts +3 -0
- package/dist/commands/sessions.js +20 -0
- package/dist/commands/skill.d.ts +4 -0
- package/dist/commands/skill.js +98 -0
- package/dist/commands/watch.d.ts +7 -0
- package/dist/commands/watch.js +169 -0
- package/dist/commands/workspace-registry.d.ts +8 -0
- package/dist/commands/workspace-registry.js +106 -0
- package/dist/display.d.ts +12 -0
- package/dist/display.js +123 -0
- package/dist/hooks.d.ts +6 -0
- package/dist/hooks.js +5 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +57 -0
- package/dist/migrate.d.ts +8 -0
- package/dist/migrate.js +191 -0
- package/dist/program.d.ts +6 -0
- package/dist/program.js +414 -0
- package/dist/provider.d.ts +23 -0
- package/dist/provider.js +136 -0
- package/dist/templates/migent/SKILL.md +62 -0
- package/dist/workspace.d.ts +8 -0
- package/dist/workspace.js +50 -0
- package/package.json +59 -3
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Migent contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,207 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Migent
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
**Compose AI coding agents into repeatable engineering workflows.**
|
|
4
|
+
|
|
5
|
+
Use the right model for each stage of the job.
|
|
6
|
+
|
|
7
|
+
Migent connects coding-agent CLIs from different providers through explicit,
|
|
8
|
+
repository-defined workflows. One model can plan, another can review, and the
|
|
9
|
+
first can revise—while Migent carries artifacts between them and remembers
|
|
10
|
+
where the process is.
|
|
11
|
+
|
|
12
|
+
## Contents
|
|
13
|
+
|
|
14
|
+
- [Migent](#migent)
|
|
15
|
+
- [Contents](#contents)
|
|
16
|
+
- [Why Migent?](#why-migent)
|
|
17
|
+
- [Supported CLIs](#supported-clis)
|
|
18
|
+
- [Quickstart](#quickstart)
|
|
19
|
+
- [Install](#install)
|
|
20
|
+
- [Upgrade](#upgrade)
|
|
21
|
+
- [Create a project](#create-a-project)
|
|
22
|
+
- [Run](#run)
|
|
23
|
+
- [Concepts](#concepts)
|
|
24
|
+
- [Current scope](#current-scope)
|
|
25
|
+
- [Documentation](#documentation)
|
|
26
|
+
- [Development](#development)
|
|
27
|
+
- [License](#license)
|
|
28
|
+
|
|
29
|
+
## Why Migent?
|
|
30
|
+
|
|
31
|
+
Calling two agent CLIs from a shell script is easy. Reliably coordinating them
|
|
32
|
+
across reviews, revisions, failures, and resumed sessions is not.
|
|
33
|
+
|
|
34
|
+
Migent is built around three ideas:
|
|
35
|
+
|
|
36
|
+
- **Use models for what they do best.** Assign each role to a provider and model
|
|
37
|
+
suited to the work, rather than asking one agent to do everything.
|
|
38
|
+
- **Treat AI engineering process as code.** Keep stages, handoffs, review gates,
|
|
39
|
+
and revision policies in version control beside the project they govern.
|
|
40
|
+
- **Keep orchestration explicit.** The team defines the process; models execute
|
|
41
|
+
roles inside it. A supervisor model does not invent or dynamically control
|
|
42
|
+
the workflow.
|
|
43
|
+
|
|
44
|
+
**Models describe execution. Roles describe intent.** Changing the model behind
|
|
45
|
+
a role does not require rewriting the workflow.
|
|
46
|
+
|
|
47
|
+
**Common workflow model, native provider capabilities.** Migent coordinates
|
|
48
|
+
the process, while each provider CLI remains responsible for authentication,
|
|
49
|
+
agent execution, and its own tools and options.
|
|
50
|
+
|
|
51
|
+
```mermaid
|
|
52
|
+
flowchart LR
|
|
53
|
+
A[Task] --> B[Planner - Codex]
|
|
54
|
+
B -->|plan.md| C[Reviewer - Grok]
|
|
55
|
+
C -->|revise| B
|
|
56
|
+
C -->|approved| D[Complete]
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Supported CLIs
|
|
60
|
+
|
|
61
|
+
Migent drives each provider through its headless CLI. Install and sign in to the
|
|
62
|
+
ones your configuration names.
|
|
63
|
+
|
|
64
|
+
| Provider | CLI |
|
|
65
|
+
| -------- | -------- |
|
|
66
|
+
| Claude | `claude` |
|
|
67
|
+
| Codex | `codex` |
|
|
68
|
+
| Grok | `grok` |
|
|
69
|
+
|
|
70
|
+
## Quickstart
|
|
71
|
+
|
|
72
|
+
Node.js 22+ on macOS or Linux, and authenticated provider CLIs named by your
|
|
73
|
+
configuration.
|
|
74
|
+
|
|
75
|
+
### Install
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
npm install -g @nodeint/migent
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Verify with `migent --version`.
|
|
82
|
+
|
|
83
|
+
### Upgrade
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
npm install -g @nodeint/migent@latest
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### Create a project
|
|
90
|
+
|
|
91
|
+
From the project where agents will work:
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
migent init --preset plan
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
`init` writes the config, a plan-and-review workflow, and a gitignore for local
|
|
98
|
+
session state:
|
|
99
|
+
|
|
100
|
+
```text
|
|
101
|
+
.migent/
|
|
102
|
+
├── config.yaml
|
|
103
|
+
├── .gitignore
|
|
104
|
+
└── workflows/
|
|
105
|
+
└── plan.yaml
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
In a terminal, pick the provider, model, and prompted options from the lists.
|
|
109
|
+
Pass `--provider` and `--model` together when input is not a terminal. Commit
|
|
110
|
+
`config.yaml` and `workflows/`. Leave `.migent/sessions/` untracked.
|
|
111
|
+
|
|
112
|
+
Model and role shape is in [Providers and model configuration](https://github.com/nodeint/migent/blob/main/docs/providers.md).
|
|
113
|
+
A full plan workflow is in [Writing workflows](https://github.com/nodeint/migent/blob/main/docs/workflows.md#complete-example).
|
|
114
|
+
|
|
115
|
+
### Run
|
|
116
|
+
|
|
117
|
+
From that project or any of its subdirectories:
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
migent start plan --task "Plan the account settings redesign"
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
Migent runs the next eligible stage until the workflow completes or stops.
|
|
124
|
+
Progress goes to stderr. Stdout is one JSON result.
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
migent sessions
|
|
128
|
+
migent watch <session-id>
|
|
129
|
+
migent continue <session-id>
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
Command fields and exit codes are in
|
|
133
|
+
[CLI commands and execution controls](https://github.com/nodeint/migent/blob/main/docs/cli.md). Session files are in
|
|
134
|
+
[Sessions and workflow composition](https://github.com/nodeint/migent/blob/main/docs/sessions.md).
|
|
135
|
+
|
|
136
|
+
## Concepts
|
|
137
|
+
|
|
138
|
+
A workflow connects stages through dependencies and explicit decision routes.
|
|
139
|
+
|
|
140
|
+
- A **model** identifies a provider model and its execution options.
|
|
141
|
+
- A **role** names a kind of work and selects its default model.
|
|
142
|
+
- A **stage** assigns work to a role and may declare dependencies, an artifact,
|
|
143
|
+
a decision, or both.
|
|
144
|
+
- An **artifact** is a named file produced by a successful stage and stored with
|
|
145
|
+
the workflow session.
|
|
146
|
+
- A **decision** selects the next route, including a route back for revision.
|
|
147
|
+
- A **session** records executions, events, decisions, and artifacts so work can
|
|
148
|
+
be inspected or resumed.
|
|
149
|
+
|
|
150
|
+
Use `depends_on` to give a stage upstream artifacts. Use `session.resume_from`
|
|
151
|
+
when the stage must also continue a provider's prior conversational session.
|
|
152
|
+
|
|
153
|
+
## Current scope
|
|
154
|
+
|
|
155
|
+
Migent is a local, file-backed orchestration layer for provider CLIs. It does
|
|
156
|
+
not replace their agent runtimes, and it does not hide their distinctive
|
|
157
|
+
capabilities behind a lowest-common-denominator API.
|
|
158
|
+
|
|
159
|
+
Today, Migent supports explicit stage routing, review loops, local session
|
|
160
|
+
history, provider-session resume, prerequisite workflows, and standalone role
|
|
161
|
+
execution. A machine-local registry service records workspaces
|
|
162
|
+
so another tool can ask which projects exist.
|
|
163
|
+
|
|
164
|
+
## Documentation
|
|
165
|
+
|
|
166
|
+
- [Writing workflows](https://github.com/nodeint/migent/blob/main/docs/workflows.md)
|
|
167
|
+
- [Providers and model configuration](https://github.com/nodeint/migent/blob/main/docs/providers.md)
|
|
168
|
+
- [Sessions and workflow composition](https://github.com/nodeint/migent/blob/main/docs/sessions.md)
|
|
169
|
+
- [CLI commands and execution controls](https://github.com/nodeint/migent/blob/main/docs/cli.md)
|
|
170
|
+
|
|
171
|
+
Run `migent <command> --help` for the exact command contract, output fields,
|
|
172
|
+
and exit codes.
|
|
173
|
+
|
|
174
|
+
## Development
|
|
175
|
+
|
|
176
|
+
The pnpm workspace contains four packages: the `@nodeint/migent` CLI and its
|
|
177
|
+
internal libraries `@nodeint/migent-kernel`, `@nodeint/migent-adapters`, and
|
|
178
|
+
`@nodeint/migent-registry`. The libraries have no stable API; depend on
|
|
179
|
+
`@nodeint/migent`.
|
|
180
|
+
|
|
181
|
+
```bash
|
|
182
|
+
pnpm install
|
|
183
|
+
pnpm build
|
|
184
|
+
pnpm test
|
|
185
|
+
pnpm migent --help # run the local build
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
### Releasing
|
|
189
|
+
|
|
190
|
+
All four packages share one version. Bump it, commit, and push a matching tag:
|
|
191
|
+
|
|
192
|
+
```bash
|
|
193
|
+
pnpm -r exec npm pkg set version=0.2.0
|
|
194
|
+
pnpm install
|
|
195
|
+
git commit -am "Release 0.2.0"
|
|
196
|
+
git tag v0.2.0
|
|
197
|
+
git push origin main v0.2.0
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
The tag runs `.github/workflows/release.yml`, which builds, tests, packs, and
|
|
201
|
+
stages each package through npm trusted publishing. Nothing goes live until a
|
|
202
|
+
maintainer approves the staged versions on npmjs.com (Staged Packages tab) or
|
|
203
|
+
with `npm stage approve`, kernel first and `@nodeint/migent` last.
|
|
204
|
+
|
|
205
|
+
## License
|
|
206
|
+
|
|
207
|
+
Migent is licensed under the [MIT License](https://github.com/nodeint/migent/blob/main/LICENSE).
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { AgentToolRunner } from "@nodeint/migent-kernel";
|
|
2
|
+
export declare function dispatchAgent(workspace: string, args: {
|
|
3
|
+
role: string;
|
|
4
|
+
task?: string | null;
|
|
5
|
+
sessionId?: string | null;
|
|
6
|
+
provider?: string | null;
|
|
7
|
+
model?: string | null;
|
|
8
|
+
options?: readonly string[];
|
|
9
|
+
prompt?: string | null;
|
|
10
|
+
promptFile?: string | null;
|
|
11
|
+
promptStdin?: boolean;
|
|
12
|
+
asJson?: boolean;
|
|
13
|
+
runner?: AgentToolRunner | null;
|
|
14
|
+
}): Promise<number>;
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { AgentToolRunner, CancellationRequested, ConfigurationError, createAgentSession, log, raiseCancellation, requireAgentSession, resolveRoleTarget, SessionStore, } from "@nodeint/migent-kernel";
|
|
2
|
+
import { printAgent, printError, printNotice } from "../display.js";
|
|
3
|
+
import { cliHooks } from "../hooks.js";
|
|
4
|
+
import { requireCurrentSchema } from "../migrate.js";
|
|
5
|
+
import { adapterMap, parseOptions } from "../provider.js";
|
|
6
|
+
import { resolvePrompt } from "../workspace.js";
|
|
7
|
+
export async function dispatchAgent(workspace, args) {
|
|
8
|
+
requireCurrentSchema(workspace);
|
|
9
|
+
const parsed = parseOptions(args.options ?? []);
|
|
10
|
+
const target = resolveRoleTarget(workspace, args.role, {
|
|
11
|
+
provider: args.provider ?? null,
|
|
12
|
+
model: args.model ?? null,
|
|
13
|
+
options: Object.keys(parsed).length > 0 ? parsed : null,
|
|
14
|
+
});
|
|
15
|
+
const [resolvedSessionId, createdSession] = resolveSession(workspace, args.sessionId ?? null, args.role, args.task ?? null);
|
|
16
|
+
let resumeExecutionId = null;
|
|
17
|
+
if (!createdSession) {
|
|
18
|
+
const previous = new SessionStore(workspace).latestExecution(resolvedSessionId);
|
|
19
|
+
if (previous !== null)
|
|
20
|
+
resumeExecutionId = previous.executionId;
|
|
21
|
+
}
|
|
22
|
+
const optionLabel = Object.entries(target.options)
|
|
23
|
+
.map(([key, value]) => `${key}: ${value}`)
|
|
24
|
+
.join(", ") || "default";
|
|
25
|
+
printNotice(`agent ${args.role} · ${target.provider}/${target.model} (${optionLabel}).`);
|
|
26
|
+
const onSigint = () => {
|
|
27
|
+
try {
|
|
28
|
+
raiseCancellation(2);
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
// The runner observes the pending cancellation.
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
const onSigterm = () => {
|
|
35
|
+
try {
|
|
36
|
+
raiseCancellation(15);
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
// The runner observes the pending cancellation.
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
process.on("SIGINT", onSigint);
|
|
43
|
+
process.on("SIGTERM", onSigterm);
|
|
44
|
+
let result;
|
|
45
|
+
try {
|
|
46
|
+
const runner = args.runner ?? cliHooks.runner ?? new AgentToolRunner(adapterMap());
|
|
47
|
+
result = await runner.run({
|
|
48
|
+
provider: target.provider,
|
|
49
|
+
model: target.model,
|
|
50
|
+
options: { ...target.options },
|
|
51
|
+
prompt: resolvePrompt({
|
|
52
|
+
prompt: args.prompt ?? null,
|
|
53
|
+
promptFile: args.promptFile ?? null,
|
|
54
|
+
promptStdin: args.promptStdin ?? false,
|
|
55
|
+
}),
|
|
56
|
+
workspace,
|
|
57
|
+
sessionId: resolvedSessionId,
|
|
58
|
+
resumeExecutionId,
|
|
59
|
+
stageId: args.role,
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
catch (error) {
|
|
63
|
+
if (error instanceof CancellationRequested) {
|
|
64
|
+
log(error.message);
|
|
65
|
+
return 130;
|
|
66
|
+
}
|
|
67
|
+
if (error instanceof ConfigurationError)
|
|
68
|
+
throw error;
|
|
69
|
+
if (error instanceof Error) {
|
|
70
|
+
printError(error.message);
|
|
71
|
+
return 2;
|
|
72
|
+
}
|
|
73
|
+
throw error;
|
|
74
|
+
}
|
|
75
|
+
finally {
|
|
76
|
+
process.off("SIGINT", onSigint);
|
|
77
|
+
process.off("SIGTERM", onSigterm);
|
|
78
|
+
}
|
|
79
|
+
if (createdSession)
|
|
80
|
+
printNotice(`session_id: ${result.session_id}`);
|
|
81
|
+
if (args.asJson)
|
|
82
|
+
process.stdout.write(`${JSON.stringify(result)}\n`);
|
|
83
|
+
else
|
|
84
|
+
printAgent({ ...result }, args.role, target.provider, target.model);
|
|
85
|
+
return result.outcome_status === "complete" ? 0 : 1;
|
|
86
|
+
}
|
|
87
|
+
function resolveSession(workspace, sessionId, role, task) {
|
|
88
|
+
if (sessionId !== null && typeof task === "string" && task.trim() !== "") {
|
|
89
|
+
throw new ConfigurationError("--task cannot be combined with a session.");
|
|
90
|
+
}
|
|
91
|
+
if (sessionId !== null) {
|
|
92
|
+
requireAgentSession(workspace, sessionId);
|
|
93
|
+
return [sessionId, false];
|
|
94
|
+
}
|
|
95
|
+
const taskSummary = (task ?? role).trim();
|
|
96
|
+
return [createAgentSession(workspace, role, taskSummary), true];
|
|
97
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { type AgentAdapter } from "@nodeint/migent-kernel";
|
|
2
|
+
import { type RunCommand, type Which } from "../provider.js";
|
|
3
|
+
export interface ConfigPrompter {
|
|
4
|
+
select(message: string, choices: ReadonlyArray<readonly [string, string]>, defaultValue?: string | null): string | Promise<string>;
|
|
5
|
+
confirm(message: string): boolean | Promise<boolean>;
|
|
6
|
+
text(message: string, defaultValue?: string): string | Promise<string>;
|
|
7
|
+
}
|
|
8
|
+
export declare function runConfigShow(workspace: string): number;
|
|
9
|
+
export declare function runConfigModel(workspace: string, options?: {
|
|
10
|
+
key?: string | null;
|
|
11
|
+
provider?: string | null;
|
|
12
|
+
model?: string | null;
|
|
13
|
+
options?: readonly string[];
|
|
14
|
+
clearOptions?: readonly string[];
|
|
15
|
+
asJson?: boolean;
|
|
16
|
+
interactive?: boolean;
|
|
17
|
+
adapters?: Record<string, AgentAdapter> | null;
|
|
18
|
+
which?: Which | null;
|
|
19
|
+
prompter?: ConfigPrompter | null;
|
|
20
|
+
runCommand?: RunCommand | null;
|
|
21
|
+
}): Promise<number>;
|
|
22
|
+
export declare function runConfigRole(workspace: string, options?: {
|
|
23
|
+
roles?: readonly string[];
|
|
24
|
+
modelName?: string | null;
|
|
25
|
+
provider?: string | null;
|
|
26
|
+
model?: string | null;
|
|
27
|
+
options?: readonly string[];
|
|
28
|
+
clearOptions?: readonly string[];
|
|
29
|
+
asJson?: boolean;
|
|
30
|
+
interactive?: boolean;
|
|
31
|
+
adapters?: Record<string, AgentAdapter> | null;
|
|
32
|
+
which?: Which | null;
|
|
33
|
+
prompter?: ConfigPrompter | null;
|
|
34
|
+
runCommand?: RunCommand | null;
|
|
35
|
+
}): Promise<number>;
|