@t2000/cli 5.31.0 → 5.32.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.
@@ -99462,7 +99462,7 @@ The wallet can also HIRE OTHER AGENTS: the agent store (agents.t2000.ai) lists a
99462
99462
  The wallet can EARN too: t2000_tasks lists live reward tasks + the community task board, t2000_task_claim collects auto-verified rewards, t2000_task_submit submits proof on board jobs, and t2000_agent_earnings reports the wallet's seller sales. None of these spend \u2014 claims RECEIVE USDC through the rail (see the skill-earn prompt or the t2000-earn skill).
99463
99463
 
99464
99464
  Spending is the user's own USDC and every t2000_pay call is bounded by maxPrice. For larger or multi-step spends, state the estimated cost first and proceed once the user is happy. Use t2000_balance to check funds. The v4 wallet is payments-only; savings / lending live on audric.ai.`;
99465
- var PKG_VERSION = "5.31.0";
99465
+ var PKG_VERSION = "5.32.0";
99466
99466
  console.log = (...args) => console.error("[log]", ...args);
99467
99467
  console.warn = (...args) => console.error("[warn]", ...args);
99468
99468
  async function startMcpServer(opts) {
@@ -99537,4 +99537,4 @@ mime-types/index.js:
99537
99537
  @scure/bip39/index.js:
99538
99538
  (*! scure-bip39 - MIT License (c) 2022 Patricio Palladino, Paul Miller (paulmillr.com) *)
99539
99539
  */
99540
- //# sourceMappingURL=dist-L3E4Q45J.js.map
99540
+ //# sourceMappingURL=dist-VB42REWC.js.map
package/dist/index.js CHANGED
@@ -33122,7 +33122,7 @@ function registerMcpStart(parent) {
33122
33122
  parent.command("start", { isDefault: true }).description("Start MCP server (stdio transport \u2014 for AI client integration)").option("--key <path>", "Custom wallet path (default ~/.t2000/wallet.key)").action(async (opts) => {
33123
33123
  let mod3;
33124
33124
  try {
33125
- mod3 = await import("./dist-L3E4Q45J.js");
33125
+ mod3 = await import("./dist-VB42REWC.js");
33126
33126
  } catch {
33127
33127
  console.error("MCP server not installed. Run:\n npm install -g @t2000/mcp");
33128
33128
  process.exit(1);
@@ -34083,7 +34083,8 @@ var HANDLER_TEMPLATE = `// t2000 hosted handler (R1). Deploys with: t2 agent ser
34083
34083
  // auto-refunded. Keep it fast (15s delivery timeout, 5s CPU cap).
34084
34084
  //
34085
34085
  // input \u2014 the buyer's request body (parsed JSON, or a raw string)
34086
- // ctx \u2014 { agent, slug, buyer }
34086
+ // ctx \u2014 { agent, slug, buyer, secrets }
34087
+ // secrets = your vault (t2 agent serve secrets set KEY=value)
34087
34088
  export default async function handle(input, ctx) {
34088
34089
  // Example: compose public data and return a result.
34089
34090
  // const res = await fetch('https://api.example.com/data');
@@ -34095,6 +34096,37 @@ export default async function handle(input, ctx) {
34095
34096
  };
34096
34097
  }
34097
34098
  `;
34099
+ var PROXY_TEMPLATE = `// t2000 hosted handler \u2014 "Proxy an API" template. You hold a key to an
34100
+ // API; this resells calls to it per-call, with your key never leaving the
34101
+ // t2000 vault. Setup:
34102
+ // 1. Edit UPSTREAM below.
34103
+ // 2. t2 agent serve secrets set UPSTREAM_KEY=<your api key>
34104
+ // 3. t2 agent serve deploy
34105
+ const UPSTREAM = 'https://api.example.com/v1/endpoint';
34106
+
34107
+ export default async function handle(input, ctx) {
34108
+ const res = await fetch(UPSTREAM, {
34109
+ method: 'POST',
34110
+ headers: {
34111
+ 'content-type': 'application/json',
34112
+ // Adjust the auth scheme to your upstream (x-api-key, basic, \u2026).
34113
+ ...(ctx.secrets?.UPSTREAM_KEY
34114
+ ? { authorization: \`Bearer \${ctx.secrets.UPSTREAM_KEY}\` }
34115
+ : {}),
34116
+ },
34117
+ body: JSON.stringify(input ?? {}),
34118
+ });
34119
+ if (!res.ok) {
34120
+ // Throwing fails the delivery \u2192 the buyer is auto-refunded.
34121
+ throw new Error(\`Upstream error \${res.status}\`);
34122
+ }
34123
+ return await res.json();
34124
+ }
34125
+ `;
34126
+ var TEMPLATES = {
34127
+ default: HANDLER_TEMPLATE,
34128
+ proxy: PROXY_TEMPLATE
34129
+ };
34098
34130
  function readManifest(dir) {
34099
34131
  const p = join8(dir, MANIFEST);
34100
34132
  if (!existsSync4(p)) {
@@ -34150,7 +34182,11 @@ function registerAgentServe(agentGroup) {
34150
34182
  const group = agentGroup.command("serve").description(
34151
34183
  "Hosted handlers \u2014 deploy a function to t2000 compute and sell it per call. No server, no wrap. [R1]"
34152
34184
  );
34153
- group.command("init").description(`Scaffold ${HANDLER} + ${MANIFEST} in the current directory.`).option("--slug <slug>", "Service slug (in the buy URL)", "my-service").option("--dir <path>", "Target directory (default: cwd)").action((opts) => {
34185
+ group.command("init").description(`Scaffold ${HANDLER} + ${MANIFEST} in the current directory.`).option("--slug <slug>", "Service slug (in the buy URL)", "my-service").option(
34186
+ "--template <name>",
34187
+ `Handler template: ${Object.keys(TEMPLATES).join(" | ")} (proxy = resell a keyed API)`,
34188
+ "default"
34189
+ ).option("--dir <path>", "Target directory (default: cwd)").action((opts) => {
34154
34190
  try {
34155
34191
  const dir = resolve2(opts.dir ?? ".");
34156
34192
  mkdirSync2(dir, { recursive: true });
@@ -34158,6 +34194,12 @@ function registerAgentServe(agentGroup) {
34158
34194
  if (!SLUG_RE2.test(slug)) {
34159
34195
  throw new Error("--slug must match [a-z0-9-], 2-40 chars.");
34160
34196
  }
34197
+ const template = TEMPLATES[opts.template];
34198
+ if (!template) {
34199
+ throw new Error(
34200
+ `Unknown --template "${opts.template}" \u2014 use: ${Object.keys(TEMPLATES).join(", ")}.`
34201
+ );
34202
+ }
34161
34203
  const manifestPath = join8(dir, MANIFEST);
34162
34204
  const handlerPath = join8(dir, HANDLER);
34163
34205
  if (existsSync4(manifestPath) || existsSync4(handlerPath)) {
@@ -34178,7 +34220,7 @@ function registerAgentServe(agentGroup) {
34178
34220
  )}
34179
34221
  `
34180
34222
  );
34181
- writeFileSync3(handlerPath, HANDLER_TEMPLATE);
34223
+ writeFileSync3(handlerPath, template);
34182
34224
  if (isJsonMode()) {
34183
34225
  printJson({ dir, files: [MANIFEST, HANDLER] });
34184
34226
  return;
@@ -34329,6 +34371,105 @@ function registerAgentServe(agentGroup) {
34329
34371
  }
34330
34372
  }
34331
34373
  );
34374
+ const secrets = group.command("secrets").description(
34375
+ "This agent's handler secrets vault \u2014 encrypted at t2000, injected as ctx.secrets on paid deliveries only. Values are write-only."
34376
+ );
34377
+ secrets.command("set").argument("<pairs...>", "NAME=value pairs (e.g. UPSTREAM_KEY=sk-\u2026)").description("Set (or overwrite) vault secrets. NAME: A-Z, 0-9, _.").option("--key <path>", "Custom wallet path (default ~/.t2000/wallet.key)").option("--gateway <url>", `Gateway URL (default ${DEFAULT_GATEWAY2})`).action(
34378
+ async (pairs, opts) => {
34379
+ try {
34380
+ const updates = {};
34381
+ for (const pair of pairs) {
34382
+ const eq = pair.indexOf("=");
34383
+ if (eq <= 0) {
34384
+ throw new Error(`"${pair}" is not NAME=value.`);
34385
+ }
34386
+ updates[pair.slice(0, eq).trim()] = pair.slice(eq + 1);
34387
+ }
34388
+ const res = await postSecrets(opts, "set", updates);
34389
+ if (isJsonMode()) {
34390
+ printJson({ names: res.names });
34391
+ return;
34392
+ }
34393
+ printBlank();
34394
+ printSuccess("Vault updated");
34395
+ printKeyValue("Secrets", res.names.join(", ") || "(none)");
34396
+ printInfo("Handlers read them as ctx.secrets.NAME on paid deliveries.");
34397
+ printBlank();
34398
+ } catch (error) {
34399
+ handleError(error);
34400
+ }
34401
+ }
34402
+ );
34403
+ secrets.command("unset").argument("<names...>", "Secret names to delete").description("Delete vault secrets.").option("--key <path>", "Custom wallet path (default ~/.t2000/wallet.key)").option("--gateway <url>", `Gateway URL (default ${DEFAULT_GATEWAY2})`).action(
34404
+ async (names, opts) => {
34405
+ try {
34406
+ const updates = {};
34407
+ for (const n of names) {
34408
+ updates[n.trim()] = "";
34409
+ }
34410
+ const res = await postSecrets(opts, "set", updates);
34411
+ if (isJsonMode()) {
34412
+ printJson({ names: res.names });
34413
+ return;
34414
+ }
34415
+ printBlank();
34416
+ printSuccess("Vault updated");
34417
+ printKeyValue("Secrets", res.names.join(", ") || "(none)");
34418
+ printBlank();
34419
+ } catch (error) {
34420
+ handleError(error);
34421
+ }
34422
+ }
34423
+ );
34424
+ secrets.command("list").description("List vault secret NAMES (values never leave the gateway).").option("--key <path>", "Custom wallet path (default ~/.t2000/wallet.key)").option("--gateway <url>", `Gateway URL (default ${DEFAULT_GATEWAY2})`).action(async (opts) => {
34425
+ try {
34426
+ const res = await postSecrets(opts, "list");
34427
+ if (isJsonMode()) {
34428
+ printJson({ names: res.names });
34429
+ return;
34430
+ }
34431
+ const names = res.names;
34432
+ printBlank();
34433
+ if (names.length === 0) {
34434
+ printLine("Vault is empty. Set one: t2 agent serve secrets set NAME=value");
34435
+ } else {
34436
+ for (const n of names) {
34437
+ printLine(` ${n}`);
34438
+ }
34439
+ }
34440
+ printBlank();
34441
+ } catch (error) {
34442
+ handleError(error);
34443
+ }
34444
+ });
34445
+ async function postSecrets(opts, op, updates) {
34446
+ const gateway = opts.gateway ?? DEFAULT_GATEWAY2;
34447
+ const agent = await withAgent({ keyPath: opts.key });
34448
+ const address = agent.address();
34449
+ const ts = Date.now();
34450
+ const payload = op === "list" ? "list" : JSON.stringify(
34451
+ Object.fromEntries(
34452
+ Object.entries(updates ?? {}).sort(
34453
+ ([a], [b]) => a.localeCompare(b)
34454
+ )
34455
+ )
34456
+ );
34457
+ const bodyHash = createHash3("sha256").update(payload).digest("hex");
34458
+ const message = new TextEncoder().encode(
34459
+ `t2000-serve-secrets:${ts}:${bodyHash}`
34460
+ );
34461
+ const { signature } = await agent.keypair.signPersonalMessage(message);
34462
+ return await fetchJson4(`${gateway}/serve/secrets`, {
34463
+ method: "POST",
34464
+ body: {
34465
+ address,
34466
+ op,
34467
+ ...op === "set" ? { updates } : {},
34468
+ timestamp: ts,
34469
+ signature
34470
+ }
34471
+ });
34472
+ }
34332
34473
  group.command("status").description("Deployed handlers + invocation stats.").option("--key <path>", "Custom wallet path (default ~/.t2000/wallet.key)").option("--gateway <url>", `Gateway URL (default ${DEFAULT_GATEWAY2})`).action(async (opts) => {
34333
34474
  try {
34334
34475
  const gateway = opts.gateway ?? DEFAULT_GATEWAY2;