@arbidocs/cli 0.4.83 β 0.4.85
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +36 -0
- package/SKILL.md +5 -3
- package/dist/index.js +217 -99
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,41 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## v0.4.85
|
|
4
|
+
|
|
5
|
+
[compare changes](https://github.com/arbicity/ARBI-frontend/compare/v0.4.83...HEAD)
|
|
6
|
+
|
|
7
|
+
### π Enhancements
|
|
8
|
+
|
|
9
|
+
- **cli:** Tag kinds in arbi tags create, list, show and matrix ([6c7331ee9](https://github.com/arbicity/ARBI-frontend/commit/6c7331ee9))
|
|
10
|
+
- **blocks:** Mail kit (ConnectedMailbox, ConnectedMailComposer) shared by the app and hosts ([3c854536e](https://github.com/arbicity/ARBI-frontend/commit/3c854536e))
|
|
11
|
+
- **tags:** Flat issues with per-kind fields; the tag list is the table ([2194bb4d0](https://github.com/arbicity/ARBI-frontend/commit/2194bb4d0))
|
|
12
|
+
|
|
13
|
+
### π©Ή Fixes
|
|
14
|
+
|
|
15
|
+
- **recording:** Overlay video captions in the lower half of the frame ([1ea3d58bc](https://github.com/arbicity/ARBI-frontend/commit/1ea3d58bc))
|
|
16
|
+
- **tags:** An issue in a list shows its evidence, not an empty rows table ([34e71de7b](https://github.com/arbicity/ARBI-frontend/commit/34e71de7b))
|
|
17
|
+
- **personas:** Overlay think-aloud captions in the lower half of the frame ([7b22e8609](https://github.com/arbicity/ARBI-frontend/commit/7b22e8609))
|
|
18
|
+
- **blocks:** Start AI-first workflow runs and never skip a failed step by default ([#1572](https://github.com/arbicity/ARBI-frontend/pull/1572))
|
|
19
|
+
- **client:** Type the password-change calls against the current schema ([498b0d1da](https://github.com/arbicity/ARBI-frontend/commit/498b0d1da))
|
|
20
|
+
|
|
21
|
+
### π
Refactors
|
|
22
|
+
|
|
23
|
+
- **tags:** Stop sending kind_to_children ([c9bac43a9](https://github.com/arbicity/ARBI-frontend/commit/c9bac43a9))
|
|
24
|
+
|
|
25
|
+
### π‘ Chore
|
|
26
|
+
|
|
27
|
+
- Update OpenAPI schema ([f2437789f](https://github.com/arbicity/ARBI-frontend/commit/f2437789f))
|
|
28
|
+
- Measure only the markdown chunk in its size budget ([48a4aeda8](https://github.com/arbicity/ARBI-frontend/commit/48a4aeda8))
|
|
29
|
+
|
|
30
|
+
### β
Tests
|
|
31
|
+
|
|
32
|
+
- **tags:** An issue in a list shows no rows table ([5e629e1a7](https://github.com/arbicity/ARBI-frontend/commit/5e629e1a7))
|
|
33
|
+
|
|
34
|
+
### π€ CI
|
|
35
|
+
|
|
36
|
+
- Run the full @arbidocs/blocks unit suite in the Test job ([c6fcbabd0](https://github.com/arbicity/ARBI-frontend/commit/c6fcbabd0))
|
|
37
|
+
- Move the blocks suite to its own path-filtered job ([a97af75bd](https://github.com/arbicity/ARBI-frontend/commit/a97af75bd))
|
|
38
|
+
|
|
3
39
|
## v0.4.83
|
|
4
40
|
|
|
5
41
|
[compare changes](https://github.com/arbicity/ARBI-frontend/compare/v0.4.81...HEAD)
|
package/SKILL.md
CHANGED
|
@@ -61,7 +61,7 @@ Scripting notes:
|
|
|
61
61
|
|
|
62
62
|
## For Automations / AI Agents
|
|
63
63
|
|
|
64
|
-
- **Structured output (`--json`)**: supported on `status`, `config show`, `health`, `models`, `workspaces`, `workspace users`, `workspace current`, `docs`, `convo` (or `convo list`), `tags` (or `tags list`), `contacts` (or `contacts list`), `find`, `settings get`, `task list` / `task status` / `task result`, `agent list`, `session list`, `dm list`, `notifications list`, `local ls` / `local find` / `local cat` / `local tree`, `update --check`, `register --non-interactive`, `ask -b`, `upload`, `watch`, `workflow list` / `create` / `run` / `update`, `run start` / `run steps` / `run step`, `tags create` / `tags fields` / `tags
|
|
64
|
+
- **Structured output (`--json`)**: supported on `status`, `config show`, `health`, `models`, `workspaces`, `workspace users`, `workspace current`, `docs`, `convo` (or `convo list`), `tags` (or `tags list`), `tags show`, `contacts` (or `contacts list`), `find`, `settings get`, `task list` / `task status` / `task result`, `agent list`, `session list`, `dm list`, `notifications list`, `local ls` / `local find` / `local cat` / `local tree`, `update --check`, `register --non-interactive`, `ask -b`, `upload`, `watch`, `workflow list` / `create` / `run` / `update`, `run start` / `run steps` / `run step`, `tags create` / `tags fields` / `tags list --links`, `tag-kinds list` / `show` / `set-fields`, `project set` / `show` / `events`, `usage conversation` / `usage project`. Use it whenever parsing output. `docs` also supports `--csv`, `--ids`, and `--count`. `arbi ask --json` without `-b` errors out β streaming mode is prose, not JSON; pass `-b` to get a background task ID, then `arbi task result --json`.
|
|
65
65
|
- **Human table output is lossy**: table rows may contain status glyphs (`β`, `π©`, etc.) and emoji, and column widths truncate content. Never parse tables β always pass `--json`.
|
|
66
66
|
- **Exit codes**:
|
|
67
67
|
- `0` success
|
|
@@ -95,8 +95,10 @@ All document list/search/meta commands support machine-readable output. Prefer `
|
|
|
95
95
|
- **Per-doc**: `arbi doc get <id...>` returns full JSON (no flag needed). `arbi doc delete <id...>` and `arbi doc update <id> '<json>'` take IDs directly.
|
|
96
96
|
- **Upload by URL**: `arbi doc upload-url <url> --json`.
|
|
97
97
|
- **Download**: `arbi download <id> -o <path>` writes the file; `-o -` streams raw bytes to stdout; `--json` emits a `{doc_id, path, bytes, filename}` metadata line after writing.
|
|
98
|
-
- **Tags**: `arbi tags list --json`, `arbi tags create <name> -t <type> [--parent <tag>]`, `arbi tags delete <id>`.
|
|
99
|
-
- **Tag
|
|
98
|
+
- **Tags**: `arbi tags list [--kind <kind>] [--parent <tag>] [--links [n]] --json`, `arbi tags show <tag> [--json]`, `arbi tags create <name> -t <type> [--kind <kind>] [--parent <tag>] [--set name=value]`, `arbi tags delete <id>`.
|
|
99
|
+
- **Tag kinds**: every tag has a `kind`: `label`, `annotation`, `search`, `issue`, `person` or `organisation` (shown in the KIND column of `tags list`, in `tags show`, and as `kind` in `--json`). `tags create --kind issue` makes an issue (without `--kind`: from the type, checkbox β label; never from a parent); `tags list --kind <kind>` filters by it; an unknown kind is refused with the list of kinds. Issues, people and organisations are flat: no `--parent` (refused), and nothing nests under one. Parents are for label hierarchies (`tags list --parent <tag>` lists a label's children).
|
|
100
|
+
- **Kind fields (the columns)**: each kind has one field list per workspace (its issue fields, its person fields β¦; types `text`, `number`, `date`, `checkbox`, `select`, `person`); each tag holds its own values. `arbi tag-kinds [list] [--json]` shows every kind's fields, `arbi tag-kinds show <kind>` one kind's (people and organisations start with built-in Position, Organisation, Role, Comment / Role, Comment). `arbi tag-kinds set-fields <kind> '<json>'` (or a `.json`/`.yaml` file of `[{name, type, options}]`) sets them in full: a field named again (any case) keeps its id and values, a type cannot change, ones left out are removed unless `--keep-others`.
|
|
101
|
+
- **Values and the table**: `arbi tags fields <tag>` shows a tag's values for its kind's fields; `--set name=value` (repeatable, `name=` clears) sets them, checked against the kind's fields and a select's options (`tags create β¦ --set` too). `arbi tags list --kind issue --links` prints the table: a row per tag, the kind's fields as columns, then DOCS, FACTS and THREADS counts, gaps marked `β` and listed; with `--json` each tag carries `field_values` and `links` (its newest documents with notes, facts and threads, up to `--links <n>`, default 50, plus the counts). Tags are taken by id or unique name.
|
|
100
102
|
- **Doctags** (tagβdoc link): `arbi doctags create <tag-id> <doc-id...>` / `arbi doctags delete <tag-id> <doc-id...>`.
|
|
101
103
|
- **Retrieve only**: `arbi find <query> --json` returns raw retrieval results without running the LLM.
|
|
102
104
|
- **Exit codes**: 0 on success (including clean skips), 1 on error. Errors print to stderr.
|
package/dist/index.js
CHANGED
|
@@ -3695,7 +3695,7 @@ function getLatestVersion(skipCache = false) {
|
|
|
3695
3695
|
}
|
|
3696
3696
|
}
|
|
3697
3697
|
function getCurrentVersion() {
|
|
3698
|
-
return "0.4.
|
|
3698
|
+
return "0.4.85";
|
|
3699
3699
|
}
|
|
3700
3700
|
function readChangelog(fromVersion, toVersion) {
|
|
3701
3701
|
try {
|
|
@@ -3748,17 +3748,17 @@ function showChangelog(fromVersion, toVersion) {
|
|
|
3748
3748
|
async function checkForUpdates(autoUpdate) {
|
|
3749
3749
|
try {
|
|
3750
3750
|
const latest = getLatestVersion();
|
|
3751
|
-
if (!latest || latest === "0.4.
|
|
3751
|
+
if (!latest || latest === "0.4.85") return;
|
|
3752
3752
|
if (autoUpdate) {
|
|
3753
3753
|
warn(`
|
|
3754
|
-
Your arbi version is out of date (${"0.4.
|
|
3754
|
+
Your arbi version is out of date (${"0.4.85"} \u2192 ${latest}). Updating...`);
|
|
3755
3755
|
child_process.execSync("npm install -g @arbidocs/cli@latest", { stdio: "inherit" });
|
|
3756
|
-
showChangelog("0.4.
|
|
3756
|
+
showChangelog("0.4.85", latest);
|
|
3757
3757
|
console.log(`Updated to ${latest}.`);
|
|
3758
3758
|
} else {
|
|
3759
3759
|
warn(
|
|
3760
3760
|
`
|
|
3761
|
-
Your arbi version is out of date (${"0.4.
|
|
3761
|
+
Your arbi version is out of date (${"0.4.85"} \u2192 ${latest}).
|
|
3762
3762
|
Run "arbi update" to upgrade, or "arbi update auto" to always stay up to date.`
|
|
3763
3763
|
);
|
|
3764
3764
|
}
|
|
@@ -3790,10 +3790,10 @@ function markNagShown(latest) {
|
|
|
3790
3790
|
function hintUpdateOnError() {
|
|
3791
3791
|
try {
|
|
3792
3792
|
const cached = readCache();
|
|
3793
|
-
if (!cached || cached.latest === "0.4.
|
|
3793
|
+
if (!cached || cached.latest === "0.4.85") return;
|
|
3794
3794
|
if (!shouldShowNag(cached.latest)) return;
|
|
3795
3795
|
warn(
|
|
3796
|
-
`Your arbi version is out of date (${"0.4.
|
|
3796
|
+
`Your arbi version is out of date (${"0.4.85"} \u2192 ${cached.latest}). Run "arbi update".`
|
|
3797
3797
|
);
|
|
3798
3798
|
markNagShown(cached.latest);
|
|
3799
3799
|
} catch {
|
|
@@ -8519,16 +8519,16 @@ function parseFieldDefinitions(arg) {
|
|
|
8519
8519
|
try {
|
|
8520
8520
|
value = JSON.parse(trimmed);
|
|
8521
8521
|
} catch (err) {
|
|
8522
|
-
throw new Error(
|
|
8522
|
+
throw new Error(`Fields are not valid JSON: ${err.message}`);
|
|
8523
8523
|
}
|
|
8524
8524
|
} else if (fs7.existsSync(arg)) value = readStructured(arg);
|
|
8525
8525
|
else
|
|
8526
8526
|
throw new Error(
|
|
8527
|
-
|
|
8527
|
+
`Fields are JSON (e.g. '[{"name":"Status","type":"text"}]') or a .json/.yaml file; no file "${arg}"`
|
|
8528
8528
|
);
|
|
8529
8529
|
const list = isRecord(value) ? value.fields : value;
|
|
8530
8530
|
if (!Array.isArray(list))
|
|
8531
|
-
throw new Error('
|
|
8531
|
+
throw new Error('Fields: expected a list of fields, or an object with a "fields" list');
|
|
8532
8532
|
const problems = [];
|
|
8533
8533
|
const names = /* @__PURE__ */ new Set();
|
|
8534
8534
|
const out = list.map((raw, i) => {
|
|
@@ -8580,7 +8580,7 @@ function parseFieldValues(pairs, fields) {
|
|
|
8580
8580
|
const field = fields.find((f) => f.name.toLowerCase() === name.toLowerCase() || f.id === name);
|
|
8581
8581
|
if (!field)
|
|
8582
8582
|
throw new Error(
|
|
8583
|
-
`No field "${name}"
|
|
8583
|
+
`No field "${name}" for this kind. Its fields: ${fields.map((f) => f.name).join(", ") || "(none: add some with arbi tag-kinds set-fields)"}`
|
|
8584
8584
|
);
|
|
8585
8585
|
if (value.trim() === "") out[field.name] = null;
|
|
8586
8586
|
else if (field.type === "select" && field.options?.length) {
|
|
@@ -8598,35 +8598,36 @@ function formatFieldValue(value) {
|
|
|
8598
8598
|
if (typeof value === "object") return JSON.stringify(value);
|
|
8599
8599
|
return String(value);
|
|
8600
8600
|
}
|
|
8601
|
-
|
|
8602
|
-
|
|
8601
|
+
var fieldType = (f) => f.type === "select" && f.options?.length ? `select: ${f.options.join("|")}` : f.type;
|
|
8602
|
+
function fieldRows(tag, fields) {
|
|
8603
|
+
return fields.map((f) => ({
|
|
8603
8604
|
id: f.id,
|
|
8604
8605
|
name: f.name,
|
|
8605
|
-
type: f
|
|
8606
|
-
value: formatFieldValue(tag.field_values?.[f.id])
|
|
8607
|
-
from: f.tag_ext_id === tag.external_id ? "own" : `inherited (${f.tag_ext_id})`
|
|
8606
|
+
type: fieldType(f),
|
|
8607
|
+
value: formatFieldValue(tag.field_values?.[f.id])
|
|
8608
8608
|
}));
|
|
8609
8609
|
}
|
|
8610
|
-
function
|
|
8611
|
-
const
|
|
8612
|
-
const headers = ["TAG", ...columns.map((c) => c.name.toUpperCase()), "DOCS", "FACTS"];
|
|
8610
|
+
function tagTable(tags, columns) {
|
|
8611
|
+
const headers = ["TAG", ...columns.map((c) => c.name.toUpperCase()), "DOCS", "FACTS", "THREADS"];
|
|
8613
8612
|
const rows = [];
|
|
8614
8613
|
const gaps = [];
|
|
8615
|
-
for (const
|
|
8616
|
-
const
|
|
8617
|
-
const
|
|
8618
|
-
|
|
8619
|
-
|
|
8614
|
+
for (const tag of tags) {
|
|
8615
|
+
const links = tag.links;
|
|
8616
|
+
const docs = links?.doc_count ?? 0;
|
|
8617
|
+
const facts = links?.fact_count ?? 0;
|
|
8618
|
+
const threads = links?.thread_count ?? 0;
|
|
8619
|
+
const cells = columns.map((c) => formatFieldValue(tag.field_values?.[c.id]));
|
|
8620
8620
|
rows.push([
|
|
8621
|
-
|
|
8621
|
+
tag.name,
|
|
8622
8622
|
...cells,
|
|
8623
|
-
|
|
8624
|
-
|
|
8623
|
+
docs ? String(docs) : GAP,
|
|
8624
|
+
facts ? String(facts) : GAP,
|
|
8625
|
+
threads ? String(threads) : GAP
|
|
8625
8626
|
]);
|
|
8626
|
-
const missing = columns.filter((
|
|
8627
|
-
if (!
|
|
8628
|
-
if (!
|
|
8629
|
-
if (missing.length) gaps.push(`${
|
|
8627
|
+
const missing = columns.filter((_, i) => cells[i] === GAP).map((c) => c.name);
|
|
8628
|
+
if (!docs) missing.push("documents");
|
|
8629
|
+
if (!facts) missing.push("facts");
|
|
8630
|
+
if (missing.length) gaps.push(`${tag.name}: no ${missing.join(", no ")}`);
|
|
8630
8631
|
}
|
|
8631
8632
|
return { headers, rows, gaps };
|
|
8632
8633
|
}
|
|
@@ -8639,7 +8640,39 @@ function renderTable(headers, rows, max = 28) {
|
|
|
8639
8640
|
return [line(headers), ...rows.map(line)];
|
|
8640
8641
|
}
|
|
8641
8642
|
|
|
8643
|
+
// src/tag-kinds.ts
|
|
8644
|
+
var KINDS = {
|
|
8645
|
+
label: true,
|
|
8646
|
+
annotation: true,
|
|
8647
|
+
search: true,
|
|
8648
|
+
issue: true,
|
|
8649
|
+
person: true,
|
|
8650
|
+
organisation: true
|
|
8651
|
+
};
|
|
8652
|
+
var TAG_KINDS = Object.keys(KINDS);
|
|
8653
|
+
function parseTagKind(value, flag = "--kind") {
|
|
8654
|
+
const kind = value.trim().toLowerCase();
|
|
8655
|
+
if (!TAG_KINDS.includes(kind))
|
|
8656
|
+
throw new Error(`${flag} must be one of ${TAG_KINDS.join(", ")} (got "${value}")`);
|
|
8657
|
+
return kind;
|
|
8658
|
+
}
|
|
8659
|
+
function tagDetails(tag, parentName, fields = []) {
|
|
8660
|
+
const type = tag.tag_type?.type ?? "";
|
|
8661
|
+
const rows = [
|
|
8662
|
+
["Kind:", tag.kind],
|
|
8663
|
+
["Type:", type],
|
|
8664
|
+
["Shared:", tag.shared ? "yes" : "no"],
|
|
8665
|
+
["Documents:", String(tag.doctag_count ?? 0)]
|
|
8666
|
+
];
|
|
8667
|
+
if (tag.parent_ext_id)
|
|
8668
|
+
rows.push(["Parent:", parentName ? `${parentName} (${tag.parent_ext_id})` : tag.parent_ext_id]);
|
|
8669
|
+
if (tag.instruction) rows.push(["Instruction:", tag.instruction]);
|
|
8670
|
+
for (const f of fields) rows.push([`${f.name}:`, formatFieldValue(tag.field_values?.[f.id])]);
|
|
8671
|
+
return rows;
|
|
8672
|
+
}
|
|
8673
|
+
|
|
8642
8674
|
// src/commands/tags.ts
|
|
8675
|
+
var KIND_LIST = TAG_KINDS.join(", ");
|
|
8643
8676
|
async function resolveTag(arbi, selector) {
|
|
8644
8677
|
const res = resolveByIdOrName(await sdk.tags.listTags(arbi), selector);
|
|
8645
8678
|
if (!res.ok) failResolveAndExit("Tag", selector, res);
|
|
@@ -8661,23 +8694,52 @@ async function fetchTagChoices(arbi) {
|
|
|
8661
8694
|
};
|
|
8662
8695
|
}
|
|
8663
8696
|
function registerTagsCommand(program2) {
|
|
8664
|
-
const tags = program2.command("tags").description("Tags: list, create, delete, update, share, unshare, rename, fields
|
|
8665
|
-
tags.command("list").description(
|
|
8697
|
+
const tags = program2.command("tags").description("Tags: list, show, create, delete, update, share, unshare, rename, fields");
|
|
8698
|
+
tags.command("list").description(
|
|
8699
|
+
"List tags in the active workspace; with --links, as a table: the kind\u2019s fields as columns, then document, fact and thread counts, gaps marked \u2014"
|
|
8700
|
+
).option("-w, --workspace <id>", "Workspace ID (defaults to selected workspace)").option("-k, --kind <kind>", `Only tags of this kind (${KIND_LIST})`).option("--parent <tag>", "Only this tag\u2019s children (id or name; a label hierarchy)").option(
|
|
8701
|
+
"--links [n]",
|
|
8702
|
+
"The table: each tag\u2019s values for its kind\u2019s fields and its documents, facts and threads (with --json: the newest n of each, default 50)"
|
|
8703
|
+
).option("--json", "Output as JSON").action(
|
|
8666
8704
|
(opts) => runAction(async () => {
|
|
8705
|
+
const kind = opts.kind === void 0 ? void 0 : parseTagKind(opts.kind);
|
|
8706
|
+
const linksLimit = typeof opts.links === "string" ? Number(opts.links) : void 0;
|
|
8707
|
+
if (linksLimit !== void 0 && (!Number.isInteger(linksLimit) || linksLimit < 0))
|
|
8708
|
+
throw new Error("--links takes a whole number");
|
|
8667
8709
|
const { arbi } = await resolveWorkspace(opts.workspace);
|
|
8668
|
-
const
|
|
8710
|
+
const parent = opts.parent ? await resolveTag(arbi, opts.parent) : void 0;
|
|
8711
|
+
const data = await sdk.tags.listTags(arbi, {
|
|
8712
|
+
...kind ? { kind } : {},
|
|
8713
|
+
...parent ? { parentId: parent.external_id } : {},
|
|
8714
|
+
...opts.links ? { include: ["links"], linksLimit } : {}
|
|
8715
|
+
});
|
|
8669
8716
|
if (opts.json) {
|
|
8670
8717
|
printJson(data);
|
|
8671
8718
|
return;
|
|
8672
8719
|
}
|
|
8673
8720
|
if (data.length === 0) {
|
|
8674
|
-
process.stderr.write(
|
|
8721
|
+
process.stderr.write(
|
|
8722
|
+
kind ? `No ${kind} tags. Add one: arbi tags create <name> --kind ${kind}
|
|
8723
|
+
` : "No tags found.\n"
|
|
8724
|
+
);
|
|
8725
|
+
return;
|
|
8726
|
+
}
|
|
8727
|
+
if (opts.links) {
|
|
8728
|
+
const columns = kind ? (await sdk.tags.getTagKind(arbi, kind)).fields : [];
|
|
8729
|
+
const table = tagTable(data, columns);
|
|
8730
|
+
for (const line of renderTable(table.headers, table.rows)) console.log(line);
|
|
8731
|
+
if (table.gaps.length) {
|
|
8732
|
+
console.log("");
|
|
8733
|
+
dim("Gaps:");
|
|
8734
|
+
for (const g of table.gaps) dim(` ${g}`);
|
|
8735
|
+
}
|
|
8675
8736
|
return;
|
|
8676
8737
|
}
|
|
8677
8738
|
printTable(
|
|
8678
8739
|
[
|
|
8679
8740
|
{ header: "ID", width: 24, value: (r) => r.external_id },
|
|
8680
8741
|
{ header: "NAME", width: 24, value: (r) => r.name },
|
|
8742
|
+
{ header: "KIND", width: 13, value: (r) => r.kind ?? "" },
|
|
8681
8743
|
{
|
|
8682
8744
|
header: "TYPE",
|
|
8683
8745
|
width: 12,
|
|
@@ -8691,12 +8753,43 @@ function registerTagsCommand(program2) {
|
|
|
8691
8753
|
);
|
|
8692
8754
|
})()
|
|
8693
8755
|
);
|
|
8756
|
+
tags.command("show <tag>").description(
|
|
8757
|
+
"A tag's details: kind, type, sharing, documents, parent, instruction and its values for its kind's fields"
|
|
8758
|
+
).option("-w, --workspace <id>", "Workspace ID (defaults to selected workspace)").option("--json", "Output as JSON").action(
|
|
8759
|
+
(selector, opts) => runAction(async () => {
|
|
8760
|
+
const { arbi } = await resolveWorkspace(opts.workspace);
|
|
8761
|
+
const all = await sdk.tags.listTags(arbi);
|
|
8762
|
+
const res = resolveByIdOrName(all, selector);
|
|
8763
|
+
if (!res.ok) failResolveAndExit("Tag", selector, res);
|
|
8764
|
+
const tag = res.item;
|
|
8765
|
+
if (opts.json) {
|
|
8766
|
+
printJson(tag);
|
|
8767
|
+
return;
|
|
8768
|
+
}
|
|
8769
|
+
const parent = all.find((t) => t.external_id === tag.parent_ext_id);
|
|
8770
|
+
const { fields } = await sdk.tags.getTagKind(arbi, tag.kind);
|
|
8771
|
+
bold(`${tag.name} (${tag.external_id})`);
|
|
8772
|
+
for (const [key, value] of tagDetails(tag, parent?.name, fields)) label(key, value);
|
|
8773
|
+
})()
|
|
8774
|
+
);
|
|
8694
8775
|
tags.command("create [name]").description("Create a new tag (interactive form if no name given)").option("-w, --workspace <id>", "Workspace ID (defaults to selected workspace)").option(
|
|
8695
8776
|
"-t, --type <type>",
|
|
8696
8777
|
"Tag type (checkbox, text, number, select, folder, search, date, assistant)",
|
|
8697
8778
|
"checkbox"
|
|
8698
|
-
).option("-i, --instruction <text>", "Tag instruction").option("--shared", "Make tag shared", false).option(
|
|
8779
|
+
).option("-i, --instruction <text>", "Tag instruction").option("--shared", "Make tag shared", false).option(
|
|
8780
|
+
"--parent <tag>",
|
|
8781
|
+
"Make it a child of this tag (id or name; labels only: issues, people and organisations are flat)"
|
|
8782
|
+
).option(
|
|
8783
|
+
"-k, --kind <kind>",
|
|
8784
|
+
`What it is (${KIND_LIST}). Default: from the type (checkbox: label)`
|
|
8785
|
+
).option(
|
|
8786
|
+
"--set <name=value>",
|
|
8787
|
+
"A value for one of the kind's fields (repeatable), e.g. --set Status=Open",
|
|
8788
|
+
collect,
|
|
8789
|
+
[]
|
|
8790
|
+
).option("--json", "Output as JSON").action(
|
|
8699
8791
|
(name, opts) => runAction(async () => {
|
|
8792
|
+
const kind = opts.kind === void 0 ? void 0 : parseTagKind(opts.kind);
|
|
8700
8793
|
const { arbi } = await resolveWorkspace(opts.workspace);
|
|
8701
8794
|
const parent = opts.parent ? await resolveTag(arbi, opts.parent) : void 0;
|
|
8702
8795
|
const interactive = !name;
|
|
@@ -8715,6 +8808,13 @@ function registerTagsCommand(program2) {
|
|
|
8715
8808
|
]);
|
|
8716
8809
|
const instruction = interactive ? opts.instruction ?? (await promptInput("Instruction (optional)", false) || null) : opts.instruction ?? null;
|
|
8717
8810
|
const shared = interactive ? opts.shared || await promptConfirm("Shared?", false) : opts.shared ?? false;
|
|
8811
|
+
const fieldValues = opts.set.length ? parseFieldValues(
|
|
8812
|
+
opts.set,
|
|
8813
|
+
(await sdk.tags.getTagKind(
|
|
8814
|
+
arbi,
|
|
8815
|
+
kind ?? (tagType === "checkbox" ? "label" : "annotation")
|
|
8816
|
+
)).fields
|
|
8817
|
+
) : null;
|
|
8718
8818
|
const data = await sdk.tags.createTag(arbi, {
|
|
8719
8819
|
name,
|
|
8720
8820
|
tagType: {
|
|
@@ -8723,14 +8823,16 @@ function registerTagsCommand(program2) {
|
|
|
8723
8823
|
},
|
|
8724
8824
|
instruction,
|
|
8725
8825
|
shared,
|
|
8726
|
-
parentId: parent?.external_id ?? null
|
|
8826
|
+
parentId: parent?.external_id ?? null,
|
|
8827
|
+
kind: kind ?? null,
|
|
8828
|
+
fieldValues
|
|
8727
8829
|
});
|
|
8728
8830
|
if (opts.json) {
|
|
8729
8831
|
printJson(data);
|
|
8730
8832
|
return;
|
|
8731
8833
|
}
|
|
8732
8834
|
success(
|
|
8733
|
-
`Created: ${data.name} (${ref(data.external_id)})${parent ? ` under ${parent.name}` : ""}`
|
|
8835
|
+
`Created: ${data.name} (${ref(data.external_id)}) [${data.kind}]${parent ? ` under ${parent.name}` : ""}`
|
|
8734
8836
|
);
|
|
8735
8837
|
})()
|
|
8736
8838
|
);
|
|
@@ -8797,41 +8899,24 @@ function registerTagsCommand(program2) {
|
|
|
8797
8899
|
})()
|
|
8798
8900
|
);
|
|
8799
8901
|
tags.command("fields <tag>").description(
|
|
8800
|
-
"Show a tag's
|
|
8801
|
-
).option(
|
|
8802
|
-
"--define <json|file>",
|
|
8803
|
-
`Its own field definitions: JSON or a .json/.yaml file, e.g. '[{"name":"budget","type":"number"},{"name":"risk","type":"select","options":["low","high"]}]'. A field defined again by name keeps its values; ones left out are dropped unless --keep-others`
|
|
8804
|
-
).option("--keep-others", "With --define: keep its other own fields").option("--set <name=value>", "Set a field value (repeatable; name= clears it)", collect, []).option("--json", "Output as JSON").action(
|
|
8902
|
+
"Show a tag's values for its kind's fields; --set them. The fields themselves: arbi tag-kinds"
|
|
8903
|
+
).option("--set <name=value>", "Set a field value (repeatable; name= clears it)", collect, []).option("--json", "Output as JSON").action(
|
|
8805
8904
|
(selector, opts) => runAction(async () => {
|
|
8806
|
-
const defs = opts.define ? parseFieldDefinitions(opts.define) : void 0;
|
|
8807
8905
|
const { arbi } = await resolveWorkspace();
|
|
8808
8906
|
let tag = await resolveTag(arbi, selector);
|
|
8809
|
-
|
|
8810
|
-
|
|
8811
|
-
|
|
8812
|
-
...(tag.fields ?? []).filter((f) => f.tag_ext_id !== tag.external_id),
|
|
8813
|
-
...fields.map((f) => ({
|
|
8814
|
-
id: f.id ?? "",
|
|
8815
|
-
name: f.name,
|
|
8816
|
-
type: f.type,
|
|
8817
|
-
options: f.options ?? null,
|
|
8818
|
-
tag_ext_id: tag.external_id
|
|
8819
|
-
}))
|
|
8820
|
-
] : tag.fields ?? [];
|
|
8821
|
-
const values = opts.set.length ? parseFieldValues(opts.set, known) : void 0;
|
|
8822
|
-
tag = await sdk.tags.updateTagFields(arbi, tag.external_id, { fields, values });
|
|
8823
|
-
}
|
|
8907
|
+
const { fields } = await sdk.tags.getTagKind(arbi, tag.kind);
|
|
8908
|
+
if (opts.set.length)
|
|
8909
|
+
tag = await sdk.tags.setTagValues(arbi, tag.external_id, parseFieldValues(opts.set, fields));
|
|
8824
8910
|
if (opts.json) {
|
|
8825
8911
|
printJson(tag);
|
|
8826
8912
|
return;
|
|
8827
8913
|
}
|
|
8828
|
-
if (
|
|
8829
|
-
success(`Updated the fields of ${tag.name} (${ref(tag.external_id)})`);
|
|
8914
|
+
if (opts.set.length) success(`Updated the values of ${tag.name} (${ref(tag.external_id)})`);
|
|
8830
8915
|
else bold(`${tag.name} (${tag.external_id})`);
|
|
8831
|
-
const rows = fieldRows(tag);
|
|
8916
|
+
const rows = fieldRows(tag, fields);
|
|
8832
8917
|
if (!rows.length) {
|
|
8833
8918
|
dim(
|
|
8834
|
-
`No fields.
|
|
8919
|
+
`No ${tag.kind} fields. Add some: arbi tag-kinds set-fields ${tag.kind} '[{"name":"Status","type":"text"}]'`
|
|
8835
8920
|
);
|
|
8836
8921
|
return;
|
|
8837
8922
|
}
|
|
@@ -8839,55 +8924,87 @@ function registerTagsCommand(program2) {
|
|
|
8839
8924
|
[
|
|
8840
8925
|
{ header: "FIELD", width: 22, value: (r) => r.name },
|
|
8841
8926
|
{ header: "TYPE", width: 24, value: (r) => r.type },
|
|
8842
|
-
{ header: "VALUE", width:
|
|
8843
|
-
{ header: "DEFINED", width: 30, value: (r) => r.from }
|
|
8927
|
+
{ header: "VALUE", width: 40, value: (r) => r.value }
|
|
8844
8928
|
],
|
|
8845
8929
|
rows
|
|
8846
8930
|
);
|
|
8847
8931
|
})()
|
|
8848
8932
|
);
|
|
8849
|
-
tags.
|
|
8850
|
-
|
|
8851
|
-
|
|
8933
|
+
tags.allowUnknownOption(true).allowExcessArguments(true).action(async () => {
|
|
8934
|
+
const tail = tags.args ?? [];
|
|
8935
|
+
await tags.commands.find((c) => c.name() === "list").parseAsync(tail, { from: "user" });
|
|
8936
|
+
});
|
|
8937
|
+
}
|
|
8938
|
+
var KIND_LIST2 = TAG_KINDS.join(", ");
|
|
8939
|
+
function printSchema(schema) {
|
|
8940
|
+
bold(`${schema.kind}${schema.is_default ? " (built-in fields)" : ""}`);
|
|
8941
|
+
if (!schema.fields.length) {
|
|
8942
|
+
dim(
|
|
8943
|
+
` No fields. Add some: arbi tag-kinds set-fields ${schema.kind} '[{"name":"Status","type":"select","options":["Open","Closed"]}]'`
|
|
8944
|
+
);
|
|
8945
|
+
return;
|
|
8946
|
+
}
|
|
8947
|
+
printTable(
|
|
8948
|
+
[
|
|
8949
|
+
{ header: "ID", width: 12, value: (r) => r.id },
|
|
8950
|
+
{ header: "FIELD", width: 24, value: (r) => r.name },
|
|
8951
|
+
{ header: "TYPE", width: 32, value: (r) => r.type }
|
|
8952
|
+
],
|
|
8953
|
+
schema.fields.map((f) => ({ id: f.id, name: f.name, type: fieldType(f) }))
|
|
8954
|
+
);
|
|
8955
|
+
}
|
|
8956
|
+
function registerTagKindsCommand(program2) {
|
|
8957
|
+
const kinds = program2.command("tag-kinds").description(
|
|
8958
|
+
"Tag kinds' fields in the workspace (the columns of a table of a kind's tags): list, show, set-fields"
|
|
8959
|
+
);
|
|
8960
|
+
kinds.command("list").description("Every kind's fields in the active workspace").option("--json", "Output as JSON").action(
|
|
8852
8961
|
(opts) => runAction(async () => {
|
|
8853
|
-
if (!opts.parent === !opts.tag.length)
|
|
8854
|
-
throw new Error("Pass --parent <tag>, or one or more --tag <tag>");
|
|
8855
|
-
const links = opts.links === void 0 ? void 0 : Number(opts.links);
|
|
8856
|
-
if (links !== void 0 && (!Number.isInteger(links) || links < 0))
|
|
8857
|
-
throw new Error("--links must be a whole number");
|
|
8858
8962
|
const { arbi } = await resolveWorkspace();
|
|
8859
|
-
const all = await sdk.tags.
|
|
8860
|
-
const pick = (selector) => {
|
|
8861
|
-
const res = resolveByIdOrName(all, selector);
|
|
8862
|
-
if (!res.ok) failResolveAndExit("Tag", selector, res);
|
|
8863
|
-
return res.item;
|
|
8864
|
-
};
|
|
8865
|
-
const selection = opts.parent ? { parentId: pick(opts.parent).external_id } : { tagIds: opts.tag.map((t) => pick(t).external_id) };
|
|
8866
|
-
const matrix = await sdk.tags.getTagMatrix(arbi, selection, links);
|
|
8963
|
+
const all = await sdk.tags.listTagKinds(arbi);
|
|
8867
8964
|
if (opts.json) {
|
|
8868
|
-
printJson(
|
|
8869
|
-
return;
|
|
8870
|
-
}
|
|
8871
|
-
const table = matrixTable(matrix);
|
|
8872
|
-
if (matrix.parent) bold(`${matrix.parent.name} (${matrix.parent.external_id})`);
|
|
8873
|
-
if (!table.rows.length) {
|
|
8874
|
-
process.stderr.write(
|
|
8875
|
-
opts.parent ? `No child tags. Add one: arbi tags create <name> --parent ${opts.parent}
|
|
8876
|
-
` : "No tags.\n"
|
|
8877
|
-
);
|
|
8965
|
+
printJson(all);
|
|
8878
8966
|
return;
|
|
8879
8967
|
}
|
|
8880
|
-
for (const
|
|
8881
|
-
|
|
8968
|
+
for (const schema of all) {
|
|
8969
|
+
printSchema(schema);
|
|
8882
8970
|
console.log("");
|
|
8883
|
-
dim("Gaps:");
|
|
8884
|
-
for (const g of table.gaps) dim(` ${g}`);
|
|
8885
8971
|
}
|
|
8886
8972
|
})()
|
|
8887
8973
|
);
|
|
8888
|
-
|
|
8889
|
-
|
|
8890
|
-
|
|
8974
|
+
kinds.command("show <kind>").description(`A kind's fields (${KIND_LIST2})`).option("--json", "Output as JSON").action(
|
|
8975
|
+
(kindArg, opts) => runAction(async () => {
|
|
8976
|
+
const kind = parseTagKind(kindArg, "kind");
|
|
8977
|
+
const { arbi } = await resolveWorkspace();
|
|
8978
|
+
const schema = await sdk.tags.getTagKind(arbi, kind);
|
|
8979
|
+
if (opts.json) printJson(schema);
|
|
8980
|
+
else printSchema(schema);
|
|
8981
|
+
})()
|
|
8982
|
+
);
|
|
8983
|
+
kinds.command("set-fields <kind> <fields>").description(
|
|
8984
|
+
`Set a kind's fields: JSON or a .json/.yaml file of [{name, type, options}], e.g. '[{"name":"Status","type":"select","options":["Open","Closed"]},{"name":"Owner","type":"person"}]'. A field named again (any case) keeps its id and values; ones left out are removed unless --keep-others`
|
|
8985
|
+
).option("--keep-others", "Keep the kind\u2019s other fields (after the given ones)").option("--json", "Output as JSON").action(
|
|
8986
|
+
(kindArg, fieldsArg, opts) => runAction(async () => {
|
|
8987
|
+
const kind = parseTagKind(kindArg, "kind");
|
|
8988
|
+
const wanted = parseFieldDefinitions(fieldsArg);
|
|
8989
|
+
const { arbi } = await resolveWorkspace();
|
|
8990
|
+
const current = await sdk.tags.getTagKind(arbi, kind);
|
|
8991
|
+
const schema = await sdk.tags.updateTagKind(
|
|
8992
|
+
arbi,
|
|
8993
|
+
kind,
|
|
8994
|
+
sdk.tags.mergeKindFieldDefinitions(current.fields, wanted, {
|
|
8995
|
+
keepOthers: !!opts.keepOthers
|
|
8996
|
+
})
|
|
8997
|
+
);
|
|
8998
|
+
if (opts.json) {
|
|
8999
|
+
printJson(schema);
|
|
9000
|
+
return;
|
|
9001
|
+
}
|
|
9002
|
+
success(`Set the ${kind} fields`);
|
|
9003
|
+
printSchema(schema);
|
|
9004
|
+
})()
|
|
9005
|
+
);
|
|
9006
|
+
kinds.action(async () => {
|
|
9007
|
+
await kinds.commands.find((c) => c.name() === "list").parseAsync([], { from: "user" });
|
|
8891
9008
|
});
|
|
8892
9009
|
}
|
|
8893
9010
|
init_prompts();
|
|
@@ -11955,7 +12072,7 @@ console.info = (...args) => {
|
|
|
11955
12072
|
_origInfo(...args);
|
|
11956
12073
|
};
|
|
11957
12074
|
var program = new commander.Command();
|
|
11958
|
-
program.name("arbi").description("ARBI CLI \u2014 interact with ARBI from the terminal").version("0.4.
|
|
12075
|
+
program.name("arbi").description("ARBI CLI \u2014 interact with ARBI from the terminal").version("0.4.85").showHelpAfterError(true).showSuggestionAfterError(true);
|
|
11959
12076
|
registerConfigCommand(program);
|
|
11960
12077
|
registerLoginCommand(program);
|
|
11961
12078
|
registerRegisterCommand(program);
|
|
@@ -11972,6 +12089,7 @@ registerWatchCommand(program);
|
|
|
11972
12089
|
registerContactsCommand(program);
|
|
11973
12090
|
registerDmCommand(program);
|
|
11974
12091
|
registerTagsCommand(program);
|
|
12092
|
+
registerTagKindsCommand(program);
|
|
11975
12093
|
registerTimelineCommand(program);
|
|
11976
12094
|
registerDoctagsCommand(program);
|
|
11977
12095
|
registerConversationsCommand(program);
|