failproofai 1.0.2-beta.4 → 1.0.2-beta.5
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/.next/standalone/.next/BUILD_ID +1 -1
- package/.next/standalone/.next/build-manifest.json +5 -5
- package/.next/standalone/.next/prerender-manifest.json +3 -3
- package/.next/standalone/.next/required-server-files.json +1 -1
- package/.next/standalone/.next/server/app/_global-error/page/build-manifest.json +2 -2
- package/.next/standalone/.next/server/app/_global-error/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/_global-error/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/_global-error.html +1 -1
- package/.next/standalone/.next/server/app/_global-error.rsc +7 -7
- package/.next/standalone/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +6 -6
- package/.next/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +7 -7
- package/.next/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_not-found/page/build-manifest.json +2 -2
- package/.next/standalone/.next/server/app/_not-found/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/_not-found/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/_not-found.html +1 -1
- package/.next/standalone/.next/server/app/_not-found.rsc +14 -14
- package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +14 -14
- package/.next/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +13 -13
- package/.next/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/api/audit/invite/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/audit/run/route.js +4 -4
- package/.next/standalone/.next/server/app/api/audit/run/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/audit/status/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/auth/login-request/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/auth/login-verify/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/auth/logout/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/auth/status/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/download/[project]/[session]/route.js +1 -1
- package/.next/standalone/.next/server/app/api/download/[project]/[session]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/audit/page/build-manifest.json +2 -2
- package/.next/standalone/.next/server/app/audit/page/server-reference-manifest.json +2 -2
- package/.next/standalone/.next/server/app/audit/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/audit/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/index.html +1 -1
- package/.next/standalone/.next/server/app/index.rsc +14 -14
- package/.next/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +13 -13
- package/.next/standalone/.next/server/app/index.segments/_full.segment.rsc +14 -14
- package/.next/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/page/build-manifest.json +2 -2
- package/.next/standalone/.next/server/app/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/policies/page/build-manifest.json +2 -2
- package/.next/standalone/.next/server/app/policies/page/server-reference-manifest.json +14 -14
- package/.next/standalone/.next/server/app/policies/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/policies/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/project/[name]/page/build-manifest.json +2 -2
- package/.next/standalone/.next/server/app/project/[name]/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/project/[name]/page.js +2 -2
- package/.next/standalone/.next/server/app/project/[name]/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/project/[name]/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/build-manifest.json +2 -2
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/react-loadable-manifest.json +2 -2
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/server-reference-manifest.json +2 -2
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page.js +2 -2
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/projects/page/build-manifest.json +2 -2
- package/.next/standalone/.next/server/app/projects/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/projects/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/projects/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/settings/page/build-manifest.json +2 -2
- package/.next/standalone/.next/server/app/settings/page/server-reference-manifest.json +4 -4
- package/.next/standalone/.next/server/app/settings/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/settings/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__03r-lqq._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0o07qi9._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__12021ot._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1le9jqc._.js +3 -0
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0clqfab._.js → [root-of-the-server]__1zkek3z._.js} +2 -2
- package/.next/standalone/.next/server/chunks/_0lxbzdq._.js +1 -1
- package/.next/standalone/.next/server/chunks/{_1lbh81u._.js → _12moi5-._.js} +1 -1
- package/.next/standalone/.next/server/chunks/_1ek68ln._.js +5 -5
- package/.next/standalone/.next/server/chunks/_1zuiiy3._.js +1 -1
- package/.next/standalone/.next/server/chunks/package_json_[json]_cjs_1nxcc4v._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__1m84s36._.js → [root-of-the-server]__00-s7h8._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__013jr2b._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__01wy8d-._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__02npjtd._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__07gm3zl._.js +3 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0da85px._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0ftmoxc._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0oa1lav._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0p-5p8u._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0s740oi._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__14muoc4._.js → [root-of-the-server]__0stn0gx._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0jzbk4_._.js → [root-of-the-server]__190won8._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1ctpynv._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1p2otjt._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0rsd3ll._.js → [root-of-the-server]__1sc84bb._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/_08x1r5t._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/_1ddpc5g._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{_1db3-8n._.js → _1if9ixi._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/{_1dkh76z._.js → _1kesqs-._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/{_0ovx4lz._.js → _1km9-gn._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/_1u8-lu2._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/_1zopuov._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/app_audit__components_audit-dashboard_tsx_0p9ud47._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/app_global-error_tsx_1kp6l3x._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/app_policies_hooks-client_tsx_19dqvpc._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/app_settings_settings-client_tsx_20lq-mq._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/lib_1cf5ya2._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/lib_opencode-projects_ts_15bjxkm._.js +1 -1
- package/.next/standalone/.next/server/middleware-build-manifest.js +5 -5
- package/.next/standalone/.next/server/pages/404.html +1 -1
- package/.next/standalone/.next/server/pages/500.html +1 -1
- package/.next/standalone/.next/server/server-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/server-reference-manifest.json +19 -19
- package/.next/standalone/.next/static/chunks/{0lshnlpy1m6bc.js → 0tyt-3a5rtzy8.js} +1 -1
- package/.next/standalone/.next/static/chunks/{0ds64uculrze8.js → 21r7iw3rmixf5.js} +1 -1
- package/.next/standalone/.next/static/chunks/{07j2u70_3qsx8.js → 26lfjhb2kzzgb.js} +1 -1
- package/.next/standalone/.next/static/chunks/{2dbi_x0c8n8fi.js → 2_27jraat038x.js} +1 -1
- package/.next/standalone/.next/static/chunks/{0d_re32wscs0b.js → 2hwc8e923g5df.js} +1 -1
- package/.next/standalone/.next/static/chunks/{1q76jk_1_wgjq.js → 33np9nrh1mvj9.js} +1 -1
- package/.next/standalone/.next/static/chunks/{0k_yvjc1yz0pq.js → 36-8i_vbkh85w.js} +1 -1
- package/.next/standalone/.next/static/chunks/{1o0ahew9568ls.js → 391tpdqcas7rq.js} +1 -1
- package/.next/standalone/.next/static/chunks/{00_t-xvc59tkb.js → 3_b73tc78jwsq.js} +1 -1
- package/.next/standalone/.next/static/chunks/{1oz0svxwt9574.js → 3i8rg2fv9nd6e.js} +2 -2
- package/.next/standalone/.next/static/chunks/{2817_8e94ah9z.js → 3jqm8ubpv3i-4.js} +1 -1
- package/.next/standalone/.next/static/chunks/{turbopack-17utl_jw0wj11.js → turbopack-2x-o099q64i8h.js} +1 -1
- package/.next/standalone/lib/opencode-db.ts +77 -0
- package/.next/standalone/lib/opencode-projects.ts +37 -41
- package/.next/standalone/lib/opencode-sessions.ts +59 -36
- package/.next/standalone/package.json +9 -9
- package/.next/standalone/server.js +1 -1
- package/bin/failproofai.mjs +24 -9
- package/dist/cli.mjs +734 -382
- package/dist/worker.mjs +179 -164
- package/lib/opencode-db.ts +77 -0
- package/lib/opencode-projects.ts +37 -41
- package/lib/opencode-sessions.ts +59 -36
- package/package.json +9 -9
- package/src/audit/cache.ts +167 -11
- package/src/audit/cli-adapters/claude.ts +111 -1
- package/src/audit/cli-adapters/index.ts +31 -1
- package/src/audit/index.ts +131 -11
- package/src/hooks/manager.ts +50 -3
- package/src/hooks/pack-cli.ts +237 -11
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1l-khtb._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1mhmdzs._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1qxztj-._.js +0 -3
- /package/.next/standalone/.next/static/{0iNzkTsP6rh14Rj5WL17o → 59jsH11LoyXu9UBoHvgGM}/_buildManifest.js +0 -0
- /package/.next/standalone/.next/static/{0iNzkTsP6rh14Rj5WL17o → 59jsH11LoyXu9UBoHvgGM}/_clientMiddlewareManifest.js +0 -0
- /package/.next/standalone/.next/static/{0iNzkTsP6rh14Rj5WL17o → 59jsH11LoyXu9UBoHvgGM}/_ssgManifest.js +0 -0
package/src/hooks/pack-cli.ts
CHANGED
|
@@ -6,10 +6,10 @@
|
|
|
6
6
|
* This layer decides nothing; it formats.
|
|
7
7
|
*/
|
|
8
8
|
import { execFileSync } from "node:child_process";
|
|
9
|
-
import { homedir } from "node:os";
|
|
9
|
+
import { homedir, tmpdir } from "node:os";
|
|
10
10
|
import { createHash } from "node:crypto";
|
|
11
|
-
import { copyFileSync, existsSync, mkdirSync, readFileSync, readdirSync, statSync, writeFileSync } from "node:fs";
|
|
12
|
-
import { resolve } from "node:path";
|
|
11
|
+
import { copyFileSync, existsSync, mkdirSync, mkdtempSync, readFileSync, readdirSync, rmSync, statSync, writeFileSync } from "node:fs";
|
|
12
|
+
import { basename, dirname, join, resolve } from "node:path";
|
|
13
13
|
import { INTEGRATION_TYPES } from "./types";
|
|
14
14
|
import { PACK_VERSION_RE } from "./pack-manifest";
|
|
15
15
|
import { detectInstalledClis } from "./integrations";
|
|
@@ -354,6 +354,15 @@ export async function runPolicyPicker(
|
|
|
354
354
|
* policy that already RUNS and already blocks something real, so the first
|
|
355
355
|
* action is editing a working thing rather than authoring an empty one.
|
|
356
356
|
*/
|
|
357
|
+
/**
|
|
358
|
+
* A policy filename, whatever spelling it arrived in. Discovery takes
|
|
359
|
+
* `.mjs`/`.js`/`.ts` and nothing else, so a name with no extension has to gain
|
|
360
|
+
* one or the file it names can never be found.
|
|
361
|
+
*/
|
|
362
|
+
function withPolicyExtension(name: string): string {
|
|
363
|
+
return /\.(mjs|js|ts)$/.test(name) ? name : `${name}.mjs`;
|
|
364
|
+
}
|
|
365
|
+
|
|
357
366
|
async function scaffold(target: string | null): Promise<PackCliResult> {
|
|
358
367
|
// Ask what the pack is called when nothing was named and there is somebody to
|
|
359
368
|
// ask. The answer becomes the FILENAME and the header, so what lands on disk
|
|
@@ -374,9 +383,14 @@ async function scaffold(target: string | null): Promise<PackCliResult> {
|
|
|
374
383
|
stdout: process.stdout,
|
|
375
384
|
});
|
|
376
385
|
if (answer === null) return ok(["Nothing written."]);
|
|
377
|
-
chosen =
|
|
386
|
+
chosen = answer.trim();
|
|
378
387
|
}
|
|
379
|
-
|
|
388
|
+
// Both paths land here, because only one of them used to. A name typed at
|
|
389
|
+
// the prompt got `.mjs`; the same name passed as `--init myguards` was taken
|
|
390
|
+
// literally and wrote a file called `myguards` — which discovery skips (it
|
|
391
|
+
// takes .mjs/.js/.ts) and which no ESM loader will import. The starter file
|
|
392
|
+
// was unreachable by every command meant to pick it up.
|
|
393
|
+
const path = resolve(withPolicyExtension(chosen ?? "my-policies"));
|
|
380
394
|
if (existsSync(path)) {
|
|
381
395
|
return fail([`${path} already exists — name a different file, or edit that one.`]);
|
|
382
396
|
}
|
|
@@ -416,7 +430,7 @@ customPolicies.add({
|
|
|
416
430
|
" then ask your agent to force-push — it gets refused",
|
|
417
431
|
"",
|
|
418
432
|
"Then publish it:",
|
|
419
|
-
|
|
433
|
+
" failproofai publish --repo <you>/<repo>",
|
|
420
434
|
]);
|
|
421
435
|
}
|
|
422
436
|
|
|
@@ -582,6 +596,7 @@ async function ensureRepo(
|
|
|
582
596
|
name: string,
|
|
583
597
|
id: string,
|
|
584
598
|
token: string,
|
|
599
|
+
sourceDir?: string,
|
|
585
600
|
): Promise<{ info: Awaited<ReturnType<typeof gh>>; created: boolean } | { error: string[] }> {
|
|
586
601
|
let info = await gh(`${GITHUB_API}/repos/${owner}/${name}`, token);
|
|
587
602
|
let created = false;
|
|
@@ -601,7 +616,15 @@ async function ensureRepo(
|
|
|
601
616
|
name,
|
|
602
617
|
private: false,
|
|
603
618
|
description: `failproofai policy pack — ${id}`,
|
|
604
|
-
auto_init
|
|
619
|
+
// NOT auto_init. The author already has the commit that holds these
|
|
620
|
+
// policies; a repository seeded with its own "Initial commit" shares
|
|
621
|
+
// no history with it, so the `git push` that every publish is followed
|
|
622
|
+
// by is rejected as unrelated — and the way out (`pull --allow-
|
|
623
|
+
// unrelated-histories`, or a force-push over the seed) is a worse
|
|
624
|
+
// first five minutes than an empty repository, which accepts the push
|
|
625
|
+
// as-is. Releases do not need a commit to hang from: the tag is
|
|
626
|
+
// created against whatever the release API is given.
|
|
627
|
+
auto_init: false,
|
|
605
628
|
}),
|
|
606
629
|
});
|
|
607
630
|
if (made.status >= 400) {
|
|
@@ -617,6 +640,14 @@ async function ensureRepo(
|
|
|
617
640
|
};
|
|
618
641
|
}
|
|
619
642
|
created = true;
|
|
643
|
+
// A repository created with no commits has no default branch, and the
|
|
644
|
+
// release API tags the default branch — so something has to land on it
|
|
645
|
+
// before the release is cut. Pushing the author's own history is the
|
|
646
|
+
// version that leaves a usable repository behind; seeding is the fallback
|
|
647
|
+
// for a pack that is not in a git checkout at all.
|
|
648
|
+
if (!(sourceDir && pushExistingHistory(sourceDir, owner, name, token))) {
|
|
649
|
+
await seedDefaultBranch(owner, name, id, token);
|
|
650
|
+
}
|
|
620
651
|
info = await gh(`${GITHUB_API}/repos/${owner}/${name}`, token);
|
|
621
652
|
}
|
|
622
653
|
if (info.status >= 400) {
|
|
@@ -625,6 +656,102 @@ async function ensureRepo(
|
|
|
625
656
|
return { info, created };
|
|
626
657
|
}
|
|
627
658
|
|
|
659
|
+
/**
|
|
660
|
+
* Push the checkout the policies live in to the repository just created for
|
|
661
|
+
* them, and report whether it landed.
|
|
662
|
+
*
|
|
663
|
+
* Why publish pushes at all: it created the repository, so it owns the one
|
|
664
|
+
* moment when pushing cannot conflict with anything. The repository used to be
|
|
665
|
+
* created with `auto_init`, which meant GitHub wrote an "Initial commit" the
|
|
666
|
+
* author did not have — so the `git push` that every publish is followed by was
|
|
667
|
+
* rejected as unrelated history, every time, for everybody. Seeding it and
|
|
668
|
+
* pushing it are the same job; doing only the first left the author to
|
|
669
|
+
* reconcile two histories by hand.
|
|
670
|
+
*
|
|
671
|
+
* It also makes the tag mean something. The release tags the default branch, so
|
|
672
|
+
* against a seeded repository `1.0.0` named a README commit that did not
|
|
673
|
+
* contain a single one of the policies it shipped.
|
|
674
|
+
*
|
|
675
|
+
* The token goes in through GIT_ASKPASS, never in the URL or the argv: a remote
|
|
676
|
+
* with a credential in it is written into `.git/config` in plaintext, and one on
|
|
677
|
+
* a command line is readable from `ps` by every user on the box.
|
|
678
|
+
*/
|
|
679
|
+
export const __pushExistingHistoryForTest = (
|
|
680
|
+
dir: string,
|
|
681
|
+
owner: string,
|
|
682
|
+
name: string,
|
|
683
|
+
token: string,
|
|
684
|
+
): boolean => pushExistingHistory(dir, owner, name, token);
|
|
685
|
+
|
|
686
|
+
function pushExistingHistory(dir: string, owner: string, name: string, token: string): boolean {
|
|
687
|
+
const git = (args: string[], env?: Record<string, string>): string | null => {
|
|
688
|
+
try {
|
|
689
|
+
return execFileSync("git", args, {
|
|
690
|
+
cwd: dir,
|
|
691
|
+
encoding: "utf8",
|
|
692
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
693
|
+
timeout: 60_000,
|
|
694
|
+
env: env ? { ...process.env, ...env } : process.env,
|
|
695
|
+
}).trim();
|
|
696
|
+
} catch {
|
|
697
|
+
return null;
|
|
698
|
+
}
|
|
699
|
+
};
|
|
700
|
+
const branch = git(["rev-parse", "--abbrev-ref", "HEAD"]);
|
|
701
|
+
// No commits yet (`HEAD` unborn) means there is nothing to push and nothing
|
|
702
|
+
// to conflict with later either.
|
|
703
|
+
if (!branch || branch === "HEAD" || !git(["rev-parse", "--verify", "HEAD"])) return false;
|
|
704
|
+
|
|
705
|
+
const askpass = join(mkdtempSync(join(tmpdir(), "fpai-askpass-")), "askpass.sh");
|
|
706
|
+
try {
|
|
707
|
+
writeFileSync(askpass, `#!/bin/sh\ncase "$1" in\n*Username*) echo x-access-token ;;\n*) echo "$FPAI_GH_TOKEN" ;;\nesac\n`, { mode: 0o700 });
|
|
708
|
+
const env = { GIT_ASKPASS: askpass, FPAI_GH_TOKEN: token, GIT_TERMINAL_PROMPT: "0" };
|
|
709
|
+
const url = `${GITHUB_GIT}/${owner}/${name}.git`;
|
|
710
|
+
// Name the remote FIRST when there is not one, so the push can be `-u` and
|
|
711
|
+
// leave the branch tracking it. Pushing to a bare URL and setting the
|
|
712
|
+
// upstream afterwards cannot work: `--set-upstream-to` needs a
|
|
713
|
+
// remote-tracking ref, and a URL push writes none.
|
|
714
|
+
const adopt = !git(["remote", "get-url", "origin"]);
|
|
715
|
+
if (adopt) git(["remote", "add", "origin", url]);
|
|
716
|
+
// An author who already has an `origin` keeps it, and the push goes to the
|
|
717
|
+
// URL directly rather than quietly redirecting their remote.
|
|
718
|
+
const pushed = adopt
|
|
719
|
+
? git(["push", "-u", "origin", `${branch}:${branch}`], env)
|
|
720
|
+
: git(["push", url, `${branch}:${branch}`], env);
|
|
721
|
+
if (pushed === null) {
|
|
722
|
+
// Leave nothing behind that was not there before.
|
|
723
|
+
if (adopt) git(["remote", "remove", "origin"]);
|
|
724
|
+
return false;
|
|
725
|
+
}
|
|
726
|
+
return true;
|
|
727
|
+
} finally {
|
|
728
|
+
try {
|
|
729
|
+
rmSync(dirname(askpass), { recursive: true, force: true });
|
|
730
|
+
} catch {
|
|
731
|
+
/* a leftover temp dir is not worth failing a publish over */
|
|
732
|
+
}
|
|
733
|
+
}
|
|
734
|
+
}
|
|
735
|
+
|
|
736
|
+
/**
|
|
737
|
+
* The minimum that gives a repository a default branch: one commit, made
|
|
738
|
+
* through the API. Only for a pack published from somewhere that is not a git
|
|
739
|
+
* checkout — otherwise the author's own history does this job better.
|
|
740
|
+
*/
|
|
741
|
+
async function seedDefaultBranch(owner: string, name: string, id: string, token: string): Promise<void> {
|
|
742
|
+
await gh(`${GITHUB_API}/repos/${owner}/${name}/contents/README.md`, token, {
|
|
743
|
+
method: "PUT",
|
|
744
|
+
contentType: "application/json",
|
|
745
|
+
body: JSON.stringify({
|
|
746
|
+
message: `${id}: create pack repository`,
|
|
747
|
+
content: Buffer.from(
|
|
748
|
+
`# ${name}\n\nA [failproofai](https://github.com/failproofai/failproofai) policy pack.\n\n\`\`\`bash\nfailproofai policies add ${owner}/${name}\n\`\`\`\n`,
|
|
749
|
+
"utf8",
|
|
750
|
+
).toString("base64"),
|
|
751
|
+
}),
|
|
752
|
+
});
|
|
753
|
+
}
|
|
754
|
+
|
|
628
755
|
/**
|
|
629
756
|
* Where `bun` is, if it is anywhere.
|
|
630
757
|
*
|
|
@@ -736,6 +863,9 @@ function publishEntryArg(rest: string[]): string | undefined {
|
|
|
736
863
|
|
|
737
864
|
const GITHUB_API = process.env.FAILPROOFAI_GITHUB_API ?? "https://api.github.com";
|
|
738
865
|
const GITHUB_UPLOADS = process.env.FAILPROOFAI_GITHUB_UPLOADS ?? "https://uploads.github.com";
|
|
866
|
+
/** Where the git remote lives, so the push path can be tested against a real
|
|
867
|
+
* local bare repository rather than only reasoned about. */
|
|
868
|
+
const GITHUB_GIT = process.env.FAILPROOFAI_GITHUB_GIT ?? "https://github.com";
|
|
739
869
|
|
|
740
870
|
/**
|
|
741
871
|
* The credential, from the places a developer already keeps one.
|
|
@@ -822,6 +952,60 @@ function ghError(res: { status: number; json: Record<string, unknown> | null; te
|
|
|
822
952
|
* - a private repository, which publishes to nobody, because installs are
|
|
823
953
|
* anonymous HTTPS with no credential to offer.
|
|
824
954
|
*/
|
|
955
|
+
/**
|
|
956
|
+
* The two things `publish` cannot work out on its own, asked instead of
|
|
957
|
+
* demanded as flags.
|
|
958
|
+
*
|
|
959
|
+
* Everything else it already derives: the policy files by content, the version
|
|
960
|
+
* by counting the repository's own releases, the id from the repository, the
|
|
961
|
+
* credential from the environment. What is left is genuinely a question —
|
|
962
|
+
* WHERE this should live, when the folder has no git remote naming somewhere —
|
|
963
|
+
* and a confirmation, because publishing is public and a version number can
|
|
964
|
+
* never be reused.
|
|
965
|
+
*
|
|
966
|
+
* Only ever on a TTY. A pipe, a CI job or a test gets the old behaviour: flags
|
|
967
|
+
* decide, and a missing `--repo` still means "build the assets and stop"
|
|
968
|
+
* rather than a prompt nobody can answer.
|
|
969
|
+
*/
|
|
970
|
+
async function askWhereToPublish(
|
|
971
|
+
suggestion: string,
|
|
972
|
+
io: { stdin: TTYIn; stdout: TTYOut },
|
|
973
|
+
): Promise<string | null> {
|
|
974
|
+
const answer = await promptText({
|
|
975
|
+
// The suggestion goes in the HINT, not just in `defaultValue`: the hint is
|
|
976
|
+
// what renders as the placeholder, while `defaultValue` is only applied on
|
|
977
|
+
// an empty submit and is never shown. Passing it as the default alone left
|
|
978
|
+
// the one keystroke that finishes this prompt — return — invisible.
|
|
979
|
+
message: "Where should this publish?",
|
|
980
|
+
hint: `${suggestion} · created if it does not exist`,
|
|
981
|
+
defaultValue: suggestion,
|
|
982
|
+
validate: (v) => {
|
|
983
|
+
const t = v.trim();
|
|
984
|
+
if (!/^[A-Za-z0-9][\w.-]*\/[A-Za-z0-9][\w.-]*$/.test(t)) return "owner/repo";
|
|
985
|
+
return null;
|
|
986
|
+
},
|
|
987
|
+
stdin: io.stdin,
|
|
988
|
+
stdout: io.stdout,
|
|
989
|
+
});
|
|
990
|
+
return answer === null ? null : answer.trim();
|
|
991
|
+
}
|
|
992
|
+
|
|
993
|
+
/**
|
|
994
|
+
* The account the credential belongs to, for the default answer above.
|
|
995
|
+
*
|
|
996
|
+
* Best-effort: a failure here costs a nicer default and nothing else, so it
|
|
997
|
+
* never blocks or reports. The prompt still has the folder name to fall back
|
|
998
|
+
* on, which is what the repository would most likely be called anyway.
|
|
999
|
+
*/
|
|
1000
|
+
async function credentialLogin(token: string): Promise<string | null> {
|
|
1001
|
+
try {
|
|
1002
|
+
const me = await gh(`${GITHUB_API}/user`, token);
|
|
1003
|
+
return typeof me.json?.login === "string" ? me.json.login : null;
|
|
1004
|
+
} catch {
|
|
1005
|
+
return null;
|
|
1006
|
+
}
|
|
1007
|
+
}
|
|
1008
|
+
|
|
825
1009
|
async function publish(rest: string[]): Promise<PackCliResult> {
|
|
826
1010
|
const flag = (name: string): string | undefined => {
|
|
827
1011
|
const i = rest.findIndex((a) => a === `--${name}` || a.startsWith(`--${name}=`));
|
|
@@ -838,7 +1022,32 @@ async function publish(rest: string[]): Promise<PackCliResult> {
|
|
|
838
1022
|
// it is that file and only that file.
|
|
839
1023
|
const discovered = entry ? [] : findEntry(process.cwd());
|
|
840
1024
|
if (!entry && discovered.length > 0) entry = discovered[0];
|
|
841
|
-
|
|
1025
|
+
let repo = flag("repo") ?? (entry ? inferRepo(entry) : null) ?? undefined;
|
|
1026
|
+
// Nothing names a destination and there is somebody to ask. This is the
|
|
1027
|
+
// whole of "just run `failproofai publish`": the folder is a git repo full
|
|
1028
|
+
// of policies, and the one thing it cannot know is where they should go.
|
|
1029
|
+
const interactive = Boolean(process.stdin.isTTY && process.stdout.isTTY);
|
|
1030
|
+
const askingWhere = interactive && !repo && entry && !rest.includes("--dry-run");
|
|
1031
|
+
if (askingWhere) {
|
|
1032
|
+
// What is about to be published, before being asked where to put it. The
|
|
1033
|
+
// question is answerable without it — but "publish" with no arguments
|
|
1034
|
+
// otherwise gives no sign of WHICH files it found, and finding the wrong
|
|
1035
|
+
// ones is the mistake that matters here.
|
|
1036
|
+
const found = discovered.length > 0 ? discovered : [entry!];
|
|
1037
|
+
process.stdout.write(
|
|
1038
|
+
`\n ${found.length} policy ${found.length === 1 ? "file" : "files"}: ` +
|
|
1039
|
+
`${found.map((f) => basename(f)).join(", ")}\n\n`,
|
|
1040
|
+
);
|
|
1041
|
+
const token = githubToken();
|
|
1042
|
+
const login = token ? await credentialLogin(token) : null;
|
|
1043
|
+
const folder = basename(resolve(entry!, ".."));
|
|
1044
|
+
const answered = await askWhereToPublish(
|
|
1045
|
+
`${login ?? "your-account"}/${folder}`,
|
|
1046
|
+
{ stdin: process.stdin as unknown as TTYIn, stdout: process.stdout as unknown as TTYOut },
|
|
1047
|
+
);
|
|
1048
|
+
if (answered === null) return ok(["Nothing was published."]);
|
|
1049
|
+
repo = answered;
|
|
1050
|
+
}
|
|
842
1051
|
// A tag on HEAD is somebody SAYING what this release is, so it wins over a
|
|
843
1052
|
// counted one. Everything else is decided after the repository is known,
|
|
844
1053
|
// because the count comes from what that repository has already published.
|
|
@@ -846,8 +1055,19 @@ async function publish(rest: string[]): Promise<PackCliResult> {
|
|
|
846
1055
|
let versionCounted = false;
|
|
847
1056
|
// The id and the repo are usually the same words, and requiring both is asking
|
|
848
1057
|
// the same question twice. Either one alone answers for the other.
|
|
849
|
-
const id = flag("id") ?? repo;
|
|
850
1058
|
const dryRun = rest.includes("--dry-run") || !repo;
|
|
1059
|
+
// A dry run publishes nothing, so the id only has to name the artifact it
|
|
1060
|
+
// writes — and refusing to build one because the folder has no git remote
|
|
1061
|
+
// yet blocked the exact thing a dry run is for: looking at the pack BEFORE
|
|
1062
|
+
// committing to a repository for it. The folder name is what the repository
|
|
1063
|
+
// would be called anyway, and `--id` or `--repo` overrides it the moment
|
|
1064
|
+
// either is known.
|
|
1065
|
+
//
|
|
1066
|
+
// `local/` rather than a guessed account: the owner is genuinely not known
|
|
1067
|
+
// yet, and a plausible-looking one would be baked into a manifest somebody
|
|
1068
|
+
// could upload by hand.
|
|
1069
|
+
const id =
|
|
1070
|
+
flag("id") ?? repo ?? (dryRun && entry ? `local/${basename(resolve(entry, ".."))}` : undefined);
|
|
851
1071
|
const [owner, name] = (repo ?? "/").split("/");
|
|
852
1072
|
if (repo && (!owner || !name || repo.split("/").length !== 2)) {
|
|
853
1073
|
return fail([`--repo must be <owner>/<repo>, got ${JSON.stringify(repo)}`]);
|
|
@@ -899,7 +1119,7 @@ async function publish(rest: string[]): Promise<PackCliResult> {
|
|
|
899
1119
|
"It needs write access to releases on that repository, and nothing else.",
|
|
900
1120
|
]);
|
|
901
1121
|
}
|
|
902
|
-
const ensured = await ensureRepo(owner, name, id, token);
|
|
1122
|
+
const ensured = await ensureRepo(owner, name, id, token, resolve(entry, ".."));
|
|
903
1123
|
if ("error" in ensured) return fail(ensured.error);
|
|
904
1124
|
created = ensured.created;
|
|
905
1125
|
repoInfo = ensured.info;
|
|
@@ -953,7 +1173,13 @@ async function publish(rest: string[]): Promise<PackCliResult> {
|
|
|
953
1173
|
? ["Dry run — nothing was published.", `Drop --dry-run to release it on ${repo}.`]
|
|
954
1174
|
: [
|
|
955
1175
|
"Nothing was published: name a repository to release it on.",
|
|
956
|
-
|
|
1176
|
+
// Just the repository. It used to spell out the entry file and the
|
|
1177
|
+
// version too — naming ONE of the files it had that moment finished
|
|
1178
|
+
// bundling, and pinning a version it works out by counting the
|
|
1179
|
+
// repository's own releases. Both were wrong the moment they were
|
|
1180
|
+
// printed, and both taught the reader that publishing needs flags
|
|
1181
|
+
// it does not need.
|
|
1182
|
+
" failproofai publish --repo <owner>/<repo>",
|
|
957
1183
|
]),
|
|
958
1184
|
]);
|
|
959
1185
|
}
|
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
module.exports=[22734,(e,r,t)=>{r.exports=e.x("fs",()=>require("fs"))},24868,(e,r,t)=>{r.exports=e.x("fs/promises",()=>require("fs/promises"))},70406,(e,r,t)=>{r.exports=e.x("next/dist/compiled/@opentelemetry/api",()=>require("next/dist/compiled/@opentelemetry/api"))},18622,(e,r,t)=>{r.exports=e.x("next/dist/compiled/next-server/app-page-turbo.runtime.prod.js",()=>require("next/dist/compiled/next-server/app-page-turbo.runtime.prod.js"))},20635,(e,r,t)=>{r.exports=e.x("next/dist/server/app-render/action-async-storage.external.js",()=>require("next/dist/server/app-render/action-async-storage.external.js"))},24725,(e,r,t)=>{r.exports=e.x("next/dist/server/app-render/after-task-async-storage.external.js",()=>require("next/dist/server/app-render/after-task-async-storage.external.js"))},56704,(e,r,t)=>{r.exports=e.x("next/dist/server/app-render/work-async-storage.external.js",()=>require("next/dist/server/app-render/work-async-storage.external.js"))},32319,(e,r,t)=>{r.exports=e.x("next/dist/server/app-render/work-unit-async-storage.external.js",()=>require("next/dist/server/app-render/work-unit-async-storage.external.js"))},59043,(e,r,t)=>{r.exports=e.x("next/dist/server/runtime-reacts.external.js",()=>require("next/dist/server/runtime-reacts.external.js"))},93695,(e,r,t)=>{r.exports=e.x("next/dist/shared/lib/no-fallback-error.external.js",()=>require("next/dist/shared/lib/no-fallback-error.external.js"))},12714,(e,r,t)=>{r.exports=e.x("node:fs/promises",()=>require("node:fs/promises"))},50227,(e,r,t)=>{r.exports=e.x("node:path",()=>require("node:path"))},81111,(e,r,t)=>{r.exports=e.x("node:stream",()=>require("node:stream"))},46786,(e,r,t)=>{r.exports=e.x("os",()=>require("os"))},14747,(e,r,t)=>{r.exports=e.x("path",()=>require("path"))},91301,e=>{e.v(r=>Promise.all(["server/chunks/[root-of-the-server]__1qb590j._.js","server/chunks/_1vslkoe._.js"].map(r=>e.l(r))).then(()=>r(30441)))},16341,e=>{e.v(r=>Promise.all(["server/chunks/[root-of-the-server]__1shcqgr._.js"].map(r=>e.l(r))).then(()=>r(93114)))},37352,e=>{e.v(r=>Promise.all(["server/chunks/[root-of-the-server]__1jm9fw6._.js"].map(r=>e.l(r))).then(()=>r(36203)))},18944,e=>{e.v(r=>Promise.all(["server/chunks/[root-of-the-server]__17g9wh7._.js","server/chunks/src_hooks_fp-home_ts_09kv0bn._.js"].map(r=>e.l(r))).then(()=>r(57232)))},71809,e=>{"use strict";async function r(e,r){let t=Array(e.length),s=0;async function o(){for(;s<e.length;){let r=s++;try{t[r]={status:"fulfilled",value:await e[r]()}}catch(e){t[r]={status:"rejected",reason:e}}}}let a=Array.from({length:Math.min(r,e.length)},()=>o());return await Promise.all(a),t}e.s(["batchAll",0,r])},5807,e=>{e.v(r=>Promise.all(["server/chunks/[root-of-the-server]__1w9zl9-._.js"].map(r=>e.l(r))).then(()=>r(55851)))},21476,e=>{e.v(r=>Promise.all(["server/chunks/[root-of-the-server]__1legmza._.js"].map(r=>e.l(r))).then(()=>r(78166)))},97452,e=>{e.v(r=>Promise.all(["server/chunks/[root-of-the-server]__1ou2ehh._.js"].map(r=>e.l(r))).then(()=>r(46413)))},23414,e=>{e.v(r=>Promise.all(["server/chunks/[root-of-the-server]__0rv7m0k._.js"].map(r=>e.l(r))).then(()=>r(72094)))},52400,e=>{e.v(r=>Promise.all(["server/chunks/[root-of-the-server]__0g6bbuw._.js","server/chunks/_1vslkoe._.js"].map(r=>e.l(r))).then(()=>r(79364)))},53229,e=>{e.v(r=>Promise.all(["server/chunks/[root-of-the-server]__1ffkmds._.js","server/chunks/_1vslkoe._.js"].map(r=>e.l(r))).then(()=>r(40375)))},62998,e=>{e.v(r=>Promise.all(["server/chunks/[root-of-the-server]__0q0qzx1._.js"].map(r=>e.l(r))).then(()=>r(69391)))},95231,e=>{e.v(r=>Promise.all(["server/chunks/[root-of-the-server]__0--lkk6._.js"].map(r=>e.l(r))).then(()=>r(28246)))},28557,e=>{"use strict";e.s(["formatDate",0,function(e){return new Intl.DateTimeFormat("en-US",{month:"short",day:"numeric",year:"numeric",hour:"numeric",minute:"2-digit",hour12:!0}).format(e)}])},31854,e=>{e.v(r=>Promise.all(["server/chunks/[root-of-the-server]__08w4wmd._.js","server/chunks/_1vslkoe._.js"].map(r=>e.l(r))).then(()=>r(69164)))},49081,e=>{e.v(r=>Promise.all(["server/chunks/[root-of-the-server]__1xuedea._.js","server/chunks/_1vslkoe._.js"].map(r=>e.l(r))).then(()=>r(36618)))},67347,e=>{e.v(r=>Promise.all(["server/chunks/[root-of-the-server]__06cuf1y._.js","server/chunks/_1vslkoe._.js"].map(r=>e.l(r))).then(()=>r(64828)))},32359,e=>{e.v(r=>Promise.all(["server/chunks/[root-of-the-server]__0jnjf2t._.js","server/chunks/_1vslkoe._.js"].map(r=>e.l(r))).then(()=>r(3605)))},40911,e=>{"use strict";let r={info:0,warn:1,error:2};function t(e){return r[e]>=r.warn}function s(e){return`[failproofai${new Date().toISOString()}] ${e}`}e.s(["logActivity",0,function(e,r,o){if(!t("info"))return;let a=[`user=${e}`,`action=${r}`];o&&a.push(o),console.log(s("ACTIVITY"),a.join(" "))},"logError",0,function(e,r){void 0!==r?console.error(s("ERROR"),e,r):console.error(s("ERROR"),e)},"logWarn",0,function(e,r){t("warn")&&(void 0!==r?console.warn(s("WARN"),e,r):console.warn(s("WARN"),e))}])},38978,e=>{e.v(r=>Promise.all(["server/chunks/[root-of-the-server]__04_h-a5._.js"].map(r=>e.l(r))).then(()=>r(90624)))},26435,e=>{e.v(r=>Promise.all(["server/chunks/[root-of-the-server]__0-219ec._.js"].map(r=>e.l(r))).then(()=>r(64199)))},82978,e=>{e.v(r=>Promise.all(["server/chunks/[root-of-the-server]__1mhmdzs._.js"].map(r=>e.l(r))).then(()=>r(35435)))},82859,e=>{e.v(r=>Promise.all(["server/chunks/[root-of-the-server]__1qxztj-._.js"].map(r=>e.l(r))).then(()=>r(99440)))},81580,e=>{"use strict";var r=e.i(46786),t=e.i(14747);e.s(["decodeFolderName",0,function(e){return/^[A-Za-z]--/.test(e)?e[0]+":/"+e.slice(3).replace(/-/g,"/"):e.replace(/-/g,"/")},"encodeFolderName",0,function(e){let r=/^([A-Za-z]):[\\/](.*)$/.exec(e);return r?r[1]+"--"+r[2].replace(/[\\/]/g,"-"):e.replace(/[\\/]/g,"-")},"getClaudeProjectsPath",0,function(){let e=process.env.CLAUDE_PROJECTS_PATH;return e||(0,t.join)((0,r.homedir)(),".claude","projects")}])},45093,e=>{e.v(r=>Promise.all(["server/chunks/[root-of-the-server]__0f7mikp._.js"].map(r=>e.l(r))).then(()=>r(19791)))},41330,e=>{e.v(r=>Promise.all(["server/chunks/[root-of-the-server]__0q-v9z2._.js"].map(r=>e.l(r))).then(()=>r(85116)))},56936,e=>{"use strict";var r=e.i(12714),t=e.i(50227),s=e.i(81580),o=e.i(83534),a=e.i(71809),n=e.i(40911),i=e.i(28557);let l=/^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/;async function c(e,t){try{return(await (0,r.stat)(e)).mtime}catch(e){return(0,n.logWarn)(`Failed to stat ${t}:`,e),new Date(0)}}async function u(e){try{if(!(await (0,r.stat)(e)).isDirectory())return null;return await (0,r.readdir)(e,{withFileTypes:!0})}catch{return null}}async function h(){try{let e=(0,s.getClaudeProjectsPath)(),r=await u(e);if(!r)return[];let o=(await (0,a.batchAll)(r.filter(e=>e.isDirectory()).map(r=>async()=>{let s=(0,t.join)(e,r.name),o=await c(s,r.name);return{name:r.name,path:s,isDirectory:!0,lastModified:o,lastModifiedFormatted:(0,i.formatDate)(o),cli:["claude"]}}),16)).filter(e=>"fulfilled"===e.status).map(e=>e.value);return o.sort((e,r)=>r.lastModified.getTime()-e.lastModified.getTime()),o}catch(e){return(0,n.logError)("Error reading Claude project folders:",e),[]}}async function d(){let[{getCodexProjects:r},{getCopilotProjects:t},{getCursorProjects:s},{getOpenCodeProjects:o},{getPiProjects:a},{getHermesProjects:i},{getOpenClawProjects:l},{getFactoryProjects:c},{getDevinProjects:u},{getAntigravityProjects:d},{getGooseProjects:m}]=await Promise.all([e.A(37352),e.A(5807),e.A(97452),e.A(82978),e.A(45093),e.A(67347),e.A(38978),e.A(62998),e.A(52400),e.A(91301),e.A(31854)]),[f,p,v,_,j,g,x,k,w,y,P,E]=await Promise.all([h(),r().catch(e=>((0,n.logError)("Error reading Codex projects:",e),[])),t().catch(e=>((0,n.logError)("Error reading Copilot projects:",e),[])),s().catch(e=>((0,n.logError)("Error reading Cursor projects:",e),[])),o().catch(e=>((0,n.logError)("Error reading OpenCode projects:",e),[])),a().catch(e=>((0,n.logError)("Error reading Pi projects:",e),[])),i().catch(e=>((0,n.logError)("Error reading Hermes projects:",e),[])),l().catch(e=>((0,n.logError)("Error reading OpenClaw projects:",e),[])),c().catch(e=>((0,n.logError)("Error reading Factory projects:",e),[])),u().catch(e=>((0,n.logError)("Error reading Devin projects:",e),[])),d().catch(e=>((0,n.logError)("Error reading Antigravity projects:",e),[])),m().catch(e=>((0,n.logError)("Error reading Goose projects:",e),[]))]);return function(...e){let r=new Map;for(let t of e)for(let e of t){let t=r.get(e.name);if(!t){r.set(e.name,{...e,cli:[...e.cli]});continue}let s=[...t.cli];for(let r of e.cli)s.includes(r)||s.push(r);let o=e.lastModified.getTime()>t.lastModified.getTime()?e:t;r.set(e.name,{...t,cli:s,lastModified:o.lastModified,lastModifiedFormatted:o.lastModifiedFormatted,sessionCount:void 0===t.sessionCount&&void 0===e.sessionCount?void 0:(t.sessionCount??0)+(e.sessionCount??0)})}let t=Array.from(r.values());return t.sort((e,r)=>r.lastModified.getTime()-e.lastModified.getTime()),t}(f,p,v,_,j,g,x,k,w,y,P,E)}function m(e){if(!e)throw RangeError("Empty project name");if(/^[/\\]/.test(e))throw RangeError("Absolute project name");let r=(0,t.resolve)((0,s.getClaudeProjectsPath)()),o=(0,t.resolve)((0,t.join)(r,e));if(!o.startsWith(r+t.sep))throw RangeError("Project path escapes root");return o}function f(e){let r=e.match(/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/i);return r?r[0]:void 0}async function p(e){try{let r=await u(e);if(!r)return[];let s=r.filter(e=>e.isFile()&&e.name.endsWith(".jsonl")&&f(e.name)),o=(await (0,a.batchAll)(s.map(r=>async()=>{let s=(0,t.join)(e,r.name),o=await c(s,r.name);return{name:r.name,path:s,lastModified:o,lastModifiedFormatted:(0,i.formatDate)(o),sessionId:f(r.name),cli:"claude"}}),16)).filter(e=>"fulfilled"===e.status).map(e=>e.value);return o.sort((e,r)=>r.lastModified.getTime()-e.lastModified.getTime()),o}catch(e){return(0,n.logError)("Error reading session files:",e),[]}}(0,o.runtimeCache)(d,30),(0,o.runtimeCache)(e=>p(e),30),e.s(["UUID_RE",0,l,"resolveProjectPath",0,m,"resolveSessionFilePath",0,function(e,r){if(!l.test(r))throw RangeError("Invalid session ID");let s=m(e);return(0,t.join)(s,`${r}.jsonl`)}])},83534,e=>{"use strict";e.s(["runtimeCache",0,function(e,r,t){let s=new Map,o=new Map,a=t?.maxSize;return async(...t)=>{let n=JSON.stringify(t),i=s.get(n);if(i&&Date.now()<i.expiry)return i.data;let l=o.get(n);if(l)return l;let c=e(...t).then(e=>{if(o.delete(n),a&&s.size>=a){let e=s.keys().next().value;s.delete(e)}return s.set(n,{data:e,expiry:Date.now()+1e3*r}),e},e=>{throw o.delete(n),e});return o.set(n,c),c}}])}];
|
|
2
|
-
|
|
3
|
-
//# sourceMappingURL=%5Broot-of-the-server%5D__1l-khtb._.js.map
|
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
module.exports=[74533,(e,t,r)=>{t.exports=e.x("node:child_process",()=>require("node:child_process"))},35435,e=>{"use strict";var t=e.i(74533),r=e.i(81580),o=e.i(83534),i=e.i(28557),d=e.i(40911);function n(e){try{let r=(0,t.execFileSync)("opencode",["db","--format","json",e],{encoding:"utf8",timeout:5e3,stdio:["ignore","pipe","pipe"]});if(!r.trim())return[];let o=JSON.parse(r);if(!Array.isArray(o))return null;return o}catch{return null}}function s(){return n("SELECT id, project_id, slug, directory, title, time_created, time_updated FROM session ORDER BY time_updated DESC LIMIT 1000")}function a(){return n("SELECT id, worktree, vcs, name, time_created, time_updated FROM project")}async function l(){let e=s(),t=a();if(null===e&&null===t)return[];let o=new Map;for(let e of t??[])o.set(e.id,e);let d=new Map;for(let t of e??[]){if(!t.project_id)continue;let e=d.get(t.project_id);e||(e={rows:[],latest:0},d.set(t.project_id,e)),e.rows.push(t),t.time_updated>e.latest&&(e.latest=t.time_updated)}let n=new Set,l=[];for(let[e,t]of d){n.add(e);let d=o.get(e),s=d?.worktree??t.rows[0]?.directory??null,a=s?(0,r.encodeFolderName)(s):e,c=s??"",u=new Date(Math.max(t.latest,d?.time_updated??0));l.push({name:a,path:c,isDirectory:!0,lastModified:u,lastModifiedFormatted:(0,i.formatDate)(u),cli:["opencode"]})}for(let e of t??[]){if(n.has(e.id))continue;let t=e.worktree??"",o=t?(0,r.encodeFolderName)(t):e.id,d=new Date(e.time_updated);l.push({name:o,path:t,isDirectory:!0,lastModified:d,lastModifiedFormatted:(0,i.formatDate)(d),cli:["opencode"]})}return l.sort((e,t)=>t.lastModified.getTime()-e.lastModified.getTime()),l}async function c(e){let t=s();return t?t.filter(t=>t.directory===e).map(e=>{let t=new Date(e.time_updated);return{name:e.title??e.slug??e.id,path:`opencode://${e.id}`,lastModified:t,lastModifiedFormatted:(0,i.formatDate)(t),sessionId:e.id,cli:"opencode"}}):[]}async function u(e){let t,o;try{t=a(),o=s()}catch(e){return(0,d.logWarn)("Failed to read OpenCode DB:",e),{cwd:null,sessions:[]}}if(!t||!o)return{cwd:null,sessions:[]};let n=t.find(t=>t.worktree&&(0,r.encodeFolderName)(t.worktree)===e);if(!n||!n.worktree)return{cwd:null,sessions:[]};let l=o.filter(e=>e.project_id===n.id);return{cwd:n.worktree,sessions:l.map(e=>{let t=new Date(e.time_updated);return{name:e.title??e.slug??e.id,path:`opencode://${e.id}`,lastModified:t,lastModifiedFormatted:(0,i.formatDate)(t),sessionId:e.id,cli:"opencode"}})}}let p=(0,o.runtimeCache)(l,30),m=(0,o.runtimeCache)(e=>c(e),30,{maxSize:50}),f=(0,o.runtimeCache)(e=>u(e),30,{maxSize:50});e.s(["getCachedOpenCodeProjects",0,p,"getCachedOpenCodeSessionsByEncodedName",0,f,"getCachedOpenCodeSessionsForCwd",0,m,"getOpenCodeProjects",0,l,"getOpenCodeSessionsByEncodedName",0,u,"getOpenCodeSessionsForCwd",0,c])}];
|
|
2
|
-
|
|
3
|
-
//# sourceMappingURL=%5Broot-of-the-server%5D__1mhmdzs._.js.map
|
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
module.exports=[74533,(t,e,i)=>{e.exports=t.x("node:child_process",()=>require("node:child_process"))},54214,67405,t=>{"use strict";var e=t.i(24868),i=t.i(14747),n=t.i(81580),s=t.i(56936);async function r(t,n,s,r){let a=`agent-${r}.jsonl`;for(let r of[(0,i.join)(t,n,a),(0,i.join)(t,n,s,a),(0,i.join)(t,n,s,"subagents",a)])if(!(0,i.relative)(t,r).startsWith(".."))try{return await (0,e.access)(r),r}catch(t){if("ENOENT"===t.code)continue;break}return null}var a=t.i(83534),o=t.i(71809),u=t.i(28557);function l(t){if(t<1e3)return`${t}ms`;let e=Math.round(t/100);if(e<600)return`${(e/10).toFixed(1)}s`;let i=Math.round(t/1e3);if(i<3600){let t=Math.floor(i/60);return`${t}m ${i%60}s`}let n=Math.round(t/6e4),s=Math.floor(n/60);return`${s}h ${n%60}m`}function d(t){let e=(0,u.formatDate)(t),i=t.getMilliseconds().toString().padStart(3,"0");return`${e}.${i}`}function m(t,e,i,n){return{_source:n,uuid:t.uuid||"",parentUuid:t.parentUuid??null,timestamp:e,timestampMs:i.getTime(),timestampFormatted:d(i)}}async function p(t,e){let i=t.split("\n").filter(t=>""!==t.trim()),n=new Map,s=[],r=[],a=new Set,o=!1;for(let t=0;t<i.length;t++){let u;t>0&&t%200==0&&await new Promise(t=>setImmediate(t));let l=i[t];try{u=JSON.parse(l)}catch{continue}let d={...u,_source:e};r.push(d);let p=u.type,c=u.timestamp;if(!c)continue;let f=new Date(c),g=f.getTime();if("user"===p){let t=u.message;if(Array.isArray(t?.content)){let e=t.content;if(e.some(t=>"tool_result"===t.type)){let t=u.toolUseResult,i="string"==typeof t?.agentId?t.agentId:void 0;for(let t of(i&&/^[a-f0-9]+$/.test(i)&&a.add(i),e)){if("tool_result"!==t.type)continue;let e=t.tool_use_id;if(!e)continue;let{text:s,images:r}=function(t){let e=t.content;if("string"==typeof e)return{text:e};if(Array.isArray(e)){let t=e.filter(t=>"text"===t.type).map(t=>t.text),i=e.filter(t=>"image"===t.type).map(t=>{let e=t.source;return{base64:e.data,mediaType:e.media_type}}).filter(t=>t.base64&&t.mediaType);return{text:t.length>0?t.join("\n"):void 0,images:i.length>0?i:void 0}}return{}}(t);n.set(e,{timestamp:c,timestampMs:g,content:s,images:r,agentId:i})}continue}}let i="string"==typeof t?.content?t.content:"";s.push({type:"user",...m(u,c,f,e),message:{role:"user",content:i}});continue}if("assistant"===p){let t=u.message,i=[];if(Array.isArray(t?.content)&&(i=t.content.filter(t=>["text","tool_use","thinking"].includes(t.type)).map(t=>{if("text"===t.type)return{type:"text",text:t.text};if("tool_use"===t.type){let e=t.input;return{type:"tool_use",id:t.id,name:t.name,input:t.input??{},..."Task"===t.name&&e?{subagentType:e.subagent_type,subagentDescription:e.description}:{}}}return{type:"thinking",thinking:t.thinking,signature:t.signature}})),0===i.length)continue;s.push({type:"assistant",...m(u,c,f,e),message:{role:"assistant",content:i,model:t?.model}});continue}if("file-history-snapshot"===p||"progress"===p||"system"===p){s.push({type:p,...m(u,c,f,e),raw:{...u}});continue}if("queue-operation"===p){let t=o?"Session Resumed":"Session Started";o=!0,s.push({type:"queue-operation",...m(u,c,f,e),label:t});continue}}let u=0;for(let t of s)if("assistant"===t.type)for(let e of(++u%200==0&&await new Promise(t=>setImmediate(t)),t.message.content)){if("tool_use"!==e.type)continue;let i=n.get(e.id);if(!i)continue;let s=new Date(i.timestamp),r=Math.max(0,i.timestampMs-t.timestampMs);e.result={timestamp:i.timestamp,timestampFormatted:d(s),content:i.content,images:i.images,durationMs:r,durationFormatted:l(r)},i.agentId&&(e.subagentId=i.agentId)}return s.length>500&&await new Promise(t=>setImmediate(t)),s.sort((t,e)=>t.timestampMs-e.timestampMs),{entries:s,rawLines:r,subagentIds:Array.from(a)}}async function c(t,e="session"){return(await p(t,e)).entries}async function f(t,a){let u=(0,s.resolveProjectPath)(t),l=(0,n.getClaudeProjectsPath)(),d=(0,i.join)(u,`${a}.jsonl`),m=await (0,e.readFile)(d,"utf-8"),{entries:c,rawLines:f,subagentIds:g}=await p(m,"session");if(0===g.length)return{entries:c,rawLines:f,subagentIds:[]};let y=await (0,o.batchAll)(g.map(i=>async()=>{let n=`agent-${i}`,s=await r(l,t,a,i);if(!s)return null;let o=await (0,e.readFile)(s,"utf-8"),{entries:u,rawLines:d}=await p(o,n);return{entries:u,rawLines:d}}),4),_=[...c],h=[...f];for(let t of y)"fulfilled"===t.status&&t.value&&(_.push(...t.value.entries),h.push(...t.value.rawLines));return _.length>500&&await new Promise(t=>setImmediate(t)),_.sort((t,e)=>t.timestampMs-e.timestampMs),{entries:_,rawLines:h,subagentIds:g}}t.s(["formatDuration",0,l],67405),(0,a.runtimeCache)((t,e)=>f(t,e),60,{maxSize:50}),t.s(["baseEntry",0,m,"formatTimestamp",0,d,"parseLogContent",0,c,"parseRawLines",0,function(t,e){return t.split("\n").filter(t=>""!==t.trim()).flatMap(t=>{try{let i=JSON.parse(t);return void 0!==e&&(i._source=e),[i]}catch{return[]}})}],54214)},99440,t=>{"use strict";var e=t.i(74533),i=t.i(83534),n=t.i(54214),s=t.i(67405);function r(t){try{let i=(0,e.execFileSync)("opencode",["db","--format","json",t],{encoding:"utf8",timeout:5e3,stdio:["ignore","pipe","pipe"]});if(!i.trim())return[];let n=JSON.parse(i);if(!Array.isArray(n))return null;return n}catch{return null}}function a(t){return!!t&&"object"==typeof t&&!Array.isArray(t)}function o(t){if("string"!=typeof t||0===t.length)return null;try{let e=JSON.parse(t);return a(e)?e:null}catch{return null}}async function u(t){if(!t||!/^[A-Za-z0-9_-]+$/.test(t))return null;let e=r(`SELECT id, project_id, slug, directory, title, time_created, time_updated FROM session WHERE id = '${t}'`);if(!e||0===e.length)return null;let i=e[0],u=r(`SELECT id, session_id, time_created, time_updated, data FROM message WHERE session_id = '${t}' ORDER BY time_created ASC`),l=r(`SELECT id, message_id, session_id, time_created, time_updated, data FROM part WHERE session_id = '${t}' ORDER BY time_created ASC`);if(!u)return{entries:[],rawLines:[],cwd:i.directory??void 0,filePath:`opencode://${t}`};let d=new Map;for(let t of l??[]){let e=d.get(t.message_id);e||(e=[],d.set(t.message_id,e)),e.push(t)}let m=[],p=[];for(let t of u){let e=d.get(t.id)??[];m.push(function(t,e,i){let r=o(t.data)??{},u="string"==typeof r.role?r.role:"system",l=new Date(t.time_created),d=l.toISOString(),m={uuid:t.id,parentUuid:null},p=(0,n.baseEntry)(m,d,l,i),c=[],f="";for(let t of e){let e=o(t.data);if(!e)continue;let i="string"==typeof e.type?e.type:"unknown";if("text"===i){let t="string"==typeof e.text?e.text:"string"==typeof e.content?e.content:"";t&&(c.push({type:"text",text:t}),f+=(f?"\n":"")+t);continue}if("tool"===i){let i="string"==typeof e.tool?e.tool:"string"==typeof e.name?e.name:"tool",r=a(e.state)?e.state:null,o=r&&a(r.input)?r.input:a(e.input)?e.input:a(e.args)?e.args:{},u={type:"tool_use",id:t.id,name:i,input:o},l=r&&"string"==typeof r.status?r.status:"";if(r&&("completed"===l||"error"===l)){let e=("error"===l&&"string"==typeof r.error?r.error:null)??r.output,i="string"==typeof e?e:null!=e?JSON.stringify(e):"",o=a(r.time)?r.time:{},d="number"==typeof o.start?o.start:t.time_created,m="number"==typeof o.end?o.end:t.time_updated,p=Math.max(0,m-d),c=new Date(m);u.result={timestamp:c.toISOString(),timestampFormatted:(0,n.formatTimestamp)(c),content:i,durationMs:p,durationFormatted:(0,s.formatDuration)(p)}}c.push(u);continue}c.push({type:"text",text:`[opencode ${i}]`})}if("user"===u)return{...p,type:"user",message:{role:"user",content:f}};if("assistant"===u){let t=a(r.model)?r.model:null,e=t&&"string"==typeof t.modelID?t.modelID:void 0;return{...p,type:"assistant",message:{role:"assistant",content:c,model:e}}}return{...p,type:"system",raw:{id:t.id,role:u,parts:c}}}(t,e,"session"));let i=o(t.data);p.push({id:t.id,session_id:t.session_id,time_created:t.time_created,data:i??t.data})}return{entries:m,rawLines:p,cwd:i.directory??void 0,filePath:`opencode://${t}`}}async function l(t){if(!t||!/^[A-Za-z0-9_-]+$/.test(t))return null;let e=r(`SELECT id, project_id, slug, directory, title, time_created, time_updated FROM session WHERE id = '${t}'`);if(!e||0===e.length)return null;let i=r(`SELECT id, session_id, time_created, time_updated, data FROM message WHERE session_id = '${t}' ORDER BY time_created ASC`),n=r(`SELECT id, message_id, session_id, time_created, time_updated, data FROM part WHERE session_id = '${t}' ORDER BY time_created ASC`);return null===i||null===n?null:{session:e[0],messages:i.map(t=>({...t,data:o(t.data)??t.data})),parts:n.map(t=>({...t,data:o(t.data)??t.data}))}}(0,i.runtimeCache)(t=>u(t),30,{maxSize:50}),t.s(["getOpenCodeSessionExport",0,l,"getOpenCodeSessionLog",0,u])}];
|
|
2
|
-
|
|
3
|
-
//# sourceMappingURL=%5Broot-of-the-server%5D__1qxztj-._.js.map
|
|
File without changes
|
|
File without changes
|
|
File without changes
|