@chibitek/chibi 0.1.155 → 0.1.158
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/assets/{abnfDiagram-O67JEVCF-B8LdsCr1.js → abnfDiagram-O67JEVCF-B8-8zzMS.js} +1 -1
- package/dist/assets/{arc-DU5fSmKU.js → arc-CSHQ9Dx3.js} +1 -1
- package/dist/assets/{architectureDiagram-NJMV4G6O-DdQSIFKv.js → architectureDiagram-NJMV4G6O-BCHM9rXW.js} +1 -1
- package/dist/assets/{blockDiagram-BEXU5L5S-CaPcGYSS.js → blockDiagram-BEXU5L5S-B-5uxPFN.js} +1 -1
- package/dist/assets/{c4Diagram-YGBWAQC7-unt0ePgO.js → c4Diagram-YGBWAQC7-CuKNM_MR.js} +1 -1
- package/dist/assets/channel-bPN03jIt.js +1 -0
- package/dist/assets/{chunk-2Q5K7J3B-Babg5Fzu.js → chunk-2Q5K7J3B-BNF02GM4.js} +1 -1
- package/dist/assets/{chunk-3FUC2YCW-D1-dWVHo.js → chunk-3FUC2YCW-uEWgBd4M.js} +2 -2
- package/dist/assets/{chunk-5VM5RSS4-DU7nSMbT.js → chunk-5VM5RSS4-eSZuXctY.js} +1 -1
- package/dist/assets/{chunk-GTNCS2PH-QIjCJIhV.js → chunk-GTNCS2PH-CslS8nRS.js} +1 -1
- package/dist/assets/{chunk-GWA4HPMP-pSByUE5R.js → chunk-GWA4HPMP-w71-MeKj.js} +1 -1
- package/dist/assets/{chunk-JWPE2WC7-Dj2AaR1b.js → chunk-JWPE2WC7-Bjju7WGh.js} +1 -1
- package/dist/assets/{chunk-NETBCI7D-pZbN0-FP.js → chunk-NETBCI7D-HxrroD4M.js} +1 -1
- package/dist/assets/{chunk-WEXAMYUT-Bqarwe4D.js → chunk-WEXAMYUT-D7Rz470x.js} +1 -1
- package/dist/assets/{chunk-XXDRQBXY-WV8lm3aa.js → chunk-XXDRQBXY-BWKnAeyM.js} +1 -1
- package/dist/assets/{classDiagram-v2-NBCMYWYE-BANBtky1.js → classDiagram-v2-NBCMYWYE-CeBDRHmP.js} +1 -1
- package/dist/assets/{cose-bilkent-JH36ORCC-CtrktgBC.js → cose-bilkent-JH36ORCC-BBbRKlvr.js} +1 -1
- package/dist/assets/{cynefin-OW5HDTMX-DnhVVfba.js → cynefin-OW5HDTMX-W02cnJ0B.js} +1 -1
- package/dist/assets/{cynefinDiagram-VND7K2PF-B42SRR6x.js → cynefinDiagram-VND7K2PF-Cs47eaxd.js} +1 -1
- package/dist/assets/{dagre-6A5THRUB-DM--vFMK.js → dagre-6A5THRUB-8mG18hzT.js} +1 -1
- package/dist/assets/{diagram-22UHCM2B-ZBupBrPU.js → diagram-22UHCM2B-DF4Qrw67.js} +1 -1
- package/dist/assets/{diagram-3UASUU5V-BPQzNIOd.js → diagram-3UASUU5V-3BAVoed1.js} +1 -1
- package/dist/assets/{diagram-ATOU4E4O-5kO8vf8Z.js → diagram-ATOU4E4O-CKO3pECE.js} +1 -1
- package/dist/assets/{diagram-CDSNMT55-DtxogB86.js → diagram-CDSNMT55-CZhrGvur.js} +1 -1
- package/dist/assets/{diagram-MLGK6HIB-Co9-nYw_.js → diagram-MLGK6HIB-C07l9pdQ.js} +1 -1
- package/dist/assets/{diagram-MPIPVDR6-DWRuMh5y.js → diagram-MPIPVDR6-D3or4lkZ.js} +1 -1
- package/dist/assets/{ebnfDiagram-ZINNZB2B-DU_nmoG9.js → ebnfDiagram-ZINNZB2B-DV2epXp_.js} +1 -1
- package/dist/assets/{elk-276RUBZZ-Bcje7S94.js → elk-276RUBZZ-DlvEn4-1.js} +1 -1
- package/dist/assets/{erDiagram-OPXOYQCR-9aCo_2CI.js → erDiagram-OPXOYQCR-CB6X7Wt5.js} +1 -1
- package/dist/assets/{flowDiagram-KWPJA3E3-D4FYFyc5.js → flowDiagram-KWPJA3E3-C3bqz4lC.js} +1 -1
- package/dist/assets/{ganttDiagram-FUAMR5RP-WQHX5rbx.js → ganttDiagram-FUAMR5RP-yo_Evhab.js} +1 -1
- package/dist/assets/{gitGraphDiagram-X574FWY7-DRyzBdiV.js → gitGraphDiagram-X574FWY7-Cq2oUlap.js} +1 -1
- package/dist/assets/{index-CG1OvRgO.js → index-CG4AFPb4.js} +1 -1
- package/dist/assets/{index-D_8SD_0K.js → index-CMcr5k3Z.js} +205 -200
- package/dist/assets/index-CZjRcUdn.css +1 -0
- package/dist/assets/{infoDiagram-VRGFBTTK-D7SOmp4n.js → infoDiagram-VRGFBTTK-Y3ZrY7qL.js} +1 -1
- package/dist/assets/{ishikawaDiagram-OU5B5YK6-CdxOnDVX.js → ishikawaDiagram-OU5B5YK6-BpOtSfyi.js} +1 -1
- package/dist/assets/{journeyDiagram-ZHPQQLJL-CH7477Oa.js → journeyDiagram-ZHPQQLJL-UQM727le.js} +1 -1
- package/dist/assets/{kanban-definition-PNTS6WVX-BdpVvkHd.js → kanban-definition-PNTS6WVX-C3s5oHpY.js} +1 -1
- package/dist/assets/{linear-DTGq6qn5.js → linear-hX6nFOQr.js} +1 -1
- package/dist/assets/{mermaid.core-Sn2sv0Ti.js → mermaid.core-DZObGLN7.js} +5 -5
- package/dist/assets/{mindmap-definition-NLK3R4M7-koCmkYuq.js → mindmap-definition-NLK3R4M7-Br-i2E3P.js} +1 -1
- package/dist/assets/{pegDiagram-GJSIUBJH-C3sqhm8e.js → pegDiagram-GJSIUBJH-D5SERB-N.js} +1 -1
- package/dist/assets/{pieDiagram-5QR66LMP-BELBK122.js → pieDiagram-5QR66LMP-BPNf4J3D.js} +1 -1
- package/dist/assets/{quadrantDiagram-O4NWA36T-Cksi5LSm.js → quadrantDiagram-O4NWA36T-Bm_Wh7Jr.js} +1 -1
- package/dist/assets/{railroadDiagram-XR7U4H2S-f1av_EZW.js → railroadDiagram-XR7U4H2S-D6bo0abD.js} +1 -1
- package/dist/assets/{requirementDiagram-PLB6GJNP-CW4O5nER.js → requirementDiagram-PLB6GJNP--1n5rkV7.js} +1 -1
- package/dist/assets/{sankeyDiagram-IPEJSGJF-Dz8ADHNY.js → sankeyDiagram-IPEJSGJF-Ct4tP2kK.js} +1 -1
- package/dist/assets/{sequenceDiagram-PO4LG4MO-Cc3HE0iZ.js → sequenceDiagram-PO4LG4MO-CCG7O5fR.js} +1 -1
- package/dist/assets/{sizeCapture-INFHLROL-gdaZNHnK.js → sizeCapture-INFHLROL-CJJJra9c.js} +1 -1
- package/dist/assets/{stateDiagram-v2-GCMORJYK--u8LCnab.js → stateDiagram-v2-GCMORJYK-BMdRvVEX.js} +1 -1
- package/dist/assets/{swimlanes-2SLR337P-4MAw4kdO.js → swimlanes-2SLR337P-B1wnogip.js} +1 -1
- package/dist/assets/swimlanesDiagram-TC7HE7FX-DWyjdGGR.js +8 -0
- package/dist/assets/{timeline-definition-EJHVYXUP-CL89YkCT.js → timeline-definition-EJHVYXUP-l-3yhXUP.js} +1 -1
- package/dist/assets/{usecaseDiagram-POWQR4AR-C92l7YQe.js → usecaseDiagram-POWQR4AR-DtwtCOoJ.js} +1 -1
- package/dist/assets/{vennDiagram-UO4OBE2U-17siYhSj.js → vennDiagram-UO4OBE2U-BZAEce1B.js} +1 -1
- package/dist/assets/{wardleyDiagram-VNRHLVJA-CNwa9VmN.js → wardleyDiagram-VNRHLVJA-Na_BCMMO.js} +1 -1
- package/dist/assets/{xychartDiagram-PMCCYNJV-Dnu6Xzih.js → xychartDiagram-PMCCYNJV-BW9dlUfE.js} +1 -1
- package/dist/index.html +2 -2
- package/dist-server/container-mcp.js +68 -14
- package/dist-server/index.js +5633 -4562
- package/dist-server/openmausbot.js +140 -81
- package/dist-server/pair-cli.js +140 -81
- package/dist-server/server/app-installers.js +107 -7
- package/dist-server/server/avatar-subscription.js +51 -0
- package/dist-server/server/cli-help.js +74 -0
- package/dist-server/server/cli.js +37 -78
- package/dist-server/server/colima-docker.js +136 -0
- package/dist-server/server/container-computer.js +31 -63
- package/dist-server/server/container-mcp.js +5 -0
- package/dist-server/server/device-routing.js +60 -0
- package/dist-server/server/drivers/claude.js +13 -11
- package/dist-server/server/drivers/local-inject.js +3 -4
- package/dist-server/server/engine-failover.js +22 -12
- package/dist-server/server/engine-tiers.js +5 -14
- package/dist-server/server/index.js +124 -120
- package/dist-server/server/personal-goal-runtime.js +86 -0
- package/dist-server/server/personal-goal-turn.js +125 -0
- package/dist-server/server/personal-goals.js +195 -0
- package/dist-server/server/port-in-use.js +21 -0
- package/dist-server/server/routes/local-models.js +3 -2
- package/dist-server/server/session-fallback.js +76 -0
- package/dist-server/server/skill-fetch.js +14 -0
- package/dist-server/server/vault/routes.js +43 -0
- package/dist-server/server/vault/runtime.js +48 -0
- package/dist-server/server/vault/store.js +177 -0
- package/dist-server/shared/desktop-private-port.js +1 -0
- package/dist-server/shared/engine-choices.js +15 -0
- package/dist-server/shared/engine-tiers.js +74 -2
- package/dist-server/shared/local-models.js +1 -3
- package/dist-server/shared/personal-goal.js +43 -0
- package/dist-server/shared/subscription-bots.js +3 -0
- package/dist-server/shared/vault.js +59 -0
- package/dist-server/vps-container-mcp.js +4 -2
- package/package.json +1 -1
- package/dist/assets/channel-GBaPOaz-.js +0 -1
- package/dist/assets/index-C8YP7Zxj.css +0 -1
- package/dist/assets/swimlanesDiagram-TC7HE7FX-CamSa0NE.js +0 -8
|
@@ -24992,7 +24992,6 @@ function idsFromModelsPayload(payload) {
|
|
|
24992
24992
|
if (typeof id !== "string" || !MODEL_ID.test(id)) return [];
|
|
24993
24993
|
const low = id.toLowerCase();
|
|
24994
24994
|
if (low.includes("embed") || low.includes("bge-") || low.includes("nomic")) return [];
|
|
24995
|
-
if (isOllamaCloudModel(record5)) return [];
|
|
24996
24995
|
return [id];
|
|
24997
24996
|
});
|
|
24998
24997
|
}
|
|
@@ -25099,7 +25098,7 @@ async function probeLocalInjects(env = process.env, fetchImpl = fetch) {
|
|
|
25099
25098
|
id: encodeInjectId(host.id, model),
|
|
25100
25099
|
host: host.id,
|
|
25101
25100
|
model,
|
|
25102
|
-
label: `${model} (${host.label})`,
|
|
25101
|
+
label: isOllamaCloudModel(model) ? `${model} (${host.label}, plan-billed)` : `${model} (${host.label})`,
|
|
25103
25102
|
loaded: loaded.has(model),
|
|
25104
25103
|
...contextWindow ? { contextWindow } : {}
|
|
25105
25104
|
});
|
|
@@ -30445,6 +30444,7 @@ var init_claude = __esm({
|
|
|
30445
30444
|
active.delete(threadId);
|
|
30446
30445
|
session.turn = null;
|
|
30447
30446
|
retryState.delete(threadId);
|
|
30447
|
+
if (t2.authFailed) closeSession(threadId, "sign-in required");
|
|
30448
30448
|
emit({ ...base3(threadId, t2.turnId), type: "turn.completed", ok, stopReason, cost, ...usage ? { usage } : {} });
|
|
30449
30449
|
if (session.child.exitCode === null && !session.closing) armIdle(threadId);
|
|
30450
30450
|
};
|
|
@@ -30634,6 +30634,11 @@ var init_claude = __esm({
|
|
|
30634
30634
|
if (o.origin?.kind === "task-notification") break;
|
|
30635
30635
|
{
|
|
30636
30636
|
const t2 = session.turn;
|
|
30637
|
+
const resultError = [o.result, ...Array.isArray(o.errors) ? o.errors : []].filter((value) => typeof value === "string").join("\n");
|
|
30638
|
+
if (o.is_error === true && !t2?.authFailed && claudeAuthFailure({ error: o.error ?? "api_error" }, resultError)) {
|
|
30639
|
+
if (t2) t2.authFailed = true;
|
|
30640
|
+
emit({ ...base3(threadId, currentTurnId()), type: "runtime.error", message: resultError, setup: true, failure: "auth_failed" });
|
|
30641
|
+
}
|
|
30637
30642
|
const usage = o.usage ? {
|
|
30638
30643
|
input: (o.usage.input_tokens || 0) + (o.usage.cache_read_input_tokens || 0) + (o.usage.cache_creation_input_tokens || 0),
|
|
30639
30644
|
output: o.usage.output_tokens || 0,
|
|
@@ -30641,7 +30646,7 @@ var init_claude = __esm({
|
|
|
30641
30646
|
} : void 0;
|
|
30642
30647
|
const earlier = t2?.carried;
|
|
30643
30648
|
const result = {
|
|
30644
|
-
ok: o.is_error !== true,
|
|
30649
|
+
ok: o.is_error !== true && !t2?.authFailed,
|
|
30645
30650
|
stopReason: t2?.authFailed ? "auth_required" : t2?.refreshConflict && o.is_error === true ? "credential_refresh_conflict" : claudeResultStopReason(o),
|
|
30646
30651
|
cost: sumCost(earlier?.cost ?? null, o.total_cost_usd ?? null),
|
|
30647
30652
|
usage: sumUsage(earlier?.usage, usage)
|
|
@@ -58743,6 +58748,82 @@ var init_browser_engine = __esm({
|
|
|
58743
58748
|
}
|
|
58744
58749
|
});
|
|
58745
58750
|
|
|
58751
|
+
// server/cli-help.ts
|
|
58752
|
+
var USAGE = `chibi \u2014 your team of AI bots, ready in a few steps
|
|
58753
|
+
|
|
58754
|
+
chibi set up once, then open your workspace
|
|
58755
|
+
chibi setup [--data-dir DIR]
|
|
58756
|
+
chibi start [the same options as serve]
|
|
58757
|
+
chibi serve [--port 8799] [--data-dir DIR] [--label NAME]
|
|
58758
|
+
[--public-url https://host] [--tailscale | --tunnel | --domain HOST] [--no-pair]
|
|
58759
|
+
chibi pair [--label NAME] [--client] [--phone ios|android]
|
|
58760
|
+
[--public-url https://host]
|
|
58761
|
+
chibi sessions [revoke ID]
|
|
58762
|
+
chibi status
|
|
58763
|
+
chibi login [--email you@example.com]
|
|
58764
|
+
chibi logout
|
|
58765
|
+
chibi command --bot ID|--group ID --thread ID --text "/goal status" [--port 8799]
|
|
58766
|
+
chibi goal --bot ID --thread ID --text "--tokens 100000 objective"
|
|
58767
|
+
chibi access list | add EMAIL [--chat-only] | remove EMAIL
|
|
58768
|
+
chibi service install [--domain HOST | --tunnel | --tailscale] [--port N] [--data-dir DIR] | uninstall
|
|
58769
|
+
chibi browser install [--with-deps] | status
|
|
58770
|
+
chibi fleet init --domain HOST [--operator USER] | create NAME --admin EMAIL [--member EMAIL] [--brand FILE]
|
|
58771
|
+
[--anthropic-key-file FILE] [--cap USD] [--license-key KEY] [--memory 1G]
|
|
58772
|
+
| list | users NAME add|remove EMAIL [--chat-only] | suspend NAME | resume NAME
|
|
58773
|
+
| delete NAME --yes [--keep-data] | upgrade (all take --dry-run)
|
|
58774
|
+
| agent [--socket PATH] [--group USER] (root; installed by init --operator)
|
|
58775
|
+
|
|
58776
|
+
setup choose AI access and optional phone access; keep existing bots and chats
|
|
58777
|
+
start same as chibi: use your saved settings and open the workspace
|
|
58778
|
+
serve starts the server without prompts and prints a pairing link + QR code
|
|
58779
|
+
pair mints a pairing code against a running server (--client: chat only)
|
|
58780
|
+
sessions lists paired devices; "sessions revoke ID" signs one out
|
|
58781
|
+
status what the server says about itself
|
|
58782
|
+
login signs this machine in to an Atomic account (an emailed code)
|
|
58783
|
+
and reserves its public address for --tunnel
|
|
58784
|
+
logout releases that address and signs out
|
|
58785
|
+
access who may sign in with an emailed code at /pair: an address or
|
|
58786
|
+
@domain; --chat-only gives chat and approvals without settings.
|
|
58787
|
+
Takes effect at once, no restart.
|
|
58788
|
+
service keep the server running across reboots: writes a systemd unit
|
|
58789
|
+
(Linux) or a launchd agent (macOS) for the same serve options and
|
|
58790
|
+
prints the commands that install it. Install the package
|
|
58791
|
+
permanently first (npm install -g @chibitek/chibi).
|
|
58792
|
+
browser install: the bots' browser engine (agent-browser, pinned) into the
|
|
58793
|
+
data dir, and Chrome for Testing into the user's browser cache.
|
|
58794
|
+
--with-deps also installs
|
|
58795
|
+
the Linux libraries Chrome needs (run as root once). Then run
|
|
58796
|
+
browser install as the user running serve, from that user's home.
|
|
58797
|
+
status: what the current user and data directory have.
|
|
58798
|
+
fleet many client workspaces on one Linux server, each its own account,
|
|
58799
|
+
service, data folder, brand, sign-in list and keys at NAME.HOST
|
|
58800
|
+
behind the system Caddy. Plans are printed unless run as root;
|
|
58801
|
+
--dry-run always prints. Install the package permanently first.
|
|
58802
|
+
init --operator USER also installs the fleet agent, a root service
|
|
58803
|
+
on a Unix socket only USER may open, so the workspace running as
|
|
58804
|
+
USER manages the others from Settings \u2192 Workspaces.
|
|
58805
|
+
|
|
58806
|
+
--tailscale serve over your tailnet: Tailscale terminates HTTPS and the
|
|
58807
|
+
link uses this machine's MagicDNS name (needs Tailscale signed in
|
|
58808
|
+
and HTTPS certificates enabled for the tailnet)
|
|
58809
|
+
--tunnel serve at a public HTTPS address through a Cloudflare tunnel
|
|
58810
|
+
from a hosted control plane (set OMB_CONTROL_PLANE_URL; Atomic
|
|
58811
|
+
ships none). Run \`chibi login\` once on this machine first.
|
|
58812
|
+
--domain serve at https://HOST on your own domain: a pinned Caddy is
|
|
58813
|
+
downloaded once and run alongside the server, and gets the
|
|
58814
|
+
certificate itself. Point the domain's DNS at this machine and
|
|
58815
|
+
open ports 80 and 443.
|
|
58816
|
+
|
|
58817
|
+
--no-open do not open a browser window
|
|
58818
|
+
--no-pair skip phone setup and do not print a pairing code
|
|
58819
|
+
--local start locally this time, ignoring saved remote-access settings
|
|
58820
|
+
--quiet skip the welcome banner (it never shows when output is piped;
|
|
58821
|
+
NO_COLOR=1 shows it without color)
|
|
58822
|
+
|
|
58823
|
+
Install once with \`npm install -g @chibitek/chibi\`, then type \`chibi\`.
|
|
58824
|
+
Or run without a global install: \`npx @chibitek/chibi\`. Node 24+ is required.
|
|
58825
|
+
`;
|
|
58826
|
+
|
|
58746
58827
|
// server/cli.ts
|
|
58747
58828
|
var import_qrcode_terminal = __toESM(require_main(), 1);
|
|
58748
58829
|
import { spawn as spawn10 } from "node:child_process";
|
|
@@ -60737,6 +60818,32 @@ function runServiceCommand(input, io2) {
|
|
|
60737
60818
|
return 0;
|
|
60738
60819
|
}
|
|
60739
60820
|
|
|
60821
|
+
// server/port-in-use.ts
|
|
60822
|
+
import { connect } from "node:net";
|
|
60823
|
+
function portInUse(port) {
|
|
60824
|
+
return new Promise((done) => {
|
|
60825
|
+
const socket = connect({ host: "127.0.0.1", port });
|
|
60826
|
+
socket.setTimeout(1e3);
|
|
60827
|
+
socket.once("connect", () => {
|
|
60828
|
+
socket.destroy();
|
|
60829
|
+
done(true);
|
|
60830
|
+
});
|
|
60831
|
+
socket.once("timeout", () => {
|
|
60832
|
+
socket.destroy();
|
|
60833
|
+
done(false);
|
|
60834
|
+
});
|
|
60835
|
+
socket.once("error", () => done(false));
|
|
60836
|
+
});
|
|
60837
|
+
}
|
|
60838
|
+
async function reportBusyPort(port, dataDirFlag) {
|
|
60839
|
+
for (const candidate of [port, Number(process.env.OMB_WEBHOOK_PORT || port + 1)]) {
|
|
60840
|
+
if (!await portInUse(candidate)) continue;
|
|
60841
|
+
console.error(`Port ${candidate} is already in use by another app. Choose a free port, for example: chibi start --port ${port + 20}${dataDirFlag}`);
|
|
60842
|
+
return true;
|
|
60843
|
+
}
|
|
60844
|
+
return false;
|
|
60845
|
+
}
|
|
60846
|
+
|
|
60740
60847
|
// shared/chibi-mark.ts
|
|
60741
60848
|
var CHIBI_GRID = [
|
|
60742
60849
|
"A...............",
|
|
@@ -62433,7 +62540,7 @@ function describeTunnelState(state2, address) {
|
|
|
62433
62540
|
|
|
62434
62541
|
// server/cli.ts
|
|
62435
62542
|
var HERE2 = dirname13(fileURLToPath3(import.meta.url));
|
|
62436
|
-
var COMMANDS = ["setup", "start", "serve", "pair", "sessions", "status", "login", "logout", "access", "service", "browser", "fleet", "help", "--help", "-h"];
|
|
62543
|
+
var COMMANDS = ["command", "goal", "setup", "start", "serve", "pair", "sessions", "status", "login", "logout", "access", "service", "browser", "fleet", "help", "--help", "-h"];
|
|
62437
62544
|
function parseArgs2(argv, env = process.env) {
|
|
62438
62545
|
const implicitStart = !argv.length || argv[0].startsWith("--") && argv[0] !== "--help";
|
|
62439
62546
|
const [command = "start", ...rest] = implicitStart ? ["start", ...argv] : argv;
|
|
@@ -62461,7 +62568,11 @@ function parseArgs2(argv, env = process.env) {
|
|
|
62461
62568
|
return v3;
|
|
62462
62569
|
};
|
|
62463
62570
|
try {
|
|
62464
|
-
if (arg === "--
|
|
62571
|
+
if ((options.command === "command" || options.command === "goal") && arg === "--bot") options.botId = value();
|
|
62572
|
+
else if ((options.command === "command" || options.command === "goal") && arg === "--group") options.groupId = value();
|
|
62573
|
+
else if ((options.command === "command" || options.command === "goal") && arg === "--thread") options.threadId = value();
|
|
62574
|
+
else if ((options.command === "command" || options.command === "goal") && arg === "--text") options.commandText = value();
|
|
62575
|
+
else if (arg === "--port") options.port = Number(value());
|
|
62465
62576
|
else if (arg === "--data-dir") options.dataDir = resolve13(value());
|
|
62466
62577
|
else if (arg === "--label") options.label = value();
|
|
62467
62578
|
else if (arg === "--public-url") options.publicUrl = value().replace(/\/+$/, "");
|
|
@@ -62517,6 +62628,7 @@ function parseArgs2(argv, env = process.env) {
|
|
|
62517
62628
|
if (!Number.isInteger(options.port) || options.port < 1 || options.port > 65535) return { error: "--port must be 1-65535" };
|
|
62518
62629
|
if (options.publicUrl && !/^https?:\/\//.test(options.publicUrl)) return { error: "--public-url must start with http:// or https://" };
|
|
62519
62630
|
if (options.tailscale && options.tunnel) return { error: "choose one of --tailscale (your tailnet) and --tunnel (a public address)" };
|
|
62631
|
+
if ((options.command === "command" || options.command === "goal") && (Boolean(options.botId) === Boolean(options.groupId) || !options.threadId || !options.commandText)) return { error: "command and goal require exactly one of --bot ID or --group ID, plus --thread ID --text TEXT" };
|
|
62520
62632
|
if (options.command === "access" && !options.accessAction) return { error: "access needs one of: list, add EMAIL [--chat-only], remove EMAIL" };
|
|
62521
62633
|
if (options.command === "service" && !options.serviceAction) return { error: "service needs one of: install [the same options as serve], uninstall" };
|
|
62522
62634
|
if (options.domain && (options.tailscale || options.tunnel || options.publicUrl)) return { error: "--domain already gives the server its address; drop --tailscale, --tunnel and --public-url" };
|
|
@@ -62530,78 +62642,6 @@ function parseArgs2(argv, env = process.env) {
|
|
|
62530
62642
|
}
|
|
62531
62643
|
return options;
|
|
62532
62644
|
}
|
|
62533
|
-
var USAGE = `chibi \u2014 your team of AI bots, ready in a few steps
|
|
62534
|
-
|
|
62535
|
-
chibi set up once, then open your workspace
|
|
62536
|
-
chibi setup [--data-dir DIR]
|
|
62537
|
-
chibi start [the same options as serve]
|
|
62538
|
-
chibi serve [--port 8799] [--data-dir DIR] [--label NAME]
|
|
62539
|
-
[--public-url https://host] [--tailscale | --tunnel | --domain HOST] [--no-pair]
|
|
62540
|
-
chibi pair [--label NAME] [--client] [--phone ios|android]
|
|
62541
|
-
[--public-url https://host]
|
|
62542
|
-
chibi sessions [revoke ID]
|
|
62543
|
-
chibi status
|
|
62544
|
-
chibi login [--email you@example.com]
|
|
62545
|
-
chibi logout
|
|
62546
|
-
chibi access list | add EMAIL [--chat-only] | remove EMAIL
|
|
62547
|
-
chibi service install [--domain HOST | --tunnel | --tailscale] [--port N] [--data-dir DIR] | uninstall
|
|
62548
|
-
chibi browser install [--with-deps] | status
|
|
62549
|
-
chibi fleet init --domain HOST [--operator USER] | create NAME --admin EMAIL [--member EMAIL] [--brand FILE]
|
|
62550
|
-
[--anthropic-key-file FILE] [--cap USD] [--license-key KEY] [--memory 1G]
|
|
62551
|
-
| list | users NAME add|remove EMAIL [--chat-only] | suspend NAME | resume NAME
|
|
62552
|
-
| delete NAME --yes [--keep-data] | upgrade (all take --dry-run)
|
|
62553
|
-
| agent [--socket PATH] [--group USER] (root; installed by init --operator)
|
|
62554
|
-
|
|
62555
|
-
setup choose AI access and optional phone access; keep existing bots and chats
|
|
62556
|
-
start same as chibi: use your saved settings and open the workspace
|
|
62557
|
-
serve starts the server without prompts and prints a pairing link + QR code
|
|
62558
|
-
pair mints a pairing code against a running server (--client: chat only)
|
|
62559
|
-
sessions lists paired devices; "sessions revoke ID" signs one out
|
|
62560
|
-
status what the server says about itself
|
|
62561
|
-
login signs this machine in to an Atomic account (an emailed code)
|
|
62562
|
-
and reserves its public address for --tunnel
|
|
62563
|
-
logout releases that address and signs out
|
|
62564
|
-
access who may sign in with an emailed code at /pair: an address or
|
|
62565
|
-
@domain; --chat-only gives chat and approvals without settings.
|
|
62566
|
-
Takes effect at once, no restart.
|
|
62567
|
-
service keep the server running across reboots: writes a systemd unit
|
|
62568
|
-
(Linux) or a launchd agent (macOS) for the same serve options and
|
|
62569
|
-
prints the commands that install it. Install the package
|
|
62570
|
-
permanently first (npm install -g @chibitek/chibi).
|
|
62571
|
-
browser install: the bots' browser engine (agent-browser, pinned) into the
|
|
62572
|
-
data dir, and Chrome for Testing into the user's browser cache.
|
|
62573
|
-
--with-deps also installs
|
|
62574
|
-
the Linux libraries Chrome needs (run as root once). Then run
|
|
62575
|
-
browser install as the user running serve, from that user's home.
|
|
62576
|
-
status: what the current user and data directory have.
|
|
62577
|
-
fleet many client workspaces on one Linux server, each its own account,
|
|
62578
|
-
service, data folder, brand, sign-in list and keys at NAME.HOST
|
|
62579
|
-
behind the system Caddy. Plans are printed unless run as root;
|
|
62580
|
-
--dry-run always prints. Install the package permanently first.
|
|
62581
|
-
init --operator USER also installs the fleet agent, a root service
|
|
62582
|
-
on a Unix socket only USER may open, so the workspace running as
|
|
62583
|
-
USER manages the others from Settings \u2192 Workspaces.
|
|
62584
|
-
|
|
62585
|
-
--tailscale serve over your tailnet: Tailscale terminates HTTPS and the
|
|
62586
|
-
link uses this machine's MagicDNS name (needs Tailscale signed in
|
|
62587
|
-
and HTTPS certificates enabled for the tailnet)
|
|
62588
|
-
--tunnel serve at a public HTTPS address through a Cloudflare tunnel
|
|
62589
|
-
from a hosted control plane (set OMB_CONTROL_PLANE_URL; Atomic
|
|
62590
|
-
ships none). Run \`chibi login\` once on this machine first.
|
|
62591
|
-
--domain serve at https://HOST on your own domain: a pinned Caddy is
|
|
62592
|
-
downloaded once and run alongside the server, and gets the
|
|
62593
|
-
certificate itself. Point the domain's DNS at this machine and
|
|
62594
|
-
open ports 80 and 443.
|
|
62595
|
-
|
|
62596
|
-
--no-open do not open a browser window
|
|
62597
|
-
--no-pair skip phone setup and do not print a pairing code
|
|
62598
|
-
--local start locally this time, ignoring saved remote-access settings
|
|
62599
|
-
--quiet skip the welcome banner (it never shows when output is piped;
|
|
62600
|
-
NO_COLOR=1 shows it without color)
|
|
62601
|
-
|
|
62602
|
-
Install once with \`npm install -g @chibitek/chibi\`, then type \`chibi\`.
|
|
62603
|
-
Or run without a global install: \`npx @chibitek/chibi\`. Node 24+ is required.
|
|
62604
|
-
`;
|
|
62605
62645
|
function defaultIo() {
|
|
62606
62646
|
return {
|
|
62607
62647
|
log: (line) => console.log(line),
|
|
@@ -63106,6 +63146,7 @@ async function runServe(options, log = console.log) {
|
|
|
63106
63146
|
console.error(`something already answers on http://127.0.0.1:${options.port}; use \`chibi pair\` against it, or --port for a second server`);
|
|
63107
63147
|
return 1;
|
|
63108
63148
|
}
|
|
63149
|
+
if (await reportBusyPort(options.port, options.dataDir === join53(homedir29(), ".atomic-app") ? "" : ` --data-dir ${options.dataDir}`)) return 1;
|
|
63109
63150
|
let publicUrl = options.publicUrl;
|
|
63110
63151
|
let tailscale = null;
|
|
63111
63152
|
if (options.tailscale) {
|
|
@@ -63373,10 +63414,9 @@ async function runOnboardingCommand(options, io2 = defaultIo(), startServer = ru
|
|
|
63373
63414
|
saveCliStartup2(options.dataDir, startupPreferences(launch));
|
|
63374
63415
|
}
|
|
63375
63416
|
if (options.command === "setup") {
|
|
63376
|
-
|
|
63377
|
-
|
|
63378
|
-
|
|
63379
|
-
}
|
|
63417
|
+
const flags = [options.dataDir !== join53(homedir29(), ".atomic-app") && ` --data-dir ${options.dataDir}`, options.port !== 8799 && ` --port ${options.port}`].filter(Boolean).join("");
|
|
63418
|
+
io2.log(`
|
|
63419
|
+
All set. Start with: chibi${flags ? ` start${flags}` : ""} (or npx @chibitek/chibi without a global install).`);
|
|
63380
63420
|
return 0;
|
|
63381
63421
|
}
|
|
63382
63422
|
if (saved) io2.log("\nWelcome back. Using your saved AI connection.");
|
|
@@ -63412,6 +63452,25 @@ ${welcomeBanner(options)}
|
|
|
63412
63452
|
`);
|
|
63413
63453
|
}
|
|
63414
63454
|
switch (options.command) {
|
|
63455
|
+
case "command":
|
|
63456
|
+
case "goal": {
|
|
63457
|
+
const text4 = options.command === "goal" ? `/goal ${options.commandText}` : options.commandText;
|
|
63458
|
+
const roomGoal = options.groupId ? /^\/goal(?:\s+([\s\S]*))?$/.exec(text4 ?? "") : null;
|
|
63459
|
+
if (roomGoal && (!roomGoal[1]?.trim() || (roomGoal[1].startsWith("--") || /^(status|pause|resume|stop|help)(?:\s|$)/.test(roomGoal[1])))) {
|
|
63460
|
+
console.error("Room goals accept an objective. Personal goal controls and budgets require --bot.");
|
|
63461
|
+
return 2;
|
|
63462
|
+
}
|
|
63463
|
+
const result = await api(options.port, `/api/${options.groupId ? "groups" : "bots"}/${encodeURIComponent(options.groupId ?? options.botId)}/messages`, {
|
|
63464
|
+
method: "POST",
|
|
63465
|
+
body: JSON.stringify({ threadId: options.threadId, text: roomGoal ? roomGoal[1] : text4, ...roomGoal ? { mode: "goal" } : {}, sendId: randomBytes4(16).toString("hex") })
|
|
63466
|
+
});
|
|
63467
|
+
if (result.status >= 400) {
|
|
63468
|
+
console.error(result.body.error ?? `Server returned ${result.status}`);
|
|
63469
|
+
return 1;
|
|
63470
|
+
}
|
|
63471
|
+
console.log(options.json ? JSON.stringify(result.body) : result.body.goalSummary ?? JSON.stringify(result.body));
|
|
63472
|
+
return 0;
|
|
63473
|
+
}
|
|
63415
63474
|
case "setup":
|
|
63416
63475
|
case "start":
|
|
63417
63476
|
return runOnboardingCommand(options);
|
package/dist-server/pair-cli.js
CHANGED
|
@@ -24992,7 +24992,6 @@ function idsFromModelsPayload(payload) {
|
|
|
24992
24992
|
if (typeof id !== "string" || !MODEL_ID.test(id)) return [];
|
|
24993
24993
|
const low = id.toLowerCase();
|
|
24994
24994
|
if (low.includes("embed") || low.includes("bge-") || low.includes("nomic")) return [];
|
|
24995
|
-
if (isOllamaCloudModel(record5)) return [];
|
|
24996
24995
|
return [id];
|
|
24997
24996
|
});
|
|
24998
24997
|
}
|
|
@@ -25099,7 +25098,7 @@ async function probeLocalInjects(env = process.env, fetchImpl = fetch) {
|
|
|
25099
25098
|
id: encodeInjectId(host.id, model),
|
|
25100
25099
|
host: host.id,
|
|
25101
25100
|
model,
|
|
25102
|
-
label: `${model} (${host.label})`,
|
|
25101
|
+
label: isOllamaCloudModel(model) ? `${model} (${host.label}, plan-billed)` : `${model} (${host.label})`,
|
|
25103
25102
|
loaded: loaded.has(model),
|
|
25104
25103
|
...contextWindow ? { contextWindow } : {}
|
|
25105
25104
|
});
|
|
@@ -30445,6 +30444,7 @@ var init_claude = __esm({
|
|
|
30445
30444
|
active.delete(threadId);
|
|
30446
30445
|
session.turn = null;
|
|
30447
30446
|
retryState.delete(threadId);
|
|
30447
|
+
if (t2.authFailed) closeSession(threadId, "sign-in required");
|
|
30448
30448
|
emit({ ...base3(threadId, t2.turnId), type: "turn.completed", ok, stopReason, cost, ...usage ? { usage } : {} });
|
|
30449
30449
|
if (session.child.exitCode === null && !session.closing) armIdle(threadId);
|
|
30450
30450
|
};
|
|
@@ -30634,6 +30634,11 @@ var init_claude = __esm({
|
|
|
30634
30634
|
if (o.origin?.kind === "task-notification") break;
|
|
30635
30635
|
{
|
|
30636
30636
|
const t2 = session.turn;
|
|
30637
|
+
const resultError = [o.result, ...Array.isArray(o.errors) ? o.errors : []].filter((value) => typeof value === "string").join("\n");
|
|
30638
|
+
if (o.is_error === true && !t2?.authFailed && claudeAuthFailure({ error: o.error ?? "api_error" }, resultError)) {
|
|
30639
|
+
if (t2) t2.authFailed = true;
|
|
30640
|
+
emit({ ...base3(threadId, currentTurnId()), type: "runtime.error", message: resultError, setup: true, failure: "auth_failed" });
|
|
30641
|
+
}
|
|
30637
30642
|
const usage = o.usage ? {
|
|
30638
30643
|
input: (o.usage.input_tokens || 0) + (o.usage.cache_read_input_tokens || 0) + (o.usage.cache_creation_input_tokens || 0),
|
|
30639
30644
|
output: o.usage.output_tokens || 0,
|
|
@@ -30641,7 +30646,7 @@ var init_claude = __esm({
|
|
|
30641
30646
|
} : void 0;
|
|
30642
30647
|
const earlier = t2?.carried;
|
|
30643
30648
|
const result = {
|
|
30644
|
-
ok: o.is_error !== true,
|
|
30649
|
+
ok: o.is_error !== true && !t2?.authFailed,
|
|
30645
30650
|
stopReason: t2?.authFailed ? "auth_required" : t2?.refreshConflict && o.is_error === true ? "credential_refresh_conflict" : claudeResultStopReason(o),
|
|
30646
30651
|
cost: sumCost(earlier?.cost ?? null, o.total_cost_usd ?? null),
|
|
30647
30652
|
usage: sumUsage(earlier?.usage, usage)
|
|
@@ -58743,6 +58748,82 @@ var init_browser_engine = __esm({
|
|
|
58743
58748
|
}
|
|
58744
58749
|
});
|
|
58745
58750
|
|
|
58751
|
+
// server/cli-help.ts
|
|
58752
|
+
var USAGE = `chibi \u2014 your team of AI bots, ready in a few steps
|
|
58753
|
+
|
|
58754
|
+
chibi set up once, then open your workspace
|
|
58755
|
+
chibi setup [--data-dir DIR]
|
|
58756
|
+
chibi start [the same options as serve]
|
|
58757
|
+
chibi serve [--port 8799] [--data-dir DIR] [--label NAME]
|
|
58758
|
+
[--public-url https://host] [--tailscale | --tunnel | --domain HOST] [--no-pair]
|
|
58759
|
+
chibi pair [--label NAME] [--client] [--phone ios|android]
|
|
58760
|
+
[--public-url https://host]
|
|
58761
|
+
chibi sessions [revoke ID]
|
|
58762
|
+
chibi status
|
|
58763
|
+
chibi login [--email you@example.com]
|
|
58764
|
+
chibi logout
|
|
58765
|
+
chibi command --bot ID|--group ID --thread ID --text "/goal status" [--port 8799]
|
|
58766
|
+
chibi goal --bot ID --thread ID --text "--tokens 100000 objective"
|
|
58767
|
+
chibi access list | add EMAIL [--chat-only] | remove EMAIL
|
|
58768
|
+
chibi service install [--domain HOST | --tunnel | --tailscale] [--port N] [--data-dir DIR] | uninstall
|
|
58769
|
+
chibi browser install [--with-deps] | status
|
|
58770
|
+
chibi fleet init --domain HOST [--operator USER] | create NAME --admin EMAIL [--member EMAIL] [--brand FILE]
|
|
58771
|
+
[--anthropic-key-file FILE] [--cap USD] [--license-key KEY] [--memory 1G]
|
|
58772
|
+
| list | users NAME add|remove EMAIL [--chat-only] | suspend NAME | resume NAME
|
|
58773
|
+
| delete NAME --yes [--keep-data] | upgrade (all take --dry-run)
|
|
58774
|
+
| agent [--socket PATH] [--group USER] (root; installed by init --operator)
|
|
58775
|
+
|
|
58776
|
+
setup choose AI access and optional phone access; keep existing bots and chats
|
|
58777
|
+
start same as chibi: use your saved settings and open the workspace
|
|
58778
|
+
serve starts the server without prompts and prints a pairing link + QR code
|
|
58779
|
+
pair mints a pairing code against a running server (--client: chat only)
|
|
58780
|
+
sessions lists paired devices; "sessions revoke ID" signs one out
|
|
58781
|
+
status what the server says about itself
|
|
58782
|
+
login signs this machine in to an Atomic account (an emailed code)
|
|
58783
|
+
and reserves its public address for --tunnel
|
|
58784
|
+
logout releases that address and signs out
|
|
58785
|
+
access who may sign in with an emailed code at /pair: an address or
|
|
58786
|
+
@domain; --chat-only gives chat and approvals without settings.
|
|
58787
|
+
Takes effect at once, no restart.
|
|
58788
|
+
service keep the server running across reboots: writes a systemd unit
|
|
58789
|
+
(Linux) or a launchd agent (macOS) for the same serve options and
|
|
58790
|
+
prints the commands that install it. Install the package
|
|
58791
|
+
permanently first (npm install -g @chibitek/chibi).
|
|
58792
|
+
browser install: the bots' browser engine (agent-browser, pinned) into the
|
|
58793
|
+
data dir, and Chrome for Testing into the user's browser cache.
|
|
58794
|
+
--with-deps also installs
|
|
58795
|
+
the Linux libraries Chrome needs (run as root once). Then run
|
|
58796
|
+
browser install as the user running serve, from that user's home.
|
|
58797
|
+
status: what the current user and data directory have.
|
|
58798
|
+
fleet many client workspaces on one Linux server, each its own account,
|
|
58799
|
+
service, data folder, brand, sign-in list and keys at NAME.HOST
|
|
58800
|
+
behind the system Caddy. Plans are printed unless run as root;
|
|
58801
|
+
--dry-run always prints. Install the package permanently first.
|
|
58802
|
+
init --operator USER also installs the fleet agent, a root service
|
|
58803
|
+
on a Unix socket only USER may open, so the workspace running as
|
|
58804
|
+
USER manages the others from Settings \u2192 Workspaces.
|
|
58805
|
+
|
|
58806
|
+
--tailscale serve over your tailnet: Tailscale terminates HTTPS and the
|
|
58807
|
+
link uses this machine's MagicDNS name (needs Tailscale signed in
|
|
58808
|
+
and HTTPS certificates enabled for the tailnet)
|
|
58809
|
+
--tunnel serve at a public HTTPS address through a Cloudflare tunnel
|
|
58810
|
+
from a hosted control plane (set OMB_CONTROL_PLANE_URL; Atomic
|
|
58811
|
+
ships none). Run \`chibi login\` once on this machine first.
|
|
58812
|
+
--domain serve at https://HOST on your own domain: a pinned Caddy is
|
|
58813
|
+
downloaded once and run alongside the server, and gets the
|
|
58814
|
+
certificate itself. Point the domain's DNS at this machine and
|
|
58815
|
+
open ports 80 and 443.
|
|
58816
|
+
|
|
58817
|
+
--no-open do not open a browser window
|
|
58818
|
+
--no-pair skip phone setup and do not print a pairing code
|
|
58819
|
+
--local start locally this time, ignoring saved remote-access settings
|
|
58820
|
+
--quiet skip the welcome banner (it never shows when output is piped;
|
|
58821
|
+
NO_COLOR=1 shows it without color)
|
|
58822
|
+
|
|
58823
|
+
Install once with \`npm install -g @chibitek/chibi\`, then type \`chibi\`.
|
|
58824
|
+
Or run without a global install: \`npx @chibitek/chibi\`. Node 24+ is required.
|
|
58825
|
+
`;
|
|
58826
|
+
|
|
58746
58827
|
// server/cli.ts
|
|
58747
58828
|
var import_qrcode_terminal = __toESM(require_main(), 1);
|
|
58748
58829
|
import { spawn as spawn10 } from "node:child_process";
|
|
@@ -60737,6 +60818,32 @@ function runServiceCommand(input, io2) {
|
|
|
60737
60818
|
return 0;
|
|
60738
60819
|
}
|
|
60739
60820
|
|
|
60821
|
+
// server/port-in-use.ts
|
|
60822
|
+
import { connect } from "node:net";
|
|
60823
|
+
function portInUse(port) {
|
|
60824
|
+
return new Promise((done) => {
|
|
60825
|
+
const socket = connect({ host: "127.0.0.1", port });
|
|
60826
|
+
socket.setTimeout(1e3);
|
|
60827
|
+
socket.once("connect", () => {
|
|
60828
|
+
socket.destroy();
|
|
60829
|
+
done(true);
|
|
60830
|
+
});
|
|
60831
|
+
socket.once("timeout", () => {
|
|
60832
|
+
socket.destroy();
|
|
60833
|
+
done(false);
|
|
60834
|
+
});
|
|
60835
|
+
socket.once("error", () => done(false));
|
|
60836
|
+
});
|
|
60837
|
+
}
|
|
60838
|
+
async function reportBusyPort(port, dataDirFlag) {
|
|
60839
|
+
for (const candidate of [port, Number(process.env.OMB_WEBHOOK_PORT || port + 1)]) {
|
|
60840
|
+
if (!await portInUse(candidate)) continue;
|
|
60841
|
+
console.error(`Port ${candidate} is already in use by another app. Choose a free port, for example: chibi start --port ${port + 20}${dataDirFlag}`);
|
|
60842
|
+
return true;
|
|
60843
|
+
}
|
|
60844
|
+
return false;
|
|
60845
|
+
}
|
|
60846
|
+
|
|
60740
60847
|
// shared/chibi-mark.ts
|
|
60741
60848
|
var CHIBI_GRID = [
|
|
60742
60849
|
"A...............",
|
|
@@ -62433,7 +62540,7 @@ function describeTunnelState(state2, address) {
|
|
|
62433
62540
|
|
|
62434
62541
|
// server/cli.ts
|
|
62435
62542
|
var HERE2 = dirname13(fileURLToPath3(import.meta.url));
|
|
62436
|
-
var COMMANDS = ["setup", "start", "serve", "pair", "sessions", "status", "login", "logout", "access", "service", "browser", "fleet", "help", "--help", "-h"];
|
|
62543
|
+
var COMMANDS = ["command", "goal", "setup", "start", "serve", "pair", "sessions", "status", "login", "logout", "access", "service", "browser", "fleet", "help", "--help", "-h"];
|
|
62437
62544
|
function parseArgs2(argv, env = process.env) {
|
|
62438
62545
|
const implicitStart = !argv.length || argv[0].startsWith("--") && argv[0] !== "--help";
|
|
62439
62546
|
const [command = "start", ...rest] = implicitStart ? ["start", ...argv] : argv;
|
|
@@ -62461,7 +62568,11 @@ function parseArgs2(argv, env = process.env) {
|
|
|
62461
62568
|
return v3;
|
|
62462
62569
|
};
|
|
62463
62570
|
try {
|
|
62464
|
-
if (arg === "--
|
|
62571
|
+
if ((options.command === "command" || options.command === "goal") && arg === "--bot") options.botId = value();
|
|
62572
|
+
else if ((options.command === "command" || options.command === "goal") && arg === "--group") options.groupId = value();
|
|
62573
|
+
else if ((options.command === "command" || options.command === "goal") && arg === "--thread") options.threadId = value();
|
|
62574
|
+
else if ((options.command === "command" || options.command === "goal") && arg === "--text") options.commandText = value();
|
|
62575
|
+
else if (arg === "--port") options.port = Number(value());
|
|
62465
62576
|
else if (arg === "--data-dir") options.dataDir = resolve13(value());
|
|
62466
62577
|
else if (arg === "--label") options.label = value();
|
|
62467
62578
|
else if (arg === "--public-url") options.publicUrl = value().replace(/\/+$/, "");
|
|
@@ -62517,6 +62628,7 @@ function parseArgs2(argv, env = process.env) {
|
|
|
62517
62628
|
if (!Number.isInteger(options.port) || options.port < 1 || options.port > 65535) return { error: "--port must be 1-65535" };
|
|
62518
62629
|
if (options.publicUrl && !/^https?:\/\//.test(options.publicUrl)) return { error: "--public-url must start with http:// or https://" };
|
|
62519
62630
|
if (options.tailscale && options.tunnel) return { error: "choose one of --tailscale (your tailnet) and --tunnel (a public address)" };
|
|
62631
|
+
if ((options.command === "command" || options.command === "goal") && (Boolean(options.botId) === Boolean(options.groupId) || !options.threadId || !options.commandText)) return { error: "command and goal require exactly one of --bot ID or --group ID, plus --thread ID --text TEXT" };
|
|
62520
62632
|
if (options.command === "access" && !options.accessAction) return { error: "access needs one of: list, add EMAIL [--chat-only], remove EMAIL" };
|
|
62521
62633
|
if (options.command === "service" && !options.serviceAction) return { error: "service needs one of: install [the same options as serve], uninstall" };
|
|
62522
62634
|
if (options.domain && (options.tailscale || options.tunnel || options.publicUrl)) return { error: "--domain already gives the server its address; drop --tailscale, --tunnel and --public-url" };
|
|
@@ -62530,78 +62642,6 @@ function parseArgs2(argv, env = process.env) {
|
|
|
62530
62642
|
}
|
|
62531
62643
|
return options;
|
|
62532
62644
|
}
|
|
62533
|
-
var USAGE = `chibi \u2014 your team of AI bots, ready in a few steps
|
|
62534
|
-
|
|
62535
|
-
chibi set up once, then open your workspace
|
|
62536
|
-
chibi setup [--data-dir DIR]
|
|
62537
|
-
chibi start [the same options as serve]
|
|
62538
|
-
chibi serve [--port 8799] [--data-dir DIR] [--label NAME]
|
|
62539
|
-
[--public-url https://host] [--tailscale | --tunnel | --domain HOST] [--no-pair]
|
|
62540
|
-
chibi pair [--label NAME] [--client] [--phone ios|android]
|
|
62541
|
-
[--public-url https://host]
|
|
62542
|
-
chibi sessions [revoke ID]
|
|
62543
|
-
chibi status
|
|
62544
|
-
chibi login [--email you@example.com]
|
|
62545
|
-
chibi logout
|
|
62546
|
-
chibi access list | add EMAIL [--chat-only] | remove EMAIL
|
|
62547
|
-
chibi service install [--domain HOST | --tunnel | --tailscale] [--port N] [--data-dir DIR] | uninstall
|
|
62548
|
-
chibi browser install [--with-deps] | status
|
|
62549
|
-
chibi fleet init --domain HOST [--operator USER] | create NAME --admin EMAIL [--member EMAIL] [--brand FILE]
|
|
62550
|
-
[--anthropic-key-file FILE] [--cap USD] [--license-key KEY] [--memory 1G]
|
|
62551
|
-
| list | users NAME add|remove EMAIL [--chat-only] | suspend NAME | resume NAME
|
|
62552
|
-
| delete NAME --yes [--keep-data] | upgrade (all take --dry-run)
|
|
62553
|
-
| agent [--socket PATH] [--group USER] (root; installed by init --operator)
|
|
62554
|
-
|
|
62555
|
-
setup choose AI access and optional phone access; keep existing bots and chats
|
|
62556
|
-
start same as chibi: use your saved settings and open the workspace
|
|
62557
|
-
serve starts the server without prompts and prints a pairing link + QR code
|
|
62558
|
-
pair mints a pairing code against a running server (--client: chat only)
|
|
62559
|
-
sessions lists paired devices; "sessions revoke ID" signs one out
|
|
62560
|
-
status what the server says about itself
|
|
62561
|
-
login signs this machine in to an Atomic account (an emailed code)
|
|
62562
|
-
and reserves its public address for --tunnel
|
|
62563
|
-
logout releases that address and signs out
|
|
62564
|
-
access who may sign in with an emailed code at /pair: an address or
|
|
62565
|
-
@domain; --chat-only gives chat and approvals without settings.
|
|
62566
|
-
Takes effect at once, no restart.
|
|
62567
|
-
service keep the server running across reboots: writes a systemd unit
|
|
62568
|
-
(Linux) or a launchd agent (macOS) for the same serve options and
|
|
62569
|
-
prints the commands that install it. Install the package
|
|
62570
|
-
permanently first (npm install -g @chibitek/chibi).
|
|
62571
|
-
browser install: the bots' browser engine (agent-browser, pinned) into the
|
|
62572
|
-
data dir, and Chrome for Testing into the user's browser cache.
|
|
62573
|
-
--with-deps also installs
|
|
62574
|
-
the Linux libraries Chrome needs (run as root once). Then run
|
|
62575
|
-
browser install as the user running serve, from that user's home.
|
|
62576
|
-
status: what the current user and data directory have.
|
|
62577
|
-
fleet many client workspaces on one Linux server, each its own account,
|
|
62578
|
-
service, data folder, brand, sign-in list and keys at NAME.HOST
|
|
62579
|
-
behind the system Caddy. Plans are printed unless run as root;
|
|
62580
|
-
--dry-run always prints. Install the package permanently first.
|
|
62581
|
-
init --operator USER also installs the fleet agent, a root service
|
|
62582
|
-
on a Unix socket only USER may open, so the workspace running as
|
|
62583
|
-
USER manages the others from Settings \u2192 Workspaces.
|
|
62584
|
-
|
|
62585
|
-
--tailscale serve over your tailnet: Tailscale terminates HTTPS and the
|
|
62586
|
-
link uses this machine's MagicDNS name (needs Tailscale signed in
|
|
62587
|
-
and HTTPS certificates enabled for the tailnet)
|
|
62588
|
-
--tunnel serve at a public HTTPS address through a Cloudflare tunnel
|
|
62589
|
-
from a hosted control plane (set OMB_CONTROL_PLANE_URL; Atomic
|
|
62590
|
-
ships none). Run \`chibi login\` once on this machine first.
|
|
62591
|
-
--domain serve at https://HOST on your own domain: a pinned Caddy is
|
|
62592
|
-
downloaded once and run alongside the server, and gets the
|
|
62593
|
-
certificate itself. Point the domain's DNS at this machine and
|
|
62594
|
-
open ports 80 and 443.
|
|
62595
|
-
|
|
62596
|
-
--no-open do not open a browser window
|
|
62597
|
-
--no-pair skip phone setup and do not print a pairing code
|
|
62598
|
-
--local start locally this time, ignoring saved remote-access settings
|
|
62599
|
-
--quiet skip the welcome banner (it never shows when output is piped;
|
|
62600
|
-
NO_COLOR=1 shows it without color)
|
|
62601
|
-
|
|
62602
|
-
Install once with \`npm install -g @chibitek/chibi\`, then type \`chibi\`.
|
|
62603
|
-
Or run without a global install: \`npx @chibitek/chibi\`. Node 24+ is required.
|
|
62604
|
-
`;
|
|
62605
62645
|
function defaultIo() {
|
|
62606
62646
|
return {
|
|
62607
62647
|
log: (line) => console.log(line),
|
|
@@ -63106,6 +63146,7 @@ async function runServe(options, log = console.log) {
|
|
|
63106
63146
|
console.error(`something already answers on http://127.0.0.1:${options.port}; use \`chibi pair\` against it, or --port for a second server`);
|
|
63107
63147
|
return 1;
|
|
63108
63148
|
}
|
|
63149
|
+
if (await reportBusyPort(options.port, options.dataDir === join53(homedir29(), ".atomic-app") ? "" : ` --data-dir ${options.dataDir}`)) return 1;
|
|
63109
63150
|
let publicUrl = options.publicUrl;
|
|
63110
63151
|
let tailscale = null;
|
|
63111
63152
|
if (options.tailscale) {
|
|
@@ -63373,10 +63414,9 @@ async function runOnboardingCommand(options, io2 = defaultIo(), startServer = ru
|
|
|
63373
63414
|
saveCliStartup2(options.dataDir, startupPreferences(launch));
|
|
63374
63415
|
}
|
|
63375
63416
|
if (options.command === "setup") {
|
|
63376
|
-
|
|
63377
|
-
|
|
63378
|
-
|
|
63379
|
-
}
|
|
63417
|
+
const flags = [options.dataDir !== join53(homedir29(), ".atomic-app") && ` --data-dir ${options.dataDir}`, options.port !== 8799 && ` --port ${options.port}`].filter(Boolean).join("");
|
|
63418
|
+
io2.log(`
|
|
63419
|
+
All set. Start with: chibi${flags ? ` start${flags}` : ""} (or npx @chibitek/chibi without a global install).`);
|
|
63380
63420
|
return 0;
|
|
63381
63421
|
}
|
|
63382
63422
|
if (saved) io2.log("\nWelcome back. Using your saved AI connection.");
|
|
@@ -63412,6 +63452,25 @@ ${welcomeBanner(options)}
|
|
|
63412
63452
|
`);
|
|
63413
63453
|
}
|
|
63414
63454
|
switch (options.command) {
|
|
63455
|
+
case "command":
|
|
63456
|
+
case "goal": {
|
|
63457
|
+
const text4 = options.command === "goal" ? `/goal ${options.commandText}` : options.commandText;
|
|
63458
|
+
const roomGoal = options.groupId ? /^\/goal(?:\s+([\s\S]*))?$/.exec(text4 ?? "") : null;
|
|
63459
|
+
if (roomGoal && (!roomGoal[1]?.trim() || (roomGoal[1].startsWith("--") || /^(status|pause|resume|stop|help)(?:\s|$)/.test(roomGoal[1])))) {
|
|
63460
|
+
console.error("Room goals accept an objective. Personal goal controls and budgets require --bot.");
|
|
63461
|
+
return 2;
|
|
63462
|
+
}
|
|
63463
|
+
const result = await api(options.port, `/api/${options.groupId ? "groups" : "bots"}/${encodeURIComponent(options.groupId ?? options.botId)}/messages`, {
|
|
63464
|
+
method: "POST",
|
|
63465
|
+
body: JSON.stringify({ threadId: options.threadId, text: roomGoal ? roomGoal[1] : text4, ...roomGoal ? { mode: "goal" } : {}, sendId: randomBytes4(16).toString("hex") })
|
|
63466
|
+
});
|
|
63467
|
+
if (result.status >= 400) {
|
|
63468
|
+
console.error(result.body.error ?? `Server returned ${result.status}`);
|
|
63469
|
+
return 1;
|
|
63470
|
+
}
|
|
63471
|
+
console.log(options.json ? JSON.stringify(result.body) : result.body.goalSummary ?? JSON.stringify(result.body));
|
|
63472
|
+
return 0;
|
|
63473
|
+
}
|
|
63415
63474
|
case "setup":
|
|
63416
63475
|
case "start":
|
|
63417
63476
|
return runOnboardingCommand(options);
|