@kici-dev/compiler 0.5.0 → 0.6.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/dist/cli.js +37 -7
- package/dist/commands/approve.d.ts +12 -0
- package/dist/commands/approve.js +5 -2
- package/dist/commands/compile.js +4 -2
- package/dist/commands/doctor.js +2 -2
- package/dist/commands/endpoints.js +4 -6
- package/dist/commands/held-run-client.d.ts +21 -1
- package/dist/commands/held-run-client.js +34 -15
- package/dist/commands/hook.js +22 -20
- package/dist/commands/index.d.ts +2 -0
- package/dist/commands/index.js +2 -1
- package/dist/commands/init.d.ts +9 -2
- package/dist/commands/init.js +43 -16
- package/dist/commands/login.js +1 -1
- package/dist/commands/orchestrators.js +3 -2
- package/dist/commands/reject.d.ts +12 -0
- package/dist/commands/reject.js +5 -2
- package/dist/commands/report/collect.d.ts +82 -0
- package/dist/commands/report/collect.js +234 -0
- package/dist/commands/report/identity.d.ts +48 -0
- package/dist/commands/report/identity.js +49 -0
- package/dist/commands/report/index.d.ts +63 -0
- package/dist/commands/report/index.js +119 -0
- package/dist/commands/report/upload.d.ts +38 -0
- package/dist/commands/report/upload.js +64 -0
- package/dist/commands/run-hold-watch.js +2 -2
- package/dist/commands/run.js +6 -3
- package/dist/commands/runs/show.js +80 -1
- package/dist/commands/types.js +51 -8
- package/dist/execution/sdk-alias.js +4 -2
- package/dist/fixtures/compiler.js +2 -1
- package/dist/format.js +3 -3
- package/dist/generators/secrets-dts.d.ts +8 -2
- package/dist/generators/secrets-dts.js +3 -2
- package/dist/hooks/installer.js +2 -1
- package/dist/llm-context/llms-architecture.txt +35 -13
- package/dist/llm-context/llms-cli.txt +142 -28
- package/dist/llm-context/llms-features-execution.txt +2017 -0
- package/dist/llm-context/llms-features.txt +298 -1483
- package/dist/llm-context/llms-full.txt +3008 -1698
- package/dist/llm-context/llms-getting-started.txt +145 -12
- package/dist/llm-context/llms-patterns.txt +176 -1
- package/dist/llm-context/llms-providers.txt +11 -27
- package/dist/llm-context/llms-sdk-runtime.txt +25 -4
- package/dist/llm-context/llms-sdk.txt +31 -1
- package/dist/llm-context/llms.txt +22 -14
- package/dist/local-plane/paths.d.ts +15 -0
- package/dist/local-plane/paths.js +22 -1
- package/dist/local-plane/plane-manager.js +2 -2
- package/dist/local-plane/port-holder.js +1 -1
- package/dist/local-plane/postgres.d.ts +3 -16
- package/dist/local-plane/postgres.js +10 -15
- package/dist/lockfile/generator.d.ts +12 -0
- package/dist/lockfile/generator.js +47 -14
- package/dist/postinstall.js +2 -1
- package/dist/remote/config.d.ts +2 -15
- package/dist/remote/config.js +2 -16
- package/dist/remote/dashboard-client.d.ts +39 -0
- package/dist/remote/dashboard-client.js +41 -0
- package/dist/remote/oauth.js +7 -5
- package/dist/remote/uploader.js +2 -2
- package/dist/templates/package-json.js +1 -1
- package/dist/test-runner/dry-run.js +4 -2
- package/dist/test-runner/git-detector.js +2 -1
- package/dist/test-runner/job-executor.js +2 -1
- package/dist/test-runner/payload-builder.js +11 -17
- package/dist/types.d.ts +33 -3
- package/dist/validation/validator.js +23 -6
- package/package.json +16 -11
- package/sbom.spdx.json +953 -901
|
@@ -8,19 +8,21 @@ The full markdown bundle of every page indexed here is available at https://docs
|
|
|
8
8
|
|
|
9
9
|
Each bundle below is a self-contained markdown file for one authoring task. Fetch only the one your task needs instead of the full bundle:
|
|
10
10
|
|
|
11
|
-
- [getting-started](https://docs.kici.dev/llms-getting-started.txt) (
|
|
12
|
-
- [patterns](https://docs.kici.dev/llms-patterns.txt) (
|
|
13
|
-
- [sdk](https://docs.kici.dev/llms-sdk.txt) (
|
|
14
|
-
- [sdk-runtime](https://docs.kici.dev/llms-sdk-runtime.txt) (
|
|
15
|
-
- [cli](https://docs.kici.dev/llms-cli.txt) (
|
|
16
|
-
- [features](https://docs.kici.dev/llms-features.txt) (
|
|
17
|
-
- [
|
|
18
|
-
- [
|
|
11
|
+
- [getting-started](https://docs.kici.dev/llms-getting-started.txt) (58 KB) — Adopt KiCI: why it exists, how workflows execute, migrating from GitHub Actions, installing the SDK, and writing/compiling/testing your first workflow
|
|
12
|
+
- [patterns](https://docs.kici.dev/llms-patterns.txt) (57 KB) — Copy-paste workflow recipes: triggers, conditionals, matrix, scheduling, integrations
|
|
13
|
+
- [sdk](https://docs.kici.dev/llms-sdk.txt) (127 KB) — Core authoring API: workflow/job/step factories, triggers, rules, matrix, dynamic jobs, cross-job outputs
|
|
14
|
+
- [sdk-runtime](https://docs.kici.dev/llms-sdk-runtime.txt) (114 KB) — Runtime and advanced authoring: step runtime context, event payloads, host fan-out, idempotent steps, caching, artifacts, waiting
|
|
15
|
+
- [cli](https://docs.kici.dev/llms-cli.txt) (194 KB) — Running the CLI: compile, test, run local/remote, auth, hooks, lock-file drift
|
|
16
|
+
- [features](https://docs.kici.dev/llms-features.txt) (90 KB) — Deployment contexts, scoped secrets, private registries, approvals, provenance, dashboard and account access
|
|
17
|
+
- [features-execution](https://docs.kici.dev/llms-features-execution.txt) (120 KB) — Concurrency, dynamic values, events, container jobs, environment variables, global workflows, idempotent steps
|
|
18
|
+
- [providers](https://docs.kici.dev/llms-providers.txt) (35 KB) — Connecting sources: GitHub App, universal-git (Forgejo/Gitea/GitLab), local file://
|
|
19
|
+
- [architecture](https://docs.kici.dev/llms-architecture.txt) (99 KB) — How the runtime works: three-tier relay model, data flows, configuration
|
|
19
20
|
|
|
20
21
|
## Getting started
|
|
21
22
|
|
|
22
23
|
- [User guide](https://docs.kici.dev/user/): Writing and testing CI/CD workflows in TypeScript, running on infrastructure you control
|
|
23
24
|
- [How your workflow code executes](https://docs.kici.dev/user/execution-model/): When and where your workflow TypeScript runs — compile time, orchestrator time, and agent time
|
|
25
|
+
- [Getting help](https://docs.kici.dev/user/getting-help/): How to report a problem to KiCI and send the diagnostic context privately
|
|
24
26
|
- [Getting started with workflows](https://docs.kici.dev/user/getting-started/): Install the SDK, write your first workflow, compile and test locally
|
|
25
27
|
- [Migrating from GitHub Actions](https://docs.kici.dev/user/migrating-from-github-actions/): Map GitHub Actions concepts to KiCI, translate a real workflow side-by-side, and see what has no equivalent yet
|
|
26
28
|
- [5-minute quickstart](https://docs.kici.dev/user/quickstart/): Stand up a KiCI orchestrator + agent and run your first workflow
|
|
@@ -30,6 +32,7 @@ Each bundle below is a self-contained markdown file for one authoring task. Fetc
|
|
|
30
32
|
|
|
31
33
|
- [Basic workflow patterns](https://docs.kici.dev/user/patterns/basic/): Basic CI, PR-only / push-only filters, multiple triggers, manual-only workflows
|
|
32
34
|
- [Conditionals & matrix patterns](https://docs.kici.dev/user/patterns/conditionals-matrix/): Conditional execution with rules, matrix builds (static + dynamic), dynamic job generation
|
|
35
|
+
- [Git credentials](https://docs.kici.dev/user/patterns/git-credentials/): Authenticated git in a workflow — declaring credentials from the secrets backend, and pushing
|
|
33
36
|
- [Host restart & wait-for-alive](https://docs.kici.dev/user/patterns/host-restart/): Reboot the host a workflow runs on and continue after it comes back
|
|
34
37
|
- [Integration patterns](https://docs.kici.dev/user/patterns/integrations/): Workflow chaining, generic webhooks, Stripe, self-hosted git forges, plain GitHub repos
|
|
35
38
|
- [Pattern reference](https://docs.kici.dev/user/patterns/reference/): Step context, examples repository, GitHub check run output — cross-cutting reference for all patterns
|
|
@@ -59,7 +62,7 @@ Each bundle below is a self-contained markdown file for one authoring task. Fetc
|
|
|
59
62
|
|
|
60
63
|
- [Drive KiCI from your coding agent](https://docs.kici.dev/user/ai-agents/): Point a coding agent at KiCI's MCP server and let it trigger, read, and re-run your CI under your own identity.
|
|
61
64
|
- [CLI authentication](https://docs.kici.dev/user/cli-auth/): Authenticate the KiCI CLI with browser OAuth, device flow, or API key paste
|
|
62
|
-
- [CLI reference](https://docs.kici.dev/user/cli-reference/): All CLI commands: compile, preview, local, fixture, types, workflows, hook, docs, run, runs, approve, reject, login, logout, init, org, pat, secrets, admin, orchestrators, endpoints, notifications, verify-attestation, diagnostics, doctor
|
|
65
|
+
- [CLI reference](https://docs.kici.dev/user/cli-reference/): All CLI commands: compile, preview, local, fixture, types, workflows, hook, docs, run, runs, approve, reject, login, logout, init, org, pat, secrets, admin, orchestrators, endpoints, notifications, verify-attestation, diagnostics, doctor, report
|
|
63
66
|
- [Common failures](https://docs.kici.dev/user/common-failures/): Symptom-to-fix reference for the failures workflow authors hit most — no jobs dispatched, lock-file drift, missing webhooks, and agents that won't connect
|
|
64
67
|
- [Lifecycle hooks](https://docs.kici.dev/user/hooks/): SDK hook API for cancel, cleanup, success, failure, and step-level callbacks
|
|
65
68
|
- [Lock file and workflow drift](https://docs.kici.dev/user/lock-file-and-drift/): Keep the lock file in sync with your workflow source and avoid drift
|
|
@@ -70,21 +73,26 @@ Each bundle below is a self-contained markdown file for one authoring task. Fetc
|
|
|
70
73
|
- [kici: notifications & diagnostics](https://docs.kici.dev/user/cli/notifications-and-diagnostics/): Notification channels, attestation verification, and diagnostics
|
|
71
74
|
- [kici: runs & approvals](https://docs.kici.dev/user/cli/runs-and-approvals/): Run push and inspection plus approval / rejection of held runs
|
|
72
75
|
|
|
73
|
-
## Workflow features
|
|
76
|
+
## Workflow features: access and approval
|
|
74
77
|
|
|
75
78
|
- [Account and sign-in](https://docs.kici.dev/user/account-and-login/): How your KiCI account relates to sign-in methods, and how to change the way you sign in.
|
|
76
79
|
- [Approval gates](https://docs.kici.dev/user/approvals/): Pause a workflow for human sign-off at step, job, or workflow granularity with approval
|
|
77
|
-
- [Concurrency groups](https://docs.kici.dev/user/concurrency/): Control parallel execution with auto-cancel and queue modes
|
|
78
80
|
- [Contexts](https://docs.kici.dev/user/contexts/): Configure deployment contexts with variables, secrets, and protection rules
|
|
79
81
|
- [Dashboard](https://docs.kici.dev/user/dashboard/): Web UI for monitoring workflow runs, managing sources, secrets, and organization settings.
|
|
82
|
+
- [Private npm registries](https://docs.kici.dev/user/private-registries/): Authenticate `npm install` against private registries (CodeArtifact, GitHub Packages, Verdaccio, …) from a workflow's `.kici/package.json`
|
|
83
|
+
- [Build provenance and attestations](https://docs.kici.dev/user/provenance/): Generate and verify signed SLSA provenance for the artifacts your workflows build
|
|
84
|
+
- [Secrets](https://docs.kici.dev/user/secrets/): How to access secrets in KiCI workflow steps
|
|
85
|
+
|
|
86
|
+
## Workflow features: execution
|
|
87
|
+
|
|
88
|
+
- [Concurrency groups](https://docs.kici.dev/user/concurrency/): Control parallel execution with auto-cancel and queue modes
|
|
89
|
+
- [Container jobs](https://docs.kici.dev/user/container-jobs/): Run a job inside any container image, including a private one, without that image shipping Node or git
|
|
80
90
|
- [Dynamic values](https://docs.kici.dev/user/dynamic-values/): Compute a job's context, env, and concurrencyGroup at runtime from the incoming event
|
|
81
91
|
- [Environment variables](https://docs.kici.dev/user/env-vars/): Environment variable reference for the CLI
|
|
82
92
|
- [Event system](https://docs.kici.dev/user/events/): How KiCI's event model works -- event types, the registration model, event matching, and circuit breaker protection
|
|
83
93
|
- [Global workflows](https://docs.kici.dev/user/global-workflows/): Cross-repo workflows that run on events from any repo in the same org
|
|
84
94
|
- [Idempotent steps and check mode](https://docs.kici.dev/user/idempotent-steps/): Declare desired state with a step check facet, then run in apply or --check preview mode
|
|
85
|
-
- [
|
|
86
|
-
- [Build provenance and attestations](https://docs.kici.dev/user/provenance/): Generate and verify signed SLSA provenance for the artifacts your workflows build
|
|
87
|
-
- [Secrets](https://docs.kici.dev/user/secrets/): How to access secrets in KiCI workflow steps
|
|
95
|
+
- [Autoscaling workflows](https://docs.kici.dev/user/workflows/autoscaling-workflows/): Write TypeScript provisioning and teardown workflows that boot and delete ephemeral cloud agents in response to the event scaler
|
|
88
96
|
|
|
89
97
|
## Providers
|
|
90
98
|
|
|
@@ -7,6 +7,21 @@ export declare const PLANE_STAMP_VERSION = 3;
|
|
|
7
7
|
/**
|
|
8
8
|
* Root directory of the local dev plane's state, following the same
|
|
9
9
|
* `KICI_CONFIG_DIR` → `~/.kici` convention the rest of the CLI uses.
|
|
10
|
+
*
|
|
11
|
+
* RESOLVED THROUGH SYMLINKS, deliberately. The plane is a singleton on fixed
|
|
12
|
+
* ports, so a caller may reach it through a config dir that only symlinks
|
|
13
|
+
* `local` at the durable one — `pnpm deploy:stg` does exactly that, to run
|
|
14
|
+
* against a throwaway config dir carrying no credentials while still reusing
|
|
15
|
+
* the warm plane.
|
|
16
|
+
*
|
|
17
|
+
* Without resolving, the plane's Postgres is started with a data directory
|
|
18
|
+
* addressed through that ephemeral path and keeps it open. When the caller
|
|
19
|
+
* removes its temp dir, Postgres PANICs — `could not open file
|
|
20
|
+
* "<tmp>/local/pgdata/global/pg_control"` — and shuts the whole plane down,
|
|
21
|
+
* taking every later phase with it. Resolving first means Postgres only ever
|
|
22
|
+
* sees the durable path, so a caller's temp dir can come and go beneath it.
|
|
23
|
+
*
|
|
24
|
+
* A path that does not exist yet resolves to itself: a fresh plane creates it.
|
|
10
25
|
*/
|
|
11
26
|
export declare function planeRoot(): string;
|
|
12
27
|
/**
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import "../rolldown-runtime-ClRpJifh.js";
|
|
2
2
|
import path from "node:path";
|
|
3
|
+
import fs from "node:fs";
|
|
3
4
|
import os from "node:os";
|
|
4
5
|
//#region src/local-plane/paths.ts
|
|
5
6
|
/**
|
|
@@ -11,10 +12,30 @@ const PLANE_STAMP_VERSION = 3;
|
|
|
11
12
|
/**
|
|
12
13
|
* Root directory of the local dev plane's state, following the same
|
|
13
14
|
* `KICI_CONFIG_DIR` → `~/.kici` convention the rest of the CLI uses.
|
|
15
|
+
*
|
|
16
|
+
* RESOLVED THROUGH SYMLINKS, deliberately. The plane is a singleton on fixed
|
|
17
|
+
* ports, so a caller may reach it through a config dir that only symlinks
|
|
18
|
+
* `local` at the durable one — `pnpm deploy:stg` does exactly that, to run
|
|
19
|
+
* against a throwaway config dir carrying no credentials while still reusing
|
|
20
|
+
* the warm plane.
|
|
21
|
+
*
|
|
22
|
+
* Without resolving, the plane's Postgres is started with a data directory
|
|
23
|
+
* addressed through that ephemeral path and keeps it open. When the caller
|
|
24
|
+
* removes its temp dir, Postgres PANICs — `could not open file
|
|
25
|
+
* "<tmp>/local/pgdata/global/pg_control"` — and shuts the whole plane down,
|
|
26
|
+
* taking every later phase with it. Resolving first means Postgres only ever
|
|
27
|
+
* sees the durable path, so a caller's temp dir can come and go beneath it.
|
|
28
|
+
*
|
|
29
|
+
* A path that does not exist yet resolves to itself: a fresh plane creates it.
|
|
14
30
|
*/
|
|
15
31
|
function planeRoot() {
|
|
16
32
|
const base = process.env.KICI_CONFIG_DIR ?? path.join(os.homedir(), ".kici");
|
|
17
|
-
|
|
33
|
+
const root = path.join(base, "local");
|
|
34
|
+
try {
|
|
35
|
+
return fs.realpathSync(root);
|
|
36
|
+
} catch {
|
|
37
|
+
return root;
|
|
38
|
+
}
|
|
18
39
|
}
|
|
19
40
|
/**
|
|
20
41
|
* Absolute paths for every artefact the plane persists under its state root.
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* `TS_CONST_PINS` in hack/containers-lock.ts (identity
|
|
4
4
|
* docker.io/library/postgres+alpine), so a lock bump rewrites it in place.
|
|
5
5
|
*/
|
|
6
|
-
export declare const PLANE_PG_IMAGE = "docker.io/library/postgres:18.
|
|
6
|
+
export declare const PLANE_PG_IMAGE = "docker.io/library/postgres:18.6-alpine";
|
|
7
7
|
/** Name of the fallback podman Postgres container. */
|
|
8
8
|
export declare const PLANE_PG_CONTAINER = "kici-local-postgres";
|
|
9
9
|
export type PlanePgHandle = {
|
|
@@ -11,13 +11,6 @@ export type PlanePgHandle = {
|
|
|
11
11
|
kind: 'embedded' | 'podman';
|
|
12
12
|
stop(): Promise<void>;
|
|
13
13
|
};
|
|
14
|
-
declare let readyPoller: typeof defaultReadyPoller;
|
|
15
|
-
/** Test seam: override the podman readiness poller. */
|
|
16
|
-
export declare function __setReadyPollerForTest(fn: typeof readyPoller): void;
|
|
17
|
-
declare let embeddedDaemon: typeof defaultEmbeddedDaemon;
|
|
18
|
-
/** Test seam: override the embedded postmaster daemonizer. */
|
|
19
|
-
export declare function __setEmbeddedDaemonForTest(fn: typeof embeddedDaemon): void;
|
|
20
|
-
declare function defaultReadyPoller(_port: number): Promise<boolean>;
|
|
21
14
|
/**
|
|
22
15
|
* Whether this plane's embedded postmaster is already serving `port`.
|
|
23
16
|
*
|
|
@@ -31,13 +24,6 @@ declare function defaultReadyPoller(_port: number): Promise<boolean>;
|
|
|
31
24
|
* one this plane can reuse.
|
|
32
25
|
*/
|
|
33
26
|
export declare function embeddedClusterIsServing(port: number): Promise<boolean>;
|
|
34
|
-
/**
|
|
35
|
-
* Start a detached embedded postmaster via `pg_ctl` so it survives the exit of
|
|
36
|
-
* this CLI process (embedded-postgres's in-process server is killed by its own
|
|
37
|
-
* exit hook, so it cannot back a warm plane). A cluster already serving this
|
|
38
|
-
* plane's port is reused as-is.
|
|
39
|
-
*/
|
|
40
|
-
declare function defaultEmbeddedDaemon(port: number): Promise<void>;
|
|
41
27
|
/**
|
|
42
28
|
* Stop the plane's Postgres by backend kind. Handle-independent so a separate
|
|
43
29
|
* CLI invocation (`kici local down`) can tear down what `up` started.
|
|
@@ -51,6 +37,7 @@ export declare function stopPlanePostgres(kind: 'embedded' | 'podman'): Promise<
|
|
|
51
37
|
*/
|
|
52
38
|
export declare function startPlanePostgres(opts?: {
|
|
53
39
|
forcePodman?: boolean;
|
|
40
|
+
readyPoller?: (port: number) => Promise<boolean>;
|
|
41
|
+
embeddedDaemon?: (port: number) => Promise<void>;
|
|
54
42
|
}): Promise<PlanePgHandle>;
|
|
55
|
-
export {};
|
|
56
43
|
//# sourceMappingURL=postgres.d.ts.map
|
|
@@ -13,19 +13,9 @@ import EmbeddedPostgres from "embedded-postgres";
|
|
|
13
13
|
* `TS_CONST_PINS` in hack/containers-lock.ts (identity
|
|
14
14
|
* docker.io/library/postgres+alpine), so a lock bump rewrites it in place.
|
|
15
15
|
*/
|
|
16
|
-
const PLANE_PG_IMAGE = "docker.io/library/postgres:18.
|
|
16
|
+
const PLANE_PG_IMAGE = "docker.io/library/postgres:18.6-alpine";
|
|
17
17
|
/** Name of the fallback podman Postgres container. */
|
|
18
18
|
const PLANE_PG_CONTAINER = "kici-local-postgres";
|
|
19
|
-
let readyPoller = defaultReadyPoller;
|
|
20
|
-
/** Test seam: override the podman readiness poller. */
|
|
21
|
-
function __setReadyPollerForTest(fn) {
|
|
22
|
-
readyPoller = fn;
|
|
23
|
-
}
|
|
24
|
-
let embeddedDaemon = defaultEmbeddedDaemon;
|
|
25
|
-
/** Test seam: override the embedded postmaster daemonizer. */
|
|
26
|
-
function __setEmbeddedDaemonForTest(fn) {
|
|
27
|
-
embeddedDaemon = fn;
|
|
28
|
-
}
|
|
29
19
|
async function defaultReadyPoller(_port) {
|
|
30
20
|
for (let i = 0; i < 60; i++) try {
|
|
31
21
|
await $`podman exec ${PLANE_PG_CONTAINER} pg_isready -U kici`.quiet();
|
|
@@ -56,7 +46,8 @@ function resolvePgCtl() {
|
|
|
56
46
|
"win32:x64": "@embedded-postgres/windows-x64"
|
|
57
47
|
}[`${platform}:${arch}`];
|
|
58
48
|
if (!pkg) throw new Error(`unsupported platform for embedded Postgres: ${platform}/${arch}`);
|
|
59
|
-
const
|
|
49
|
+
const require = createRequire(import.meta.url);
|
|
50
|
+
const entry = createRequire(require.resolve("embedded-postgres")).resolve(pkg);
|
|
60
51
|
const binName = platform === "win32" ? "pg_ctl.exe" : "pg_ctl";
|
|
61
52
|
return path.resolve(path.dirname(entry), "..", "native", "bin", binName);
|
|
62
53
|
}
|
|
@@ -119,13 +110,15 @@ async function embeddedClusterIsServing(port) {
|
|
|
119
110
|
async function defaultEmbeddedDaemon(port) {
|
|
120
111
|
const { pgData, logFile } = planePaths();
|
|
121
112
|
if (await embeddedClusterIsServing(port)) return;
|
|
122
|
-
|
|
113
|
+
const pgCtl = resolvePgCtl();
|
|
114
|
+
await $`${pgCtl} -D ${pgData} -o ${`-p ${port}`} -l ${`${logFile}.pg`} -w start`.quiet();
|
|
123
115
|
}
|
|
124
116
|
/** Stop the detached embedded postmaster (handle-independent, reads the data dir). */
|
|
125
117
|
async function stopEmbeddedDaemon() {
|
|
126
118
|
const { pgData } = planePaths();
|
|
127
119
|
if (!fs.existsSync(path.join(pgData, "postmaster.pid"))) return;
|
|
128
|
-
|
|
120
|
+
const pgCtl = resolvePgCtl();
|
|
121
|
+
await $`${pgCtl} -D ${pgData} stop -m fast`.quiet().catch(() => {});
|
|
129
122
|
}
|
|
130
123
|
/**
|
|
131
124
|
* Stop the plane's Postgres by backend kind. Handle-independent so a separate
|
|
@@ -142,6 +135,8 @@ async function stopPlanePostgres(kind) {
|
|
|
142
135
|
* (or when forced via `forcePodman` / `KICI_LOCAL_PG_MODE=podman`).
|
|
143
136
|
*/
|
|
144
137
|
async function startPlanePostgres(opts = {}) {
|
|
138
|
+
const readyPoller = opts.readyPoller ?? defaultReadyPoller;
|
|
139
|
+
const embeddedDaemon = opts.embeddedDaemon ?? defaultEmbeddedDaemon;
|
|
145
140
|
const { postgres: port } = planePorts();
|
|
146
141
|
const url = `postgres://kici:kici@127.0.0.1:${port}/kici_local`;
|
|
147
142
|
if (!(opts.forcePodman || process.env.KICI_LOCAL_PG_MODE === "podman")) try {
|
|
@@ -182,6 +177,6 @@ async function startPlanePostgres(opts = {}) {
|
|
|
182
177
|
};
|
|
183
178
|
}
|
|
184
179
|
//#endregion
|
|
185
|
-
export { PLANE_PG_CONTAINER, PLANE_PG_IMAGE,
|
|
180
|
+
export { PLANE_PG_CONTAINER, PLANE_PG_IMAGE, embeddedClusterIsServing, startPlanePostgres, stopPlanePostgres };
|
|
186
181
|
|
|
187
182
|
//# sourceMappingURL=postgres.js.map
|
|
@@ -36,6 +36,18 @@ export declare function detectGitRoot(): string;
|
|
|
36
36
|
* For yarn the prefix also carries the flavor (`yarn-classic` / `yarn-berry`),
|
|
37
37
|
* so a classic-layout dep-cache tarball is never restored into a berry install.
|
|
38
38
|
*
|
|
39
|
+
* The detected manager only orders the search; it never restricts it. Detection
|
|
40
|
+
* falls back to the AMBIENT `npm_config_user_agent` when a directory carries no
|
|
41
|
+
* signal of its own, so a repo whose root holds neither a `package.json` nor a
|
|
42
|
+
* lockfile is reported as whatever manager happened to invoke the compiler. A
|
|
43
|
+
* repo compiled under pnpm that keeps an npm `.kici/package-lock.json` was
|
|
44
|
+
* therefore searched for `pnpm-lock.yaml` only, found none, and got no hash at
|
|
45
|
+
* all — which silently disables the orchestrator's dependency cache for it, so
|
|
46
|
+
* every agent installs from the registry and an agent with no registry route
|
|
47
|
+
* cannot run the job at all. Searching every manager's candidates after the
|
|
48
|
+
* detected one's keeps the detected manager authoritative where it has real
|
|
49
|
+
* evidence, and still finds the lockfile that is actually on disk.
|
|
50
|
+
*
|
|
39
51
|
* @param gitRoot - Absolute path to git repository root
|
|
40
52
|
* @returns Hex SHA-256 hash string, or null if no lockfile is found
|
|
41
53
|
*/
|
|
@@ -66,16 +66,39 @@ function detectGitRoot() {
|
|
|
66
66
|
* For yarn the prefix also carries the flavor (`yarn-classic` / `yarn-berry`),
|
|
67
67
|
* so a classic-layout dep-cache tarball is never restored into a berry install.
|
|
68
68
|
*
|
|
69
|
+
* The detected manager only orders the search; it never restricts it. Detection
|
|
70
|
+
* falls back to the AMBIENT `npm_config_user_agent` when a directory carries no
|
|
71
|
+
* signal of its own, so a repo whose root holds neither a `package.json` nor a
|
|
72
|
+
* lockfile is reported as whatever manager happened to invoke the compiler. A
|
|
73
|
+
* repo compiled under pnpm that keeps an npm `.kici/package-lock.json` was
|
|
74
|
+
* therefore searched for `pnpm-lock.yaml` only, found none, and got no hash at
|
|
75
|
+
* all — which silently disables the orchestrator's dependency cache for it, so
|
|
76
|
+
* every agent installs from the registry and an agent with no registry route
|
|
77
|
+
* cannot run the job at all. Searching every manager's candidates after the
|
|
78
|
+
* detected one's keeps the detected manager authoritative where it has real
|
|
79
|
+
* evidence, and still finds the lockfile that is actually on disk.
|
|
80
|
+
*
|
|
69
81
|
* @param gitRoot - Absolute path to git repository root
|
|
70
82
|
* @returns Hex SHA-256 hash string, or null if no lockfile is found
|
|
71
83
|
*/
|
|
72
84
|
function computeLockfileHash(gitRoot) {
|
|
73
85
|
const pm = detectPackageManagerSync(gitRoot) === PackageManager.Npm ? detectPackageManagerSync(path.join(gitRoot, ".kici")) : detectPackageManagerSync(gitRoot);
|
|
74
|
-
const
|
|
75
|
-
const
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
86
|
+
const byManager = (m) => m === PackageManager.Pnpm ? [path.join(gitRoot, "pnpm-lock.yaml"), path.join(gitRoot, ".kici", "pnpm-lock.yaml")] : m === PackageManager.Yarn ? [path.join(gitRoot, "yarn.lock"), path.join(gitRoot, ".kici", "yarn.lock")] : [path.join(gitRoot, ".kici", "package-lock.json")];
|
|
87
|
+
const order = [pm, ...[
|
|
88
|
+
PackageManager.Npm,
|
|
89
|
+
PackageManager.Pnpm,
|
|
90
|
+
PackageManager.Yarn
|
|
91
|
+
].filter((m) => m !== pm)];
|
|
92
|
+
for (const manager of order) for (const lockfilePath of byManager(manager)) {
|
|
93
|
+
let content;
|
|
94
|
+
try {
|
|
95
|
+
content = readFileSync(lockfilePath, "utf-8");
|
|
96
|
+
} catch {
|
|
97
|
+
continue;
|
|
98
|
+
}
|
|
99
|
+
const prefix = manager === PackageManager.Yarn ? `${manager}-${detectYarnFlavorSync(path.dirname(lockfilePath))}` : manager;
|
|
100
|
+
return sha256(`${prefix}\n${content}`);
|
|
101
|
+
}
|
|
79
102
|
return null;
|
|
80
103
|
}
|
|
81
104
|
/**
|
|
@@ -112,16 +135,17 @@ function generateLockFile(workflowsWithSource) {
|
|
|
112
135
|
const workflows = workflowsWithSource.map(({ workflow, source, bundleSource }) => {
|
|
113
136
|
return transformWorkflow(workflow, path.relative(gitRoot, source.file).replaceAll("\\", "/"), formatExportRef(source), bundleSource, gitRoot);
|
|
114
137
|
});
|
|
138
|
+
const contentHash = sha256(JSON.stringify({
|
|
139
|
+
schemaVersion: SCHEMA_VERSION$1,
|
|
140
|
+
minReaderVersion: BREAKING_FLOOR$1,
|
|
141
|
+
source: topLevelSource,
|
|
142
|
+
workflows
|
|
143
|
+
}));
|
|
115
144
|
return {
|
|
116
145
|
schemaVersion: SCHEMA_VERSION$1,
|
|
117
146
|
minReaderVersion: BREAKING_FLOOR$1,
|
|
118
147
|
source: topLevelSource,
|
|
119
|
-
contentHash
|
|
120
|
-
schemaVersion: SCHEMA_VERSION$1,
|
|
121
|
-
minReaderVersion: BREAKING_FLOOR$1,
|
|
122
|
-
source: topLevelSource,
|
|
123
|
-
workflows
|
|
124
|
-
})),
|
|
148
|
+
contentHash,
|
|
125
149
|
...lockfileHash && { lockfileHash },
|
|
126
150
|
workflows
|
|
127
151
|
};
|
|
@@ -209,12 +233,14 @@ function serializeRegexEntry(entry, ctx) {
|
|
|
209
233
|
try {
|
|
210
234
|
re = new RegExp(pattern, flags);
|
|
211
235
|
} catch (err) {
|
|
212
|
-
|
|
236
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
237
|
+
throw compilerError("E123", `${ctx}: invalid regex — ${reason}`);
|
|
213
238
|
}
|
|
214
239
|
try {
|
|
215
240
|
assertSafeRegex(re.source, re.flags, ctx);
|
|
216
241
|
} catch (err) {
|
|
217
|
-
|
|
242
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
243
|
+
throw compilerError("E123", `${ctx}: ${reason}`);
|
|
218
244
|
}
|
|
219
245
|
return `/${re.source}/${re.flags}`;
|
|
220
246
|
}
|
|
@@ -660,7 +686,7 @@ function transformJob(job, configPath, index, gitRoot, uuidToName) {
|
|
|
660
686
|
location: jobLocation,
|
|
661
687
|
suggestion: "Set exactly one of runsOn (single agent) or runsOnAll (fan-out to every matching agent)."
|
|
662
688
|
});
|
|
663
|
-
if (job.runsOn === void 0 && job.runsOnAll === void 0) throw compilerError("E109", `job '${job.name}': one of runsOn or runsOnAll is required`, {
|
|
689
|
+
if (job.invoke === void 0 && job.runsOn === void 0 && job.runsOnAll === void 0) throw compilerError("E109", `job '${job.name}': one of runsOn or runsOnAll is required`, {
|
|
664
690
|
location: jobLocation,
|
|
665
691
|
suggestion: "Add runsOn: \"kici:os:linux\" (or another agent label) to the job."
|
|
666
692
|
});
|
|
@@ -700,8 +726,15 @@ function transformJob(job, configPath, index, gitRoot, uuidToName) {
|
|
|
700
726
|
...job.runsOnAll !== void 0 && { runsOnAll: normalizeRunsOnAllToMatchers(job.runsOnAll, `job '${job.name}' runsOnAll`) },
|
|
701
727
|
...job.onUnreachable !== void 0 && { onUnreachable: job.onUnreachable },
|
|
702
728
|
...job.includeUninitialized !== void 0 && { includeUninitialized: job.includeUninitialized },
|
|
729
|
+
...job.gitCredentials !== void 0 && { gitCredentials: job.gitCredentials },
|
|
703
730
|
...job.maxParallel !== void 0 && { maxParallel: job.maxParallel },
|
|
704
731
|
...job.failFast !== void 0 && { failFast: job.failFast },
|
|
732
|
+
...job.invoke !== void 0 && { invoke: {
|
|
733
|
+
event: job.invoke.event,
|
|
734
|
+
scope: job.invoke.scope,
|
|
735
|
+
...job.invoke.payload !== void 0 && { payload: job.invoke.payload },
|
|
736
|
+
...job.invoke.optional === true && { optional: true }
|
|
737
|
+
} },
|
|
705
738
|
...resolveNeedsForLock(job.needs, uuidToName),
|
|
706
739
|
steps: transformSteps(job.steps, gitRoot, jobLocation),
|
|
707
740
|
matrix: job.matrix ? transformMatrix(job.matrix, job.name, configPath) : void 0,
|
package/dist/postinstall.js
CHANGED
|
@@ -26,7 +26,8 @@ async function detectDevelopmentMode() {
|
|
|
26
26
|
if (process.env.KICI_DEV === "true") return true;
|
|
27
27
|
try {
|
|
28
28
|
const rootDir = process.env.INIT_CWD || process.cwd();
|
|
29
|
-
const
|
|
29
|
+
const rootPkgPath = path.join(rootDir, "package.json");
|
|
30
|
+
const content = await readFile(rootPkgPath, "utf-8");
|
|
30
31
|
return JSON.parse(content).kici?.development === true;
|
|
31
32
|
} catch {
|
|
32
33
|
return false;
|
package/dist/remote/config.d.ts
CHANGED
|
@@ -35,22 +35,9 @@ export interface GlobalConfig {
|
|
|
35
35
|
*
|
|
36
36
|
* Resolution order:
|
|
37
37
|
* 1. `KICI_CONFIG_DIR`, when set to a non-empty value.
|
|
38
|
-
* 2.
|
|
39
|
-
* machine's `~/.kici/config` names a real endpoint and carries a live
|
|
40
|
-
* PAT, so a test process that reads it authenticates against whatever
|
|
41
|
-
* that config points at — in practice, production. Every test that needs
|
|
42
|
-
* a config must name its own isolated directory.
|
|
43
|
-
* 3. `~/.kici`.
|
|
38
|
+
* 2. `~/.kici`.
|
|
44
39
|
*
|
|
45
|
-
* `
|
|
46
|
-
* `hack/lib/vitest-isolation.ts`. It is deliberately a KiCI-owned name rather
|
|
47
|
-
* than the runner's `VITEST`: `kici` is a compat-protected CLI, and `VITEST`
|
|
48
|
-
* is a third-party marker that propagates into spawned children, so keying off
|
|
49
|
-
* it would break a customer whose vitest test shells out to `kici`.
|
|
50
|
-
*
|
|
51
|
-
* `env` is injectable so this module's own tests can exercise every branch.
|
|
52
|
-
* It is NOT an opt-out: production call sites pass no argument and inherit the
|
|
53
|
-
* guard.
|
|
40
|
+
* `env` is injectable so this module's own tests can exercise both branches.
|
|
54
41
|
*/
|
|
55
42
|
export declare function getConfigDir(env?: NodeJS.ProcessEnv): string;
|
|
56
43
|
/**
|
package/dist/remote/config.js
CHANGED
|
@@ -33,26 +33,12 @@ function sanitizeConfig(raw) {
|
|
|
33
33
|
*
|
|
34
34
|
* Resolution order:
|
|
35
35
|
* 1. `KICI_CONFIG_DIR`, when set to a non-empty value.
|
|
36
|
-
* 2.
|
|
37
|
-
* machine's `~/.kici/config` names a real endpoint and carries a live
|
|
38
|
-
* PAT, so a test process that reads it authenticates against whatever
|
|
39
|
-
* that config points at — in practice, production. Every test that needs
|
|
40
|
-
* a config must name its own isolated directory.
|
|
41
|
-
* 3. `~/.kici`.
|
|
36
|
+
* 2. `~/.kici`.
|
|
42
37
|
*
|
|
43
|
-
* `
|
|
44
|
-
* `hack/lib/vitest-isolation.ts`. It is deliberately a KiCI-owned name rather
|
|
45
|
-
* than the runner's `VITEST`: `kici` is a compat-protected CLI, and `VITEST`
|
|
46
|
-
* is a third-party marker that propagates into spawned children, so keying off
|
|
47
|
-
* it would break a customer whose vitest test shells out to `kici`.
|
|
48
|
-
*
|
|
49
|
-
* `env` is injectable so this module's own tests can exercise every branch.
|
|
50
|
-
* It is NOT an opt-out: production call sites pass no argument and inherit the
|
|
51
|
-
* guard.
|
|
38
|
+
* `env` is injectable so this module's own tests can exercise both branches.
|
|
52
39
|
*/
|
|
53
40
|
function getConfigDir(env = process.env) {
|
|
54
41
|
if (env.KICI_CONFIG_DIR) return env.KICI_CONFIG_DIR;
|
|
55
|
-
if (env.KICI_TEST_ISOLATION) throw new Error("Refusing to read the ambient ~/.kici config from a test process. Set KICI_CONFIG_DIR to an isolated directory for this run — the developer machine config may point at production.");
|
|
56
42
|
return path.join(os.homedir(), ".kici");
|
|
57
43
|
}
|
|
58
44
|
/**
|
|
@@ -37,6 +37,18 @@ export declare const webhookActivitySchema: z.ZodObject<{
|
|
|
37
37
|
orchestratorUnavailable: z.ZodBoolean;
|
|
38
38
|
}, z.core.$strip>;
|
|
39
39
|
export type WebhookActivity = z.infer<typeof webhookActivitySchema>;
|
|
40
|
+
declare const issueReportListSchema: z.ZodObject<{
|
|
41
|
+
reports: z.ZodArray<z.ZodObject<{
|
|
42
|
+
ref: z.ZodString;
|
|
43
|
+
bundleId: z.ZodString;
|
|
44
|
+
byteSize: z.ZodNumber;
|
|
45
|
+
status: z.ZodString;
|
|
46
|
+
createdAt: z.ZodString;
|
|
47
|
+
userId: z.ZodString;
|
|
48
|
+
message: z.ZodNullable<z.ZodString>;
|
|
49
|
+
}, z.core.$strip>>;
|
|
50
|
+
}, z.core.$strip>;
|
|
51
|
+
export type IssueReportListResponse = z.infer<typeof issueReportListSchema>;
|
|
40
52
|
/** Result of {@link DashboardClient.listRegistrations}. */
|
|
41
53
|
export interface RegistrationsListResult {
|
|
42
54
|
registrations: RegistrationItem[];
|
|
@@ -104,6 +116,33 @@ export declare class DashboardClient {
|
|
|
104
116
|
* relays it without re-signing, so the artifact bytes never transit Platform.
|
|
105
117
|
*/
|
|
106
118
|
listArtifacts(runId: string): Promise<ArtifactsListResult>;
|
|
119
|
+
/**
|
|
120
|
+
* Reserve an issue-report upload slot.
|
|
121
|
+
*
|
|
122
|
+
* Returns a presigned PUT the caller uploads the bundle bytes to directly —
|
|
123
|
+
* the Platform never proxies them — plus the reference id the customer
|
|
124
|
+
* quotes to support.
|
|
125
|
+
*/
|
|
126
|
+
createIssueReport(body: {
|
|
127
|
+
bundleId: string;
|
|
128
|
+
byteSize: number;
|
|
129
|
+
sha256: string;
|
|
130
|
+
message?: string;
|
|
131
|
+
email?: string;
|
|
132
|
+
}): Promise<{
|
|
133
|
+
ref: string;
|
|
134
|
+
uploadUrl: string;
|
|
135
|
+
}>;
|
|
136
|
+
/** Tell the Platform the bytes landed, so it can verify and mark the report received. */
|
|
137
|
+
confirmIssueReport(ref: string): Promise<{
|
|
138
|
+
ref: string;
|
|
139
|
+
status: string;
|
|
140
|
+
}>;
|
|
141
|
+
listIssueReports(): Promise<IssueReportListResponse>;
|
|
142
|
+
withdrawIssueReport(ref: string): Promise<{
|
|
143
|
+
ref: string;
|
|
144
|
+
deleted: boolean;
|
|
145
|
+
}>;
|
|
107
146
|
rerunRun(runId: string): Promise<{
|
|
108
147
|
newRunId: string;
|
|
109
148
|
}>;
|
|
@@ -31,6 +31,27 @@ const webhookActivitySchema = z.object({
|
|
|
31
31
|
lockfileMissing: z.number().optional(),
|
|
32
32
|
orchestratorUnavailable: z.boolean()
|
|
33
33
|
});
|
|
34
|
+
const issueReportCreateSchema = z.object({
|
|
35
|
+
ref: z.string(),
|
|
36
|
+
uploadUrl: z.string()
|
|
37
|
+
});
|
|
38
|
+
const issueReportConfirmSchema = z.object({
|
|
39
|
+
ref: z.string(),
|
|
40
|
+
status: z.string()
|
|
41
|
+
});
|
|
42
|
+
const issueReportDeleteSchema = z.object({
|
|
43
|
+
ref: z.string(),
|
|
44
|
+
deleted: z.boolean()
|
|
45
|
+
});
|
|
46
|
+
const issueReportListSchema = z.object({ reports: z.array(z.object({
|
|
47
|
+
ref: z.string(),
|
|
48
|
+
bundleId: z.string(),
|
|
49
|
+
byteSize: z.number(),
|
|
50
|
+
status: z.string(),
|
|
51
|
+
createdAt: z.string(),
|
|
52
|
+
userId: z.string(),
|
|
53
|
+
message: z.string().nullable()
|
|
54
|
+
})) });
|
|
34
55
|
const rerunResponseSchema = z.object({ newRunId: z.string() });
|
|
35
56
|
const cancelResponseSchema = z.object({
|
|
36
57
|
cancelledJobs: z.number().optional(),
|
|
@@ -176,6 +197,26 @@ var DashboardClient = class DashboardClient {
|
|
|
176
197
|
async listArtifacts(runId) {
|
|
177
198
|
return artifactsListResultSchema.parse(await this.getJson(`/runs/${runId}/artifacts`));
|
|
178
199
|
}
|
|
200
|
+
/**
|
|
201
|
+
* Reserve an issue-report upload slot.
|
|
202
|
+
*
|
|
203
|
+
* Returns a presigned PUT the caller uploads the bundle bytes to directly —
|
|
204
|
+
* the Platform never proxies them — plus the reference id the customer
|
|
205
|
+
* quotes to support.
|
|
206
|
+
*/
|
|
207
|
+
async createIssueReport(body) {
|
|
208
|
+
return issueReportCreateSchema.parse(await this.postJson("/issue-reports", body));
|
|
209
|
+
}
|
|
210
|
+
/** Tell the Platform the bytes landed, so it can verify and mark the report received. */
|
|
211
|
+
async confirmIssueReport(ref) {
|
|
212
|
+
return issueReportConfirmSchema.parse(await this.postJson(`/issue-reports/${encodeURIComponent(ref)}/confirm`));
|
|
213
|
+
}
|
|
214
|
+
async listIssueReports() {
|
|
215
|
+
return issueReportListSchema.parse(await this.getJson("/issue-reports"));
|
|
216
|
+
}
|
|
217
|
+
async withdrawIssueReport(ref) {
|
|
218
|
+
return issueReportDeleteSchema.parse(await this.deleteJson(`/issue-reports/${encodeURIComponent(ref)}`));
|
|
219
|
+
}
|
|
179
220
|
async rerunRun(runId) {
|
|
180
221
|
return rerunResponseSchema.parse(await this.postJson(`/runs/${runId}/rerun`));
|
|
181
222
|
}
|
package/dist/remote/oauth.js
CHANGED
|
@@ -106,7 +106,7 @@ function describeListenFailure(err, listenPort) {
|
|
|
106
106
|
* @returns OIDC access token
|
|
107
107
|
*/
|
|
108
108
|
async function pkceFlow(opts) {
|
|
109
|
-
const { issuer, clientId, nudgeAfterMs = 9e4, timeoutMs =
|
|
109
|
+
const { issuer, clientId, nudgeAfterMs = 9e4, timeoutMs = 3e5 } = opts;
|
|
110
110
|
let listenPort = 0;
|
|
111
111
|
const callbackPortEnv = process.env.KICI_CALLBACK_PORT;
|
|
112
112
|
if (callbackPortEnv) {
|
|
@@ -211,10 +211,12 @@ async function pkceFlow(opts) {
|
|
|
211
211
|
if (browserCmd === "none") {
|
|
212
212
|
console.log(`KICI_AUTH_URL=${authUrl.toString()}`);
|
|
213
213
|
console.log(pc.cyan(` Waiting for browser callback on port ${actualPort}...`));
|
|
214
|
-
} else if (browserCmd)
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
214
|
+
} else if (browserCmd) {
|
|
215
|
+
const cmd = browserCmd.replace("{url}", authUrl.toString());
|
|
216
|
+
exec(cmd, (err) => {
|
|
217
|
+
if (err) console.log(pc.yellow(` Custom browser command failed: ${err.message}\n Please visit:\n ${authUrl.toString()}`));
|
|
218
|
+
});
|
|
219
|
+
} else {
|
|
218
220
|
console.log(pc.cyan(" Opening browser for authentication..."));
|
|
219
221
|
console.log(pc.dim(` If it does not open, visit:\n ${authUrl.toString()}`));
|
|
220
222
|
open(authUrl.toString()).catch(() => {
|
package/dist/remote/uploader.js
CHANGED
|
@@ -9,9 +9,9 @@ import { makeTempDir } from "@kici-dev/core/tmp";
|
|
|
9
9
|
import picomatch from "picomatch";
|
|
10
10
|
//#region src/remote/uploader.ts
|
|
11
11
|
/** Size threshold for warning (50MB) */
|
|
12
|
-
const SIZE_WARN_THRESHOLD =
|
|
12
|
+
const SIZE_WARN_THRESHOLD = 52428800;
|
|
13
13
|
/** Size threshold for hard error (500MB) */
|
|
14
|
-
const SIZE_ERROR_THRESHOLD =
|
|
14
|
+
const SIZE_ERROR_THRESHOLD = 524288e3;
|
|
15
15
|
/** Maximum upload retry attempts */
|
|
16
16
|
const MAX_RETRIES = 3;
|
|
17
17
|
/**
|