@sinoia/hubdoc-tools 1.10.0 → 1.11.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/cli.js +111 -22
- package/docs/llm-usage.md +37 -11
- package/package.json +1 -1
package/cli.js
CHANGED
|
@@ -95034,7 +95034,7 @@ var require_bignumber = __commonJS({
|
|
|
95034
95034
|
"node_modules/bignumber.js/bignumber.js"(exports2, module2) {
|
|
95035
95035
|
(function(globalObject) {
|
|
95036
95036
|
"use strict";
|
|
95037
|
-
var BigNumber, isNumeric = /^-?(?:\d+(?:\.\d*)?|\.\d+)(?:e[+-]?\d+)?$/i, mathceil = Math.ceil, mathfloor = Math.floor, bignumberError = "[BigNumber Error] ", tooManyDigits = bignumberError + "Number primitive has more than 15 significant digits: ",
|
|
95037
|
+
var BigNumber, isNumeric = /^-?(?:\d+(?:\.\d*)?|\.\d+)(?:e[+-]?\d+)?$/i, mathceil = Math.ceil, mathfloor = Math.floor, bignumberError = "[BigNumber Error] ", tooManyDigits = bignumberError + "Number primitive has more than 15 significant digits: ", BASE5 = 1e14, LOG_BASE = 14, MAX_SAFE_INTEGER = 9007199254740991, POWS_TEN = [1, 10, 100, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 1e11, 1e12, 1e13], SQRT_BASE = 1e7, MAX = 1e9;
|
|
95038
95038
|
function clone(configObject) {
|
|
95039
95039
|
var div, convertBase, parseNumeric, P = BigNumber2.prototype = { constructor: BigNumber2, toString: null, valueOf: null }, ONE = new BigNumber2(1), DECIMAL_PLACES = 20, ROUNDING_MODE = 4, TO_EXP_NEG = -7, TO_EXP_POS = 21, MIN_EXP = -1e7, MAX_EXP = 1e7, CRYPTO = false, MODULO_MODE = 1, POW_PRECISION = 0, FORMAT = {
|
|
95040
95040
|
prefix: "",
|
|
@@ -95286,7 +95286,7 @@ var require_bignumber = __commonJS({
|
|
|
95286
95286
|
if (String(c3[0]).length == i3) {
|
|
95287
95287
|
for (i3 = 0; i3 < c3.length; i3++) {
|
|
95288
95288
|
n3 = c3[i3];
|
|
95289
|
-
if (n3 < 0 || n3 >=
|
|
95289
|
+
if (n3 < 0 || n3 >= BASE5 || n3 !== mathfloor(n3)) break out;
|
|
95290
95290
|
}
|
|
95291
95291
|
if (n3 !== 0) return true;
|
|
95292
95292
|
}
|
|
@@ -95503,7 +95503,7 @@ var require_bignumber = __commonJS({
|
|
|
95503
95503
|
e3 = x3.e - y2.e;
|
|
95504
95504
|
s3 = dp + e3 + 1;
|
|
95505
95505
|
if (!base) {
|
|
95506
|
-
base =
|
|
95506
|
+
base = BASE5;
|
|
95507
95507
|
e3 = bitFloor(x3.e / LOG_BASE) - bitFloor(y2.e / LOG_BASE);
|
|
95508
95508
|
s3 = s3 / LOG_BASE | 0;
|
|
95509
95509
|
}
|
|
@@ -95582,7 +95582,7 @@ var require_bignumber = __commonJS({
|
|
|
95582
95582
|
more = rem[0] != null;
|
|
95583
95583
|
if (!qc[0]) qc.splice(0, 1);
|
|
95584
95584
|
}
|
|
95585
|
-
if (base ==
|
|
95585
|
+
if (base == BASE5) {
|
|
95586
95586
|
for (i3 = 1, s3 = qc[0]; s3 >= 10; s3 /= 10, i3++) ;
|
|
95587
95587
|
round(q3, dp + (q3.e = i3 + e3 * LOG_BASE - 1) + 1, rm, more);
|
|
95588
95588
|
} else {
|
|
@@ -95741,12 +95741,12 @@ var require_bignumber = __commonJS({
|
|
|
95741
95741
|
for (k3 = 1; j3 >= 10; j3 /= 10, k3++) ;
|
|
95742
95742
|
if (i3 != k3) {
|
|
95743
95743
|
x3.e++;
|
|
95744
|
-
if (xc[0] ==
|
|
95744
|
+
if (xc[0] == BASE5) xc[0] = 1;
|
|
95745
95745
|
}
|
|
95746
95746
|
break;
|
|
95747
95747
|
} else {
|
|
95748
95748
|
xc[ni] += k3;
|
|
95749
|
-
if (xc[ni] !=
|
|
95749
|
+
if (xc[ni] != BASE5) break;
|
|
95750
95750
|
xc[ni--] = 0;
|
|
95751
95751
|
k3 = 1;
|
|
95752
95752
|
}
|
|
@@ -95955,12 +95955,12 @@ var require_bignumber = __commonJS({
|
|
|
95955
95955
|
}
|
|
95956
95956
|
b3 = (j3 = yc.length) - (i3 = xc.length);
|
|
95957
95957
|
if (b3 > 0) for (; b3--; xc[i3++] = 0) ;
|
|
95958
|
-
b3 =
|
|
95958
|
+
b3 = BASE5 - 1;
|
|
95959
95959
|
for (; j3 > a3; ) {
|
|
95960
95960
|
if (xc[--j3] < yc[j3]) {
|
|
95961
95961
|
for (i3 = j3; i3 && !xc[--i3]; xc[i3] = b3) ;
|
|
95962
95962
|
--xc[i3];
|
|
95963
|
-
xc[j3] +=
|
|
95963
|
+
xc[j3] += BASE5;
|
|
95964
95964
|
}
|
|
95965
95965
|
xc[j3] -= yc[j3];
|
|
95966
95966
|
}
|
|
@@ -96022,7 +96022,7 @@ var require_bignumber = __commonJS({
|
|
|
96022
96022
|
ycL = i3;
|
|
96023
96023
|
}
|
|
96024
96024
|
for (i3 = xcL + ycL, zc = []; i3--; zc.push(0)) ;
|
|
96025
|
-
base =
|
|
96025
|
+
base = BASE5;
|
|
96026
96026
|
sqrtBase = SQRT_BASE;
|
|
96027
96027
|
for (i3 = ycL; --i3 >= 0; ) {
|
|
96028
96028
|
c3 = 0;
|
|
@@ -96088,8 +96088,8 @@ var require_bignumber = __commonJS({
|
|
|
96088
96088
|
b3 = a3;
|
|
96089
96089
|
}
|
|
96090
96090
|
for (a3 = 0; b3; ) {
|
|
96091
|
-
a3 = (xc[--b3] = xc[b3] + yc[b3] + a3) /
|
|
96092
|
-
xc[b3] =
|
|
96091
|
+
a3 = (xc[--b3] = xc[b3] + yc[b3] + a3) / BASE5 | 0;
|
|
96092
|
+
xc[b3] = BASE5 === xc[b3] ? 0 : xc[b3] % BASE5;
|
|
96093
96093
|
}
|
|
96094
96094
|
if (a3) {
|
|
96095
96095
|
xc = [a3].concat(xc);
|
|
@@ -733822,7 +733822,7 @@ var PERM_COLUMNS = [
|
|
|
733822
733822
|
{ header: "ID", key: "id" },
|
|
733823
733823
|
{ header: "Actor", key: "actor_type", format: (v6, row) => `${v6}:${row.actor?.display_name ?? row.actor_id?.substring(0, 8)}` },
|
|
733824
733824
|
{ header: "Level", key: "level" },
|
|
733825
|
-
{ header: "On", key: "permissible_type", format: (v6) => v6?.replace(/^Documents::/, "") ?? "" },
|
|
733825
|
+
{ header: "On", key: "permissible_type", format: (v6) => v6?.replace(/^(Documents|Projects)::/, "") ?? "" },
|
|
733826
733826
|
{ header: "Resource ID", key: "permissible_id" },
|
|
733827
733827
|
{ header: "Updated", key: "updated_at" }
|
|
733828
733828
|
];
|
|
@@ -733831,7 +733831,8 @@ var PERMISSIBLE_ALIASES = {
|
|
|
733831
733831
|
workspace: "Documents::Workspace",
|
|
733832
733832
|
folder: "Documents::Folder",
|
|
733833
733833
|
file: "Documents::File",
|
|
733834
|
-
share_link: "Documents::ShareLink"
|
|
733834
|
+
share_link: "Documents::ShareLink",
|
|
733835
|
+
project: "Projects::Project"
|
|
733835
733836
|
};
|
|
733836
733837
|
var ACTOR_ALIASES = {
|
|
733837
733838
|
user: "User",
|
|
@@ -733841,10 +733842,10 @@ var ACTOR_ALIASES = {
|
|
|
733841
733842
|
function normalizePermissibleType(input, out) {
|
|
733842
733843
|
const lower = input.toLowerCase();
|
|
733843
733844
|
if (PERMISSIBLE_ALIASES[lower]) return PERMISSIBLE_ALIASES[lower];
|
|
733844
|
-
if (input.startsWith("Documents::")) return input;
|
|
733845
|
+
if (input.startsWith("Documents::") || input.startsWith("Projects::")) return input;
|
|
733845
733846
|
out.fail(
|
|
733846
733847
|
new Error(
|
|
733847
|
-
`Invalid --on-type: '${input}'. Use workspace/folder/file/share_link or a fully-qualified Documents::\u2026 class name.`
|
|
733848
|
+
`Invalid --on-type: '${input}'. Use workspace/folder/file/share_link/project or a fully-qualified Documents::\u2026 / Projects::\u2026 class name.`
|
|
733848
733849
|
)
|
|
733849
733850
|
);
|
|
733850
733851
|
return "";
|
|
@@ -734334,7 +734335,7 @@ async function handleTicketsShow(id, opts) {
|
|
|
734334
734335
|
out.fail(err);
|
|
734335
734336
|
}
|
|
734336
734337
|
}
|
|
734337
|
-
function ticketBodyFromOpts(opts,
|
|
734338
|
+
function ticketBodyFromOpts(opts, out) {
|
|
734338
734339
|
const body2 = {};
|
|
734339
734340
|
if (opts.title !== void 0) body2.title = opts.title;
|
|
734340
734341
|
if (opts.description !== void 0) body2.description = opts.description;
|
|
@@ -734355,14 +734356,21 @@ function ticketBodyFromOpts(opts, includeAll) {
|
|
|
734355
734356
|
const labels = parseLabels(opts.labels);
|
|
734356
734357
|
if (labels !== void 0) body2.labels = labels;
|
|
734357
734358
|
if (opts.column !== void 0) body2.column_status = opts.column;
|
|
734358
|
-
|
|
734359
|
+
if (opts.agentConfig !== void 0) {
|
|
734360
|
+
try {
|
|
734361
|
+
body2.agent_config = JSON.parse(opts.agentConfig);
|
|
734362
|
+
} catch (err) {
|
|
734363
|
+
out.fail(new Error(`Invalid JSON for --agent-config: ${err.message}`));
|
|
734364
|
+
}
|
|
734365
|
+
}
|
|
734366
|
+
return body2;
|
|
734359
734367
|
}
|
|
734360
734368
|
async function handleTicketsCreate(opts) {
|
|
734361
734369
|
const out = output(opts);
|
|
734362
734370
|
requireProject2(opts, out);
|
|
734363
734371
|
const ctx = await buildApiContext(out);
|
|
734364
734372
|
if (!opts.title) out.fail(new Error("--title is required"));
|
|
734365
|
-
const body2 = ticketBodyFromOpts(opts,
|
|
734373
|
+
const body2 = ticketBodyFromOpts(opts, out);
|
|
734366
734374
|
try {
|
|
734367
734375
|
const res = await ctx.axios.post(ticketsBase(opts.project), body2);
|
|
734368
734376
|
const ticket = res.data?.ticket ?? res.data;
|
|
@@ -734375,7 +734383,7 @@ async function handleTicketsUpdate(id, opts) {
|
|
|
734375
734383
|
const out = output(opts);
|
|
734376
734384
|
requireProject2(opts, out);
|
|
734377
734385
|
const ctx = await buildApiContext(out);
|
|
734378
|
-
const body2 = ticketBodyFromOpts(opts,
|
|
734386
|
+
const body2 = ticketBodyFromOpts(opts, out);
|
|
734379
734387
|
if (Object.keys(body2).length === 0) out.fail(new Error("No fields to update"));
|
|
734380
734388
|
try {
|
|
734381
734389
|
const res = await ctx.axios.patch(
|
|
@@ -734414,6 +734422,34 @@ async function handleTicketsDelete(id, opts) {
|
|
|
734414
734422
|
out.fail(err);
|
|
734415
734423
|
}
|
|
734416
734424
|
}
|
|
734425
|
+
async function handleTicketsSetAgent(id, opts) {
|
|
734426
|
+
const out = output(opts);
|
|
734427
|
+
requireProject2(opts, out);
|
|
734428
|
+
const ctx = await buildApiContext(out);
|
|
734429
|
+
if (opts.agent === void 0) out.fail(new Error("--agent <agent-id|null> is required"));
|
|
734430
|
+
const body2 = {
|
|
734431
|
+
assignee_id: opts.agent === "null" ? null : opts.agent
|
|
734432
|
+
};
|
|
734433
|
+
if (opts.agentConfig !== void 0) {
|
|
734434
|
+
try {
|
|
734435
|
+
body2.agent_config = JSON.parse(opts.agentConfig);
|
|
734436
|
+
} catch (err) {
|
|
734437
|
+
out.fail(new Error(`Invalid JSON for --agent-config: ${err.message}`));
|
|
734438
|
+
}
|
|
734439
|
+
}
|
|
734440
|
+
try {
|
|
734441
|
+
const res = await ctx.axios.patch(
|
|
734442
|
+
`${ticketsBase(opts.project)}/${encodeURIComponent(id)}`,
|
|
734443
|
+
body2
|
|
734444
|
+
);
|
|
734445
|
+
out.ok(
|
|
734446
|
+
body2.assignee_id === null ? `Ticket ${id} agent cleared` : `Ticket ${id} agent set to ${body2.assignee_id}`,
|
|
734447
|
+
res.data?.ticket ?? res.data
|
|
734448
|
+
);
|
|
734449
|
+
} catch (err) {
|
|
734450
|
+
out.fail(err);
|
|
734451
|
+
}
|
|
734452
|
+
}
|
|
734417
734453
|
async function handleTicketsAssign(id, opts) {
|
|
734418
734454
|
const out = output(opts);
|
|
734419
734455
|
requireProject2(opts, out);
|
|
@@ -734604,6 +734640,49 @@ async function handleTicketsDispatch(id, opts) {
|
|
|
734604
734640
|
}
|
|
734605
734641
|
}
|
|
734606
734642
|
|
|
734643
|
+
// apps/cli/cli/handlers/agent-handlers.ts
|
|
734644
|
+
var BASE4 = "/api/v1/agents";
|
|
734645
|
+
var AGENT_COLUMNS = [
|
|
734646
|
+
{ header: "ID", key: "id" },
|
|
734647
|
+
{ header: "Key", key: "key" },
|
|
734648
|
+
{ header: "Name", key: "name", maxWidth: 30 },
|
|
734649
|
+
{ header: "Type", key: "type", format: (v6) => v6?.replace(/^Agents::/, "") ?? "" },
|
|
734650
|
+
{ header: "Active", key: "active", format: (v6) => v6 ? "\u2714" : "" }
|
|
734651
|
+
];
|
|
734652
|
+
async function handleAgentsList(opts) {
|
|
734653
|
+
const out = output(opts);
|
|
734654
|
+
const ctx = await buildApiContext(out);
|
|
734655
|
+
const params = {};
|
|
734656
|
+
if (opts.active !== void 0) params.active = opts.active;
|
|
734657
|
+
if (opts.page) params.page = Number(opts.page);
|
|
734658
|
+
if (opts.perPage) params.per_page = Number(opts.perPage);
|
|
734659
|
+
try {
|
|
734660
|
+
const res = await ctx.axios.get(BASE4, { params });
|
|
734661
|
+
const items = Array.isArray(res.data) ? res.data : [];
|
|
734662
|
+
const pagination = extractPagination(res.headers, items.length);
|
|
734663
|
+
if (opts.json) {
|
|
734664
|
+
out.show({ items, pagination });
|
|
734665
|
+
return;
|
|
734666
|
+
}
|
|
734667
|
+
out.list(items, AGENT_COLUMNS);
|
|
734668
|
+
if (pagination.pages > 1) {
|
|
734669
|
+
out.note(`page ${pagination.page}/${pagination.pages} (${pagination.count} total)`);
|
|
734670
|
+
}
|
|
734671
|
+
} catch (err) {
|
|
734672
|
+
out.fail(err);
|
|
734673
|
+
}
|
|
734674
|
+
}
|
|
734675
|
+
async function handleAgentsShow(id, opts) {
|
|
734676
|
+
const out = output(opts);
|
|
734677
|
+
const ctx = await buildApiContext(out);
|
|
734678
|
+
try {
|
|
734679
|
+
const res = await ctx.axios.get(`${BASE4}/${encodeURIComponent(id)}`);
|
|
734680
|
+
out.show(res.data?.agent ?? res.data, { title: `Agent ${id}` });
|
|
734681
|
+
} catch (err) {
|
|
734682
|
+
out.fail(err);
|
|
734683
|
+
}
|
|
734684
|
+
}
|
|
734685
|
+
|
|
734607
734686
|
// apps/cli/cli/handlers/task-handlers.ts
|
|
734608
734687
|
var tasksBase = (pid, tid) => `/api/v1/projects/${encodeURIComponent(pid)}/tickets/${encodeURIComponent(tid)}/tasks`;
|
|
734609
734688
|
var TASK_COLUMNS = [
|
|
@@ -734778,7 +734857,7 @@ async function handleTasksReorder(opts) {
|
|
|
734778
734857
|
// apps/cli/cli.ts
|
|
734779
734858
|
var getVersion = () => {
|
|
734780
734859
|
try {
|
|
734781
|
-
if (true) return "1.
|
|
734860
|
+
if (true) return "1.11.0";
|
|
734782
734861
|
} catch {
|
|
734783
734862
|
}
|
|
734784
734863
|
for (const candidate of [
|
|
@@ -735123,10 +735202,10 @@ tickets.command("ls").alias("list").description("List tickets").requiredOption("
|
|
|
735123
735202
|
tickets.command("show <id>").description("Show a ticket (with tasks, subtasks, deliverables)").requiredOption("--project <id>", "Parent project id").action(async (id, options) => {
|
|
735124
735203
|
await handleTicketsShow(id, withGlobals(options));
|
|
735125
735204
|
});
|
|
735126
|
-
tickets.command("create").description("Create a ticket").requiredOption("--project <id>", "Parent project id").requiredOption("--title <text>").option("--description <text>").option("--type <ticket_type>", "task (default) | bug | story | epic | \u2026").option("--sprint <id>", "Attach to a sprint; omit to leave in backlog").option("--assignee <id>", "Assign to a user id").option("--priority <priority>", "lowest | low | medium | high | highest").option("--status <status>").option("--parent <id>", "Parent ticket id (for subtasks)").option("--due <YYYY-MM-DD>").option("--story-points <n>").option("--labels <a,b,c>", "Comma-separated labels").option("--column <column_status>").action(async (options) => {
|
|
735205
|
+
tickets.command("create").description("Create a ticket").requiredOption("--project <id>", "Parent project id").requiredOption("--title <text>").option("--description <text>").option("--type <ticket_type>", "task (default) | bug | story | epic | \u2026").option("--sprint <id>", "Attach to a sprint; omit to leave in backlog").option("--assignee <id>", "Assign to a user id").option("--priority <priority>", "lowest | low | medium | high | highest").option("--status <status>").option("--parent <id>", "Parent ticket id (for subtasks)").option("--due <YYYY-MM-DD>").option("--story-points <n>").option("--labels <a,b,c>", "Comma-separated labels").option("--column <column_status>").option("--agent-config <json>", "JSON payload written to the ticket agent_config (corex#591)").action(async (options) => {
|
|
735127
735206
|
await handleTicketsCreate(withGlobals(options));
|
|
735128
735207
|
});
|
|
735129
|
-
tickets.command("update <id>").description("Update a ticket").requiredOption("--project <id>", "Parent project id").option("--title <text>").option("--description <text>").option("--type <ticket_type>").option("--sprint <id>", 'Move to a sprint; use "null" for backlog').option("--assignee <id>", 'Reassign; use "null" to unassign').option("--priority <priority>").option("--status <status>").option("--parent <id>").option("--due <YYYY-MM-DD>").option("--story-points <n>").option("--labels <a,b,c>").option("--column <column_status>").action(async (id, options) => {
|
|
735208
|
+
tickets.command("update <id>").description("Update a ticket").requiredOption("--project <id>", "Parent project id").option("--title <text>").option("--description <text>").option("--type <ticket_type>").option("--sprint <id>", 'Move to a sprint; use "null" for backlog').option("--assignee <id>", 'Reassign; use "null" to unassign').option("--priority <priority>").option("--status <status>").option("--parent <id>").option("--due <YYYY-MM-DD>").option("--story-points <n>").option("--labels <a,b,c>").option("--column <column_status>").option("--agent-config <json>", "JSON payload written to the ticket agent_config (corex#591)").action(async (id, options) => {
|
|
735130
735209
|
await handleTicketsUpdate(id, withGlobals(options));
|
|
735131
735210
|
});
|
|
735132
735211
|
tickets.command("delete <id>").description("Delete a ticket (drops its tasks, deliverables, activities)").requiredOption("--project <id>", "Parent project id").option("--yes", "Skip the interactive confirmation").action(async (id, options) => {
|
|
@@ -735135,6 +735214,9 @@ tickets.command("delete <id>").description("Delete a ticket (drops its tasks, de
|
|
|
735135
735214
|
tickets.command("assign <id>").description("Assign a ticket to a user; --to null to unassign").requiredOption("--project <id>", "Parent project id").requiredOption("--to <user-id|null>").action(async (id, options) => {
|
|
735136
735215
|
await handleTicketsAssign(id, withGlobals(options));
|
|
735137
735216
|
});
|
|
735217
|
+
tickets.command("set-agent <id>").description("Configure the ticket with an agent (assignee + agent_config in one PATCH) \u2014 needed before `dispatch` (corex#591)").requiredOption("--project <id>", "Parent project id").requiredOption("--agent <agent-id|null>", 'Agents::Agent UUID (use "null" to clear)').option("--agent-config <json>", "Optional JSON payload merged into agent_config").action(async (id, options) => {
|
|
735218
|
+
await handleTicketsSetAgent(id, withGlobals(options));
|
|
735219
|
+
});
|
|
735138
735220
|
tickets.command("status <id>").description("Change a ticket status (optionally pin the kanban column with --column)").requiredOption("--project <id>", "Parent project id").requiredOption("--to <status>", "open | in_progress | done | blocked | awaiting_human | cancelled | failed").option("--column <column_status>", "Optionally set the kanban column at the same time").action(async (id, options) => {
|
|
735139
735221
|
await handleTicketsStatus(id, withGlobals(options));
|
|
735140
735222
|
});
|
|
@@ -735178,6 +735260,13 @@ tasks.command("complete <id>").description("Mark a task as completed (or re-open
|
|
|
735178
735260
|
tasks.command("reorder").description("Reorder tasks under a ticket").requiredOption("--project <id>", "Parent project id").requiredOption("--ticket <id>", "Parent ticket id").requiredOption("--order <ids>", "Comma-separated task ids in the desired order").action(async (options) => {
|
|
735179
735261
|
await handleTasksReorder(withGlobals(options));
|
|
735180
735262
|
});
|
|
735263
|
+
var agents = program2.command("agents").description("List agents dispatchable on tickets (corex#591)");
|
|
735264
|
+
agents.command("ls").alias("list").description("List agents").option("--active", "Only agents whose config is active").option("--page <n>").option("--per-page <n>").action(async (options) => {
|
|
735265
|
+
await handleAgentsList(withGlobals(options));
|
|
735266
|
+
});
|
|
735267
|
+
agents.command("show <id>").description("Show an agent").action(async (id, options) => {
|
|
735268
|
+
await handleAgentsShow(id, withGlobals(options));
|
|
735269
|
+
});
|
|
735181
735270
|
program2.parse();
|
|
735182
735271
|
/*! Bundled license information:
|
|
735183
735272
|
|
package/docs/llm-usage.md
CHANGED
|
@@ -377,16 +377,36 @@ themselves. All commands support `--json` for machine parsing.
|
|
|
377
377
|
| start | complete`.
|
|
378
378
|
|
|
379
379
|
`hubdoc tickets --project=<pid>` — `ls | show | create | update | delete
|
|
380
|
-
| assign | status | move | activities | deliverable |
|
|
381
|
-
comment | comments`. Every verb requires `--project=<pid>`.
|
|
382
|
-
--backlog` (or `ls --sprint null`) lists the backlog. `assign --to
|
|
383
|
-
unassigns. `status --to <state> [--column <col>]` uses the
|
|
384
|
-
statuses: `open | in_progress | done | blocked |
|
|
385
|
-
cancelled | failed` and optionally pins the kanban
|
|
386
|
-
time. `comment <id> --body <text>` (or `--body-file
|
|
387
|
-
message on the ticket's discussion thread (visible in
|
|
388
|
-
attributed to the token holder); `comments <id>` reads
|
|
389
|
-
oldest-first (paginated like `activities`).
|
|
380
|
+
| assign | set-agent | status | move | activities | deliverable |
|
|
381
|
+
dispatch | comment | comments`. Every verb requires `--project=<pid>`.
|
|
382
|
+
`ls --backlog` (or `ls --sprint null`) lists the backlog. `assign --to
|
|
383
|
+
null` unassigns. `status --to <state> [--column <col>]` uses the
|
|
384
|
+
canonical statuses: `open | in_progress | done | blocked |
|
|
385
|
+
awaiting_human | cancelled | failed` and optionally pins the kanban
|
|
386
|
+
column at the same time. `comment <id> --body <text>` (or `--body-file
|
|
387
|
+
<path>`) posts a message on the ticket's discussion thread (visible in
|
|
388
|
+
Corex / Agoria, attributed to the token holder); `comments <id>` reads
|
|
389
|
+
the thread oldest-first (paginated like `activities`).
|
|
390
|
+
|
|
391
|
+
**Agent configuration on tickets** (corex#591) : `create` and `update`
|
|
392
|
+
both accept `--agent-config <json>` — free-form jsonb persisted on the
|
|
393
|
+
ticket and read back by `dispatch_agent` / the agent runner (canonical
|
|
394
|
+
keys: `agent_role: planner|executor|…`, `instructions`). The convenience
|
|
395
|
+
verb `tickets set-agent <id> --project <pid> --agent <agent-id>
|
|
396
|
+
[--agent-config <json>]` PATCHes `assignee_id` and (optionally)
|
|
397
|
+
`agent_config` in one call — the shortest path from "empty ticket" to
|
|
398
|
+
"dispatchable". Use `hubdoc agents ls [--active]` to discover
|
|
399
|
+
dispatchable agent UUIDs (STI: `Agents::Planner`, `Agents::Executor`,
|
|
400
|
+
`Agents::Classifier`, `Agents::Conversational`, …).
|
|
401
|
+
|
|
402
|
+
**Project ACL** (hubdoc-tools#15) : the `permissions` verbs now accept
|
|
403
|
+
`--on-type project` (alias of `Projects::Project`) — the corex
|
|
404
|
+
`/api/v1/permissions` controller is polymorphic and `Projects::Project`
|
|
405
|
+
includes `HasPermissionsConcern`. This lets an agent share a **standalone
|
|
406
|
+
project** (no workspace attached) with a colleague or another agent
|
|
407
|
+
without going through a workspace-scoped ACL. Example:
|
|
408
|
+
`hubdoc permissions grant --to <user-id> --to-type user --on <project-id>
|
|
409
|
+
--on-type project --level admin`.
|
|
390
410
|
|
|
391
411
|
`hubdoc tasks --project=<pid> --ticket=<tid>` — `ls | show | create |
|
|
392
412
|
update | delete | complete | reorder`. Sub-tasks live under a ticket;
|
|
@@ -444,7 +464,13 @@ hubdoc tasks create --project "$PID" --ticket "$TID" \
|
|
|
444
464
|
hubdoc tasks create --project "$PID" --ticket "$TID" \
|
|
445
465
|
--title "Rédiger devis" --priority high --due 2026-07-16 --json
|
|
446
466
|
|
|
447
|
-
# 5.
|
|
467
|
+
# 5. Pick a dispatchable agent then set it on the ticket in one shot.
|
|
468
|
+
AGENT_ID=$(hubdoc agents ls --active --json | jq -r '.items[] | select(.key=="planner") | .id')
|
|
469
|
+
hubdoc tickets set-agent "$TID" --project "$PID" \
|
|
470
|
+
--agent "$AGENT_ID" \
|
|
471
|
+
--agent-config '{"agent_role":"planner","instructions":"Rédige un devis à partir des PJ."}' --json
|
|
472
|
+
|
|
473
|
+
# 5b. Now `dispatch` can actually fire (agent + agent_config both set).
|
|
448
474
|
hubdoc tickets dispatch "$TID" --project "$PID" --json
|
|
449
475
|
|
|
450
476
|
# 6. Later — post a follow-up on the ticket thread (visible to the human):
|