@eventmodelers/cli 1.0.69 → 1.0.71
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/README.md +21 -5
- package/cli.js +91 -21
- package/package.json +1 -1
- package/shared/skills/learn-eventmodelers-api/SKILL.md +2 -0
package/README.md
CHANGED
|
@@ -211,8 +211,10 @@ starting in one command. Resolution order for a run is `--credentials` and the i
|
|
|
211
211
|
`--token`/`--organization-id`/`--board-id`/`--base-url` flags, then `EVENTMODELERS_*` env vars,
|
|
212
212
|
then `~/.eventmodelers/boards/<board>.json`, then the usual `.eventmodelers/config.json` walk,
|
|
213
213
|
and finally the account's default board. Whatever a run resolves is saved back to the
|
|
214
|
-
per-board file (`0600`, in a `0700` directory)
|
|
215
|
-
|
|
214
|
+
per-board file (`0600`, in a `0700` directory). The agent id is *not* stored there — a standalone
|
|
215
|
+
run mints a fresh one each time, so two ad-hoc agents on one board stay two agents (see
|
|
216
|
+
[Naming an agent](#naming-an-agent)). One machine can therefore drive several boards, across
|
|
217
|
+
several accounts, at once.
|
|
216
218
|
The global kit itself holds no credentials at all — the token reaches `claude` through the
|
|
217
219
|
spawned process's environment.
|
|
218
220
|
|
|
@@ -401,16 +403,30 @@ npx @eventmodelers/cli init-config --name ci-builder # name the agent this c
|
|
|
401
403
|
|
|
402
404
|
### Naming an agent
|
|
403
405
|
|
|
404
|
-
Every agent identifies itself to the platform with
|
|
406
|
+
Every agent identifies itself to the platform with an `agentId`, and the board's live-agent view shows that bare uuid. A **project install** mints one on first use and reuses it on every restart (`agentIds` in the project root's `.eventmodelers/config.json`). A **standalone/global run** mints a fresh one per run instead: nothing stops two ad-hoc agents running for one board, and since the heartbeat is keyed on `(token, agentId, agentType)`, a shared id would make the second agent replace the first — one agent visible however many are running, and their board writes indistinguishable.
|
|
407
|
+
|
|
408
|
+
`--name` gives an agent a readable label instead of the uuid — accepted by `init`, `re-init`, and `init-config`, saved into `config.json` as `agentName`, and sent with every heartbeat from then on:
|
|
405
409
|
|
|
406
410
|
```bash
|
|
407
411
|
npx @eventmodelers/cli init --stack node --name ci-builder # persisted for every later run of this kit
|
|
408
412
|
npx @eventmodelers/cli init-config --name martins-laptop # same, without re-installing
|
|
409
413
|
npx @eventmodelers/cli run --name one-off-check # override for a single run, nothing written
|
|
410
|
-
npx @eventmodelers/cli run --id <id> #
|
|
414
|
+
npx @eventmodelers/cli run --id <id> # pin ONE identity across restarts
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
`run --id` is what you want when an agent has to keep the same identity every time it starts: a supervisor that already knows the id, a second agent of the same type in one *project* (which would otherwise share the project's single minted id), or an agent a board has starred as its **preferred agent** — that star addresses prompts to one id, so an agent whose id changes per run loses it on restart. `run --id`/`run --name` are per-run only: nothing is written to disk.
|
|
418
|
+
|
|
419
|
+
#### Working only what you were addressed (`--exclusive`)
|
|
420
|
+
|
|
421
|
+
By default an agent claims two kinds of prompt: the ones addressed to its own id, and every prompt nobody addressed to anyone. That's right for the single agent on a board, and wrong for a dedicated one — a specialist sitting next to a general agent, or an agent a supervisor drives by id, ends up answering whatever the queue happens to hold. `--exclusive` drops that second kind:
|
|
422
|
+
|
|
423
|
+
```bash
|
|
424
|
+
npx @eventmodelers/cli run --standalone --board-id <uuid> --id <agent-uuid> --exclusive
|
|
411
425
|
```
|
|
412
426
|
|
|
413
|
-
|
|
427
|
+
Only prompts carrying this agent's id are worked. Anything untargeted is handed straight back to the queue (status `ADDED`) for another agent to take — the addressee filter lives in the queue's claim query, which hands an agent its own prompts *and* the untargeted ones, so claiming is the only way to find out which arrived. An exclusive run therefore claims as usual and gives back what wasn't meant for it, once it has walked past it to its own work.
|
|
428
|
+
|
|
429
|
+
Pair it with `--id`: a `--standalone`/`--global` run mints a fresh id per run, so prompts addressed to the previous run's id are never claimed. `--exclusive` applies to the prompt queue only — a `--standalone` agent's self-directed turns are nobody's prompt, and it keeps taking them.
|
|
414
430
|
|
|
415
431
|
### Env vars and `--config` (scripted/CI installs)
|
|
416
432
|
|
package/cli.js
CHANGED
|
@@ -1390,7 +1390,7 @@ function ensureEnvToken(targetDir, token) {
|
|
|
1390
1390
|
const GLOBAL_DIR = join(homedir(), '.eventmodelers');
|
|
1391
1391
|
const GLOBAL_KIT_DIR = join(GLOBAL_DIR, 'kit');
|
|
1392
1392
|
|
|
1393
|
-
// One file per board: `{token, organizationId, boardId, baseUrl
|
|
1393
|
+
// One file per board: `{token, organizationId, boardId, baseUrl}`. Credentials
|
|
1394
1394
|
// ARE per board — a token is scoped to the org that owns it — so one machine can drive
|
|
1395
1395
|
// several boards across several accounts at once, each with its own. Written 0600 in a
|
|
1396
1396
|
// 0700 dir: unlike a project's .eventmodelers/config.json, there is no .gitignore standing
|
|
@@ -1408,21 +1408,20 @@ function boardCredentialsPath(boardId) {
|
|
|
1408
1408
|
function writeBoardCredentials(config) {
|
|
1409
1409
|
const path = boardCredentialsPath(config.boardId);
|
|
1410
1410
|
mkdirSync(dirname(path), { recursive: true, mode: 0o700 });
|
|
1411
|
-
// agentName
|
|
1412
|
-
//
|
|
1413
|
-
//
|
|
1414
|
-
//
|
|
1411
|
+
// agentName is stored, the agent id is not: the name is a label for whoever runs here (and
|
|
1412
|
+
// this file is the only config a `run --standalone` from an arbitrary directory reads, so
|
|
1413
|
+
// dropping it would lose `init-config --name` on the very next run), while the id is minted
|
|
1414
|
+
// per run now — see resolveModelingCredentials for why.
|
|
1415
1415
|
const agentName = config.agentName ? { agentName: config.agentName } : {};
|
|
1416
1416
|
const body = config.useBoard
|
|
1417
1417
|
? { boardId: config.boardId, useBoard: config.useBoard }
|
|
1418
1418
|
: config.useGlobal
|
|
1419
|
-
? { boardId: config.boardId, useGlobal: true,
|
|
1419
|
+
? { boardId: config.boardId, useGlobal: true, ...agentName }
|
|
1420
1420
|
: {
|
|
1421
1421
|
token: config.token,
|
|
1422
1422
|
organizationId: config.organizationId,
|
|
1423
1423
|
boardId: config.boardId,
|
|
1424
1424
|
baseUrl: config.baseUrl,
|
|
1425
|
-
agentId: config.agentId,
|
|
1426
1425
|
...agentName,
|
|
1427
1426
|
};
|
|
1428
1427
|
writeFileSync(path, JSON.stringify(body, null, 2), { mode: 0o600 });
|
|
@@ -1605,12 +1604,18 @@ async function resolveModelingCredentials(cwd, flags, explicitConfigPath, print)
|
|
|
1605
1604
|
process.exit(1);
|
|
1606
1605
|
}
|
|
1607
1606
|
|
|
1608
|
-
//
|
|
1609
|
-
//
|
|
1610
|
-
//
|
|
1611
|
-
|
|
1607
|
+
// A fresh identity for every standalone run, deliberately not persisted. A standalone agent
|
|
1608
|
+
// is started ad hoc from wherever, and nothing stops two of them running for the same board —
|
|
1609
|
+
// with one id stored per board they upserted the same alive row (the heartbeat is keyed on
|
|
1610
|
+
// token + agent_id + agent_type), so the second agent replaced the first instead of joining
|
|
1611
|
+
// it: the board showed one agent however many were running, and their writes were
|
|
1612
|
+
// indistinguishable. A per-run uuid costs the identity its continuity across restarts (a
|
|
1613
|
+
// restarted agent is a new row, and the old one lingers until its 45s window lapses) — pass
|
|
1614
|
+
// `run --id <uuid>` when an agent needs to keep one identity, which is also what makes
|
|
1615
|
+
// "preferred agent" on the board stick to it.
|
|
1616
|
+
config.agentId = randomUUID();
|
|
1612
1617
|
writeBoardCredentials(stored.useGlobal
|
|
1613
|
-
? { boardId: config.boardId, useGlobal: true,
|
|
1618
|
+
? { boardId: config.boardId, useGlobal: true, agentName: config.agentName }
|
|
1614
1619
|
: config);
|
|
1615
1620
|
|
|
1616
1621
|
return config;
|
|
@@ -1667,7 +1672,13 @@ async function ensureGlobalKit(baseUrl) {
|
|
|
1667
1672
|
// question, sketch a screen. Without the flag that channel is still subscribed on
|
|
1668
1673
|
// the same connection and every event on it is dropped, so the two modes differ by
|
|
1669
1674
|
// one filter rather than by a whole second realtime stack.
|
|
1670
|
-
|
|
1675
|
+
//
|
|
1676
|
+
// `exclusive` narrows the prompt lane to this agent alone: only a prompt the user
|
|
1677
|
+
// addressed to this agent id (the board's "preferred agent") is worked, and anything
|
|
1678
|
+
// untargeted is handed straight back to the queue for another agent to take. It says
|
|
1679
|
+
// nothing about the standalone lane — a self-directed turn is nobody's task, so an
|
|
1680
|
+
// exclusive standalone agent still works the board on its own initiative.
|
|
1681
|
+
async function runModeling(kitDir, projectDir, { verbose = false, standalone = false, exclusive = false, overrides = null, maxAgents = DEFAULT_MAX_AGENTS, identity = {} } = {}) {
|
|
1671
1682
|
const configLibPath = join(kitDir, 'lib', 'config.js');
|
|
1672
1683
|
if (!existsSync(configLibPath)) {
|
|
1673
1684
|
console.error(`❌ ${relative(process.cwd(), configLibPath)} not found — --modeling needs a kit installed via \`init --modeling\`.`);
|
|
@@ -1697,14 +1708,20 @@ async function runModeling(kitDir, projectDir, verbose = false, standalone = fal
|
|
|
1697
1708
|
console.error('❌ --modeling needs platform credentials in .eventmodelers/config.json (token + organizationId) — run `/connect` once or paste your config first.');
|
|
1698
1709
|
process.exit(1);
|
|
1699
1710
|
}
|
|
1700
|
-
// The identity flags go on last: the global install's `overrides` carry the
|
|
1701
|
-
//
|
|
1702
|
-
//
|
|
1711
|
+
// The identity flags go on last: the global install's `overrides` carry the agent id
|
|
1712
|
+
// resolveModelingCredentials just minted for this run, which would otherwise win back over
|
|
1713
|
+
// an explicit --id.
|
|
1703
1714
|
const cfg = { ...(await fetchPlatformConfig(local)), ...(overrides ?? {}), ...(identity.agentId ? { agentId: identity.agentId } : {}), ...(identity.agentName ? { agentName: identity.agentName } : {}) }; // adds realtimeProvider + its provider-specific fields (supabaseUrl/supabaseAnonKey or pocketbaseUrl), + boardId if the config has a default one
|
|
1704
1715
|
if (!cfg.boardId) {
|
|
1705
1716
|
console.error('❌ --modeling needs a boardId — a modeling agent always runs for exactly one board. Run `/connect board=<uuid>` once, or add boardId to .eventmodelers/config.json.');
|
|
1706
1717
|
process.exit(1);
|
|
1707
1718
|
}
|
|
1719
|
+
// Nothing can be addressed to an agent with no id, so an exclusive run without one would
|
|
1720
|
+
// hand every prompt back and sit idle forever — a silent no-op worth failing on instead.
|
|
1721
|
+
if (exclusive && !cfg.agentId) {
|
|
1722
|
+
console.error('❌ --exclusive needs an agent id — that is what a prompt is addressed to. Pass `run --id <uuid>` (or let the kit mint one) and address the prompt to it on the board.');
|
|
1723
|
+
process.exit(1);
|
|
1724
|
+
}
|
|
1708
1725
|
|
|
1709
1726
|
const subagentModel = cfg.subagentModel || DEFAULT_SUBAGENT_MODEL;
|
|
1710
1727
|
|
|
@@ -1917,11 +1934,19 @@ async function runModeling(kitDir, projectDir, verbose = false, standalone = fal
|
|
|
1917
1934
|
}
|
|
1918
1935
|
|
|
1919
1936
|
spawnProcess();
|
|
1937
|
+
log(`agent: ${cfg.agentName ? `${cfg.agentName} (${cfg.agentId})` : cfg.agentId}`);
|
|
1920
1938
|
log(
|
|
1921
1939
|
standalone
|
|
1922
1940
|
? `standalone: ON — reacting to direct prompts AND to board changes on its own initiative (max ${maxAgents} subagent(s) per self-directed turn)`
|
|
1923
1941
|
: 'standalone: off — reacting to direct prompts only (board changes are dropped)',
|
|
1924
1942
|
);
|
|
1943
|
+
if (exclusive) {
|
|
1944
|
+
log(`exclusive: ON — only prompts addressed to ${cfg.agentId} are worked; every untargeted prompt is handed back to the queue`);
|
|
1945
|
+
// A global/standalone run mints its id per run (see resolveModelingCredentials), so an id
|
|
1946
|
+
// someone addressed a prompt to yesterday is not this agent — worth saying out loud here,
|
|
1947
|
+
// where the alternative is an agent that looks healthy and quietly works nothing.
|
|
1948
|
+
if (overrides && !identity.agentId) log('exclusive: this run minted a fresh agent id — star it on the board now, or restart with `--id <uuid>` to keep one addressable identity');
|
|
1949
|
+
}
|
|
1925
1950
|
warmUpSession();
|
|
1926
1951
|
|
|
1927
1952
|
async function getRealtimeToken() {
|
|
@@ -1941,15 +1966,47 @@ async function runModeling(kitDir, projectDir, verbose = false, standalone = fal
|
|
|
1941
1966
|
return res.json();
|
|
1942
1967
|
}
|
|
1943
1968
|
|
|
1969
|
+
// Puts a prompt this agent claimed but will not work back on the queue (CLAIMED -> ADDED),
|
|
1970
|
+
// so whichever agent it was actually open to can still take it. `x-token` only — the status
|
|
1971
|
+
// endpoint is meant to be called by the agent holding the prompt.
|
|
1972
|
+
async function releasePrompt(promptId) {
|
|
1973
|
+
const res = await fetch(`${cfg.baseUrl}/api/org/${cfg.organizationId}/prompts/${promptId}/status`, {
|
|
1974
|
+
method: 'POST',
|
|
1975
|
+
headers: { 'x-token': cfg.token, 'Content-Type': 'application/json', ...agentHeaders(cfg) },
|
|
1976
|
+
body: JSON.stringify({ status: 'ADDED' }),
|
|
1977
|
+
});
|
|
1978
|
+
if (!res.ok) throw new Error(`prompts/${promptId}/status: HTTP ${res.status}`);
|
|
1979
|
+
}
|
|
1980
|
+
|
|
1944
1981
|
let realtimeToken = await getRealtimeToken();
|
|
1945
1982
|
|
|
1946
1983
|
let draining = false;
|
|
1947
1984
|
async function drain() {
|
|
1948
1985
|
if (draining) return;
|
|
1949
1986
|
draining = true;
|
|
1987
|
+
// --exclusive only: prompts claimed in this pass that weren't addressed to this agent,
|
|
1988
|
+
// handed back once the pass is over (see below).
|
|
1989
|
+
const handBack = [];
|
|
1950
1990
|
try {
|
|
1951
1991
|
let p;
|
|
1952
1992
|
while ((p = await fetchNextPrompt(realtimeToken)) !== null) {
|
|
1993
|
+
// The queue can't filter by addressee for us: `prompts/next` hands an agent both the
|
|
1994
|
+
// prompts addressed to it and every untargeted one (`agent_id IS NULL`) — claiming is
|
|
1995
|
+
// what reveals which kind arrived — so an exclusive run claims as usual and gives back
|
|
1996
|
+
// what wasn't meant for it.
|
|
1997
|
+
//
|
|
1998
|
+
// The hand-back is deferred to the end of the pass on purpose: a prompt released
|
|
1999
|
+
// mid-loop goes straight back to the head of the very queue this loop is reading, so
|
|
2000
|
+
// the next fetch would return the prompt just released instead of the addressed one
|
|
2001
|
+
// queued behind it, and the agent would never reach its own work. Holding them CLAIMED
|
|
2002
|
+
// until the queue runs dry walks past them instead. The cost is a brief CLAIMED blip on
|
|
2003
|
+
// someone else's prompt, and — if no other agent happens to be draining when the
|
|
2004
|
+
// hand-back lands — that prompt waiting for the next `prompt:created` to be noticed.
|
|
2005
|
+
if (exclusive && (p.agent_id ?? null) !== cfg.agentId) {
|
|
2006
|
+
log(`prompt ${p.id} ${p.agent_id ? `is addressed to agent ${p.agent_id}` : 'is addressed to no agent'} — handing it back (--exclusive)`);
|
|
2007
|
+
handBack.push(p.id);
|
|
2008
|
+
continue;
|
|
2009
|
+
}
|
|
1953
2010
|
log(`prompt received: "${p.prompt}" (board=${p.board_id ?? cfg.boardId ?? 'n/a'}, priority=${p.priority})`);
|
|
1954
2011
|
try {
|
|
1955
2012
|
await runClaudeWarm(buildTurn(p));
|
|
@@ -1958,6 +2015,16 @@ async function runModeling(kitDir, projectDir, verbose = false, standalone = fal
|
|
|
1958
2015
|
}
|
|
1959
2016
|
}
|
|
1960
2017
|
} finally {
|
|
2018
|
+
for (const id of handBack) {
|
|
2019
|
+
try {
|
|
2020
|
+
await releasePrompt(id);
|
|
2021
|
+
} catch (err) {
|
|
2022
|
+
// Left CLAIMED, which is worse for whoever sent it than a retry would be — but
|
|
2023
|
+
// retrying here risks wedging the loop, and the next pass claims nothing new
|
|
2024
|
+
// while this one is still unwinding. Say so and move on.
|
|
2025
|
+
log(`handing prompt ${id} back failed, it stays CLAIMED: ${err.message}`);
|
|
2026
|
+
}
|
|
2027
|
+
}
|
|
1961
2028
|
draining = false;
|
|
1962
2029
|
// A prompt turn counts as activity: the board isn't idle just because nobody edited
|
|
1963
2030
|
// it while the agent was busy answering someone.
|
|
@@ -2710,9 +2777,6 @@ credentialFlags(program
|
|
|
2710
2777
|
process.exit(1);
|
|
2711
2778
|
}
|
|
2712
2779
|
if (!parsed.baseUrl) parsed.baseUrl = DEFAULT_BASE_URL;
|
|
2713
|
-
// Preserved across re-configuration: the platform keys a board's alive-ping on it, so
|
|
2714
|
-
// regenerating it would present a long-running agent as a brand-new one.
|
|
2715
|
-
parsed.agentId = readJsonSafe(boardCredentialsPath(parsed.boardId)).agentId || randomUUID();
|
|
2716
2780
|
writeBoardCredentials(parsed);
|
|
2717
2781
|
console.log('\n ✓ Saved credentials for board ' + parsed.boardId + ' to ' + boardCredentialsPath(parsed.boardId));
|
|
2718
2782
|
console.log('\n Start the agent from anywhere with:\n');
|
|
@@ -2803,10 +2867,11 @@ credentialFlags(program
|
|
|
2803
2867
|
.option('--modeling', 'Keep one Claude process warm across prompts instead of spawning a fresh one per task, for low-latency voice/live use. Runs from a modeling-kit install in this directory, or from the global install (~/.eventmodelers/kit) when there is none. Built into the CLI, not a per-project file.')
|
|
2804
2868
|
.option('--standalone', 'Let the modeling agent work the board in the background, on its own initiative: on top of direct prompts it subscribes to the board\'s change channel (like the build agents do) and, whenever the board goes quiet after an edit — or has simply been idle for a while — it takes a turn nobody asked for. Changed nodes are a notification, not the task: it judges the model as a whole and fans the work out over parallel subagents, one per changed area (examples on a new node, specs for a new command or read model, a missing attribute along a chain, a screen, a question comment). Filling that detail in while the human keeps modeling is the point — it does not wait for the board to be finished. Implies --modeling.')
|
|
2805
2869
|
.option('--max-agents <n>', 'Cap how many subagents a self-directed --standalone turn may dispatch at once, to bound what an unattended agent can spend per turn. The agent merges work that shares a slice or chain first, then takes the most valuable pieces up to this many and leaves the rest for a later turn. 1 makes it do the single most valuable piece itself, without spawning anything. Default 5. Ignored without --standalone — prompt turns are one piece of work by definition.', '5')
|
|
2870
|
+
.option('--exclusive', 'Work only the prompts addressed to this agent\'s id — the board\'s "preferred agent" (the star in the prompts panel) — and hand every untargeted prompt straight back to the queue for another agent to take. Without it an agent also works everything nobody addressed to anyone, which is what you want for a single agent and exactly what you do not want for a dedicated one (a board with a general agent plus a specialist, or an agent a supervisor drives by id). Pair it with --id so the same agent is addressable across restarts — --global/--standalone otherwise mint a fresh id per run, and prompts addressed to the previous run\'s id are never claimed. Leaves --standalone alone: a self-directed turn is nobody\'s prompt, so an exclusive standalone agent still works the board on its own initiative.')
|
|
2806
2871
|
.option('--global', 'Run the modeling agent from the global install (~/.eventmodelers/kit), initializing it on first use, and ignore any kit in this directory. This is also what --modeling/--standalone fall back to on their own when nothing is installed here — pass it explicitly to prefer the global install over a local one. Credentials come from the flags below, EVENTMODELERS_* env vars, or ~/.eventmodelers/boards/<board>.json, so nothing is written into the current directory.')
|
|
2807
2872
|
.option('--local', 'Skip platform config/credential lookup entirely and run the local-only loop (no board sync, no realtime agent) — even if .eventmodelers/config.json has credentials (build-kit stacks only)')
|
|
2808
2873
|
.option('--verbose', 'Log every tool call\'s full input (commands, skill args, file paths) and assistant reasoning text. Default is condensed, high-level per-step logging only.')
|
|
2809
|
-
.option('--id <id>', '
|
|
2874
|
+
.option('--id <id>', 'Pin the agent id this run identifies itself with on the platform. A project install otherwise mints one id per project and reuses it on every restart; --global/--standalone mints a fresh one per run, since two ad-hoc agents for one board must not share a row (the heartbeat is keyed on token + agent_id + agent_type, so the second would replace the first). Pass this when an agent has to keep ONE identity across restarts — a supervisor that already knows the id, or a board where it is the starred "preferred agent". Per-run only: nothing is written to disk.')
|
|
2810
2875
|
.option('--name <name>', 'A human-readable name for this agent, sent with every heartbeat so the board shows which agent is live rather than a bare uuid (e.g. "ci-builder", "martins-laptop"). Per-run only, like --id: the persistent name is `agentName` in config.json (set via `init --name` / `init-config --name`), and this overrides it for one run without writing anything.')
|
|
2811
2876
|
.option('--credentials <values>', 'Credentials as the comma-separated blob from app.eventmodelers.ai/account (token=...,boardId=...,organizationId=...,baseUrl=...), the equivalent JSON, or - to read either from stdin. Saved to ~/.eventmodelers/boards/<board>.json, so it is only needed once per board, and passing it skips the first-run question. The individual flags below override single fields of it.'))
|
|
2812
2877
|
.action(async (opts, command) => {
|
|
@@ -2819,6 +2884,11 @@ credentialFlags(program
|
|
|
2819
2884
|
if (command.getOptionValueSource('maxAgents') === 'cli' && !opts.standalone) {
|
|
2820
2885
|
console.log('ℹ️ --max-agents only applies to --standalone turns; ignoring it here.');
|
|
2821
2886
|
}
|
|
2887
|
+
// The build-kit runners claim their work from the same queue but have no addressee
|
|
2888
|
+
// filter, so the flag would silently do nothing there rather than half of what it says.
|
|
2889
|
+
if (opts.exclusive && !(opts.modeling || opts.standalone || opts.global)) {
|
|
2890
|
+
console.log('ℹ️ --exclusive only applies to the modeling loop (--modeling/--standalone/--global); ignoring it here.');
|
|
2891
|
+
}
|
|
2822
2892
|
// --id/--name are what the platform will see for this run, so a blank one is a
|
|
2823
2893
|
// mistake worth failing on rather than silently falling back to the stored identity.
|
|
2824
2894
|
const identity = {
|
|
@@ -2899,7 +2969,7 @@ credentialFlags(program
|
|
|
2899
2969
|
const shown = relative(cwd, kitDir);
|
|
2900
2970
|
await new Promise((res) => process.stdout.write(`▶ Starting modeling loop (warm Claude process) for ${shown && !shown.startsWith('..') ? shown : kitDir}...\n\n`, res));
|
|
2901
2971
|
try {
|
|
2902
|
-
await runModeling(kitDir, projectDir, !!opts.verbose, !!opts.standalone, overrides, maxAgents, identity);
|
|
2972
|
+
await runModeling(kitDir, projectDir, { verbose: !!opts.verbose, standalone: !!opts.standalone, exclusive: !!opts.exclusive, overrides, maxAgents, identity });
|
|
2903
2973
|
} catch (err) {
|
|
2904
2974
|
console.error('[modeling] Fatal:', err);
|
|
2905
2975
|
process.exit(1);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@eventmodelers/cli",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.71",
|
|
4
4
|
"description": "Eventmodelers CLI — real-time Claude agent + skills for Claude Code, for any stack (Node, Supabase, Axon, Cratis, OpenCQRS, UmaDB, Kurrent, or modeling-only)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -860,6 +860,8 @@ Claim the next pending (`ADDED`) prompt for a board — atomically flips it to `
|
|
|
860
860
|
|
|
861
861
|
Send `x-agent-id` here too: a prompt the user addressed to one preferred agent (`prompts.agent_id`) is only ever handed to the agent claiming with that id, and a caller without the header claims untargeted prompts only. Addressing one is `POST /api/org/:orgId/prompts` with `agent_id: "<uuid>"` — the board's prompts panel does it when someone stars an agent.
|
|
862
862
|
|
|
863
|
+
Note what this endpoint does *not* do: an agent that sends its id still gets every untargeted prompt on top of its own. A caller that wants only what was addressed to it has to hand the rest back itself (`POST /prompts/:id/status` with `status: 'ADDED'`), which is what `eventmodelers run --exclusive` does.
|
|
864
|
+
|
|
863
865
|
**Query params**: `board_id` (required)
|
|
864
866
|
**Response**: `200` — the claimed row (now `status: "CLAIMED"`), including its parsed `context` and the `hidden` flag · `404` — no `ADDED` prompts available
|
|
865
867
|
|