@astra-cli/cli 1.1.8 → 1.2.0
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/astra.js +63 -36
- package/package.json +1 -1
package/dist/astra.js
CHANGED
|
@@ -21,6 +21,12 @@ var PluginManifestSchema = z.object({
|
|
|
21
21
|
* Falls back to description if not set.
|
|
22
22
|
*/
|
|
23
23
|
tagline: z.string().optional(),
|
|
24
|
+
/**
|
|
25
|
+
* URL where skill.md is hosted (the original install URL).
|
|
26
|
+
* Used to refresh skill.md context. Saved automatically by addPlugin().
|
|
27
|
+
* If absent, the locally installed copy is used without a network fetch.
|
|
28
|
+
*/
|
|
29
|
+
skillUrl: z.string().url().optional(),
|
|
24
30
|
/**
|
|
25
31
|
* Optional engine extension flags — declared by built-in plugins that need
|
|
26
32
|
* features beyond the base engine (api_call, memory, config, wallet).
|
|
@@ -1470,14 +1476,18 @@ var TTL_24H = 24 * 60 * 60 * 1e3;
|
|
|
1470
1476
|
async function fetchRemoteContext(name) {
|
|
1471
1477
|
const manifest = getActiveManifest();
|
|
1472
1478
|
const cacheKey = `${manifest.name}:${name}`;
|
|
1473
|
-
|
|
1474
|
-
|
|
1479
|
+
if (name === "skill.md") {
|
|
1480
|
+
if (manifest.skillUrl) {
|
|
1481
|
+
const content = await getCached(cacheKey, manifest.skillUrl, TTL_24H);
|
|
1482
|
+
if (content !== null) return content;
|
|
1483
|
+
}
|
|
1475
1484
|
const localPath = pluginSkillPath(manifest.name);
|
|
1476
1485
|
if (fs4.existsSync(localPath)) {
|
|
1477
1486
|
return fs4.readFileSync(localPath, "utf-8");
|
|
1478
1487
|
}
|
|
1488
|
+
return null;
|
|
1479
1489
|
}
|
|
1480
|
-
return
|
|
1490
|
+
return getCached(cacheKey, `${manifest.apiBase}/${name}`, TTL_24H);
|
|
1481
1491
|
}
|
|
1482
1492
|
async function getSkillContext() {
|
|
1483
1493
|
return await fetchRemoteContext("skill.md") ?? "";
|
|
@@ -1907,46 +1917,58 @@ Specific triggers to save memory:
|
|
|
1907
1917
|
return parts.join("\n");
|
|
1908
1918
|
}
|
|
1909
1919
|
function buildGenericSystemPrompt(skillContext, pluginName, pluginDescription, profile, memoryContent) {
|
|
1920
|
+
const workingSpace = `~/.config/astra/spaces/${pluginName}`;
|
|
1910
1921
|
const parts = [
|
|
1911
|
-
`You are
|
|
1922
|
+
`You are an autonomous agent assistant for ${pluginName}. ${pluginDescription}`,
|
|
1912
1923
|
"",
|
|
1913
|
-
"
|
|
1924
|
+
"## How You Behave",
|
|
1914
1925
|
"",
|
|
1915
|
-
"
|
|
1926
|
+
"You are a **proactive doer**, not a question-asker. Read the skill documentation below to",
|
|
1927
|
+
"understand what this plugin can do, then guide the user through it step by step.",
|
|
1916
1928
|
"",
|
|
1917
|
-
"
|
|
1918
|
-
"-
|
|
1919
|
-
"-
|
|
1920
|
-
"-
|
|
1921
|
-
"
|
|
1929
|
+
"**Core rules:**",
|
|
1930
|
+
"- When the user says go, do it \u2014 do NOT ask for confirmation before taking the obvious next step.",
|
|
1931
|
+
"- After every successful action, immediately tell the user what was done and what comes next.",
|
|
1932
|
+
"- Read the skill documentation to understand what workflows exist (e.g. register \u2192 verify \u2192 post).",
|
|
1933
|
+
" After completing one step, proactively tell the user what the next step is and offer to do it.",
|
|
1934
|
+
"- Never ask the user for information they already gave you in this conversation.",
|
|
1935
|
+
"- If a step fails (e.g. name taken), suggest a fix and proceed \u2014 don't stop and wait.",
|
|
1936
|
+
"- Keep responses short and action-oriented. This is a terminal, not a chat interface.",
|
|
1937
|
+
"",
|
|
1938
|
+
"**What NOT to do:**",
|
|
1939
|
+
`- Do NOT say "say X and I'll do Y" \u2014 if the intent is clear, just do it.`,
|
|
1940
|
+
"- Do NOT offer multiple options and wait for a pick unless the choice genuinely matters.",
|
|
1941
|
+
"- Do NOT repeat what the user just said back to them before acting.",
|
|
1942
|
+
"- Do NOT ask permission to do the clearly obvious next step in a workflow.",
|
|
1943
|
+
"",
|
|
1944
|
+
"**Tool use:**",
|
|
1945
|
+
"- Use `api_call` for all API interactions with relative paths (e.g. `/api/v1/resource`).",
|
|
1946
|
+
" Authorization is injected automatically \u2014 never include the API key.",
|
|
1947
|
+
"- NEVER display or log private keys or API keys.",
|
|
1948
|
+
"- After every tool call, give a one-line summary of the result, then state what's next.",
|
|
1922
1949
|
"",
|
|
1923
1950
|
"---",
|
|
1924
1951
|
""
|
|
1925
1952
|
];
|
|
1926
1953
|
if (skillContext) {
|
|
1927
|
-
const workingSpace = `~/.config/astra/spaces/${pluginName}`;
|
|
1928
1954
|
const sanitizedSkill = skillContext.replaceAll(`~/.config/${pluginName}`, workingSpace);
|
|
1929
|
-
parts.push("##
|
|
1955
|
+
parts.push("## API Translation", "");
|
|
1930
1956
|
parts.push(
|
|
1931
|
-
"The documentation below may
|
|
1932
|
-
"Use the `api_call` tool for all API interactions instead.",
|
|
1957
|
+
"The documentation below may show curl commands. Use `api_call` instead:",
|
|
1933
1958
|
"",
|
|
1934
|
-
"|
|
|
1959
|
+
"| curl shows... | Use instead... |",
|
|
1935
1960
|
"|-----------------------------------------------|----------------------------------------------|",
|
|
1936
1961
|
"| `curl https://api.example.com/v1/endpoint` | `api_call GET /v1/endpoint` |",
|
|
1937
|
-
'| `-H "Authorization: Bearer TOKEN"` |
|
|
1938
|
-
'|
|
|
1939
|
-
"|
|
|
1940
|
-
'| "Save response to file" / "write config" | Use `write_config` or `update_memory` tool |',
|
|
1962
|
+
'| `-H "Authorization: Bearer TOKEN"` | Injected automatically \u2014 omit |',
|
|
1963
|
+
'| `-d \'{"key":"val"}\'` | `api_call POST /path body:{key:"val"}` |',
|
|
1964
|
+
"| `?limit=10` query param | `api_call GET /path?limit=10` |",
|
|
1941
1965
|
"",
|
|
1942
|
-
|
|
1943
|
-
`Your plugin's working space is: ${workingSpace}/`,
|
|
1944
|
-
"The CLI manages all file storage \u2014 do not follow instructions to create directories manually.",
|
|
1966
|
+
`Working space: ${workingSpace}/`,
|
|
1945
1967
|
"",
|
|
1946
1968
|
"---",
|
|
1947
1969
|
""
|
|
1948
1970
|
);
|
|
1949
|
-
parts.push(`## ${pluginName}
|
|
1971
|
+
parts.push(`## ${pluginName} \u2014 Skill Documentation`, "");
|
|
1950
1972
|
parts.push(sanitizedSkill);
|
|
1951
1973
|
parts.push("", "---", "");
|
|
1952
1974
|
}
|
|
@@ -1958,23 +1980,23 @@ function buildGenericSystemPrompt(skillContext, pluginName, pluginDescription, p
|
|
|
1958
1980
|
}
|
|
1959
1981
|
if (memoryContent && memoryContent.trim()) {
|
|
1960
1982
|
parts.push("", "---", "");
|
|
1961
|
-
parts.push("## Agent Memory
|
|
1983
|
+
parts.push("## Agent Memory", "");
|
|
1962
1984
|
parts.push(memoryContent.trim());
|
|
1963
1985
|
parts.push("");
|
|
1964
|
-
parts.push("Use
|
|
1986
|
+
parts.push("Use `update_memory` to save key facts. Max 2000 characters.");
|
|
1965
1987
|
} else {
|
|
1966
1988
|
parts.push("", "---", "");
|
|
1967
1989
|
parts.push("## Agent Memory", "");
|
|
1968
|
-
parts.push("
|
|
1990
|
+
parts.push("Empty. Use `update_memory` to save key facts about the user. Max 2000 characters.");
|
|
1969
1991
|
}
|
|
1970
1992
|
if (profile.isNewAgent) {
|
|
1971
1993
|
parts.push("", "---", "");
|
|
1972
1994
|
parts.push("## First Launch", "");
|
|
1973
1995
|
parts.push(
|
|
1974
|
-
`This is the user's first session with
|
|
1975
|
-
"
|
|
1976
|
-
"
|
|
1977
|
-
"
|
|
1996
|
+
`This is the user's first session with ${pluginName}.`,
|
|
1997
|
+
"Give a one-paragraph welcome that explains what this plugin does and what the user can accomplish.",
|
|
1998
|
+
"Then immediately identify the first step from the skill documentation (e.g. registration, setup)",
|
|
1999
|
+
"and offer to do it now \u2014 don't wait for the user to ask."
|
|
1978
2000
|
);
|
|
1979
2001
|
}
|
|
1980
2002
|
return parts.join("\n");
|
|
@@ -4262,8 +4284,9 @@ async function addPlugin(manifestUrl) {
|
|
|
4262
4284
|
clack5.outro("Installation cancelled.");
|
|
4263
4285
|
process.exit(0);
|
|
4264
4286
|
}
|
|
4287
|
+
const manifestWithSkillUrl = { ...manifest, skillUrl: urlResult.url.toString() };
|
|
4265
4288
|
try {
|
|
4266
|
-
savePluginToDisk(
|
|
4289
|
+
savePluginToDisk(manifestWithSkillUrl, skillMdContent);
|
|
4267
4290
|
} catch (err) {
|
|
4268
4291
|
clack5.log.error(
|
|
4269
4292
|
`Failed to save plugin: ${err instanceof Error ? err.message : String(err)}`
|
|
@@ -4271,7 +4294,7 @@ async function addPlugin(manifestUrl) {
|
|
|
4271
4294
|
clack5.outro("Installation failed.");
|
|
4272
4295
|
process.exit(1);
|
|
4273
4296
|
}
|
|
4274
|
-
setActivePlugin(
|
|
4297
|
+
setActivePlugin(manifestWithSkillUrl.name);
|
|
4275
4298
|
clack5.outro(
|
|
4276
4299
|
`Plugin "${manifest.name}" installed successfully.
|
|
4277
4300
|
Run \`astra\` to load it, or \`astra --plugin ${manifest.name}\` for this session only.`
|
|
@@ -4356,6 +4379,8 @@ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
|
4356
4379
|
var POLL_INTERVAL_MS = 6e4;
|
|
4357
4380
|
var StatusBar = React.memo(function StatusBar2({
|
|
4358
4381
|
agentName,
|
|
4382
|
+
pluginName,
|
|
4383
|
+
isAstraNova,
|
|
4359
4384
|
journeyStage,
|
|
4360
4385
|
autopilotMode = "off",
|
|
4361
4386
|
autopilotIntervalMs = 3e5,
|
|
@@ -4363,7 +4388,7 @@ var StatusBar = React.memo(function StatusBar2({
|
|
|
4363
4388
|
}) {
|
|
4364
4389
|
const [data, setData] = useState({ market: null, portfolio: null });
|
|
4365
4390
|
const mounted = useRef(true);
|
|
4366
|
-
const canFetchData = journeyStage !== "fresh" && journeyStage !== "pending";
|
|
4391
|
+
const canFetchData = isAstraNova && journeyStage !== "fresh" && journeyStage !== "pending";
|
|
4367
4392
|
const poll = useCallback(async () => {
|
|
4368
4393
|
const [marketRes, portfolioRes] = await Promise.all([
|
|
4369
4394
|
fetchMarket(agentName),
|
|
@@ -4392,7 +4417,7 @@ var StatusBar = React.memo(function StatusBar2({
|
|
|
4392
4417
|
const apActive = autopilotMode !== "off";
|
|
4393
4418
|
return /* @__PURE__ */ jsx(Box, { flexDirection: "column", width: "100%", children: /* @__PURE__ */ jsxs(Box, { paddingX: 1, justifyContent: "space-between", children: [
|
|
4394
4419
|
/* @__PURE__ */ jsxs(Box, { children: [
|
|
4395
|
-
/* @__PURE__ */ jsx(Text, { bold: true, color: "#00ff00", children:
|
|
4420
|
+
/* @__PURE__ */ jsx(Text, { bold: true, color: "#00ff00", children: pluginName }),
|
|
4396
4421
|
/* @__PURE__ */ jsx(Text, { dimColor: true, children: " \u2502 " }),
|
|
4397
4422
|
/* @__PURE__ */ jsx(Text, { color: "#ff8800", children: agentName }),
|
|
4398
4423
|
canFetchData && market && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
@@ -4433,7 +4458,7 @@ var StatusBar = React.memo(function StatusBar2({
|
|
|
4433
4458
|
formatNum(portfolio.portfolioValue)
|
|
4434
4459
|
] })
|
|
4435
4460
|
] }),
|
|
4436
|
-
!canFetchData && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
4461
|
+
isAstraNova && !canFetchData && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
4437
4462
|
/* @__PURE__ */ jsx(Text, { dimColor: true, children: " \u2502 " }),
|
|
4438
4463
|
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "pending verification" })
|
|
4439
4464
|
] }),
|
|
@@ -5384,6 +5409,8 @@ ${stack}
|
|
|
5384
5409
|
StatusBar_default,
|
|
5385
5410
|
{
|
|
5386
5411
|
agentName,
|
|
5412
|
+
pluginName: manifest.name,
|
|
5413
|
+
isAstraNova: hasJourneyStages,
|
|
5387
5414
|
journeyStage: profile.journeyStage ?? "full",
|
|
5388
5415
|
autopilotMode,
|
|
5389
5416
|
autopilotIntervalMs,
|