@standardagents/cli 0.13.2 → 0.14.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/README.md +28 -1
- package/dist/index.js +574 -34
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -10,7 +10,7 @@ import { parse, modify, applyEdits } from 'jsonc-parser';
|
|
|
10
10
|
import { loadFile, writeFile, generateCode } from 'magicast';
|
|
11
11
|
import { addVitePlugin } from 'magicast/helpers';
|
|
12
12
|
import net from 'net';
|
|
13
|
-
import { fileURLToPath } from 'url';
|
|
13
|
+
import { fileURLToPath, pathToFileURL } from 'url';
|
|
14
14
|
import os from 'os';
|
|
15
15
|
import { copySkill, readSkillFile } from '@standardagents/skill';
|
|
16
16
|
|
|
@@ -534,10 +534,10 @@ Agents orchestrate conversations by defining prompts, stop conditions, and turn
|
|
|
534
534
|
| \`stopOnResponse\` | \`boolean\` | No | Stop turn when LLM returns text (default: true) |
|
|
535
535
|
| \`stopTool\` | \`string\` | No | Tool that stops this side's turn |
|
|
536
536
|
| \`stopToolResponseProperty\` | \`string\` | No | Property to extract from stop tool result |
|
|
537
|
-
| \`
|
|
538
|
-
| \`
|
|
539
|
-
| \`
|
|
540
|
-
| \`
|
|
537
|
+
| \`maxSteps\` | \`number\` | No | Maximum step budget for this side |
|
|
538
|
+
| \`sessionStop\` | \`string \\| SessionToolBinding\` | No | Terminal success lifecycle binding |
|
|
539
|
+
| \`sessionFail\` | \`string \\| SessionToolBinding\` | No | Terminal failure lifecycle binding |
|
|
540
|
+
| \`sessionStatus\` | \`string \\| SessionToolBinding\` | No | Non-terminal status lifecycle binding |
|
|
541
541
|
| \`manualStopCondition\` | \`boolean\` | No | Enable custom stop handling via hooks |
|
|
542
542
|
|
|
543
543
|
## Basic Example (AI-Human)
|
|
@@ -552,8 +552,8 @@ export default defineAgent({
|
|
|
552
552
|
label: 'Support',
|
|
553
553
|
prompt: 'customer_support',
|
|
554
554
|
stopOnResponse: true,
|
|
555
|
-
|
|
556
|
-
|
|
555
|
+
sessionStop: 'close_ticket',
|
|
556
|
+
maxSteps: 50,
|
|
557
557
|
},
|
|
558
558
|
tags: ['support', 'tier-1'],
|
|
559
559
|
});
|
|
@@ -597,9 +597,9 @@ export default defineAgent({
|
|
|
597
597
|
sideA: {
|
|
598
598
|
label: 'Worker',
|
|
599
599
|
prompt: 'research_worker',
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
600
|
+
sessionStatus: 'set_subagent_status',
|
|
601
|
+
sessionFail: 'fail_research_subagent',
|
|
602
|
+
sessionStop: 'finish_subagent',
|
|
603
603
|
},
|
|
604
604
|
sideB: {
|
|
605
605
|
label: 'Reviewer',
|
|
@@ -629,10 +629,10 @@ Other prompts can then include the agent name in their \`tools\` array to enable
|
|
|
629
629
|
|
|
630
630
|
## Stop Conditions (Priority Order)
|
|
631
631
|
|
|
632
|
-
1. **
|
|
633
|
-
2. **
|
|
632
|
+
1. **sessionFail** - Ends entire conversation with a terminal failure
|
|
633
|
+
2. **sessionStop** - Ends entire conversation successfully
|
|
634
634
|
3. **stopTool** - Ends current side's turn
|
|
635
|
-
4. **
|
|
635
|
+
4. **maxSteps** - Ends side execution when the safety budget is reached
|
|
636
636
|
5. **stopOnResponse** - Ends turn when LLM returns text
|
|
637
637
|
6. **maxSessionTurns** - Ends conversation (hard limit: 250)
|
|
638
638
|
|
|
@@ -662,7 +662,7 @@ This convention is enforced by the builder UI and makes agents easily identifiab
|
|
|
662
662
|
|
|
663
663
|
- **Use descriptive names** (\`customer_support_agent\` not \`agent1\`)
|
|
664
664
|
- **Always use the _agent suffix** - names like \`support_agent\`, \`research_agent\`
|
|
665
|
-
- **Always set
|
|
665
|
+
- **Always set maxSteps or maxSessionTurns** as safety limits
|
|
666
666
|
- **Match stop conditions to use case** - chat apps use stopOnResponse, workflows use stopTool
|
|
667
667
|
- **Use labels** for clarity in logs and UI
|
|
668
668
|
- **Organize with tags** for filtering
|
|
@@ -1278,13 +1278,15 @@ Full reference: https://docs.standardagentbuilder.com/core-concepts/api
|
|
|
1278
1278
|
`;
|
|
1279
1279
|
|
|
1280
1280
|
// src/commands/scaffold.ts
|
|
1281
|
+
function getScaffoldCompatibilityDate() {
|
|
1282
|
+
return "2025-08-13";
|
|
1283
|
+
}
|
|
1281
1284
|
var WRANGLER_TEMPLATE = (name) => {
|
|
1282
|
-
const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
1283
1285
|
return `{
|
|
1284
1286
|
"$schema": "node_modules/wrangler/config-schema.json",
|
|
1285
1287
|
"name": "${name}",
|
|
1286
1288
|
"main": "worker/index.ts",
|
|
1287
|
-
"compatibility_date": "${
|
|
1289
|
+
"compatibility_date": "${getScaffoldCompatibilityDate()}",
|
|
1288
1290
|
"compatibility_flags": ["nodejs_compat"],
|
|
1289
1291
|
"observability": {
|
|
1290
1292
|
"enabled": true
|
|
@@ -1807,6 +1809,33 @@ function runCommand(command, args, cwd, env) {
|
|
|
1807
1809
|
function toKebabCase(str) {
|
|
1808
1810
|
return str.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
1809
1811
|
}
|
|
1812
|
+
function findWorkspaceRoot(startDir) {
|
|
1813
|
+
let currentDir = startDir;
|
|
1814
|
+
while (true) {
|
|
1815
|
+
if (fs3.existsSync(path3.join(currentDir, "pnpm-workspace.yaml"))) {
|
|
1816
|
+
return currentDir;
|
|
1817
|
+
}
|
|
1818
|
+
const parentDir = path3.dirname(currentDir);
|
|
1819
|
+
if (parentDir === currentDir) {
|
|
1820
|
+
return null;
|
|
1821
|
+
}
|
|
1822
|
+
currentDir = parentDir;
|
|
1823
|
+
}
|
|
1824
|
+
}
|
|
1825
|
+
function getPnpmWorkspaceFilterTarget(projectPath) {
|
|
1826
|
+
if (process.env.STANDARDAGENTS_WORKSPACE !== "1") {
|
|
1827
|
+
return null;
|
|
1828
|
+
}
|
|
1829
|
+
const workspaceRoot = findWorkspaceRoot(projectPath);
|
|
1830
|
+
if (!workspaceRoot) {
|
|
1831
|
+
return null;
|
|
1832
|
+
}
|
|
1833
|
+
const relativeProjectPath = path3.relative(workspaceRoot, projectPath).split(path3.sep).join("/");
|
|
1834
|
+
return {
|
|
1835
|
+
cwd: workspaceRoot,
|
|
1836
|
+
filterTarget: relativeProjectPath.startsWith(".") ? relativeProjectPath : `./${relativeProjectPath}`
|
|
1837
|
+
};
|
|
1838
|
+
}
|
|
1810
1839
|
function detectPackageManager() {
|
|
1811
1840
|
const userAgent = process.env.npm_config_user_agent;
|
|
1812
1841
|
if (userAgent) {
|
|
@@ -1820,15 +1849,62 @@ function detectPackageManager() {
|
|
|
1820
1849
|
if (fs3.existsSync("package-lock.json")) return "npm";
|
|
1821
1850
|
return "npm";
|
|
1822
1851
|
}
|
|
1852
|
+
function normalizeScaffoldedPackageJson(packageJson, projectName, versions) {
|
|
1853
|
+
const normalized = { ...packageJson };
|
|
1854
|
+
normalized.name = toKebabCase(projectName);
|
|
1855
|
+
normalized.devDependencies = {
|
|
1856
|
+
...normalized.devDependencies || {},
|
|
1857
|
+
vite: versions.vite,
|
|
1858
|
+
typescript: versions.typescript,
|
|
1859
|
+
"@cloudflare/vite-plugin": versions.cloudflareVitePlugin,
|
|
1860
|
+
wrangler: versions.wrangler
|
|
1861
|
+
};
|
|
1862
|
+
return normalized;
|
|
1863
|
+
}
|
|
1864
|
+
function applyPackageSpecifiers(packageJson, key, specifiers) {
|
|
1865
|
+
packageJson[key] = {
|
|
1866
|
+
...packageJson[key] || {}
|
|
1867
|
+
};
|
|
1868
|
+
for (const specifier of specifiers) {
|
|
1869
|
+
const atIndex = specifier.lastIndexOf("@");
|
|
1870
|
+
if (atIndex <= 0) {
|
|
1871
|
+
packageJson[key][specifier] = "^4.0.0";
|
|
1872
|
+
continue;
|
|
1873
|
+
}
|
|
1874
|
+
const name = specifier.slice(0, atIndex);
|
|
1875
|
+
const version = specifier.slice(atIndex + 1);
|
|
1876
|
+
packageJson[key][name] = version;
|
|
1877
|
+
}
|
|
1878
|
+
}
|
|
1823
1879
|
function getWorkspacePackageVersion() {
|
|
1824
1880
|
if (process.env.STANDARDAGENTS_WORKSPACE === "1") {
|
|
1825
1881
|
return "workspace:*";
|
|
1826
1882
|
}
|
|
1827
|
-
return "0.
|
|
1883
|
+
return "0.14.0";
|
|
1828
1884
|
}
|
|
1829
1885
|
function getSipPackageVersion() {
|
|
1830
1886
|
return "1.0.1";
|
|
1831
1887
|
}
|
|
1888
|
+
function getScaffoldToolchainVersions() {
|
|
1889
|
+
return {
|
|
1890
|
+
vite: "^7.0.6",
|
|
1891
|
+
typescript: "^5.9.0",
|
|
1892
|
+
cloudflareVitePlugin: "^1.17.0",
|
|
1893
|
+
wrangler: "^4.54.0"
|
|
1894
|
+
};
|
|
1895
|
+
}
|
|
1896
|
+
async function runPackageBinary(packageManager, binary, binaryArgs, cwd, env) {
|
|
1897
|
+
switch (packageManager) {
|
|
1898
|
+
case "pnpm":
|
|
1899
|
+
return runCommand("pnpm", ["exec", binary, ...binaryArgs], cwd, env);
|
|
1900
|
+
case "yarn":
|
|
1901
|
+
return runCommand("yarn", ["exec", binary, ...binaryArgs], cwd, env);
|
|
1902
|
+
case "bun":
|
|
1903
|
+
return runCommand("bunx", [binary, ...binaryArgs], cwd, env);
|
|
1904
|
+
default:
|
|
1905
|
+
return runCommand("npx", [binary, ...binaryArgs], cwd, env);
|
|
1906
|
+
}
|
|
1907
|
+
}
|
|
1832
1908
|
async function selectPackageManager(detected) {
|
|
1833
1909
|
const options = ["npm", "pnpm", "yarn", "bun"];
|
|
1834
1910
|
const detectedIndex = options.indexOf(detected);
|
|
@@ -1961,11 +2037,12 @@ export default defineConfig({
|
|
|
1961
2037
|
const packageJsonPath = path3.join(projectPath, "package.json");
|
|
1962
2038
|
if (fs3.existsSync(packageJsonPath)) {
|
|
1963
2039
|
const packageJson = JSON.parse(fs3.readFileSync(packageJsonPath, "utf-8"));
|
|
1964
|
-
const
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
2040
|
+
const normalizedPackageJson = normalizeScaffoldedPackageJson(
|
|
2041
|
+
packageJson,
|
|
2042
|
+
projectName,
|
|
2043
|
+
getScaffoldToolchainVersions()
|
|
2044
|
+
);
|
|
2045
|
+
fs3.writeFileSync(packageJsonPath, JSON.stringify(normalizedPackageJson, null, 2) + "\n", "utf-8");
|
|
1969
2046
|
}
|
|
1970
2047
|
logger.log("");
|
|
1971
2048
|
logger.info("Step 2: Configuring environment variables...");
|
|
@@ -2025,12 +2102,33 @@ export default defineConfig({
|
|
|
2025
2102
|
const devFlag = pm === "npm" ? "--save-dev" : "-D";
|
|
2026
2103
|
const workspacePackageVersion = getWorkspacePackageVersion();
|
|
2027
2104
|
const sipPackageVersion = getSipPackageVersion();
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
"
|
|
2032
|
-
|
|
2033
|
-
|
|
2105
|
+
const isWorkspaceMode = pm === "pnpm" && process.env.STANDARDAGENTS_WORKSPACE === "1";
|
|
2106
|
+
const pnpmWorkspaceFilter = pm === "pnpm" ? getPnpmWorkspaceFilterTarget(projectPath) : null;
|
|
2107
|
+
const installPackages = async (packages, { dev = false } = {}) => {
|
|
2108
|
+
if (pm === "pnpm" && pnpmWorkspaceFilter) {
|
|
2109
|
+
await runCommand(
|
|
2110
|
+
pm,
|
|
2111
|
+
[
|
|
2112
|
+
installCmd,
|
|
2113
|
+
...dev ? [devFlag] : [],
|
|
2114
|
+
...packages,
|
|
2115
|
+
"--filter",
|
|
2116
|
+
pnpmWorkspaceFilter.filterTarget
|
|
2117
|
+
],
|
|
2118
|
+
pnpmWorkspaceFilter.cwd
|
|
2119
|
+
);
|
|
2120
|
+
return;
|
|
2121
|
+
}
|
|
2122
|
+
await runCommand(
|
|
2123
|
+
pm,
|
|
2124
|
+
[
|
|
2125
|
+
installCmd,
|
|
2126
|
+
...dev ? [devFlag] : [],
|
|
2127
|
+
...packages
|
|
2128
|
+
],
|
|
2129
|
+
projectPath
|
|
2130
|
+
);
|
|
2131
|
+
};
|
|
2034
2132
|
const deps = [
|
|
2035
2133
|
`@standardagents/builder@${workspacePackageVersion}`,
|
|
2036
2134
|
`@standardagents/spec@${workspacePackageVersion}`,
|
|
@@ -2058,7 +2156,22 @@ export default defineConfig({
|
|
|
2058
2156
|
if (xaiKey) {
|
|
2059
2157
|
deps.push(`@standardagents/xai@${workspacePackageVersion}`);
|
|
2060
2158
|
}
|
|
2061
|
-
|
|
2159
|
+
if (isWorkspaceMode) {
|
|
2160
|
+
const packageJson = JSON.parse(fs3.readFileSync(packageJsonPath, "utf-8"));
|
|
2161
|
+
applyPackageSpecifiers(packageJson, "devDependencies", [
|
|
2162
|
+
`@cloudflare/vite-plugin@${getScaffoldToolchainVersions().cloudflareVitePlugin}`,
|
|
2163
|
+
`wrangler@${getScaffoldToolchainVersions().wrangler}`
|
|
2164
|
+
]);
|
|
2165
|
+
applyPackageSpecifiers(packageJson, "dependencies", deps);
|
|
2166
|
+
fs3.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2) + "\n", "utf-8");
|
|
2167
|
+
logger.info("Workspace mode detected: wrote dependency specs to package.json and deferred install.");
|
|
2168
|
+
} else {
|
|
2169
|
+
await installPackages([
|
|
2170
|
+
`@cloudflare/vite-plugin@${getScaffoldToolchainVersions().cloudflareVitePlugin}`,
|
|
2171
|
+
`wrangler@${getScaffoldToolchainVersions().wrangler}`
|
|
2172
|
+
], { dev: true });
|
|
2173
|
+
await installPackages(deps);
|
|
2174
|
+
}
|
|
2062
2175
|
} catch (error) {
|
|
2063
2176
|
logger.error("Failed to install dependencies");
|
|
2064
2177
|
process.exit(1);
|
|
@@ -2137,10 +2250,14 @@ export default defineConfig({
|
|
|
2137
2250
|
logger.log("");
|
|
2138
2251
|
logger.info("Step 5: Generating Cloudflare types...");
|
|
2139
2252
|
logger.log("");
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
}
|
|
2143
|
-
|
|
2253
|
+
if (pm === "pnpm" && process.env.STANDARDAGENTS_WORKSPACE === "1") {
|
|
2254
|
+
logger.info("Workspace mode detected: skipping Wrangler type generation until dependencies are installed.");
|
|
2255
|
+
} else {
|
|
2256
|
+
try {
|
|
2257
|
+
await runPackageBinary(pm, "wrangler", ["types"], projectPath);
|
|
2258
|
+
} catch (error) {
|
|
2259
|
+
logger.warning("Could not generate types automatically. Run your package manager's Wrangler types command manually.");
|
|
2260
|
+
}
|
|
2144
2261
|
}
|
|
2145
2262
|
logger.log("");
|
|
2146
2263
|
logger.success("Project created successfully!");
|
|
@@ -3570,10 +3687,431 @@ async function skill(options = {}) {
|
|
|
3570
3687
|
process.exit(1);
|
|
3571
3688
|
}
|
|
3572
3689
|
}
|
|
3690
|
+
var UUID_LIKE_MODEL_ID = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
3691
|
+
var CLOUDFLARE_PROVIDER_MODEL_ID = /^@cf\//i;
|
|
3692
|
+
var PAGE_SIZE = 100;
|
|
3693
|
+
var MAX_PAGES = 1e3;
|
|
3694
|
+
var CURRENT_MODELS_URLS = [
|
|
3695
|
+
"https://standardagentspec.org/models.md",
|
|
3696
|
+
"https://standardagentspec.com/models.md"
|
|
3697
|
+
];
|
|
3698
|
+
var PROVIDER_DEFINITIONS = [
|
|
3699
|
+
{
|
|
3700
|
+
name: "cloudflare",
|
|
3701
|
+
packageName: "@standardagents/cloudflare",
|
|
3702
|
+
exportName: "cloudflare",
|
|
3703
|
+
label: "Cloudflare Workers AI",
|
|
3704
|
+
envKeys: ["CLOUDFLARE_API_TOKEN", "CLOUDFLARE_ACCOUNT_ID"]
|
|
3705
|
+
},
|
|
3706
|
+
{
|
|
3707
|
+
name: "cerebras",
|
|
3708
|
+
packageName: "@standardagents/cerebras",
|
|
3709
|
+
exportName: "cerebras",
|
|
3710
|
+
label: "Cerebras",
|
|
3711
|
+
envKeys: ["CEREBRAS_API_KEY"]
|
|
3712
|
+
},
|
|
3713
|
+
{
|
|
3714
|
+
name: "google",
|
|
3715
|
+
packageName: "@standardagents/google",
|
|
3716
|
+
exportName: "google",
|
|
3717
|
+
label: "Google Gemini",
|
|
3718
|
+
envKeys: ["GOOGLE_API_KEY"]
|
|
3719
|
+
},
|
|
3720
|
+
{
|
|
3721
|
+
name: "groq",
|
|
3722
|
+
packageName: "@standardagents/groq",
|
|
3723
|
+
exportName: "groq",
|
|
3724
|
+
label: "Groq",
|
|
3725
|
+
envKeys: ["GROQ_API_KEY"]
|
|
3726
|
+
},
|
|
3727
|
+
{
|
|
3728
|
+
name: "openai",
|
|
3729
|
+
packageName: "@standardagents/openai",
|
|
3730
|
+
exportName: "openai",
|
|
3731
|
+
label: "OpenAI",
|
|
3732
|
+
envKeys: ["OPENAI_API_KEY"]
|
|
3733
|
+
},
|
|
3734
|
+
{
|
|
3735
|
+
name: "openrouter",
|
|
3736
|
+
packageName: "@standardagents/openrouter",
|
|
3737
|
+
exportName: "openrouter",
|
|
3738
|
+
label: "OpenRouter",
|
|
3739
|
+
envKeys: ["OPENROUTER_API_KEY"]
|
|
3740
|
+
},
|
|
3741
|
+
{
|
|
3742
|
+
name: "xai",
|
|
3743
|
+
packageName: "@standardagents/xai",
|
|
3744
|
+
exportName: "xai",
|
|
3745
|
+
label: "xai",
|
|
3746
|
+
envKeys: ["XAI_API_KEY"]
|
|
3747
|
+
}
|
|
3748
|
+
];
|
|
3749
|
+
function isOpaqueModelId(modelId) {
|
|
3750
|
+
if (!modelId) return true;
|
|
3751
|
+
return UUID_LIKE_MODEL_ID.test(modelId) || CLOUDFLARE_PROVIDER_MODEL_ID.test(modelId);
|
|
3752
|
+
}
|
|
3753
|
+
function getProviderDefinition(name) {
|
|
3754
|
+
return PROVIDER_DEFINITIONS.find((provider) => provider.name === name);
|
|
3755
|
+
}
|
|
3756
|
+
function parseEnvFile2(content) {
|
|
3757
|
+
const result = {};
|
|
3758
|
+
for (const line of content.split("\n")) {
|
|
3759
|
+
const trimmed = line.trim();
|
|
3760
|
+
if (!trimmed || trimmed.startsWith("#")) continue;
|
|
3761
|
+
const withoutExport = trimmed.startsWith("export ") ? trimmed.slice("export ".length).trim() : trimmed;
|
|
3762
|
+
const eqIndex = withoutExport.indexOf("=");
|
|
3763
|
+
if (eqIndex === -1) continue;
|
|
3764
|
+
const key = withoutExport.slice(0, eqIndex).trim();
|
|
3765
|
+
let value = withoutExport.slice(eqIndex + 1).trim();
|
|
3766
|
+
if (value.startsWith('"') && value.endsWith('"')) {
|
|
3767
|
+
value = value.slice(1, -1).replace(/\\"/g, '"');
|
|
3768
|
+
} else if (value.startsWith("'") && value.endsWith("'")) {
|
|
3769
|
+
value = value.slice(1, -1);
|
|
3770
|
+
}
|
|
3771
|
+
result[key] = value;
|
|
3772
|
+
}
|
|
3773
|
+
return result;
|
|
3774
|
+
}
|
|
3775
|
+
function findProjectRoot(startDir = process.cwd()) {
|
|
3776
|
+
let currentDir = path3.resolve(startDir);
|
|
3777
|
+
while (true) {
|
|
3778
|
+
if (fs3.existsSync(path3.join(currentDir, "package.json"))) {
|
|
3779
|
+
return currentDir;
|
|
3780
|
+
}
|
|
3781
|
+
const parentDir = path3.dirname(currentDir);
|
|
3782
|
+
if (parentDir === currentDir) {
|
|
3783
|
+
return path3.resolve(startDir);
|
|
3784
|
+
}
|
|
3785
|
+
currentDir = parentDir;
|
|
3786
|
+
}
|
|
3787
|
+
}
|
|
3788
|
+
function readProjectPackageJson(projectRoot) {
|
|
3789
|
+
const packagePath = path3.join(projectRoot, "package.json");
|
|
3790
|
+
if (!fs3.existsSync(packagePath)) {
|
|
3791
|
+
return {};
|
|
3792
|
+
}
|
|
3793
|
+
return JSON.parse(fs3.readFileSync(packagePath, "utf8"));
|
|
3794
|
+
}
|
|
3795
|
+
function getDeclaredProviderPackages(projectRoot) {
|
|
3796
|
+
const pkg = readProjectPackageJson(projectRoot);
|
|
3797
|
+
const combined = {
|
|
3798
|
+
...pkg.dependencies ?? {},
|
|
3799
|
+
...pkg.devDependencies ?? {},
|
|
3800
|
+
...pkg.optionalDependencies ?? {},
|
|
3801
|
+
...pkg.peerDependencies ?? {}
|
|
3802
|
+
};
|
|
3803
|
+
return PROVIDER_DEFINITIONS.map((provider) => provider.packageName).filter((packageName) => typeof combined[packageName] === "string");
|
|
3804
|
+
}
|
|
3805
|
+
function resolvePackageEntry(packageName, projectRoot) {
|
|
3806
|
+
const packageDir = findInstalledPackageDir(packageName, projectRoot);
|
|
3807
|
+
if (!packageDir) {
|
|
3808
|
+
return null;
|
|
3809
|
+
}
|
|
3810
|
+
const packageJsonPath = path3.join(packageDir, "package.json");
|
|
3811
|
+
try {
|
|
3812
|
+
const packageJson = JSON.parse(fs3.readFileSync(packageJsonPath, "utf8"));
|
|
3813
|
+
const exportPath = resolvePackageExportPath(packageJson.exports) || packageJson.main || "index.js";
|
|
3814
|
+
return path3.join(packageDir, exportPath);
|
|
3815
|
+
} catch {
|
|
3816
|
+
return null;
|
|
3817
|
+
}
|
|
3818
|
+
}
|
|
3819
|
+
function findInstalledPackageDir(packageName, projectRoot) {
|
|
3820
|
+
let currentDir = path3.resolve(projectRoot);
|
|
3821
|
+
while (true) {
|
|
3822
|
+
const candidate = path3.join(currentDir, "node_modules", ...packageName.split("/"));
|
|
3823
|
+
if (fs3.existsSync(candidate)) {
|
|
3824
|
+
return candidate;
|
|
3825
|
+
}
|
|
3826
|
+
const parentDir = path3.dirname(currentDir);
|
|
3827
|
+
if (parentDir === currentDir) {
|
|
3828
|
+
return null;
|
|
3829
|
+
}
|
|
3830
|
+
currentDir = parentDir;
|
|
3831
|
+
}
|
|
3832
|
+
}
|
|
3833
|
+
function resolvePackageExportPath(exportsField) {
|
|
3834
|
+
if (typeof exportsField === "string") {
|
|
3835
|
+
return exportsField;
|
|
3836
|
+
}
|
|
3837
|
+
if (!exportsField || typeof exportsField !== "object") {
|
|
3838
|
+
return null;
|
|
3839
|
+
}
|
|
3840
|
+
const rootExport = exportsField["."];
|
|
3841
|
+
if (typeof rootExport === "string") {
|
|
3842
|
+
return rootExport;
|
|
3843
|
+
}
|
|
3844
|
+
if (!rootExport || typeof rootExport !== "object") {
|
|
3845
|
+
return null;
|
|
3846
|
+
}
|
|
3847
|
+
const rootExportRecord = rootExport;
|
|
3848
|
+
const candidate = rootExportRecord.import || rootExportRecord.default || rootExportRecord.require;
|
|
3849
|
+
return typeof candidate === "string" ? candidate : null;
|
|
3850
|
+
}
|
|
3851
|
+
function isProviderPackageInstalled(packageName, projectRoot) {
|
|
3852
|
+
return resolvePackageEntry(packageName, projectRoot) !== null;
|
|
3853
|
+
}
|
|
3854
|
+
function loadProjectEnv(projectRoot, processEnv = process.env) {
|
|
3855
|
+
const result = {};
|
|
3856
|
+
const envFiles = [".env", ".env.local", ".dev.vars", ".dev.vars.local"];
|
|
3857
|
+
for (const fileName of envFiles) {
|
|
3858
|
+
const filePath = path3.join(projectRoot, fileName);
|
|
3859
|
+
if (!fs3.existsSync(filePath)) continue;
|
|
3860
|
+
Object.assign(result, parseEnvFile2(fs3.readFileSync(filePath, "utf8")));
|
|
3861
|
+
}
|
|
3862
|
+
for (const [key, value] of Object.entries(processEnv)) {
|
|
3863
|
+
if (typeof value === "string") {
|
|
3864
|
+
result[key] = value;
|
|
3865
|
+
}
|
|
3866
|
+
}
|
|
3867
|
+
return result;
|
|
3868
|
+
}
|
|
3869
|
+
function detectProviders(projectRoot, env = loadProjectEnv(projectRoot)) {
|
|
3870
|
+
const declaredPackages = new Set(getDeclaredProviderPackages(projectRoot));
|
|
3871
|
+
return PROVIDER_DEFINITIONS.filter((provider) => declaredPackages.has(provider.packageName)).map((provider) => {
|
|
3872
|
+
const installed = isProviderPackageInstalled(provider.packageName, projectRoot);
|
|
3873
|
+
const missingEnvKeys = provider.envKeys.filter((envKey) => !env[envKey]);
|
|
3874
|
+
return {
|
|
3875
|
+
...provider,
|
|
3876
|
+
declared: true,
|
|
3877
|
+
installed,
|
|
3878
|
+
configured: installed && missingEnvKeys.length === 0,
|
|
3879
|
+
missingEnvKeys
|
|
3880
|
+
};
|
|
3881
|
+
});
|
|
3882
|
+
}
|
|
3883
|
+
async function loadProviderFactory(provider, projectRoot) {
|
|
3884
|
+
const entryPath = resolvePackageEntry(provider.packageName, projectRoot);
|
|
3885
|
+
if (!entryPath) {
|
|
3886
|
+
throw new Error(`Provider package ${provider.packageName} is not installed in ${projectRoot}.`);
|
|
3887
|
+
}
|
|
3888
|
+
const moduleUrl = entryPath.startsWith("file:") ? entryPath : pathToFileURL(entryPath).href;
|
|
3889
|
+
const providerModule = await import(moduleUrl);
|
|
3890
|
+
const factory = providerModule[provider.exportName];
|
|
3891
|
+
if (typeof factory !== "function") {
|
|
3892
|
+
throw new Error(`Provider package ${provider.packageName} does not export ${provider.exportName}().`);
|
|
3893
|
+
}
|
|
3894
|
+
return factory;
|
|
3895
|
+
}
|
|
3896
|
+
function buildProviderConfig(provider, env) {
|
|
3897
|
+
const apiKey = env[provider.envKeys[0]] || "";
|
|
3898
|
+
if (provider.name === "cloudflare") {
|
|
3899
|
+
const accountId = env.CLOUDFLARE_ACCOUNT_ID;
|
|
3900
|
+
return {
|
|
3901
|
+
apiKey,
|
|
3902
|
+
accountId,
|
|
3903
|
+
baseUrl: accountId ? `https://api.cloudflare.com/client/v4/accounts/${accountId}/ai/v1` : void 0
|
|
3904
|
+
};
|
|
3905
|
+
}
|
|
3906
|
+
return { apiKey };
|
|
3907
|
+
}
|
|
3908
|
+
async function collectProviderModels(providerName, providerInstance) {
|
|
3909
|
+
const rawModels = [];
|
|
3910
|
+
if (providerInstance.getModelsPage) {
|
|
3911
|
+
for (let page = 1; page <= MAX_PAGES; page += 1) {
|
|
3912
|
+
const result = await providerInstance.getModelsPage({ page, perPage: PAGE_SIZE });
|
|
3913
|
+
rawModels.push(...result.models);
|
|
3914
|
+
if (!result.hasNextPage) {
|
|
3915
|
+
return normalizeProviderModels(providerName, rawModels);
|
|
3916
|
+
}
|
|
3917
|
+
}
|
|
3918
|
+
throw new Error(`Provider ${providerName} exceeded ${MAX_PAGES} model pages without terminating pagination.`);
|
|
3919
|
+
}
|
|
3920
|
+
if (providerInstance.getModels) {
|
|
3921
|
+
rawModels.push(...await providerInstance.getModels());
|
|
3922
|
+
return normalizeProviderModels(providerName, rawModels);
|
|
3923
|
+
}
|
|
3924
|
+
throw new Error(`Provider ${providerName} does not support model discovery.`);
|
|
3925
|
+
}
|
|
3926
|
+
async function fetchAvailableModelsForProvider(providerName, projectRoot, env, factoryLoader = loadProviderFactory) {
|
|
3927
|
+
const provider = getProviderDefinition(providerName);
|
|
3928
|
+
if (!provider) {
|
|
3929
|
+
throw new Error(`Unknown provider "${providerName}".`);
|
|
3930
|
+
}
|
|
3931
|
+
const factory = await factoryLoader(provider, projectRoot);
|
|
3932
|
+
const providerInstance = factory(buildProviderConfig(provider, env));
|
|
3933
|
+
return collectProviderModels(provider.name, providerInstance);
|
|
3934
|
+
}
|
|
3935
|
+
async function fetchCurrentModelsMarkdown(urls = CURRENT_MODELS_URLS) {
|
|
3936
|
+
let lastError = null;
|
|
3937
|
+
for (const url of urls) {
|
|
3938
|
+
try {
|
|
3939
|
+
const response = await fetch(url);
|
|
3940
|
+
if (!response.ok) {
|
|
3941
|
+
throw new Error(`HTTP ${response.status} ${response.statusText}`.trim());
|
|
3942
|
+
}
|
|
3943
|
+
return {
|
|
3944
|
+
url,
|
|
3945
|
+
content: await response.text()
|
|
3946
|
+
};
|
|
3947
|
+
} catch (error) {
|
|
3948
|
+
lastError = error instanceof Error ? new Error(`Failed to fetch ${url}: ${error.message}`) : new Error(`Failed to fetch ${url}.`);
|
|
3949
|
+
}
|
|
3950
|
+
}
|
|
3951
|
+
throw lastError ?? new Error("No current models URLs configured.");
|
|
3952
|
+
}
|
|
3953
|
+
function buildProviderSelectionHelp(providers) {
|
|
3954
|
+
const providerNames = providers.map((provider) => provider.name).join(", ");
|
|
3955
|
+
const examples = providers.map((provider) => ` agents available-models --provider=${provider.name}`).join("\n");
|
|
3956
|
+
return [
|
|
3957
|
+
`Multiple configured providers were found: ${providerNames}`,
|
|
3958
|
+
"Re-run with a specific provider to fetch all model IDs:",
|
|
3959
|
+
examples
|
|
3960
|
+
].join("\n");
|
|
3961
|
+
}
|
|
3962
|
+
function describeProviderAvailability(provider) {
|
|
3963
|
+
if (!provider.installed) {
|
|
3964
|
+
return `${provider.name}: not installed`;
|
|
3965
|
+
}
|
|
3966
|
+
if (provider.missingEnvKeys.length > 0) {
|
|
3967
|
+
return `${provider.name}: missing ${provider.missingEnvKeys.join(", ")}`;
|
|
3968
|
+
}
|
|
3969
|
+
return `${provider.name}: unavailable`;
|
|
3970
|
+
}
|
|
3971
|
+
function formatAvailableModelsOutput(provider, models) {
|
|
3972
|
+
const lines = [
|
|
3973
|
+
`# ${provider.label} models`,
|
|
3974
|
+
"",
|
|
3975
|
+
"Use the `model` values exactly as shown in `defineModel({ model: ... })`.",
|
|
3976
|
+
"",
|
|
3977
|
+
"| model | label | context | notes |",
|
|
3978
|
+
"| --- | --- | ---: | --- |"
|
|
3979
|
+
];
|
|
3980
|
+
for (const model of models) {
|
|
3981
|
+
const context = model.contextLength ? model.contextLength.toLocaleString("en-US") : "";
|
|
3982
|
+
lines.push(
|
|
3983
|
+
`| \`${escapeTableCell(model.value)}\` | ${escapeTableCell(model.label)} | ${context} | ${escapeTableCell(model.description)} |`
|
|
3984
|
+
);
|
|
3985
|
+
}
|
|
3986
|
+
return `${lines.join("\n")}
|
|
3987
|
+
`;
|
|
3988
|
+
}
|
|
3989
|
+
function normalizeProviderModels(providerName, rawModels) {
|
|
3990
|
+
const deduped = /* @__PURE__ */ new Map();
|
|
3991
|
+
for (const model of rawModels) {
|
|
3992
|
+
const value = getExecutableModelId(providerName, model);
|
|
3993
|
+
if (!value) continue;
|
|
3994
|
+
if (!deduped.has(value)) {
|
|
3995
|
+
deduped.set(value, {
|
|
3996
|
+
value,
|
|
3997
|
+
label: model.name || value,
|
|
3998
|
+
description: model.description || "",
|
|
3999
|
+
contextLength: model.contextLength,
|
|
4000
|
+
slug: model.slug
|
|
4001
|
+
});
|
|
4002
|
+
}
|
|
4003
|
+
}
|
|
4004
|
+
return [...deduped.values()].sort((left, right) => left.value.localeCompare(right.value));
|
|
4005
|
+
}
|
|
4006
|
+
function getExecutableModelId(providerName, model) {
|
|
4007
|
+
if (model.id && !isOpaqueModelId(model.id)) {
|
|
4008
|
+
return model.id;
|
|
4009
|
+
}
|
|
4010
|
+
if (providerName === "cloudflare") {
|
|
4011
|
+
const publicCloudflareId = [model.name, model.slug].find((value) => typeof value === "string" && value.includes("/"));
|
|
4012
|
+
if (publicCloudflareId) {
|
|
4013
|
+
return publicCloudflareId.startsWith("@cf/") ? publicCloudflareId : `@cf/${publicCloudflareId.replace(/^@cf\//, "")}`;
|
|
4014
|
+
}
|
|
4015
|
+
}
|
|
4016
|
+
return model.slug || model.name || model.id;
|
|
4017
|
+
}
|
|
4018
|
+
function escapeTableCell(value) {
|
|
4019
|
+
return value.replace(/\|/g, "\\|").replace(/\n/g, "<br />");
|
|
4020
|
+
}
|
|
4021
|
+
|
|
4022
|
+
// src/commands/current-models.ts
|
|
4023
|
+
async function currentModels(options = {}) {
|
|
4024
|
+
try {
|
|
4025
|
+
const { content } = await fetchCurrentModelsMarkdown(
|
|
4026
|
+
options.url ? [options.url] : void 0
|
|
4027
|
+
);
|
|
4028
|
+
process.stdout.write(content.endsWith("\n") ? content : `${content}
|
|
4029
|
+
`);
|
|
4030
|
+
} catch (error) {
|
|
4031
|
+
const message = error instanceof Error ? error.message : "Failed to fetch current models.";
|
|
4032
|
+
process.stderr.write(`${message}
|
|
4033
|
+
`);
|
|
4034
|
+
process.exit(1);
|
|
4035
|
+
}
|
|
4036
|
+
}
|
|
4037
|
+
|
|
4038
|
+
// src/commands/available-models.ts
|
|
4039
|
+
function writeError(message) {
|
|
4040
|
+
process.stderr.write(`${message}
|
|
4041
|
+
`);
|
|
4042
|
+
process.exit(1);
|
|
4043
|
+
}
|
|
4044
|
+
async function availableModels(options = {}) {
|
|
4045
|
+
const projectRoot = findProjectRoot(process.cwd());
|
|
4046
|
+
const env = loadProjectEnv(projectRoot);
|
|
4047
|
+
const detectedProviders = detectProviders(projectRoot, env);
|
|
4048
|
+
if (detectedProviders.length === 0) {
|
|
4049
|
+
writeError(
|
|
4050
|
+
[
|
|
4051
|
+
`No installed provider packages were found in ${projectRoot}.`,
|
|
4052
|
+
"Add a provider package such as `@standardagents/cerebras`, then run this command again."
|
|
4053
|
+
].join("\n")
|
|
4054
|
+
);
|
|
4055
|
+
}
|
|
4056
|
+
const providerName = options.provider?.trim();
|
|
4057
|
+
if (providerName) {
|
|
4058
|
+
const provider2 = detectedProviders.find((candidate) => candidate.name === providerName);
|
|
4059
|
+
if (!getProviderDefinition(providerName)) {
|
|
4060
|
+
writeError(
|
|
4061
|
+
`Unknown provider "${providerName}". Supported providers: ${detectedProviders.map((candidate) => candidate.name).join(", ")}.`
|
|
4062
|
+
);
|
|
4063
|
+
}
|
|
4064
|
+
if (!provider2) {
|
|
4065
|
+
writeError(
|
|
4066
|
+
[
|
|
4067
|
+
`Provider "${providerName}" is not installed in ${projectRoot}.`,
|
|
4068
|
+
`Install ${getProviderDefinition(providerName)?.packageName || providerName} and try again.`
|
|
4069
|
+
].join("\n")
|
|
4070
|
+
);
|
|
4071
|
+
}
|
|
4072
|
+
if (!provider2.configured) {
|
|
4073
|
+
writeError(
|
|
4074
|
+
[
|
|
4075
|
+
`Provider "${providerName}" is missing required environment variables.`,
|
|
4076
|
+
`Missing: ${provider2.missingEnvKeys.join(", ")}`
|
|
4077
|
+
].join("\n")
|
|
4078
|
+
);
|
|
4079
|
+
}
|
|
4080
|
+
try {
|
|
4081
|
+
const models = await fetchAvailableModelsForProvider(provider2.name, projectRoot, env);
|
|
4082
|
+
process.stdout.write(formatAvailableModelsOutput(provider2, models));
|
|
4083
|
+
return;
|
|
4084
|
+
} catch (error) {
|
|
4085
|
+
const message = error instanceof Error ? error.message : `Failed to fetch models for ${providerName}.`;
|
|
4086
|
+
writeError(message);
|
|
4087
|
+
}
|
|
4088
|
+
}
|
|
4089
|
+
const configuredProviders = detectedProviders.filter((provider2) => provider2.configured);
|
|
4090
|
+
if (configuredProviders.length === 0) {
|
|
4091
|
+
const missingSummary = detectedProviders.map((provider2) => describeProviderAvailability(provider2)).join("\n");
|
|
4092
|
+
writeError(
|
|
4093
|
+
[
|
|
4094
|
+
"No installed providers are fully configured yet.",
|
|
4095
|
+
missingSummary
|
|
4096
|
+
].join("\n")
|
|
4097
|
+
);
|
|
4098
|
+
}
|
|
4099
|
+
if (configuredProviders.length > 1) {
|
|
4100
|
+
writeError(buildProviderSelectionHelp(configuredProviders));
|
|
4101
|
+
}
|
|
4102
|
+
const provider = configuredProviders[0];
|
|
4103
|
+
try {
|
|
4104
|
+
const models = await fetchAvailableModelsForProvider(provider.name, projectRoot, env);
|
|
4105
|
+
process.stdout.write(formatAvailableModelsOutput(provider, models));
|
|
4106
|
+
} catch (error) {
|
|
4107
|
+
const message = error instanceof Error ? error.message : `Failed to fetch models for ${provider.name}.`;
|
|
4108
|
+
writeError(message);
|
|
4109
|
+
}
|
|
4110
|
+
}
|
|
3573
4111
|
|
|
3574
4112
|
// src/index.ts
|
|
3575
4113
|
var program = new Command();
|
|
3576
|
-
program.name("agents").description("CLI tool for Standard Agents / AgentBuilder").version("0.
|
|
4114
|
+
program.name("agents").description("CLI tool for Standard Agents / AgentBuilder").version("0.14.0");
|
|
3577
4115
|
program.command("init [project-name]").description("Create a new Standard Agents project (runs create vite, then scaffold)").option("-y, --yes", "Skip prompts and use defaults").option("--template <template>", "Vite template to use", "vanilla-ts").action(init);
|
|
3578
4116
|
program.command("scaffold").description("Add Standard Agents to an existing Vite project").option("--force", "Overwrite existing configuration").action(scaffold);
|
|
3579
4117
|
program.command("init-chat [project-name]").description("Scaffold a frontend chat application").option("-y, --yes", "Skip prompts and use defaults").option("--framework <framework>", "Framework to use (vite or nextjs)").action(initChat);
|
|
@@ -3582,6 +4120,8 @@ program.command("unpack [package]").description("Unpack a packed agent to the lo
|
|
|
3582
4120
|
program.command("list-packed").description("List all discovered packed agents").action(listPacked);
|
|
3583
4121
|
program.command("deploy").description("Build and deploy your project to the Standard Agents platform").option("--api-key <key>", "Platform API key (overrides PLATFORM_API_KEY env var)").option("--endpoint <url>", "Platform API endpoint (default: https://api.standardagents.ai)").action(deploy);
|
|
3584
4122
|
program.command("skill").description("Install the bundled AgentBuilder guidance into a supported coding agent").option("--agent <target>", "Install target: codex or claude").option("--dir <path>", "Install directory override for the selected target").option("--force", "Overwrite an existing installed skill").action(skill);
|
|
4123
|
+
program.command("current-models").description("Print the live curated model guide from standardagentspec.com").option("--url <url>", "Override the models markdown URL").action(currentModels);
|
|
4124
|
+
program.command("available-models").description("List every available model for one configured provider in the current project").option("--provider <provider>", "Provider to query, for example cerebras or openai").action(availableModels);
|
|
3585
4125
|
program.parse();
|
|
3586
4126
|
//# sourceMappingURL=index.js.map
|
|
3587
4127
|
//# sourceMappingURL=index.js.map
|