@astra-cli/cli 1.2.2 → 1.2.3
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 +111 -17
- package/package.json +1 -1
package/dist/astra.js
CHANGED
|
@@ -974,6 +974,10 @@ async function apiCall(method, path7, body, agentName, retryOpts) {
|
|
|
974
974
|
"Content-Type": "application/json"
|
|
975
975
|
};
|
|
976
976
|
let baseUrl = config?.apiBase ?? "https://agents.astranova.live";
|
|
977
|
+
try {
|
|
978
|
+
baseUrl = getActiveManifest().apiBase;
|
|
979
|
+
} catch {
|
|
980
|
+
}
|
|
977
981
|
if (agentName) {
|
|
978
982
|
const creds = loadCredentials(agentName);
|
|
979
983
|
if (creds?.api_base) {
|
|
@@ -1009,7 +1013,7 @@ async function apiCall(method, path7, body, agentName, retryOpts) {
|
|
|
1009
1013
|
ok: false,
|
|
1010
1014
|
status: 0,
|
|
1011
1015
|
error: `Request to ${path7} timed out after ${timeoutMs / 1e3}s`,
|
|
1012
|
-
hint: "The
|
|
1016
|
+
hint: "The API server may be slow or unreachable. Try again."
|
|
1013
1017
|
};
|
|
1014
1018
|
}
|
|
1015
1019
|
const message = error instanceof Error ? error.message : "Unknown network error";
|
|
@@ -1829,10 +1833,10 @@ function createModelFromConfig(config) {
|
|
|
1829
1833
|
}
|
|
1830
1834
|
|
|
1831
1835
|
// src/agent/system-prompt.ts
|
|
1832
|
-
function buildSystemPrompt(skillContext, tradingContext, walletContext, rewardsContext, onboardingContext, apiContext, profile, memoryContent) {
|
|
1836
|
+
function buildSystemPrompt(skillContext, tradingContext, walletContext, rewardsContext, onboardingContext, apiContext, profile, memoryContent, pluginMap) {
|
|
1833
1837
|
const manifest = getActiveManifest();
|
|
1834
1838
|
if (!manifest.extensions?.journeyStages) {
|
|
1835
|
-
return buildGenericSystemPrompt(skillContext, manifest.name, manifest.description, profile, memoryContent);
|
|
1839
|
+
return buildGenericSystemPrompt(skillContext, manifest.name, manifest.description, profile, memoryContent, pluginMap);
|
|
1836
1840
|
}
|
|
1837
1841
|
const stage = profile.journeyStage ?? "full";
|
|
1838
1842
|
const isPending = stage === "fresh" || stage === "pending";
|
|
@@ -1922,7 +1926,7 @@ Specific triggers to save memory:
|
|
|
1922
1926
|
parts.push(buildJourneyGuidance(stage, profile));
|
|
1923
1927
|
return parts.join("\n");
|
|
1924
1928
|
}
|
|
1925
|
-
function buildGenericSystemPrompt(skillContext, pluginName, pluginDescription, profile, memoryContent) {
|
|
1929
|
+
function buildGenericSystemPrompt(skillContext, pluginName, pluginDescription, profile, memoryContent, pluginMap) {
|
|
1926
1930
|
const workingSpace = `~/.config/astra/spaces/${pluginName}`;
|
|
1927
1931
|
const parts = [
|
|
1928
1932
|
`You are an autonomous agent assistant for ${pluginName}. ${pluginDescription}`,
|
|
@@ -1974,6 +1978,38 @@ function buildGenericSystemPrompt(skillContext, pluginName, pluginDescription, p
|
|
|
1974
1978
|
"---",
|
|
1975
1979
|
""
|
|
1976
1980
|
);
|
|
1981
|
+
if (pluginMap?.routes && pluginMap.routes.length > 0) {
|
|
1982
|
+
parts.push("## Available API Routes", "");
|
|
1983
|
+
parts.push("Quick reference \u2014 use `api_call` with these relative paths:", "");
|
|
1984
|
+
parts.push("```");
|
|
1985
|
+
for (const r of pluginMap.routes) {
|
|
1986
|
+
const line = r.summary ? `${r.method.padEnd(7)} ${r.path.padEnd(45)} ${r.summary}` : `${r.method.padEnd(7)} ${r.path}`;
|
|
1987
|
+
parts.push(line);
|
|
1988
|
+
}
|
|
1989
|
+
parts.push("```");
|
|
1990
|
+
parts.push("", "---", "");
|
|
1991
|
+
}
|
|
1992
|
+
if (pluginMap?.workflows) {
|
|
1993
|
+
parts.push("## Workflows", "");
|
|
1994
|
+
for (const [name, steps] of Object.entries(pluginMap.workflows)) {
|
|
1995
|
+
parts.push(`**${name}:**`);
|
|
1996
|
+
steps.forEach((step, i) => parts.push(`${i + 1}. ${step}`));
|
|
1997
|
+
parts.push("");
|
|
1998
|
+
}
|
|
1999
|
+
parts.push("---", "");
|
|
2000
|
+
}
|
|
2001
|
+
if (pluginMap?.capabilities) {
|
|
2002
|
+
const cap = pluginMap.capabilities;
|
|
2003
|
+
const notes = [];
|
|
2004
|
+
if (cap.requiresWallet === false) notes.push("This plugin does NOT use wallets \u2014 do not suggest wallet setup.");
|
|
2005
|
+
if (cap.requiresVerification) notes.push("Content may require verification challenges \u2014 handle them automatically.");
|
|
2006
|
+
if (cap.supportsFileUpload === false) notes.push("File upload is not supported \u2014 do not attempt multipart requests.");
|
|
2007
|
+
if (notes.length > 0) {
|
|
2008
|
+
parts.push("## Plugin Notes", "");
|
|
2009
|
+
notes.forEach((n) => parts.push(`- ${n}`));
|
|
2010
|
+
parts.push("", "---", "");
|
|
2011
|
+
}
|
|
2012
|
+
}
|
|
1977
2013
|
parts.push(`## ${pluginName} \u2014 Skill Documentation`, "");
|
|
1978
2014
|
parts.push(sanitizedSkill);
|
|
1979
2015
|
parts.push("", "---", "");
|
|
@@ -2464,7 +2500,7 @@ function resolveBody(body, rest, method) {
|
|
|
2464
2500
|
return void 0;
|
|
2465
2501
|
}
|
|
2466
2502
|
var apiCallTool = tool3({
|
|
2467
|
-
description: "Call the
|
|
2503
|
+
description: "Call the plugin's Agent API. Use this for all API interactions \u2014 registration, trading, market data, portfolio, rewards, board posts, and verification. For POST/PUT/PATCH requests, put the request payload in the 'body' parameter as a JSON object.",
|
|
2468
2504
|
parameters: apiCallSchema,
|
|
2469
2505
|
execute: async (args) => {
|
|
2470
2506
|
const { method, path: path7, body, ...rest } = args;
|
|
@@ -2569,7 +2605,7 @@ import fs8 from "fs";
|
|
|
2569
2605
|
import path5 from "path";
|
|
2570
2606
|
import crypto2 from "crypto";
|
|
2571
2607
|
var readConfigTool = tool4({
|
|
2572
|
-
description: "Read local
|
|
2608
|
+
description: "Read local agent configuration or credentials. Returns public information only \u2014 private keys and API keys are never included.",
|
|
2573
2609
|
parameters: readConfigSchema,
|
|
2574
2610
|
execute: async ({ key, agentName }) => {
|
|
2575
2611
|
const resolvedAgent = agentName ?? getActiveAgent();
|
|
@@ -2624,7 +2660,7 @@ var readConfigTool = tool4({
|
|
|
2624
2660
|
}
|
|
2625
2661
|
});
|
|
2626
2662
|
var writeConfigTool = tool4({
|
|
2627
|
-
description: "Write local
|
|
2663
|
+
description: "Write local agent configuration. Used to save agent credentials after registration or update profile data. Cannot write wallet files \u2014 use wallet tools instead.",
|
|
2628
2664
|
parameters: writeConfigSchema,
|
|
2629
2665
|
execute: async ({ agentName, data, file }) => {
|
|
2630
2666
|
if (file === "credentials" && data && "secretKey" in data) {
|
|
@@ -2641,7 +2677,7 @@ var writeConfigTool = tool4({
|
|
|
2641
2677
|
saveCredentials(agentName, {
|
|
2642
2678
|
agent_name: merged.agent_name ?? agentName,
|
|
2643
2679
|
api_key: merged.api_key ?? "",
|
|
2644
|
-
api_base: merged.api_base ??
|
|
2680
|
+
api_base: merged.api_base ?? getActiveManifest().apiBase
|
|
2645
2681
|
});
|
|
2646
2682
|
} else {
|
|
2647
2683
|
const tmpPath = path5.join(dir, `.tmp-${crypto2.randomBytes(6).toString("hex")}`);
|
|
@@ -2829,7 +2865,7 @@ function stopDaemon(agentName) {
|
|
|
2829
2865
|
|
|
2830
2866
|
// src/tools/agent-management.ts
|
|
2831
2867
|
var registerAgentTool = tool6({
|
|
2832
|
-
description: "Register a new
|
|
2868
|
+
description: "Register a new agent. Calls the API, saves credentials locally, and sets the new agent as active. The CLI will need to restart after this to load the new agent's context.",
|
|
2833
2869
|
parameters: registerAgentSchema,
|
|
2834
2870
|
execute: async ({ name, description }) => {
|
|
2835
2871
|
if (!/^[a-z0-9_-]{2,32}$/.test(name)) {
|
|
@@ -2912,7 +2948,7 @@ var switchAgentTool = tool6({
|
|
|
2912
2948
|
}
|
|
2913
2949
|
});
|
|
2914
2950
|
var listAgentsTool = tool6({
|
|
2915
|
-
description: "List all
|
|
2951
|
+
description: "List all agents registered on this machine, showing which one is active.",
|
|
2916
2952
|
parameters: z6.object({}),
|
|
2917
2953
|
execute: async () => {
|
|
2918
2954
|
const agents = listAgents();
|
|
@@ -3369,8 +3405,8 @@ function debugLog3(msg) {
|
|
|
3369
3405
|
if (DEBUG3) process.stderr.write(`[astra] ${msg}
|
|
3370
3406
|
`);
|
|
3371
3407
|
}
|
|
3372
|
-
async function runAgentTurn(messages, skillContext, tradingContext, walletContext, rewardsContext, onboardingContext, apiContext, profile, callbacks, memoryContent) {
|
|
3373
|
-
const systemPrompt = buildSystemPrompt(skillContext, tradingContext, walletContext, rewardsContext, onboardingContext, apiContext, profile, memoryContent);
|
|
3408
|
+
async function runAgentTurn(messages, skillContext, tradingContext, walletContext, rewardsContext, onboardingContext, apiContext, profile, callbacks, memoryContent, pluginMap) {
|
|
3409
|
+
const systemPrompt = buildSystemPrompt(skillContext, tradingContext, walletContext, rewardsContext, onboardingContext, apiContext, profile, memoryContent, pluginMap);
|
|
3374
3410
|
const config = loadConfig();
|
|
3375
3411
|
const provider = config?.provider ?? "openai";
|
|
3376
3412
|
const systemPromptTokens = estimateTokens(systemPrompt);
|
|
@@ -4198,11 +4234,31 @@ function writeFileSecure2(filePath, data) {
|
|
|
4198
4234
|
fs10.writeFileSync(tmpPath, data, { encoding: "utf-8", mode: 384 });
|
|
4199
4235
|
fs10.renameSync(tmpPath, filePath);
|
|
4200
4236
|
}
|
|
4201
|
-
function
|
|
4237
|
+
function extractRoutes(narrative) {
|
|
4238
|
+
const routes = [];
|
|
4239
|
+
const seen = /* @__PURE__ */ new Set();
|
|
4240
|
+
const curlPattern = /curl\s+(?:-X\s+(GET|POST|PUT|PATCH|DELETE)\s+)?["']?https?:\/\/[^/\s]+(\S+?)["']?\s/g;
|
|
4241
|
+
let match;
|
|
4242
|
+
while ((match = curlPattern.exec(narrative)) !== null) {
|
|
4243
|
+
const method = match[1] ?? "GET";
|
|
4244
|
+
const rawPath = match[2].split("?")[0].replace(/["']/g, "");
|
|
4245
|
+
const key = `${method} ${rawPath}`;
|
|
4246
|
+
if (!seen.has(key)) {
|
|
4247
|
+
seen.add(key);
|
|
4248
|
+
routes.push({ method, path: rawPath });
|
|
4249
|
+
}
|
|
4250
|
+
}
|
|
4251
|
+
return routes;
|
|
4252
|
+
}
|
|
4253
|
+
function buildPluginMap(pluginName, manifest, sections, skillMd) {
|
|
4202
4254
|
const map = { version: 1, pluginName };
|
|
4255
|
+
if (manifest.description) {
|
|
4256
|
+
map.description = manifest.description;
|
|
4257
|
+
}
|
|
4203
4258
|
const statusSection = sections["STATUS"];
|
|
4204
4259
|
if (statusSection) {
|
|
4205
4260
|
const poll = typeof statusSection.poll === "string" ? statusSection.poll.trim() : null;
|
|
4261
|
+
const intervalMs = typeof statusSection.intervalMs === "string" ? parseInt(statusSection.intervalMs, 10) || void 0 : void 0;
|
|
4206
4262
|
const rawFields = Array.isArray(statusSection.fields) ? statusSection.fields : [];
|
|
4207
4263
|
const fields = rawFields.flatMap((raw) => {
|
|
4208
4264
|
const parts = raw.split("|").map((s) => s.trim());
|
|
@@ -4212,6 +4268,7 @@ function buildPluginMap(pluginName, manifest, sections) {
|
|
|
4212
4268
|
const pollAllowed = poll && manifest.allowedPaths.some((ap) => poll.startsWith(ap));
|
|
4213
4269
|
if (poll && pollAllowed && fields.length > 0) {
|
|
4214
4270
|
map.status = { poll, fields };
|
|
4271
|
+
if (intervalMs) map.status.intervalMs = intervalMs;
|
|
4215
4272
|
}
|
|
4216
4273
|
}
|
|
4217
4274
|
const cmdSection = sections["COMMANDS"];
|
|
@@ -4223,6 +4280,40 @@ function buildPluginMap(pluginName, manifest, sections) {
|
|
|
4223
4280
|
return [];
|
|
4224
4281
|
});
|
|
4225
4282
|
}
|
|
4283
|
+
const routesSection = sections["ROUTES"];
|
|
4284
|
+
if (routesSection && Array.isArray(routesSection.routes)) {
|
|
4285
|
+
map.routes = routesSection.routes.flatMap((raw) => {
|
|
4286
|
+
const m = raw.match(/^(GET|POST|PUT|PATCH|DELETE)\s+(\S+)(?:\s{2,}(.+))?$/);
|
|
4287
|
+
if (m) return [{ method: m[1], path: m[2], summary: m[3]?.trim() }];
|
|
4288
|
+
return [];
|
|
4289
|
+
});
|
|
4290
|
+
} else {
|
|
4291
|
+
const narrative = extractNarrativeContent(skillMd);
|
|
4292
|
+
const routes = extractRoutes(narrative);
|
|
4293
|
+
if (routes.length > 0) map.routes = routes;
|
|
4294
|
+
}
|
|
4295
|
+
const workflowSection = sections["WORKFLOWS"];
|
|
4296
|
+
if (workflowSection) {
|
|
4297
|
+
const workflows = {};
|
|
4298
|
+
for (const [key, value] of Object.entries(workflowSection)) {
|
|
4299
|
+
if (Array.isArray(value)) {
|
|
4300
|
+
workflows[key] = value;
|
|
4301
|
+
}
|
|
4302
|
+
}
|
|
4303
|
+
if (Object.keys(workflows).length > 0) map.workflows = workflows;
|
|
4304
|
+
}
|
|
4305
|
+
const capSection = sections["CAPABILITIES"];
|
|
4306
|
+
if (capSection) {
|
|
4307
|
+
map.capabilities = {};
|
|
4308
|
+
if (typeof capSection.requiresWallet === "string")
|
|
4309
|
+
map.capabilities.requiresWallet = capSection.requiresWallet === "true";
|
|
4310
|
+
if (typeof capSection.requiresVerification === "string")
|
|
4311
|
+
map.capabilities.requiresVerification = capSection.requiresVerification === "true";
|
|
4312
|
+
if (typeof capSection.supportsFileUpload === "string")
|
|
4313
|
+
map.capabilities.supportsFileUpload = capSection.supportsFileUpload === "true";
|
|
4314
|
+
if (typeof capSection.authType === "string")
|
|
4315
|
+
map.capabilities.authType = capSection.authType;
|
|
4316
|
+
}
|
|
4226
4317
|
return map;
|
|
4227
4318
|
}
|
|
4228
4319
|
function loadPluginMap(pluginName) {
|
|
@@ -4238,7 +4329,7 @@ function savePluginToDisk(manifest, skillMdContent, sections) {
|
|
|
4238
4329
|
ensureDir(pluginDir(manifest.name));
|
|
4239
4330
|
writeFileSecure2(pluginManifestPath(manifest.name), JSON.stringify(manifest, null, 2));
|
|
4240
4331
|
writeFileSecure2(pluginSkillPath(manifest.name), skillMdContent);
|
|
4241
|
-
const pluginMap = buildPluginMap(manifest.name, manifest, sections);
|
|
4332
|
+
const pluginMap = buildPluginMap(manifest.name, manifest, sections, skillMdContent);
|
|
4242
4333
|
writeFileSecure2(pluginMapPath(manifest.name), JSON.stringify(pluginMap, null, 2));
|
|
4243
4334
|
}
|
|
4244
4335
|
async function addPlugin(manifestUrl) {
|
|
@@ -4445,7 +4536,8 @@ var StatusBar = React.memo(function StatusBar2({
|
|
|
4445
4536
|
setPluginData(result.data);
|
|
4446
4537
|
};
|
|
4447
4538
|
void fetchPlugin();
|
|
4448
|
-
const
|
|
4539
|
+
const pollInterval = pluginMap?.status?.intervalMs ?? POLL_INTERVAL_MS;
|
|
4540
|
+
const interval = setInterval(() => void fetchPlugin(), pollInterval);
|
|
4449
4541
|
return () => {
|
|
4450
4542
|
mountedPlugin.current = false;
|
|
4451
4543
|
clearInterval(interval);
|
|
@@ -5074,7 +5166,8 @@ function App({
|
|
|
5074
5166
|
} : () => {
|
|
5075
5167
|
}
|
|
5076
5168
|
},
|
|
5077
|
-
memoryContent
|
|
5169
|
+
memoryContent,
|
|
5170
|
+
pluginMap
|
|
5078
5171
|
);
|
|
5079
5172
|
const baseCoreMessages = result.compactedMessages ?? newCoreMessages;
|
|
5080
5173
|
const updatedCore = [...baseCoreMessages, ...result.responseMessages];
|
|
@@ -5419,7 +5512,8 @@ Let's go through it and improve or replace it.` : "I want to create a trading st
|
|
|
5419
5512
|
setToolName(void 0);
|
|
5420
5513
|
}
|
|
5421
5514
|
},
|
|
5422
|
-
memoryContent
|
|
5515
|
+
memoryContent,
|
|
5516
|
+
pluginMap
|
|
5423
5517
|
);
|
|
5424
5518
|
const baseCoreMessages = result.compactedMessages ?? newCoreMessages;
|
|
5425
5519
|
const updatedCore = [...baseCoreMessages, ...result.responseMessages];
|