promigence 0.1.0-beta.5 → 0.1.0-beta.7
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/account.js +23 -1
- package/dist/agent.js +11 -1
- package/dist/bin.js +6 -1
- package/dist/commands.d.ts +4 -0
- package/dist/commands.js +20 -15
- package/dist/credits.js +57 -8
- package/dist/devcontainer.d.ts +5 -0
- package/dist/devcontainer.js +5 -0
- package/dist/dirsnap.js +1 -1
- package/dist/errfix.js +8 -2
- package/dist/generated.js +9 -0
- package/dist/github.js +2 -3
- package/dist/gitlab.js +2 -2
- package/dist/guide.d.ts +2 -0
- package/dist/guide.js +9 -3
- package/dist/handlers.js +3 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/login.js +2 -0
- package/dist/mcp.js +1 -1
- package/dist/pricing.d.ts +3 -1
- package/dist/pricing.js +10 -7
- package/dist/runners-spec.js +22 -11
- package/dist/runners.js +2 -2
- package/dist/sdk/client.d.ts +62 -24
- package/dist/sdk/client.js +17 -20
- package/dist/sdk/core.d.ts +1 -1
- package/dist/sdk/core.js +4 -2
- package/dist/sdk/models.gen.d.ts +73 -19
- package/dist/sdk/sandbox.d.ts +6 -7
- package/dist/sdk/sandbox.js +0 -2
- package/dist/surface.js +3 -4
- package/llms.txt +4 -4
- package/package.json +1 -1
package/dist/account.js
CHANGED
|
@@ -4,6 +4,21 @@ import { duration } from "./report.js";
|
|
|
4
4
|
import { emit, ms, okEnvelope, overMost, parseCount, parseDuration, parseUsd, usageError } from "./io.js";
|
|
5
5
|
import { sh } from "./term.js";
|
|
6
6
|
const usd = (n) => n === undefined ? "—" : `$${n.toFixed(n < 0.01 && n > 0 ? 4 : 2)}`;
|
|
7
|
+
export const PAYMENT_METHOD_NAMES = {
|
|
8
|
+
apple_pay: "Apple Pay",
|
|
9
|
+
google_pay: "Google Pay",
|
|
10
|
+
samsung_pay: "Samsung Pay",
|
|
11
|
+
link: "Link",
|
|
12
|
+
cashapp: "Cash App Pay",
|
|
13
|
+
amazon_pay: "Amazon Pay",
|
|
14
|
+
};
|
|
15
|
+
export function paymentMethodText(card) {
|
|
16
|
+
const key = card?.brand ?? "";
|
|
17
|
+
const named = Object.prototype.hasOwnProperty.call(PAYMENT_METHOD_NAMES, key) ? PAYMENT_METHOD_NAMES[key] : undefined;
|
|
18
|
+
if (named)
|
|
19
|
+
return card?.last4 ? `${named} •••• ${card.last4}` : named;
|
|
20
|
+
return `${card?.brand ?? "card"} ••${card?.last4 ?? "??"}`;
|
|
21
|
+
}
|
|
7
22
|
function limitOf(ctx, fallback, most) {
|
|
8
23
|
const raw = str(ctx, "--limit");
|
|
9
24
|
if (raw === undefined)
|
|
@@ -244,7 +259,7 @@ const billingUsage = async (ctx) => {
|
|
|
244
259
|
const trial = b.trial;
|
|
245
260
|
if (trial?.credits_remaining !== undefined)
|
|
246
261
|
lines.push(` trial credits left: ${usd(trial.credits_remaining)}`);
|
|
247
|
-
lines.push(` card: ${b.card_on_file ?
|
|
262
|
+
lines.push(` card: ${b.card_on_file ? paymentMethodText(b.card) : `none on file${billingOff ? " (card payments are not open yet)" : ""}`}`);
|
|
248
263
|
if (b.upcoming_invoice?.amount_due !== undefined && b.upcoming_invoice?.amount_due !== null) {
|
|
249
264
|
lines.push(` next invoice: ${usd(b.upcoming_invoice.amount_due)}`);
|
|
250
265
|
}
|
|
@@ -520,6 +535,12 @@ export function sandboxFactLines(s, facts, nowMs = Date.now()) {
|
|
|
520
535
|
}
|
|
521
536
|
return out;
|
|
522
537
|
}
|
|
538
|
+
export function supportStopLines(s) {
|
|
539
|
+
if (s.outcome !== "stopped_by_support")
|
|
540
|
+
return [];
|
|
541
|
+
const message = s.failure?.message;
|
|
542
|
+
return [` ${typeof message === "string" && message.trim() ? message : "Stopped by Promigence support"}`];
|
|
543
|
+
}
|
|
523
544
|
const sandboxInfo = async (ctx) => {
|
|
524
545
|
const sid = positional(ctx, "a sandbox id", "promigence sandbox info sbx_01");
|
|
525
546
|
const c = client(ctx);
|
|
@@ -539,6 +560,7 @@ const sandboxInfo = async (ctx) => {
|
|
|
539
560
|
: why ? [] : [[sh `promigence exec --sandbox ${sid} -- CMD`, "run something in it"]]));
|
|
540
561
|
const lines = [
|
|
541
562
|
`sandbox ${sid}: ${s.state}${why ? ` (${why})` : ""}${s.outcome ? ` (${s.outcome})` : ""}${s.run_id ? ` · run ${s.run_id}` : ""}`,
|
|
563
|
+
...supportStopLines(s),
|
|
542
564
|
...(why ? [" its files and state are kept, and paused time is not billed"] : []),
|
|
543
565
|
...queuedLines([s]),
|
|
544
566
|
...(s.snapshot_id ? [` snapshot ${s.snapshot_id}`] : []),
|
package/dist/agent.js
CHANGED
|
@@ -42,9 +42,17 @@ export const SETUP_SCRIPT = [
|
|
|
42
42
|
'if [ -n "$3" ] && [ ! -d "$4/.git" ]; then',
|
|
43
43
|
' mkdir -p "$(dirname "$4")"',
|
|
44
44
|
' git clone --quiet -- "$3" "$4" >&2',
|
|
45
|
+
' if [ -n "${5:-}" ]; then chown -R -- "$5" "$4"; fi',
|
|
45
46
|
"fi",
|
|
46
47
|
'"$1" --version',
|
|
47
48
|
].join("\n");
|
|
49
|
+
async function snapshotUser(c, snapshot) {
|
|
50
|
+
if (snapshot === DEFAULT_SNAPSHOT)
|
|
51
|
+
return undefined;
|
|
52
|
+
const rec = await c.snapshots.get(snapshot).catch(() => undefined);
|
|
53
|
+
const u = rec?.user;
|
|
54
|
+
return typeof u === "string" && u !== "" && u !== "root" && u !== "0" ? u : undefined;
|
|
55
|
+
}
|
|
48
56
|
export function repoDir(url) {
|
|
49
57
|
const last = url.replace(/[/]+$/, "").split(/[/:]/).pop() ?? "";
|
|
50
58
|
const name = last.replace(/\.git$/, "").replace(/[^A-Za-z0-9._-]/g, "") || "repo";
|
|
@@ -269,8 +277,10 @@ const agentStart = async (ctx) => {
|
|
|
269
277
|
throw e;
|
|
270
278
|
}
|
|
271
279
|
};
|
|
280
|
+
const runAs = await snapshotUser(c, snapshot);
|
|
272
281
|
const setup = await endOnThrow(c.sandboxes.exec(sid, {
|
|
273
|
-
argv: ["sh", "-c", SETUP_SCRIPT, "agent-setup", agent.bin, agent.pkg, repo ?? "", cwd ?? ""],
|
|
282
|
+
argv: ["sh", "-c", SETUP_SCRIPT, "agent-setup", agent.bin, agent.pkg, repo ?? "", cwd ?? "", runAs ?? ""],
|
|
283
|
+
user: "root",
|
|
274
284
|
timeoutMs: 10 * 60_000,
|
|
275
285
|
}));
|
|
276
286
|
if (setup.exit_code !== 0) {
|
package/dist/bin.js
CHANGED
|
@@ -13,7 +13,7 @@ import { TEMPLATES_HANDLERS } from "./templates.js";
|
|
|
13
13
|
import { ACCOUNT_HANDLERS } from "./account.js";
|
|
14
14
|
import { MCP_HANDLERS } from "./mcp.js";
|
|
15
15
|
import { AGENT_HANDLERS } from "./agent.js";
|
|
16
|
-
import { CREDITS_HANDLERS } from "./credits.js";
|
|
16
|
+
import { CREDITS_HANDLERS, canAsk, claimOnRefusal } from "./credits.js";
|
|
17
17
|
import { RUNNERS_HANDLERS } from "./runners.js";
|
|
18
18
|
import { PRICING_HANDLERS } from "./pricing.js";
|
|
19
19
|
import { GITHUB_HANDLERS } from "./github.js";
|
|
@@ -321,6 +321,11 @@ async function main(argv) {
|
|
|
321
321
|
env.promigence_exit = exit;
|
|
322
322
|
exit = e.code === "enoent" ? 127 : cmd.passthroughExit;
|
|
323
323
|
}
|
|
324
|
+
if (e.code === "credit_unclaimed" && mode === "text" && canAsk()) {
|
|
325
|
+
const lines = await claimOnRefusal(ctx).catch(() => undefined);
|
|
326
|
+
if (lines)
|
|
327
|
+
return void (await emit(mode, env, lines, exit, false));
|
|
328
|
+
}
|
|
324
329
|
await emit(mode, env, errorTextLines(cmd.name, e, exit, next), exit, !cmd.noGuidePointer);
|
|
325
330
|
}
|
|
326
331
|
}
|
package/dist/commands.d.ts
CHANGED
|
@@ -99,6 +99,10 @@ export declare function outputTails(c: PromigenceClient, sandboxes: ReadonlyArra
|
|
|
99
99
|
}>;
|
|
100
100
|
}>): Promise<Map<string, OutputTail>>;
|
|
101
101
|
export declare function positional(ctx: Ctx, what: string, example: string): string;
|
|
102
|
+
export declare function supportStoppedLines(sandboxes: ReadonlyArray<{
|
|
103
|
+
sandbox_id: string;
|
|
104
|
+
outcome?: string | null;
|
|
105
|
+
}>): string[];
|
|
102
106
|
export declare function filesPutTarArgs(out: string, parent: string, base: string, noMetadata?: string[]): string[];
|
|
103
107
|
export declare const HANDLERS: Readonly<Record<string, Handler>>;
|
|
104
108
|
export {};
|
package/dist/commands.js
CHANGED
|
@@ -6,7 +6,7 @@ import { basename, dirname, join, resolve } from "node:path";
|
|
|
6
6
|
import { DEFAULT_API_URL, DEFAULT_SNAPSHOT, ERRORS_DOCS_URL, MAX_OUTPUT_BYTES_DEFAULT, CONTEXT_GIT_RE, PromigenceClient, checkRepoUrl, withoutPin, PromigenceError, SpendCapError, TimeoutError, checkImageRef, contextRelative, credentialsPath, FILE_PUT_CHUNK_BYTES, imageSnapshot, isWaiting, execOutputBytes, listContext, packContext, readCredentials, } from "./sdk/index.js";
|
|
7
7
|
import { fmtMs, recordTiming } from "./timing.js";
|
|
8
8
|
import { capacityLine, queuedClause, queuedLines, statusLine } from "./capacity.js";
|
|
9
|
-
import { DevcontainerError, detectOne, load, planJson, planLines, planSetup, resolveGiven, snapshotEnv, translate, workspaceRootFor, wrapCommand, } from "./devcontainer.js";
|
|
9
|
+
import { DevcontainerError, detectOne, load, planJson, planLines, planSetup, resolveGiven, snapshotEnv, snapshotUsers, translate, workspaceRootFor, wrapCommand, } from "./devcontainer.js";
|
|
10
10
|
import { detect, ecosystemOfCommands, imageCreateCommand, readConfig } from "./init.js";
|
|
11
11
|
import { CREDENTIAL_REMEDY, confirmOverride, credentialRefusal, emitUploadList, localTarNoMetadataArgs } from "./uploadguard.js";
|
|
12
12
|
import { emit, errorEnvelope, errorTextLines, exitWith, forkLine, forkSummary, gradeLine, ms, noCommandFix, okEnvelope, parseMaxOutput, recordNotice, sandboxGrade, parseCommandTimeout, parseCount, parseDuration, parseUsd, pickExit, reportSummaryLines, toPromigenceError, totalsLine, usageError, write, writeBytes, } from "./io.js";
|
|
@@ -212,7 +212,7 @@ function reportExits(report) {
|
|
|
212
212
|
return codes;
|
|
213
213
|
if (t.env_failed > 0 || (t.grader_failed ?? 0) > 0)
|
|
214
214
|
codes.push(3);
|
|
215
|
-
if (t.not_started > 0 || t.cap_killed > 0 || t.expired > 0)
|
|
215
|
+
if (t.not_started > 0 || t.cap_killed > 0 || t.expired > 0 || (t.stopped_by_support ?? 0) > 0)
|
|
216
216
|
codes.push(12);
|
|
217
217
|
if (t.task_failed > 0 || t.snapshot_failed > 0)
|
|
218
218
|
codes.push(4);
|
|
@@ -385,7 +385,7 @@ function boundUseLines(res) {
|
|
|
385
385
|
" requests the sandbox sends to this address are authenticated with it:",
|
|
386
386
|
...urls.map((u) => ` ${urlLine(u, res.env)}`),
|
|
387
387
|
` a request sent straight to ${hosts.map((h) => `https://${h}`).join(" or ")} is not authenticated: send it to the address above`,
|
|
388
|
-
...(res.scan_responses ===
|
|
388
|
+
...(res.scan_responses === true ? [" the host's answers never show the value: an echo service shows asterisks instead"] : []),
|
|
389
389
|
];
|
|
390
390
|
return lines;
|
|
391
391
|
}
|
|
@@ -723,7 +723,10 @@ async function devcontainerCreate(ctx, plan) {
|
|
|
723
723
|
}
|
|
724
724
|
const setup = planSetup(plan, { repo, commit, userSetup: list(ctx, "--setup") });
|
|
725
725
|
const env = snapshotEnv(plan);
|
|
726
|
-
const
|
|
726
|
+
const users = snapshotUsers(plan);
|
|
727
|
+
const opts = {
|
|
728
|
+
...source, ...(setup.length ? { setup } : {}), ...(env ? { env } : {}), ...(users ?? {}),
|
|
729
|
+
};
|
|
727
730
|
const verify = str(ctx, "--verify");
|
|
728
731
|
if (verify !== undefined)
|
|
729
732
|
opts.verify = { cmd: wrapCommand(plan, verify) };
|
|
@@ -762,7 +765,6 @@ const snapshotCreate = async (ctx) => {
|
|
|
762
765
|
const plan = gh ? undefined : devcontainerPlan(ctx, form);
|
|
763
766
|
const setup = list(ctx, "--setup");
|
|
764
767
|
const alias = str(ctx, "--alias");
|
|
765
|
-
const cpuClass = str(ctx, "--cpu-class");
|
|
766
768
|
let opts;
|
|
767
769
|
let label;
|
|
768
770
|
let submitted;
|
|
@@ -833,8 +835,6 @@ const snapshotCreate = async (ctx) => {
|
|
|
833
835
|
const c = client(ctx);
|
|
834
836
|
if (alias !== undefined)
|
|
835
837
|
opts.alias = alias;
|
|
836
|
-
if (cpuClass !== undefined)
|
|
837
|
-
opts.cpuClass = cpuClass;
|
|
838
838
|
const grade = gradeOpts(ctx);
|
|
839
839
|
if (grade)
|
|
840
840
|
opts.grade = grade;
|
|
@@ -1472,8 +1472,6 @@ const exec = async (ctx) => {
|
|
|
1472
1472
|
stdout: res.stdout ?? "",
|
|
1473
1473
|
stderr: res.stderr ?? "",
|
|
1474
1474
|
truncated: res.truncated ?? false,
|
|
1475
|
-
...(res.stdout_ref === undefined ? {} : { stdout_ref: res.stdout_ref }),
|
|
1476
|
-
...(res.stderr_ref === undefined ? {} : { stderr_ref: res.stderr_ref }),
|
|
1477
1475
|
...(res.stdout_b64 === undefined ? {} : { stdout_b64: res.stdout_b64 }),
|
|
1478
1476
|
...(res.stderr_b64 === undefined ? {} : { stderr_b64: res.stderr_b64 }),
|
|
1479
1477
|
...(res["idempotent_replay"] === true ? { idempotent_replay: true } : {}),
|
|
@@ -1598,7 +1596,7 @@ async function runImageSnapshot(ctx, c) {
|
|
|
1598
1596
|
if (cap < price + (quoted ?? 0)) {
|
|
1599
1597
|
const existing = (quoted ?? 0) <= cap ? await existingImageSnapshot(c, image) : undefined;
|
|
1600
1598
|
throw new SpendCapError(`a new image's snapshot build costs ${moneyUsd(price)} on top of the run` +
|
|
1601
|
-
`${quoted === undefined ? "" : ` (about ${moneyUsd(quoted)})`}, over --cap ${moneyUsd(cap)}; nothing was built or started`, (existing === undefined ? "" : `This image already has snapshot ${existing}: run it under this cap with ${sh `promigence run --snapshot ${existing}`} instead of --image. Or `) +
|
|
1599
|
+
`${quoted === undefined ? "" : ` (about ${moneyUsd(quoted)})`}, over --cap ${moneyUsd(cap)}; nothing was built or started`, (existing === undefined ? "" : `This image already has snapshot ${existing}: run it under this cap with ${sh `promigence run --snapshot ${existing}`} instead of --image (any start command or settings it was made with come with it). Or `) +
|
|
1602
1600
|
`${existing === undefined ? "Pass" : "pass"} --cap ${needed.toFixed(2)} or more (a build is charged once, only when this image has no snapshot yet, and reused free after), ` +
|
|
1603
1601
|
`or build it first, ${sh `promigence snapshot create --image ${image} --wait`}, and run its snapshot with --snapshot.`);
|
|
1604
1602
|
}
|
|
@@ -1633,7 +1631,7 @@ async function existingImageSnapshot(c, image) {
|
|
|
1633
1631
|
for (let page = 0; page < 5; page++) {
|
|
1634
1632
|
const p = await c.snapshots.listPage({ limit: 100, ...(cursor === undefined ? {} : { cursor }) });
|
|
1635
1633
|
const hit = p.items.find((s) => s.source?.kind === "image" && typeof s.source.digest === "string" && digests.has(s.source.digest) &&
|
|
1636
|
-
s.source["from_sandbox"] === undefined && !s.unavailable && !(s.setup?.length) && !s.
|
|
1634
|
+
s.source["from_sandbox"] === undefined && !s.unavailable && !(s.setup?.length) && !s.verify?.cmd &&
|
|
1637
1635
|
(s.tier === undefined || s.tier === "small"));
|
|
1638
1636
|
if (hit)
|
|
1639
1637
|
return hit.snapshot_id;
|
|
@@ -1967,11 +1965,12 @@ function settledWhy(report, keep) {
|
|
|
1967
1965
|
return `${open.length} sandbox${open.length === 1 ? " has" : "es have"} not ended yet, so ${open.length === 1 ? "its" : "their"} last charge is still to land`;
|
|
1968
1966
|
}
|
|
1969
1967
|
const OUTCOME_EXIT = {
|
|
1970
|
-
env_failed: 3, grader_failed: 3, not_started: 12, cap_killed: 12, expired: 12,
|
|
1968
|
+
env_failed: 3, grader_failed: 3, not_started: 12, cap_killed: 12, expired: 12, stopped_by_support: 12,
|
|
1969
|
+
task_failed: 4, snapshot_failed: 4,
|
|
1971
1970
|
};
|
|
1972
1971
|
const OUTCOME_CODE = {
|
|
1973
1972
|
env_failed: "env_failed", grader_failed: "grader_failed", not_started: "not_started", cap_killed: "cap_killed",
|
|
1974
|
-
expired: "expired", task_failed: "nonzero_exit", snapshot_failed: "snapshot_failed",
|
|
1973
|
+
expired: "expired", stopped_by_support: "stopped_by_support", task_failed: "nonzero_exit", snapshot_failed: "snapshot_failed",
|
|
1975
1974
|
};
|
|
1976
1975
|
function failureFix(runId, s) {
|
|
1977
1976
|
const f = s.failure;
|
|
@@ -2005,7 +2004,7 @@ export function runHeadline(report, count) {
|
|
|
2005
2004
|
const t = (report.totals ?? {});
|
|
2006
2005
|
const others = Object.entries(t)
|
|
2007
2006
|
.filter(([k, v]) => !["completed", "env_verified", "evidence_missing"].includes(k) && typeof v === "number" && v > 0)
|
|
2008
|
-
.map(([k, v]) => `${v} ${k}`);
|
|
2007
|
+
.map(([k, v]) => `${v} ${k === "stopped_by_support" ? "stopped by Promigence support" : k}`);
|
|
2009
2008
|
const done = typeof t["completed"] === "number" ? t["completed"] : 0;
|
|
2010
2009
|
return `run ${report.run_id}: ${done} of ${count} completed${others.length ? ` · ${others.join(" · ")}` : ""}` +
|
|
2011
2010
|
`${report.cost ? ` · charged ${moneyUsd(report.cost.charged)}` : ""}`;
|
|
@@ -2125,6 +2124,12 @@ const runReport = async (ctx) => {
|
|
|
2125
2124
|
const next = nexts([sh `promigence run status ${runId}`, "the run's current state"]);
|
|
2126
2125
|
return emit(ctx.mode, okEnvelope(ctx.cmd.name, { run_id: runId, report }, next), reportLines(report, view), 0, ctx.pointer);
|
|
2127
2126
|
};
|
|
2127
|
+
export function supportStoppedLines(sandboxes) {
|
|
2128
|
+
const stopped = sandboxes.filter((s) => s.outcome === "stopped_by_support");
|
|
2129
|
+
if (!stopped.length)
|
|
2130
|
+
return [];
|
|
2131
|
+
return [` ${stopped.length} stopped by Promigence support; ${sh `promigence sandbox info ${stopped[0].sandbox_id}`} says why`];
|
|
2132
|
+
}
|
|
2128
2133
|
const runStatus = async (ctx) => {
|
|
2129
2134
|
const runId = positional(ctx, "a run id", "promigence run status run_01 --wait");
|
|
2130
2135
|
const c = client(ctx);
|
|
@@ -2141,7 +2146,7 @@ const runStatus = async (ctx) => {
|
|
|
2141
2146
|
states[s.state] = (states[s.state] ?? 0) + 1;
|
|
2142
2147
|
const next = nexts([sh `promigence run report ${runId} --json`, "the validity report"]);
|
|
2143
2148
|
const tail = Object.keys(states).length ? ` - ${Object.entries(states).map(([k, v]) => `${k} ${v}`).join(" - ")}` : "";
|
|
2144
|
-
return emit(ctx.mode, okEnvelope(ctx.cmd.name, { run_id: runId, state: run.state, sandbox_states: states, run }, next), [`run ${runId}: ${run.state}${tail}`, ...queuedLines(run.sandboxes ?? [])], 0, ctx.pointer);
|
|
2149
|
+
return emit(ctx.mode, okEnvelope(ctx.cmd.name, { run_id: runId, state: run.state, sandbox_states: states, run }, next), [`run ${runId}: ${run.state}${tail}`, ...supportStoppedLines(run.sandboxes ?? []), ...queuedLines(run.sandboxes ?? [])], 0, ctx.pointer);
|
|
2145
2150
|
};
|
|
2146
2151
|
const runKill = async (ctx) => {
|
|
2147
2152
|
const runId = positional(ctx, "a run id", "promigence run kill run_01");
|
package/dist/credits.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
import { createInterface } from "node:readline";
|
|
1
2
|
import { PromigenceClient } from "./sdk/index.js";
|
|
2
3
|
import { bool, clientOpts, nexts } from "./commands.js";
|
|
3
4
|
import { deviceFetch, deviceHeader } from "./device.js";
|
|
4
|
-
import { emit, okEnvelope, recordNotice } from "./io.js";
|
|
5
|
+
import { emit, okEnvelope, recordNotice, write } from "./io.js";
|
|
5
6
|
import { headless, openBrowser } from "./login.js";
|
|
6
7
|
import { usd } from "./money.js";
|
|
7
8
|
export function dollars(n) {
|
|
@@ -104,18 +105,66 @@ export async function offerAfterLogin(ctx, apiUrl, apiKey, consoleHome) {
|
|
|
104
105
|
lines: claimLines(offer, link, opened),
|
|
105
106
|
};
|
|
106
107
|
}
|
|
107
|
-
async function
|
|
108
|
+
async function askLine(prompt) {
|
|
109
|
+
const rl = createInterface({ input: process.stdin, output: process.stderr });
|
|
110
|
+
try {
|
|
111
|
+
return await new Promise((resolve) => rl.question(prompt, resolve));
|
|
112
|
+
}
|
|
113
|
+
finally {
|
|
114
|
+
rl.close();
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
export function canAsk(env = process.env) {
|
|
118
|
+
const ci = (env["CI"] ?? "").trim().toLowerCase();
|
|
119
|
+
return Boolean(process.stdin.isTTY && process.stderr.isTTY) && (ci === "" || ci === "0" || ci === "false");
|
|
120
|
+
}
|
|
121
|
+
export async function claimOnRefusal(ctx, io = {}) {
|
|
122
|
+
const opts = { ...clientOpts(ctx), onNotice: recordNotice };
|
|
123
|
+
let o;
|
|
124
|
+
try {
|
|
125
|
+
o = await getOffer(new PromigenceClient(opts));
|
|
126
|
+
}
|
|
127
|
+
catch {
|
|
128
|
+
return undefined;
|
|
129
|
+
}
|
|
130
|
+
if (!o || o.state !== "claimable")
|
|
131
|
+
return undefined;
|
|
132
|
+
const credit = typeof o.credit_usd === "number" ? `${dollars(o.credit_usd)} of free credit` : "free credit";
|
|
133
|
+
await write(process.stderr, `This account has ${credit} waiting to be claimed; nothing was started or charged.\n`);
|
|
134
|
+
const answer = await (io.ask ?? askLine)("Claim it now? It opens the claim page in your browser, where you accept the terms. [y/N] ");
|
|
135
|
+
if (!/^\s*y(es)?\s*$/i.test(answer))
|
|
136
|
+
return ["Not claimed. When you are ready: promigence credits claim"];
|
|
137
|
+
let link;
|
|
138
|
+
try {
|
|
139
|
+
link = await getClaimLink(claimClient(opts));
|
|
140
|
+
if (!link || typeof link.url !== "string")
|
|
141
|
+
throw new Error("no claim link in the answer");
|
|
142
|
+
}
|
|
143
|
+
catch (e) {
|
|
144
|
+
const err = e;
|
|
145
|
+
return [
|
|
146
|
+
`Could not open the claim page: ${err?.message ?? String(e)}`,
|
|
147
|
+
` Try again: promigence credits claim${err?.code === "forbidden" ? " (owners; members ask an owner)" : ""}`,
|
|
148
|
+
];
|
|
149
|
+
}
|
|
150
|
+
const opened = maybeOpen(ctx, link.url);
|
|
151
|
+
return [...claimLines(o, link, opened), "Once it is claimed, run the command again."];
|
|
152
|
+
}
|
|
153
|
+
async function cardState(c, o) {
|
|
154
|
+
const none = { off: false, onFile: false };
|
|
108
155
|
if (!(typeof o.card_bonus_usd === "number" && o.card_bonus_usd > 0) || o.state === "none")
|
|
109
|
-
return
|
|
110
|
-
return c.billing.usage().then((b) => b.billing_enabled === false).catch(() =>
|
|
156
|
+
return none;
|
|
157
|
+
return c.billing.usage().then((b) => ({ off: b.billing_enabled === false, onFile: b.card_on_file === true })).catch(() => none);
|
|
111
158
|
}
|
|
112
|
-
function offerLines(head, o,
|
|
159
|
+
function offerLines(head, o, st = { off: false, onFile: false }) {
|
|
113
160
|
const lines = [`${head}: ${say(o)}`];
|
|
114
161
|
if (o.state !== "none") {
|
|
115
162
|
if (typeof o.credit_usd === "number")
|
|
116
163
|
lines.push(` credit: ${dollars(o.credit_usd)}`);
|
|
117
164
|
if (typeof o.card_bonus_usd === "number" && o.card_bonus_usd > 0) {
|
|
118
|
-
lines.push(
|
|
165
|
+
lines.push(st.onFile
|
|
166
|
+
? ` card bonus: ${dollars(o.card_bonus_usd)} more with your first paid invoice`
|
|
167
|
+
: ` card bonus: ${dollars(o.card_bonus_usd)} more when you add a card${st.off ? " (card payments are not open yet)" : " (promigence billing card)"}`);
|
|
119
168
|
}
|
|
120
169
|
if (o.expires_at)
|
|
121
170
|
lines.push(` expires: ${o.expires_at}`);
|
|
@@ -128,14 +177,14 @@ function offerLines(head, o, off = false) {
|
|
|
128
177
|
const credits = async (ctx) => {
|
|
129
178
|
const c = new PromigenceClient({ ...clientOpts(ctx), onNotice: recordNotice });
|
|
130
179
|
const o = await getOffer(c);
|
|
131
|
-
return emit(ctx.mode, okEnvelope(ctx.cmd.name, { ...o }, offerNext(o)), offerLines("promigence credits", o, await
|
|
180
|
+
return emit(ctx.mode, okEnvelope(ctx.cmd.name, { ...o }, offerNext(o)), offerLines("promigence credits", o, await cardState(c, o)), 0, ctx.pointer);
|
|
132
181
|
};
|
|
133
182
|
const creditsClaim = async (ctx) => {
|
|
134
183
|
const opts = { ...clientOpts(ctx), onNotice: recordNotice };
|
|
135
184
|
const c = new PromigenceClient(opts);
|
|
136
185
|
const o = await getOffer(c);
|
|
137
186
|
if (o.state !== "claimable") {
|
|
138
|
-
return emit(ctx.mode, okEnvelope(ctx.cmd.name, { ...o, claim_url: null }, offerNext(o)), offerLines("promigence credits claim", o, await
|
|
187
|
+
return emit(ctx.mode, okEnvelope(ctx.cmd.name, { ...o, claim_url: null }, offerNext(o)), offerLines("promigence credits claim", o, await cardState(c, o)), 0, ctx.pointer);
|
|
139
188
|
}
|
|
140
189
|
const link = await getClaimLink(claimClient(opts));
|
|
141
190
|
const opened = maybeOpen(ctx, link.url);
|
package/dist/devcontainer.d.ts
CHANGED
|
@@ -62,6 +62,7 @@ export interface Plan {
|
|
|
62
62
|
env: Record<string, string>;
|
|
63
63
|
workspaceFolder: string;
|
|
64
64
|
user: string | undefined;
|
|
65
|
+
remoteUser?: string | undefined;
|
|
65
66
|
lifecycle: LifecycleStep[];
|
|
66
67
|
ports: number[];
|
|
67
68
|
tier: string | undefined;
|
|
@@ -84,6 +85,10 @@ export declare function lifecycleSteps(v: unknown, field: string, ctx: Substitut
|
|
|
84
85
|
export declare function shellQuote(s: string): string;
|
|
85
86
|
export declare function wrapCommand(plan: Plan, command: string): string;
|
|
86
87
|
export declare function snapshotEnv(plan: Plan): Record<string, string> | undefined;
|
|
88
|
+
export declare function snapshotUsers(plan: Plan): {
|
|
89
|
+
user: string;
|
|
90
|
+
setupUser: string;
|
|
91
|
+
} | undefined;
|
|
87
92
|
export interface SetupOptions {
|
|
88
93
|
repo?: string | undefined;
|
|
89
94
|
commit?: string | undefined;
|
package/dist/devcontainer.js
CHANGED
|
@@ -462,6 +462,7 @@ export function translate(loaded, opts) {
|
|
|
462
462
|
env,
|
|
463
463
|
workspaceFolder,
|
|
464
464
|
user,
|
|
465
|
+
...(remoteUser === undefined ? {} : { remoteUser }),
|
|
465
466
|
lifecycle,
|
|
466
467
|
ports,
|
|
467
468
|
tier,
|
|
@@ -682,6 +683,10 @@ export function wrapCommand(plan, command) {
|
|
|
682
683
|
export function snapshotEnv(plan) {
|
|
683
684
|
return Object.keys(plan.env).length ? { ...plan.env } : undefined;
|
|
684
685
|
}
|
|
686
|
+
export function snapshotUsers(plan) {
|
|
687
|
+
const user = plan.remoteUser ?? plan.user;
|
|
688
|
+
return user === undefined ? undefined : { user, setupUser: "root" };
|
|
689
|
+
}
|
|
685
690
|
export function planSetup(plan, opts = {}) {
|
|
686
691
|
const steps = [];
|
|
687
692
|
if (opts.repo && opts.commit) {
|
package/dist/dirsnap.js
CHANGED
|
@@ -25,7 +25,7 @@ const INTERRUPTED = {
|
|
|
25
25
|
};
|
|
26
26
|
const NOT_WITH_DIR = [
|
|
27
27
|
"--repo", "--commit", "--ref", "--track", "--also-repo", "--image", "--dockerfile", "--context",
|
|
28
|
-
"--devcontainer", "--start", "--
|
|
28
|
+
"--devcontainer", "--start", "--grade", "--holdout", "--grade-score", "--grade-timeout",
|
|
29
29
|
"--grade-output", "--tier",
|
|
30
30
|
];
|
|
31
31
|
export { secretLike };
|
package/dist/errfix.js
CHANGED
|
@@ -17,11 +17,17 @@ export function notFoundKind(message) {
|
|
|
17
17
|
const m = /^(.+?) `([^`]*)` not found$/.exec(message.trim());
|
|
18
18
|
return m ? { kind: m[1].toLowerCase(), id: m[2] } : undefined;
|
|
19
19
|
}
|
|
20
|
-
function notFoundFor(kind, ctx) {
|
|
20
|
+
function notFoundFor(kind, ctx, apiFix) {
|
|
21
21
|
const sid = ctx.sandbox ?? "SID";
|
|
22
22
|
switch (kind) {
|
|
23
23
|
case "snapshot":
|
|
24
24
|
return undefined;
|
|
25
|
+
case "ref":
|
|
26
|
+
case "commit":
|
|
27
|
+
return {
|
|
28
|
+
fix: apiFix,
|
|
29
|
+
next: [{ cmd: "promigence repos", why: "the repositories you can build, each with its default branch" }],
|
|
30
|
+
};
|
|
25
31
|
case "exec":
|
|
26
32
|
return {
|
|
27
33
|
fix: `Check the exec id: \`${sh `promigence exec ps --sandbox ${sid}`}\` lists the background ones, \`${sh `promigence sandbox info ${sid}`}\` every one.`,
|
|
@@ -195,7 +201,7 @@ export async function refineError(e, ctx) {
|
|
|
195
201
|
}
|
|
196
202
|
if (e.code === "not_found") {
|
|
197
203
|
const nf = notFoundKind(e.message);
|
|
198
|
-
const fitted = nf ? notFoundFor(nf.kind, ctx) : undefined;
|
|
204
|
+
const fitted = nf ? notFoundFor(nf.kind, ctx, err.fix ?? "") : undefined;
|
|
199
205
|
if (fitted) {
|
|
200
206
|
err = reworded(err, fitted.fix);
|
|
201
207
|
next = fitted.next;
|
package/dist/generated.js
CHANGED
|
@@ -83,6 +83,9 @@ export const ERRORS = [
|
|
|
83
83
|
{ code: "aborted_by_client", category: "other", http: 200, exit: 130, billed: "yes",
|
|
84
84
|
message: "sandbox killed by the client",
|
|
85
85
|
fix: "Nothing to fix; billed for the seconds used." },
|
|
86
|
+
{ code: "stopped_by_support", category: "other", http: 200, exit: 12, billed: "unless_ours",
|
|
87
|
+
message: "Stopped by Promigence support: {reason}",
|
|
88
|
+
fix: "Billed for the seconds it ran, as a kill is, unless support found the cause was on our side; then that time is credited back. Questions: tell support@promigence.ai the sandbox id." },
|
|
86
89
|
{ code: "expired", category: "other", http: 200, exit: 12, billed: "yes",
|
|
87
90
|
message: "sandbox timeout reached (counted from hand-off)",
|
|
88
91
|
fix: "Raise `--timeout` if the task needs longer." },
|
|
@@ -176,6 +179,9 @@ export const ERRORS = [
|
|
|
176
179
|
{ code: "credit_unclaimed", category: "other", http: 402, exit: 5, billed: "no",
|
|
177
180
|
message: "this account has free credit waiting to be claimed",
|
|
178
181
|
fix: "Claim it in your browser: `promigence credits claim` (owners; members ask an owner). Or add a card: `promigence billing card`. Nothing was started or charged." },
|
|
182
|
+
{ code: "setup_required", category: "other", http: 403, exit: 7, billed: "no",
|
|
183
|
+
message: "finish setting up your account before starting new work",
|
|
184
|
+
fix: "Open {setup_url} and answer the setup questions (under a minute), then run this again. Nothing was started or charged." },
|
|
179
185
|
{ code: "card_required", category: "other", http: 402, exit: 5, billed: "no",
|
|
180
186
|
message: "a card is required for new work since {effective_at}",
|
|
181
187
|
fix: "Add a card (owners: `promigence billing card`, or POST /v1/billing/checkout; members ask an owner). Your trial credits are kept and used first; reads and results stay available." },
|
|
@@ -233,6 +239,9 @@ export const ERRORS = [
|
|
|
233
239
|
{ code: "key_expired", category: "other", http: 401, exit: 7, billed: "no",
|
|
234
240
|
message: "this API key expired at {expired_at}",
|
|
235
241
|
fix: "Create a new key (`promigence keys create`, or sign in again with `promigence login`) and replace this one wherever it is used." },
|
|
242
|
+
{ code: "account_blocked", category: "other", http: 401, exit: 7, billed: "no",
|
|
243
|
+
message: "this account is blocked",
|
|
244
|
+
fix: "Write to support@promigence.ai to have it reviewed." },
|
|
236
245
|
];
|
|
237
246
|
export const ERROR_BY_CODE = Object.fromEntries(ERRORS.map((e) => [e.code, e]));
|
|
238
247
|
export const CLIENT_ERRORS = [
|
package/dist/github.js
CHANGED
|
@@ -14,7 +14,7 @@ function pollMs() {
|
|
|
14
14
|
}
|
|
15
15
|
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
16
16
|
function notConfigured(s) {
|
|
17
|
-
return usageError(s.message ?? "GitHub
|
|
17
|
+
return usageError(s.message ?? "Connecting GitHub isn't available here yet", "Bring the code in another way: `promigence snapshot create --dir .` uploads the files git tracks here, or clone a public repository in a --setup step.");
|
|
18
18
|
}
|
|
19
19
|
function connectionLine(c) {
|
|
20
20
|
return ` ${c.account} ${c.account_type} · ${c.repository_selection} repositories · installation ${c.installation_id}${c.suspended ? " SUSPENDED on GitHub" : ""}`;
|
|
@@ -107,7 +107,7 @@ const githubStatus = async (ctx) => {
|
|
|
107
107
|
const s = await client(ctx).github.status();
|
|
108
108
|
if (!s.configured) {
|
|
109
109
|
const next = nexts(["promigence snapshot create --dir . --alias app --wait", "bring the files git tracks here instead"]);
|
|
110
|
-
return emit(ctx.mode, okEnvelope(ctx.cmd.name, { ...s }, next), [`github: ${s.message ?? "GitHub
|
|
110
|
+
return emit(ctx.mode, okEnvelope(ctx.cmd.name, { ...s }, next), [`github: ${s.message ?? "Connecting GitHub isn't available here yet"}`], 0, ctx.pointer);
|
|
111
111
|
}
|
|
112
112
|
const lines = [
|
|
113
113
|
s.connections.length
|
|
@@ -215,7 +215,6 @@ const NOT_WITH_GITHUB = [
|
|
|
215
215
|
["--devcontainer", "it is not read for a connected repository; use --setup steps"],
|
|
216
216
|
["--start", "a background process is part of an image snapshot"],
|
|
217
217
|
["--also-repo", "clone further repositories in a --setup step"],
|
|
218
|
-
["--cpu-class", "the build goes wherever there is room"],
|
|
219
218
|
["--dir", "--dir uploads a local tree instead; pass one of them"],
|
|
220
219
|
];
|
|
221
220
|
const GITHUB_ONLY = ["--ref", "--from", "--track"];
|
package/dist/gitlab.js
CHANGED
|
@@ -12,7 +12,7 @@ function pollMs() {
|
|
|
12
12
|
}
|
|
13
13
|
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
14
14
|
function notConfigured(s) {
|
|
15
|
-
return usageError(s.message ?? "GitLab
|
|
15
|
+
return usageError(s.message ?? "Connecting GitLab isn't available here yet", "Bring the code in another way: `promigence snapshot create --dir .` uploads the files git tracks here, or clone in a --setup step.");
|
|
16
16
|
}
|
|
17
17
|
function connectionLine(c) {
|
|
18
18
|
return ` ${c.username} on ${c.gitlab_url} · ${c.connection_id}${c.broken ? ` BROKEN: ${c.broken_reason ?? "connect again"}` : ""}`;
|
|
@@ -108,7 +108,7 @@ const gitlabStatus = async (ctx) => {
|
|
|
108
108
|
const s = await client(ctx).gitlab.status();
|
|
109
109
|
if (!s.configured) {
|
|
110
110
|
const next = nexts(["promigence snapshot create --dir . --alias app --wait", "bring the files git tracks here instead"]);
|
|
111
|
-
return emit(ctx.mode, okEnvelope(ctx.cmd.name, { ...s }, next), [`gitlab: ${s.message ?? "GitLab
|
|
111
|
+
return emit(ctx.mode, okEnvelope(ctx.cmd.name, { ...s }, next), [`gitlab: ${s.message ?? "Connecting GitLab isn't available here yet"}`], 0, ctx.pointer);
|
|
112
112
|
}
|
|
113
113
|
const lines = [
|
|
114
114
|
s.connections.length
|
package/dist/guide.d.ts
CHANGED
|
@@ -7,6 +7,8 @@ export declare const BUDGETS: Readonly<Record<Section, number>>;
|
|
|
7
7
|
export declare function lookupError(code: string): ErrorEntry | undefined;
|
|
8
8
|
export declare const ALL_ERROR_CODES: readonly string[];
|
|
9
9
|
export declare const estimateTokens: (s: string) => number;
|
|
10
|
+
export declare const HUMAN_START = "promigence run --count 1 --cap 1 -- python3 -c 'print(6*7)'";
|
|
11
|
+
export declare function humanHeader(): string;
|
|
10
12
|
export interface GuideOpts {
|
|
11
13
|
section?: Section;
|
|
12
14
|
code?: string;
|
package/dist/guide.js
CHANGED
|
@@ -10,7 +10,7 @@ export const SECTIONS = ["core", "commands", "errors", "cost"];
|
|
|
10
10
|
export const BUDGETS = {
|
|
11
11
|
core: 1200,
|
|
12
12
|
commands: 4475,
|
|
13
|
-
errors:
|
|
13
|
+
errors: 2325,
|
|
14
14
|
cost: 600,
|
|
15
15
|
};
|
|
16
16
|
export function lookupError(code) {
|
|
@@ -222,8 +222,10 @@ function renderCost(prices) {
|
|
|
222
222
|
const source = prices === undefined
|
|
223
223
|
? "List prices when this CLI was built. Live, and your plan's: `promigence pricing`."
|
|
224
224
|
: prices.source === "api"
|
|
225
|
-
? `Live from the API (${view?.as_of ?? "now"}):
|
|
226
|
-
:
|
|
225
|
+
? `Live from the API (${view?.as_of ?? "now"}): your organization's prices. \`promigence pricing\` shows the rest.`
|
|
226
|
+
: prices.source === "published"
|
|
227
|
+
? "Published list prices. Your organization's own: `promigence login`, then `promigence pricing`."
|
|
228
|
+
: `${prices.note ?? "list prices at build time; could not reach the API"} (\`promigence pricing\` asks again).`;
|
|
227
229
|
const limit = view?.limits.max_sandbox_vcpus;
|
|
228
230
|
const out = [
|
|
229
231
|
`# Promigence — what it costs (promigence@${VERSION})`,
|
|
@@ -259,6 +261,10 @@ function renderCost(prices) {
|
|
|
259
261
|
];
|
|
260
262
|
return out.filter((l) => l !== undefined).join("\n");
|
|
261
263
|
}
|
|
264
|
+
export const HUMAN_START = "promigence run --count 1 --cap 1 -- python3 -c 'print(6*7)'";
|
|
265
|
+
export function humanHeader() {
|
|
266
|
+
return `For people: this is the guide your coding agent reads, dense on purpose.\nStart here: ${HUMAN_START}\n\n`;
|
|
267
|
+
}
|
|
262
268
|
export function renderGuide(opts = {}) {
|
|
263
269
|
if (opts.code)
|
|
264
270
|
return renderCode(opts.code);
|
package/dist/handlers.js
CHANGED
|
@@ -4,7 +4,7 @@ import { BUNDLE_EXT, DEFAULT_SNAPSHOT, PromigenceError, VERSION as SDK_VERSION,
|
|
|
4
4
|
import { storeLabel } from "./sdk/credstore.js";
|
|
5
5
|
import { bool, client, list, nexts, positional, required, str, } from "./commands.js";
|
|
6
6
|
import { emit, exitWith, forkSummary, markGuideSeen, ms, okEnvelope, parseCount, parseDuration, parseUsd, pickExit, usageError, write, } from "./io.js";
|
|
7
|
-
import { ALL_ERROR_CODES, BUDGETS, estimateTokens, guideJson, lookupError, renderGuide } from "./guide.js";
|
|
7
|
+
import { ALL_ERROR_CODES, BUDGETS, estimateTokens, guideJson, humanHeader, lookupError, renderGuide } from "./guide.js";
|
|
8
8
|
import { livePricing, quickClient } from "./pricing.js";
|
|
9
9
|
import { install, installLines } from "./install.js";
|
|
10
10
|
import { backgroundOutput } from "./live.js";
|
|
@@ -66,6 +66,8 @@ const agentGuide = async (ctx) => {
|
|
|
66
66
|
await write(process.stdout, jsonLine(process.stdout, env));
|
|
67
67
|
return exitWith(0);
|
|
68
68
|
}
|
|
69
|
+
if (section === "core" && code === undefined && process.stdout.isTTY)
|
|
70
|
+
await write(process.stdout, humanHeader());
|
|
69
71
|
await write(process.stdout, guide);
|
|
70
72
|
const budget = BUDGETS[section] ?? BUDGETS.core;
|
|
71
73
|
const used = estimateTokens(guide);
|
package/dist/index.d.ts
CHANGED
|
@@ -9,6 +9,6 @@ export { FENCE_BEGIN, FENCE_END, FENCE_MAX_LINES, fenceBody, install, spliceFenc
|
|
|
9
9
|
export type { Artifact, InstallResult } from "./install.js";
|
|
10
10
|
export { detect, gitFacts, normalizeRemote, readConfig, renderConfig, stripRemoteCredentials } from "./init.js";
|
|
11
11
|
export type { Config, Detection, Ecosystem, GitFacts, ReadConfig } from "./init.js";
|
|
12
|
-
export { DEVCONTAINER_NAMES, DEVCONTAINER_SPEC, DevcontainerError, detectOne, discover, load, parseJsonc, planJson, planLines, planSetup, resolveGiven, shellQuote, snapshotEnv, substituteString, translate, workspaceRootFor, wrapCommand, } from "./devcontainer.js";
|
|
12
|
+
export { DEVCONTAINER_NAMES, DEVCONTAINER_SPEC, DevcontainerError, detectOne, discover, load, parseJsonc, planJson, planLines, planSetup, resolveGiven, shellQuote, snapshotEnv, snapshotUsers, substituteString, translate, workspaceRootFor, wrapCommand, } from "./devcontainer.js";
|
|
13
13
|
export type { LoadedDevcontainer, Plan, PlanSource, LifecycleStep, IgnoredProperty } from "./devcontainer.js";
|
|
14
14
|
export type { Command, Flag, Group, CommandStatus, ExitCode, Envelope, EnvelopeError, NextHint } from "./surface.js";
|
package/dist/index.js
CHANGED
|
@@ -4,4 +4,4 @@ export { ALL_ERROR_CODES, BILLED_TEXT, BUDGETS, SECTIONS, estimateTokens, guideJ
|
|
|
4
4
|
export { CLIENT_ERRORS, CLIENT_ERROR_BY_CODE, ERRORS, ERROR_BY_CODE, TIERS, BUILD_PRICE, PRICING } from "./generated.js";
|
|
5
5
|
export { FENCE_BEGIN, FENCE_END, FENCE_MAX_LINES, fenceBody, install, spliceFence } from "./install.js";
|
|
6
6
|
export { detect, gitFacts, normalizeRemote, readConfig, renderConfig, stripRemoteCredentials } from "./init.js";
|
|
7
|
-
export { DEVCONTAINER_NAMES, DEVCONTAINER_SPEC, DevcontainerError, detectOne, discover, load, parseJsonc, planJson, planLines, planSetup, resolveGiven, shellQuote, snapshotEnv, substituteString, translate, workspaceRootFor, wrapCommand, } from "./devcontainer.js";
|
|
7
|
+
export { DEVCONTAINER_NAMES, DEVCONTAINER_SPEC, DevcontainerError, detectOne, discover, load, parseJsonc, planJson, planLines, planSetup, resolveGiven, shellQuote, snapshotEnv, snapshotUsers, substituteString, translate, workspaceRootFor, wrapCommand, } from "./devcontainer.js";
|
package/dist/login.js
CHANGED
|
@@ -765,6 +765,8 @@ async function signInAndStore(ctx, isSignup) {
|
|
|
765
765
|
if (!idp) {
|
|
766
766
|
throw usageError(`--provider: '${provider}' is not a login method`, `Pass --provider ${Object.keys(cfg.identity_providers).join(" | ")}, or omit it to choose in the browser.`);
|
|
767
767
|
}
|
|
768
|
+
if (provider === "email")
|
|
769
|
+
idp = undefined;
|
|
768
770
|
}
|
|
769
771
|
const keyName = (str(ctx, "--key-name") ?? `cli@${deviceName()}`).slice(0, 64);
|
|
770
772
|
const ref = str(ctx, "--ref")?.trim();
|
package/dist/mcp.js
CHANGED
|
@@ -132,7 +132,7 @@ function reportSummary(report) {
|
|
|
132
132
|
export const MCP_TOOLS = [
|
|
133
133
|
{
|
|
134
134
|
name: "sandbox_create",
|
|
135
|
-
description: "Create a sandbox from a Promigence snapshot (id or alias; default promigence/base: Debian with Python 3.12,
|
|
135
|
+
description: "Create a sandbox from a Promigence snapshot (id or alias; default promigence/base: Debian with Python 3.12, Node 24, Go, Docker, git, gcc and the Claude Code, Codex, Gemini and OpenCode CLIs) or from a container image (a tag, which the API pins, or NAME@sha256:…), and return its sandbox_id.",
|
|
136
136
|
readOnly: false,
|
|
137
137
|
inputSchema: {
|
|
138
138
|
type: "object",
|
package/dist/pricing.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { PromigenceClient, type PricingView } from "./sdk/index.js";
|
|
2
2
|
import { type Ctx, type Handler } from "./commands.js";
|
|
3
3
|
export declare const COMPILED_NOTE = "list prices at build time; could not reach the API";
|
|
4
|
+
export declare const PUBLISHED_NOTE = "published list prices; your organization's own need a key (promigence login)";
|
|
4
5
|
export interface PriceTier {
|
|
5
6
|
name: string;
|
|
6
7
|
vcpus: number;
|
|
@@ -12,7 +13,7 @@ export interface PriceTier {
|
|
|
12
13
|
available?: boolean;
|
|
13
14
|
}
|
|
14
15
|
export interface Prices {
|
|
15
|
-
source: "api" | "compiled";
|
|
16
|
+
source: "api" | "compiled" | "published";
|
|
16
17
|
note?: string;
|
|
17
18
|
reason?: string;
|
|
18
19
|
view?: PricingView;
|
|
@@ -24,6 +25,7 @@ export interface Prices {
|
|
|
24
25
|
granularity_seconds: number;
|
|
25
26
|
tiers: PriceTier[];
|
|
26
27
|
}
|
|
28
|
+
export declare function publishedPrices(): Prices;
|
|
27
29
|
export declare function compiledPrices(note?: string, reason?: string): Prices;
|
|
28
30
|
export declare function pricesFrom(view: PricingView): Prices;
|
|
29
31
|
export declare function livePricing(c: PromigenceClient, opts?: {
|