olakai-cli 0.6.1 → 0.6.3
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/dist/{chunk-PGRX347G.js → chunk-OHPX4STO.js} +9 -2
- package/dist/chunk-OHPX4STO.js.map +1 -0
- package/dist/index.js +85 -18
- package/dist/index.js.map +1 -1
- package/dist/{status-NK4PX2NS.js → status-CAHO5FHI.js} +2 -2
- package/package.json +1 -1
- package/dist/chunk-PGRX347G.js.map +0 -1
- /package/dist/{status-NK4PX2NS.js.map → status-CAHO5FHI.js.map} +0 -0
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
getClaudeCodeStatus,
|
|
3
3
|
printClaudeCodeStatus
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-OHPX4STO.js";
|
|
5
5
|
export {
|
|
6
6
|
getClaudeCodeStatus,
|
|
7
7
|
printClaudeCodeStatus
|
|
8
8
|
};
|
|
9
|
-
//# sourceMappingURL=status-
|
|
9
|
+
//# sourceMappingURL=status-CAHO5FHI.js.map
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/monitor/plugins/claude-code/status.ts","../src/lib/profiles.ts","../src/lib/config.ts","../src/lib/auth.ts","../src/monitor/plugins/claude-code/settings.ts","../src/monitor/plugins/claude-code/config.ts","../src/monitor/paths.ts","../src/monitor/migrations.ts"],"sourcesContent":["import path from \"node:path\";\nimport type { StatusReport } from \"../../plugin.js\";\nimport { getValidToken } from \"../../../lib/auth.js\";\nimport { getBaseUrl } from \"../../../lib/config.js\";\nimport {\n OLAKAI_HOOK_MARKER,\n getSettingsPath,\n readJsonFile,\n type ClaudeSettings,\n} from \"./settings.js\";\nimport {\n getClaudeCodeConfigPath,\n loadClaudeCodeConfig,\n} from \"./config.js\";\n\nexport async function getClaudeCodeStatus(opts?: {\n projectRoot?: string;\n}): Promise<StatusReport> {\n const projectRoot = opts?.projectRoot ?? process.cwd();\n const configPath = getClaudeCodeConfigPath(projectRoot);\n const config = loadClaudeCodeConfig(projectRoot);\n\n const settings = readJsonFile<ClaudeSettings>(getSettingsPath(projectRoot));\n const hooksConfigured = settings?.hooks\n ? Object.values(settings.hooks).some((entries) =>\n entries.some((e) =>\n e.hooks.some((h) => h.command.includes(OLAKAI_HOOK_MARKER)),\n ),\n )\n : false;\n\n if (!config) {\n return {\n toolId: \"claude-code\",\n configured: false,\n hooksConfigured,\n configPath,\n notes: hooksConfigured\n ? [\"Hooks present in settings.json but no monitor config — re-run init.\"]\n : [],\n };\n }\n\n return {\n toolId: \"claude-code\",\n configured: true,\n hooksConfigured,\n agentId: config.agentId,\n agentName: config.agentName,\n source: config.source,\n apiKeyMasked: config.apiKey.slice(0, 12) + \"...\",\n monitoringEndpoint: config.monitoringEndpoint,\n configuredAt: config.createdAt,\n configPath,\n };\n}\n\n/**\n * Print a human-readable status summary for the Claude Code plugin\n * (non-JSON path). Also fetches recent activity if a token is\n * available — same behavior as pre-Stage-2 `monitor status`.\n */\nexport async function printClaudeCodeStatus(opts?: {\n projectRoot?: string;\n}): Promise<void> {\n const projectRoot = opts?.projectRoot ?? process.cwd();\n const status = await getClaudeCodeStatus({ projectRoot });\n\n if (!status.configured) {\n console.log(\"Monitoring is not configured for this workspace.\");\n console.log(\n \"Run 'olakai monitor init --tool claude-code' to set up monitoring.\",\n );\n process.exit(1);\n }\n\n const configRel = status.configPath\n ? path.relative(projectRoot, status.configPath)\n : \"(unknown)\";\n\n console.log(\"Olakai Monitor Status (Claude Code)\");\n console.log(\"===================================\");\n console.log(`Agent: ${status.agentName}`);\n console.log(`Agent ID: ${status.agentId}`);\n console.log(`API Key: ${status.apiKeyMasked}`);\n console.log(`Endpoint: ${status.monitoringEndpoint}`);\n console.log(`Source: ${status.source}`);\n console.log(`Configured: ${status.configuredAt}`);\n console.log(`Config file: ${configRel}`);\n console.log(\n `Hooks: ${status.hooksConfigured ? \"Active\" : \"Missing (re-run 'olakai monitor init --tool claude-code')\"}`,\n );\n\n try {\n const token = getValidToken();\n if (token && status.agentId) {\n const params = new URLSearchParams({\n agentId: status.agentId,\n limit: \"5\",\n });\n const response = await fetch(\n `${getBaseUrl()}/api/activity/prompts?${params}`,\n {\n headers: { Authorization: `Bearer ${token}` },\n },\n );\n if (response.ok) {\n const data = (await response.json()) as {\n prompts: Array<{ id: string; createdAt: string }>;\n };\n if (data.prompts && data.prompts.length > 0) {\n console.log(\"\");\n console.log(\"Recent Activity:\");\n for (const p of data.prompts) {\n console.log(` ${p.createdAt} ${p.id.slice(0, 12)}...`);\n }\n } else {\n console.log(\"\");\n console.log(\"No activity recorded yet.\");\n }\n }\n }\n } catch {\n // Activity check is optional — don't fail\n }\n}\n","/**\n * AWS-style profile manager for the Olakai CLI.\n *\n * Two configuration surfaces:\n *\n * 1. Global profile registry — `~/.config/olakai/profiles.json`\n * Stores one or more named profiles, each carrying a host + token\n * + (optionally) user/account identifiers. Owner-readable only\n * (file `0600`, parent dir `0700`).\n *\n * 2. Per-workspace pointer — `.olakai/config.json` in the workspace\n * root (the CWD or any ancestor). Either selects a profile by\n * name (`{ \"profile\": \"saas-prod\" }`) or pins an ad-hoc host\n * (`{ \"host\": \"https://...\" }`).\n *\n * Profile resolution order (highest precedence first):\n *\n * 1. `--profile` CLI flag (via `setProfileOverride()`)\n * 2. `OLAKAI_PROFILE` env var\n * 3. Workspace config `profile` field\n * 4. `profiles.json:default`\n *\n * Host resolution order:\n *\n * 1. `--host` flag / `OLAKAI_HOST` env (handled in `config.ts`)\n * 2. Workspace config `host` field (ad-hoc override)\n * 3. Resolved profile's `host`\n * 4. Named environment fallback (handled in `config.ts`)\n *\n * Migration: on first profile-manager read, if a legacy\n * `~/.config/olakai/credentials.json` exists and `profiles.json` does\n * NOT, the legacy credentials are imported as a single profile named\n * `\"default\"` and marked as the default. The legacy file is left in\n * place for one release as a non-destructive safety net; see\n * `migrateLegacyCredentialsIfNeeded()` below.\n */\n\nimport * as fs from \"node:fs\";\nimport * as os from \"node:os\";\nimport * as path from \"node:path\";\nimport type { Environment } from \"./config.js\";\n\nexport const PROFILES_FILE_VERSION = 1;\n\nexport const HOSTS: Record<Environment, string> = {\n production: \"https://app.olakai.ai\",\n staging: \"https://staging.app.olakai.ai\",\n local: \"http://localhost:3000\",\n};\n\n/**\n * One profile record. `host` is the only required runtime field; the\n * rest are filled in after login. Identifiers (`userId`, `accountId`)\n * are cached locally so `whoami` and similar commands don't have to\n * make a network call to know which account a profile belongs to.\n */\nexport interface Profile {\n host: string;\n token?: string;\n expiresAt?: number; // Unix timestamp in seconds\n userId?: string;\n accountId?: string;\n email?: string;\n}\n\nexport interface ProfilesFile {\n version: number;\n default?: string;\n profiles: Record<string, Profile>;\n}\n\nexport interface WorkspaceConfig {\n profile?: string;\n host?: string;\n}\n\n/**\n * Resolved view of the profile actually in effect for the current\n * command invocation. Exposed to consumers (whoami, login, the API\n * client) so they can read the active host/token without re-walking\n * the resolution chain.\n */\nexport interface ResolvedProfile {\n /** Name of the profile that won resolution. */\n name: string;\n /** The profile record itself (host/token/etc). */\n profile: Profile;\n /**\n * Effective host. May differ from `profile.host` if the workspace\n * config or `--host` overrode it; in that case the profile's token\n * is still used but the host comes from the override.\n */\n host: string;\n /** True when the host was overridden by workspace config (`host`). */\n hostFromWorkspaceConfig: boolean;\n /** Where the profile name itself came from. */\n source: \"flag\" | \"env\" | \"workspace\" | \"default\";\n}\n\n// ---- module state -----------------------------------------------------------\n\nlet profileOverride: string | undefined;\n\n/** Set from the `--profile` global flag in the CLI preAction hook. */\nexport function setProfileOverride(name: string | undefined): void {\n profileOverride = name && name.length > 0 ? name : undefined;\n}\n\nexport function getProfileOverride(): string | undefined {\n return profileOverride;\n}\n\n// ---- paths ------------------------------------------------------------------\n\nfunction getConfigDir(home: string = os.homedir()): string {\n return path.join(home, \".config\", \"olakai\");\n}\n\nexport function getProfilesPath(home: string = os.homedir()): string {\n return path.join(getConfigDir(home), \"profiles.json\");\n}\n\nexport function getLegacyCredentialsPath(home: string = os.homedir()): string {\n return path.join(getConfigDir(home), \"credentials.json\");\n}\n\nfunction ensureConfigDir(home: string = os.homedir()): void {\n const dir = getConfigDir(home);\n if (!fs.existsSync(dir)) {\n fs.mkdirSync(dir, { recursive: true, mode: 0o700 });\n } else {\n // Best-effort tighten — ignore failures (e.g. on Windows).\n try {\n fs.chmodSync(dir, 0o700);\n } catch {\n // ignore\n }\n }\n}\n\n// ---- profiles.json IO -------------------------------------------------------\n\nfunction emptyProfilesFile(): ProfilesFile {\n return { version: PROFILES_FILE_VERSION, profiles: {} };\n}\n\nfunction readProfilesFileRaw(home: string = os.homedir()): ProfilesFile | null {\n const file = getProfilesPath(home);\n if (!fs.existsSync(file)) return null;\n try {\n const content = fs.readFileSync(file, \"utf-8\");\n const parsed = JSON.parse(content) as Partial<ProfilesFile>;\n if (\n typeof parsed !== \"object\" ||\n parsed === null ||\n typeof parsed.profiles !== \"object\" ||\n parsed.profiles === null\n ) {\n return null;\n }\n return {\n version:\n typeof parsed.version === \"number\"\n ? parsed.version\n : PROFILES_FILE_VERSION,\n default: typeof parsed.default === \"string\" ? parsed.default : undefined,\n profiles: parsed.profiles as Record<string, Profile>,\n };\n } catch {\n return null;\n }\n}\n\n/**\n * Read the profiles registry, applying lazy migration from a legacy\n * `credentials.json` on first read. Always returns a valid object;\n * returns the empty registry when no on-disk state exists.\n */\nexport function readProfilesFile(home: string = os.homedir()): ProfilesFile {\n migrateLegacyCredentialsIfNeeded(home);\n return readProfilesFileRaw(home) ?? emptyProfilesFile();\n}\n\n/**\n * Atomically write the profiles registry to disk with `0600` perms.\n * Parent directory is created with `0700` perms if missing.\n */\nexport function writeProfilesFile(\n data: ProfilesFile,\n home: string = os.homedir(),\n): void {\n ensureConfigDir(home);\n const file = getProfilesPath(home);\n // Per-invocation tmp filename to avoid corruption when two CLI\n // processes race on the same registry (e.g. concurrent `olakai\n // login` flows). PID + random suffix is overkill in practice but\n // costs ~nothing.\n const tmp = `${file}.${process.pid}.${Math.random().toString(36).slice(2)}.tmp`;\n fs.writeFileSync(tmp, JSON.stringify(data, null, 2), { mode: 0o600 });\n fs.renameSync(tmp, file);\n // `renameSync` preserves the tmp file's mode but be defensive on\n // platforms where it might not — re-apply 0600 explicitly.\n try {\n fs.chmodSync(file, 0o600);\n } catch {\n // ignore\n }\n}\n\n// ---- legacy migration -------------------------------------------------------\n\ninterface LegacyCredentials {\n token: string;\n expiresAt: number;\n environment: Environment;\n}\n\n/**\n * If `profiles.json` is missing and a legacy `credentials.json` exists,\n * import the legacy credentials as a profile named `\"default\"` and set\n * it as the default. Idempotent — a no-op if `profiles.json` already\n * exists.\n *\n * The legacy `credentials.json` is intentionally LEFT IN PLACE for one\n * release. Once we ship this in olakai-cli ≥ N+1, we should add a\n * follow-up that deletes the legacy file post-migration. (Tracking in\n * OLA-213.)\n */\nexport function migrateLegacyCredentialsIfNeeded(\n home: string = os.homedir(),\n): void {\n const profilesPath = getProfilesPath(home);\n if (fs.existsSync(profilesPath)) return;\n\n const legacyPath = getLegacyCredentialsPath(home);\n if (!fs.existsSync(legacyPath)) return;\n\n let legacy: LegacyCredentials;\n try {\n const raw = fs.readFileSync(legacyPath, \"utf-8\");\n legacy = JSON.parse(raw) as LegacyCredentials;\n } catch {\n // Unparseable legacy file — skip migration silently rather than\n // crashing every command. User can run `olakai login` to start\n // fresh.\n return;\n }\n\n if (\n typeof legacy?.token !== \"string\" ||\n typeof legacy?.expiresAt !== \"number\" ||\n typeof legacy?.environment !== \"string\"\n ) {\n return;\n }\n\n const host = HOSTS[legacy.environment] ?? HOSTS.production;\n\n const migrated: ProfilesFile = {\n version: PROFILES_FILE_VERSION,\n default: \"default\",\n profiles: {\n default: {\n host,\n token: legacy.token,\n expiresAt: legacy.expiresAt,\n },\n },\n };\n\n try {\n writeProfilesFile(migrated, home);\n } catch {\n // Migration is best-effort — failure to write should not break\n // the calling command. Subsequent commands will retry.\n }\n}\n\n// ---- workspace config -------------------------------------------------------\n\nconst WORKSPACE_CONFIG_FILENAME = \"config.json\";\nconst WORKSPACE_CONFIG_DIR = \".olakai\";\n\n/**\n * Walk up from `startDir` looking for a `.olakai/config.json` file.\n * Stops at filesystem root or at the user's home directory (whichever\n * comes first) so we don't accidentally pick up a config from above\n * `$HOME`.\n */\nexport function findWorkspaceConfigPath(\n startDir: string = process.cwd(),\n home: string = os.homedir(),\n): string | null {\n let current = path.resolve(startDir);\n const root = path.parse(current).root;\n\n // Allow finding a config in HOME itself, but don't escape above HOME\n // by default. If `startDir` is outside HOME (e.g. a system path),\n // walk all the way to root.\n const stopAtHome = current.startsWith(home);\n\n // We bound the loop on `current` reaching root to guarantee termination.\n while (true) {\n const candidate = path.join(current, WORKSPACE_CONFIG_DIR, WORKSPACE_CONFIG_FILENAME);\n if (fs.existsSync(candidate)) return candidate;\n\n if (current === root) return null;\n if (stopAtHome && current === home) return null;\n\n const parent = path.dirname(current);\n if (parent === current) return null;\n current = parent;\n }\n}\n\nexport function readWorkspaceConfig(\n startDir: string = process.cwd(),\n home: string = os.homedir(),\n): WorkspaceConfig | null {\n const file = findWorkspaceConfigPath(startDir, home);\n if (!file) return null;\n try {\n const raw = fs.readFileSync(file, \"utf-8\");\n const parsed = JSON.parse(raw) as Partial<WorkspaceConfig>;\n return {\n profile:\n typeof parsed?.profile === \"string\" && parsed.profile.length > 0\n ? parsed.profile\n : undefined,\n host:\n typeof parsed?.host === \"string\" && parsed.host.length > 0\n ? parsed.host\n : undefined,\n };\n } catch {\n return null;\n }\n}\n\n// ---- resolution -------------------------------------------------------------\n\nfunction normalizeHost(host: string): string {\n const withScheme = /^https?:\\/\\//i.test(host) ? host : `https://${host}`;\n return withScheme.replace(/\\/+$/, \"\");\n}\n\n/**\n * Resolve the profile name to use for this invocation, given the\n * precedence rules. Returns `null` only when no profile is configured\n * at all (registry empty AND no env/flag/workspace pointer).\n */\nexport function resolveProfileName(\n startDir: string = process.cwd(),\n home: string = os.homedir(),\n): { name: string; source: ResolvedProfile[\"source\"] } | null {\n // 1. --profile flag\n if (profileOverride) {\n return { name: profileOverride, source: \"flag\" };\n }\n // 2. OLAKAI_PROFILE env\n const envProfile = process.env.OLAKAI_PROFILE?.trim();\n if (envProfile) {\n return { name: envProfile, source: \"env\" };\n }\n // 3. Workspace config\n const workspace = readWorkspaceConfig(startDir, home);\n if (workspace?.profile) {\n return { name: workspace.profile, source: \"workspace\" };\n }\n // 4. profiles.default\n const file = readProfilesFile(home);\n if (file.default) {\n return { name: file.default, source: \"default\" };\n }\n return null;\n}\n\n/**\n * Resolve the active profile + host for the current invocation, or\n * null if no profile is configured. The returned object's `host` is\n * already normalized (trailing slash stripped, scheme prepended).\n *\n * Throws when the user EXPLICITLY requested a profile (via `--profile`,\n * `OLAKAI_PROFILE`, or workspace config) that doesn't exist in the\n * registry. Callers in flows that legitimately create profiles on the\n * fly (e.g. `olakai login --profile new-name`) should use\n * `tryResolveActiveProfile` instead.\n */\nexport function resolveActiveProfile(\n startDir: string = process.cwd(),\n home: string = os.homedir(),\n): ResolvedProfile | null {\n const resolved = resolveProfileName(startDir, home);\n if (!resolved) return null;\n\n const file = readProfilesFile(home);\n const profile = file.profiles[resolved.name];\n if (!profile) {\n // Name was explicitly requested but the profile doesn't exist.\n // Surface this with a clear error so the caller can react.\n throw new Error(\n `Profile \"${resolved.name}\" not found. Run 'olakai profiles list' to see available profiles.`,\n );\n }\n\n const workspace = readWorkspaceConfig(startDir, home);\n let host = profile.host;\n let hostFromWorkspaceConfig = false;\n if (workspace?.host) {\n host = workspace.host;\n hostFromWorkspaceConfig = true;\n }\n\n return {\n name: resolved.name,\n profile,\n host: normalizeHost(host),\n hostFromWorkspaceConfig,\n source: resolved.source,\n };\n}\n\n/**\n * Lenient sibling of `resolveActiveProfile`: returns `null` BOTH when\n * no profile is configured AND when the requested profile doesn't yet\n * exist. Use this in flows that may legitimately need to operate\n * before the profile is created — notably `olakai login --profile new`\n * and the internal `getBaseUrl()` resolver (which must work during\n * first-login).\n */\nexport function tryResolveActiveProfile(\n startDir: string = process.cwd(),\n home: string = os.homedir(),\n): ResolvedProfile | null {\n try {\n return resolveActiveProfile(startDir, home);\n } catch {\n return null;\n }\n}\n\n// ---- mutators ---------------------------------------------------------------\n\n/**\n * Update (or insert) a profile and persist. If `setDefault` is true OR\n * the registry has no default yet, the profile is marked as default.\n */\nexport function upsertProfile(\n name: string,\n profile: Profile,\n options: { setDefault?: boolean } = {},\n home: string = os.homedir(),\n): ProfilesFile {\n const file = readProfilesFile(home);\n file.profiles[name] = profile;\n if (options.setDefault || !file.default) {\n file.default = name;\n }\n writeProfilesFile(file, home);\n return file;\n}\n\n/**\n * Patch fields of an existing profile (or create it with the patch\n * applied). Preserves any existing fields not present in `patch`.\n */\nexport function patchProfile(\n name: string,\n patch: Partial<Profile>,\n home: string = os.homedir(),\n): Profile {\n const file = readProfilesFile(home);\n const existing = file.profiles[name];\n const merged: Profile = {\n host: patch.host ?? existing?.host ?? HOSTS.production,\n token: patch.token ?? existing?.token,\n expiresAt: patch.expiresAt ?? existing?.expiresAt,\n userId: patch.userId ?? existing?.userId,\n accountId: patch.accountId ?? existing?.accountId,\n email: patch.email ?? existing?.email,\n };\n file.profiles[name] = merged;\n if (!file.default) {\n file.default = name;\n }\n writeProfilesFile(file, home);\n return merged;\n}\n\n/**\n * Remove `name` from the registry. Throws if the profile is the\n * current default — callers should switch the default first.\n */\nexport function removeProfile(\n name: string,\n home: string = os.homedir(),\n): void {\n const file = readProfilesFile(home);\n if (!file.profiles[name]) {\n throw new Error(`Profile \"${name}\" does not exist.`);\n }\n if (file.default === name) {\n throw new Error(\n `Cannot remove profile \"${name}\" because it is the active default. ` +\n `Switch the default first with 'olakai profiles use <other>'.`,\n );\n }\n delete file.profiles[name];\n writeProfilesFile(file, home);\n}\n\n/**\n * Set `name` as the registry's default profile. Throws if `name`\n * doesn't exist.\n */\nexport function setDefaultProfile(\n name: string,\n home: string = os.homedir(),\n): void {\n const file = readProfilesFile(home);\n if (!file.profiles[name]) {\n throw new Error(\n `Profile \"${name}\" does not exist. Run 'olakai login --profile ${name}' first.`,\n );\n }\n file.default = name;\n writeProfilesFile(file, home);\n}\n\n/**\n * Clear stored token fields on a profile (but keep the profile itself\n * around so the host + identifiers survive a logout).\n */\nexport function clearProfileToken(\n name: string,\n home: string = os.homedir(),\n): void {\n const file = readProfilesFile(home);\n const profile = file.profiles[name];\n if (!profile) return;\n delete profile.token;\n delete profile.expiresAt;\n writeProfilesFile(file, home);\n}\n","import { tryResolveActiveProfile } from \"./profiles.js\";\n\nexport type Environment = \"production\" | \"staging\" | \"local\";\n\nconst HOSTS: Record<Environment, string> = {\n production: \"https://app.olakai.ai\",\n staging: \"https://staging.app.olakai.ai\",\n local: \"http://localhost:3000\",\n};\n\n// CLI client identifier\nexport const CLIENT_ID = \"olakai-cli\";\n\nlet currentEnvironment: Environment = \"production\";\nlet hostOverride: string | undefined;\n\n/**\n * Set the current environment\n */\nexport function setEnvironment(env: Environment): void {\n currentEnvironment = env;\n}\n\n/**\n * Set an explicit host override (e.g. for on-prem deployments).\n * Accepts a hostname only (\"olakai.acme.com\") or a full URL.\n * Pass `undefined` to clear the override.\n */\nexport function setHostOverride(host: string | undefined): void {\n hostOverride = host;\n}\n\n/**\n * Get the current environment from:\n * 1. Environment variable OLAKAI_ENV\n * 2. Programmatically set value\n * 3. Default to \"production\"\n */\nexport function getEnvironment(): Environment {\n const envVar = process.env.OLAKAI_ENV as Environment | undefined;\n if (envVar && isValidEnvironment(envVar)) {\n return envVar;\n }\n return currentEnvironment;\n}\n\n/**\n * Normalize a user-supplied host value into a base URL.\n * Accepts either a full URL (\"https://olakai.acme.com\") or a bare hostname\n * (\"olakai.acme.com\"); for bare hostnames `https://` is prepended.\n * Trailing slashes are stripped so callers can safely append paths.\n */\nfunction normalizeHost(host: string): string {\n const withScheme = /^https?:\\/\\//i.test(host) ? host : `https://${host}`;\n return withScheme.replace(/\\/+$/, \"\");\n}\n\n/**\n * Get the API base URL.\n *\n * Resolution precedence:\n * 1. Programmatic host override (`setHostOverride()`, set from `--host` flag)\n * 2. `OLAKAI_HOST` env var (on-prem deployments)\n * 3. Active profile's host (workspace config `host` > profile `host`)\n * 4. Named environment via `OLAKAI_ENV` / `--env` (production, staging, local)\n *\n * The profile lookup is loaded lazily to avoid a hard dependency cycle\n * between this module (used by `profiles.ts`) and `profiles.ts` itself.\n */\nexport function getBaseUrl(): string {\n const override = hostOverride?.trim();\n if (override) {\n return normalizeHost(override);\n }\n const envHost = process.env.OLAKAI_HOST?.trim();\n if (envHost) {\n return normalizeHost(envHost);\n }\n\n // Profile-aware host (workspace config overrides profile.host, but\n // both are below --host / OLAKAI_HOST). We use the LENIENT resolver\n // here because `getBaseUrl()` runs during first-login flows where\n // the requested profile name might not exist yet (e.g.\n // `olakai login --profile brand-new`). Dedicated `olakai profiles\n // ...` commands surface the not-found error directly. A null return\n // here just means \"fall through to the named-env default\".\n const active = tryResolveActiveProfile();\n if (active) {\n return active.host;\n }\n\n return HOSTS[getEnvironment()];\n}\n\n/**\n * Check if a string is a valid environment\n */\nexport function isValidEnvironment(env: string): env is Environment {\n return env === \"production\" || env === \"staging\" || env === \"local\";\n}\n\n/**\n * Get list of valid environments for CLI help\n */\nexport function getValidEnvironments(): Environment[] {\n return [\"production\", \"staging\", \"local\"];\n}\n","/**\n * Token storage shim that delegates to the profile manager.\n *\n * Historically the CLI stored a single token at\n * `~/.config/olakai/credentials.json`. As of OLA-213 we manage one or\n * more named profiles in `~/.config/olakai/profiles.json` (each with\n * its own token). This module preserves the original\n * `loadToken / isTokenValid / saveToken / clearToken / getValidToken`\n * API so the dozens of callers across `src/commands/` and\n * `src/lib/api.ts` can keep working without per-call refactors.\n *\n * All operations resolve against the *active* profile (the one chosen\n * by `--profile` / `OLAKAI_PROFILE` / workspace config / registry\n * default). Saving a token mutates the active profile's stored token;\n * clearing it removes only the token fields, leaving the host +\n * cached identifiers in place.\n */\n\nimport { getBaseUrl, getEnvironment, type Environment } from \"./config.js\";\nimport {\n HOSTS,\n clearProfileToken,\n readProfilesFile,\n resolveActiveProfile,\n resolveProfileName,\n writeProfilesFile,\n} from \"./profiles.js\";\n\nexport interface StoredCredentials {\n token: string;\n expiresAt: number; // Unix timestamp in seconds\n /**\n * Legacy field kept for callers that still want a coarse-grained\n * environment label. Populated from the active profile's host —\n * falls back to the active CLI environment when the profile's host\n * doesn't match a known named env.\n */\n environment: Environment;\n}\n\nfunction hostToEnvironment(host: string): Environment {\n for (const env of [\"production\", \"staging\", \"local\"] as const) {\n if (HOSTS[env] === host) return env;\n }\n return getEnvironment();\n}\n\n/**\n * Save an access token to disk under the active profile.\n *\n * If `--profile`/env/workspace selected a profile that doesn't exist\n * yet, it is created on the spot (typical first-login flow). If\n * nothing was selected, the token is written to a profile named\n * `\"default\"` and that becomes the registry default — preserving the\n * pre-profile-manager UX where `olakai login` Just Worked.\n */\nexport function saveToken(token: string, expiresIn: number): void {\n const expiresAt = Math.floor(Date.now() / 1000) + expiresIn;\n\n // Determine target profile name + host. `resolveProfileName` doesn't\n // require the profile to already exist (vs `resolveActiveProfile`\n // which throws).\n const resolved = resolveProfileName();\n const name = resolved?.name ?? \"default\";\n const host = getBaseUrl();\n\n const file = readProfilesFile();\n const existing = file.profiles[name];\n file.profiles[name] = {\n host,\n token,\n expiresAt,\n userId: existing?.userId,\n accountId: existing?.accountId,\n email: existing?.email,\n };\n // Set as the default profile when:\n // - There is no default yet, OR\n // - The caller didn't explicitly request a profile (so the new\n // login should land on the registry's default).\n if (!file.default || !resolved) {\n file.default = name;\n }\n writeProfilesFile(file);\n}\n\n/**\n * Load the credentials for the active profile, in the legacy shape so\n * existing callers (esp. `whoami` and `api.ts`) keep compiling. Returns\n * null if no profile is configured or the active profile has no token.\n */\nexport function loadToken(): StoredCredentials | null {\n let active;\n try {\n active = resolveActiveProfile();\n } catch {\n // Requested profile doesn't exist — treat as \"not logged in\" for\n // the legacy callers. The dedicated profile commands surface the\n // error directly.\n return null;\n }\n if (!active?.profile.token || !active.profile.expiresAt) return null;\n return {\n token: active.profile.token,\n expiresAt: active.profile.expiresAt,\n environment: hostToEnvironment(active.host),\n };\n}\n\n/**\n * Clear the token on the active profile (but keep the profile record\n * itself so the host + identifiers survive a logout).\n */\nexport function clearToken(): void {\n let resolved;\n try {\n resolved = resolveActiveProfile();\n } catch {\n return;\n }\n if (!resolved) return;\n clearProfileToken(resolved.name);\n}\n\n/**\n * Check whether the active profile holds a non-expired token. A 60s\n * skew is applied so callers don't ship a request with a token that's\n * about to expire mid-flight.\n */\nexport function isTokenValid(): boolean {\n const credentials = loadToken();\n if (!credentials) return false;\n\n // 60 second skew to avoid the API rejecting a token that's about to\n // expire.\n const now = Math.floor(Date.now() / 1000);\n if (credentials.expiresAt <= now + 60) return false;\n\n return true;\n}\n\n/** Convenience: return the active token if it's valid, else null. */\nexport function getValidToken(): string | null {\n if (!isTokenValid()) return null;\n return loadToken()?.token ?? null;\n}\n","/**\n * Claude Code `settings.json` hook-block helpers.\n *\n * Pure functions extracted out of the original `monitor.ts` so they\n * remain unit-testable without touching the filesystem. The dispatcher\n * is owned by `install.ts` / `uninstall.ts`.\n */\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\n\nexport const CLAUDE_DIR = \".claude\";\nexport const SETTINGS_FILE = \"settings.json\";\n\n/**\n * Substring used to identify Olakai-installed hook commands inside an\n * existing Claude `settings.json`. Both stop and subagent-stop entries\n * carry this marker as a prefix of the command string.\n */\nexport const OLAKAI_HOOK_MARKER = \"olakai monitor hook\";\n\nexport interface HookCommand {\n type: string;\n command: string;\n}\n\nexport interface HookMatcherEntry {\n matcher: string;\n hooks: HookCommand[];\n}\n\nexport interface ClaudeSettings {\n hooks?: Record<string, HookMatcherEntry[]>;\n [key: string]: unknown;\n}\n\nexport const HOOK_DEFINITIONS: Record<string, HookMatcherEntry[]> = {\n Stop: [\n {\n matcher: \"\",\n hooks: [\n {\n type: \"command\",\n command: \"olakai monitor hook stop\",\n },\n ],\n },\n ],\n SubagentStop: [\n {\n matcher: \"\",\n hooks: [\n {\n type: \"command\",\n command: \"olakai monitor hook subagent-stop\",\n },\n ],\n },\n ],\n};\n\n/**\n * Layer the Olakai default hook definitions onto an existing hooks\n * block. See the original docstring in `monitor.ts` for the merge\n * rules — preserved verbatim during the Stage 2 refactor.\n */\nexport function mergeHooksSettings(\n existing: Record<string, HookMatcherEntry[]> | undefined,\n definitions: Record<string, HookMatcherEntry[]> = HOOK_DEFINITIONS,\n): Record<string, HookMatcherEntry[]> {\n const merged: Record<string, HookMatcherEntry[]> = {\n ...(existing ?? {}),\n };\n\n for (const [event, defaultEntries] of Object.entries(definitions)) {\n const existingEntries = merged[event] ?? [];\n const hasOlakaiHook = existingEntries.some((e) =>\n e.hooks.some((h) => h.command.includes(OLAKAI_HOOK_MARKER)),\n );\n\n if (hasOlakaiHook) {\n merged[event] = existingEntries;\n } else {\n merged[event] = [...existingEntries, ...defaultEntries];\n }\n }\n\n return merged;\n}\n\nexport function getClaudeDir(projectRoot: string): string {\n return path.join(projectRoot, CLAUDE_DIR);\n}\n\nexport function getSettingsPath(projectRoot: string): string {\n return path.join(getClaudeDir(projectRoot), SETTINGS_FILE);\n}\n\nexport function readJsonFile<T>(filePath: string): T | null {\n try {\n if (!fs.existsSync(filePath)) return null;\n const content = fs.readFileSync(filePath, \"utf-8\");\n return JSON.parse(content) as T;\n } catch {\n return null;\n }\n}\n\nexport function writeJsonFile(filePath: string, data: unknown): void {\n const dir = path.dirname(filePath);\n if (!fs.existsSync(dir)) {\n fs.mkdirSync(dir, { recursive: true });\n }\n fs.writeFileSync(filePath, JSON.stringify(data, null, 2) + \"\\n\", \"utf-8\");\n}\n","/**\n * Per-tool monitor config storage for Claude Code. Lives at\n * `.olakai/monitor-claude-code.json` (post-Stage-2). Pre-Stage-2 the\n * file lived at `.claude/olakai-monitor.json`; the auto-migration\n * shim in `monitor/migrations.ts` upgrades old workspaces transparently.\n */\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport {\n getMonitorConfigPath as resolveMonitorConfigPath,\n getOlakaiDir,\n} from \"../../paths.js\";\nimport { migrateLegacyClaudeConfigIfNeeded } from \"../../migrations.js\";\n\nexport interface MonitorConfig {\n agentId: string;\n apiKey: string;\n agentName: string;\n source: string;\n createdAt: string;\n monitoringEndpoint: string;\n}\n\nexport function getClaudeCodeConfigPath(projectRoot: string): string {\n return resolveMonitorConfigPath(projectRoot, \"claude-code\");\n}\n\n/**\n * Load the Claude Code monitor config. Migrates legacy\n * `.claude/olakai-monitor.json` to the new path on first read when\n * needed. `notify` is plumbed through so the hook path can pass a\n * no-op (silent), while init/status/disable use stderr.\n */\nexport function loadClaudeCodeConfig(\n projectRoot: string,\n notify?: (msg: string) => void,\n): MonitorConfig | null {\n migrateLegacyClaudeConfigIfNeeded(projectRoot, notify);\n const filePath = getClaudeCodeConfigPath(projectRoot);\n try {\n if (!fs.existsSync(filePath)) return null;\n const raw = fs.readFileSync(filePath, \"utf-8\");\n return JSON.parse(raw) as MonitorConfig;\n } catch {\n return null;\n }\n}\n\nexport function writeClaudeCodeConfig(\n projectRoot: string,\n config: MonitorConfig,\n): void {\n const filePath = getClaudeCodeConfigPath(projectRoot);\n const dir = path.dirname(filePath);\n if (!fs.existsSync(dir)) {\n fs.mkdirSync(dir, { recursive: true });\n }\n fs.writeFileSync(filePath, JSON.stringify(config, null, 2) + \"\\n\", \"utf-8\");\n try {\n fs.chmodSync(filePath, 0o600);\n } catch {\n // chmod failures are non-fatal — Windows / unusual filesystems\n }\n}\n\nexport function deleteClaudeCodeConfig(projectRoot: string): boolean {\n const filePath = getClaudeCodeConfigPath(projectRoot);\n if (!fs.existsSync(filePath)) return false;\n try {\n fs.unlinkSync(filePath);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Path to the directory that the new config lives in. Exposed for\n * messages like \"config saved to <dir>\".\n */\nexport function getOlakaiConfigDir(projectRoot: string): string {\n return getOlakaiDir(projectRoot);\n}\n","/**\n * Per-tool config-path resolver. Centralized so plugins, the\n * auto-migration shim, and the hook dispatcher all agree on where each\n * tool's config lives.\n *\n * Layout:\n * .olakai/\n * monitor-claude-code.json\n * monitor-codex.json\n * monitor-cursor.json\n *\n * Pre-Stage-2 layout (Claude Code only):\n * .claude/\n * olakai-monitor.json <-- migrated to the new path on first read\n */\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport type { ToolId } from \"./plugin.js\";\n\nexport const OLAKAI_DIR = \".olakai\";\nexport const LEGACY_CLAUDE_DIR = \".claude\";\nexport const LEGACY_CLAUDE_CONFIG_FILE = \"olakai-monitor.json\";\n\nexport function getOlakaiDir(projectRoot: string): string {\n return path.join(projectRoot, OLAKAI_DIR);\n}\n\nexport function getMonitorConfigFileName(toolId: ToolId): string {\n return `monitor-${toolId}.json`;\n}\n\nexport function getMonitorConfigPath(\n projectRoot: string,\n toolId: ToolId,\n): string {\n return path.join(getOlakaiDir(projectRoot), getMonitorConfigFileName(toolId));\n}\n\nexport function getLegacyClaudeMonitorConfigPath(projectRoot: string): string {\n return path.join(\n projectRoot,\n LEGACY_CLAUDE_DIR,\n LEGACY_CLAUDE_CONFIG_FILE,\n );\n}\n\n/**\n * Walk up from `startDir` looking for ANY indicator that this tree was\n * configured by `olakai monitor init`. Used by the hook dispatcher to\n * locate the configured workspace independently of the calling\n * process's CWD (Claude Code, Codex, and Cursor all reserve the right\n * to spawn hooks from arbitrary directories — see INV-002).\n *\n * Returns the closest ancestor directory containing either the new\n * `.olakai/monitor-<tool>.json` file (for any tool) OR the legacy\n * `.claude/olakai-monitor.json` file. Returns null when nothing is\n * found — callers MUST treat that as silent-exit.\n *\n * Exported for unit tests.\n */\nexport function findConfiguredWorkspace(\n startDir: string,\n toolIds: readonly ToolId[],\n): string | null {\n let dir = startDir;\n while (true) {\n if (hasConfiguredMonitorIn(dir, toolIds)) {\n return dir;\n }\n const parent = path.dirname(dir);\n if (parent === dir) break;\n dir = parent;\n }\n return null;\n}\n\nfunction hasConfiguredMonitorIn(\n dir: string,\n toolIds: readonly ToolId[],\n): boolean {\n for (const toolId of toolIds) {\n if (fs.existsSync(getMonitorConfigPath(dir, toolId))) {\n return true;\n }\n }\n if (fs.existsSync(getLegacyClaudeMonitorConfigPath(dir))) {\n return true;\n }\n return false;\n}\n","/**\n * Auto-migration: pre-Stage-2 layout\n * .claude/olakai-monitor.json\n * to the new per-tool layout\n * .olakai/monitor-claude-code.json\n *\n * Trigger: any read path that asks for the Claude Code monitor config.\n * If the new path is missing AND the legacy path exists, we copy the\n * legacy file's contents to the new location (preserving fields and\n * 0600 permissions) and emit a one-line notice via `notify`.\n *\n * The legacy file is intentionally NOT deleted — users may have it in\n * automation, and leaving it in place gives a clear rollback path.\n */\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport {\n getLegacyClaudeMonitorConfigPath,\n getMonitorConfigPath,\n getOlakaiDir,\n LEGACY_CLAUDE_CONFIG_FILE,\n LEGACY_CLAUDE_DIR,\n OLAKAI_DIR,\n} from \"./paths.js\";\n\nexport type MigrationNotifier = (message: string) => void;\n\nconst defaultNotifier: MigrationNotifier = (msg) => {\n console.error(msg);\n};\n\n/**\n * If a legacy `.claude/olakai-monitor.json` exists at `projectRoot`\n * and the new `.olakai/monitor-claude-code.json` does not, copy the\n * legacy content to the new path. Returns true when a migration\n * happened, false otherwise. Never throws.\n *\n * The hook code path is silent-only — pass a no-op `notify` there so\n * we don't spam stderr (which could break Claude Code). Init/status/\n * disable use the default notifier.\n */\nexport function migrateLegacyClaudeConfigIfNeeded(\n projectRoot: string,\n notify: MigrationNotifier = defaultNotifier,\n): boolean {\n try {\n const legacyPath = getLegacyClaudeMonitorConfigPath(projectRoot);\n const newPath = getMonitorConfigPath(projectRoot, \"claude-code\");\n if (fs.existsSync(newPath)) return false;\n if (!fs.existsSync(legacyPath)) return false;\n\n const raw = fs.readFileSync(legacyPath, \"utf-8\");\n // Validate the legacy file is parseable JSON before writing — a\n // corrupt legacy file shouldn't seed a corrupt new file.\n JSON.parse(raw);\n\n const newDir = getOlakaiDir(projectRoot);\n if (!fs.existsSync(newDir)) {\n fs.mkdirSync(newDir, { recursive: true });\n }\n fs.writeFileSync(newPath, raw, \"utf-8\");\n try {\n fs.chmodSync(newPath, 0o600);\n } catch {\n // chmod can fail on Windows / weird filesystems — non-fatal\n }\n\n try {\n notify(\n `[olakai] Migrated ${path.join(LEGACY_CLAUDE_DIR, LEGACY_CLAUDE_CONFIG_FILE)} -> ${path.join(OLAKAI_DIR, \"monitor-claude-code.json\")} (legacy file kept).`,\n );\n } catch {\n // Notifier failures must not break the caller\n }\n return true;\n } catch {\n return false;\n }\n}\n"],"mappings":"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","names":["path","HOSTS","normalizeHost","fs","path","fs","path","fs","path","fs","path","path"]}
|
|
File without changes
|