@remits/remits-cli 0.1.109 → 0.1.110
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 +81 -20
- package/package.json +1 -1
- package/skills/remits-cli/SKILL.md +46 -17
package/index.js
CHANGED
|
@@ -5617,13 +5617,37 @@ function resolveAgentId(flags, options = {}) {
|
|
|
5617
5617
|
);
|
|
5618
5618
|
}
|
|
5619
5619
|
|
|
5620
|
+
/**
|
|
5621
|
+
* The host and lane a support agent registers against when it is told nothing.
|
|
5622
|
+
*
|
|
5623
|
+
* An agent works REAL support tickets, and it must be startable from any directory on the machine —
|
|
5624
|
+
* not only from inside an account repo. So it defaults to the platform host the CLI ships with
|
|
5625
|
+
* (`REMITS_BASE_URL` when set) and to the `prod` lane.
|
|
5626
|
+
*
|
|
5627
|
+
* That is a deliberate exception to the CLI's test-first default, which exists to stop a developer
|
|
5628
|
+
* ITERATING from touching live data. Registering presence mutates no business data, and a test-lane
|
|
5629
|
+
* agent is silently useless for support: it registers, appears online, and can never be routed a
|
|
5630
|
+
* production ticket. Ask for `--data-mode test` when you want a fixture agent.
|
|
5631
|
+
*/
|
|
5632
|
+
function agentDefaults(flags, entry) {
|
|
5633
|
+
return {
|
|
5634
|
+
baseUrl: normalizeBaseUrl(
|
|
5635
|
+
(flags && flags['base-url']) || (entry && entry.baseUrl) || DEFAULT_BASE_URL),
|
|
5636
|
+
dataMode: normalizeDataMode(
|
|
5637
|
+
(flags && (flags['data-mode'] || flags.dataMode)) || (entry && entry.dataMode) || 'prod')
|
|
5638
|
+
};
|
|
5639
|
+
}
|
|
5640
|
+
|
|
5620
5641
|
function agentSessionFor(flags, entry) {
|
|
5621
5642
|
const cwd = (entry && entry.cwd) || process.cwd();
|
|
5643
|
+
const defaults = agentDefaults(flags, entry);
|
|
5622
5644
|
const context = resolveSessionContext(cwd, Object.assign({}, flags, {
|
|
5623
|
-
'base-url':
|
|
5645
|
+
'base-url': defaults.baseUrl,
|
|
5646
|
+
'data-mode': defaults.dataMode
|
|
5624
5647
|
}));
|
|
5625
5648
|
if (!context.session || !context.session.token) {
|
|
5626
|
-
throw new Error('No authenticated session
|
|
5649
|
+
throw new Error('No authenticated session for ' + defaults.baseUrl +
|
|
5650
|
+
'. Run: remits-cli auth --base-url ' + defaults.baseUrl);
|
|
5627
5651
|
}
|
|
5628
5652
|
// resolveSessionContext names it `resolvedBaseUrl` and resolves no data lane, so normalize both here
|
|
5629
5653
|
// rather than letting each caller re-derive them. Destructuring `{ baseUrl, dataMode }` off it yields
|
|
@@ -5631,8 +5655,8 @@ function agentSessionFor(flags, entry) {
|
|
|
5631
5655
|
return {
|
|
5632
5656
|
session: context.session,
|
|
5633
5657
|
accountId: context.accountId,
|
|
5634
|
-
baseUrl:
|
|
5635
|
-
dataMode:
|
|
5658
|
+
baseUrl: defaults.baseUrl,
|
|
5659
|
+
dataMode: defaults.dataMode,
|
|
5636
5660
|
sessionResolutionWarning: context.sessionResolutionWarning
|
|
5637
5661
|
};
|
|
5638
5662
|
}
|
|
@@ -5712,6 +5736,9 @@ async function agentRegisterCommand(flags, options = {}) {
|
|
|
5712
5736
|
cwd,
|
|
5713
5737
|
baseUrl,
|
|
5714
5738
|
dataMode,
|
|
5739
|
+
// The accounts the platform ACCEPTED, so `agent list` can scope itself to the work this session
|
|
5740
|
+
// can actually be routed rather than to whichever session happened to be most recent.
|
|
5741
|
+
accountIds: response.accountIds || [],
|
|
5715
5742
|
accountId: Number(session.accountId) || null,
|
|
5716
5743
|
anchorPid: anchor.pid,
|
|
5717
5744
|
anchorSource: anchor.source,
|
|
@@ -5729,19 +5756,31 @@ async function agentRegisterCommand(flags, options = {}) {
|
|
|
5729
5756
|
return;
|
|
5730
5757
|
}
|
|
5731
5758
|
|
|
5732
|
-
|
|
5759
|
+
const accepted = response.accountIds || [];
|
|
5760
|
+
console.log('Registered as a support agent: ' + response.agentId);
|
|
5733
5761
|
console.log(' label ' + payload.label);
|
|
5734
|
-
console.log('
|
|
5735
|
-
console.log('
|
|
5762
|
+
console.log(' platform ' + baseUrl);
|
|
5763
|
+
console.log(' data lane ' + dataMode + (dataMode === 'prod' ? ' (live support tickets)' : ' (fixtures only)'));
|
|
5764
|
+
console.log(' accounts ' + accepted.length + ' account(s) this session can be routed work for');
|
|
5765
|
+
console.log(' ' + accepted.join(', '));
|
|
5736
5766
|
console.log(' heartbeat every ' + Math.round(AGENT_HEARTBEAT_INTERVAL_MS / 1000) + 's, anchored to pid ' +
|
|
5737
|
-
anchor.pid + ' (' + anchor.source + ')');
|
|
5767
|
+
anchor.pid + ' (' + anchor.source + '), ends when this session ends');
|
|
5738
5768
|
if ((response.skippedAccounts || []).length) {
|
|
5739
5769
|
console.log(' refused ' + response.skippedAccounts
|
|
5740
5770
|
.map((entry) => entry.accountId + ' (' + entry.reason + ')').join(', '));
|
|
5741
5771
|
}
|
|
5772
|
+
if (dataMode !== 'prod') {
|
|
5773
|
+
console.log('');
|
|
5774
|
+
console.log('NOTE: a ' + dataMode + '-lane agent never receives production tickets. Re-register with');
|
|
5775
|
+
console.log(' --data-mode prod to take real support work.');
|
|
5776
|
+
}
|
|
5742
5777
|
console.log('');
|
|
5743
|
-
console.log('
|
|
5744
|
-
console.log(' remits-cli agent work');
|
|
5778
|
+
console.log('You are on duty. The support loop, repeated for as long as you are working:');
|
|
5779
|
+
console.log(' 1. remits-cli agent work --wait 600 # ask for work; returns as soon as any arrives');
|
|
5780
|
+
console.log(' 2. remits-cli agent status --state working --ticket <id> --activity "what you are doing"');
|
|
5781
|
+
console.log(' 3. work the ticket; keep step 2 current as you change what you are doing');
|
|
5782
|
+
console.log(' 4. close it out via mcp_support_ticket (accept -> update_status -> complete)');
|
|
5783
|
+
console.log(' 5. remits-cli agent status --state idle # then go back to step 1');
|
|
5745
5784
|
}
|
|
5746
5785
|
|
|
5747
5786
|
function readCliVersion() {
|
|
@@ -5946,11 +5985,24 @@ async function agentWorkCommand(flags) {
|
|
|
5946
5985
|
|
|
5947
5986
|
async function agentListCommand(flags) {
|
|
5948
5987
|
const cwd = process.cwd();
|
|
5949
|
-
const
|
|
5950
|
-
const
|
|
5951
|
-
|
|
5988
|
+
const mine = listLocalAgents()[0] || null;
|
|
5989
|
+
const context = agentSessionFor(flags, mine);
|
|
5990
|
+
|
|
5991
|
+
// An explicit --account-id asks about one account. Otherwise, if this machine has a registered
|
|
5992
|
+
// agent, scope to the accounts it was accepted for — the peers it could actually share work with.
|
|
5993
|
+
// Falling back to "whichever session was most recent" answers a question nobody asked.
|
|
5994
|
+
const explicitAccountId = Number(flags && flags['account-id']);
|
|
5995
|
+
const scopedAccountIds = (!Number.isFinite(explicitAccountId) && mine && Array.isArray(mine.accountIds))
|
|
5996
|
+
? mine.accountIds
|
|
5997
|
+
: null;
|
|
5998
|
+
const accountId = Number.isFinite(explicitAccountId) && explicitAccountId > 0
|
|
5999
|
+
? explicitAccountId
|
|
6000
|
+
: (scopedAccountIds ? null : resolvePreferredAccountId(cwd, flags, context.session));
|
|
6001
|
+
|
|
6002
|
+
const response = await buildAxios(context.baseUrl, context.session.token, 20000)
|
|
5952
6003
|
.post('/cli/agents', {
|
|
5953
6004
|
accountId,
|
|
6005
|
+
accountIds: scopedAccountIds,
|
|
5954
6006
|
dataMode: context.dataMode,
|
|
5955
6007
|
all: flagEnabled(flags.all)
|
|
5956
6008
|
}).then((r) => r.data);
|
|
@@ -5959,12 +6011,14 @@ async function agentListCommand(flags) {
|
|
|
5959
6011
|
console.log(JSON.stringify(response, null, 2));
|
|
5960
6012
|
return;
|
|
5961
6013
|
}
|
|
6014
|
+
const scopeLabel = accountId ? 'account ' + accountId
|
|
6015
|
+
: (scopedAccountIds ? scopedAccountIds.length + ' account(s) this session covers' : 'your accounts');
|
|
5962
6016
|
const agents = (response && response.agents) || [];
|
|
5963
6017
|
if (!agents.length) {
|
|
5964
|
-
console.log('No agents are registered for
|
|
6018
|
+
console.log('No agents are registered for ' + scopeLabel + ' in the ' + context.dataMode + ' lane.');
|
|
5965
6019
|
return;
|
|
5966
6020
|
}
|
|
5967
|
-
console.log(agents.length + ' agent(s) available
|
|
6021
|
+
console.log(agents.length + ' agent(s) available across ' + scopeLabel + ':');
|
|
5968
6022
|
for (const agent of agents) {
|
|
5969
6023
|
console.log('');
|
|
5970
6024
|
console.log(' ' + agent.agentId);
|
|
@@ -6008,9 +6062,13 @@ async function agentCommand(flags, subcommand) {
|
|
|
6008
6062
|
function printAgentHelp() {
|
|
6009
6063
|
console.log('Usage: remits-cli agent <subcommand>');
|
|
6010
6064
|
console.log('');
|
|
6011
|
-
console.log(' register [--label NAME] [--data-mode test|prod] [--
|
|
6012
|
-
console.log(' Make THIS terminal session available to work support tickets.
|
|
6013
|
-
console.log('
|
|
6065
|
+
console.log(' register [--label NAME] [--data-mode test|prod] [--base-url URL]');
|
|
6066
|
+
console.log(' Make THIS terminal session available to work support tickets. Runs from ANY');
|
|
6067
|
+
console.log(' directory — it registers for every account repo indexed on this machine that your');
|
|
6068
|
+
console.log(' user can reach, so you do not have to be inside a particular repo. Defaults to the');
|
|
6069
|
+
console.log(' production platform and the prod lane, because a support agent works real tickets.');
|
|
6070
|
+
console.log(' Starts a heartbeat that ends when this session ends, so a closed tab stops');
|
|
6071
|
+
console.log(' receiving work on its own.');
|
|
6014
6072
|
console.log('');
|
|
6015
6073
|
console.log(' work [--wait SECONDS] [--json]');
|
|
6016
6074
|
console.log(' Ask for the tickets routed to this session. With --wait it keeps asking until');
|
|
@@ -6021,6 +6079,9 @@ function printAgentHelp() {
|
|
|
6021
6079
|
console.log('');
|
|
6022
6080
|
console.log(' list [--account-id ID] [--json] Who else is available for an account.');
|
|
6023
6081
|
console.log(' release Deregister this session immediately.');
|
|
6082
|
+
console.log('');
|
|
6083
|
+
console.log(' After `register`, the other subcommands need no flags: they reuse the platform, lane');
|
|
6084
|
+
console.log(' and identity this session registered with.');
|
|
6024
6085
|
}
|
|
6025
6086
|
|
|
6026
6087
|
async function listenCommand(flags) {
|
|
@@ -6589,8 +6650,8 @@ async function main() {
|
|
|
6589
6650
|
console.log(' remits-cli auth [--base-url URL] [--account-id ID] [--port 8765] [--data-mode test|prod]');
|
|
6590
6651
|
console.log(' remits-cli sessions [list|remove] [--account-id ID] [--base-url URL] [--data-mode test|prod]');
|
|
6591
6652
|
console.log(' remits-cli config [set] [--agent claude|codex|gemini]');
|
|
6592
|
-
console.log(' remits-cli agent register
|
|
6593
|
-
console.log(' remits-cli agent work [--wait SECONDS]
|
|
6653
|
+
console.log(' remits-cli agent register # become a support agent (any directory, prod by default)');
|
|
6654
|
+
console.log(' remits-cli agent work [--wait SECONDS] # ask for tickets routed to this session');
|
|
6594
6655
|
console.log(' remits-cli agent status [--state idle|working|paused] [--ticket ID] [--activity "..."]');
|
|
6595
6656
|
console.log(' remits-cli agent list [--account-id ID] # who else is available');
|
|
6596
6657
|
console.log(' remits-cli agent release # stop receiving tickets now');
|
package/package.json
CHANGED
|
@@ -20,6 +20,8 @@ description: Use remits-cli for fast branch-scoped component staging, test execu
|
|
|
20
20
|
- [Required Local Index Reads](#required-local-index-reads)
|
|
21
21
|
- [Big Picture: How remits-cli State Is Organized](#big-picture-how-remits-cli-state-is-organized)
|
|
22
22
|
- [Support Ticket Mental Model](#support-ticket-mental-model)
|
|
23
|
+
- [You are an agent, and you register yourself](#you-are-an-agent-and-you-register-yourself)
|
|
24
|
+
- [The loop](#the-loop)
|
|
23
25
|
- [Efficiency Rules](#efficiency-rules)
|
|
24
26
|
- [Account Repository Index](#account-repository-index)
|
|
25
27
|
- [Two Workflows](#two-workflows)
|
|
@@ -460,16 +462,21 @@ workflows, and never one product's view of it.
|
|
|
460
462
|
|
|
461
463
|
### You are an agent, and you register yourself
|
|
462
464
|
|
|
463
|
-
|
|
465
|
+
**If the user says anything like "register to become a support agent", run exactly this and nothing
|
|
466
|
+
else first:**
|
|
464
467
|
|
|
465
468
|
```bash
|
|
466
|
-
remits-cli agent register
|
|
467
|
-
remits-cli agent work # ask for the tickets routed to it
|
|
469
|
+
remits-cli agent register
|
|
468
470
|
```
|
|
469
471
|
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
472
|
+
No flags, no setup, **no need to be in an account repo** — run it from wherever the session started.
|
|
473
|
+
It registers this terminal for every account repo indexed on this machine that your user can reach,
|
|
474
|
+
against the production platform and the production lane, and prints the accounts it was accepted for.
|
|
475
|
+
It also prints the support loop; follow it.
|
|
476
|
+
|
|
477
|
+
Three tabs running an agent are three agents. Each is independently routable, each reports its own
|
|
478
|
+
activity, and each stops receiving work when its tab closes — a heartbeat anchored to the session dies
|
|
479
|
+
with it, so a crashed agent and a quit agent look identical to the platform.
|
|
473
480
|
|
|
474
481
|
**Nothing is pushed at you.** A terminal mid-task cannot receive a push, so delivery is you asking.
|
|
475
482
|
That is why the routing decision is a durable field on the ticket rather than a message: you can
|
|
@@ -487,21 +494,35 @@ A ticket routed to you is not yet yours. Claim it with `accept`, and the queue t
|
|
|
487
494
|
|
|
488
495
|
### The loop
|
|
489
496
|
|
|
497
|
+
After `register`, **no agent command needs a flag** — they reuse the platform, lane and identity this
|
|
498
|
+
session registered with.
|
|
499
|
+
|
|
490
500
|
```bash
|
|
491
|
-
remits-cli agent
|
|
492
|
-
remits-cli agent work --wait 300 # blocks until something arrives
|
|
501
|
+
remits-cli agent work --wait 600 # returns as soon as work arrives
|
|
493
502
|
remits-cli agent status --state working --ticket 22454 --activity "reproducing the upload failure"
|
|
494
|
-
# ... investigate, fix, verify ...
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
remits-cli agent status --state idle # ready for the next one
|
|
503
|
+
# ... investigate, fix, verify — keep `status` current as what you are doing changes ...
|
|
504
|
+
# ... close the ticket lifecycle through mcp_support_ticket (accept -> update_status -> complete) ...
|
|
505
|
+
remits-cli agent status --state idle # then ask for work again
|
|
498
506
|
```
|
|
499
507
|
|
|
508
|
+
**Stay on duty.** When `agent work` returns nothing, ask again — do not stop and wait to be
|
|
509
|
+
re-prompted. Registration persists for the life of the session (the heartbeat keeps you visible and
|
|
510
|
+
routable even while you are not polling), but collecting work is something you have to do.
|
|
511
|
+
|
|
500
512
|
**Report what you are doing.** `agent status` is how an operator watching the dashboard, or another
|
|
501
513
|
agent, knows this session is alive and what it is on. It costs one command and it is the difference
|
|
502
514
|
between a visible queue and a silent one. Update it when you change what you are doing, not on a
|
|
503
515
|
timer.
|
|
504
516
|
|
|
517
|
+
**Work the ticket in the right repo.** A ticket names its `accountId`, and often an
|
|
518
|
+
`implementationAccountId` — the platform/product account whose repo holds the code. Resolve that to a
|
|
519
|
+
local directory through `~/.remits-cli/account-repos.json` and `cd` there before making changes. You
|
|
520
|
+
registered from anywhere; you do not fix anything from anywhere.
|
|
521
|
+
|
|
522
|
+
**Lane note:** `register` defaults to the production lane because a support agent works real tickets.
|
|
523
|
+
`--data-mode test` registers a fixture agent instead, which will never be routed a production ticket —
|
|
524
|
+
use it only when you are deliberately testing the routing itself.
|
|
525
|
+
|
|
505
526
|
### Seeing the queue as a human does
|
|
506
527
|
|
|
507
528
|
`remits-cli start` opens a browser control center showing the same facts you are acting on: which
|
|
@@ -2750,19 +2771,27 @@ so in its own output; when a test run genuinely needs prod data, pass the flag.
|
|
|
2750
2771
|
independent of everything else — no background service is required, and every tab is its own agent.
|
|
2751
2772
|
|
|
2752
2773
|
```bash
|
|
2753
|
-
remits-cli agent register # this session is now routable
|
|
2774
|
+
remits-cli agent register # this session is now routable — no flags, any directory
|
|
2754
2775
|
remits-cli agent work --wait 300 # ask for tickets routed here
|
|
2755
2776
|
remits-cli agent status --state working --ticket 22454 --activity "reproducing"
|
|
2756
|
-
remits-cli agent list # who else is available
|
|
2777
|
+
remits-cli agent list # who else is available across the accounts you cover
|
|
2757
2778
|
remits-cli agent release # stop receiving tickets right now
|
|
2758
2779
|
```
|
|
2759
2780
|
|
|
2781
|
+
**Defaults exist so the user does not have to type them.** With no flags, `register` targets the
|
|
2782
|
+
production platform (`REMITS_BASE_URL` when set) and the **prod** lane, and claims every account repo
|
|
2783
|
+
indexed on this machine. That is a deliberate exception to the CLI's test-first default: registering
|
|
2784
|
+
presence mutates no business data, and a test-lane agent is silently useless for support — it appears
|
|
2785
|
+
online and can never be routed a production ticket. Every command after `register` reuses the
|
|
2786
|
+
platform, lane and identity it registered with.
|
|
2787
|
+
|
|
2760
2788
|
### What registration actually does
|
|
2761
2789
|
|
|
2762
2790
|
- Mints an `agentId` for this session and tells the platform which account repos this machine has
|
|
2763
|
-
checked out
|
|
2764
|
-
the
|
|
2765
|
-
|
|
2791
|
+
checked out — read from the machine-wide index (`~/.remits-cli/account-repos.json`), which is why
|
|
2792
|
+
the working directory does not matter. The platform **verifies** those claims against what your user
|
|
2793
|
+
can access and returns the ones it refused, so "I registered but never get tickets for account 52"
|
|
2794
|
+
is answerable from the registration output alone.
|
|
2766
2795
|
- Starts a small detached heartbeat process **anchored to the agent process that owns this terminal**
|
|
2767
2796
|
(it walks up the process tree to find `claude`/`codex`/`gemini`, then an interactive shell). When
|
|
2768
2797
|
that process ends, the heartbeat ends and the session stops being routable within a couple of
|