@ipul-labs/forge 1.16.8 → 1.17.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 +39 -21
- package/lib/bin/cli/analyze.d.ts +9 -0
- package/lib/bin/cli/analyze.d.ts.map +1 -0
- package/lib/bin/cli/analyze.js +491 -0
- package/lib/bin/cli/analyze.js.map +1 -0
- package/lib/bin/cli/apply.d.ts +2 -0
- package/lib/bin/cli/apply.d.ts.map +1 -0
- package/lib/bin/cli/apply.js +262 -0
- package/lib/bin/cli/apply.js.map +1 -0
- package/lib/bin/cli/cifix.d.ts +2 -0
- package/lib/bin/cli/cifix.d.ts.map +1 -0
- package/lib/bin/cli/cifix.js +310 -0
- package/lib/bin/cli/cifix.js.map +1 -0
- package/lib/bin/cli/close.d.ts +2 -0
- package/lib/bin/cli/close.d.ts.map +1 -0
- package/lib/bin/cli/close.js +113 -0
- package/lib/bin/cli/close.js.map +1 -0
- package/lib/bin/cli/createIssue.d.ts +2 -0
- package/lib/bin/cli/createIssue.d.ts.map +1 -0
- package/lib/bin/cli/createIssue.js +108 -0
- package/lib/bin/cli/createIssue.js.map +1 -0
- package/lib/bin/cli/doctor.d.ts +2 -0
- package/lib/bin/cli/doctor.d.ts.map +1 -0
- package/lib/bin/cli/doctor.js +145 -0
- package/lib/bin/cli/doctor.js.map +1 -0
- package/lib/bin/cli/init.d.ts +4 -0
- package/lib/bin/cli/init.d.ts.map +1 -0
- package/lib/bin/cli/init.js +288 -0
- package/lib/bin/cli/init.js.map +1 -0
- package/lib/bin/cli/ink.d.ts +23 -0
- package/lib/bin/cli/ink.d.ts.map +1 -0
- package/{bin → lib/bin}/cli/ink.js +18 -19
- package/lib/bin/cli/ink.js.map +1 -0
- package/lib/bin/cli/issue.d.ts +2 -0
- package/lib/bin/cli/issue.d.ts.map +1 -0
- package/lib/bin/cli/issue.js +114 -0
- package/lib/bin/cli/issue.js.map +1 -0
- package/lib/bin/cli/issues.d.ts +2 -0
- package/lib/bin/cli/issues.d.ts.map +1 -0
- package/lib/bin/cli/issues.js +149 -0
- package/lib/bin/cli/issues.js.map +1 -0
- package/lib/bin/cli/merge.d.ts +2 -0
- package/lib/bin/cli/merge.d.ts.map +1 -0
- package/lib/bin/cli/merge.js +162 -0
- package/lib/bin/cli/merge.js.map +1 -0
- package/lib/bin/cli/refine.d.ts +2 -0
- package/lib/bin/cli/refine.d.ts.map +1 -0
- package/lib/bin/cli/refine.js +249 -0
- package/lib/bin/cli/refine.js.map +1 -0
- package/lib/bin/cli/repl.d.ts +2 -0
- package/lib/bin/cli/repl.d.ts.map +1 -0
- package/lib/bin/cli/repl.js +309 -0
- package/lib/bin/cli/repl.js.map +1 -0
- package/lib/bin/cli/repos.d.ts +2 -0
- package/lib/bin/cli/repos.d.ts.map +1 -0
- package/lib/bin/cli/repos.js +86 -0
- package/lib/bin/cli/repos.js.map +1 -0
- package/lib/bin/cli/resolution.d.ts +2 -0
- package/lib/bin/cli/resolution.d.ts.map +1 -0
- package/lib/bin/cli/resolution.js +139 -0
- package/lib/bin/cli/resolution.js.map +1 -0
- package/lib/bin/cli/serverClient.d.ts +26 -0
- package/lib/bin/cli/serverClient.d.ts.map +1 -0
- package/lib/bin/cli/serverClient.js +111 -0
- package/lib/bin/cli/serverClient.js.map +1 -0
- package/lib/bin/cli/session.d.ts +8 -0
- package/lib/bin/cli/session.d.ts.map +1 -0
- package/lib/bin/cli/session.js +212 -0
- package/lib/bin/cli/session.js.map +1 -0
- package/lib/bin/cli/sessionStore.d.ts +69 -0
- package/lib/bin/cli/sessionStore.d.ts.map +1 -0
- package/lib/bin/cli/sessionStore.js +196 -0
- package/lib/bin/cli/sessionStore.js.map +1 -0
- package/lib/bin/cli/ship.d.ts +33 -0
- package/lib/bin/cli/ship.d.ts.map +1 -0
- package/lib/bin/cli/ship.js +737 -0
- package/lib/bin/cli/ship.js.map +1 -0
- package/lib/bin/cli/types.d.ts +59 -0
- package/lib/bin/cli/types.d.ts.map +1 -0
- package/lib/bin/cli/types.js +2 -0
- package/lib/bin/cli/types.js.map +1 -0
- package/lib/bin/cli/update.d.ts +2 -0
- package/lib/bin/cli/update.d.ts.map +1 -0
- package/lib/bin/cli/update.js +87 -0
- package/lib/bin/cli/update.js.map +1 -0
- package/lib/bin/cli/utils.d.ts +43 -0
- package/lib/bin/cli/utils.d.ts.map +1 -0
- package/lib/bin/cli/utils.js +171 -0
- package/lib/bin/cli/utils.js.map +1 -0
- package/lib/bin/cli/validate.d.ts +2 -0
- package/lib/bin/cli/validate.d.ts.map +1 -0
- package/lib/bin/cli/validate.js +283 -0
- package/lib/bin/cli/validate.js.map +1 -0
- package/lib/bin/cli/watch.d.ts +5 -0
- package/lib/bin/cli/watch.d.ts.map +1 -0
- package/lib/bin/cli/watch.js +263 -0
- package/lib/bin/cli/watch.js.map +1 -0
- package/lib/bin/forge-agent.d.ts +3 -0
- package/lib/bin/forge-agent.d.ts.map +1 -0
- package/{bin → lib/bin}/forge-agent.js +104 -105
- package/lib/bin/forge-agent.js.map +1 -0
- package/lib/server/forge/core/ForgeAgent.d.ts +260 -0
- package/lib/server/forge/core/ForgeAgent.d.ts.map +1 -0
- package/lib/server/forge/core/ForgeAgent.js +995 -0
- package/lib/server/forge/core/ForgeAgent.js.map +1 -0
- package/lib/server/forge/core/agentClient.d.ts +39 -0
- package/lib/server/forge/core/agentClient.d.ts.map +1 -0
- package/{server → lib/server}/forge/core/agentClient.js +7 -12
- package/lib/server/forge/core/agentClient.js.map +1 -0
- package/lib/server/forge/core/branchName.d.ts +20 -0
- package/lib/server/forge/core/branchName.d.ts.map +1 -0
- package/lib/server/forge/core/branchName.js +39 -0
- package/lib/server/forge/core/branchName.js.map +1 -0
- package/lib/server/forge/core/claudeClient.d.ts +60 -0
- package/lib/server/forge/core/claudeClient.d.ts.map +1 -0
- package/lib/server/forge/core/claudeClient.js +347 -0
- package/lib/server/forge/core/claudeClient.js.map +1 -0
- package/lib/server/forge/core/configStore.d.ts +76 -0
- package/lib/server/forge/core/configStore.d.ts.map +1 -0
- package/lib/server/forge/core/configStore.js +213 -0
- package/lib/server/forge/core/configStore.js.map +1 -0
- package/lib/server/forge/core/gitlabClient.d.ts +144 -0
- package/lib/server/forge/core/gitlabClient.d.ts.map +1 -0
- package/{server → lib/server}/forge/core/gitlabClient.js +98 -180
- package/lib/server/forge/core/gitlabClient.js.map +1 -0
- package/lib/server/forge/core/jobs.d.ts +67 -0
- package/lib/server/forge/core/jobs.d.ts.map +1 -0
- package/lib/server/forge/core/jobs.js +185 -0
- package/lib/server/forge/core/jobs.js.map +1 -0
- package/lib/server/forge/core/k8s.d.ts +18 -0
- package/lib/server/forge/core/k8s.d.ts.map +1 -0
- package/lib/server/forge/core/k8s.js +49 -0
- package/lib/server/forge/core/k8s.js.map +1 -0
- package/lib/server/forge/core/localRepo.d.ts +36 -0
- package/lib/server/forge/core/localRepo.d.ts.map +1 -0
- package/lib/server/forge/core/localRepo.js +165 -0
- package/lib/server/forge/core/localRepo.js.map +1 -0
- package/lib/server/forge/core/openclawClient.d.ts +61 -0
- package/lib/server/forge/core/openclawClient.d.ts.map +1 -0
- package/lib/server/forge/core/openclawClient.js +111 -0
- package/lib/server/forge/core/openclawClient.js.map +1 -0
- package/lib/server/forge/core/prompts.d.ts +96 -0
- package/lib/server/forge/core/prompts.d.ts.map +1 -0
- package/lib/server/forge/core/prompts.js +450 -0
- package/lib/server/forge/core/prompts.js.map +1 -0
- package/lib/server/forge/core/providers/azuredevops.d.ts +134 -0
- package/lib/server/forge/core/providers/azuredevops.d.ts.map +1 -0
- package/lib/server/forge/core/providers/azuredevops.js +360 -0
- package/lib/server/forge/core/providers/azuredevops.js.map +1 -0
- package/lib/server/forge/core/providers/base.d.ts +114 -0
- package/lib/server/forge/core/providers/base.d.ts.map +1 -0
- package/lib/server/forge/core/providers/base.js +98 -0
- package/lib/server/forge/core/providers/base.js.map +1 -0
- package/lib/server/forge/core/providers/github.d.ts +133 -0
- package/lib/server/forge/core/providers/github.d.ts.map +1 -0
- package/lib/server/forge/core/providers/github.js +307 -0
- package/lib/server/forge/core/providers/github.js.map +1 -0
- package/lib/server/forge/core/providers/gitlab.d.ts +144 -0
- package/lib/server/forge/core/providers/gitlab.d.ts.map +1 -0
- package/lib/server/forge/core/providers/gitlab.js +407 -0
- package/lib/server/forge/core/providers/gitlab.js.map +1 -0
- package/lib/server/forge/core/providers/index.d.ts +21 -0
- package/lib/server/forge/core/providers/index.d.ts.map +1 -0
- package/lib/server/forge/core/providers/index.js +43 -0
- package/lib/server/forge/core/providers/index.js.map +1 -0
- package/lib/server/forge/core/providers/types.d.ts +80 -0
- package/lib/server/forge/core/providers/types.d.ts.map +1 -0
- package/lib/server/forge/core/providers/types.js +2 -0
- package/lib/server/forge/core/providers/types.js.map +1 -0
- package/lib/server/forge/core/quotaClient.d.ts +48 -0
- package/lib/server/forge/core/quotaClient.d.ts.map +1 -0
- package/lib/server/forge/core/quotaClient.js +88 -0
- package/lib/server/forge/core/quotaClient.js.map +1 -0
- package/lib/server/forge/core/types.d.ts +160 -0
- package/lib/server/forge/core/types.d.ts.map +1 -0
- package/lib/server/forge/core/types.js +2 -0
- package/lib/server/forge/core/types.js.map +1 -0
- package/lib/server/forge/core/validator/attribute.d.ts +31 -0
- package/lib/server/forge/core/validator/attribute.d.ts.map +1 -0
- package/lib/server/forge/core/validator/attribute.js +82 -0
- package/lib/server/forge/core/validator/attribute.js.map +1 -0
- package/lib/server/forge/core/validator/clone.d.ts +14 -0
- package/lib/server/forge/core/validator/clone.d.ts.map +1 -0
- package/lib/server/forge/core/validator/clone.js +99 -0
- package/lib/server/forge/core/validator/clone.js.map +1 -0
- package/lib/server/forge/core/validator/cmd.d.ts +23 -0
- package/lib/server/forge/core/validator/cmd.d.ts.map +1 -0
- package/lib/server/forge/core/validator/cmd.js +87 -0
- package/lib/server/forge/core/validator/cmd.js.map +1 -0
- package/lib/server/forge/core/validator/fs.d.ts +5 -0
- package/lib/server/forge/core/validator/fs.d.ts.map +1 -0
- package/{server → lib/server}/forge/core/validator/fs.js +8 -3
- package/lib/server/forge/core/validator/fs.js.map +1 -0
- package/lib/server/forge/core/validator/overlay.d.ts +13 -0
- package/lib/server/forge/core/validator/overlay.d.ts.map +1 -0
- package/lib/server/forge/core/validator/overlay.js +53 -0
- package/lib/server/forge/core/validator/overlay.js.map +1 -0
- package/lib/server/forge/core/validator/projectType.d.ts +20 -0
- package/lib/server/forge/core/validator/projectType.d.ts.map +1 -0
- package/lib/server/forge/core/validator/projectType.js +94 -0
- package/lib/server/forge/core/validator/projectType.js.map +1 -0
- package/lib/server/forge/core/validator/runners/go.d.ts +21 -0
- package/lib/server/forge/core/validator/runners/go.d.ts.map +1 -0
- package/lib/server/forge/core/validator/runners/go.js +99 -0
- package/lib/server/forge/core/validator/runners/go.js.map +1 -0
- package/lib/server/forge/core/validator/runners/node.d.ts +12 -0
- package/lib/server/forge/core/validator/runners/node.d.ts.map +1 -0
- package/lib/server/forge/core/validator/runners/node.js +75 -0
- package/lib/server/forge/core/validator/runners/node.js.map +1 -0
- package/lib/server/forge/core/validator/tdd.d.ts +30 -0
- package/lib/server/forge/core/validator/tdd.d.ts.map +1 -0
- package/lib/server/forge/core/validator/tdd.js +96 -0
- package/lib/server/forge/core/validator/tdd.js.map +1 -0
- package/lib/server/forge/core/validator.d.ts +58 -0
- package/lib/server/forge/core/validator.d.ts.map +1 -0
- package/lib/server/forge/core/validator.js +150 -0
- package/lib/server/forge/core/validator.js.map +1 -0
- package/lib/server/forge/routes.d.ts +22 -0
- package/lib/server/forge/routes.d.ts.map +1 -0
- package/lib/server/forge/routes.js +984 -0
- package/lib/server/forge/routes.js.map +1 -0
- package/lib/server.d.ts +2 -0
- package/lib/server.d.ts.map +1 -0
- package/lib/server.js +52 -0
- package/lib/server.js.map +1 -0
- package/lib/shared/events.d.ts +12 -0
- package/lib/shared/events.d.ts.map +1 -0
- package/lib/shared/events.js +12 -0
- package/lib/shared/events.js.map +1 -0
- package/package.json +15 -13
- package/scripts/fix-shebang.cjs +10 -0
- package/bin/cli/analyze.js +0 -516
- package/bin/cli/apply.js +0 -264
- package/bin/cli/cifix.js +0 -300
- package/bin/cli/close.js +0 -125
- package/bin/cli/createIssue.js +0 -112
- package/bin/cli/doctor.js +0 -161
- package/bin/cli/init.js +0 -306
- package/bin/cli/issue.js +0 -116
- package/bin/cli/issues.js +0 -155
- package/bin/cli/merge.js +0 -175
- package/bin/cli/refine.js +0 -253
- package/bin/cli/repl.js +0 -301
- package/bin/cli/repos.js +0 -91
- package/bin/cli/resolution.js +0 -126
- package/bin/cli/session.js +0 -230
- package/bin/cli/sessionStore.js +0 -211
- package/bin/cli/ship.js +0 -762
- package/bin/cli/update.js +0 -95
- package/bin/cli/utils.js +0 -145
- package/bin/cli/validate.js +0 -280
- package/bin/cli/watch.js +0 -274
- package/server/forge/core/ForgeAgent.js +0 -1179
- package/server/forge/core/ForgeAgent.test.js +0 -179
- package/server/forge/core/branchName.js +0 -41
- package/server/forge/core/claudeClient.js +0 -378
- package/server/forge/core/configStore.js +0 -229
- package/server/forge/core/configStore.test.js +0 -89
- package/server/forge/core/jobs.js +0 -180
- package/server/forge/core/k8s.js +0 -54
- package/server/forge/core/localRepo.js +0 -163
- package/server/forge/core/openclawClient.js +0 -125
- package/server/forge/core/prompts.js +0 -483
- package/server/forge/core/prompts.test.js +0 -219
- package/server/forge/core/providers/azuredevops.js +0 -409
- package/server/forge/core/providers/base.js +0 -208
- package/server/forge/core/providers/github.js +0 -348
- package/server/forge/core/providers/gitlab.js +0 -529
- package/server/forge/core/providers/index.js +0 -47
- package/server/forge/core/quotaClient.js +0 -101
- package/server/forge/core/validator/attribute.js +0 -84
- package/server/forge/core/validator/clone.js +0 -116
- package/server/forge/core/validator/cmd.js +0 -98
- package/server/forge/core/validator/overlay.js +0 -52
- package/server/forge/core/validator/projectType.js +0 -87
- package/server/forge/core/validator/runners/go.js +0 -107
- package/server/forge/core/validator/runners/node.js +0 -84
- package/server/forge/core/validator/tdd.js +0 -105
- package/server/forge/core/validator.js +0 -167
- package/server/forge/routes.js +0 -1027
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI → Server API client.
|
|
3
|
+
*
|
|
4
|
+
* Tries the running Forge server first. If the server is unreachable,
|
|
5
|
+
* returns { available: false } so callers can fall back to direct
|
|
6
|
+
* ForgeAgent calls (offline mode).
|
|
7
|
+
*
|
|
8
|
+
* Every method mirrors a server endpoint. SSE-streaming endpoints
|
|
9
|
+
* (analyze, refine, ci-fix, validate) return an async iterator of
|
|
10
|
+
* parsed events plus the jobId so the caller can cancel.
|
|
11
|
+
*/
|
|
12
|
+
const DIM = "\x1b[2m";
|
|
13
|
+
const RESET = "\x1b[0m";
|
|
14
|
+
const GREEN = "\x1b[32m";
|
|
15
|
+
const YELLOW = "\x1b[33m";
|
|
16
|
+
function baseUrl() {
|
|
17
|
+
const port = process.env.PORT ?? 5001;
|
|
18
|
+
return `http://localhost:${port}/api/forge`;
|
|
19
|
+
}
|
|
20
|
+
function headers() {
|
|
21
|
+
const token = process.env.FORGE_TOKEN;
|
|
22
|
+
return {
|
|
23
|
+
"Content-Type": "application/json",
|
|
24
|
+
...(token ? { Authorization: `Bearer ${token}` } : {}),
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
export const SERVER_MODE = `${GREEN}●${RESET} ${DIM}server${RESET}`;
|
|
28
|
+
export const LOCAL_MODE = `${YELLOW}●${RESET} ${DIM}local${RESET}`;
|
|
29
|
+
export async function isServerAvailable() {
|
|
30
|
+
try {
|
|
31
|
+
const res = await fetch(`${baseUrl()}/status`, {
|
|
32
|
+
headers: headers(),
|
|
33
|
+
signal: AbortSignal.timeout(2000),
|
|
34
|
+
});
|
|
35
|
+
return res.ok;
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
export async function postJson(path, body = {}) {
|
|
42
|
+
const res = await fetch(`${baseUrl()}${path}`, {
|
|
43
|
+
method: "POST",
|
|
44
|
+
headers: headers(),
|
|
45
|
+
body: JSON.stringify(body),
|
|
46
|
+
});
|
|
47
|
+
if (!res.ok) {
|
|
48
|
+
const err = (await res.json().catch(() => ({})));
|
|
49
|
+
throw new Error(err.error || `Server returned ${res.status}`);
|
|
50
|
+
}
|
|
51
|
+
return res.json();
|
|
52
|
+
}
|
|
53
|
+
export async function getJson(path) {
|
|
54
|
+
const res = await fetch(`${baseUrl()}${path}`, { headers: headers() });
|
|
55
|
+
if (!res.ok) {
|
|
56
|
+
const err = (await res.json().catch(() => ({})));
|
|
57
|
+
throw new Error(err.error || `Server returned ${res.status}`);
|
|
58
|
+
}
|
|
59
|
+
return res.json();
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Start a job-based SSE stream. Returns { jobId, events } where events
|
|
63
|
+
* is an async generator yielding parsed event objects.
|
|
64
|
+
*/
|
|
65
|
+
export function streamJob(path, body = {}) {
|
|
66
|
+
const token = process.env.FORGE_TOKEN ?? "";
|
|
67
|
+
let jobId = null;
|
|
68
|
+
const events = (async function* () {
|
|
69
|
+
const startRes = await fetch(`${baseUrl()}${path}`, {
|
|
70
|
+
method: "POST",
|
|
71
|
+
headers: headers(),
|
|
72
|
+
body: JSON.stringify(body),
|
|
73
|
+
});
|
|
74
|
+
if (!startRes.ok) {
|
|
75
|
+
const err = (await startRes.json().catch(() => ({})));
|
|
76
|
+
throw new Error(err.error || `Server returned ${startRes.status}`);
|
|
77
|
+
}
|
|
78
|
+
const { jobId: id } = (await startRes.json());
|
|
79
|
+
jobId = id;
|
|
80
|
+
const streamUrl = `${baseUrl()}/jobs/${id}/stream?token=${encodeURIComponent(token)}`;
|
|
81
|
+
const streamRes = await fetch(streamUrl);
|
|
82
|
+
if (!streamRes.ok)
|
|
83
|
+
throw new Error(`Stream failed: ${streamRes.status}`);
|
|
84
|
+
const reader = streamRes.body.getReader();
|
|
85
|
+
const decoder = new TextDecoder();
|
|
86
|
+
let buffer = "";
|
|
87
|
+
while (true) {
|
|
88
|
+
const { done, value } = await reader.read();
|
|
89
|
+
if (done)
|
|
90
|
+
break;
|
|
91
|
+
buffer += decoder.decode(value, { stream: true });
|
|
92
|
+
let nl;
|
|
93
|
+
while ((nl = buffer.indexOf("\n\n")) !== -1) {
|
|
94
|
+
const chunk = buffer.slice(0, nl).trim();
|
|
95
|
+
buffer = buffer.slice(nl + 2);
|
|
96
|
+
if (!chunk.startsWith("data: "))
|
|
97
|
+
continue;
|
|
98
|
+
const json = chunk.slice(6);
|
|
99
|
+
try {
|
|
100
|
+
const evt = JSON.parse(json);
|
|
101
|
+
yield evt;
|
|
102
|
+
if (evt.type === "done" || evt.type === "error" || evt.type === "cancelled")
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
catch { }
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
})();
|
|
109
|
+
return { get jobId() { return jobId; }, events };
|
|
110
|
+
}
|
|
111
|
+
//# sourceMappingURL=serverClient.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"serverClient.js","sourceRoot":"","sources":["../../../bin/cli/serverClient.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAIH,MAAM,GAAG,GAAG,SAAS,CAAC;AACtB,MAAM,KAAK,GAAG,SAAS,CAAC;AACxB,MAAM,KAAK,GAAG,UAAU,CAAC;AACzB,MAAM,MAAM,GAAG,UAAU,CAAC;AAE1B,SAAS,OAAO;IACf,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,IAAI,CAAC;IACtC,OAAO,oBAAoB,IAAI,YAAY,CAAC;AAC7C,CAAC;AAED,SAAS,OAAO;IACf,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC;IACtC,OAAO;QACN,cAAc,EAAE,kBAAkB;QAClC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,UAAU,KAAK,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACtD,CAAC;AACH,CAAC;AAED,MAAM,CAAC,MAAM,WAAW,GAAG,GAAG,KAAK,IAAI,KAAK,IAAI,GAAG,SAAS,KAAK,EAAE,CAAC;AACpE,MAAM,CAAC,MAAM,UAAU,GAAG,GAAG,MAAM,IAAI,KAAK,IAAI,GAAG,QAAQ,KAAK,EAAE,CAAC;AAEnE,MAAM,CAAC,KAAK,UAAU,iBAAiB;IACtC,IAAI,CAAC;QACJ,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,OAAO,EAAE,SAAS,EAAE;YAC9C,OAAO,EAAE,OAAO,EAAE;YAClB,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC;SACjC,CAAC,CAAC;QACH,OAAO,GAAG,CAAC,EAAE,CAAC;IACf,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,KAAK,CAAC;IACd,CAAC;AACF,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,IAAY,EAAE,OAAgC,EAAE;IAC9E,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,OAAO,EAAE,GAAG,IAAI,EAAE,EAAE;QAC9C,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,OAAO,EAAE;QAClB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;KAC1B,CAAC,CAAC;IACH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACb,MAAM,GAAG,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAuB,CAAC;QACvE,MAAM,IAAI,KAAK,CAAC,GAAG,CAAC,KAAK,IAAI,mBAAmB,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;IAC/D,CAAC;IACD,OAAO,GAAG,CAAC,IAAI,EAAE,CAAC;AACnB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,IAAY;IACzC,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,OAAO,EAAE,GAAG,IAAI,EAAE,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE,CAAC,CAAC;IACvE,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACb,MAAM,GAAG,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAuB,CAAC;QACvE,MAAM,IAAI,KAAK,CAAC,GAAG,CAAC,KAAK,IAAI,mBAAmB,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;IAC/D,CAAC;IACD,OAAO,GAAG,CAAC,IAAI,EAAE,CAAC;AACnB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,SAAS,CAAC,IAAY,EAAE,OAAgC,EAAE;IACzE,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,EAAE,CAAC;IAC5C,IAAI,KAAK,GAAkB,IAAI,CAAC;IAEhC,MAAM,MAAM,GAAG,CAAC,KAAK,SAAS,CAAC;QAC9B,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,OAAO,EAAE,GAAG,IAAI,EAAE,EAAE;YACnD,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,OAAO,EAAE;YAClB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;SAC1B,CAAC,CAAC;QACH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YAClB,MAAM,GAAG,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAuB,CAAC;YAC5E,MAAM,IAAI,KAAK,CAAC,GAAG,CAAC,KAAK,IAAI,mBAAmB,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;QACpE,CAAC;QACD,MAAM,EAAE,KAAK,EAAE,EAAE,EAAE,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAsB,CAAC;QACnE,KAAK,GAAG,EAAE,CAAC;QAEX,MAAM,SAAS,GAAG,GAAG,OAAO,EAAE,SAAS,EAAE,iBAAiB,kBAAkB,CAAC,KAAK,CAAC,EAAE,CAAC;QACtF,MAAM,SAAS,GAAG,MAAM,KAAK,CAAC,SAAS,CAAC,CAAC;QACzC,IAAI,CAAC,SAAS,CAAC,EAAE;YAAE,MAAM,IAAI,KAAK,CAAC,kBAAkB,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC;QAEzE,MAAM,MAAM,GAAG,SAAS,CAAC,IAAK,CAAC,SAAS,EAAE,CAAC;QAC3C,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAC;QAClC,IAAI,MAAM,GAAG,EAAE,CAAC;QAEhB,OAAO,IAAI,EAAE,CAAC;YACb,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;YAC5C,IAAI,IAAI;gBAAE,MAAM;YAChB,MAAM,IAAI,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;YAElD,IAAI,EAAU,CAAC;YACf,OAAO,CAAC,EAAE,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC;gBAC7C,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;gBACzC,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;gBAC9B,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,QAAQ,CAAC;oBAAE,SAAS;gBAC1C,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;gBAC5B,IAAI,CAAC;oBACJ,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAe,CAAC;oBAC3C,MAAM,GAAG,CAAC;oBACV,IAAI,GAAG,CAAC,IAAI,KAAK,MAAM,IAAI,GAAG,CAAC,IAAI,KAAK,OAAO,IAAI,GAAG,CAAC,IAAI,KAAK,WAAW;wBAAE,OAAO;gBACrF,CAAC;gBAAC,MAAM,CAAC,CAAA,CAAC;YACX,CAAC;QACF,CAAC;IACF,CAAC,CAAC,EAAE,CAAC;IAEL,OAAO,EAAE,IAAI,KAAK,KAAK,OAAO,KAAK,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC;AAClD,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export declare function cmdSession(argv: string[]): Promise<void>;
|
|
2
|
+
/**
|
|
3
|
+
* Top-level `forge show [<iid>]` — re-renders the cached analysis from
|
|
4
|
+
* the session through the same Ink view as live analyze. Resolves <iid> via
|
|
5
|
+
* positional arg or HEAD pointer.
|
|
6
|
+
*/
|
|
7
|
+
export declare function cmdShow(argv: string[]): Promise<void>;
|
|
8
|
+
//# sourceMappingURL=session.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../../bin/cli/session.ts"],"names":[],"mappings":"AAgNA,wBAAsB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,iBAQ9C;AAED;;;;GAIG;AACH,wBAAsB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,iBA+B3C"}
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
import { h, Box, Text, runApp } from "./ink.js";
|
|
2
|
+
import { getFlag } from "./utils.js";
|
|
3
|
+
import { cleanAll, cleanSession, getHead, listSessions, readAnalysis, readState, resolveSessionTarget, sessionDir, } from "./sessionStore.js";
|
|
4
|
+
function relTime(iso) {
|
|
5
|
+
if (!iso)
|
|
6
|
+
return "";
|
|
7
|
+
const ms = Date.now() - new Date(iso).getTime();
|
|
8
|
+
if (Number.isNaN(ms) || ms < 0)
|
|
9
|
+
return "";
|
|
10
|
+
const s = Math.floor(ms / 1000);
|
|
11
|
+
if (s < 60)
|
|
12
|
+
return `${s}s ago`;
|
|
13
|
+
const m = Math.floor(s / 60);
|
|
14
|
+
if (m < 60)
|
|
15
|
+
return `${m}m ago`;
|
|
16
|
+
const h = Math.floor(m / 60);
|
|
17
|
+
if (h < 24)
|
|
18
|
+
return `${h}h ago`;
|
|
19
|
+
return `${Math.floor(h / 24)}d ago`;
|
|
20
|
+
}
|
|
21
|
+
function SessionsTable({ sessions, head }) {
|
|
22
|
+
if (sessions.length === 0) {
|
|
23
|
+
return h `<${Box} flexDirection="column">
|
|
24
|
+
<${Text} dimColor>No sessions yet.</>
|
|
25
|
+
<${Text}>${"Run: forge analyze <iid>"}</>
|
|
26
|
+
</>`;
|
|
27
|
+
}
|
|
28
|
+
const rows = sessions.map((s) => {
|
|
29
|
+
const isHead = head && head.repo === s.repo && head.iid === s.iid;
|
|
30
|
+
return {
|
|
31
|
+
marker: isHead ? "*" : " ",
|
|
32
|
+
ref: `${s.repo}#${s.iid}`,
|
|
33
|
+
phase: s.phase ?? "?",
|
|
34
|
+
when: relTime(s.updatedAt),
|
|
35
|
+
};
|
|
36
|
+
});
|
|
37
|
+
const wRef = Math.max(3, ...rows.map((r) => r.ref.length));
|
|
38
|
+
const wPhase = Math.max(5, ...rows.map((r) => r.phase.length));
|
|
39
|
+
return h `<${Box} flexDirection="column" marginTop=${1}>
|
|
40
|
+
${rows.map((r, i) => h `<${Box} key=${i}>
|
|
41
|
+
<${Text} color=${r.marker === "*" ? "green" : undefined}> ${r.marker}</>
|
|
42
|
+
<${Box} width=${wRef + 2}><${Text}> ${r.ref}</></>
|
|
43
|
+
<${Box} width=${wPhase + 2}><${Text} color="yellow">${r.phase}</></>
|
|
44
|
+
<${Text} dimColor>${r.when}</>
|
|
45
|
+
</>`)}
|
|
46
|
+
<${Box} marginTop=${1}>
|
|
47
|
+
<${Text} dimColor>${"* HEAD — commands without <iid> resume here"}</>
|
|
48
|
+
</>
|
|
49
|
+
</>`;
|
|
50
|
+
}
|
|
51
|
+
function SessionDetail({ state, analysisSummary }) {
|
|
52
|
+
return h `<${Box} flexDirection="column">
|
|
53
|
+
<${Box}>
|
|
54
|
+
<${Text} color="yellow">Session </>
|
|
55
|
+
<${Text}>${state.repo}#${state.iid}</>
|
|
56
|
+
</>
|
|
57
|
+
<${Box}>
|
|
58
|
+
<${Text} color="yellow">Phase </>
|
|
59
|
+
<${Text}>${state.phase ?? "?"}</>
|
|
60
|
+
</>
|
|
61
|
+
${state.primary
|
|
62
|
+
? h `<${Box}>
|
|
63
|
+
<${Text} color="yellow">Primary </>
|
|
64
|
+
<${Text}>${state.primary}</>
|
|
65
|
+
</>`
|
|
66
|
+
: null}
|
|
67
|
+
${state.secondaries?.length
|
|
68
|
+
? h `<${Box}>
|
|
69
|
+
<${Text} color="yellow">Secondary</>
|
|
70
|
+
<${Text}> ${state.secondaries.join(", ")}</>
|
|
71
|
+
</>`
|
|
72
|
+
: null}
|
|
73
|
+
${state.branch
|
|
74
|
+
? h `<${Box}>
|
|
75
|
+
<${Text} color="yellow">Branch </>
|
|
76
|
+
<${Text}>${state.branch}</>
|
|
77
|
+
</>`
|
|
78
|
+
: null}
|
|
79
|
+
${state.mrIid
|
|
80
|
+
? h `<${Box}>
|
|
81
|
+
<${Text} color="yellow">MR </>
|
|
82
|
+
<${Text}>!${state.mrIid}</>
|
|
83
|
+
</>`
|
|
84
|
+
: null}
|
|
85
|
+
${state.lastError
|
|
86
|
+
? h `<${Box}>
|
|
87
|
+
<${Text} color="red">Error </>
|
|
88
|
+
<${Text}>${state.lastError}</>
|
|
89
|
+
</>`
|
|
90
|
+
: null}
|
|
91
|
+
<${Box} marginTop=${1}>
|
|
92
|
+
<${Text} dimColor>${`Created ${relTime(state.createdAt)} · Updated ${relTime(state.updatedAt)}`}</>
|
|
93
|
+
</>
|
|
94
|
+
${analysisSummary
|
|
95
|
+
? h `<${Box} flexDirection="column" marginTop=${1}>
|
|
96
|
+
<${Text} dimColor>${"Cached analysis:"}</>
|
|
97
|
+
<${Text}>${` ${analysisSummary.changes} change(s) · ${analysisSummary.repos} repo(s) · ${analysisSummary.mrTitle ?? "(no proposed title)"}`}</>
|
|
98
|
+
</>`
|
|
99
|
+
: h `<${Box} marginTop=${1}>
|
|
100
|
+
<${Text} dimColor>${"No cached analysis on disk."}</>
|
|
101
|
+
</>`}
|
|
102
|
+
</>`;
|
|
103
|
+
}
|
|
104
|
+
async function listCommand(argv) {
|
|
105
|
+
const json = argv.includes("--json");
|
|
106
|
+
const sessions = await listSessions();
|
|
107
|
+
if (json) {
|
|
108
|
+
process.stdout.write(`${JSON.stringify(sessions, null, 2)}\n`);
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
const head = await getHead();
|
|
112
|
+
await runApp(h `<${SessionsTable} sessions=${sessions} head=${head} />`);
|
|
113
|
+
}
|
|
114
|
+
async function showCommand(argv) {
|
|
115
|
+
const json = argv.includes("--json");
|
|
116
|
+
const explicitIid = Number(argv[2]);
|
|
117
|
+
const explicitRepo = getFlag(argv, "--repo");
|
|
118
|
+
const target = await resolveSessionTarget({
|
|
119
|
+
explicitIid: Number.isInteger(explicitIid) && explicitIid > 0 ? explicitIid : null,
|
|
120
|
+
explicitRepo,
|
|
121
|
+
});
|
|
122
|
+
if (!target?.repo || !target?.iid) {
|
|
123
|
+
console.error("No session target. Pass an <iid>, set --repo, or run analyze first.");
|
|
124
|
+
process.exit(1);
|
|
125
|
+
}
|
|
126
|
+
const state = await readState(target.repo, target.iid);
|
|
127
|
+
if (!state) {
|
|
128
|
+
console.error(`No session at ${sessionDir(target.repo, target.iid)}`);
|
|
129
|
+
process.exit(1);
|
|
130
|
+
}
|
|
131
|
+
const analysis = await readAnalysis(target.repo, target.iid);
|
|
132
|
+
if (json) {
|
|
133
|
+
process.stdout.write(`${JSON.stringify({ state, analysis }, null, 2)}\n`);
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
const summary = analysis
|
|
137
|
+
? {
|
|
138
|
+
changes: analysis.changes?.length ?? 0,
|
|
139
|
+
repos: analysis.repos?.length ?? 0,
|
|
140
|
+
mrTitle: analysis.mrTitle ?? null,
|
|
141
|
+
}
|
|
142
|
+
: null;
|
|
143
|
+
await runApp(h `<${SessionDetail} state=${state} analysisSummary=${summary} />`);
|
|
144
|
+
}
|
|
145
|
+
async function cleanCommand(argv) {
|
|
146
|
+
if (argv.includes("--all")) {
|
|
147
|
+
await cleanAll();
|
|
148
|
+
process.stderr.write(`✓ Removed all sessions\n`);
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
const explicitIid = Number(argv[2]);
|
|
152
|
+
const explicitRepo = getFlag(argv, "--repo");
|
|
153
|
+
const target = await resolveSessionTarget({
|
|
154
|
+
explicitIid: Number.isInteger(explicitIid) && explicitIid > 0 ? explicitIid : null,
|
|
155
|
+
explicitRepo,
|
|
156
|
+
});
|
|
157
|
+
if (!target?.repo || !target?.iid) {
|
|
158
|
+
console.error("No session target. Pass an <iid>, set --repo, or use --all to wipe everything.");
|
|
159
|
+
process.exit(1);
|
|
160
|
+
}
|
|
161
|
+
const removed = await cleanSession(target.repo, target.iid);
|
|
162
|
+
if (removed)
|
|
163
|
+
process.stderr.write(`✓ Removed ${target.repo}#${target.iid}\n`);
|
|
164
|
+
else
|
|
165
|
+
process.stderr.write(`Nothing to remove at ${target.repo}#${target.iid}\n`);
|
|
166
|
+
}
|
|
167
|
+
export async function cmdSession(argv) {
|
|
168
|
+
const sub = argv[1] ?? "list";
|
|
169
|
+
if (sub === "list" || sub === "ls")
|
|
170
|
+
return listCommand(argv);
|
|
171
|
+
if (sub === "show")
|
|
172
|
+
return showCommand(argv);
|
|
173
|
+
if (sub === "clean" || sub === "rm")
|
|
174
|
+
return cleanCommand(argv);
|
|
175
|
+
console.error(`Unknown subcommand: ${sub}`);
|
|
176
|
+
console.error("Subcommands: list, show, clean");
|
|
177
|
+
process.exit(1);
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Top-level `forge show [<iid>]` — re-renders the cached analysis from
|
|
181
|
+
* the session through the same Ink view as live analyze. Resolves <iid> via
|
|
182
|
+
* positional arg or HEAD pointer.
|
|
183
|
+
*/
|
|
184
|
+
export async function cmdShow(argv) {
|
|
185
|
+
const explicitIid = Number(argv[1]);
|
|
186
|
+
const explicitRepo = getFlag(argv, "--repo");
|
|
187
|
+
const json = argv.includes("--json");
|
|
188
|
+
const target = await resolveSessionTarget({
|
|
189
|
+
explicitIid: Number.isInteger(explicitIid) && explicitIid > 0 ? explicitIid : null,
|
|
190
|
+
explicitRepo,
|
|
191
|
+
});
|
|
192
|
+
if (!target?.repo || !target?.iid) {
|
|
193
|
+
console.error("No session target. Pass an <iid>, or run analyze first to seed HEAD.");
|
|
194
|
+
process.exit(1);
|
|
195
|
+
}
|
|
196
|
+
const analysis = await readAnalysis(target.repo, target.iid);
|
|
197
|
+
if (!analysis) {
|
|
198
|
+
console.error(`No cached analysis at ${sessionDir(target.repo, target.iid)}.\n` +
|
|
199
|
+
`Run: forge analyze ${target.iid}`);
|
|
200
|
+
process.exit(1);
|
|
201
|
+
}
|
|
202
|
+
if (json) {
|
|
203
|
+
process.stdout.write(`${JSON.stringify(analysis, null, 2)}\n`);
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
// Reuse analyze.js's ResultBlock by importing it lazily — keeps the
|
|
207
|
+
// dependency cycle simple (session.js depends on the analyze view, but
|
|
208
|
+
// analyze.js doesn't depend on session.js's UI).
|
|
209
|
+
const { renderCachedResult } = await import("./analyze.js");
|
|
210
|
+
await renderCachedResult(analysis);
|
|
211
|
+
}
|
|
212
|
+
//# sourceMappingURL=session.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session.js","sourceRoot":"","sources":["../../../bin/cli/session.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session store for the ship workflow.
|
|
3
|
+
*
|
|
4
|
+
* ~/.forge/sessions/<canonical-repo>/<iid>/
|
|
5
|
+
* analysis.json — last cached ForgeAgent.analyzeIssue result
|
|
6
|
+
* state.json — { phase, primary, secondaries, branch?, mrIid?, ... }
|
|
7
|
+
* events.ndjson — append-only log of every event we received
|
|
8
|
+
*
|
|
9
|
+
* ~/.forge/sessions/HEAD
|
|
10
|
+
* — single line: "<canonical-repo>/<iid>" of the most recently touched
|
|
11
|
+
* session. Used so subsequent commands without an explicit <iid> can
|
|
12
|
+
* resume the current unit of work, in the spirit of git's HEAD.
|
|
13
|
+
*
|
|
14
|
+
* Override the root with FORGE_SESSIONS_PATH (test isolation).
|
|
15
|
+
*/
|
|
16
|
+
import type { AnalysisResult, ForgeEvent } from "../../server/forge/core/types.ts";
|
|
17
|
+
import type { SessionState } from "./types.ts";
|
|
18
|
+
export declare const PHASES: Readonly<{
|
|
19
|
+
ANALYZED: "analyzed";
|
|
20
|
+
REFINED: "refined";
|
|
21
|
+
VALIDATED: "validated";
|
|
22
|
+
APPLIED: "applied";
|
|
23
|
+
WATCHING: "watching";
|
|
24
|
+
MERGED: "merged";
|
|
25
|
+
RESOLVED: "resolved";
|
|
26
|
+
CLOSED: "closed";
|
|
27
|
+
}>;
|
|
28
|
+
/**
|
|
29
|
+
* Resolve the on-disk directory for a session. Repo is canonicalised so
|
|
30
|
+
* "iplayulisten/web-app" and "gitlab:iplayulisten/web-app" map to the
|
|
31
|
+
* same folder.
|
|
32
|
+
*/
|
|
33
|
+
export declare function sessionDir(repo: string, iid: number | string): string;
|
|
34
|
+
export declare function writeAnalysis(repo: string, iid: number | string, analysis: AnalysisResult): Promise<void>;
|
|
35
|
+
export declare function readAnalysis(repo: string, iid: number | string): Promise<AnalysisResult | null>;
|
|
36
|
+
export declare function readState(repo: string, iid: number | string): Promise<SessionState | null>;
|
|
37
|
+
export declare function updateState(repo: string, iid: number | string, partial: Partial<SessionState>): Promise<SessionState>;
|
|
38
|
+
export declare function appendEvent(repo: string, iid: number | string, evt: ForgeEvent | Record<string, unknown>): Promise<void>;
|
|
39
|
+
export declare function setHead(repo: string, iid: number | string): Promise<void>;
|
|
40
|
+
/**
|
|
41
|
+
* Return { repo, iid } of the HEAD session, or null.
|
|
42
|
+
*/
|
|
43
|
+
export declare function getHead(): Promise<{
|
|
44
|
+
repo: string;
|
|
45
|
+
iid: number;
|
|
46
|
+
}>;
|
|
47
|
+
/**
|
|
48
|
+
* Walk the on-disk tree and return every session it finds. Sorted by
|
|
49
|
+
* updatedAt descending (most recent first).
|
|
50
|
+
*/
|
|
51
|
+
export declare function listSessions(): Promise<SessionState[]>;
|
|
52
|
+
export declare function cleanSession(repo: string, iid: number | string): Promise<boolean>;
|
|
53
|
+
export declare function cleanAll(): Promise<void>;
|
|
54
|
+
/**
|
|
55
|
+
* Resolve a session target from CLI argv. Honours an explicit positional iid
|
|
56
|
+
* or HEAD as fallback. Returns { repo, iid } or null.
|
|
57
|
+
*
|
|
58
|
+
* forge show → HEAD
|
|
59
|
+
* forge show 42 → primary repo + iid 42
|
|
60
|
+
* forge show 42 --repo X → repo X + iid 42
|
|
61
|
+
*/
|
|
62
|
+
export declare function resolveSessionTarget({ explicitIid, explicitRepo }: {
|
|
63
|
+
explicitIid: number | null;
|
|
64
|
+
explicitRepo: string | null | undefined;
|
|
65
|
+
}): Promise<{
|
|
66
|
+
repo: string;
|
|
67
|
+
iid: number;
|
|
68
|
+
}>;
|
|
69
|
+
//# sourceMappingURL=sessionStore.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sessionStore.d.ts","sourceRoot":"","sources":["../../../bin/cli/sessionStore.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAOH,OAAO,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,kCAAkC,CAAC;AACnF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C,eAAO,MAAM,MAAM;;;;;;;;;EASjB,CAAC;AASH;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,UAE5D;AAMD,wBAAsB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,QAAQ,EAAE,cAAc,iBAK/F;AAED,wBAAsB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAIrG;AAED,wBAAsB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAIhG;AAED,wBAAsB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,YAAY,CAAC,GAAG,OAAO,CAAC,YAAY,CAAC,CAc3H;AAED,wBAAsB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,EAAE,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,iBAQ9G;AAED,wBAAsB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,iBAQ/D;AAED;;GAEG;AACH,wBAAsB,OAAO;;;GAU5B;AAED;;;GAGG;AACH,wBAAsB,YAAY,4BAsCjC;AAUD,wBAAsB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,oBASpE;AAED,wBAAsB,QAAQ,kBAI7B;AAED;;;;;;;GAOG;AACH,wBAAsB,oBAAoB,CAAC,EAAE,WAAW,EAAE,YAAY,EAAE,EAAE;IAAE,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,YAAY,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAA;CAAE;;;GAWhJ"}
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session store for the ship workflow.
|
|
3
|
+
*
|
|
4
|
+
* ~/.forge/sessions/<canonical-repo>/<iid>/
|
|
5
|
+
* analysis.json — last cached ForgeAgent.analyzeIssue result
|
|
6
|
+
* state.json — { phase, primary, secondaries, branch?, mrIid?, ... }
|
|
7
|
+
* events.ndjson — append-only log of every event we received
|
|
8
|
+
*
|
|
9
|
+
* ~/.forge/sessions/HEAD
|
|
10
|
+
* — single line: "<canonical-repo>/<iid>" of the most recently touched
|
|
11
|
+
* session. Used so subsequent commands without an explicit <iid> can
|
|
12
|
+
* resume the current unit of work, in the spirit of git's HEAD.
|
|
13
|
+
*
|
|
14
|
+
* Override the root with FORGE_SESSIONS_PATH (test isolation).
|
|
15
|
+
*/
|
|
16
|
+
import { existsSync } from "node:fs";
|
|
17
|
+
import fs from "node:fs/promises";
|
|
18
|
+
import os from "node:os";
|
|
19
|
+
import path from "node:path";
|
|
20
|
+
import { canonicalRepoId } from "./utils.js";
|
|
21
|
+
export const PHASES = Object.freeze({
|
|
22
|
+
ANALYZED: "analyzed",
|
|
23
|
+
REFINED: "refined",
|
|
24
|
+
VALIDATED: "validated",
|
|
25
|
+
APPLIED: "applied",
|
|
26
|
+
WATCHING: "watching",
|
|
27
|
+
MERGED: "merged",
|
|
28
|
+
RESOLVED: "resolved",
|
|
29
|
+
CLOSED: "closed",
|
|
30
|
+
});
|
|
31
|
+
function rootDir() {
|
|
32
|
+
return (process.env.FORGE_SESSIONS_PATH ??
|
|
33
|
+
path.join(os.homedir(), ".forge", "sessions"));
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Resolve the on-disk directory for a session. Repo is canonicalised so
|
|
37
|
+
* "iplayulisten/web-app" and "gitlab:iplayulisten/web-app" map to the
|
|
38
|
+
* same folder.
|
|
39
|
+
*/
|
|
40
|
+
export function sessionDir(repo, iid) {
|
|
41
|
+
return path.join(rootDir(), canonicalRepoId(String(repo)), String(iid));
|
|
42
|
+
}
|
|
43
|
+
async function ensureDir(dir) {
|
|
44
|
+
await fs.mkdir(dir, { recursive: true, mode: 0o700 });
|
|
45
|
+
}
|
|
46
|
+
export async function writeAnalysis(repo, iid, analysis) {
|
|
47
|
+
const dir = sessionDir(repo, iid);
|
|
48
|
+
await ensureDir(dir);
|
|
49
|
+
const file = path.join(dir, "analysis.json");
|
|
50
|
+
await fs.writeFile(file, JSON.stringify(analysis, null, 2), { encoding: "utf8", mode: 0o600 });
|
|
51
|
+
}
|
|
52
|
+
export async function readAnalysis(repo, iid) {
|
|
53
|
+
const file = path.join(sessionDir(repo, iid), "analysis.json");
|
|
54
|
+
if (!existsSync(file))
|
|
55
|
+
return null;
|
|
56
|
+
return JSON.parse(await fs.readFile(file, "utf8"));
|
|
57
|
+
}
|
|
58
|
+
export async function readState(repo, iid) {
|
|
59
|
+
const file = path.join(sessionDir(repo, iid), "state.json");
|
|
60
|
+
if (!existsSync(file))
|
|
61
|
+
return null;
|
|
62
|
+
return JSON.parse(await fs.readFile(file, "utf8"));
|
|
63
|
+
}
|
|
64
|
+
export async function updateState(repo, iid, partial) {
|
|
65
|
+
const dir = sessionDir(repo, iid);
|
|
66
|
+
await ensureDir(dir);
|
|
67
|
+
const file = path.join(dir, "state.json");
|
|
68
|
+
const now = new Date().toISOString();
|
|
69
|
+
const prev = (await readState(repo, iid)) ?? {
|
|
70
|
+
repo: canonicalRepoId(String(repo)),
|
|
71
|
+
iid: Number(iid),
|
|
72
|
+
phase: "unknown",
|
|
73
|
+
createdAt: now,
|
|
74
|
+
};
|
|
75
|
+
const next = { ...prev, ...partial, updatedAt: now };
|
|
76
|
+
await fs.writeFile(file, JSON.stringify(next, null, 2), { encoding: "utf8", mode: 0o600 });
|
|
77
|
+
return next;
|
|
78
|
+
}
|
|
79
|
+
export async function appendEvent(repo, iid, evt) {
|
|
80
|
+
const dir = sessionDir(repo, iid);
|
|
81
|
+
await ensureDir(dir);
|
|
82
|
+
await fs.appendFile(path.join(dir, "events.ndjson"), `${JSON.stringify({ ts: new Date().toISOString(), ...evt })}\n`, "utf8");
|
|
83
|
+
}
|
|
84
|
+
export async function setHead(repo, iid) {
|
|
85
|
+
const root = rootDir();
|
|
86
|
+
await fs.mkdir(root, { recursive: true });
|
|
87
|
+
await fs.writeFile(path.join(root, "HEAD"), `${canonicalRepoId(String(repo))}/${iid}\n`, "utf8");
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Return { repo, iid } of the HEAD session, or null.
|
|
91
|
+
*/
|
|
92
|
+
export async function getHead() {
|
|
93
|
+
const file = path.join(rootDir(), "HEAD");
|
|
94
|
+
if (!existsSync(file))
|
|
95
|
+
return null;
|
|
96
|
+
const raw = (await fs.readFile(file, "utf8")).trim();
|
|
97
|
+
const lastSlash = raw.lastIndexOf("/");
|
|
98
|
+
if (lastSlash <= 0)
|
|
99
|
+
return null;
|
|
100
|
+
const repo = raw.slice(0, lastSlash);
|
|
101
|
+
const iid = Number(raw.slice(lastSlash + 1));
|
|
102
|
+
if (!Number.isInteger(iid) || iid <= 0)
|
|
103
|
+
return null;
|
|
104
|
+
return { repo, iid };
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Walk the on-disk tree and return every session it finds. Sorted by
|
|
108
|
+
* updatedAt descending (most recent first).
|
|
109
|
+
*/
|
|
110
|
+
export async function listSessions() {
|
|
111
|
+
const root = rootDir();
|
|
112
|
+
if (!existsSync(root))
|
|
113
|
+
return [];
|
|
114
|
+
const out = [];
|
|
115
|
+
const repoDirs = await safeReadDir(root);
|
|
116
|
+
for (const repoEntry of repoDirs) {
|
|
117
|
+
if (!repoEntry.isDirectory())
|
|
118
|
+
continue;
|
|
119
|
+
// Repos may be nested one level (e.g. "iplayulisten/web-app").
|
|
120
|
+
const repoLevel1 = path.join(root, repoEntry.name);
|
|
121
|
+
const repoSubdirs = await safeReadDir(repoLevel1);
|
|
122
|
+
for (const sub of repoSubdirs) {
|
|
123
|
+
if (!sub.isDirectory())
|
|
124
|
+
continue;
|
|
125
|
+
const candidatePath = path.join(repoLevel1, sub.name);
|
|
126
|
+
// Two layouts:
|
|
127
|
+
// a) repoLevel1/<iid>/state.json (single-segment repo)
|
|
128
|
+
// b) repoLevel1/<sub>/<iid>/state.json (two-segment repo)
|
|
129
|
+
if (existsSync(path.join(candidatePath, "state.json"))) {
|
|
130
|
+
const state = JSON.parse(await fs.readFile(path.join(candidatePath, "state.json"), "utf8"));
|
|
131
|
+
out.push(state);
|
|
132
|
+
continue;
|
|
133
|
+
}
|
|
134
|
+
const iidEntries = await safeReadDir(candidatePath);
|
|
135
|
+
for (const iidEntry of iidEntries) {
|
|
136
|
+
if (!iidEntry.isDirectory())
|
|
137
|
+
continue;
|
|
138
|
+
const stateFile = path.join(candidatePath, iidEntry.name, "state.json");
|
|
139
|
+
if (!existsSync(stateFile))
|
|
140
|
+
continue;
|
|
141
|
+
const state = JSON.parse(await fs.readFile(stateFile, "utf8"));
|
|
142
|
+
out.push(state);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
out.sort((a, b) => (b.updatedAt ?? "").localeCompare(a.updatedAt ?? ""));
|
|
147
|
+
return out;
|
|
148
|
+
}
|
|
149
|
+
async function safeReadDir(dir) {
|
|
150
|
+
try {
|
|
151
|
+
return await fs.readdir(dir, { withFileTypes: true });
|
|
152
|
+
}
|
|
153
|
+
catch {
|
|
154
|
+
return [];
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
export async function cleanSession(repo, iid) {
|
|
158
|
+
const dir = sessionDir(repo, iid);
|
|
159
|
+
if (!existsSync(dir))
|
|
160
|
+
return false;
|
|
161
|
+
await fs.rm(dir, { recursive: true, force: true });
|
|
162
|
+
const head = await getHead();
|
|
163
|
+
if (head && canonicalRepoId(head.repo) === canonicalRepoId(String(repo)) && head.iid === Number(iid)) {
|
|
164
|
+
await fs.rm(path.join(rootDir(), "HEAD"), { force: true });
|
|
165
|
+
}
|
|
166
|
+
return true;
|
|
167
|
+
}
|
|
168
|
+
export async function cleanAll() {
|
|
169
|
+
const root = rootDir();
|
|
170
|
+
if (!existsSync(root))
|
|
171
|
+
return;
|
|
172
|
+
await fs.rm(root, { recursive: true, force: true });
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Resolve a session target from CLI argv. Honours an explicit positional iid
|
|
176
|
+
* or HEAD as fallback. Returns { repo, iid } or null.
|
|
177
|
+
*
|
|
178
|
+
* forge show → HEAD
|
|
179
|
+
* forge show 42 → primary repo + iid 42
|
|
180
|
+
* forge show 42 --repo X → repo X + iid 42
|
|
181
|
+
*/
|
|
182
|
+
export async function resolveSessionTarget({ explicitIid, explicitRepo }) {
|
|
183
|
+
if (Number.isInteger(explicitIid) && explicitIid > 0) {
|
|
184
|
+
// repo defaults to HEAD's repo if available, else explicitRepo, else
|
|
185
|
+
// the configStore primary. Keeps `show 42` working when there's a
|
|
186
|
+
// prior HEAD that was on the same repo.
|
|
187
|
+
if (explicitRepo)
|
|
188
|
+
return { repo: explicitRepo, iid: explicitIid };
|
|
189
|
+
const head = await getHead();
|
|
190
|
+
if (head)
|
|
191
|
+
return { repo: head.repo, iid: explicitIid };
|
|
192
|
+
return { repo: null, iid: explicitIid };
|
|
193
|
+
}
|
|
194
|
+
return await getHead();
|
|
195
|
+
}
|
|
196
|
+
//# sourceMappingURL=sessionStore.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sessionStore.js","sourceRoot":"","sources":["../../../bin/cli/sessionStore.ts"],"names":[],"mappings":"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"}
|