@outerlayer/cli 0.8.6 → 0.10.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/CHANGELOG.md +21 -0
- package/README.md +24 -14
- package/dist/{agent-setup-LEQF4V5F.js → agent-setup-ODTDC3US.js} +8 -7
- package/dist/{build-3FSJR5OO.js → build-LELVCWHV.js} +2 -2
- package/dist/build-info.json +1 -1
- package/dist/{builder-5UFAF5LW.js → builder-5DKTBWT3.js} +5 -5
- package/dist/{check-443BADSD.js → check-VJRJ2KQ4.js} +69 -34
- package/dist/{chunk-Y7UQHKFY.js → chunk-3FMPZPJQ.js} +1 -4
- package/dist/chunk-3JVYMD4G.js +18 -0
- package/dist/{chunk-K4MGMSMN.js → chunk-4HMXH2OA.js} +8 -2
- package/dist/{chunk-H6IGIE3I.js → chunk-543OT6V5.js} +4 -4
- package/dist/chunk-5K3IUOPJ.js +178 -0
- package/dist/{chunk-HWMYGAKF.js → chunk-6CXYORUS.js} +1 -1
- package/dist/{inspect-XAUSB7L3.js → chunk-6MZSX4M7.js} +12 -6
- package/dist/{chunk-IS4DIGBQ.js → chunk-ABIWDUMS.js} +1 -13
- package/dist/{chunk-WLV4KCAW.js → chunk-BGWTYRSS.js} +1 -1
- package/dist/{chunk-2MFYKH3C.js → chunk-BMX3L7CR.js} +1 -1
- package/dist/{chunk-HKMPVPO7.js → chunk-BYT5O5RV.js} +7 -1
- package/dist/{chunk-WGLWDX5J.js → chunk-FKFGQJNN.js} +1 -1
- package/dist/{chunk-MSV44EB5.js → chunk-KPUJGBA4.js} +2 -2
- package/dist/{chunk-TY7EZC7U.js → chunk-KWCJLAHQ.js} +5 -5
- package/dist/{chunk-GJ3OWUFO.js → chunk-LBU4CLK5.js} +113 -24
- package/dist/{chunk-CDISNKM4.js → chunk-LTJPX7TX.js} +93 -13
- package/dist/{chunk-TFJGK4UB.js → chunk-LYESSQUA.js} +22 -4
- package/dist/{chunk-7KI224YS.js → chunk-M2PBLRB7.js} +1 -1
- package/dist/{chunk-2FWL7CE2.js → chunk-M6G7TJVF.js} +1 -1
- package/dist/{chunk-CRLAB4PM.js → chunk-NTLGWCWK.js} +1 -1
- package/dist/{chunk-ALCXFVUV.js → chunk-OSKO3PAL.js} +25 -19
- package/dist/{chunk-AIW6GLET.js → chunk-PDTSUOVT.js} +1 -1
- package/dist/{chunk-LKUUQ3XV.js → chunk-QPPPUKQJ.js} +1 -1
- package/dist/{chunk-6AFQOYO3.js → chunk-RWQWPZB4.js} +10 -6
- package/dist/{chunk-2E2MG3KW.js → chunk-S6IUUNCD.js} +1 -1
- package/dist/{chunk-AGMIJ725.js → chunk-SUMWRA7K.js} +1 -1
- package/dist/{chunk-NKU5OPYP.js → chunk-TB7EP24C.js} +1 -1
- package/dist/{chunk-DE4GLH3P.js → chunk-TV36SKEN.js} +2 -2
- package/dist/{chunk-J5DPVNL3.js → chunk-V42JY4F6.js} +2 -2
- package/dist/{chunk-FCDET2U5.js → chunk-VMK7I3TB.js} +3 -3
- package/dist/{chunk-IOG6LPEI.js → chunk-WJBJY5DQ.js} +2 -2
- package/dist/{chunk-SWGQAURM.js → chunk-XGCJNSI7.js} +26 -7
- package/dist/{chunk-FTW6C2E7.js → chunk-XZNO4QED.js} +10 -10
- package/dist/{chunk-NQWTCX3A.js → chunk-YCPV7FN6.js} +31 -19
- package/dist/{chunk-PK5NANMT.js → chunk-YT35WGIP.js} +5 -3
- package/dist/{chunk-DSPYQUH4.js → chunk-YU5GL7QS.js} +2 -2
- package/dist/{chunk-BL63NBJZ.js → chunk-ZEQMTBRD.js} +1 -1
- package/dist/{cli-PNMCZVQ4.js → cli-77URFYI7.js} +83 -83
- package/dist/{command-WKRTL3JQ.js → command-2LYWVGIK.js} +21 -21
- package/dist/{config-OOBPCY7Q.js → config-X45X7AS4.js} +3 -3
- package/dist/{connect-cmd-YEO7WRSL.js → connect-cmd-MPZWSEKY.js} +4 -4
- package/dist/{context-adopt-3REPEEQR.js → context-adopt-A77G67CP.js} +6 -5
- package/dist/{context-materialize-DU6B6RXF.js → context-materialize-KQZYATQZ.js} +6 -5
- package/dist/{dist-PKBWZAAL.js → dist-QY5CL5LB.js} +2 -2
- package/dist/{docker-5DUNHNOH.js → docker-V7B6UKPF.js} +6 -6
- package/dist/{doctor-FEIBPZL7.js → doctor-PUAL5LTL.js} +46 -35
- package/dist/{emit-artifact-cmd-S3CASUQK.js → emit-artifact-cmd-P3IWNSQY.js} +7 -7
- package/dist/{emit-cmd-ETI47BA6.js → emit-cmd-SU62J2PB.js} +4 -4
- package/dist/{emit-criteria-cmd-ZTUP7OGA.js → emit-criteria-cmd-GOSP6X74.js} +5 -5
- package/dist/{emit-finding-cmd-TTXBZ4B7.js → emit-finding-cmd-D554IQKU.js} +5 -5
- package/dist/{emit-result-cmd-34OC6TI5.js → emit-result-cmd-QACXTIBV.js} +7 -7
- package/dist/{exec-client-2UX6NHAO.js → exec-client-QTUO6TZT.js} +4 -4
- package/dist/{guest-init-VHQNFCFS.js → guest-init-4UW4HM6N.js} +4 -4
- package/dist/{hook-fast-CFLLVMSV.js → hook-fast-AQCAQIA6.js} +1 -1
- package/dist/{import-capture-cmd-Z3232HR4.js → import-capture-cmd-5NJVL2HN.js} +3 -3
- package/dist/{import-ruler-cmd-2PLXZXM7.js → import-ruler-cmd-TUK3MRPC.js} +2 -2
- package/dist/index.js +3 -3
- package/dist/{init-AHQHM56A.js → init-TMBE3BRN.js} +20 -20
- package/dist/{init-UZ5TXACM.js → init-WX5XE6L3.js} +47 -23
- package/dist/{init-cmd-F4FS5AVC.js → init-cmd-4FQKQLJ5.js} +14 -14
- package/dist/inspect-6UYAAXH7.js +6 -0
- package/dist/{install-C33LT5KQ.js → install-PYNCWSTV.js} +4 -4
- package/dist/{loop-U7GLISBM.js → loop-QLL4DKRF.js} +31 -30
- package/dist/{machine-Y3TBDMXD.js → machine-7T7FBSUL.js} +19 -19
- package/dist/{real-deps-AKVGIDPZ.js → real-deps-LS64D3M6.js} +2 -1
- package/dist/{session-sender-LKVVLAUP.js → session-sender-HVWTYG35.js} +6 -6
- package/dist/{starter-pack-L5WPXL4Q.js → starter-pack-I35VNYAR.js} +4 -4
- package/dist/{status-OQ23WOUP.js → status-SMF5JG2K.js} +24 -24
- package/dist/{sync-cmd-VH6HSMG5.js → sync-cmd-SLMPCUXO.js} +5 -5
- package/dist/{watch-HUKDEFUX.js → watch-TLM5QN5X.js} +5 -5
- package/dist/{work-claim-cmd-JLCU5SPP.js → work-claim-cmd-VSSZDFY5.js} +34 -12
- package/dist/{work-cmd-SBKQJBJ2.js → work-cmd-TK4VOOHL.js} +6 -6
- package/dist/{work-comment-cmd-TNUDUUAT.js → work-comment-cmd-VQCG72ZQ.js} +6 -6
- package/dist/{work-open-pr-cmd-IB57SMAD.js → work-open-pr-cmd-YESMWATB.js} +17 -9
- package/dist/{work-pr-cmd-HDDNFSKA.js → work-pr-cmd-6TMSCO3Q.js} +7 -6
- package/package.json +1 -1
- package/skill-pack/maintained/amend/SKILL.md +22 -12
- package/skill-pack/template/build/SKILL.md +13 -2
- package/skill-pack/template/build/references/evidence.md +2 -2
- package/dist/chunk-PVC36MFI.js +0 -103
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,26 @@
|
|
|
1
1
|
# @outerlayer/cli
|
|
2
2
|
|
|
3
|
+
## 0.10.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 60067bc: `outerlayer work pr` and `outerlayer work open-pr` now declare a pull request onto the work item named by `OUTERLAYER_WORK`, and refuse when the session is not on that item. The message names both item numbers and `--session-id`. A successful declaration prints the item's number and title. `outerlayer work pr <n> --withdraw --item <number>` removes a wrong declaration.
|
|
8
|
+
|
|
9
|
+
## 0.9.0
|
|
10
|
+
|
|
11
|
+
### Minor Changes
|
|
12
|
+
|
|
13
|
+
- a44097e: A runner now reads a governed repository's control plane with a read-only GitHub App token that the gateway issues for the build, so the host needs no git login for it. A gateway with no GitHub App still uses the host's git login. `outerlayer doctor` passes `Control plane access` through the App when the gateway has one. The runner protocol is now 15.
|
|
14
|
+
|
|
15
|
+
### Patch Changes
|
|
16
|
+
|
|
17
|
+
- accf74c: The amend skill now answers each criterion thread a reviewer sent a note on, replying on that thread and handing it back with `--ready`, instead of answering only the general thread.
|
|
18
|
+
- 680086e: `outerlayer init` now says to commit and push `.outerlayer/` whenever it left files there, even when a step failed or the repository is not linked yet. `outerlayer connect` says the same when it succeeds and `.outerlayer/` holds uncommitted files.
|
|
19
|
+
- 279f42a: `outerlayer runner init` on a Mac now creates a Linux VM, installs Node and the CLI in it, and sets up the runner there. It prints a progress line every 30 seconds while the image downloads.
|
|
20
|
+
- d399d98: Inside a runner build, sessions, artifacts, findings and results name the repository again, for example `github.com/acme/app`. Previously they named the runner's git relay, `127.0.0.1:<port>/github.com/acme/app`. With the relay address, `outerlayer emit artifact --pr <n>` was refused with `item_key_out_of_scope`, and a session-bound artifact never attached to its pull request. When a git `insteadOf` rule rewrites a remote onto a loopback address, the CLI now reads the remote's URL as configured. Every other rewrite, such as a shorthand alias, is still followed.
|
|
21
|
+
- dfb4b76: The runner no longer maps a `gitlab` tracker to a repository host, and `gitlab` is no longer an accepted work-item tracker. GitHub, Linear and Jira remain.
|
|
22
|
+
- 80174a6: `outerlayer work release --item <n>`, run inside a session with no `--host`, now releases that session's own lease on the item, so a person can review a finished local build without closing the session. It never releases another session's lease. `--session-id` names the session when it cannot be detected, and `--host` keeps the release to a host's claim. The `build` template skill runs it as its last step.
|
|
23
|
+
|
|
3
24
|
## 0.8.6
|
|
4
25
|
|
|
5
26
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -74,8 +74,10 @@ content:
|
|
|
74
74
|
hook spawns `outerlayer work link-session` when you launch a session with
|
|
75
75
|
`OUTERLAYER_WORK`, naming the item and the session id — the item itself
|
|
76
76
|
must already exist, created ahead of time with `outerlayer work build --local`.
|
|
77
|
-
`outerlayer work pr` sends the session id
|
|
78
|
-
repository — never the session's
|
|
77
|
+
`outerlayer work pr` sends the session id, the `OUTERLAYER_WORK` item
|
|
78
|
+
number and the pull request number and repository — never the session's
|
|
79
|
+
own content. With `--withdraw` it sends a DELETE naming the item, the
|
|
80
|
+
repository and the pull request number. `outerlayer work open-pr`
|
|
79
81
|
sends the pull request's title and the text of the body file you name. In a
|
|
80
82
|
host build, which holds an item key, it goes to the gateway, which opens or
|
|
81
83
|
edits the pull request as the factory's GitHub App on the branch the claim
|
|
@@ -108,7 +110,8 @@ content:
|
|
|
108
110
|
evidence verdict, before releasing it: it sends nothing but the request.
|
|
109
111
|
Just before that read, the runner runs the repository's host checks. A host
|
|
110
112
|
check is a command the repository's `where: host` validators declare. The
|
|
111
|
-
runner reads the definitions
|
|
113
|
+
runner reads the definitions, through a control-plane token when the gateway
|
|
114
|
+
issues one and otherwise with the host's own git credentials, runs each
|
|
112
115
|
command in a new container, and sends one `POST /v1/emitted-results` for
|
|
113
116
|
each: the check's name, pass or fail, and for a fail the exit status and the
|
|
114
117
|
last line of its output, scrubbed.
|
|
@@ -220,12 +223,17 @@ content:
|
|
|
220
223
|
- **`outerlayer runner start` with `builtin:container` hooks** also asks your
|
|
221
224
|
gateway which repository governs the item's repository (`GET
|
|
222
225
|
/v1/context/source`, signed with the host key), after the recipe's
|
|
223
|
-
lifecycle commands. When one does, the runner
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
226
|
+
lifecycle commands. When one does, the runner asks your gateway for a
|
|
227
|
+
read-only token for that control plane (`POST /v1/work-items/{id}/claim/tokens`
|
|
228
|
+
with `target: control_plane`, signed with the host key), runs `git fetch`
|
|
229
|
+
against it on the host with that token, and copies its context into the
|
|
230
|
+
checkout through the build's directory. The token goes to git in its
|
|
231
|
+
environment for that one fetch, never to disk, a log or the build. The runner
|
|
232
|
+
revokes it when the attempt ends. A gateway with no GitHub App issues none,
|
|
233
|
+
and the fetch then uses the host's own git credentials. The build receives
|
|
234
|
+
files and no credential for the control plane. The runner deletes the staged
|
|
235
|
+
copy before the command starts. A host that cannot read the control plane
|
|
236
|
+
fails the build at provision.
|
|
229
237
|
- **`outerlayer runner start` with `builtin:process` hooks** runs each build
|
|
230
238
|
as a process under the runner's own user, with no isolation, and the
|
|
231
239
|
attempt records `shared-user`. The runner clones the item's repository
|
|
@@ -269,9 +277,11 @@ content:
|
|
|
269
277
|
say whether the version the runner's images pin is behind. The request
|
|
270
278
|
names the package and nothing about the host. On a host with
|
|
271
279
|
`builtin:container` hooks it also asks your gateway which repository governs
|
|
272
|
-
each repository in `repos.include` (`GET /v1/context/source`)
|
|
273
|
-
|
|
274
|
-
|
|
280
|
+
each repository in `repos.include` (`GET /v1/context/source`). When the
|
|
281
|
+
gateway has a GitHub App (`GET /v1/repositories/access` does not answer
|
|
282
|
+
`repository_tokens_unavailable`), builds read the control plane through it.
|
|
283
|
+
Otherwise doctor runs `git ls-remote` against the control plane with the
|
|
284
|
+
host's own git credentials, to say whether the host can read it.
|
|
275
285
|
- **`outerlayer emit artifact`** uploads the file you name — a screenshot, a
|
|
276
286
|
recording, a report, a log — along with its caption, its name, type, size
|
|
277
287
|
and sha256, and the repository, branch, commit, pull request and CI run it
|
|
@@ -367,11 +377,11 @@ before it gives up.
|
|
|
367
377
|
| `outerlayer work remove --issue <n>\|--pr <n> --reason <text> [--repo]` | Withdraws the caller's own addition, recording the reason. Never deletes anything; the item leaves the Work page only once no live addition remains on it. Removing again is a no-op that still succeeds. |
|
|
368
378
|
| `outerlayer work status --issue <n>\|--pr <n> [--repo]` | Shows one item's stage, section, gate ledger, linked pull requests and sessions, and its additions. |
|
|
369
379
|
| `outerlayer work list [--stage] [--section] [--repo] [--claimed] [--unclaimed] [--startable] [--needs amend]` | Lists live work items for the current factory, filterable by stage, section, claim state, startability and whether a comment thread is waiting on an agent. |
|
|
370
|
-
| `outerlayer work pr <n> [--repo] [--session-id]` | Run inside a session on a work item: declares that pull request `<n>` in the checkout's repository belongs to
|
|
380
|
+
| `outerlayer work pr <n> [--repo] [--session-id] [--withdraw --item <number>]` | Run inside a session on a work item: declares that pull request `<n>` in the checkout's repository belongs to the `OUTERLAYER_WORK` item. Idempotent — declaring the same pull request twice is a no-op. Refuses when the session is not on that item, or the repository is not connected. `--withdraw --item <number>` removes that item's declaration; it needs your own login. |
|
|
371
381
|
| `outerlayer work open-pr --title <text> --body-file <path> [--repo] [--session-id] [--json]` | Opens the pull request for the work item this session is on, or edits the one already open on its branch. A host build, which holds an item key, sends it to the gateway, which opens it as the factory's GitHub App from the branch the claim named; no `gh` command runs. Your own session runs `gh pr create` or `gh pr edit` under your login and then declares the pull request on the item. Run it again after changing the title or description. |
|
|
372
382
|
| `outerlayer work claim --item <n>\|--issue <n> --kind implement\|amend [--repo] [--host] [--seconds]` | Records a lease for this host (default: its own hostname), so two hosts never build the same item at once. The lease belongs to the runner key that claimed it: a live lease held by a different key is refused, even under the same host name, and claiming again with the same key extends it. The first claim creates the host key (`host-key.pem` beside the config file) and binds the runner key to it; from then on every request made with that key is signed. Lease length defaults to 900 seconds, the server's own cap. |
|
|
373
383
|
| `outerlayer work renew --item <n>\|--issue <n> [--repo] [--host] [--seconds]` | Extends this host's own live lease. Refused if the lease has expired, or if a different runner key holds it (403 `claim_not_held`). |
|
|
374
|
-
| `outerlayer work release --item <n>\|--issue <n> [--repo] [--host] [--outcome]` | Marks the lease this API key holds released, optionally recording how the attempt ended. Releasing an already-released lease is a no-op that returns the recorded release time and outcome. |
|
|
384
|
+
| `outerlayer work release --item <n>\|--issue <n> [--repo] [--host] [--session-id] [--outcome]` | Marks the lease this API key holds released, optionally recording how the attempt ended. Releasing an already-released lease is a no-op that returns the recorded release time and outcome. Run inside a session with no `--host`, it releases that session's own lease instead (`--session-id` names the session when it cannot be detected), so the item's review opens without ending the session. |
|
|
375
385
|
| `outerlayer runner init [--vm\|--no-vm] [--config <path>]` | Writes a `runner` block with defaults, keeping every key the config already had. It names `builtin:vm` on a Linux machine where the user can use `/dev/kvm` and Docker Engine can build images once the guest kernel and helper are published (not yet), `builtin:container` on that machine until then, `builtin:container` on any other machine with Docker Engine, and `builtin:process` on one without, and writes no hook script. Refuses rather than overwriting an existing block. On macOS it asks whether to create a Linux VM with Lima, installs Docker Engine and the runner in it, and starts both at login; `--vm` answers yes and `--no-vm` answers no, and a run with no terminal answers no. The runner key and the host key then live only in the VM: the Mac's config loses `apiKey` and `runner` and gains a `runnerVm` note, which `outerlayer doctor` reads. |
|
|
376
386
|
| `outerlayer runner check [--config <path>]` | Validates the config, the hooks and the key, prints the settings the runner would use, and exits non-zero on a problem. Takes no work and writes no pid file. |
|
|
377
387
|
| `outerlayer runner start [--config <path>]` | Runs the loop: claim work, run it, sync, clean up, report, release with an outcome. Repeat. Reads the `runner` block from the config file (default `~/.outerlayer/config.json`). Refuses to start on a bad config, an unrunnable hook, or a refused key. |
|
|
@@ -1,18 +1,19 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
3
|
import { addStdioMcpEntryIfAbsent } from './chunk-47RS42OZ.js';
|
|
4
|
-
import { installStarterPack } from './chunk-
|
|
5
|
-
import { runEmit } from './chunk-
|
|
4
|
+
import { installStarterPack } from './chunk-SUMWRA7K.js';
|
|
5
|
+
import { runEmit } from './chunk-YU5GL7QS.js';
|
|
6
6
|
import { C } from './chunk-YRYMNBGQ.js';
|
|
7
|
-
import { resolveGitCommonDir, defaultGitRunner } from './chunk-
|
|
7
|
+
import { resolveGitCommonDir, defaultGitRunner } from './chunk-RWQWPZB4.js';
|
|
8
8
|
import './chunk-ZJSNLVCE.js';
|
|
9
|
-
import { pinExists, readContextManifest } from './chunk-
|
|
10
|
-
import { loadTemplateFiles, loadMaintainedFiles, skillDir } from './chunk-
|
|
11
|
-
import { generatedHeaderSource } from './chunk-
|
|
9
|
+
import { pinExists, readContextManifest } from './chunk-BMX3L7CR.js';
|
|
10
|
+
import { loadTemplateFiles, loadMaintainedFiles, skillDir } from './chunk-BGWTYRSS.js';
|
|
11
|
+
import { generatedHeaderSource } from './chunk-TB7EP24C.js';
|
|
12
12
|
import './chunk-YO4PSLVB.js';
|
|
13
13
|
import './chunk-PLMTLGYH.js';
|
|
14
|
-
import './chunk-
|
|
14
|
+
import './chunk-YT35WGIP.js';
|
|
15
15
|
import './chunk-EABW6AJQ.js';
|
|
16
|
+
import './chunk-BYT5O5RV.js';
|
|
16
17
|
import './chunk-RA3O54FC.js';
|
|
17
18
|
import './chunk-V7NIVOFD.js';
|
|
18
19
|
import './chunk-ZM2IMMYN.js';
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
|
-
export { buildRepositoryImage } from './chunk-
|
|
3
|
+
export { buildRepositoryImage } from './chunk-3FMPZPJQ.js';
|
|
4
4
|
import './chunk-N5FOE5PS.js';
|
|
5
5
|
export { RecipeError } from './chunk-QOZKPLVJ.js';
|
|
6
6
|
import './chunk-CX22S5BA.js';
|
|
7
|
-
import './chunk-
|
|
7
|
+
import './chunk-BYT5O5RV.js';
|
|
8
8
|
import './chunk-ZM2IMMYN.js';
|
|
9
9
|
import './chunk-Z5GEFMRW.js';
|
|
10
10
|
|
package/dist/build-info.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"id":"2026-10-
|
|
1
|
+
{"id":"2026-10-07T12:35:00.915Z+be9473d","root":"/home/runner/_work/outerlayer/outerlayer","pkg":"outerlayer"}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
|
-
export { MIN_BUILDX_VERSION, builderName, builderSpec, buildxState, ensureBuilder, ensureFailureCount, isOutOfMemory, proxyEnvironment, trackImageBuild } from './chunk-
|
|
3
|
+
export { MIN_BUILDX_VERSION, builderName, builderSpec, buildxState, ensureBuilder, ensureFailureCount, isOutOfMemory, proxyEnvironment, trackImageBuild } from './chunk-TV36SKEN.js';
|
|
4
4
|
import './chunk-CX22S5BA.js';
|
|
5
|
-
import './chunk-
|
|
5
|
+
import './chunk-LTJPX7TX.js';
|
|
6
6
|
import './chunk-7RQ73DLO.js';
|
|
7
|
-
import './chunk-
|
|
8
|
-
import './chunk-
|
|
9
|
-
import './chunk-
|
|
7
|
+
import './chunk-M6G7TJVF.js';
|
|
8
|
+
import './chunk-YT35WGIP.js';
|
|
9
|
+
import './chunk-BYT5O5RV.js';
|
|
10
10
|
import './chunk-ZM2IMMYN.js';
|
|
11
11
|
import './chunk-Z5GEFMRW.js';
|
|
12
12
|
|
|
@@ -1,73 +1,83 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
|
-
import { probeCredentials } from './chunk-
|
|
4
|
-
import './chunk-
|
|
3
|
+
import { probeCredentials } from './chunk-YCPV7FN6.js';
|
|
4
|
+
import './chunk-3JVYMD4G.js';
|
|
5
5
|
import './chunk-I2UOAV7X.js';
|
|
6
|
-
import './chunk-
|
|
6
|
+
import './chunk-ABIWDUMS.js';
|
|
7
|
+
import './chunk-OSKO3PAL.js';
|
|
7
8
|
import './chunk-T6OIJQRT.js';
|
|
8
|
-
import './chunk-
|
|
9
|
+
import './chunk-PDTSUOVT.js';
|
|
9
10
|
import './chunk-UGP76IZ5.js';
|
|
10
|
-
import './chunk-
|
|
11
|
-
import './chunk-
|
|
12
|
-
import './chunk-
|
|
11
|
+
import './chunk-VMK7I3TB.js';
|
|
12
|
+
import './chunk-V42JY4F6.js';
|
|
13
|
+
import './chunk-543OT6V5.js';
|
|
13
14
|
import './chunk-HHJDN6AU.js';
|
|
14
|
-
import { placeholderQueues, placeholderProblem, needsClaudeCredential, claudeCredentialCheck, claimPermissionProblem } from './chunk-
|
|
15
|
+
import { placeholderQueues, placeholderProblem, permissionModeProblems, permissionModeProblem, needsClaudeCredential, claudeCredentialCheck, claimPermissionProblem } from './chunk-XGCJNSI7.js';
|
|
15
16
|
import './chunk-TI7B7UEO.js';
|
|
16
17
|
import './chunk-YYYRBYWG.js';
|
|
17
18
|
import './chunk-TBT347UY.js';
|
|
18
|
-
import './chunk-
|
|
19
|
-
import './chunk-
|
|
20
|
-
import './chunk-
|
|
19
|
+
import './chunk-WJBJY5DQ.js';
|
|
20
|
+
import './chunk-QPPPUKQJ.js';
|
|
21
|
+
import './chunk-LBU4CLK5.js';
|
|
22
|
+
import { parseRunnerEnv } from './chunk-6MZSX4M7.js';
|
|
21
23
|
import './chunk-JKIWMRFH.js';
|
|
22
|
-
import './chunk-
|
|
24
|
+
import './chunk-3FMPZPJQ.js';
|
|
23
25
|
import './chunk-N5FOE5PS.js';
|
|
24
26
|
import './chunk-OGFGZQA3.js';
|
|
25
|
-
import './chunk-
|
|
27
|
+
import './chunk-FKFGQJNN.js';
|
|
26
28
|
import './chunk-QOZKPLVJ.js';
|
|
27
|
-
import './chunk-
|
|
29
|
+
import './chunk-TV36SKEN.js';
|
|
28
30
|
import './chunk-CX22S5BA.js';
|
|
29
|
-
import './chunk-
|
|
30
|
-
import './chunk-
|
|
31
|
+
import './chunk-6CXYORUS.js';
|
|
32
|
+
import './chunk-S6IUUNCD.js';
|
|
31
33
|
import './chunk-F7CU5ABH.js';
|
|
32
34
|
import './chunk-BKO6JEZI.js';
|
|
33
|
-
import './chunk-
|
|
34
|
-
import './chunk-
|
|
35
|
+
import './chunk-KWCJLAHQ.js';
|
|
36
|
+
import './chunk-KPUJGBA4.js';
|
|
35
37
|
import './chunk-BFESLKPP.js';
|
|
36
|
-
import './chunk-
|
|
37
|
-
import './chunk-
|
|
38
|
-
import './chunk-
|
|
38
|
+
import './chunk-LYESSQUA.js';
|
|
39
|
+
import './chunk-ZEQMTBRD.js';
|
|
40
|
+
import './chunk-LTJPX7TX.js';
|
|
39
41
|
import './chunk-USO2DKBD.js';
|
|
40
42
|
import './chunk-N6LURUEF.js';
|
|
41
43
|
import './chunk-YRYMNBGQ.js';
|
|
42
|
-
import { loadRunnerConfig, RunnerConfigError, checkHooks } from './chunk-
|
|
44
|
+
import { loadRunnerConfig, RunnerConfigError, checkHooks } from './chunk-M2PBLRB7.js';
|
|
43
45
|
import './chunk-UXYLWVTQ.js';
|
|
44
46
|
import './chunk-7RQ73DLO.js';
|
|
45
|
-
import './chunk-
|
|
46
|
-
import './chunk-HKMPVPO7.js';
|
|
47
|
+
import './chunk-M6G7TJVF.js';
|
|
47
48
|
import './chunk-GQD22KKN.js';
|
|
48
49
|
import './chunk-WZBHBH3J.js';
|
|
49
50
|
import './chunk-5QRP3MVS.js';
|
|
50
|
-
import './chunk-
|
|
51
|
+
import './chunk-RWQWPZB4.js';
|
|
51
52
|
import './chunk-ZJSNLVCE.js';
|
|
52
|
-
import './chunk-
|
|
53
|
-
import './chunk-
|
|
54
|
-
import './chunk-
|
|
53
|
+
import './chunk-BMX3L7CR.js';
|
|
54
|
+
import './chunk-BGWTYRSS.js';
|
|
55
|
+
import './chunk-TB7EP24C.js';
|
|
55
56
|
import './chunk-YO4PSLVB.js';
|
|
56
57
|
import './chunk-PLMTLGYH.js';
|
|
57
|
-
import './chunk-
|
|
58
|
+
import './chunk-YT35WGIP.js';
|
|
58
59
|
import './chunk-EABW6AJQ.js';
|
|
60
|
+
import './chunk-BYT5O5RV.js';
|
|
59
61
|
import './chunk-RA3O54FC.js';
|
|
60
62
|
import './chunk-V7NIVOFD.js';
|
|
61
63
|
import './chunk-ZM2IMMYN.js';
|
|
62
|
-
import './chunk-
|
|
64
|
+
import './chunk-4HMXH2OA.js';
|
|
63
65
|
import './chunk-XCCLFVXM.js';
|
|
64
66
|
import './chunk-BJ3KTMDH.js';
|
|
65
67
|
import './chunk-VNVZDWO3.js';
|
|
66
68
|
import './chunk-Z5GEFMRW.js';
|
|
69
|
+
import { readFileSync } from 'fs';
|
|
70
|
+
import { join, dirname } from 'path';
|
|
67
71
|
|
|
68
72
|
createRequire(import.meta.url);
|
|
69
|
-
|
|
70
|
-
|
|
73
|
+
function readRunnerEnv(path) {
|
|
74
|
+
try {
|
|
75
|
+
return { env: parseRunnerEnv(readFileSync(path, "utf8")) };
|
|
76
|
+
} catch (err) {
|
|
77
|
+
if (err.code === "ENOENT") return { env: {} };
|
|
78
|
+
return { error: err instanceof Error ? err.message : String(err) };
|
|
79
|
+
}
|
|
80
|
+
}
|
|
71
81
|
async function runRunnerCheck(configPath, deps = {}) {
|
|
72
82
|
let config;
|
|
73
83
|
try {
|
|
@@ -81,11 +91,35 @@ async function runRunnerCheck(configPath, deps = {}) {
|
|
|
81
91
|
if (placeholders.length > 0) {
|
|
82
92
|
return { ok: false, check: "placeholders", message: `${configPath}: ${placeholderProblem(placeholders)}` };
|
|
83
93
|
}
|
|
94
|
+
const modeProblems = permissionModeProblems(config);
|
|
95
|
+
if (modeProblems.length > 0) {
|
|
96
|
+
return { ok: false, check: "permission mode", message: `${configPath}: ${permissionModeProblem(modeProblems)}` };
|
|
97
|
+
}
|
|
98
|
+
let credentialLine;
|
|
84
99
|
if (needsClaudeCredential(config.hooks)) {
|
|
85
|
-
const
|
|
100
|
+
const env = deps.env ?? process.env;
|
|
101
|
+
const runnerEnvPath = join(dirname(configPath), "runner.env");
|
|
102
|
+
const inShell = claudeCredentialCheck(env);
|
|
103
|
+
let credential = inShell;
|
|
104
|
+
if (inShell.status !== "pass") {
|
|
105
|
+
const fromFile = readRunnerEnv(runnerEnvPath);
|
|
106
|
+
if ("error" in fromFile) {
|
|
107
|
+
return {
|
|
108
|
+
ok: false,
|
|
109
|
+
check: "claude credential",
|
|
110
|
+
message: `the Claude credential is not in this shell, and ${runnerEnvPath} could not be read to look for it: ${fromFile.error}`
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
credential = claudeCredentialCheck(fromFile.env);
|
|
114
|
+
}
|
|
86
115
|
if (credential.status === "fail") {
|
|
87
|
-
return {
|
|
116
|
+
return {
|
|
117
|
+
ok: false,
|
|
118
|
+
check: "claude credential",
|
|
119
|
+
message: `${credential.detail}, in this shell or in ${runnerEnvPath}. ${credential.fix}`
|
|
120
|
+
};
|
|
88
121
|
}
|
|
122
|
+
credentialLine = `claude credential ${credential.detail}${inShell.status === "pass" ? "" : ` (read from ${runnerEnvPath})`}`;
|
|
89
123
|
}
|
|
90
124
|
const probe = await probeCredentials(config, deps.fetchImpl);
|
|
91
125
|
if (!probe.ok && probe.fatal) return { ok: false, check: "credentials", message: probe.reason };
|
|
@@ -103,6 +137,7 @@ async function runRunnerCheck(configPath, deps = {}) {
|
|
|
103
137
|
`time limit ${config.timeLimitMinutes}m`,
|
|
104
138
|
`idle limit ${config.idleLimitMinutes}m`,
|
|
105
139
|
`auto update ${config.autoUpdate ? "on" : "off"}`,
|
|
140
|
+
...credentialLine === void 0 ? [] : [credentialLine],
|
|
106
141
|
...config.queues.map((queue) => `command ${queue.padEnd(11)} ${config.commands[queue] ?? "(none)"}`),
|
|
107
142
|
`hook provision ${config.hooks.provision}`,
|
|
108
143
|
`hook cleanup ${config.hooks.cleanup}`,
|
|
@@ -3,7 +3,7 @@ import { createRequire } from 'node:module';
|
|
|
3
3
|
import { startTimeOf, claimPidFile, RunnerAlreadyRunningError, releasePidFile } from './chunk-N5FOE5PS.js';
|
|
4
4
|
import { RecipeError, locateRecipe, readRecipe, assertBuildable, writeSanitizedRecipe, classifyProperties, SANITIZED_NAME } from './chunk-QOZKPLVJ.js';
|
|
5
5
|
import { CLAUDE_CODE_VERSION, NODE_IMAGE, DEFAULT_BASE_IMAGE, TINI_VERSION, GH_VERSION, GH_SHA256, TINI_SHA256 } from './chunk-CX22S5BA.js';
|
|
6
|
-
import { withGitConfig } from './chunk-
|
|
6
|
+
import { withGitConfig, tokenHeader } from './chunk-BYT5O5RV.js';
|
|
7
7
|
import { RUNNER_DIR_MODE, repoCacheDir, imagesDir, attemptStamp, runnerDir, rootfsPathFor, RUNNER_FILE_MODE } from './chunk-ZM2IMMYN.js';
|
|
8
8
|
import { mkdirSync, rmSync, existsSync, mkdtempSync, cpSync, readFileSync, writeFileSync, readdirSync, lstatSync, readlinkSync } from 'fs';
|
|
9
9
|
import { tmpdir } from 'os';
|
|
@@ -18,9 +18,6 @@ function gitEnvironment(base) {
|
|
|
18
18
|
for (const name of INHERITED_REPOSITORY_VARIABLES) delete env[name];
|
|
19
19
|
return env;
|
|
20
20
|
}
|
|
21
|
-
function tokenHeader(token) {
|
|
22
|
-
return `Authorization: Basic ${Buffer.from(`x-access-token:${token}`).toString("base64")}`;
|
|
23
|
-
}
|
|
24
21
|
function tokenSettings(remote, token) {
|
|
25
22
|
return (env) => withGitConfig(env, `http.${remote}.extraHeader`, tokenHeader(token));
|
|
26
23
|
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { createRequire } from 'node:module';
|
|
3
|
+
|
|
4
|
+
createRequire(import.meta.url);
|
|
5
|
+
|
|
6
|
+
// src/runner/update/installed-switch.ts
|
|
7
|
+
function decideInstalledSwitch(input) {
|
|
8
|
+
const to = input.current;
|
|
9
|
+
if (to === void 0 || to === input.own || !input.fromCurrent) return { kind: "none" };
|
|
10
|
+
if (!input.installed) return { kind: "missing", to };
|
|
11
|
+
if (!input.underService) return { kind: "foreground", to };
|
|
12
|
+
return { kind: "restart", to };
|
|
13
|
+
}
|
|
14
|
+
function startedByService(env, parentPid) {
|
|
15
|
+
return (env.INVOCATION_ID ?? "") !== "" && parentPid === 1;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export { decideInstalledSwitch, startedByService };
|
|
@@ -439,6 +439,12 @@ async function missingRenewalHookContext(home, cwd) {
|
|
|
439
439
|
}
|
|
440
440
|
}
|
|
441
441
|
var WORK_LEASE_RENEW_DEBOUNCE_MS = 5 * 60 * 1e3;
|
|
442
|
+
function markWorkLeaseRenewed(sessionId, home = homeFromEnv(), now = Date.now()) {
|
|
443
|
+
try {
|
|
444
|
+
writeFileSync(join(spoolDir(home), `work-lease-renew-${sessionId}`), String(now));
|
|
445
|
+
} catch {
|
|
446
|
+
}
|
|
447
|
+
}
|
|
442
448
|
async function maybeRenewWorkLease(event, sessionId, home = homeFromEnv(), env = process.env, spawnImpl = spawnDetached, now = Date.now(), cwd = process.cwd()) {
|
|
443
449
|
try {
|
|
444
450
|
if (event !== "PostToolUse") return;
|
|
@@ -628,7 +634,7 @@ async function runHookFast(event, home = homeFromEnv(), read = readStdin, env =
|
|
|
628
634
|
recordHookErrorsSeen(home, hookErrorsBytes);
|
|
629
635
|
if (contextPossiblyGoverned(sessionCwd, home)) {
|
|
630
636
|
try {
|
|
631
|
-
const { materializeContext: materialize } = await import('./context-materialize-
|
|
637
|
+
const { materializeContext: materialize } = await import('./context-materialize-KQZYATQZ.js');
|
|
632
638
|
const sessionId = typeof payload.session_id === "string" ? payload.session_id : "unknown";
|
|
633
639
|
const result = await materialize({ cwd: sessionCwd, sessionId, home });
|
|
634
640
|
materializeMessage = result.message;
|
|
@@ -693,4 +699,4 @@ function recordLinkExitFailure(argv, home = homeFromEnv(), target = process) {
|
|
|
693
699
|
});
|
|
694
700
|
}
|
|
695
701
|
|
|
696
|
-
export { AUTO_SYNC_DEBOUNCE_MS, SYNC_STALE_AFTER_MS, WORK_LEASE_RENEW_DEBOUNCE_MS, WORK_LINK_RETRIES, assessSyncHealth, checkInstalledCliStaleness, contextPossiblyGoverned, formatAgo, handleWorkLaunch, handleWorkSessionEnd, hookFiredMarkerPath, installedCliDistDir, logHookError, maybeAutoSync, maybeRenewWorkLease, readSyncStatus, recordLinkExitFailure, refreshCommand, runHookFast, sanitizeForContext, spoolDir, workspaceRootOf, writeSyncStatus };
|
|
702
|
+
export { AUTO_SYNC_DEBOUNCE_MS, SYNC_STALE_AFTER_MS, WORK_LEASE_RENEW_DEBOUNCE_MS, WORK_LINK_RETRIES, assessSyncHealth, checkInstalledCliStaleness, contextPossiblyGoverned, formatAgo, handleWorkLaunch, handleWorkSessionEnd, hookFiredMarkerPath, installedCliDistDir, logHookError, markWorkLeaseRenewed, maybeAutoSync, maybeRenewWorkLease, readSyncStatus, recordLinkExitFailure, refreshCommand, runHookFast, sanitizeForContext, spoolDir, workspaceRootOf, writeSyncStatus };
|
|
@@ -4,17 +4,17 @@ import { LaunchFilter } from './chunk-HHJDN6AU.js';
|
|
|
4
4
|
import { RepoFilter } from './chunk-TBT347UY.js';
|
|
5
5
|
import { hookExecSpoolPath } from './chunk-F7CU5ABH.js';
|
|
6
6
|
import { applyReportedCost } from './chunk-BKO6JEZI.js';
|
|
7
|
-
import { migrateLegacyArtifactSidecars, planArtifactUpload, artifactsStatePath, sanitizeTerminal, artifactBlobsDir, resolveArtifactTurnIndex, isArtifactTombstoned, ARTIFACT_RETRY_MAX_AGE_MS, writeArtifactSpoolState, reclaimUnneededArtifactBlobs, neededArtifactShas } from './chunk-
|
|
8
|
-
import { setCustomScrubbers, setLocalIdentity, tailTranscript, enrichSessionRepo, scanAll, setRepoRoot, resolveRepoIdentity, sessionIdFromPath, scrubDeep, SOURCE_ADAPTERS } from './chunk-
|
|
7
|
+
import { migrateLegacyArtifactSidecars, planArtifactUpload, artifactsStatePath, sanitizeTerminal, artifactBlobsDir, resolveArtifactTurnIndex, isArtifactTombstoned, ARTIFACT_RETRY_MAX_AGE_MS, writeArtifactSpoolState, reclaimUnneededArtifactBlobs, neededArtifactShas } from './chunk-ZEQMTBRD.js';
|
|
8
|
+
import { setCustomScrubbers, setLocalIdentity, tailTranscript, enrichSessionRepo, scanAll, setRepoRoot, resolveRepoIdentity, sessionIdFromPath, scrubDeep, SOURCE_ADAPTERS } from './chunk-LTJPX7TX.js';
|
|
9
9
|
import { C } from './chunk-YRYMNBGQ.js';
|
|
10
10
|
import { readLaunchSpoolState, launchStatusIsDecisive, launchedItemsBySession, launchesPath } from './chunk-GQD22KKN.js';
|
|
11
11
|
import { readLatestProvenanceForSession, readContextProvenance } from './chunk-ZJSNLVCE.js';
|
|
12
12
|
import { defaultFetch } from './chunk-YO4PSLVB.js';
|
|
13
13
|
import { resolveGatewayCredentials, unauthorizedMessage } from './chunk-PLMTLGYH.js';
|
|
14
|
-
import { CAPTURE_TIERS, inferArtifactKind, bannedPathsForTier, downconvertSession, isHumanUserTurn, turnCountBound, EVENT_TYPES } from './chunk-
|
|
14
|
+
import { CAPTURE_TIERS, inferArtifactKind, bannedPathsForTier, downconvertSession, isHumanUserTurn, turnCountBound, EVENT_TYPES } from './chunk-YT35WGIP.js';
|
|
15
15
|
import { readCloudConfig, cloudConfigPath, writeCloudConfig } from './chunk-EABW6AJQ.js';
|
|
16
16
|
import { signerFor, signRunnerRequest } from './chunk-V7NIVOFD.js';
|
|
17
|
-
import { writeSyncStatus, spoolDir } from './chunk-
|
|
17
|
+
import { writeSyncStatus, spoolDir } from './chunk-4HMXH2OA.js';
|
|
18
18
|
import { removeJournalHooks } from './chunk-XCCLFVXM.js';
|
|
19
19
|
import { readRepoConnection, findGitDirs } from './chunk-BJ3KTMDH.js';
|
|
20
20
|
import { homeFromEnv } from './chunk-VNVZDWO3.js';
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { createRequire } from 'node:module';
|
|
3
|
+
import { autoConnect } from './chunk-KPUJGBA4.js';
|
|
4
|
+
import { detectActiveSession } from './chunk-BFESLKPP.js';
|
|
5
|
+
import { resolveRepoIdentity } from './chunk-LTJPX7TX.js';
|
|
6
|
+
import { parseWorkItemEnv } from './chunk-GQD22KKN.js';
|
|
7
|
+
import { parseTrackerNumber, trackerNumberError } from './chunk-WZBHBH3J.js';
|
|
8
|
+
import { defaultFetch } from './chunk-YO4PSLVB.js';
|
|
9
|
+
import { unauthorizedMessage, resolveGatewayCredentials } from './chunk-PLMTLGYH.js';
|
|
10
|
+
import { homeFromEnv } from './chunk-VNVZDWO3.js';
|
|
11
|
+
|
|
12
|
+
createRequire(import.meta.url);
|
|
13
|
+
|
|
14
|
+
// src/work-pr-cmd.ts
|
|
15
|
+
var GREEN = "\x1B[32m";
|
|
16
|
+
var DIM = "\x1B[2m";
|
|
17
|
+
var RESET = "\x1B[0m";
|
|
18
|
+
var WorkPrCommandError = class extends Error {
|
|
19
|
+
};
|
|
20
|
+
function resolveCredentials(opts) {
|
|
21
|
+
const resolved = resolveGatewayCredentials(opts);
|
|
22
|
+
if (!resolved.ok) throw new WorkPrCommandError(resolved.message);
|
|
23
|
+
return { url: resolved.url, apiKey: resolved.credential, appId: resolved.appId };
|
|
24
|
+
}
|
|
25
|
+
function resolveRepository(repoFlag, cwd) {
|
|
26
|
+
if (repoFlag) return repoFlag;
|
|
27
|
+
const identity = resolveRepoIdentity(cwd);
|
|
28
|
+
if (identity.gitRepo) return identity.gitRepo;
|
|
29
|
+
throw new WorkPrCommandError(
|
|
30
|
+
"no repository. Pass --repo <owner/name>, or run from a git checkout with a remote."
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
function resolvePrNumber(raw) {
|
|
34
|
+
const n = parseTrackerNumber(raw);
|
|
35
|
+
if (n === void 0) throw new WorkPrCommandError(trackerNumberError("<n>", raw ?? ""));
|
|
36
|
+
return n;
|
|
37
|
+
}
|
|
38
|
+
var SESSION_ID_HINT = "pass --session-id <id> to name the session that was launched on the item";
|
|
39
|
+
function sessionNotOnItemMessage(error, sessionId) {
|
|
40
|
+
const on = error.sessionItems;
|
|
41
|
+
const onText = on === void 0 ? "" : `; it is on ${on.length === 0 ? "no work item" : on.map((n) => `item ${n}`).join(", ")}`;
|
|
42
|
+
return `session ${sessionId} is not on item ${error.workItem ?? "?"} (OUTERLAYER_WORK)${onText}. Nothing was declared. If another session was launched for item ${error.workItem ?? "?"}, ${SESSION_ID_HINT}.`;
|
|
43
|
+
}
|
|
44
|
+
function itemLabel(data) {
|
|
45
|
+
if (data.workItemNumber == null) return data.workItemId;
|
|
46
|
+
return data.workItemTitle ? `item ${data.workItemNumber} ${DIM}\xB7${RESET} ${data.workItemTitle}` : `item ${data.workItemNumber}`;
|
|
47
|
+
}
|
|
48
|
+
async function runWorkPrWithdraw(opts, ctx) {
|
|
49
|
+
const itemNumber = parseTrackerNumber(opts.item);
|
|
50
|
+
if (itemNumber === void 0) {
|
|
51
|
+
throw new WorkPrCommandError("--withdraw needs --item <number>, the item to remove the declaration from.");
|
|
52
|
+
}
|
|
53
|
+
const { creds, prNumber, repository, sessionId } = ctx;
|
|
54
|
+
const fetchImpl = opts.fetchImpl ?? defaultFetch;
|
|
55
|
+
const query = sessionId === void 0 ? "" : `?sessionId=${encodeURIComponent(sessionId)}`;
|
|
56
|
+
const endpoint = new URL(
|
|
57
|
+
`/v1/work-items/${itemNumber}/pull-requests/${encodeURIComponent(repository)}/${prNumber}${query}`,
|
|
58
|
+
creds.url
|
|
59
|
+
).toString();
|
|
60
|
+
let response;
|
|
61
|
+
try {
|
|
62
|
+
response = await fetchImpl(endpoint, {
|
|
63
|
+
method: "DELETE",
|
|
64
|
+
headers: { authorization: `Bearer ${creds.apiKey}`, "x-outerlayer-app-id": creds.appId }
|
|
65
|
+
});
|
|
66
|
+
} catch (err) {
|
|
67
|
+
throw new WorkPrCommandError(`network error reaching ${endpoint}: ${String(err)}`);
|
|
68
|
+
}
|
|
69
|
+
if (response.status === 401) throw new WorkPrCommandError(unauthorizedMessage(creds.apiKey));
|
|
70
|
+
let json;
|
|
71
|
+
try {
|
|
72
|
+
json = await response.json();
|
|
73
|
+
} catch {
|
|
74
|
+
throw new WorkPrCommandError(
|
|
75
|
+
`${endpoint} answered ${response.status} with a body that is not JSON \u2014 the request may not have reached the gateway`
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
if (!response.ok || !json.data) {
|
|
79
|
+
if (json.error?.code === "withdraw_needs_person") {
|
|
80
|
+
throw new WorkPrCommandError("only a person can withdraw a declaration; run this from your own login, not an agent session or a factory key.");
|
|
81
|
+
}
|
|
82
|
+
if (json.error?.code === "declaration_not_found") {
|
|
83
|
+
throw new WorkPrCommandError(`item ${itemNumber} has no declaration of ${repository}#${prNumber}.`);
|
|
84
|
+
}
|
|
85
|
+
if (json.error?.code === "work_item_not_found") {
|
|
86
|
+
throw new WorkPrCommandError(`item ${itemNumber} does not exist in this factory.`);
|
|
87
|
+
}
|
|
88
|
+
throw new WorkPrCommandError(json.error?.message ?? `request failed (${response.status})`);
|
|
89
|
+
}
|
|
90
|
+
const data = json.data;
|
|
91
|
+
const output = opts.json ? JSON.stringify(data) : `${GREEN}\u2713${RESET} withdrawn ${DIM}\xB7${RESET} ${data.repository}#${data.prNumber} ${DIM}from${RESET} item ${itemNumber}`;
|
|
92
|
+
if (!opts.quiet) process.stdout.write(output + "\n");
|
|
93
|
+
return { data, output };
|
|
94
|
+
}
|
|
95
|
+
async function runWorkPr(opts) {
|
|
96
|
+
const cwd = opts.cwd ?? process.cwd();
|
|
97
|
+
const env = opts.env ?? process.env;
|
|
98
|
+
const home = opts.home ?? homeFromEnv(env);
|
|
99
|
+
const refusal = await autoConnect({ ...opts, repository: opts.repo });
|
|
100
|
+
if (refusal !== void 0) throw new WorkPrCommandError(refusal);
|
|
101
|
+
const creds = resolveCredentials(opts);
|
|
102
|
+
const prNumber = resolvePrNumber(opts.number);
|
|
103
|
+
const repository = resolveRepository(opts.repo, cwd);
|
|
104
|
+
const identity = resolveRepoIdentity(cwd);
|
|
105
|
+
const sessionId = opts.sessionId ?? detectActiveSession({
|
|
106
|
+
env,
|
|
107
|
+
home,
|
|
108
|
+
cwds: identity.repoRoot !== void 0 ? [identity.repoRoot, cwd] : [cwd],
|
|
109
|
+
nowMs: Date.now()
|
|
110
|
+
});
|
|
111
|
+
if (opts.withdraw) return runWorkPrWithdraw(opts, { creds, prNumber, repository, sessionId });
|
|
112
|
+
let workItem;
|
|
113
|
+
if (env.OUTERLAYER_WORK !== void 0) {
|
|
114
|
+
const parsed = parseWorkItemEnv(env.OUTERLAYER_WORK);
|
|
115
|
+
if (!("number" in parsed)) throw new WorkPrCommandError(parsed.reason);
|
|
116
|
+
workItem = parsed.number;
|
|
117
|
+
}
|
|
118
|
+
if (sessionId === void 0) {
|
|
119
|
+
throw new WorkPrCommandError(
|
|
120
|
+
`no active session detected. \`work pr\` declares a pull request from inside the session that opened it, or ${SESSION_ID_HINT}.`
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
const fetchImpl = opts.fetchImpl ?? defaultFetch;
|
|
124
|
+
const headers = {
|
|
125
|
+
"content-type": "application/json",
|
|
126
|
+
authorization: `Bearer ${creds.apiKey}`,
|
|
127
|
+
"x-outerlayer-app-id": creds.appId
|
|
128
|
+
};
|
|
129
|
+
const endpoint = new URL("/v1/work-items/pull-requests", creds.url).toString();
|
|
130
|
+
let response;
|
|
131
|
+
try {
|
|
132
|
+
response = await fetchImpl(endpoint, {
|
|
133
|
+
method: "POST",
|
|
134
|
+
headers,
|
|
135
|
+
body: JSON.stringify({
|
|
136
|
+
sessionId,
|
|
137
|
+
workItem,
|
|
138
|
+
// JSON.stringify omits it when undefined
|
|
139
|
+
pullRequest: { repository, number: prNumber }
|
|
140
|
+
})
|
|
141
|
+
});
|
|
142
|
+
} catch (err) {
|
|
143
|
+
throw new WorkPrCommandError(`network error reaching ${endpoint}: ${String(err)}`);
|
|
144
|
+
}
|
|
145
|
+
if (response.status === 401) {
|
|
146
|
+
throw new WorkPrCommandError(
|
|
147
|
+
unauthorizedMessage(creds.apiKey)
|
|
148
|
+
);
|
|
149
|
+
}
|
|
150
|
+
let json;
|
|
151
|
+
try {
|
|
152
|
+
json = await response.json();
|
|
153
|
+
} catch {
|
|
154
|
+
throw new WorkPrCommandError(
|
|
155
|
+
`${endpoint} answered ${response.status} with a body that is not JSON \u2014 the request may not have reached the gateway`
|
|
156
|
+
);
|
|
157
|
+
}
|
|
158
|
+
if (!response.ok || !json.data) {
|
|
159
|
+
if (json.error?.code === "session_not_on_item") {
|
|
160
|
+
if (response.status === 409) throw new WorkPrCommandError(sessionNotOnItemMessage(json.error, sessionId));
|
|
161
|
+
throw new WorkPrCommandError("this session is not launched on a work item.");
|
|
162
|
+
}
|
|
163
|
+
if (json.error?.code === "work_item_not_found" && workItem !== void 0) {
|
|
164
|
+
throw new WorkPrCommandError(`OUTERLAYER_WORK names item ${workItem}, which does not exist in this factory.`);
|
|
165
|
+
}
|
|
166
|
+
if (json.error?.code === "repository_not_connected") {
|
|
167
|
+
throw new WorkPrCommandError(`${repository} is not a workpiece of this factory.`);
|
|
168
|
+
}
|
|
169
|
+
throw new WorkPrCommandError(json.error?.message ?? `request failed (${response.status})`);
|
|
170
|
+
}
|
|
171
|
+
const data = json.data;
|
|
172
|
+
const verb = data.created ? "declared" : "already declared";
|
|
173
|
+
const output = opts.json ? JSON.stringify(data) : `${GREEN}\u2713${RESET} ${verb} ${DIM}\xB7${RESET} ${data.repository}#${data.prNumber} ${DIM}\u2192${RESET} ${itemLabel(data)}`;
|
|
174
|
+
if (!opts.quiet) process.stdout.write(output + "\n");
|
|
175
|
+
return { data, output };
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
export { WorkPrCommandError, itemLabel, runWorkPr };
|