@remits/remits-cli 0.1.89 → 0.1.90

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/index.js CHANGED
@@ -268,6 +268,19 @@ function printResolvedBaseUrl(baseUrl) {
268
268
  console.log('Base URL:', normalizeBaseUrl(baseUrl || DEFAULT_BASE_URL));
269
269
  }
270
270
 
271
+ // A tool's OWN verdict, which is separate from whether the call was dispatched. Only an explicit
272
+ // failure signal counts: tools legitimately return strings, arrays, and maps with no `success` key.
273
+ // Used as a fallback when the platform build predates the envelope's `toolSuccess`.
274
+ function toolResultFailed(result) {
275
+ if (!result || typeof result !== 'object' || Array.isArray(result)) return false;
276
+ return result.success === false || result.is_error === true;
277
+ }
278
+
279
+ function toolResultMessage(result) {
280
+ if (!toolResultFailed(result)) return null;
281
+ return result.message || result.error || 'The tool returned an error';
282
+ }
283
+
271
284
  function readConfig() {
272
285
  if (!fs.existsSync(CONFIG_FILE)) {
273
286
  return {};
@@ -2485,7 +2498,12 @@ async function toolCommand(flags) {
2485
2498
  if (data.threadGroupingId) console.log('Thread grouping ID:', data.threadGroupingId);
2486
2499
  console.log('Session log:', sessionJsonlFile(cwd));
2487
2500
  console.log('Tool response file:', statusResponse.responseFile);
2488
- if (data.status === 'failed') process.exitCode = 1;
2501
+ // A completed run can still carry a tool-level refusal — see toolResultFailed.
2502
+ const polledFailed = data.toolSuccess === false || toolResultFailed(data.result);
2503
+ if (polledFailed) {
2504
+ console.log('Tool error:', data.toolMessage || toolResultMessage(data.result));
2505
+ }
2506
+ if (data.status === 'failed' || polledFailed) process.exitCode = 1;
2489
2507
  return;
2490
2508
  }
2491
2509
 
@@ -2507,9 +2525,19 @@ async function toolCommand(flags) {
2507
2525
  throw new Error(data.message || 'Tool execution failed');
2508
2526
  }
2509
2527
 
2528
+ // `data.success` only means the tool was found and DISPATCHED. A tool that ran and refused (unmet
2529
+ // precondition, rejected enum value, validation failure) still comes back 200 with its own
2530
+ // success:false, and printing "Tool call succeeded" for that has caused agents to report work as
2531
+ // done that never happened. Prefer the server's hoisted verdict; fall back to introspecting the
2532
+ // result so this still works against an older platform build.
2533
+ const toolFailed = data.toolSuccess === false || toolResultFailed(data.result);
2534
+ const toolFailureMessage = data.toolMessage || toolResultMessage(data.result);
2535
+
2510
2536
  printSessionResolutionWarning(sessionContext);
2511
2537
  printResolvedBaseUrl(baseUrl);
2512
- console.log(asyncMode ? 'Tool call started.' : 'Tool call succeeded.');
2538
+ console.log(asyncMode ? 'Tool call started.'
2539
+ : (toolFailed ? 'Tool call FAILED — the tool ran and returned an error.' : 'Tool call succeeded.'));
2540
+ if (toolFailed && toolFailureMessage) console.log('Tool error:', toolFailureMessage);
2513
2541
  console.log('Call ID:', callId);
2514
2542
  console.log('Data mode:', data.dataMode || dataMode);
2515
2543
  if (data.variantBranch || variantBranch) console.log('Variant branch:', data.variantBranch || variantBranch);
@@ -2523,6 +2551,9 @@ async function toolCommand(flags) {
2523
2551
  console.log('Session log:', sessionJsonlFile(cwd));
2524
2552
  console.log('Tool response file:', response.responseFile);
2525
2553
 
2554
+ // Non-zero exit so scripted/agent callers that check status notice the refusal too.
2555
+ if (toolFailed) process.exitCode = 1;
2556
+
2526
2557
  if (asyncMode && waitForAsync) {
2527
2558
  const finalStatus = await waitForToolStatus(api, cwd, {
2528
2559
  token: session.token,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@remits/remits-cli",
3
- "version": "0.1.89",
3
+ "version": "0.1.90",
4
4
  "description": "Local CLI for auth, component sync, and live test execution against Remits",
5
5
  "license": "MIT",
6
6
  "private": false,
@@ -917,6 +917,7 @@ summary: One-line statement of what this component is for.
917
917
  description: |
918
918
  Longer technical description with line-number references to the key logic.
919
919
  path: /page/merchant-portal # Readers and Embeddables only
920
+ injectionType: DIRECT # Embeddables only: DIRECT or IFRAME
920
921
  category: default
921
922
  auxiliary: false # `true` means the sync SKIPS the file entirely — see Auxiliary
922
923
  mermaid: |
@@ -1135,7 +1136,7 @@ account:<accountId>:cli:<cliUserId>:components:<branch>:<family>:name:<normalize
1135
1136
  component's OWN type enum such as `ObjectType`/`RuleType`, or absent — **never** the family), `hash`,
1136
1137
  `updatedAt`, the staged content field(s) (`source`/`prompt`/`html`/`javascript`/`schema`/
1137
1138
  `inputSchema`/`previewData`), and `.meta.yml` metadata fields such as `description`, `summary`, `mermaid`,
1138
- `path`, `category`, and Schema flags (`enableTrigger`, `enableFullText`, `enableRAG`, `enableRevisions`,
1139
+ `path`, Embeddable `injectionType`, `category`, and Schema flags (`enableTrigger`, `enableFullText`, `enableRAG`, `enableRevisions`,
1139
1140
  `enableBigQuerySync`, `enableRules`, `anchor`, `auxiliary`).
1140
1141
 
1141
1142
  ### How the platform picks staged vs DB (the compile signature)
@@ -1406,7 +1407,7 @@ changes validation and where the subscriber's documents physically land. Treat s
1406
1407
  same care as a trunk schema change.
1407
1408
 
1408
1409
  **What a branch may override.** A variant speaks the same `.meta.yml` vocabulary trunk does — `name`,
1409
- `description`, `summary`, `mermaid`, `category`, `type`, `path`, `collectionName`, `job`, `model`,
1410
+ `description`, `summary`, `mermaid`, `category`, `type`, `path`, `injectionType`, `collectionName`, `job`, `model`,
1410
1411
  `agentTimeout`, `mcp`, `cli`, `global`, `purpose`, `auxiliary`, plus Schema flags (`enableTrigger`,
1411
1412
  `enableFullText`, `enableRAG`, `enableRevisions`, `enableBigQuerySync`, `enableRules`, `anchor`) — and the
1412
1413
  component's content files. Keys outside that set are ignored, deliberately: trunk cannot express them either,
@@ -1727,6 +1728,23 @@ remits-cli tool --name "mcp_firestore_search" --input '{"accountId": 37, "collec
1727
1728
 
1728
1729
  Response saved to `./.remits-cli/tool-responses/<callId>.json`. Read the file to see results.
1729
1730
 
1731
+ **"Tool call succeeded" means DISPATCHED, not that the tool did what you asked.** A tool that runs
1732
+ and refuses — an unmet precondition, a rejected enum value, a failed validation — returns HTTP 200
1733
+ with its own `success: false` inside `result`. The CLI now prints `Tool call FAILED — the tool ran
1734
+ and returned an error.` plus a `Tool error:` line and exits non-zero, and the response envelope
1735
+ carries `toolSuccess` / `toolMessage`. **For any MUTATING call, confirm the tool's own verdict before
1736
+ reporting the work as done** — do not grep the terminal output for "succeeded":
1737
+
1738
+ ```bash
1739
+ F=$(remits-cli tool --name mcp_support_ticket --input "$(cat payload.json)" --data-mode prod 2>&1 \
1740
+ | grep -o '[^ ]*tool-responses/[a-f0-9-]*\.json' | tail -1)
1741
+ python3 -c "import json;r=json.load(open('$F'))['result'];print(r.get('success'), r.get('message'))"
1742
+ ```
1743
+
1744
+ Build non-trivial JSON into a file (e.g. with `python3 -c 'json.dumps(...)'`) and pass it as
1745
+ `--input "$(cat payload.json)"`. Long inline single-quoted JSON intermittently produces no response
1746
+ file at all.
1747
+
1730
1748
  For long-running Action/Agent runners, use the tool's own async mode (`executionMode:"async"`), which returns
1731
1749
  the `actionRunId`/`agentRunId` (and, for agents, `sessionId`) immediately:
1732
1750
 
@@ -2141,10 +2159,10 @@ Create and manage the full lifecycle of account-relative `support_tickets`.
2141
2159
  | `affectedComponent` | no | Component or platform area affected (`create`) |
2142
2160
  | `implementationAccountId` / `implementationAccountName` | no | Owning `PLATFORM`/`PRODUCT` account when the ticket concerns shared implementation (e.g. a back-stage platform fix) |
2143
2161
  | `stepsToReproduce` / `acceptanceCriteria` / `tags` | no | Extra `create` fields for defect/enhancement tickets |
2144
- | `assignee` | no | Required for `accept` |
2145
- | `status` | no | Required for `update_status`. Valid values: `in_progress`, `pending_review` |
2162
+ | `assignee` | no | Required for `accept`. The agent's own name by convention — `claude`, `codex`, `gemini` |
2163
+ | `status` | no | Required for `update_status`. Valid values: `in_progress`, `pending_review`. **The ticket must be `accept`ed first** — otherwise the call is rejected with *"Ticket must be accepted before updating status"* |
2146
2164
  | `resolution` | no | Required for `complete` |
2147
- | `category` / `summary` / `details` / `findings` / `nextStep` | no | Worklog fields for `record_progress` (`category` + `summary` required) |
2165
+ | `category` / `summary` / `details` / `findings` / `nextStep` | no | Worklog fields for `record_progress` (`category` + `summary` required). `category` is a **fixed enum** — `triage`, `investigation`, `reproduction`, `fix`, `verification`, `handoff`, `other` — and any other value fails the whole call. `findings` is a **list of strings**, not a paragraph |
2148
2166
  | `artifactType` / `artifactLabel` / `contentBase64` / `gcsPath` / `url` | no | Evidence fields for `add_artifact` (screenshot/trace/log/test_result/link) |
2149
2167
  | `notes` | no | Optional lifecycle note stored with the ticket activity |
2150
2168
  | `attachmentIndex` | no | Zero-based index of the attachment to download. Used with `get_attachment`. |
@@ -2159,13 +2177,24 @@ Create and manage the full lifecycle of account-relative `support_tickets`.
2159
2177
 
2160
2178
  This keeps file retrieval self-contained — no separate download endpoint is needed.
2161
2179
 
2162
- **Recommended flow:**
2163
- 1. `read` with the ticket's `accountId` — check ticket state and any attachments
2164
- 2. `accept` with the ticket's `accountId`
2180
+ **Recommended flow** — `accountId` is optional throughout; `ticketId` resolves the owning account:
2181
+ 1. `read` — check ticket state and any attachments
2182
+ 2. **`accept`** (with `assignee`) — this is a **hard precondition for `update_status`**, not just etiquette
2165
2183
  3. `get_attachment` if attachments are present and relevant to the investigation
2166
- 4. `update_status` with the ticket's `accountId`
2167
- 5. investigate/fix/verify on the owning ticket account or its implementation account as appropriate
2168
- 6. `complete` or `release` with the ticket's `accountId`
2184
+ 4. `update_status` — `in_progress` while working, `pending_review` when the fix is done but not yet deployed
2185
+ 5. `record_progress` as you go — one `investigation` entry for the root cause, one `verification` entry for the proof
2186
+ 6. investigate/fix/verify on the owning ticket account or its implementation account as appropriate
2187
+ 7. `complete` (with `resolution`) or `release` if handing off
2188
+
2189
+ **Check each mutation actually landed.** Every action above is a write that can be refused while the
2190
+ CLI still reports the *call* as fine — see "Execute a Tool" for why, and read `result.success` from
2191
+ the response file. A silent no-op here means telling the user a ticket moved when it did not.
2192
+
2193
+ **Duplicates are common.** The same defect is often filed twice — once against the `CLIENT`/subscriber
2194
+ account where it was observed and once against the owning `PLATFORM`/`PRODUCT` account. Before
2195
+ starting, check `mcp_support_ticket_queue` for the same subject or affected component. Close the
2196
+ duplicate with a `resolution` naming the ticket that carries the real work, rather than investigating
2197
+ it twice.
2169
2198
 
2170
2199
  **Automation rule:** If a ticket is involved, you should usually:
2171
2200
  - `read` at the start