@ashulab/carrier 0.0.0-stage → 0.1.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/LICENSE +21 -0
- package/README.md +264 -2
- package/dist/chat/claude.js +367 -0
- package/dist/chat/codex.js +375 -0
- package/dist/chat/config.js +61 -0
- package/dist/chat/db.js +9 -0
- package/dist/chat/fake.js +203 -0
- package/dist/chat/folder.js +56 -0
- package/dist/chat/git.js +27 -0
- package/dist/chat/group.js +28 -0
- package/dist/chat/health.js +49 -0
- package/dist/chat/host.js +123 -0
- package/dist/chat/idle.js +20 -0
- package/dist/chat/migrations/0000_lame_quasar.sql +15 -0
- package/dist/chat/migrations/0001_quiet_penance.sql +23 -0
- package/dist/chat/migrations/0002_slim_ezekiel_stane.sql +1 -0
- package/dist/chat/migrations/0003_naive_iron_lad.sql +5 -0
- package/dist/chat/migrations/0004_skinny_dakota_north.sql +1 -0
- package/dist/chat/migrations/0005_tidy_strong_guy.sql +1 -0
- package/dist/chat/migrations/meta/0000_snapshot.json +121 -0
- package/dist/chat/migrations/meta/0001_snapshot.json +277 -0
- package/dist/chat/migrations/meta/0002_snapshot.json +284 -0
- package/dist/chat/migrations/meta/0003_snapshot.json +320 -0
- package/dist/chat/migrations/meta/0004_snapshot.json +327 -0
- package/dist/chat/migrations/meta/0005_snapshot.json +334 -0
- package/dist/chat/migrations/meta/_journal.json +48 -0
- package/dist/chat/names.js +97 -0
- package/dist/chat/plan.js +21 -0
- package/dist/chat/projects.js +242 -0
- package/dist/chat/runner.js +6 -0
- package/dist/chat/schema.js +48 -0
- package/dist/chat/server.js +202 -0
- package/dist/chat/sessions.js +766 -0
- package/dist/chat/sweep.js +64 -0
- package/dist/chat/transcript.js +31 -0
- package/dist/chat/words.js +20 -0
- package/dist/chat/workspace.js +134 -0
- package/dist/chat/worktree.js +142 -0
- package/dist/config/default-path.js +7 -0
- package/dist/config/engine-places.js +9 -0
- package/dist/config/json-schema.js +15 -0
- package/dist/config/load.js +48 -0
- package/dist/config/resolve.js +41 -0
- package/dist/config/schema.js +225 -0
- package/dist/control/epic.js +219 -0
- package/dist/control/events.js +48 -0
- package/dist/control/files.js +262 -0
- package/dist/control/replies.js +1 -0
- package/dist/control/server.js +237 -0
- package/dist/control/sessions.js +68 -0
- package/dist/doctor/doctor.js +255 -0
- package/dist/doctor/fixes.js +35 -0
- package/dist/execution/agent-runner.js +1 -0
- package/dist/execution/caller-result.js +61 -0
- package/dist/execution/events.js +19 -0
- package/dist/execution/failure.js +3 -0
- package/dist/execution/fake.js +82 -0
- package/dist/execution/git-workspaces.js +136 -0
- package/dist/execution/import-result.js +23 -0
- package/dist/execution/workspaces.js +1 -0
- package/dist/format/duration.js +12 -0
- package/dist/harnesses/agy.js +131 -0
- package/dist/harnesses/claude.js +246 -0
- package/dist/harnesses/codex.js +118 -0
- package/dist/harnesses/common.js +59 -0
- package/dist/harnesses/credentials.js +38 -0
- package/dist/harnesses/host-runner.js +225 -0
- package/dist/harnesses/local.js +25 -0
- package/dist/harnesses/names.js +9 -0
- package/dist/harnesses/replay-events.js +57 -0
- package/dist/integrations/available-repos.js +29 -0
- package/dist/integrations/forge-cwd.js +27 -0
- package/dist/integrations/github-graphql.js +216 -0
- package/dist/integrations/github.js +231 -0
- package/dist/logging/logger.js +53 -0
- package/dist/logging/redact.js +21 -0
- package/dist/orchestration/blockers.js +25 -0
- package/dist/orchestration/changes-slices.js +5 -0
- package/dist/orchestration/clock.js +7 -0
- package/dist/orchestration/engine.js +1068 -0
- package/dist/orchestration/fake.js +152 -0
- package/dist/orchestration/final-pr.js +15 -0
- package/dist/orchestration/github.js +31 -0
- package/dist/orchestration/reserve.js +32 -0
- package/dist/orchestration/resume-refused.js +7 -0
- package/dist/orchestration/retention.js +145 -0
- package/dist/orchestration/retry.js +16 -0
- package/dist/prompts/build-prompt.js +13 -0
- package/dist/prompts/fix.js +21 -0
- package/dist/prompts/intro.js +21 -0
- package/dist/prompts/invoke.js +2 -0
- package/dist/prompts/persona.js +12 -0
- package/dist/prompts/result.js +32 -0
- package/dist/prompts/review.js +15 -0
- package/dist/prompts/ship.js +8 -0
- package/dist/status/snapshot.js +92 -0
- package/dist/status/types.js +1 -0
- package/dist/storage/caller-results.js +7 -0
- package/dist/storage/db.js +8 -0
- package/dist/storage/epic-review-threads.js +19 -0
- package/dist/storage/epic-slices.js +17 -0
- package/dist/storage/events.js +52 -0
- package/dist/storage/executions.js +31 -0
- package/dist/storage/lock.js +21 -0
- package/dist/storage/migrations/0000_nosy_demogoblin.sql +5 -0
- package/dist/storage/migrations/0001_worried_grey_gargoyle.sql +3 -0
- package/dist/storage/migrations/0002_tough_squirrel_girl.sql +5 -0
- package/dist/storage/migrations/0003_loose_maria_hill.sql +4 -0
- package/dist/storage/migrations/0004_long_cerise.sql +18 -0
- package/dist/storage/migrations/0005_review_result.sql +2 -0
- package/dist/storage/migrations/0006_melted_menace.sql +10 -0
- package/dist/storage/migrations/0007_powerful_bloodscream.sql +2 -0
- package/dist/storage/migrations/0008_panel_state.sql +4 -0
- package/dist/storage/migrations/0009_workable_tiger_shark.sql +5 -0
- package/dist/storage/migrations/0010_nasty_blue_marvel.sql +4 -0
- package/dist/storage/migrations/0011_steep_lila_cheney.sql +13 -0
- package/dist/storage/migrations/0012_talented_big_bertha.sql +1 -0
- package/dist/storage/migrations/0013_third_mulholland_black.sql +17 -0
- package/dist/storage/migrations/0014_perfect_marten_broadcloak.sql +20 -0
- package/dist/storage/migrations/0015_long_bloodaxe.sql +1 -0
- package/dist/storage/migrations/0016_neat_true_believers.sql +5 -0
- package/dist/storage/migrations/0017_previous_swarm.sql +6 -0
- package/dist/storage/migrations/0018_opposite_plazm.sql +2 -0
- package/dist/storage/migrations/0019_hesitant_triton.sql +3 -0
- package/dist/storage/migrations/meta/0000_snapshot.json +49 -0
- package/dist/storage/migrations/meta/0001_snapshot.json +74 -0
- package/dist/storage/migrations/meta/0002_snapshot.json +105 -0
- package/dist/storage/migrations/meta/0003_snapshot.json +134 -0
- package/dist/storage/migrations/meta/0004_snapshot.json +257 -0
- package/dist/storage/migrations/meta/0005_snapshot.json +271 -0
- package/dist/storage/migrations/meta/0006_snapshot.json +337 -0
- package/dist/storage/migrations/meta/0007_snapshot.json +351 -0
- package/dist/storage/migrations/meta/0008_snapshot.json +379 -0
- package/dist/storage/migrations/meta/0009_snapshot.json +414 -0
- package/dist/storage/migrations/meta/0010_snapshot.json +442 -0
- package/dist/storage/migrations/meta/0011_snapshot.json +531 -0
- package/dist/storage/migrations/meta/0012_snapshot.json +538 -0
- package/dist/storage/migrations/meta/0013_snapshot.json +655 -0
- package/dist/storage/migrations/meta/0014_snapshot.json +772 -0
- package/dist/storage/migrations/meta/0015_snapshot.json +779 -0
- package/dist/storage/migrations/meta/0016_snapshot.json +793 -0
- package/dist/storage/migrations/meta/0017_snapshot.json +835 -0
- package/dist/storage/migrations/meta/0018_snapshot.json +849 -0
- package/dist/storage/migrations/meta/0019_snapshot.json +870 -0
- package/dist/storage/migrations/meta/_journal.json +146 -0
- package/dist/storage/schema.js +43 -0
- package/dist/terminal/cli/args.js +91 -0
- package/dist/terminal/cli/cli-error.js +11 -0
- package/dist/terminal/cli/commands/chat-host.js +18 -0
- package/dist/terminal/cli/commands/chat.js +321 -0
- package/dist/terminal/cli/commands/control.js +46 -0
- package/dist/terminal/cli/commands/doctor.js +15 -0
- package/dist/terminal/cli/commands/init.js +43 -0
- package/dist/terminal/cli/commands/restart.js +92 -0
- package/dist/terminal/cli/commands/run.js +20 -0
- package/dist/terminal/cli/commands/schema.js +4 -0
- package/dist/terminal/cli/commands/start.js +21 -0
- package/dist/terminal/cli/commands/status.js +61 -0
- package/dist/terminal/cli/commands/watch.js +112 -0
- package/dist/terminal/cli/compose.js +163 -0
- package/dist/terminal/cli/config-file.js +24 -0
- package/dist/terminal/cli/control-client.js +94 -0
- package/dist/terminal/cli/detached.js +41 -0
- package/dist/terminal/cli/interrupt.js +39 -0
- package/dist/terminal/cli/main.js +85 -0
- package/dist/terminal/cli/open-url.js +9 -0
- package/dist/terminal/dashboard/dashboard.js +204 -0
- package/dist/terminal/dashboard/history.js +38 -0
- package/dist/terminal/dashboard/interactive.js +60 -0
- package/dist/terminal/dashboard/keys.js +22 -0
- package/dist/terminal/dashboard/logs.js +85 -0
- package/dist/terminal/dashboard/panel.js +62 -0
- package/dist/terminal/dashboard/plain.js +32 -0
- package/dist/terminal/dashboard/printable.js +2 -0
- package/dist/terminal/dashboard/ui-state.js +110 -0
- package/dist/terminal/prompts/clack.js +121 -0
- package/dist/terminal/prompts/types.js +3 -0
- package/dist/terminal/wizard/build-config.js +66 -0
- package/dist/terminal/wizard/deps.js +94 -0
- package/dist/terminal/wizard/flags.js +1 -0
- package/dist/terminal/wizard/forge-registry.js +23 -0
- package/dist/terminal/wizard/prior.js +20 -0
- package/dist/terminal/wizard/questions/agent.js +61 -0
- package/dist/terminal/wizard/questions/identities.js +28 -0
- package/dist/terminal/wizard/questions/identity.js +30 -0
- package/dist/terminal/wizard/questions/options.js +93 -0
- package/dist/terminal/wizard/questions/out.js +16 -0
- package/dist/terminal/wizard/questions/persona.js +47 -0
- package/dist/terminal/wizard/questions/repos.js +61 -0
- package/dist/terminal/wizard/summary.js +31 -0
- package/dist/terminal/wizard/testing.js +106 -0
- package/dist/terminal/wizard/wizard.js +172 -0
- package/package.json +46 -3
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import { join, resolve } from 'node:path';
|
|
2
|
+
import { carrierHome } from '../../config/default-path.js';
|
|
3
|
+
import { defaults, loadConfig } from '../../config/load.js';
|
|
4
|
+
import { installFix } from '../../doctor/fixes.js';
|
|
5
|
+
import { localKinds } from '../../harnesses/local.js';
|
|
6
|
+
import { harnessNames } from '../../harnesses/names.js';
|
|
7
|
+
import { Cancelled } from '../prompts/types.js';
|
|
8
|
+
import { buildConfig, identityText, parseIdentity } from './build-config.js';
|
|
9
|
+
import { realDeps } from './deps.js';
|
|
10
|
+
import { priorFrom } from './prior.js';
|
|
11
|
+
import { askIdentities } from './questions/identities.js';
|
|
12
|
+
import { askIdentity } from './questions/identity.js';
|
|
13
|
+
import { askFailover, askProviders, askRoleProvider, declareFlaggedProvider } from './questions/options.js';
|
|
14
|
+
import { askModel } from './questions/agent.js';
|
|
15
|
+
import { askPersona } from './questions/persona.js';
|
|
16
|
+
import { askOut } from './questions/out.js';
|
|
17
|
+
import { askRepos } from './questions/repos.js';
|
|
18
|
+
import { summary, tilde } from './summary.js';
|
|
19
|
+
const ghIdentity = { kind: 'gh' };
|
|
20
|
+
/** The setup flow: look at the machine, ask what is missing, recap, save, check, offer to start. */
|
|
21
|
+
export async function runInit(flags, ui, deps = realDeps, folder = carrierHome()) {
|
|
22
|
+
ui.intro('Carrier setup');
|
|
23
|
+
const interactive = ui.interactive && !flags.yes; // --yes never asks, whatever the terminal
|
|
24
|
+
const forge = { agents: [] };
|
|
25
|
+
const readForge = () => {
|
|
26
|
+
try {
|
|
27
|
+
forge.agents = deps.forgeAgents();
|
|
28
|
+
}
|
|
29
|
+
catch (error) {
|
|
30
|
+
ui.warn(`Could not read the Agent Forge registry: ${error instanceof Error ? error.message : String(error)}`);
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
const harnesses = harnessNames.filter((p) => deps.which(p));
|
|
34
|
+
const login = deps.ghLogin();
|
|
35
|
+
// Local model servers are optional: a server that is not running is shown as such, not as a failure.
|
|
36
|
+
const locals = {};
|
|
37
|
+
for (const kind of localKinds)
|
|
38
|
+
locals[kind] = await deps.localModels(kind).catch(() => undefined);
|
|
39
|
+
// Nothing is shown when the machine is fine. What cannot work at all stops here, with how to fix it.
|
|
40
|
+
const lacking = [
|
|
41
|
+
...['git', 'gh'].filter((tool) => !deps.which(tool)).map((tool) => `${tool}: ${installFix[tool]}`),
|
|
42
|
+
...(harnesses.length === 0 ? ['an agent CLI, any of these:', ...harnessNames.map((h) => ` ${h}: ${installFix[h]}`)] : []),
|
|
43
|
+
];
|
|
44
|
+
if (lacking.length > 0)
|
|
45
|
+
throw new Error(`Carrier needs these before it can run:\n${lacking.map((line) => ` ${line}`).join('\n')}`);
|
|
46
|
+
if (login === undefined)
|
|
47
|
+
ui.warn('gh is not logged in (run: gh auth login): your repos cannot be listed, and a "my own gh login" identity will not work.');
|
|
48
|
+
// A config that is already there: edit it (its answers become the starting points), start over, or leave it.
|
|
49
|
+
const fallback = join(folder, 'config.json');
|
|
50
|
+
let out = flags.out === undefined ? undefined : resolve(flags.out);
|
|
51
|
+
let settled = false; // the question below settled where the config goes, and that it may be replaced
|
|
52
|
+
let prior;
|
|
53
|
+
if (flags.out === undefined && interactive && deps.exists(fallback)) {
|
|
54
|
+
const choice = await ui.select({
|
|
55
|
+
message: `A config already exists at ${tilde(fallback)}`,
|
|
56
|
+
options: [
|
|
57
|
+
{ value: 'edit', label: 'Edit it', hint: 'its answers are the starting points' },
|
|
58
|
+
{ value: 'fresh', label: 'Start over', hint: 'replaces it' },
|
|
59
|
+
{ value: 'elsewhere', label: 'Save a new one in another file' },
|
|
60
|
+
{ value: 'cancel', label: 'Leave it as it is' },
|
|
61
|
+
],
|
|
62
|
+
initialValue: 'edit',
|
|
63
|
+
});
|
|
64
|
+
if (choice === 'cancel')
|
|
65
|
+
throw new Cancelled();
|
|
66
|
+
if (choice === 'edit' || choice === 'fresh') {
|
|
67
|
+
out = fallback;
|
|
68
|
+
settled = true;
|
|
69
|
+
}
|
|
70
|
+
if (choice === 'edit') {
|
|
71
|
+
try {
|
|
72
|
+
prior = priorFrom(deps.readConfig(fallback));
|
|
73
|
+
}
|
|
74
|
+
catch {
|
|
75
|
+
// unreadable: handled as no prior below
|
|
76
|
+
}
|
|
77
|
+
if (prior === undefined)
|
|
78
|
+
ui.warn(`${tilde(fallback)} is not a valid config, so there is nothing to start from.`);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
const repos = flags.repo ?? (await askRepos(ui, deps, prior?.repos));
|
|
82
|
+
// 1. AI Providers: accounts and connections (pure setup, no models)
|
|
83
|
+
let providers = { ...prior?.providers };
|
|
84
|
+
const flagged = (roleKey, roleName) => {
|
|
85
|
+
const flag = flags[roleKey];
|
|
86
|
+
if (flag === undefined)
|
|
87
|
+
return undefined;
|
|
88
|
+
const declared = declareFlaggedProvider(providers, roleName.replace(/\s+/g, '-'), flag, flags[`${roleKey}Provider`]);
|
|
89
|
+
providers = declared.providers;
|
|
90
|
+
return { provider: declared.providerName, model: declared.model };
|
|
91
|
+
};
|
|
92
|
+
const [flaggedAuthor, flaggedReviewer, flaggedLeadReviewer] = [flagged('author', 'author'), flagged('reviewer', 'reviewer'), flagged('leadReviewer', 'lead reviewer')];
|
|
93
|
+
const unattended = flaggedAuthor !== undefined && flaggedReviewer !== undefined;
|
|
94
|
+
if (!unattended)
|
|
95
|
+
providers = await askProviders(ui, providers, harnesses, locals, deps);
|
|
96
|
+
// 2. GitHub identities: shared vs separate, resolved together
|
|
97
|
+
const identities = await askIdentities(ui, flags, login, interactive, prior?.identities);
|
|
98
|
+
const shared = identities === 'shared';
|
|
99
|
+
if (!shared)
|
|
100
|
+
readForge();
|
|
101
|
+
const authorIdentity = shared ? ghIdentity : flags.authorProfile ? parseIdentity(flags.authorProfile) : await askIdentity(ui, 'author', forge, readForge, login, [], deps, interactive, prior?.author.identity);
|
|
102
|
+
const reviewerIdentity = shared ? ghIdentity : flags.reviewerProfile ? parseIdentity(flags.reviewerProfile) : await askIdentity(ui, 'reviewer', forge, readForge, login, [authorIdentity], deps, interactive, prior?.reviewer.identity);
|
|
103
|
+
if (!shared && identityText(authorIdentity) === identityText(reviewerIdentity))
|
|
104
|
+
throw new Error('Author and reviewer identities must differ');
|
|
105
|
+
// 3. Agents: Author and Reviewer (provider, model, persona)
|
|
106
|
+
if (!(flags.authorProfile && flags.author))
|
|
107
|
+
ui.note('Implements the epic: runs ship, then answers the reviewer.\nOptionally it gets a persona at the end: a name and how it behaves.', 'Author');
|
|
108
|
+
const authorProvider = flaggedAuthor?.provider ?? (await askRoleProvider(ui, 'author', providers, prior?.author.provider));
|
|
109
|
+
const authorModel = flaggedAuthor?.model ?? (await askModel(ui, providers[authorProvider].harness, providers[authorProvider].provider, locals, deps, 'author', prior?.author.model));
|
|
110
|
+
const authorPersona = await askPersona(ui, 'author', { name: flags.authorPersonaName, prompt: flags.authorPersonaPrompt }, interactive, prior?.author.persona);
|
|
111
|
+
const author = { identity: authorIdentity, provider: authorProvider, model: authorModel, ...(authorPersona && { persona: authorPersona }) };
|
|
112
|
+
if (!(flags.reviewerProfile && flags.reviewer))
|
|
113
|
+
ui.note('Reviews the final PR.\nOptionally it gets a persona at the end: a name and how it behaves.', 'Reviewer');
|
|
114
|
+
const reviewerProvider = flaggedReviewer?.provider ?? (await askRoleProvider(ui, 'reviewer', providers, prior?.reviewer.provider, authorProvider));
|
|
115
|
+
const reviewerModel = flaggedReviewer?.model ?? (await askModel(ui, providers[reviewerProvider].harness, providers[reviewerProvider].provider, locals, deps, 'reviewer', prior?.reviewer.model));
|
|
116
|
+
const reviewerPersona = await askPersona(ui, 'reviewer', { name: flags.reviewerPersonaName, prompt: flags.reviewerPersonaPrompt }, interactive, prior?.reviewer.persona);
|
|
117
|
+
const reviewer = { identity: reviewerIdentity, provider: reviewerProvider, model: reviewerModel, ...(reviewerPersona && { persona: reviewerPersona }) };
|
|
118
|
+
// 4. Optional Lead Reviewer (Tech Lead role setup)
|
|
119
|
+
let leadReviewer;
|
|
120
|
+
const wantLead = flags.leadReviewer !== undefined
|
|
121
|
+
? true
|
|
122
|
+
: interactive
|
|
123
|
+
? await (async () => {
|
|
124
|
+
ui.note('An optional technical lead role (configuration setup).\nIt configures an evaluation role for architecture and production readiness.', 'Lead Reviewer');
|
|
125
|
+
return ui.confirm('Add a Lead Reviewer to the workflow?');
|
|
126
|
+
})()
|
|
127
|
+
: prior?.leadReviewer !== undefined;
|
|
128
|
+
if (wantLead) {
|
|
129
|
+
const leadIdentity = shared
|
|
130
|
+
? ghIdentity
|
|
131
|
+
: flags.leadReviewerProfile
|
|
132
|
+
? parseIdentity(flags.leadReviewerProfile)
|
|
133
|
+
: await askIdentity(ui, 'lead reviewer', forge, readForge, login, [authorIdentity], deps, interactive, prior?.leadReviewer?.identity ?? reviewerIdentity);
|
|
134
|
+
if (!shared && identityText(authorIdentity) === identityText(leadIdentity)) {
|
|
135
|
+
throw new Error('Author and lead reviewer identities must differ');
|
|
136
|
+
}
|
|
137
|
+
const leadProvider = flaggedLeadReviewer?.provider ?? (await askRoleProvider(ui, 'lead reviewer', providers, prior?.leadReviewer?.provider, reviewerProvider));
|
|
138
|
+
const leadModel = flaggedLeadReviewer?.model ?? (await askModel(ui, providers[leadProvider].harness, providers[leadProvider].provider, locals, deps, 'lead reviewer', prior?.leadReviewer?.model));
|
|
139
|
+
const leadPersona = await askPersona(ui, 'lead reviewer', { name: flags.leadReviewerPersonaName, prompt: flags.leadReviewerPersonaPrompt }, interactive, prior?.leadReviewer?.persona);
|
|
140
|
+
leadReviewer = { identity: leadIdentity, provider: leadProvider, model: leadModel, ...(leadPersona && { persona: leadPersona }) };
|
|
141
|
+
}
|
|
142
|
+
const failover = prior?.failover ?? (unattended || Object.keys(providers).length < 2 ? undefined : await askFailover(ui, providers));
|
|
143
|
+
const user = buildConfig({ repos, author, reviewer, leadReviewer, providers, failover, identities });
|
|
144
|
+
const loaded = loadConfig(defaults, user);
|
|
145
|
+
if (!loaded.ok)
|
|
146
|
+
throw new Error(`the answers do not make a valid config:\n${loaded.errors.map((e) => ` ${e.path}: ${e.message}`).join('\n')}`);
|
|
147
|
+
out ??= resolve(await askOut(ui, fallback));
|
|
148
|
+
if (!settled && deps.exists(out) && !flags.yes && !(await ui.confirm(`${out} exists. Overwrite it?`)))
|
|
149
|
+
throw new Error(`${out} already exists`);
|
|
150
|
+
if (interactive) {
|
|
151
|
+
ui.note(summary(repos, author, reviewer, providers, failover, out, identities, leadReviewer), 'This is what will be saved');
|
|
152
|
+
if (!(await ui.confirm('Save it?')))
|
|
153
|
+
throw new Cancelled();
|
|
154
|
+
}
|
|
155
|
+
deps.write(out, `${JSON.stringify(user, null, 2)}\n`);
|
|
156
|
+
ui.note(tilde(out), 'Config written');
|
|
157
|
+
const checks = await deps.doctor(loaded.config, folder, {}, ui.check, ui.checkStart);
|
|
158
|
+
const use = out === fallback ? '' : ` --config ${out}`; // the default location needs no flag
|
|
159
|
+
const failed = checks.filter((c) => c.status === 'fail').length;
|
|
160
|
+
ui.checksEnd(checks.length, failed);
|
|
161
|
+
if (failed > 0) {
|
|
162
|
+
ui.outro(`${failed} check${failed === 1 ? '' : 's'} failed. Fix them and run: carrier doctor${use}`);
|
|
163
|
+
return { path: out, checks, config: loaded.config, start: false };
|
|
164
|
+
}
|
|
165
|
+
const ready = await deps.readyEpics(loaded.config, folder);
|
|
166
|
+
const waiting = Object.entries(ready).map(([repo, count]) => `${repo}: ${count === undefined ? 'could not read' : `${count} epic${count === 1 ? '' : 's'} marked ready`}`);
|
|
167
|
+
ui.note(waiting.join('\n'), 'Waiting for Carrier');
|
|
168
|
+
const start = interactive && (await ui.confirm('Start Carrier now? (Ctrl+C stops it)'));
|
|
169
|
+
if (!start)
|
|
170
|
+
ui.outro(`Ready. Start it with: carrier${use}\nThen mark an epic of ${repos[0]} as solve:epic:ready.`); // otherwise the caller carries on in the same frame
|
|
171
|
+
return { path: out, checks, config: loaded.config, start };
|
|
172
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,49 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ashulab/carrier",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Autonomous epic orchestrator: ships and reviews Solve epics with AI agents on your machine.",
|
|
5
|
+
"author": "Diego Ghersi",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/AshuLab/carrier.git"
|
|
10
|
+
},
|
|
11
|
+
"type": "module",
|
|
12
|
+
"engines": {
|
|
13
|
+
"node": ">=22"
|
|
14
|
+
},
|
|
15
|
+
"bin": {
|
|
16
|
+
"carrier": "./dist/terminal/cli/main.js"
|
|
17
|
+
},
|
|
18
|
+
"files": [
|
|
19
|
+
"dist",
|
|
20
|
+
"README.md",
|
|
21
|
+
"LICENSE"
|
|
22
|
+
],
|
|
23
|
+
"publishConfig": {
|
|
24
|
+
"access": "public"
|
|
25
|
+
},
|
|
26
|
+
"dependencies": {
|
|
27
|
+
"@anthropic-ai/claude-agent-sdk": "0.3.311",
|
|
28
|
+
"@ashulab/universal-logger": "^0.1.1",
|
|
29
|
+
"@clack/prompts": "^1.8.1",
|
|
30
|
+
"better-sqlite3": "^13.0.3",
|
|
31
|
+
"drizzle-orm": "^0.45.4",
|
|
32
|
+
"zod": "^4.6.7"
|
|
33
|
+
},
|
|
34
|
+
"devDependencies": {
|
|
35
|
+
"@types/better-sqlite3": "^9.6.0",
|
|
36
|
+
"@types/node": "^26.6.5",
|
|
37
|
+
"drizzle-kit": "^0.31.11",
|
|
38
|
+
"typescript": "^7.0.2",
|
|
39
|
+
"vitest": "^5.0.4"
|
|
40
|
+
},
|
|
41
|
+
"scripts": {
|
|
42
|
+
"build": "rm -rf dist && tsc -p tsconfig.build.json && cp -r src/storage/migrations dist/storage/migrations && cp -r src/chat/migrations dist/chat/migrations && chmod +x dist/terminal/cli/main.js",
|
|
43
|
+
"typecheck": "tsc --noEmit",
|
|
44
|
+
"test": "vitest run",
|
|
45
|
+
"test:integration": "vitest run --config vitest.integration.config.ts --passWithNoTests",
|
|
46
|
+
"db:generate": "drizzle-kit generate && drizzle-kit generate --config drizzle.chat.config.ts",
|
|
47
|
+
"replay:events": "node src/harnesses/replay-events.ts"
|
|
48
|
+
}
|
|
6
49
|
}
|