@sibyllinesoft/smith-installer 0.1.1
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/agents.md +109 -0
- package/dist/agents.d.ts +9 -0
- package/dist/agents.d.ts.map +1 -0
- package/dist/agents.js +42 -0
- package/dist/agents.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +301 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/dist/lib.d.ts +49 -0
- package/dist/lib.d.ts.map +1 -0
- package/dist/lib.js +265 -0
- package/dist/lib.js.map +1 -0
- package/package.json +51 -0
- package/skills/build-client/SKILL.md +49 -0
- package/skills/choose-deployment/SKILL.md +48 -0
- package/skills/configure-agentd/SKILL.md +74 -0
- package/skills/configure-policy/SKILL.md +134 -0
- package/skills/detect-system/SKILL.md +69 -0
- package/skills/generate-certs/SKILL.md +54 -0
- package/skills/generate-pairing-code/SKILL.md +87 -0
- package/skills/install-agentd/SKILL.md +46 -0
- package/skills/install-runtime/SKILL.md +49 -0
- package/skills/preflight/SKILL.md +86 -0
- package/skills/setup-activitywatch/SKILL.md +44 -0
- package/skills/setup-chat-bridge/SKILL.md +289 -0
- package/skills/start-agentd/SKILL.md +55 -0
- package/skills/start-chat-bridge/SKILL.md +109 -0
- package/skills/start-stack/SKILL.md +56 -0
- package/skills/verify/SKILL.md +53 -0
package/dist/lib.js
ADDED
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
import { existsSync, readFileSync, readdirSync, statSync } from "fs";
|
|
2
|
+
import { resolve, join } from "path";
|
|
3
|
+
export function parseArgs(argv) {
|
|
4
|
+
const args = {
|
|
5
|
+
nonInteractive: false,
|
|
6
|
+
provider: "anthropic",
|
|
7
|
+
model: "claude-sonnet-4-20250514",
|
|
8
|
+
thinkingLevel: "medium",
|
|
9
|
+
force: false,
|
|
10
|
+
help: false,
|
|
11
|
+
};
|
|
12
|
+
for (let i = 2; i < argv.length; i++) {
|
|
13
|
+
switch (argv[i]) {
|
|
14
|
+
case "--non-interactive":
|
|
15
|
+
args.nonInteractive = true;
|
|
16
|
+
break;
|
|
17
|
+
case "--provider":
|
|
18
|
+
args.provider = argv[++i];
|
|
19
|
+
break;
|
|
20
|
+
case "--model":
|
|
21
|
+
args.model = argv[++i];
|
|
22
|
+
break;
|
|
23
|
+
case "--thinking":
|
|
24
|
+
args.thinkingLevel = argv[++i];
|
|
25
|
+
break;
|
|
26
|
+
case "--step":
|
|
27
|
+
args.step = argv[++i];
|
|
28
|
+
break;
|
|
29
|
+
case "--force":
|
|
30
|
+
args.force = true;
|
|
31
|
+
break;
|
|
32
|
+
case "--repo":
|
|
33
|
+
args.repo = argv[++i];
|
|
34
|
+
break;
|
|
35
|
+
case "--help":
|
|
36
|
+
case "-h":
|
|
37
|
+
args.help = true;
|
|
38
|
+
break;
|
|
39
|
+
default:
|
|
40
|
+
throw new Error(`Unknown option: ${argv[i]} (try --help)`);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return args;
|
|
44
|
+
}
|
|
45
|
+
export function findSmithRoot(startDir) {
|
|
46
|
+
let dir = resolve(startDir);
|
|
47
|
+
const root = resolve("/");
|
|
48
|
+
while (dir !== root) {
|
|
49
|
+
const looksLikeRepoRoot = existsSync(join(dir, "Cargo.toml")) &&
|
|
50
|
+
existsSync(join(dir, "docker-compose.yaml")) &&
|
|
51
|
+
existsSync(join(dir, "justfile")) &&
|
|
52
|
+
existsSync(join(dir, "installer", "package.json"));
|
|
53
|
+
if (looksLikeRepoRoot) {
|
|
54
|
+
return dir;
|
|
55
|
+
}
|
|
56
|
+
dir = resolve(dir, "..");
|
|
57
|
+
}
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
60
|
+
export function loadSkills(skillsDir) {
|
|
61
|
+
const skills = [];
|
|
62
|
+
let entries;
|
|
63
|
+
try {
|
|
64
|
+
entries = readdirSync(skillsDir);
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
return skills;
|
|
68
|
+
}
|
|
69
|
+
for (const entry of entries) {
|
|
70
|
+
const skillDir = join(skillsDir, entry);
|
|
71
|
+
const skillFile = join(skillDir, "SKILL.md");
|
|
72
|
+
try {
|
|
73
|
+
if (!statSync(skillDir).isDirectory())
|
|
74
|
+
continue;
|
|
75
|
+
const content = readFileSync(skillFile, "utf8");
|
|
76
|
+
// Extract description from frontmatter
|
|
77
|
+
const match = content.match(/^---\s*\ndescription:\s*(.+)\n---/);
|
|
78
|
+
const description = match?.[1] ?? entry;
|
|
79
|
+
skills.push({ name: entry, description, content });
|
|
80
|
+
}
|
|
81
|
+
catch {
|
|
82
|
+
// Skip skills without SKILL.md
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return skills;
|
|
86
|
+
}
|
|
87
|
+
export function buildSystemPrompt(opts) {
|
|
88
|
+
let prompt = "You are the Smith Core installer and configuration agent.\n\n";
|
|
89
|
+
prompt += `smith-core repo root: ${opts.smithRoot}\n`;
|
|
90
|
+
if (process.platform === "darwin") {
|
|
91
|
+
prompt +=
|
|
92
|
+
"\nThis host is macOS. Ensure Gondolin-backed persistent VM sessions are enabled by setting:\n" +
|
|
93
|
+
"- SMITH_EXECUTOR_VM_POOL_ENABLED=true\n" +
|
|
94
|
+
"- SMITH_EXECUTOR_VM_METHOD=gondolin\n" +
|
|
95
|
+
"- SMITH_EXECUTOR_GONDOLIN_COMMAND=gondolin\n" +
|
|
96
|
+
"- SMITH_EXECUTOR_GONDOLIN_ARGS=exec,--\n";
|
|
97
|
+
}
|
|
98
|
+
if (opts.step) {
|
|
99
|
+
prompt += `\nThe user wants to run installer step '${opts.step}' only.\n`;
|
|
100
|
+
}
|
|
101
|
+
const configSteps = ["configure-policy", "policy"];
|
|
102
|
+
if (opts.step && configSteps.includes(opts.step.toLowerCase())) {
|
|
103
|
+
prompt += "You are in configuration mode (not bootstrapping). " +
|
|
104
|
+
"Focus on inspecting and configuring the policy system. " +
|
|
105
|
+
"Do not run build or infrastructure setup commands.\n";
|
|
106
|
+
}
|
|
107
|
+
if (opts.force) {
|
|
108
|
+
prompt += "--force is set — recreate infrastructure before bootstrapping.\n";
|
|
109
|
+
}
|
|
110
|
+
if (opts.securityWarnings && opts.securityWarnings.length > 0) {
|
|
111
|
+
prompt +=
|
|
112
|
+
"\nLocal security posture warnings were detected. These are non-blocking, " +
|
|
113
|
+
"but you must present them clearly before continuing:\n";
|
|
114
|
+
for (const warning of opts.securityWarnings) {
|
|
115
|
+
prompt += `- ${warning}\n`;
|
|
116
|
+
}
|
|
117
|
+
prompt +=
|
|
118
|
+
"Explicitly warn when deployment is not on a private network and recommend " +
|
|
119
|
+
"VPN/tunnel controls (for example Cloudflare Tunnel or Tailscale).\n";
|
|
120
|
+
}
|
|
121
|
+
return prompt;
|
|
122
|
+
}
|
|
123
|
+
function parseEnvFile(path) {
|
|
124
|
+
const vars = {};
|
|
125
|
+
const content = readFileSync(path, "utf8");
|
|
126
|
+
for (const rawLine of content.split("\n")) {
|
|
127
|
+
const line = rawLine.trim();
|
|
128
|
+
if (!line || line.startsWith("#"))
|
|
129
|
+
continue;
|
|
130
|
+
const eq = line.indexOf("=");
|
|
131
|
+
if (eq <= 0)
|
|
132
|
+
continue;
|
|
133
|
+
const key = line.slice(0, eq).trim();
|
|
134
|
+
let value = line.slice(eq + 1).trim();
|
|
135
|
+
if ((value.startsWith('"') && value.endsWith('"')) ||
|
|
136
|
+
(value.startsWith("'") && value.endsWith("'"))) {
|
|
137
|
+
value = value.slice(1, -1);
|
|
138
|
+
}
|
|
139
|
+
vars[key] = value;
|
|
140
|
+
}
|
|
141
|
+
return vars;
|
|
142
|
+
}
|
|
143
|
+
function hasNonEmpty(vars, keys) {
|
|
144
|
+
return keys.some((key) => (vars[key] ?? "").trim().length > 0);
|
|
145
|
+
}
|
|
146
|
+
function looksLikeWeakSecret(value, weakValues) {
|
|
147
|
+
const normalized = value.trim();
|
|
148
|
+
return normalized.length === 0 || weakValues.includes(normalized);
|
|
149
|
+
}
|
|
150
|
+
function isLikelyLoopbackListen(value) {
|
|
151
|
+
const v = value.trim().toLowerCase();
|
|
152
|
+
return (v.includes("127.0.0.1") ||
|
|
153
|
+
v.includes("localhost") ||
|
|
154
|
+
v.includes("[::1]") ||
|
|
155
|
+
v === "::1" ||
|
|
156
|
+
v.startsWith("::1:"));
|
|
157
|
+
}
|
|
158
|
+
export function evaluateInstallerSecurity(smithRoot) {
|
|
159
|
+
const envPath = join(smithRoot, ".env");
|
|
160
|
+
const envExamplePath = join(smithRoot, ".env.example");
|
|
161
|
+
const sourceFile = existsSync(envPath)
|
|
162
|
+
? envPath
|
|
163
|
+
: existsSync(envExamplePath)
|
|
164
|
+
? envExamplePath
|
|
165
|
+
: null;
|
|
166
|
+
if (!sourceFile) {
|
|
167
|
+
return {
|
|
168
|
+
sourceFile: null,
|
|
169
|
+
warnings: [
|
|
170
|
+
{
|
|
171
|
+
id: "missing-env",
|
|
172
|
+
message: "No .env or .env.example was found to evaluate security posture.",
|
|
173
|
+
recommendation: "Create .env from .env.example and review secrets plus network exposure settings.",
|
|
174
|
+
},
|
|
175
|
+
],
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
const vars = parseEnvFile(sourceFile);
|
|
179
|
+
const warnings = [];
|
|
180
|
+
const weakSecrets = [
|
|
181
|
+
[
|
|
182
|
+
"POSTGRES_PASSWORD",
|
|
183
|
+
["smith-dev", "postgres", "password", "changeme"],
|
|
184
|
+
"Set POSTGRES_PASSWORD to a unique, high-entropy value.",
|
|
185
|
+
],
|
|
186
|
+
[
|
|
187
|
+
"CLICKHOUSE_PASSWORD",
|
|
188
|
+
["observability-dev", "clickhouse", "password", "changeme"],
|
|
189
|
+
"Set CLICKHOUSE_PASSWORD to a unique, high-entropy value.",
|
|
190
|
+
],
|
|
191
|
+
[
|
|
192
|
+
"GRAFANA_ADMIN_PASSWORD",
|
|
193
|
+
["admin", "grafana", "password", "changeme"],
|
|
194
|
+
"Set GRAFANA_ADMIN_PASSWORD to a unique, high-entropy value.",
|
|
195
|
+
],
|
|
196
|
+
];
|
|
197
|
+
for (const [key, weakValues, recommendation] of weakSecrets) {
|
|
198
|
+
const value = (vars[key] ?? "").trim();
|
|
199
|
+
if (looksLikeWeakSecret(value, weakValues)) {
|
|
200
|
+
warnings.push({
|
|
201
|
+
id: `weak-${key.toLowerCase()}`,
|
|
202
|
+
message: `${key} is empty or set to a known weak default.`,
|
|
203
|
+
recommendation,
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
const mcpToken = (vars.MCP_INDEX_API_TOKEN ?? "").trim();
|
|
208
|
+
if (mcpToken.length < 24) {
|
|
209
|
+
warnings.push({
|
|
210
|
+
id: "weak-mcp-index-token",
|
|
211
|
+
message: "MCP_INDEX_API_TOKEN is missing or too short; MCP index APIs may be unauthenticated or weakly protected.",
|
|
212
|
+
recommendation: "Set MCP_INDEX_API_TOKEN to a long random secret (at least 24 characters).",
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
const capabilityDigest = (vars.AGENTD_CAPABILITY_DIGEST ?? "").trim();
|
|
216
|
+
if (!/^[a-fA-F0-9]{64}$/.test(capabilityDigest)) {
|
|
217
|
+
warnings.push({
|
|
218
|
+
id: "invalid-capability-digest",
|
|
219
|
+
message: "AGENTD_CAPABILITY_DIGEST is missing or not a valid 64-character hex digest.",
|
|
220
|
+
recommendation: "Set AGENTD_CAPABILITY_DIGEST to the intended capability bundle digest before production use.",
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
else if (/^0{64}$/.test(capabilityDigest)) {
|
|
224
|
+
warnings.push({
|
|
225
|
+
id: "zero-capability-digest",
|
|
226
|
+
message: "AGENTD_CAPABILITY_DIGEST is all zeros and will be rejected by secure defaults.",
|
|
227
|
+
recommendation: "Set AGENTD_CAPABILITY_DIGEST to a real digest, or only allow zero in local development overrides.",
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
const cloudflareKeys = [
|
|
231
|
+
"CLOUDFLARED_TUNNEL_TOKEN",
|
|
232
|
+
"CLOUDFLARE_TUNNEL_TOKEN",
|
|
233
|
+
"CLOUDFLARE_TUNNEL_ID",
|
|
234
|
+
"CLOUDFLARE_TUNNEL_HOSTNAME",
|
|
235
|
+
"CLOUDFLARE_TUNNEL_E2E_URL",
|
|
236
|
+
"CF_TUNNEL_TOKEN",
|
|
237
|
+
"TUNNEL_TOKEN",
|
|
238
|
+
];
|
|
239
|
+
const tailscaleKeys = [
|
|
240
|
+
"TAILSCALE_AUTHKEY",
|
|
241
|
+
"TS_AUTHKEY",
|
|
242
|
+
"TAILSCALE_OAUTH_CLIENT_ID",
|
|
243
|
+
"TAILSCALE_HOSTNAME",
|
|
244
|
+
"TAILSCALE_TUNNEL_E2E_URL",
|
|
245
|
+
];
|
|
246
|
+
const hasCloudflare = hasNonEmpty(vars, cloudflareKeys);
|
|
247
|
+
const hasTailscale = hasNonEmpty(vars, tailscaleKeys);
|
|
248
|
+
if (!hasCloudflare && !hasTailscale) {
|
|
249
|
+
warnings.push({
|
|
250
|
+
id: "missing-private-network-indicator",
|
|
251
|
+
message: "No Cloudflare Tunnel or Tailscale configuration indicators were found.",
|
|
252
|
+
recommendation: "Use a private network path (VPN/tunnel), and avoid exposing management endpoints directly to public networks.",
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
const grpcListen = (vars.AGENTD_GRPC_LISTEN ?? "").trim();
|
|
256
|
+
if (grpcListen && !isLikelyLoopbackListen(grpcListen)) {
|
|
257
|
+
warnings.push({
|
|
258
|
+
id: "agentd-grpc-non-loopback",
|
|
259
|
+
message: `AGENTD_GRPC_LISTEN is set to a non-loopback address (${grpcListen}).`,
|
|
260
|
+
recommendation: "Keep AGENTD_GRPC_LISTEN on loopback or enforce network controls before exposing it beyond trusted private networks.",
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
return { sourceFile, warnings };
|
|
264
|
+
}
|
|
265
|
+
//# sourceMappingURL=lib.js.map
|
package/dist/lib.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lib.js","sourceRoot":"","sources":["../src/lib.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@sibyllinesoft/smith-installer",
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"description": "AI-guided Smith platform installer powered by pi-agent",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "https://github.com/sibyllinesoft/smith-core.git",
|
|
9
|
+
"directory": "installer"
|
|
10
|
+
},
|
|
11
|
+
"homepage": "https://smithcore.dev",
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/sibyllinesoft/smith-core/issues"
|
|
14
|
+
},
|
|
15
|
+
"type": "module",
|
|
16
|
+
"bin": {
|
|
17
|
+
"smith-install": "./dist/cli.js"
|
|
18
|
+
},
|
|
19
|
+
"main": "./dist/index.js",
|
|
20
|
+
"types": "./dist/index.d.ts",
|
|
21
|
+
"exports": {
|
|
22
|
+
".": {
|
|
23
|
+
"import": "./dist/index.js",
|
|
24
|
+
"types": "./dist/index.d.ts"
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
"files": [
|
|
28
|
+
"dist",
|
|
29
|
+
"agents.md",
|
|
30
|
+
"skills"
|
|
31
|
+
],
|
|
32
|
+
"scripts": {
|
|
33
|
+
"build": "rm -rf dist && tsc",
|
|
34
|
+
"dev": "tsc --watch",
|
|
35
|
+
"typecheck": "tsc --noEmit",
|
|
36
|
+
"test": "vitest run",
|
|
37
|
+
"test:watch": "vitest"
|
|
38
|
+
},
|
|
39
|
+
"engines": {
|
|
40
|
+
"node": ">=22"
|
|
41
|
+
},
|
|
42
|
+
"dependencies": {
|
|
43
|
+
"@mariozechner/pi-coding-agent": "^0.52.0",
|
|
44
|
+
"@mariozechner/pi-ai": "^0.52.0"
|
|
45
|
+
},
|
|
46
|
+
"devDependencies": {
|
|
47
|
+
"@types/node": "^20.0.0",
|
|
48
|
+
"typescript": "^5.4.0",
|
|
49
|
+
"vitest": "^2.0.0"
|
|
50
|
+
}
|
|
51
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Build Node workspaces required by installer and bridge services
|
|
3
|
+
---
|
|
4
|
+
# Build Client
|
|
5
|
+
|
|
6
|
+
Run:
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
npm install
|
|
10
|
+
npm run build --workspaces --if-present
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## What It Does
|
|
14
|
+
|
|
15
|
+
This skill builds TypeScript/Node workspace packages used by Smith Core.
|
|
16
|
+
|
|
17
|
+
1. Installs workspace dependencies.
|
|
18
|
+
2. Builds workspaces that expose a `build` script.
|
|
19
|
+
3. Verifies installer and bridge artifacts compile.
|
|
20
|
+
4. Ensures runtime JS entrypoints exist before launch.
|
|
21
|
+
|
|
22
|
+
## Prerequisites
|
|
23
|
+
|
|
24
|
+
- Node.js 22+.
|
|
25
|
+
- npm available.
|
|
26
|
+
- Internet access for package installation.
|
|
27
|
+
|
|
28
|
+
## Expected Output
|
|
29
|
+
|
|
30
|
+
- `npm install` completes without fatal errors.
|
|
31
|
+
- Build runs for `@smith/pi-bridge` and `@sibyllinesoft/smith-installer`.
|
|
32
|
+
|
|
33
|
+
## Reading Results
|
|
34
|
+
|
|
35
|
+
- TypeScript compile failures indicate code/config drift.
|
|
36
|
+
- Missing workspace build output blocks installer CLI execution.
|
|
37
|
+
|
|
38
|
+
## Common Failures
|
|
39
|
+
|
|
40
|
+
| Symptom | Cause | Fix |
|
|
41
|
+
|---------|-------|-----|
|
|
42
|
+
| npm install fails | Network/auth/registry issues | Fix npm connectivity and retry |
|
|
43
|
+
| TypeScript errors in build | Source mismatch | Fix TS errors before bootstrap |
|
|
44
|
+
| Wrong Node version | Node < 22 | Upgrade Node runtime |
|
|
45
|
+
| Workspace not built | Missing `build` script | Add or correct workspace script |
|
|
46
|
+
|
|
47
|
+
## Notes
|
|
48
|
+
|
|
49
|
+
Use this before running installer commands that depend on `dist/` outputs.
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Choose deployment profile for Smith Core installation
|
|
3
|
+
---
|
|
4
|
+
# Choose Deployment
|
|
5
|
+
|
|
6
|
+
Run:
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
export SMITH_DEPLOYMENT_MODE=local
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
## What It Does
|
|
13
|
+
|
|
14
|
+
This skill sets deployment intent for the installer session.
|
|
15
|
+
|
|
16
|
+
1. Selects local-first deployment for open-source Smith Core.
|
|
17
|
+
2. Keeps infrastructure on local Docker networking.
|
|
18
|
+
3. Avoids assumptions about external managed tunnel services.
|
|
19
|
+
4. Ensures follow-up commands target local endpoints.
|
|
20
|
+
|
|
21
|
+
## Prerequisites
|
|
22
|
+
|
|
23
|
+
- User decision on local vs externally exposed deployment.
|
|
24
|
+
|
|
25
|
+
## Expected Output
|
|
26
|
+
|
|
27
|
+
Environment reflects local mode:
|
|
28
|
+
|
|
29
|
+
```text
|
|
30
|
+
SMITH_DEPLOYMENT_MODE=local
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Reading Results
|
|
34
|
+
|
|
35
|
+
- `local` means services run via `docker compose` on this machine.
|
|
36
|
+
- Any external ingress should be configured separately after bootstrap.
|
|
37
|
+
|
|
38
|
+
## Common Failures
|
|
39
|
+
|
|
40
|
+
| Symptom | Cause | Fix |
|
|
41
|
+
|---------|-------|-----|
|
|
42
|
+
| Variable not visible in later commands | Exported in another shell | Export in the active shell/session |
|
|
43
|
+
| Confusion about cloud mode | Legacy docs mention tunnels | Use local mode for core OSS bootstrap |
|
|
44
|
+
| External access needed | Out-of-scope for default installer | Configure reverse proxy separately |
|
|
45
|
+
|
|
46
|
+
## Notes
|
|
47
|
+
|
|
48
|
+
Current installer implementation validates and bootstraps local development flows.
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Configure environment and path defaults used by agentd and bridge components
|
|
3
|
+
---
|
|
4
|
+
# Configure Agentd
|
|
5
|
+
|
|
6
|
+
Run:
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
cp -n .env.example .env || true
|
|
10
|
+
|
|
11
|
+
if [ "$(uname -s)" = "Darwin" ]; then
|
|
12
|
+
command -v gondolin >/dev/null
|
|
13
|
+
grep -q '^SMITH_EXECUTOR_VM_POOL_ENABLED=' .env || echo 'SMITH_EXECUTOR_VM_POOL_ENABLED=true' >> .env
|
|
14
|
+
grep -q '^SMITH_EXECUTOR_VM_METHOD=' .env || echo 'SMITH_EXECUTOR_VM_METHOD=gondolin' >> .env
|
|
15
|
+
grep -q '^SMITH_EXECUTOR_GONDOLIN_COMMAND=' .env || echo 'SMITH_EXECUTOR_GONDOLIN_COMMAND=gondolin' >> .env
|
|
16
|
+
grep -q '^SMITH_EXECUTOR_GONDOLIN_ARGS=' .env || echo 'SMITH_EXECUTOR_GONDOLIN_ARGS=exec,--' >> .env
|
|
17
|
+
fi
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## What It Does
|
|
21
|
+
|
|
22
|
+
This skill establishes baseline environment configuration for local runs.
|
|
23
|
+
|
|
24
|
+
1. Creates `.env` from `.env.example` when missing.
|
|
25
|
+
2. Ensures key URLs and credentials are available for local services.
|
|
26
|
+
3. Makes bridge and stack configuration explicit and reproducible.
|
|
27
|
+
4. Avoids hidden machine-specific defaults.
|
|
28
|
+
5. On macOS, enables Gondolin-backed persistent VM sessions by default.
|
|
29
|
+
|
|
30
|
+
## Prerequisites
|
|
31
|
+
|
|
32
|
+
- Repository root writable.
|
|
33
|
+
- `.env.example` present.
|
|
34
|
+
|
|
35
|
+
## Expected Output
|
|
36
|
+
|
|
37
|
+
- `.env` exists at repository root.
|
|
38
|
+
- Variables for NATS/Postgres/Grafana/stack endpoints are present.
|
|
39
|
+
- On macOS, Gondolin VM defaults are present:
|
|
40
|
+
- `SMITH_EXECUTOR_VM_POOL_ENABLED=true`
|
|
41
|
+
- `SMITH_EXECUTOR_VM_METHOD=gondolin`
|
|
42
|
+
- `SMITH_EXECUTOR_GONDOLIN_COMMAND=gondolin`
|
|
43
|
+
- `SMITH_EXECUTOR_GONDOLIN_ARGS=exec,--`
|
|
44
|
+
|
|
45
|
+
## Reading Results
|
|
46
|
+
|
|
47
|
+
Review and customize at minimum:
|
|
48
|
+
|
|
49
|
+
- `POSTGRES_PASSWORD`
|
|
50
|
+
- `GRAFANA_ADMIN_PASSWORD`
|
|
51
|
+
- `MCP_INDEX_API_TOKEN`
|
|
52
|
+
- `AGENTD_CONFIG`
|
|
53
|
+
- `SMITH_NATS_URL`
|
|
54
|
+
- `SMITH_DATABASE_URL`
|
|
55
|
+
- `AGENTD_URL`
|
|
56
|
+
- `SMITH_EXECUTOR_VM_POOL_ENABLED` (set to `true` on macOS)
|
|
57
|
+
- `SMITH_EXECUTOR_VM_METHOD` (set to `gondolin` on macOS)
|
|
58
|
+
|
|
59
|
+
If this system is not isolated to a private network, set up a private access path
|
|
60
|
+
(for example Cloudflare Tunnel or Tailscale) before exposing services.
|
|
61
|
+
|
|
62
|
+
## Common Failures
|
|
63
|
+
|
|
64
|
+
| Symptom | Cause | Fix |
|
|
65
|
+
|---------|-------|-----|
|
|
66
|
+
| `.env` not created | Permission/path issue | Create file manually and retry |
|
|
67
|
+
| Service auth failures | Password mismatch with compose | Align `.env` values and restart stack |
|
|
68
|
+
| Bridge cannot reach agentd | Bad `AGENTD_URL` | Set reachable URL and rerun |
|
|
69
|
+
| Unexpected defaults used | Variable unset | Populate `.env` explicitly |
|
|
70
|
+
| `gondolin` not found on macOS | Gondolin missing from PATH | Install Gondolin and retry |
|
|
71
|
+
|
|
72
|
+
## Notes
|
|
73
|
+
|
|
74
|
+
There is no generated `agentd.toml` workflow in the current installer path.
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Inspect and configure OPA security policies for agentd intent evaluation and gateway authorization
|
|
3
|
+
---
|
|
4
|
+
# Configure Policy
|
|
5
|
+
|
|
6
|
+
Run these read-only inspection commands to understand the current policy state:
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
# Query opa_policies table for active policy records
|
|
10
|
+
docker compose exec -T postgres psql -U smith -d smith -c "SELECT id, name, updated_at FROM opa_policies ORDER BY updated_at DESC;"
|
|
11
|
+
|
|
12
|
+
# View tool-access policy data (most commonly edited artifact)
|
|
13
|
+
docker compose exec -T postgres psql -U smith -d smith -c "SELECT data FROM opa_policies WHERE name = 'tool_access';"
|
|
14
|
+
|
|
15
|
+
# Check OPA server health (Docker-internal only, port 8181 is not published to host)
|
|
16
|
+
docker compose exec -T opa-management wget -qO- http://localhost:8181/health
|
|
17
|
+
|
|
18
|
+
# List loaded OPA policies
|
|
19
|
+
docker compose exec -T opa-management wget -qO- http://localhost:8181/v1/policies
|
|
20
|
+
|
|
21
|
+
# Show executor.policy section from agentd config
|
|
22
|
+
grep -A 20 '^\[executor\.policy\]' agent/agentd/config/agentd.toml || echo "No [executor.policy] section found"
|
|
23
|
+
|
|
24
|
+
# List Rego policy files
|
|
25
|
+
ls -la agent/agentd/policy/*.rego 2>/dev/null || echo "No .rego files found"
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## What It Does
|
|
29
|
+
|
|
30
|
+
This skill inspects and configures the OPA (Open Policy Agent) security policy system that governs agentd intent evaluation and gateway authorization.
|
|
31
|
+
|
|
32
|
+
### Security Profiles
|
|
33
|
+
|
|
34
|
+
Smith Core ships three security profiles:
|
|
35
|
+
|
|
36
|
+
1. **Permissive** (workstation) — broad tool access; suitable for local development.
|
|
37
|
+
2. **Strict** (server) — restricted tool set; requires explicit allowlisting.
|
|
38
|
+
3. **Paranoid** (max security) — minimal defaults; every tool must be individually approved.
|
|
39
|
+
|
|
40
|
+
### Architecture
|
|
41
|
+
|
|
42
|
+
- 10 Rego policy files live at `agent/agentd/policy/*.rego`.
|
|
43
|
+
- Policy data is stored in PostgreSQL (`opa_policies` table) and synced to the OPA management server.
|
|
44
|
+
- Sync flow: **PostgreSQL** -> **admission service** -> **OPA server (8181)** -> **Envoy ext_authz (9292)**.
|
|
45
|
+
- Separately, agentd evaluates policies in-process via the `regorus` embedded Rego engine using `[executor.policy]` config in `agentd.toml`.
|
|
46
|
+
|
|
47
|
+
### Important: OPA is Docker-internal only
|
|
48
|
+
|
|
49
|
+
OPA uses `expose: ["8181"]` in docker-compose (no `ports:` mapping), so `curl localhost:8181` will **not** work from the host. All OPA API commands must use `docker compose exec -T opa-management` to reach the OPA API.
|
|
50
|
+
|
|
51
|
+
## Mutation Commands
|
|
52
|
+
|
|
53
|
+
These commands modify policy state. Use them interactively after inspecting current state:
|
|
54
|
+
|
|
55
|
+
### Edit tool-access policy data
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
docker compose exec -T postgres psql -U smith -d smith -c "UPDATE opa_policies SET data = '<new-json>' WHERE name = 'tool_access';"
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### Build policy bundle
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
bash agent/agentd/scripts/build-policy-bundle.sh
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### Validate Rego files (requires OPA CLI on host)
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
opa check agent/agentd/policy/
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### Force re-sync from PostgreSQL to OPA
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
docker compose restart opa-management
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## Prerequisites
|
|
80
|
+
|
|
81
|
+
- Docker stack running (`docker compose ps` shows `postgres` and `opa-management` healthy).
|
|
82
|
+
- `opa_policies` table populated (happens during initial `start-stack` phase).
|
|
83
|
+
- `agent/agentd/config/agentd.toml` present.
|
|
84
|
+
|
|
85
|
+
## Expected Output
|
|
86
|
+
|
|
87
|
+
- `opa_policies` table lists active policy records with timestamps.
|
|
88
|
+
- OPA health endpoint returns `{"status": "ok"}` or similar.
|
|
89
|
+
- Rego files are listed at `agent/agentd/policy/*.rego`.
|
|
90
|
+
- `[executor.policy]` config section is visible in `agentd.toml`.
|
|
91
|
+
|
|
92
|
+
## Common Failures
|
|
93
|
+
|
|
94
|
+
| Symptom | Cause | Fix |
|
|
95
|
+
|---------|-------|-----|
|
|
96
|
+
| `psql` connection refused | Postgres container not running | `docker compose up -d postgres` |
|
|
97
|
+
| OPA health check fails | `opa-management` container not running | `docker compose up -d opa-management` |
|
|
98
|
+
| Empty `opa_policies` table | Policies not seeded | Re-run `start-stack` skill or seed manually |
|
|
99
|
+
| `regorus` evaluation errors in agentd logs | Rego syntax error in policy files | Run `opa check agent/agentd/policy/` to validate |
|
|
100
|
+
| Changes not reflected in authorization | Sync lag or stale cache | `docker compose restart opa-management` |
|
|
101
|
+
|
|
102
|
+
## Notes
|
|
103
|
+
|
|
104
|
+
### Tool-Access Policy Data Structure
|
|
105
|
+
|
|
106
|
+
The `tool_access` policy record in `opa_policies` stores a JSON document with the following structure:
|
|
107
|
+
|
|
108
|
+
```json
|
|
109
|
+
{
|
|
110
|
+
"default": "permissive",
|
|
111
|
+
"exceptions": {
|
|
112
|
+
"strict": {
|
|
113
|
+
"allowed_tools": ["shell_exec", "file_read", "file_write"],
|
|
114
|
+
"denied_tools": ["network_raw", "kernel_module"]
|
|
115
|
+
},
|
|
116
|
+
"paranoid": {
|
|
117
|
+
"allowed_tools": ["file_read"],
|
|
118
|
+
"denied_tools": ["*"]
|
|
119
|
+
}
|
|
120
|
+
},
|
|
121
|
+
"source_restrictions": {
|
|
122
|
+
"untrusted": {
|
|
123
|
+
"untrusted_allowed_tools": ["file_read", "shell_exec"]
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
- **`default`**: The active security profile name (`permissive`, `strict`, or `paranoid`).
|
|
130
|
+
- **`exceptions`**: Per-profile overrides that define `allowed_tools` and `denied_tools` lists.
|
|
131
|
+
- **`source_restrictions`**: Controls which tools are available to untrusted request sources.
|
|
132
|
+
- **`untrusted_allowed_tools`**: Subset of tools that untrusted callers may invoke regardless of profile.
|
|
133
|
+
|
|
134
|
+
To change the active profile, update the `default` field. To customize tool access within a profile, modify the corresponding entry in `exceptions`.
|