@genoventures-labs/deckhand 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 +152 -0
- package/agent/agent.ts +5 -0
- package/agent/instructions.md +23 -0
- package/agent/schedules/workspace_scan.md +5 -0
- package/agent/skills/conflict-triage.md +7 -0
- package/agent/skills/git-sync.md +11 -0
- package/agent/skills/github-entities.md +7 -0
- package/agent/tools/draft_commit_message.ts +12 -0
- package/agent/tools/gh_actions_list.ts +12 -0
- package/agent/tools/gh_actions_run.ts +17 -0
- package/agent/tools/gh_actions_watch.ts +14 -0
- package/agent/tools/gh_checks.ts +12 -0
- package/agent/tools/gh_issue_create.ts +16 -0
- package/agent/tools/gh_pr_create.ts +17 -0
- package/agent/tools/gh_project_create.ts +15 -0
- package/agent/tools/gh_repo_create.ts +18 -0
- package/agent/tools/git_add.ts +15 -0
- package/agent/tools/git_branch.ts +15 -0
- package/agent/tools/git_commit.ts +14 -0
- package/agent/tools/git_conflicts.ts +15 -0
- package/agent/tools/git_pull.ts +12 -0
- package/agent/tools/git_push.ts +16 -0
- package/agent/tools/git_status.ts +13 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +262 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/runs.d.ts +2 -0
- package/dist/commands/runs.js +80 -0
- package/dist/commands/runs.js.map +1 -0
- package/dist/eve-dev.d.ts +1 -0
- package/dist/eve-dev.js +41 -0
- package/dist/eve-dev.js.map +1 -0
- package/dist/lib/config.d.ts +8 -0
- package/dist/lib/config.js +28 -0
- package/dist/lib/config.js.map +1 -0
- package/dist/lib/doctor.d.ts +6 -0
- package/dist/lib/doctor.js +42 -0
- package/dist/lib/doctor.js.map +1 -0
- package/dist/lib/env.d.ts +5 -0
- package/dist/lib/env.js +26 -0
- package/dist/lib/env.js.map +1 -0
- package/dist/lib/gh.d.ts +34 -0
- package/dist/lib/gh.js +52 -0
- package/dist/lib/gh.js.map +1 -0
- package/dist/lib/git.d.ts +26 -0
- package/dist/lib/git.js +131 -0
- package/dist/lib/git.js.map +1 -0
- package/dist/lib/model.d.ts +4 -0
- package/dist/lib/model.js +60 -0
- package/dist/lib/model.js.map +1 -0
- package/dist/lib/ollama.d.ts +4 -0
- package/dist/lib/ollama.js +65 -0
- package/dist/lib/ollama.js.map +1 -0
- package/dist/lib/paths.d.ts +2 -0
- package/dist/lib/paths.js +9 -0
- package/dist/lib/paths.js.map +1 -0
- package/dist/lib/run.d.ts +21 -0
- package/dist/lib/run.js +75 -0
- package/dist/lib/run.js.map +1 -0
- package/dist/lib/runs.d.ts +55 -0
- package/dist/lib/runs.js +168 -0
- package/dist/lib/runs.js.map +1 -0
- package/dist/lib/watch.d.ts +12 -0
- package/dist/lib/watch.js +38 -0
- package/dist/lib/watch.js.map +1 -0
- package/dist/lib/workspace.d.ts +1 -0
- package/dist/lib/workspace.js +5 -0
- package/dist/lib/workspace.js.map +1 -0
- package/dist/ui/format.d.ts +16 -0
- package/dist/ui/format.js +82 -0
- package/dist/ui/format.js.map +1 -0
- package/dist/ui/help.d.ts +7 -0
- package/dist/ui/help.js +197 -0
- package/dist/ui/help.js.map +1 -0
- package/dist/ui/table.d.ts +4 -0
- package/dist/ui/table.js +39 -0
- package/dist/ui/table.js.map +1 -0
- package/dist/ui/theme.d.ts +14 -0
- package/dist/ui/theme.js +22 -0
- package/dist/ui/theme.js.map +1 -0
- package/package.json +55 -0
- package/templates/github-actions/gated-sync.yml +35 -0
- package/templates/github-actions/morning-pull.yml +42 -0
- package/templates/github-actions/nightly-checks.yml +33 -0
- package/templates/github-actions/weekday-status.yml +17 -0
- package/templates/runs/gated-sync.yaml +19 -0
- package/templates/runs/morning-pull.yaml +17 -0
- package/templates/runs/nightly-checks.yaml +17 -0
- package/templates/runs/weekday-status.yaml +17 -0
- package/templates/schema/gated-run.v1.json +67 -0
package/dist/lib/runs.js
ADDED
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, readdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { basename, join } from "node:path";
|
|
3
|
+
import { parse as parseYaml } from "yaml";
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
import { listChecks, listRuns } from "./gh.js";
|
|
6
|
+
import { formatStatus, gitAdd, gitCommit, gitPull, gitPush, gitStatus } from "./git.js";
|
|
7
|
+
import { generateCommitMessage } from "./model.js";
|
|
8
|
+
import { templatesRoot } from "./paths.js";
|
|
9
|
+
import { workspaceRoot } from "./workspace.js";
|
|
10
|
+
export const RUN_ACTIONS = ["status", "pull", "sync", "checks", "actions-list"];
|
|
11
|
+
const cronField = z.string().regex(/^(\S+\s+){4}\S+$/, "cron must have 5 fields (min hour day month weekday)");
|
|
12
|
+
const gatedRunSchema = z.object({
|
|
13
|
+
apiVersion: z.literal("deckhand/v1"),
|
|
14
|
+
kind: z.literal("GatedRun"),
|
|
15
|
+
metadata: z.object({
|
|
16
|
+
name: z.string().min(1),
|
|
17
|
+
description: z.string().optional(),
|
|
18
|
+
}),
|
|
19
|
+
spec: z.object({
|
|
20
|
+
schedule: z.object({
|
|
21
|
+
cron: cronField,
|
|
22
|
+
timezone: z.string().default("UTC"),
|
|
23
|
+
}),
|
|
24
|
+
action: z.enum(RUN_ACTIONS),
|
|
25
|
+
workspace: z.string().default("."),
|
|
26
|
+
gate: z
|
|
27
|
+
.object({
|
|
28
|
+
enabled: z.boolean().default(true),
|
|
29
|
+
environment: z.string().default("deckhand-gate"),
|
|
30
|
+
requireCleanTree: z.boolean().default(true),
|
|
31
|
+
requireChecks: z.boolean().default(false),
|
|
32
|
+
})
|
|
33
|
+
.default({
|
|
34
|
+
enabled: true,
|
|
35
|
+
environment: "deckhand-gate",
|
|
36
|
+
requireCleanTree: true,
|
|
37
|
+
requireChecks: false,
|
|
38
|
+
}),
|
|
39
|
+
sync: z
|
|
40
|
+
.object({
|
|
41
|
+
push: z.boolean().default(false),
|
|
42
|
+
message: z.string().optional(),
|
|
43
|
+
})
|
|
44
|
+
.optional(),
|
|
45
|
+
}),
|
|
46
|
+
});
|
|
47
|
+
export function userRunsDir(cwd) {
|
|
48
|
+
return join(workspaceRoot(cwd), ".deckhand", "runs");
|
|
49
|
+
}
|
|
50
|
+
export function packagedRunTemplatesDir() {
|
|
51
|
+
return join(templatesRoot(), "runs");
|
|
52
|
+
}
|
|
53
|
+
export function packagedWorkflowTemplatesDir() {
|
|
54
|
+
return join(templatesRoot(), "github-actions");
|
|
55
|
+
}
|
|
56
|
+
export function parseGatedRun(raw, source) {
|
|
57
|
+
const parsed = gatedRunSchema.safeParse(parseYaml(raw));
|
|
58
|
+
if (!parsed.success) {
|
|
59
|
+
throw new Error(`${source}: ${parsed.error.issues.map((issue) => issue.message).join("; ")}`);
|
|
60
|
+
}
|
|
61
|
+
return parsed.data;
|
|
62
|
+
}
|
|
63
|
+
export function loadRunFile(path) {
|
|
64
|
+
return { path, run: parseGatedRun(readFileSync(path, "utf8"), path) };
|
|
65
|
+
}
|
|
66
|
+
function yamlFiles(dir) {
|
|
67
|
+
if (!existsSync(dir))
|
|
68
|
+
return [];
|
|
69
|
+
return readdirSync(dir)
|
|
70
|
+
.filter((name) => name.endsWith(".yaml") || name.endsWith(".yml"))
|
|
71
|
+
.map((name) => join(dir, name));
|
|
72
|
+
}
|
|
73
|
+
export function listTemplateRuns() {
|
|
74
|
+
return yamlFiles(packagedRunTemplatesDir()).map(loadRunFile);
|
|
75
|
+
}
|
|
76
|
+
export function listUserRuns(cwd) {
|
|
77
|
+
return yamlFiles(userRunsDir(cwd)).map(loadRunFile);
|
|
78
|
+
}
|
|
79
|
+
export function findRun(name, cwd) {
|
|
80
|
+
const fromUser = listUserRuns(cwd).find((entry) => entry.run.metadata.name === name);
|
|
81
|
+
if (fromUser)
|
|
82
|
+
return fromUser;
|
|
83
|
+
const fromTemplates = listTemplateRuns().find((entry) => entry.run.metadata.name === name);
|
|
84
|
+
if (fromTemplates)
|
|
85
|
+
return fromTemplates;
|
|
86
|
+
throw new Error(`No gated run named "${name}". Try: deckhand runs list`);
|
|
87
|
+
}
|
|
88
|
+
export function initRunTemplate(name, cwd) {
|
|
89
|
+
const template = listTemplateRuns().find((entry) => entry.run.metadata.name === name);
|
|
90
|
+
if (!template) {
|
|
91
|
+
const available = listTemplateRuns()
|
|
92
|
+
.map((entry) => entry.run.metadata.name)
|
|
93
|
+
.join(", ");
|
|
94
|
+
throw new Error(`Unknown template "${name}". Available: ${available}`);
|
|
95
|
+
}
|
|
96
|
+
const destDir = userRunsDir(cwd);
|
|
97
|
+
mkdirSync(destDir, { recursive: true });
|
|
98
|
+
const dest = join(destDir, basename(template.path));
|
|
99
|
+
writeFileSync(dest, readFileSync(template.path, "utf8"));
|
|
100
|
+
return dest;
|
|
101
|
+
}
|
|
102
|
+
export function installWorkflowTemplate(name, cwd) {
|
|
103
|
+
const source = join(packagedWorkflowTemplatesDir(), `${name}.yml`);
|
|
104
|
+
if (!existsSync(source)) {
|
|
105
|
+
const available = yamlFiles(packagedWorkflowTemplatesDir())
|
|
106
|
+
.map((path) => basename(path, ".yml"))
|
|
107
|
+
.join(", ");
|
|
108
|
+
throw new Error(`Unknown workflow template "${name}". Available: ${available}`);
|
|
109
|
+
}
|
|
110
|
+
const destDir = join(workspaceRoot(cwd), ".github", "workflows");
|
|
111
|
+
mkdirSync(destDir, { recursive: true });
|
|
112
|
+
const dest = join(destDir, `deckhand-${name}.yml`);
|
|
113
|
+
writeFileSync(dest, readFileSync(source, "utf8"));
|
|
114
|
+
return dest;
|
|
115
|
+
}
|
|
116
|
+
export async function applyRun(loaded, options) {
|
|
117
|
+
const { run } = loaded;
|
|
118
|
+
const cwd = options.cwd ?? run.spec.workspace;
|
|
119
|
+
const gate = run.spec.gate;
|
|
120
|
+
if (gate.enabled && !options.approve && process.env.DECKHAND_RUN_APPROVED !== "1") {
|
|
121
|
+
throw new Error(`Run "${run.metadata.name}" is gated by environment "${gate.environment}". Re-run with --approve after review, or set DECKHAND_RUN_APPROVED=1 on a trusted runner.`);
|
|
122
|
+
}
|
|
123
|
+
if (gate.requireCleanTree && run.spec.action !== "status" && run.spec.action !== "sync") {
|
|
124
|
+
const status = await gitStatus(cwd);
|
|
125
|
+
if (!status.clean) {
|
|
126
|
+
throw new Error(`Gate requires a clean tree:\n${formatStatus(status)}`);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
if (gate.requireChecks) {
|
|
130
|
+
const checks = await listChecks(cwd);
|
|
131
|
+
if (/fail|pending|error/i.test(checks)) {
|
|
132
|
+
throw new Error(`Gate requires green PR checks:\n${checks}`);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
const action = run.spec.action;
|
|
136
|
+
switch (action) {
|
|
137
|
+
case "status":
|
|
138
|
+
return formatStatus(await gitStatus(cwd));
|
|
139
|
+
case "pull":
|
|
140
|
+
return gitPull(cwd);
|
|
141
|
+
case "sync": {
|
|
142
|
+
const status = await gitStatus(cwd);
|
|
143
|
+
if (status.clean)
|
|
144
|
+
return "Working tree is clean. Nothing to sync.";
|
|
145
|
+
await gitAdd(["."], cwd);
|
|
146
|
+
const message = run.spec.sync?.message ?? (await generateCommitMessage(cwd));
|
|
147
|
+
const committed = await gitCommit(message, cwd);
|
|
148
|
+
if (run.spec.sync?.push) {
|
|
149
|
+
try {
|
|
150
|
+
return `${committed}\n${await gitPush(cwd)}`;
|
|
151
|
+
}
|
|
152
|
+
catch {
|
|
153
|
+
return `${committed}\n${await gitPush(cwd, true)}`;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
return committed;
|
|
157
|
+
}
|
|
158
|
+
case "checks":
|
|
159
|
+
return listChecks(cwd);
|
|
160
|
+
case "actions-list":
|
|
161
|
+
return listRuns(cwd);
|
|
162
|
+
default: {
|
|
163
|
+
const exhaustive = action;
|
|
164
|
+
throw new Error(`Unhandled run action: ${String(exhaustive)}`);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
//# sourceMappingURL=runs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runs.js","sourceRoot":"","sources":["../../src/lib/runs.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { type GitStatus } from "./git.js";
|
|
2
|
+
export type WatchHandle = {
|
|
3
|
+
close: () => void;
|
|
4
|
+
};
|
|
5
|
+
export type WatchEvent = {
|
|
6
|
+
ok: true;
|
|
7
|
+
status: GitStatus;
|
|
8
|
+
} | {
|
|
9
|
+
ok: false;
|
|
10
|
+
error: string;
|
|
11
|
+
};
|
|
12
|
+
export declare function watchWorkspace(cwd: string | undefined, onChange: (event: WatchEvent) => void): Promise<WatchHandle>;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { watch as watchFiles } from "node:fs";
|
|
2
|
+
import { resolve } from "node:path";
|
|
3
|
+
import { loadConfig } from "./config.js";
|
|
4
|
+
import { gitStatus } from "./git.js";
|
|
5
|
+
import { workspaceRoot } from "./workspace.js";
|
|
6
|
+
export async function watchWorkspace(cwd, onChange) {
|
|
7
|
+
const root = workspaceRoot(cwd);
|
|
8
|
+
const config = loadConfig(root);
|
|
9
|
+
const watchers = config.workspaces.map((relative) => {
|
|
10
|
+
const target = resolve(root, relative);
|
|
11
|
+
return watchFiles(target, { recursive: true }, debounce(800, async () => {
|
|
12
|
+
try {
|
|
13
|
+
onChange({ ok: true, status: await gitStatus(root) });
|
|
14
|
+
}
|
|
15
|
+
catch (error) {
|
|
16
|
+
onChange({ ok: false, error: error instanceof Error ? error.message : String(error) });
|
|
17
|
+
}
|
|
18
|
+
}));
|
|
19
|
+
});
|
|
20
|
+
onChange({ ok: true, status: await gitStatus(root) });
|
|
21
|
+
return {
|
|
22
|
+
close: () => {
|
|
23
|
+
for (const watcher of watchers)
|
|
24
|
+
watcher.close();
|
|
25
|
+
},
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
function debounce(ms, fn) {
|
|
29
|
+
let timer;
|
|
30
|
+
return () => {
|
|
31
|
+
if (timer)
|
|
32
|
+
clearTimeout(timer);
|
|
33
|
+
timer = setTimeout(() => {
|
|
34
|
+
void fn();
|
|
35
|
+
}, ms);
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=watch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"watch.js","sourceRoot":"","sources":["../../src/lib/watch.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,IAAI,UAAU,EAAE,MAAM,SAAS,CAAC;AAC9C,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,SAAS,EAAkB,MAAM,UAAU,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAQ/C,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,GAAuB,EACvB,QAAqC;IAErC,MAAM,IAAI,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC;IAChC,MAAM,MAAM,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;IAChC,MAAM,QAAQ,GAAG,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE;QAClD,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;QACvC,OAAO,UAAU,CACf,MAAM,EACN,EAAE,SAAS,EAAE,IAAI,EAAE,EACnB,QAAQ,CAAC,GAAG,EAAE,KAAK,IAAI,EAAE;YACvB,IAAI,CAAC;gBACH,QAAQ,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACxD,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,QAAQ,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;YACzF,CAAC;QACH,CAAC,CAAC,CACH,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAEtD,OAAO;QACL,KAAK,EAAE,GAAG,EAAE;YACV,KAAK,MAAM,OAAO,IAAI,QAAQ;gBAAE,OAAO,CAAC,KAAK,EAAE,CAAC;QAClD,CAAC;KACF,CAAC;AACJ,CAAC;AAED,SAAS,QAAQ,CAAC,EAAU,EAAE,EAA8B;IAC1D,IAAI,KAAgD,CAAC;IACrD,OAAO,GAAG,EAAE;QACV,IAAI,KAAK;YAAE,YAAY,CAAC,KAAK,CAAC,CAAC;QAC/B,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;YACtB,KAAK,EAAE,EAAE,CAAC;QACZ,CAAC,EAAE,EAAE,CAAC,CAAC;IACT,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function workspaceRoot(explicit?: string): string;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workspace.js","sourceRoot":"","sources":["../../src/lib/workspace.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,MAAM,UAAU,aAAa,CAAC,QAAiB;IAC7C,OAAO,OAAO,CAAC,QAAQ,IAAI,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;AACxE,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { DoctorCheck } from "../lib/doctor.js";
|
|
2
|
+
import type { GitStatus } from "../lib/git.js";
|
|
3
|
+
import type { LoadedRun } from "../lib/runs.js";
|
|
4
|
+
export declare function banner(): string;
|
|
5
|
+
export declare function section(title: string): string;
|
|
6
|
+
export declare function notice(kind: "ok" | "fail" | "warn" | "info", message: string): string;
|
|
7
|
+
export declare function print(text: string): void;
|
|
8
|
+
export declare function printError(message: string): void;
|
|
9
|
+
export declare function doctorTable(checks: DoctorCheck[]): string;
|
|
10
|
+
export declare function statusTables(status: GitStatus): string;
|
|
11
|
+
export declare function runsTables(templates: LoadedRun[], local: LoadedRun[]): string;
|
|
12
|
+
export declare function kvTable(title: string, entries: Record<string, string>): string;
|
|
13
|
+
export declare function commandTable(groups: {
|
|
14
|
+
title: string;
|
|
15
|
+
rows: [string, string][];
|
|
16
|
+
}[]): string;
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { renderTable } from "./table.js";
|
|
2
|
+
import { theme, VERSION } from "./theme.js";
|
|
3
|
+
export function banner() {
|
|
4
|
+
const rule = theme.muted("─".repeat(Math.min(56, process.stdout.columns ?? 56)));
|
|
5
|
+
return [
|
|
6
|
+
theme.brand("Deckhand") + theme.muted(` v${VERSION}`),
|
|
7
|
+
theme.muted("Git, GitHub, and gated runs — via Eve and AI Gateway"),
|
|
8
|
+
rule,
|
|
9
|
+
].join("\n");
|
|
10
|
+
}
|
|
11
|
+
export function section(title) {
|
|
12
|
+
return theme.heading(title);
|
|
13
|
+
}
|
|
14
|
+
export function notice(kind, message) {
|
|
15
|
+
const tag = kind === "ok"
|
|
16
|
+
? theme.ok("ok")
|
|
17
|
+
: kind === "fail"
|
|
18
|
+
? theme.fail("fail")
|
|
19
|
+
: kind === "warn"
|
|
20
|
+
? theme.warn("warn")
|
|
21
|
+
: theme.info("info");
|
|
22
|
+
return `${tag} ${message}`;
|
|
23
|
+
}
|
|
24
|
+
export function print(text) {
|
|
25
|
+
console.log(text);
|
|
26
|
+
}
|
|
27
|
+
export function printError(message) {
|
|
28
|
+
console.error(notice("fail", message));
|
|
29
|
+
}
|
|
30
|
+
export function doctorTable(checks) {
|
|
31
|
+
const rows = checks.map((check) => [
|
|
32
|
+
check.name,
|
|
33
|
+
check.ok ? theme.ok("pass") : theme.fail("fail"),
|
|
34
|
+
check.detail,
|
|
35
|
+
]);
|
|
36
|
+
return [section("Doctor"), renderTable(["Check", "Status", "Detail"], rows)].join("\n");
|
|
37
|
+
}
|
|
38
|
+
export function statusTables(status) {
|
|
39
|
+
const tracking = status.ahead || status.behind ? `ahead ${status.ahead} / behind ${status.behind}` : "in sync";
|
|
40
|
+
const meta = renderTable(["Field", "Value"], [
|
|
41
|
+
["Repo", status.cwd],
|
|
42
|
+
["Branch", `${status.branch}${status.detached ? " (detached)" : ""}`],
|
|
43
|
+
["Tracking", tracking],
|
|
44
|
+
["Tree", status.clean ? theme.ok("clean") : theme.warn(`${status.changes.length} changes`)],
|
|
45
|
+
]);
|
|
46
|
+
if (status.clean) {
|
|
47
|
+
return [section("Status"), meta, notice("ok", "Working tree is clean.")].join("\n");
|
|
48
|
+
}
|
|
49
|
+
const changes = renderTable(["Kind", "Index", "Worktree", "Path"], status.changes.map((change) => [
|
|
50
|
+
change.kind,
|
|
51
|
+
change.index.trim() ? change.index : "·",
|
|
52
|
+
change.worktree.trim() ? change.worktree : "·",
|
|
53
|
+
change.path,
|
|
54
|
+
]));
|
|
55
|
+
return [section("Status"), meta, "", section("Changes"), changes].join("\n");
|
|
56
|
+
}
|
|
57
|
+
export function runsTables(templates, local) {
|
|
58
|
+
const toRows = (entries, source) => entries.map((entry) => [
|
|
59
|
+
entry.run.metadata.name,
|
|
60
|
+
entry.run.spec.schedule.cron,
|
|
61
|
+
entry.run.spec.schedule.timezone,
|
|
62
|
+
entry.run.spec.action,
|
|
63
|
+
entry.run.spec.gate.enabled ? theme.warn(entry.run.spec.gate.environment) : theme.ok("ungated"),
|
|
64
|
+
source,
|
|
65
|
+
entry.run.metadata.description ?? "",
|
|
66
|
+
]);
|
|
67
|
+
const headers = ["Name", "Cron", "Timezone", "Action", "Gate", "Source", "Description"];
|
|
68
|
+
const rows = [...toRows(templates, "template"), ...toRows(local, "local")];
|
|
69
|
+
return [section("Gated runs"), renderTable(headers, rows)].join("\n");
|
|
70
|
+
}
|
|
71
|
+
export function kvTable(title, entries) {
|
|
72
|
+
return [
|
|
73
|
+
section(title),
|
|
74
|
+
renderTable(["Key", "Value"], Object.entries(entries).map(([key, value]) => [key, value])),
|
|
75
|
+
].join("\n");
|
|
76
|
+
}
|
|
77
|
+
export function commandTable(groups) {
|
|
78
|
+
return groups
|
|
79
|
+
.map((group) => [section(group.title), renderTable(["Command", "What it does"], group.rows)].join("\n"))
|
|
80
|
+
.join("\n\n");
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=format.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"format.js","sourceRoot":"","sources":["../../src/ui/format.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { Command } from "commander";
|
|
2
|
+
export declare const HELP_TOPICS: readonly ["getting-started", "git", "github", "runs", "gateway", "examples"];
|
|
3
|
+
export type HelpTopic = (typeof HELP_TOPICS)[number];
|
|
4
|
+
export declare function printRootHelp(program: Command): void;
|
|
5
|
+
export declare function printTopicIndex(): void;
|
|
6
|
+
export declare function printTopic(topic: HelpTopic): void;
|
|
7
|
+
export declare function showHelpTopicOrCommand(program: Command, topic?: string): void;
|
package/dist/ui/help.js
ADDED
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
import { banner, commandTable, print, section } from "./format.js";
|
|
2
|
+
import { renderTable } from "./table.js";
|
|
3
|
+
import { theme } from "./theme.js";
|
|
4
|
+
export const HELP_TOPICS = [
|
|
5
|
+
"getting-started",
|
|
6
|
+
"git",
|
|
7
|
+
"github",
|
|
8
|
+
"runs",
|
|
9
|
+
"gateway",
|
|
10
|
+
"examples",
|
|
11
|
+
];
|
|
12
|
+
function isHelpTopic(value) {
|
|
13
|
+
return HELP_TOPICS.includes(value);
|
|
14
|
+
}
|
|
15
|
+
export function printRootHelp(program) {
|
|
16
|
+
print([
|
|
17
|
+
banner(),
|
|
18
|
+
"",
|
|
19
|
+
theme.muted("Usage"),
|
|
20
|
+
" deckhand <command> [options]",
|
|
21
|
+
" deckhand help [topic|command]",
|
|
22
|
+
"",
|
|
23
|
+
commandTable([
|
|
24
|
+
{
|
|
25
|
+
title: "Workspace",
|
|
26
|
+
rows: [
|
|
27
|
+
["doctor", "Check git, gh, AI Gateway, and Node"],
|
|
28
|
+
["status", "Repo, branch, and change table"],
|
|
29
|
+
["watch", "Live status as files change"],
|
|
30
|
+
["config", "Resolved Deckhand settings"],
|
|
31
|
+
],
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
title: "Git",
|
|
35
|
+
rows: [
|
|
36
|
+
["sync", "Stage, commit (Gateway message), push"],
|
|
37
|
+
["pull", "Fast-forward pull"],
|
|
38
|
+
["branch <name>", "Create or switch a branch"],
|
|
39
|
+
["conflicts", "Conflict list plus model guidance"],
|
|
40
|
+
],
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
title: "GitHub",
|
|
44
|
+
rows: [
|
|
45
|
+
["pr create", "Open a pull request"],
|
|
46
|
+
["issue create", "Open an issue"],
|
|
47
|
+
["repo create", "Create a repository"],
|
|
48
|
+
["project create", "Create a GitHub Project"],
|
|
49
|
+
["checks", "PR status checks"],
|
|
50
|
+
["actions list|watch|run", "GitHub Actions"],
|
|
51
|
+
],
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
title: "Automation",
|
|
55
|
+
rows: [
|
|
56
|
+
["runs", "Gated YAML schedules and templates"],
|
|
57
|
+
["agent", "Start the Eve terminal session"],
|
|
58
|
+
],
|
|
59
|
+
},
|
|
60
|
+
]),
|
|
61
|
+
"",
|
|
62
|
+
section("Help"),
|
|
63
|
+
renderTable(["Command", "Opens"], [
|
|
64
|
+
["deckhand help", "This overview"],
|
|
65
|
+
["deckhand help topics", "All help topics"],
|
|
66
|
+
["deckhand help runs", "Gated-run guide"],
|
|
67
|
+
["deckhand <command> --help", "Flags for one command"],
|
|
68
|
+
]),
|
|
69
|
+
"",
|
|
70
|
+
theme.muted("Global flags: -h, --help -V, --version -C, --cwd <path> on most commands"),
|
|
71
|
+
].join("\n"));
|
|
72
|
+
void program;
|
|
73
|
+
}
|
|
74
|
+
export function printTopicIndex() {
|
|
75
|
+
print([
|
|
76
|
+
banner(),
|
|
77
|
+
"",
|
|
78
|
+
section("Help topics"),
|
|
79
|
+
renderTable(["Topic", "Covers"], [
|
|
80
|
+
["getting-started", "Install, auth, first commands"],
|
|
81
|
+
["git", "status, watch, sync, pull, conflicts"],
|
|
82
|
+
["github", "pr, issue, repo, project, checks, actions"],
|
|
83
|
+
["runs", "YAML gated runs and GitHub Environments"],
|
|
84
|
+
["gateway", "AI Gateway keys and models"],
|
|
85
|
+
["examples", "Copy-paste command recipes"],
|
|
86
|
+
]),
|
|
87
|
+
"",
|
|
88
|
+
theme.muted("deckhand help <topic>"),
|
|
89
|
+
].join("\n"));
|
|
90
|
+
}
|
|
91
|
+
export function printTopic(topic) {
|
|
92
|
+
const body = topicBody(topic);
|
|
93
|
+
print([banner(), "", body].join("\n"));
|
|
94
|
+
}
|
|
95
|
+
function topicBody(topic) {
|
|
96
|
+
switch (topic) {
|
|
97
|
+
case "getting-started":
|
|
98
|
+
return [
|
|
99
|
+
section("Getting started"),
|
|
100
|
+
"1. npm install && npm run build",
|
|
101
|
+
"2. gh auth login",
|
|
102
|
+
"3. Copy .env.example to .env.local and set AI_GATEWAY_API_KEY",
|
|
103
|
+
"4. deckhand doctor",
|
|
104
|
+
"5. deckhand status",
|
|
105
|
+
"",
|
|
106
|
+
theme.muted("Eve agent (Node 24+): deckhand agent"),
|
|
107
|
+
].join("\n");
|
|
108
|
+
case "git":
|
|
109
|
+
return [
|
|
110
|
+
section("Git"),
|
|
111
|
+
"deckhand status Change table for the current repo",
|
|
112
|
+
"deckhand watch Reprint status on filesystem events",
|
|
113
|
+
"deckhand pull git pull --ff-only",
|
|
114
|
+
"deckhand sync add + Gateway commit message + push",
|
|
115
|
+
"deckhand sync --no-push commit only",
|
|
116
|
+
"deckhand sync -m \"msg\" skip the model",
|
|
117
|
+
"deckhand branch topic/fix create or switch",
|
|
118
|
+
"deckhand conflicts list + resolution notes",
|
|
119
|
+
"",
|
|
120
|
+
theme.muted("Never force-pushes. Pulls are fast-forward only."),
|
|
121
|
+
].join("\n");
|
|
122
|
+
case "github":
|
|
123
|
+
return [
|
|
124
|
+
section("GitHub"),
|
|
125
|
+
"Requires gh on PATH (deckhand doctor).",
|
|
126
|
+
"",
|
|
127
|
+
"deckhand pr create -t \"Title\"",
|
|
128
|
+
"deckhand issue create -t \"Title\"",
|
|
129
|
+
"deckhand repo create my-repo --private",
|
|
130
|
+
"deckhand project create -t \"Board\" -o my-org",
|
|
131
|
+
"deckhand checks",
|
|
132
|
+
"deckhand actions list",
|
|
133
|
+
"deckhand actions watch [runId]",
|
|
134
|
+
"deckhand actions run ci.yml --ref main",
|
|
135
|
+
].join("\n");
|
|
136
|
+
case "runs":
|
|
137
|
+
return [
|
|
138
|
+
section("Gated runs"),
|
|
139
|
+
"YAML under templates/runs and .deckhand/runs.",
|
|
140
|
+
"GitHub Environment deckhand-gate holds execute jobs for review.",
|
|
141
|
+
"",
|
|
142
|
+
"deckhand runs list",
|
|
143
|
+
"deckhand runs init morning-pull",
|
|
144
|
+
"deckhand runs install-workflow morning-pull",
|
|
145
|
+
"deckhand runs apply morning-pull --approve",
|
|
146
|
+
"",
|
|
147
|
+
"Gated apply without --approve exits with an error on purpose.",
|
|
148
|
+
"GitHub cron is UTC; YAML timezone documents local intent.",
|
|
149
|
+
].join("\n");
|
|
150
|
+
case "gateway":
|
|
151
|
+
return [
|
|
152
|
+
section("AI Gateway"),
|
|
153
|
+
"Set AI_GATEWAY_API_KEY, or vercel link && vercel env pull .env.local",
|
|
154
|
+
"Default model: openai/gpt-5.6-luna-fast",
|
|
155
|
+
"Override with DECKHAND_MODEL or deckhand.json { \"model\": \"provider/model\" }",
|
|
156
|
+
"",
|
|
157
|
+
"deckhand doctor shows whether credentials resolved",
|
|
158
|
+
"deckhand config prints the effective model and workspaces",
|
|
159
|
+
].join("\n");
|
|
160
|
+
case "examples":
|
|
161
|
+
return [
|
|
162
|
+
section("Examples"),
|
|
163
|
+
"deckhand doctor",
|
|
164
|
+
"deckhand status -C ../other-repo",
|
|
165
|
+
"deckhand sync --no-push",
|
|
166
|
+
"deckhand pr create -t \"Tighten pull gates\" --draft",
|
|
167
|
+
"deckhand runs list",
|
|
168
|
+
"deckhand help git",
|
|
169
|
+
].join("\n");
|
|
170
|
+
default: {
|
|
171
|
+
const exhaustive = topic;
|
|
172
|
+
return String(exhaustive);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
export function showHelpTopicOrCommand(program, topic) {
|
|
177
|
+
if (!topic || topic === "help") {
|
|
178
|
+
printRootHelp(program);
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
if (topic === "topics") {
|
|
182
|
+
printTopicIndex();
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
if (isHelpTopic(topic)) {
|
|
186
|
+
printTopic(topic);
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
const command = program.commands.find((entry) => entry.name() === topic || entry.aliases().includes(topic));
|
|
190
|
+
if (command) {
|
|
191
|
+
command.outputHelp();
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
print(`${theme.fail("Unknown help topic:")} ${topic}`);
|
|
195
|
+
printTopicIndex();
|
|
196
|
+
}
|
|
197
|
+
//# sourceMappingURL=help.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"help.js","sourceRoot":"","sources":["../../src/ui/help.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export declare function visibleWidth(text: string): number;
|
|
2
|
+
export declare function padVisible(text: string, width: number): string;
|
|
3
|
+
export declare function truncate(text: string, max: number): string;
|
|
4
|
+
export declare function renderTable(headers: string[], rows: string[][]): string;
|
package/dist/ui/table.js
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
export function visibleWidth(text) {
|
|
2
|
+
return text.replace(/\u001b\[[0-9;]*m/g, "").length;
|
|
3
|
+
}
|
|
4
|
+
export function padVisible(text, width) {
|
|
5
|
+
const pad = Math.max(0, width - visibleWidth(text));
|
|
6
|
+
return `${text}${" ".repeat(pad)}`;
|
|
7
|
+
}
|
|
8
|
+
export function truncate(text, max) {
|
|
9
|
+
if (visibleWidth(text) <= max)
|
|
10
|
+
return text;
|
|
11
|
+
if (max <= 1)
|
|
12
|
+
return "…";
|
|
13
|
+
return `${text.replace(/\u001b\[[0-9;]*m/g, "").slice(0, Math.max(0, max - 1))}…`;
|
|
14
|
+
}
|
|
15
|
+
export function renderTable(headers, rows) {
|
|
16
|
+
if (rows.length === 0) {
|
|
17
|
+
return `${headers.join(" ")}\n (none)`;
|
|
18
|
+
}
|
|
19
|
+
const colCount = headers.length;
|
|
20
|
+
const budget = Math.max(60, (process.stdout.columns ?? 100) - 4);
|
|
21
|
+
const widths = headers.map((header, index) => {
|
|
22
|
+
const longest = Math.max(header.length, ...rows.map((row) => visibleWidth(row[index] ?? "")));
|
|
23
|
+
return Math.min(longest, index === colCount - 1 ? 80 : 36);
|
|
24
|
+
});
|
|
25
|
+
const total = widths.reduce((sum, width) => sum + width, 0) + (colCount - 1) * 3 + 4;
|
|
26
|
+
if (total > budget && widths.length > 0) {
|
|
27
|
+
const overflow = total - budget;
|
|
28
|
+
widths[widths.length - 1] = Math.max(16, widths[widths.length - 1] - overflow);
|
|
29
|
+
}
|
|
30
|
+
const top = `┌${widths.map((width) => "─".repeat(width + 2)).join("┬")}┐`;
|
|
31
|
+
const mid = `├${widths.map((width) => "─".repeat(width + 2)).join("┼")}┤`;
|
|
32
|
+
const bottom = `└${widths.map((width) => "─".repeat(width + 2)).join("┴")}┘`;
|
|
33
|
+
const formatRow = (cells) => {
|
|
34
|
+
const padded = cells.map((cell, index) => padVisible(truncate(cell ?? "", widths[index] ?? 0), widths[index] ?? 0));
|
|
35
|
+
return `│ ${padded.join(" │ ")} │`;
|
|
36
|
+
};
|
|
37
|
+
return [top, formatRow(headers), mid, ...rows.map(formatRow), bottom].join("\n");
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=table.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"table.js","sourceRoot":"","sources":["../../src/ui/table.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { styleText } from "node:util";
|
|
2
|
+
export declare function paint(style: Parameters<typeof styleText>[0], text: string): string;
|
|
3
|
+
export declare const theme: {
|
|
4
|
+
brand: (text: string) => string;
|
|
5
|
+
muted: (text: string) => string;
|
|
6
|
+
heading: (text: string) => string;
|
|
7
|
+
ok: (text: string) => string;
|
|
8
|
+
fail: (text: string) => string;
|
|
9
|
+
warn: (text: string) => string;
|
|
10
|
+
info: (text: string) => string;
|
|
11
|
+
label: (text: string) => string;
|
|
12
|
+
path: (text: string) => string;
|
|
13
|
+
};
|
|
14
|
+
export declare const VERSION = "0.1.0";
|