@oriro/orirocli 0.3.6 → 0.3.7

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.
Files changed (2) hide show
  1. package/dist/cli.js +77 -23
  2. package/package.json +3 -1
package/dist/cli.js CHANGED
@@ -7527,6 +7527,9 @@ async function confirmDestructive(what, opts = {}) {
7527
7527
  }
7528
7528
  }
7529
7529
 
7530
+ // src/commands/output.ts
7531
+ import jmespath from "jmespath";
7532
+
7530
7533
  // src/config/store.ts
7531
7534
  import { readFileSync as readFileSync22, writeFileSync as writeFileSync20, mkdirSync as mkdirSync16 } from "fs";
7532
7535
  import { join as join29 } from "path";
@@ -7589,40 +7592,63 @@ function configUnset(key) {
7589
7592
  // src/commands/output.ts
7590
7593
  function parseFormat(o) {
7591
7594
  const f = (o ?? configGet("output") ?? "text").toLowerCase();
7592
- if (f === "json" || f === "csv" || f === "text") return f;
7593
- throw new Error(`invalid --output '${o}'. Use: text | json | csv`);
7595
+ if (f === "json" || f === "csv" || f === "text" || f === "md") return f;
7596
+ throw new Error(`invalid --output '${o}'. Use: text | json | csv | md`);
7594
7597
  }
7598
+ var LIGHTWEIGHT_QUERY = /^[\w.-]+(=[^:]*)?(:[\w.-]+)?$/;
7595
7599
  function applyQuery(rows, query) {
7596
7600
  if (!query) return rows;
7597
- const [filterPart, selectField] = query.split(":", 2);
7598
- let out = rows;
7599
- const fp = filterPart ?? "";
7600
- if (fp.includes("=")) {
7601
- const [field2, value] = fp.split("=", 2);
7602
- out = rows.filter((r) => String(r[field2] ?? "") === value);
7603
- } else if (fp && !selectField) {
7604
- return rows.map((r) => r[fp]);
7605
- }
7606
- if (selectField) return out.map((r) => r[selectField]);
7607
- return out;
7601
+ if (LIGHTWEIGHT_QUERY.test(query.trim())) {
7602
+ const [filterPart, selectField] = query.trim().split(":", 2);
7603
+ let out = rows;
7604
+ const fp = filterPart ?? "";
7605
+ if (fp.includes("=")) {
7606
+ const [field2, value] = fp.split("=", 2);
7607
+ out = rows.filter((r) => String(r[field2] ?? "") === value);
7608
+ } else if (fp && !selectField) {
7609
+ return rows.map((r) => r[fp]);
7610
+ }
7611
+ if (selectField) return out.map((r) => r[selectField]);
7612
+ return out;
7613
+ }
7614
+ try {
7615
+ return jmespath.search(rows, query);
7616
+ } catch (e) {
7617
+ throw new Error(`invalid --query '${query}' \u2014 not lightweight (field / field=value[:select]) nor valid JMESPath: ${e instanceof Error ? e.message : String(e)}`);
7618
+ }
7608
7619
  }
7609
7620
  function csvCell(v) {
7610
7621
  const s = v === null || v === void 0 ? "" : String(v);
7611
7622
  return /[",\n]/.test(s) ? `"${s.replace(/"/g, '""')}"` : s;
7612
7623
  }
7624
+ function mdCell(v) {
7625
+ const s = v === null || v === void 0 ? "" : String(v);
7626
+ return s.replace(/\|/g, "\\|").replace(/\n/g, " ");
7627
+ }
7613
7628
  function renderList2(rows, opts = {}) {
7614
7629
  const fmt = parseFormat(opts.output);
7615
- const queried = applyQuery(rows, opts.query);
7616
- if (fmt === "json") return JSON.stringify(queried, null, 2);
7617
- if (!Array.isArray(queried) || queried.length === 0) return "";
7630
+ const raw = applyQuery(rows, opts.query);
7631
+ if (fmt === "json") return JSON.stringify(raw, null, 2);
7632
+ const queried = Array.isArray(raw) ? raw : raw === void 0 || raw === null ? [] : [raw];
7633
+ if (queried.length === 0) return "";
7618
7634
  const first = queried[0];
7619
7635
  const scalar = typeof first !== "object" || first === null;
7620
- if (scalar) return queried.map((v) => fmt === "csv" ? csvCell(v) : String(v)).join("\n");
7636
+ if (scalar) {
7637
+ if (fmt === "md") return queried.map((v) => `- ${mdCell(v)}`).join("\n");
7638
+ return queried.map((v) => fmt === "csv" ? csvCell(v) : String(v)).join("\n");
7639
+ }
7621
7640
  const objs = queried;
7622
7641
  const cols = opts.columns ?? [...new Set(objs.flatMap((r) => Object.keys(r)))];
7623
7642
  if (fmt === "csv") {
7624
7643
  return [cols.map(csvCell).join(","), ...objs.map((r) => cols.map((c) => csvCell(r[c])).join(","))].join("\n");
7625
7644
  }
7645
+ if (fmt === "md") {
7646
+ return [
7647
+ `| ${cols.map(mdCell).join(" | ")} |`,
7648
+ `| ${cols.map(() => "---").join(" | ")} |`,
7649
+ ...objs.map((r) => `| ${cols.map((c) => mdCell(r[c])).join(" | ")} |`)
7650
+ ].join("\n");
7651
+ }
7626
7652
  const widths = cols.map((c) => Math.max(c.length, ...objs.map((r) => String(r[c] ?? "").length)));
7627
7653
  const line = (cells) => cells.map((s, i) => s.padEnd(widths[i] ?? 0)).join(" ").trimEnd();
7628
7654
  return [line(cols), ...objs.map((r) => line(cols.map((c) => String(r[c] ?? ""))))].join("\n");
@@ -7632,12 +7658,12 @@ function isMachineOutput(opts) {
7632
7658
  }
7633
7659
  function outputError(opts) {
7634
7660
  const f = (opts.output ?? configGet("output") ?? "text").toLowerCase();
7635
- return f === "json" || f === "csv" || f === "text" ? null : `invalid --output '${opts.output}' \u2014 use text | json | csv`;
7661
+ return f === "json" || f === "csv" || f === "text" || f === "md" ? null : `invalid --output '${opts.output}' \u2014 use text | json | csv | md`;
7636
7662
  }
7637
7663
 
7638
7664
  // src/commands/sessions.ts
7639
7665
  function registerSessionsCommand(program2) {
7640
- program2.command("sessions").description("list your saved chat sessions (resume with `oriro -c` or `oriro --resume <id>`)").option("-o, --output <fmt>", "output format: text (default) | json | csv").option("-q, --query <expr>", "filter/select: 'field', 'field=value', or 'field=value:selectField'").action(async (opts) => {
7666
+ program2.command("sessions").description("list your saved chat sessions (resume with `oriro -c` or `oriro --resume <id>`)").option("-o, --output <fmt>", "output format: text (default) | json | csv | md").option("-q, --query <expr>", "filter/select: 'field', 'field=value[:selectField]', or any JMESPath").action(async (opts) => {
7641
7667
  const oerr = outputError(opts);
7642
7668
  if (oerr) die(oerr);
7643
7669
  const infos = await listSessions();
@@ -7656,10 +7682,37 @@ function registerSessionsCommand(program2) {
7656
7682
  });
7657
7683
  }
7658
7684
 
7685
+ // src/commands/project.ts
7686
+ function registerProjectCommands(program2) {
7687
+ program2.command("init").description("write a starter AGENTS.md for this project (same as the in-chat /init)").option("--force", "overwrite an existing AGENTS.md").action((opts) => {
7688
+ process.stdout.write(handleInit(`/init${opts.force ? " --force" : ""}`).join("\n") + "\n");
7689
+ });
7690
+ program2.command("compact [focus...]").description("summarize + free a saved session's history (default: most recent here; same as /compact)").option("--resume <id>", "compact a specific saved session (id or unique prefix)").action(async (focus, opts) => {
7691
+ let session;
7692
+ let sessionNote;
7693
+ try {
7694
+ ({ session, sessionNote } = await assembleOriroSession({
7695
+ resume: opts.resume ? { resumeId: opts.resume } : { continue: true }
7696
+ }));
7697
+ } catch (e) {
7698
+ die(e instanceof Error ? e.message : String(e));
7699
+ return;
7700
+ }
7701
+ if (sessionNote) process.stdout.write(` ${dim(sessionNote)}
7702
+ `);
7703
+ const lines = await handleCompact(session, `/compact${focus.length ? ` ${focus.join(" ")}` : ""}`);
7704
+ process.stdout.write(lines.join("\n") + "\n");
7705
+ try {
7706
+ session.dispose();
7707
+ } catch {
7708
+ }
7709
+ });
7710
+ }
7711
+
7659
7712
  // src/commands/routers.ts
7660
7713
  function registerRoutersCommand(program2) {
7661
7714
  const routers = program2.command("routers").description("manage the free-router pool the model runs on");
7662
- routers.command("list").description("list the router catalog and the active pool").option("-o, --output <fmt>", "output format: text (default) | json | csv").option("-q, --query <expr>", "filter/select: 'field', 'field=value', or 'field=value:selectField'").action((opts) => {
7715
+ routers.command("list").description("list the router catalog and the active pool").option("-o, --output <fmt>", "output format: text (default) | json | csv | md").option("-q, --query <expr>", "filter/select: 'field', 'field=value[:selectField]', or any JMESPath").action((opts) => {
7663
7716
  const oerr = outputError(opts);
7664
7717
  if (oerr) die(oerr);
7665
7718
  const pool = new Set(resolvePool().map((p) => p.id));
@@ -7991,7 +8044,7 @@ function parsePairs(s) {
7991
8044
  // src/commands/connectors.ts
7992
8045
  function registerConnectorsCommand(program2) {
7993
8046
  const connectors = program2.command("connectors").description("MCP connectors \u2014 add external tools/services (inert until used)");
7994
- connectors.command("list [category]").description("list the connector catalog (optionally filtered by category)").option("-o, --output <fmt>", "output format: text (default) | json | csv").option("-q, --query <expr>", "filter/select: 'field', 'field=value', or 'field=value:selectField'").action((category, opts) => {
8047
+ connectors.command("list [category]").description("list the connector catalog (optionally filtered by category)").option("-o, --output <fmt>", "output format: text (default) | json | csv | md").option("-q, --query <expr>", "filter/select: 'field', 'field=value[:selectField]', or any JMESPath").action((category, opts) => {
7995
8048
  const oerr = outputError(opts);
7996
8049
  if (oerr) die(oerr);
7997
8050
  if (category && !connectorCategories().includes(category)) {
@@ -8413,7 +8466,7 @@ import { existsSync as existsSync21, statSync as statSync5, mkdirSync as mkdirSy
8413
8466
  import { resolve as resolve2, join as join32, basename as basename3, dirname as dirname4 } from "path";
8414
8467
  function registerSkillsCommand(program2) {
8415
8468
  const skills = program2.command("skills").description("the ORIRO skill library \u2014 bundled + your own");
8416
- skills.command("list").description("show CORE / TAIL skill counts (use --all to list names)").option("-a, --all", "list every skill name").option("-o, --output <fmt>", "output format: text (default) | json | csv").option("-q, --query <expr>", "filter/select: 'field', 'field=value', or 'field=value:selectField'").action(async (opts) => {
8469
+ skills.command("list").description("show CORE / TAIL skill counts (use --all to list names)").option("-a, --all", "list every skill name").option("-o, --output <fmt>", "output format: text (default) | json | csv | md").option("-q, --query <expr>", "filter/select: 'field', 'field=value[:selectField]', or any JMESPath").action(async (opts) => {
8417
8470
  const oerr = outputError(opts);
8418
8471
  if (oerr) die(oerr);
8419
8472
  const s = await loadOriroSkills();
@@ -8783,7 +8836,7 @@ function registerAgentsCommand(program2) {
8783
8836
  info(`make one: ${accent('oriro agents make <name> --task "\u2026" [--router <id>] [--schedule 1h]')}`);
8784
8837
  info(`then: ${accent("oriro agents run <name>")} ${dim("\xB7 or")} ${accent("oriro agents tick")} ${dim("for scheduled ones")}`);
8785
8838
  });
8786
- agents.command("list").description("list your saved agents").option("-o, --output <fmt>", "output format: text (default) | json | csv").option("-q, --query <expr>", "filter/select: 'field', 'field=value', or 'field=value:selectField'").action((opts) => {
8839
+ agents.command("list").description("list your saved agents").option("-o, --output <fmt>", "output format: text (default) | json | csv | md").option("-q, --query <expr>", "filter/select: 'field', 'field=value[:selectField]', or any JMESPath").action((opts) => {
8787
8840
  const oerr = outputError(opts);
8788
8841
  if (oerr) die(oerr);
8789
8842
  const all = listAgents();
@@ -9241,6 +9294,7 @@ program.name("oriro").description("ORIRO \u2014 a free, on-device-friendly termi
9241
9294
  await runRepl({ resume });
9242
9295
  });
9243
9296
  registerSessionsCommand(program);
9297
+ registerProjectCommands(program);
9244
9298
  registerRoutersCommand(program);
9245
9299
  registerScribeCommand(program);
9246
9300
  registerConnectorsCommand(program);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oriro/orirocli",
3
- "version": "0.3.6",
3
+ "version": "0.3.7",
4
4
  "description": "ORIRO — a free, on-device-friendly terminal AI agent. Built on the Pi agent harness (used as a library).",
5
5
  "type": "module",
6
6
  "bin": {
@@ -37,6 +37,7 @@
37
37
  "commander": "^12.1.0",
38
38
  "discord.js": "^14.26.4",
39
39
  "grammy": "^1.44.0",
40
+ "jmespath": "^0.16.0",
40
41
  "typebox": "^1.1.38"
41
42
  },
42
43
  "peerDependencies": {
@@ -52,6 +53,7 @@
52
53
  }
53
54
  },
54
55
  "devDependencies": {
56
+ "@types/jmespath": "^0.15.2",
55
57
  "@types/node": "^22",
56
58
  "tsup": "^8",
57
59
  "tsx": "^4",