promigence 0.1.0-beta.5 → 0.1.0-beta.6

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/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/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,6 +105,51 @@ export async function offerAfterLogin(ctx, apiUrl, apiKey, consoleHome) {
104
105
  lines: claimLines(offer, link, opened),
105
106
  };
106
107
  }
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
+ }
107
153
  async function cardsOff(c, o) {
108
154
  if (!(typeof o.card_bonus_usd === "number" && o.card_bonus_usd > 0) || o.state === "none")
109
155
  return false;
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/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
@@ -259,6 +259,10 @@ function renderCost(prices) {
259
259
  ];
260
260
  return out.filter((l) => l !== undefined).join("\n");
261
261
  }
262
+ export const HUMAN_START = "promigence run --count 1 --cap 1 -- python3 -c 'print(6*7)'";
263
+ export function humanHeader() {
264
+ return `For people: this is the guide your coding agent reads, dense on purpose.\nStart here: ${HUMAN_START}\n\n`;
265
+ }
262
266
  export function renderGuide(opts = {}) {
263
267
  if (opts.code)
264
268
  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/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, node, git, gcc) or from a container image (a tag, which the API pins, or NAME@sha256:…), and return its sandbox_id.",
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",
@@ -1,5 +1,5 @@
1
1
  /** Promigence SDK — constants, error hierarchy and shared types. */
2
- export declare const VERSION = "0.1.0-beta.5";
2
+ export declare const VERSION = "0.1.0-beta.6";
3
3
  export declare const DOCS_URL = "https://promigence.ai";
4
4
  /** The error reference; each code is an anchor on it (the API's `docs` link has the same form). */
5
5
  export declare const ERRORS_DOCS_URL = "https://www.promigence.ai/docs/errors";
package/dist/sdk/core.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { hintArg } from "./hint.js";
2
- export const VERSION = "0.1.0-beta.5";
2
+ export const VERSION = "0.1.0-beta.6";
3
3
  export const DOCS_URL = "https://promigence.ai";
4
4
  export const ERRORS_DOCS_URL = "https://www.promigence.ai/docs/errors";
5
5
  export const DEFAULT_API_URL = "https://api.promigence.ai/v1";
@@ -224,9 +224,10 @@ interface SandboxInit {
224
224
  timeoutMs?: number;
225
225
  }
226
226
  /**
227
- * The snapshot `Sandbox.create()` forks when it is given none: Debian 12 + Python 3.12, node/npm,
228
- * git, curl, jq, gcc/make, `small` tier (built in, not verified). It is always ready to start. The template
229
- * name `'base'` means the same thing.
227
+ * The snapshot `Sandbox.create()` forks when it is given none: Debian 12 + Python 3.12 (pip, venv, uv),
228
+ * Node 24 (npm), Bun, Go 1.27, Docker, git, Git LFS, the GitHub CLI, curl, jq, ripgrep, rsync, gcc/make,
229
+ * and the Claude Code, Codex, Gemini CLI and OpenCode agents, `small` tier (built in, not verified). It
230
+ * is always ready to start. The template name `'base'` means the same thing.
230
231
  */
231
232
  export declare const DEFAULT_SNAPSHOT = "promigence/base";
232
233
  /**
package/llms.txt CHANGED
@@ -1,4 +1,4 @@
1
- # Promigence — promigence@0.1.0-beta.5
1
+ # Promigence — promigence@0.1.0-beta.6
2
2
 
3
3
  > Verified, reproducible, forkable execution environments for agents. The CLI is the
4
4
  > `promigence` command (package `promigence`, which is also the TypeScript SDK).
@@ -126,7 +126,7 @@
126
126
 
127
127
  ---
128
128
 
129
- # Promigence — agent guide (promigence@0.1.0-beta.5)
129
+ # Promigence — agent guide (promigence@0.1.0-beta.6)
130
130
 
131
131
  Promigence is an **environment runtime**: verified, reproducible, forkable execution
132
132
  environments, billed per second (vCPU + memory). The model is one line:
@@ -196,4 +196,4 @@ Highest-precedence code wins: 2 > 5 > 6 > 7/8/9/10 > 11 > 3 > 12 > 4 > 1 > 0.
196
196
  · `promigence <command> --help` · https://promigence.ai
197
197
  Same surface as MCP tools: `promigence mcp` (stdio; `claude mcp add promigence -- promigence mcp`).
198
198
 
199
- Live in v0.1.0-beta.5: login · signup · logout · auth login · keys list/create/revoke · org list/create/switch/members/invite/invites/uninvite/resend/role/remove/leave/join/audit/rename/delete · project list/create/rename/delete/cap/move · me · billing card/usage/portal · doctor · ping · init · examples · templates +show · agent-guide · mcp · snapshot create/status/list/inspect/verify/export/delete/builds/alias · image resolve · github connect/status/disconnect/untrack · repos · gitlab connect/status/disconnect/untrack · run +quote/report/status/cancel/kill/replay/open/captures/list · fork · exec +output/ps/stdin/kill · files put/get/ls/search/mkdir/mv/cp/chmod/rm · agent start · sandbox kill/network/shell/ssh/list/pause/resume/snapshot/info/extend/autopause/probe · port expose/list/revoke · secrets set/list/delete · bench burst · runners github/gitlab · status · referrals +apply · pricing · credits +claim
199
+ Live in v0.1.0-beta.6: login · signup · logout · auth login · keys list/create/revoke · org list/create/switch/members/invite/invites/uninvite/resend/role/remove/leave/join/audit/rename/delete · project list/create/rename/delete/cap/move · me · billing card/usage/portal · doctor · ping · init · examples · templates +show · agent-guide · mcp · snapshot create/status/list/inspect/verify/export/delete/builds/alias · image resolve · github connect/status/disconnect/untrack · repos · gitlab connect/status/disconnect/untrack · run +quote/report/status/cancel/kill/replay/open/captures/list · fork · exec +output/ps/stdin/kill · files put/get/ls/search/mkdir/mv/cp/chmod/rm · agent start · sandbox kill/network/shell/ssh/list/pause/resume/snapshot/info/extend/autopause/probe · port expose/list/revoke · secrets set/list/delete · bench burst · runners github/gitlab · status · referrals +apply · pricing · credits +claim
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "promigence",
3
- "version": "0.1.0-beta.5",
3
+ "version": "0.1.0-beta.6",
4
4
  "description": "The fastest sandboxes for AI agents and code. Snapshot an environment once, fork it as often as you need, run commands in every copy, and get a report that tells environment failures from task failures. Billed per second, with a quote before a run and a hard spend cap. One package: the promigence command and the TypeScript SDK.",
5
5
  "license": "Apache-2.0",
6
6
  "homepage": "https://www.promigence.ai",