@oriro/orirocli 0.3.5 → 0.3.6
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/cli.js +181 -29
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -4570,8 +4570,13 @@ var armed = false;
|
|
|
4570
4570
|
function armPostureGate() {
|
|
4571
4571
|
armed = true;
|
|
4572
4572
|
}
|
|
4573
|
+
function bypassPosture(depthEnv) {
|
|
4574
|
+
const d = Number(depthEnv);
|
|
4575
|
+
return Number.isFinite(d) && d > 0;
|
|
4576
|
+
}
|
|
4573
4577
|
function registerPostureGate(pi) {
|
|
4574
4578
|
pi.on("tool_call", async (event, ctx) => {
|
|
4579
|
+
if (bypassPosture(process.env.ORIRO_AGENT_DEPTH)) return void 0;
|
|
4575
4580
|
const d = decideTool({ toolName: event.toolName, guardianBlocked: false });
|
|
4576
4581
|
if (d.decision === "block") {
|
|
4577
4582
|
return {
|
|
@@ -6724,6 +6729,136 @@ async function handleUndo(session) {
|
|
|
6724
6729
|
}
|
|
6725
6730
|
}
|
|
6726
6731
|
|
|
6732
|
+
// src/agents/worktree.ts
|
|
6733
|
+
import { execFile } from "child_process";
|
|
6734
|
+
import { promisify } from "util";
|
|
6735
|
+
import { join as join27, basename as basename2 } from "path";
|
|
6736
|
+
var run = promisify(execFile);
|
|
6737
|
+
var MAX_FAN = 4;
|
|
6738
|
+
function parseAgentsSlash(line) {
|
|
6739
|
+
const m = /^\/agents(?:\s+(\S[\s\S]*))?$/i.exec(line.trim());
|
|
6740
|
+
if (!m) return void 0;
|
|
6741
|
+
const rest = m[1]?.trim();
|
|
6742
|
+
if (!rest) return { cmd: "help" };
|
|
6743
|
+
const nx = /^(\d+)x\s+(\S[\s\S]*)$/i.exec(rest);
|
|
6744
|
+
if (nx) {
|
|
6745
|
+
const n = Math.min(Math.max(Number(nx[1]), 1), MAX_FAN);
|
|
6746
|
+
return { cmd: "fan", tasks: Array.from({ length: n }, () => nx[2].trim()) };
|
|
6747
|
+
}
|
|
6748
|
+
const tasks = rest.split("|").map((s) => s.trim()).filter(Boolean).slice(0, MAX_FAN);
|
|
6749
|
+
return tasks.length ? { cmd: "fan", tasks } : { cmd: "help" };
|
|
6750
|
+
}
|
|
6751
|
+
function fanStamp(now) {
|
|
6752
|
+
const p = (n, w = 2) => String(n).padStart(w, "0");
|
|
6753
|
+
return `${p(now.getMonth() + 1)}${p(now.getDate())}-${p(now.getHours())}${p(now.getMinutes())}${p(now.getSeconds())}`;
|
|
6754
|
+
}
|
|
6755
|
+
function fanBranch(stamp, i) {
|
|
6756
|
+
return `oriro/agents/${stamp}-a${i + 1}`;
|
|
6757
|
+
}
|
|
6758
|
+
function fanDir(repoRoot, stamp, i) {
|
|
6759
|
+
return join27(oriroDir(), "worktrees", `${basename2(repoRoot)}-${stamp}-a${i + 1}`);
|
|
6760
|
+
}
|
|
6761
|
+
async function git(cwd, ...args) {
|
|
6762
|
+
try {
|
|
6763
|
+
const { stdout: stdout12 } = await run("git", ["-C", cwd, ...args], { windowsHide: true });
|
|
6764
|
+
return { ok: true, out: stdout12.trim() };
|
|
6765
|
+
} catch (e) {
|
|
6766
|
+
return { ok: false, out: e instanceof Error ? e.message : String(e) };
|
|
6767
|
+
}
|
|
6768
|
+
}
|
|
6769
|
+
async function gitRoot(cwd) {
|
|
6770
|
+
const r = await git(cwd, "rev-parse", "--show-toplevel");
|
|
6771
|
+
return r.ok && r.out ? r.out : void 0;
|
|
6772
|
+
}
|
|
6773
|
+
async function addWorktree(root, dir, branch) {
|
|
6774
|
+
const r = await git(root, "worktree", "add", "-b", branch, dir);
|
|
6775
|
+
return r.ok ? void 0 : r.out;
|
|
6776
|
+
}
|
|
6777
|
+
async function changedFiles(dir) {
|
|
6778
|
+
const r = await git(dir, "status", "--short");
|
|
6779
|
+
return r.ok && r.out ? r.out.split("\n").map((s) => s.trim()).filter(Boolean) : [];
|
|
6780
|
+
}
|
|
6781
|
+
async function removeWorktree(root, dir, branch, force = false) {
|
|
6782
|
+
await git(root, "worktree", "remove", ...force ? ["--force"] : [], dir);
|
|
6783
|
+
if (branch) await git(root, "branch", "-D", branch);
|
|
6784
|
+
}
|
|
6785
|
+
var SNIPPET = 400;
|
|
6786
|
+
function formatFanReport(reports) {
|
|
6787
|
+
const lines = [];
|
|
6788
|
+
for (const r of reports) {
|
|
6789
|
+
lines.push(` \u2692 ${r.role} ${r.ok ? "\u2713" : "\u2717"} \u2014 ${r.task.length > 70 ? `${r.task.slice(0, 70)}\u2026` : r.task}`);
|
|
6790
|
+
const snip = r.output.length > SNIPPET ? `${r.output.slice(0, SNIPPET)}\u2026` : r.output;
|
|
6791
|
+
if (snip) lines.push(...snip.split("\n").map((l) => ` ${l}`));
|
|
6792
|
+
if (r.dir && r.branch && r.changes?.length) {
|
|
6793
|
+
lines.push(` \u270E ${r.changes.length} file${r.changes.length === 1 ? "" : "s"} changed on ${r.branch}`);
|
|
6794
|
+
lines.push(` review: cd "${r.dir}" \xB7 keep: commit there, then \`git merge ${r.branch}\` here`);
|
|
6795
|
+
} else if (r.changes && r.changes.length === 0) {
|
|
6796
|
+
lines.push(" (no file changes \u2014 worktree cleaned up)");
|
|
6797
|
+
}
|
|
6798
|
+
}
|
|
6799
|
+
const kept = reports.filter((r) => r.dir).length;
|
|
6800
|
+
lines.push(` \u2692 fan-out done: ${reports.filter((r) => r.ok).length}/${reports.length} ok${kept ? ` \xB7 ${kept} worktree${kept === 1 ? "" : "s"} kept for review` : ""}`);
|
|
6801
|
+
return lines;
|
|
6802
|
+
}
|
|
6803
|
+
|
|
6804
|
+
// src/agents/fanout.ts
|
|
6805
|
+
var CONCURRENCY = 2;
|
|
6806
|
+
function defFor(role, task) {
|
|
6807
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
6808
|
+
return { name: `fan-${role}`, task, createdAt: now, updatedAt: now };
|
|
6809
|
+
}
|
|
6810
|
+
async function runFanout(tasks, cwd) {
|
|
6811
|
+
const capped = tasks.slice(0, MAX_FAN);
|
|
6812
|
+
const root = await gitRoot(cwd);
|
|
6813
|
+
const stamp = fanStamp(/* @__PURE__ */ new Date());
|
|
6814
|
+
const prevDepth = process.env.ORIRO_AGENT_DEPTH;
|
|
6815
|
+
process.env.ORIRO_AGENT_DEPTH = String((Number(prevDepth) || 0) + 1);
|
|
6816
|
+
let reports;
|
|
6817
|
+
try {
|
|
6818
|
+
reports = await runPool(capped.map((task, i) => ({ task, i })), CONCURRENCY, async ({ task, i }) => {
|
|
6819
|
+
const role = `a${i + 1}`;
|
|
6820
|
+
if (!root) {
|
|
6821
|
+
const r2 = await runAgent2(defFor(role, task), { cwd });
|
|
6822
|
+
return { role, task, ok: r2.ok, output: r2.output };
|
|
6823
|
+
}
|
|
6824
|
+
const dir = fanDir(root, stamp, i);
|
|
6825
|
+
const branch = fanBranch(stamp, i);
|
|
6826
|
+
const err = await addWorktree(root, dir, branch);
|
|
6827
|
+
if (err) return { role, task, ok: false, output: `could not create worktree: ${err}` };
|
|
6828
|
+
const r = await runAgent2(defFor(role, task), { cwd: dir });
|
|
6829
|
+
const changes = await changedFiles(dir);
|
|
6830
|
+
if (changes.length === 0) {
|
|
6831
|
+
await removeWorktree(root, dir, branch);
|
|
6832
|
+
return { role, task, ok: r.ok, output: r.output, changes: [] };
|
|
6833
|
+
}
|
|
6834
|
+
return { role, task, ok: r.ok, output: r.output, dir, branch, changes };
|
|
6835
|
+
});
|
|
6836
|
+
} finally {
|
|
6837
|
+
if (prevDepth === void 0) delete process.env.ORIRO_AGENT_DEPTH;
|
|
6838
|
+
else process.env.ORIRO_AGENT_DEPTH = prevDepth;
|
|
6839
|
+
}
|
|
6840
|
+
const lines = formatFanReport(reports);
|
|
6841
|
+
if (!root) lines.unshift(" \u2692 not a git repo \u2014 agents ran in the SAME directory (no worktree isolation)");
|
|
6842
|
+
return lines;
|
|
6843
|
+
}
|
|
6844
|
+
|
|
6845
|
+
// src/repl-ui/slash-agents.ts
|
|
6846
|
+
function isAgentsSlash(slash) {
|
|
6847
|
+
return parseAgentsSlash(slash) !== void 0;
|
|
6848
|
+
}
|
|
6849
|
+
async function handleAgents(line) {
|
|
6850
|
+
const p = parseAgentsSlash(line);
|
|
6851
|
+
if (!p || p.cmd === "help") {
|
|
6852
|
+
return [
|
|
6853
|
+
` ${accent("/agents")} ${dim("\u2014 parallel sub-agents in isolated git worktrees (results merged here)")}`,
|
|
6854
|
+
` ${accent("/agents 3x <task>")} ${dim("three agents race the same task")}`,
|
|
6855
|
+
` ${accent("/agents <task A> | <task B>")} ${dim(`different tasks in parallel (max ${MAX_FAN}; '|' separates tasks)`)}`,
|
|
6856
|
+
` ${dim("each agent gets its own worktree + branch; clean ones are removed, changed ones kept for review")}`
|
|
6857
|
+
];
|
|
6858
|
+
}
|
|
6859
|
+
return runFanout(p.tasks, process.cwd());
|
|
6860
|
+
}
|
|
6861
|
+
|
|
6727
6862
|
// src/repl-ui/tui-repl.ts
|
|
6728
6863
|
var editorTheme = {
|
|
6729
6864
|
borderColor: (s) => dim(s),
|
|
@@ -6810,7 +6945,7 @@ async function runTuiRepl(session) {
|
|
|
6810
6945
|
` ${accent("/routers")} pool add\xB7rotate ${accent("/model")} <id\u2026> switch ${accent("/usage")} health ${accent("/trace")} tool+router activity ${accent("/compact")} free context`,
|
|
6811
6946
|
` ${accent("/review")} artifacts ${accent("/save")} <n> [path] ${accent("/init")} AGENTS.md ${accent("/skills")} ${accent("/connectors")} ${accent("/voice")}`,
|
|
6812
6947
|
` ${accent("/sessions")} list saved ${accent("/undo")} rewind a turn ${dim("resume:")} ${accent("oriro -c")} / ${accent("oriro --resume <id>")}`,
|
|
6813
|
-
` ${accent("/plan")} <task> plan read-only ${accent("/approve")} execute it ${accent("/reject")} discard`,
|
|
6948
|
+
` ${accent("/plan")} <task> plan read-only ${accent("/approve")} execute it ${accent("/reject")} discard ${accent("/agents")} parallel worktree fan-out`,
|
|
6814
6949
|
` ${dim("Shift+Tab")} posture ${dim("Alt+Shift+T")} thinking ${accent("/help")} ${accent("/exit")}`
|
|
6815
6950
|
].join("\n");
|
|
6816
6951
|
chat.addChild(new Text(help, 0, 0));
|
|
@@ -6891,6 +7026,18 @@ async function runTuiRepl(session) {
|
|
|
6891
7026
|
})();
|
|
6892
7027
|
return;
|
|
6893
7028
|
}
|
|
7029
|
+
if (isAgentsSlash(slash)) {
|
|
7030
|
+
editor.setText("");
|
|
7031
|
+
const pending = new Text(dim(" \u2692 deploying agents\u2026"), 0, 0);
|
|
7032
|
+
chat.addChild(pending);
|
|
7033
|
+
tui.requestRender();
|
|
7034
|
+
void (async () => {
|
|
7035
|
+
const lines = await handleAgents(text);
|
|
7036
|
+
pending.setText(lines.join("\n"));
|
|
7037
|
+
tui.requestRender();
|
|
7038
|
+
})();
|
|
7039
|
+
return;
|
|
7040
|
+
}
|
|
6894
7041
|
const plan = parsePlanSlash(text);
|
|
6895
7042
|
let internalPrompt;
|
|
6896
7043
|
let turnText = text;
|
|
@@ -7023,7 +7170,7 @@ ${english}`;
|
|
|
7023
7170
|
// src/voice/mic.ts
|
|
7024
7171
|
import { spawn as spawn3 } from "child_process";
|
|
7025
7172
|
import { tmpdir as tmpdir3 } from "os";
|
|
7026
|
-
import { join as
|
|
7173
|
+
import { join as join28 } from "path";
|
|
7027
7174
|
import { existsSync as existsSync18, statSync as statSync4 } from "fs";
|
|
7028
7175
|
function recorders(outFile, seconds) {
|
|
7029
7176
|
const dur = String(seconds);
|
|
@@ -7045,7 +7192,7 @@ function recorders(outFile, seconds) {
|
|
|
7045
7192
|
];
|
|
7046
7193
|
}
|
|
7047
7194
|
async function recordMic(seconds = 6) {
|
|
7048
|
-
const outFile =
|
|
7195
|
+
const outFile = join28(tmpdir3(), `oriro-voice-${process.pid}-${seconds}.wav`);
|
|
7049
7196
|
for (const r of recorders(outFile, seconds)) {
|
|
7050
7197
|
const okFile = await new Promise((resolve3) => {
|
|
7051
7198
|
const child = spawn3(r.cmd, r.args, { stdio: "ignore" });
|
|
@@ -7118,6 +7265,7 @@ function replHelp() {
|
|
|
7118
7265
|
${dim("This session")} ${accent("/usage")} pool health & turns ${accent("/trace")} activity ${accent("/compact")} free context ${accent("/undo")} rewind a turn
|
|
7119
7266
|
${dim("Continuity")} ${accent("/sessions")} list saved sessions ${dim("resume:")} ${accent("oriro -c")} ${dim("or")} ${accent("oriro --resume <id>")}
|
|
7120
7267
|
${dim("Plan loop")} ${accent("/plan")} <task> read-only plan ${accent("/approve")} execute it ${accent("/reject")} discard
|
|
7268
|
+
${dim("Fan-out")} ${accent("/agents")} <A> | <B> parallel sub-agents in isolated git worktrees
|
|
7121
7269
|
${dim("Artifacts")} ${accent("/review")} code/SVG from the last reply ${accent("/save")} <n> [path] write one
|
|
7122
7270
|
${dim("Project")} ${accent("/init")} write a starter AGENTS.md ORIRO reads each session
|
|
7123
7271
|
${dim("Capabilities")} ${accent("/skills")} ${accent("/connectors")} ${accent("/voice")} speak a turn
|
|
@@ -7217,6 +7365,10 @@ async function runReadlineRepl(session) {
|
|
|
7217
7365
|
stdout7.write(handleArtifactSlash(line).join("\n") + "\n");
|
|
7218
7366
|
continue;
|
|
7219
7367
|
}
|
|
7368
|
+
if (isAgentsSlash(slash)) {
|
|
7369
|
+
stdout7.write((await handleAgents(line)).join("\n") + "\n");
|
|
7370
|
+
continue;
|
|
7371
|
+
}
|
|
7220
7372
|
const plan = parsePlanSlash(line);
|
|
7221
7373
|
let internalPrompt;
|
|
7222
7374
|
let turnText = line;
|
|
@@ -7377,7 +7529,7 @@ async function confirmDestructive(what, opts = {}) {
|
|
|
7377
7529
|
|
|
7378
7530
|
// src/config/store.ts
|
|
7379
7531
|
import { readFileSync as readFileSync22, writeFileSync as writeFileSync20, mkdirSync as mkdirSync16 } from "fs";
|
|
7380
|
-
import { join as
|
|
7532
|
+
import { join as join29 } from "path";
|
|
7381
7533
|
var KEYS = {
|
|
7382
7534
|
output: {
|
|
7383
7535
|
desc: "default output format for list commands: text | json | csv",
|
|
@@ -7399,7 +7551,7 @@ function validateConfig(key, value) {
|
|
|
7399
7551
|
return KEYS[key].validate?.(value) ?? null;
|
|
7400
7552
|
}
|
|
7401
7553
|
function file4() {
|
|
7402
|
-
return
|
|
7554
|
+
return join29(oriroDir(), "config.json");
|
|
7403
7555
|
}
|
|
7404
7556
|
var cache = null;
|
|
7405
7557
|
function readAll() {
|
|
@@ -8002,9 +8154,9 @@ function registerConnectorsCommand(program2) {
|
|
|
8002
8154
|
|
|
8003
8155
|
// src/channels/config.ts
|
|
8004
8156
|
import { readFileSync as readFileSync25, writeFileSync as writeFileSync21 } from "fs";
|
|
8005
|
-
import { join as
|
|
8157
|
+
import { join as join30 } from "path";
|
|
8006
8158
|
function file5() {
|
|
8007
|
-
return
|
|
8159
|
+
return join30(oriroDir(), "channels.json");
|
|
8008
8160
|
}
|
|
8009
8161
|
function readChannels() {
|
|
8010
8162
|
try {
|
|
@@ -8017,10 +8169,10 @@ function readChannels() {
|
|
|
8017
8169
|
function saveChannel(cfg) {
|
|
8018
8170
|
const all = readChannels().filter((c) => c.kind !== cfg.kind);
|
|
8019
8171
|
all.push(cfg);
|
|
8020
|
-
writeFileSync21(
|
|
8172
|
+
writeFileSync21(join30(ensureOriroDir(), "channels.json"), JSON.stringify(all, null, 2), "utf8");
|
|
8021
8173
|
}
|
|
8022
8174
|
function removeChannel(kind) {
|
|
8023
|
-
writeFileSync21(
|
|
8175
|
+
writeFileSync21(join30(ensureOriroDir(), "channels.json"), JSON.stringify(readChannels().filter((c) => c.kind !== kind), null, 2), "utf8");
|
|
8024
8176
|
}
|
|
8025
8177
|
|
|
8026
8178
|
// src/channels/telegram.ts
|
|
@@ -8137,9 +8289,9 @@ async function startDiscord(token) {
|
|
|
8137
8289
|
}
|
|
8138
8290
|
|
|
8139
8291
|
// src/channels/whatsapp.ts
|
|
8140
|
-
import { join as
|
|
8292
|
+
import { join as join31 } from "path";
|
|
8141
8293
|
function whatsappAuthDir() {
|
|
8142
|
-
return
|
|
8294
|
+
return join31(oriroDir(), "whatsapp-auth");
|
|
8143
8295
|
}
|
|
8144
8296
|
async function startWhatsApp() {
|
|
8145
8297
|
let baileys;
|
|
@@ -8258,7 +8410,7 @@ function registerChannelsCommand(program2) {
|
|
|
8258
8410
|
|
|
8259
8411
|
// src/commands/skills.ts
|
|
8260
8412
|
import { existsSync as existsSync21, statSync as statSync5, mkdirSync as mkdirSync17, cpSync, rmSync as rmSync4 } from "fs";
|
|
8261
|
-
import { resolve as resolve2, join as
|
|
8413
|
+
import { resolve as resolve2, join as join32, basename as basename3, dirname as dirname4 } from "path";
|
|
8262
8414
|
function registerSkillsCommand(program2) {
|
|
8263
8415
|
const skills = program2.command("skills").description("the ORIRO skill library \u2014 bundled + your own");
|
|
8264
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) => {
|
|
@@ -8295,22 +8447,22 @@ function registerSkillsCommand(program2) {
|
|
|
8295
8447
|
mkdirSync17(dest, { recursive: true });
|
|
8296
8448
|
const st = statSync5(src);
|
|
8297
8449
|
if (st.isDirectory()) {
|
|
8298
|
-
if (!existsSync21(
|
|
8299
|
-
const name =
|
|
8300
|
-
cpSync(src,
|
|
8301
|
-
ok(`added skill ${accent(name)} \u2192 ${
|
|
8302
|
-
} else if (
|
|
8303
|
-
const name =
|
|
8304
|
-
mkdirSync17(
|
|
8305
|
-
cpSync(src,
|
|
8306
|
-
ok(`added skill ${accent(name)} \u2192 ${
|
|
8450
|
+
if (!existsSync21(join32(src, "SKILL.md"))) die(`no SKILL.md in ${src} \u2014 a skill folder must contain SKILL.md`);
|
|
8451
|
+
const name = basename3(src);
|
|
8452
|
+
cpSync(src, join32(dest, name), { recursive: true });
|
|
8453
|
+
ok(`added skill ${accent(name)} \u2192 ${join32(dest, name)}`);
|
|
8454
|
+
} else if (basename3(src).toLowerCase() === "skill.md") {
|
|
8455
|
+
const name = basename3(dirname4(src)) || "custom-skill";
|
|
8456
|
+
mkdirSync17(join32(dest, name), { recursive: true });
|
|
8457
|
+
cpSync(src, join32(dest, name, "SKILL.md"));
|
|
8458
|
+
ok(`added skill ${accent(name)} \u2192 ${join32(dest, name)}`);
|
|
8307
8459
|
} else {
|
|
8308
8460
|
die("expected a folder containing SKILL.md, or a SKILL.md file");
|
|
8309
8461
|
}
|
|
8310
8462
|
info("It loads on next launch \u2014 and is available in chat via /skill.");
|
|
8311
8463
|
});
|
|
8312
8464
|
skills.command("remove <name>").description("remove a skill you added").option("-f, --force", "skip the confirmation prompt").action(async (name, opts) => {
|
|
8313
|
-
const target =
|
|
8465
|
+
const target = join32(userSkillsDir(), name);
|
|
8314
8466
|
if (!existsSync21(target)) {
|
|
8315
8467
|
info(`'${name}' is not a user-added skill \u2014 nothing to remove`);
|
|
8316
8468
|
return;
|
|
@@ -8899,7 +9051,7 @@ function registerConfigCommand(program2) {
|
|
|
8899
9051
|
|
|
8900
9052
|
// src/commands/setup.ts
|
|
8901
9053
|
import { rmSync as rmSync5 } from "fs";
|
|
8902
|
-
import { join as
|
|
9054
|
+
import { join as join33 } from "path";
|
|
8903
9055
|
import { stdin as stdin12, stdout as stdout11 } from "process";
|
|
8904
9056
|
var MARKERS = [
|
|
8905
9057
|
"language.json",
|
|
@@ -8907,14 +9059,14 @@ var MARKERS = [
|
|
|
8907
9059
|
"skills-onboarded.json",
|
|
8908
9060
|
"connectors-onboarded.json",
|
|
8909
9061
|
"models-onboarded.json",
|
|
8910
|
-
|
|
9062
|
+
join33("routers", "onboarded.json")
|
|
8911
9063
|
];
|
|
8912
9064
|
function registerSetupCommand(program2) {
|
|
8913
9065
|
program2.command("setup").description("run the guided setup wizard (language \xB7 routers \xB7 connectors \xB7 skills \xB7 avatar)").option("--reset", "clear your settled choices and re-ask every step").action(async (opts) => {
|
|
8914
9066
|
if (opts.reset) {
|
|
8915
9067
|
for (const m of MARKERS) {
|
|
8916
9068
|
try {
|
|
8917
|
-
rmSync5(
|
|
9069
|
+
rmSync5(join33(oriroDir(), m), { force: true });
|
|
8918
9070
|
} catch {
|
|
8919
9071
|
}
|
|
8920
9072
|
}
|
|
@@ -8932,7 +9084,7 @@ function registerSetupCommand(program2) {
|
|
|
8932
9084
|
|
|
8933
9085
|
// src/commands/import.ts
|
|
8934
9086
|
import { existsSync as existsSync22, readFileSync as readFileSync27, readdirSync as readdirSync4, statSync as statSync6, cpSync as cpSync2, mkdirSync as mkdirSync18 } from "fs";
|
|
8935
|
-
import { join as
|
|
9087
|
+
import { join as join34, basename as basename4 } from "path";
|
|
8936
9088
|
function registerImportCommand(program2) {
|
|
8937
9089
|
const imp = program2.command("import").description("migrate from another CLI (MCP servers, skills)");
|
|
8938
9090
|
imp.command("mcp <file>").description("import MCP servers from a Claude-compatible mcp.json (Guardian-vetted)").action((file6) => {
|
|
@@ -8989,11 +9141,11 @@ function registerImportCommand(program2) {
|
|
|
8989
9141
|
const dest = userSkillsDir();
|
|
8990
9142
|
mkdirSync18(dest, { recursive: true });
|
|
8991
9143
|
heading("Import skills");
|
|
8992
|
-
const sources = existsSync22(
|
|
9144
|
+
const sources = existsSync22(join34(dir, "SKILL.md")) ? [dir] : readdirSync4(dir).map((e) => join34(dir, e)).filter((p) => statSync6(p).isDirectory() && existsSync22(join34(p, "SKILL.md")));
|
|
8993
9145
|
let n = 0;
|
|
8994
9146
|
for (const src of sources) {
|
|
8995
|
-
cpSync2(src,
|
|
8996
|
-
process.stdout.write(` ${fgHex(PALETTE.success, "\u2713")} ${accent(
|
|
9147
|
+
cpSync2(src, join34(dest, basename4(src)), { recursive: true });
|
|
9148
|
+
process.stdout.write(` ${fgHex(PALETTE.success, "\u2713")} ${accent(basename4(src))}
|
|
8997
9149
|
`);
|
|
8998
9150
|
n++;
|
|
8999
9151
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oriro/orirocli",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.6",
|
|
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": {
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"dev": "tsx src/cli.ts",
|
|
24
24
|
"build": "tsup",
|
|
25
25
|
"typecheck": "tsc --noEmit",
|
|
26
|
-
"test:unit": "tsx scripts/test-tool-sanitize.ts && tsx scripts/test-guardian.ts && tsx scripts/test-scribe.ts && tsx scripts/test-race.ts && tsx scripts/test-weights.ts && tsx scripts/test-output.ts && tsx scripts/test-connectors.ts && tsx scripts/test-artifacts.ts && tsx scripts/test-project-md.ts && tsx scripts/test-compact.ts && tsx scripts/test-init.ts && tsx scripts/test-sessions.ts && tsx scripts/test-permission.ts && tsx scripts/test-plan-mode.ts",
|
|
26
|
+
"test:unit": "tsx scripts/test-tool-sanitize.ts && tsx scripts/test-guardian.ts && tsx scripts/test-scribe.ts && tsx scripts/test-race.ts && tsx scripts/test-weights.ts && tsx scripts/test-output.ts && tsx scripts/test-connectors.ts && tsx scripts/test-artifacts.ts && tsx scripts/test-project-md.ts && tsx scripts/test-compact.ts && tsx scripts/test-init.ts && tsx scripts/test-sessions.ts && tsx scripts/test-permission.ts && tsx scripts/test-plan-mode.ts && tsx scripts/test-agents-fanout.ts",
|
|
27
27
|
"smoke": "npm run build && node scripts/smoke.mjs",
|
|
28
28
|
"prepublishOnly": "npm run build && npm run test:unit && node scripts/smoke.mjs && node scripts/prepublish-check.mjs",
|
|
29
29
|
"start": "node dist/cli.js"
|