@nomac/cli 0.2.0 → 0.2.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nomac/cli",
3
- "version": "0.2.0",
3
+ "version": "0.2.2",
4
4
  "description": "Ship iOS apps to TestFlight and the App Store without a Mac — built for agents.",
5
5
  "license": "UNLICENSED",
6
6
  "type": "module",
package/skill/SKILL.md CHANGED
@@ -54,5 +54,9 @@ status # poll ~30s until ready | failed
54
54
  ## When stuck
55
55
 
56
56
  `report_issue` with the failing `ref_id` files a support ticket with full
57
- context auto-attached (deduped, so safe to call). Read replies with the same
58
- tool. Never retry-loop an identical failure more than twice.
57
+ context auto-attached (deduped, so safe to call). Its optional `email` requests
58
+ a direct resolution update; without it, read replies with the same tool. If the
59
+ tool returns a Private Relay warning, explain that Apple relay addresses may
60
+ reject later mail and offer a non-relay address. Never show that warning for a
61
+ normal address such as `@icloud.com`. Never retry-loop an identical failure
62
+ more than twice.
package/src/cli.mjs CHANGED
@@ -117,8 +117,11 @@ async function push() {
117
117
  }
118
118
  console.log(`✅ snapshot ${res.snapshot_id} (commit ${res.commit.slice(0, 8)})`);
119
119
  const d = res.detected ?? {};
120
+ const framework = d.project_kind
121
+ ? ` · ${d.project_kind}${d.flutter_sdk_version ? ` ${d.flutter_sdk_version}` : ""}`
122
+ : "";
120
123
  console.log(
121
- ` detected: ${d.xcodeproj ?? "?"} · scheme ${d.scheme ?? "?"} · ${d.bundle_id ?? "no bundle id"}${d.marketing_version ? ` · v${d.marketing_version}` : ""}`,
124
+ ` detected: ${d.xcodeproj ?? "?"} · scheme ${d.scheme ?? "?"} · ${d.bundle_id ?? "no bundle id"}${d.marketing_version ? ` · v${d.marketing_version}` : ""}${framework}`,
122
125
  );
123
126
  if (res.lint) {
124
127
  const icon = res.lint.grade === "green" ? "🟢" : res.lint.grade === "yellow" ? "🟡" : "🔴";
package/src/mcp.mjs CHANGED
@@ -2,6 +2,7 @@
2
2
  // Thin wrappers over the nomac REST API; API-key auth (nomac login / env).
3
3
  // Works in every MCP client day one; the hosted transport is mcp.nomac.app.
4
4
 
5
+ import { randomUUID } from "node:crypto";
5
6
  import { createInterface } from "node:readline";
6
7
  import { api } from "./api.mjs";
7
8
  import { loadProjectState, saveProjectState } from "./config.mjs";
@@ -210,10 +211,16 @@ export const TOOLS = [
210
211
  },
211
212
  handler: async (args) => {
212
213
  const project_id = await resolveProjectId(args);
214
+ const mode = args?.confirm ? "confirm" : "stage";
215
+ // Idempotency keys identify one tool invocation, not every publish for
216
+ // this project forever. A later invocation must re-run mutable lint and
217
+ // App Store preflight checks; retries inside this invocation reuse this
218
+ // single key.
219
+ const idempotencyKey = `mcp-pub-${project_id}-${mode}-${randomUUID()}`;
213
220
  return text(
214
221
  await api("POST", "/api/v1/publish", {
215
222
  body: { project_id, confirm: args?.confirm ?? false, force: args?.force ?? false },
216
- idempotencyKey: `mcp-pub-${project_id}-${args?.confirm ? "confirm" : "stage"}`,
223
+ idempotencyKey,
217
224
  }),
218
225
  );
219
226
  },
@@ -233,12 +240,18 @@ export const TOOLS = [
233
240
  {
234
241
  name: "report_issue",
235
242
  description:
236
- "File an unknown/unfixable error with nomac support. Auto-attaches build error, logs (redacted) and lint state when you pass ref_id (a bld_… id). Deduped by error fingerprint. Read replies by calling with no description.",
243
+ "File an unknown/unfixable error with nomac support. Auto-attaches build error, logs (redacted) and lint state when you pass ref_id (a bld_… id). Deduped by error fingerprint. An optional email requests a direct resolution update; replies are always available by calling with no description.",
237
244
  inputSchema: {
238
245
  type: "object",
239
246
  properties: {
240
247
  description: { type: "string", description: "what went wrong + what you tried (≥10 chars). Omit to read existing tickets/replies." },
241
248
  ref_id: { type: "string" },
249
+ email: {
250
+ type: "string",
251
+ format: "email",
252
+ maxLength: 320,
253
+ description: "optional follow-up email for a direct resolution update",
254
+ },
242
255
  },
243
256
  additionalProperties: false,
244
257
  },