zk-agent-cli 0.1.0-rc.9 → 1.0.1

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.
Files changed (3) hide show
  1. package/README.md +83 -12
  2. package/dist/index.js +916 -61
  3. package/package.json +10 -3
package/dist/index.js CHANGED
@@ -8090,6 +8090,12 @@ function buildPaymentDashboardRecommendedCommand() {
8090
8090
  function buildPaymentFeedRecommendedCommand() {
8091
8091
  return "zk-agent payment feed";
8092
8092
  }
8093
+ function buildPaymentPublishRecommendedCommand() {
8094
+ return "zk-agent payment publish";
8095
+ }
8096
+ function buildPaymentServeRecommendedCommand() {
8097
+ return "zk-agent payment serve";
8098
+ }
8093
8099
  function buildPaymentApprovalRecommendedCommand(requestId) {
8094
8100
  return `zk-agent payment approval --request-id ${requestId}`;
8095
8101
  }
@@ -10393,7 +10399,7 @@ function buildSetupHelpText() {
10393
10399
  " zk-agent next -> canonical live routing contract",
10394
10400
  "",
10395
10401
  "Then stay on the default local-first path:",
10396
- " zk-agent next",
10402
+ " zk-agent start",
10397
10403
  " zk-agent wallet create --await-local",
10398
10404
  " zk-agent next",
10399
10405
  ` ${buildTopLevelPayRecommendedCommand("main")}`,
@@ -11384,7 +11390,7 @@ function buildNextHelpText() {
11384
11390
  "",
11385
11391
  "Default first-run path:",
11386
11392
  " zk-agent setup",
11387
- " zk-agent next",
11393
+ " zk-agent start",
11388
11394
  " zk-agent wallet create --await-local",
11389
11395
  " zk-agent next",
11390
11396
  ` ${buildTopLevelPayRecommendedCommand("main")}`,
@@ -11454,7 +11460,7 @@ function buildStartHelpText() {
11454
11460
  "",
11455
11461
  "Shortest first proof:",
11456
11462
  " zk-agent setup",
11457
- " zk-agent next",
11463
+ " zk-agent start",
11458
11464
  " zk-agent wallet create --await-local",
11459
11465
  " zk-agent next",
11460
11466
  ` ${buildTopLevelPayRecommendedCommand("main")}`,
@@ -13263,6 +13269,8 @@ function createDefaultsCommand() {
13263
13269
 
13264
13270
  // src/commands/payment.ts
13265
13271
  import { randomBytes as randomBytes5 } from "node:crypto";
13272
+ import { mkdir as mkdir2, rm as rm2, writeFile as writeFile2 } from "node:fs/promises";
13273
+ import path7 from "node:path";
13266
13274
  import { Command as Command7 } from "commander";
13267
13275
 
13268
13276
  // ../agent-pay/src/lifecycle.ts
@@ -15180,6 +15188,117 @@ async function removeStoredPaymentRequest(requestId) {
15180
15188
  return deletePaymentRequest(requestId);
15181
15189
  }
15182
15190
 
15191
+ // src/lib/static-server.ts
15192
+ import { readFile as readFile2, stat } from "node:fs/promises";
15193
+ import { createServer } from "node:http";
15194
+ import path6 from "node:path";
15195
+ function writeBody(response, statusCode, contentType, value) {
15196
+ response.statusCode = statusCode;
15197
+ response.setHeader("Content-Type", contentType);
15198
+ response.end(value);
15199
+ }
15200
+ function writeJson2(response, statusCode, value) {
15201
+ writeBody(
15202
+ response,
15203
+ statusCode,
15204
+ "application/json; charset=utf-8",
15205
+ `${JSON.stringify(value, null, 2)}
15206
+ `
15207
+ );
15208
+ }
15209
+ function contentTypeFor(filePath) {
15210
+ switch (path6.extname(filePath).toLowerCase()) {
15211
+ case ".html":
15212
+ return "text/html; charset=utf-8";
15213
+ case ".json":
15214
+ return "application/json; charset=utf-8";
15215
+ case ".js":
15216
+ return "text/javascript; charset=utf-8";
15217
+ case ".css":
15218
+ return "text/css; charset=utf-8";
15219
+ case ".svg":
15220
+ return "image/svg+xml";
15221
+ case ".txt":
15222
+ return "text/plain; charset=utf-8";
15223
+ default:
15224
+ return "application/octet-stream";
15225
+ }
15226
+ }
15227
+ function isSafeResolvedPath(rootDir, filePath) {
15228
+ if (filePath === rootDir) return true;
15229
+ const rootWithSeparator = rootDir.endsWith(path6.sep) ? rootDir : `${rootDir}${path6.sep}`;
15230
+ return filePath.startsWith(rootWithSeparator);
15231
+ }
15232
+ async function startStaticServer(options) {
15233
+ const rootDir = path6.resolve(options.rootDir);
15234
+ const healthPath = options.healthPath?.trim() || "/health";
15235
+ const server = createServer(async (request, response) => {
15236
+ try {
15237
+ const requestUrl = new URL(request.url || "/", "http://localhost");
15238
+ const pathname = decodeURIComponent(requestUrl.pathname);
15239
+ const method = request.method || "GET";
15240
+ if (method === "OPTIONS") {
15241
+ writeJson2(response, 204, {});
15242
+ return;
15243
+ }
15244
+ if (method === "GET" && pathname === healthPath) {
15245
+ writeJson2(response, 200, options.healthPayload ? options.healthPayload() : { ok: true });
15246
+ return;
15247
+ }
15248
+ if (method !== "GET" && method !== "HEAD") {
15249
+ writeJson2(response, 405, { error: `Unsupported static-server method: ${method}` });
15250
+ return;
15251
+ }
15252
+ const relativePath = pathname === "/" ? "/index.html" : pathname;
15253
+ const filePath = path6.resolve(rootDir, `.${relativePath}`);
15254
+ if (!isSafeResolvedPath(rootDir, filePath)) {
15255
+ writeJson2(response, 403, { error: "Forbidden path" });
15256
+ return;
15257
+ }
15258
+ const fileStats = await stat(filePath).catch(() => null);
15259
+ if (!fileStats?.isFile()) {
15260
+ writeJson2(response, 404, { error: `Static file not found: ${pathname}` });
15261
+ return;
15262
+ }
15263
+ const body = await readFile2(filePath);
15264
+ response.statusCode = 200;
15265
+ response.setHeader("Content-Type", contentTypeFor(filePath));
15266
+ response.end(method === "HEAD" ? void 0 : body);
15267
+ } catch (error) {
15268
+ writeJson2(response, 500, {
15269
+ error: error instanceof Error ? error.message : String(error)
15270
+ });
15271
+ }
15272
+ });
15273
+ const address = await new Promise((resolve, reject) => {
15274
+ server.once("error", reject);
15275
+ server.listen(options.port, options.host, () => {
15276
+ const bound = server.address();
15277
+ if (!bound || typeof bound === "string") {
15278
+ reject(new Error("Unable to resolve static server address."));
15279
+ return;
15280
+ }
15281
+ resolve({
15282
+ address: bound.address,
15283
+ port: bound.port
15284
+ });
15285
+ });
15286
+ });
15287
+ return {
15288
+ origin: `http://${address.address}:${address.port}`,
15289
+ port: address.port,
15290
+ close: async () => await new Promise((resolve, reject) => {
15291
+ server.close((error) => {
15292
+ if (error) {
15293
+ reject(error);
15294
+ return;
15295
+ }
15296
+ resolve();
15297
+ });
15298
+ })
15299
+ };
15300
+ }
15301
+
15183
15302
  // src/commands/payment.ts
15184
15303
  function parseMetadataEntries2(entries) {
15185
15304
  const metadata = {};
@@ -15566,15 +15685,435 @@ function paymentIntentLines(intent, inspectCommand, handoffCommand, partiesComma
15566
15685
  function buildAgentPayProductLayer(surface) {
15567
15686
  return {
15568
15687
  stage: "local-first-workbench",
15569
- publicShell: "submit -> next -> approval -> workspace -> handoff -> feed",
15688
+ publicShell: "submit -> payment next -> approval -> workspace -> handoff -> feed",
15570
15689
  productClaim: "compact ingress, wallet-aware follow-up, one cross-request workspace, and stable exports",
15571
15690
  surfaceRole: surface === "workspace" ? "cross-request-workbench" : surface === "handoff" ? "single-request-export" : "cross-request-export",
15572
15691
  platformDirection: "handoff and feed are already shaped for external dashboards, agents, or backend ingestion",
15573
15692
  boundary: "local-first only today; not a hosted multi-tenant control plane"
15574
15693
  };
15575
15694
  }
15695
+ function buildAgentPayIntegrationLayer() {
15696
+ return {
15697
+ stage: "operator-controlled-export",
15698
+ currentMode: "same-runtime, static export, or operator-controlled hosted preview",
15699
+ currentProof: "stable workspace/feed/handoff JSON can already be published and served as a static bundle for external dashboards, agents, or backends from the same runtime or one operator-controlled host",
15700
+ workbenchSurface: buildWorkspaceRecommendedCommand(),
15701
+ singleRequestSurface: buildHandoffRecommendedCommand("<request-id>"),
15702
+ batchSurface: buildFeedRecommendedCommand(),
15703
+ publishSurface: buildPaymentPublishRecommendedCommand(),
15704
+ serveSurface: buildPaymentServeRecommendedCommand(),
15705
+ nextHostedStep: "prove the served static workspace/feed/handoff bundle behind one externally reachable operator URL before adding multi-tenant persistence",
15706
+ boundary: "not yet a hosted multi-tenant control plane"
15707
+ };
15708
+ }
15709
+ function sanitizePublishSegment(value) {
15710
+ const normalized = value.trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
15711
+ return normalized || "all";
15712
+ }
15713
+ function defaultPaymentPublishDir(filters) {
15714
+ const generatedAt = (/* @__PURE__ */ new Date()).toISOString().replace(/[:]/g, "-");
15715
+ const walletSegment = sanitizePublishSegment(filters.walletName || "all-wallets");
15716
+ const statusSegment = sanitizePublishSegment(filters.status || "all-statuses");
15717
+ return path7.join(
15718
+ storageDir(),
15719
+ "exports",
15720
+ "agent-pay",
15721
+ `${generatedAt}-${walletSegment}-${statusSegment}`
15722
+ );
15723
+ }
15724
+ function resolvePaymentPublishDir(dir, filters) {
15725
+ const trimmed = dir?.trim();
15726
+ return trimmed ? path7.resolve(trimmed) : defaultPaymentPublishDir(filters);
15727
+ }
15728
+ function resolvePaymentPublishPublicBaseUrl(value) {
15729
+ return resolvePaymentAbsoluteHttpUrl(
15730
+ value,
15731
+ "--public-base-url",
15732
+ "PAYMENT_PUBLISH_PUBLIC_BASE_URL_INVALID"
15733
+ );
15734
+ }
15735
+ function resolvePaymentServePublicOrigin(value) {
15736
+ return resolvePaymentAbsoluteHttpUrl(
15737
+ value,
15738
+ "--public-origin",
15739
+ "PAYMENT_SERVE_PUBLIC_ORIGIN_INVALID"
15740
+ );
15741
+ }
15742
+ function resolvePaymentAbsoluteHttpUrl(value, optionLabel, errorCode) {
15743
+ const trimmed = value?.trim();
15744
+ if (!trimmed) return null;
15745
+ let parsed;
15746
+ try {
15747
+ parsed = new URL(trimmed);
15748
+ } catch {
15749
+ throw new AgentError(
15750
+ errorCode,
15751
+ `Invalid ${optionLabel} value: ${value}. Use an absolute http(s) URL.`
15752
+ );
15753
+ }
15754
+ if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
15755
+ throw new AgentError(
15756
+ errorCode,
15757
+ `Invalid ${optionLabel} value: ${value}. Use an absolute http(s) URL.`
15758
+ );
15759
+ }
15760
+ return parsed.href.replace(/\/+$/, "");
15761
+ }
15762
+ function paymentPublicOriginLooksLocal(origin) {
15763
+ try {
15764
+ const { hostname } = new URL(origin);
15765
+ return hostname === "localhost" || hostname === "127.0.0.1" || hostname === "0.0.0.0" || hostname === "::1" || hostname === "[::1]";
15766
+ } catch {
15767
+ return false;
15768
+ }
15769
+ }
15770
+ function resolvePaymentServePort(value) {
15771
+ const parsed = Number.parseInt(value?.trim() || "4495", 10);
15772
+ if (!Number.isInteger(parsed) || parsed < 0 || parsed > 65535) {
15773
+ throw new AgentError(
15774
+ "PAYMENT_SERVE_PORT_INVALID",
15775
+ `Invalid payment serve port: ${value}. Use an integer between 0 and 65535.`
15776
+ );
15777
+ }
15778
+ return parsed;
15779
+ }
15780
+ function buildPaymentPublishArtifactLink(relativePath, publicBaseUrl) {
15781
+ const normalizedPath = relativePath.replace(/\\/g, "/");
15782
+ return {
15783
+ path: normalizedPath,
15784
+ publicUrl: publicBaseUrl ? `${publicBaseUrl}/${normalizedPath}` : null
15785
+ };
15786
+ }
15787
+ async function writePublishJsonFile(filePath, payload) {
15788
+ await mkdir2(path7.dirname(filePath), { recursive: true, mode: 448 });
15789
+ await writeFile2(filePath, `${JSON.stringify(payload, null, 2)}
15790
+ `, { mode: 384 });
15791
+ }
15792
+ async function writePublishTextFile(filePath, content) {
15793
+ await mkdir2(path7.dirname(filePath), { recursive: true, mode: 448 });
15794
+ await writeFile2(filePath, content, { mode: 384 });
15795
+ }
15796
+ function resolvePaymentPublishSelection(options) {
15797
+ return {
15798
+ walletName: options.wallet,
15799
+ status: options.status ? resolvePaymentStatus(options.status) : void 0,
15800
+ queueLimit: resolvePositiveInteger(options.queueLimit, "--queue-limit"),
15801
+ walletLimit: resolvePositiveInteger(options.walletLimit, "--wallet-limit"),
15802
+ recentActivityLimit: resolvePositiveInteger(options.activityLimit, "--activity-limit"),
15803
+ feedLimit: resolvePositiveInteger(options.feedLimit, "--feed-limit")
15804
+ };
15805
+ }
15806
+ async function loadPaymentPublishData(input) {
15807
+ const workspaceResult = await buildStoredPaymentRequestsWorkspace({
15808
+ walletName: input.walletName,
15809
+ status: input.status,
15810
+ queueLimit: input.queueLimit,
15811
+ walletLimit: input.walletLimit,
15812
+ recentActivityLimit: input.recentActivityLimit,
15813
+ feedLimit: input.feedLimit
15814
+ });
15815
+ const requests = await listStoredPaymentRequests({
15816
+ walletName: input.walletName,
15817
+ status: input.status
15818
+ });
15819
+ const handoffResults = await Promise.all(
15820
+ requests.map((record) => getStoredPaymentRequestHandoff(record.requestId))
15821
+ );
15822
+ return {
15823
+ outputDir: resolvePaymentPublishDir(input.dir, workspaceResult.workspace.filters),
15824
+ workspace: workspaceResult.workspace,
15825
+ requests,
15826
+ handoffResults
15827
+ };
15828
+ }
15829
+ function buildPaymentPublishBundle(input) {
15830
+ const workspaceRelativePath = "workspace.json";
15831
+ const feedRelativePath = "feed.json";
15832
+ const manifestRelativePath = "manifest.json";
15833
+ const indexRelativePath = "index.html";
15834
+ const handoffsRelativeDir = "handoffs";
15835
+ const workspacePayload = buildPublishedWorkspacePayload(input.data.workspace);
15836
+ const feedPayload = buildPublishedFeedPayload(input.data.workspace.feed);
15837
+ const handoffPayloads = input.data.handoffResults.map((result) => {
15838
+ const relativePath = `${handoffsRelativeDir}/${result.paymentRequest.requestId}.json`;
15839
+ return {
15840
+ requestId: result.paymentRequest.requestId,
15841
+ status: result.paymentRequest.settlement.status,
15842
+ relativePath,
15843
+ payload: buildPublishedHandoffPayload(result)
15844
+ };
15845
+ });
15846
+ const manifest = {
15847
+ format: "zk-agent-payment-publish-manifest",
15848
+ version: 1,
15849
+ generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
15850
+ source: "local-first",
15851
+ mode: "operator-controlled-static-export",
15852
+ productLayer: buildAgentPayProductLayer("workspace"),
15853
+ integrationLayer: buildAgentPayIntegrationLayer(),
15854
+ filters: {
15855
+ walletName: input.data.workspace.filters.walletName,
15856
+ status: input.data.workspace.filters.status,
15857
+ recentActivityLimit: input.data.workspace.filters.recentActivityLimit,
15858
+ queueLimit: input.data.workspace.filters.queueLimit,
15859
+ walletLimit: input.data.workspace.filters.walletLimit,
15860
+ feedLimit: input.data.workspace.filters.feedLimit
15861
+ },
15862
+ summary: {
15863
+ totalRequests: input.data.requests.length,
15864
+ workspaceRequests: input.data.workspace.summary.totalRequests,
15865
+ feedItems: input.data.workspace.feed.items.length,
15866
+ queueItems: input.data.workspace.queue.items.length,
15867
+ recentActivityCount: input.data.workspace.summary.recentActivityCount,
15868
+ handoffCount: handoffPayloads.length
15869
+ },
15870
+ output: {
15871
+ directory: input.data.outputDir,
15872
+ publicBaseUrl: input.publicBaseUrl
15873
+ },
15874
+ entrypoints: {
15875
+ index: buildPaymentPublishArtifactLink(indexRelativePath, input.publicBaseUrl),
15876
+ manifest: buildPaymentPublishArtifactLink(manifestRelativePath, input.publicBaseUrl),
15877
+ workspace: buildPaymentPublishArtifactLink(workspaceRelativePath, input.publicBaseUrl),
15878
+ feed: buildPaymentPublishArtifactLink(feedRelativePath, input.publicBaseUrl),
15879
+ handoffs: buildPaymentPublishArtifactLink(`${handoffsRelativeDir}/`, input.publicBaseUrl)
15880
+ },
15881
+ handoffs: handoffPayloads.map((entry) => ({
15882
+ requestId: entry.requestId,
15883
+ status: entry.status,
15884
+ path: entry.relativePath,
15885
+ publicUrl: buildPaymentPublishArtifactLink(entry.relativePath, input.publicBaseUrl).publicUrl
15886
+ }))
15887
+ };
15888
+ return {
15889
+ outputDir: input.data.outputDir,
15890
+ publicBaseUrl: input.publicBaseUrl,
15891
+ workspacePayload,
15892
+ feedPayload,
15893
+ handoffPayloads,
15894
+ manifest
15895
+ };
15896
+ }
15897
+ async function writePaymentPublishBundle(bundle) {
15898
+ await mkdir2(bundle.outputDir, { recursive: true, mode: 448 });
15899
+ await rm2(path7.join(bundle.outputDir, "handoffs"), { recursive: true, force: true });
15900
+ await Promise.all([
15901
+ writePublishJsonFile(path7.join(bundle.outputDir, "workspace.json"), bundle.workspacePayload),
15902
+ writePublishJsonFile(path7.join(bundle.outputDir, "feed.json"), bundle.feedPayload),
15903
+ writePublishJsonFile(path7.join(bundle.outputDir, "manifest.json"), bundle.manifest),
15904
+ writePublishTextFile(
15905
+ path7.join(bundle.outputDir, "index.html"),
15906
+ buildPaymentPublishIndexHtml({
15907
+ manifest: bundle.manifest,
15908
+ workspaceLink: bundle.manifest.entrypoints.workspace,
15909
+ feedLink: bundle.manifest.entrypoints.feed
15910
+ })
15911
+ ),
15912
+ ...bundle.handoffPayloads.map(
15913
+ (entry) => writePublishJsonFile(path7.join(bundle.outputDir, entry.relativePath), entry.payload)
15914
+ )
15915
+ ]);
15916
+ }
15917
+ function buildPaymentPublishPayload(bundle) {
15918
+ return {
15919
+ productLayer: bundle.manifest.productLayer,
15920
+ integrationLayer: bundle.manifest.integrationLayer,
15921
+ publish: {
15922
+ format: "zk-agent-payment-publish",
15923
+ version: 1,
15924
+ generatedAt: bundle.manifest.generatedAt,
15925
+ source: bundle.manifest.source,
15926
+ mode: bundle.manifest.mode,
15927
+ outputDir: bundle.outputDir,
15928
+ publicBaseUrl: bundle.publicBaseUrl,
15929
+ filters: bundle.manifest.filters,
15930
+ summary: bundle.manifest.summary,
15931
+ entrypoints: bundle.manifest.entrypoints
15932
+ },
15933
+ manifest: bundle.manifest
15934
+ };
15935
+ }
15936
+ function buildPaymentServeRecommendedCommands(options) {
15937
+ return {
15938
+ serve: buildPaymentServeRecommendedCommand(),
15939
+ publish: buildPaymentPublishRecommendedCommand(),
15940
+ workspace: buildPaymentWorkspaceRecommendedCommand(),
15941
+ handoff: buildPaymentHandoffRecommendedCommand("<request-id>"),
15942
+ feed: buildPaymentFeedRecommendedCommand(),
15943
+ ...options.publicOriginLooksLocal ? {
15944
+ restartWithPublicOrigin: "zk-agent payment serve --public-origin https://pay.example.com"
15945
+ } : {}
15946
+ };
15947
+ }
15948
+ function buildPaymentServeNotes(options) {
15949
+ if (!options.publicOriginLooksLocal) {
15950
+ return [];
15951
+ }
15952
+ return [
15953
+ options.publicOrigin.startsWith("http://127.0.0.1") || options.publicOrigin.startsWith("http://localhost") ? "Static bundle is still advertising a local bind origin. Set --public-origin to the externally reachable URL before using this as an externally hosted Agent Pay preview." : "Static bundle is still advertising a local-only public origin. Set --public-origin to the externally reachable URL before using this as an externally hosted Agent Pay preview."
15954
+ ];
15955
+ }
15956
+ function buildPaymentPublishIndexHtml(input) {
15957
+ const handoffItems = input.manifest.handoffs.length === 0 ? "<li>No handoff files were published for the current filter.</li>" : input.manifest.handoffs.slice(0, 20).map(
15958
+ (entry) => `<li><a href="./${entry.path}">${entry.requestId}</a> <span>${entry.status}</span></li>`
15959
+ ).join("\n");
15960
+ const publicBaseUrl = input.manifest.output.publicBaseUrl ? `<p><strong>Public base URL:</strong> <code>${input.manifest.output.publicBaseUrl}</code></p>` : "";
15961
+ return `<!doctype html>
15962
+ <html lang="en">
15963
+ <head>
15964
+ <meta charset="utf-8" />
15965
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
15966
+ <title>zk-agent Agent Pay Publish Bundle</title>
15967
+ <style>
15968
+ :root {
15969
+ color-scheme: light;
15970
+ --bg: #f6f1e8;
15971
+ --panel: #fffaf2;
15972
+ --text: #1f2a22;
15973
+ --muted: #5e675f;
15974
+ --line: #d6c9b4;
15975
+ --accent: #0d7a52;
15976
+ }
15977
+ body {
15978
+ margin: 0;
15979
+ font-family: "Iowan Old Style", "Palatino Linotype", "Book Antiqua", serif;
15980
+ background:
15981
+ radial-gradient(circle at top right, rgba(13, 122, 82, 0.08), transparent 28rem),
15982
+ linear-gradient(180deg, #fcf8f1 0%, var(--bg) 100%);
15983
+ color: var(--text);
15984
+ }
15985
+ main {
15986
+ max-width: 960px;
15987
+ margin: 0 auto;
15988
+ padding: 48px 20px 72px;
15989
+ }
15990
+ section {
15991
+ background: rgba(255, 250, 242, 0.92);
15992
+ border: 1px solid var(--line);
15993
+ border-radius: 20px;
15994
+ padding: 24px;
15995
+ margin-top: 20px;
15996
+ box-shadow: 0 18px 40px rgba(52, 45, 29, 0.08);
15997
+ }
15998
+ h1, h2 {
15999
+ margin: 0 0 12px;
16000
+ font-weight: 600;
16001
+ }
16002
+ p, li {
16003
+ line-height: 1.5;
16004
+ }
16005
+ ul {
16006
+ padding-left: 20px;
16007
+ }
16008
+ a {
16009
+ color: var(--accent);
16010
+ }
16011
+ code {
16012
+ background: rgba(31, 42, 34, 0.06);
16013
+ padding: 0.1rem 0.35rem;
16014
+ border-radius: 0.35rem;
16015
+ }
16016
+ .meta {
16017
+ color: var(--muted);
16018
+ }
16019
+ .grid {
16020
+ display: grid;
16021
+ gap: 12px;
16022
+ grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
16023
+ }
16024
+ .card {
16025
+ border: 1px solid var(--line);
16026
+ border-radius: 14px;
16027
+ padding: 14px 16px;
16028
+ background: rgba(255, 255, 255, 0.72);
16029
+ }
16030
+ </style>
16031
+ </head>
16032
+ <body>
16033
+ <main>
16034
+ <section>
16035
+ <p class="meta">zk-agent Agent Pay static export</p>
16036
+ <h1>Operator-controlled publish bundle</h1>
16037
+ <p>This directory is the current static export proof for Agent Pay. It snapshots the stable <code>workspace</code>, <code>feed</code>, and per-request <code>handoff</code> contracts without claiming a hosted multi-tenant control plane.</p>
16038
+ <p class="meta">Generated at ${input.manifest.generatedAt}</p>
16039
+ ${publicBaseUrl}
16040
+ </section>
16041
+ <section>
16042
+ <h2>Bundle summary</h2>
16043
+ <div class="grid">
16044
+ <div class="card"><strong>${input.manifest.summary.totalRequests}</strong><br />requests</div>
16045
+ <div class="card"><strong>${input.manifest.summary.feedItems}</strong><br />feed items</div>
16046
+ <div class="card"><strong>${input.manifest.summary.queueItems}</strong><br />queue items</div>
16047
+ <div class="card"><strong>${input.manifest.summary.handoffCount}</strong><br />handoff files</div>
16048
+ </div>
16049
+ </section>
16050
+ <section>
16051
+ <h2>Entry points</h2>
16052
+ <ul>
16053
+ <li><a href="./manifest.json">manifest.json</a></li>
16054
+ <li><a href="./${input.workspaceLink.path}">${input.workspaceLink.path}</a></li>
16055
+ <li><a href="./${input.feedLink.path}">${input.feedLink.path}</a></li>
16056
+ </ul>
16057
+ </section>
16058
+ <section>
16059
+ <h2>Published handoffs</h2>
16060
+ <ul>
16061
+ ${handoffItems}
16062
+ </ul>
16063
+ </section>
16064
+ </main>
16065
+ </body>
16066
+ </html>
16067
+ `;
16068
+ }
16069
+ function paymentPublishLines(input) {
16070
+ return [
16071
+ ["mode", input.manifest.mode],
16072
+ ["output dir", input.outputDir],
16073
+ ["requests", String(input.manifest.summary.totalRequests)],
16074
+ ["feed items", String(input.manifest.summary.feedItems)],
16075
+ ["handoffs", String(input.manifest.summary.handoffCount)],
16076
+ ["workspace", input.manifest.entrypoints.workspace.path],
16077
+ ["feed", input.manifest.entrypoints.feed.path],
16078
+ ["manifest", input.manifest.entrypoints.manifest.path],
16079
+ ["index", input.manifest.entrypoints.index.path],
16080
+ ["publish", buildPaymentPublishRecommendedCommand()],
16081
+ ["serve", buildPaymentServeRecommendedCommand()],
16082
+ ["workspace command", buildPaymentWorkspaceRecommendedCommand()],
16083
+ ["feed command", buildPaymentFeedRecommendedCommand()]
16084
+ ];
16085
+ }
16086
+ function paymentServeLines(input) {
16087
+ return [
16088
+ ["status", "payment-serving"],
16089
+ ["origin", input.origin],
16090
+ ["public origin", input.publicOrigin],
16091
+ ["public origin source", input.publicOriginSource],
16092
+ ["output dir", input.bundle.outputDir],
16093
+ [
16094
+ "workspace",
16095
+ input.bundle.manifest.entrypoints.workspace.publicUrl || input.bundle.manifest.entrypoints.workspace.path
16096
+ ],
16097
+ [
16098
+ "feed",
16099
+ input.bundle.manifest.entrypoints.feed.publicUrl || input.bundle.manifest.entrypoints.feed.path
16100
+ ],
16101
+ [
16102
+ "manifest",
16103
+ input.bundle.manifest.entrypoints.manifest.publicUrl || input.bundle.manifest.entrypoints.manifest.path
16104
+ ],
16105
+ [
16106
+ "index",
16107
+ input.bundle.manifest.entrypoints.index.publicUrl || input.bundle.manifest.entrypoints.index.path
16108
+ ],
16109
+ ["health", `${input.origin}/health`],
16110
+ ["publish", buildPaymentPublishRecommendedCommand()],
16111
+ ["serve", buildPaymentServeRecommendedCommand()]
16112
+ ];
16113
+ }
15576
16114
  function paymentHandoffLines(handoff, inspectCommand, partiesCommand, shareCommand, settlementCommand) {
15577
16115
  const productLayer = buildAgentPayProductLayer("handoff");
16116
+ const integrationLayer = buildAgentPayIntegrationLayer();
15578
16117
  const lines = [
15579
16118
  ["request", handoff.requestId],
15580
16119
  ["product stage", productLayer.stage],
@@ -15582,6 +16121,15 @@ function paymentHandoffLines(handoff, inspectCommand, partiesCommand, shareComma
15582
16121
  ["surface role", productLayer.surfaceRole],
15583
16122
  ["platform direction", productLayer.platformDirection],
15584
16123
  ["boundary", productLayer.boundary],
16124
+ ["integration stage", integrationLayer.stage],
16125
+ ["integration mode", integrationLayer.currentMode],
16126
+ ["integration proof", integrationLayer.currentProof],
16127
+ [
16128
+ "integration surfaces",
16129
+ `${integrationLayer.workbenchSurface} -> ${integrationLayer.singleRequestSurface} -> ${integrationLayer.batchSurface}`
16130
+ ],
16131
+ ["hosted direction", integrationLayer.nextHostedStep],
16132
+ ["integration boundary", integrationLayer.boundary],
15585
16133
  ["source", handoff.source],
15586
16134
  ["chain", `${handoff.chain} (${handoff.chainId})`],
15587
16135
  ["status", handoff.summary.settlementStatus],
@@ -15840,6 +16388,7 @@ function paymentIngressLines(input) {
15840
16388
  function paymentWorkspaceLines(workspace, workspaceCommand = buildDefaultPaymentWorkspaceCommand(), submitCommand = buildDefaultPaymentSubmitCommand(), approvalCommand = buildPaymentApprovalRecommendedCommand("<request-id>"), handoffCommand = buildPaymentHandoffRecommendedCommand("<request-id>"), feedCommand = buildPaymentFeedRecommendedCommand()) {
15841
16389
  const walletName = workspace.filters.walletName || "main";
15842
16390
  const productLayer = buildAgentPayProductLayer("workspace");
16391
+ const integrationLayer = buildAgentPayIntegrationLayer();
15843
16392
  const lines = [
15844
16393
  ["surface", "cross-request Agent Pay workspace"],
15845
16394
  [
@@ -15852,6 +16401,15 @@ function paymentWorkspaceLines(workspace, workspaceCommand = buildDefaultPayment
15852
16401
  ["public shell", productLayer.publicShell],
15853
16402
  ["platform direction", productLayer.platformDirection],
15854
16403
  ["boundary", productLayer.boundary],
16404
+ ["integration stage", integrationLayer.stage],
16405
+ ["integration mode", integrationLayer.currentMode],
16406
+ ["integration proof", integrationLayer.currentProof],
16407
+ [
16408
+ "integration surfaces",
16409
+ `${integrationLayer.workbenchSurface} -> ${integrationLayer.singleRequestSurface} -> ${integrationLayer.batchSurface}`
16410
+ ],
16411
+ ["hosted direction", integrationLayer.nextHostedStep],
16412
+ ["integration boundary", integrationLayer.boundary],
15855
16413
  ["generated", workspace.generatedAt],
15856
16414
  ["source", workspace.source],
15857
16415
  ["submit", submitCommand || buildPaymentSubmitRecommendedCommand(walletName)],
@@ -15916,6 +16474,72 @@ function buildDefaultPaymentWorkspaceCommand() {
15916
16474
  function buildDefaultPaymentSubmitCommand() {
15917
16475
  return buildPaymentSubmitRecommendedCommand();
15918
16476
  }
16477
+ function buildPublishedWorkspacePayload(workspace) {
16478
+ const walletName = workspace.filters.walletName || "main";
16479
+ return {
16480
+ ok: true,
16481
+ productLayer: buildAgentPayProductLayer("workspace"),
16482
+ integrationLayer: buildAgentPayIntegrationLayer(),
16483
+ workspace: {
16484
+ ...workspace,
16485
+ queue: {
16486
+ ...workspace.queue,
16487
+ items: workspace.queue.items.map((item) => ({
16488
+ descriptor: item.descriptor,
16489
+ executionPlan: buildPaymentExecutionPlanJson(item.executionPlan),
16490
+ next: item.next
16491
+ }))
16492
+ }
16493
+ },
16494
+ recommendedCommands: {
16495
+ workspace: buildPaymentWorkspaceRecommendedCommand(),
16496
+ approval: buildPaymentApprovalRecommendedCommand("<request-id>"),
16497
+ handoff: buildPaymentHandoffRecommendedCommand("<request-id>"),
16498
+ feed: buildPaymentFeedRecommendedCommand(),
16499
+ dashboard: buildPaymentDashboardRecommendedCommand(),
16500
+ queue: buildPaymentQueueRecommendedCommand(),
16501
+ report: buildPaymentReportRecommendedCommand(),
16502
+ submit: buildPaymentSubmitRecommendedCommand(walletName),
16503
+ next: buildPaymentNextRecommendedCommand("<request-id>"),
16504
+ publish: buildPaymentPublishRecommendedCommand(),
16505
+ serve: buildPaymentServeRecommendedCommand()
16506
+ }
16507
+ };
16508
+ }
16509
+ function buildPublishedFeedPayload(feed) {
16510
+ const walletName = feed.filters.walletName || "main";
16511
+ return {
16512
+ ok: true,
16513
+ productLayer: buildAgentPayProductLayer("feed"),
16514
+ integrationLayer: buildAgentPayIntegrationLayer(),
16515
+ feed,
16516
+ recommendedCommands: {
16517
+ workspace: buildPaymentWorkspaceRecommendedCommand(),
16518
+ handoff: buildPaymentHandoffRecommendedCommand("<request-id>"),
16519
+ feed: buildPaymentFeedRecommendedCommand(),
16520
+ dashboard: buildPaymentDashboardRecommendedCommand(),
16521
+ queue: buildPaymentQueueRecommendedCommand(),
16522
+ report: buildPaymentReportRecommendedCommand(),
16523
+ submit: buildPaymentSubmitRecommendedCommand(walletName),
16524
+ publish: buildPaymentPublishRecommendedCommand(),
16525
+ serve: buildPaymentServeRecommendedCommand()
16526
+ }
16527
+ };
16528
+ }
16529
+ function buildPublishedHandoffPayload(input) {
16530
+ return {
16531
+ ok: true,
16532
+ requestId: input.paymentRequest.requestId,
16533
+ productLayer: buildAgentPayProductLayer("handoff"),
16534
+ integrationLayer: buildAgentPayIntegrationLayer(),
16535
+ handoff: input.handoff,
16536
+ recommendedCommands: {
16537
+ ...buildPaymentRecommendedCommands(input.paymentRequest, input.executionPlan),
16538
+ publish: buildPaymentPublishRecommendedCommand(),
16539
+ serve: buildPaymentServeRecommendedCommand()
16540
+ }
16541
+ };
16542
+ }
15919
16543
  function buildWorkspaceSurfaceHelpText(options) {
15920
16544
  if (options.topLevel) {
15921
16545
  return [
@@ -15923,6 +16547,10 @@ function buildWorkspaceSurfaceHelpText(options) {
15923
16547
  " Public workspace shortcut:",
15924
16548
  " Use this when you already know the current question is the cross-request Agent Pay workbench.",
15925
16549
  " This is the top-level shortcut for `zk-agent payment workspace`.",
16550
+ " Today this same workspace -> handoff -> feed chain already gives one operator-controlled external export path.",
16551
+ " `zk-agent payment publish` now materializes that same workspace/feed/handoff bundle as a hostable static export.",
16552
+ " `zk-agent payment serve` now turns that same bundle into the current operator-controlled hosted preview.",
16553
+ " The next hosted step is to keep that served bundle stable behind one externally reachable operator URL without claiming a multi-tenant control plane yet.",
15926
16554
  " Stay on `suite` when the question is broader than the Agent Pay workbench.",
15927
16555
  " Stay on `payment next`, `approval`, or `handoff` when the question is still one request lifecycle.",
15928
16556
  "",
@@ -15940,7 +16568,11 @@ function buildWorkspaceSurfaceHelpText(options) {
15940
16568
  " Product workspace surface:",
15941
16569
  " Use this when you need one cross-request Agent Pay workspace instead of stitching dashboard, queue, report, and feed together manually.",
15942
16570
  " Public shortcut: zk-agent workspace.",
15943
- " Shortest route into workspace: submit -> next -> approval -> workspace.",
16571
+ " Shortest route into workspace: submit -> payment next -> approval -> workspace.",
16572
+ " Today this same workspace -> handoff -> feed chain already gives one operator-controlled external export path.",
16573
+ " `zk-agent payment publish` now materializes that same workspace/feed/handoff bundle as a hostable static export.",
16574
+ " `zk-agent payment serve` now turns that same bundle into the current operator-controlled hosted preview.",
16575
+ " The next hosted step is to keep that served bundle stable behind one externally reachable operator URL without claiming a multi-tenant control plane yet.",
15944
16576
  " Stay on `dashboard`, `queue`, `report`, or `feed` only when the workspace question has already narrowed to one slice.",
15945
16577
  " Stay on `payment next`, `payment approval`, or `payment handoff` when the question is still one request lifecycle.",
15946
16578
  "",
@@ -15999,6 +16631,7 @@ function addWorkspaceSurfaceCommand(command, options) {
15999
16631
  {
16000
16632
  ok: true,
16001
16633
  productLayer: buildAgentPayProductLayer("workspace"),
16634
+ integrationLayer: buildAgentPayIntegrationLayer(),
16002
16635
  workspace: {
16003
16636
  ...result.workspace,
16004
16637
  queue: {
@@ -16212,6 +16845,7 @@ function paymentDashboardLines(dashboard) {
16212
16845
  }
16213
16846
  function paymentFeedLines(feed, options = {}) {
16214
16847
  const productLayer = buildAgentPayProductLayer("feed");
16848
+ const integrationLayer = buildAgentPayIntegrationLayer();
16215
16849
  const workspaceCommand = options.workspaceCommand ?? buildPaymentWorkspaceRecommendedCommand();
16216
16850
  const feedCommand = options.feedCommand ?? buildPaymentFeedRecommendedCommand();
16217
16851
  const lines = [
@@ -16220,6 +16854,15 @@ function paymentFeedLines(feed, options = {}) {
16220
16854
  ["surface role", productLayer.surfaceRole],
16221
16855
  ["platform direction", productLayer.platformDirection],
16222
16856
  ["boundary", productLayer.boundary],
16857
+ ["integration stage", integrationLayer.stage],
16858
+ ["integration mode", integrationLayer.currentMode],
16859
+ ["integration proof", integrationLayer.currentProof],
16860
+ [
16861
+ "integration surfaces",
16862
+ `${integrationLayer.workbenchSurface} -> ${integrationLayer.singleRequestSurface} -> ${integrationLayer.batchSurface}`
16863
+ ],
16864
+ ["hosted direction", integrationLayer.nextHostedStep],
16865
+ ["integration boundary", integrationLayer.boundary],
16223
16866
  ["generated", feed.generatedAt],
16224
16867
  ["source", feed.source],
16225
16868
  ["requests", String(feed.summary.totalRequests)],
@@ -16263,6 +16906,10 @@ function buildFeedSurfaceHelpText(options) {
16263
16906
  " Public feed shortcut:",
16264
16907
  " Use this when the current question is already the integration-ready cross-request Agent Pay export.",
16265
16908
  " This is the top-level shortcut for `zk-agent payment feed`.",
16909
+ " This already works as the current operator-controlled external export proof on the same runtime or host.",
16910
+ " `zk-agent payment publish` now snapshots the same feed/handoff bundle as a hostable static export.",
16911
+ " `zk-agent payment serve` now turns that same bundle into the current operator-controlled hosted preview.",
16912
+ " The next hosted step is to keep that served bundle stable behind one externally reachable operator URL before claiming a control plane.",
16266
16913
  " Stay on `workspace` when you still need the broader cross-request Agent Pay workbench.",
16267
16914
  " Stay on `handoff` when the current question is still one single-request export.",
16268
16915
  "",
@@ -16281,6 +16928,10 @@ function buildFeedSurfaceHelpText(options) {
16281
16928
  " Integration-ready feed surface:",
16282
16929
  " Use this when you need the stable cross-request Agent Pay batch export for dashboards, agents, or backend ingestion.",
16283
16930
  " Public shortcut: zk-agent feed.",
16931
+ " This already works as the current operator-controlled external export proof on the same runtime or host.",
16932
+ " `zk-agent payment publish` now snapshots the same feed/handoff bundle as a hostable static export.",
16933
+ " `zk-agent payment serve` now turns that same bundle into the current operator-controlled hosted preview.",
16934
+ " The next hosted step is to keep that served bundle stable behind one externally reachable operator URL before claiming a control plane.",
16284
16935
  " Stay on `payment workspace` when you still need the broader cross-request workbench first.",
16285
16936
  " Stay on `payment handoff` when the current question is still one single-request export.",
16286
16937
  "",
@@ -16324,6 +16975,7 @@ function addFeedSurfaceCommand(command, options) {
16324
16975
  {
16325
16976
  ok: true,
16326
16977
  productLayer: buildAgentPayProductLayer("feed"),
16978
+ integrationLayer: buildAgentPayIntegrationLayer(),
16327
16979
  feed: result.feed,
16328
16980
  recommendedCommands: {
16329
16981
  workspace: workspaceCommand,
@@ -16367,6 +17019,10 @@ function buildHandoffSurfaceHelpText(options) {
16367
17019
  " Public handoff shortcut:",
16368
17020
  " Use this when the current question is already the stable single-request Agent Pay export.",
16369
17021
  " This is the top-level shortcut for `zk-agent payment handoff`.",
17022
+ " This is already the single-request export proof for the current operator-controlled hosted direction.",
17023
+ " `zk-agent payment publish` now snapshots this handoff alongside workspace/feed as a hostable static export bundle.",
17024
+ " `zk-agent payment serve` now turns that same bundle into the current operator-controlled hosted preview.",
17025
+ " The next hosted step is to keep that served bundle stable behind one externally reachable operator URL before claiming a control plane.",
16370
17026
  " Stay on `workspace` when you still need the broader cross-request Agent Pay workbench.",
16371
17027
  " Stay on `feed` when the current question has already widened to the cross-request batch export.",
16372
17028
  "",
@@ -16385,6 +17041,10 @@ function buildHandoffSurfaceHelpText(options) {
16385
17041
  " Integration-ready handoff surface:",
16386
17042
  " Use this when you need one stable local-first Agent Pay export bundle for an external dashboard, agent, or backend.",
16387
17043
  " Public shortcut: zk-agent handoff.",
17044
+ " This is already the single-request export proof for the current operator-controlled hosted direction.",
17045
+ " `zk-agent payment publish` now snapshots this handoff alongside workspace/feed as a hostable static export bundle.",
17046
+ " `zk-agent payment serve` now turns that same bundle into the current operator-controlled hosted preview.",
17047
+ " The next hosted step is to keep that served bundle stable behind one externally reachable operator URL before claiming a control plane.",
16388
17048
  " Stay on `payment inspect` when you still need the broader single-request aggregate view.",
16389
17049
  " Stay on `payment share` or `payment parties` when the question has already narrowed to one projection.",
16390
17050
  "",
@@ -16412,6 +17072,7 @@ async function executePaymentHandoffSurface(requestId, topLevel) {
16412
17072
  ok: true,
16413
17073
  requestId: result.paymentRequest.requestId,
16414
17074
  productLayer: buildAgentPayProductLayer("handoff"),
17075
+ integrationLayer: buildAgentPayIntegrationLayer(),
16415
17076
  handoff: result.handoff,
16416
17077
  recommendedCommands: buildPaymentRecommendedCommands(
16417
17078
  result.paymentRequest,
@@ -16720,7 +17381,10 @@ function createPaymentCommand() {
16720
17381
  " `workspace`: review the cross-request operator view.",
16721
17382
  " `handoff`: export one stable single-request integration bundle.",
16722
17383
  " `feed`: export the stable cross-request batch view.",
16723
- " If you only remember one route: submit -> next -> approval -> workspace -> handoff -> feed.",
17384
+ " `publish`: materialize the same stable workspace/feed/handoff bundle as a hostable static export.",
17385
+ " `serve`: host that same bundle from one operator-controlled endpoint.",
17386
+ " If you only remember one route: submit -> payment next -> approval -> workspace -> handoff -> feed.",
17387
+ " Current public hosted proof: publish -> serve the same workspace/feed/handoff bundle behind one operator-controlled URL.",
16724
17388
  "",
16725
17389
  " Payment request surface:",
16726
17390
  " Use this layer when execution is not the whole story and you need request capture, follow-up, sharing, reporting, or approval repair around the write path.",
@@ -16745,13 +17409,21 @@ function createPaymentCommand() {
16745
17409
  " zk-agent workspace",
16746
17410
  " zk-agent handoff --request-id <id>",
16747
17411
  " zk-agent feed",
17412
+ " zk-agent payment publish --public-base-url <https-url>",
17413
+ " zk-agent payment serve --public-origin <https-url>",
16748
17414
  " This proves compact ingress -> wallet-aware follow-up -> approval readiness -> cross-request workspace -> integration-ready export.",
17415
+ " `payment publish` turns those same exports into one static bundle that can be hosted by the operator.",
17416
+ " `payment serve` turns that same bundle into the current operator-controlled hosted preview.",
17417
+ " Together, publish -> serve is the current public Agent Pay proof on the hosted-preview boundary.",
17418
+ " The next hosted step is to keep that served bundle stable behind one externally reachable operator URL before claiming a multi-tenant control plane.",
16749
17419
  "",
16750
17420
  " Public start here:",
16751
17421
  " zk-agent submit --wallet main --to <address> --amount <amount>",
16752
17422
  " zk-agent workspace",
16753
17423
  " zk-agent handoff --request-id <id>",
16754
17424
  " zk-agent feed",
17425
+ " zk-agent payment publish --public-base-url <https-url>",
17426
+ " zk-agent payment serve --public-origin <https-url>",
16755
17427
  " zk-agent approval --request-id <id>",
16756
17428
  " zk-agent payment next --request-id <id>",
16757
17429
  "",
@@ -16759,6 +17431,8 @@ function createPaymentCommand() {
16759
17431
  " zk-agent payment dashboard",
16760
17432
  " zk-agent payment queue",
16761
17433
  " zk-agent payment report",
17434
+ " zk-agent payment publish",
17435
+ " zk-agent payment serve",
16762
17436
  " zk-agent payment sync-approval --request-id <id>",
16763
17437
  " zk-agent payment inspect --request-id <id>",
16764
17438
  " zk-agent payment parties --request-id <id>",
@@ -16770,6 +17444,8 @@ function createPaymentCommand() {
16770
17444
  " `dashboard`: what is the current dashboard summary across requests?",
16771
17445
  " `handoff`: what is the stable single-request integration bundle?",
16772
17446
  " `feed`: what is the stable cross-request integration feed?",
17447
+ " `publish`: what is the hostable static export bundle for the current Agent Pay surface?",
17448
+ " `serve`: what is the operator-controlled hosted preview for the current Agent Pay surface?",
16773
17449
  " `suite`: I still need the packaged catalog across requests, discovery, funding, paymaster, and remote recovery.",
16774
17450
  "",
16775
17451
  " Deeper per-request reads and writes:",
@@ -16800,6 +17476,8 @@ function createPaymentCommand() {
16800
17476
  " zk-agent feed",
16801
17477
  " zk-agent payment queue",
16802
17478
  " zk-agent payment report",
17479
+ " zk-agent payment publish",
17480
+ " zk-agent payment serve",
16803
17481
  " zk-agent approval --request-id <id>",
16804
17482
  " zk-agent payment sync-approval --request-id <id>",
16805
17483
  " zk-agent payment list",
@@ -16939,6 +17617,157 @@ function createPaymentCommand() {
16939
17617
  }
16940
17618
  )
16941
17619
  );
17620
+ payment.command("publish").description(
17621
+ "Materialize the current Agent Pay workspace/feed/handoff bundle as a hostable static export"
17622
+ ).option("--wallet <name>", "Optional payer wallet filter").option(
17623
+ "--status <status>",
17624
+ "Optional status filter: draft, approval_pending, ready, paid, failed, expired, or cancelled"
17625
+ ).option("--queue-limit <count>", "Optional maximum number of queue items to include in workspace.json").option("--wallet-limit <count>", "Optional maximum number of wallet summaries in workspace.json").option("--activity-limit <count>", "Optional recent-activity limit in workspace.json").option("--feed-limit <count>", "Optional maximum number of feed items in workspace.json and feed.json").option("--dir <path>", "Optional explicit output directory for the static export bundle").option(
17626
+ "--public-base-url <url>",
17627
+ "Optional absolute public base URL used to precompute public artifact URLs in the manifest"
17628
+ ).addHelpText(
17629
+ "after",
17630
+ [
17631
+ "",
17632
+ " Hosted static export surface:",
17633
+ " Use this when the current Agent Pay question is no longer just local inspection and you need one hostable static bundle.",
17634
+ " This command writes `index.html`, `manifest.json`, `workspace.json`, `feed.json`, and one `handoffs/<request-id>.json` file per matching request.",
17635
+ " This is the static half of the current public Agent Pay proof.",
17636
+ " It does not start a service or claim a hosted multi-tenant control plane.",
17637
+ " Pass `--public-base-url` when you already know where the bundle will be hosted and you want absolute artifact URLs in the manifest.",
17638
+ "",
17639
+ " Common commands:",
17640
+ ` ${buildPaymentPublishRecommendedCommand()}`,
17641
+ " zk-agent payment publish --wallet main --public-base-url <https-url>",
17642
+ " zk-agent payment workspace",
17643
+ " zk-agent payment handoff --request-id <id>",
17644
+ " zk-agent payment feed"
17645
+ ].join("\n")
17646
+ ).action(async (options) => {
17647
+ const selection = resolvePaymentPublishSelection(options);
17648
+ const publicBaseUrl = resolvePaymentPublishPublicBaseUrl(options.publicBaseUrl);
17649
+ const data = await loadPaymentPublishData({
17650
+ ...selection,
17651
+ dir: options.dir
17652
+ });
17653
+ const bundle = buildPaymentPublishBundle({
17654
+ data,
17655
+ publicBaseUrl
17656
+ });
17657
+ await writePaymentPublishBundle(bundle);
17658
+ printResult(paymentPublishLines({ manifest: bundle.manifest, outputDir: bundle.outputDir }), {
17659
+ ok: true,
17660
+ ...buildPaymentPublishPayload(bundle),
17661
+ recommendedCommands: {
17662
+ publish: buildPaymentPublishRecommendedCommand(),
17663
+ serve: buildPaymentServeRecommendedCommand(),
17664
+ workspace: buildPaymentWorkspaceRecommendedCommand(),
17665
+ handoff: buildPaymentHandoffRecommendedCommand("<request-id>"),
17666
+ feed: buildPaymentFeedRecommendedCommand()
17667
+ }
17668
+ });
17669
+ });
17670
+ payment.command("serve").description(
17671
+ "Serve the current Agent Pay workspace/feed/handoff bundle from one operator-controlled static endpoint"
17672
+ ).option("--wallet <name>", "Optional payer wallet filter").option(
17673
+ "--status <status>",
17674
+ "Optional status filter: draft, approval_pending, ready, paid, failed, expired, or cancelled"
17675
+ ).option("--queue-limit <count>", "Optional maximum number of queue items to include in workspace.json").option("--wallet-limit <count>", "Optional maximum number of wallet summaries in workspace.json").option("--activity-limit <count>", "Optional recent-activity limit in workspace.json").option("--feed-limit <count>", "Optional maximum number of feed items in workspace.json and feed.json").option("--dir <path>", "Optional explicit output directory for the static export bundle").option("--host <host>", "Host to bind", "127.0.0.1").option("--port <port>", "Port to bind (0 = choose a free port)", "4495").option(
17676
+ "--public-origin <url>",
17677
+ "Optional absolute public origin to advertise when this static bundle is behind a tunnel or reverse proxy"
17678
+ ).addHelpText(
17679
+ "after",
17680
+ [
17681
+ "",
17682
+ " Hosted preview surface:",
17683
+ " Use this when the static Agent Pay bundle is no longer enough on disk and you need one operator-controlled hosted endpoint.",
17684
+ " This command regenerates the same `index.html`, `manifest.json`, `workspace.json`, `feed.json`, and `handoffs/<request-id>.json` bundle before serving it.",
17685
+ " This is the hosted half of the current public Agent Pay proof.",
17686
+ " Pass `--public-origin` when the bind origin is not the externally reachable URL.",
17687
+ "",
17688
+ " Common commands:",
17689
+ ` ${buildPaymentServeRecommendedCommand()}`,
17690
+ " zk-agent payment serve --public-origin <https-url>",
17691
+ " zk-agent payment publish --public-base-url <https-url>",
17692
+ " zk-agent workspace",
17693
+ " zk-agent feed"
17694
+ ].join("\n")
17695
+ ).action(async (options) => {
17696
+ const selection = resolvePaymentPublishSelection(options);
17697
+ const host = options.host?.trim() || "127.0.0.1";
17698
+ const port = resolvePaymentServePort(options.port);
17699
+ const data = await loadPaymentPublishData({
17700
+ ...selection,
17701
+ dir: options.dir
17702
+ });
17703
+ let origin = "";
17704
+ let publicOrigin = "";
17705
+ const server = await startStaticServer({
17706
+ rootDir: data.outputDir,
17707
+ host,
17708
+ port,
17709
+ healthPayload: () => ({
17710
+ ok: true,
17711
+ service: "zk-agent-payment-static",
17712
+ mode: "operator-controlled-static-export",
17713
+ origin,
17714
+ publicOrigin,
17715
+ outputDir: data.outputDir
17716
+ })
17717
+ });
17718
+ origin = server.origin;
17719
+ publicOrigin = resolvePaymentServePublicOrigin(options.publicOrigin) || server.origin;
17720
+ const publicOriginSource = options.publicOrigin?.trim() ? "configured" : "bind-origin-default";
17721
+ const publicOriginLooksLocal = paymentPublicOriginLooksLocal(publicOrigin);
17722
+ const bundle = buildPaymentPublishBundle({
17723
+ data,
17724
+ publicBaseUrl: publicOrigin
17725
+ });
17726
+ await writePaymentPublishBundle(bundle);
17727
+ const recommendedCommands = buildPaymentServeRecommendedCommands({
17728
+ publicOriginLooksLocal
17729
+ });
17730
+ const notes = buildPaymentServeNotes({
17731
+ publicOrigin,
17732
+ publicOriginLooksLocal
17733
+ });
17734
+ printResult(
17735
+ paymentServeLines({
17736
+ origin,
17737
+ publicOrigin,
17738
+ publicOriginSource,
17739
+ bundle
17740
+ }),
17741
+ {
17742
+ ok: true,
17743
+ status: "payment-serving",
17744
+ origin,
17745
+ publicOrigin,
17746
+ publicOriginSource,
17747
+ publicOriginLooksLocal,
17748
+ port: server.port,
17749
+ outputDir: bundle.outputDir,
17750
+ healthUrl: `${origin}/health`,
17751
+ publicHealthUrl: `${publicOrigin}/health`,
17752
+ ...buildPaymentPublishPayload(bundle),
17753
+ recommendedCommands,
17754
+ notes
17755
+ }
17756
+ );
17757
+ const shutdown = async () => {
17758
+ process.off("SIGINT", handleSignal);
17759
+ process.off("SIGTERM", handleSignal);
17760
+ await server.close();
17761
+ process.exit(0);
17762
+ };
17763
+ const handleSignal = () => {
17764
+ void shutdown();
17765
+ };
17766
+ process.on("SIGINT", handleSignal);
17767
+ process.on("SIGTERM", handleSignal);
17768
+ await new Promise(() => {
17769
+ });
17770
+ });
16942
17771
  payment.command("queue").description(
16943
17772
  "Build the wallet-aware queue slice inside the cross-request Agent Pay workspace"
16944
17773
  ).option("--wallet <name>", "Optional payer wallet filter").option(
@@ -18092,9 +18921,11 @@ function buildOperatorSuitePayload(options = {}) {
18092
18921
  productClaim: "flagship pay, Agent Pay request routing, and hosted approval recovery already read like one product shell",
18093
18922
  flagshipSurface: publicFlagshipCommand,
18094
18923
  agentPaySurface: `${publicPaymentCommand} -> ${buildApprovalRecommendedCommand("<request-id>")} -> ${publicWorkspaceCommand} -> ${publicHandoffCommand} -> ${publicFeedCommand}`,
18924
+ agentPayExportSurface: `${publicWorkspaceCommand} -> ${publicHandoffCommand} -> ${publicFeedCommand}`,
18095
18925
  hostedRecoverySurface: hostedRelayBaselineCommand,
18096
18926
  proofSurfaceIds: proofPaths.map((entry) => entry.id),
18097
- nextMaturityTarget: "add one stronger hosted/platform-facing proof surface above the current local-first request workbench",
18927
+ hostedDirection: "current public proof is to publish and serve the stable workspace/feed/handoff bundle behind one operator-controlled hosted endpoint instead of claiming a multi-tenant control plane",
18928
+ nextMaturityTarget: "prove the hosted Agent Pay bundle repeatedly behind one externally reachable operator URL",
18098
18929
  boundary: "local-first by default today; Agent Pay is not yet a hosted multi-tenant control plane"
18099
18930
  };
18100
18931
  return {
@@ -18255,8 +19086,10 @@ function operatorSuiteLines(payload) {
18255
19086
  ["platform claim", payload.platformLayer.productClaim],
18256
19087
  ["platform flagship surface", payload.platformLayer.flagshipSurface],
18257
19088
  ["platform agent pay surface", payload.platformLayer.agentPaySurface],
19089
+ ["platform agent pay export surface", payload.platformLayer.agentPayExportSurface],
18258
19090
  ["platform hosted recovery surface", payload.platformLayer.hostedRecoverySurface],
18259
19091
  ["platform proof surfaces", payload.platformLayer.proofSurfaceIds.join(" -> ")],
19092
+ ["platform hosted direction", payload.platformLayer.hostedDirection],
18260
19093
  ["platform next maturity", payload.platformLayer.nextMaturityTarget],
18261
19094
  ["platform boundary", payload.platformLayer.boundary],
18262
19095
  ["entry modes", payload.summary.entryModes.join(" -> ")],
@@ -18328,7 +19161,7 @@ function createSuiteCommand() {
18328
19161
  "",
18329
19162
  " Most common product journeys:",
18330
19163
  " send value now: go straight to the flagship pay path",
18331
- " capture and track payments: follow submit -> next -> approval -> workspace -> handoff -> feed",
19164
+ " capture and track payments: follow submit -> payment next -> approval -> workspace -> handoff -> feed",
18332
19165
  " inspect before acting: open assets/defaults/token inspection first",
18333
19166
  " unstick a write: recover paymaster/funding readiness on the workflow path",
18334
19167
  " recover remote approval: move approval to the hosted relay path",
@@ -18339,7 +19172,13 @@ function createSuiteCommand() {
18339
19172
  " `workspace`: review the cross-request operator surface",
18340
19173
  " `handoff`: export one stable single-request bundle",
18341
19174
  " `feed`: export the stable cross-request batch view",
18342
- " shortest tracked route: submit -> next -> approval -> workspace -> handoff -> feed",
19175
+ " shortest tracked route: submit -> payment next -> approval -> workspace -> handoff -> feed",
19176
+ "",
19177
+ " Hosted/platform direction inside suite:",
19178
+ " current export proof: zk-agent workspace -> zk-agent handoff --request-id <id> -> zk-agent feed",
19179
+ ` hostable bundle: ${buildPaymentPublishRecommendedCommand()} --public-base-url <https-url>`,
19180
+ " current public hosted proof: zk-agent payment publish --public-base-url <https-url> -> zk-agent payment serve --public-origin <https-url>",
19181
+ " next hosted step: keep one served bundle stable behind one externally reachable operator URL before claiming a multi-tenant control plane",
18343
19182
  "",
18344
19183
  " If you only need one default starting point inside suite:",
18345
19184
  " send value now",
@@ -18744,16 +19583,16 @@ function normalizeRole2(value) {
18744
19583
  import { Command as Command11 } from "commander";
18745
19584
 
18746
19585
  // src/lib/relay.ts
18747
- import { createServer } from "node:http";
19586
+ import { createServer as createServer2 } from "node:http";
18748
19587
  import fs7 from "node:fs";
18749
- import path7 from "node:path";
19588
+ import path9 from "node:path";
18750
19589
  import { fileURLToPath as fileURLToPath3 } from "node:url";
18751
19590
 
18752
19591
  // src/lib/http.ts
18753
19592
  import { spawn } from "node:child_process";
18754
- import { mkdtemp, readFile as readFile2, rm as rm2 } from "node:fs/promises";
19593
+ import { mkdtemp, readFile as readFile3, rm as rm3 } from "node:fs/promises";
18755
19594
  import os2 from "node:os";
18756
- import path6 from "node:path";
19595
+ import path8 from "node:path";
18757
19596
  function isDnsResolutionFailure(error) {
18758
19597
  if (!error || typeof error !== "object") {
18759
19598
  return false;
@@ -18792,9 +19631,9 @@ function parseCurlHeaders(rawHeaders) {
18792
19631
  return { status, headers };
18793
19632
  }
18794
19633
  async function runCurlRequest(url, options) {
18795
- const tempDir = await mkdtemp(path6.join(os2.tmpdir(), "zk-agent-http-"));
18796
- const headersPath = path6.join(tempDir, "headers.txt");
18797
- const bodyPath = path6.join(tempDir, "body.txt");
19634
+ const tempDir = await mkdtemp(path8.join(os2.tmpdir(), "zk-agent-http-"));
19635
+ const headersPath = path8.join(tempDir, "headers.txt");
19636
+ const bodyPath = path8.join(tempDir, "body.txt");
18798
19637
  try {
18799
19638
  const args = [
18800
19639
  "--silent",
@@ -18838,8 +19677,8 @@ async function runCurlRequest(url, options) {
18838
19677
  throw new Error(stderr.trim() || stdout.trim() || `curl exited with code ${exitCode}`);
18839
19678
  }
18840
19679
  const [rawHeaders, body] = await Promise.all([
18841
- readFile2(headersPath, "utf8"),
18842
- readFile2(bodyPath, "utf8")
19680
+ readFile3(headersPath, "utf8"),
19681
+ readFile3(bodyPath, "utf8")
18843
19682
  ]);
18844
19683
  const { status, headers } = parseCurlHeaders(rawHeaders);
18845
19684
  return {
@@ -18849,7 +19688,7 @@ async function runCurlRequest(url, options) {
18849
19688
  body
18850
19689
  };
18851
19690
  } finally {
18852
- await rm2(tempDir, { recursive: true, force: true });
19691
+ await rm3(tempDir, { recursive: true, force: true });
18853
19692
  }
18854
19693
  }
18855
19694
  async function fetchTextWithFallback(url, options = {}) {
@@ -18889,14 +19728,14 @@ var RELAY_SCHEMA_VERSION = 1;
18889
19728
  var RELAY_STATE_BACKEND = "local-filesystem";
18890
19729
  var RELAY_DEPLOYMENT_SCOPE = "single-host";
18891
19730
  function relayDir() {
18892
- const directory = path7.join(storageDir(), "relay");
19731
+ const directory = path9.join(storageDir(), "relay");
18893
19732
  if (!fs7.existsSync(directory)) {
18894
19733
  fs7.mkdirSync(directory, { recursive: true, mode: 448 });
18895
19734
  }
18896
19735
  return directory;
18897
19736
  }
18898
19737
  function relayRecordPath(requestId) {
18899
- return path7.join(relayDir(), `${requestId}.json`);
19738
+ return path9.join(relayDir(), `${requestId}.json`);
18900
19739
  }
18901
19740
  function writeRelayRecord(record) {
18902
19741
  fs7.writeFileSync(relayRecordPath(record.request_id), JSON.stringify(record, null, 2), {
@@ -18964,14 +19803,14 @@ function readRequestBody(request, limitBytes = RELAY_BODY_LIMIT_BYTES) {
18964
19803
  request.once("error", reject);
18965
19804
  });
18966
19805
  }
18967
- function writeJson2(response, statusCode, payload) {
18968
- writeBody(response, statusCode, "application/json; charset=utf-8", JSON.stringify(payload, null, 2), {
19806
+ function writeJson3(response, statusCode, payload) {
19807
+ writeBody2(response, statusCode, "application/json; charset=utf-8", JSON.stringify(payload, null, 2), {
18969
19808
  "Access-Control-Allow-Origin": "*",
18970
19809
  "Access-Control-Allow-Methods": "GET, POST, OPTIONS",
18971
19810
  "Access-Control-Allow-Headers": "Content-Type"
18972
19811
  });
18973
19812
  }
18974
- function writeBody(response, statusCode, contentType, value, extraHeaders = {}) {
19813
+ function writeBody2(response, statusCode, contentType, value, extraHeaders = {}) {
18975
19814
  response.statusCode = statusCode;
18976
19815
  response.setHeader("Content-Type", contentType);
18977
19816
  response.setHeader("Content-Length", Buffer.isBuffer(value) ? String(value.byteLength) : String(Buffer.byteLength(value)));
@@ -18982,20 +19821,20 @@ function writeBody(response, statusCode, contentType, value, extraHeaders = {})
18982
19821
  }
18983
19822
  function resolveConnectorUiDistRoot() {
18984
19823
  const currentFile = fileURLToPath3(import.meta.url);
18985
- const currentDir2 = path7.dirname(currentFile);
19824
+ const currentDir2 = path9.dirname(currentFile);
18986
19825
  const candidates = [
18987
- path7.resolve(currentDir2, "./connector-ui"),
18988
- path7.resolve(currentDir2, "../../../zk-connector-ui/dist"),
18989
- path7.resolve(currentDir2, "../../zk-connector-ui/dist")
19826
+ path9.resolve(currentDir2, "./connector-ui"),
19827
+ path9.resolve(currentDir2, "../../../zk-connector-ui/dist"),
19828
+ path9.resolve(currentDir2, "../../zk-connector-ui/dist")
18990
19829
  ];
18991
19830
  for (const candidate of candidates) {
18992
- if (fs7.existsSync(path7.join(candidate, "index.html"))) {
19831
+ if (fs7.existsSync(path9.join(candidate, "index.html"))) {
18993
19832
  return candidate;
18994
19833
  }
18995
19834
  }
18996
19835
  return null;
18997
19836
  }
18998
- function contentTypeFor(filePath) {
19837
+ function contentTypeFor2(filePath) {
18999
19838
  if (filePath.endsWith(".html")) return "text/html; charset=utf-8";
19000
19839
  if (filePath.endsWith(".js")) return "text/javascript; charset=utf-8";
19001
19840
  if (filePath.endsWith(".css")) return "text/css; charset=utf-8";
@@ -19107,18 +19946,18 @@ async function startRelayServer(options) {
19107
19946
  const uiDistRoot = resolveConnectorUiDistRoot();
19108
19947
  let bindBaseUrl = "";
19109
19948
  const publicOriginSource = options.publicOrigin?.trim() ? "configured" : "bind-origin-default";
19110
- const server = createServer(async (request, response) => {
19949
+ const server = createServer2(async (request, response) => {
19111
19950
  try {
19112
19951
  const requestUrl = new URL(request.url || "/", "http://localhost");
19113
19952
  const pathname = requestUrl.pathname;
19114
19953
  const method = request.method || "GET";
19115
19954
  const publicBaseUrl = resolveRelayPublicBaseUrl(bindBaseUrl, options.publicOrigin);
19116
19955
  if (method === "OPTIONS") {
19117
- writeJson2(response, 204, {});
19956
+ writeJson3(response, 204, {});
19118
19957
  return;
19119
19958
  }
19120
19959
  if (method === "GET" && pathname === "/health") {
19121
- writeJson2(
19960
+ writeJson3(
19122
19961
  response,
19123
19962
  200,
19124
19963
  relayHealthResponse(
@@ -19141,7 +19980,7 @@ async function startRelayServer(options) {
19141
19980
  request: body.request
19142
19981
  };
19143
19982
  writeRelayRecord(record);
19144
- writeJson2(response, existing ? 200 : 201, {
19983
+ writeJson3(response, existing ? 200 : 201, {
19145
19984
  request_id: record.request_id,
19146
19985
  status: relayStatus(record),
19147
19986
  share_url: relayShareUrl(publicBaseUrl, record.request_id),
@@ -19154,33 +19993,33 @@ async function startRelayServer(options) {
19154
19993
  if (requestMatch && method === "GET") {
19155
19994
  const record = loadRelayRecord(requestMatch[1]);
19156
19995
  if (!record) {
19157
- writeJson2(response, 404, { error: `Relay request not found: ${requestMatch[1]}` });
19996
+ writeJson3(response, 404, { error: `Relay request not found: ${requestMatch[1]}` });
19158
19997
  return;
19159
19998
  }
19160
- writeJson2(response, 200, relayStatusResponse(publicBaseUrl, record));
19999
+ writeJson3(response, 200, relayStatusResponse(publicBaseUrl, record));
19161
20000
  return;
19162
20001
  }
19163
20002
  const approvalMatch = pathname.match(/^\/api\/requests\/([^/]+)\/approval$/);
19164
20003
  if (approvalMatch && method === "GET") {
19165
20004
  const record = loadRelayRecord(approvalMatch[1]);
19166
20005
  if (!record) {
19167
- writeJson2(response, 404, { error: `Relay request not found: ${approvalMatch[1]}` });
20006
+ writeJson3(response, 404, { error: `Relay request not found: ${approvalMatch[1]}` });
19168
20007
  return;
19169
20008
  }
19170
- writeJson2(response, 200, relayApprovalResponse(record));
20009
+ writeJson3(response, 200, relayApprovalResponse(record));
19171
20010
  return;
19172
20011
  }
19173
20012
  if (approvalMatch && method === "POST") {
19174
20013
  const record = loadRelayRecord(approvalMatch[1]);
19175
20014
  if (!record) {
19176
- writeJson2(response, 404, { error: `Relay request not found: ${approvalMatch[1]}` });
20015
+ writeJson3(response, 404, { error: `Relay request not found: ${approvalMatch[1]}` });
19177
20016
  return;
19178
20017
  }
19179
20018
  const body = JSON.parse(await readRequestBody(request));
19180
20019
  record.encrypted_payload = body.encrypted_payload;
19181
20020
  record.approval_submitted_at = (/* @__PURE__ */ new Date()).toISOString();
19182
20021
  writeRelayRecord(record);
19183
- writeJson2(response, 200, relayApprovalResponse(record));
20022
+ writeJson3(response, 200, relayApprovalResponse(record));
19184
20023
  return;
19185
20024
  }
19186
20025
  const shareMatch = pathname.match(/^\/r\/([^/]+)$/);
@@ -19195,24 +20034,24 @@ async function startRelayServer(options) {
19195
20034
  }
19196
20035
  if (method === "GET" && uiDistRoot) {
19197
20036
  const relativePath = pathname === "/" ? "/index.html" : pathname;
19198
- const filePath = path7.resolve(uiDistRoot, `.${relativePath}`);
20037
+ const filePath = path9.resolve(uiDistRoot, `.${relativePath}`);
19199
20038
  if (!filePath.startsWith(uiDistRoot)) {
19200
- writeJson2(response, 403, { error: "Forbidden path" });
20039
+ writeJson3(response, 403, { error: "Forbidden path" });
19201
20040
  return;
19202
20041
  }
19203
20042
  if (fs7.existsSync(filePath) && fs7.statSync(filePath).isFile()) {
19204
- writeBody(response, 200, contentTypeFor(filePath), fs7.readFileSync(filePath));
20043
+ writeBody2(response, 200, contentTypeFor2(filePath), fs7.readFileSync(filePath));
19205
20044
  return;
19206
20045
  }
19207
- const indexPath = path7.join(uiDistRoot, "index.html");
20046
+ const indexPath = path9.join(uiDistRoot, "index.html");
19208
20047
  if (fs7.existsSync(indexPath)) {
19209
- writeBody(response, 200, "text/html; charset=utf-8", fs7.readFileSync(indexPath));
20048
+ writeBody2(response, 200, "text/html; charset=utf-8", fs7.readFileSync(indexPath));
19210
20049
  return;
19211
20050
  }
19212
20051
  }
19213
- writeJson2(response, 404, { error: `Relay route not found: ${pathname}` });
20052
+ writeJson3(response, 404, { error: `Relay route not found: ${pathname}` });
19214
20053
  } catch (error) {
19215
- writeJson2(response, 500, {
20054
+ writeJson3(response, 500, {
19216
20055
  error: error instanceof Error ? error.message : String(error)
19217
20056
  });
19218
20057
  }
@@ -20044,18 +20883,18 @@ function createRelayCommand() {
20044
20883
  }
20045
20884
 
20046
20885
  // src/commands/wallet.ts
20047
- import { createServer as createServer2 } from "node:http";
20886
+ import { createServer as createServer3 } from "node:http";
20048
20887
  import { createInterface } from "node:readline/promises";
20049
20888
  import { Command as Command12 } from "commander";
20050
20889
 
20051
20890
  // ../account-profiles/src/profiles.ts
20052
20891
  import fs8 from "node:fs";
20053
- import path8 from "node:path";
20892
+ import path10 from "node:path";
20054
20893
  import { fileURLToPath as fileURLToPath4 } from "node:url";
20055
20894
  var PACKAGE_NAME = "@zk-agent/account-profiles";
20056
20895
  var PACKAGE_ROOT_FALLBACK = `<${PACKAGE_NAME} package root unavailable>`;
20057
20896
  function isExpectedPackageRoot(candidate) {
20058
- const manifestPath = path8.join(candidate, "package.json");
20897
+ const manifestPath = path10.join(candidate, "package.json");
20059
20898
  if (!fs8.existsSync(manifestPath)) return false;
20060
20899
  try {
20061
20900
  const manifest = JSON.parse(fs8.readFileSync(manifestPath, "utf8"));
@@ -20065,19 +20904,19 @@ function isExpectedPackageRoot(candidate) {
20065
20904
  }
20066
20905
  }
20067
20906
  function resolvePackageRoot() {
20068
- const moduleRoot = path8.resolve(path8.dirname(fileURLToPath4(import.meta.url)), "..");
20907
+ const moduleRoot = path10.resolve(path10.dirname(fileURLToPath4(import.meta.url)), "..");
20069
20908
  const cwd = process.cwd();
20070
20909
  const candidates = [
20071
20910
  process.env.ZK_AGENT_ACCOUNT_PROFILES_ROOT,
20072
- path8.join(moduleRoot, "dist", "builtin-account-profiles"),
20911
+ path10.join(moduleRoot, "dist", "builtin-account-profiles"),
20073
20912
  moduleRoot,
20074
- path8.join(cwd, "packages", "account-profiles"),
20075
- path8.join(cwd, "account-profiles"),
20913
+ path10.join(cwd, "packages", "account-profiles"),
20914
+ path10.join(cwd, "account-profiles"),
20076
20915
  cwd
20077
20916
  ].filter((value) => typeof value === "string" && value.trim().length > 0);
20078
20917
  const seen = /* @__PURE__ */ new Set();
20079
20918
  for (const candidate of candidates) {
20080
- const normalized = path8.resolve(candidate);
20919
+ const normalized = path10.resolve(candidate);
20081
20920
  if (seen.has(normalized)) continue;
20082
20921
  seen.add(normalized);
20083
20922
  if (isExpectedPackageRoot(normalized)) {
@@ -20149,11 +20988,11 @@ function missingArtifactError(profileId, artifactPath2) {
20149
20988
  }
20150
20989
  function contractPath(...segments) {
20151
20990
  const packageRoot = tryResolvePackageRoot();
20152
- return packageRoot ? path8.join(packageRoot, "contracts", ...segments) : path8.join(PACKAGE_ROOT_FALLBACK, "contracts", ...segments);
20991
+ return packageRoot ? path10.join(packageRoot, "contracts", ...segments) : path10.join(PACKAGE_ROOT_FALLBACK, "contracts", ...segments);
20153
20992
  }
20154
20993
  function artifactPath(...segments) {
20155
20994
  const packageRoot = tryResolvePackageRoot();
20156
- return packageRoot ? path8.join(packageRoot, "artifacts", ...segments) : path8.join(PACKAGE_ROOT_FALLBACK, "artifacts", ...segments);
20995
+ return packageRoot ? path10.join(packageRoot, "artifacts", ...segments) : path10.join(PACKAGE_ROOT_FALLBACK, "artifacts", ...segments);
20157
20996
  }
20158
20997
  function createDailySpendLimitProfile() {
20159
20998
  const resolvedArtifactPath = artifactPath("daily-spend-limit", "Account.json");
@@ -22586,7 +23425,7 @@ function buildCallbackUrl(host, port) {
22586
23425
  async function awaitLocalWalletApproval(options) {
22587
23426
  const { walletRequest, walletName, host, requestedPort, timeoutSeconds } = options;
22588
23427
  assertRequestActive(walletRequest.expiresAt);
22589
- const server = createServer2();
23428
+ const server = createServer3();
22590
23429
  let settled = false;
22591
23430
  const completion = new Promise((resolve, reject) => {
22592
23431
  server.on("error", reject);
@@ -28031,14 +28870,30 @@ function buildDefaultOperatorPathHelpText() {
28031
28870
  " One-shot CLI: npx zk-agent-cli --help",
28032
28871
  " Global CLI: npm install -g zk-agent-cli",
28033
28872
  "",
28873
+ "Install -> first proof -> broader follow-up:",
28874
+ " install once -> pick skills, npx, or npm -g",
28875
+ " prove once -> zk-agent setup -> zk-agent start -> zk-agent wallet create --await-local -> zk-agent next -> zk-agent pay --wallet main --to <address> --amount <amount>",
28876
+ " broaden only after that first success -> zk-agent suite",
28877
+ "",
28878
+ "Product shell in one line:",
28879
+ " prove one local-first zkSync-native pay path first",
28880
+ " grow into Agent Pay requests, workspace, handoff, and feed on the same wallet runtime",
28881
+ " open hosted relay approval only when the browser is remote",
28882
+ "",
28883
+ "Payment-first product story:",
28884
+ " first proof -> get one wallet ready and send value once",
28885
+ " first expansion -> keep the same wallet runtime and add Agent Pay follow-up, workspace, handoff, and feed",
28886
+ " hosted fallback -> move approval to relay only when the browser is remote",
28887
+ "",
28034
28888
  "Why use it:",
28035
28889
  " local-first wallet and session control",
28036
28890
  " zkSync-native smart-account and paymaster path centered on sed-lite",
28037
- " Agent Pay request capture and follow-up surface around the same wallet runtime",
28891
+ " payment-first public shell: prove pay first, then grow into Agent Pay on the same runtime",
28038
28892
  "",
28039
28893
  "Best fit:",
28040
28894
  " you want wallet and session control to stay local instead of starting with a managed browser product",
28041
28895
  " you want a zkSync-native pay and paymaster path instead of a generic multichain wrapper",
28896
+ " you want to prove one pay route before reading a broad command catalog",
28042
28897
  " you want Agent Pay request capture and a workbench on the same wallet runtime",
28043
28898
  "",
28044
28899
  "What makes zk-agent-cli different:",
@@ -28067,7 +28922,7 @@ function buildDefaultOperatorPathHelpText() {
28067
28922
  "",
28068
28923
  "First proof from a clean machine:",
28069
28924
  " zk-agent setup",
28070
- " zk-agent next",
28925
+ " zk-agent start",
28071
28926
  " zk-agent wallet create --await-local",
28072
28927
  " zk-agent next",
28073
28928
  ` ${buildTopLevelPayRecommendedCommand("main")}`,
@@ -28181,7 +29036,7 @@ function applyRootHelpCommandOrder(program) {
28181
29036
  }
28182
29037
  function createProgram() {
28183
29038
  const program = new Command14().name("zk-agent").description(
28184
- "Local-first zkSync-native CLI for wallet approval, flagship pay execution, Agent Pay request routing, and single-host hosted relay recovery"
29039
+ "Payment-first local-first zkSync-native CLI for flagship pay, Agent Pay follow-up, and hosted approval fallback"
28185
29040
  ).showHelpAfterError().option("--json", "Force JSON output for agent harnesses", false).hook("preAction", (thisCommand) => {
28186
29041
  if (thisCommand.optsWithGlobals().json) process.env.ZK_AGENT_OUTPUT = "json";
28187
29042
  });