fix(pi): add snap node compatibility diagnostics and documentation
- Added detailed error logging to detect snap node compatibility issues - When Pi process exits with code 1, log helpful diagnostic info including node path - Add hint to check for snap node and reinstall via apt/nvm - Create SNAP_NODE_COMPATIBILITY.md with full troubleshooting guide - Document root cause: snap node has file descriptor incompatibility with Bun.spawn stdin pipes - Provide clear installation instructions for NodeSource and nvm alternatives
This commit is contained in:
@@ -1,6 +1,16 @@
|
||||
import { existsSync, mkdirSync, readdirSync, readFileSync, writeFileSync } from 'node:fs';
|
||||
import { join } from 'node:path';
|
||||
import { getGlobalToolsDir, getUserToolsDir, getGlobalSkillsDir, getUserSkillsDir, getGlobalTasksDir, getUserTasksDir, getGlobalResourcesDir, getHomeDir, DATA_PATH } from '@@/data-path';
|
||||
import {
|
||||
getGlobalToolsDir,
|
||||
getUserToolsDir,
|
||||
getGlobalSkillsDir,
|
||||
getUserSkillsDir,
|
||||
getGlobalTasksDir,
|
||||
getUserTasksDir,
|
||||
getGlobalResourcesDir,
|
||||
getHomeDir,
|
||||
DATA_PATH,
|
||||
} from '@@/data-path';
|
||||
|
||||
type HookEntry = { type: string; command: string };
|
||||
type HookRule = { matcher?: Record<string, unknown>; hooks: HookEntry[] };
|
||||
@@ -53,9 +63,15 @@ export function generateContainerContext(email: string): string {
|
||||
const tasks = dedup([...scanDir(getGlobalTasksDir(), 'TASK.md'), ...scanDir(getUserTasksDir(email), 'TASK.md')]);
|
||||
const resources = scanDir(getGlobalResourcesDir(), 'RESOURCE.md');
|
||||
|
||||
const content = `# Officer — Container Environment
|
||||
const globalToolsDir = getGlobalToolsDir();
|
||||
const userToolsDir = getUserToolsDir(email);
|
||||
const globalSkillsDir = getGlobalSkillsDir();
|
||||
const userSkillsDir = getUserSkillsDir(email);
|
||||
const userDataDir = join(DATA_PATH, email);
|
||||
|
||||
This is a sandboxed development container managed by the Officer platform.
|
||||
const content = `# Officer — User Environment
|
||||
|
||||
This is an isolated Linux user environment managed by the Officer platform.
|
||||
|
||||
## Directory Layout
|
||||
|
||||
@@ -64,14 +80,14 @@ This is a sandboxed development container managed by the Officer platform.
|
||||
| \`~\` | User home directory (read-write) |
|
||||
| \`~/Projects/\` | User projects |
|
||||
| \`~/Downloads/\` | Downloaded files |
|
||||
| \`/officer/tools/\` | Global tools (read-only) |
|
||||
| \`/officer/user/tools/\` | User tools (read-only) |
|
||||
| \`/officer/skills/\` | Reference skills (read-only) |
|
||||
| \`/officer/data/\` | User data (emails.db, attachments, etc.) |
|
||||
| \`${globalToolsDir}/\` | Global tools |
|
||||
| \`${userToolsDir}/\` | User tools |
|
||||
| \`${globalSkillsDir}/\` | Reference skills |
|
||||
| \`${userDataDir}/\` | User data (emails.db, attachments, etc.) |
|
||||
|
||||
## Available Tools
|
||||
|
||||
Tools are callable capabilities used by the Officer AI agent (Pi). Each tool has a \`TOOL.md\` with documentation and an \`index.ts\` that exports an \`execute()\` function. Read individual tool docs at \`/officer/tools/<name>/TOOL.md\` or \`/officer/user/tools/<name>/TOOL.md\`.
|
||||
Tools are callable capabilities used by the Officer AI agent (Pi). Each tool has a \`TOOL.md\` with documentation and an \`index.ts\` that exports an \`execute()\` function. Read individual tool docs at \`${globalToolsDir}/<name>/TOOL.md\` or \`${userToolsDir}/<name>/TOOL.md\`.
|
||||
|
||||
${formatList(tools)}
|
||||
## Available Skills
|
||||
@@ -91,7 +107,7 @@ Resources are external service integrations (TTS, STT, OCR, etc.) configured in
|
||||
${formatList(resources)}
|
||||
## Creating New Tools
|
||||
|
||||
Create a directory in \`/officer/user/tools/<tool-name>/\` with two files:
|
||||
Create a directory in \`${userToolsDir}/<tool-name>/\` with two files:
|
||||
|
||||
**TOOL.md** — Frontmatter metadata + markdown documentation:
|
||||
\`\`\`yaml
|
||||
@@ -118,8 +134,6 @@ export async function execute(_toolCallId: string, params: Record<string, unknow
|
||||
}
|
||||
\`\`\`
|
||||
|
||||
Full guide: \`/officer/tools/TOOLS.md\`
|
||||
|
||||
## Environment Variables
|
||||
|
||||
| Variable | Description |
|
||||
@@ -167,8 +181,8 @@ export function generateClaudeSettings(email: string, username?: string): string
|
||||
|
||||
// Pre-seed trust and skip-permissions in .claude.json so interactive Claude Code skips all prompts
|
||||
if (username) {
|
||||
const containerHome = `/home/${username}`;
|
||||
const claudeJsonPath = join(getHomeDir(email), '.claude.json');
|
||||
const homeDir = getHomeDir(email);
|
||||
const claudeJsonPath = join(homeDir, '.claude.json');
|
||||
let claudeJson: Record<string, unknown> = {};
|
||||
try {
|
||||
claudeJson = JSON.parse(readFileSync(claudeJsonPath, 'utf-8')) as Record<string, unknown>;
|
||||
@@ -176,7 +190,7 @@ export function generateClaudeSettings(email: string, username?: string): string
|
||||
// no existing config
|
||||
}
|
||||
const projects = (claudeJson.projects ?? {}) as Record<string, Record<string, unknown>>;
|
||||
const projectKey = containerHome;
|
||||
const projectKey = homeDir;
|
||||
if (!projects[projectKey]) projects[projectKey] = {};
|
||||
projects[projectKey]!.hasTrustDialogAccepted = true;
|
||||
claudeJson.projects = projects;
|
||||
|
||||
Reference in New Issue
Block a user