@robbeverhelst/do 1.151.0 → 1.153.0
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/do.js +301 -3
- package/package.json +1 -1
package/dist/do.js
CHANGED
|
@@ -2571,6 +2571,7 @@ var tenants = pgTable("tenants", {
|
|
|
2571
2571
|
id: text("id").primaryKey(),
|
|
2572
2572
|
name: text("name").notNull(),
|
|
2573
2573
|
backdrop: text("backdrop"),
|
|
2574
|
+
gaardHouseUrl: text("gaard_house_url"),
|
|
2574
2575
|
createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
|
|
2575
2576
|
updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
|
|
2576
2577
|
deletedAt: timestamp("deleted_at", { withTimezone: true })
|
|
@@ -18024,7 +18025,7 @@ var spaceSchema = createSelectSchema(tenants, {
|
|
|
18024
18025
|
createdAt: exports_external.coerce.date(),
|
|
18025
18026
|
updatedAt: exports_external.coerce.date(),
|
|
18026
18027
|
deletedAt: exports_external.coerce.date().nullable()
|
|
18027
|
-
});
|
|
18028
|
+
}).omit({ gaardHouseUrl: true });
|
|
18028
18029
|
var backdropIdSchema = exports_external.string().trim().regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/, "a backdrop id is lowercase words joined by dashes").max(40);
|
|
18029
18030
|
var updateSpaceInputSchema = exports_external.object({
|
|
18030
18031
|
name: exports_external.string().trim().min(1).max(120).optional(),
|
|
@@ -18050,6 +18051,60 @@ var linkGoogleInputSchema = exports_external.object({
|
|
|
18050
18051
|
state: exports_external.string().min(1)
|
|
18051
18052
|
});
|
|
18052
18053
|
|
|
18054
|
+
// ../../packages/schema/src/contracts/changes.ts
|
|
18055
|
+
var changeOpSchema = exports_external.enum(["created", "updated", "deleted"]);
|
|
18056
|
+
var CHANGE_ENTITY_SCOPES = {
|
|
18057
|
+
task: "tasks:read",
|
|
18058
|
+
project: "projects:read",
|
|
18059
|
+
area: "areas:read",
|
|
18060
|
+
routine: "routines:read",
|
|
18061
|
+
habit: "habits:read",
|
|
18062
|
+
occurrence: "occurrences:read",
|
|
18063
|
+
note: "notes:read",
|
|
18064
|
+
contact: "contacts:read",
|
|
18065
|
+
collection_item: "collections:read",
|
|
18066
|
+
inventory_item: "inventory:read",
|
|
18067
|
+
shopping_list: "shopping:read",
|
|
18068
|
+
recipe: "meals:read",
|
|
18069
|
+
meal_plan: "meals:read",
|
|
18070
|
+
event: "calendar:read",
|
|
18071
|
+
time_block: "calendar:read",
|
|
18072
|
+
place: "places:read"
|
|
18073
|
+
};
|
|
18074
|
+
var CHANGE_ENTITIES = Object.keys(CHANGE_ENTITY_SCOPES);
|
|
18075
|
+
var changeEntitySchema = exports_external.enum(CHANGE_ENTITIES);
|
|
18076
|
+
var changeSchema = exports_external.object({
|
|
18077
|
+
entity: changeEntitySchema,
|
|
18078
|
+
id: exports_external.string(),
|
|
18079
|
+
op: changeOpSchema,
|
|
18080
|
+
changedAt: exports_external.coerce.date()
|
|
18081
|
+
});
|
|
18082
|
+
var MAX_CHANGES_LIMIT = 500;
|
|
18083
|
+
var CHANGES_SINCE_NOW = "now";
|
|
18084
|
+
var CURSOR_RE = /^(\d+)-(\d+)$/;
|
|
18085
|
+
function parseChangeCursor(raw) {
|
|
18086
|
+
const m = CURSOR_RE.exec(raw);
|
|
18087
|
+
if (!m)
|
|
18088
|
+
return null;
|
|
18089
|
+
const txid = Number(m[1]);
|
|
18090
|
+
const seq = Number(m[2]);
|
|
18091
|
+
if (!Number.isSafeInteger(txid) || !Number.isSafeInteger(seq))
|
|
18092
|
+
return null;
|
|
18093
|
+
return { txid, seq };
|
|
18094
|
+
}
|
|
18095
|
+
var changesQuerySchema = exports_external.object({
|
|
18096
|
+
since: exports_external.string().refine((s) => s === CHANGES_SINCE_NOW || parseChangeCursor(s) !== null, {
|
|
18097
|
+
message: "since must be a cursor from a prior page's nextCursor, or 'now'"
|
|
18098
|
+
}).optional(),
|
|
18099
|
+
limit: exports_external.coerce.number().int().positive().transform((n) => Math.min(n, MAX_CHANGES_LIMIT)).optional(),
|
|
18100
|
+
entity: exports_external.string().transform((s) => s.split(",").map((e) => e.trim()).filter((e) => e.length > 0)).pipe(exports_external.array(changeEntitySchema).min(1)).optional()
|
|
18101
|
+
});
|
|
18102
|
+
var changesPageSchema = exports_external.object({
|
|
18103
|
+
data: exports_external.array(changeSchema),
|
|
18104
|
+
nextCursor: exports_external.string(),
|
|
18105
|
+
hasMore: exports_external.boolean()
|
|
18106
|
+
});
|
|
18107
|
+
|
|
18053
18108
|
// ../../packages/schema/src/contracts/value-sets.ts
|
|
18054
18109
|
var areaColorSchema = exports_external.enum(areaColor.enumValues);
|
|
18055
18110
|
var reviewCadenceSchema = exports_external.enum(reviewCadence.enumValues);
|
|
@@ -19071,6 +19126,22 @@ var importPlacesResultSchema = exports_external.object({
|
|
|
19071
19126
|
skipped: exports_external.number().int().min(0),
|
|
19072
19127
|
places: exports_external.array(placeViewSchema)
|
|
19073
19128
|
});
|
|
19129
|
+
function asUrl(value) {
|
|
19130
|
+
try {
|
|
19131
|
+
return new URL(value);
|
|
19132
|
+
} catch {
|
|
19133
|
+
return null;
|
|
19134
|
+
}
|
|
19135
|
+
}
|
|
19136
|
+
var gaardHouseUrlSchema = exports_external.string().trim().max(2048).url("that isn't a URL").refine((value) => asUrl(value)?.protocol === "https:", "the URL must start with https://").refine((value) => {
|
|
19137
|
+
const url2 = asUrl(value);
|
|
19138
|
+
return !url2 || url2.username === "" && url2.password === "";
|
|
19139
|
+
}, "the URL can't hold a username or password");
|
|
19140
|
+
var placesSourceSchema = exports_external.object({ gaardHouseUrl: exports_external.string().nullable() });
|
|
19141
|
+
var updatePlacesSourceInputSchema = exports_external.object({
|
|
19142
|
+
gaardHouseUrl: exports_external.union([exports_external.literal("").transform(() => null), gaardHouseUrlSchema]).nullable()
|
|
19143
|
+
}).strict();
|
|
19144
|
+
var importLinkedHouseInputSchema = exports_external.object({ houseIndex: exports_external.number().int().min(0).default(0) }).strict();
|
|
19074
19145
|
|
|
19075
19146
|
// ../../packages/schema/src/contracts/modules.ts
|
|
19076
19147
|
var MODULE_KEYS = [
|
|
@@ -19532,6 +19603,110 @@ var timeBlockRangeQuerySchema = exports_external.object({
|
|
|
19532
19603
|
path: ["to"]
|
|
19533
19604
|
});
|
|
19534
19605
|
|
|
19606
|
+
// ../../packages/schema/src/contracts/agent-chat.ts
|
|
19607
|
+
var agentConnectionSourceSchema = exports_external.enum(["space", "env"]);
|
|
19608
|
+
var agentConnectionSchema = exports_external.object({
|
|
19609
|
+
connected: exports_external.boolean(),
|
|
19610
|
+
source: agentConnectionSourceSchema.nullable(),
|
|
19611
|
+
endpoint: exports_external.string().nullable(),
|
|
19612
|
+
model: exports_external.string().nullable(),
|
|
19613
|
+
hasKey: exports_external.boolean(),
|
|
19614
|
+
agentId: exports_external.string().nullable(),
|
|
19615
|
+
autoFile: exports_external.boolean(),
|
|
19616
|
+
updatedAt: exports_external.coerce.date().nullable()
|
|
19617
|
+
});
|
|
19618
|
+
var agentEndpointSchema = exports_external.string().trim().max(2000).url().refine((value) => /^https?:\/\//i.test(value), "endpoint must be an http(s) URL");
|
|
19619
|
+
var saveAgentConnectionInputSchema = exports_external.object({
|
|
19620
|
+
endpoint: agentEndpointSchema,
|
|
19621
|
+
apiKey: exports_external.string().trim().min(1).max(4000).nullable().optional(),
|
|
19622
|
+
model: exports_external.string().trim().min(1).max(200).nullable().optional(),
|
|
19623
|
+
agentId: exports_external.string().trim().min(1).max(64).nullable().optional(),
|
|
19624
|
+
autoFile: exports_external.boolean().optional()
|
|
19625
|
+
}).strict();
|
|
19626
|
+
var agentPageContextSchema = exports_external.object({
|
|
19627
|
+
route: exports_external.string().trim().min(1).max(500).startsWith("/"),
|
|
19628
|
+
nodeId: exports_external.string().trim().min(1).max(64).nullable()
|
|
19629
|
+
}).strict();
|
|
19630
|
+
var agentChatInputSchema = exports_external.object({
|
|
19631
|
+
message: exports_external.string().trim().min(1).max(8000),
|
|
19632
|
+
context: agentPageContextSchema
|
|
19633
|
+
}).strict();
|
|
19634
|
+
var agentChatEventSchema = exports_external.discriminatedUnion("type", [
|
|
19635
|
+
exports_external.object({ type: exports_external.literal("delta"), text: exports_external.string() }),
|
|
19636
|
+
exports_external.object({ type: exports_external.literal("done") }),
|
|
19637
|
+
exports_external.object({ type: exports_external.literal("error"), message: exports_external.string() })
|
|
19638
|
+
]);
|
|
19639
|
+
var agentChangeValueSchema = exports_external.union([
|
|
19640
|
+
exports_external.string(),
|
|
19641
|
+
exports_external.number(),
|
|
19642
|
+
exports_external.boolean(),
|
|
19643
|
+
exports_external.null(),
|
|
19644
|
+
exports_external.array(exports_external.string())
|
|
19645
|
+
]);
|
|
19646
|
+
var agentChangeFieldSchema = exports_external.object({
|
|
19647
|
+
field: exports_external.string(),
|
|
19648
|
+
before: agentChangeValueSchema,
|
|
19649
|
+
after: agentChangeValueSchema,
|
|
19650
|
+
beforeLabel: exports_external.string().nullable().optional(),
|
|
19651
|
+
afterLabel: exports_external.string().nullable().optional()
|
|
19652
|
+
});
|
|
19653
|
+
var agentChangeSchema = exports_external.object({
|
|
19654
|
+
entity: changeEntitySchema,
|
|
19655
|
+
id: exports_external.string(),
|
|
19656
|
+
op: changeOpSchema,
|
|
19657
|
+
changedAt: exports_external.coerce.date(),
|
|
19658
|
+
title: exports_external.string().nullable(),
|
|
19659
|
+
actor: actorRefSchema,
|
|
19660
|
+
fields: exports_external.array(agentChangeFieldSchema).optional()
|
|
19661
|
+
});
|
|
19662
|
+
var agentChangesPageSchema = exports_external.object({
|
|
19663
|
+
data: exports_external.array(agentChangeSchema),
|
|
19664
|
+
nextCursor: exports_external.string()
|
|
19665
|
+
});
|
|
19666
|
+
var agentChangesQuerySchema = exports_external.object({
|
|
19667
|
+
since: exports_external.string().refine((s) => s === "now" || /^\d+-\d+$/.test(s), {
|
|
19668
|
+
message: "since must be a cursor from a prior page's nextCursor, or 'now'"
|
|
19669
|
+
})
|
|
19670
|
+
});
|
|
19671
|
+
var agentConfirmationKindSchema = exports_external.enum(["delete", "cancel", "google", "orca", "bulk"]);
|
|
19672
|
+
var agentConfirmationStatusSchema = exports_external.enum([
|
|
19673
|
+
"pending",
|
|
19674
|
+
"confirmed",
|
|
19675
|
+
"done",
|
|
19676
|
+
"failed",
|
|
19677
|
+
"declined"
|
|
19678
|
+
]);
|
|
19679
|
+
var agentConfirmationSchema = exports_external.object({
|
|
19680
|
+
id: exports_external.string(),
|
|
19681
|
+
kind: agentConfirmationKindSchema,
|
|
19682
|
+
summary: exports_external.string(),
|
|
19683
|
+
items: exports_external.array(exports_external.object({ id: exports_external.string(), title: exports_external.string().nullable() })),
|
|
19684
|
+
method: exports_external.string(),
|
|
19685
|
+
path: exports_external.string(),
|
|
19686
|
+
status: agentConfirmationStatusSchema,
|
|
19687
|
+
agent: exports_external.object({ id: exports_external.string(), name: exports_external.string().nullable() }),
|
|
19688
|
+
createdAt: exports_external.coerce.date(),
|
|
19689
|
+
decidedAt: exports_external.coerce.date().nullable()
|
|
19690
|
+
});
|
|
19691
|
+
var agentUndoInputSchema = exports_external.object({
|
|
19692
|
+
id: exports_external.string().trim().min(1).max(64),
|
|
19693
|
+
since: exports_external.string().regex(/^\d+-\d+$/, "since must be a change-feed cursor")
|
|
19694
|
+
}).strict();
|
|
19695
|
+
var agentUndoResultSchema = exports_external.object({
|
|
19696
|
+
id: exports_external.string(),
|
|
19697
|
+
undone: exports_external.enum(["removed", "restored"])
|
|
19698
|
+
});
|
|
19699
|
+
var agentRedoResultSchema = exports_external.object({
|
|
19700
|
+
id: exports_external.string(),
|
|
19701
|
+
redone: exports_external.literal(true)
|
|
19702
|
+
});
|
|
19703
|
+
var agentFilingSchema = exports_external.object({
|
|
19704
|
+
confident: exports_external.boolean().default(false),
|
|
19705
|
+
areaId: exports_external.string().nullable().optional(),
|
|
19706
|
+
owner: exports_external.string().nullable().optional(),
|
|
19707
|
+
date: exports_external.string().regex(/^\d{4}-\d{2}-\d{2}$/).nullable().optional()
|
|
19708
|
+
});
|
|
19709
|
+
|
|
19535
19710
|
// ../../packages/schema/src/contracts/roles.ts
|
|
19536
19711
|
var permissionSetSchema = createSelectSchema(permissionSets, {
|
|
19537
19712
|
createdAt: exports_external.coerce.date(),
|
|
@@ -20631,7 +20806,7 @@ function parseCapture2(input, now) {
|
|
|
20631
20806
|
|
|
20632
20807
|
// src/meta.ts
|
|
20633
20808
|
var CLI_NAME = "do";
|
|
20634
|
-
var VERSION = "1.
|
|
20809
|
+
var VERSION = "1.153.0";
|
|
20635
20810
|
var API_PREFIX = "/api/v1";
|
|
20636
20811
|
var DEFAULT_API_URL = "http://localhost:3001";
|
|
20637
20812
|
|
|
@@ -21530,6 +21705,68 @@ var COMMAND_SPECS = [
|
|
|
21530
21705
|
returns: "None",
|
|
21531
21706
|
notes: "Gated behind --allow-destructive + an orca:write key. Idempotent."
|
|
21532
21707
|
},
|
|
21708
|
+
{
|
|
21709
|
+
path: ["agents", "list"],
|
|
21710
|
+
summary: "List the Space's Agents (id + name).",
|
|
21711
|
+
args: [],
|
|
21712
|
+
flags: [],
|
|
21713
|
+
scopes: ["agents:read"],
|
|
21714
|
+
returns: "AgentSummary",
|
|
21715
|
+
notes: "Creating an Agent and minting its keys stays a member's job in the app."
|
|
21716
|
+
},
|
|
21717
|
+
{
|
|
21718
|
+
path: ["agent", "connection", "get"],
|
|
21719
|
+
summary: "Show the agent runtime the Echo panel's chat goes to (never its key).",
|
|
21720
|
+
args: [],
|
|
21721
|
+
flags: [],
|
|
21722
|
+
scopes: ["agents:read"],
|
|
21723
|
+
returns: "AgentConnection",
|
|
21724
|
+
notes: "hasKey says whether a key is set; the key itself is write-only."
|
|
21725
|
+
},
|
|
21726
|
+
{
|
|
21727
|
+
path: ["agent", "connection", "set"],
|
|
21728
|
+
summary: "Point the Echo panel at an agent runtime (replaces the connection).",
|
|
21729
|
+
args: [],
|
|
21730
|
+
flags: [
|
|
21731
|
+
{ name: "endpoint", type: "string", description: "The runtime's base URL (required)." },
|
|
21732
|
+
{
|
|
21733
|
+
name: "model",
|
|
21734
|
+
type: "string",
|
|
21735
|
+
description: "The model to ask for, if the runtime needs one."
|
|
21736
|
+
},
|
|
21737
|
+
{
|
|
21738
|
+
name: "agent",
|
|
21739
|
+
type: "string",
|
|
21740
|
+
description: "The Agent the runtime acts as: its id or name (see `agents list`)."
|
|
21741
|
+
},
|
|
21742
|
+
{
|
|
21743
|
+
name: "auto-file",
|
|
21744
|
+
type: "boolean",
|
|
21745
|
+
description: "Let Echo file new captures (needs --agent)."
|
|
21746
|
+
},
|
|
21747
|
+
{ name: "no-auto-file", type: "boolean", description: "Stop Echo filing new captures." },
|
|
21748
|
+
{
|
|
21749
|
+
name: "key-stdin",
|
|
21750
|
+
type: "boolean",
|
|
21751
|
+
description: "Read the runtime's API key from stdin's first line instead of DO_AGENT_API_KEY."
|
|
21752
|
+
},
|
|
21753
|
+
{ name: "clear-key", type: "boolean", description: "Remove the stored key." }
|
|
21754
|
+
],
|
|
21755
|
+
scopes: ["agents:write"],
|
|
21756
|
+
returns: "AgentConnection",
|
|
21757
|
+
notes: "The runtime's key is read from DO_AGENT_API_KEY or, with --key-stdin, from stdin \u2014 never a flag. With neither, the stored key is kept. --model and --agent are replaced as sent (left out clears them). Owner/admin only (canManageSpace)."
|
|
21758
|
+
},
|
|
21759
|
+
{
|
|
21760
|
+
path: ["agent", "connection", "remove"],
|
|
21761
|
+
summary: "Forget the Space's agent connection (destructive).",
|
|
21762
|
+
args: [],
|
|
21763
|
+
flags: [
|
|
21764
|
+
{ name: "allow-destructive", type: "boolean", description: "Required to actually remove." }
|
|
21765
|
+
],
|
|
21766
|
+
scopes: ["agents:write"],
|
|
21767
|
+
returns: "None",
|
|
21768
|
+
notes: "Owner/admin only. An Agent's key gets a 428 confirmation_required until the member confirms in the Echo panel."
|
|
21769
|
+
},
|
|
21533
21770
|
{
|
|
21534
21771
|
path: ["settings", "get"],
|
|
21535
21772
|
summary: "Show the caller's settings for the Space.",
|
|
@@ -22051,7 +22288,7 @@ var COMMAND_SPECS = [
|
|
|
22051
22288
|
}
|
|
22052
22289
|
];
|
|
22053
22290
|
function matchCommandSpec(positionals) {
|
|
22054
|
-
for (const len of [2, 1]) {
|
|
22291
|
+
for (const len of [3, 2, 1]) {
|
|
22055
22292
|
const candidate = positionals.slice(0, len);
|
|
22056
22293
|
if (candidate.length < len)
|
|
22057
22294
|
continue;
|
|
@@ -23217,6 +23454,35 @@ var HANDLERS = {
|
|
|
23217
23454
|
const input = parseInput(logMetricInputSchema, { value, ...at ? { occurredAt: at } : {} });
|
|
23218
23455
|
return { data: await requireClient().post(`/metrics/${key}`, input), render: renderRecord };
|
|
23219
23456
|
},
|
|
23457
|
+
"agents list": async ({ requireClient }) => ({
|
|
23458
|
+
data: await requireClient().getPage("/agents"),
|
|
23459
|
+
render: renderList
|
|
23460
|
+
}),
|
|
23461
|
+
"agent connection get": async ({ requireClient }) => ({
|
|
23462
|
+
data: await requireClient().get("/agent/connection"),
|
|
23463
|
+
render: renderRecord
|
|
23464
|
+
}),
|
|
23465
|
+
"agent connection set": async ({ io, flags, requireClient }) => {
|
|
23466
|
+
const endpoint = flagString(flags, "endpoint");
|
|
23467
|
+
if (endpoint === undefined)
|
|
23468
|
+
throw usageError("agent connection set needs --endpoint <url>");
|
|
23469
|
+
const client = requireClient();
|
|
23470
|
+
const agent = flagString(flags, "agent");
|
|
23471
|
+
const autoFile = flagBool(flags, "auto-file") ? true : flagBool(flags, "no-auto-file") ? false : undefined;
|
|
23472
|
+
const body = parseInput(saveAgentConnectionInputSchema, {
|
|
23473
|
+
endpoint,
|
|
23474
|
+
model: flagString(flags, "model"),
|
|
23475
|
+
agentId: agent === undefined ? undefined : await resolveAgentId(client, agent),
|
|
23476
|
+
autoFile,
|
|
23477
|
+
apiKey: await readAgentKey(io, flags)
|
|
23478
|
+
});
|
|
23479
|
+
return { data: await client.put("/agent/connection", body), render: renderRecord };
|
|
23480
|
+
},
|
|
23481
|
+
"agent connection remove": async ({ flags, requireClient }) => {
|
|
23482
|
+
assertDestructiveAllowed(flags, "remove the agent connection");
|
|
23483
|
+
await requireClient().delete("/agent/connection");
|
|
23484
|
+
return { data: { ok: true, removed: "agent connection" }, render: renderRecord };
|
|
23485
|
+
},
|
|
23220
23486
|
"settings get": async ({ requireClient }) => ({
|
|
23221
23487
|
data: await requireClient().get("/settings"),
|
|
23222
23488
|
render: renderRecord
|
|
@@ -23635,6 +23901,38 @@ function redact(secret) {
|
|
|
23635
23901
|
return "********";
|
|
23636
23902
|
return `${secret.slice(0, 6)}\u2026${secret.slice(-2)}`;
|
|
23637
23903
|
}
|
|
23904
|
+
var AGENT_KEY_ENV = "DO_AGENT_API_KEY";
|
|
23905
|
+
async function readAgentKey(io, flags) {
|
|
23906
|
+
if (flagBool(flags, "clear-key"))
|
|
23907
|
+
return null;
|
|
23908
|
+
if (flagBool(flags, "key-stdin")) {
|
|
23909
|
+
let first;
|
|
23910
|
+
if (io.stdin) {
|
|
23911
|
+
for await (const line2 of io.stdin) {
|
|
23912
|
+
first = line2;
|
|
23913
|
+
break;
|
|
23914
|
+
}
|
|
23915
|
+
}
|
|
23916
|
+
const key = first?.trim();
|
|
23917
|
+
if (!key)
|
|
23918
|
+
throw usageError("--key-stdin read no key: pipe the key in on stdin");
|
|
23919
|
+
return key;
|
|
23920
|
+
}
|
|
23921
|
+
const fromEnv = io.env[AGENT_KEY_ENV]?.trim();
|
|
23922
|
+
return fromEnv ? fromEnv : undefined;
|
|
23923
|
+
}
|
|
23924
|
+
var ULID = /^[0-9A-HJKMNP-TV-Z]{26}$/i;
|
|
23925
|
+
async function resolveAgentId(client, agent) {
|
|
23926
|
+
if (ULID.test(agent))
|
|
23927
|
+
return agent;
|
|
23928
|
+
const { data } = await client.getPage("/agents");
|
|
23929
|
+
const wanted = agent.trim().toLowerCase();
|
|
23930
|
+
const match = data.find((a) => a.name.toLowerCase() === wanted);
|
|
23931
|
+
if (!match) {
|
|
23932
|
+
throw new CliError("not_found", `no Agent named ${agent} \u2014 see \`do agents list\``, EXIT.NOT_FOUND);
|
|
23933
|
+
}
|
|
23934
|
+
return match.id;
|
|
23935
|
+
}
|
|
23638
23936
|
function requireWrite(entity, op) {
|
|
23639
23937
|
if (!entity.write) {
|
|
23640
23938
|
throw usageError(`\`${entity.name}\` is read-only \u2014 \`${op}\` is not available`);
|