@inneranimalmedia/agentsam-sdk 2.6.3 → 2.6.4
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/AGENTSAM.md +6 -0
- package/README.md +16 -1
- package/bin/agentsam +16 -1
- package/docs/BRAND_INTELLIGENCE.md +1 -1
- package/docs/architecture/AGENTSAM_DISTRIBUTION_OWNERSHIP.md +176 -0
- package/docs/architecture/AGENTSAM_GO_RUNTIME.md +282 -0
- package/docs/architecture/CODEBASEINDEX_GUIDED_PATH.md +202 -0
- package/docs/architecture/FS_E2E_CLOSURE_RECEIPT.md +59 -0
- package/docs/architecture/LOCAL_FS_AUTHORITY.md +38 -0
- package/docs/architecture/LOCAL_STUDIO_CLOUDFLARE_OAUTH.md +28 -0
- package/docs/architecture/PLAN_CLI_AND_LOCAL_STUDIO_DESKTOP.md +96 -0
- package/docs/architecture/SAM_ACTIVITY_RECOVERY_RECEIPT.md +39 -0
- package/docs/architecture/SAM_DECISION_WORK_RECEIPT.md +54 -0
- package/docs/architecture/SAM_KERNEL.md +181 -0
- package/docs/architecture/SAM_MACHINE_NORMALIZATION_PRECOMMIT_REPORT.md +208 -0
- package/docs/architecture/SLASH_SKILLS_PORTABLE.md +116 -0
- package/docs/architecture/fs-e2e-receipt.latest.json +42 -0
- package/docs/architecture/previews/codebaseindex-guided-path/CODEBASEINDEX_GUIDED_PATH.md +202 -0
- package/docs/architecture/previews/codebaseindex-guided-path/index.html +321 -0
- package/migrations/d1/0010_portable_tickets_memory.sql +140 -0
- package/migrations/d1/0011_agentsam_skill_v2.sql +185 -0
- package/migrations/d1/0011b_agentsam_skill_v2_cutover.sql +22 -0
- package/migrations/d1/0011c_agentsam_skill_v2_backfill.sql +76 -0
- package/migrations/d1/0011d_agentsam_skill_v2_retrieval_revisions.sql +50 -0
- package/migrations/d1/0012_agentsam_tools_required_seed.sql +67 -0
- package/migrations/d1/0013_identity_oauth_states.sql +15 -0
- package/migrations/d1/0014_auth_event_log.sql +20 -0
- package/migrations/d1/0015_identity_oauth_state_app_id.sql +3 -0
- package/migrations/d1/README_PORTABLE_CONTROL_PLANE.md +16 -0
- package/migrations/sqlite/agentsam_skill_retrieval.portable.sql +42 -0
- package/package.json +19 -4
- package/packages/agentsam-contracts/src/errors.ts +16 -0
- package/packages/agentsam-errors/src/envelope.js +53 -0
- package/packages/agentsam-errors/src/index.js +1 -0
- package/packages/agentsam-errors/src/recovery.js +301 -0
- package/packages/agentsam-knowledge/src/providers/index.js +18 -6
- package/packages/connectors/cloudflare/src/routes.js +9 -0
- package/packages/connectors/cloudflare/tests/connector.test.mjs +26 -1
- package/packages/identity/.agentsam/features/oauth-login-portal/agentsam.feature.json +1 -1
- package/packages/identity/.agentsam/features/oauth-login-portal/routes.json +11 -2
- package/packages/identity/docs/PORTABLE_IDENTITY_ARCHITECTURE.md +50 -0
- package/packages/identity/migrations/D1_SCHEMA_MAPPING.md +31 -0
- package/packages/identity/migrations/sqlite/001_identity_core.sql +99 -0
- package/packages/identity/migrations/sqlite/002_identity_oauth_client.sql +38 -0
- package/packages/identity/migrations/sqlite/003_identity_oauth_server.sql +64 -0
- package/packages/identity/package.json +2 -2
- package/packages/identity/src/adapters/cloudflare-d1/index.js +122 -22
- package/packages/identity/src/adapters/sqlite/index.js +319 -0
- package/packages/identity/src/app/verify-app.js +95 -0
- package/packages/identity/src/contracts/identity-store.js +115 -0
- package/packages/identity/src/contracts/route-ids.js +30 -0
- package/packages/identity/src/contracts/route-projection.js +218 -0
- package/packages/identity/src/contracts/routes.js +11 -0
- package/packages/identity/src/core/browser-paths.js +4 -5
- package/packages/identity/src/core/constants.js +13 -8
- package/packages/identity/src/core/session-policy.js +32 -0
- package/packages/identity/src/frontend/auth-portal/pages/login.html +10 -10
- package/packages/identity/src/frontend/auth-portal/pages/reset.html +3 -3
- package/packages/identity/src/frontend/auth-portal/pages/signup.html +3 -3
- package/packages/identity/src/frontend/auth-portal/preview/dashboard-stub.html +1 -1
- package/packages/identity/src/index.js +25 -0
- package/packages/identity/src/oauth/README.md +10 -4
- package/packages/identity/src/oauth/credentials.js +20 -13
- package/packages/identity/src/oauth/finalize-inbound.js +1 -1
- package/packages/identity/src/oauth/iam-platform.js +8 -7
- package/packages/identity/src/oauth/redirect-paths.js +27 -36
- package/packages/identity/src/server/identity-service.js +30 -13
- package/packages/identity/src/server/mount-policy.js +30 -0
- package/packages/identity/src/server/post-auth.js +79 -0
- package/packages/identity/src/server/worker-router.js +104 -72
- package/packages/identity/tests/finalize-inbound-oauth.test.mjs +6 -6
- package/packages/identity/tests/iam-provider.test.mjs +1 -1
- package/packages/identity/tests/identity-service.test.mjs +36 -5
- package/packages/identity/tests/oauth-credentials.test.mjs +3 -1
- package/packages/identity/tests/portable-identity-architecture.test.mjs +157 -0
- package/packages/identity/tests/session-routes-policy.test.mjs +21 -0
- package/packages/theme-church-site/package.json +2 -1
- package/packages/theme-church-site/src/index.js +1 -0
- package/packages/theme-companions-site/package.json +2 -1
- package/packages/theme-companions-site/src/index.js +1 -0
- package/packages/theme-floors-site/package.json +2 -1
- package/packages/theme-floors-site/src/index.js +1 -0
- package/packages/theme-fuelnfree-site/package.json +2 -1
- package/packages/theme-fuelnfree-site/src/index.js +1 -0
- package/packages/theme-handyman-site/package.json +2 -1
- package/packages/theme-handyman-site/src/index.js +1 -0
- package/packages/theme-insurance-site/package.json +2 -1
- package/packages/theme-insurance-site/src/index.js +1 -0
- package/packages/theme-shinshu-site/package.json +2 -1
- package/packages/theme-shinshu-site/src/index.js +1 -0
- package/protocol/apps/agentsam.app.v1.schema.json +51 -0
- package/protocol/brand/brandpack.v1.schema.json +43 -0
- package/protocol/credentials/issue.v1.schema.json +38 -0
- package/protocol/database/connection.v1.schema.json +41 -0
- package/protocol/embeddings/embedding-profile.v1.schema.json +20 -0
- package/protocol/errors/error-envelope.schema.json +135 -1
- package/protocol/errors/recovery.v1.schema.json +50 -0
- package/protocol/runtime/workspace-fs.v1.schema.json +71 -0
- package/protocol/sam/activity.v1.schema.json +48 -0
- package/protocol/sam/answer.v1.schema.json +35 -0
- package/protocol/sam/calibration.v1.schema.json +21 -0
- package/protocol/sam/decision-receipt.v1.schema.json +29 -0
- package/protocol/sam/evaluation.v1.schema.json +19 -0
- package/protocol/sam/operation.schema.json +66 -0
- package/protocol/sam/outcome.v1.schema.json +36 -0
- package/protocol/sam/question.v1.schema.json +26 -0
- package/protocol/sam/registry.seed.json +153 -0
- package/protocol/sam/result.schema.json +53 -0
- package/protocol/sam/state.v1.schema.json +23 -0
- package/protocol/skills/agentsam.interaction.v1.schema.json +50 -0
- package/protocol/skills/agentsam.skill.v1.schema.json +57 -0
- package/protocol/ui/icon-registry.mjs +226 -0
- package/protocol/ui/icon.v1.schema.json +51 -0
- package/skills/README.md +22 -9
- package/skills/agentsam-codebaseindex/SKILL.md +225 -0
- package/skills/catalog.json +14 -0
- package/src/cli/command-catalog.js +130 -0
- package/src/cli/dispatch.js +48 -0
- package/src/cli.js +43 -1
- package/src/commands/api-key.js +244 -0
- package/src/commands/app.js +60 -28
- package/src/commands/brand.js +17 -19
- package/src/commands/codebaseindex.js +688 -0
- package/src/commands/env.js +152 -25
- package/src/commands/go.js +366 -53
- package/src/commands/interaction-clack.js +115 -0
- package/src/commands/models.js +1 -1
- package/src/commands/providers.js +62 -14
- package/src/commands/shell.js +43 -2
- package/src/commands/skill.js +248 -0
- package/src/commands/skills.js +1 -1
- package/src/commands/start-local.js +4 -0
- package/src/commands/whoami.js +90 -18
- package/src/go/build.js +229 -39
- package/src/go/cloudflare.js +506 -105
- package/src/go/container.js +120 -0
- package/src/go/contract.js +9 -4
- package/src/go/discover.js +149 -33
- package/src/go/index.js +15 -3
- package/src/go/native-probe-runner.mjs +119 -0
- package/src/go/{registry.js → official-registry.js} +64 -7
- package/src/go/official-release.js +10 -0
- package/src/go/receipts.js +77 -10
- package/src/go/verify.js +9 -2
- package/src/index.js +27 -0
- package/src/indexing/ingest/discover-models.js +298 -0
- package/src/indexing/ingest/inventory.js +243 -0
- package/src/indexing/ingest/job-graph.js +181 -0
- package/src/indexing/ingest/materials.js +210 -0
- package/src/lib/provider-credentials.js +63 -21
- package/src/lib/slash-commands.js +1 -0
- package/src/local-fs/capability.js +121 -0
- package/src/local-fs/freshness.js +75 -0
- package/src/local-fs/index.js +385 -0
- package/src/local-fs/paths.js +100 -0
- package/src/local-pty/server.js +295 -19
- package/src/mcp/client.js +2 -2
- package/src/models/ai-access-onboarding.js +112 -0
- package/src/models/discovery.js +10 -2
- package/src/models/inventory-core.js +9 -1
- package/src/sam/activity/index.js +183 -0
- package/src/sam/client.js +252 -0
- package/src/sam/decision/calibration.js +109 -0
- package/src/sam/decision/confidence.js +126 -0
- package/src/sam/decision/evaluate.js +157 -0
- package/src/sam/decision/evaluators/deterministic.js +341 -0
- package/src/sam/decision/evaluators/heuristic.js +61 -0
- package/src/sam/decision/evaluators/select.js +50 -0
- package/src/sam/decision/evaluators/semantic.js +149 -0
- package/src/sam/decision/hierarchical.js +61 -0
- package/src/sam/decision/index.js +53 -0
- package/src/sam/decision/policy.js +86 -0
- package/src/sam/decision/questions.js +120 -0
- package/src/sam/decision/receipt.js +148 -0
- package/src/sam/decision/state.js +117 -0
- package/src/sam/decision/types.js +22 -0
- package/src/sam/decision/validate.js +200 -0
- package/src/sam/define.js +51 -0
- package/src/sam/index.js +65 -0
- package/src/sam/operations/brand-scan.js +62 -0
- package/src/sam/operations/cad-blender-inspect.js +36 -0
- package/src/sam/operations/codebaseindex-ingest.js +49 -0
- package/src/sam/operations/decision-evaluate.js +59 -0
- package/src/sam/operations/planning-astar.js +77 -0
- package/src/sam/operations/planning-goap.js +60 -0
- package/src/sam/operations/repository-inspect.js +72 -0
- package/src/sam/operations/security-scan.js +33 -0
- package/src/sam/operations/terminal-exec.js +29 -0
- package/src/sam/planning/astar.js +311 -0
- package/src/sam/planning/goap.js +177 -0
- package/src/sam/planning/index.js +21 -0
- package/src/sam/planning/state.js +84 -0
- package/src/sam/registry.js +48 -0
- package/src/sam/result.js +77 -0
- package/src/sam/seed.js +44 -0
- package/src/sam/types.js +91 -0
- package/src/skills/catalog.js +64 -0
- package/src/skills/content-resolver.js +124 -0
- package/src/skills/hosted-store.js +37 -0
- package/src/skills/index.js +29 -64
- package/src/skills/interaction.js +102 -0
- package/src/skills/local-store.js +228 -0
- package/src/skills/manifest.js +104 -0
- package/src/skills/metrics.js +31 -0
- package/src/skills/registry.js +184 -0
- package/src/skills/runtime.js +287 -0
- package/src/skills/slash.js +44 -0
- package/src/ui/cli/help.js +94 -101
- package/test/cli/api-key-env-whoami.test.mjs +129 -0
- package/test/cli/codebaseindex-plan-ux.test.mjs +37 -0
- package/test/cli/go.test.mjs +62 -5
- package/test/cli/skill-npm-and-env.test.mjs +52 -0
- package/test/cli/wireframes-go-registry.test.mjs +87 -2
- package/test/go/build-source-identity.test.mjs +31 -0
- package/test/go/cloudflare-probe.test.mjs +274 -10
- package/test/go/distribution.test.mjs +28 -0
- package/test/integration/ai-access-onboarding.test.mjs +47 -0
- package/test/integration/cli-help.test.mjs +1 -1
- package/test/integration/cms-site-tenancy-contract.test.mjs +6 -6
- package/test/integration/codebaseindex-ingest.test.mjs +166 -0
- package/test/integration/icon-registry.test.mjs +67 -0
- package/test/integration/ingest-discover-models.test.mjs +30 -0
- package/test/integration/install-script.test.mjs +12 -9
- package/test/integration/local-fs.test.mjs +113 -0
- package/test/integration/provider-env-cli.test.mjs +2 -1
- package/test/integration/sam-activity-recovery.test.mjs +147 -0
- package/test/integration/sam-decision.test.mjs +584 -0
- package/test/integration/sam-kernel.test.mjs +99 -0
- package/test/integration/sam-planning-astar.test.mjs +279 -0
- package/test/integration/skill-runtime.test.mjs +240 -0
- package/test/integration/studio-fs-pty-e2e.test.mjs +294 -0
- package/test/models.test.mjs +14 -7
- package/test/shell.test.mjs +4 -4
package/src/ui/cli/help.js
CHANGED
|
@@ -1,87 +1,19 @@
|
|
|
1
1
|
import pc from 'picocolors';
|
|
2
2
|
import { isCancel, select } from '@clack/prompts';
|
|
3
3
|
import pkg from '../../../package.json' with { type: 'json' };
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
['agentsam resume [session]', 'Resume a saved Agent Sam session'],
|
|
13
|
-
['agentsam whoami', 'Show authenticated account and credential status'],
|
|
14
|
-
['agentsam models', 'Probe account-visible hosted/local models'],
|
|
15
|
-
['agentsam providers', 'Configure and verify machine provider credentials'],
|
|
16
|
-
['agentsam env init <provider>', 'Low-level provider profile compatibility command'],
|
|
17
|
-
],
|
|
18
|
-
},
|
|
19
|
-
{
|
|
20
|
-
id: 'work',
|
|
21
|
-
label: 'Build / inspect',
|
|
22
|
-
summary: 'Repository intelligence and normal project work.',
|
|
23
|
-
rows: [
|
|
24
|
-
['agentsam inspect', 'Bounded repository index / authority view'],
|
|
25
|
-
['agentsam index', 'Incremental AST and optional embeddings'],
|
|
26
|
-
['agentsam search "query"', 'Search indexed code/text'],
|
|
27
|
-
['agentsam repo snapshot', 'Git composition/churn snapshot'],
|
|
28
|
-
['agentsam security', 'Dependency and trust-boundary scan'],
|
|
29
|
-
['agentsam merkle', 'Integrity snapshots and comparisons'],
|
|
30
|
-
],
|
|
31
|
-
},
|
|
32
|
-
{
|
|
33
|
-
id: 'runtime',
|
|
34
|
-
label: 'Runtime / terminal',
|
|
35
|
-
summary: 'Local, remote, sandbox, and deployment controls.',
|
|
36
|
-
rows: [
|
|
37
|
-
['agentsam status', 'Honest awareness (account, models, terminal, live deploy) · -i menu'],
|
|
38
|
-
['agentsam start-local', 'Start the local PTY service'],
|
|
39
|
-
['agentsam connections', 'Inspect available execution connections'],
|
|
40
|
-
['agentsam tunnel', 'List, inspect, and run real Cloudflare Tunnels through Wrangler'],
|
|
41
|
-
['agentsam mcp <add|status|doctor|list|remove>', 'Manage MCP connections, server catalogs, and client adapters'],
|
|
42
|
-
['agentsam eval <context|live>', 'Deterministic context scoring or live agent evaluation telemetry'],
|
|
43
|
-
['agentsam deploy', 'Graduate intentionally to cloud infrastructure'],
|
|
44
|
-
['agentsam cloudflare', 'Wrangler and Cloudflare runtime diagnostics'],
|
|
45
|
-
['agentsam go', 'Go runtime discovery, build, Cloudflare container deploy, D1 registry'],
|
|
46
|
-
],
|
|
47
|
-
},
|
|
48
|
-
{
|
|
49
|
-
id: 'inside',
|
|
50
|
-
label: 'Inside Agent Sam',
|
|
51
|
-
summary: 'Commands available while the interactive session is running.',
|
|
52
|
-
rows: [
|
|
53
|
-
['/', 'Open the keyboard command picker'],
|
|
54
|
-
['/model', 'Choose model, reasoning, and processing tier'],
|
|
55
|
-
['/providers', 'Configure and verify machine provider credentials'],
|
|
56
|
-
['/context', 'Show live context economics'],
|
|
57
|
-
['/usage', 'Show token/cost/session receipt'],
|
|
58
|
-
['/settings', 'Change runtime, terminal, and model policy'],
|
|
59
|
-
['/status', 'Honest project awareness + next-step tips'],
|
|
60
|
-
['/connections', 'Inspect live account, terminal, Worker, and Cloudflare connection evidence'],
|
|
61
|
-
['/tunnel', 'Choose an existing Cloudflare Tunnel and inspect or run it through Wrangler'],
|
|
62
|
-
['/help [topic]', 'Show in-session help'],
|
|
63
|
-
['/exit', 'Return to the host shell'],
|
|
64
|
-
],
|
|
65
|
-
},
|
|
66
|
-
{
|
|
67
|
-
id: 'create',
|
|
68
|
-
label: 'Create / extend',
|
|
69
|
-
summary: 'Scaffold and add reusable capabilities.',
|
|
70
|
-
rows: [
|
|
71
|
-
['agentsam create <name> --preset <preset>', 'Create a new AgentSam project'],
|
|
72
|
-
['agentsam add <capability>', 'Add a supported capability'],
|
|
73
|
-
['agentsam capabilities [id]', 'Inspect capability contracts'],
|
|
74
|
-
['agentsam skills [id]', 'Inspect packaged skills'],
|
|
75
|
-
['agentsam identity init', 'Add reusable identity surfaces'],
|
|
76
|
-
['agentsam scaffold <cms|worker-api>', 'Generate a Cloudflare starter project'],
|
|
77
|
-
['agentsam dockerize', 'Build supported container targets'],
|
|
78
|
-
],
|
|
79
|
-
},
|
|
80
|
-
]);
|
|
4
|
+
import {
|
|
5
|
+
CLI_COMMAND_CATALOG,
|
|
6
|
+
CLI_HELP_TOPICS,
|
|
7
|
+
getCliCommand,
|
|
8
|
+
listCliCommands,
|
|
9
|
+
printAssistTip,
|
|
10
|
+
} from '../../cli/command-catalog.js';
|
|
11
|
+
import { SLASH_COMMANDS } from '../../lib/slash-commands.js';
|
|
81
12
|
|
|
82
13
|
const TOPIC_ALIASES = new Map([
|
|
83
14
|
['models', 'start'], ['model', 'start'], ['provider', 'start'], ['providers', 'start'], ['resume', 'start'],
|
|
84
15
|
['repo', 'work'], ['repository', 'work'], ['inspect', 'work'], ['index', 'work'], ['security', 'work'],
|
|
16
|
+
['ingest', 'work'], ['codebaseindex', 'work'], ['codebase-index', 'work'],
|
|
85
17
|
['terminal', 'runtime'], ['connections', 'runtime'], ['remote', 'runtime'], ['sandbox', 'runtime'], ['deploy', 'runtime'],
|
|
86
18
|
['mcp', 'runtime'], ['eval', 'runtime'],
|
|
87
19
|
['slash', 'inside'], ['commands', 'inside'], ['session', 'inside'], ['usage', 'inside'], ['context', 'inside'],
|
|
@@ -92,44 +24,66 @@ function clean(value) {
|
|
|
92
24
|
return value == null ? '' : String(value).trim().toLowerCase();
|
|
93
25
|
}
|
|
94
26
|
|
|
27
|
+
function commandsForTopic(topicId) {
|
|
28
|
+
return listCliCommands({ topic: topicId }).map((entry) => {
|
|
29
|
+
const aliases = (entry.aliases || []).filter((a) => !a.startsWith('-')).slice(0, 2);
|
|
30
|
+
const name = aliases.length ? `agentsam ${entry.id}|${aliases.join('|')}` : `agentsam ${entry.id}`;
|
|
31
|
+
const tip = entry.skill ? ` · skill ${entry.skill}` : '';
|
|
32
|
+
return [name, `${entry.summary}${tip}`];
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
|
|
95
36
|
function padRows(rows) {
|
|
96
|
-
const width = Math.min(
|
|
37
|
+
const width = Math.min(52, Math.max(...rows.map(([command]) => command.length), 0));
|
|
97
38
|
return rows.map(([command, description]) => ' ' + pc.cyan(command.padEnd(width)) + ' ' + pc.dim(description));
|
|
98
39
|
}
|
|
99
40
|
|
|
100
41
|
export function resolveHelpTopic(value) {
|
|
101
42
|
const query = clean(value);
|
|
102
43
|
if (!query) return null;
|
|
103
|
-
const direct =
|
|
104
|
-
if (direct)
|
|
44
|
+
const direct = CLI_HELP_TOPICS.find((topic) => topic.id === query || clean(topic.label) === query);
|
|
45
|
+
if (direct) {
|
|
46
|
+
return { ...direct, rows: commandsForTopic(direct.id) };
|
|
47
|
+
}
|
|
105
48
|
const alias = TOPIC_ALIASES.get(query);
|
|
106
|
-
if (alias)
|
|
107
|
-
|
|
108
|
-
topic
|
|
49
|
+
if (alias) {
|
|
50
|
+
const topic = CLI_HELP_TOPICS.find((t) => t.id === alias);
|
|
51
|
+
return topic ? { ...topic, rows: commandsForTopic(topic.id) } : null;
|
|
52
|
+
}
|
|
53
|
+
const command = getCliCommand(query);
|
|
54
|
+
if (command) {
|
|
55
|
+
const topic = CLI_HELP_TOPICS.find((t) => t.id === command.topic);
|
|
56
|
+
return topic ? { ...topic, rows: commandsForTopic(topic.id) } : null;
|
|
57
|
+
}
|
|
58
|
+
return CLI_HELP_TOPICS.map((topic) => ({ ...topic, rows: commandsForTopic(topic.id) }))
|
|
59
|
+
.find((topic) => topic.rows.some(([cmd, description]) => clean(cmd).includes(query) || clean(description).includes(query))) || null;
|
|
109
60
|
}
|
|
110
61
|
|
|
111
62
|
export function renderHelpOverview(version, options = {}) {
|
|
63
|
+
const common = listCliCommands({ common: true });
|
|
112
64
|
const lines = [
|
|
113
65
|
'',
|
|
114
66
|
' ' + pc.bold('Agent Sam') + ' ' + pc.dim('v' + version),
|
|
115
|
-
' ' + pc.dim('
|
|
67
|
+
' ' + pc.dim('SAM = Systematic Autonomous Machinery · help is generated from the command catalog.'),
|
|
116
68
|
'',
|
|
117
69
|
' ' + pc.bold('Start'),
|
|
118
70
|
' ' + pc.cyan('agentsam') + ' ' + pc.dim('enter the interactive experience'),
|
|
119
71
|
' ' + pc.cyan('agentsam resume') + ' ' + pc.dim('continue saved work'),
|
|
120
|
-
' ' + pc.cyan('agentsam help <topic>') + ' ' + pc.dim('focused help'),
|
|
72
|
+
' ' + pc.cyan('agentsam help <topic>') + ' ' + pc.dim('focused help from catalog'),
|
|
73
|
+
' ' + pc.cyan('agentsam skills <id>') + ' ' + pc.dim('load how-to skill instructions'),
|
|
121
74
|
'',
|
|
122
75
|
' ' + pc.bold('Common'),
|
|
123
|
-
' ' + pc.cyan('agentsam inspect') + ' ' + pc.dim('understand this repository'),
|
|
124
|
-
' ' + pc.cyan('agentsam models') + ' ' + pc.dim('see account-visible models'),
|
|
125
|
-
' ' + pc.cyan('agentsam status') + ' ' + pc.dim('check project/runtime health'),
|
|
126
|
-
' ' + pc.cyan('agentsam security') + ' ' + pc.dim('scan dependency + trust boundaries'),
|
|
127
|
-
' ' + pc.cyan('agentsam deploy') + ' ' + pc.dim('graduate intentionally'),
|
|
128
|
-
'',
|
|
129
|
-
' ' + pc.dim('Inside Agent Sam: press / for the command picker. Ask the selected model for natural-language help at any time.'),
|
|
130
76
|
];
|
|
77
|
+
for (const entry of common) {
|
|
78
|
+
lines.push(' ' + pc.cyan(('agentsam ' + entry.id).padEnd(34)) + ' ' + pc.dim(entry.summary));
|
|
79
|
+
}
|
|
80
|
+
lines.push(
|
|
81
|
+
'',
|
|
82
|
+
' ' + pc.dim('Every command prints: tip: use skill <id> — machine baseline for in-CLI guidance.'),
|
|
83
|
+
' ' + pc.dim('Inside Agent Sam: press / for the command picker.'),
|
|
84
|
+
);
|
|
131
85
|
if (options.showTopics !== false) {
|
|
132
|
-
lines.push('', ' ' + pc.dim('Topics: ' +
|
|
86
|
+
lines.push('', ' ' + pc.dim('Topics: ' + CLI_HELP_TOPICS.map((topic) => topic.id).join(' · ') + ' · all · skills'));
|
|
133
87
|
}
|
|
134
88
|
lines.push('');
|
|
135
89
|
return lines.join('\n');
|
|
@@ -137,21 +91,37 @@ export function renderHelpOverview(version, options = {}) {
|
|
|
137
91
|
|
|
138
92
|
export function renderHelpTopic(topic, version) {
|
|
139
93
|
if (!topic) return renderHelpOverview(version);
|
|
94
|
+
const skillHint = topic.rows?.[0]?.[1]?.includes('skill')
|
|
95
|
+
? ''
|
|
96
|
+
: '';
|
|
140
97
|
return [
|
|
141
98
|
'',
|
|
142
99
|
' ' + pc.bold('Agent Sam') + ' ' + pc.dim('v' + version) + ' ' + pc.dim('·') + ' ' + pc.bold(topic.label),
|
|
143
100
|
' ' + pc.dim(topic.summary),
|
|
144
101
|
'',
|
|
145
|
-
...padRows(topic.rows),
|
|
102
|
+
...padRows(topic.rows || []),
|
|
146
103
|
'',
|
|
147
|
-
' ' + pc.dim('Tip:
|
|
104
|
+
' ' + pc.dim('Tip: agentsam skills <id> loads how-to instructions for that command’s skill.'),
|
|
105
|
+
skillHint,
|
|
148
106
|
'',
|
|
149
107
|
].join('\n');
|
|
150
108
|
}
|
|
151
109
|
|
|
152
110
|
export function renderAllHelp(version) {
|
|
153
111
|
const lines = [renderHelpOverview(version, { showTopics: false })];
|
|
154
|
-
for (const topic of
|
|
112
|
+
for (const topic of CLI_HELP_TOPICS) {
|
|
113
|
+
lines.push(renderHelpTopic({ ...topic, rows: commandsForTopic(topic.id) }, version));
|
|
114
|
+
}
|
|
115
|
+
lines.push(
|
|
116
|
+
'',
|
|
117
|
+
' ' + pc.bold('Inside shell (slash)'),
|
|
118
|
+
...padRows(SLASH_COMMANDS.slice(0, 16).map((row) => [row.cmd, row.description])),
|
|
119
|
+
' ' + pc.dim(`… ${SLASH_COMMANDS.length} slash commands total · /help inside the shell`),
|
|
120
|
+
'',
|
|
121
|
+
' ' + pc.bold('Catalog'),
|
|
122
|
+
' ' + pc.dim(`${CLI_COMMAND_CATALOG.length} top-level commands · source: src/cli/command-catalog.js`),
|
|
123
|
+
'',
|
|
124
|
+
);
|
|
155
125
|
return lines.join('');
|
|
156
126
|
}
|
|
157
127
|
|
|
@@ -160,11 +130,27 @@ export async function runHelp(argv = [], options = {}) {
|
|
|
160
130
|
const write = options.write || ((value) => process.stdout.write(value));
|
|
161
131
|
const args = argv.filter((arg) => arg !== '--interactive');
|
|
162
132
|
|
|
133
|
+
printAssistTip('help', { write: (s) => process.stderr.write(s) });
|
|
134
|
+
|
|
163
135
|
if (args.includes('--all') || args.some((arg) => clean(arg) === 'all')) {
|
|
164
136
|
write(renderAllHelp(version));
|
|
165
137
|
return;
|
|
166
138
|
}
|
|
167
139
|
|
|
140
|
+
if (args.some((arg) => clean(arg) === 'skills' || clean(arg) === 'skill')) {
|
|
141
|
+
write([
|
|
142
|
+
'',
|
|
143
|
+
' ' + pc.bold('Skills') + ' ' + pc.dim('· how-to instructions per surface'),
|
|
144
|
+
' ' + pc.cyan('agentsam skills') + ' ' + pc.dim('list portable skills'),
|
|
145
|
+
' ' + pc.cyan('agentsam skills <id>') + ' ' + pc.dim('print skill instructions'),
|
|
146
|
+
' ' + pc.cyan('agentsam skills <id> --references') + ' ' + pc.dim('include reference docs'),
|
|
147
|
+
'',
|
|
148
|
+
' ' + pc.dim('Every CLI command tip points at a skill id — that is the machine baseline.'),
|
|
149
|
+
'',
|
|
150
|
+
].join('\n'));
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
|
|
168
154
|
const topicArg = args.find((arg) => !arg.startsWith('-'));
|
|
169
155
|
if (topicArg) {
|
|
170
156
|
const topic = resolveHelpTopic(topicArg);
|
|
@@ -184,18 +170,25 @@ export async function runHelp(argv = [], options = {}) {
|
|
|
184
170
|
}
|
|
185
171
|
|
|
186
172
|
const choice = await select({
|
|
187
|
-
message: 'Agent Sam help',
|
|
173
|
+
message: 'Agent Sam help (catalog-driven)',
|
|
188
174
|
options: [
|
|
189
|
-
...
|
|
190
|
-
{ value: '
|
|
175
|
+
...CLI_HELP_TOPICS.map((topic) => ({ value: topic.id, label: topic.label, hint: topic.summary })),
|
|
176
|
+
{ value: 'skills', label: 'Skills', hint: 'How-to instructions loaded via agentsam skills' },
|
|
177
|
+
{ value: 'all', label: 'All commands', hint: 'Print the complete catalog map' },
|
|
191
178
|
{ value: 'exit', label: 'Back', hint: 'Return without printing more help' },
|
|
192
179
|
],
|
|
193
180
|
});
|
|
194
181
|
if (isCancel(choice) || choice === 'exit') return;
|
|
195
182
|
if (choice === 'all') write(renderAllHelp(version));
|
|
196
|
-
else
|
|
183
|
+
else if (choice === 'skills') {
|
|
184
|
+
write([
|
|
185
|
+
'',
|
|
186
|
+
' Run ' + pc.cyan('agentsam skills') + ' to list, or ' + pc.cyan('agentsam skills agentsam-codebaseindex') + ' for ingest how-to.',
|
|
187
|
+
'',
|
|
188
|
+
].join('\n'));
|
|
189
|
+
} else write(renderHelpTopic(resolveHelpTopic(choice), version));
|
|
197
190
|
}
|
|
198
191
|
|
|
199
192
|
export function listHelpTopics() {
|
|
200
|
-
return
|
|
193
|
+
return CLI_HELP_TOPICS.map((topic) => ({ id: topic.id, label: topic.label, summary: topic.summary }));
|
|
201
194
|
}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import assert from 'node:assert/strict';
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import os from 'node:os';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
import test from 'node:test';
|
|
6
|
+
import { runEnv } from '../../src/commands/env.js';
|
|
7
|
+
import { ensureAgentEnvLoader, renderEnvShellExports, setProviderCredential } from '../../src/lib/provider-credentials.js';
|
|
8
|
+
import { runApiKey } from '../../src/commands/api-key.js';
|
|
9
|
+
import { collectWhoami } from '../../src/commands/whoami.js';
|
|
10
|
+
|
|
11
|
+
function tmpHome() {
|
|
12
|
+
return fs.mkdtempSync(path.join(os.tmpdir(), 'agentsam-env-api-'));
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
test('load-agent-env.sh delegates to agentsam env shell (no plaintext secrets)', () => {
|
|
16
|
+
const home = tmpHome();
|
|
17
|
+
const loader = ensureAgentEnvLoader({ home });
|
|
18
|
+
const source = fs.readFileSync(loader, 'utf8');
|
|
19
|
+
assert.match(source, /agentsam env shell --profile default/);
|
|
20
|
+
assert.doesNotMatch(source, /export AGENTSAM_API_KEY=/);
|
|
21
|
+
assert.doesNotMatch(source, /env\.d\//);
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
test('env boot-line prints source load-agent-env without provider args', async () => {
|
|
25
|
+
const home = tmpHome();
|
|
26
|
+
const result = await runEnv(['boot-line'], { home, write: () => {} });
|
|
27
|
+
assert.equal(result.command, 'source ~/.agentsam/load-agent-env.sh');
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
test('env shell emits exports from vault without requiring ambient AGENTSAM_API_KEY', async () => {
|
|
31
|
+
const home = tmpHome();
|
|
32
|
+
setProviderCredential('inneranimalmedia', 'aak_testsecretvalue1234567890abcdef', {
|
|
33
|
+
home,
|
|
34
|
+
disableOsStore: true,
|
|
35
|
+
});
|
|
36
|
+
const result = await runEnv(['shell', '--profile', 'default'], {
|
|
37
|
+
home,
|
|
38
|
+
env: {},
|
|
39
|
+
write: () => {},
|
|
40
|
+
});
|
|
41
|
+
assert.match(result.script, /export AGENTSAM_API_KEY=/);
|
|
42
|
+
assert.ok(result.providers.includes('inneranimalmedia'));
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
test('renderEnvShellExports prefers vault over empty ambient env', () => {
|
|
46
|
+
const home = tmpHome();
|
|
47
|
+
setProviderCredential('cursor', 'cursor_test_key_value_xxxxxxxx', {
|
|
48
|
+
home,
|
|
49
|
+
disableOsStore: true,
|
|
50
|
+
});
|
|
51
|
+
const result = renderEnvShellExports({ home, env: {}, profile: 'default' });
|
|
52
|
+
assert.ok(result.providers.includes('cursor'));
|
|
53
|
+
assert.match(result.script, /export CURSOR_API_KEY=/);
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
test('api-key create stores secret via host mint response', async () => {
|
|
57
|
+
const home = tmpHome();
|
|
58
|
+
const result = await runApiKey(['create', '--name', 'Test Mac', '--store', 'vault', '--activate'], {
|
|
59
|
+
home,
|
|
60
|
+
env: {},
|
|
61
|
+
disableOsStore: true,
|
|
62
|
+
authorityLoader: async () => ({ value: 'oauth_session_token', kind: 'browser_oauth', source: 'test' }),
|
|
63
|
+
postJsonImpl: async () => ({
|
|
64
|
+
ok: true,
|
|
65
|
+
credential: { id: 'aakcred_1', name: 'Test Mac', prefix: 'aak_abc…', scopes: ['account:read'] },
|
|
66
|
+
secret_once: 'aak_mintedsecretvalue1234567890abcd',
|
|
67
|
+
}),
|
|
68
|
+
write: () => {},
|
|
69
|
+
});
|
|
70
|
+
assert.equal(result.ok, true);
|
|
71
|
+
assert.equal(result.activated, true);
|
|
72
|
+
assert.equal(result.credential.prefix, 'aak_abc…');
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
test('whoami surfaces tokenPermissions and authType from context', async () => {
|
|
76
|
+
const home = tmpHome();
|
|
77
|
+
const status = await collectWhoami({
|
|
78
|
+
home,
|
|
79
|
+
env: {},
|
|
80
|
+
authorityLoader: async () => ({ value: 'aak_presented', kind: 'api_key', source: 'environment' }),
|
|
81
|
+
contextLoader: async () => ({
|
|
82
|
+
user_id: 'au_1',
|
|
83
|
+
account_id: 'acct_1',
|
|
84
|
+
email: 'dev@example.test',
|
|
85
|
+
auth_type: 'api_key',
|
|
86
|
+
tokenPermissions: ['account:read', 'repository:read', 'models:invoke'],
|
|
87
|
+
credential: {
|
|
88
|
+
id: 'aakcred_1',
|
|
89
|
+
name: 'Sams-iMac',
|
|
90
|
+
prefix: 'aak_7fm…',
|
|
91
|
+
environment: 'development',
|
|
92
|
+
status: 'active',
|
|
93
|
+
},
|
|
94
|
+
cloudflare: { ok: true },
|
|
95
|
+
byok: {},
|
|
96
|
+
terminal: { available: false, instances: [], connections: [] },
|
|
97
|
+
}),
|
|
98
|
+
});
|
|
99
|
+
assert.equal(status.loggedIn, true);
|
|
100
|
+
assert.equal(status.authType, 'api_key');
|
|
101
|
+
assert.deepEqual(status.tokenPermissions, ['account:read', 'repository:read', 'models:invoke']);
|
|
102
|
+
assert.equal(status.credential.name, 'Sams-iMac');
|
|
103
|
+
assert.doesNotMatch(JSON.stringify(status), /aak_presented/);
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
test('repository does not normalize AGENTSAM_DEFAULT_APP', () => {
|
|
107
|
+
const root = path.resolve(path.dirname(new URL(import.meta.url).pathname), '../..');
|
|
108
|
+
const hits = [];
|
|
109
|
+
function walk(dir) {
|
|
110
|
+
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
111
|
+
if (entry.name === 'node_modules' || entry.name === '.git' || entry.name === 'dist') continue;
|
|
112
|
+
const full = path.join(dir, entry.name);
|
|
113
|
+
if (entry.isDirectory()) walk(full);
|
|
114
|
+
else if (/\.(js|mjs|ts|tsx|sh|json|md)$/.test(entry.name)) {
|
|
115
|
+
const text = fs.readFileSync(full, 'utf8');
|
|
116
|
+
// Allow docs that explicitly forbid the variable.
|
|
117
|
+
if (/AGENTSAM_DEFAULT_APP/.test(text) && !/no AGENTSAM_DEFAULT_APP|not normalize AGENTSAM_DEFAULT_APP|Remove.*AGENTSAM_DEFAULT_APP|doesNotMatch.*AGENTSAM_DEFAULT_APP|APP_SELECTOR=/.test(text)) {
|
|
118
|
+
if (/process\.env\.AGENTSAM_DEFAULT_APP|AGENTSAM_DEFAULT_APP\s*\|\||\$\{AGENTSAM_DEFAULT_APP/.test(text)) {
|
|
119
|
+
hits.push(full);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
walk(path.join(root, 'src'));
|
|
126
|
+
walk(path.join(root, 'scripts'));
|
|
127
|
+
walk(path.join(root, 'apps/local-studio/backend'));
|
|
128
|
+
assert.deepEqual(hits, []);
|
|
129
|
+
});
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import assert from 'node:assert/strict';
|
|
2
|
+
import { describe, it } from 'node:test';
|
|
3
|
+
import {
|
|
4
|
+
createCodebaseindexJobGraph,
|
|
5
|
+
advanceJobGraph,
|
|
6
|
+
freezePlanJobGraph,
|
|
7
|
+
formatJobGraphHuman,
|
|
8
|
+
} from '../../src/indexing/ingest/job-graph.js';
|
|
9
|
+
import { classifyTopLevel } from '../../src/indexing/ingest/inventory.js';
|
|
10
|
+
|
|
11
|
+
describe('codebaseindex job graph plan freeze', () => {
|
|
12
|
+
it('does not leave → run pointer after plan.dry_run', () => {
|
|
13
|
+
let g = createCodebaseindexJobGraph();
|
|
14
|
+
g = advanceJobGraph(g, 'plan.dry_run');
|
|
15
|
+
assert.equal(g.nodes.find((n) => n.status === 'run')?.id, 'ast.parse');
|
|
16
|
+
g = freezePlanJobGraph(g, { skipEmbedding: true });
|
|
17
|
+
assert.equal(g.status, 'planned');
|
|
18
|
+
assert.equal(g.nodes.filter((n) => n.status === 'run').length, 0);
|
|
19
|
+
assert.equal(g.nodes.find((n) => n.id === 'embedding.generate')?.status, 'skipped');
|
|
20
|
+
const text = formatJobGraphHuman(g, { planOnly: true });
|
|
21
|
+
assert.match(text, /PLANNED FOR RUN/);
|
|
22
|
+
assert.match(text, /○ ast\.parse/);
|
|
23
|
+
assert.doesNotMatch(text, /→/);
|
|
24
|
+
});
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
describe('inventory path categories', () => {
|
|
28
|
+
it('classifies source vs dependencies vs generated', () => {
|
|
29
|
+
assert.equal(classifyTopLevel('src'), 'source');
|
|
30
|
+
assert.equal(classifyTopLevel('apps'), 'source');
|
|
31
|
+
assert.equal(classifyTopLevel('docs'), 'docs');
|
|
32
|
+
assert.equal(classifyTopLevel('node_modules'), 'dependencies');
|
|
33
|
+
assert.equal(classifyTopLevel('dist'), 'dependencies');
|
|
34
|
+
assert.equal(classifyTopLevel('generated'), 'generated');
|
|
35
|
+
assert.equal(classifyTopLevel('.agentsam'), 'config');
|
|
36
|
+
});
|
|
37
|
+
});
|
package/test/cli/go.test.mjs
CHANGED
|
@@ -9,6 +9,11 @@ import { runGo } from '../../src/commands/go.js';
|
|
|
9
9
|
|
|
10
10
|
const SDK_ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '../..');
|
|
11
11
|
|
|
12
|
+
|
|
13
|
+
function tempStateRoot() {
|
|
14
|
+
return fs.mkdtempSync(path.join(os.tmpdir(), 'agentsam-go-test-state-'));
|
|
15
|
+
}
|
|
16
|
+
|
|
12
17
|
test('discoverGoRuntime finds agentsam-go-worker without inventing a sibling', () => {
|
|
13
18
|
const discovery = discoverGoRuntime(SDK_ROOT);
|
|
14
19
|
assert.equal(discovery.go.ok, true);
|
|
@@ -30,30 +35,75 @@ test('ensureProductContract refuses missing product roots instead of scaffolding
|
|
|
30
35
|
test('buildGoProduct emits build receipt after go test/vet/build', () => {
|
|
31
36
|
const discovery = discoverGoRuntime(SDK_ROOT);
|
|
32
37
|
const productRoot = resolveProductRoot(discovery);
|
|
38
|
+
const stateRoot = tempStateRoot();
|
|
33
39
|
const result = buildGoProduct({
|
|
34
40
|
productRoot,
|
|
35
41
|
runtimeRoot: discovery.runtime.runtimeRoot,
|
|
36
42
|
repositoryRoot: discovery.repository_root,
|
|
43
|
+
stateRoot,
|
|
37
44
|
});
|
|
38
45
|
assert.equal(result.receipt.schema, 'agentsam.go-build-receipt.v1');
|
|
39
46
|
assert.equal(result.tests.ok, true);
|
|
40
47
|
assert.equal(result.vet.ok, true);
|
|
41
48
|
assert.ok(result.build.binary);
|
|
49
|
+
assert.match(result.receipt.artifact.digest, /^sha256:[a-f0-9]{64}$/);
|
|
50
|
+
assert.equal(result.receipt.tests.runtime_probe, true);
|
|
51
|
+
assert.match(result.receipt.source.identity, /^git:[a-f0-9]{40}$/);
|
|
52
|
+
assert.equal(result.probe.checks.source_identity, true);
|
|
53
|
+
assert.equal(result.probe.checks.source_commit, true);
|
|
54
|
+
assert.equal(result.probe.checks.error_envelope, true);
|
|
55
|
+
assert.equal(result.probe.checks.clean_shutdown, true);
|
|
42
56
|
assert.ok(fs.existsSync(result.receiptPath));
|
|
43
57
|
});
|
|
44
58
|
|
|
59
|
+
test('agentsam go build --json exposes only portable build paths', async () => {
|
|
60
|
+
const stateRoot = tempStateRoot();
|
|
61
|
+
const chunks = [];
|
|
62
|
+
|
|
63
|
+
const result = await runGo(
|
|
64
|
+
['build', '--json'],
|
|
65
|
+
{
|
|
66
|
+
write: (value) => chunks.push(String(value)),
|
|
67
|
+
stateRoot,
|
|
68
|
+
},
|
|
69
|
+
);
|
|
70
|
+
|
|
71
|
+
assert.ok(path.isAbsolute(result.receiptPath), 'internal execution keeps absolute receipt path');
|
|
72
|
+
assert.ok(path.isAbsolute(result.build.binary), 'internal execution keeps absolute binary path');
|
|
73
|
+
|
|
74
|
+
const output = chunks.join('');
|
|
75
|
+
const parsed = JSON.parse(output);
|
|
76
|
+
|
|
77
|
+
assert.equal(path.isAbsolute(parsed.receiptPath), false);
|
|
78
|
+
assert.equal(path.isAbsolute(parsed.build.binary), false);
|
|
79
|
+
assert.equal(path.isAbsolute(parsed.receipt.runtime.module_root), false);
|
|
80
|
+
assert.equal(Object.hasOwn(parsed.probe || {}, 'origin'), false);
|
|
81
|
+
assert.equal(Object.hasOwn(parsed.receipt?.probe || {}, 'origin'), false);
|
|
82
|
+
assert.equal(output.includes(SDK_ROOT), false);
|
|
83
|
+
});
|
|
84
|
+
|
|
45
85
|
test('agentsam go --cloudflare agentsam-go-worker --skip-deploy is idempotent', async () => {
|
|
86
|
+
const stateRoot = tempStateRoot();
|
|
46
87
|
const chunks = [];
|
|
47
88
|
const write = (v) => chunks.push(String(v));
|
|
48
|
-
const first = await runGo(
|
|
89
|
+
const first = await runGo(
|
|
90
|
+
['--cloudflare', 'agentsam-go-worker', '--skip-deploy', '--json'],
|
|
91
|
+
{ write, stateRoot },
|
|
92
|
+
);
|
|
49
93
|
assert.equal(first.ok, true);
|
|
50
94
|
assert.equal(first.product, 'agentsam-go-worker');
|
|
51
95
|
assert.equal(first.scaffold_changes_required, false);
|
|
96
|
+
assert.equal(first.mode, 'self_host');
|
|
97
|
+
assert.equal(first.deploy.registry.reason, 'self_host_registry_isolated');
|
|
52
98
|
|
|
53
99
|
const chunks2 = [];
|
|
54
|
-
const second = await runGo(
|
|
55
|
-
|
|
56
|
-
|
|
100
|
+
const second = await runGo(
|
|
101
|
+
['--cloudflare', 'agentsam-go-worker', '--skip-deploy', '--json'],
|
|
102
|
+
{
|
|
103
|
+
write: (v) => chunks2.push(String(v)),
|
|
104
|
+
stateRoot,
|
|
105
|
+
},
|
|
106
|
+
);
|
|
57
107
|
assert.equal(second.ok, true);
|
|
58
108
|
assert.equal(second.existing_product, true);
|
|
59
109
|
assert.equal(second.scaffold_changes_required, false);
|
|
@@ -62,8 +112,15 @@ test('agentsam go --cloudflare agentsam-go-worker --skip-deploy is idempotent',
|
|
|
62
112
|
});
|
|
63
113
|
|
|
64
114
|
test('agentsam go status --json reports discovery', async () => {
|
|
115
|
+
const stateRoot = tempStateRoot();
|
|
65
116
|
const chunks = [];
|
|
66
|
-
const result = await runGo(
|
|
117
|
+
const result = await runGo(
|
|
118
|
+
['status', '--json'],
|
|
119
|
+
{
|
|
120
|
+
write: (v) => chunks.push(String(v)),
|
|
121
|
+
stateRoot,
|
|
122
|
+
},
|
|
123
|
+
);
|
|
67
124
|
assert.equal(result.ok, true);
|
|
68
125
|
assert.ok(result.discovery.go.ok);
|
|
69
126
|
const parsed = JSON.parse(chunks.join(''));
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import assert from 'node:assert/strict';
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import os from 'node:os';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
import { spawnSync } from 'node:child_process';
|
|
6
|
+
import test from 'node:test';
|
|
7
|
+
import { resolveNpmSkillPackage } from '../../src/commands/skill.js';
|
|
8
|
+
import { installSkillFromPath } from '../../src/skills/index.js';
|
|
9
|
+
import { runEnv } from '../../src/commands/env.js';
|
|
10
|
+
|
|
11
|
+
function tmpHome() {
|
|
12
|
+
return fs.mkdtempSync(path.join(os.tmpdir(), 'agentsam-finish-'));
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
test('resolveNpmSkillPackage extracts agentsam.skill.json via npm pack', (t) => {
|
|
16
|
+
// Build a tiny local package and pack it by path (no registry).
|
|
17
|
+
const pkgRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'agentsam-npm-skill-'));
|
|
18
|
+
fs.writeFileSync(
|
|
19
|
+
path.join(pkgRoot, 'package.json'),
|
|
20
|
+
JSON.stringify({ name: 'tmp-agentsam-skill-fixture', version: '0.0.0', private: true }),
|
|
21
|
+
);
|
|
22
|
+
fs.writeFileSync(
|
|
23
|
+
path.join(pkgRoot, 'agentsam.skill.json'),
|
|
24
|
+
JSON.stringify({
|
|
25
|
+
schema: 'agentsam.skill.v1',
|
|
26
|
+
id: 'npm-fixture',
|
|
27
|
+
name: 'NPM Fixture',
|
|
28
|
+
slash: { suggested: '/npm-fixture' },
|
|
29
|
+
instructions: { source: 'inline', inline: '# npm fixture' },
|
|
30
|
+
execution: { mode: 'turn' },
|
|
31
|
+
}),
|
|
32
|
+
);
|
|
33
|
+
const resolved = resolveNpmSkillPackage(pkgRoot, { spawnSyncImpl: spawnSync });
|
|
34
|
+
assert.ok(fs.existsSync(path.join(resolved, 'agentsam.skill.json')));
|
|
35
|
+
|
|
36
|
+
const home = tmpHome();
|
|
37
|
+
const installed = installSkillFromPath(resolved, { home });
|
|
38
|
+
assert.equal(installed.id, 'npm-fixture');
|
|
39
|
+
assert.equal(installed.trigger, '/npm-fixture');
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
test('env boot-line prints source load-agent-env command', async () => {
|
|
43
|
+
const home = tmpHome();
|
|
44
|
+
const lines = [];
|
|
45
|
+
const result = await runEnv(['boot-line', 'cursor', 'inneranimalmedia'], {
|
|
46
|
+
home,
|
|
47
|
+
write: (t) => lines.push(t),
|
|
48
|
+
});
|
|
49
|
+
assert.equal(result.command, 'source ~/.agentsam/load-agent-env.sh');
|
|
50
|
+
assert.ok(lines.join('').includes('load-agent-env.sh'));
|
|
51
|
+
assert.ok(lines.join('').includes('agentsam env shell'));
|
|
52
|
+
});
|