@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
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Present AgentSamInteraction via Clack (or plain write fallback).
|
|
3
|
+
* Hosts (shell, Local Studio, Tauri) can swap the prompt impls.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { confirm, isCancel, select, text } from '@clack/prompts';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @param {import('../skills/interaction.js').AgentSamInteraction} interaction
|
|
10
|
+
* @param {{
|
|
11
|
+
* write?: (s: string) => void,
|
|
12
|
+
* interactive?: boolean,
|
|
13
|
+
* selectImpl?: typeof select,
|
|
14
|
+
* confirmImpl?: typeof confirm,
|
|
15
|
+
* textImpl?: typeof text,
|
|
16
|
+
* }} [options]
|
|
17
|
+
* @returns {Promise<{ action: string|null, value: string|null, cancelled: boolean }>}
|
|
18
|
+
*/
|
|
19
|
+
export async function presentAgentSamInteraction(interaction, options = {}) {
|
|
20
|
+
const write = options.write || ((s) => process.stdout.write(s));
|
|
21
|
+
const interactive =
|
|
22
|
+
options.interactive ?? Boolean(process.stdin.isTTY && process.stdout.isTTY);
|
|
23
|
+
const prompt = interaction?.prompt;
|
|
24
|
+
|
|
25
|
+
if (!prompt?.message) {
|
|
26
|
+
return { action: null, value: null, cancelled: false };
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
for (const line of String(prompt.message).split('\n')) {
|
|
30
|
+
write(` ${line}\n`);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (!interactive) {
|
|
34
|
+
return { action: null, value: null, cancelled: false };
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const status = interaction.status;
|
|
38
|
+
|
|
39
|
+
if (status === 'needs_input' && prompt.kind === 'select' && Array.isArray(prompt.options) && prompt.options.length) {
|
|
40
|
+
const answer = await (options.selectImpl || select)({
|
|
41
|
+
message: prompt.title || 'Choose',
|
|
42
|
+
options: prompt.options.map((opt) => ({
|
|
43
|
+
value: opt.value,
|
|
44
|
+
label: opt.label,
|
|
45
|
+
hint: opt.description,
|
|
46
|
+
})),
|
|
47
|
+
});
|
|
48
|
+
if (isCancel(answer)) return { action: null, value: null, cancelled: true };
|
|
49
|
+
return { action: String(answer), value: String(answer), cancelled: false };
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if (status === 'needs_input' && prompt.kind === 'text') {
|
|
53
|
+
const answer = await (options.textImpl || text)({
|
|
54
|
+
message: prompt.title || prompt.message,
|
|
55
|
+
});
|
|
56
|
+
if (isCancel(answer)) return { action: null, value: null, cancelled: true };
|
|
57
|
+
return { action: 'text', value: String(answer), cancelled: false };
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if (status === 'needs_approval' || (status === 'needs_input' && prompt.kind === 'confirm')) {
|
|
61
|
+
const answer = await (options.confirmImpl || confirm)({
|
|
62
|
+
message: prompt.title || prompt.message,
|
|
63
|
+
});
|
|
64
|
+
if (isCancel(answer)) return { action: null, value: null, cancelled: true };
|
|
65
|
+
return { action: answer ? 'confirm' : 'cancel', value: answer ? 'yes' : 'no', cancelled: false };
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if (
|
|
69
|
+
(status === 'blocked' || status === 'needs_input') &&
|
|
70
|
+
Array.isArray(prompt.actions) &&
|
|
71
|
+
prompt.actions.length
|
|
72
|
+
) {
|
|
73
|
+
const answer = await (options.selectImpl || select)({
|
|
74
|
+
message: prompt.title || 'Next',
|
|
75
|
+
options: prompt.actions.map((a) => ({ value: a.id, label: a.label })),
|
|
76
|
+
});
|
|
77
|
+
if (isCancel(answer)) return { action: null, value: null, cancelled: true };
|
|
78
|
+
return { action: String(answer), value: String(answer), cancelled: false };
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
return { action: null, value: null, cancelled: false };
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Map shell skill interaction choices to follow-up CLI actions.
|
|
86
|
+
*/
|
|
87
|
+
export async function handleSkillInteractionChoice(choice, state = {}) {
|
|
88
|
+
const write = state.write || ((s) => process.stdout.write(s));
|
|
89
|
+
const { runSkill } = await import('./skill.js');
|
|
90
|
+
if (!choice || choice.cancelled) return null;
|
|
91
|
+
if (choice.action === 'create' || choice.value === 'create') {
|
|
92
|
+
const id = 'my-first-skill';
|
|
93
|
+
write(`\n Running: agentsam skill create ${id}\n\n`);
|
|
94
|
+
return runSkill(['create', id], { write, home: state.home, env: state.env });
|
|
95
|
+
}
|
|
96
|
+
if (typeof choice.value === 'string' && choice.value.startsWith('create:')) {
|
|
97
|
+
const id = choice.value.slice('create:'.length) || 'my-first-skill';
|
|
98
|
+
write(`\n Running: agentsam skill create ${id}\n\n`);
|
|
99
|
+
return runSkill(['create', id], { write, home: state.home, env: state.env });
|
|
100
|
+
}
|
|
101
|
+
if (typeof choice.action === 'string' && choice.action.startsWith('create:')) {
|
|
102
|
+
const id = choice.action.slice('create:'.length) || 'my-first-skill';
|
|
103
|
+
write(`\n Running: agentsam skill create ${id}\n\n`);
|
|
104
|
+
return runSkill(['create', id], { write, home: state.home, env: state.env });
|
|
105
|
+
}
|
|
106
|
+
if (choice.action === 'install' || choice.value === 'install') {
|
|
107
|
+
write('\n Next: agentsam skill install ./path-to-skill (or @scope/pkg)\n\n');
|
|
108
|
+
return null;
|
|
109
|
+
}
|
|
110
|
+
if (choice.action === 'list' || choice.value === 'list') {
|
|
111
|
+
return runSkill(['list'], { write, home: state.home, env: state.env });
|
|
112
|
+
}
|
|
113
|
+
// create with prefilled id handled above
|
|
114
|
+
return null;
|
|
115
|
+
}
|
package/src/commands/models.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import pc from 'picocolors';
|
|
2
2
|
import { isCancel, select } from '@clack/prompts';
|
|
3
3
|
import { probeOllama, resolveOllamaConfig } from './ollama.js';
|
|
4
|
-
import { listModelCatalog } from '../models/
|
|
4
|
+
import { listModelCatalog } from '../models/catalog.js';
|
|
5
5
|
import { discoverProviderModels } from '../models/discovery.js';
|
|
6
6
|
import { resolveProviderCredential } from '../lib/provider-credentials.js';
|
|
7
7
|
import { providerChoices, promptAndConfigureProvider } from './providers.js';
|
|
@@ -164,8 +164,13 @@ export async function validateAndSaveProviderCredential(provider, secret, option
|
|
|
164
164
|
};
|
|
165
165
|
}
|
|
166
166
|
|
|
167
|
-
// Key is verified
|
|
168
|
-
|
|
167
|
+
// Key is verified. Persist securely to the OS store + AES-256-GCM vault.
|
|
168
|
+
// Plaintext shell profiles remain explicit opt-in only.
|
|
169
|
+
setProviderCredential(id, cleanSecret, {
|
|
170
|
+
...options,
|
|
171
|
+
accountId,
|
|
172
|
+
writeEnvProfile: options.writeEnvProfile === true,
|
|
173
|
+
});
|
|
169
174
|
|
|
170
175
|
return {
|
|
171
176
|
attempted: true,
|
|
@@ -213,7 +218,11 @@ export async function promptAndConfigureProvider(provider, options = {}) {
|
|
|
213
218
|
const spin = options.spinnerImpl ? options.spinnerImpl() : spinner();
|
|
214
219
|
spin.start(`Verifying ${spec.label} API credential`);
|
|
215
220
|
|
|
216
|
-
const result = await validateAndSaveProviderCredential(id, String(secret), {
|
|
221
|
+
const result = await validateAndSaveProviderCredential(id, String(secret), {
|
|
222
|
+
...options,
|
|
223
|
+
accountId,
|
|
224
|
+
writeEnvProfile: options.writeEnvProfile === true,
|
|
225
|
+
});
|
|
217
226
|
|
|
218
227
|
if (!result.ok) {
|
|
219
228
|
spin.stop(`Verification failed: ${result.error || 'invalid key'} · Key was NOT saved`, 1);
|
|
@@ -255,10 +264,19 @@ async function runInteractiveProviders(options = {}) {
|
|
|
255
264
|
}
|
|
256
265
|
|
|
257
266
|
function parseArgs(argv = []) {
|
|
258
|
-
const out = {
|
|
267
|
+
const out = {
|
|
268
|
+
command: 'interactive',
|
|
269
|
+
provider: '',
|
|
270
|
+
json: false,
|
|
271
|
+
verify: false,
|
|
272
|
+
yes: false,
|
|
273
|
+
fromEnv: '',
|
|
274
|
+
fromStdin: false,
|
|
275
|
+
exportProfile: true,
|
|
276
|
+
};
|
|
259
277
|
const args = [...argv];
|
|
260
278
|
if (args[0] && !args[0].startsWith('-')) out.command = args.shift();
|
|
261
|
-
if (['add', 'set', 'remove', 'verify', 'status', 'export'].includes(out.command) && args[0] && !args[0].startsWith('-')) {
|
|
279
|
+
if (['add', 'set', 'remove', 'verify', 'status', 'export', 'roll'].includes(out.command) && args[0] && !args[0].startsWith('-')) {
|
|
262
280
|
out.provider = normalizeProviderId(args.shift());
|
|
263
281
|
}
|
|
264
282
|
while (args.length) {
|
|
@@ -267,6 +285,9 @@ function parseArgs(argv = []) {
|
|
|
267
285
|
else if (arg === '--verify') out.verify = true;
|
|
268
286
|
else if (arg === '--yes' || arg === '-y') out.yes = true;
|
|
269
287
|
else if (arg === '--from-env') out.fromEnv = clean(args.shift());
|
|
288
|
+
else if (arg === '--from-stdin') out.fromStdin = true;
|
|
289
|
+
else if (arg === '--no-export') out.exportProfile = false;
|
|
290
|
+
else if (arg === '--export') out.exportProfile = true;
|
|
270
291
|
else if (arg === '--help' || arg === '-h') out.command = 'help';
|
|
271
292
|
else throw new Error(`unknown providers option: ${arg}`);
|
|
272
293
|
}
|
|
@@ -281,13 +302,17 @@ export async function runProviders(argv = [], options = {}) {
|
|
|
281
302
|
write([
|
|
282
303
|
'agentsam providers',
|
|
283
304
|
'agentsam providers status [provider] [--verify] [--json]',
|
|
284
|
-
'agentsam providers add <provider> [--from-env NAME]',
|
|
305
|
+
'agentsam providers add <provider> [--from-env NAME|--from-stdin] [--no-export]',
|
|
306
|
+
'agentsam providers roll <provider> [--from-env NAME|--from-stdin] replace + export env.d',
|
|
285
307
|
'agentsam providers export <provider>',
|
|
286
308
|
'agentsam providers verify [provider] [--json]',
|
|
287
309
|
'agentsam providers remove <provider> [--yes]',
|
|
288
310
|
'',
|
|
289
311
|
`Providers: ${PROVIDER_ORDER.join(', ')}`,
|
|
290
312
|
'',
|
|
313
|
+
'Boot load: source ~/.agentsam/load-agent-env.sh <provider…>',
|
|
314
|
+
' agentsam env boot-line',
|
|
315
|
+
'',
|
|
291
316
|
].join('\n'));
|
|
292
317
|
return;
|
|
293
318
|
}
|
|
@@ -338,24 +363,47 @@ export async function runProviders(argv = [], options = {}) {
|
|
|
338
363
|
return results;
|
|
339
364
|
}
|
|
340
365
|
|
|
341
|
-
if (parsed.command === 'add' || parsed.command === 'set') {
|
|
366
|
+
if (parsed.command === 'add' || parsed.command === 'set' || parsed.command === 'roll') {
|
|
342
367
|
if (!parsed.provider) throw new Error('providers add requires a provider');
|
|
343
|
-
if (parsed.
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
368
|
+
if (parsed.command === 'roll') {
|
|
369
|
+
removeProviderCredential(parsed.provider, options);
|
|
370
|
+
}
|
|
371
|
+
let secretValue = '';
|
|
372
|
+
if (parsed.fromStdin) {
|
|
373
|
+
const chunks = [];
|
|
374
|
+
for await (const chunk of options.stdin || process.stdin) chunks.push(chunk);
|
|
375
|
+
secretValue = Buffer.concat(chunks.map((c) => (Buffer.isBuffer(c) ? c : Buffer.from(c)))).toString('utf8').trim();
|
|
376
|
+
if (!secretValue) throw new Error('stdin credential missing');
|
|
377
|
+
} else if (parsed.fromEnv) {
|
|
378
|
+
secretValue = clean((options.env || process.env)[parsed.fromEnv]);
|
|
379
|
+
if (!secretValue) throw new Error(`environment credential missing: ${parsed.fromEnv}`);
|
|
380
|
+
}
|
|
381
|
+
if (secretValue) {
|
|
382
|
+
const verified = await validateAndSaveProviderCredential(parsed.provider, secretValue, {
|
|
383
|
+
...options,
|
|
384
|
+
writeEnvProfile: parsed.exportProfile,
|
|
385
|
+
});
|
|
347
386
|
if (!verified.ok) {
|
|
348
387
|
throw new Error(`Provider verification failed: ${verified.error}. Credential was not saved.`);
|
|
349
388
|
}
|
|
350
|
-
writeLine(write, ` ${parsed.provider} verified · ${
|
|
389
|
+
writeLine(write, ` ${parsed.provider} verified · saved${parsed.exportProfile ? ' · env.d exported' : ''}`);
|
|
390
|
+
if (parsed.exportProfile) {
|
|
391
|
+
writeLine(write, ` source ~/.agentsam/load-agent-env.sh ${parsed.provider}`);
|
|
392
|
+
}
|
|
351
393
|
return verified;
|
|
352
394
|
}
|
|
353
395
|
if (options.interactive === false || !(options.interactive ?? Boolean(process.stdin.isTTY && process.stdout.isTTY))) {
|
|
354
|
-
throw new Error('providers add requires an interactive terminal
|
|
396
|
+
throw new Error('providers add requires an interactive terminal, --from-env NAME, or --from-stdin');
|
|
355
397
|
}
|
|
356
|
-
const result = await promptAndConfigureProvider(parsed.provider,
|
|
398
|
+
const result = await promptAndConfigureProvider(parsed.provider, {
|
|
399
|
+
...options,
|
|
400
|
+
writeEnvProfile: parsed.exportProfile,
|
|
401
|
+
});
|
|
357
402
|
if (!result) return null;
|
|
358
403
|
writeLine(write, result.ok ? ` ${parsed.provider} verified` : ` ${parsed.provider} verification failed: ${result.error}`);
|
|
404
|
+
if (result.ok && parsed.exportProfile) {
|
|
405
|
+
writeLine(write, ` source ~/.agentsam/load-agent-env.sh ${parsed.provider}`);
|
|
406
|
+
}
|
|
359
407
|
return result;
|
|
360
408
|
}
|
|
361
409
|
|
package/src/commands/shell.js
CHANGED
|
@@ -20,7 +20,7 @@ import { createInlineActivity } from '../ui/cli/activity.js';
|
|
|
20
20
|
import { createCliRuntimePresenter } from '../ui/cli/runtime-events.js';
|
|
21
21
|
import { renderCliFooter, renderDiffPreview, renderUsagePanel } from '../ui/cli/footer.js';
|
|
22
22
|
import { diagnosticFromError, renderDiagnosticError } from '../errors/index.js';
|
|
23
|
-
import { getModelRecord, mergeModelReference } from '../models/index.js';
|
|
23
|
+
import { getModelRecord, mergeModelReference, listModelCatalog } from '../models/index.js';
|
|
24
24
|
import { discoverProviderModels } from '../models/discovery.js';
|
|
25
25
|
import { detectCliProject, findCliProjectRoot, readCliPreferences, updateCliPreferences } from '../lib/cli-preferences.js';
|
|
26
26
|
import { buildContextEconomicsReport, renderContextEconomics } from './context-economics.js';
|
|
@@ -40,6 +40,11 @@ import { tryResolveGitContext } from '../../packages/agentsam-repository/src/git
|
|
|
40
40
|
import { syncWorkspaceStateToD1, readWorkspaceStateFromD1 } from '../../packages/agentsam-repository/src/workspace-state.js';
|
|
41
41
|
import { syncGitCommitsToD1 } from '../../packages/agentsam-repository/src/work-tracking.js';
|
|
42
42
|
import { readGoapState, listGoapTickets, createGoapGoal, switchGoapGoal, closeGoapGoal, renderGoapStatus, renderGoapList, renderGoapGoal, renderGoapWhy, renderGoapPlan } from '../../packages/agentsam-repository/src/goap.js';
|
|
43
|
+
import { SkillRegistry, SkillRuntime, SkillContentResolver } from '../skills/index.js';
|
|
44
|
+
import {
|
|
45
|
+
presentAgentSamInteraction,
|
|
46
|
+
handleSkillInteractionChoice,
|
|
47
|
+
} from './interaction-clack.js';
|
|
43
48
|
|
|
44
49
|
function writeLine(write, value = '') { write(`${value}\n`); }
|
|
45
50
|
|
|
@@ -1026,8 +1031,44 @@ export async function dispatchShellLine(line, state = {}) {
|
|
|
1026
1031
|
await runInteractiveModelTurn(line, state);
|
|
1027
1032
|
break;
|
|
1028
1033
|
}
|
|
1034
|
+
{
|
|
1035
|
+
// Explicit slash → portable skill registry (no D1 / R2 / subagents).
|
|
1036
|
+
const skillRuntime = new SkillRuntime({
|
|
1037
|
+
registry: new SkillRegistry({ home: state.home }),
|
|
1038
|
+
contentResolver: new SkillContentResolver(),
|
|
1039
|
+
});
|
|
1040
|
+
const skillResult = await skillRuntime.invoke({ input: line });
|
|
1041
|
+
if (skillResult.matched) {
|
|
1042
|
+
const interactiveStatuses = new Set(['needs_input', 'needs_approval', 'blocked']);
|
|
1043
|
+
if (
|
|
1044
|
+
state.interactive &&
|
|
1045
|
+
interactiveStatuses.has(skillResult.interaction?.status) &&
|
|
1046
|
+
skillResult.interaction?.prompt
|
|
1047
|
+
) {
|
|
1048
|
+
const choice = await presentAgentSamInteraction(skillResult.interaction, {
|
|
1049
|
+
write,
|
|
1050
|
+
interactive: state.interactive,
|
|
1051
|
+
});
|
|
1052
|
+
if (choice.action === 'create' || String(choice.value || '').startsWith('create')) {
|
|
1053
|
+
await handleSkillInteractionChoice(choice, { write, home: state.home });
|
|
1054
|
+
} else if (choice.action === 'list' || choice.value === 'list') {
|
|
1055
|
+
await handleSkillInteractionChoice(choice, { write, home: state.home });
|
|
1056
|
+
} else if (choice.action === 'install' || choice.value === 'install') {
|
|
1057
|
+
await handleSkillInteractionChoice(choice, { write, home: state.home });
|
|
1058
|
+
}
|
|
1059
|
+
} else if (skillResult.interaction?.prompt?.message) {
|
|
1060
|
+
for (const msgLine of String(skillResult.interaction.prompt.message).split('\n')) {
|
|
1061
|
+
writeLine(write, ` ${msgLine}`);
|
|
1062
|
+
}
|
|
1063
|
+
} else if (skillResult.modelInstructions?.content) {
|
|
1064
|
+
writeLine(write, ` skill ${skillResult.skill?.id} · ${skillResult.receipt?.checksum || 'resolved'}`);
|
|
1065
|
+
writeLine(write, ` (turn instructions ready · ${skillResult.tools?.length || 0} tools declared)`);
|
|
1066
|
+
}
|
|
1067
|
+
break;
|
|
1068
|
+
}
|
|
1069
|
+
}
|
|
1029
1070
|
writeLine(write, ` Unknown Agent Sam command: ${command}`);
|
|
1030
|
-
writeLine(write, ' Type / or /help for available commands.');
|
|
1071
|
+
writeLine(write, ' Type / or /help for available commands. Use /skills for installable slash skills.');
|
|
1031
1072
|
return { handled: false, exit: false, cwd: state.cwd };
|
|
1032
1073
|
}
|
|
1033
1074
|
} catch (error) {
|
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import os from 'node:os';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { spawnSync } from 'node:child_process';
|
|
5
|
+
import {
|
|
6
|
+
SkillRegistry,
|
|
7
|
+
SkillRuntime,
|
|
8
|
+
SkillContentResolver,
|
|
9
|
+
createUserSkill,
|
|
10
|
+
installSkillFromPath,
|
|
11
|
+
aliasSkill,
|
|
12
|
+
removeSkill,
|
|
13
|
+
readLocalRegistry,
|
|
14
|
+
} from '../skills/index.js';
|
|
15
|
+
|
|
16
|
+
function writeLine(write, value = '') {
|
|
17
|
+
write(`${value}\n`);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function help() {
|
|
21
|
+
return [
|
|
22
|
+
'AgentSam · skill',
|
|
23
|
+
' agentsam skill list',
|
|
24
|
+
' agentsam skill create <id>',
|
|
25
|
+
' agentsam skill inspect <id>',
|
|
26
|
+
' agentsam skill edit <id> (prints path to edit)',
|
|
27
|
+
' agentsam skill install <path|npm-package> [--alias /trigger]',
|
|
28
|
+
' agentsam skill alias <id> </trigger>',
|
|
29
|
+
' agentsam skill remove <id>',
|
|
30
|
+
' agentsam skill publish <id> (prints package checklist; no network)',
|
|
31
|
+
' agentsam skill invoke </trigger> [args...]',
|
|
32
|
+
'',
|
|
33
|
+
'Slash triggers are local. Package manifests only suggest a trigger.',
|
|
34
|
+
'Collisions require an explicit alias — nothing is globally reserved.',
|
|
35
|
+
'',
|
|
36
|
+
].join('\n');
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function looksLikeNpmPackage(source) {
|
|
40
|
+
const s = String(source || '').trim();
|
|
41
|
+
if (!s) return false;
|
|
42
|
+
if (s.startsWith('.') || s.startsWith('/') || s.includes('\\')) return false;
|
|
43
|
+
if (s.startsWith('@')) return true;
|
|
44
|
+
// bare package name (no path separators)
|
|
45
|
+
return !s.includes('/') && !s.endsWith('.json');
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Download an npm package tarball and return the extracted package root
|
|
50
|
+
* that contains agentsam.skill.json (or package root for relative resolve).
|
|
51
|
+
*/
|
|
52
|
+
export function resolveNpmSkillPackage(spec, options = {}) {
|
|
53
|
+
const spawn = options.spawnSyncImpl || spawnSync;
|
|
54
|
+
const tmp = fs.mkdtempSync(path.join(os.tmpdir(), 'agentsam-skill-npm-'));
|
|
55
|
+
const pack = spawn('npm', ['pack', spec, '--pack-destination', tmp], {
|
|
56
|
+
encoding: 'utf8',
|
|
57
|
+
cwd: options.cwd || process.cwd(),
|
|
58
|
+
env: options.env || process.env,
|
|
59
|
+
});
|
|
60
|
+
if ((pack.status ?? 1) !== 0) {
|
|
61
|
+
throw new Error(`npm_pack_failed:${spec}:${String(pack.stderr || pack.stdout || '').trim() || 'unknown'}`);
|
|
62
|
+
}
|
|
63
|
+
const tgzName = String(pack.stdout || '')
|
|
64
|
+
.trim()
|
|
65
|
+
.split(/\r?\n/)
|
|
66
|
+
.filter(Boolean)
|
|
67
|
+
.pop();
|
|
68
|
+
if (!tgzName) throw new Error(`npm_pack_empty:${spec}`);
|
|
69
|
+
const tgzPath = path.join(tmp, path.basename(tgzName));
|
|
70
|
+
if (!fs.existsSync(tgzPath)) throw new Error(`npm_pack_missing:${tgzPath}`);
|
|
71
|
+
|
|
72
|
+
const extractDir = path.join(tmp, 'pkg');
|
|
73
|
+
fs.mkdirSync(extractDir, { recursive: true });
|
|
74
|
+
const tar = spawn('tar', ['-xzf', tgzPath, '-C', extractDir], { encoding: 'utf8' });
|
|
75
|
+
if ((tar.status ?? 1) !== 0) {
|
|
76
|
+
throw new Error(`npm_extract_failed:${String(tar.stderr || '').trim() || 'tar failed'}`);
|
|
77
|
+
}
|
|
78
|
+
const packageRoot = path.join(extractDir, 'package');
|
|
79
|
+
const candidates = [
|
|
80
|
+
path.join(packageRoot, 'agentsam.skill.json'),
|
|
81
|
+
path.join(packageRoot, 'skill', 'agentsam.skill.json'),
|
|
82
|
+
path.join(packageRoot, 'skills', 'agentsam.skill.json'),
|
|
83
|
+
];
|
|
84
|
+
for (const file of candidates) {
|
|
85
|
+
if (fs.existsSync(file)) return path.dirname(file);
|
|
86
|
+
}
|
|
87
|
+
// walk one level
|
|
88
|
+
if (fs.existsSync(packageRoot)) {
|
|
89
|
+
for (const name of fs.readdirSync(packageRoot)) {
|
|
90
|
+
const nested = path.join(packageRoot, name, 'agentsam.skill.json');
|
|
91
|
+
if (fs.existsSync(nested)) return path.dirname(nested);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
throw new Error(`agentsam.skill.json_not_found_in_package:${spec}`);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* @param {string[]} argv
|
|
99
|
+
* @param {{ write?: Function, home?: string, env?: NodeJS.ProcessEnv }} [options]
|
|
100
|
+
*/
|
|
101
|
+
export async function runSkill(argv = [], options = {}) {
|
|
102
|
+
const write = options.write || ((t) => process.stdout.write(t));
|
|
103
|
+
const [command = 'list', ...rest] = argv;
|
|
104
|
+
|
|
105
|
+
if (command === '--help' || command === '-h' || command === 'help') {
|
|
106
|
+
write(help());
|
|
107
|
+
return null;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
const registry = new SkillRegistry({ home: options.home, env: options.env });
|
|
111
|
+
const runtime = new SkillRuntime({
|
|
112
|
+
registry,
|
|
113
|
+
contentResolver: new SkillContentResolver(),
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
if (command === 'list') {
|
|
117
|
+
const rows = registry.list();
|
|
118
|
+
writeLine(write, '');
|
|
119
|
+
writeLine(write, ' AgentSam · skills');
|
|
120
|
+
writeLine(write, '');
|
|
121
|
+
for (const row of rows) {
|
|
122
|
+
const trig = row.trigger ? row.trigger.padEnd(22) : '(no trigger)'.padEnd(22);
|
|
123
|
+
writeLine(write, ` ${trig} ${row.id.padEnd(28)} [${row.source}]`);
|
|
124
|
+
if (row.description) writeLine(write, ` ${row.description}`);
|
|
125
|
+
}
|
|
126
|
+
writeLine(write, '');
|
|
127
|
+
return rows;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
if (command === 'create') {
|
|
131
|
+
const id = rest[0];
|
|
132
|
+
if (!id) throw new Error('skill create requires <id>');
|
|
133
|
+
const result = createUserSkill(id, { home: options.home, env: options.env });
|
|
134
|
+
writeLine(write, '');
|
|
135
|
+
writeLine(write, ` created ${result.manifest.id}`);
|
|
136
|
+
writeLine(write, ` trigger ${result.trigger}`);
|
|
137
|
+
writeLine(write, ` path ${result.root}`);
|
|
138
|
+
writeLine(write, '');
|
|
139
|
+
return result;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
if (command === 'inspect') {
|
|
143
|
+
const id = rest[0];
|
|
144
|
+
if (!id) throw new Error('skill inspect requires <id>');
|
|
145
|
+
const skill = registry.getById(id);
|
|
146
|
+
if (!skill) throw new Error(`unknown_skill:${id}`);
|
|
147
|
+
write(`${JSON.stringify(skill, null, 2)}\n`);
|
|
148
|
+
return skill;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
if (command === 'edit') {
|
|
152
|
+
const id = rest[0];
|
|
153
|
+
if (!id) throw new Error('skill edit requires <id>');
|
|
154
|
+
const local = readLocalRegistry({ home: options.home, env: options.env });
|
|
155
|
+
const entry = local.entries[id];
|
|
156
|
+
if (!entry) throw new Error(`skill_not_user_editable:${id}`);
|
|
157
|
+
writeLine(write, entry.manifestPath);
|
|
158
|
+
writeLine(write, path.join(entry.baseDir, 'SKILL.md'));
|
|
159
|
+
return entry;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
if (command === 'install') {
|
|
163
|
+
const source = rest[0];
|
|
164
|
+
if (!source) throw new Error('skill install requires <path|npm-package>');
|
|
165
|
+
let aliasOnCollision;
|
|
166
|
+
for (let i = 1; i < rest.length; i += 1) {
|
|
167
|
+
if (rest[i] === '--alias' || rest[i] === '--trigger') aliasOnCollision = rest[++i];
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
let installPath = source;
|
|
171
|
+
if (looksLikeNpmPackage(source)) {
|
|
172
|
+
writeLine(write, ` packing ${source}…`);
|
|
173
|
+
installPath = resolveNpmSkillPackage(source, options);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
try {
|
|
177
|
+
const result = installSkillFromPath(installPath, {
|
|
178
|
+
home: options.home,
|
|
179
|
+
env: options.env,
|
|
180
|
+
aliasOnCollision,
|
|
181
|
+
});
|
|
182
|
+
writeLine(write, '');
|
|
183
|
+
writeLine(write, ` installed ${result.id}`);
|
|
184
|
+
writeLine(write, ` trigger ${result.trigger}`);
|
|
185
|
+
writeLine(write, '');
|
|
186
|
+
return result;
|
|
187
|
+
} catch (error) {
|
|
188
|
+
if (error?.code === 'SLASH_COLLISION') {
|
|
189
|
+
writeLine(write, '');
|
|
190
|
+
writeLine(write, ` Conflict: ${error.suggested} already owned by ${error.owner}`);
|
|
191
|
+
writeLine(write, ' Choose an alias:');
|
|
192
|
+
for (const c of error.candidates || []) {
|
|
193
|
+
writeLine(write, ` agentsam skill install ${source} --alias ${c}`);
|
|
194
|
+
}
|
|
195
|
+
writeLine(write, '');
|
|
196
|
+
throw error;
|
|
197
|
+
}
|
|
198
|
+
throw error;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
if (command === 'alias') {
|
|
203
|
+
const id = rest[0];
|
|
204
|
+
const trigger = rest[1];
|
|
205
|
+
if (!id || !trigger) throw new Error('skill alias requires <id> </trigger>');
|
|
206
|
+
const result = aliasSkill(id, trigger, { home: options.home, env: options.env });
|
|
207
|
+
writeLine(write, ` ${result.id} → ${result.trigger}`);
|
|
208
|
+
return result;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
if (command === 'remove') {
|
|
212
|
+
const id = rest[0];
|
|
213
|
+
if (!id) throw new Error('skill remove requires <id>');
|
|
214
|
+
const result = removeSkill(id, { home: options.home, env: options.env });
|
|
215
|
+
writeLine(write, result.removed ? ` removed ${id}` : ` ${id} was not installed`);
|
|
216
|
+
return result;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
if (command === 'publish') {
|
|
220
|
+
const id = rest[0];
|
|
221
|
+
if (!id) throw new Error('skill publish requires <id>');
|
|
222
|
+
const skill = registry.getById(id);
|
|
223
|
+
if (!skill) throw new Error(`unknown_skill:${id}`);
|
|
224
|
+
writeLine(write, '');
|
|
225
|
+
writeLine(write, ' Publish checklist (no network from portable core):');
|
|
226
|
+
writeLine(write, ' 1. Ensure agentsam.skill.json validates as agentsam.skill.v1');
|
|
227
|
+
writeLine(write, ' 2. npm publish (suggested slash is not globally reserved)');
|
|
228
|
+
writeLine(write, ' 3. Consumers: agentsam skill install <path|@scope/pkg>');
|
|
229
|
+
writeLine(write, ` skill ${skill.id}`);
|
|
230
|
+
writeLine(write, ` slash ${skill.manifest.slash?.suggested || '(none)'}`);
|
|
231
|
+
writeLine(write, '');
|
|
232
|
+
return { id: skill.id, checklist: true };
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
if (command === 'invoke') {
|
|
236
|
+
const input = rest.join(' ').trim();
|
|
237
|
+
if (!input.startsWith('/')) throw new Error('skill invoke requires a /trigger');
|
|
238
|
+
const result = await runtime.invoke({ input });
|
|
239
|
+
write(`${JSON.stringify(result, null, 2)}\n`);
|
|
240
|
+
return result;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
throw new Error(`unknown skill command: ${command}`);
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
export function skillCommandHelp() {
|
|
247
|
+
return help();
|
|
248
|
+
}
|
package/src/commands/skills.js
CHANGED
|
@@ -45,6 +45,9 @@ export async function runStartLocal(opts = {}) {
|
|
|
45
45
|
console.log(` ✓ PTY listening ${server.url}`);
|
|
46
46
|
console.log(` ✓ Health ${server.healthUrl}`);
|
|
47
47
|
console.log(` ✓ Project root ${server.cwd}`);
|
|
48
|
+
console.log(` ✓ Workspace ${server.workspace_id}`);
|
|
49
|
+
console.log(` ✓ Capability ${server.capability.capability.slice(0, 12)}… (loopback bootstrap)`);
|
|
50
|
+
console.log(` ✓ Runtime file ${server.runtimeFile}`);
|
|
48
51
|
console.log(` ✓ Shell ${server.shell}`);
|
|
49
52
|
console.log(`
|
|
50
53
|
Project services:
|
|
@@ -52,6 +55,7 @@ export async function runStartLocal(opts = {}) {
|
|
|
52
55
|
npm run db:status → inspect local SQLite
|
|
53
56
|
npx agentsam → enter Agent Sam
|
|
54
57
|
|
|
58
|
+
Studio: open a filesystem workspace rooted at this same directory.
|
|
55
59
|
Press Ctrl+C to stop.
|
|
56
60
|
`);
|
|
57
61
|
|