@agentskit/cli 0.7.1 → 0.9.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 +2 -2
- package/dist/bin.cjs +826 -2
- package/dist/bin.cjs.map +1 -1
- package/dist/bin.js +1 -1
- package/dist/{chunk-72XFU2X2.js → chunk-ZEESHYST.js} +828 -4
- package/dist/chunk-ZEESHYST.js.map +1 -0
- package/dist/index.cjs +826 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/package.json +22 -11
- package/dist/chunk-72XFU2X2.js.map +0 -1
|
@@ -20,6 +20,7 @@ import kleur3 from 'kleur';
|
|
|
20
20
|
import { createRAG } from '@agentskit/rag';
|
|
21
21
|
import { Command } from 'commander';
|
|
22
22
|
import { input, select, checkbox, confirm } from '@inquirer/prompts';
|
|
23
|
+
import { validateAgentSchema } from '@agentskit/core/agent-schema';
|
|
23
24
|
|
|
24
25
|
async function loadJsonConfig(path5) {
|
|
25
26
|
try {
|
|
@@ -1818,6 +1819,635 @@ console.log(\`\\n\u2014 \${result.steps} steps \xB7 \${result.toolCalls.length}
|
|
|
1818
1819
|
"README.md": readmeFor(ctx)
|
|
1819
1820
|
};
|
|
1820
1821
|
}
|
|
1822
|
+
function buildAdapterServerImport(provider) {
|
|
1823
|
+
if (provider === "demo") return "";
|
|
1824
|
+
return `import { ${PROVIDER_IMPORT[provider]} } from '@agentskit/adapters'
|
|
1825
|
+
`;
|
|
1826
|
+
}
|
|
1827
|
+
function envExampleFor(provider) {
|
|
1828
|
+
const envKey = PROVIDER_ENV_KEY[provider];
|
|
1829
|
+
return envKey ? `${envKey}=
|
|
1830
|
+
` : "# No API key required for the demo provider\n";
|
|
1831
|
+
}
|
|
1832
|
+
function sveltekitStarter(ctx) {
|
|
1833
|
+
const deps = {
|
|
1834
|
+
"@agentskit/svelte": "^0.4.0",
|
|
1835
|
+
"@sveltejs/kit": "^2.0.0",
|
|
1836
|
+
svelte: "^5.0.0"
|
|
1837
|
+
};
|
|
1838
|
+
if (ctx.provider !== "demo") deps["@agentskit/adapters"] = "^0.4.0";
|
|
1839
|
+
const adapterCallStr = adapterCall(ctx.provider);
|
|
1840
|
+
const adapterImport2 = buildAdapterServerImport(ctx.provider);
|
|
1841
|
+
const demoSnippet = ctx.provider === "demo" ? demoAdapterSnippet() : "";
|
|
1842
|
+
return {
|
|
1843
|
+
"package.json": JSON.stringify(
|
|
1844
|
+
{
|
|
1845
|
+
name: "agentskit-sveltekit-app",
|
|
1846
|
+
private: true,
|
|
1847
|
+
type: "module",
|
|
1848
|
+
scripts: {
|
|
1849
|
+
dev: "vite dev",
|
|
1850
|
+
build: "vite build",
|
|
1851
|
+
preview: "vite preview",
|
|
1852
|
+
check: "svelte-check --tsconfig ./tsconfig.json"
|
|
1853
|
+
},
|
|
1854
|
+
dependencies: deps,
|
|
1855
|
+
devDependencies: {
|
|
1856
|
+
"@sveltejs/adapter-auto": "^4.0.0",
|
|
1857
|
+
"@sveltejs/vite-plugin-svelte": "^6.0.0",
|
|
1858
|
+
"svelte-check": "^4.0.0",
|
|
1859
|
+
typescript: "^5.5.0",
|
|
1860
|
+
vite: "^7.0.0"
|
|
1861
|
+
}
|
|
1862
|
+
},
|
|
1863
|
+
null,
|
|
1864
|
+
2
|
|
1865
|
+
) + "\n",
|
|
1866
|
+
"svelte.config.js": `import adapter from '@sveltejs/adapter-auto'
|
|
1867
|
+
import { vitePreprocess } from '@sveltejs/vite-plugin-svelte'
|
|
1868
|
+
|
|
1869
|
+
export default {
|
|
1870
|
+
preprocess: vitePreprocess(),
|
|
1871
|
+
kit: { adapter: adapter() },
|
|
1872
|
+
}
|
|
1873
|
+
`,
|
|
1874
|
+
"vite.config.ts": `import { sveltekit } from '@sveltejs/kit/vite'
|
|
1875
|
+
import { defineConfig } from 'vite'
|
|
1876
|
+
export default defineConfig({ plugins: [sveltekit()] })
|
|
1877
|
+
`,
|
|
1878
|
+
"tsconfig.json": JSON.stringify(
|
|
1879
|
+
{
|
|
1880
|
+
extends: "./.svelte-kit/tsconfig.json",
|
|
1881
|
+
compilerOptions: {
|
|
1882
|
+
allowJs: true,
|
|
1883
|
+
checkJs: true,
|
|
1884
|
+
esModuleInterop: true,
|
|
1885
|
+
forceConsistentCasingInFileNames: true,
|
|
1886
|
+
resolveJsonModule: true,
|
|
1887
|
+
skipLibCheck: true,
|
|
1888
|
+
sourceMap: true,
|
|
1889
|
+
strict: true,
|
|
1890
|
+
moduleResolution: "bundler"
|
|
1891
|
+
}
|
|
1892
|
+
},
|
|
1893
|
+
null,
|
|
1894
|
+
2
|
|
1895
|
+
) + "\n",
|
|
1896
|
+
"src/app.html": `<!doctype html>
|
|
1897
|
+
<html lang="en">
|
|
1898
|
+
<head>
|
|
1899
|
+
<meta charset="utf-8" />
|
|
1900
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
1901
|
+
%sveltekit.head%
|
|
1902
|
+
</head>
|
|
1903
|
+
<body>%sveltekit.body%</body>
|
|
1904
|
+
</html>
|
|
1905
|
+
`,
|
|
1906
|
+
"src/routes/+page.svelte": `<script lang="ts">
|
|
1907
|
+
import { useChat } from '@agentskit/svelte'
|
|
1908
|
+
import '@agentskit/svelte/theme'
|
|
1909
|
+
|
|
1910
|
+
const chat = useChat({ endpoint: '/api/chat' })
|
|
1911
|
+
</script>
|
|
1912
|
+
|
|
1913
|
+
<main>
|
|
1914
|
+
{#each $chat.messages as message (message.id)}
|
|
1915
|
+
<article data-ak-message data-role={message.role}>{message.content}</article>
|
|
1916
|
+
{/each}
|
|
1917
|
+
<form on:submit|preventDefault={() => chat.send($chat.input)}>
|
|
1918
|
+
<input bind:value={$chat.input} />
|
|
1919
|
+
<button>Send</button>
|
|
1920
|
+
</form>
|
|
1921
|
+
</main>
|
|
1922
|
+
`,
|
|
1923
|
+
"src/routes/api/chat/+server.ts": `import type { RequestHandler } from './$types'
|
|
1924
|
+
${adapterImport2}${demoSnippet}export const POST: RequestHandler = async ({ request }) => {
|
|
1925
|
+
const { messages } = await request.json()
|
|
1926
|
+
const adapter = ${adapterCallStr}
|
|
1927
|
+
const source = adapter.createSource({ messages: messages.map((m: { role: string; content: string }, i: number) => ({
|
|
1928
|
+
id: String(i), role: m.role, content: m.content,
|
|
1929
|
+
status: 'complete' as const, createdAt: new Date(0),
|
|
1930
|
+
})) })
|
|
1931
|
+
|
|
1932
|
+
const stream = new ReadableStream<Uint8Array>({
|
|
1933
|
+
async start(controller) {
|
|
1934
|
+
const encoder = new TextEncoder()
|
|
1935
|
+
for await (const chunk of source.stream()) {
|
|
1936
|
+
if (chunk.type === 'text') controller.enqueue(encoder.encode(chunk.content))
|
|
1937
|
+
}
|
|
1938
|
+
controller.close()
|
|
1939
|
+
},
|
|
1940
|
+
})
|
|
1941
|
+
return new Response(stream, { headers: { 'content-type': 'text/plain; charset=utf-8' } })
|
|
1942
|
+
}
|
|
1943
|
+
`,
|
|
1944
|
+
".env.example": envExampleFor(ctx.provider),
|
|
1945
|
+
".gitignore": "node_modules\n.svelte-kit\nbuild\n.env\n.env.local\n",
|
|
1946
|
+
"README.md": readmeFor(ctx)
|
|
1947
|
+
};
|
|
1948
|
+
}
|
|
1949
|
+
function nuxtStarter(ctx) {
|
|
1950
|
+
const deps = {
|
|
1951
|
+
"@agentskit/vue": "^0.4.0",
|
|
1952
|
+
nuxt: "^4.0.0",
|
|
1953
|
+
vue: "^3.5.0"
|
|
1954
|
+
};
|
|
1955
|
+
if (ctx.provider !== "demo") deps["@agentskit/adapters"] = "^0.4.0";
|
|
1956
|
+
const adapterCallStr = adapterCall(ctx.provider);
|
|
1957
|
+
const adapterImport2 = buildAdapterServerImport(ctx.provider);
|
|
1958
|
+
const demoSnippet = ctx.provider === "demo" ? demoAdapterSnippet() : "";
|
|
1959
|
+
return {
|
|
1960
|
+
"package.json": JSON.stringify(
|
|
1961
|
+
{
|
|
1962
|
+
name: "agentskit-nuxt-app",
|
|
1963
|
+
private: true,
|
|
1964
|
+
type: "module",
|
|
1965
|
+
scripts: {
|
|
1966
|
+
dev: "nuxt dev",
|
|
1967
|
+
build: "nuxt build",
|
|
1968
|
+
preview: "nuxt preview",
|
|
1969
|
+
generate: "nuxt generate"
|
|
1970
|
+
},
|
|
1971
|
+
dependencies: deps,
|
|
1972
|
+
devDependencies: { typescript: "^5.5.0" }
|
|
1973
|
+
},
|
|
1974
|
+
null,
|
|
1975
|
+
2
|
|
1976
|
+
) + "\n",
|
|
1977
|
+
"nuxt.config.ts": `export default defineNuxtConfig({
|
|
1978
|
+
compatibilityDate: '2026-04-01',
|
|
1979
|
+
modules: [],
|
|
1980
|
+
typescript: { strict: true },
|
|
1981
|
+
})
|
|
1982
|
+
`,
|
|
1983
|
+
"tsconfig.json": JSON.stringify(
|
|
1984
|
+
{ extends: "./.nuxt/tsconfig.json" },
|
|
1985
|
+
null,
|
|
1986
|
+
2
|
|
1987
|
+
) + "\n",
|
|
1988
|
+
"app.vue": `<script setup lang="ts">
|
|
1989
|
+
import { useChat } from '@agentskit/vue'
|
|
1990
|
+
import '@agentskit/vue/theme'
|
|
1991
|
+
|
|
1992
|
+
const { messages, input, send } = useChat({ endpoint: '/api/chat' })
|
|
1993
|
+
</script>
|
|
1994
|
+
|
|
1995
|
+
<template>
|
|
1996
|
+
<main>
|
|
1997
|
+
<article v-for="message in messages" :key="message.id" :data-role="message.role">
|
|
1998
|
+
{{ message.content }}
|
|
1999
|
+
</article>
|
|
2000
|
+
<form @submit.prevent="send(input)">
|
|
2001
|
+
<input v-model="input" />
|
|
2002
|
+
<button>Send</button>
|
|
2003
|
+
</form>
|
|
2004
|
+
</main>
|
|
2005
|
+
</template>
|
|
2006
|
+
`,
|
|
2007
|
+
"server/api/chat.post.ts": `${adapterImport2}${demoSnippet}export default defineEventHandler(async (event) => {
|
|
2008
|
+
const { messages } = await readBody<{ messages: Array<{ role: string; content: string }> }>(event)
|
|
2009
|
+
const adapter = ${adapterCallStr}
|
|
2010
|
+
const source = adapter.createSource({ messages: messages.map((m, i) => ({
|
|
2011
|
+
id: String(i), role: m.role as 'user' | 'assistant' | 'system',
|
|
2012
|
+
content: m.content, status: 'complete' as const, createdAt: new Date(0),
|
|
2013
|
+
})) })
|
|
2014
|
+
|
|
2015
|
+
setHeader(event, 'content-type', 'text/plain; charset=utf-8')
|
|
2016
|
+
return sendStream(event, new ReadableStream<Uint8Array>({
|
|
2017
|
+
async start(controller) {
|
|
2018
|
+
const encoder = new TextEncoder()
|
|
2019
|
+
for await (const chunk of source.stream()) {
|
|
2020
|
+
if (chunk.type === 'text') controller.enqueue(encoder.encode(chunk.content))
|
|
2021
|
+
}
|
|
2022
|
+
controller.close()
|
|
2023
|
+
},
|
|
2024
|
+
}))
|
|
2025
|
+
})
|
|
2026
|
+
`,
|
|
2027
|
+
".env.example": envExampleFor(ctx.provider),
|
|
2028
|
+
".gitignore": "node_modules\n.nuxt\n.output\n.env\n.env.local\n",
|
|
2029
|
+
"README.md": readmeFor(ctx)
|
|
2030
|
+
};
|
|
2031
|
+
}
|
|
2032
|
+
function viteInkStarter(ctx) {
|
|
2033
|
+
const deps = {
|
|
2034
|
+
"@agentskit/ink": "^0.4.0",
|
|
2035
|
+
ink: "^7.0.0",
|
|
2036
|
+
react: "^19.0.0"
|
|
2037
|
+
};
|
|
2038
|
+
if (ctx.provider !== "demo") deps["@agentskit/adapters"] = "^0.4.0";
|
|
2039
|
+
if (ctx.tools.length > 0) deps["@agentskit/tools"] = "^0.4.0";
|
|
2040
|
+
return {
|
|
2041
|
+
"package.json": JSON.stringify(
|
|
2042
|
+
{
|
|
2043
|
+
name: "agentskit-vite-ink-app",
|
|
2044
|
+
private: true,
|
|
2045
|
+
type: "module",
|
|
2046
|
+
scripts: {
|
|
2047
|
+
dev: "vite-node --watch src/index.tsx",
|
|
2048
|
+
start: "vite-node src/index.tsx",
|
|
2049
|
+
build: "vite build"
|
|
2050
|
+
},
|
|
2051
|
+
dependencies: deps,
|
|
2052
|
+
devDependencies: {
|
|
2053
|
+
"@types/react": "^19.0.0",
|
|
2054
|
+
"vite-node": "^4.0.0",
|
|
2055
|
+
vite: "^7.0.0",
|
|
2056
|
+
typescript: "^5.5.0"
|
|
2057
|
+
}
|
|
2058
|
+
},
|
|
2059
|
+
null,
|
|
2060
|
+
2
|
|
2061
|
+
) + "\n",
|
|
2062
|
+
"vite.config.ts": `import { defineConfig } from 'vite'
|
|
2063
|
+
export default defineConfig({
|
|
2064
|
+
build: { ssr: true, target: 'node22', rollupOptions: { input: 'src/index.tsx' } },
|
|
2065
|
+
})
|
|
2066
|
+
`,
|
|
2067
|
+
"tsconfig.json": JSON.stringify(
|
|
2068
|
+
{
|
|
2069
|
+
compilerOptions: {
|
|
2070
|
+
target: "ES2022",
|
|
2071
|
+
module: "ESNext",
|
|
2072
|
+
moduleResolution: "bundler",
|
|
2073
|
+
jsx: "react-jsx",
|
|
2074
|
+
strict: true,
|
|
2075
|
+
noEmit: true,
|
|
2076
|
+
skipLibCheck: true
|
|
2077
|
+
},
|
|
2078
|
+
include: ["src"]
|
|
2079
|
+
},
|
|
2080
|
+
null,
|
|
2081
|
+
2
|
|
2082
|
+
) + "\n",
|
|
2083
|
+
"src/index.tsx": `import React from 'react'
|
|
2084
|
+
import { render } from 'ink'
|
|
2085
|
+
import { ChatContainer, InputBar, Message, useChat } from '@agentskit/ink'
|
|
2086
|
+
${adapterImport(ctx.provider)}${toolImports(ctx.tools)}
|
|
2087
|
+
${ctx.provider === "demo" ? demoAdapterSnippet() : ""}function App() {
|
|
2088
|
+
const chat = useChat({
|
|
2089
|
+
adapter: ${adapterCall(ctx.provider)},${ctx.tools.length > 0 ? `
|
|
2090
|
+
tools: ${toolList(ctx.tools)},` : ""}
|
|
2091
|
+
})
|
|
2092
|
+
|
|
2093
|
+
return (
|
|
2094
|
+
<ChatContainer>
|
|
2095
|
+
{chat.messages.map(message => (
|
|
2096
|
+
<Message key={message.id} message={message} />
|
|
2097
|
+
))}
|
|
2098
|
+
<InputBar chat={chat} />
|
|
2099
|
+
</ChatContainer>
|
|
2100
|
+
)
|
|
2101
|
+
}
|
|
2102
|
+
|
|
2103
|
+
render(<App />)
|
|
2104
|
+
`,
|
|
2105
|
+
".env.example": envExampleFor(ctx.provider),
|
|
2106
|
+
".gitignore": "node_modules\ndist\n.env\n.env.local\n.agentskit-history.*\n",
|
|
2107
|
+
"README.md": readmeFor(ctx)
|
|
2108
|
+
};
|
|
2109
|
+
}
|
|
2110
|
+
function cloudflareWorkersStarter(ctx) {
|
|
2111
|
+
const deps = {
|
|
2112
|
+
"itty-router": "^5.0.0"
|
|
2113
|
+
};
|
|
2114
|
+
if (ctx.provider !== "demo") deps["@agentskit/adapters"] = "^0.4.0";
|
|
2115
|
+
const adapterCallEdge = ctx.provider === "demo" ? "demoAdapter()" : ctx.provider === "ollama" ? `ollama({ model: '${PROVIDER_DEFAULT_MODEL[ctx.provider]}' })` : `${PROVIDER_IMPORT[ctx.provider]}({ apiKey: env.${PROVIDER_ENV_KEY[ctx.provider]} ?? '', model: '${PROVIDER_DEFAULT_MODEL[ctx.provider]}' })`;
|
|
2116
|
+
const adapterImport2 = buildAdapterServerImport(ctx.provider);
|
|
2117
|
+
const demoSnippet = ctx.provider === "demo" ? demoAdapterSnippet() : "";
|
|
2118
|
+
const envKey = PROVIDER_ENV_KEY[ctx.provider];
|
|
2119
|
+
return {
|
|
2120
|
+
"package.json": JSON.stringify(
|
|
2121
|
+
{
|
|
2122
|
+
name: "agentskit-cf-worker",
|
|
2123
|
+
private: true,
|
|
2124
|
+
type: "module",
|
|
2125
|
+
scripts: {
|
|
2126
|
+
dev: "wrangler dev",
|
|
2127
|
+
deploy: "wrangler deploy"
|
|
2128
|
+
},
|
|
2129
|
+
dependencies: deps,
|
|
2130
|
+
devDependencies: {
|
|
2131
|
+
"@cloudflare/workers-types": "^4.0.0",
|
|
2132
|
+
typescript: "^5.5.0",
|
|
2133
|
+
wrangler: "^3.0.0"
|
|
2134
|
+
}
|
|
2135
|
+
},
|
|
2136
|
+
null,
|
|
2137
|
+
2
|
|
2138
|
+
) + "\n",
|
|
2139
|
+
"wrangler.toml": `name = "agentskit-cf-worker"
|
|
2140
|
+
main = "src/worker.ts"
|
|
2141
|
+
compatibility_date = "2026-04-01"
|
|
2142
|
+
compatibility_flags = ["nodejs_compat"]
|
|
2143
|
+
|
|
2144
|
+
# Bind D1 + KV when you wire memory:
|
|
2145
|
+
# [[d1_databases]]
|
|
2146
|
+
# binding = "DB"
|
|
2147
|
+
# database_name = "agentskit"
|
|
2148
|
+
#
|
|
2149
|
+
# [[kv_namespaces]]
|
|
2150
|
+
# binding = "KV"
|
|
2151
|
+
# id = "..."
|
|
2152
|
+
|
|
2153
|
+
[vars]
|
|
2154
|
+
${envKey ? `# Set ${envKey} via 'wrangler secret put ${envKey}'` : "# No API key required for the demo provider"}
|
|
2155
|
+
`,
|
|
2156
|
+
"tsconfig.json": JSON.stringify(
|
|
2157
|
+
{
|
|
2158
|
+
compilerOptions: {
|
|
2159
|
+
target: "ES2022",
|
|
2160
|
+
module: "ESNext",
|
|
2161
|
+
moduleResolution: "bundler",
|
|
2162
|
+
lib: ["ES2022"],
|
|
2163
|
+
types: ["@cloudflare/workers-types"],
|
|
2164
|
+
strict: true,
|
|
2165
|
+
noEmit: true,
|
|
2166
|
+
skipLibCheck: true
|
|
2167
|
+
},
|
|
2168
|
+
include: ["src"]
|
|
2169
|
+
},
|
|
2170
|
+
null,
|
|
2171
|
+
2
|
|
2172
|
+
) + "\n",
|
|
2173
|
+
"src/worker.ts": `import { Router } from 'itty-router'
|
|
2174
|
+
${adapterImport2}
|
|
2175
|
+
${demoSnippet}interface Env {
|
|
2176
|
+
${envKey ? `${envKey}: string` : "/* no env vars */"}
|
|
2177
|
+
}
|
|
2178
|
+
|
|
2179
|
+
const router = Router()
|
|
2180
|
+
|
|
2181
|
+
router.post('/chat', async (request: Request, env: Env) => {
|
|
2182
|
+
const { messages } = await request.json() as { messages: Array<{ role: string; content: string }> }
|
|
2183
|
+
const adapter = ${adapterCallEdge}
|
|
2184
|
+
const source = adapter.createSource({ messages: messages.map((m, i) => ({
|
|
2185
|
+
id: String(i), role: m.role as 'user' | 'assistant' | 'system',
|
|
2186
|
+
content: m.content, status: 'complete' as const, createdAt: new Date(0),
|
|
2187
|
+
})) })
|
|
2188
|
+
|
|
2189
|
+
const stream = new ReadableStream<Uint8Array>({
|
|
2190
|
+
async start(controller) {
|
|
2191
|
+
const encoder = new TextEncoder()
|
|
2192
|
+
for await (const chunk of source.stream()) {
|
|
2193
|
+
if (chunk.type === 'text') controller.enqueue(encoder.encode(chunk.content))
|
|
2194
|
+
}
|
|
2195
|
+
controller.close()
|
|
2196
|
+
},
|
|
2197
|
+
})
|
|
2198
|
+
return new Response(stream, { headers: { 'content-type': 'text/plain; charset=utf-8' } })
|
|
2199
|
+
})
|
|
2200
|
+
|
|
2201
|
+
router.all('*', () => new Response('not found', { status: 404 }))
|
|
2202
|
+
|
|
2203
|
+
export default {
|
|
2204
|
+
fetch: (req: Request, env: Env, ctx: ExecutionContext) => router.handle(req, env, ctx),
|
|
2205
|
+
} satisfies ExportedHandler<Env>
|
|
2206
|
+
`,
|
|
2207
|
+
".env.example": envExampleFor(ctx.provider),
|
|
2208
|
+
".gitignore": "node_modules\n.wrangler\n.dev.vars\n.env\n.env.local\n",
|
|
2209
|
+
"README.md": readmeFor(ctx)
|
|
2210
|
+
};
|
|
2211
|
+
}
|
|
2212
|
+
function bunStarter(ctx) {
|
|
2213
|
+
const deps = {};
|
|
2214
|
+
if (ctx.provider !== "demo") deps["@agentskit/adapters"] = "^0.4.0";
|
|
2215
|
+
const adapterCallStr = adapterCall(ctx.provider);
|
|
2216
|
+
const adapterImport2 = buildAdapterServerImport(ctx.provider);
|
|
2217
|
+
const demoSnippet = ctx.provider === "demo" ? demoAdapterSnippet() : "";
|
|
2218
|
+
return {
|
|
2219
|
+
"package.json": JSON.stringify(
|
|
2220
|
+
{
|
|
2221
|
+
name: "agentskit-bun-server",
|
|
2222
|
+
private: true,
|
|
2223
|
+
type: "module",
|
|
2224
|
+
scripts: {
|
|
2225
|
+
dev: "bun --hot src/server.ts",
|
|
2226
|
+
start: "bun src/server.ts"
|
|
2227
|
+
},
|
|
2228
|
+
dependencies: deps,
|
|
2229
|
+
devDependencies: { typescript: "^5.5.0" }
|
|
2230
|
+
},
|
|
2231
|
+
null,
|
|
2232
|
+
2
|
|
2233
|
+
) + "\n",
|
|
2234
|
+
"tsconfig.json": JSON.stringify(
|
|
2235
|
+
{
|
|
2236
|
+
compilerOptions: {
|
|
2237
|
+
target: "ES2022",
|
|
2238
|
+
module: "ESNext",
|
|
2239
|
+
moduleResolution: "bundler",
|
|
2240
|
+
types: ["bun-types"],
|
|
2241
|
+
strict: true,
|
|
2242
|
+
noEmit: true,
|
|
2243
|
+
skipLibCheck: true
|
|
2244
|
+
},
|
|
2245
|
+
include: ["src"]
|
|
2246
|
+
},
|
|
2247
|
+
null,
|
|
2248
|
+
2
|
|
2249
|
+
) + "\n",
|
|
2250
|
+
"src/server.ts": `${adapterImport2}${demoSnippet}const adapter = ${adapterCallStr}
|
|
2251
|
+
|
|
2252
|
+
const server = Bun.serve({
|
|
2253
|
+
port: Number(process.env.PORT ?? 3000),
|
|
2254
|
+
async fetch(request) {
|
|
2255
|
+
const url = new URL(request.url)
|
|
2256
|
+
if (request.method === 'POST' && url.pathname === '/chat') {
|
|
2257
|
+
const { messages } = await request.json() as { messages: Array<{ role: string; content: string }> }
|
|
2258
|
+
const source = adapter.createSource({ messages: messages.map((m, i) => ({
|
|
2259
|
+
id: String(i), role: m.role as 'user' | 'assistant' | 'system',
|
|
2260
|
+
content: m.content, status: 'complete' as const, createdAt: new Date(0),
|
|
2261
|
+
})) })
|
|
2262
|
+
const stream = new ReadableStream<Uint8Array>({
|
|
2263
|
+
async start(controller) {
|
|
2264
|
+
const encoder = new TextEncoder()
|
|
2265
|
+
for await (const chunk of source.stream()) {
|
|
2266
|
+
if (chunk.type === 'text') controller.enqueue(encoder.encode(chunk.content))
|
|
2267
|
+
}
|
|
2268
|
+
controller.close()
|
|
2269
|
+
},
|
|
2270
|
+
})
|
|
2271
|
+
return new Response(stream, { headers: { 'content-type': 'text/plain; charset=utf-8' } })
|
|
2272
|
+
}
|
|
2273
|
+
if (url.pathname === '/') {
|
|
2274
|
+
return new Response(\`<!doctype html><title>AgentsKit Bun starter</title>
|
|
2275
|
+
<body><pre>POST /chat with { messages: [...] }</pre></body>\`, {
|
|
2276
|
+
headers: { 'content-type': 'text/html' },
|
|
2277
|
+
})
|
|
2278
|
+
}
|
|
2279
|
+
return new Response('not found', { status: 404 })
|
|
2280
|
+
},
|
|
2281
|
+
})
|
|
2282
|
+
|
|
2283
|
+
console.log(\`Listening on http://localhost:\${server.port}\`)
|
|
2284
|
+
`,
|
|
2285
|
+
".env.example": envExampleFor(ctx.provider),
|
|
2286
|
+
".gitignore": "node_modules\n.env\n.env.local\nbun.lockb\n",
|
|
2287
|
+
"README.md": readmeFor(ctx)
|
|
2288
|
+
};
|
|
2289
|
+
}
|
|
2290
|
+
function nextjsStarter(ctx) {
|
|
2291
|
+
const deps = {
|
|
2292
|
+
"@agentskit/react": "^0.4.0",
|
|
2293
|
+
next: "^15.0.0",
|
|
2294
|
+
react: "^19.0.0",
|
|
2295
|
+
"react-dom": "^19.0.0"
|
|
2296
|
+
};
|
|
2297
|
+
if (ctx.provider !== "demo") deps["@agentskit/adapters"] = "^0.4.0";
|
|
2298
|
+
if (ctx.tools.length > 0) deps["@agentskit/tools"] = "^0.4.0";
|
|
2299
|
+
const envKey = PROVIDER_ENV_KEY[ctx.provider];
|
|
2300
|
+
const adapter = adapterCall(ctx.provider);
|
|
2301
|
+
const apiAdapterImport = ctx.provider === "demo" ? "" : `import { ${PROVIDER_IMPORT[ctx.provider]} } from '@agentskit/adapters'
|
|
2302
|
+
`;
|
|
2303
|
+
const apiDemoSnippet = ctx.provider === "demo" ? demoAdapterSnippet() : "";
|
|
2304
|
+
return {
|
|
2305
|
+
"package.json": JSON.stringify(
|
|
2306
|
+
{
|
|
2307
|
+
name: "agentskit-nextjs-app",
|
|
2308
|
+
private: true,
|
|
2309
|
+
type: "module",
|
|
2310
|
+
scripts: {
|
|
2311
|
+
dev: "next dev",
|
|
2312
|
+
build: "next build",
|
|
2313
|
+
start: "next start",
|
|
2314
|
+
lint: "next lint"
|
|
2315
|
+
},
|
|
2316
|
+
dependencies: deps,
|
|
2317
|
+
devDependencies: {
|
|
2318
|
+
"@types/node": "^22.0.0",
|
|
2319
|
+
"@types/react": "^19.0.0",
|
|
2320
|
+
"@types/react-dom": "^19.0.0",
|
|
2321
|
+
typescript: "^5.5.0"
|
|
2322
|
+
}
|
|
2323
|
+
},
|
|
2324
|
+
null,
|
|
2325
|
+
2
|
|
2326
|
+
) + "\n",
|
|
2327
|
+
"next.config.mjs": `/** @type {import('next').NextConfig} */
|
|
2328
|
+
const nextConfig = {}
|
|
2329
|
+
export default nextConfig
|
|
2330
|
+
`,
|
|
2331
|
+
"tsconfig.json": JSON.stringify(
|
|
2332
|
+
{
|
|
2333
|
+
compilerOptions: {
|
|
2334
|
+
target: "ES2022",
|
|
2335
|
+
lib: ["dom", "dom.iterable", "ES2022"],
|
|
2336
|
+
allowJs: true,
|
|
2337
|
+
skipLibCheck: true,
|
|
2338
|
+
strict: true,
|
|
2339
|
+
noEmit: true,
|
|
2340
|
+
esModuleInterop: true,
|
|
2341
|
+
module: "ESNext",
|
|
2342
|
+
moduleResolution: "bundler",
|
|
2343
|
+
resolveJsonModule: true,
|
|
2344
|
+
isolatedModules: true,
|
|
2345
|
+
jsx: "preserve",
|
|
2346
|
+
incremental: true,
|
|
2347
|
+
plugins: [{ name: "next" }],
|
|
2348
|
+
paths: { "@/*": ["./*"] }
|
|
2349
|
+
},
|
|
2350
|
+
include: ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
|
|
2351
|
+
exclude: ["node_modules"]
|
|
2352
|
+
},
|
|
2353
|
+
null,
|
|
2354
|
+
2
|
|
2355
|
+
) + "\n",
|
|
2356
|
+
"app/layout.tsx": `import type { ReactNode } from 'react'
|
|
2357
|
+
import '@agentskit/react/theme'
|
|
2358
|
+
|
|
2359
|
+
export const metadata = { title: 'AgentsKit \xB7 Next.js Starter' }
|
|
2360
|
+
|
|
2361
|
+
export default function RootLayout({ children }: { children: ReactNode }) {
|
|
2362
|
+
return (
|
|
2363
|
+
<html lang="en">
|
|
2364
|
+
<body>{children}</body>
|
|
2365
|
+
</html>
|
|
2366
|
+
)
|
|
2367
|
+
}
|
|
2368
|
+
`,
|
|
2369
|
+
"app/page.tsx": `'use client'
|
|
2370
|
+
|
|
2371
|
+
import { ChatContainer, InputBar, Message, useChat } from '@agentskit/react'
|
|
2372
|
+
import { genericAdapter } from './chat-adapter'
|
|
2373
|
+
|
|
2374
|
+
export default function Page() {
|
|
2375
|
+
const chat = useChat({ adapter: genericAdapter('/api/chat') })
|
|
2376
|
+
|
|
2377
|
+
return (
|
|
2378
|
+
<main style={{ display: 'grid', placeItems: 'center', minHeight: '100dvh' }}>
|
|
2379
|
+
<ChatContainer>
|
|
2380
|
+
{chat.messages.map(message => (
|
|
2381
|
+
<Message key={message.id} message={message} />
|
|
2382
|
+
))}
|
|
2383
|
+
<InputBar chat={chat} />
|
|
2384
|
+
</ChatContainer>
|
|
2385
|
+
</main>
|
|
2386
|
+
)
|
|
2387
|
+
}
|
|
2388
|
+
`,
|
|
2389
|
+
"app/chat-adapter.ts": `import { generic } from '@agentskit/adapters'
|
|
2390
|
+
|
|
2391
|
+
export const genericAdapter = (route: string) => generic({
|
|
2392
|
+
fetch: async ({ messages, signal }) => {
|
|
2393
|
+
const response = await fetch(route, {
|
|
2394
|
+
method: 'POST',
|
|
2395
|
+
headers: { 'Content-Type': 'application/json' },
|
|
2396
|
+
body: JSON.stringify({ messages }),
|
|
2397
|
+
signal,
|
|
2398
|
+
})
|
|
2399
|
+
if (!response.body) throw new Error('No body returned from /api/chat')
|
|
2400
|
+
return response
|
|
2401
|
+
},
|
|
2402
|
+
})
|
|
2403
|
+
`,
|
|
2404
|
+
"app/api/chat/route.ts": `${apiAdapterImport}${apiDemoSnippet}export const runtime = 'edge'
|
|
2405
|
+
|
|
2406
|
+
export async function POST(request: Request) {
|
|
2407
|
+
const { messages } = await request.json() as { messages: Array<{ role: string; content: string }> }
|
|
2408
|
+
|
|
2409
|
+
const adapter = ${adapter}
|
|
2410
|
+
|
|
2411
|
+
const source = adapter.createSource({ messages: messages.map((message, index) => ({
|
|
2412
|
+
id: String(index),
|
|
2413
|
+
role: message.role as 'user' | 'assistant' | 'system',
|
|
2414
|
+
content: message.content,
|
|
2415
|
+
status: 'complete' as const,
|
|
2416
|
+
createdAt: new Date(0),
|
|
2417
|
+
})) })
|
|
2418
|
+
|
|
2419
|
+
const stream = new ReadableStream<Uint8Array>({
|
|
2420
|
+
async start(controller) {
|
|
2421
|
+
const encoder = new TextEncoder()
|
|
2422
|
+
try {
|
|
2423
|
+
for await (const chunk of source.stream()) {
|
|
2424
|
+
if (chunk.type === 'text') controller.enqueue(encoder.encode(chunk.content))
|
|
2425
|
+
}
|
|
2426
|
+
} catch (err) {
|
|
2427
|
+
controller.error(err)
|
|
2428
|
+
return
|
|
2429
|
+
}
|
|
2430
|
+
controller.close()
|
|
2431
|
+
},
|
|
2432
|
+
})
|
|
2433
|
+
|
|
2434
|
+
return new Response(stream, {
|
|
2435
|
+
headers: { 'Content-Type': 'text/plain; charset=utf-8', 'Cache-Control': 'no-cache' },
|
|
2436
|
+
})
|
|
2437
|
+
}
|
|
2438
|
+
`,
|
|
2439
|
+
".env.example": envKey ? `${envKey}=
|
|
2440
|
+
` : "# No API key required for the demo provider\n",
|
|
2441
|
+
".gitignore": `node_modules
|
|
2442
|
+
.next
|
|
2443
|
+
out
|
|
2444
|
+
.env
|
|
2445
|
+
.env.local
|
|
2446
|
+
.agentskit-history.*
|
|
2447
|
+
`,
|
|
2448
|
+
"README.md": readmeFor(ctx)
|
|
2449
|
+
};
|
|
2450
|
+
}
|
|
1821
2451
|
function readmeFor(ctx) {
|
|
1822
2452
|
const installCmd = ctx.pm === "npm" ? "npm install" : `${ctx.pm} install`;
|
|
1823
2453
|
const runCmd = ctx.pm === "npm" ? "npm run dev" : `${ctx.pm} dev`;
|
|
@@ -1855,9 +2485,15 @@ ISC
|
|
|
1855
2485
|
}
|
|
1856
2486
|
var TEMPLATE_FN = {
|
|
1857
2487
|
react: reactStarter,
|
|
2488
|
+
nextjs: nextjsStarter,
|
|
1858
2489
|
ink: inkStarter,
|
|
1859
2490
|
runtime: runtimeStarter,
|
|
1860
|
-
"multi-agent": multiAgentStarter
|
|
2491
|
+
"multi-agent": multiAgentStarter,
|
|
2492
|
+
sveltekit: sveltekitStarter,
|
|
2493
|
+
nuxt: nuxtStarter,
|
|
2494
|
+
"vite-ink": viteInkStarter,
|
|
2495
|
+
"cloudflare-workers": cloudflareWorkersStarter,
|
|
2496
|
+
bun: bunStarter
|
|
1861
2497
|
};
|
|
1862
2498
|
async function writeStarterProject(options) {
|
|
1863
2499
|
const ctx = {
|
|
@@ -2656,7 +3292,13 @@ ${kleur3.bold().green("\u25B2")} ${kleur3.bold("agentskit init")}
|
|
|
2656
3292
|
default: defaults.template ?? "react",
|
|
2657
3293
|
choices: [
|
|
2658
3294
|
{ name: "React chat (Vite + browser)", value: "react", description: "Streaming UI with @agentskit/react" },
|
|
3295
|
+
{ name: "Next.js chat (App Router + Route Handler)", value: "nextjs", description: "app/api/chat streams to a useChat client" },
|
|
3296
|
+
{ name: "SvelteKit chat", value: "sveltekit", description: "@agentskit/svelte client + server route streaming" },
|
|
3297
|
+
{ name: "Nuxt chat", value: "nuxt", description: "@agentskit/vue composable + Nitro server route streaming" },
|
|
2659
3298
|
{ name: "Ink chat (terminal UI)", value: "ink", description: "Same chat but in your terminal" },
|
|
3299
|
+
{ name: "Vite + Ink (terminal, hot-reload)", value: "vite-ink", description: "Ink chat with vite-node hot reload" },
|
|
3300
|
+
{ name: "Cloudflare Workers (edge)", value: "cloudflare-workers", description: "Edge runtime with itty-router + streaming" },
|
|
3301
|
+
{ name: "Bun server", value: "bun", description: "Bun.serve with hot reload" },
|
|
2660
3302
|
{ name: "Runtime (headless agent, no UI)", value: "runtime", description: "Autonomous task \u2192 result" },
|
|
2661
3303
|
{ name: "Multi-agent (planner + delegates)", value: "multi-agent", description: "Supervisor pattern, ready to extend" }
|
|
2662
3304
|
]
|
|
@@ -2765,7 +3407,7 @@ function printNextSteps(options) {
|
|
|
2765
3407
|
|
|
2766
3408
|
// src/commands/init.ts
|
|
2767
3409
|
function registerInitCommand(program) {
|
|
2768
|
-
program.command("init").description("Generate a starter project. Run with no flags for interactive mode.").option("--template <template>", "Starter template (react|ink|runtime|multi-agent)").option("--dir <directory>", "Target directory", "agentskit-app").option("--provider <provider>", "LLM provider (openai|anthropic|gemini|ollama|demo)").option("--tools <tools>", "Comma-separated tools (web_search,filesystem,shell)").option("--memory <backend>", "Memory backend (none|file|sqlite)").option("--pm <packageManager>", "Package manager (pnpm|npm|yarn|bun)").option("-y, --yes", "Skip interactive prompts; use flag values + defaults").action(async (rawOptions) => {
|
|
3410
|
+
program.command("init").description("Generate a starter project. Run with no flags for interactive mode.").option("--template <template>", "Starter template (react|nextjs|sveltekit|nuxt|ink|vite-ink|cloudflare-workers|bun|runtime|multi-agent)").option("--dir <directory>", "Target directory", "agentskit-app").option("--provider <provider>", "LLM provider (openai|anthropic|gemini|ollama|demo)").option("--tools <tools>", "Comma-separated tools (web_search,filesystem,shell)").option("--memory <backend>", "Memory backend (none|file|sqlite)").option("--pm <packageManager>", "Package manager (pnpm|npm|yarn|bun)").option("-y, --yes", "Skip interactive prompts; use flag values + defaults").action(async (rawOptions) => {
|
|
2769
3411
|
const isCi = !process.stdout.isTTY || rawOptions.yes || rawOptions.template;
|
|
2770
3412
|
let resolved;
|
|
2771
3413
|
if (isCi) {
|
|
@@ -2950,6 +3592,187 @@ function registerRagCommand(program) {
|
|
|
2950
3592
|
});
|
|
2951
3593
|
}
|
|
2952
3594
|
|
|
3595
|
+
// src/ai/scaffold.ts
|
|
3596
|
+
function snakeToCamel(name) {
|
|
3597
|
+
return name.replace(/[-_](\w)/g, (_, c) => c.toUpperCase());
|
|
3598
|
+
}
|
|
3599
|
+
function toolStub(tool) {
|
|
3600
|
+
const fnName = snakeToCamel(tool.name);
|
|
3601
|
+
const schema = tool.schema ? JSON.stringify(tool.schema, null, 2) : '{ type: "object", properties: {} }';
|
|
3602
|
+
return `import { defineTool } from '@agentskit/core'
|
|
3603
|
+
|
|
3604
|
+
/**
|
|
3605
|
+
* ${tool.description ?? tool.name}
|
|
3606
|
+
* ${tool.implementation ? `
|
|
3607
|
+
* Implementation hint: ${tool.implementation}` : ""}
|
|
3608
|
+
*/
|
|
3609
|
+
export const ${fnName} = defineTool({
|
|
3610
|
+
name: '${tool.name}',
|
|
3611
|
+
description: ${JSON.stringify(tool.description ?? "")},
|
|
3612
|
+
schema: ${schema} as const,
|
|
3613
|
+
${tool.requiresConfirmation ? "requiresConfirmation: true," : ""}
|
|
3614
|
+
async execute(args) {
|
|
3615
|
+
// TODO: implement ${tool.name}
|
|
3616
|
+
return { args }
|
|
3617
|
+
},
|
|
3618
|
+
})
|
|
3619
|
+
`;
|
|
3620
|
+
}
|
|
3621
|
+
function indexTs(schema) {
|
|
3622
|
+
const toolImports2 = (schema.tools ?? []).map((t) => `import { ${snakeToCamel(t.name)} } from './tools/${t.name}'`).join("\n");
|
|
3623
|
+
const toolList2 = (schema.tools ?? []).map((t) => snakeToCamel(t.name)).join(", ");
|
|
3624
|
+
return `import { createRuntime } from '@agentskit/runtime'
|
|
3625
|
+
${toolImports2}
|
|
3626
|
+
|
|
3627
|
+
export const agent = {
|
|
3628
|
+
name: '${schema.name}',
|
|
3629
|
+
systemPrompt: ${JSON.stringify(schema.systemPrompt ?? "")},
|
|
3630
|
+
tools: [${toolList2}],
|
|
3631
|
+
}
|
|
3632
|
+
|
|
3633
|
+
export function createAgent(adapter: Parameters<typeof createRuntime>[0]['adapter']) {
|
|
3634
|
+
return createRuntime({
|
|
3635
|
+
adapter,
|
|
3636
|
+
systemPrompt: agent.systemPrompt,
|
|
3637
|
+
tools: agent.tools,
|
|
3638
|
+
})
|
|
3639
|
+
}
|
|
3640
|
+
`;
|
|
3641
|
+
}
|
|
3642
|
+
function readme(schema) {
|
|
3643
|
+
const lines = [];
|
|
3644
|
+
lines.push(`# ${schema.name}`);
|
|
3645
|
+
lines.push("");
|
|
3646
|
+
if (schema.description) lines.push(schema.description, "");
|
|
3647
|
+
lines.push(`## Model`);
|
|
3648
|
+
lines.push("");
|
|
3649
|
+
lines.push(`- Provider: \`${schema.model.provider}\``);
|
|
3650
|
+
if (schema.model.model) lines.push(`- Model: \`${schema.model.model}\``);
|
|
3651
|
+
lines.push("");
|
|
3652
|
+
if (schema.tools && schema.tools.length > 0) {
|
|
3653
|
+
lines.push("## Tools");
|
|
3654
|
+
lines.push("");
|
|
3655
|
+
for (const t of schema.tools) {
|
|
3656
|
+
lines.push(`- \`${t.name}\` \u2014 ${t.description ?? ""}`);
|
|
3657
|
+
}
|
|
3658
|
+
lines.push("");
|
|
3659
|
+
}
|
|
3660
|
+
if (schema.skills && schema.skills.length > 0) {
|
|
3661
|
+
lines.push("## Skills");
|
|
3662
|
+
lines.push("");
|
|
3663
|
+
for (const s of schema.skills) lines.push(`- ${s}`);
|
|
3664
|
+
lines.push("");
|
|
3665
|
+
}
|
|
3666
|
+
lines.push("## Generated by");
|
|
3667
|
+
lines.push("");
|
|
3668
|
+
lines.push('`npx agentskit ai "<description>"`');
|
|
3669
|
+
lines.push("");
|
|
3670
|
+
return lines.join("\n");
|
|
3671
|
+
}
|
|
3672
|
+
function scaffoldAgent(schema) {
|
|
3673
|
+
const files = [
|
|
3674
|
+
{ path: "agent.json", content: JSON.stringify(schema, null, 2) + "\n" },
|
|
3675
|
+
{ path: "agent.ts", content: indexTs(schema) },
|
|
3676
|
+
{ path: "README.md", content: readme(schema) }
|
|
3677
|
+
];
|
|
3678
|
+
for (const tool of schema.tools ?? []) {
|
|
3679
|
+
files.push({ path: `tools/${tool.name}.ts`, content: toolStub(tool) });
|
|
3680
|
+
}
|
|
3681
|
+
return files;
|
|
3682
|
+
}
|
|
3683
|
+
async function writeScaffold(files, outDir, opts = {}) {
|
|
3684
|
+
const { writeFile: writeFile2, mkdir: mkdir2, access } = await import('fs/promises');
|
|
3685
|
+
const { dirname, join: join5 } = await import('path');
|
|
3686
|
+
const written = [];
|
|
3687
|
+
for (const f of files) {
|
|
3688
|
+
const full = join5(outDir, f.path);
|
|
3689
|
+
await mkdir2(dirname(full), { recursive: true });
|
|
3690
|
+
if (!opts.overwrite) {
|
|
3691
|
+
try {
|
|
3692
|
+
await access(full);
|
|
3693
|
+
continue;
|
|
3694
|
+
} catch {
|
|
3695
|
+
}
|
|
3696
|
+
}
|
|
3697
|
+
await writeFile2(full, f.content, "utf8");
|
|
3698
|
+
written.push(f.path);
|
|
3699
|
+
}
|
|
3700
|
+
return written;
|
|
3701
|
+
}
|
|
3702
|
+
var PLANNER_SYSTEM_PROMPT = `You design AI agents for the AgentsKit framework.
|
|
3703
|
+
Given a user's plain-language description, return a single JSON object
|
|
3704
|
+
matching the AgentsKit AgentSchema type. Do not include commentary or
|
|
3705
|
+
markdown fences \u2014 emit raw JSON only.
|
|
3706
|
+
|
|
3707
|
+
Schema:
|
|
3708
|
+
{
|
|
3709
|
+
"name": "kebab-or-snake-case",
|
|
3710
|
+
"description": "short summary",
|
|
3711
|
+
"systemPrompt": "you are...",
|
|
3712
|
+
"model": { "provider": "anthropic"|"openai"|"gemini"|..., "model": "..." },
|
|
3713
|
+
"tools": [{ "name": "search", "description": "...", "schema": {...}, "implementation": "fetch('/api/search?q=...')" }],
|
|
3714
|
+
"memory": { "kind": "inMemory"|"localStorage", "key": "..." },
|
|
3715
|
+
"skills": ["researcher", "critic"]
|
|
3716
|
+
}
|
|
3717
|
+
|
|
3718
|
+
Prefer fewer well-scoped tools over many overlapping ones. Name tools
|
|
3719
|
+
in snake_case.`;
|
|
3720
|
+
function extractJson(text) {
|
|
3721
|
+
const fenced = text.match(/```(?:json)?\s*([\s\S]+?)```/);
|
|
3722
|
+
const raw = fenced?.[1] ?? text;
|
|
3723
|
+
const start = raw.indexOf("{");
|
|
3724
|
+
const end = raw.lastIndexOf("}");
|
|
3725
|
+
if (start < 0 || end <= start) throw new Error("Planner response did not contain a JSON object");
|
|
3726
|
+
return raw.slice(start, end + 1);
|
|
3727
|
+
}
|
|
3728
|
+
function createAdapterPlanner(adapter) {
|
|
3729
|
+
return async (description) => {
|
|
3730
|
+
const messages = [
|
|
3731
|
+
{ id: "sys", role: "system", content: PLANNER_SYSTEM_PROMPT, status: "complete", createdAt: /* @__PURE__ */ new Date(0) },
|
|
3732
|
+
{ id: "user", role: "user", content: description, status: "complete", createdAt: /* @__PURE__ */ new Date(0) }
|
|
3733
|
+
];
|
|
3734
|
+
const request = { messages, context: { temperature: 0 } };
|
|
3735
|
+
const source = adapter.createSource(request);
|
|
3736
|
+
let text = "";
|
|
3737
|
+
for await (const chunk of source.stream()) {
|
|
3738
|
+
if (chunk.type === "text" && chunk.content) text += chunk.content;
|
|
3739
|
+
}
|
|
3740
|
+
const json = extractJson(text);
|
|
3741
|
+
return validateAgentSchema(JSON.parse(json));
|
|
3742
|
+
};
|
|
3743
|
+
}
|
|
3744
|
+
|
|
3745
|
+
// src/commands/ai.ts
|
|
3746
|
+
function registerAiCommand(program) {
|
|
3747
|
+
program.command("ai <description...>").description("Generate an agent (config + tools + skill wiring) from a natural-language description.").option("-o, --out <dir>", "Output directory", "./my-agent").option("--provider <provider>", "Planner provider (openai | anthropic | ...)", "anthropic").option("--model <model>", "Planner model id").option("--api-key <key>", "API key (falls back to env)").option("--base-url <url>", "Override base URL (for OpenAI-compatible endpoints)").option("--overwrite", "Overwrite existing files", false).option("--dry-run", "Print the plan + files without writing", false).action(async (descriptionWords, options) => {
|
|
3748
|
+
const description = descriptionWords.join(" ").trim();
|
|
3749
|
+
if (!description) {
|
|
3750
|
+
process.stderr.write("agentskit ai: missing description.\n");
|
|
3751
|
+
process.exit(1);
|
|
3752
|
+
}
|
|
3753
|
+
const resolved = resolveChatProvider({
|
|
3754
|
+
provider: options.provider,
|
|
3755
|
+
model: options.model,
|
|
3756
|
+
apiKey: options.apiKey,
|
|
3757
|
+
baseUrl: options.baseUrl
|
|
3758
|
+
});
|
|
3759
|
+
const planner2 = createAdapterPlanner(resolved.adapter);
|
|
3760
|
+
process.stderr.write(`Planning agent for: "${description}"
|
|
3761
|
+
`);
|
|
3762
|
+
const schema = await planner2(description);
|
|
3763
|
+
const files = scaffoldAgent(schema);
|
|
3764
|
+
if (options.dryRun) {
|
|
3765
|
+
process.stdout.write(JSON.stringify({ schema, files: files.map((f) => f.path) }, null, 2) + "\n");
|
|
3766
|
+
return;
|
|
3767
|
+
}
|
|
3768
|
+
const written = await writeScaffold(files, options.out, { overwrite: options.overwrite });
|
|
3769
|
+
process.stderr.write(`Wrote ${written.length} file(s) to ${options.out}
|
|
3770
|
+
`);
|
|
3771
|
+
for (const f of written) process.stderr.write(` + ${f}
|
|
3772
|
+
`);
|
|
3773
|
+
});
|
|
3774
|
+
}
|
|
3775
|
+
|
|
2953
3776
|
// src/commands/index.ts
|
|
2954
3777
|
function createCli() {
|
|
2955
3778
|
const program = new Command();
|
|
@@ -2962,9 +3785,10 @@ function createCli() {
|
|
|
2962
3785
|
registerConfigCommand(program);
|
|
2963
3786
|
registerTunnelCommand(program);
|
|
2964
3787
|
registerRagCommand(program);
|
|
3788
|
+
registerAiCommand(program);
|
|
2965
3789
|
return program;
|
|
2966
3790
|
}
|
|
2967
3791
|
|
|
2968
3792
|
export { ChatApp, HookDispatcher, McpClient, applyPolicyToTool, applyPolicyToTools, bridgeMcpServers, buildRagFromConfig, computeCost, configHooksToHandlers, createCli, createOpenAiEmbedder, defaultPolicy, derivePreview, disposeMcpClients, evaluatePolicy, findLatestSession, findSession, forkSession, generateSessionId, getPricing, indexSources, listSessions, loadConfig, loadPlugins, mergePluginsIntoBundle, registerPricing, renameSession, renderChatHeader, renderReport, resolveChatProvider, resolveSession, runAgent, runDoctor, sessionFilePath, startDev, startTunnel, writeSessionMeta, writeStarterProject };
|
|
2969
|
-
//# sourceMappingURL=chunk-
|
|
2970
|
-
//# sourceMappingURL=chunk-
|
|
3793
|
+
//# sourceMappingURL=chunk-ZEESHYST.js.map
|
|
3794
|
+
//# sourceMappingURL=chunk-ZEESHYST.js.map
|