@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,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* server/forge/core/jobs.js
|
|
3
|
+
*
|
|
4
|
+
* Unified in-memory job store with event buffering + multi-subscriber replay.
|
|
5
|
+
*
|
|
6
|
+
* Why this exists: SSE endpoints like refine / ci-fix / validate / analyze
|
|
7
|
+
* run a long task and stream events to one EventSource. If the browser
|
|
8
|
+
* reloads or React re-mounts the component, that stream dies. Before this
|
|
9
|
+
* module, the job also died — its state was deleted the moment the stream
|
|
10
|
+
* was consumed, so there was nothing to reconnect to.
|
|
11
|
+
*
|
|
12
|
+
* With this store:
|
|
13
|
+
* 1. `createJob(type, runner)` starts the runner immediately in the
|
|
14
|
+
* background and buffers every event it emits.
|
|
15
|
+
* 2. `subscribe(id, handler)` replays the buffer synchronously, then wires
|
|
16
|
+
* the handler to future events until the job is terminal.
|
|
17
|
+
* 3. A reconnecting client gets the full history on reconnect and then
|
|
18
|
+
* live events — identical to if it had been watching all along.
|
|
19
|
+
*
|
|
20
|
+
* Process-restart survival is out of scope for v1 (Map is in-memory only).
|
|
21
|
+
*/
|
|
22
|
+
import type { ForgeEvent, JobRecord, JobSnapshot } from "./types.ts";
|
|
23
|
+
/**
|
|
24
|
+
* Create and start a job. `runner` is an async function that receives
|
|
25
|
+
* `(send, signal)` — any value it returns is captured as `doneResult`.
|
|
26
|
+
* A terminal `done`, `error`, or `cancelled` event is emitted automatically
|
|
27
|
+
* when runner settles; runners must not emit those themselves.
|
|
28
|
+
*
|
|
29
|
+
* The `signal` is an `AbortSignal` that fires when a client calls `cancelJob`.
|
|
30
|
+
* Runners should forward it to any subprocess / fetch / SDK call that
|
|
31
|
+
* supports AbortSignal so the underlying work actually stops (and API/CLI
|
|
32
|
+
* costs aren't incurred for work the user no longer wants).
|
|
33
|
+
*/
|
|
34
|
+
interface CreateJobOptions {
|
|
35
|
+
idPrefix?: string;
|
|
36
|
+
onComplete?: (result: {
|
|
37
|
+
status: string;
|
|
38
|
+
result: unknown;
|
|
39
|
+
}) => void;
|
|
40
|
+
meta?: Record<string, unknown>;
|
|
41
|
+
}
|
|
42
|
+
export declare function createJob(type: string, runner: (send: (event: ForgeEvent) => void, signal: AbortSignal) => Promise<unknown>, { idPrefix, onComplete, meta }?: CreateJobOptions): string;
|
|
43
|
+
/**
|
|
44
|
+
* Cancel a running job. Aborts the signal, emits a terminal `cancelled`
|
|
45
|
+
* event, and marks the job non-running. No-op if the job is already
|
|
46
|
+
* terminal or doesn't exist — returns whether a cancel was actually issued.
|
|
47
|
+
*/
|
|
48
|
+
export declare function cancelJob(id: string): boolean;
|
|
49
|
+
export declare function getJob(id: string): JobRecord;
|
|
50
|
+
/**
|
|
51
|
+
* Replay buffered events to `handler`, then subscribe for live events until
|
|
52
|
+
* the job reaches terminal state. Returns an `unsubscribe` function, or
|
|
53
|
+
* `null` if the job doesn't exist.
|
|
54
|
+
*
|
|
55
|
+
* The terminal `done`/`error` event is part of the buffered replay — callers
|
|
56
|
+
* that want to end the response on terminal should check for it inside
|
|
57
|
+
* their handler.
|
|
58
|
+
*/
|
|
59
|
+
export declare function subscribe(id: string, handler: (event: ForgeEvent) => void): () => void;
|
|
60
|
+
/**
|
|
61
|
+
* Public status snapshot — safe to send to clients. Excludes the event
|
|
62
|
+
* buffer (potentially large) and subscribers (not serialisable).
|
|
63
|
+
*/
|
|
64
|
+
export declare function snapshot(id: string): JobSnapshot | null;
|
|
65
|
+
export declare function findActiveByMeta(key: string, value: unknown): JobSnapshot;
|
|
66
|
+
export {};
|
|
67
|
+
//# sourceMappingURL=jobs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jobs.d.ts","sourceRoot":"","sources":["../../../../server/forge/core/jobs.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAyBrE;;;;;;;;;;GAUG;AACH,UAAU,gBAAgB;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,CAAC,MAAM,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,OAAO,CAAA;KAAE,KAAK,IAAI,CAAC;IACnE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC/B;AAED,wBAAgB,SAAS,CACxB,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,EAAE,MAAM,EAAE,WAAW,KAAK,OAAO,CAAC,OAAO,CAAC,EACpF,EAAE,QAAe,EAAE,UAAU,EAAE,IAAI,EAAE,GAAE,gBAAqB,UAuD5D;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,EAAE,EAAE,MAAM,WAiBnC;AAED,wBAAgB,MAAM,CAAC,EAAE,EAAE,MAAM,aAEhC;AAED;;;;;;;;GAQG;AACH,wBAAgB,SAAS,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,cAczE;AAED;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI,CAavD;AAED,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,eAO3D"}
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* server/forge/core/jobs.js
|
|
3
|
+
*
|
|
4
|
+
* Unified in-memory job store with event buffering + multi-subscriber replay.
|
|
5
|
+
*
|
|
6
|
+
* Why this exists: SSE endpoints like refine / ci-fix / validate / analyze
|
|
7
|
+
* run a long task and stream events to one EventSource. If the browser
|
|
8
|
+
* reloads or React re-mounts the component, that stream dies. Before this
|
|
9
|
+
* module, the job also died — its state was deleted the moment the stream
|
|
10
|
+
* was consumed, so there was nothing to reconnect to.
|
|
11
|
+
*
|
|
12
|
+
* With this store:
|
|
13
|
+
* 1. `createJob(type, runner)` starts the runner immediately in the
|
|
14
|
+
* background and buffers every event it emits.
|
|
15
|
+
* 2. `subscribe(id, handler)` replays the buffer synchronously, then wires
|
|
16
|
+
* the handler to future events until the job is terminal.
|
|
17
|
+
* 3. A reconnecting client gets the full history on reconnect and then
|
|
18
|
+
* live events — identical to if it had been watching all along.
|
|
19
|
+
*
|
|
20
|
+
* Process-restart survival is out of scope for v1 (Map is in-memory only).
|
|
21
|
+
*/
|
|
22
|
+
const TTL_MS = 10 * 60 * 1000;
|
|
23
|
+
const SWEEP_INTERVAL_MS = 60 * 1000;
|
|
24
|
+
const jobs = new Map();
|
|
25
|
+
let sweeper = null;
|
|
26
|
+
function ensureSweeper() {
|
|
27
|
+
if (sweeper)
|
|
28
|
+
return;
|
|
29
|
+
sweeper = setInterval(() => {
|
|
30
|
+
const now = Date.now();
|
|
31
|
+
for (const [id, job] of jobs) {
|
|
32
|
+
if (job.expiresAt && job.expiresAt <= now && job.subscribers.size === 0) {
|
|
33
|
+
jobs.delete(id);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}, SWEEP_INTERVAL_MS);
|
|
37
|
+
sweeper.unref?.();
|
|
38
|
+
}
|
|
39
|
+
function newId(prefix) {
|
|
40
|
+
return `${prefix}-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
41
|
+
}
|
|
42
|
+
export function createJob(type, runner, { idPrefix = type, onComplete, meta } = {}) {
|
|
43
|
+
ensureSweeper();
|
|
44
|
+
const id = newId(idPrefix);
|
|
45
|
+
const controller = new AbortController();
|
|
46
|
+
const job = {
|
|
47
|
+
id,
|
|
48
|
+
type,
|
|
49
|
+
status: "running",
|
|
50
|
+
events: [],
|
|
51
|
+
doneResult: undefined,
|
|
52
|
+
error: null,
|
|
53
|
+
createdAt: Date.now(),
|
|
54
|
+
finishedAt: null,
|
|
55
|
+
expiresAt: null,
|
|
56
|
+
subscribers: new Set(),
|
|
57
|
+
controller,
|
|
58
|
+
meta: meta ?? {},
|
|
59
|
+
};
|
|
60
|
+
jobs.set(id, job);
|
|
61
|
+
const send = (event) => {
|
|
62
|
+
job.events.push(event);
|
|
63
|
+
for (const sub of job.subscribers) {
|
|
64
|
+
try {
|
|
65
|
+
sub(event);
|
|
66
|
+
}
|
|
67
|
+
catch { /* subscriber errors don't break fanout */ }
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
(async () => {
|
|
71
|
+
try {
|
|
72
|
+
const result = await runner(send, controller.signal);
|
|
73
|
+
if (job.status === "cancelled")
|
|
74
|
+
return;
|
|
75
|
+
job.doneResult = result ?? null;
|
|
76
|
+
job.status = "done";
|
|
77
|
+
send({ type: "done" });
|
|
78
|
+
onComplete?.({ status: "done", result });
|
|
79
|
+
}
|
|
80
|
+
catch (e) {
|
|
81
|
+
if (job.status === "cancelled")
|
|
82
|
+
return;
|
|
83
|
+
// If the runner threw because of our own abort, prefer the cancelled
|
|
84
|
+
// terminal over a misleading error event.
|
|
85
|
+
if (controller.signal.aborted) {
|
|
86
|
+
job.status = "cancelled";
|
|
87
|
+
send({ type: "cancelled" });
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
job.status = "error";
|
|
91
|
+
job.error = (e instanceof Error ? e.message : null) ?? String(e);
|
|
92
|
+
send({ type: "error", message: job.error });
|
|
93
|
+
}
|
|
94
|
+
finally {
|
|
95
|
+
job.finishedAt = Date.now();
|
|
96
|
+
job.expiresAt = job.finishedAt + TTL_MS;
|
|
97
|
+
}
|
|
98
|
+
})();
|
|
99
|
+
return id;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Cancel a running job. Aborts the signal, emits a terminal `cancelled`
|
|
103
|
+
* event, and marks the job non-running. No-op if the job is already
|
|
104
|
+
* terminal or doesn't exist — returns whether a cancel was actually issued.
|
|
105
|
+
*/
|
|
106
|
+
export function cancelJob(id) {
|
|
107
|
+
const job = jobs.get(id);
|
|
108
|
+
if (!job)
|
|
109
|
+
return false;
|
|
110
|
+
if (job.status !== "running")
|
|
111
|
+
return false;
|
|
112
|
+
job.status = "cancelled";
|
|
113
|
+
try {
|
|
114
|
+
job.controller.abort();
|
|
115
|
+
}
|
|
116
|
+
catch { /* ignore */ }
|
|
117
|
+
// Emit the terminal *before* the runner's catch block runs, so reconnecting
|
|
118
|
+
// clients always see a cancellation event in the buffer.
|
|
119
|
+
job.events.push({ type: "cancelled" });
|
|
120
|
+
for (const sub of job.subscribers) {
|
|
121
|
+
try {
|
|
122
|
+
sub({ type: "cancelled" });
|
|
123
|
+
}
|
|
124
|
+
catch { /* ignore */ }
|
|
125
|
+
}
|
|
126
|
+
job.finishedAt = Date.now();
|
|
127
|
+
job.expiresAt = job.finishedAt + TTL_MS;
|
|
128
|
+
return true;
|
|
129
|
+
}
|
|
130
|
+
export function getJob(id) {
|
|
131
|
+
return jobs.get(id) ?? null;
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Replay buffered events to `handler`, then subscribe for live events until
|
|
135
|
+
* the job reaches terminal state. Returns an `unsubscribe` function, or
|
|
136
|
+
* `null` if the job doesn't exist.
|
|
137
|
+
*
|
|
138
|
+
* The terminal `done`/`error` event is part of the buffered replay — callers
|
|
139
|
+
* that want to end the response on terminal should check for it inside
|
|
140
|
+
* their handler.
|
|
141
|
+
*/
|
|
142
|
+
export function subscribe(id, handler) {
|
|
143
|
+
const job = jobs.get(id);
|
|
144
|
+
if (!job)
|
|
145
|
+
return null;
|
|
146
|
+
for (const e of job.events) {
|
|
147
|
+
try {
|
|
148
|
+
handler(e);
|
|
149
|
+
}
|
|
150
|
+
catch { /* ignore */ }
|
|
151
|
+
}
|
|
152
|
+
if (job.status !== "running") {
|
|
153
|
+
return () => { };
|
|
154
|
+
}
|
|
155
|
+
job.subscribers.add(handler);
|
|
156
|
+
return () => { job.subscribers.delete(handler); };
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Public status snapshot — safe to send to clients. Excludes the event
|
|
160
|
+
* buffer (potentially large) and subscribers (not serialisable).
|
|
161
|
+
*/
|
|
162
|
+
export function snapshot(id) {
|
|
163
|
+
const job = jobs.get(id);
|
|
164
|
+
if (!job)
|
|
165
|
+
return null;
|
|
166
|
+
return {
|
|
167
|
+
id: job.id,
|
|
168
|
+
type: job.type,
|
|
169
|
+
status: job.status,
|
|
170
|
+
createdAt: job.createdAt,
|
|
171
|
+
finishedAt: job.finishedAt,
|
|
172
|
+
error: job.error,
|
|
173
|
+
eventCount: job.events.length,
|
|
174
|
+
meta: job.meta,
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
export function findActiveByMeta(key, value) {
|
|
178
|
+
for (const job of jobs.values()) {
|
|
179
|
+
if (job.status === "running" && job.meta?.[key] === value) {
|
|
180
|
+
return snapshot(job.id);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
return null;
|
|
184
|
+
}
|
|
185
|
+
//# sourceMappingURL=jobs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jobs.js","sourceRoot":"","sources":["../../../../server/forge/core/jobs.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export declare function listDeployments(namespace: string): Promise<{
|
|
2
|
+
name: string;
|
|
3
|
+
namespace: string;
|
|
4
|
+
image: string;
|
|
5
|
+
replicas: {
|
|
6
|
+
desired: number;
|
|
7
|
+
ready: number;
|
|
8
|
+
available: number;
|
|
9
|
+
unavailable: number;
|
|
10
|
+
updated: number;
|
|
11
|
+
};
|
|
12
|
+
conditions: {
|
|
13
|
+
type: string;
|
|
14
|
+
status: string;
|
|
15
|
+
message: string;
|
|
16
|
+
}[];
|
|
17
|
+
}[]>;
|
|
18
|
+
//# sourceMappingURL=k8s.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"k8s.d.ts","sourceRoot":"","sources":["../../../../server/forge/core/k8s.ts"],"names":[],"mappings":"AA6DA,wBAAsB,eAAe,CAAC,SAAS,EAAE,MAAM;;;;;;;;;;;;;;;;KAItD"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import * as k8s from "@kubernetes/client-node";
|
|
2
|
+
let kc = new k8s.KubeConfig();
|
|
3
|
+
function loadConfig() {
|
|
4
|
+
kc = new k8s.KubeConfig();
|
|
5
|
+
const token = process.env.K8S_CLUSTER_TOKEN;
|
|
6
|
+
const server = process.env.K8S_CLUSTER_SERVER;
|
|
7
|
+
if (token && server) {
|
|
8
|
+
kc.loadFromOptions({
|
|
9
|
+
clusters: [{ name: "cluster", server, skipTLSVerify: process.env.K8S_SKIP_TLS_VERIFY === "true" }],
|
|
10
|
+
users: [{ name: "admin", token }],
|
|
11
|
+
contexts: [{ name: "default", cluster: "cluster", user: "admin" }],
|
|
12
|
+
currentContext: "default",
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
else {
|
|
16
|
+
kc.loadFromDefault();
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
loadConfig();
|
|
20
|
+
function getAppsApi() {
|
|
21
|
+
return kc.makeApiClient(k8s.AppsV1Api);
|
|
22
|
+
}
|
|
23
|
+
function formatDeployment(dep) {
|
|
24
|
+
const containers = dep.spec?.template?.spec?.containers || [];
|
|
25
|
+
const status = dep.status || {};
|
|
26
|
+
return {
|
|
27
|
+
name: dep.metadata?.name,
|
|
28
|
+
namespace: dep.metadata?.namespace,
|
|
29
|
+
image: containers[0]?.image || "unknown",
|
|
30
|
+
replicas: {
|
|
31
|
+
desired: dep.spec?.replicas || 0,
|
|
32
|
+
ready: status.readyReplicas || 0,
|
|
33
|
+
available: status.availableReplicas || 0,
|
|
34
|
+
unavailable: status.unavailableReplicas || 0,
|
|
35
|
+
updated: status.updatedReplicas || 0,
|
|
36
|
+
},
|
|
37
|
+
conditions: (status.conditions || []).map((c) => ({
|
|
38
|
+
type: c.type,
|
|
39
|
+
status: c.status,
|
|
40
|
+
message: c.message,
|
|
41
|
+
})),
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
export async function listDeployments(namespace) {
|
|
45
|
+
const api = getAppsApi();
|
|
46
|
+
const res = await api.listNamespacedDeployment({ namespace });
|
|
47
|
+
return (res.items || []).map(formatDeployment);
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=k8s.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"k8s.js","sourceRoot":"","sources":["../../../../server/forge/core/k8s.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,GAAG,MAAM,yBAAyB,CAAC;AAc/C,IAAI,EAAE,GAAG,IAAI,GAAG,CAAC,UAAU,EAAE,CAAC;AAE9B,SAAS,UAAU;IAClB,EAAE,GAAG,IAAI,GAAG,CAAC,UAAU,EAAE,CAAC;IAC1B,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC;IAC5C,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC;IAE9C,IAAI,KAAK,IAAI,MAAM,EAAE,CAAC;QACrB,EAAE,CAAC,eAAe,CAAC;YAClB,QAAQ,EAAE,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,aAAa,EAAE,OAAO,CAAC,GAAG,CAAC,mBAAmB,KAAK,MAAM,EAAE,CAAC;YAClG,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;YACjC,QAAQ,EAAE,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;YAClE,cAAc,EAAE,SAAS;SACzB,CAAC,CAAC;IACJ,CAAC;SAAM,CAAC;QACP,EAAE,CAAC,eAAe,EAAE,CAAC;IACtB,CAAC;AACF,CAAC;AAED,UAAU,EAAE,CAAC;AAEb,SAAS,UAAU;IAClB,OAAO,EAAE,CAAC,aAAa,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;AACxC,CAAC;AAED,SAAS,gBAAgB,CAAC,GAAkB;IAC3C,MAAM,UAAU,GAAG,GAAG,CAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,UAAU,IAAI,EAAE,CAAC;IAC9D,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,IAAI,EAAE,CAAC;IAChC,OAAO;QACN,IAAI,EAAE,GAAG,CAAC,QAAQ,EAAE,IAAI;QACxB,SAAS,EAAE,GAAG,CAAC,QAAQ,EAAE,SAAS;QAClC,KAAK,EAAE,UAAU,CAAC,CAAC,CAAC,EAAE,KAAK,IAAI,SAAS;QACxC,QAAQ,EAAE;YACT,OAAO,EAAE,GAAG,CAAC,IAAI,EAAE,QAAQ,IAAI,CAAC;YAChC,KAAK,EAAE,MAAM,CAAC,aAAa,IAAI,CAAC;YAChC,SAAS,EAAE,MAAM,CAAC,iBAAiB,IAAI,CAAC;YACxC,WAAW,EAAE,MAAM,CAAC,mBAAmB,IAAI,CAAC;YAC5C,OAAO,EAAE,MAAM,CAAC,eAAe,IAAI,CAAC;SACpC;QACD,UAAU,EAAE,CAAC,MAAM,CAAC,UAAU,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAqD,EAAE,EAAE,CAAC,CAAC;YACrG,IAAI,EAAE,CAAC,CAAC,IAAI;YACZ,MAAM,EAAE,CAAC,CAAC,MAAM;YAChB,OAAO,EAAE,CAAC,CAAC,OAAO;SAClB,CAAC,CAAC;KACH,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,SAAiB;IACtD,MAAM,GAAG,GAAG,UAAU,EAAE,CAAC;IACzB,MAAM,GAAG,GAAG,MAAM,GAAG,CAAC,wBAAwB,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC;IAC9D,OAAO,CAAC,GAAG,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;AAChD,CAAC"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* server/forge/core/localRepo.js
|
|
3
|
+
*
|
|
4
|
+
* Shared helpers for maintaining a shallow working clone of a repo under
|
|
5
|
+
* ~/.forge/cache/<repo>/ and overlaying proposed file changes onto it.
|
|
6
|
+
*
|
|
7
|
+
* Used by:
|
|
8
|
+
* - validator.js → run lint/typecheck/test against the overlaid tree
|
|
9
|
+
* - ForgeAgent.refineIssue → give the refine model real Read/Glob/Grep access
|
|
10
|
+
* against the current state of the working tree (FORGE_REFINE_REPO_ACCESS)
|
|
11
|
+
*
|
|
12
|
+
* Scope matches validator v1: GitLab HTTPS clones only. GitHub / Azure DevOps
|
|
13
|
+
* raise a clear "not supported yet" error so the caller can fall back cleanly.
|
|
14
|
+
*/
|
|
15
|
+
import type { ForgeChange } from "./types.ts";
|
|
16
|
+
export declare function cachePathFor(repo: string): string;
|
|
17
|
+
/**
|
|
18
|
+
* Ensures the repo is cloned and reset to a clean branch at origin/main.
|
|
19
|
+
* Reuses any existing clone under ~/.forge/cache/<repo>/.
|
|
20
|
+
*
|
|
21
|
+
* @param {string} repo Repo id (may carry a "gitlab:" prefix)
|
|
22
|
+
* @param {string} branchName Workspace branch to check out
|
|
23
|
+
* @param {(msg: string) => void} [onLog]
|
|
24
|
+
* @returns {Promise<string>} Absolute path to the working tree
|
|
25
|
+
*/
|
|
26
|
+
export declare function ensureWorkingTree(repo: string, branchName: string, onLog?: (msg: string) => void): Promise<string>;
|
|
27
|
+
/**
|
|
28
|
+
* Writes proposed file contents into the working tree (or deletes files for
|
|
29
|
+
* action="delete"). Refuses paths that escape the clone directory.
|
|
30
|
+
*
|
|
31
|
+
* @param {string} dir
|
|
32
|
+
* @param {Array<{file: string, action: 'create'|'modify'|'delete', proposed?: string}>} changes
|
|
33
|
+
* @param {(msg: string) => void} [onLog]
|
|
34
|
+
*/
|
|
35
|
+
export declare function overlayChanges(dir: string, changes: ForgeChange[], onLog?: (msg: string) => void): Promise<void>;
|
|
36
|
+
//# sourceMappingURL=localRepo.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"localRepo.d.ts","sourceRoot":"","sources":["../../../../server/forge/core/localRepo.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AASH,OAAO,KAAK,EAAgB,WAAW,EAAE,MAAM,YAAY,CAAC;AAuE5D,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,UAExC;AAED;;;;;;;;GAQG;AACH,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,mBA+BtG;AAED;;;;;;;GAOG;AACH,wBAAsB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,EAAE,KAAK,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,iBAgBtG"}
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* server/forge/core/localRepo.js
|
|
3
|
+
*
|
|
4
|
+
* Shared helpers for maintaining a shallow working clone of a repo under
|
|
5
|
+
* ~/.forge/cache/<repo>/ and overlaying proposed file changes onto it.
|
|
6
|
+
*
|
|
7
|
+
* Used by:
|
|
8
|
+
* - validator.js → run lint/typecheck/test against the overlaid tree
|
|
9
|
+
* - ForgeAgent.refineIssue → give the refine model real Read/Glob/Grep access
|
|
10
|
+
* against the current state of the working tree (FORGE_REFINE_REPO_ACCESS)
|
|
11
|
+
*
|
|
12
|
+
* Scope matches validator v1: GitLab HTTPS clones only. GitHub / Azure DevOps
|
|
13
|
+
* raise a clear "not supported yet" error so the caller can fall back cleanly.
|
|
14
|
+
*/
|
|
15
|
+
import { spawn } from "child_process";
|
|
16
|
+
import { writeFileSync, unlinkSync } from "fs";
|
|
17
|
+
import fs from "fs/promises";
|
|
18
|
+
import os from "os";
|
|
19
|
+
import path from "path";
|
|
20
|
+
import { getConnection } from "./configStore.js";
|
|
21
|
+
const CACHE_ROOT = process.env.FORGE_VALIDATE_CACHE
|
|
22
|
+
?? path.join(os.homedir(), ".forge", "cache");
|
|
23
|
+
function runGit(args, opts = {}, onLog) {
|
|
24
|
+
return new Promise((resolve) => {
|
|
25
|
+
const proc = spawn("git", args, {
|
|
26
|
+
...opts,
|
|
27
|
+
env: { ...process.env, ...(opts.env ?? {}), FORCE_COLOR: "0", NO_COLOR: "1", TERM: "dumb" },
|
|
28
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
29
|
+
});
|
|
30
|
+
const lines = [];
|
|
31
|
+
const collect = (buf) => {
|
|
32
|
+
for (const raw of buf.toString().split("\n")) {
|
|
33
|
+
const line = raw.replace(/\r$/, "");
|
|
34
|
+
if (!line)
|
|
35
|
+
continue;
|
|
36
|
+
lines.push(line);
|
|
37
|
+
onLog?.(line);
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
proc.stdout.on("data", collect);
|
|
41
|
+
proc.stderr.on("data", collect);
|
|
42
|
+
proc.on("error", (err) => resolve({ code: -1, output: lines.join("\n"), error: err.message }));
|
|
43
|
+
proc.on("close", (code) => resolve({ code: code ?? -1, output: lines.join("\n"), error: null }));
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
async function exists(p) {
|
|
47
|
+
try {
|
|
48
|
+
await fs.access(p);
|
|
49
|
+
return true;
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
function sanitizeRepo(repo) {
|
|
56
|
+
return repo.replace(/[^a-zA-Z0-9_./-]/g, "_");
|
|
57
|
+
}
|
|
58
|
+
function gitlabCloneUrl(project) {
|
|
59
|
+
return `https://gitlab.com/${project}.git`;
|
|
60
|
+
}
|
|
61
|
+
function createAskpassScript(token) {
|
|
62
|
+
const script = path.join(os.tmpdir(), `.forge-askpass-${process.pid}-${Date.now()}`);
|
|
63
|
+
writeFileSync(script, `#!/bin/sh\ncase "$1" in *Username*) echo oauth2;; *) echo "${token}";; esac\n`, { mode: 0o700 });
|
|
64
|
+
return script;
|
|
65
|
+
}
|
|
66
|
+
function gitEnvWithToken() {
|
|
67
|
+
const { token } = getConnection("gitlab");
|
|
68
|
+
if (!token)
|
|
69
|
+
throw new Error("GitLab token is required to clone the repo locally. Set it in Settings → Connections or via GITLAB_TOKEN env var.");
|
|
70
|
+
const askpass = createAskpassScript(token);
|
|
71
|
+
return {
|
|
72
|
+
env: {
|
|
73
|
+
GIT_ASKPASS: askpass,
|
|
74
|
+
GIT_TERMINAL_PROMPT: "0",
|
|
75
|
+
},
|
|
76
|
+
cleanup: () => { try {
|
|
77
|
+
unlinkSync(askpass);
|
|
78
|
+
}
|
|
79
|
+
catch { } },
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
function resolveCloneUrl(repoInput) {
|
|
83
|
+
const colon = repoInput.indexOf(":");
|
|
84
|
+
if (colon > 0) {
|
|
85
|
+
const prefix = repoInput.slice(0, colon).toLowerCase();
|
|
86
|
+
if (prefix === "gitlab")
|
|
87
|
+
return gitlabCloneUrl(repoInput.slice(colon + 1));
|
|
88
|
+
if (prefix === "github" || prefix === "azuredevops" || prefix === "azure") {
|
|
89
|
+
throw new Error(`Local clone for ${prefix} repos isn't supported yet — GitLab only.`);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
return gitlabCloneUrl(repoInput);
|
|
93
|
+
}
|
|
94
|
+
export function cachePathFor(repo) {
|
|
95
|
+
return path.join(CACHE_ROOT, sanitizeRepo(repo));
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Ensures the repo is cloned and reset to a clean branch at origin/main.
|
|
99
|
+
* Reuses any existing clone under ~/.forge/cache/<repo>/.
|
|
100
|
+
*
|
|
101
|
+
* @param {string} repo Repo id (may carry a "gitlab:" prefix)
|
|
102
|
+
* @param {string} branchName Workspace branch to check out
|
|
103
|
+
* @param {(msg: string) => void} [onLog]
|
|
104
|
+
* @returns {Promise<string>} Absolute path to the working tree
|
|
105
|
+
*/
|
|
106
|
+
export async function ensureWorkingTree(repo, branchName, onLog) {
|
|
107
|
+
const dir = cachePathFor(repo);
|
|
108
|
+
const hasRepo = await exists(path.join(dir, ".git"));
|
|
109
|
+
const log = (m) => onLog?.(m);
|
|
110
|
+
const { env: gitEnv, cleanup } = gitEnvWithToken();
|
|
111
|
+
const envOpts = { env: { ...process.env, ...gitEnv } };
|
|
112
|
+
try {
|
|
113
|
+
if (!hasRepo) {
|
|
114
|
+
log(`Cloning ${repo} → ${dir}`);
|
|
115
|
+
await fs.mkdir(dir, { recursive: true });
|
|
116
|
+
const clone = await runGit(["clone", "--depth=1", resolveCloneUrl(repo), dir], envOpts, onLog);
|
|
117
|
+
if (clone.code !== 0)
|
|
118
|
+
throw new Error(`git clone failed (code ${clone.code})`);
|
|
119
|
+
}
|
|
120
|
+
else {
|
|
121
|
+
log(`Reusing clone at ${dir}`);
|
|
122
|
+
}
|
|
123
|
+
const fetch = await runGit(["fetch", "--depth=1", "origin", "main"], { cwd: dir, ...envOpts }, onLog);
|
|
124
|
+
if (fetch.code !== 0)
|
|
125
|
+
throw new Error(`git fetch failed (code ${fetch.code})`);
|
|
126
|
+
const reset = await runGit(["reset", "--hard", "origin/main"], { cwd: dir }, onLog);
|
|
127
|
+
if (reset.code !== 0)
|
|
128
|
+
throw new Error(`git reset failed (code ${reset.code})`);
|
|
129
|
+
await runGit(["clean", "-fd"], { cwd: dir }, onLog);
|
|
130
|
+
const checkout = await runGit(["checkout", "-B", branchName], { cwd: dir }, onLog);
|
|
131
|
+
if (checkout.code !== 0)
|
|
132
|
+
throw new Error(`git checkout ${branchName} failed (code ${checkout.code})`);
|
|
133
|
+
return dir;
|
|
134
|
+
}
|
|
135
|
+
finally {
|
|
136
|
+
cleanup();
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Writes proposed file contents into the working tree (or deletes files for
|
|
141
|
+
* action="delete"). Refuses paths that escape the clone directory.
|
|
142
|
+
*
|
|
143
|
+
* @param {string} dir
|
|
144
|
+
* @param {Array<{file: string, action: 'create'|'modify'|'delete', proposed?: string}>} changes
|
|
145
|
+
* @param {(msg: string) => void} [onLog]
|
|
146
|
+
*/
|
|
147
|
+
export async function overlayChanges(dir, changes, onLog) {
|
|
148
|
+
const realBase = await fs.realpath(dir);
|
|
149
|
+
for (const c of changes) {
|
|
150
|
+
const full = path.resolve(dir, c.file);
|
|
151
|
+
if (!full.startsWith(realBase + path.sep) && full !== realBase) {
|
|
152
|
+
throw new Error(`Refusing to write outside clone dir: ${c.file}`);
|
|
153
|
+
}
|
|
154
|
+
if (c.action === "delete") {
|
|
155
|
+
await fs.rm(full, { force: true });
|
|
156
|
+
onLog?.(`- ${c.file}`);
|
|
157
|
+
}
|
|
158
|
+
else {
|
|
159
|
+
await fs.mkdir(path.dirname(full), { recursive: true });
|
|
160
|
+
await fs.writeFile(full, c.proposed ?? "");
|
|
161
|
+
onLog?.(`+ ${c.file} (${c.action})`);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
//# sourceMappingURL=localRepo.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"localRepo.js","sourceRoot":"","sources":["../../../../server/forge/core/localRepo.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* server/forge/core/openclawClient.js
|
|
3
|
+
*
|
|
4
|
+
* Communicates with a locally-running OpenClaw Gateway over HTTP.
|
|
5
|
+
* Configure with:
|
|
6
|
+
* OPENCLAW_GATEWAY_URL — e.g. http://192.168.x.x:18789 (Tailscale) or SSH tunnel
|
|
7
|
+
* OPENCLAW_TOKEN — Bearer token if your Gateway requires auth
|
|
8
|
+
*
|
|
9
|
+
* The Gateway runs on 127.0.0.1:18789 by default. Expose it remotely via:
|
|
10
|
+
* Tailscale: bind to tailnet interface
|
|
11
|
+
* SSH tunnel: ssh -N -L 18789:127.0.0.1:18789 user@host
|
|
12
|
+
*/
|
|
13
|
+
import type { NormalDiff } from "./providers/types.ts";
|
|
14
|
+
import type { AgentResponse, ForgeChange, ForgeEvent } from "./types.ts";
|
|
15
|
+
interface IssueInput {
|
|
16
|
+
iid?: number;
|
|
17
|
+
title?: string | null;
|
|
18
|
+
description?: string | null;
|
|
19
|
+
labels?: Array<string | {
|
|
20
|
+
name?: string;
|
|
21
|
+
}> | null;
|
|
22
|
+
}
|
|
23
|
+
interface FileContent {
|
|
24
|
+
repo?: string;
|
|
25
|
+
path: string;
|
|
26
|
+
content: string;
|
|
27
|
+
}
|
|
28
|
+
interface RepoTree {
|
|
29
|
+
repo: string;
|
|
30
|
+
files: string[];
|
|
31
|
+
}
|
|
32
|
+
interface ProposeFixOptions {
|
|
33
|
+
feedback?: string;
|
|
34
|
+
ciContext?: string;
|
|
35
|
+
userPrompt?: string;
|
|
36
|
+
repos?: string[];
|
|
37
|
+
promptRules?: string;
|
|
38
|
+
previousChanges?: ForgeChange[];
|
|
39
|
+
}
|
|
40
|
+
interface RefineOptions {
|
|
41
|
+
feedback?: string;
|
|
42
|
+
previousChanges?: ForgeChange[];
|
|
43
|
+
validationState?: unknown;
|
|
44
|
+
repos?: string[];
|
|
45
|
+
repoTrees?: RepoTree[];
|
|
46
|
+
repoAccessMode?: string;
|
|
47
|
+
promptRules?: string;
|
|
48
|
+
repoCwd?: string;
|
|
49
|
+
sessionId?: string;
|
|
50
|
+
resumeSession?: boolean;
|
|
51
|
+
}
|
|
52
|
+
interface GatewayCallOpts {
|
|
53
|
+
signal?: AbortSignal;
|
|
54
|
+
timeout?: number;
|
|
55
|
+
}
|
|
56
|
+
export declare function checkResolution(issue: IssueInput, diffs: NormalDiff[], model: string | undefined, opts?: GatewayCallOpts): Promise<AgentResponse>;
|
|
57
|
+
export declare function identifyRelevantFiles(issue: IssueInput, fileTree: RepoTree[] | string[], model: string | undefined, opts?: GatewayCallOpts): Promise<AgentResponse>;
|
|
58
|
+
export declare function proposeFix(issue: IssueInput, fileContents: FileContent[], options: ProposeFixOptions, model: string | undefined, opts?: GatewayCallOpts): Promise<AgentResponse>;
|
|
59
|
+
export declare function refineOrAsk(issue: IssueInput, fileContents: FileContent[], options: RefineOptions, model: string | undefined, _onEvent: ((evt: ForgeEvent) => void) | undefined, opts?: GatewayCallOpts): Promise<AgentResponse>;
|
|
60
|
+
export {};
|
|
61
|
+
//# sourceMappingURL=openclawClient.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openclawClient.d.ts","sourceRoot":"","sources":["../../../../server/forge/core/openclawClient.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAQH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAEzE,UAAU,UAAU;IACnB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,MAAM,CAAC,EAAE,KAAK,CAAC,MAAM,GAAG;QAAE,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,GAAG,IAAI,CAAC;CAClD;AAED,UAAU,WAAW;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CAChB;AAED,UAAU,QAAQ;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,EAAE,CAAC;CAChB;AAED,UAAU,iBAAiB;IAC1B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,eAAe,CAAC,EAAE,WAAW,EAAE,CAAC;CAChC;AAED,UAAU,aAAa;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,WAAW,EAAE,CAAC;IAChC,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,SAAS,CAAC,EAAE,QAAQ,EAAE,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,OAAO,CAAC;CACxB;AAED,UAAU,eAAe;IACxB,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB;AAuFD,wBAAsB,eAAe,CAAC,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,SAAS,EAAE,IAAI,GAAE,eAAoB,GAAG,OAAO,CAAC,aAAa,CAAC,CAI3J;AAED,wBAAsB,qBAAqB,CAAC,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,QAAQ,EAAE,GAAG,MAAM,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,SAAS,EAAE,IAAI,GAAE,eAAoB,GAAG,OAAO,CAAC,aAAa,CAAC,CAI7K;AAED,wBAAsB,UAAU,CAAC,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,WAAW,EAAE,EAAE,OAAO,EAAE,iBAAsB,EAAE,KAAK,EAAE,MAAM,GAAG,SAAS,EAAE,IAAI,GAAE,eAAoB,GAAG,OAAO,CAAC,aAAa,CAAC,CAI/L;AAED,wBAAsB,WAAW,CAAC,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,WAAW,EAAE,EAAE,OAAO,EAAE,aAAkB,EAAE,KAAK,EAAE,MAAM,GAAG,SAAS,EAAE,QAAQ,EAAE,CAAC,CAAC,GAAG,EAAE,UAAU,KAAK,IAAI,CAAC,GAAG,SAAS,EAAE,IAAI,GAAE,eAAoB,GAAG,OAAO,CAAC,aAAa,CAAC,CAM/O"}
|