@astra-cli/cli 1.2.0 → 1.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/astra.js +96 -8
  2. package/package.json +1 -1
package/dist/astra.js CHANGED
@@ -139,6 +139,9 @@ function pluginManifestPath(pluginName) {
139
139
  function pluginSkillPath(pluginName) {
140
140
  return path.join(pluginDir(pluginName), "skill.md");
141
141
  }
142
+ function pluginMapPath(pluginName) {
143
+ return path.join(pluginDir(pluginName), "plugin-map.json");
144
+ }
142
145
  function ensureDir(dirPath) {
143
146
  if (!fs.existsSync(dirPath)) {
144
147
  fs.mkdirSync(dirPath, { recursive: true });
@@ -967,12 +970,15 @@ var FETCH_TIMEOUT_MS = 3e4;
967
970
  var FETCH_TIMEOUT_RETRY_MS = 15e3;
968
971
  async function apiCall(method, path7, body, agentName, retryOpts) {
969
972
  const config = loadConfig();
970
- const baseUrl = config?.apiBase ?? "https://agents.astranova.live";
971
973
  const headers = {
972
974
  "Content-Type": "application/json"
973
975
  };
976
+ let baseUrl = config?.apiBase ?? "https://agents.astranova.live";
974
977
  if (agentName) {
975
978
  const creds = loadCredentials(agentName);
979
+ if (creds?.api_base) {
980
+ baseUrl = creds.api_base;
981
+ }
976
982
  if (creds?.api_key) {
977
983
  headers["Authorization"] = `Bearer ${creds.api_key}`;
978
984
  }
@@ -4192,10 +4198,48 @@ function writeFileSecure2(filePath, data) {
4192
4198
  fs10.writeFileSync(tmpPath, data, { encoding: "utf-8", mode: 384 });
4193
4199
  fs10.renameSync(tmpPath, filePath);
4194
4200
  }
4195
- function savePluginToDisk(manifest, skillMdContent) {
4201
+ function buildPluginMap(pluginName, manifest, sections) {
4202
+ const map = { version: 1, pluginName };
4203
+ const statusSection = sections["STATUS"];
4204
+ if (statusSection) {
4205
+ const poll = typeof statusSection.poll === "string" ? statusSection.poll.trim() : null;
4206
+ const rawFields = Array.isArray(statusSection.fields) ? statusSection.fields : [];
4207
+ const fields = rawFields.flatMap((raw) => {
4208
+ const parts = raw.split("|").map((s) => s.trim());
4209
+ if (parts.length === 3) return [{ path: parts[0], label: parts[1], color: parts[2] }];
4210
+ return [];
4211
+ });
4212
+ const pollAllowed = poll && manifest.allowedPaths.some((ap) => poll.startsWith(ap));
4213
+ if (poll && pollAllowed && fields.length > 0) {
4214
+ map.status = { poll, fields };
4215
+ }
4216
+ }
4217
+ const cmdSection = sections["COMMANDS"];
4218
+ if (cmdSection) {
4219
+ const rawCmds = Array.isArray(cmdSection.commands) ? cmdSection.commands : [];
4220
+ map.commands = rawCmds.flatMap((raw) => {
4221
+ const match = raw.match(/^(\S+)\s{2,}(.+)$/);
4222
+ if (match) return [{ command: match[1], description: match[2].trim() }];
4223
+ return [];
4224
+ });
4225
+ }
4226
+ return map;
4227
+ }
4228
+ function loadPluginMap(pluginName) {
4229
+ const p = pluginMapPath(pluginName);
4230
+ if (!fs10.existsSync(p)) return null;
4231
+ try {
4232
+ return JSON.parse(fs10.readFileSync(p, "utf-8"));
4233
+ } catch {
4234
+ return null;
4235
+ }
4236
+ }
4237
+ function savePluginToDisk(manifest, skillMdContent, sections) {
4196
4238
  ensureDir(pluginDir(manifest.name));
4197
4239
  writeFileSecure2(pluginManifestPath(manifest.name), JSON.stringify(manifest, null, 2));
4198
4240
  writeFileSecure2(pluginSkillPath(manifest.name), skillMdContent);
4241
+ const pluginMap = buildPluginMap(manifest.name, manifest, sections);
4242
+ writeFileSecure2(pluginMapPath(manifest.name), JSON.stringify(pluginMap, null, 2));
4199
4243
  }
4200
4244
  async function addPlugin(manifestUrl) {
4201
4245
  clack5.intro(" astra add ");
@@ -4286,7 +4330,7 @@ async function addPlugin(manifestUrl) {
4286
4330
  }
4287
4331
  const manifestWithSkillUrl = { ...manifest, skillUrl: urlResult.url.toString() };
4288
4332
  try {
4289
- savePluginToDisk(manifestWithSkillUrl, skillMdContent);
4333
+ savePluginToDisk(manifestWithSkillUrl, skillMdContent, sections);
4290
4334
  } catch (err) {
4291
4335
  clack5.log.error(
4292
4336
  `Failed to save plugin: ${err instanceof Error ? err.message : String(err)}`
@@ -4384,11 +4428,29 @@ var StatusBar = React.memo(function StatusBar2({
4384
4428
  journeyStage,
4385
4429
  autopilotMode = "off",
4386
4430
  autopilotIntervalMs = 3e5,
4387
- onEpochChange
4431
+ onEpochChange,
4432
+ pluginMap
4388
4433
  }) {
4389
4434
  const [data, setData] = useState({ market: null, portfolio: null });
4390
4435
  const mounted = useRef(true);
4391
4436
  const canFetchData = isAstraNova && journeyStage !== "fresh" && journeyStage !== "pending";
4437
+ const [pluginData, setPluginData] = useState(null);
4438
+ const mountedPlugin = useRef(true);
4439
+ useEffect(() => {
4440
+ if (isAstraNova || !pluginMap?.status) return;
4441
+ mountedPlugin.current = true;
4442
+ const fetchPlugin = async () => {
4443
+ const result = await apiCall("GET", pluginMap.status.poll, void 0, agentName);
4444
+ if (!result.ok || !mountedPlugin.current) return;
4445
+ setPluginData(result.data);
4446
+ };
4447
+ void fetchPlugin();
4448
+ const interval = setInterval(() => void fetchPlugin(), POLL_INTERVAL_MS);
4449
+ return () => {
4450
+ mountedPlugin.current = false;
4451
+ clearInterval(interval);
4452
+ };
4453
+ }, [isAstraNova, pluginMap, agentName]);
4392
4454
  const poll = useCallback(async () => {
4393
4455
  const [marketRes, portfolioRes] = await Promise.all([
4394
4456
  fetchMarket(agentName),
@@ -4420,6 +4482,22 @@ var StatusBar = React.memo(function StatusBar2({
4420
4482
  /* @__PURE__ */ jsx(Text, { bold: true, color: "#00ff00", children: pluginName }),
4421
4483
  /* @__PURE__ */ jsx(Text, { dimColor: true, children: " \u2502 " }),
4422
4484
  /* @__PURE__ */ jsx(Text, { color: "#ff8800", children: agentName }),
4485
+ !isAstraNova && pluginData && pluginMap?.status?.fields.map((field) => {
4486
+ const value = getNestedValue(pluginData, field.path);
4487
+ if (value == null) return null;
4488
+ return /* @__PURE__ */ jsxs(React.Fragment, { children: [
4489
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: " \u2502 " }),
4490
+ /* @__PURE__ */ jsxs(Text, { color: field.color, children: [
4491
+ field.label,
4492
+ ": ",
4493
+ String(value)
4494
+ ] })
4495
+ ] }, field.path);
4496
+ }),
4497
+ !isAstraNova && !pluginData && pluginMap?.status && /* @__PURE__ */ jsxs(Fragment, { children: [
4498
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: " \u2502 " }),
4499
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "loading..." })
4500
+ ] }),
4423
4501
  canFetchData && market && /* @__PURE__ */ jsxs(Fragment, { children: [
4424
4502
  /* @__PURE__ */ jsx(Text, { dimColor: true, children: " \u2502 " }),
4425
4503
  /* @__PURE__ */ jsx(Text, { color: "#ffff00", children: "$NOVA " }),
@@ -4500,6 +4578,12 @@ function moodColor(mood) {
4500
4578
  return "white";
4501
4579
  }
4502
4580
  }
4581
+ function getNestedValue(obj, path7) {
4582
+ return path7.split(".").reduce(
4583
+ (cur, key) => cur && typeof cur === "object" ? cur[key] : void 0,
4584
+ obj
4585
+ );
4586
+ }
4503
4587
  async function fetchMarket(agentName) {
4504
4588
  const result = await apiCall("GET", "/api/v1/market/state", void 0, agentName);
4505
4589
  if (!result.ok) return null;
@@ -4888,7 +4972,8 @@ function App({
4888
4972
  initialChatMessages,
4889
4973
  initialAutopilotConfig,
4890
4974
  initialPendingTrades = 0,
4891
- debug
4975
+ debug,
4976
+ pluginMap
4892
4977
  }) {
4893
4978
  const { exit } = useApp();
4894
4979
  const manifest = getActiveManifest();
@@ -5414,14 +5499,15 @@ ${stack}
5414
5499
  journeyStage: profile.journeyStage ?? "full",
5415
5500
  autopilotMode,
5416
5501
  autopilotIntervalMs,
5417
- onEpochChange: handleEpochChange
5502
+ onEpochChange: handleEpochChange,
5503
+ pluginMap
5418
5504
  }
5419
5505
  ) }),
5420
5506
  /* @__PURE__ */ jsx7(Box7, { flexShrink: 0, width: "100%", paddingX: 2, marginTop: 1, justifyContent: "space-between", children: hasJourneyStages ? /* @__PURE__ */ jsxs8(Fragment3, { children: [
5421
5507
  /* @__PURE__ */ jsx7(Text8, { dimColor: true, children: "/help \xB7 /portfolio \xB7 /market \xB7 /strategy \xB7 /exit" }),
5422
5508
  /* @__PURE__ */ jsx7(Text8, { dimColor: true, children: "/auto on\xB7off\xB7set \xB7 Ctrl+C quit" })
5423
5509
  ] }) : /* @__PURE__ */ jsxs8(Fragment3, { children: [
5424
- /* @__PURE__ */ jsx7(Text8, { dimColor: true, children: "/help \xB7 /exit \xB7 Ctrl+C quit" }),
5510
+ /* @__PURE__ */ jsx7(Text8, { dimColor: true, children: (pluginMap?.commands?.map((c) => c.command).join(" \xB7 ") ?? "/help") + " \xB7 /exit" }),
5425
5511
  /* @__PURE__ */ jsx7(Text8, { dimColor: true, children: manifest.name })
5426
5512
  ] }) })
5427
5513
  ] });
@@ -5491,6 +5577,7 @@ async function main() {
5491
5577
  manifest = ASTRANOVA_MANIFEST;
5492
5578
  }
5493
5579
  setActiveManifest(manifest);
5580
+ const pluginMap = activePluginName === "astranova" ? null : loadPluginMap(activePluginName);
5494
5581
  if (isDaemonMode) {
5495
5582
  await runDaemon();
5496
5583
  return;
@@ -5637,7 +5724,8 @@ async function main() {
5637
5724
  initialChatMessages,
5638
5725
  initialAutopilotConfig,
5639
5726
  initialPendingTrades,
5640
- debug
5727
+ debug,
5728
+ pluginMap
5641
5729
  })
5642
5730
  );
5643
5731
  await waitUntilExit();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@astra-cli/cli",
3
- "version": "1.2.0",
3
+ "version": "1.2.2",
4
4
  "description": "The terminal for autonomous agents. Powered by AstraNova.",
5
5
  "type": "module",
6
6
  "bin": {