@inneranimalmedia/agentsam-sdk 2.4.1 → 2.5.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 +7 -6
- package/docs/AGENTSAM_WORKBENCH.md +30 -0
- package/docs/AUTH_IDENTITY_CONTRACT.md +52 -0
- package/docs/CAPABILITIES.md +5 -3
- package/docs/CLI_SHELL.md +57 -80
- package/docs/CMS_STUDIO.md +101 -0
- package/docs/CONTEXT.md +170 -0
- package/docs/LOCAL_OLLAMA.md +58 -0
- package/docs/MERKLE.md +19 -19
- package/docs/PORTABLE_CONTEXT.md +4 -3
- package/docs/PROJECT_CONFIG.md +72 -0
- package/docs/RELEASES.md +26 -2
- package/docs/REPOSITORY_INTELLIGENCE.md +1 -1
- package/docs/REPOSITORY_KNOWLEDGE.md +114 -0
- package/docs/SDK_WORKER.md +86 -0
- package/docs/SECURITY.md +59 -22
- package/docs/client-cms-editor.md +15 -0
- package/docs/local-studio/WORKMODE_DONOR_NOTES.md +485 -0
- package/package.json +17 -4
- package/packages/identity/package.json +11 -2
- package/packages/identity/src/contracts/auth-config.js +98 -0
- package/packages/identity/src/index.js +1 -0
- package/packages/identity/src/oauth/README.md +2 -2
- package/packages/identity/src/oauth/credentials.js +11 -4
- package/packages/identity/src/oauth/iam-platform.js +3 -3
- package/packages/identity/src/providers/iam/index.js +7 -7
- package/packages/identity/src/providers/iam/oauth.js +6 -4
- package/packages/identity/src/providers/iam/profile.js +5 -5
- package/packages/identity/tests/auth-config.test.mjs +57 -0
- package/packages/identity/tests/oauth-credentials.test.mjs +13 -2
- package/protocol/FILEMETA_V1.md +95 -0
- package/protocol/INSPECT_VIEWS_V1.md +40 -0
- package/protocol/MERKLE_PERSISTENCE_V1.md +50 -0
- package/protocol/MERKLE_V1.md +3 -1
- package/protocol/capabilities/manifest.json +32 -3
- package/protocol/capabilities/repository-snapshot.schema.json +1 -0
- package/protocol/context/context-budget.schema.json +41 -0
- package/protocol/context/context-item.schema.json +20 -0
- package/protocol/context/resolved-context-pack.schema.json +42 -0
- package/protocol/context/result-policy.schema.json +17 -0
- package/protocol/knowledge/context-pack.schema.json +33 -0
- package/protocol/knowledge/retrieval-query.schema.json +68 -13
- package/python/README.md +15 -7
- package/python/agentsam_sdk/cli.py +0 -21
- package/python/agentsam_sdk/tui/README.md +17 -12
- package/python/agentsam_sdk/tui/bootstrap.py +2 -2
- package/python/agentsam_sdk/tui/demo.py +25 -10
- package/python/agentsam_sdk/tui/onboarding.py +208 -0
- package/python/tests/test_tui_cli.py +7 -6
- package/skills/README.md +21 -0
- package/skills/agentsam-app-fundamentals/SKILL.md +165 -0
- package/skills/agentsam-app-fundamentals/references/graphs-contracts-ast-merkle.md +89 -0
- package/skills/agentsam-app-fundamentals/references/trust-credentials-and-destinations.md +99 -0
- package/skills/agentsam-jr-dev/SKILL.md +232 -0
- package/skills/agentsam-jr-dev/references/real-application-logic.md +156 -0
- package/skills/agentsam-jr-dev/references/web-application-fundamentals.md +240 -0
- package/skills/agentsam-progression-guard/SKILL.md +197 -0
- package/skills/agentsam-progression-guard/references/checkpoint-chain.md +111 -0
- package/skills/agentsam-progression-guard/references/hooks-operational-io.md +96 -0
- package/skills/catalog.json +53 -0
- package/src/capabilities/index.js +7 -0
- package/src/capabilities/repository-snapshot-view.js +238 -0
- package/src/capabilities/repository-snapshot.js +28 -14
- package/src/cli.js +108 -56
- package/src/commands/context.js +14 -2
- package/src/commands/db.js +4 -7
- package/src/commands/deploy.js +17 -31
- package/src/commands/interactive.js +21 -0
- package/src/commands/knowledge.js +27 -4
- package/src/commands/merkle-persist.js +118 -0
- package/src/commands/merkle.js +32 -17
- package/src/commands/models.js +107 -0
- package/src/commands/ollama.js +259 -0
- package/src/commands/preferences.js +102 -0
- package/src/commands/product.js +86 -16
- package/src/commands/security.js +3 -3
- package/src/commands/shell.js +71 -27
- package/src/commands/skills.js +66 -0
- package/src/commands/start-local.js +1 -1
- package/src/commands/tunnel.js +5 -4
- package/src/context/budget.js +58 -0
- package/src/context/compact.js +28 -0
- package/src/context/index.js +5 -0
- package/src/context/resolve.js +84 -0
- package/src/context/result-policy.js +66 -0
- package/src/index.js +16 -0
- package/src/indexing/execution-boundary.js +144 -0
- package/src/indexing/index.js +8 -0
- package/src/indexing/provider.js +41 -0
- package/src/knowledge/config.js +2 -2
- package/src/knowledge/context-pack.js +12 -1
- package/src/knowledge/contracts.js +9 -4
- package/src/knowledge/engine.js +7 -3
- package/src/knowledge/service/server.js +1 -1
- package/src/lib/bridge-client.js +7 -5
- package/src/lib/cli-preferences.js +74 -0
- package/src/lib/core-client.js +8 -8
- package/src/lib/deploy-receipt/index.js +5 -2
- package/src/lib/detect-context.js +6 -5
- package/src/lib/identity-scaffold.js +1 -1
- package/src/lib/local-scaffold.js +35 -33
- package/src/lib/local-status.js +9 -17
- package/src/lib/merkle/cloudflare-persistence.js +321 -0
- package/src/lib/merkle/filemeta.js +43 -0
- package/src/lib/merkle/git-ignore.js +24 -0
- package/src/lib/merkle/hash.js +1 -0
- package/src/lib/merkle/index.js +22 -0
- package/src/lib/merkle/persistence.js +72 -0
- package/src/lib/merkle/semantic.js +359 -0
- package/src/lib/merkle/snapshot.js +9 -3
- package/src/lib/merkle/tree.js +11 -6
- package/src/lib/project-config.js +227 -0
- package/src/lib/project-rules.js +68 -0
- package/src/lib/save-sdk-token.js +1 -1
- package/src/lib/slash-commands.js +2 -1
- package/src/lib/tools.js +11 -5
- package/src/security/index.js +1 -0
- package/src/security/inventory.js +4 -1
- package/src/security/render.js +27 -5
- package/src/security/scan.js +24 -9
- package/src/security/trust-boundary.js +24 -0
- package/src/skills/index.js +64 -0
- package/src/tools/index.js +1 -0
- package/src/tools/search.js +70 -0
- package/src/ui/ansi.js +1 -1
- package/src/ui/boot.js +56 -0
- package/src/ui/merkle/render.js +1 -0
- package/src/ui/runtime-activity.js +192 -0
- package/src/ui/theme.js +19 -18
- package/test/app-building-skills.test.mjs +61 -0
- package/test/apps-scaffold-contract.test.mjs +56 -0
- package/test/capabilities.test.mjs +53 -4
- package/test/cli-preferences.test.mjs +25 -0
- package/test/context.test.mjs +95 -0
- package/test/indexing-provider.test.mjs +29 -0
- package/test/jr-dev-skill.test.mjs +26 -0
- package/test/knowledge-context-pack.test.mjs +19 -0
- package/test/knowledge.test.mjs +1 -1
- package/test/merkle-persistence.test.mjs +91 -0
- package/test/merkle.test.mjs +77 -3
- package/test/models.test.mjs +37 -0
- package/test/ollama.test.mjs +94 -0
- package/test/project-config.test.mjs +81 -0
- package/test/project-rules.test.mjs +44 -0
- package/test/release-hygiene.test.mjs +34 -0
- package/test/repository-snapshot-view.test.mjs +112 -0
- package/test/runtime-activity.test.mjs +98 -0
- package/test/sdk-worker-contract.test.mjs +68 -0
- package/test/security.test.mjs +46 -0
- package/test/shell.test.mjs +8 -1
- package/test/skills.test.mjs +22 -0
- package/test/smoke.mjs +2 -2
- package/test/theme-portability.test.mjs +14 -0
- package/test/tools-search.test.mjs +27 -0
- package/examples/agentsam-tui-ansi.mjs +0 -149
- package/src/commands/tui.js +0 -120
- package/src/ui/splash-xterm.js +0 -290
- package/src/ui/splash.js +0 -426
package/src/cli.js
CHANGED
|
@@ -2,14 +2,17 @@
|
|
|
2
2
|
|
|
3
3
|
import pkg from '../package.json' with { type: 'json' };
|
|
4
4
|
import readline from 'readline';
|
|
5
|
+
import { cancel, intro, isCancel, outro, select, text } from '@clack/prompts';
|
|
5
6
|
import path from 'node:path';
|
|
6
|
-
import { buildLocalScaffoldMeta
|
|
7
|
+
import { buildLocalScaffoldMeta } from './lib/local-scaffold.js';
|
|
7
8
|
import { writeScaffoldFiles } from './lib/write-files.js';
|
|
8
9
|
import { initializeGitRepository } from './lib/init-git.js';
|
|
9
10
|
import { initializeLocalSqlite } from './local/sqlite.js';
|
|
10
11
|
import { printContextSummary } from './lib/detect-context.js';
|
|
11
12
|
import { promptOptionalByokKeys } from './lib/prompt-byok.js';
|
|
12
13
|
import { runStartLocal } from './commands/start-local.js';
|
|
14
|
+
import { runOllama } from './commands/ollama.js';
|
|
15
|
+
import { runModels } from './commands/models.js';
|
|
13
16
|
import { runTunnel } from './commands/tunnel.js';
|
|
14
17
|
import { runDeploy } from './commands/deploy.js';
|
|
15
18
|
import { runIdentityPreview } from './commands/identity-preview.js';
|
|
@@ -17,7 +20,7 @@ import { runIdentityInit } from './commands/identity-init.js';
|
|
|
17
20
|
import { runContext } from './commands/context.js';
|
|
18
21
|
import { runDb } from './commands/db.js';
|
|
19
22
|
import { runStatus } from './commands/status.js';
|
|
20
|
-
import {
|
|
23
|
+
import { runInteractive } from './commands/interactive.js';
|
|
21
24
|
import { runShell } from './commands/shell.js';
|
|
22
25
|
import { runDockerize } from './commands/dockerize.js';
|
|
23
26
|
import { runMini } from './commands/mini.js';
|
|
@@ -26,10 +29,12 @@ import { runDeployReceipt } from './commands/deploy-receipt.js';
|
|
|
26
29
|
import { runSecurity } from './commands/security.js';
|
|
27
30
|
import { runRecon } from './commands/recon.js';
|
|
28
31
|
import { runCad } from './commands/cad.js';
|
|
32
|
+
import { runSkills } from './commands/skills.js';
|
|
29
33
|
import { applyPresetSelection, runAdd, runCapabilities, runDev, runInspect } from './commands/product.js';
|
|
30
34
|
import { listPresets, resolvePreset } from './presets/index.js';
|
|
31
35
|
import fs from 'node:fs';
|
|
32
36
|
import { repositoryRoot } from './knowledge/config.js';
|
|
37
|
+
import { resolveSdkKey } from '../packages/identity/src/contracts/auth-config.js';
|
|
33
38
|
|
|
34
39
|
const VERSION = pkg.version;
|
|
35
40
|
|
|
@@ -46,14 +51,16 @@ function printHelp() {
|
|
|
46
51
|
Agent Sam SDK — CLI v${VERSION}
|
|
47
52
|
|
|
48
53
|
Product UX:
|
|
54
|
+
agentsam Enter the interactive Agent Sam experience
|
|
49
55
|
agentsam create <name> --preset <fullstack|cms|prototype|data>
|
|
50
56
|
agentsam add <auth|cms|knowledge|agent|deploy-cloudflare>
|
|
51
57
|
agentsam dev Run this project's existing npm dev script
|
|
52
|
-
agentsam inspect [--json]
|
|
58
|
+
agentsam inspect [--json] Bounded repository index by default; use --view full for authority envelope
|
|
53
59
|
agentsam deploy Graduate an AgentSam project intentionally
|
|
54
60
|
|
|
55
61
|
Capability discovery:
|
|
56
62
|
agentsam capabilities [capability-id] [--json]
|
|
63
|
+
agentsam skills [skill-id-or-alias] [--references] [--json]
|
|
57
64
|
|
|
58
65
|
Power-user UX:
|
|
59
66
|
agentsam context [--json] Git repo/revision + bridge configuration from any repo
|
|
@@ -63,15 +70,15 @@ function printHelp() {
|
|
|
63
70
|
agentsam repo snapshot Git composition/churn; --save retains observations
|
|
64
71
|
agentsam cad blender Programmatic Blender inspect/build/render/export (--help)
|
|
65
72
|
agentsam mini <name> Create and preview a small local gadget (--help for options)
|
|
66
|
-
agentsam merkle File integrity, snapshots, comparisons, and
|
|
73
|
+
agentsam merkle File integrity, snapshots, comparisons, and interactive explorer (--help)
|
|
67
74
|
agentsam deploy-receipt Merkle deploy/checkpoint capture + promote/failure receipts (--help)
|
|
68
75
|
agentsam recon Bounded-worker task packets + finding-report validation (--help)
|
|
69
76
|
agentsam security Dependency scan, log triage, and verified repair (--help)
|
|
70
77
|
agentsam status [--json] Live local Git + DB + API + PTY status
|
|
71
78
|
agentsam db init|status Manage the project-local SQLite database
|
|
72
|
-
agentsam
|
|
73
|
-
agentsam tui rich Optional Python Rich dashboard (--install for local venv)
|
|
79
|
+
agentsam models Show configured providers and local model inventory
|
|
74
80
|
agentsam start-local Local PTY on ws://127.0.0.1:3099 (no tunnel, no Cloudflare)
|
|
81
|
+
agentsam ollama Opt-in local Ollama setup/status/model management
|
|
75
82
|
agentsam shell Interactive Agent Sam slash-command shell
|
|
76
83
|
agentsam tunnel Explicitly expose local PTY when remote access is wanted
|
|
77
84
|
agentsam deploy Graduate to Cloudflare / GCP when ready
|
|
@@ -84,6 +91,21 @@ function printHelp() {
|
|
|
84
91
|
Context options:
|
|
85
92
|
--json Machine-readable output
|
|
86
93
|
--cwd <path> Resolve a different working directory
|
|
94
|
+
|
|
95
|
+
Inspect options:
|
|
96
|
+
--view <full|index|files> Full authority envelope, facet index, or bounded matching files (default index)
|
|
97
|
+
--full Explicitly request the full authority envelope
|
|
98
|
+
--system/--package <name> Filter semantic ownership
|
|
99
|
+
--category/--tag <value> Filter semantic classification
|
|
100
|
+
--layer/--role <value> Filter architecture role
|
|
101
|
+
--path <prefix|glob> Filter repository paths (supports * and **)
|
|
102
|
+
--symbol/--import <value> Filter AST symbols or imports
|
|
103
|
+
--match <text> Lexical AND-match across semantic routing metadata
|
|
104
|
+
--limit <1..500> Bound files view (default 50)
|
|
105
|
+
--facet-limit <1..200> Bound each facet list (default 48)
|
|
106
|
+
--snapshot-file <file> Reuse a saved canonical repository.snapshot; skips Merkle/AST rescan
|
|
107
|
+
--save-snapshot <file> Save the canonical full snapshot while emitting the selected view
|
|
108
|
+
--pretty Pretty-print JSON; machine JSON is compact by default
|
|
87
109
|
--remote <name> Preferred Git remote (default origin; falls back to first remote)
|
|
88
110
|
|
|
89
111
|
Init is completable with Node only — no IAM login, no OAuth, no Cloudflare.
|
|
@@ -93,7 +115,7 @@ function printHelp() {
|
|
|
93
115
|
--quick Quick tunnel (default) — trycloudflare.com URL
|
|
94
116
|
--named Named CF tunnel (needs --tunnel-name --hostname --zone-id)
|
|
95
117
|
--port <n> Local PTY port (default 3099)
|
|
96
|
-
--token <sdk_…> Use existing
|
|
118
|
+
--token <sdk_…> Use existing AGENTSAM_SDK_KEY (skip browser auth)
|
|
97
119
|
|
|
98
120
|
Init options:
|
|
99
121
|
--name <name> Project directory name
|
|
@@ -176,7 +198,7 @@ async function runLocalInit(config) {
|
|
|
176
198
|
✓ Environment ${path.join(dir, '.env')}
|
|
177
199
|
✓ SQLite ${db.dbPath} (${db.tables.length} tables)
|
|
178
200
|
✓ Local API Node · http://127.0.0.1:8787
|
|
179
|
-
✓
|
|
201
|
+
✓ Agent Sam interactive CLI ready
|
|
180
202
|
|
|
181
203
|
Next:`);
|
|
182
204
|
console.log(` cd ${meta.projectName}`);
|
|
@@ -184,9 +206,10 @@ async function runLocalInit(config) {
|
|
|
184
206
|
console.log(` ${step}`);
|
|
185
207
|
}
|
|
186
208
|
|
|
187
|
-
|
|
209
|
+
const sdkKey = resolveSdkKey(process.env);
|
|
210
|
+
if (prompt && sdkKey) {
|
|
188
211
|
console.log('\n Optional — BYOK keys for IAM dashboard Agent Sam (skip with Enter):\n');
|
|
189
|
-
await promptOptionalByokKeys(
|
|
212
|
+
await promptOptionalByokKeys(sdkKey, prompt);
|
|
190
213
|
}
|
|
191
214
|
|
|
192
215
|
console.log(`
|
|
@@ -196,58 +219,61 @@ async function runLocalInit(config) {
|
|
|
196
219
|
}
|
|
197
220
|
|
|
198
221
|
async function initInteractive(partial = {}) {
|
|
199
|
-
const
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
`);
|
|
207
|
-
|
|
208
|
-
const projectName =
|
|
209
|
-
partial.projectName ||
|
|
210
|
-
(await prompt.ask(' 1) Project name: '));
|
|
211
|
-
|
|
212
|
-
if (!partial.lane) {
|
|
213
|
-
console.log(`
|
|
214
|
-
2) Lane:
|
|
215
|
-
1) Full Stack 2) CMS 3) Data 4) CRM 5) Creative
|
|
216
|
-
`);
|
|
217
|
-
}
|
|
218
|
-
const laneKey = partial.lane
|
|
219
|
-
? partial.lane
|
|
220
|
-
: LANE_KEYS[await prompt.ask(' Pick lane [1-5]: ')] || 'fullstack';
|
|
222
|
+
const pick = (value) => {
|
|
223
|
+
if (!isCancel(value)) return value;
|
|
224
|
+
cancel('Agent Sam init cancelled.');
|
|
225
|
+
const error = new Error('init_cancelled');
|
|
226
|
+
error.code = 'AGENTSAM_INIT_CANCELLED';
|
|
227
|
+
throw error;
|
|
228
|
+
};
|
|
221
229
|
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
230
|
+
intro('Create an Agent Sam project');
|
|
231
|
+
|
|
232
|
+
const projectName = partial.projectName || pick(await text({
|
|
233
|
+
message: 'Project name',
|
|
234
|
+
placeholder: 'my-agent',
|
|
235
|
+
validate(value) {
|
|
236
|
+
if (!String(value || '').trim()) return 'Project name is required';
|
|
237
|
+
},
|
|
238
|
+
}));
|
|
239
|
+
|
|
240
|
+
const laneKey = partial.lane || pick(await select({
|
|
241
|
+
message: 'Project type',
|
|
242
|
+
initialValue: 'fullstack',
|
|
243
|
+
options: [
|
|
244
|
+
{ value: 'fullstack', label: 'Full Stack' },
|
|
245
|
+
{ value: 'cms', label: 'CMS' },
|
|
246
|
+
{ value: 'data', label: 'Data Solutions' },
|
|
247
|
+
{ value: 'crm', label: 'Customer Management' },
|
|
248
|
+
{ value: 'creative', label: 'Creative & Design' },
|
|
249
|
+
],
|
|
250
|
+
}));
|
|
251
|
+
|
|
252
|
+
const runTarget = partial.runTarget || pick(await select({
|
|
253
|
+
message: 'Future deploy target',
|
|
254
|
+
initialValue: 'local',
|
|
255
|
+
options: [
|
|
256
|
+
{ value: 'local', label: 'Local only / decide later' },
|
|
257
|
+
{ value: 'cloudflare', label: 'Cloudflare later' },
|
|
258
|
+
{ value: 'gcp', label: 'GCP later' },
|
|
259
|
+
],
|
|
260
|
+
}));
|
|
225
261
|
|
|
226
|
-
1) Local only / decide later
|
|
227
|
-
2) Cloudflare later (Worker + D1 adapter at deploy time)
|
|
228
|
-
3) GCP later (your Google Cloud project)
|
|
229
|
-
`);
|
|
230
|
-
}
|
|
231
|
-
const runTarget = partial.runTarget
|
|
232
|
-
? partial.runTarget
|
|
233
|
-
: RUN_TARGETS[await prompt.ask(' Select [1]: ')] || 'local';
|
|
234
|
-
|
|
235
|
-
// Credential detection is demand-driven, not unconditional. missingForInit()
|
|
236
|
-
// already knows local needs nothing (`if (runTarget === 'local') return []`)
|
|
237
|
-
// — it just never got consulted before this fix, because detectContext()
|
|
238
|
-
// used to run before runTarget was even known. runTarget alone is enough
|
|
239
|
-
// to decide whether detection is needed at all, so skip the subprocess
|
|
240
|
-
// calls entirely for local instead of just hiding their output.
|
|
241
262
|
if (runTarget !== 'local') {
|
|
242
263
|
const { detectContext, missingForInit } = await import('./lib/detect-context.js');
|
|
243
264
|
const ctx = await detectContext();
|
|
244
|
-
if (missingForInit(ctx, process.env
|
|
265
|
+
if (missingForInit(ctx, resolveSdkKey(process.env), { runTarget }).length) {
|
|
245
266
|
printContextSummary(ctx);
|
|
246
267
|
}
|
|
247
268
|
}
|
|
248
269
|
|
|
249
|
-
|
|
250
|
-
|
|
270
|
+
const prompt = resolveSdkKey(process.env) ? createPrompt() : null;
|
|
271
|
+
try {
|
|
272
|
+
await runLocalInit({ projectName, lane: laneKey, runTarget, prompt });
|
|
273
|
+
} finally {
|
|
274
|
+
prompt?.close();
|
|
275
|
+
}
|
|
276
|
+
outro(`Created ${projectName}`);
|
|
251
277
|
}
|
|
252
278
|
|
|
253
279
|
async function initFromArgs(argv) {
|
|
@@ -264,8 +290,20 @@ const rest = process.argv.slice(3);
|
|
|
264
290
|
|
|
265
291
|
if (command === '--version' || command === '-v') {
|
|
266
292
|
console.log(VERSION);
|
|
267
|
-
} else if (command === '--help' || command === '-h'
|
|
293
|
+
} else if (command === '--help' || command === '-h') {
|
|
268
294
|
printHelp();
|
|
295
|
+
} else if (!command) {
|
|
296
|
+
if (process.stdin.isTTY && process.stdout.isTTY) {
|
|
297
|
+
try { await runInteractive(); }
|
|
298
|
+
catch (e) {
|
|
299
|
+
if (e?.code !== 'AGENTSAM_SETUP_CANCELLED') {
|
|
300
|
+
console.error(`\n ✗ ${e?.message || e}\n`);
|
|
301
|
+
process.exitCode = 1;
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
} else {
|
|
305
|
+
printHelp();
|
|
306
|
+
}
|
|
269
307
|
} else if (command === 'create') {
|
|
270
308
|
try {
|
|
271
309
|
const opts = parseCreateArgs(rest);
|
|
@@ -311,9 +349,9 @@ if (command === '--version' || command === '-v') {
|
|
|
311
349
|
console.error(`\n ✗ ${e?.message || e}\n`);
|
|
312
350
|
process.exit(1);
|
|
313
351
|
}
|
|
314
|
-
} else if (command === '
|
|
352
|
+
} else if (command === 'models') {
|
|
315
353
|
try {
|
|
316
|
-
await
|
|
354
|
+
await runModels(rest);
|
|
317
355
|
} catch (e) {
|
|
318
356
|
console.error(`\n ✗ ${e?.message || e}\n`);
|
|
319
357
|
process.exit(1);
|
|
@@ -327,6 +365,13 @@ if (command === '--version' || command === '-v') {
|
|
|
327
365
|
}
|
|
328
366
|
} else if (command === 'start-local') {
|
|
329
367
|
await runStartLocal({});
|
|
368
|
+
} else if (command === 'ollama') {
|
|
369
|
+
try {
|
|
370
|
+
await runOllama(rest);
|
|
371
|
+
} catch (e) {
|
|
372
|
+
console.error(`\n ✗ ${e?.message || e}\n`);
|
|
373
|
+
process.exitCode = 1;
|
|
374
|
+
}
|
|
330
375
|
} else if (command === 'tunnel') {
|
|
331
376
|
try {
|
|
332
377
|
await runTunnel(rest);
|
|
@@ -357,6 +402,13 @@ if (command === '--version' || command === '-v') {
|
|
|
357
402
|
}
|
|
358
403
|
} else if (command === 'security' || command === 'sca') {
|
|
359
404
|
await runSecurity(rest);
|
|
405
|
+
} else if (command === 'skills' || command === 'skill') {
|
|
406
|
+
try {
|
|
407
|
+
runSkills(rest);
|
|
408
|
+
} catch (e) {
|
|
409
|
+
console.error(`\n ✗ ${e?.message || e}\n`);
|
|
410
|
+
process.exitCode = 1;
|
|
411
|
+
}
|
|
360
412
|
} else if (command === 'merkle') {
|
|
361
413
|
await runMerkle(rest);
|
|
362
414
|
} else if (command === 'deploy-receipt') {
|
package/src/commands/context.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { tryResolveGitContext } from '../lib/git-context.js';
|
|
2
2
|
import { resolveAgentSamBaseUrl, resolveBridgeKey } from '../lib/bridge-client.js';
|
|
3
|
+
import { loadProjectRules } from '../lib/project-rules.js';
|
|
3
4
|
|
|
4
5
|
function parseArgs(argv = []) {
|
|
5
6
|
const options = { json: false, cwd: process.cwd(), remote: 'origin' };
|
|
@@ -15,10 +16,20 @@ function parseArgs(argv = []) {
|
|
|
15
16
|
|
|
16
17
|
export function buildContextReport(options = {}) {
|
|
17
18
|
const env = options.env || process.env;
|
|
18
|
-
const
|
|
19
|
+
const cwd = options.cwd || process.cwd();
|
|
20
|
+
const git = tryResolveGitContext({ cwd, remote: options.remote || 'origin' });
|
|
21
|
+
const rules = loadProjectRules(cwd);
|
|
19
22
|
return {
|
|
20
|
-
schemaVersion: 'agentsam-context-
|
|
23
|
+
schemaVersion: 'agentsam-context-v2',
|
|
21
24
|
git,
|
|
25
|
+
rules: {
|
|
26
|
+
found: rules.found,
|
|
27
|
+
path: rules.path,
|
|
28
|
+
chars: rules.chars,
|
|
29
|
+
source_chars: rules.source_chars || 0,
|
|
30
|
+
truncated: rules.truncated,
|
|
31
|
+
hash: rules.hash,
|
|
32
|
+
},
|
|
22
33
|
bridge: {
|
|
23
34
|
baseUrl: resolveAgentSamBaseUrl(env),
|
|
24
35
|
configured: Boolean(resolveBridgeKey(env)),
|
|
@@ -46,6 +57,7 @@ export async function runContext(argv = []) {
|
|
|
46
57
|
} else {
|
|
47
58
|
console.log(' repo not inside a Git repository');
|
|
48
59
|
}
|
|
60
|
+
console.log(` rules ${report.rules.found ? `${report.rules.path} · ${report.rules.chars} chars` : 'none'}`);
|
|
49
61
|
console.log(` core ${report.bridge.baseUrl}`);
|
|
50
62
|
console.log(` bridge ${report.bridge.configured ? 'configured' : 'AGENTSAM_BRIDGE_KEY not set'}`);
|
|
51
63
|
console.log('');
|
package/src/commands/db.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import { initializeLocalSqlite, inspectLocalSqlite } from '../local/sqlite.js';
|
|
4
|
+
import { getLocalDatabasePath, getLocalSchemaPath, readProjectConfig } from '../lib/project-config.js';
|
|
4
5
|
|
|
5
6
|
function findProjectRoot(startDir) {
|
|
6
7
|
let dir = path.resolve(startDir);
|
|
@@ -13,14 +14,10 @@ function findProjectRoot(startDir) {
|
|
|
13
14
|
throw new Error('Not an Agent Sam project — run `agentsam init` first.');
|
|
14
15
|
}
|
|
15
16
|
|
|
16
|
-
function readConfig(root) {
|
|
17
|
-
return JSON.parse(fs.readFileSync(path.join(root, '.agentsam', 'config.json'), 'utf8'));
|
|
18
|
-
}
|
|
19
|
-
|
|
20
17
|
function resolveDb(root, config) {
|
|
21
18
|
return {
|
|
22
|
-
dbPath: path.resolve(root, config
|
|
23
|
-
schemaPath: path.resolve(root, config
|
|
19
|
+
dbPath: path.resolve(root, getLocalDatabasePath(config)),
|
|
20
|
+
schemaPath: path.resolve(root, getLocalSchemaPath(config)),
|
|
24
21
|
};
|
|
25
22
|
}
|
|
26
23
|
|
|
@@ -31,7 +28,7 @@ export async function runDb(argv = [], opts = {}) {
|
|
|
31
28
|
}
|
|
32
29
|
|
|
33
30
|
const root = findProjectRoot(opts.cwd || process.cwd());
|
|
34
|
-
const config =
|
|
31
|
+
const config = readProjectConfig(root);
|
|
35
32
|
const paths = resolveDb(root, config);
|
|
36
33
|
|
|
37
34
|
if (sub === 'init') {
|
package/src/commands/deploy.js
CHANGED
|
@@ -6,26 +6,16 @@ import path from 'node:path';
|
|
|
6
6
|
import readline from 'node:readline';
|
|
7
7
|
import { authenticateViaBrowser } from '../lib/auth.js';
|
|
8
8
|
import { getJson, streamScaffold } from '../lib/core-client.js';
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
const configPath = path.join(cwd, '.agentsam', 'config.json');
|
|
12
|
-
if (!fs.existsSync(configPath)) {
|
|
13
|
-
throw new Error('Not an Agent Sam project — run agentsam init first.');
|
|
14
|
-
}
|
|
15
|
-
return JSON.parse(fs.readFileSync(configPath, 'utf8'));
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
function writeConfig(cwd, config) {
|
|
19
|
-
const configPath = path.join(cwd, '.agentsam', 'config.json');
|
|
20
|
-
fs.writeFileSync(configPath, `${JSON.stringify(config, null, 2)}\n`, 'utf8');
|
|
21
|
-
}
|
|
9
|
+
import { resolveSdkKey } from '../../packages/identity/src/contracts/auth-config.js';
|
|
10
|
+
import { getDefaultProfile, getDeployTarget, getLocalSchemaPath, getProjectName, getProjectPreset, readProjectConfig, setDeployTarget, writeProjectConfig } from '../lib/project-config.js';
|
|
22
11
|
|
|
23
12
|
function writeCloudflareAdapter(cwd, config, cf) {
|
|
24
|
-
const
|
|
13
|
+
const projectName = getProjectName(config, path.basename(cwd));
|
|
14
|
+
const workerName = cf.worker_name || projectName;
|
|
25
15
|
const adapterPath = path.join(cwd, 'src', 'cloudflare-worker.js');
|
|
26
16
|
const migrationDir = path.join(cwd, 'migrations');
|
|
27
17
|
const migrationPath = path.join(migrationDir, '0001_agentsam_core.sql');
|
|
28
|
-
const localSchemaPath = path.join(cwd, config
|
|
18
|
+
const localSchemaPath = path.join(cwd, getLocalSchemaPath(config));
|
|
29
19
|
const tomlPath = path.join(cwd, 'wrangler.toml');
|
|
30
20
|
|
|
31
21
|
fs.mkdirSync(path.dirname(adapterPath), { recursive: true });
|
|
@@ -33,7 +23,7 @@ function writeCloudflareAdapter(cwd, config, cf) {
|
|
|
33
23
|
|
|
34
24
|
fs.writeFileSync(
|
|
35
25
|
adapterPath,
|
|
36
|
-
`import { createAgent } from './agent.js';\n\nexport default {\n async fetch(request, env) {\n const app = createAgent({\n env,\n project: ${JSON.stringify(
|
|
26
|
+
`import { createAgent } from './agent.js';\n\nexport default {\n async fetch(request, env) {\n const app = createAgent({\n env,\n project: ${JSON.stringify(projectName)},\n lane: ${JSON.stringify(getProjectPreset(config))},\n agent: ${JSON.stringify(getDefaultProfile(config))},\n });\n return app.handle(request);\n },\n};\n`,
|
|
37
27
|
'utf8',
|
|
38
28
|
);
|
|
39
29
|
|
|
@@ -51,7 +41,7 @@ function writeCloudflareAdapter(cwd, config, cf) {
|
|
|
51
41
|
if (cf.d1_database_id) {
|
|
52
42
|
lines.push('', '[[d1_databases]]');
|
|
53
43
|
lines.push('binding = "DB"');
|
|
54
|
-
lines.push(`database_name = ${JSON.stringify(cf.d1_database_name || `${
|
|
44
|
+
lines.push(`database_name = ${JSON.stringify(cf.d1_database_name || `${projectName}-db`)}`);
|
|
55
45
|
lines.push(`database_id = ${JSON.stringify(cf.d1_database_id)}`);
|
|
56
46
|
}
|
|
57
47
|
if (cf.kv_namespace_id) {
|
|
@@ -77,7 +67,7 @@ function ask(question) {
|
|
|
77
67
|
async function runCloudflareDeploy(cwd, config, accountId) {
|
|
78
68
|
console.log('\n Cloudflare deploy — browser sign-in + resource provisioning…\n');
|
|
79
69
|
|
|
80
|
-
let token = process.env
|
|
70
|
+
let token = resolveSdkKey(process.env);
|
|
81
71
|
if (!token) {
|
|
82
72
|
const session = await authenticateViaBrowser();
|
|
83
73
|
token = session.access_token;
|
|
@@ -92,8 +82,8 @@ async function runCloudflareDeploy(cwd, config, accountId) {
|
|
|
92
82
|
let complete = null;
|
|
93
83
|
await streamScaffold(
|
|
94
84
|
{
|
|
95
|
-
project_name: config.
|
|
96
|
-
lane: config
|
|
85
|
+
project_name: getProjectName(config, path.basename(cwd)),
|
|
86
|
+
lane: getProjectPreset(config),
|
|
97
87
|
hosting: 'cloudflare',
|
|
98
88
|
provision_only: true,
|
|
99
89
|
account_id: accountId || undefined,
|
|
@@ -114,13 +104,8 @@ async function runCloudflareDeploy(cwd, config, accountId) {
|
|
|
114
104
|
if (!complete?.cloudflare) throw new Error('deploy incomplete — no cloudflare ids returned');
|
|
115
105
|
|
|
116
106
|
const adapter = writeCloudflareAdapter(cwd, config, complete.cloudflare);
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
deploy_target: 'cloudflare',
|
|
120
|
-
cloudflare: complete.cloudflare,
|
|
121
|
-
cloud_adapter: path.relative(cwd, adapter.adapterPath),
|
|
122
|
-
deployed_at: new Date().toISOString(),
|
|
123
|
-
});
|
|
107
|
+
setDeployTarget(config, 'cloudflare');
|
|
108
|
+
writeProjectConfig(cwd, config);
|
|
124
109
|
|
|
125
110
|
console.log(`
|
|
126
111
|
✓ Cloudflare resources provisioned in YOUR account
|
|
@@ -141,10 +126,10 @@ async function runCloudflareDeploy(cwd, config, accountId) {
|
|
|
141
126
|
*/
|
|
142
127
|
export async function runDeploy(opts = {}) {
|
|
143
128
|
const cwd = path.resolve(opts.cwd || process.cwd());
|
|
144
|
-
const config =
|
|
129
|
+
const config = readProjectConfig(cwd);
|
|
145
130
|
|
|
146
|
-
let target = opts.target || config
|
|
147
|
-
if (!opts.target && !config
|
|
131
|
+
let target = opts.target || getDeployTarget(config) || 'cloudflare';
|
|
132
|
+
if (!opts.target && !getDeployTarget(config)) {
|
|
148
133
|
console.log(`
|
|
149
134
|
Where do you want to deploy?
|
|
150
135
|
|
|
@@ -166,7 +151,8 @@ export async function runDeploy(opts = {}) {
|
|
|
166
151
|
Your local project keeps running with npm run dev.
|
|
167
152
|
Container/Worker deploy scripts are project-specific — add when ready.
|
|
168
153
|
`);
|
|
169
|
-
|
|
154
|
+
setDeployTarget(config, 'gcp');
|
|
155
|
+
writeProjectConfig(cwd, config);
|
|
170
156
|
return;
|
|
171
157
|
}
|
|
172
158
|
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { configureCliPreferences } from './preferences.js';
|
|
2
|
+
import { runShell } from './shell.js';
|
|
3
|
+
import { detectCliProject, readCliPreferences } from '../lib/cli-preferences.js';
|
|
4
|
+
import { runBootScene } from '../ui/boot.js';
|
|
5
|
+
|
|
6
|
+
export async function runInteractive(options = {}) {
|
|
7
|
+
let identity = detectCliProject(options.cwd || process.cwd());
|
|
8
|
+
let preferences = readCliPreferences(identity.root);
|
|
9
|
+
|
|
10
|
+
if (!preferences) {
|
|
11
|
+
const configured = await configureCliPreferences({ cwd: identity.root, firstRun: true });
|
|
12
|
+
identity = configured.identity;
|
|
13
|
+
preferences = configured.preferences;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
await runBootScene({ identity, preferences, animate: options.animate !== false });
|
|
17
|
+
await runShell([], {
|
|
18
|
+
cwd: identity.root,
|
|
19
|
+
intro: 'quiet',
|
|
20
|
+
});
|
|
21
|
+
}
|
|
@@ -6,12 +6,15 @@ import { execFile } from 'node:child_process';
|
|
|
6
6
|
import { promisify } from 'node:util';
|
|
7
7
|
import { fileURLToPath } from 'node:url';
|
|
8
8
|
import { randomUUID } from 'node:crypto';
|
|
9
|
+
import pkg from '../../package.json' with { type: 'json' };
|
|
9
10
|
import { CONFIG_PATH, repositoryRoot, initRepository, readConfig, scopeKey, cacheNamespace } from '../knowledge/config.js';
|
|
10
11
|
import { openSqliteStore } from '../knowledge/stores/sqlite.js';
|
|
11
12
|
import { openPostgresStore } from '../knowledge/stores/postgres.js';
|
|
12
13
|
import { planIndex, runIndex, retrieve } from '../knowledge/engine.js';
|
|
13
14
|
import { createGeminiEmbedder } from '../knowledge/providers/gemini.js';
|
|
14
15
|
import { compareObservations } from '../knowledge/evolution.js';
|
|
16
|
+
import { ensureProjectManifest, getProjectName, getRepositoryId } from '../lib/project-config.js';
|
|
17
|
+
import { ensureProjectRules } from '../lib/project-rules.js';
|
|
15
18
|
|
|
16
19
|
const execute = promisify(execFile);
|
|
17
20
|
const split = text => text.split(',').map(s => s.trim()).filter(Boolean);
|
|
@@ -28,7 +31,20 @@ export async function runRepositoryInit(argv) {
|
|
|
28
31
|
if (opts.help) { console.log('agentsam init [.] [--cwd PATH] [--yes] [--include src,docs] [--exclude src/generated] [--scope NAME] [--target local|production] [--dimensions 768]'); return; }
|
|
29
32
|
if (positionals.length > 1 || (positionals[0] && positionals[0] !== '.')) throw new Error('Use init . --cwd PATH to adopt an existing repository, or init --name NAME to scaffold.');
|
|
30
33
|
const root = repositoryRoot(opts.cwd);
|
|
31
|
-
|
|
34
|
+
const knowledgePath = path.join(root, CONFIG_PATH);
|
|
35
|
+
const existingKnowledge = fs.existsSync(knowledgePath) ? readConfig(root) : null;
|
|
36
|
+
const projectManifest = ensureProjectManifest(root, {
|
|
37
|
+
repositoryId: existingKnowledge?.repository_id || undefined,
|
|
38
|
+
sdkVersion: pkg.version,
|
|
39
|
+
});
|
|
40
|
+
ensureProjectRules(root, getProjectName(projectManifest));
|
|
41
|
+
const projectRepositoryId = getRepositoryId(projectManifest);
|
|
42
|
+
if (existingKnowledge) {
|
|
43
|
+
if (projectRepositoryId && existingKnowledge.repository_id !== projectRepositoryId) {
|
|
44
|
+
throw new Error(`repository_identity_mismatch: project=${projectRepositoryId} knowledge=${existingKnowledge.repository_id}`);
|
|
45
|
+
}
|
|
46
|
+
throw new Error(`${CONFIG_PATH} already exists; edit it to change scope/profile. Existing configuration was preserved.`);
|
|
47
|
+
}
|
|
32
48
|
let include = opts.include, exclude = opts.exclude, target = opts.target, dimensions = opts.dimensions;
|
|
33
49
|
if (!opts.yes) {
|
|
34
50
|
if (!process.stdin.isTTY) throw new Error('Existing-repository setup needs a terminal or --yes with explicit options.');
|
|
@@ -41,7 +57,14 @@ export async function runRepositoryInit(argv) {
|
|
|
41
57
|
dimensions ??= await prompt.question('4) Gemini Embedding 2 dimensions [768]: ') || '768';
|
|
42
58
|
} finally { prompt.close(); }
|
|
43
59
|
}
|
|
44
|
-
const config = initRepository(root, {
|
|
60
|
+
const config = initRepository(root, {
|
|
61
|
+
include: split(include || '.'),
|
|
62
|
+
exclude: split(exclude || ''),
|
|
63
|
+
scope: opts.scope || 'default',
|
|
64
|
+
target: target || 'local',
|
|
65
|
+
dimensions: Number(dimensions || 768),
|
|
66
|
+
repositoryId: projectRepositoryId,
|
|
67
|
+
});
|
|
45
68
|
show({ root, config: CONFIG_PATH, storage: config.storage.driver, next: config.storage.driver === 'postgres' ? ['agentsam index setup-store', 'agentsam index plan', 'agentsam index run'] : ['agentsam index plan', 'agentsam index run', 'agentsam search "your symbol"'], note: 'No indexing, credentials, network calls, or source-file changes during setup.' });
|
|
46
69
|
}
|
|
47
70
|
|
|
@@ -73,9 +96,9 @@ export async function runKnowledge(argv) {
|
|
|
73
96
|
|
|
74
97
|
export async function runSearch(argv) {
|
|
75
98
|
const { values: opts, positionals } = flags(argv, { semantic: { type: 'boolean' }, 'top-k': { type: 'string' }, 'token-budget': { type: 'string' }, generation: { type: 'string' } });
|
|
76
|
-
if (opts.help) { console.log('agentsam search "query" [--cwd PATH] [--semantic] [--top-k 8] [--token-budget
|
|
99
|
+
if (opts.help) { console.log('agentsam search "query" [--cwd PATH] [--semantic] [--top-k 8] [--token-budget 6000] [--generation ID]'); return; }
|
|
77
100
|
const root = repositoryRoot(opts.cwd), config = readConfig(root), store = await openStore(root, config, true);
|
|
78
|
-
try { show(await retrieve({ store, config, text: positionals.join(' '), semantic: opts.semantic, embedder: opts.semantic ? provider() : null, topK: Number(opts['top-k'] || 8), tokenBudget: Number(opts['token-budget'] ||
|
|
101
|
+
try { show(await retrieve({ store, config, text: positionals.join(' '), semantic: opts.semantic, embedder: opts.semantic ? provider() : null, topK: Number(opts['top-k'] || 8), tokenBudget: Number(opts['token-budget'] || 6000), generationId: opts.generation })); }
|
|
79
102
|
finally { await store?.close(); }
|
|
80
103
|
}
|
|
81
104
|
|