orkestrator 2.29.0-beta → 2.30.0-beta
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/dist/client.js +956 -335
- package/dist/main.js +172332 -153863
- package/package.json +5 -5
- package/resources/claude-bridge/dist/index.js +264 -195
- package/resources/codex-bridge/dist/index.js +343 -60
package/dist/client.js
CHANGED
|
@@ -6557,6 +6557,70 @@ var PUBLIC_ACTIONS = {
|
|
|
6557
6557
|
milestone: "D",
|
|
6558
6558
|
summary: "Read one page of a session's turns, each with the backend's change projection."
|
|
6559
6559
|
},
|
|
6560
|
+
"attention.list": {
|
|
6561
|
+
version: 1,
|
|
6562
|
+
mutation: false,
|
|
6563
|
+
effects: [],
|
|
6564
|
+
observation: "immediate",
|
|
6565
|
+
milestone: "D",
|
|
6566
|
+
summary: "What needs attention: pending questions and approvals, the caller's runs that settled and environments whose setup finished, since a cursor."
|
|
6567
|
+
},
|
|
6568
|
+
"ticket.list": {
|
|
6569
|
+
version: 1,
|
|
6570
|
+
mutation: false,
|
|
6571
|
+
effects: [],
|
|
6572
|
+
observation: "immediate",
|
|
6573
|
+
milestone: "D",
|
|
6574
|
+
summary: "List a project's Kanban tickets."
|
|
6575
|
+
},
|
|
6576
|
+
"ticket.get": {
|
|
6577
|
+
version: 1,
|
|
6578
|
+
mutation: false,
|
|
6579
|
+
effects: [],
|
|
6580
|
+
observation: "immediate",
|
|
6581
|
+
milestone: "D",
|
|
6582
|
+
summary: "Read one Kanban ticket with its description, criteria and latest comments."
|
|
6583
|
+
},
|
|
6584
|
+
"ticket.create": {
|
|
6585
|
+
version: 1,
|
|
6586
|
+
mutation: true,
|
|
6587
|
+
effects: ["metadata"],
|
|
6588
|
+
observation: "receipt",
|
|
6589
|
+
milestone: "D",
|
|
6590
|
+
summary: "Create a Kanban ticket in a project."
|
|
6591
|
+
},
|
|
6592
|
+
"ticket.update": {
|
|
6593
|
+
version: 1,
|
|
6594
|
+
mutation: true,
|
|
6595
|
+
effects: ["metadata"],
|
|
6596
|
+
observation: "receipt",
|
|
6597
|
+
milestone: "D",
|
|
6598
|
+
summary: "Change a Kanban ticket's title, description, criteria or column."
|
|
6599
|
+
},
|
|
6600
|
+
"ticket.comment": {
|
|
6601
|
+
version: 1,
|
|
6602
|
+
mutation: true,
|
|
6603
|
+
effects: ["metadata"],
|
|
6604
|
+
observation: "receipt",
|
|
6605
|
+
milestone: "D",
|
|
6606
|
+
summary: "Append a comment to a Kanban ticket."
|
|
6607
|
+
},
|
|
6608
|
+
"mail.mailboxes": {
|
|
6609
|
+
version: 1,
|
|
6610
|
+
mutation: false,
|
|
6611
|
+
effects: [],
|
|
6612
|
+
observation: "immediate",
|
|
6613
|
+
milestone: "D",
|
|
6614
|
+
summary: "List agent mailboxes a message can be sent to."
|
|
6615
|
+
},
|
|
6616
|
+
"mail.send": {
|
|
6617
|
+
version: 1,
|
|
6618
|
+
mutation: true,
|
|
6619
|
+
effects: ["metadata"],
|
|
6620
|
+
observation: "receipt",
|
|
6621
|
+
milestone: "D",
|
|
6622
|
+
summary: "Place a message in one tab's inbox; external messages are never injected into a turn."
|
|
6623
|
+
},
|
|
6560
6624
|
"run.get": {
|
|
6561
6625
|
version: 1,
|
|
6562
6626
|
mutation: false,
|
|
@@ -6752,6 +6816,8 @@ var PUBLIC_API_LIMITS = Object.freeze({
|
|
|
6752
6816
|
transcriptTextMaxChars: 20000,
|
|
6753
6817
|
interactionsMax: 32,
|
|
6754
6818
|
historyMaxEntries: 100,
|
|
6819
|
+
attentionDefaultItems: 20,
|
|
6820
|
+
attentionMaxItems: 50,
|
|
6755
6821
|
responseMaxBytes: 8 * 1024 * 1024,
|
|
6756
6822
|
requestMaxBytes: 1024 * 1024,
|
|
6757
6823
|
execArgvMaxItems: 256,
|
|
@@ -7444,7 +7510,7 @@ import path4 from "path";
|
|
|
7444
7510
|
// ../../apps/backend/package.json
|
|
7445
7511
|
var package_default = {
|
|
7446
7512
|
name: "@orkestrator/backend",
|
|
7447
|
-
version: "2.
|
|
7513
|
+
version: "2.30.0-beta",
|
|
7448
7514
|
private: true,
|
|
7449
7515
|
type: "module",
|
|
7450
7516
|
exports: {
|
|
@@ -7459,7 +7525,7 @@ var package_default = {
|
|
|
7459
7525
|
"start:web-public": "bun dist/main.js --tailscale-serve --allowed-origins https://orkestrator.dev,https://www.orkestrator.dev",
|
|
7460
7526
|
test: "bun test --preload ../../tests/setup-node.ts src tests --parallel",
|
|
7461
7527
|
"test:workspace": "bun test --preload ../../tests/setup-node.ts src tests --only-failures ${ORKESTRATOR_TEST_TIMINGS_DIR:+--timings=$ORKESTRATOR_TEST_TIMINGS_DIR/backend.json --update-timings} $ORKESTRATOR_BACKEND_TEST_IGNORE --parallel=${ORKESTRATOR_BACKEND_TEST_WORKERS:-${ORKESTRATOR_TEST_WORKERS:-2}}",
|
|
7462
|
-
typecheck: "
|
|
7528
|
+
typecheck: "bun check -p tsconfig.json && bun check -p tsconfig.test.json"
|
|
7463
7529
|
},
|
|
7464
7530
|
dependencies: {
|
|
7465
7531
|
"@modelcontextprotocol/node": "2.1.1",
|
|
@@ -7998,269 +8064,37 @@ function runFixProcess(argv, version) {
|
|
|
7998
8064
|
});
|
|
7999
8065
|
}
|
|
8000
8066
|
|
|
8001
|
-
//
|
|
8002
|
-
|
|
8003
|
-
|
|
8004
|
-
|
|
8005
|
-
|
|
8006
|
-
|
|
8007
|
-
|
|
8008
|
-
|
|
8009
|
-
|
|
8010
|
-
type: "agent",
|
|
8011
|
-
inherits: true,
|
|
8012
|
-
application,
|
|
8013
|
-
description: "Agent platform used when a launch does not name one."
|
|
8014
|
-
},
|
|
8015
|
-
...AGENT_PLATFORM_KEYS.flatMap((platform) => [
|
|
8016
|
-
{
|
|
8017
|
-
key: `agent.${platform}.mode`,
|
|
8018
|
-
scope,
|
|
8019
|
-
type: "agent-mode",
|
|
8020
|
-
inherits: true,
|
|
8021
|
-
application,
|
|
8022
|
-
description: `Launch mode (native or terminal) for ${platform}.`
|
|
8023
|
-
},
|
|
8024
|
-
{
|
|
8025
|
-
key: `agent.${platform}.model`,
|
|
8026
|
-
scope,
|
|
8027
|
-
type: "string",
|
|
8028
|
-
inherits: true,
|
|
8029
|
-
application,
|
|
8030
|
-
description: `Default model for new ${platform} sessions.`
|
|
8031
|
-
},
|
|
8032
|
-
{
|
|
8033
|
-
key: `agent.${platform}.reasoningEffort`,
|
|
8034
|
-
scope,
|
|
8035
|
-
type: "string",
|
|
8036
|
-
inherits: true,
|
|
8037
|
-
application,
|
|
8038
|
-
description: `Default reasoning level for new ${platform} sessions.`
|
|
8039
|
-
},
|
|
8040
|
-
{
|
|
8041
|
-
key: `agent.${platform}.fastMode`,
|
|
8042
|
-
scope,
|
|
8043
|
-
type: "boolean",
|
|
8044
|
-
inherits: true,
|
|
8045
|
-
application,
|
|
8046
|
-
description: `Default speed for new ${platform} sessions (true is Fast).`
|
|
8047
|
-
}
|
|
8048
|
-
])
|
|
8049
|
-
];
|
|
8050
|
-
}
|
|
8051
|
-
var PUBLIC_PROJECT_SETTINGS = Object.freeze([
|
|
8052
|
-
{
|
|
8053
|
-
key: "defaultBranch",
|
|
8054
|
-
scope: "project",
|
|
8055
|
-
type: "string",
|
|
8056
|
-
inherits: false,
|
|
8057
|
-
application: "next-environment",
|
|
8058
|
-
description: "Branch new environments are created from."
|
|
8059
|
-
},
|
|
8060
|
-
{
|
|
8061
|
-
key: "prBaseBranch",
|
|
8062
|
-
scope: "project",
|
|
8063
|
-
type: "string",
|
|
8064
|
-
inherits: false,
|
|
8065
|
-
application: "applied",
|
|
8066
|
-
description: "Base branch for pull requests and diff baselines."
|
|
8067
|
-
},
|
|
8068
|
-
{
|
|
8069
|
-
key: "defaultPortMappings",
|
|
8070
|
-
scope: "project",
|
|
8071
|
-
type: "port-mappings",
|
|
8072
|
-
inherits: false,
|
|
8073
|
-
environmentTypes: ["container"],
|
|
8074
|
-
application: "next-environment",
|
|
8075
|
-
description: "Port mappings copied into new container environments."
|
|
8076
|
-
},
|
|
8077
|
-
{
|
|
8078
|
-
key: "filesToCopy",
|
|
8079
|
-
scope: "project",
|
|
8080
|
-
type: "string-list",
|
|
8081
|
-
inherits: false,
|
|
8082
|
-
application: "next-environment",
|
|
8083
|
-
description: "Untracked files copied into new environments."
|
|
8084
|
-
},
|
|
8085
|
-
{
|
|
8086
|
-
key: "entryPort",
|
|
8087
|
-
scope: "project",
|
|
8088
|
-
type: "port",
|
|
8089
|
-
inherits: false,
|
|
8090
|
-
application: "next-environment",
|
|
8091
|
-
description: "Default preview entry port for new environments."
|
|
8092
|
-
},
|
|
8093
|
-
...agentSettingDescriptors("project")
|
|
8094
|
-
]);
|
|
8095
|
-
var PUBLIC_ENVIRONMENT_SETTINGS = Object.freeze([
|
|
8096
|
-
{
|
|
8097
|
-
key: "portMappings",
|
|
8098
|
-
scope: "environment",
|
|
8099
|
-
type: "port-mappings",
|
|
8100
|
-
inherits: false,
|
|
8101
|
-
environmentTypes: ["container"],
|
|
8102
|
-
application: "next-start",
|
|
8103
|
-
description: "Container port mappings; a running container adopts them on recreate."
|
|
8104
|
-
},
|
|
8105
|
-
{
|
|
8106
|
-
key: "allowedDomains",
|
|
8107
|
-
scope: "environment",
|
|
8108
|
-
type: "domain-list",
|
|
8109
|
-
inherits: true,
|
|
8110
|
-
environmentTypes: ["container"],
|
|
8111
|
-
application: "next-start",
|
|
8112
|
-
description: "Restricted-network allowlist; unset inherits the global list. A running container whose image supports it applies the change immediately (reported as applied)."
|
|
8113
|
-
},
|
|
8114
|
-
...agentSettingDescriptors("environment")
|
|
8115
|
-
]);
|
|
8116
|
-
|
|
8117
|
-
// src/client/format.ts
|
|
8118
|
-
function table(headers, rows) {
|
|
8119
|
-
if (rows.length === 0)
|
|
8120
|
-
return ["(none)"];
|
|
8121
|
-
const widths = headers.map((header, index) => Math.min(60, Math.max(header.length, ...rows.map((row) => (row[index] ?? "").length))));
|
|
8122
|
-
const line = (cells) => cells.map((cell, index) => {
|
|
8123
|
-
const text = cell.length > widths[index] ? `${cell.slice(0, widths[index] - 1)}\u2026` : cell;
|
|
8124
|
-
return text.padEnd(widths[index]);
|
|
8125
|
-
}).join(" ").trimEnd();
|
|
8126
|
-
return [line(headers), ...rows.map(line)];
|
|
8067
|
+
// src/client/wait.ts
|
|
8068
|
+
class ObservationStopped extends Error {
|
|
8069
|
+
reason;
|
|
8070
|
+
signalName;
|
|
8071
|
+
constructor(reason, signalName) {
|
|
8072
|
+
super(reason === "deadline" ? "Observation deadline passed" : "Observation interrupted");
|
|
8073
|
+
this.reason = reason;
|
|
8074
|
+
this.signalName = signalName;
|
|
8075
|
+
}
|
|
8127
8076
|
}
|
|
8128
|
-
function
|
|
8129
|
-
|
|
8130
|
-
|
|
8131
|
-
|
|
8132
|
-
|
|
8077
|
+
function defaultSleep(ms, signal) {
|
|
8078
|
+
return new Promise((resolve) => {
|
|
8079
|
+
if (signal?.aborted) {
|
|
8080
|
+
resolve();
|
|
8081
|
+
return;
|
|
8082
|
+
}
|
|
8083
|
+
const timer = setTimeout(done, ms);
|
|
8084
|
+
function done() {
|
|
8085
|
+
clearTimeout(timer);
|
|
8086
|
+
signal?.removeEventListener("abort", done);
|
|
8087
|
+
resolve();
|
|
8088
|
+
}
|
|
8089
|
+
signal?.addEventListener("abort", done, { once: true });
|
|
8133
8090
|
});
|
|
8134
8091
|
}
|
|
8135
|
-
function
|
|
8136
|
-
return
|
|
8137
|
-
["id", project.id],
|
|
8138
|
-
["name", project.name],
|
|
8139
|
-
["remote", project.gitUrl],
|
|
8140
|
-
["path", project.localPath],
|
|
8141
|
-
["folder", project.folder],
|
|
8142
|
-
["environments", project.environmentCount],
|
|
8143
|
-
["revision", project.revision]
|
|
8144
|
-
]);
|
|
8145
|
-
}
|
|
8146
|
-
function projectRows(projects) {
|
|
8147
|
-
return table(["ID", "NAME", "ENVS", "PATH"], projects.map((project) => [
|
|
8148
|
-
project.id,
|
|
8149
|
-
project.name,
|
|
8150
|
-
String(project.environmentCount),
|
|
8151
|
-
project.localPath ?? "-"
|
|
8152
|
-
]));
|
|
8153
|
-
}
|
|
8154
|
-
function environmentLines(environment) {
|
|
8155
|
-
return keyValues([
|
|
8156
|
-
["id", environment.id],
|
|
8157
|
-
["project", environment.projectId],
|
|
8158
|
-
["name", environment.name],
|
|
8159
|
-
["branch", environment.branch],
|
|
8160
|
-
["type", environment.environmentType],
|
|
8161
|
-
["status", environment.status],
|
|
8162
|
-
["ready", environment.ready],
|
|
8163
|
-
["setup", `${environment.setup.phase}${environment.setup.overridden ? " (overridden)" : ""}`],
|
|
8164
|
-
["activity", environment.activity.state],
|
|
8165
|
-
["lifecycle error", environment.lifecycle.error],
|
|
8166
|
-
["workspace", environment.workspacePath],
|
|
8167
|
-
["base", environment.base.commit ?? environment.base.branch],
|
|
8168
|
-
["startup session", environment.startupSession?.sessionId]
|
|
8169
|
-
]);
|
|
8092
|
+
function signalName(signal) {
|
|
8093
|
+
return signal?.reason === "SIGTERM" ? "SIGTERM" : "SIGINT";
|
|
8170
8094
|
}
|
|
8171
|
-
function
|
|
8172
|
-
|
|
8173
|
-
|
|
8174
|
-
environment.name,
|
|
8175
|
-
environment.environmentType,
|
|
8176
|
-
environment.status,
|
|
8177
|
-
environment.ready ? "yes" : "no"
|
|
8178
|
-
]));
|
|
8179
|
-
}
|
|
8180
|
-
function sessionRows(sessions) {
|
|
8181
|
-
return table(["SESSION", "AGENT", "TAB", "ACTIVITY", "TITLE"], sessions.map((session) => [
|
|
8182
|
-
session.id,
|
|
8183
|
-
session.agent,
|
|
8184
|
-
session.tabId,
|
|
8185
|
-
session.activity,
|
|
8186
|
-
session.title ?? ""
|
|
8187
|
-
]));
|
|
8188
|
-
}
|
|
8189
|
-
function sessionLines(session) {
|
|
8190
|
-
return keyValues([
|
|
8191
|
-
["id", session.id],
|
|
8192
|
-
["environment", session.environmentId],
|
|
8193
|
-
["tab", session.tabId],
|
|
8194
|
-
["agent", session.agent],
|
|
8195
|
-
["title", session.title],
|
|
8196
|
-
["activity", session.activity],
|
|
8197
|
-
["latest request", session.latestRequestId],
|
|
8198
|
-
["pending interactions", session.pendingInteractionCount],
|
|
8199
|
-
["recoverable dispatch", session.recoverableDispatch]
|
|
8200
|
-
]);
|
|
8201
|
-
}
|
|
8202
|
-
function receiptLines(receipt) {
|
|
8203
|
-
return keyValues([
|
|
8204
|
-
["operation", receipt.operationId],
|
|
8205
|
-
["action", receipt.action],
|
|
8206
|
-
["state", receipt.state],
|
|
8207
|
-
["stage", receipt.stage],
|
|
8208
|
-
["request", `${receipt.requestId} (${receipt.namespace})`],
|
|
8209
|
-
["replayed", receipt.replayed],
|
|
8210
|
-
["resources", receipt.resources],
|
|
8211
|
-
["dispatch", receipt.dispatch?.state],
|
|
8212
|
-
["execution", receipt.execution?.state],
|
|
8213
|
-
["evidence", receipt.execution?.evidence],
|
|
8214
|
-
["exit code", receipt.execution?.exitCode],
|
|
8215
|
-
["error", receipt.error ? `${receipt.error.code}: ${receipt.error.message}` : undefined],
|
|
8216
|
-
["updated", receipt.updatedAt],
|
|
8217
|
-
["retained until", receipt.retainedUntil]
|
|
8218
|
-
]);
|
|
8219
|
-
}
|
|
8220
|
-
function settingsLines(snapshot) {
|
|
8221
|
-
return [
|
|
8222
|
-
`revision ${snapshot.revision}`,
|
|
8223
|
-
...table(["KEY", "VALUE", "EFFECTIVE", "SOURCE", "APPLIES"], snapshot.settings.map((setting) => [
|
|
8224
|
-
setting.key,
|
|
8225
|
-
setting.value === null || setting.value === undefined ? "-" : JSON.stringify(setting.value),
|
|
8226
|
-
setting.effective === null || setting.effective === undefined ? "-" : JSON.stringify(setting.effective),
|
|
8227
|
-
setting.source,
|
|
8228
|
-
setting.application
|
|
8229
|
-
]))
|
|
8230
|
-
];
|
|
8231
|
-
}
|
|
8232
|
-
|
|
8233
|
-
// src/client/wait.ts
|
|
8234
|
-
class ObservationStopped extends Error {
|
|
8235
|
-
reason;
|
|
8236
|
-
signalName;
|
|
8237
|
-
constructor(reason, signalName) {
|
|
8238
|
-
super(reason === "deadline" ? "Observation deadline passed" : "Observation interrupted");
|
|
8239
|
-
this.reason = reason;
|
|
8240
|
-
this.signalName = signalName;
|
|
8241
|
-
}
|
|
8242
|
-
}
|
|
8243
|
-
function defaultSleep(ms, signal) {
|
|
8244
|
-
return new Promise((resolve) => {
|
|
8245
|
-
if (signal?.aborted) {
|
|
8246
|
-
resolve();
|
|
8247
|
-
return;
|
|
8248
|
-
}
|
|
8249
|
-
const timer = setTimeout(done, ms);
|
|
8250
|
-
function done() {
|
|
8251
|
-
clearTimeout(timer);
|
|
8252
|
-
signal?.removeEventListener("abort", done);
|
|
8253
|
-
resolve();
|
|
8254
|
-
}
|
|
8255
|
-
signal?.addEventListener("abort", done, { once: true });
|
|
8256
|
-
});
|
|
8257
|
-
}
|
|
8258
|
-
function signalName(signal) {
|
|
8259
|
-
return signal?.reason === "SIGTERM" ? "SIGTERM" : "SIGINT";
|
|
8260
|
-
}
|
|
8261
|
-
function throwIfInterrupted(signal) {
|
|
8262
|
-
if (signal?.aborted)
|
|
8263
|
-
throw new CliError("observation-interrupted", "Interrupted");
|
|
8095
|
+
function throwIfInterrupted(signal) {
|
|
8096
|
+
if (signal?.aborted)
|
|
8097
|
+
throw new CliError("observation-interrupted", "Interrupted");
|
|
8264
8098
|
}
|
|
8265
8099
|
async function observe(check, options2) {
|
|
8266
8100
|
if (options2.timeoutMs > PUBLIC_API_LIMITS.waitMaxMs) {
|
|
@@ -8284,6 +8118,61 @@ async function observe(check, options2) {
|
|
|
8284
8118
|
}
|
|
8285
8119
|
}
|
|
8286
8120
|
|
|
8121
|
+
// ../protocol/src/public-api-wait.ts
|
|
8122
|
+
function isTerminalPublicReceipt(receipt) {
|
|
8123
|
+
return !["admitted", "running", "unknown"].includes(receipt.state);
|
|
8124
|
+
}
|
|
8125
|
+
function classifyReceiptForWait(receipt, options2 = {}) {
|
|
8126
|
+
if (isTerminalPublicReceipt(receipt)) {
|
|
8127
|
+
return { kind: "terminal", succeeded: receipt.state === "succeeded" };
|
|
8128
|
+
}
|
|
8129
|
+
const execution = receipt.execution;
|
|
8130
|
+
if (execution?.state === "waiting-for-input" && !options2.continueOnInteraction) {
|
|
8131
|
+
return {
|
|
8132
|
+
kind: "stopped",
|
|
8133
|
+
code: "interaction-required",
|
|
8134
|
+
message: "The run is waiting for an answer to a pending interaction",
|
|
8135
|
+
interactions: execution.interactions ?? []
|
|
8136
|
+
};
|
|
8137
|
+
}
|
|
8138
|
+
if (receipt.state === "unknown" && receipt.dispatch?.state === "unknown") {
|
|
8139
|
+
return {
|
|
8140
|
+
kind: "stopped",
|
|
8141
|
+
code: "dispatch-unknown",
|
|
8142
|
+
message: "The provider may or may not have received the prompt; retry it under the same key or discard it",
|
|
8143
|
+
retryable: true
|
|
8144
|
+
};
|
|
8145
|
+
}
|
|
8146
|
+
if (receipt.state === "unknown") {
|
|
8147
|
+
return {
|
|
8148
|
+
kind: "stopped",
|
|
8149
|
+
code: "run-unknown",
|
|
8150
|
+
message: receipt.error?.message ?? "The outcome of this run is not known"
|
|
8151
|
+
};
|
|
8152
|
+
}
|
|
8153
|
+
if (execution?.state === "unsupported") {
|
|
8154
|
+
return {
|
|
8155
|
+
kind: "stopped",
|
|
8156
|
+
code: "capability-unavailable",
|
|
8157
|
+
message: execution.reason ?? "Completion of this run cannot be observed for its provider"
|
|
8158
|
+
};
|
|
8159
|
+
}
|
|
8160
|
+
return { kind: "pending" };
|
|
8161
|
+
}
|
|
8162
|
+
function terminalReceiptErrorCode(receipt) {
|
|
8163
|
+
if (receipt.state === "succeeded")
|
|
8164
|
+
return null;
|
|
8165
|
+
if (receipt.state === "partial")
|
|
8166
|
+
return "partial-failure";
|
|
8167
|
+
if (receipt.state === "cancelled")
|
|
8168
|
+
return "run-cancelled";
|
|
8169
|
+
if (receipt.state === "interrupted")
|
|
8170
|
+
return "run-interrupted";
|
|
8171
|
+
if (receipt.state === "unknown")
|
|
8172
|
+
return "run-unknown";
|
|
8173
|
+
return receipt.error?.code ?? "operation-failed";
|
|
8174
|
+
}
|
|
8175
|
+
|
|
8287
8176
|
// src/client/commands/common.ts
|
|
8288
8177
|
var REQUEST_ID_OPTION = {
|
|
8289
8178
|
name: "request-id",
|
|
@@ -8394,7 +8283,7 @@ async function readOperation(session, operationId, timeoutMs) {
|
|
|
8394
8283
|
return receipt;
|
|
8395
8284
|
}
|
|
8396
8285
|
function isTerminalReceipt(receipt) {
|
|
8397
|
-
return
|
|
8286
|
+
return isTerminalPublicReceipt(receipt);
|
|
8398
8287
|
}
|
|
8399
8288
|
function stoppedError(error, action, receipt, what) {
|
|
8400
8289
|
if (error.reason === "signal") {
|
|
@@ -8410,12 +8299,15 @@ function stoppedError(error, action, receipt, what) {
|
|
|
8410
8299
|
});
|
|
8411
8300
|
}
|
|
8412
8301
|
function receiptFailure(receipt) {
|
|
8413
|
-
|
|
8302
|
+
const code = terminalReceiptErrorCode(receipt);
|
|
8303
|
+
if (!code)
|
|
8414
8304
|
return;
|
|
8415
8305
|
const message = receipt.error?.message ?? `Operation ended ${receipt.state}`;
|
|
8416
|
-
const code = receipt.state === "partial" ? "partial-failure" : receipt.state === "cancelled" ? "run-cancelled" : receipt.state === "interrupted" ? "run-interrupted" : receipt.state === "unknown" ? "run-unknown" : receipt.error?.code ?? "operation-failed";
|
|
8417
8306
|
return new CliError(code, message, { receipt, action: receipt.action });
|
|
8418
8307
|
}
|
|
8308
|
+
var CLI_STOP_MESSAGES = {
|
|
8309
|
+
"dispatch-unknown": "The provider may or may not have received the prompt; use `run retry` (same key) or `run discard`"
|
|
8310
|
+
};
|
|
8419
8311
|
async function waitForOperation(context, session, initial, timeoutMs, options2 = {}) {
|
|
8420
8312
|
let latest = initial;
|
|
8421
8313
|
const deadline = Date.now() + timeoutMs;
|
|
@@ -8432,94 +8324,423 @@ async function waitForOperation(context, session, initial, timeoutMs, options2 =
|
|
|
8432
8324
|
throw new ObservationStopped("deadline");
|
|
8433
8325
|
throw error;
|
|
8434
8326
|
}
|
|
8435
|
-
|
|
8327
|
+
const verdict = classifyReceiptForWait(latest, options2);
|
|
8328
|
+
if (verdict.kind === "terminal")
|
|
8436
8329
|
return { done: true, value: latest };
|
|
8437
|
-
|
|
8438
|
-
|
|
8439
|
-
throw new CliError("interaction-required", "The run is waiting for an answer to a pending interaction", {
|
|
8330
|
+
if (verdict.kind === "stopped") {
|
|
8331
|
+
throw new CliError(verdict.code, CLI_STOP_MESSAGES[verdict.code] ?? verdict.message, {
|
|
8440
8332
|
receipt: latest,
|
|
8441
8333
|
action: latest.action,
|
|
8442
|
-
|
|
8334
|
+
...verdict.retryable ? { retryable: true } : {},
|
|
8335
|
+
...verdict.interactions ? { details: { interactions: verdict.interactions } } : {}
|
|
8443
8336
|
});
|
|
8444
8337
|
}
|
|
8445
|
-
|
|
8446
|
-
|
|
8338
|
+
return { done: false };
|
|
8339
|
+
}, { timeoutMs, signal: context.signal });
|
|
8340
|
+
} catch (error) {
|
|
8341
|
+
if (error instanceof ObservationStopped) {
|
|
8342
|
+
throw stoppedError(error, latest.action, latest, "the operation");
|
|
8343
|
+
}
|
|
8344
|
+
throw error;
|
|
8345
|
+
}
|
|
8346
|
+
}
|
|
8347
|
+
async function waitForEnvironment(context, session, environmentId, condition, receipt, timeoutMs) {
|
|
8348
|
+
let latestReceipt = receipt;
|
|
8349
|
+
const conditionMet = (environment) => {
|
|
8350
|
+
if (condition === "deleted")
|
|
8351
|
+
return environment === null;
|
|
8352
|
+
if (!environment)
|
|
8353
|
+
return false;
|
|
8354
|
+
if (condition === "running")
|
|
8355
|
+
return environment.status === "running";
|
|
8356
|
+
if (condition === "stopped")
|
|
8357
|
+
return environment.status === "stopped";
|
|
8358
|
+
return environment.ready;
|
|
8359
|
+
};
|
|
8360
|
+
try {
|
|
8361
|
+
return await observe(async () => {
|
|
8362
|
+
if (latestReceipt && !isTerminalReceipt(latestReceipt)) {
|
|
8363
|
+
latestReceipt = await readOperation(session, latestReceipt.operationId);
|
|
8364
|
+
}
|
|
8365
|
+
if (latestReceipt && isTerminalReceipt(latestReceipt)) {
|
|
8366
|
+
const failure = receiptFailure(latestReceipt);
|
|
8367
|
+
if (failure)
|
|
8368
|
+
throw failure;
|
|
8447
8369
|
}
|
|
8448
|
-
|
|
8449
|
-
|
|
8450
|
-
|
|
8451
|
-
|
|
8370
|
+
let environment;
|
|
8371
|
+
try {
|
|
8372
|
+
environment = await session.read("environment.get", {
|
|
8373
|
+
environmentId
|
|
8452
8374
|
});
|
|
8375
|
+
} catch (error) {
|
|
8376
|
+
if (error instanceof CliError && error.code === "not-found")
|
|
8377
|
+
environment = null;
|
|
8378
|
+
else
|
|
8379
|
+
throw error;
|
|
8453
8380
|
}
|
|
8454
|
-
if (
|
|
8455
|
-
throw new CliError("
|
|
8381
|
+
if (condition !== "deleted" && !environment) {
|
|
8382
|
+
throw new CliError("not-found", "The environment no longer exists", latestReceipt ? { receipt: latestReceipt } : {});
|
|
8383
|
+
}
|
|
8384
|
+
if (environment && (condition === "ready" || condition === "running")) {
|
|
8385
|
+
if (environment.setup.phase === "failed" || environment.status === "error") {
|
|
8386
|
+
throw new CliError("setup-failed", environment.lifecycle.error ?? "Environment setup failed", { ...latestReceipt ? { receipt: latestReceipt } : {}, details: { environmentId } });
|
|
8387
|
+
}
|
|
8388
|
+
}
|
|
8389
|
+
const operationSettled = !latestReceipt || isTerminalReceipt(latestReceipt) || condition === "running" && latestReceipt.stage === "setup";
|
|
8390
|
+
if (operationSettled && conditionMet(environment)) {
|
|
8391
|
+
return {
|
|
8392
|
+
done: true,
|
|
8393
|
+
value: { environment, ...latestReceipt ? { receipt: latestReceipt } : {} }
|
|
8394
|
+
};
|
|
8456
8395
|
}
|
|
8457
8396
|
return { done: false };
|
|
8458
8397
|
}, { timeoutMs, signal: context.signal });
|
|
8459
8398
|
} catch (error) {
|
|
8460
8399
|
if (error instanceof ObservationStopped) {
|
|
8461
|
-
throw stoppedError(error,
|
|
8400
|
+
throw stoppedError(error, latestReceipt?.action ?? "environment.get", latestReceipt, `the environment (${condition})`);
|
|
8462
8401
|
}
|
|
8463
8402
|
throw error;
|
|
8464
8403
|
}
|
|
8465
8404
|
}
|
|
8466
|
-
|
|
8467
|
-
|
|
8468
|
-
|
|
8469
|
-
|
|
8470
|
-
|
|
8471
|
-
|
|
8472
|
-
|
|
8473
|
-
|
|
8474
|
-
|
|
8475
|
-
|
|
8476
|
-
|
|
8477
|
-
|
|
8478
|
-
|
|
8479
|
-
|
|
8480
|
-
|
|
8481
|
-
|
|
8482
|
-
|
|
8483
|
-
|
|
8484
|
-
|
|
8485
|
-
|
|
8486
|
-
|
|
8487
|
-
|
|
8488
|
-
|
|
8489
|
-
|
|
8490
|
-
|
|
8491
|
-
|
|
8492
|
-
|
|
8493
|
-
|
|
8494
|
-
|
|
8495
|
-
|
|
8496
|
-
|
|
8497
|
-
|
|
8498
|
-
|
|
8499
|
-
|
|
8500
|
-
|
|
8501
|
-
|
|
8502
|
-
|
|
8503
|
-
|
|
8504
|
-
|
|
8505
|
-
|
|
8506
|
-
|
|
8507
|
-
|
|
8508
|
-
const
|
|
8509
|
-
|
|
8510
|
-
|
|
8511
|
-
|
|
8512
|
-
|
|
8513
|
-
|
|
8514
|
-
|
|
8515
|
-
|
|
8516
|
-
|
|
8517
|
-
|
|
8518
|
-
|
|
8519
|
-
|
|
8520
|
-
|
|
8521
|
-
|
|
8522
|
-
|
|
8405
|
+
|
|
8406
|
+
// src/client/commands/attention.ts
|
|
8407
|
+
function attentionLine(item) {
|
|
8408
|
+
if (item.kind === "interaction") {
|
|
8409
|
+
return `${item.blocking ? "waiting" : "pending"} ${item.agent} in ${item.environmentName}: ${item.title} (${item.sessionId} ${item.interactionId} rev ${item.revision})`;
|
|
8410
|
+
}
|
|
8411
|
+
if (item.kind === "setup") {
|
|
8412
|
+
return `setup ${item.phase} ${item.environmentName} (${item.environmentId})`;
|
|
8413
|
+
}
|
|
8414
|
+
return `run ${item.state} ${item.action}${item.errorCode ? ` ${item.errorCode}` : ""} (${item.operationId})`;
|
|
8415
|
+
}
|
|
8416
|
+
function itemKey(item) {
|
|
8417
|
+
if (item.kind === "interaction")
|
|
8418
|
+
return `interaction:${item.interactionId}:${item.revision}`;
|
|
8419
|
+
if (item.kind === "setup")
|
|
8420
|
+
return `setup:${item.environmentId}:${item.at}`;
|
|
8421
|
+
return `run:${item.operationId}:${item.state}`;
|
|
8422
|
+
}
|
|
8423
|
+
var attentionCommands = [
|
|
8424
|
+
{
|
|
8425
|
+
path: ["attention"],
|
|
8426
|
+
action: "attention.list",
|
|
8427
|
+
summary: "What needs attention: questions, approvals, settled runs, finished setups.",
|
|
8428
|
+
description: "Lists pending questions and approvals (always), and the runs this client started and setups that finished since --cursor (default: the last hour). --follow --jsonl polls and prints each new item once, which is how a voice runtime or notifier can hear about work without asking; it stops at --timeout or Ctrl+C and never changes anything.",
|
|
8429
|
+
positionals: [],
|
|
8430
|
+
options: [
|
|
8431
|
+
{
|
|
8432
|
+
name: "cursor",
|
|
8433
|
+
kind: "string",
|
|
8434
|
+
valueName: "CURSOR",
|
|
8435
|
+
description: "cursor from a previous read: only what changed since."
|
|
8436
|
+
},
|
|
8437
|
+
{ name: "limit", kind: "integer", valueName: "N", description: "Most items (max 50)." },
|
|
8438
|
+
{
|
|
8439
|
+
name: "follow",
|
|
8440
|
+
kind: "boolean",
|
|
8441
|
+
description: "Keep polling and print new items (use --jsonl for machines)."
|
|
8442
|
+
},
|
|
8443
|
+
TIMEOUT_OPTION
|
|
8444
|
+
],
|
|
8445
|
+
jsonl: true,
|
|
8446
|
+
async run(context, parsed) {
|
|
8447
|
+
const session = await context.session();
|
|
8448
|
+
const input = {};
|
|
8449
|
+
if (parsed.options.cursor !== undefined)
|
|
8450
|
+
input.cursor = parsed.options.cursor;
|
|
8451
|
+
if (parsed.options.limit !== undefined)
|
|
8452
|
+
input.limit = parsed.options.limit;
|
|
8453
|
+
if (parsed.options.follow !== true) {
|
|
8454
|
+
if (context.global.output === "jsonl") {
|
|
8455
|
+
throw new CliError("invalid-input", "--jsonl needs --follow");
|
|
8456
|
+
}
|
|
8457
|
+
const page = await session.read("attention.list", input);
|
|
8458
|
+
return {
|
|
8459
|
+
action: "attention.list",
|
|
8460
|
+
result: page,
|
|
8461
|
+
connection: session.identity,
|
|
8462
|
+
human: [
|
|
8463
|
+
...page.items.length ? page.items.map(attentionLine) : ["Nothing needs attention."],
|
|
8464
|
+
...page.more ? [`and ${page.more} more (raise --limit)`] : [],
|
|
8465
|
+
`cursor: ${page.cursor}`
|
|
8466
|
+
]
|
|
8467
|
+
};
|
|
8468
|
+
}
|
|
8469
|
+
const seen = new Set;
|
|
8470
|
+
let cursor = input.cursor;
|
|
8471
|
+
let emitted = 0;
|
|
8472
|
+
try {
|
|
8473
|
+
await observe(async () => {
|
|
8474
|
+
const page = await session.read("attention.list", {
|
|
8475
|
+
...input,
|
|
8476
|
+
...cursor ? { cursor } : {}
|
|
8477
|
+
});
|
|
8478
|
+
cursor = page.cursor;
|
|
8479
|
+
for (const item of page.items) {
|
|
8480
|
+
const key = itemKey(item);
|
|
8481
|
+
if (seen.has(key))
|
|
8482
|
+
continue;
|
|
8483
|
+
seen.add(key);
|
|
8484
|
+
emitted += 1;
|
|
8485
|
+
if (context.global.output === "jsonl") {
|
|
8486
|
+
context.io.stdout(`${JSON.stringify({ type: "attention", item })}
|
|
8487
|
+
`);
|
|
8488
|
+
} else if (context.global.output === "human") {
|
|
8489
|
+
context.io.stdout(`${attentionLine(item)}
|
|
8490
|
+
`);
|
|
8491
|
+
}
|
|
8492
|
+
}
|
|
8493
|
+
if (seen.size > 1e4)
|
|
8494
|
+
seen.clear();
|
|
8495
|
+
return { done: false };
|
|
8496
|
+
}, {
|
|
8497
|
+
timeoutMs: parsed.options.timeout ?? DEFAULT_WAIT_MS,
|
|
8498
|
+
signal: context.signal
|
|
8499
|
+
});
|
|
8500
|
+
} catch (error) {
|
|
8501
|
+
if (!(error instanceof ObservationStopped))
|
|
8502
|
+
throw error;
|
|
8503
|
+
}
|
|
8504
|
+
return {
|
|
8505
|
+
action: "attention.list",
|
|
8506
|
+
result: { followed: true, emitted, cursor: cursor ?? null },
|
|
8507
|
+
connection: session.identity,
|
|
8508
|
+
human: []
|
|
8509
|
+
};
|
|
8510
|
+
}
|
|
8511
|
+
}
|
|
8512
|
+
];
|
|
8513
|
+
|
|
8514
|
+
// ../protocol/src/public-api-resources.ts
|
|
8515
|
+
var PUBLIC_CHANGE_SCOPES = Object.freeze(["environment"]);
|
|
8516
|
+
var AGENT_PLATFORM_KEYS = ["claude", "codex", "cursor", "grok", "opencode", "pi"];
|
|
8517
|
+
function agentSettingDescriptors(scope) {
|
|
8518
|
+
const application = "next-session";
|
|
8519
|
+
return [
|
|
8520
|
+
{
|
|
8521
|
+
key: "agent.defaultAgent",
|
|
8522
|
+
scope,
|
|
8523
|
+
type: "agent",
|
|
8524
|
+
inherits: true,
|
|
8525
|
+
application,
|
|
8526
|
+
description: "Agent platform used when a launch does not name one."
|
|
8527
|
+
},
|
|
8528
|
+
...AGENT_PLATFORM_KEYS.flatMap((platform) => [
|
|
8529
|
+
{
|
|
8530
|
+
key: `agent.${platform}.mode`,
|
|
8531
|
+
scope,
|
|
8532
|
+
type: "agent-mode",
|
|
8533
|
+
inherits: true,
|
|
8534
|
+
application,
|
|
8535
|
+
description: `Launch mode (native or terminal) for ${platform}.`
|
|
8536
|
+
},
|
|
8537
|
+
{
|
|
8538
|
+
key: `agent.${platform}.model`,
|
|
8539
|
+
scope,
|
|
8540
|
+
type: "string",
|
|
8541
|
+
inherits: true,
|
|
8542
|
+
application,
|
|
8543
|
+
description: `Default model for new ${platform} sessions.`
|
|
8544
|
+
},
|
|
8545
|
+
{
|
|
8546
|
+
key: `agent.${platform}.reasoningEffort`,
|
|
8547
|
+
scope,
|
|
8548
|
+
type: "string",
|
|
8549
|
+
inherits: true,
|
|
8550
|
+
application,
|
|
8551
|
+
description: `Default reasoning level for new ${platform} sessions.`
|
|
8552
|
+
},
|
|
8553
|
+
{
|
|
8554
|
+
key: `agent.${platform}.fastMode`,
|
|
8555
|
+
scope,
|
|
8556
|
+
type: "boolean",
|
|
8557
|
+
inherits: true,
|
|
8558
|
+
application,
|
|
8559
|
+
description: `Default speed for new ${platform} sessions (true is Fast).`
|
|
8560
|
+
}
|
|
8561
|
+
])
|
|
8562
|
+
];
|
|
8563
|
+
}
|
|
8564
|
+
var PUBLIC_PROJECT_SETTINGS = Object.freeze([
|
|
8565
|
+
{
|
|
8566
|
+
key: "defaultBranch",
|
|
8567
|
+
scope: "project",
|
|
8568
|
+
type: "string",
|
|
8569
|
+
inherits: false,
|
|
8570
|
+
application: "next-environment",
|
|
8571
|
+
description: "Branch new environments are created from."
|
|
8572
|
+
},
|
|
8573
|
+
{
|
|
8574
|
+
key: "prBaseBranch",
|
|
8575
|
+
scope: "project",
|
|
8576
|
+
type: "string",
|
|
8577
|
+
inherits: false,
|
|
8578
|
+
application: "applied",
|
|
8579
|
+
description: "Base branch for pull requests and diff baselines."
|
|
8580
|
+
},
|
|
8581
|
+
{
|
|
8582
|
+
key: "defaultPortMappings",
|
|
8583
|
+
scope: "project",
|
|
8584
|
+
type: "port-mappings",
|
|
8585
|
+
inherits: false,
|
|
8586
|
+
environmentTypes: ["container"],
|
|
8587
|
+
application: "next-environment",
|
|
8588
|
+
description: "Port mappings copied into new container environments."
|
|
8589
|
+
},
|
|
8590
|
+
{
|
|
8591
|
+
key: "filesToCopy",
|
|
8592
|
+
scope: "project",
|
|
8593
|
+
type: "string-list",
|
|
8594
|
+
inherits: false,
|
|
8595
|
+
application: "next-environment",
|
|
8596
|
+
description: "Untracked files copied into new environments."
|
|
8597
|
+
},
|
|
8598
|
+
{
|
|
8599
|
+
key: "entryPort",
|
|
8600
|
+
scope: "project",
|
|
8601
|
+
type: "port",
|
|
8602
|
+
inherits: false,
|
|
8603
|
+
application: "next-environment",
|
|
8604
|
+
description: "Default preview entry port for new environments."
|
|
8605
|
+
},
|
|
8606
|
+
...agentSettingDescriptors("project")
|
|
8607
|
+
]);
|
|
8608
|
+
var PUBLIC_ENVIRONMENT_SETTINGS = Object.freeze([
|
|
8609
|
+
{
|
|
8610
|
+
key: "portMappings",
|
|
8611
|
+
scope: "environment",
|
|
8612
|
+
type: "port-mappings",
|
|
8613
|
+
inherits: false,
|
|
8614
|
+
environmentTypes: ["container"],
|
|
8615
|
+
application: "next-start",
|
|
8616
|
+
description: "Container port mappings; a running container adopts them on recreate."
|
|
8617
|
+
},
|
|
8618
|
+
{
|
|
8619
|
+
key: "allowedDomains",
|
|
8620
|
+
scope: "environment",
|
|
8621
|
+
type: "domain-list",
|
|
8622
|
+
inherits: true,
|
|
8623
|
+
environmentTypes: ["container"],
|
|
8624
|
+
application: "next-start",
|
|
8625
|
+
description: "Restricted-network allowlist; unset inherits the global list. A running container whose image supports it applies the change immediately (reported as applied)."
|
|
8626
|
+
},
|
|
8627
|
+
...agentSettingDescriptors("environment")
|
|
8628
|
+
]);
|
|
8629
|
+
|
|
8630
|
+
// src/client/format.ts
|
|
8631
|
+
function table(headers, rows) {
|
|
8632
|
+
if (rows.length === 0)
|
|
8633
|
+
return ["(none)"];
|
|
8634
|
+
const widths = headers.map((header, index) => Math.min(60, Math.max(header.length, ...rows.map((row) => (row[index] ?? "").length))));
|
|
8635
|
+
const line = (cells) => cells.map((cell, index) => {
|
|
8636
|
+
const text = cell.length > widths[index] ? `${cell.slice(0, widths[index] - 1)}\u2026` : cell;
|
|
8637
|
+
return text.padEnd(widths[index]);
|
|
8638
|
+
}).join(" ").trimEnd();
|
|
8639
|
+
return [line(headers), ...rows.map(line)];
|
|
8640
|
+
}
|
|
8641
|
+
function keyValues(entries) {
|
|
8642
|
+
const width = Math.max(...entries.map(([key]) => key.length));
|
|
8643
|
+
return entries.filter(([, value]) => value !== undefined).map(([key, value]) => {
|
|
8644
|
+
const text = value === null ? "-" : typeof value === "object" ? JSON.stringify(value) : String(value);
|
|
8645
|
+
return `${key.padEnd(width)} ${text}`;
|
|
8646
|
+
});
|
|
8647
|
+
}
|
|
8648
|
+
function projectLines(project) {
|
|
8649
|
+
return keyValues([
|
|
8650
|
+
["id", project.id],
|
|
8651
|
+
["name", project.name],
|
|
8652
|
+
["remote", project.gitUrl],
|
|
8653
|
+
["path", project.localPath],
|
|
8654
|
+
["folder", project.folder],
|
|
8655
|
+
["environments", project.environmentCount],
|
|
8656
|
+
["revision", project.revision]
|
|
8657
|
+
]);
|
|
8658
|
+
}
|
|
8659
|
+
function projectRows(projects) {
|
|
8660
|
+
return table(["ID", "NAME", "ENVS", "PATH"], projects.map((project) => [
|
|
8661
|
+
project.id,
|
|
8662
|
+
project.name,
|
|
8663
|
+
String(project.environmentCount),
|
|
8664
|
+
project.localPath ?? "-"
|
|
8665
|
+
]));
|
|
8666
|
+
}
|
|
8667
|
+
function environmentLines(environment) {
|
|
8668
|
+
return keyValues([
|
|
8669
|
+
["id", environment.id],
|
|
8670
|
+
["project", environment.projectId],
|
|
8671
|
+
["name", environment.name],
|
|
8672
|
+
["branch", environment.branch],
|
|
8673
|
+
["type", environment.environmentType],
|
|
8674
|
+
["status", environment.status],
|
|
8675
|
+
["ready", environment.ready],
|
|
8676
|
+
["setup", `${environment.setup.phase}${environment.setup.overridden ? " (overridden)" : ""}`],
|
|
8677
|
+
["activity", environment.activity.state],
|
|
8678
|
+
["lifecycle error", environment.lifecycle.error],
|
|
8679
|
+
["workspace", environment.workspacePath],
|
|
8680
|
+
["base", environment.base.commit ?? environment.base.branch],
|
|
8681
|
+
["startup session", environment.startupSession?.sessionId]
|
|
8682
|
+
]);
|
|
8683
|
+
}
|
|
8684
|
+
function environmentRows(environments) {
|
|
8685
|
+
return table(["ID", "NAME", "TYPE", "STATUS", "READY"], environments.map((environment) => [
|
|
8686
|
+
environment.id,
|
|
8687
|
+
environment.name,
|
|
8688
|
+
environment.environmentType,
|
|
8689
|
+
environment.status,
|
|
8690
|
+
environment.ready ? "yes" : "no"
|
|
8691
|
+
]));
|
|
8692
|
+
}
|
|
8693
|
+
function sessionRows(sessions) {
|
|
8694
|
+
return table(["SESSION", "AGENT", "TAB", "ACTIVITY", "TITLE"], sessions.map((session) => [
|
|
8695
|
+
session.id,
|
|
8696
|
+
session.agent,
|
|
8697
|
+
session.tabId,
|
|
8698
|
+
session.activity,
|
|
8699
|
+
session.title ?? ""
|
|
8700
|
+
]));
|
|
8701
|
+
}
|
|
8702
|
+
function sessionLines(session) {
|
|
8703
|
+
return keyValues([
|
|
8704
|
+
["id", session.id],
|
|
8705
|
+
["environment", session.environmentId],
|
|
8706
|
+
["tab", session.tabId],
|
|
8707
|
+
["agent", session.agent],
|
|
8708
|
+
["title", session.title],
|
|
8709
|
+
["activity", session.activity],
|
|
8710
|
+
["latest request", session.latestRequestId],
|
|
8711
|
+
["pending interactions", session.pendingInteractionCount],
|
|
8712
|
+
["recoverable dispatch", session.recoverableDispatch]
|
|
8713
|
+
]);
|
|
8714
|
+
}
|
|
8715
|
+
function receiptLines(receipt) {
|
|
8716
|
+
return keyValues([
|
|
8717
|
+
["operation", receipt.operationId],
|
|
8718
|
+
["action", receipt.action],
|
|
8719
|
+
["state", receipt.state],
|
|
8720
|
+
["stage", receipt.stage],
|
|
8721
|
+
["request", `${receipt.requestId} (${receipt.namespace})`],
|
|
8722
|
+
["replayed", receipt.replayed],
|
|
8723
|
+
["resources", receipt.resources],
|
|
8724
|
+
["dispatch", receipt.dispatch?.state],
|
|
8725
|
+
["execution", receipt.execution?.state],
|
|
8726
|
+
["evidence", receipt.execution?.evidence],
|
|
8727
|
+
["exit code", receipt.execution?.exitCode],
|
|
8728
|
+
["error", receipt.error ? `${receipt.error.code}: ${receipt.error.message}` : undefined],
|
|
8729
|
+
["updated", receipt.updatedAt],
|
|
8730
|
+
["retained until", receipt.retainedUntil]
|
|
8731
|
+
]);
|
|
8732
|
+
}
|
|
8733
|
+
function settingsLines(snapshot) {
|
|
8734
|
+
return [
|
|
8735
|
+
`revision ${snapshot.revision}`,
|
|
8736
|
+
...table(["KEY", "VALUE", "EFFECTIVE", "SOURCE", "APPLIES"], snapshot.settings.map((setting) => [
|
|
8737
|
+
setting.key,
|
|
8738
|
+
setting.value === null || setting.value === undefined ? "-" : JSON.stringify(setting.value),
|
|
8739
|
+
setting.effective === null || setting.effective === undefined ? "-" : JSON.stringify(setting.effective),
|
|
8740
|
+
setting.source,
|
|
8741
|
+
setting.application
|
|
8742
|
+
]))
|
|
8743
|
+
];
|
|
8523
8744
|
}
|
|
8524
8745
|
|
|
8525
8746
|
// src/client/commands/changes.ts
|
|
@@ -8625,6 +8846,7 @@ function changesHistoryLines(history) {
|
|
|
8625
8846
|
var changesCommands = [
|
|
8626
8847
|
{
|
|
8627
8848
|
path: ["changes", "view"],
|
|
8849
|
+
action: "changes.view",
|
|
8628
8850
|
summary: "Show an environment's file and line changes as the backend measures them.",
|
|
8629
8851
|
description: "Read-only: prints the backend's change projection for the environment \u2014 the numbers the desktop shows \u2014 and one page of changed files. Counts carry their quality: ~ partial or estimated, ? unknown, \u2265/\u2264 a bound; binary files and submodules have no line counts. Nothing is ever shown as zero unless the backend measured zero. Pass the printed cursor as --cursor for the next page; a cursor stops working once the changes move on. --json prints the action result verbatim ({projection, files}).",
|
|
8630
8852
|
positionals: [{ name: "environment", required: true, description: "Environment ID." }],
|
|
@@ -8674,6 +8896,7 @@ var changesCommands = [
|
|
|
8674
8896
|
},
|
|
8675
8897
|
{
|
|
8676
8898
|
path: ["changes", "history"],
|
|
8899
|
+
action: "changes.history",
|
|
8677
8900
|
summary: "List a session's turns, oldest first, with the changes each one made.",
|
|
8678
8901
|
description: "Read-only: each turn's backend measurement from its start to its end, with the same count qualities as `changes view`. No workspace scan, transcript or provider read. Pass the printed cursor as --cursor for newer turns.",
|
|
8679
8902
|
positionals: [{ name: "session", required: true, description: "Session ID (ses_\u2026)." }],
|
|
@@ -9900,6 +10123,7 @@ function settingsCommands(scope) {
|
|
|
9900
10123
|
return [
|
|
9901
10124
|
{
|
|
9902
10125
|
path: [scope, "config", "get"],
|
|
10126
|
+
action: `${scope}.config.get`,
|
|
9903
10127
|
summary: `Show ${scope} settings with effective values, sources and application timing.`,
|
|
9904
10128
|
positionals: [{ name: idName, required: true }],
|
|
9905
10129
|
options: [],
|
|
@@ -9918,6 +10142,7 @@ function settingsCommands(scope) {
|
|
|
9918
10142
|
},
|
|
9919
10143
|
{
|
|
9920
10144
|
path: [scope, "config", "set"],
|
|
10145
|
+
action: `${scope}.config.set`,
|
|
9921
10146
|
summary: `Set and/or unset ${scope} settings atomically.`,
|
|
9922
10147
|
description: `Settable keys:
|
|
9923
10148
|
${keysHelp}
|
|
@@ -10015,6 +10240,8 @@ ${applies}`,
|
|
|
10015
10240
|
},
|
|
10016
10241
|
{
|
|
10017
10242
|
path: [scope, "config", "unset"],
|
|
10243
|
+
action: `${scope}.config.set`,
|
|
10244
|
+
inputFields: { key: "unset" },
|
|
10018
10245
|
summary: `Unset ${scope} settings, restoring inheritance.`,
|
|
10019
10246
|
positionals: [
|
|
10020
10247
|
{ name: idName, required: true },
|
|
@@ -10092,6 +10319,7 @@ async function lifecycle(context, parsed, action, conditions, extraInput = {}) {
|
|
|
10092
10319
|
var environmentCommands = [
|
|
10093
10320
|
{
|
|
10094
10321
|
path: ["environment", "list"],
|
|
10322
|
+
action: "environment.list",
|
|
10095
10323
|
summary: "List environments from the backend snapshot.",
|
|
10096
10324
|
positionals: [],
|
|
10097
10325
|
options: [
|
|
@@ -10138,6 +10366,7 @@ var environmentCommands = [
|
|
|
10138
10366
|
},
|
|
10139
10367
|
{
|
|
10140
10368
|
path: ["environment", "get"],
|
|
10369
|
+
action: "environment.get",
|
|
10141
10370
|
summary: "Show one environment by ID, or by --project and --name when unique.",
|
|
10142
10371
|
positionals: [{ name: "environment", required: false }],
|
|
10143
10372
|
options: [
|
|
@@ -10173,6 +10402,7 @@ var environmentCommands = [
|
|
|
10173
10402
|
},
|
|
10174
10403
|
{
|
|
10175
10404
|
path: ["environment", "create"],
|
|
10405
|
+
action: "environment.create",
|
|
10176
10406
|
summary: "Create an environment record (does not start it).",
|
|
10177
10407
|
description: "--base-branch with --base-commit (a full 40-character SHA) pins the exact base; the backend validates it and records what was used. Without them the project's default branch is used at start time.",
|
|
10178
10408
|
positionals: [],
|
|
@@ -10231,6 +10461,7 @@ var environmentCommands = [
|
|
|
10231
10461
|
},
|
|
10232
10462
|
{
|
|
10233
10463
|
path: ["environment", "start"],
|
|
10464
|
+
action: "environment.start",
|
|
10234
10465
|
summary: "Start an environment; setup continues in the backend.",
|
|
10235
10466
|
description: "`--wait running` returns once processes run; `--wait ready` also requires setup to complete (an explicit setup override is reported, never applied by the CLI). Setup failure exits 1 with the recorded reason.",
|
|
10236
10467
|
positionals: [{ name: "environment", required: true }],
|
|
@@ -10240,6 +10471,7 @@ var environmentCommands = [
|
|
|
10240
10471
|
},
|
|
10241
10472
|
{
|
|
10242
10473
|
path: ["environment", "stop"],
|
|
10474
|
+
action: "environment.stop",
|
|
10243
10475
|
summary: "Stop an environment's processes (and container).",
|
|
10244
10476
|
positionals: [{ name: "environment", required: true }],
|
|
10245
10477
|
options: [waitOption(["stopped"]), TIMEOUT_OPTION, REQUEST_ID_OPTION],
|
|
@@ -10248,6 +10480,7 @@ var environmentCommands = [
|
|
|
10248
10480
|
},
|
|
10249
10481
|
{
|
|
10250
10482
|
path: ["environment", "recreate"],
|
|
10483
|
+
action: "environment.recreate",
|
|
10251
10484
|
summary: "Rebuild the container, keeping its files; with --discard, DESTRUCTIVELY reset it (container environments only).",
|
|
10252
10485
|
description: "Without --discard the workspace (tracked, untracked and ignored files, unpushed commits) and the preserved agent session state are copied to a new container and verified before it replaces the old one, which is kept stopped as a recovery copy. The rebuild is refused, with nothing changed, when the image or Docker engine cannot preserve them. --discard instead deletes the container's local files, installed tools and container-local agent sessions. Local worktree environments cannot be recreated.",
|
|
10253
10486
|
positionals: [{ name: "environment", required: true }],
|
|
@@ -10266,6 +10499,7 @@ var environmentCommands = [
|
|
|
10266
10499
|
},
|
|
10267
10500
|
{
|
|
10268
10501
|
path: ["environment", "delete"],
|
|
10502
|
+
action: "environment.delete",
|
|
10269
10503
|
summary: "DESTRUCTIVE: stop and delete the environment, its worktree or container, and its record.",
|
|
10270
10504
|
description: "Uncommitted work in the environment is lost. Cleanup is tracked by the operation; a failed cleanup stays inspectable and can be retried with a new request.",
|
|
10271
10505
|
positionals: [{ name: "environment", required: true }],
|
|
@@ -10275,6 +10509,7 @@ var environmentCommands = [
|
|
|
10275
10509
|
},
|
|
10276
10510
|
{
|
|
10277
10511
|
path: ["environment", "fork"],
|
|
10512
|
+
action: "environment.fork",
|
|
10278
10513
|
summary: "Create a new environment from this environment's current state.",
|
|
10279
10514
|
positionals: [{ name: "environment", required: true }],
|
|
10280
10515
|
options: [TYPE_OPTION, REQUEST_ID_OPTION],
|
|
@@ -10295,6 +10530,7 @@ var environmentCommands = [
|
|
|
10295
10530
|
},
|
|
10296
10531
|
{
|
|
10297
10532
|
path: ["environment", "rename"],
|
|
10533
|
+
action: "environment.rename",
|
|
10298
10534
|
summary: "Rename an environment (and its branch).",
|
|
10299
10535
|
positionals: [
|
|
10300
10536
|
{ name: "environment", required: true },
|
|
@@ -10317,6 +10553,7 @@ var environmentCommands = [
|
|
|
10317
10553
|
},
|
|
10318
10554
|
{
|
|
10319
10555
|
path: ["environment", "launch"],
|
|
10556
|
+
action: "environment.launch",
|
|
10320
10557
|
summary: "Create and start an environment whose startup agent receives one first prompt.",
|
|
10321
10558
|
description: "The backend owns the whole flow: create, start, setup, then exactly one initial prompt to the startup session. Do not follow it with `session start`. --wait ready observes setup; follow the prompt's run with `run wait`.",
|
|
10322
10559
|
positionals: [],
|
|
@@ -10427,6 +10664,8 @@ var environmentCommands = [
|
|
|
10427
10664
|
},
|
|
10428
10665
|
{
|
|
10429
10666
|
path: ["environment", "exec"],
|
|
10667
|
+
action: "environment.exec",
|
|
10668
|
+
inputFields: { "stdin-file": "stdinBase64", "exec-timeout": "timeoutMs" },
|
|
10430
10669
|
summary: "Run one command in the environment workspace and report its exit status.",
|
|
10431
10670
|
description: "Arguments after `--` are passed as argv without a shell; use `-- sh -c '...'` to opt into shell expansion. The command runs in a backend-owned worker that outlives this client; --wait observes it and exits with the operation's result (`--exit-code` passes the child's exit code through instead). Output is kept in bounded private artifacts; read it with `run output`.",
|
|
10432
10671
|
positionals: [{ name: "environment", required: true }],
|
|
@@ -10646,6 +10885,7 @@ async function waitForReceipt(context, session, receipt, limit, action) {
|
|
|
10646
10885
|
function taskCommand(spec) {
|
|
10647
10886
|
return {
|
|
10648
10887
|
path: spec.path,
|
|
10888
|
+
action: spec.action,
|
|
10649
10889
|
summary: spec.summary,
|
|
10650
10890
|
...spec.description ? { description: spec.description } : {},
|
|
10651
10891
|
positionals: [],
|
|
@@ -10677,6 +10917,7 @@ function taskCommand(spec) {
|
|
|
10677
10917
|
var hostCommands = [
|
|
10678
10918
|
{
|
|
10679
10919
|
path: ["host", "status"],
|
|
10920
|
+
action: "host.status",
|
|
10680
10921
|
summary: "Show the Orkestrator version on the backend's computer, its updater and any update.",
|
|
10681
10922
|
positionals: [],
|
|
10682
10923
|
options: [],
|
|
@@ -10693,6 +10934,7 @@ var hostCommands = [
|
|
|
10693
10934
|
},
|
|
10694
10935
|
{
|
|
10695
10936
|
path: ["host", "update", "channel"],
|
|
10937
|
+
action: "host.update.channel",
|
|
10696
10938
|
summary: "Choose the host's update channel: stable, beta or unstable.",
|
|
10697
10939
|
positionals: [{ name: "channel", required: true, description: "stable, beta or unstable" }],
|
|
10698
10940
|
options: [REQUEST_ID_OPTION],
|
|
@@ -10713,6 +10955,7 @@ var hostCommands = [
|
|
|
10713
10955
|
},
|
|
10714
10956
|
{
|
|
10715
10957
|
path: ["host", "update", "check"],
|
|
10958
|
+
action: "host.update.check",
|
|
10716
10959
|
summary: "Ask the backend's computer to check for an Orkestrator update.",
|
|
10717
10960
|
positionals: [],
|
|
10718
10961
|
options: [WAIT_OPTION, TIMEOUT_OPTION, REQUEST_ID_OPTION],
|
|
@@ -10747,6 +10990,13 @@ var hostCommands = [
|
|
|
10747
10990
|
},
|
|
10748
10991
|
{
|
|
10749
10992
|
path: ["host", "update", "apply"],
|
|
10993
|
+
action: "host.update.apply",
|
|
10994
|
+
inputFields: {
|
|
10995
|
+
release: "version",
|
|
10996
|
+
yes: "confirm",
|
|
10997
|
+
"when-idle": "drain",
|
|
10998
|
+
"max-wait": "maxWaitSeconds"
|
|
10999
|
+
},
|
|
10750
11000
|
summary: "Install an Orkestrator update on the backend's computer. It restarts there after a 60 s countdown.",
|
|
10751
11001
|
description: "Someone at that computer can postpone the restart; the update then installs the next time the app quits. Restarting ends agent turns and terminals running on that computer; containers keep running.",
|
|
10752
11002
|
positionals: [],
|
|
@@ -10820,6 +11070,7 @@ var hostCommands = [
|
|
|
10820
11070
|
},
|
|
10821
11071
|
{
|
|
10822
11072
|
path: ["host", "update", "cancel"],
|
|
11073
|
+
action: "host.update.cancel",
|
|
10823
11074
|
summary: "Cancel the host's update before it restarts.",
|
|
10824
11075
|
positionals: [],
|
|
10825
11076
|
options: [REQUEST_ID_OPTION],
|
|
@@ -10862,6 +11113,98 @@ var hostCommands = [
|
|
|
10862
11113
|
})
|
|
10863
11114
|
];
|
|
10864
11115
|
|
|
11116
|
+
// src/client/commands/mail.ts
|
|
11117
|
+
var mailCommands = [
|
|
11118
|
+
{
|
|
11119
|
+
path: ["mail", "mailboxes"],
|
|
11120
|
+
action: "mail.mailboxes",
|
|
11121
|
+
summary: "List agent mailboxes a message can be sent to.",
|
|
11122
|
+
positionals: [],
|
|
11123
|
+
options: [
|
|
11124
|
+
{ name: "q", kind: "string", valueName: "TEXT", description: "Filter by name." },
|
|
11125
|
+
{ name: "offset", kind: "integer", valueName: "N", description: "Rows to skip." },
|
|
11126
|
+
{ name: "limit", kind: "integer", valueName: "N", description: "Rows (max 200)." }
|
|
11127
|
+
],
|
|
11128
|
+
async run(context, parsed) {
|
|
11129
|
+
const session = await context.session();
|
|
11130
|
+
const page = await session.read("mail.mailboxes", {
|
|
11131
|
+
...parsed.options.q !== undefined ? { q: parsed.options.q } : {},
|
|
11132
|
+
...parsed.options.offset !== undefined ? { offset: parsed.options.offset } : {},
|
|
11133
|
+
...parsed.options.limit !== undefined ? { limit: parsed.options.limit } : {}
|
|
11134
|
+
});
|
|
11135
|
+
return {
|
|
11136
|
+
action: "mail.mailboxes",
|
|
11137
|
+
result: page,
|
|
11138
|
+
connection: session.identity,
|
|
11139
|
+
human: table(["ENVIRONMENT", "TAB", "NAME", "PRESENCE"], page.mailboxes.map((mailbox) => [
|
|
11140
|
+
mailbox.environmentId,
|
|
11141
|
+
mailbox.tabId,
|
|
11142
|
+
`${mailbox.environmentName} / ${mailbox.displayName}`,
|
|
11143
|
+
mailbox.presence
|
|
11144
|
+
]))
|
|
11145
|
+
};
|
|
11146
|
+
}
|
|
11147
|
+
},
|
|
11148
|
+
{
|
|
11149
|
+
path: ["mail", "send"],
|
|
11150
|
+
action: "mail.send",
|
|
11151
|
+
summary: "Place a message in one tab's inbox (never injected into a turn).",
|
|
11152
|
+
positionals: [
|
|
11153
|
+
{ name: "environment", required: true },
|
|
11154
|
+
{ name: "tab", required: true }
|
|
11155
|
+
],
|
|
11156
|
+
options: [
|
|
11157
|
+
{ name: "subject", kind: "string", valueName: "TEXT", description: "Subject line." },
|
|
11158
|
+
{ name: "body", kind: "string", valueName: "TEXT", description: "Message text." },
|
|
11159
|
+
{
|
|
11160
|
+
name: "body-file",
|
|
11161
|
+
kind: "string",
|
|
11162
|
+
valueName: "PATH",
|
|
11163
|
+
description: "Read the message from a local file."
|
|
11164
|
+
},
|
|
11165
|
+
{ name: "body-stdin", kind: "boolean", description: "Read the message from stdin." },
|
|
11166
|
+
REQUEST_ID_OPTION
|
|
11167
|
+
],
|
|
11168
|
+
inputFields: {
|
|
11169
|
+
environment: "toEnvironmentId",
|
|
11170
|
+
tab: "toTabId",
|
|
11171
|
+
"body-file": "body",
|
|
11172
|
+
"body-stdin": "body"
|
|
11173
|
+
},
|
|
11174
|
+
idOutput: "message ID",
|
|
11175
|
+
async run(context, parsed) {
|
|
11176
|
+
const body = await readTextSource(context.io, {
|
|
11177
|
+
file: parsed.options["body-file"],
|
|
11178
|
+
stdin: parsed.options["body-stdin"],
|
|
11179
|
+
inline: parsed.options.body,
|
|
11180
|
+
label: "Message",
|
|
11181
|
+
maxBytes: 32 * 1024,
|
|
11182
|
+
names: { file: "--body-file", stdin: "--body-stdin", inline: "--body" },
|
|
11183
|
+
required: true
|
|
11184
|
+
});
|
|
11185
|
+
const subject = stringOption(parsed.options, "subject");
|
|
11186
|
+
if (subject !== undefined && subject.trim().length === 0) {
|
|
11187
|
+
throw new CliError("invalid-input", "--subject is empty");
|
|
11188
|
+
}
|
|
11189
|
+
const { session, result, receipt, warnings } = await submit(context, "mail.send", {
|
|
11190
|
+
toEnvironmentId: parsed.positionals.environment,
|
|
11191
|
+
toTabId: parsed.positionals.tab,
|
|
11192
|
+
body,
|
|
11193
|
+
...subject ? { subject } : {}
|
|
11194
|
+
}, parsed.options);
|
|
11195
|
+
return {
|
|
11196
|
+
action: "mail.send",
|
|
11197
|
+
result,
|
|
11198
|
+
receipt,
|
|
11199
|
+
warnings,
|
|
11200
|
+
connection: session.identity,
|
|
11201
|
+
ids: result.messageId ? [result.messageId] : [],
|
|
11202
|
+
human: [`sent message ${result.messageId ?? ""}`.trim()]
|
|
11203
|
+
};
|
|
11204
|
+
}
|
|
11205
|
+
}
|
|
11206
|
+
];
|
|
11207
|
+
|
|
10865
11208
|
// src/client/commands/service.ts
|
|
10866
11209
|
import { spawnSync } from "child_process";
|
|
10867
11210
|
import { existsSync as existsSync5 } from "fs";
|
|
@@ -11477,6 +11820,7 @@ var PAGE_OPTIONS = [
|
|
|
11477
11820
|
var projectCommands = [
|
|
11478
11821
|
{
|
|
11479
11822
|
path: ["project", "list"],
|
|
11823
|
+
action: "project.list",
|
|
11480
11824
|
summary: "List projects.",
|
|
11481
11825
|
positionals: [],
|
|
11482
11826
|
options: PAGE_OPTIONS,
|
|
@@ -11501,6 +11845,7 @@ var projectCommands = [
|
|
|
11501
11845
|
},
|
|
11502
11846
|
{
|
|
11503
11847
|
path: ["project", "get"],
|
|
11848
|
+
action: "project.get",
|
|
11504
11849
|
summary: "Show one project by ID, or by --name when unique.",
|
|
11505
11850
|
positionals: [{ name: "project", required: false }],
|
|
11506
11851
|
options: [
|
|
@@ -11526,6 +11871,7 @@ var projectCommands = [
|
|
|
11526
11871
|
},
|
|
11527
11872
|
{
|
|
11528
11873
|
path: ["project", "add"],
|
|
11874
|
+
action: "project.add",
|
|
11529
11875
|
summary: "Register a repository, attach a backend checkout, or clone into a backend path.",
|
|
11530
11876
|
description: "--remote alone registers the remote. --path alone attaches an existing checkout on the BACKEND's filesystem and reads its origin there. Both together attach the checkout if it exists, or clone the remote into that backend path when it is missing or empty. No GitHub repository is created.",
|
|
11531
11877
|
positionals: [],
|
|
@@ -11560,6 +11906,7 @@ var projectCommands = [
|
|
|
11560
11906
|
},
|
|
11561
11907
|
{
|
|
11562
11908
|
path: ["project", "create"],
|
|
11909
|
+
action: "project.create",
|
|
11563
11910
|
summary: "Create a new repository: git init, a PRIVATE GitHub repository, and a push.",
|
|
11564
11911
|
description: "This creates an external repository on GitHub using the backend's GitHub CLI credentials, pushes the initial commit, and registers the project. It requires --github-private to confirm that effect. Local-only initialization is not supported.",
|
|
11565
11912
|
positionals: [],
|
|
@@ -11599,6 +11946,15 @@ var projectCommands = [
|
|
|
11599
11946
|
},
|
|
11600
11947
|
{
|
|
11601
11948
|
path: ["project", "update"],
|
|
11949
|
+
action: "project.update",
|
|
11950
|
+
inputFields: {
|
|
11951
|
+
name: "set",
|
|
11952
|
+
folder: "set",
|
|
11953
|
+
"no-folder": "set",
|
|
11954
|
+
remote: "set",
|
|
11955
|
+
path: "set",
|
|
11956
|
+
"no-path": "set"
|
|
11957
|
+
},
|
|
11602
11958
|
summary: "Edit project metadata (does not move checkouts or rewrite .git/config).",
|
|
11603
11959
|
positionals: [{ name: "project", required: true }],
|
|
11604
11960
|
options: [
|
|
@@ -11668,6 +12024,7 @@ var projectCommands = [
|
|
|
11668
12024
|
},
|
|
11669
12025
|
{
|
|
11670
12026
|
path: ["project", "remove"],
|
|
12027
|
+
action: "project.remove",
|
|
11671
12028
|
summary: "Remove an empty project registration (refused while environments exist).",
|
|
11672
12029
|
description: "Only the registration is removed. The checkout on disk and any remote repository are never deleted.",
|
|
11673
12030
|
positionals: [{ name: "project", required: true }],
|
|
@@ -11693,6 +12050,7 @@ var projectCommands = [
|
|
|
11693
12050
|
var runCommands = [
|
|
11694
12051
|
{
|
|
11695
12052
|
path: ["run", "get"],
|
|
12053
|
+
action: "run.get",
|
|
11696
12054
|
summary: "Show an operation by ID, or by its original --request-id.",
|
|
11697
12055
|
description: "Lookup by request key finds the operation even when the original response was lost. `history-expired` (exit 3) means the key's namespace was retired and its outcome is no longer retained; it is not evidence that nothing ran.",
|
|
11698
12056
|
positionals: [{ name: "operation", required: false }],
|
|
@@ -11749,6 +12107,7 @@ var runCommands = [
|
|
|
11749
12107
|
},
|
|
11750
12108
|
{
|
|
11751
12109
|
path: ["run", "wait"],
|
|
12110
|
+
action: "run.get",
|
|
11752
12111
|
summary: "Observe an operation until it finishes (exit 0 only on success).",
|
|
11753
12112
|
description: "Exit codes: 0 succeeded, 1 failed/cancelled/interrupted, 5 --timeout passed (still running), 6 waiting for an interaction answer, 7 dispatch or outcome unknown. Ctrl+C stops observing only.",
|
|
11754
12113
|
positionals: [{ name: "operation", required: true }],
|
|
@@ -11779,6 +12138,7 @@ var runCommands = [
|
|
|
11779
12138
|
},
|
|
11780
12139
|
{
|
|
11781
12140
|
path: ["run", "retry"],
|
|
12141
|
+
action: "run.retry",
|
|
11782
12142
|
summary: "Retry the exact parked prompt/steer of an unknown dispatch under its original key.",
|
|
11783
12143
|
description: "Never sends a different prompt and never mints a new key.",
|
|
11784
12144
|
positionals: [{ name: "operation", required: true }],
|
|
@@ -11799,6 +12159,7 @@ var runCommands = [
|
|
|
11799
12159
|
},
|
|
11800
12160
|
{
|
|
11801
12161
|
path: ["run", "discard"],
|
|
12162
|
+
action: "run.discard",
|
|
11802
12163
|
summary: "Clear the recovery state of an unknown dispatch (does NOT undo a turn that ran).",
|
|
11803
12164
|
positionals: [{ name: "operation", required: true }],
|
|
11804
12165
|
options: [REQUEST_ID_OPTION],
|
|
@@ -11818,6 +12179,7 @@ var runCommands = [
|
|
|
11818
12179
|
},
|
|
11819
12180
|
{
|
|
11820
12181
|
path: ["run", "cancel"],
|
|
12182
|
+
action: "run.cancel",
|
|
11821
12183
|
summary: "Cancel a running exec operation (its exact worker and descendants).",
|
|
11822
12184
|
positionals: [{ name: "operation", required: true }],
|
|
11823
12185
|
options: [REQUEST_ID_OPTION],
|
|
@@ -11837,6 +12199,8 @@ var runCommands = [
|
|
|
11837
12199
|
},
|
|
11838
12200
|
{
|
|
11839
12201
|
path: ["run", "output"],
|
|
12202
|
+
action: "run.output",
|
|
12203
|
+
inputFields: { tail: "tailBytes" },
|
|
11840
12204
|
summary: "Read a bounded window of an exec operation's stdout or stderr.",
|
|
11841
12205
|
positionals: [{ name: "operation", required: true }],
|
|
11842
12206
|
options: [
|
|
@@ -12039,6 +12403,7 @@ function parseAnswers(options2) {
|
|
|
12039
12403
|
var sessionCommands = [
|
|
12040
12404
|
{
|
|
12041
12405
|
path: ["agent", "options"],
|
|
12406
|
+
action: "agent.options",
|
|
12042
12407
|
summary: "Enabled agents, model catalogues (with freshness), and supported controls.",
|
|
12043
12408
|
description: "Reads the backend's cached catalogues; --refresh asks providers again, which can take a while. An `empty` catalogue is a successful empty answer; `stale`/`unavailable` means the backend could not read it.",
|
|
12044
12409
|
positionals: [],
|
|
@@ -12084,6 +12449,7 @@ var sessionCommands = [
|
|
|
12084
12449
|
},
|
|
12085
12450
|
{
|
|
12086
12451
|
path: ["session", "list"],
|
|
12452
|
+
action: "session.list",
|
|
12087
12453
|
summary: "List native-agent sessions of an environment (no transcripts are read).",
|
|
12088
12454
|
positionals: [],
|
|
12089
12455
|
options: [
|
|
@@ -12112,6 +12478,7 @@ var sessionCommands = [
|
|
|
12112
12478
|
},
|
|
12113
12479
|
{
|
|
12114
12480
|
path: ["session", "get"],
|
|
12481
|
+
action: "session.get",
|
|
12115
12482
|
summary: "Show one session (activity, latest request, pending interactions).",
|
|
12116
12483
|
positionals: [{ name: "session", required: true }],
|
|
12117
12484
|
options: [],
|
|
@@ -12132,6 +12499,7 @@ var sessionCommands = [
|
|
|
12132
12499
|
},
|
|
12133
12500
|
{
|
|
12134
12501
|
path: ["session", "start"],
|
|
12502
|
+
action: "session.start",
|
|
12135
12503
|
summary: "Start an independent conversation in a ready environment and send its first prompt.",
|
|
12136
12504
|
description: "Creates a new agent tab without focusing it. The response is a submission receipt; add --wait (or run `run wait`) to observe the turn. Independent sessions in one environment share its files.",
|
|
12137
12505
|
positionals: [],
|
|
@@ -12194,6 +12562,7 @@ var sessionCommands = [
|
|
|
12194
12562
|
},
|
|
12195
12563
|
{
|
|
12196
12564
|
path: ["session", "prompt"],
|
|
12565
|
+
action: "session.prompt",
|
|
12197
12566
|
summary: "Send a follow-up prompt to an idle session.",
|
|
12198
12567
|
description: "Busy sessions are refused (exit 8); use `session steer` to redirect an active turn. The target must be the exact session: a vanished session is never replaced by a new one.",
|
|
12199
12568
|
positionals: [{ name: "session", required: true }],
|
|
@@ -12232,6 +12601,7 @@ var sessionCommands = [
|
|
|
12232
12601
|
},
|
|
12233
12602
|
{
|
|
12234
12603
|
path: ["session", "stop"],
|
|
12604
|
+
action: "session.stop",
|
|
12235
12605
|
summary: "Stop the session's current turn (not the environment).",
|
|
12236
12606
|
description: "--expect-run binds the stop to that run: if a different turn is now active the stop is refused (exit 8). Success requires the provider to confirm the turn ended; otherwise the result is unknown (exit 7).",
|
|
12237
12607
|
positionals: [{ name: "session", required: true }],
|
|
@@ -12263,6 +12633,7 @@ var sessionCommands = [
|
|
|
12263
12633
|
},
|
|
12264
12634
|
{
|
|
12265
12635
|
path: ["session", "steer"],
|
|
12636
|
+
action: "session.steer",
|
|
12266
12637
|
summary: "Redirect the active turn (providers that support steering only).",
|
|
12267
12638
|
positionals: [{ name: "session", required: true }],
|
|
12268
12639
|
options: [
|
|
@@ -12311,6 +12682,7 @@ var sessionCommands = [
|
|
|
12311
12682
|
},
|
|
12312
12683
|
{
|
|
12313
12684
|
path: ["session", "config", "get"],
|
|
12685
|
+
action: "session.config.get",
|
|
12314
12686
|
summary: "Show the live session's effective controls.",
|
|
12315
12687
|
positionals: [{ name: "session", required: true }],
|
|
12316
12688
|
options: [],
|
|
@@ -12329,6 +12701,7 @@ var sessionCommands = [
|
|
|
12329
12701
|
},
|
|
12330
12702
|
{
|
|
12331
12703
|
path: ["session", "config", "set"],
|
|
12704
|
+
action: "session.config.set",
|
|
12332
12705
|
summary: "Change the live session's controls (not environment defaults).",
|
|
12333
12706
|
description: "Applies to this conversation now, as validated by its provider; the response shows the values actually in force (a provider may clamp them). To change defaults for future sessions use `environment config set`.",
|
|
12334
12707
|
positionals: [{ name: "session", required: true }],
|
|
@@ -12350,6 +12723,7 @@ var sessionCommands = [
|
|
|
12350
12723
|
},
|
|
12351
12724
|
{
|
|
12352
12725
|
path: ["session", "history"],
|
|
12726
|
+
action: "session.history",
|
|
12353
12727
|
summary: "List earlier provider conversations this session can resume.",
|
|
12354
12728
|
positionals: [{ name: "session", required: true }],
|
|
12355
12729
|
options: [],
|
|
@@ -12372,6 +12746,7 @@ var sessionCommands = [
|
|
|
12372
12746
|
},
|
|
12373
12747
|
{
|
|
12374
12748
|
path: ["session", "resume"],
|
|
12749
|
+
action: "session.resume",
|
|
12375
12750
|
summary: "Rebind the session to an earlier conversation from `session history`.",
|
|
12376
12751
|
description: "The current conversation's history is kept; nothing is deleted.",
|
|
12377
12752
|
positionals: [
|
|
@@ -12386,6 +12761,8 @@ var sessionCommands = [
|
|
|
12386
12761
|
},
|
|
12387
12762
|
{
|
|
12388
12763
|
path: ["session", "fork"],
|
|
12764
|
+
action: "session.fork",
|
|
12765
|
+
inputFields: { message: "messageId" },
|
|
12389
12766
|
summary: "Fork the conversation into a new session (optionally at a message).",
|
|
12390
12767
|
positionals: [{ name: "session", required: true }],
|
|
12391
12768
|
options: [
|
|
@@ -12416,6 +12793,7 @@ var sessionCommands = [
|
|
|
12416
12793
|
},
|
|
12417
12794
|
{
|
|
12418
12795
|
path: ["session", "interactions", "list"],
|
|
12796
|
+
action: "session.interactions",
|
|
12419
12797
|
summary: "List pending questions and approvals with their permitted answers.",
|
|
12420
12798
|
positionals: [{ name: "session", required: true }],
|
|
12421
12799
|
options: [],
|
|
@@ -12440,6 +12818,8 @@ var sessionCommands = [
|
|
|
12440
12818
|
},
|
|
12441
12819
|
{
|
|
12442
12820
|
path: ["session", "interactions", "resolve"],
|
|
12821
|
+
action: "session.interaction.resolve",
|
|
12822
|
+
inputFields: { revision: "expectedRevision", choose: "answers", text: "answers" },
|
|
12443
12823
|
summary: "Answer one pending interaction at its current revision.",
|
|
12444
12824
|
description: "--revision must match the interaction's current revision; a replaced or expired interaction is refused (exit 8), never answered. Nothing is approved implicitly.",
|
|
12445
12825
|
positionals: [
|
|
@@ -12511,6 +12891,7 @@ var sessionCommands = [
|
|
|
12511
12891
|
},
|
|
12512
12892
|
{
|
|
12513
12893
|
path: ["session", "transcript"],
|
|
12894
|
+
action: "session.transcript",
|
|
12514
12895
|
summary: "Read a bounded transcript page; --follow polls for new messages.",
|
|
12515
12896
|
description: "Pages are oldest-first and hold at most --limit messages (max 100). Pass the returned olderCursor as --before for earlier history. --follow --jsonl streams one record per new message by polling snapshots; it stops at --timeout or Ctrl+C and never affects the session.",
|
|
12516
12897
|
positionals: [{ name: "session", required: true }],
|
|
@@ -12621,6 +13002,243 @@ var sessionCommands = [
|
|
|
12621
13002
|
}
|
|
12622
13003
|
];
|
|
12623
13004
|
|
|
13005
|
+
// src/client/commands/ticket.ts
|
|
13006
|
+
var STATUSES = ["backlog", "in-progress", "review", "done"];
|
|
13007
|
+
var PROJECT_OPTION = {
|
|
13008
|
+
name: "project",
|
|
13009
|
+
kind: "string",
|
|
13010
|
+
valueName: "PROJECT_ID",
|
|
13011
|
+
description: "Project ID (project list)."
|
|
13012
|
+
};
|
|
13013
|
+
var STATUS_OPTION = {
|
|
13014
|
+
name: "status",
|
|
13015
|
+
kind: "string",
|
|
13016
|
+
valueName: "COLUMN",
|
|
13017
|
+
description: `Column: ${STATUSES.join(", ")}.`
|
|
13018
|
+
};
|
|
13019
|
+
var TEXT_FIELD_OPTIONS = [
|
|
13020
|
+
{ name: "title", kind: "string", valueName: "TEXT", description: "Ticket title." },
|
|
13021
|
+
{
|
|
13022
|
+
name: "description",
|
|
13023
|
+
kind: "string",
|
|
13024
|
+
valueName: "TEXT",
|
|
13025
|
+
description: "Description (or --description-file)."
|
|
13026
|
+
},
|
|
13027
|
+
{
|
|
13028
|
+
name: "description-file",
|
|
13029
|
+
kind: "string",
|
|
13030
|
+
valueName: "PATH",
|
|
13031
|
+
description: "Read the description from a local file."
|
|
13032
|
+
},
|
|
13033
|
+
{
|
|
13034
|
+
name: "criteria",
|
|
13035
|
+
kind: "string",
|
|
13036
|
+
valueName: "TEXT",
|
|
13037
|
+
description: "Acceptance criteria."
|
|
13038
|
+
}
|
|
13039
|
+
];
|
|
13040
|
+
function requireProject(options2) {
|
|
13041
|
+
const projectId = stringOption(options2, "project");
|
|
13042
|
+
if (!projectId)
|
|
13043
|
+
throw new CliError("invalid-input", "--project is required");
|
|
13044
|
+
return projectId;
|
|
13045
|
+
}
|
|
13046
|
+
async function ticketFields(io, options2) {
|
|
13047
|
+
const description = await readTextSource(io, {
|
|
13048
|
+
file: options2["description-file"],
|
|
13049
|
+
inline: options2.description,
|
|
13050
|
+
label: "Description",
|
|
13051
|
+
maxBytes: 400000,
|
|
13052
|
+
names: { file: "--description-file", stdin: "--description-stdin", inline: "--description" },
|
|
13053
|
+
required: false
|
|
13054
|
+
});
|
|
13055
|
+
return {
|
|
13056
|
+
...stringOption(options2, "title") !== undefined ? { title: options2.title } : {},
|
|
13057
|
+
...description !== undefined ? { description } : {},
|
|
13058
|
+
...stringOption(options2, "criteria") !== undefined ? { acceptanceCriteria: options2.criteria } : {},
|
|
13059
|
+
...options2.status !== undefined ? { status: oneOf(options2.status, STATUSES, "--status") } : {}
|
|
13060
|
+
};
|
|
13061
|
+
}
|
|
13062
|
+
function ticketRows(tickets) {
|
|
13063
|
+
return table(["ID", "STATUS", "TITLE", "COMMENTS"], tickets.map((ticket) => [ticket.id, ticket.status, ticket.title, String(ticket.commentCount)]));
|
|
13064
|
+
}
|
|
13065
|
+
function ticketLines(ticket) {
|
|
13066
|
+
return [
|
|
13067
|
+
...keyValues([
|
|
13068
|
+
["id", ticket.id],
|
|
13069
|
+
["project", ticket.projectId],
|
|
13070
|
+
["status", ticket.status],
|
|
13071
|
+
["title", ticket.title],
|
|
13072
|
+
["environment", ticket.environmentId],
|
|
13073
|
+
["pr", ticket.pr.url]
|
|
13074
|
+
]),
|
|
13075
|
+
...ticket.description ? ["", ticket.description] : [],
|
|
13076
|
+
...ticket.acceptanceCriteria ? ["", "Acceptance criteria:", ticket.acceptanceCriteria] : [],
|
|
13077
|
+
...ticket.comments.flatMap((comment) => ["", `[${comment.createdAt}] ${comment.text}`])
|
|
13078
|
+
];
|
|
13079
|
+
}
|
|
13080
|
+
var ticketCommands = [
|
|
13081
|
+
{
|
|
13082
|
+
path: ["ticket", "list"],
|
|
13083
|
+
action: "ticket.list",
|
|
13084
|
+
summary: "List a project's Kanban tickets.",
|
|
13085
|
+
positionals: [],
|
|
13086
|
+
options: [
|
|
13087
|
+
PROJECT_OPTION,
|
|
13088
|
+
STATUS_OPTION,
|
|
13089
|
+
{ name: "limit", kind: "integer", valueName: "N", description: "Items per page (max 200)." },
|
|
13090
|
+
{
|
|
13091
|
+
name: "cursor",
|
|
13092
|
+
kind: "string",
|
|
13093
|
+
valueName: "CURSOR",
|
|
13094
|
+
description: "Continue from a previous page."
|
|
13095
|
+
}
|
|
13096
|
+
],
|
|
13097
|
+
idOutput: "ticket IDs, one per line",
|
|
13098
|
+
async run(context, parsed) {
|
|
13099
|
+
const session = await context.session();
|
|
13100
|
+
const page = await session.read("ticket.list", {
|
|
13101
|
+
projectId: requireProject(parsed.options),
|
|
13102
|
+
...parsed.options.status !== undefined ? { status: oneOf(parsed.options.status, STATUSES, "--status") } : {},
|
|
13103
|
+
...parsed.options.limit !== undefined ? { limit: parsed.options.limit } : {},
|
|
13104
|
+
...parsed.options.cursor !== undefined ? { cursor: parsed.options.cursor } : {}
|
|
13105
|
+
});
|
|
13106
|
+
return {
|
|
13107
|
+
action: "ticket.list",
|
|
13108
|
+
result: page,
|
|
13109
|
+
connection: session.identity,
|
|
13110
|
+
ids: page.items.map((ticket) => ticket.id),
|
|
13111
|
+
human: [
|
|
13112
|
+
...ticketRows(page.items),
|
|
13113
|
+
...page.nextCursor ? [`more: --cursor ${page.nextCursor}`] : []
|
|
13114
|
+
]
|
|
13115
|
+
};
|
|
13116
|
+
}
|
|
13117
|
+
},
|
|
13118
|
+
{
|
|
13119
|
+
path: ["ticket", "get"],
|
|
13120
|
+
action: "ticket.get",
|
|
13121
|
+
summary: "Show one ticket with its description, criteria and latest comments.",
|
|
13122
|
+
positionals: [{ name: "ticket", required: true }],
|
|
13123
|
+
options: [PROJECT_OPTION],
|
|
13124
|
+
inputFields: { ticket: "ticketId" },
|
|
13125
|
+
idOutput: "ticket ID",
|
|
13126
|
+
async run(context, parsed) {
|
|
13127
|
+
const session = await context.session();
|
|
13128
|
+
const ticket = await session.read("ticket.get", {
|
|
13129
|
+
projectId: requireProject(parsed.options),
|
|
13130
|
+
ticketId: parsed.positionals.ticket
|
|
13131
|
+
});
|
|
13132
|
+
return {
|
|
13133
|
+
action: "ticket.get",
|
|
13134
|
+
result: ticket,
|
|
13135
|
+
connection: session.identity,
|
|
13136
|
+
ids: [ticket.id],
|
|
13137
|
+
human: ticketLines(ticket)
|
|
13138
|
+
};
|
|
13139
|
+
}
|
|
13140
|
+
},
|
|
13141
|
+
{
|
|
13142
|
+
path: ["ticket", "create"],
|
|
13143
|
+
action: "ticket.create",
|
|
13144
|
+
summary: "Create a Kanban ticket.",
|
|
13145
|
+
positionals: [],
|
|
13146
|
+
options: [PROJECT_OPTION, ...TEXT_FIELD_OPTIONS, STATUS_OPTION, REQUEST_ID_OPTION],
|
|
13147
|
+
inputFields: {
|
|
13148
|
+
"description-file": "description",
|
|
13149
|
+
criteria: "acceptanceCriteria"
|
|
13150
|
+
},
|
|
13151
|
+
idOutput: "ticket ID",
|
|
13152
|
+
async run(context, parsed) {
|
|
13153
|
+
const fields = await ticketFields(context.io, parsed.options);
|
|
13154
|
+
if (typeof fields.title !== "string")
|
|
13155
|
+
throw new CliError("invalid-input", "--title is required");
|
|
13156
|
+
const { session, result, receipt, warnings } = await submit(context, "ticket.create", { projectId: requireProject(parsed.options), ...fields }, parsed.options);
|
|
13157
|
+
return {
|
|
13158
|
+
action: "ticket.create",
|
|
13159
|
+
result,
|
|
13160
|
+
receipt,
|
|
13161
|
+
warnings,
|
|
13162
|
+
connection: session.identity,
|
|
13163
|
+
ids: [result.ticketId],
|
|
13164
|
+
human: [`created ticket ${result.ticketId}`]
|
|
13165
|
+
};
|
|
13166
|
+
}
|
|
13167
|
+
},
|
|
13168
|
+
{
|
|
13169
|
+
path: ["ticket", "update"],
|
|
13170
|
+
action: "ticket.update",
|
|
13171
|
+
summary: "Change a ticket's title, description, criteria or column.",
|
|
13172
|
+
positionals: [{ name: "ticket", required: true }],
|
|
13173
|
+
options: [PROJECT_OPTION, ...TEXT_FIELD_OPTIONS, STATUS_OPTION, REQUEST_ID_OPTION],
|
|
13174
|
+
inputFields: {
|
|
13175
|
+
ticket: "ticketId",
|
|
13176
|
+
"description-file": "description",
|
|
13177
|
+
criteria: "acceptanceCriteria"
|
|
13178
|
+
},
|
|
13179
|
+
idOutput: "ticket ID",
|
|
13180
|
+
async run(context, parsed) {
|
|
13181
|
+
const fields = await ticketFields(context.io, parsed.options);
|
|
13182
|
+
if (Object.keys(fields).length === 0) {
|
|
13183
|
+
throw new CliError("invalid-input", "Pass at least one field to change");
|
|
13184
|
+
}
|
|
13185
|
+
const { session, result, receipt, warnings } = await submit(context, "ticket.update", {
|
|
13186
|
+
projectId: requireProject(parsed.options),
|
|
13187
|
+
ticketId: parsed.positionals.ticket,
|
|
13188
|
+
...fields
|
|
13189
|
+
}, parsed.options);
|
|
13190
|
+
return {
|
|
13191
|
+
action: "ticket.update",
|
|
13192
|
+
result,
|
|
13193
|
+
receipt,
|
|
13194
|
+
warnings,
|
|
13195
|
+
connection: session.identity,
|
|
13196
|
+
ids: [result.ticketId],
|
|
13197
|
+
human: [`updated ticket ${result.ticketId}`]
|
|
13198
|
+
};
|
|
13199
|
+
}
|
|
13200
|
+
},
|
|
13201
|
+
{
|
|
13202
|
+
path: ["ticket", "comment"],
|
|
13203
|
+
action: "ticket.comment",
|
|
13204
|
+
summary: "Append a comment to a ticket.",
|
|
13205
|
+
positionals: [{ name: "ticket", required: true }],
|
|
13206
|
+
options: [
|
|
13207
|
+
PROJECT_OPTION,
|
|
13208
|
+
{ name: "text", kind: "string", valueName: "TEXT", description: "Comment text." },
|
|
13209
|
+
{
|
|
13210
|
+
name: "text-file",
|
|
13211
|
+
kind: "string",
|
|
13212
|
+
valueName: "PATH",
|
|
13213
|
+
description: "Read the comment from a local file."
|
|
13214
|
+
},
|
|
13215
|
+
REQUEST_ID_OPTION
|
|
13216
|
+
],
|
|
13217
|
+
inputFields: { ticket: "ticketId", "text-file": "text" },
|
|
13218
|
+
idOutput: "ticket ID",
|
|
13219
|
+
async run(context, parsed) {
|
|
13220
|
+
const text = await readTextSource(context.io, {
|
|
13221
|
+
file: parsed.options["text-file"],
|
|
13222
|
+
inline: parsed.options.text,
|
|
13223
|
+
label: "Comment",
|
|
13224
|
+
maxBytes: 80000,
|
|
13225
|
+
names: { file: "--text-file", stdin: "--text-stdin", inline: "--text" },
|
|
13226
|
+
required: true
|
|
13227
|
+
});
|
|
13228
|
+
const { session, result, receipt, warnings } = await submit(context, "ticket.comment", { projectId: requireProject(parsed.options), ticketId: parsed.positionals.ticket, text }, parsed.options);
|
|
13229
|
+
return {
|
|
13230
|
+
action: "ticket.comment",
|
|
13231
|
+
result,
|
|
13232
|
+
receipt,
|
|
13233
|
+
warnings,
|
|
13234
|
+
connection: session.identity,
|
|
13235
|
+
ids: [result.ticketId],
|
|
13236
|
+
human: [`commented on ticket ${result.ticketId}`]
|
|
13237
|
+
};
|
|
13238
|
+
}
|
|
13239
|
+
}
|
|
13240
|
+
];
|
|
13241
|
+
|
|
12624
13242
|
// src/client/commands/toolchain.ts
|
|
12625
13243
|
import path18 from "path";
|
|
12626
13244
|
function dataDirectory2(context, parsed) {
|
|
@@ -13046,6 +13664,9 @@ var CLIENT_COMMANDS = [
|
|
|
13046
13664
|
...environmentCommands,
|
|
13047
13665
|
...sessionCommands,
|
|
13048
13666
|
...changesCommands,
|
|
13667
|
+
...attentionCommands,
|
|
13668
|
+
...ticketCommands,
|
|
13669
|
+
...mailCommands,
|
|
13049
13670
|
...runCommands,
|
|
13050
13671
|
...toolchainCommands,
|
|
13051
13672
|
...hostCommands,
|