@oriro/orirocli 0.3.3 → 0.3.4
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 +219 -77
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -3382,19 +3382,77 @@ import {
|
|
|
3382
3382
|
createAgentSession as createAgentSession2,
|
|
3383
3383
|
AuthStorage as AuthStorage2,
|
|
3384
3384
|
ModelRegistry as ModelRegistry2,
|
|
3385
|
-
SessionManager as SessionManager2,
|
|
3386
3385
|
SettingsManager,
|
|
3387
3386
|
DefaultResourceLoader,
|
|
3388
3387
|
getAgentDir
|
|
3389
3388
|
} from "@earendil-works/pi-coding-agent";
|
|
3390
3389
|
|
|
3390
|
+
// src/sessions/store.ts
|
|
3391
|
+
import { join as join16 } from "path";
|
|
3392
|
+
import { SessionManager } from "@earendil-works/pi-coding-agent";
|
|
3393
|
+
function sessionsDir() {
|
|
3394
|
+
return join16(oriroDir(), "sessions");
|
|
3395
|
+
}
|
|
3396
|
+
async function findByIdPrefix(cwd, idish, verb) {
|
|
3397
|
+
const infos = await SessionManager.list(cwd, sessionsDir());
|
|
3398
|
+
const exact = infos.find((s) => s.id === idish);
|
|
3399
|
+
if (exact) return exact;
|
|
3400
|
+
const pref = infos.filter((s) => s.id.startsWith(idish));
|
|
3401
|
+
if (pref.length === 1) return pref[0];
|
|
3402
|
+
if (pref.length > 1) throw new Error(`'${idish}' matches ${pref.length} sessions \u2014 use a longer id (oriro sessions)`);
|
|
3403
|
+
throw new Error(`no session '${idish}' to ${verb} here \u2014 see: oriro sessions`);
|
|
3404
|
+
}
|
|
3405
|
+
async function resolveSessionManager(cwd, opts = {}) {
|
|
3406
|
+
const dir = sessionsDir();
|
|
3407
|
+
if (opts.ephemeral) return { sm: SessionManager.inMemory(cwd), note: "ephemeral \u2014 this session is NOT saved" };
|
|
3408
|
+
if (opts.continue) return { sm: SessionManager.continueRecent(cwd, dir), note: "continuing your most recent session" };
|
|
3409
|
+
if (opts.resumeId) {
|
|
3410
|
+
const hit = await findByIdPrefix(cwd, opts.resumeId, "resume");
|
|
3411
|
+
return { sm: SessionManager.open(hit.path, dir), note: `resumed ${hit.id.slice(0, 8)} (${hit.messageCount} msgs)` };
|
|
3412
|
+
}
|
|
3413
|
+
if (opts.forkId) {
|
|
3414
|
+
const hit = await findByIdPrefix(cwd, opts.forkId, "fork");
|
|
3415
|
+
return { sm: SessionManager.forkFrom(hit.path, cwd, dir), note: `forked a new session from ${hit.id.slice(0, 8)}` };
|
|
3416
|
+
}
|
|
3417
|
+
return { sm: SessionManager.create(cwd, dir), note: "new session (saved locally \u2014 resume with `oriro -c`)" };
|
|
3418
|
+
}
|
|
3419
|
+
async function listSessions(cwd = process.cwd()) {
|
|
3420
|
+
const infos = await SessionManager.list(cwd, sessionsDir());
|
|
3421
|
+
return infos.sort((a, b) => b.modified.getTime() - a.modified.getTime());
|
|
3422
|
+
}
|
|
3423
|
+
function shortWhen(d) {
|
|
3424
|
+
const mon = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"][d.getMonth()] ?? "";
|
|
3425
|
+
const p = (n) => String(n).padStart(2, "0");
|
|
3426
|
+
return `${mon} ${p(d.getDate())} ${p(d.getHours())}:${p(d.getMinutes())}`;
|
|
3427
|
+
}
|
|
3428
|
+
function formatSessionList(infos) {
|
|
3429
|
+
if (!infos.length) return [dim(" no saved sessions yet \u2014 they're created as you chat. Resume the last with `oriro -c`.")];
|
|
3430
|
+
const lines = [];
|
|
3431
|
+
for (const s of infos) {
|
|
3432
|
+
const id = s.id.slice(0, 8);
|
|
3433
|
+
const first = (s.firstMessage ?? s.name ?? "(empty)").replace(/\s+/g, " ").trim().slice(0, 56);
|
|
3434
|
+
lines.push(` ${accent(id)} ${dim(shortWhen(s.modified).padEnd(12))} ${dim(`${String(s.messageCount).padStart(3)} msg`)} ${first}`);
|
|
3435
|
+
}
|
|
3436
|
+
lines.push(dim(` ${infos.length} session${infos.length === 1 ? "" : "s"} \xB7 resume: `) + accent("oriro --resume <id>") + dim(" \xB7 continue last: ") + accent("oriro -c"));
|
|
3437
|
+
return lines;
|
|
3438
|
+
}
|
|
3439
|
+
function sessionRows(infos) {
|
|
3440
|
+
return infos.map((s) => ({
|
|
3441
|
+
id: s.id,
|
|
3442
|
+
messages: s.messageCount,
|
|
3443
|
+
modified: s.modified.toISOString(),
|
|
3444
|
+
cwd: s.cwd,
|
|
3445
|
+
first: (s.firstMessage ?? "").replace(/\s+/g, " ").trim().slice(0, 80)
|
|
3446
|
+
}));
|
|
3447
|
+
}
|
|
3448
|
+
|
|
3391
3449
|
// src/routers/mux-provider.ts
|
|
3392
3450
|
import { streamSimple as piStreamSimple2, createAssistantMessageEventStream } from "@earendil-works/pi-ai";
|
|
3393
3451
|
import { register as registerOpenAICompletions } from "@earendil-works/pi-ai/openai-completions";
|
|
3394
3452
|
|
|
3395
3453
|
// src/routers/mux.ts
|
|
3396
3454
|
import { existsSync as existsSync7, mkdirSync as mkdirSync9, readFileSync as readFileSync11, writeFileSync as writeFileSync12 } from "fs";
|
|
3397
|
-
import { join as
|
|
3455
|
+
import { join as join17 } from "path";
|
|
3398
3456
|
var COOLDOWN_DEFAULT_MS = 6e4;
|
|
3399
3457
|
var UNHEALTHY_AFTER = 3;
|
|
3400
3458
|
var RouterMux = class {
|
|
@@ -3464,11 +3522,11 @@ var RouterMux = class {
|
|
|
3464
3522
|
}
|
|
3465
3523
|
};
|
|
3466
3524
|
function healthStatePath(dir) {
|
|
3467
|
-
return
|
|
3525
|
+
return join17(dir, "routers", "health.json");
|
|
3468
3526
|
}
|
|
3469
3527
|
function saveMuxState(dir, stats) {
|
|
3470
3528
|
const p = healthStatePath(dir);
|
|
3471
|
-
mkdirSync9(
|
|
3529
|
+
mkdirSync9(join17(dir, "routers"), { recursive: true });
|
|
3472
3530
|
writeFileSync12(p, JSON.stringify(stats, null, 2), "utf8");
|
|
3473
3531
|
}
|
|
3474
3532
|
function loadMuxState(dir) {
|
|
@@ -3570,28 +3628,28 @@ import { Type } from "typebox";
|
|
|
3570
3628
|
|
|
3571
3629
|
// src/scribe/capture.ts
|
|
3572
3630
|
import { closeSync as closeSync2, fsyncSync as fsyncSync2, mkdirSync as mkdirSync12, openSync as openSync2, writeSync as writeSync2 } from "fs";
|
|
3573
|
-
import { join as
|
|
3631
|
+
import { join as join19 } from "path";
|
|
3574
3632
|
|
|
3575
3633
|
// src/scribe/digest.ts
|
|
3576
3634
|
import { existsSync as existsSync8, mkdirSync as mkdirSync10, readFileSync as readFileSync12, writeFileSync as writeFileSync13 } from "fs";
|
|
3577
3635
|
|
|
3578
3636
|
// src/scribe/paths.ts
|
|
3579
|
-
import { join as
|
|
3637
|
+
import { join as join18 } from "path";
|
|
3580
3638
|
function scribeDir() {
|
|
3581
3639
|
const override = process.env.ORIRO_SCRIBE_DIR?.trim();
|
|
3582
|
-
return override && override.length > 0 ? override :
|
|
3640
|
+
return override && override.length > 0 ? override : join18(CONFIG_DIR, "scribe");
|
|
3583
3641
|
}
|
|
3584
3642
|
function journalFile(date) {
|
|
3585
|
-
return
|
|
3643
|
+
return join18(scribeDir(), `${date}.md`);
|
|
3586
3644
|
}
|
|
3587
3645
|
function digestFile() {
|
|
3588
|
-
return
|
|
3646
|
+
return join18(scribeDir(), "_digest.md");
|
|
3589
3647
|
}
|
|
3590
3648
|
function timelineFile() {
|
|
3591
|
-
return
|
|
3649
|
+
return join18(scribeDir(), "_timeline.md");
|
|
3592
3650
|
}
|
|
3593
3651
|
function artifactsDir() {
|
|
3594
|
-
return
|
|
3652
|
+
return join18(scribeDir(), "artifacts");
|
|
3595
3653
|
}
|
|
3596
3654
|
|
|
3597
3655
|
// src/scribe/digest.ts
|
|
@@ -3774,7 +3832,7 @@ var INLINE_CAP = 4e3;
|
|
|
3774
3832
|
function sideFile(date, ts, kind, full) {
|
|
3775
3833
|
mkdirSync12(artifactsDir(), { recursive: true });
|
|
3776
3834
|
const name = `${date}_${ts.replace(/[:.]/g, "-")}_${kind}.md`;
|
|
3777
|
-
const p =
|
|
3835
|
+
const p = join19(artifactsDir(), name);
|
|
3778
3836
|
const fd = openSync2(p, "w");
|
|
3779
3837
|
try {
|
|
3780
3838
|
writeSync2(fd, full);
|
|
@@ -3866,12 +3924,12 @@ import {
|
|
|
3866
3924
|
writeFileSync as writeFileSync14,
|
|
3867
3925
|
writeSync as writeSync3
|
|
3868
3926
|
} from "fs";
|
|
3869
|
-
import { join as
|
|
3927
|
+
import { join as join20 } from "path";
|
|
3870
3928
|
function healthFile() {
|
|
3871
|
-
return
|
|
3929
|
+
return join20(scribeDir(), "_health.json");
|
|
3872
3930
|
}
|
|
3873
3931
|
function faultLogFile() {
|
|
3874
|
-
return
|
|
3932
|
+
return join20(scribeDir(), "_faults.log");
|
|
3875
3933
|
}
|
|
3876
3934
|
function read2() {
|
|
3877
3935
|
try {
|
|
@@ -3924,9 +3982,9 @@ import {
|
|
|
3924
3982
|
writeFileSync as writeFileSync15,
|
|
3925
3983
|
writeSync as writeSync4
|
|
3926
3984
|
} from "fs";
|
|
3927
|
-
import { join as
|
|
3985
|
+
import { join as join21 } from "path";
|
|
3928
3986
|
function walFile() {
|
|
3929
|
-
return
|
|
3987
|
+
return join21(scribeDir(), "_wal.jsonl");
|
|
3930
3988
|
}
|
|
3931
3989
|
function appendLine(obj) {
|
|
3932
3990
|
mkdirSync14(scribeDir(), { recursive: true });
|
|
@@ -4138,12 +4196,12 @@ function attachScribe(session) {
|
|
|
4138
4196
|
|
|
4139
4197
|
// src/context/project-md.ts
|
|
4140
4198
|
import { existsSync as existsSync13, readFileSync as readFileSync18, statSync as statSync2 } from "fs";
|
|
4141
|
-
import { join as
|
|
4199
|
+
import { join as join22, dirname as dirname3, parse } from "path";
|
|
4142
4200
|
var NAMES = ["AGENTS.md", "CLAUDE.md", ".oriro/ORIRO.md"];
|
|
4143
4201
|
var MAX_BYTES = 32 * 1024;
|
|
4144
4202
|
var MAX_LEVELS = 24;
|
|
4145
4203
|
function isRoot(dir) {
|
|
4146
|
-
return existsSync13(
|
|
4204
|
+
return existsSync13(join22(dir, ".git")) || existsSync13(join22(dir, ".oriro"));
|
|
4147
4205
|
}
|
|
4148
4206
|
function discoverProjectInstructions(cwd) {
|
|
4149
4207
|
const chain = [];
|
|
@@ -4151,7 +4209,7 @@ function discoverProjectInstructions(cwd) {
|
|
|
4151
4209
|
const rootOfDrive = parse(cwd).root;
|
|
4152
4210
|
for (let i = 0; i < MAX_LEVELS; i++) {
|
|
4153
4211
|
for (const name of NAMES) {
|
|
4154
|
-
const p =
|
|
4212
|
+
const p = join22(dir, name);
|
|
4155
4213
|
try {
|
|
4156
4214
|
if (existsSync13(p) && statSync2(p).isFile()) {
|
|
4157
4215
|
let text = readFileSync18(p, "utf8");
|
|
@@ -4765,7 +4823,7 @@ async function comparePages(opts) {
|
|
|
4765
4823
|
|
|
4766
4824
|
// src/head/run.ts
|
|
4767
4825
|
import { writeFile } from "fs/promises";
|
|
4768
|
-
import { join as
|
|
4826
|
+
import { join as join23 } from "path";
|
|
4769
4827
|
|
|
4770
4828
|
// src/head/inspection-html.ts
|
|
4771
4829
|
var PRIORITY_COLOR = {
|
|
@@ -5267,7 +5325,7 @@ async function runInspect(target, competitors, opts = {}) {
|
|
|
5267
5325
|
const report = await comparePages({ targetUrl: target, competitorUrls: competitors.length ? competitors : [target] });
|
|
5268
5326
|
const files = [];
|
|
5269
5327
|
if (opts.html) {
|
|
5270
|
-
const path =
|
|
5328
|
+
const path = join23(opts.outDir ?? process.cwd(), `oriro-head-${hostSlug(target)}-inspect.html`);
|
|
5271
5329
|
await writeFile(path, buildInspectionHtml(report), "utf8");
|
|
5272
5330
|
files.push(path);
|
|
5273
5331
|
}
|
|
@@ -5283,7 +5341,7 @@ function parseHeadTargets(text, selfOrigin) {
|
|
|
5283
5341
|
async function runUrlToCode(url, opts = {}) {
|
|
5284
5342
|
try {
|
|
5285
5343
|
const res = await urlToCode(url, headModels(), { goal: opts.goal, stack: opts.stack });
|
|
5286
|
-
const codePath =
|
|
5344
|
+
const codePath = join23(opts.outDir ?? process.cwd(), `oriro-head-${hostSlug(url)}${extForStack(opts.stack)}`);
|
|
5287
5345
|
await writeFile(codePath, res.code, "utf8");
|
|
5288
5346
|
return { summary: `Reverse-engineered ${url} into clean code (${res.code.length} chars) \u2192 ${codePath}`, files: [codePath] };
|
|
5289
5347
|
} catch (e) {
|
|
@@ -5293,7 +5351,7 @@ async function runUrlToCode(url, opts = {}) {
|
|
|
5293
5351
|
async function runUrlToSpec(url, opts = {}) {
|
|
5294
5352
|
try {
|
|
5295
5353
|
const res = await urlToSpec(url, headModels(), { goal: opts.goal });
|
|
5296
|
-
const specPath =
|
|
5354
|
+
const specPath = join23(opts.outDir ?? process.cwd(), `oriro-head-${hostSlug(url)}.spec.yaml`);
|
|
5297
5355
|
await writeFile(specPath, res.spec, "utf8");
|
|
5298
5356
|
return { summary: `Reverse-engineered ${url} into a YAML build spec \u2192 ${specPath}`, files: [specPath] };
|
|
5299
5357
|
} catch (e) {
|
|
@@ -5305,7 +5363,7 @@ async function runCapture(urls, opts = {}) {
|
|
|
5305
5363
|
const { captureScreens: captureScreens2, buildScreenshotFlowHtml: buildScreenshotFlowHtml2 } = await Promise.resolve().then(() => (init_screenshot_flow(), screenshot_flow_exports));
|
|
5306
5364
|
const caps = await captureScreens2(urls, { video: opts.video });
|
|
5307
5365
|
const html = buildScreenshotFlowHtml2([{ name: "Captured screens", captures: caps }]);
|
|
5308
|
-
const flowPath =
|
|
5366
|
+
const flowPath = join23(opts.outDir ?? process.cwd(), "oriro-head-flow.html");
|
|
5309
5367
|
await writeFile(flowPath, html, "utf8");
|
|
5310
5368
|
const ok2 = caps.filter((c) => c.ok).length;
|
|
5311
5369
|
return { summary: `Captured ${ok2}/${caps.length} full-page screenshots \u2192 ${flowPath}`, files: [flowPath] };
|
|
@@ -5326,7 +5384,7 @@ async function runVideoToCode(videoPath, opts = {}) {
|
|
|
5326
5384
|
{ videoPath, frames, mimeType: mime, goal: opts.goal, stack: opts.stack },
|
|
5327
5385
|
headVideoModels()
|
|
5328
5386
|
);
|
|
5329
|
-
const codePath =
|
|
5387
|
+
const codePath = join23(opts.outDir ?? process.cwd(), `oriro-head-video${extForStack(opts.stack)}`);
|
|
5330
5388
|
await writeFile(codePath, res.code, "utf8");
|
|
5331
5389
|
return { summary: `Watched ${videoPath} \u2192 built code (${res.code.length} chars) \u2192 ${codePath}
|
|
5332
5390
|
(experimental on the free floor \u2014 add a vision-capable router for pixel-faithful results.)`, files: [codePath] };
|
|
@@ -5419,7 +5477,7 @@ function registerHead(pi) {
|
|
|
5419
5477
|
}
|
|
5420
5478
|
|
|
5421
5479
|
// src/orchestrate.ts
|
|
5422
|
-
import { createAgentSession, AuthStorage, ModelRegistry, SessionManager } from "@earendil-works/pi-coding-agent";
|
|
5480
|
+
import { createAgentSession, AuthStorage, ModelRegistry, SessionManager as SessionManager2 } from "@earendil-works/pi-coding-agent";
|
|
5423
5481
|
import { Type as Type3 } from "typebox";
|
|
5424
5482
|
var MAX_AGENTS = 8;
|
|
5425
5483
|
var MAX_CONCURRENCY = 4;
|
|
@@ -5432,7 +5490,7 @@ async function runOnce(spec) {
|
|
|
5432
5490
|
model,
|
|
5433
5491
|
authStorage,
|
|
5434
5492
|
modelRegistry,
|
|
5435
|
-
sessionManager:
|
|
5493
|
+
sessionManager: SessionManager2.inMemory(),
|
|
5436
5494
|
noTools: "all"
|
|
5437
5495
|
});
|
|
5438
5496
|
let out = "";
|
|
@@ -5509,19 +5567,19 @@ import { Type as Type4 } from "typebox";
|
|
|
5509
5567
|
|
|
5510
5568
|
// src/agents/store.ts
|
|
5511
5569
|
import { mkdirSync as mkdirSync15, readFileSync as readFileSync19, writeFileSync as writeFileSync16, readdirSync as readdirSync2, rmSync as rmSync3, existsSync as existsSync14 } from "fs";
|
|
5512
|
-
import { join as
|
|
5570
|
+
import { join as join24 } from "path";
|
|
5513
5571
|
var SLUG = /^[a-z0-9][a-z0-9-]{0,63}$/;
|
|
5514
5572
|
function isValidAgentName(name) {
|
|
5515
5573
|
return SLUG.test(name);
|
|
5516
5574
|
}
|
|
5517
5575
|
function agentsDir() {
|
|
5518
|
-
return
|
|
5576
|
+
return join24(oriroDir(), "agents");
|
|
5519
5577
|
}
|
|
5520
5578
|
function agentFile(name) {
|
|
5521
|
-
return
|
|
5579
|
+
return join24(agentsDir(), `${name}.json`);
|
|
5522
5580
|
}
|
|
5523
5581
|
function stateFile() {
|
|
5524
|
-
return
|
|
5582
|
+
return join24(agentsDir(), ".state.json");
|
|
5525
5583
|
}
|
|
5526
5584
|
function listAgents() {
|
|
5527
5585
|
const dir = agentsDir();
|
|
@@ -5530,7 +5588,7 @@ function listAgents() {
|
|
|
5530
5588
|
for (const f of readdirSync2(dir)) {
|
|
5531
5589
|
if (!f.endsWith(".json") || f.startsWith(".")) continue;
|
|
5532
5590
|
try {
|
|
5533
|
-
const def = JSON.parse(readFileSync19(
|
|
5591
|
+
const def = JSON.parse(readFileSync19(join24(dir, f), "utf8"));
|
|
5534
5592
|
if (def && typeof def.name === "string" && typeof def.task === "string") out.push(def);
|
|
5535
5593
|
} catch {
|
|
5536
5594
|
}
|
|
@@ -5843,9 +5901,9 @@ function registerToolList(pi, serverName, client, tools, seen = /* @__PURE__ */
|
|
|
5843
5901
|
|
|
5844
5902
|
// src/connectors/custom.ts
|
|
5845
5903
|
import { readFileSync as readFileSync20, writeFileSync as writeFileSync17 } from "fs";
|
|
5846
|
-
import { join as
|
|
5904
|
+
import { join as join25 } from "path";
|
|
5847
5905
|
function file3() {
|
|
5848
|
-
return
|
|
5906
|
+
return join25(oriroDir(), "mcp-custom.json");
|
|
5849
5907
|
}
|
|
5850
5908
|
function readCustomServers() {
|
|
5851
5909
|
try {
|
|
@@ -5857,13 +5915,13 @@ function readCustomServers() {
|
|
|
5857
5915
|
}
|
|
5858
5916
|
function saveCustomServer(server) {
|
|
5859
5917
|
const rest = readCustomServers().filter((s) => s.name.toLowerCase() !== server.name.toLowerCase());
|
|
5860
|
-
writeFileSync17(
|
|
5918
|
+
writeFileSync17(join25(ensureOriroDir(), "mcp-custom.json"), JSON.stringify([...rest, server], null, 2), "utf8");
|
|
5861
5919
|
}
|
|
5862
5920
|
function removeCustomServer(name) {
|
|
5863
5921
|
const before = readCustomServers();
|
|
5864
5922
|
const after = before.filter((s) => s.name.toLowerCase() !== name.toLowerCase());
|
|
5865
5923
|
if (after.length === before.length) return false;
|
|
5866
|
-
writeFileSync17(
|
|
5924
|
+
writeFileSync17(join25(ensureOriroDir(), "mcp-custom.json"), JSON.stringify(after, null, 2), "utf8");
|
|
5867
5925
|
return true;
|
|
5868
5926
|
}
|
|
5869
5927
|
function trustedServerNames() {
|
|
@@ -5928,16 +5986,17 @@ async function assembleOriroSession(opts = {}) {
|
|
|
5928
5986
|
]
|
|
5929
5987
|
});
|
|
5930
5988
|
await resourceLoader.reload();
|
|
5989
|
+
const { sm, note: sessionNote } = await resolveSessionManager(cwd, opts.resume);
|
|
5931
5990
|
const { session, extensionsResult } = await createAgentSession2({
|
|
5932
5991
|
model,
|
|
5933
5992
|
authStorage,
|
|
5934
5993
|
modelRegistry,
|
|
5935
5994
|
settingsManager,
|
|
5936
|
-
sessionManager:
|
|
5995
|
+
sessionManager: sm,
|
|
5937
5996
|
resourceLoader
|
|
5938
5997
|
});
|
|
5939
5998
|
attachScribe(session);
|
|
5940
|
-
return { session, extensionsResult };
|
|
5999
|
+
return { session, extensionsResult, sessionNote };
|
|
5941
6000
|
}
|
|
5942
6001
|
|
|
5943
6002
|
// src/language/nllb-translator.ts
|
|
@@ -6405,7 +6464,7 @@ async function handleCompact(session, cmd) {
|
|
|
6405
6464
|
|
|
6406
6465
|
// src/context/init-agents.ts
|
|
6407
6466
|
import { existsSync as existsSync17, readFileSync as readFileSync21, readdirSync as readdirSync3, statSync as statSync3, writeFileSync as writeFileSync19 } from "fs";
|
|
6408
|
-
import { join as
|
|
6467
|
+
import { join as join26, basename } from "path";
|
|
6409
6468
|
var CODE_EXT = {
|
|
6410
6469
|
ts: "TypeScript",
|
|
6411
6470
|
tsx: "TypeScript",
|
|
@@ -6438,7 +6497,7 @@ function readJson(p) {
|
|
|
6438
6497
|
}
|
|
6439
6498
|
function detectProject(cwd) {
|
|
6440
6499
|
const facts = { name: basename(cwd) || "project", languages: [], commands: [], topDirs: [] };
|
|
6441
|
-
const pkgPath =
|
|
6500
|
+
const pkgPath = join26(cwd, "package.json");
|
|
6442
6501
|
if (existsSync17(pkgPath)) {
|
|
6443
6502
|
const pkg = readJson(pkgPath);
|
|
6444
6503
|
if (typeof pkg.name === "string" && pkg.name) facts.name = pkg.name;
|
|
@@ -6447,11 +6506,11 @@ function detectProject(cwd) {
|
|
|
6447
6506
|
for (const key of ["dev", "build", "test", "lint", "start"]) {
|
|
6448
6507
|
if (scripts[key]) facts.commands.push({ label: key, cmd: `npm run ${key}` });
|
|
6449
6508
|
}
|
|
6450
|
-
} else if (existsSync17(
|
|
6509
|
+
} else if (existsSync17(join26(cwd, "pyproject.toml")) || existsSync17(join26(cwd, "requirements.txt"))) {
|
|
6451
6510
|
if (!facts.description) facts.description = "Python project";
|
|
6452
|
-
} else if (existsSync17(
|
|
6511
|
+
} else if (existsSync17(join26(cwd, "Cargo.toml"))) {
|
|
6453
6512
|
facts.commands.push({ label: "build", cmd: "cargo build" }, { label: "test", cmd: "cargo test" });
|
|
6454
|
-
} else if (existsSync17(
|
|
6513
|
+
} else if (existsSync17(join26(cwd, "go.mod"))) {
|
|
6455
6514
|
facts.commands.push({ label: "build", cmd: "go build ./..." }, { label: "test", cmd: "go test ./..." });
|
|
6456
6515
|
}
|
|
6457
6516
|
const langCount = /* @__PURE__ */ new Map();
|
|
@@ -6466,7 +6525,7 @@ function detectProject(cwd) {
|
|
|
6466
6525
|
} catch {
|
|
6467
6526
|
}
|
|
6468
6527
|
for (const e of entries) {
|
|
6469
|
-
const full =
|
|
6528
|
+
const full = join26(cwd, e);
|
|
6470
6529
|
let isDir = false;
|
|
6471
6530
|
try {
|
|
6472
6531
|
isDir = statSync3(full).isDirectory();
|
|
@@ -6479,7 +6538,7 @@ function detectProject(cwd) {
|
|
|
6479
6538
|
try {
|
|
6480
6539
|
for (const f of readdirSync3(full)) {
|
|
6481
6540
|
try {
|
|
6482
|
-
if (statSync3(
|
|
6541
|
+
if (statSync3(join26(full, f)).isFile()) tallyExt(f);
|
|
6483
6542
|
} catch {
|
|
6484
6543
|
}
|
|
6485
6544
|
}
|
|
@@ -6513,7 +6572,7 @@ function generateAgentsMd(cwd) {
|
|
|
6513
6572
|
return lines.join("\n");
|
|
6514
6573
|
}
|
|
6515
6574
|
function writeAgentsMd(cwd = process.cwd(), force = false) {
|
|
6516
|
-
const path =
|
|
6575
|
+
const path = join26(cwd, "AGENTS.md");
|
|
6517
6576
|
const facts = detectProject(cwd);
|
|
6518
6577
|
if (existsSync17(path) && !force) return { path, created: false, facts };
|
|
6519
6578
|
writeFileSync19(path, generateAgentsMd(cwd), "utf8");
|
|
@@ -6544,6 +6603,37 @@ function handleInit(cmd, cwd = process.cwd()) {
|
|
|
6544
6603
|
return lines;
|
|
6545
6604
|
}
|
|
6546
6605
|
|
|
6606
|
+
// src/repl-ui/slash-sessions.ts
|
|
6607
|
+
function isSessionsSlash(cmd) {
|
|
6608
|
+
return /^\/sessions?(\s|$)/i.test(cmd.trim());
|
|
6609
|
+
}
|
|
6610
|
+
function isUndoSlash(cmd) {
|
|
6611
|
+
return /^\/undo(\s|$)/i.test(cmd.trim());
|
|
6612
|
+
}
|
|
6613
|
+
async function handleSessions() {
|
|
6614
|
+
try {
|
|
6615
|
+
return formatSessionList(await listSessions());
|
|
6616
|
+
} catch (e) {
|
|
6617
|
+
return [` ${fgHex(PALETTE.error, "sessions failed")}: ${dim(e instanceof Error ? e.message : String(e))}`];
|
|
6618
|
+
}
|
|
6619
|
+
}
|
|
6620
|
+
async function handleUndo(session) {
|
|
6621
|
+
try {
|
|
6622
|
+
const turns2 = session.getUserMessagesForForking();
|
|
6623
|
+
if (turns2.length < 2) {
|
|
6624
|
+
return [dim(" nothing to undo \u2014 this is the first turn of the session.")];
|
|
6625
|
+
}
|
|
6626
|
+
const target = turns2[turns2.length - 2];
|
|
6627
|
+
if (!target) return [dim(" nothing to undo.")];
|
|
6628
|
+
const res = await session.navigateTree(target.entryId, { label: "undo" });
|
|
6629
|
+
if (res.cancelled) return [dim(" undo cancelled.")];
|
|
6630
|
+
const preview = target.text.replace(/\s+/g, " ").trim().slice(0, 48);
|
|
6631
|
+
return [` ${fgHex(PALETTE.success, "\u21BA undone")} ${dim("\u2014 rewound to:")} ${accent(preview || "(prev turn)")}`];
|
|
6632
|
+
} catch (e) {
|
|
6633
|
+
return [` ${fgHex(PALETTE.error, "undo failed")}: ${dim(e instanceof Error ? e.message : String(e))}`];
|
|
6634
|
+
}
|
|
6635
|
+
}
|
|
6636
|
+
|
|
6547
6637
|
// src/repl-ui/tui-repl.ts
|
|
6548
6638
|
var editorTheme = {
|
|
6549
6639
|
borderColor: (s) => dim(s),
|
|
@@ -6626,7 +6716,8 @@ async function runTuiRepl(session) {
|
|
|
6626
6716
|
const help = [
|
|
6627
6717
|
" Just type to chat \u2014 ORIRO writes and runs code for you (keyless, free).",
|
|
6628
6718
|
` ${accent("/routers")} pool add\xB7rotate ${accent("/model")} <id\u2026> switch ${accent("/usage")} health ${accent("/trace")} tool+router activity ${accent("/compact")} free context`,
|
|
6629
|
-
` ${accent("/review")} artifacts
|
|
6719
|
+
` ${accent("/review")} artifacts ${accent("/save")} <n> [path] ${accent("/init")} AGENTS.md ${accent("/skills")} ${accent("/connectors")} ${accent("/voice")}`,
|
|
6720
|
+
` ${accent("/sessions")} list saved ${accent("/undo")} rewind a turn ${dim("resume:")} ${accent("oriro -c")} / ${accent("oriro --resume <id>")}`,
|
|
6630
6721
|
` ${dim("Shift+Tab")} posture ${dim("Alt+Shift+T")} thinking ${accent("/help")} ${accent("/exit")}`
|
|
6631
6722
|
].join("\n");
|
|
6632
6723
|
chat.addChild(new Text(help, 0, 0));
|
|
@@ -6695,6 +6786,18 @@ async function runTuiRepl(session) {
|
|
|
6695
6786
|
tui.requestRender();
|
|
6696
6787
|
return;
|
|
6697
6788
|
}
|
|
6789
|
+
if (isSessionsSlash(slash) || isUndoSlash(slash)) {
|
|
6790
|
+
editor.setText("");
|
|
6791
|
+
const pending = new Text(dim(" \u2026"), 0, 0);
|
|
6792
|
+
chat.addChild(pending);
|
|
6793
|
+
tui.requestRender();
|
|
6794
|
+
void (async () => {
|
|
6795
|
+
const lines = isUndoSlash(slash) ? await handleUndo(session) : await handleSessions();
|
|
6796
|
+
pending.setText(lines.join("\n"));
|
|
6797
|
+
tui.requestRender();
|
|
6798
|
+
})();
|
|
6799
|
+
return;
|
|
6800
|
+
}
|
|
6698
6801
|
if (slash === "/voice") {
|
|
6699
6802
|
editor.setText("");
|
|
6700
6803
|
const status = new Text(dim(" \u{1F399} listening\u2026 (needs ffmpeg + the transformers voice peer)"), 0, 0);
|
|
@@ -6786,7 +6889,7 @@ ${english}`;
|
|
|
6786
6889
|
// src/voice/mic.ts
|
|
6787
6890
|
import { spawn as spawn3 } from "child_process";
|
|
6788
6891
|
import { tmpdir as tmpdir3 } from "os";
|
|
6789
|
-
import { join as
|
|
6892
|
+
import { join as join27 } from "path";
|
|
6790
6893
|
import { existsSync as existsSync18, statSync as statSync4 } from "fs";
|
|
6791
6894
|
function recorders(outFile, seconds) {
|
|
6792
6895
|
const dur = String(seconds);
|
|
@@ -6808,7 +6911,7 @@ function recorders(outFile, seconds) {
|
|
|
6808
6911
|
];
|
|
6809
6912
|
}
|
|
6810
6913
|
async function recordMic(seconds = 6) {
|
|
6811
|
-
const outFile =
|
|
6914
|
+
const outFile = join27(tmpdir3(), `oriro-voice-${process.pid}-${seconds}.wav`);
|
|
6812
6915
|
for (const r of recorders(outFile, seconds)) {
|
|
6813
6916
|
const okFile = await new Promise((resolve3) => {
|
|
6814
6917
|
const child = spawn3(r.cmd, r.args, { stdio: "ignore" });
|
|
@@ -6878,7 +6981,8 @@ function replHelp() {
|
|
|
6878
6981
|
${dim("Just type to chat; ORIRO writes and runs code for you (keyless, free).")}
|
|
6879
6982
|
|
|
6880
6983
|
${dim("Models & routers")} ${accent("/routers")} list\xB7add\xB7rotate the racing pool ${accent("/model")} <id\u2026> switch
|
|
6881
|
-
${dim("This session")} ${accent("/usage")} pool health & turns ${accent("/trace")}
|
|
6984
|
+
${dim("This session")} ${accent("/usage")} pool health & turns ${accent("/trace")} activity ${accent("/compact")} free context ${accent("/undo")} rewind a turn
|
|
6985
|
+
${dim("Continuity")} ${accent("/sessions")} list saved sessions ${dim("resume:")} ${accent("oriro -c")} ${dim("or")} ${accent("oriro --resume <id>")}
|
|
6882
6986
|
${dim("Artifacts")} ${accent("/review")} code/SVG from the last reply ${accent("/save")} <n> [path] write one
|
|
6883
6987
|
${dim("Project")} ${accent("/init")} write a starter AGENTS.md ORIRO reads each session
|
|
6884
6988
|
${dim("Capabilities")} ${accent("/skills")} ${accent("/connectors")} ${accent("/voice")} speak a turn
|
|
@@ -6888,10 +6992,12 @@ function replHelp() {
|
|
|
6888
6992
|
|
|
6889
6993
|
`;
|
|
6890
6994
|
}
|
|
6891
|
-
async function runRepl() {
|
|
6995
|
+
async function runRepl(opts = {}) {
|
|
6892
6996
|
if (isFirstRun()) await runOnboarding();
|
|
6893
6997
|
else stdout7.write(banner());
|
|
6894
|
-
const { session } = await assembleOriroSession();
|
|
6998
|
+
const { session, sessionNote } = await assembleOriroSession({ resume: opts.resume });
|
|
6999
|
+
if (sessionNote) stdout7.write(` ${dim(sessionNote)}
|
|
7000
|
+
`);
|
|
6895
7001
|
setupVoiceInput();
|
|
6896
7002
|
if (stdin6.isTTY && stdout7.isTTY) {
|
|
6897
7003
|
await runTuiRepl(session);
|
|
@@ -6964,6 +7070,14 @@ async function runReadlineRepl(session) {
|
|
|
6964
7070
|
stdout7.write(handleInit(line).join("\n") + "\n");
|
|
6965
7071
|
continue;
|
|
6966
7072
|
}
|
|
7073
|
+
if (isSessionsSlash(slash)) {
|
|
7074
|
+
stdout7.write((await handleSessions()).join("\n") + "\n");
|
|
7075
|
+
continue;
|
|
7076
|
+
}
|
|
7077
|
+
if (isUndoSlash(slash)) {
|
|
7078
|
+
stdout7.write((await handleUndo(session)).join("\n") + "\n");
|
|
7079
|
+
continue;
|
|
7080
|
+
}
|
|
6967
7081
|
if (isArtifactSlash(slash)) {
|
|
6968
7082
|
stdout7.write(handleArtifactSlash(line).join("\n") + "\n");
|
|
6969
7083
|
continue;
|
|
@@ -7092,7 +7206,7 @@ async function confirmDestructive(what, opts = {}) {
|
|
|
7092
7206
|
|
|
7093
7207
|
// src/config/store.ts
|
|
7094
7208
|
import { readFileSync as readFileSync22, writeFileSync as writeFileSync20, mkdirSync as mkdirSync16 } from "fs";
|
|
7095
|
-
import { join as
|
|
7209
|
+
import { join as join28 } from "path";
|
|
7096
7210
|
var KEYS = {
|
|
7097
7211
|
output: {
|
|
7098
7212
|
desc: "default output format for list commands: text | json | csv",
|
|
@@ -7114,7 +7228,7 @@ function validateConfig(key, value) {
|
|
|
7114
7228
|
return KEYS[key].validate?.(value) ?? null;
|
|
7115
7229
|
}
|
|
7116
7230
|
function file4() {
|
|
7117
|
-
return
|
|
7231
|
+
return join28(oriroDir(), "config.json");
|
|
7118
7232
|
}
|
|
7119
7233
|
var cache = null;
|
|
7120
7234
|
function readAll() {
|
|
@@ -7198,6 +7312,27 @@ function outputError(opts) {
|
|
|
7198
7312
|
return f === "json" || f === "csv" || f === "text" ? null : `invalid --output '${opts.output}' \u2014 use text | json | csv`;
|
|
7199
7313
|
}
|
|
7200
7314
|
|
|
7315
|
+
// src/commands/sessions.ts
|
|
7316
|
+
function registerSessionsCommand(program2) {
|
|
7317
|
+
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) => {
|
|
7318
|
+
const oerr = outputError(opts);
|
|
7319
|
+
if (oerr) die(oerr);
|
|
7320
|
+
const infos = await listSessions();
|
|
7321
|
+
if (isMachineOutput(opts) || opts.query) {
|
|
7322
|
+
process.stdout.write(
|
|
7323
|
+
renderList2(sessionRows(infos), {
|
|
7324
|
+
output: opts.output,
|
|
7325
|
+
query: opts.query,
|
|
7326
|
+
columns: ["id", "messages", "modified", "first", "cwd"]
|
|
7327
|
+
}) + "\n"
|
|
7328
|
+
);
|
|
7329
|
+
return;
|
|
7330
|
+
}
|
|
7331
|
+
heading("Sessions");
|
|
7332
|
+
process.stdout.write(formatSessionList(infos).join("\n") + "\n");
|
|
7333
|
+
});
|
|
7334
|
+
}
|
|
7335
|
+
|
|
7201
7336
|
// src/commands/routers.ts
|
|
7202
7337
|
function registerRoutersCommand(program2) {
|
|
7203
7338
|
const routers = program2.command("routers").description("manage the free-router pool the model runs on");
|
|
@@ -7696,9 +7831,9 @@ function registerConnectorsCommand(program2) {
|
|
|
7696
7831
|
|
|
7697
7832
|
// src/channels/config.ts
|
|
7698
7833
|
import { readFileSync as readFileSync25, writeFileSync as writeFileSync21 } from "fs";
|
|
7699
|
-
import { join as
|
|
7834
|
+
import { join as join29 } from "path";
|
|
7700
7835
|
function file5() {
|
|
7701
|
-
return
|
|
7836
|
+
return join29(oriroDir(), "channels.json");
|
|
7702
7837
|
}
|
|
7703
7838
|
function readChannels() {
|
|
7704
7839
|
try {
|
|
@@ -7711,10 +7846,10 @@ function readChannels() {
|
|
|
7711
7846
|
function saveChannel(cfg) {
|
|
7712
7847
|
const all = readChannels().filter((c) => c.kind !== cfg.kind);
|
|
7713
7848
|
all.push(cfg);
|
|
7714
|
-
writeFileSync21(
|
|
7849
|
+
writeFileSync21(join29(ensureOriroDir(), "channels.json"), JSON.stringify(all, null, 2), "utf8");
|
|
7715
7850
|
}
|
|
7716
7851
|
function removeChannel(kind) {
|
|
7717
|
-
writeFileSync21(
|
|
7852
|
+
writeFileSync21(join29(ensureOriroDir(), "channels.json"), JSON.stringify(readChannels().filter((c) => c.kind !== kind), null, 2), "utf8");
|
|
7718
7853
|
}
|
|
7719
7854
|
|
|
7720
7855
|
// src/channels/telegram.ts
|
|
@@ -7831,9 +7966,9 @@ async function startDiscord(token) {
|
|
|
7831
7966
|
}
|
|
7832
7967
|
|
|
7833
7968
|
// src/channels/whatsapp.ts
|
|
7834
|
-
import { join as
|
|
7969
|
+
import { join as join30 } from "path";
|
|
7835
7970
|
function whatsappAuthDir() {
|
|
7836
|
-
return
|
|
7971
|
+
return join30(oriroDir(), "whatsapp-auth");
|
|
7837
7972
|
}
|
|
7838
7973
|
async function startWhatsApp() {
|
|
7839
7974
|
let baileys;
|
|
@@ -7952,7 +8087,7 @@ function registerChannelsCommand(program2) {
|
|
|
7952
8087
|
|
|
7953
8088
|
// src/commands/skills.ts
|
|
7954
8089
|
import { existsSync as existsSync21, statSync as statSync5, mkdirSync as mkdirSync17, cpSync, rmSync as rmSync4 } from "fs";
|
|
7955
|
-
import { resolve as resolve2, join as
|
|
8090
|
+
import { resolve as resolve2, join as join31, basename as basename2, dirname as dirname4 } from "path";
|
|
7956
8091
|
function registerSkillsCommand(program2) {
|
|
7957
8092
|
const skills = program2.command("skills").description("the ORIRO skill library \u2014 bundled + your own");
|
|
7958
8093
|
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) => {
|
|
@@ -7989,22 +8124,22 @@ function registerSkillsCommand(program2) {
|
|
|
7989
8124
|
mkdirSync17(dest, { recursive: true });
|
|
7990
8125
|
const st = statSync5(src);
|
|
7991
8126
|
if (st.isDirectory()) {
|
|
7992
|
-
if (!existsSync21(
|
|
8127
|
+
if (!existsSync21(join31(src, "SKILL.md"))) die(`no SKILL.md in ${src} \u2014 a skill folder must contain SKILL.md`);
|
|
7993
8128
|
const name = basename2(src);
|
|
7994
|
-
cpSync(src,
|
|
7995
|
-
ok(`added skill ${accent(name)} \u2192 ${
|
|
8129
|
+
cpSync(src, join31(dest, name), { recursive: true });
|
|
8130
|
+
ok(`added skill ${accent(name)} \u2192 ${join31(dest, name)}`);
|
|
7996
8131
|
} else if (basename2(src).toLowerCase() === "skill.md") {
|
|
7997
8132
|
const name = basename2(dirname4(src)) || "custom-skill";
|
|
7998
|
-
mkdirSync17(
|
|
7999
|
-
cpSync(src,
|
|
8000
|
-
ok(`added skill ${accent(name)} \u2192 ${
|
|
8133
|
+
mkdirSync17(join31(dest, name), { recursive: true });
|
|
8134
|
+
cpSync(src, join31(dest, name, "SKILL.md"));
|
|
8135
|
+
ok(`added skill ${accent(name)} \u2192 ${join31(dest, name)}`);
|
|
8001
8136
|
} else {
|
|
8002
8137
|
die("expected a folder containing SKILL.md, or a SKILL.md file");
|
|
8003
8138
|
}
|
|
8004
8139
|
info("It loads on next launch \u2014 and is available in chat via /skill.");
|
|
8005
8140
|
});
|
|
8006
8141
|
skills.command("remove <name>").description("remove a skill you added").option("-f, --force", "skip the confirmation prompt").action(async (name, opts) => {
|
|
8007
|
-
const target =
|
|
8142
|
+
const target = join31(userSkillsDir(), name);
|
|
8008
8143
|
if (!existsSync21(target)) {
|
|
8009
8144
|
info(`'${name}' is not a user-added skill \u2014 nothing to remove`);
|
|
8010
8145
|
return;
|
|
@@ -8593,7 +8728,7 @@ function registerConfigCommand(program2) {
|
|
|
8593
8728
|
|
|
8594
8729
|
// src/commands/setup.ts
|
|
8595
8730
|
import { rmSync as rmSync5 } from "fs";
|
|
8596
|
-
import { join as
|
|
8731
|
+
import { join as join32 } from "path";
|
|
8597
8732
|
import { stdin as stdin12, stdout as stdout11 } from "process";
|
|
8598
8733
|
var MARKERS = [
|
|
8599
8734
|
"language.json",
|
|
@@ -8601,14 +8736,14 @@ var MARKERS = [
|
|
|
8601
8736
|
"skills-onboarded.json",
|
|
8602
8737
|
"connectors-onboarded.json",
|
|
8603
8738
|
"models-onboarded.json",
|
|
8604
|
-
|
|
8739
|
+
join32("routers", "onboarded.json")
|
|
8605
8740
|
];
|
|
8606
8741
|
function registerSetupCommand(program2) {
|
|
8607
8742
|
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) => {
|
|
8608
8743
|
if (opts.reset) {
|
|
8609
8744
|
for (const m of MARKERS) {
|
|
8610
8745
|
try {
|
|
8611
|
-
rmSync5(
|
|
8746
|
+
rmSync5(join32(oriroDir(), m), { force: true });
|
|
8612
8747
|
} catch {
|
|
8613
8748
|
}
|
|
8614
8749
|
}
|
|
@@ -8626,7 +8761,7 @@ function registerSetupCommand(program2) {
|
|
|
8626
8761
|
|
|
8627
8762
|
// src/commands/import.ts
|
|
8628
8763
|
import { existsSync as existsSync22, readFileSync as readFileSync27, readdirSync as readdirSync4, statSync as statSync6, cpSync as cpSync2, mkdirSync as mkdirSync18 } from "fs";
|
|
8629
|
-
import { join as
|
|
8764
|
+
import { join as join33, basename as basename3 } from "path";
|
|
8630
8765
|
function registerImportCommand(program2) {
|
|
8631
8766
|
const imp = program2.command("import").description("migrate from another CLI (MCP servers, skills)");
|
|
8632
8767
|
imp.command("mcp <file>").description("import MCP servers from a Claude-compatible mcp.json (Guardian-vetted)").action((file6) => {
|
|
@@ -8683,10 +8818,10 @@ function registerImportCommand(program2) {
|
|
|
8683
8818
|
const dest = userSkillsDir();
|
|
8684
8819
|
mkdirSync18(dest, { recursive: true });
|
|
8685
8820
|
heading("Import skills");
|
|
8686
|
-
const sources = existsSync22(
|
|
8821
|
+
const sources = existsSync22(join33(dir, "SKILL.md")) ? [dir] : readdirSync4(dir).map((e) => join33(dir, e)).filter((p) => statSync6(p).isDirectory() && existsSync22(join33(p, "SKILL.md")));
|
|
8687
8822
|
let n = 0;
|
|
8688
8823
|
for (const src of sources) {
|
|
8689
|
-
cpSync2(src,
|
|
8824
|
+
cpSync2(src, join33(dest, basename3(src)), { recursive: true });
|
|
8690
8825
|
process.stdout.write(` ${fgHex(PALETTE.success, "\u2713")} ${accent(basename3(src))}
|
|
8691
8826
|
`);
|
|
8692
8827
|
n++;
|
|
@@ -8747,7 +8882,7 @@ function enableHelpOnError(program2) {
|
|
|
8747
8882
|
// src/cli.ts
|
|
8748
8883
|
var version = createRequire(import.meta.url)("../package.json").version;
|
|
8749
8884
|
var program = new Command();
|
|
8750
|
-
program.name("oriro").description("ORIRO \u2014 a free, on-device-friendly terminal AI agent.").version(version, "-v, --version").option("-p, --print <prompt>", "headless one-shot: run a single prompt, print the answer, exit (CI-friendly)").option("--output-format <fmt>", "with --print: text | json | stream-json", "text").action(async (options, command) => {
|
|
8885
|
+
program.name("oriro").description("ORIRO \u2014 a free, on-device-friendly terminal AI agent.").version(version, "-v, --version").option("-p, --print <prompt>", "headless one-shot: run a single prompt, print the answer, exit (CI-friendly)").option("--output-format <fmt>", "with --print: text | json | stream-json", "text").option("-c, --continue", "resume your most recent session in this folder").option("--resume <id>", "resume a specific saved session (id or unique prefix \u2014 see: oriro sessions)").option("--fork <id>", "start a new session branched from an existing one").option("--no-session", "don't save this session to disk (ephemeral)").action(async (options, command) => {
|
|
8751
8886
|
if (options.print !== void 0) {
|
|
8752
8887
|
const fmt = options.outputFormat ?? "text";
|
|
8753
8888
|
if (!isOutputFormatMode(fmt)) {
|
|
@@ -8774,8 +8909,15 @@ program.name("oriro").description("ORIRO \u2014 a free, on-device-friendly termi
|
|
|
8774
8909
|
process.exitCode = 1;
|
|
8775
8910
|
return;
|
|
8776
8911
|
}
|
|
8777
|
-
|
|
8912
|
+
const resume = {
|
|
8913
|
+
continue: options.continue,
|
|
8914
|
+
resumeId: options.resume,
|
|
8915
|
+
forkId: options.fork,
|
|
8916
|
+
ephemeral: options.session === false
|
|
8917
|
+
};
|
|
8918
|
+
await runRepl({ resume });
|
|
8778
8919
|
});
|
|
8920
|
+
registerSessionsCommand(program);
|
|
8779
8921
|
registerRoutersCommand(program);
|
|
8780
8922
|
registerScribeCommand(program);
|
|
8781
8923
|
registerConnectorsCommand(program);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oriro/orirocli",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.4",
|
|
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",
|
|
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",
|
|
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"
|