@shardflux/cli 0.23.1 → 0.24.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.
- package/CHANGELOG.md +139 -0
- package/README.md +249 -4
- package/dist/account-args.js +8 -3
- package/dist/account-commands.js +15 -2
- package/dist/account-pool.js +5 -1
- package/dist/acp-journal.d.ts +2 -2
- package/dist/acp-journal.js +14 -4
- package/dist/acp-permission-elsewhere.d.ts +38 -0
- package/dist/acp-permission-elsewhere.js +85 -0
- package/dist/acp-rpc.d.ts +2 -1
- package/dist/acp-rpc.js +11 -2
- package/dist/acp.js +125 -30
- package/dist/agent-credentials.d.ts +3 -0
- package/dist/agent-credentials.js +7 -0
- package/dist/args.d.ts +1 -1
- package/dist/args.js +154 -8
- package/dist/board-args.d.ts +6 -0
- package/dist/board-args.js +155 -0
- package/dist/board-commands.d.ts +62 -0
- package/dist/board-commands.js +395 -0
- package/dist/codex-cloud.d.ts +30 -3
- package/dist/codex-cloud.js +86 -12
- package/dist/conversation-commands.d.ts +30 -0
- package/dist/conversation-commands.js +312 -9
- package/dist/conversation-transcript.d.ts +44 -0
- package/dist/conversation-transcript.js +206 -0
- package/dist/conversations.d.ts +5 -2
- package/dist/conversations.js +20 -10
- package/dist/default-volume-commands.d.ts +3 -0
- package/dist/default-volume-commands.js +35 -0
- package/dist/device-approvals.js +4 -3
- package/dist/device-bridge.d.ts +42 -1
- package/dist/device-bridge.js +241 -14
- package/dist/device-folders.d.ts +58 -0
- package/dist/device-folders.js +228 -0
- package/dist/device-helper.d.ts +6 -0
- package/dist/device-helper.js +87 -14
- package/dist/drive-commands.d.ts +25 -0
- package/dist/drive-commands.js +201 -0
- package/dist/filesystem-commands.js +2 -1
- package/dist/handlers.js +6 -1
- package/dist/local-sessions.d.ts +7 -1
- package/dist/local-sessions.js +38 -0
- package/dist/main.js +3 -0
- package/dist/move-files.d.ts +39 -0
- package/dist/move-files.js +167 -0
- package/dist/move-interrupt.d.ts +18 -0
- package/dist/move-interrupt.js +193 -0
- package/dist/move.js +28 -17
- package/dist/onboarding.d.ts +6 -2
- package/dist/onboarding.js +24 -6
- package/dist/project-git.d.ts +7 -1
- package/dist/project-git.js +16 -3
- package/dist/project-preparation.d.ts +7 -0
- package/dist/project-preparation.js +14 -0
- package/dist/project-template-setup.js +32 -11
- package/dist/router-commands.d.ts +22 -0
- package/dist/router-commands.js +179 -0
- package/dist/worktree-twin-engine.js +16 -6
- package/package.json +7 -5
package/dist/args.js
CHANGED
|
@@ -11,9 +11,10 @@
|
|
|
11
11
|
*/
|
|
12
12
|
import { parseArgs } from 'node:util';
|
|
13
13
|
import { ACCOUNT_COMMANDS } from "./account-args.js";
|
|
14
|
+
import { BOARD_COMMANDS } from "./board-args.js";
|
|
14
15
|
import { UsageError } from "./errors.js";
|
|
15
16
|
import { DEFAULT_CHOICE, MODEL_CHOICES } from "./agent-models.js";
|
|
16
|
-
export const CLI_VERSION = '0.
|
|
17
|
+
export const CLI_VERSION = '0.24.1';
|
|
17
18
|
export const GLOBAL_OPTIONS = {
|
|
18
19
|
'api-url': { type: 'string', value: '<url>', description: 'API base URL (default $SHARDFLUX_API_URL, else https://api.shardflux.dev).' },
|
|
19
20
|
json: { type: 'boolean', description: 'Print machine-readable JSON on stdout (errors as JSON on stderr).' },
|
|
@@ -147,15 +148,52 @@ const LAYER_HELP = {
|
|
|
147
148
|
};
|
|
148
149
|
const KEY_COMMANDS = [
|
|
149
150
|
{ path: ['conversations', 'list'], summary: 'List project conversations', positionals: [], options: { all: { type: 'boolean', description: 'Fetch every page.' },
|
|
150
|
-
project: { type: 'string', value: '<id>', description: 'Project ID for a user session.' }, state: { type: 'string', value: '<state>', description: 'Conversation state.' },
|
|
151
|
-
parent: { type: 'string', value: '<id>', description: 'Children of this conversation.' },
|
|
151
|
+
project: { type: 'string', value: '<id>', description: 'Project ID for a user session.' }, org: { type: 'string', value: '<id|slug>', description: 'Signed in: the conversations of every project of this organization you work in (0.25.0+).' }, state: { type: 'string', value: '<state>', description: 'Conversation state.' },
|
|
152
|
+
parent: { type: 'string', value: '<id>', description: 'Children of this conversation.' }, 'updated-after': { type: 'string', value: '<time>', description: 'Only conversations changed after this time (RFC 3339).' },
|
|
153
|
+
limit: { type: 'string', value: '<count>', description: 'Page size.' }, cursor: { type: 'string', value: '<cursor>', description: 'Next page cursor.' } },
|
|
154
|
+
description: 'With an API key: its project’s conversations. Signed in (shard auth login) without a key: the conversations of every project you work in, across your organizations (0.25.0+); --org narrows them to one organization and --project to one project. --org uses your sign-in when you have one.',
|
|
155
|
+
examples: ['shard c list --state needs_you', 'shard c list --org acme --all --json'] },
|
|
156
|
+
{ path: ['conversations', 'feed'], summary: 'Print project conversations as they change', positionals: [], options: {
|
|
157
|
+
project: { type: 'string', value: '<id>', description: 'Project ID for a user session.' }, org: { type: 'string', value: '<id|slug>', description: 'Signed in: every project of this organization you work in (0.25.0+).' }, cursor: { type: 'string', value: '<cursor>', description: 'Continue after this feed cursor (--json prints it with each change).' }
|
|
158
|
+
},
|
|
159
|
+
description: 'Prints each conversation the moment it changes, until interrupted: "<id> <title> <state>", and why it needs you when it does; --json prints one {conversation, cursor} object per line. With an API key: its project. Signed in without a key: every project you work in, on one cursor (0.25.0+); --org follows one organization’s projects and uses your sign-in when you have one.',
|
|
160
|
+
examples: ['shard c feed', 'shard c feed --org acme --json'] },
|
|
152
161
|
{ path: ['conversations', 'resume'], summary: 'Resume a saved conversation in a fresh VM', positionals: [{ name: 'id', required: true }], options: {} },
|
|
153
162
|
{ path: ['conversations', 'reader'], summary: 'Open a read-only project space reader', positionals: [{ name: 'project_id', required: true }], options: {} },
|
|
154
|
-
{ path: ['conversations', 'get'], summary: 'Show a conversation and its current VM', positionals: [{ name: 'id', required: true }], options: {}
|
|
155
|
-
|
|
163
|
+
{ path: ['conversations', 'get'], summary: 'Show a conversation and its current VM', positionals: [{ name: 'id', required: true }], options: {},
|
|
164
|
+
description: 'Prints its title, state and branch, why it needs you when it does, then one line per port a process listens on in its computer: the port, the program, and its URL once exposed (or 127.0.0.1 only). --json returns the conversation with pty_id, listening_ports and listening_ports_at.' },
|
|
165
|
+
{ path: ['conversations', 'watch'], summary: 'Watch a conversation’s terminal live, read-only', positionals: [{ name: 'id', required: true }], options: {},
|
|
166
|
+
description: 'Shows the terminal the conversation’s agent runs in (its pty_id, terminal conversations) as the agent works: its last 256 KiB, then live output, until the agent’s session exits or you press Ctrl-C. Nothing you type reaches it. Watching never keeps the computer awake while the agent is idle, and ends when the computer sleeps. The output is the terminal’s own bytes, so there is no --json form; shard agents logs <id> --json returns recent output as JSON.',
|
|
167
|
+
examples: ['shard conversations watch conv_a7k2m4q6s3t5v7x2z4b6d3f5h7'] },
|
|
168
|
+
{ path: ['conversations', 'send'], summary: 'Send the next user turn', positionals: [{ name: 'id', required: true }, { name: 'text', variadic: true, words: true }], options: {
|
|
169
|
+
file: { type: 'string', multiple: true, value: '<path>', description: 'Attach a file (repeatable, up to 20 of 64 MiB each): it lands in the conversation’s computer before the message, which lists its path there (0.25.0+).' }
|
|
170
|
+
},
|
|
171
|
+
description: 'Text and files reach the conversation’s agent as its next turn. A conversation that ended is restored into a fresh computer first. Attached files keep their names under /home/user/.shardflux/attachments/<conversation id>/; each stored path is printed.',
|
|
172
|
+
examples: ['shard conversations send conv_6qz2dmu4kd3xa7v5l2hgmfnpjy "Fix the failing export test"', 'shard conversations send conv_6qz2dmu4kd3xa7v5l2hgmfnpjy "Why does this page break?" --file screenshot.png --file console.log'] },
|
|
156
173
|
{ path: ['conversations', 'wait'], summary: 'Wait for a result or question', positionals: [{ name: 'id', required: true }], options: {
|
|
157
174
|
until: { type: 'string', value: '<states>', description: 'Comma-separated conversation states.' }, timeout: { type: 'string', value: '<seconds>', description: 'Wait for 0..900 seconds (default 900).' }
|
|
158
175
|
} },
|
|
176
|
+
{ path: ['conversations', 'permissions'], summary: 'List what a conversation’s agent asked permission for, oldest first', positionals: [{ name: 'id', required: true }], options: {
|
|
177
|
+
state: { type: 'string', value: '<state>', description: 'pending, answered or canceled (default every state).' }, all: { type: 'boolean', description: 'Fetch every page.' },
|
|
178
|
+
limit: { type: 'string', value: '<count>', description: 'Page size (1..200, default 50).' }, cursor: { type: 'string', value: '<cursor>', description: 'Next page cursor.' }
|
|
179
|
+
},
|
|
180
|
+
description: 'A conversation is needs_you while its agent waits on a permission request: to run a command, edit a file or fetch a URL. Each line is the request id, its state, what the agent wants to do, the command, path or URL, and the decision once answered. Answer a pending one with shard conversations answer (0.25.0+).',
|
|
181
|
+
examples: ['shard conversations permissions <conversation-id> --state pending', 'shard c permissions <conversation-id> --all --json'] },
|
|
182
|
+
{ path: ['conversations', 'answer'], summary: 'Answer a permission request (allow, always or deny) or the agent’s question (--pick)', positionals: [{ name: 'id', required: true }, { name: 'permission_id', required: true }, { name: 'decision' }], options: {
|
|
183
|
+
pick: { type: 'string', multiple: true, value: '<option|question=option>', description: 'The option you pick for the agent’s question (0.25.0+): its label or your own words; repeat it for a multi-select question; "<question>=<option>" when it asks several.' }
|
|
184
|
+
},
|
|
185
|
+
description: 'allow lets the agent run the tool this once, always also lets its harness stop asking for this kind of call, deny refuses it (allow_once, allow_always and deny work too). The agent’s question (a request with questions, such as Claude Code’s AskUserQuestion) takes --pick, or deny to decline it; the agent gets exactly what you picked. The agent goes on with its turn, and a parked computer wakes to take the answer. A request answered already, here or where the agent runs, is refused with permission_answered (0.25.0+).',
|
|
186
|
+
examples: ['shard conversations answer <conversation-id> <permission-id> allow', 'shard c answer <conversation-id> <permission-id> --pick Blue', 'shard c answer <conversation-id> <permission-id> deny'] },
|
|
187
|
+
{ path: ['conversations', 'transcript'], summary: 'Print a conversation’s transcript: its agent’s own JSONL (0.25.0+)', positionals: [{ name: 'id', required: true }], options: {
|
|
188
|
+
offset: { type: 'string', value: '<bytes>', description: 'Start at this byte offset, such as the next_offset of an earlier read.' },
|
|
189
|
+
session: { type: 'string', value: '<id>', description: 'An earlier session of the conversation (default: the latest).' },
|
|
190
|
+
follow: { type: 'boolean', short: 'f', description: 'Keep printing new lines as they are stored, until Ctrl-C.' }
|
|
191
|
+
},
|
|
192
|
+
description: 'Prints the Claude Code or Codex transcript byte for byte, as the agent wrote it, for working, parked and finished conversations alike, without waking a VM. With --json: one object (session_id, file, offset, next_offset, size, data); with --follow, one object per line.',
|
|
193
|
+
examples: ['shard c transcript conv_k3m5q7s2u4w6y3b5d7f2h4j6ln > session.jsonl', 'shard c transcript conv_k3m5q7s2u4w6y3b5d7f2h4j6ln --follow | jq -c \'select(.type=="assistant")\''] },
|
|
194
|
+
{ path: ['conversations', 'events'], summary: 'Follow a conversation live: state, transcript, reply text and tool calls (0.25.0+)', positionals: [{ name: 'id', required: true }], options: {},
|
|
195
|
+
description: 'Streams the conversation until Ctrl-C, one line per event: state changes, new transcript lines and tool calls, with the reply written as the agent streams it. With --json: one event per line, {"type":"conversation"|"transcript"|"delta","id":…} with the conversation, the transcript lines or the ACP session updates.',
|
|
196
|
+
examples: ['shard c events conv_k3m5q7s2u4w6y3b5d7f2h4j6ln', 'shard c events conv_k3m5q7s2u4w6y3b5d7f2h4j6ln --json | jq -c \'select(.type=="delta")\''] },
|
|
159
197
|
{ path: ['conversations', 'land'], summary: 'Record the landing action performed by the agent', positionals: [{ name: 'id', required: true }, { name: 'action', required: true }], options: { into: { type: 'string', value: '<ref>', description: 'Destination branch or PR URL.' } } },
|
|
160
198
|
{ path: ['conversations', 'move'], summary: 'Move at the end of the turn', positionals: [{ name: 'id', required: true }, { name: 'to', required: true }], options: {} },
|
|
161
199
|
{ path: ['conversations', 'landing'], summary: 'Show or set how finished conversations reach this checkout', positionals: [{ name: 'mode' }, { name: 'backup' }], options: {
|
|
@@ -1296,7 +1334,19 @@ const AGENT_COMMANDS = [
|
|
|
1296
1334
|
detach: { type: 'boolean', description: 'Start it in the cloud without opening it here.' },
|
|
1297
1335
|
}, examples: ['shard move --last', 'shard move --list', 'shard move --session 3d085e35-aa66-4866-9a53-f09719d6767c --detach --json'] },
|
|
1298
1336
|
{ path: ['device', 'requests'], summary: 'Review local device requests waiting for approval', positionals: [], options: {} },
|
|
1299
|
-
...['approve', 'deny'].map((action) => ({ path: ['device', action], summary: `${action} a local device request`, positionals: [{ name: 'id', required: true }], options: action === 'approve' ? { always: { type: 'boolean', description: 'Allow matching requests for this project; never for outside
|
|
1337
|
+
...['approve', 'deny'].map((action) => ({ path: ['device', action], summary: `${action} a local device request`, positionals: [{ name: 'id', required: true }], options: action === 'approve' ? { always: { type: 'boolean', description: 'Allow matching requests for this project, or for a folder request (0.25.0+) that folder and what is inside it; never for other access outside the conversation folder.' } } : {} })),
|
|
1338
|
+
{ path: ['conversations', 'start'], summary: 'Start a conversation from the project or on your machine, no folder needed (0.25.0+)', positionals: [], options: {
|
|
1339
|
+
project: { type: 'string', value: '<id>', description: 'The project (default: the API key’s, or this computer’s selected project).' },
|
|
1340
|
+
home: { type: 'boolean', description: 'Start on your machine’s home, without a repository: the agent runs in /home/user and starts threads in the project’s repositories.' },
|
|
1341
|
+
repo: { type: 'string', value: '<remote>', description: 'The repository (default: the project’s most recently active one).' },
|
|
1342
|
+
branch: { type: 'string', value: '<name>', description: 'Start from this branch’s newest saved point in the project (default main, then master).' },
|
|
1343
|
+
app: { type: 'string', value: '<claude|codex>', description: 'Agent app (default claude).' },
|
|
1344
|
+
title: { type: 'string', value: '<text>', description: 'The conversation’s title (default: named by its first message).' },
|
|
1345
|
+
...MODEL_OPTIONS,
|
|
1346
|
+
prompt: { type: 'string', value: '<text>', description: 'The first message.' },
|
|
1347
|
+
file: { type: 'string', multiple: true, value: '<path>', description: 'Attach a file to the first message (repeatable, up to 20 of 64 MiB each; needs --prompt).' },
|
|
1348
|
+
}, description: 'Starts a Claude Code or Codex conversation in its own cloud computer straight from the project: the repository is checked out from the project’s saved branches, so no local folder is needed. --home starts a coordinator on your machine instead, which spawns threads in the project’s repositories. Prints the conversation id, key and state; open it with shard agents open <id>.',
|
|
1349
|
+
examples: ['shard conversations start --prompt "Add CSV export to the invoices page"', 'shard conversations start --repo https://github.com/acme/app.git --branch main --app codex --prompt "Fix the flaky login test" --file trace.log', 'shard conversations start --home --title "Plan the billing work" --json'] },
|
|
1300
1350
|
{ path: ['conversations', 'try'], summary: 'Try a conversation in a synced local worktree', positionals: [{ name: 'conversation', required: true }], options: { path: { type: 'string', value: '<path>', description: 'Local project checkout.' }, stop: { type: 'boolean', description: 'Stop the device helper’s local sync and ports.' } } },
|
|
1301
1351
|
{ path: ['agents', 'targets'], summary: 'Detect apps or configure managed desktop connections', positionals: [{ name: 'agent' }], options: {
|
|
1302
1352
|
remove: { type: 'boolean', description: 'Remove this agent’s managed entries, or all entries for this API URL.' },
|
|
@@ -1374,12 +1424,97 @@ const SETTINGS_COMMANDS = [{
|
|
|
1374
1424
|
description: 'Shows the title marker, where new conversations open and the terminal app (change those two with "shard agents targets --open-in" and "--terminal"). The menu bar and desktop apps change the same settings.',
|
|
1375
1425
|
examples: ['shard settings', 'shard settings --title-prefix SF', 'shard settings --title-prefix none', 'shard settings --title-prefix default --json'],
|
|
1376
1426
|
}];
|
|
1377
|
-
|
|
1427
|
+
/** The board's input bar from a terminal (0.25.0+): route a line of input, ask a quick question about the work. */
|
|
1428
|
+
const BOARD_SCOPE = {
|
|
1429
|
+
org: { type: 'string', value: '<id|slug>', description: 'Organization whose board to read (default: the saved one, shard orgs use, else your only organization). Slugs need your signed-in session.' },
|
|
1430
|
+
project: { type: 'string', value: '<id|slug>', description: 'A project of it: the input leans to it when nothing else decides.' },
|
|
1431
|
+
};
|
|
1432
|
+
const BOARD_SCOPE_HELP = 'Reads your organization’s projects and open tasks with your signed-in session; with SHARDFLUX_API_KEY set (or only a saved project API key), that key’s project. It never starts work and never wakes a computer.';
|
|
1433
|
+
const ROUTER_COMMANDS = [
|
|
1434
|
+
{
|
|
1435
|
+
path: ['route'],
|
|
1436
|
+
summary: 'Route input like the board’s input bar: its project, task, question or steer, split per task (0.25.0+)',
|
|
1437
|
+
description: [
|
|
1438
|
+
'Decides which project the input belongs to (or your home, for personal work), whether it is a new task, a question or a steer for an open task, and splits input that asks for several tasks into your own words per task, each with a title. "?" or "quick question" at the start makes it a question.',
|
|
1439
|
+
BOARD_SCOPE_HELP,
|
|
1440
|
+
'Prints the kind and where it goes, then each part. With --json: the RouterResult (kind, parts with text, title, project_id and home, task_ref, confidence, uncertain, forced, routed_by, latency_ms).',
|
|
1441
|
+
].join('\n\n'),
|
|
1442
|
+
positionals: [{ name: 'text', variadic: true, words: true, required: true }],
|
|
1443
|
+
options: {
|
|
1444
|
+
task: { type: 'string', value: '<task-id>', description: 'The open task you point at (task_…): input about it steers it, unless it asks about it.' },
|
|
1445
|
+
...BOARD_SCOPE,
|
|
1446
|
+
},
|
|
1447
|
+
examples: ['shard route "fix the hero image on the landing page and add a GPU row to the pricing table"', 'shard route --task task_healthzhealthzhealthzhealt return 503 instead of 500 when the database is down', 'shard route "? is the deploy done" --json'],
|
|
1448
|
+
},
|
|
1449
|
+
{
|
|
1450
|
+
path: ['ask'],
|
|
1451
|
+
summary: 'Ask a quick question about your work, answered from the board as it is written (0.25.0+)',
|
|
1452
|
+
description: [
|
|
1453
|
+
'Answers from your tasks, their plans and states, sealed reports, the conversations behind them and what their agents last wrote. The answer streams to standard output as it is written; one that needs work ends with "Make it a task?".',
|
|
1454
|
+
BOARD_SCOPE_HELP,
|
|
1455
|
+
'With --json: the whole answer as one object (text, needs_work, sources, answered_by, first_token_ms, total_ms).',
|
|
1456
|
+
].join('\n\n'),
|
|
1457
|
+
positionals: [{ name: 'question', variadic: true, words: true, required: true }],
|
|
1458
|
+
options: {
|
|
1459
|
+
task: { type: 'string', value: '<task-id>', description: 'The task the question is about (task_…).' },
|
|
1460
|
+
...BOARD_SCOPE,
|
|
1461
|
+
},
|
|
1462
|
+
examples: ['shard ask what is the healthz work doing right now', 'shard ask --task task_healthzhealthzhealthzhealt "is it done?"', 'shard ask "what is blocking the pricing page?" --json'],
|
|
1463
|
+
},
|
|
1464
|
+
];
|
|
1465
|
+
/** The project a drive or models command acts in (0.25.0+). */
|
|
1466
|
+
const PROJECT_SCOPE = {
|
|
1467
|
+
project: { type: 'string', value: '<id|slug>', description: 'The project (default: the API key’s, else your default project). Signed in, any of your projects, by id or slug.' },
|
|
1468
|
+
};
|
|
1469
|
+
const DRIVE_HELP = 'The project drive keeps a project’s files: the screenshots, logs, reports and notes your agents and people save and read by path, the same from a phone, a script or another agent whether the project’s computers are working, asleep or gone. Paths are relative to the project space root, the names agents see under /shardflux/project (tasks/t_ab12/evidence/healthz.png, BOARD.md). Every save is a new version named by the SHA-256 of its bytes, and every version stays readable by its sha256, also after the path is overwritten or removed.';
|
|
1470
|
+
const DRIVE_COMMANDS = [
|
|
1471
|
+
{ path: ['drive', 'ls'], summary: 'List the project drive’s files: size, saved time, type and path (0.25.0+)', positionals: [{ name: 'prefix' }], options: {
|
|
1472
|
+
...PROJECT_SCOPE,
|
|
1473
|
+
all: { type: 'boolean', description: 'Fetch every page.' },
|
|
1474
|
+
limit: { type: 'string', value: '<n>', description: 'Page size (1 to 1000, default 200).' },
|
|
1475
|
+
cursor: { type: 'string', value: '<cursor>', description: 'Continue from a previous page.' },
|
|
1476
|
+
}, description: `${DRIVE_HELP} Lists the current version of each file, by path; a prefix such as tasks/t_ab12/ lists only that folder. --json returns data (each file with its sha256) and next_cursor.`,
|
|
1477
|
+
examples: ['shard drive ls', 'shard drive ls tasks/t_ab12/evidence/', 'shard drive ls --all --json'] },
|
|
1478
|
+
{ path: ['drive', 'get'], summary: 'Read a file from the project drive: its bytes to standard output, or to a file with -o (0.25.0+)', positionals: [{ name: 'path', required: true }], options: {
|
|
1479
|
+
...PROJECT_SCOPE,
|
|
1480
|
+
sha256: { type: 'string', value: '<hex>', description: 'Read exactly this version (the current one or an earlier one).' },
|
|
1481
|
+
out: { type: 'string', short: 'o', value: '<file>', description: 'Write the bytes to this file.' },
|
|
1482
|
+
}, description: `${DRIVE_HELP} The bytes are checked against their SHA-256 before they are written. --json without -o returns the file as content_base64 with its sha256, size and content_type.`,
|
|
1483
|
+
examples: ['shard drive get BOARD.md', 'shard drive get tasks/t_ab12/evidence/healthz.png -o healthz.png', 'shard drive get BOARD.md --sha256 9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08'] },
|
|
1484
|
+
{ path: ['drive', 'put'], summary: 'Save a file to the project drive as a new version, and print its path and sha256 (0.25.0+)', positionals: [{ name: 'local-file', required: true }, { name: 'drive-path' }], options: {
|
|
1485
|
+
...PROJECT_SCOPE,
|
|
1486
|
+
'content-type': { type: 'string', value: '<type>', description: 'Stored with the file (default: from its extension, e.g. .png image/png, .md text/markdown).' },
|
|
1487
|
+
}, description: `${DRIVE_HELP} The drive path defaults to the file’s name; - reads the file from standard input (name the drive path). Saving the bytes that are already current keeps that version.`,
|
|
1488
|
+
examples: ['shard drive put BOARD.md', 'shard drive put ./out/healthz.png tasks/t_ab12/evidence/healthz.png', 'git diff | shard drive put - tasks/t_ab12/review.diff --json'] },
|
|
1489
|
+
{ path: ['drive', 'rm'], summary: 'Remove a file from the project drive; its versions stay readable by sha256 (0.25.0+)', positionals: [{ name: 'path', required: true }], options: { ...PROJECT_SCOPE },
|
|
1490
|
+
description: `${DRIVE_HELP} After rm the path no longer lists or reads; shard drive get <path> --sha256 <hex> still reads each of its versions.`,
|
|
1491
|
+
examples: ['shard drive rm tasks/t_ab12/notes/draft.md'] },
|
|
1492
|
+
];
|
|
1493
|
+
const MODELS_HELP = 'The model template: which agent app (harness), model and effort each role of a task runs with, from the Claude and Codex accounts your organization connected. master plans and coordinates, builder does the work, hard takes the hardest parts, light the small ones, and reviewer reviews with a fresh context. The primary provider runs master, builder and hard; the other one, light and reviewer. A role whose account waits for its next usage window shows until when, and what the other provider would run now.';
|
|
1494
|
+
const MODEL_COMMANDS = [
|
|
1495
|
+
{ path: ['models'], summary: 'Show which harness, model and effort each role of a task runs with (0.25.0+)', positionals: [], options: {
|
|
1496
|
+
...PROJECT_SCOPE,
|
|
1497
|
+
harness: { type: 'string', value: '<claude|codex>', description: 'The provider the task runs on: keeps master, builder and hard work on it.' },
|
|
1498
|
+
attempt: { type: 'string', value: '<n>', description: 'A retry after a failure (1 to 10): retries move to the other provider, or one tier up when only one is connected.' },
|
|
1499
|
+
}, description: `${MODELS_HELP} --json returns the template: primary, secondary, connected and roles, with each role’s harness, model and effort exactly as shard conversations start --app, --model and --effort take them.`,
|
|
1500
|
+
examples: ['shard models', 'shard models --harness codex --attempt 1', 'shard models --json'] },
|
|
1501
|
+
{ path: ['models', 'primary'], summary: 'Make Claude or Codex the primary provider of this project or your organization, or clear it (0.25.0+)', positionals: [{ name: 'claude|codex|clear', required: true }], options: {
|
|
1502
|
+
...PROJECT_SCOPE,
|
|
1503
|
+
org: { type: 'string', value: '<id|slug>', description: 'Set the organization’s default for every project instead (owners and admins, signed in).' },
|
|
1504
|
+
}, description: `${MODELS_HELP} The primary is this project’s choice when it has one, else the organization’s, else the provider connected first; clear removes the choice. Prints the template with the new primary.`,
|
|
1505
|
+
examples: ['shard models primary codex', 'shard models primary claude --org acme', 'shard models primary clear --project web'] },
|
|
1506
|
+
];
|
|
1507
|
+
export const COMMANDS = [...ACCOUNT_COMMANDS.filter((c) => c.path[0] !== 'templates'), ...AGENT_COMMANDS, ...ROUTER_COMMANDS, ...AGENT_CREDENTIAL_COMMANDS, ...AGENT_ACCOUNT_COMMANDS, ...ACCOUNT_ALIASES, ...CLI_PROXY_COMMANDS, ...MENUBAR_COMMANDS, ...SETTINGS_COMMANDS, ...KEY_COMMANDS, ...BOARD_COMMANDS, ...DRIVE_COMMANDS, ...MODEL_COMMANDS, ...ACCOUNT_COMMANDS.filter((c) => c.path[0] === 'templates')];
|
|
1378
1508
|
const GROUPS = {
|
|
1379
1509
|
device: 'Local device approvals',
|
|
1380
1510
|
'cli-proxy': 'Your hosted CLIProxyAPI, reachable at http://127.0.0.1:8317 on this computer and in every VM',
|
|
1381
1511
|
menubar: 'macOS menu bar app',
|
|
1382
1512
|
conversations: 'Project conversations, branches and messages',
|
|
1513
|
+
task: 'Tasks on the board, in your own words: add, show, edit, move, steer, delete and clear them (0.25.0+)',
|
|
1514
|
+
'needs-you': 'Everything your agents wait on, oldest first, and one answer command for each (0.25.0+)',
|
|
1515
|
+
approvals: 'The approval mode and always-allow rules your agents work under (0.25.0+)',
|
|
1516
|
+
drive: 'The project drive: files every agent, phone and person of the project reads and writes, each version kept by its SHA-256 (0.25.0+)',
|
|
1517
|
+
models: 'The model template: which harness, model and effort each role of a task runs with, and the primary provider (0.25.0+)',
|
|
1383
1518
|
agents: 'Cloud agent sessions and copied credentials',
|
|
1384
1519
|
auth: 'Create an account and sign in (the session is saved in the credentials file); passwords, email, two-factor authentication and sessions',
|
|
1385
1520
|
'auth password': 'Change or reset your password',
|
|
@@ -1692,6 +1827,17 @@ export function parseCommandLine(argv, options = {}) {
|
|
|
1692
1827
|
if (positionals[1] === undefined && flagged[0] !== undefined && positionals.length === 1)
|
|
1693
1828
|
positionals.push(flagged[0]);
|
|
1694
1829
|
}
|
|
1830
|
+
if (command.path[0] === 'volumes' && ['attach', 'detach'].includes(command.path[1] ?? '')) {
|
|
1831
|
+
if (values.machine === true && values.template === true)
|
|
1832
|
+
throw new UsageError('Choose --machine or --template');
|
|
1833
|
+
if (values.path !== undefined && values.template !== true)
|
|
1834
|
+
throw new UsageError('--path requires --template');
|
|
1835
|
+
const defaults = values.machine === true || values.template === true;
|
|
1836
|
+
if (positionals.length < (defaults ? 1 : 2))
|
|
1837
|
+
throw new UsageError(`missing <volume> for "shard ${command.path.join(' ')}"`);
|
|
1838
|
+
if (defaults && positionals.length !== 1)
|
|
1839
|
+
throw new UsageError('Supply one volume with --machine or --template');
|
|
1840
|
+
}
|
|
1695
1841
|
const specs = command.positionals;
|
|
1696
1842
|
const variadic = specs.at(-1)?.variadic === true;
|
|
1697
1843
|
const required = specs.filter((s) => s.required && !s.variadic).length;
|
|
@@ -1781,7 +1927,7 @@ export const EXIT_CODE_HELP = [
|
|
|
1781
1927
|
/** The top help's sections: every command's group (first word) is in exactly one (args.test.ts checks). */
|
|
1782
1928
|
export const HELP_SECTIONS = [
|
|
1783
1929
|
{ title: 'Account (a user session: shard signup or shard auth login)', groups: ['signup', 'verify', 'auth', 'setup', 'env', 'orgs', 'projects', 'api-keys', 'members', 'invitations', 'billing', 'audit', 'account'] },
|
|
1784
|
-
{ title: 'Cloud agents (shard ./ starts one; a project API key)', groups: ['conversations', 'move', 'machine', 'template', 'agents', 'settings', 'accounts', 'device', 'cli-proxy', 'ssh-proxy'] },
|
|
1930
|
+
{ title: 'Cloud agents (shard ./ starts one; a project API key)', groups: ['conversations', 'board', 'task', 'needs-you', 'approvals', 'route', 'ask', 'drive', 'models', 'move', 'machine', 'template', 'agents', 'settings', 'accounts', 'device', 'cli-proxy', 'ssh-proxy'] },
|
|
1785
1931
|
{ title: 'Workspaces for your app (a project API key: SHARDFLUX_API_KEY, else the one shard setup saved)', groups: ['login', 'whoami', 'status', 'usage', 'workspaces', 'files', 'operations', 'executions', 'secrets', 'credentials', 'volumes', 'egress'] },
|
|
1786
1932
|
{ title: 'Templates for your app’s workspaces (not for cloud agents; publish and archive use the session, the rest the API key)', groups: ['templates'] },
|
|
1787
1933
|
{ title: 'Other', groups: ['menubar', 'update', 'feedback', 'version'] },
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Orchestrator board's command table (0.25.0+, SDK 0.28.0): `shard board`, `shard task …`, `shard needs-you …` and
|
|
3
|
+
* `shard approvals …`. Pure data like args.ts, which merges it into COMMANDS; board-commands.ts has the handlers.
|
|
4
|
+
*/
|
|
5
|
+
import type { CommandSpec } from './args.js';
|
|
6
|
+
export declare const BOARD_COMMANDS: CommandSpec[];
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
const PROJECT_FILTER = { project: { type: 'string', value: '<id>', description: 'Only this project.' } };
|
|
2
|
+
const PROJECT = { project: { type: 'string', value: '<id>', description: 'The project (default: the API key’s).' } };
|
|
3
|
+
const BUCKET_FLAGS = (verb) => ({
|
|
4
|
+
now: { type: 'boolean', description: `${verb} Now.` },
|
|
5
|
+
next: { type: 'boolean', description: `${verb} Next.` },
|
|
6
|
+
later: { type: 'boolean', description: `${verb} Later.` },
|
|
7
|
+
});
|
|
8
|
+
const ORDER = {
|
|
9
|
+
after: { type: 'string', value: '<task-id>', description: 'Place it right after this task of its bucket.' },
|
|
10
|
+
first: { type: 'boolean', description: 'Place it first in its bucket.' },
|
|
11
|
+
};
|
|
12
|
+
const MODES = 'ask sends every permission request to you (shard needs-you); routine approves tests, builds, reads and installs for you; trusted approves everything except deploys, pushes to main and spending.';
|
|
13
|
+
export const BOARD_COMMANDS = [
|
|
14
|
+
{
|
|
15
|
+
path: ['board'],
|
|
16
|
+
summary: 'Show the board: what needs you, then every task in Now, Next and Later (0.25.0+)',
|
|
17
|
+
positionals: [],
|
|
18
|
+
options: { ...PROJECT_FILTER, follow: { type: 'boolean', short: 'f', description: 'Keep printing each change as it happens, until Ctrl-C.' } },
|
|
19
|
+
description: [
|
|
20
|
+
'One board on every device: what waits on you comes first, oldest first, each with its id (shard needs-you answer',
|
|
21
|
+
'takes it) and what is asked. Then the tasks of Now, Next and Later in order: id, state (queued, working, needs_you,',
|
|
22
|
+
'done, unverified, failed), title or your words, and project. Reading the board never wakes a computer.',
|
|
23
|
+
'',
|
|
24
|
+
'--follow keeps printing changes from the held feed: a changed task with its bucket (or deleted, cleared), a sealed',
|
|
25
|
+
'report with its evidence, what started or stopped waiting on you, the approval policy. --json prints the board;',
|
|
26
|
+
'with --follow, the board on the first line, then one feed answer per line.',
|
|
27
|
+
].join('\n'),
|
|
28
|
+
examples: ['shard board', 'shard board --follow', `shard board --json | jq -r '.needs_you[] | "\\(.id)\\t\\(.ask)"'`],
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
path: ['task', 'add'],
|
|
32
|
+
summary: 'Add a task in your own words (0.25.0+)',
|
|
33
|
+
positionals: [{ name: 'words', variadic: true, words: true, required: true }],
|
|
34
|
+
options: {
|
|
35
|
+
...PROJECT,
|
|
36
|
+
next: { type: 'boolean', description: 'Add it to Next (default: Now).' },
|
|
37
|
+
later: { type: 'boolean', description: 'Add it to Later.' },
|
|
38
|
+
home: { type: 'boolean', description: 'A personal task: it runs on the project’s machine home, without a repository.' },
|
|
39
|
+
after: { type: 'string', value: '<task-id>', description: 'Place it right after this task of its bucket (default: last).' },
|
|
40
|
+
first: { type: 'boolean', description: 'Place it first in its bucket.' },
|
|
41
|
+
},
|
|
42
|
+
description: 'Your words are kept exactly as you wrote them. The project’s master agent picks the task up and starts the work; its reports arrive on the board (shard task show). Prints the task id, its bucket and its state.',
|
|
43
|
+
examples: ['shard task add Fix the wake race in resume', 'shard task add --later "Try a shorter pricing headline"', 'shard task add --first Hotfix the login redirect'],
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
path: ['task', 'show'],
|
|
47
|
+
summary: 'Show a task, its plan and every report sealed for it (0.25.0+)',
|
|
48
|
+
positionals: [{ name: 'id', required: true }],
|
|
49
|
+
options: {},
|
|
50
|
+
description: 'Prints its title or your words, its state, bucket and project, your exact words, the plan with each step’s state, the conversations that work on it, then each report oldest first: milestone, title, outcome and evidence (tests 12/12, live probe 200, screenshot) with the command, URL or file behind each. --json returns {task, reports}.',
|
|
51
|
+
examples: ['shard task show task_h7g4d7tqyv2pz3a2npyo4rpgzq', 'shard task show task_h7g4d7tqyv2pz3a2npyo4rpgzq --json | jq ".reports[-1].evidence"'],
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
path: ['task', 'edit'],
|
|
55
|
+
summary: 'Edit, move, keep or clear a task (0.25.0+)',
|
|
56
|
+
positionals: [{ name: 'id', required: true }],
|
|
57
|
+
options: {
|
|
58
|
+
text: { type: 'string', value: '<words>', description: 'New words; its master hears the change.' },
|
|
59
|
+
title: { type: 'string', value: '<title>', description: 'A short title ("" removes it).' },
|
|
60
|
+
...BUCKET_FLAGS('Move it to'),
|
|
61
|
+
...ORDER,
|
|
62
|
+
keep: { type: 'boolean', description: 'Keep an agent’s suggestion as a task of your own.' },
|
|
63
|
+
clear: { type: 'boolean', description: 'Clear it from the board (--no-clear brings it back).' },
|
|
64
|
+
},
|
|
65
|
+
description: 'Moving a task (--now, --next, --later, --after, --first) sets the order its master works in. Prints the task as shard board lists it.',
|
|
66
|
+
examples: ['shard task edit task_h7g4d7tqyv2pz3a2npyo4rpgzq --first', 'shard task edit task_h7g4d7tqyv2pz3a2npyo4rpgzq --next --title "Wake race"', 'shard task edit task_h7g4d7tqyv2pz3a2npyo4rpgzq --keep'],
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
path: ['task', 'rm'],
|
|
70
|
+
summary: 'Delete a task; its master stops the work (0.25.0+)',
|
|
71
|
+
positionals: [{ name: 'id', required: true }],
|
|
72
|
+
options: {},
|
|
73
|
+
description: 'Its follow-ups go with it, on every device.',
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
path: ['task', 'steer'],
|
|
77
|
+
summary: 'Send steering words to a task’s master (0.25.0+)',
|
|
78
|
+
positionals: [{ name: 'id', required: true }, { name: 'words', variadic: true, words: true, required: true }],
|
|
79
|
+
options: {},
|
|
80
|
+
description: 'Your words go to the agent that runs the task, which adjusts its plan. The task keeps its own words.',
|
|
81
|
+
examples: ['shard task steer task_h7g4d7tqyv2pz3a2npyo4rpgzq use postgres instead'],
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
path: ['task', 'clear-done'],
|
|
85
|
+
summary: 'Clear every finished task from the board (0.25.0+)',
|
|
86
|
+
positionals: [],
|
|
87
|
+
options: PROJECT_FILTER,
|
|
88
|
+
description: 'Clears done and unverified tasks on every device. shard task show <id> still reads their reports.',
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
path: ['needs-you'],
|
|
92
|
+
summary: 'List what waits on you, oldest first (0.25.0+)',
|
|
93
|
+
positionals: [],
|
|
94
|
+
options: PROJECT_FILTER,
|
|
95
|
+
description: [
|
|
96
|
+
'Everything your agents wait on, across the board: permission requests (perm_…), questions (cq_…, ask_…),',
|
|
97
|
+
'credential requests (cred_…), finished work to land (land_…) and Later tasks to keep or clear (prune_…). Each line is',
|
|
98
|
+
'the id, what is asked, and the command, options or branch behind it. Answer with shard needs-you answer <id>.',
|
|
99
|
+
'--json returns {data}.',
|
|
100
|
+
].join('\n'),
|
|
101
|
+
examples: ['shard needs-you', 'shard needs-you --json'],
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
path: ['needs-you', 'answer'],
|
|
105
|
+
summary: 'Answer something that waits on you (0.25.0+)',
|
|
106
|
+
positionals: [{ name: 'id', required: true }, { name: 'decision' }],
|
|
107
|
+
options: {
|
|
108
|
+
everywhere: { type: 'boolean', description: 'With always: the rule covers every project.' },
|
|
109
|
+
text: { type: 'string', value: '<answer>', description: 'Your answer to an agent’s question.' },
|
|
110
|
+
pick: { type: 'string', multiple: true, value: '<option|question=option>', description: 'The option you pick for an agent’s question in a permission request (repeatable for a multi-select question; "<question>=<option>" when it asks several).' },
|
|
111
|
+
keep: { type: 'string', multiple: true, value: '<task-id>', description: 'Later tasks: keep these (repeatable); the rest are cleared.' },
|
|
112
|
+
},
|
|
113
|
+
description: [
|
|
114
|
+
'One command for every kind:',
|
|
115
|
+
' perm_… allow (this once), always (also adds the always-allow rule for the project; --everywhere for every',
|
|
116
|
+
' project) or deny; an agent’s question takes --pick',
|
|
117
|
+
' cq_… --text <answer>: the agent gets it as its next message',
|
|
118
|
+
' ask_… --text <answer>: the task’s master gets it',
|
|
119
|
+
' cred_… deny (the value goes through the credential request, sealed for its computer)',
|
|
120
|
+
' land_… land (the worker merges its branch and pushes it), keep (the branch stays) or discard',
|
|
121
|
+
' prune_… --keep <task-id> for each task to keep, keep for all of them, or discard to clear them',
|
|
122
|
+
'The agent goes on as soon as you answer.',
|
|
123
|
+
].join('\n'),
|
|
124
|
+
examples: ['shard needs-you answer perm_01a1300c-0000-7000-8000-000000000001 always', 'shard needs-you answer ask_rep_66cbevz65m72ij7mbiyrw4xvdy --text "eu-north-1"', 'shard needs-you answer land_conv_id4zts6jxsqraju2pggr55n3tq land'],
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
path: ['approvals'],
|
|
128
|
+
summary: 'Show the approval mode and the always-allow rules your agents work under (0.25.0+)',
|
|
129
|
+
positionals: [],
|
|
130
|
+
options: {},
|
|
131
|
+
description: `The mode answers the permission requests of your board’s conversations before they reach you: ${MODES} A rule always allows a tool for commands (or paths, URLs) that start with its pattern. Prints the default mode, each project’s own mode, then each rule: its id, tool, pattern and project.`,
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
path: ['approvals', 'set'],
|
|
135
|
+
summary: 'Set the approval mode of a project or the default (0.25.0+)',
|
|
136
|
+
positionals: [{ name: 'mode', required: true }],
|
|
137
|
+
options: { ...PROJECT, default: { type: 'boolean', description: 'Set the default mode, for every project without a mode of its own.' } },
|
|
138
|
+
description: `${MODES} default puts the project back on the default mode. Requests already waiting that the new mode covers are answered at once.`,
|
|
139
|
+
examples: ['shard approvals set trusted', 'shard approvals set ask --project 01a1415f-759f-7fb0-9d56-973ed5d27465', 'shard approvals set default'],
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
path: ['approvals', 'allow'],
|
|
143
|
+
summary: 'Always allow a tool for commands that start with a pattern (0.25.0+)',
|
|
144
|
+
positionals: [{ name: 'tool', required: true }, { name: 'pattern', variadic: true, words: true, required: true }],
|
|
145
|
+
options: { ...PROJECT, everywhere: { type: 'boolean', description: 'Cover every project.' } },
|
|
146
|
+
description: 'The tool as the agent’s harness names it (Bash, WebFetch, Edit) and the command prefix, path or URL it allows: "shard approvals allow Bash pnpm test" allows pnpm test and pnpm test --watch; "" allows every use of the tool. Waiting requests the rule covers are answered at once. Prints the rule’s id, tool, pattern and project.',
|
|
147
|
+
examples: ['shard approvals allow Bash pnpm test', 'shard approvals allow WebFetch https://docs.shardflux.dev/'],
|
|
148
|
+
},
|
|
149
|
+
{
|
|
150
|
+
path: ['approvals', 'remove'],
|
|
151
|
+
summary: 'Remove an always-allow rule (0.25.0+)',
|
|
152
|
+
positionals: [{ name: 'rule-id', required: true }],
|
|
153
|
+
options: {},
|
|
154
|
+
},
|
|
155
|
+
];
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Orchestrator board (0.25.0+, SDK 0.28.0): `shard board` (with --follow), `shard task add|show|edit|rm|steer|
|
|
3
|
+
* clear-done`, `shard needs-you [answer]` and `shard approvals [set|allow|remove]`. The command table is board-args.ts.
|
|
4
|
+
*
|
|
5
|
+
* Every command uses the project API key (SHARDFLUX_API_KEY, else the saved one): its board is the key's project.
|
|
6
|
+
* Text output is one line per item, tab-separated, id first; --json prints the API's objects.
|
|
7
|
+
*/
|
|
8
|
+
import type { ApprovalPolicy, ApprovalRule, Board, BoardUpdate, NeedsYouAnswer, NeedsYouAnswered, NeedsYouItem, Task, TaskDetail, TaskReport } from '@shardflux/sdk';
|
|
9
|
+
import type { Handler } from './commands.js';
|
|
10
|
+
/** A task as people read it: its title once it has one, else your words, on one line of at most `max` characters. */
|
|
11
|
+
export declare function taskLabel(t: Pick<Task, 'title' | 'text'>, max?: number): string;
|
|
12
|
+
/**
|
|
13
|
+
* One task as `shard board` lists it: id, state (with why it waits to start: "queued (Claude usage resets 15:00)"),
|
|
14
|
+
* title or words (a follow-up ↳, a suggestion marked), project.
|
|
15
|
+
*/
|
|
16
|
+
export declare function taskLine(t: Task): string;
|
|
17
|
+
/** One item that waits on you: its id, what is asked, then the command, the suggested answers or the branch behind it. */
|
|
18
|
+
export declare function needsLine(n: NeedsYouItem): string;
|
|
19
|
+
/** A sealed report as --follow prints it: id, milestone, title, then its evidence labels. */
|
|
20
|
+
export declare function reportLine(r: TaskReport): string;
|
|
21
|
+
/** The board as text: Needs you first (oldest first), then Now, Next and Later in their order. */
|
|
22
|
+
export declare function boardText(b: Pick<Board, 'tasks' | 'needs_you'>): string;
|
|
23
|
+
/** The approval policy on one line: the default, each project's own mode, the number of rules. */
|
|
24
|
+
export declare function policyLine(p: ApprovalPolicy): string;
|
|
25
|
+
/** One always-allow rule: id, tool, the pattern it allows, its project. */
|
|
26
|
+
export declare function ruleLine(r: ApprovalRule): string;
|
|
27
|
+
/** `shard approvals`: the default mode, each project's own mode, then each rule. */
|
|
28
|
+
export declare function policyText(p: ApprovalPolicy): string;
|
|
29
|
+
/**
|
|
30
|
+
* `shard board --follow`: the lines of each feed answer. A changed task is its board line plus its bucket (deleted,
|
|
31
|
+
* cleared once gone); a sealed report its report line; an item that started waiting on you its needs line, one that
|
|
32
|
+
* stopped `<id>\tresolved`; a policy change one line. After a reset the whole board is printed again.
|
|
33
|
+
*/
|
|
34
|
+
export declare class BoardFollower {
|
|
35
|
+
#private;
|
|
36
|
+
constructor(board: Pick<Board, 'needs_you'>);
|
|
37
|
+
next(u: BoardUpdate): string;
|
|
38
|
+
}
|
|
39
|
+
/** A feed answer as `board --follow --json` prints it: the API's fields (with `board` after a reset). */
|
|
40
|
+
export declare function feedJson(u: BoardUpdate): Record<string, unknown>;
|
|
41
|
+
/** `shard task show`: the task, its plan and conversations, then every report oldest first with its evidence. */
|
|
42
|
+
export declare function taskDetailText(d: TaskDetail): string;
|
|
43
|
+
/** An item's kind from its id (perm_, cq_, ask_, cred_, land_, prune_); undefined for another id. */
|
|
44
|
+
export declare function itemKind(id: string): NeedsYouItem['kind'] | undefined;
|
|
45
|
+
export interface AnswerInput {
|
|
46
|
+
word?: string | undefined;
|
|
47
|
+
text?: string | undefined;
|
|
48
|
+
picks: readonly string[];
|
|
49
|
+
keep: readonly string[];
|
|
50
|
+
everywhere: boolean;
|
|
51
|
+
}
|
|
52
|
+
/** Whether the answer needs the item itself: the questions of a permission request, every task of a prune prompt. */
|
|
53
|
+
export declare const answerNeedsItem: (id: string, a: AnswerInput) => boolean;
|
|
54
|
+
/**
|
|
55
|
+
* The API answer for item `id` from the command's words and options, checked before anything is sent: each kind takes
|
|
56
|
+
* its own (needs-you.ts). `item` is the waiting item when answerNeedsItem says it is needed; without it such an answer
|
|
57
|
+
* is only checked (its `answers` or `keep` come back empty).
|
|
58
|
+
*/
|
|
59
|
+
export declare function needsAnswer(id: string, a: AnswerInput, item?: NeedsYouItem): NeedsYouAnswer;
|
|
60
|
+
/** What an answer did, in one line. */
|
|
61
|
+
export declare function answeredText(r: NeedsYouAnswered, a: NeedsYouAnswer): string;
|
|
62
|
+
export declare const BOARD_HANDLERS: Record<string, Handler>;
|