@kohala/devkit 0.1.4 → 0.1.5
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/CHANGELOG.md +13 -0
- package/dist/cli/index.js +39 -1
- package/dist/cli/index.js.map +1 -1
- package/docs/MANIFEST.md +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
# @kohala/devkit
|
|
2
2
|
|
|
3
|
+
## 0.1.5
|
|
4
|
+
|
|
5
|
+
- **BUG-069 fixed: the manifest `schedule` now actually lands on the
|
|
6
|
+
platform.** The CLI used to send it as a top-level `schedule` key that is
|
|
7
|
+
not in the platform schema and was silently dropped (agent deployed green,
|
|
8
|
+
`agentScheduleCron` stayed null). Deploy now sends the platform's canonical
|
|
9
|
+
`agentScheduleCron` + `agentScheduleEnabled` fields, and — because the
|
|
10
|
+
platform honors them only on agent *create*, not on the idempotent
|
|
11
|
+
upsert-by-name update — additionally PATCHes the schedule after the upsert
|
|
12
|
+
and verifies it round-tripped, failing loudly if it did not. Deploy stays
|
|
13
|
+
additive: no schedule in the manifest means the schedule fields are not
|
|
14
|
+
sent at all, so an existing schedule is never disabled.
|
|
15
|
+
|
|
3
16
|
## 0.1.4
|
|
4
17
|
|
|
5
18
|
- **BUG-067 fixed: skills deployed by `kohala deploy` are now actually
|
package/dist/cli/index.js
CHANGED
|
@@ -2264,7 +2264,7 @@ function buildDeployPlan(manifest, agentDir) {
|
|
|
2264
2264
|
charter: manifest.charter,
|
|
2265
2265
|
toolAllowlist: manifest.toolAllowlist,
|
|
2266
2266
|
runtimeMode: manifest.runtimeMode,
|
|
2267
|
-
...manifest.schedule ? {
|
|
2267
|
+
...manifest.schedule ? { agentScheduleCron: manifest.schedule, agentScheduleEnabled: true } : {}
|
|
2268
2268
|
},
|
|
2269
2269
|
skills,
|
|
2270
2270
|
quota: {
|
|
@@ -2340,6 +2340,26 @@ var KohalaClient = class {
|
|
|
2340
2340
|
);
|
|
2341
2341
|
}
|
|
2342
2342
|
}
|
|
2343
|
+
/**
|
|
2344
|
+
* Step 2b (only when the manifest has a schedule): persist the cron.
|
|
2345
|
+
*
|
|
2346
|
+
* BUG-069: POST /agents honors agentScheduleCron on *create* but silently
|
|
2347
|
+
* ignores it when upserting an existing agent, so deploy PATCHes the
|
|
2348
|
+
* schedule explicitly and verifies it round-tripped. Never called without
|
|
2349
|
+
* a schedule — deploy is additive and must not disable existing schedules.
|
|
2350
|
+
*/
|
|
2351
|
+
async setSchedule(agentId, cron) {
|
|
2352
|
+
const data = await this.request("PATCH", `/api/v1/agents/${agentId}`, {
|
|
2353
|
+
agentScheduleCron: cron,
|
|
2354
|
+
agentScheduleEnabled: true
|
|
2355
|
+
});
|
|
2356
|
+
if (data?.agentScheduleCron !== cron || data?.agentScheduleEnabled !== true) {
|
|
2357
|
+
throw new DeployError(
|
|
2358
|
+
500,
|
|
2359
|
+
`Platform did not persist the schedule "${cron}" (got agentScheduleCron=${JSON.stringify(data?.agentScheduleCron)}, agentScheduleEnabled=${JSON.stringify(data?.agentScheduleEnabled)}) \u2014 aborting.`
|
|
2360
|
+
);
|
|
2361
|
+
}
|
|
2362
|
+
}
|
|
2343
2363
|
/** Step 3: set the token caps. */
|
|
2344
2364
|
async setQuota(agentId, payload) {
|
|
2345
2365
|
await this.request("PUT", `/api/v1/agents/${agentId}/quota`, payload);
|
|
@@ -2363,6 +2383,20 @@ function registerDeployCommand(program2) {
|
|
|
2363
2383
|
console.log("");
|
|
2364
2384
|
console.log(pc8.bold("1. POST /api/v1/agents (idempotent on name)"));
|
|
2365
2385
|
console.log(JSON.stringify(plan.agent, null, 2));
|
|
2386
|
+
if (plan.agent.agentScheduleCron) {
|
|
2387
|
+
console.log("");
|
|
2388
|
+
console.log(pc8.bold("1b. PATCH /api/v1/agents/:id (persist schedule on updates)"));
|
|
2389
|
+
console.log(
|
|
2390
|
+
JSON.stringify(
|
|
2391
|
+
{
|
|
2392
|
+
agentScheduleCron: plan.agent.agentScheduleCron,
|
|
2393
|
+
agentScheduleEnabled: true
|
|
2394
|
+
},
|
|
2395
|
+
null,
|
|
2396
|
+
2
|
|
2397
|
+
)
|
|
2398
|
+
);
|
|
2399
|
+
}
|
|
2366
2400
|
for (const skill of plan.skills) {
|
|
2367
2401
|
console.log("");
|
|
2368
2402
|
console.log(pc8.bold(`2. POST /api/v1/agents/:id/skills \u2014 "${skill.name}"`));
|
|
@@ -2395,6 +2429,10 @@ function registerDeployCommand(program2) {
|
|
|
2395
2429
|
console.log(
|
|
2396
2430
|
pc8.green(` \u2714 agent ${upserted.created ? "created" : "updated"} (id ${upserted.id})`)
|
|
2397
2431
|
);
|
|
2432
|
+
if (plan.agent.agentScheduleCron) {
|
|
2433
|
+
await client.setSchedule(upserted.id, plan.agent.agentScheduleCron);
|
|
2434
|
+
console.log(pc8.green(` \u2714 schedule set (${plan.agent.agentScheduleCron})`));
|
|
2435
|
+
}
|
|
2398
2436
|
for (const skill of plan.skills) {
|
|
2399
2437
|
await client.upsertSkill(upserted.id, skill);
|
|
2400
2438
|
console.log(pc8.green(` \u2714 skill "${skill.name}" uploaded (${skill.scriptFilename})`));
|
package/dist/cli/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/cli/index.ts","../../src/cli/init.ts","../../src/manifest/schema.ts","../../src/cli/validate.ts","../../src/manifest/load.ts","../../src/manifest/known-tools.ts","../../src/cli/run.ts","../../src/memory/file.ts","../../src/memory/store.ts","../../src/util/lock.ts","../../src/memory/postgres.ts","../../src/memory/create.ts","../../src/emulator/runner.ts","../../src/trace/writer.ts","../../src/emulator/tokens.ts","../../src/emulator/validators.ts","../../src/sdk/rpc.ts","../../src/sdk/dispatch.ts","../../src/emulator/allowlist.ts","../../src/emulator/llm-client.ts","../../src/emulator/llm-mode.ts","../../src/emulator/python.ts","../../src/cli/trace.ts","../../src/trace/reader.ts","../../src/trace/format.ts","../../src/cli/memory-serve.ts","../../src/mcp/server.ts","../../src/cli/login.ts","../../src/deploy/credentials.ts","../../src/cli/deploy.ts","../../src/deploy/client.ts","../../src/cli/doctor.ts"],"sourcesContent":["import { createRequire } from \"node:module\";\nimport { Command } from \"commander\";\nimport pc from \"picocolors\";\nimport { registerInitCommand } from \"./init.js\";\nimport { registerValidateCommand } from \"./validate.js\";\nimport { registerRunCommand } from \"./run.js\";\nimport { registerTraceCommand } from \"./trace.js\";\nimport { registerMemoryCommand } from \"./memory-serve.js\";\nimport { registerLoginCommand } from \"./login.js\";\nimport { registerDeployCommand } from \"./deploy.js\";\nimport { registerDoctorCommand } from \"./doctor.js\";\n\n/**\n * The `kohala` CLI entry point.\n *\n * Command files under src/cli/ are deliberately thin: they parse flags, call\n * into lib code (manifest/, emulator/, memory/, deploy/), and format output.\n * All behavior lives in the libraries so it is unit-testable without a TTY.\n */\n\nconst require = createRequire(import.meta.url);\n// Version comes straight from package.json so `kohala --version` can never drift.\nconst { version } = require(\"../../package.json\") as { version: string };\n\nconst program = new Command();\n\nprogram\n .name(\"kohala\")\n .description(\n \"Kohala Devkit — build and run agents entirely on your own machine, then push the same agent to Kohala when you want it hosted.\",\n )\n .version(version);\n\nregisterInitCommand(program);\nregisterValidateCommand(program);\nregisterRunCommand(program);\nregisterTraceCommand(program);\nregisterMemoryCommand(program);\nregisterLoginCommand(program);\nregisterDeployCommand(program);\nregisterDoctorCommand(program);\n\nprogram.parseAsync(process.argv).catch((error: Error) => {\n // Central failure path: every command failure lands here, loudly and red.\n console.error(pc.red(`\\n${error.message}`));\n process.exitCode = 1;\n});\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport type { Command } from \"commander\";\nimport pc from \"picocolors\";\nimport { manifestSchema } from \"../manifest/schema.js\";\n\n/**\n * `kohala init <name>` — scaffold a new agent from templates/.\n *\n * The scaffold is a complete, runnable agent: kohala.json, skills/main.py (a\n * working example that writes to memory), skills/_tools.py (the local SDK),\n * and a README. `kohala run <name> --local` works immediately after init.\n */\n\n/** Locate the templates directory relative to the built CLI bundle. */\nfunction templatesDir(): string {\n // dist/cli/index.js -> ../../templates ; src/cli/init.ts -> ../../templates\n const here = path.dirname(fileURLToPath(import.meta.url));\n const candidates = [\n path.resolve(here, \"..\", \"..\", \"templates\"),\n path.resolve(here, \"..\", \"..\", \"..\", \"templates\"),\n ];\n for (const candidate of candidates) {\n if (fs.existsSync(path.join(candidate, \"kohala.json\"))) return candidate;\n }\n throw new Error(`Could not locate the devkit templates directory (looked in: ${candidates.join(\", \")})`);\n}\n\n/** Recursively copy the template tree, substituting {{AGENT_NAME}}. */\nfunction copyTemplates(sourceDir: string, targetDir: string, agentName: string): void {\n fs.mkdirSync(targetDir, { recursive: true });\n for (const entry of fs.readdirSync(sourceDir, { withFileTypes: true })) {\n const sourcePath = path.join(sourceDir, entry.name);\n const targetPath = path.join(targetDir, entry.name);\n if (entry.isDirectory()) {\n copyTemplates(sourcePath, targetPath, agentName);\n } else {\n const contents = fs.readFileSync(sourcePath, \"utf8\");\n fs.writeFileSync(targetPath, contents.replaceAll(\"{{AGENT_NAME}}\", agentName), \"utf8\");\n }\n }\n}\n\nexport function registerInitCommand(program: Command): void {\n program\n .command(\"init\")\n .argument(\"<name>\", \"agent name (also the directory name)\")\n .description(\"Scaffold a new agent: kohala.json, a working skill, and the local SDK\")\n .action((name: string) => {\n const nameCheck = manifestSchema.shape.name.safeParse(name);\n if (!nameCheck.success) {\n throw new Error(\n `\"${name}\" is not a valid agent name: ${nameCheck.error.issues[0]?.message ?? \"invalid\"}`,\n );\n }\n const targetDir = path.resolve(process.cwd(), name);\n if (fs.existsSync(targetDir)) {\n throw new Error(`${targetDir} already exists — pick a new name or remove the directory.`);\n }\n copyTemplates(templatesDir(), targetDir, name);\n console.log(pc.green(`Created agent \"${name}\" in ${targetDir}`));\n console.log(\"\");\n console.log(\"Next steps:\");\n console.log(pc.cyan(` kohala validate ${name}`));\n console.log(pc.cyan(` kohala run ${name} --local`));\n console.log(pc.cyan(` kohala trace ${name}`));\n });\n}\n","import { z } from \"zod\";\n\n/**\n * Zod schema for `kohala.json` — the agent manifest.\n *\n * This is the devkit's half of the compatibility contract with the hosted\n * Kohala platform. Every field here maps 1:1 onto a platform field:\n *\n * | Manifest field | Platform field |\n * | -------------------- | ------------------------ |\n * | `name` | agent name (deploy is idempotent on name) |\n * | `charter` | `agentCharter` |\n * | `toolAllowlist` | `agentToolAllowlist` |\n * | `runtimeMode` | `agentRuntimeMode` |\n * | `skills` | `agentSkills` |\n * | `schedule` | `agentScheduleCron` |\n * | `caps.perRunTokens` | `agentPerRunTokenCap` |\n * | `caps.perDayTokens` | `agentPerDayTokenCap` |\n * | `caps.billingTokens` | `agentBillingCapTokens` |\n * | `caps.billingPeriod` | `agentBillingCapPeriod` |\n * | `validators` | agent validators |\n *\n * Do not rename fields here without a matching platform change — the whole\n * point of the devkit is that a local agent round-trips losslessly.\n */\n\n/** Billing periods accepted by the platform for `agentBillingCapPeriod`. */\nexport const BILLING_PERIODS = [\"day\", \"week\", \"month\"] as const;\n\n/**\n * `shape` validator — the run output must exist and be at least `minBytes`\n * bytes long. This is the platform's cheapest sanity check: \"did the agent\n * actually produce something?\"\n */\nexport const shapeValidatorSchema = z\n .object({\n type: z.literal(\"shape\"),\n minBytes: z.number().int().nonnegative(),\n })\n .strict();\n\n/**\n * `freshness` validator — a referenced memory asset (by logical key) must be\n * newer than `maxAgeHours`. The platform uses this to catch agents that\n * \"succeed\" without actually refreshing their data.\n */\nexport const freshnessValidatorSchema = z\n .object({\n type: z.literal(\"freshness\"),\n /** Logical memory key of the asset that must be fresh. */\n asset: z.string().min(1),\n maxAgeHours: z.number().positive(),\n })\n .strict();\n\n/**\n * `invariant` validator — the run output must match (or must NOT match) a\n * regular expression. `mustMatch: false` inverts the check.\n */\nexport const invariantValidatorSchema = z\n .object({\n type: z.literal(\"invariant\"),\n /** JavaScript-flavored regular expression source (no delimiters). */\n pattern: z.string().min(1),\n /** When false, the output must NOT match the pattern. Defaults to true. */\n mustMatch: z.boolean().default(true),\n })\n .strict();\n\n/** All validator types supported by the platform, with identical names. */\nexport const validatorSchema = z.discriminatedUnion(\"type\", [\n shapeValidatorSchema,\n freshnessValidatorSchema,\n invariantValidatorSchema,\n]);\n\n/**\n * Token caps. The local emulator enforces these exactly like the hosted\n * platform (see emulator/), but never bills anything — token counts are for\n * cap enforcement and trace visibility only.\n */\nexport const capsSchema = z\n .object({\n /** Hard token ceiling for a single shift (platform: agentPerRunTokenCap). */\n perRunTokens: z.number().int().positive(),\n /** Cumulative token ceiling per UTC day (platform: agentPerDayTokenCap). */\n perDayTokens: z.number().int().positive(),\n /** Billing-period token cap (platform: agentBillingCapTokens). Ignored locally. */\n billingTokens: z.number().int().positive().optional(),\n /** Billing period for billingTokens (platform: agentBillingCapPeriod). */\n billingPeriod: z.enum(BILLING_PERIODS).optional(),\n })\n .strict()\n .refine((caps) => caps.billingTokens === undefined || caps.billingPeriod !== undefined, {\n message: \"caps.billingPeriod is required when caps.billingTokens is set\",\n path: [\"billingPeriod\"],\n });\n\n/** Agent names double as deploy identity and directory names — keep them tame. */\nconst nameSchema = z\n .string()\n .min(1)\n .max(64)\n .regex(\n /^[a-z0-9][a-z0-9_-]*$/i,\n \"must start with a letter or digit and contain only letters, digits, '-' and '_'\",\n );\n\n/** Full manifest schema for kohala.json. */\nexport const manifestSchema = z\n .object({\n name: nameSchema,\n /** The agent's mission text (platform: agentCharter). */\n charter: z.string().min(1),\n /**\n * Tools the agent may call, e.g. [\"s3.put\", \"http.post_json\"].\n * Everything not on this list is denied loudly at runtime.\n */\n toolAllowlist: z.array(z.string().min(1)).default([]),\n /**\n * \"wrap\" — execute the skill script directly and validate its output.\n * \"llm\" — run a real tool-use loop against the developer's own LLM key.\n */\n runtimeMode: z.enum([\"wrap\", \"llm\"]),\n /** Map of skill name -> script filename, e.g. {\"collect\": \"main.py\"}. */\n skills: z.record(z.string().min(1), z.string().min(1)).default({}),\n /** Cron expression. Used only on deploy; local runs are always manual. */\n schedule: z.string().min(1).optional(),\n caps: capsSchema,\n validators: z.array(validatorSchema).default([]),\n })\n .strict();\n\n/** A parsed, validated kohala.json. */\nexport type AgentManifest = z.infer<typeof manifestSchema>;\n/** A single validator entry. */\nexport type AgentValidator = z.infer<typeof validatorSchema>;\n/** Token caps block. */\nexport type AgentCaps = z.infer<typeof capsSchema>;\n","import path from \"node:path\";\nimport type { Command } from \"commander\";\nimport pc from \"picocolors\";\nimport { loadManifest, ManifestError } from \"../manifest/load.js\";\nimport { unknownToolIds } from \"../manifest/known-tools.js\";\n\n/**\n * `kohala validate <agent>` — load and validate the agent's kohala.json,\n * printing every problem with a fix hint. Exit code 1 on any problem.\n */\nexport function registerValidateCommand(program: Command): void {\n program\n .command(\"validate\")\n .argument(\"<agent>\", \"agent directory (containing kohala.json)\")\n .option(\n \"--allow-unknown-tools\",\n \"do not fail on tool ids missing from the bundled catalog snapshot\",\n )\n .description(\"Validate an agent's kohala.json and print precise errors\")\n .action((agent: string, options: { allowUnknownTools?: boolean }) => {\n const agentDir = path.resolve(process.cwd(), agent);\n try {\n const manifest = loadManifest(agentDir);\n // Catch typo'd / unknown tool ids offline, mirroring the server-side\n // deploy gate (which enforces the live catalog authoritatively).\n const unknown = unknownToolIds(manifest.toolAllowlist);\n if (unknown.length > 0) {\n const msg =\n `toolAllowlist contains tool id(s) not in the Kohala tool catalog: ` +\n unknown.join(\", \");\n if (options.allowUnknownTools) {\n console.warn(pc.yellow(`warning: ${msg}`));\n } else {\n console.error(pc.red(msg));\n console.error(\n pc.dim(\n \" If these are new platform tools the bundled snapshot doesn't know yet, re-run with --allow-unknown-tools (the deploy endpoint will still verify against the live catalog).\",\n ),\n );\n process.exitCode = 1;\n return;\n }\n }\n console.log(pc.green(`kohala.json for \"${manifest.name}\" is valid.`));\n console.log(\n pc.dim(\n ` runtimeMode=${manifest.runtimeMode} skills=${Object.keys(manifest.skills).length} ` +\n `validators=${manifest.validators.length} allowlist=[${manifest.toolAllowlist.join(\", \")}]`,\n ),\n );\n } catch (error) {\n if (error instanceof ManifestError) {\n console.error(pc.red(error.message));\n for (const problem of error.problems) {\n console.error(pc.red(` • ${problem}`));\n }\n process.exitCode = 1;\n return;\n }\n throw error;\n }\n });\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport type { ZodError, ZodIssue } from \"zod\";\nimport { manifestSchema, type AgentManifest } from \"./schema.js\";\n\n/** Error thrown when a kohala.json cannot be read, parsed, or validated. */\nexport class ManifestError extends Error {\n /** One human-readable problem per line, each with a fix hint when we have one. */\n readonly problems: string[];\n\n constructor(message: string, problems: string[] = []) {\n super(message);\n this.name = \"ManifestError\";\n this.problems = problems;\n }\n}\n\n/**\n * Fix hints keyed by the top-level manifest field an issue occurred under.\n * These show up next to validation errors so a broken manifest is\n * self-explanatory without opening the docs.\n */\nconst FIELD_HINTS: Record<string, string> = {\n name: 'use a short identifier like \"my-agent\" (letters, digits, \"-\", \"_\")',\n charter: \"write the agent's mission as a non-empty string\",\n toolAllowlist: 'list allowed tool names, e.g. [\"s3.put\", \"http.post_json\"]',\n runtimeMode: 'must be \"wrap\" (script wrapper) or \"llm\" (tool-use loop)',\n skills: 'map skill name to script filename, e.g. {\"collect\": \"main.py\"}',\n schedule: 'use a cron expression like \"0 9 * * *\" (only used on deploy)',\n caps: \"set caps.perRunTokens and caps.perDayTokens as positive integers\",\n validators: 'each validator needs a \"type\" of \"shape\", \"freshness\" or \"invariant\"',\n};\n\n/** Turn one Zod issue into a \"path: message (hint: ...)\" line. */\nfunction formatIssue(issue: ZodIssue): string {\n const issuePath = issue.path.length > 0 ? issue.path.join(\".\") : \"(root)\";\n const topLevelField = String(issue.path[0] ?? \"\");\n const hint = FIELD_HINTS[topLevelField];\n const hintSuffix = hint ? ` (hint: ${hint})` : \"\";\n return `${issuePath}: ${issue.message}${hintSuffix}`;\n}\n\n/** Format a full ZodError into per-issue problem lines. */\nexport function formatManifestIssues(error: ZodError): string[] {\n return error.issues.map(formatIssue);\n}\n\n/** Absolute path of the kohala.json inside an agent directory. */\nexport function manifestPath(agentDir: string): string {\n return path.join(agentDir, \"kohala.json\");\n}\n\n/**\n * Load and validate the kohala.json inside `agentDir`.\n *\n * Fails loudly with a ManifestError that lists every problem plus a fix hint —\n * never returns a partially-valid manifest.\n */\nexport function loadManifest(agentDir: string): AgentManifest {\n const filePath = manifestPath(agentDir);\n if (!fs.existsSync(filePath)) {\n throw new ManifestError(\n `No kohala.json found at ${filePath}`,\n [`create one with: kohala init ${path.basename(agentDir) || \"<name>\"}`],\n );\n }\n\n let raw: string;\n try {\n raw = fs.readFileSync(filePath, \"utf8\");\n } catch (error) {\n throw new ManifestError(`Could not read ${filePath}: ${(error as Error).message}`);\n }\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch (error) {\n throw new ManifestError(`${filePath} is not valid JSON: ${(error as Error).message}`, [\n \"check for trailing commas or missing quotes\",\n ]);\n }\n\n const result = manifestSchema.safeParse(parsed);\n if (!result.success) {\n throw new ManifestError(`${filePath} failed validation`, formatManifestIssues(result.error));\n }\n return result.data;\n}\n","/**\n * Snapshot of the Kohala platform tool catalog (tool ids only), used by\n * `kohala validate` to catch unknown/typo tool ids OFFLINE before deploy.\n * The server-side deploy endpoint enforces the live catalog authoritatively;\n * this list is a best-effort snapshot and may lag new platform tools —\n * pass --allow-unknown-tools to bypass when the snapshot is stale.\n * Snapshot date: 2026-08-10.\n */\nexport const KNOWN_TOOL_IDS: ReadonlySet<string> = new Set([\n \"http.get\",\n \"http.brightdata\",\n \"run_python_script\",\n \"web.search\",\n \"image.generate\",\n \"code.run\",\n \"s3.put\",\n \"koan.publish\",\n \"report.publish\",\n \"email.send\",\n \"send_email\",\n \"email.user_send\",\n \"email.user_inbox\",\n \"calendar.user_events\",\n \"calendar.user_create_event\",\n \"whatsapp.user_send\",\n \"whatsapp.user_inbox\",\n \"linkedin.user_post\",\n \"linkedin.user_profile\",\n \"linkedin.org_posts\",\n \"linkedin.org_stats\",\n \"validate_output\",\n \"html.parse\",\n \"json.parse\",\n \"csv.parse\",\n \"canvas.message\",\n \"canvas.request_approval\",\n \"odoo.search_read\",\n \"odoo.read\",\n \"odoo.read_group\",\n \"odoo.create\",\n \"odoo.write\",\n \"odoo.unlink\",\n \"odoo.call_method\",\n \"odoo.message_post\",\n \"odoo.attachments.upload\",\n \"aftership.create_tracking\",\n \"aftership.get_tracking\",\n \"aftership.list_trackings\",\n \"aftership.update_tracking\",\n \"aftership.delete_tracking\",\n \"aftership.detect_courier\",\n \"fedex.track\",\n \"ups.track\",\n \"era5.point_history\",\n \"noaa.forecast\",\n \"noaa.alerts\",\n \"airlabs.flight\",\n \"airlabs.schedules\",\n \"adsb.aircraft_near\",\n \"adsb.by_callsign\",\n \"aftership.list_couriers\",\n \"ga.run_report\",\n \"ga.realtime_report\",\n \"ga.get_metadata\",\n \"ga.list_properties\",\n \"epicor.query\",\n \"epicor.list\",\n \"epicor.get\",\n \"epicor.create\",\n \"epicor.update\",\n \"epicor.call_method\",\n \"ideogram.generate\",\n \"ideogram.edit\",\n \"ideogram.remix\",\n \"ideogram.reframe\",\n \"ideogram.replace_background\",\n \"ideogram.upscale\",\n \"ideogram.describe\",\n \"elevenlabs.text_to_speech\",\n \"elevenlabs.speech_to_text\",\n \"elevenlabs.speech_to_speech\",\n \"elevenlabs.sound_effects\",\n \"elevenlabs.voice_isolator\",\n \"elevenlabs.music\",\n \"elevenlabs.dubbing\",\n \"elevenlabs.dubbing_result\",\n \"elevenlabs.voice_design\",\n \"elevenlabs.list_voices\",\n \"video.generate_social\",\n \"video.generate_cinematic\",\n \"video.generate_avatar\",\n \"video.status\",\n \"extract.fields\",\n \"extract.receipt\",\n \"extract.financial\",\n \"extract.legal\",\n \"extract.product_spec\",\n \"extract.menu\",\n \"extract.evaluate\",\n \"memory.search\",\n \"memory.remember\",\n \"http.post_json\",\n \"s3.list\",\n \"s3.get\",\n \"s3.delete\",\n \"feed.fetch\",\n \"text.diff\",\n \"data.diff\",\n \"pinecone.upsert\",\n \"pinecone.query\",\n \"pinecone.fetch\",\n \"pinecone.delete\",\n \"llm.complete\",\n \"pdf.extract\",\n \"geocode\",\n \"slack.message\",\n \"discord.message\",\n \"schedule.next_run\",\n \"schedule.last_run\",\n \"metrics.record\",\n \"vector.embed\",\n \"sms.send\",\n \"push.send\",\n \"webhook.post\",\n \"notify.send\",\n \"agent.handoff\",\n \"bus.publish\",\n \"bus.subscribe\",\n \"bus.list_subscriptions\",\n \"bus.unsubscribe\",\n \"invoice.record\",\n \"invoice.generate\",\n \"invoice.modify\",\n \"invoice.list\",\n \"invoice.publish_koan\",\n \"invoice.ap_run\",\n \"invoice.ap_sweep\",\n \"invoice.ar_sweep\",\n \"invoice.ar_draft\",\n \"invoice.send\",\n \"invoice.review\",\n \"invoice.calibrate\",\n \"invoice.settings\",\n \"invoice.status\",\n \"sales_agreement.record\",\n \"sales_agreement.review\",\n \"sales_agreement.list\",\n \"sales_agreement.publish_koan\",\n \"customers.list\",\n \"customers.add\",\n \"customers.get_brand_profile\",\n \"secrets.get\",\n \"secrets.set\",\n \"secrets.list\",\n \"secrets.delete\",\n \"aws.ec2_list\",\n \"aws.ec2_start\",\n \"aws.ec2_stop\",\n \"aws.s3_list\",\n \"aws.lambda_list\",\n \"aws.lambda_invoke\",\n \"aws.cloudwatch_alarms\",\n \"aws.cost_summary\",\n \"aws.rds_list\",\n \"aws.bedrock_models\",\n \"aws.grafana_list\",\n \"googleads.list_accounts\",\n \"googleads.search\",\n \"googleads.campaign_performance\",\n \"googleads.ad_group_performance\",\n \"googleads.keyword_performance\",\n \"googleads.budget_summary\",\n \"calendar.generate\",\n \"content.analyze\",\n \"finance.ar.summary\",\n \"finance.ar_aging\",\n \"finance.ar_pastdue_report\",\n \"finance.ar_overdue_notify\",\n \"finance.ap.summary\",\n \"finance.ap_aging\",\n \"finance.reporting.summary\",\n \"finance.trial_balance\",\n \"sales.pipeline.summary\",\n \"sales.pipeline_read\",\n \"inventory.stock.summary\",\n \"inventory.procurement_read\",\n \"slack.list_channels\",\n \"slack.post_message\",\n \"notion.search\",\n \"notion.append_page\",\n \"hubspot.list_engagements\",\n \"hubspot.log_call\",\n \"hubspot.update_deal\",\n \"linear.create_issue\",\n \"asana.create_task\",\n \"airtable.list_records\",\n \"airtable.create_record\",\n \"pandadoc.create_document\",\n \"canva.create_design\",\n \"canva.autofill_deck\",\n \"zapier.trigger_zap\",\n \"commitments.recall\",\n \"workspacesync.fanout\",\n \"dealdesk.draft\",\n \"pricing.catalog_list\",\n \"pricing.assumptions_list\",\n \"pricing.benchmark_list\",\n \"pricing.single_use_list\",\n \"pricing.reusable_tco_list\",\n \"pricing.monitoring_list\",\n \"pricing.simulate_save\"\n]);\n\n/** Return the declared tool ids that are not in the snapshot catalog. */\nexport function unknownToolIds(tools: readonly string[]): string[] {\n return tools.filter((t) => !KNOWN_TOOL_IDS.has(t));\n}\n","import path from \"node:path\";\nimport type { Command } from \"commander\";\nimport pc from \"picocolors\";\nimport { loadManifest } from \"../manifest/load.js\";\nimport { createMemoryStore } from \"../memory/create.js\";\nimport { runShift } from \"../emulator/runner.js\";\n\n/**\n * `kohala run <agent> --local` — run one shift against the local emulator.\n *\n * Local runs are always manual (the manifest's schedule only matters on\n * deploy). The emulator enforces admission, allowlist, caps, and validators\n * exactly like the hosted platform, but never meters anything.\n */\nexport function registerRunCommand(program: Command): void {\n program\n .command(\"run\")\n .argument(\"<agent>\", \"agent directory (containing kohala.json)\")\n .option(\"--local\", \"run against the local emulator (required for now)\")\n .option(\"--skill <name>\", \"which skill to run (defaults to the only skill)\")\n .option(\n \"--backend <backend>\",\n \"memory backend for this run: file | postgres\",\n \"file\",\n )\n .option(\"--url <url>\", \"postgres connection string (or set DATABASE_URL)\")\n .description(\"Run a shift against the local emulator\")\n .action(\n async (\n agent: string,\n options: { local?: boolean; skill?: string; backend: string; url?: string },\n ) => {\n if (!options.local) {\n throw new Error(\n \"Hosted runs start from the platform, not the CLI. Use --local to run against the local emulator, or `kohala deploy --run` to trigger a hosted run.\",\n );\n }\n if (options.backend !== \"file\" && options.backend !== \"postgres\") {\n throw new Error(`Unknown backend \"${options.backend}\" — use \"file\" or \"postgres\".`);\n }\n const rootDir = process.cwd();\n const agentDir = path.resolve(rootDir, agent);\n const manifest = loadManifest(agentDir);\n const store = await createMemoryStore({\n backend: options.backend,\n agent: manifest.name,\n rootDir,\n url: options.url ?? process.env.DATABASE_URL,\n });\n\n try {\n console.log(\n pc.cyan(`Running shift for \"${manifest.name}\" (${manifest.runtimeMode} mode)...`),\n );\n const result = await runShift({ rootDir, agentDir, manifest, store, skill: options.skill });\n\n console.log(\"\");\n if (result.status === \"succeeded\") {\n console.log(pc.green(`✔ Shift ${result.runId} succeeded`));\n } else {\n console.log(pc.red(`✘ Shift ${result.runId} ${result.status.replace(/_/g, \" \")}`));\n if (result.detail) console.log(pc.red(` ${result.detail}`));\n }\n console.log(pc.dim(` tokens used: ${result.totalTokens} (counted, never billed)`));\n for (const validator of result.validatorResults) {\n const mark = validator.passed ? pc.green(\"passed\") : pc.red(\"failed\");\n console.log(pc.dim(` validator ${validator.validator}: `) + mark + pc.dim(` — ${validator.detail}`));\n }\n if (result.output.trim() !== \"\") {\n console.log(\"\");\n console.log(pc.dim(\"── output ─────────────────────────────\"));\n console.log(result.output.trim());\n }\n console.log(\"\");\n console.log(pc.dim(`Full audit trail: kohala trace ${agent}`));\n if (result.status !== \"succeeded\") {\n process.exitCode = 1;\n }\n } finally {\n await store.close();\n }\n },\n );\n}\n","import crypto from \"node:crypto\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport {\n DEFAULT_CATEGORY,\n DEFAULT_LIST_LIMIT,\n type MemoryAsset,\n type MemoryRecord,\n type MemoryStore,\n} from \"./store.js\";\nimport { atomicWriteFile, withFileLock } from \"../util/lock.js\";\n\n/** Shape of the on-disk JSON index file. */\ninterface IndexFile {\n records: MemoryRecord[];\n}\n\n/** Directory holding one agent's file-backed memory. */\nexport function memoryDirFor(rootDir: string, agent: string): string {\n return path.join(rootDir, \".kohala\", \"memory\", agent);\n}\n\n/**\n * File-backed memory store — the default backend.\n *\n * Layout (per agent, mirroring the platform's per-agent asset tracking):\n *\n * .kohala/memory/<agent>/index.json — the asset index (key, category,\n * timestamps, active flag)\n * .kohala/memory/<agent>/bodies/<id> — raw body bytes, one file per asset\n *\n * The index is small and rewritten atomically on every mutation (write to a\n * temp file, then rename) so a crash can't leave a half-written index.\n */\nexport class FileMemoryStore implements MemoryStore {\n private readonly dir: string;\n private readonly indexPath: string;\n private readonly bodiesDir: string;\n\n constructor(rootDir: string, agent: string) {\n this.dir = memoryDirFor(rootDir, agent);\n this.indexPath = path.join(this.dir, \"index.json\");\n this.bodiesDir = path.join(this.dir, \"bodies\");\n fs.mkdirSync(this.bodiesDir, { recursive: true });\n }\n\n private readIndex(): IndexFile {\n if (!fs.existsSync(this.indexPath)) {\n return { records: [] };\n }\n const raw = fs.readFileSync(this.indexPath, \"utf8\");\n return JSON.parse(raw) as IndexFile;\n }\n\n private writeIndex(index: IndexFile): void {\n atomicWriteFile(this.indexPath, JSON.stringify(index, null, 2));\n }\n\n private bodyPath(id: string): string {\n return path.join(this.bodiesDir, id);\n }\n\n async put(key: string, body: Buffer, category: string = DEFAULT_CATEGORY): Promise<MemoryRecord> {\n // The index read-modify-write is guarded by an interprocess lock so a\n // concurrent run or MCP server can't clobber this update.\n return withFileLock(this.indexPath, () => {\n const index = this.readIndex();\n const now = new Date().toISOString();\n const existing = index.records.find((record) => record.active && record.key === key);\n\n if (existing) {\n // Logical keys are unique among active assets: overwrite in place.\n existing.category = category;\n existing.size = body.byteLength;\n existing.updatedAt = now;\n fs.writeFileSync(this.bodyPath(existing.id), body);\n this.writeIndex(index);\n return { ...existing };\n }\n\n const record: MemoryRecord = {\n id: crypto.randomUUID(),\n key,\n category,\n size: body.byteLength,\n createdAt: now,\n updatedAt: now,\n active: true,\n };\n fs.writeFileSync(this.bodyPath(record.id), body);\n index.records.push(record);\n this.writeIndex(index);\n return { ...record };\n });\n }\n\n async get(keyOrId: string): Promise<MemoryAsset | null> {\n const index = this.readIndex();\n // Platform resolution order: active logical key first, then record id.\n const record =\n index.records.find((entry) => entry.active && entry.key === keyOrId) ??\n index.records.find((entry) => entry.active && entry.id === keyOrId);\n if (!record) return null;\n const filePath = this.bodyPath(record.id);\n if (!fs.existsSync(filePath)) {\n throw new Error(\n `Memory index lists ${record.key} (${record.id}) but its body file is missing at ${filePath}`,\n );\n }\n return { record: { ...record }, body: fs.readFileSync(filePath) };\n }\n\n async list(prefix?: string, limit: number = DEFAULT_LIST_LIMIT): Promise<MemoryRecord[]> {\n const index = this.readIndex();\n return index.records\n .filter((record) => record.active && (prefix === undefined || record.key.startsWith(prefix)))\n .sort((a, b) => (a.updatedAt < b.updatedAt ? 1 : -1))\n .slice(0, limit)\n .map((record) => ({ ...record }));\n }\n\n async delete(keyOrId: string): Promise<MemoryRecord | null> {\n return withFileLock(this.indexPath, () => {\n const index = this.readIndex();\n const record =\n index.records.find((entry) => entry.active && entry.key === keyOrId) ??\n index.records.find((entry) => entry.active && entry.id === keyOrId);\n if (!record) return null;\n // Remove the body, deactivate the index entry (soft delete, like the platform).\n record.active = false;\n record.updatedAt = new Date().toISOString();\n const filePath = this.bodyPath(record.id);\n if (fs.existsSync(filePath)) {\n fs.unlinkSync(filePath);\n }\n this.writeIndex(index);\n return { ...record };\n });\n }\n\n async close(): Promise<void> {\n // Nothing to release for the file backend.\n }\n}\n","/**\n * The MemoryStore interface — the platform's memory surface, locally.\n *\n * Both the emulator (via the SDK RPC) and the MCP memory server sit on top of\n * this interface, so an agent sees identical memory semantics whether it is\n * talking to `kohala run --local`, `kohala memory serve`, or the hosted\n * platform:\n *\n * - `s3.put(key, body, category?)` — store under a logical key\n * - `s3.get(keyOrId)` — resolve by logical key first\n * - `s3.list(prefix?, limit?)` — list active assets for the agent\n * - `s3.delete(keyOrId)` — remove + deactivate\n */\n\n/** Index entry for one stored asset — mirrors how the platform tracks assets. */\nexport interface MemoryRecord {\n /** Stable unique id (UUID). `get`/`delete` accept this as a fallback to the key. */\n id: string;\n /** Logical key the agent chose, e.g. \"weather/latest\". */\n key: string;\n /** Asset category. Run results default to \"agentoutput\" on the platform. */\n category: string;\n /** Body size in bytes. */\n size: number;\n /** ISO-8601 creation time. */\n createdAt: string;\n /** ISO-8601 last-update time. */\n updatedAt: string;\n /** Deleted assets are deactivated, not erased from the index. */\n active: boolean;\n}\n\n/** Default category for run results, matching the platform. */\nexport const DEFAULT_CATEGORY = \"agentoutput\";\n\n/** Default `list` page size. */\nexport const DEFAULT_LIST_LIMIT = 100;\n\n/** A record plus its body, as returned by `get`. */\nexport interface MemoryAsset {\n record: MemoryRecord;\n body: Buffer;\n}\n\n/**\n * Storage backend contract. Implementations: FileMemoryStore (default) and\n * PostgresMemoryStore (optional, requires `pg`).\n */\nexport interface MemoryStore {\n /**\n * Store `body` under `key`. If an active record already exists for the key,\n * it is updated in place (same id, new body/category/updatedAt) — logical\n * keys are unique among active assets.\n */\n put(key: string, body: Buffer, category?: string): Promise<MemoryRecord>;\n\n /**\n * Fetch an asset. Resolution order matches the platform: active logical key\n * first, then record id. Returns null when nothing matches.\n */\n get(keyOrId: string): Promise<MemoryAsset | null>;\n\n /** List active assets, optionally filtered by key prefix, newest first. */\n list(prefix?: string, limit?: number): Promise<MemoryRecord[]>;\n\n /**\n * Remove + deactivate an asset: the body is deleted, the index entry stays\n * with `active: false` (mirroring the platform's soft-delete). Returns the\n * deactivated record, or null if nothing matched.\n */\n delete(keyOrId: string): Promise<MemoryRecord | null>;\n\n /** Release any underlying resources (DB connections, file handles). */\n close(): Promise<void>;\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\n\n/**\n * Minimal interprocess mutex built on atomic `mkdir`.\n *\n * The usage ledger and the file memory index are read-modify-write JSON\n * files that can be touched by overlapping processes (two `kohala run`s, or\n * `kohala memory serve` next to a run). `mkdir` is atomic on every platform\n * Node supports, so a lock directory gives us a portable mutex without any\n * dependencies.\n *\n * Locks are considered stale (crashed holder) after STALE_MS and are broken\n * loudly rather than waited on forever.\n */\n\nconst STALE_MS = 10_000;\nconst ACQUIRE_TIMEOUT_MS = 5_000;\nconst RETRY_DELAY_MS = 15;\n\nfunction sleep(ms: number): void {\n // Synchronous sleep keeps the locked sections synchronous (the callers are\n // sync fs code); Atomics.wait avoids burning CPU in the retry loop.\n const buffer = new SharedArrayBuffer(4);\n Atomics.wait(new Int32Array(buffer), 0, 0, ms);\n}\n\n/**\n * Run `fn` while holding an exclusive lock named after `filePath`.\n * Throws if the lock cannot be acquired within ACQUIRE_TIMEOUT_MS.\n */\nexport function withFileLock<T>(filePath: string, fn: () => T): T {\n const lockDir = `${filePath}.lock`;\n fs.mkdirSync(path.dirname(lockDir), { recursive: true });\n\n const deadline = Date.now() + ACQUIRE_TIMEOUT_MS;\n for (;;) {\n try {\n fs.mkdirSync(lockDir);\n break;\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== \"EEXIST\") throw error;\n // Break stale locks left behind by a crashed process.\n try {\n const age = Date.now() - fs.statSync(lockDir).mtimeMs;\n if (age > STALE_MS) {\n fs.rmdirSync(lockDir);\n continue;\n }\n } catch {\n // The holder released it between our checks — retry immediately.\n continue;\n }\n if (Date.now() > deadline) {\n throw new Error(\n `Timed out waiting for lock ${lockDir} — another kohala process is holding it. ` +\n `If no other process is running, delete the directory and retry.`,\n { cause: error },\n );\n }\n sleep(RETRY_DELAY_MS);\n }\n }\n\n try {\n return fn();\n } finally {\n try {\n fs.rmdirSync(lockDir);\n } catch {\n // Already removed (stale-broken by another waiter); nothing to do.\n }\n }\n}\n\n/** Atomically replace `filePath` with `content` (temp file + rename). */\nexport function atomicWriteFile(filePath: string, content: string): void {\n fs.mkdirSync(path.dirname(filePath), { recursive: true });\n const tempPath = `${filePath}.${process.pid}.tmp`;\n fs.writeFileSync(tempPath, content, \"utf8\");\n fs.renameSync(tempPath, filePath);\n}\n","import crypto from \"node:crypto\";\nimport {\n DEFAULT_CATEGORY,\n DEFAULT_LIST_LIMIT,\n type MemoryAsset,\n type MemoryRecord,\n type MemoryStore,\n} from \"./store.js\";\n\n/** Minimal structural type for the parts of `pg.Pool` we use. */\ninterface PgPoolLike {\n query(text: string, values?: unknown[]): Promise<{ rows: Record<string, unknown>[] }>;\n end(): Promise<void>;\n}\n\n/** One row of the kohala_memory table, as returned by pg. */\ninterface MemoryRow {\n id: string;\n key: string;\n category: string;\n body: Buffer | null;\n size: string | number;\n created_at: Date;\n updated_at: Date;\n active: boolean;\n}\n\nfunction rowToRecord(row: MemoryRow): MemoryRecord {\n return {\n id: row.id,\n key: row.key,\n category: row.category,\n size: Number(row.size),\n createdAt: new Date(row.created_at).toISOString(),\n updatedAt: new Date(row.updated_at).toISOString(),\n active: row.active,\n };\n}\n\n/**\n * Postgres-backed memory store.\n *\n * Design decision (documented per the build plan): the index AND the bodies\n * live in one table — bodies are stored as `bytea` in the same row. This\n * keeps the backend to a single table with no filesystem coupling, so any\n * plain Postgres URL works (no volume required).\n *\n * The table is created on first connect (idempotent migration). `pg` is an\n * optional peer dependency and is imported lazily so file-backend users never\n * need it installed.\n */\nexport class PostgresMemoryStore implements MemoryStore {\n private constructor(\n private readonly pool: PgPoolLike,\n private readonly agent: string,\n ) {}\n\n /** Connect, run the idempotent migration, and return a ready store. */\n static async connect(url: string, agent: string): Promise<PostgresMemoryStore> {\n let pgModule: typeof import(\"pg\");\n try {\n pgModule = await import(\"pg\");\n } catch {\n throw new Error(\n 'The postgres backend requires the optional \"pg\" package. Install it with: npm install pg',\n );\n }\n const PoolCtor = pgModule.default?.Pool ?? pgModule.Pool;\n const pool = new PoolCtor({ connectionString: url }) as unknown as PgPoolLike;\n\n // Idempotent migration on first connect — a single table holds the index\n // semantics from A.1 (key, category, timestamps, active flag) plus bodies.\n await pool.query(`\n CREATE TABLE IF NOT EXISTS kohala_memory (\n id UUID PRIMARY KEY,\n agent TEXT NOT NULL,\n key TEXT NOT NULL,\n category TEXT NOT NULL,\n body BYTEA,\n size BIGINT NOT NULL,\n created_at TIMESTAMPTZ NOT NULL,\n updated_at TIMESTAMPTZ NOT NULL,\n active BOOLEAN NOT NULL DEFAULT TRUE\n )\n `);\n await pool.query(`\n CREATE UNIQUE INDEX IF NOT EXISTS kohala_memory_active_key\n ON kohala_memory (agent, key) WHERE active\n `);\n\n return new PostgresMemoryStore(pool, agent);\n }\n\n async put(key: string, body: Buffer, category: string = DEFAULT_CATEGORY): Promise<MemoryRecord> {\n const now = new Date();\n const existing = await this.pool.query(\n \"SELECT * FROM kohala_memory WHERE agent = $1 AND key = $2 AND active\",\n [this.agent, key],\n );\n if (existing.rows.length > 0) {\n const row = existing.rows[0] as unknown as MemoryRow;\n const updated = await this.pool.query(\n `UPDATE kohala_memory SET category = $1, body = $2, size = $3, updated_at = $4\n WHERE id = $5 RETURNING *`,\n [category, body, body.byteLength, now, row.id],\n );\n return rowToRecord(updated.rows[0] as unknown as MemoryRow);\n }\n const inserted = await this.pool.query(\n `INSERT INTO kohala_memory (id, agent, key, category, body, size, created_at, updated_at, active)\n VALUES ($1, $2, $3, $4, $5, $6, $7, $7, TRUE) RETURNING *`,\n [crypto.randomUUID(), this.agent, key, category, body, body.byteLength, now],\n );\n return rowToRecord(inserted.rows[0] as unknown as MemoryRow);\n }\n\n async get(keyOrId: string): Promise<MemoryAsset | null> {\n // Platform resolution order: active logical key first, then record id.\n const byKey = await this.pool.query(\n \"SELECT * FROM kohala_memory WHERE agent = $1 AND key = $2 AND active\",\n [this.agent, keyOrId],\n );\n let row = byKey.rows[0] as unknown as MemoryRow | undefined;\n if (!row && isUuid(keyOrId)) {\n const byId = await this.pool.query(\n \"SELECT * FROM kohala_memory WHERE agent = $1 AND id = $2 AND active\",\n [this.agent, keyOrId],\n );\n row = byId.rows[0] as unknown as MemoryRow | undefined;\n }\n if (!row) return null;\n return { record: rowToRecord(row), body: row.body ?? Buffer.alloc(0) };\n }\n\n async list(prefix?: string, limit: number = DEFAULT_LIST_LIMIT): Promise<MemoryRecord[]> {\n const result = prefix\n ? await this.pool.query(\n `SELECT id, agent, key, category, NULL AS body, size, created_at, updated_at, active\n FROM kohala_memory WHERE agent = $1 AND active AND key LIKE $2 || '%'\n ORDER BY updated_at DESC LIMIT $3`,\n [this.agent, prefix, limit],\n )\n : await this.pool.query(\n `SELECT id, agent, key, category, NULL AS body, size, created_at, updated_at, active\n FROM kohala_memory WHERE agent = $1 AND active\n ORDER BY updated_at DESC LIMIT $2`,\n [this.agent, limit],\n );\n return result.rows.map((row) => rowToRecord(row as unknown as MemoryRow));\n }\n\n async delete(keyOrId: string): Promise<MemoryRecord | null> {\n const asset = await this.get(keyOrId);\n if (!asset) return null;\n // Remove the body, deactivate the row (soft delete, like the platform).\n const updated = await this.pool.query(\n `UPDATE kohala_memory SET active = FALSE, body = NULL, updated_at = $1\n WHERE id = $2 RETURNING *`,\n [new Date(), asset.record.id],\n );\n return rowToRecord(updated.rows[0] as unknown as MemoryRow);\n }\n\n async close(): Promise<void> {\n await this.pool.end();\n }\n}\n\n/** Loose UUID check so non-UUID keys never hit the uuid-typed id column. */\nfunction isUuid(value: string): boolean {\n return /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(value);\n}\n","import { FileMemoryStore } from \"./file.js\";\nimport { PostgresMemoryStore } from \"./postgres.js\";\nimport type { MemoryStore } from \"./store.js\";\n\n/** Supported backend names for `kohala memory serve --backend <name>`. */\nexport type MemoryBackend = \"file\" | \"postgres\";\n\n/** Options for creating a memory store for one agent. */\nexport interface CreateMemoryStoreOptions {\n backend: MemoryBackend;\n /** Agent name — memory is always scoped per agent, like on the platform. */\n agent: string;\n /** Workspace root for the file backend (defaults to process.cwd()). */\n rootDir?: string;\n /** Postgres connection string (required for the postgres backend). */\n url?: string;\n}\n\n/**\n * Create a MemoryStore for the requested backend.\n *\n * Fails loudly when the postgres backend is requested without a URL — there\n * is no silent fallback to the file backend.\n */\nexport async function createMemoryStore(options: CreateMemoryStoreOptions): Promise<MemoryStore> {\n if (options.backend === \"file\") {\n return new FileMemoryStore(options.rootDir ?? process.cwd(), options.agent);\n }\n if (!options.url) {\n throw new Error(\n \"The postgres backend needs a connection string. Pass --url or set DATABASE_URL.\",\n );\n }\n return PostgresMemoryStore.connect(options.url, options.agent);\n}\n","import crypto from \"node:crypto\";\nimport path from \"node:path\";\nimport { execa, ExecaError } from \"execa\";\nimport type { AgentManifest } from \"../manifest/schema.js\";\nimport type { MemoryStore } from \"../memory/store.js\";\nimport { TraceWriter } from \"../trace/writer.js\";\nimport type { RunStatus } from \"../trace/events.js\";\nimport { CapExceededError, TokenMeter } from \"./tokens.js\";\nimport { evaluateValidators, type ValidatorResult } from \"./validators.js\";\nimport { startSdkRpcServer } from \"../sdk/rpc.js\";\nimport { runLlmShift } from \"./llm-mode.js\";\nimport { findPython } from \"./python.js\";\n\n/**\n * The shift runner — executes one agent shift with the platform's exact\n * enforcement order (A.2):\n *\n * 1. Admission (per-day token cap, refused BEFORE any work)\n * 2. Tool allowlist (enforced on every tool call via the dispatcher)\n * 3. Per-run cap (projected before each LLM turn)\n * 4. Validators, with a bounded repair loop (max 2 attempts, platform default)\n *\n * Tokens are counted for cap enforcement and shown in the trace, but nothing\n * is ever charged — that is the \"no metering\" promise.\n */\n\n/** Platform default: at most 2 repair attempts after a validator failure. */\nexport const MAX_REPAIR_ATTEMPTS = 2;\n\n/** Inputs for one shift. */\nexport interface RunShiftOptions {\n /** Workspace root (where .kohala/ lives). */\n rootDir: string;\n /** The agent's directory (contains kohala.json and skills/). */\n agentDir: string;\n manifest: AgentManifest;\n store: MemoryStore;\n /** Skill to run; defaults to the only skill when there is exactly one. */\n skill?: string;\n}\n\n/** Outcome of one shift. */\nexport interface ShiftResult {\n runId: string;\n status: RunStatus;\n /** The run output (script stdout in wrap mode; final text in llm mode). */\n output: string;\n totalTokens: number;\n validatorResults: ValidatorResult[];\n /** Human-readable failure/abort detail, if any. */\n detail?: string;\n}\n\n/** Resolve which skill a shift should execute, failing loudly on ambiguity. */\nexport function resolveSkill(manifest: AgentManifest, requested?: string): [string, string] {\n const entries = Object.entries(manifest.skills);\n if (entries.length === 0) {\n throw new Error(`Agent \"${manifest.name}\" has no skills in kohala.json`);\n }\n if (requested) {\n const script = manifest.skills[requested];\n if (!script) {\n throw new Error(\n `Skill \"${requested}\" not found. Available skills: ${entries.map(([name]) => name).join(\", \")}`,\n );\n }\n return [requested, script];\n }\n if (entries.length === 1) {\n return entries[0] as [string, string];\n }\n throw new Error(\n `Agent \"${manifest.name}\" has ${entries.length} skills — pick one with --skill <name> ` +\n `(${entries.map(([name]) => name).join(\", \")})`,\n );\n}\n\n/** Run one shift end-to-end. Never throws for run-level failures — the result carries the status. */\nexport async function runShift(options: RunShiftOptions): Promise<ShiftResult> {\n const { rootDir, agentDir, manifest, store } = options;\n const runId = `run_${Date.now().toString(36)}_${crypto.randomBytes(3).toString(\"hex\")}`;\n const trace = new TraceWriter(rootDir, manifest.name);\n const meter = new TokenMeter(rootDir, manifest.name, manifest.caps);\n const startedAt = Date.now();\n const [skillName, scriptFilename] = resolveSkill(manifest, options.skill);\n\n const finish = (\n status: RunStatus,\n output: string,\n validatorResults: ValidatorResult[],\n detail?: string,\n ): ShiftResult => {\n trace.append({\n ts: new Date().toISOString(),\n runId,\n agent: manifest.name,\n type: \"run_finished\",\n status,\n totalTokens: meter.runTotal,\n durationMs: Date.now() - startedAt,\n ...(detail ? { detail } : {}),\n });\n return { runId, status, output, totalTokens: meter.runTotal, validatorResults, detail };\n };\n\n // 1. Admission: refuse the shift before any work if the per-day cap is spent.\n try {\n meter.admitRun();\n } catch (error) {\n if (error instanceof CapExceededError) {\n return finish(\"aborted_per_day_token_cap\", \"\", [], error.message);\n }\n throw error;\n }\n\n trace.append({\n ts: new Date().toISOString(),\n runId,\n agent: manifest.name,\n type: \"run_started\",\n runtimeMode: manifest.runtimeMode,\n skill: skillName,\n scriptFilename,\n });\n\n const context = { manifest, store, trace, meter, runId };\n\n // llm mode: a real tool-use loop against the developer's own key, with the\n // same bounded validator repair loop as wrap mode (A.2 step 4).\n if (manifest.runtimeMode === \"llm\") {\n try {\n let repairReason = \"\";\n for (let attempt = 0; attempt <= MAX_REPAIR_ATTEMPTS; attempt += 1) {\n if (attempt > 0) {\n trace.append({\n ts: new Date().toISOString(),\n runId,\n agent: manifest.name,\n type: \"repair_attempt\",\n attempt,\n maxAttempts: MAX_REPAIR_ATTEMPTS,\n reason: repairReason,\n });\n }\n const output = await runLlmShift(\n context,\n skillName,\n path.join(agentDir, \"skills\", scriptFilename),\n attempt > 0 ? repairReason : undefined,\n );\n const validatorResults = await evaluateValidators(manifest.validators, output, store);\n recordValidatorResults(trace, runId, manifest.name, validatorResults);\n const failures = validatorResults.filter((result) => !result.passed);\n if (failures.length === 0) {\n return finish(\"succeeded\", output, validatorResults);\n }\n repairReason = failures\n .map((failure) => `${failure.validator}: ${failure.detail}`)\n .join(\"; \");\n if (attempt === MAX_REPAIR_ATTEMPTS) {\n return finish(\n \"failed\",\n output,\n validatorResults,\n `validators failed after ${MAX_REPAIR_ATTEMPTS} repair attempts: ${repairReason}`,\n );\n }\n }\n throw new Error(\"repair loop exited without a result\");\n } catch (error) {\n if (error instanceof CapExceededError || meter.abortedWith) {\n const cap = (error instanceof CapExceededError ? error : meter.abortedWith) as CapExceededError;\n const status: RunStatus =\n cap.code === \"PER_RUN_TOKEN_CAP\" ? \"aborted_per_run_token_cap\" : \"aborted_per_day_token_cap\";\n return finish(status, \"\", [], cap.message);\n }\n return finish(\"error\", \"\", [], (error as Error).message);\n }\n }\n\n // wrap mode: execute the skill script directly and validate its output.\n const rpc = await startSdkRpcServer(context);\n try {\n let repairReason = \"\";\n for (let attempt = 0; attempt <= MAX_REPAIR_ATTEMPTS; attempt += 1) {\n if (attempt > 0) {\n trace.append({\n ts: new Date().toISOString(),\n runId,\n agent: manifest.name,\n type: \"repair_attempt\",\n attempt,\n maxAttempts: MAX_REPAIR_ATTEMPTS,\n reason: repairReason,\n });\n }\n\n const execution = await executeScript({\n agentDir,\n scriptFilename,\n rpcUrl: rpc.url,\n manifest,\n runId,\n repairAttempt: attempt,\n repairFeedback: repairReason,\n });\n\n if (!execution.ok) {\n // A cap abort inside the script (llm.complete denied) surfaces here.\n if (meter.abortedWith?.code === \"PER_RUN_TOKEN_CAP\") {\n return finish(\"aborted_per_run_token_cap\", execution.stdout, [], meter.abortedWith.message);\n }\n return finish(\"error\", execution.stdout, [], execution.errorDetail);\n }\n\n const validatorResults = await evaluateValidators(\n manifest.validators,\n execution.stdout,\n store,\n );\n recordValidatorResults(trace, runId, manifest.name, validatorResults);\n\n const failures = validatorResults.filter((result) => !result.passed);\n if (failures.length === 0) {\n return finish(\"succeeded\", execution.stdout, validatorResults);\n }\n repairReason = failures.map((failure) => `${failure.validator}: ${failure.detail}`).join(\"; \");\n if (attempt === MAX_REPAIR_ATTEMPTS) {\n return finish(\"failed\", execution.stdout, validatorResults, `validators failed after ${MAX_REPAIR_ATTEMPTS} repair attempts: ${repairReason}`);\n }\n }\n // Unreachable: the loop always returns.\n throw new Error(\"repair loop exited without a result\");\n } finally {\n await rpc.close();\n }\n}\n\nfunction recordValidatorResults(\n trace: TraceWriter,\n runId: string,\n agent: string,\n results: ValidatorResult[],\n): void {\n for (const result of results) {\n trace.append({\n ts: new Date().toISOString(),\n runId,\n agent,\n type: \"validator_result\",\n validator: result.validator,\n passed: result.passed,\n detail: result.detail,\n });\n }\n}\n\ninterface ExecuteScriptOptions {\n agentDir: string;\n scriptFilename: string;\n rpcUrl: string;\n manifest: AgentManifest;\n runId: string;\n repairAttempt: number;\n repairFeedback: string;\n}\n\ninterface ScriptExecution {\n ok: boolean;\n stdout: string;\n errorDetail?: string;\n}\n\n/**\n * Execute a skill script with the SDK environment. The script's stdout is the\n * run output that validators evaluate — stderr is passed through for\n * debugging and never treated as output.\n */\nasync function executeScript(options: ExecuteScriptOptions): Promise<ScriptExecution> {\n const python = await findPython();\n const scriptPath = path.join(options.agentDir, \"skills\", options.scriptFilename);\n try {\n const result = await execa(python, [scriptPath], {\n cwd: options.agentDir,\n env: {\n KOHALA_RPC_URL: options.rpcUrl,\n KOHALA_AGENT: options.manifest.name,\n KOHALA_RUN_ID: options.runId,\n KOHALA_REPAIR_ATTEMPT: String(options.repairAttempt),\n KOHALA_VALIDATOR_FEEDBACK: options.repairFeedback,\n },\n // Surface the script's stderr live so developers see their own logging.\n stderr: \"inherit\",\n reject: false,\n timeout: 10 * 60 * 1000,\n });\n if (result.exitCode !== 0) {\n return {\n ok: false,\n stdout: result.stdout ?? \"\",\n errorDetail: `script ${options.scriptFilename} exited with code ${result.exitCode}`,\n };\n }\n return { ok: true, stdout: result.stdout ?? \"\" };\n } catch (error) {\n const message = error instanceof ExecaError ? error.message : (error as Error).message;\n return { ok: false, stdout: \"\", errorDetail: message };\n }\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport type { TraceEvent } from \"./events.js\";\n\n/** Absolute path of an agent's JSONL trace file under the workspace root. */\nexport function traceFilePath(rootDir: string, agent: string): string {\n return path.join(rootDir, \".kohala\", \"trace\", `${agent}.jsonl`);\n}\n\n/**\n * Appends structured events to `.kohala/trace/<agent>.jsonl`.\n *\n * Writes are synchronous appends — one JSON object per line — so a crash\n * mid-run still leaves a readable audit trail up to the crash point,\n * mirroring the platform's append-only run records.\n */\nexport class TraceWriter {\n private readonly filePath: string;\n\n constructor(rootDir: string, agent: string) {\n this.filePath = traceFilePath(rootDir, agent);\n fs.mkdirSync(path.dirname(this.filePath), { recursive: true });\n }\n\n /** Append one event as a JSONL line. */\n append(event: TraceEvent): void {\n fs.appendFileSync(this.filePath, `${JSON.stringify(event)}\\n`, \"utf8\");\n }\n\n /** The file this writer appends to (used by `kohala trace`). */\n get file(): string {\n return this.filePath;\n }\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport type { AgentCaps } from \"../manifest/schema.js\";\nimport { atomicWriteFile, withFileLock } from \"../util/lock.js\";\n\n/**\n * Token accounting without billing.\n *\n * The emulator counts tokens exactly like the platform does for cap\n * enforcement — but it never charges anything. That is the devkit's\n * \"no metering\" promise: numbers show up in the trace, money never does.\n */\n\n/** Rough token estimate: ~4 characters per token, the platform's heuristic. */\nexport function estimateTokens(text: string): number {\n return Math.ceil(text.length / 4);\n}\n\n/** Current UTC day as YYYY-MM-DD — per-day caps reset on UTC midnight. */\nexport function utcDay(now: Date = new Date()): string {\n return now.toISOString().slice(0, 10);\n}\n\n/** Shape of the on-disk usage ledger (.kohala/usage/<agent>.json). */\ninterface UsageFile {\n /** Map of UTC day -> total tokens consumed by local runs that day. */\n days: Record<string, number>;\n}\n\nfunction usageFilePath(rootDir: string, agent: string): string {\n return path.join(rootDir, \".kohala\", \"usage\", `${agent}.json`);\n}\n\n/** Read the persisted per-day token totals for an agent. */\nexport function readUsage(rootDir: string, agent: string): UsageFile {\n const filePath = usageFilePath(rootDir, agent);\n if (!fs.existsSync(filePath)) return { days: {} };\n return JSON.parse(fs.readFileSync(filePath, \"utf8\")) as UsageFile;\n}\n\n/** Persist the per-day token totals for an agent (atomic replace). */\nfunction writeUsage(rootDir: string, agent: string, usage: UsageFile): void {\n atomicWriteFile(usageFilePath(rootDir, agent), JSON.stringify(usage, null, 2));\n}\n\n/** Thrown when a cap would be crossed. `code` mirrors the platform's abort codes. */\nexport class CapExceededError extends Error {\n constructor(\n readonly code: \"PER_DAY_TOKEN_CAP\" | \"PER_RUN_TOKEN_CAP\",\n message: string,\n ) {\n super(message);\n this.name = \"CapExceededError\";\n }\n}\n\n/**\n * Tracks token consumption for one shift and enforces both caps.\n *\n * Enforcement order mirrors the platform (A.2):\n * 1. `admitRun()` — admission check against the per-day cap BEFORE any work.\n * 2. `admitLlmTurn(projected)` — before each LLM turn, abort if the projected\n * total would cross the per-run cap.\n * 3. `add(tokens)` — record actual consumption and persist the day total.\n */\nexport class TokenMeter {\n /** Tokens consumed by this shift so far. */\n runTotal = 0;\n /** Set when a cap abort happened, so the runner can report the right status. */\n abortedWith: CapExceededError | null = null;\n\n constructor(\n private readonly rootDir: string,\n private readonly agent: string,\n private readonly caps: AgentCaps,\n ) {}\n\n /** Tokens already consumed today (UTC), across all local runs. */\n dayTotal(): number {\n const usage = readUsage(this.rootDir, this.agent);\n return usage.days[utcDay()] ?? 0;\n }\n\n /**\n * Admission: refuse the shift before any work if today's local runs have\n * already exhausted the per-day cap — the platform refuses the same way.\n */\n admitRun(): void {\n const today = this.dayTotal();\n if (today >= this.caps.perDayTokens) {\n const error = new CapExceededError(\n \"PER_DAY_TOKEN_CAP\",\n `PER_DAY_TOKEN_CAP: today's usage (${today} tokens) has reached the per-day cap of ${this.caps.perDayTokens}. The cap resets at UTC midnight.`,\n );\n this.abortedWith = error;\n throw error;\n }\n }\n\n /**\n * Pre-turn projection: abort the run if `projectedTokens` more would cross\n * the per-run cap. Called before every LLM turn (wrap-mode llm.complete\n * calls and llm-mode loop turns alike).\n */\n admitLlmTurn(projectedTokens: number): void {\n if (this.runTotal + projectedTokens > this.caps.perRunTokens) {\n const error = new CapExceededError(\n \"PER_RUN_TOKEN_CAP\",\n `PER_RUN_TOKEN_CAP: this turn is projected to use ~${projectedTokens} tokens, which would push the run total past the per-run cap of ${this.caps.perRunTokens} (used so far: ${this.runTotal}).`,\n );\n this.abortedWith = error;\n throw error;\n }\n }\n\n /**\n * Record actual consumption and persist it into today's ledger. Returns the\n * new day total. The read-modify-write is guarded by an interprocess lock so\n * overlapping runs can't lose each other's updates (which would undercount\n * usage and let concurrent runs slip past the day cap).\n */\n add(tokens: number): number {\n this.runTotal += tokens;\n return withFileLock(usageFilePath(this.rootDir, this.agent), () => {\n const usage = readUsage(this.rootDir, this.agent);\n const day = utcDay();\n usage.days[day] = (usage.days[day] ?? 0) + tokens;\n writeUsage(this.rootDir, this.agent, usage);\n return usage.days[day] as number;\n });\n }\n}\n","import type { AgentValidator } from \"../manifest/schema.js\";\nimport type { MemoryStore } from \"../memory/store.js\";\n\n/** Outcome of evaluating one validator. */\nexport interface ValidatorResult {\n validator: AgentValidator[\"type\"];\n passed: boolean;\n /** Human-readable explanation — shown in the trace and fed to repair attempts. */\n detail: string;\n}\n\n/**\n * Evaluate all manifest validators against a run's output, in order.\n *\n * Matches the platform's three validator types (A.3):\n * - `shape` — output must exist and be at least minBytes\n * - `freshness` — a referenced memory asset must be newer than maxAgeHours\n * - `invariant` — output must match / must not match a regex\n *\n * All validators are always evaluated (no short-circuit) so the trace shows\n * the complete picture, exactly like the platform's validator report.\n */\nexport async function evaluateValidators(\n validators: readonly AgentValidator[],\n output: string,\n store: MemoryStore,\n now: Date = new Date(),\n): Promise<ValidatorResult[]> {\n const results: ValidatorResult[] = [];\n for (const validator of validators) {\n switch (validator.type) {\n case \"shape\": {\n const bytes = Buffer.byteLength(output, \"utf8\");\n const passed = bytes >= validator.minBytes;\n results.push({\n validator: \"shape\",\n passed,\n detail: passed\n ? `output is ${bytes} bytes (>= ${validator.minBytes})`\n : `output is ${bytes} bytes, expected at least ${validator.minBytes}`,\n });\n break;\n }\n case \"freshness\": {\n const asset = await store.get(validator.asset);\n if (!asset) {\n results.push({\n validator: \"freshness\",\n passed: false,\n detail: `memory asset \"${validator.asset}\" does not exist`,\n });\n break;\n }\n const ageHours = (now.getTime() - new Date(asset.record.updatedAt).getTime()) / 3_600_000;\n const passed = ageHours <= validator.maxAgeHours;\n results.push({\n validator: \"freshness\",\n passed,\n detail: passed\n ? `asset \"${validator.asset}\" is ${ageHours.toFixed(2)}h old (<= ${validator.maxAgeHours}h)`\n : `asset \"${validator.asset}\" is ${ageHours.toFixed(2)}h old, must be newer than ${validator.maxAgeHours}h`,\n });\n break;\n }\n case \"invariant\": {\n let regex: RegExp;\n try {\n regex = new RegExp(validator.pattern);\n } catch (error) {\n results.push({\n validator: \"invariant\",\n passed: false,\n detail: `invalid regex \"${validator.pattern}\": ${(error as Error).message}`,\n });\n break;\n }\n const matched = regex.test(output);\n const passed = validator.mustMatch ? matched : !matched;\n results.push({\n validator: \"invariant\",\n passed,\n detail: passed\n ? `output ${validator.mustMatch ? \"matches\" : \"does not match\"} /${validator.pattern}/ as required`\n : `output ${matched ? \"matches\" : \"does not match\"} /${validator.pattern}/ but ${validator.mustMatch ? \"must match\" : \"must NOT match\"}`,\n });\n break;\n }\n }\n }\n return results;\n}\n","import http from \"node:http\";\nimport { ToolCallError, ToolDispatcher, type DispatchContext } from \"./dispatch.js\";\n\n/**\n * Loopback HTTP RPC server — the script <-> runtime boundary.\n *\n * Scaffolded Python scripts talk to the emulator over this loopback endpoint\n * (the same pattern the platform uses), NOT by importing emulator internals.\n * That keeps a locally-written script byte-identical when deployed: only the\n * KOHALA_RPC_URL environment variable changes.\n *\n * Protocol: POST / with JSON `{\"tool\": \"s3.put\", \"args\": {...}}`.\n * Success: 200 `{\"ok\": true, \"result\": ...}`\n * Failure: 200 `{\"ok\": false, \"error\": {\"code\": \"...\", \"message\": \"...\"}}`\n * (Tool failures are application-level, not transport-level, so the Python\n * SDK can raise a typed KohalaToolError with the platform's error codes.)\n */\n\n/** A running RPC server bound to 127.0.0.1 on an ephemeral port. */\nexport interface SdkRpcServer {\n /** Base URL, e.g. \"http://127.0.0.1:53412\" — passed to scripts as KOHALA_RPC_URL. */\n url: string;\n close(): Promise<void>;\n}\n\n/** Start the loopback RPC server for one shift. */\nexport async function startSdkRpcServer(context: DispatchContext): Promise<SdkRpcServer> {\n const dispatcher = new ToolDispatcher(context);\n\n const server = http.createServer((request, response) => {\n if (request.method !== \"POST\") {\n response.writeHead(405, { \"content-type\": \"application/json\" });\n response.end(JSON.stringify({ ok: false, error: { code: \"METHOD_NOT_ALLOWED\", message: \"POST only\" } }));\n return;\n }\n let raw = \"\";\n request.on(\"data\", (chunk) => {\n raw += chunk;\n });\n request.on(\"end\", () => {\n void (async () => {\n let payload: { tool?: unknown; args?: unknown };\n try {\n payload = JSON.parse(raw) as { tool?: unknown; args?: unknown };\n } catch {\n respond(response, { ok: false, error: { code: \"BAD_JSON\", message: \"Request body is not valid JSON\" } });\n return;\n }\n if (typeof payload.tool !== \"string\") {\n respond(response, { ok: false, error: { code: \"BAD_REQUEST\", message: 'Missing \"tool\" field' } });\n return;\n }\n try {\n const result = await dispatcher.call(\n payload.tool,\n (payload.args ?? {}) as Record<string, unknown>,\n );\n respond(response, { ok: true, result });\n } catch (error) {\n if (error instanceof ToolCallError) {\n respond(response, { ok: false, error: { code: error.code, message: error.message } });\n return;\n }\n respond(response, {\n ok: false,\n error: { code: \"INTERNAL\", message: (error as Error).message },\n });\n }\n })();\n });\n });\n\n await new Promise<void>((resolve) => {\n // Bind to loopback only — the RPC surface must never be reachable off-host.\n server.listen(0, \"127.0.0.1\", resolve);\n });\n const address = server.address();\n if (address === null || typeof address === \"string\") {\n throw new Error(\"Could not determine RPC server port\");\n }\n\n return {\n url: `http://127.0.0.1:${address.port}`,\n close: () =>\n new Promise<void>((resolve, reject) => {\n server.close((error) => (error ? reject(error) : resolve()));\n }),\n };\n}\n\nfunction respond(response: http.ServerResponse, body: unknown): void {\n const json = JSON.stringify(body);\n response.writeHead(200, { \"content-type\": \"application/json\" });\n response.end(json);\n}\n","import dns from \"node:dns/promises\";\nimport net from \"node:net\";\nimport { assertToolAllowed, ToolDeniedError } from \"../emulator/allowlist.js\";\nimport { CapExceededError, estimateTokens, type TokenMeter } from \"../emulator/tokens.js\";\nimport { completeText } from \"../emulator/llm-client.js\";\nimport type { AgentManifest } from \"../manifest/schema.js\";\nimport type { MemoryStore } from \"../memory/store.js\";\nimport type { TraceWriter } from \"../trace/writer.js\";\n\n/** Everything the dispatcher needs to execute tools for one shift. */\nexport interface DispatchContext {\n manifest: AgentManifest;\n store: MemoryStore;\n trace: TraceWriter;\n meter: TokenMeter;\n runId: string;\n}\n\n/** Structured tool error carried back to the caller (script or LLM loop). */\nexport interface ToolErrorShape {\n code: string;\n message: string;\n}\n\n/** Thrown by dispatch when a tool fails; carries a machine-readable code. */\nexport class ToolCallError extends Error {\n constructor(\n readonly code: string,\n message: string,\n ) {\n super(message);\n this.name = \"ToolCallError\";\n }\n}\n\n/** Truncated, non-sensitive one-line summary of tool args for the trace. */\nexport function summarizeArgs(args: unknown): string {\n const json = JSON.stringify(args) ?? \"{}\";\n return json.length > 200 ? `${json.slice(0, 200)}…` : json;\n}\n\n/**\n * SSRF guard for http.post_json — the same guard the platform applies.\n *\n * Checks the hostname pattern AND every IP the hostname resolves to (so a\n * public DNS name pointing at an internal address is still refused), for\n * both IPv4 and IPv6. Redirects are followed manually with each hop\n * re-validated.\n */\nfunction isBlockedHostname(hostname: string): boolean {\n const lower = hostname.toLowerCase().replace(/^\\[|\\]$/g, \"\");\n if (lower === \"localhost\" || lower.endsWith(\".localhost\")) return true;\n if (net.isIP(lower)) return isBlockedIp(lower);\n return false;\n}\n\nfunction isBlockedIp(ip: string): boolean {\n const version = net.isIP(ip);\n if (version === 4) {\n const octets = ip.split(\".\").map(Number);\n const [a = 0, b = 0] = octets;\n if (a === 0 || a === 10 || a === 127) return true; // this-net, private, loopback\n if (a === 169 && b === 254) return true; // link-local / cloud metadata\n if (a === 172 && b >= 16 && b <= 31) return true; // private\n if (a === 192 && b === 168) return true; // private\n if (a === 100 && b >= 64 && b <= 127) return true; // CGNAT\n return false;\n }\n if (version === 6) {\n const lower = ip.toLowerCase();\n if (lower === \"::\" || lower === \"::1\") return true; // unspecified, loopback\n if (lower.startsWith(\"fe8\") || lower.startsWith(\"fe9\") || lower.startsWith(\"fea\") || lower.startsWith(\"feb\"))\n return true; // link-local fe80::/10\n if (lower.startsWith(\"fc\") || lower.startsWith(\"fd\")) return true; // ULA fc00::/7\n if (lower.startsWith(\"::ffff:\")) {\n // IPv4-mapped — validate the embedded IPv4 address.\n const mapped = lower.slice(\"::ffff:\".length);\n return net.isIP(mapped) === 4 ? isBlockedIp(mapped) : true;\n }\n return false;\n }\n return true; // not a valid IP at all — refuse\n}\n\n/** Throw BLOCKED_HOST unless the hostname and all its resolved IPs are public. */\nasync function assertPublicHost(hostname: string): Promise<void> {\n if (isBlockedHostname(hostname)) {\n throw new ToolCallError(\n \"BLOCKED_HOST\",\n `http.post_json refuses internal/private hosts (\"${hostname}\") — same guard the platform applies.`,\n );\n }\n const bare = hostname.replace(/^\\[|\\]$/g, \"\");\n if (net.isIP(bare)) return; // literal IP already validated above\n let addresses: { address: string }[];\n try {\n addresses = await dns.lookup(bare, { all: true, verbatim: true });\n } catch {\n throw new ToolCallError(\"BAD_URL\", `http.post_json could not resolve host \"${hostname}\"`);\n }\n for (const { address } of addresses) {\n if (isBlockedIp(address)) {\n throw new ToolCallError(\n \"BLOCKED_HOST\",\n `http.post_json refuses \"${hostname}\" — it resolves to the internal/private address ${address}.`,\n );\n }\n }\n}\n\n/** Max redirect hops http.post_json will follow (each hop is re-validated). */\nconst MAX_REDIRECTS = 3;\n\n/**\n * Executes one tool call with the full platform semantics:\n * allowlist check -> execution -> trace `tool_call` event (allow/deny,\n * duration). Used by both the loopback RPC server (wrap mode) and the\n * llm-mode tool-use loop, so enforcement is identical in both paths.\n */\nexport class ToolDispatcher {\n constructor(private readonly context: DispatchContext) {}\n\n /** All tools the emulator knows how to execute. */\n static readonly KNOWN_TOOLS = [\n \"s3.put\",\n \"s3.get\",\n \"s3.list\",\n \"s3.delete\",\n \"http.post_json\",\n \"llm.complete\",\n \"notify.send\",\n \"metrics.record\",\n ] as const;\n\n /**\n * Execute `tool` with `args`. Always writes a tool_call trace event, whether\n * the call was allowed, denied, or failed.\n */\n async call(tool: string, args: Record<string, unknown>): Promise<unknown> {\n const { manifest, trace, runId } = this.context;\n const startedAt = Date.now();\n const base = {\n ts: new Date().toISOString(),\n runId,\n agent: manifest.name,\n type: \"tool_call\" as const,\n tool,\n argsSummary: summarizeArgs(args),\n };\n\n // 1. Allowlist — every tool call is checked; disallowed calls fail loudly.\n try {\n assertToolAllowed(manifest.toolAllowlist, tool);\n } catch (error) {\n trace.append({\n ...base,\n allowed: false,\n ok: false,\n durationMs: Date.now() - startedAt,\n error: (error as Error).message,\n });\n throw new ToolCallError(\"TOOL_DENIED\", (error as ToolDeniedError).message);\n }\n\n // 2. Execute.\n try {\n const result = await this.execute(tool, args);\n trace.append({ ...base, allowed: true, ok: true, durationMs: Date.now() - startedAt });\n return result;\n } catch (error) {\n const message = (error as Error).message;\n trace.append({\n ...base,\n allowed: true,\n ok: false,\n durationMs: Date.now() - startedAt,\n error: message,\n });\n if (error instanceof ToolCallError) throw error;\n if (error instanceof CapExceededError) throw new ToolCallError(error.code, message);\n throw new ToolCallError(\"TOOL_ERROR\", message);\n }\n }\n\n private async execute(tool: string, args: Record<string, unknown>): Promise<unknown> {\n const { store, meter, trace, manifest, runId } = this.context;\n switch (tool) {\n case \"s3.put\": {\n const key = requireString(args, \"key\");\n const body = requireString(args, \"body\");\n const category = optionalString(args, \"category\");\n const record = await store.put(key, Buffer.from(body, \"utf8\"), category);\n return { record };\n }\n case \"s3.get\": {\n const keyOrId = requireString(args, \"keyOrId\");\n const asset = await store.get(keyOrId);\n if (!asset) {\n throw new ToolCallError(\"NOT_FOUND\", `No active memory asset matches \"${keyOrId}\"`);\n }\n return { record: asset.record, body: asset.body.toString(\"utf8\") };\n }\n case \"s3.list\": {\n const prefix = optionalString(args, \"prefix\");\n const limit = typeof args.limit === \"number\" ? args.limit : undefined;\n const records = await store.list(prefix, limit);\n return { records };\n }\n case \"s3.delete\": {\n const keyOrId = requireString(args, \"keyOrId\");\n const record = await store.delete(keyOrId);\n if (!record) {\n throw new ToolCallError(\"NOT_FOUND\", `No active memory asset matches \"${keyOrId}\"`);\n }\n return { record };\n }\n case \"http.post_json\": {\n const url = requireString(args, \"url\");\n const headers = (args.headers ?? {}) as Record<string, string>;\n const requestBody = JSON.stringify(args.body ?? {});\n\n // Redirects are followed manually so every hop goes through the same\n // SSRF guard — a public URL redirecting to an internal address is\n // refused just like a direct request to it would be.\n let currentUrl = url;\n let response: Response;\n for (let hop = 0; ; hop += 1) {\n const parsed = safeParseUrl(currentUrl);\n if (!parsed || (parsed.protocol !== \"http:\" && parsed.protocol !== \"https:\")) {\n throw new ToolCallError(\n \"BAD_URL\",\n `http.post_json needs an http(s) URL, got \"${currentUrl}\"`,\n );\n }\n await assertPublicHost(parsed.hostname);\n response = await fetch(currentUrl, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\", ...headers },\n body: requestBody,\n redirect: \"manual\",\n });\n if (response.status < 300 || response.status >= 400) break;\n const location = response.headers.get(\"location\");\n if (!location) break;\n if (hop >= MAX_REDIRECTS) {\n throw new ToolCallError(\n \"TOO_MANY_REDIRECTS\",\n `http.post_json gave up after ${MAX_REDIRECTS} redirects (last: ${currentUrl})`,\n );\n }\n currentUrl = new URL(location, currentUrl).toString();\n }\n\n const text = await response.text();\n let json: unknown = null;\n try {\n json = JSON.parse(text);\n } catch {\n // Non-JSON responses come back as text only; that is not an error.\n }\n return { status: response.status, ok: response.ok, body: text, json };\n }\n case \"llm.complete\": {\n const prompt = requireString(args, \"prompt\");\n const model = optionalString(args, \"model\");\n // Pre-turn projection against the per-run cap (A.2 step 3): prompt\n // estimate + the max output we allow for one completion.\n const maxOutput = 1024;\n meter.admitLlmTurn(estimateTokens(prompt) + maxOutput);\n const completion = await completeText(prompt, model, maxOutput);\n const consumed = completion.inputTokens + completion.outputTokens;\n const dayTotal = meter.add(consumed);\n trace.append({\n ts: new Date().toISOString(),\n runId,\n agent: manifest.name,\n type: \"tokens\",\n tokens: consumed,\n runTotal: meter.runTotal,\n dayTotal,\n source: `llm.complete ${completion.provider}/${completion.model}`,\n });\n return {\n text: completion.text,\n model: completion.model,\n provider: completion.provider,\n inputTokens: completion.inputTokens,\n outputTokens: completion.outputTokens,\n };\n }\n case \"notify.send\": {\n // Locally, notifications just land in the trace (the tool_call event\n // records channel + message via argsSummary). Nothing is sent anywhere.\n requireString(args, \"channel\");\n requireString(args, \"message\");\n return { delivered: \"trace\" };\n }\n case \"metrics.record\": {\n // Locally, metrics are appended to the trace via the tool_call event.\n requireString(args, \"name\");\n if (typeof args.value !== \"number\") {\n throw new ToolCallError(\"BAD_ARGS\", \"metrics.record needs a numeric value\");\n }\n return { recorded: \"trace\" };\n }\n default:\n throw new ToolCallError(\n \"UNKNOWN_TOOL\",\n `Unknown tool \"${tool}\". Known tools: ${ToolDispatcher.KNOWN_TOOLS.join(\", \")}`,\n );\n }\n }\n}\n\nfunction requireString(args: Record<string, unknown>, name: string): string {\n const value = args[name];\n if (typeof value !== \"string\" || value.length === 0) {\n throw new ToolCallError(\"BAD_ARGS\", `Missing required string argument \"${name}\"`);\n }\n return value;\n}\n\nfunction optionalString(args: Record<string, unknown>, name: string): string | undefined {\n const value = args[name];\n if (value === undefined || value === null) return undefined;\n if (typeof value !== \"string\") {\n throw new ToolCallError(\"BAD_ARGS\", `Argument \"${name}\" must be a string when provided`);\n }\n return value;\n}\n\nfunction safeParseUrl(url: string): URL | null {\n try {\n return new URL(url);\n } catch {\n return null;\n }\n}\n","/**\n * Tool allowlist enforcement.\n *\n * The platform checks every tool call an agent makes against\n * `agentToolAllowlist`; the emulator applies the identical rule to\n * `toolAllowlist` from kohala.json. There are no implicit grants — a tool the\n * manifest does not list is denied loudly, and the denial is recorded in the\n * trace.\n */\n\n/** Thrown when a script or LLM loop calls a tool that is not allowlisted. */\nexport class ToolDeniedError extends Error {\n constructor(readonly tool: string, allowlist: readonly string[]) {\n super(\n `TOOL_DENIED: \"${tool}\" is not in the agent's toolAllowlist ` +\n `[${allowlist.join(\", \")}]. Add it to kohala.json if the agent should be able to use it.`,\n );\n this.name = \"ToolDeniedError\";\n }\n}\n\n/** True when the manifest allows this exact tool name. */\nexport function isToolAllowed(allowlist: readonly string[], tool: string): boolean {\n return allowlist.includes(tool);\n}\n\n/** Assert a tool is allowed; throws ToolDeniedError otherwise. */\nexport function assertToolAllowed(allowlist: readonly string[], tool: string): void {\n if (!isToolAllowed(allowlist, tool)) {\n throw new ToolDeniedError(tool, allowlist);\n }\n}\n","/**\n * Thin LLM client used by `llm.complete` (wrap mode) and the llm-mode loop.\n *\n * Uses the developer's OWN key from the environment — ANTHROPIC_API_KEY first,\n * then GEMINI_API_KEY. If neither is set the call fails with a clear\n * \"no key configured\" error. There is deliberately no mock fallback: silent\n * fake completions would hide real integration problems (Part B: errors fail\n * loudly).\n */\n\n/** Result of a single completion, with token usage for cap accounting. */\nexport interface CompletionResult {\n text: string;\n inputTokens: number;\n outputTokens: number;\n provider: \"anthropic\" | \"gemini\";\n model: string;\n}\n\n/** Thrown when no LLM API key is configured in the environment. */\nexport class NoLlmKeyError extends Error {\n constructor() {\n super(\n \"NO_LLM_KEY: no LLM key configured. Set ANTHROPIC_API_KEY (preferred) or \" +\n \"GEMINI_API_KEY in your environment — the devkit never mocks completions.\",\n );\n this.name = \"NoLlmKeyError\";\n }\n}\n\n/**\n * Default models per provider.\n *\n * Override at runtime with environment variables:\n * ANTHROPIC_MODEL — e.g. \"claude-3-5-haiku-latest\"\n * GEMINI_MODEL — e.g. \"gemini-2.0-flash\"\n * KOHALA_LLM_MODEL — provider-agnostic override (takes precedence)\n *\n * Defaults match the hosted platform so local behaviour is as close as\n * possible to what runs after `kohala deploy`.\n */\nconst DEFAULT_ANTHROPIC_MODEL = \"claude-sonnet-4-6\";\nconst DEFAULT_GEMINI_MODEL = \"gemini-flash-latest\";\n\n/** Which provider will handle completions given the current environment. */\nexport function detectLlmProvider(\n env: NodeJS.ProcessEnv = process.env,\n): \"anthropic\" | \"gemini\" | null {\n if (env.ANTHROPIC_API_KEY) return \"anthropic\";\n if (env.GEMINI_API_KEY) return \"gemini\";\n return null;\n}\n\n/**\n * Complete a prompt with the developer's own key.\n *\n * @param prompt - The user prompt to complete.\n * @param model - Optional model override (provider-native model name).\n * @param maxOutputTokens - Ceiling passed to the provider (defaults to 1024).\n */\nexport async function completeText(\n prompt: string,\n model?: string,\n maxOutputTokens = 1024,\n env: NodeJS.ProcessEnv = process.env,\n): Promise<CompletionResult> {\n const provider = detectLlmProvider(env);\n if (provider === \"anthropic\") {\n // Resolution order: explicit arg → KOHALA_LLM_MODEL → ANTHROPIC_MODEL → default\n const resolvedModel =\n model ??\n env.KOHALA_LLM_MODEL ??\n env.ANTHROPIC_MODEL ??\n DEFAULT_ANTHROPIC_MODEL;\n return completeAnthropic(prompt, resolvedModel, maxOutputTokens, env);\n }\n if (provider === \"gemini\") {\n // Resolution order: explicit arg → KOHALA_LLM_MODEL → GEMINI_MODEL → default\n const resolvedModel =\n model ??\n env.KOHALA_LLM_MODEL ??\n env.GEMINI_MODEL ??\n DEFAULT_GEMINI_MODEL;\n return completeGemini(prompt, resolvedModel, maxOutputTokens, env);\n }\n throw new NoLlmKeyError();\n}\n\nasync function completeAnthropic(\n prompt: string,\n model: string,\n maxOutputTokens: number,\n env: NodeJS.ProcessEnv,\n): Promise<CompletionResult> {\n const response = await fetch(\"https://api.anthropic.com/v1/messages\", {\n method: \"POST\",\n headers: {\n \"content-type\": \"application/json\",\n \"x-api-key\": env.ANTHROPIC_API_KEY as string,\n \"anthropic-version\": \"2023-06-01\",\n },\n body: JSON.stringify({\n model,\n max_tokens: maxOutputTokens,\n messages: [{ role: \"user\", content: prompt }],\n }),\n });\n if (!response.ok) {\n const body = await response.text();\n throw new Error(`Anthropic API error ${response.status}: ${body.slice(0, 300)}`);\n }\n const data = (await response.json()) as {\n content: { type: string; text?: string }[];\n usage: { input_tokens: number; output_tokens: number };\n };\n const text = data.content\n .filter((block) => block.type === \"text\")\n .map((block) => block.text ?? \"\")\n .join(\"\");\n return {\n text,\n inputTokens: data.usage.input_tokens,\n outputTokens: data.usage.output_tokens,\n provider: \"anthropic\",\n model,\n };\n}\n\nasync function completeGemini(\n prompt: string,\n model: string,\n maxOutputTokens: number,\n env: NodeJS.ProcessEnv,\n): Promise<CompletionResult> {\n const url = `https://generativelanguage.googleapis.com/v1beta/models/${model}:generateContent`;\n const response = await fetch(url, {\n method: \"POST\",\n headers: {\n \"content-type\": \"application/json\",\n \"x-goog-api-key\": env.GEMINI_API_KEY as string,\n },\n body: JSON.stringify({\n contents: [{ parts: [{ text: prompt }] }],\n generationConfig: { maxOutputTokens },\n }),\n });\n if (!response.ok) {\n const body = await response.text();\n throw new Error(`Gemini API error ${response.status}: ${body.slice(0, 300)}`);\n }\n const data = (await response.json()) as {\n candidates?: { content?: { parts?: { text?: string }[] } }[];\n usageMetadata?: { promptTokenCount?: number; candidatesTokenCount?: number };\n };\n const text = (data.candidates?.[0]?.content?.parts ?? []).map((part) => part.text ?? \"\").join(\"\");\n return {\n text,\n inputTokens: data.usageMetadata?.promptTokenCount ?? 0,\n outputTokens: data.usageMetadata?.candidatesTokenCount ?? 0,\n provider: \"gemini\",\n model,\n };\n}\n","import fs from \"node:fs\";\nimport { estimateTokens } from \"./tokens.js\";\nimport { ToolCallError, ToolDispatcher, type DispatchContext } from \"../sdk/dispatch.js\";\n\n/**\n * llm runtime mode — a real tool-use loop against the developer's own\n * Anthropic key (Anthropic first, per the build plan; Gemini support for\n * llm-mode can follow).\n *\n * The allowlisted tools are exposed to the model as tool definitions; every\n * tool invocation goes through the same ToolDispatcher as wrap mode, so\n * allowlist checks, tracing, and token accounting are identical. Before each\n * turn we project the next request's token cost against caps.perRunTokens and\n * abort with PER_RUN_TOKEN_CAP if it would cross (A.2 step 3).\n */\n\n/** Max loop turns as a hard safety stop, independent of token caps. */\nconst MAX_TURNS = 16;\n\n/** Per-turn output ceiling passed to the API. */\nconst MAX_OUTPUT_TOKENS = 1024;\n\n/** JSON Schema definitions for each platform tool, keyed by tool name. */\nconst TOOL_DEFINITIONS: Record<string, { description: string; input_schema: object }> = {\n \"s3.put\": {\n description:\n 'Store a value in agent memory under a logical key. Category defaults to \"agentoutput\".',\n input_schema: {\n type: \"object\",\n properties: {\n key: { type: \"string\" },\n body: { type: \"string\" },\n category: { type: \"string\" },\n },\n required: [\"key\", \"body\"],\n },\n },\n \"s3.get\": {\n description: \"Fetch a memory asset by logical key (or record id).\",\n input_schema: {\n type: \"object\",\n properties: { keyOrId: { type: \"string\" } },\n required: [\"keyOrId\"],\n },\n },\n \"s3.list\": {\n description: \"List active memory assets, optionally filtered by key prefix.\",\n input_schema: {\n type: \"object\",\n properties: { prefix: { type: \"string\" }, limit: { type: \"number\" } },\n },\n },\n \"s3.delete\": {\n description: \"Remove and deactivate a memory asset by key or id.\",\n input_schema: {\n type: \"object\",\n properties: { keyOrId: { type: \"string\" } },\n required: [\"keyOrId\"],\n },\n },\n \"http.post_json\": {\n description: \"POST a JSON body to an external http(s) URL and return the response.\",\n input_schema: {\n type: \"object\",\n properties: {\n url: { type: \"string\" },\n body: { type: \"object\" },\n headers: { type: \"object\" },\n },\n required: [\"url\"],\n },\n },\n \"notify.send\": {\n description: \"Send a notification (locally this is recorded in the audit trace).\",\n input_schema: {\n type: \"object\",\n properties: { channel: { type: \"string\" }, message: { type: \"string\" } },\n required: [\"channel\", \"message\"],\n },\n },\n \"metrics.record\": {\n description: \"Record a metric point (locally this is recorded in the audit trace).\",\n input_schema: {\n type: \"object\",\n properties: {\n name: { type: \"string\" },\n value: { type: \"number\" },\n tags: { type: \"object\" },\n },\n required: [\"name\", \"value\"],\n },\n },\n};\n\ninterface AnthropicContentBlock {\n type: string;\n text?: string;\n id?: string;\n name?: string;\n input?: Record<string, unknown>;\n tool_use_id?: string;\n content?: string;\n is_error?: boolean;\n}\n\ninterface AnthropicResponse {\n content: AnthropicContentBlock[];\n stop_reason: string;\n usage: { input_tokens: number; output_tokens: number };\n}\n\n/**\n * Run one llm-mode shift. Returns the model's final text output.\n *\n * The skill script file, if present, contributes its contents as task context\n * (llm-mode agents describe their task in the skill file; the charter is the\n * system prompt) — this mirrors how the platform prompts hosted llm agents.\n */\nexport async function runLlmShift(\n context: DispatchContext,\n skillName: string,\n scriptPath: string,\n repairFeedback?: string,\n): Promise<string> {\n const apiKey = process.env.ANTHROPIC_API_KEY;\n if (!apiKey) {\n // llm mode uses the Anthropic tool-use API specifically.\n // GEMINI_API_KEY enables llm.complete in wrap mode but not this loop.\n throw new Error(\n \"NO_LLM_KEY: llm mode requires ANTHROPIC_API_KEY. \" +\n \"GEMINI_API_KEY enables llm.complete calls inside wrap-mode skills, \" +\n \"but the llm-mode tool-use loop only supports Anthropic. \" +\n \"Set ANTHROPIC_API_KEY in your environment to use runtimeMode: \\\"llm\\\".\",\n );\n }\n // Resolution order: KOHALA_LLM_MODEL → ANTHROPIC_MODEL → default.\n // Default matches the hosted platform model so local behaviour is close to deployed.\n const model =\n process.env.KOHALA_LLM_MODEL ?? process.env.ANTHROPIC_MODEL ?? \"claude-sonnet-4-6\";\n const dispatcher = new ToolDispatcher(context);\n const { manifest, meter, trace, runId } = context;\n\n // Only allowlisted tools are exposed as definitions — the model cannot even\n // see tools it is not allowed to call.\n const tools = Object.entries(TOOL_DEFINITIONS)\n .filter(([name]) => manifest.toolAllowlist.includes(name))\n .map(([name, definition]) => ({ name: toApiToolName(name), ...definition }));\n\n const taskContext = fs.existsSync(scriptPath) ? fs.readFileSync(scriptPath, \"utf8\") : \"\";\n const messages: { role: \"user\" | \"assistant\"; content: unknown }[] = [\n {\n role: \"user\",\n content:\n `You are running one shift of the agent skill \"${skillName}\".\\n` +\n (taskContext ? `Task instructions:\\n${taskContext}\\n` : \"\") +\n (repairFeedback\n ? `\\nThis is a repair attempt. Your previous output failed validation:\\n${repairFeedback}\\nFix the problem this time.\\n`\n : \"\") +\n \"Use your tools as needed, then reply with a final text summary of what you did.\",\n },\n ];\n\n for (let turn = 0; turn < MAX_TURNS; turn += 1) {\n // Pre-turn projection (A.2 step 3): estimate the request we are about to\n // send plus the response ceiling, and abort before crossing the cap.\n const projected = estimateTokens(JSON.stringify(messages) + manifest.charter) + MAX_OUTPUT_TOKENS;\n meter.admitLlmTurn(projected);\n\n const response = await fetch(\"https://api.anthropic.com/v1/messages\", {\n method: \"POST\",\n headers: {\n \"content-type\": \"application/json\",\n \"x-api-key\": apiKey,\n \"anthropic-version\": \"2023-06-01\",\n },\n body: JSON.stringify({\n model,\n max_tokens: MAX_OUTPUT_TOKENS,\n system: manifest.charter,\n tools,\n messages,\n }),\n });\n if (!response.ok) {\n const body = await response.text();\n throw new Error(`Anthropic API error ${response.status}: ${body.slice(0, 300)}`);\n }\n const data = (await response.json()) as AnthropicResponse;\n\n const consumed = data.usage.input_tokens + data.usage.output_tokens;\n const dayTotal = meter.add(consumed);\n trace.append({\n ts: new Date().toISOString(),\n runId,\n agent: manifest.name,\n type: \"tokens\",\n tokens: consumed,\n runTotal: meter.runTotal,\n dayTotal,\n source: `llm-mode turn ${turn + 1} (${model})`,\n });\n\n const finalText = data.content\n .filter((block) => block.type === \"text\")\n .map((block) => block.text ?? \"\")\n .join(\"\");\n\n if (data.stop_reason !== \"tool_use\") {\n return finalText;\n }\n\n // Execute each requested tool through the shared dispatcher, then feed\n // results (or loud errors) back to the model.\n messages.push({ role: \"assistant\", content: data.content });\n const toolResults: AnthropicContentBlock[] = [];\n for (const block of data.content) {\n if (block.type !== \"tool_use\" || !block.id || !block.name) continue;\n const toolName = fromApiToolName(block.name);\n try {\n const result = await dispatcher.call(toolName, block.input ?? {});\n toolResults.push({\n type: \"tool_result\",\n tool_use_id: block.id,\n content: JSON.stringify(result).slice(0, 8000),\n });\n } catch (error) {\n const toolError = error as ToolCallError;\n toolResults.push({\n type: \"tool_result\",\n tool_use_id: block.id,\n content: `${toolError.code ?? \"TOOL_ERROR\"}: ${toolError.message}`,\n is_error: true,\n });\n }\n }\n messages.push({ role: \"user\", content: toolResults });\n }\n\n throw new Error(`llm-mode shift exceeded ${MAX_TURNS} turns without finishing`);\n}\n\n/**\n * Anthropic tool names must match [a-zA-Z0-9_-], so the platform's dotted\n * names are transported with \"__\" in place of \".\" and mapped back on dispatch.\n */\nfunction toApiToolName(name: string): string {\n return name.replace(/\\./g, \"__\");\n}\n\nfunction fromApiToolName(name: string): string {\n return name.replace(/__/g, \".\");\n}\n","import { execa } from \"execa\";\n\n/**\n * Python is an optional runtime dependency at use time (running skills),\n * never an install-time dependency. We look for `python3` first, then\n * `python`, and fail with an actionable message if neither exists.\n */\nlet cachedPython: string | null = null;\n\n/** Locate a working Python 3 interpreter or throw with install guidance. */\nexport async function findPython(): Promise<string> {\n if (cachedPython) return cachedPython;\n for (const candidate of [\"python3\", \"python\"]) {\n try {\n const result = await execa(candidate, [\"--version\"], { reject: false });\n if (result.exitCode === 0 && /Python 3/.test(`${result.stdout}${result.stderr}`)) {\n cachedPython = candidate;\n return candidate;\n }\n } catch {\n // Candidate not on PATH — try the next one.\n }\n }\n throw new Error(\n \"Python 3 is required to run agent skills but was not found on your PATH. \" +\n \"Install it from https://www.python.org/downloads/ (or via your package manager: \" +\n \"`brew install python3`, `apt install python3`), then re-run this command.\",\n );\n}\n\n/** Test-only: reset the cached interpreter path. */\nexport function resetPythonCache(): void {\n cachedPython = null;\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport type { Command } from \"commander\";\nimport pc from \"picocolors\";\nimport { followTraceFile, readTraceFile } from \"../trace/reader.js\";\nimport { formatTraceEvent } from \"../trace/format.js\";\nimport { traceFilePath } from \"../trace/writer.js\";\nimport { loadManifest } from \"../manifest/load.js\";\n\n/**\n * `kohala trace <agent>` — pretty-print (and optionally follow) the agent's\n * JSONL audit trace, the local twin of the platform's run records.\n */\nexport function registerTraceCommand(program: Command): void {\n program\n .command(\"trace\")\n .argument(\"<agent>\", \"agent directory or agent name\")\n .option(\"--follow\", \"keep watching for new events (like tail -f)\")\n .option(\"--json\", \"print raw JSONL events instead of the pretty view\")\n .description(\"Tail the audit trace for an agent\")\n .action((agent: string, options: { follow?: boolean; json?: boolean }) => {\n const rootDir = process.cwd();\n // Accept either a directory (read its manifest for the name) or a bare name.\n let agentName = agent;\n const agentDir = path.resolve(rootDir, agent);\n if (fs.existsSync(path.join(agentDir, \"kohala.json\"))) {\n agentName = loadManifest(agentDir).name;\n }\n const filePath = traceFilePath(rootDir, agentName);\n if (!fs.existsSync(filePath)) {\n throw new Error(\n `No trace found for \"${agentName}\" (looked at ${filePath}). Run the agent first: kohala run ${agent} --local`,\n );\n }\n\n const print = options.json\n ? (event: object) => console.log(JSON.stringify(event))\n : (event: object) => console.log(formatTraceEvent(event as Parameters<typeof formatTraceEvent>[0]));\n\n for (const event of readTraceFile(filePath)) {\n print(event);\n }\n\n if (options.follow) {\n console.error(pc.dim(`— following ${filePath} (ctrl-c to stop) —`));\n followTraceFile(filePath, print);\n }\n });\n}\n","import fs from \"node:fs\";\nimport type { TraceEvent } from \"./events.js\";\n\n/**\n * Parse the full contents of a JSONL trace file.\n *\n * Unparseable lines are surfaced as errors rather than skipped — a corrupt\n * audit trail should be loud, not silently truncated.\n */\nexport function readTraceFile(filePath: string): TraceEvent[] {\n const raw = fs.readFileSync(filePath, \"utf8\");\n return parseTraceLines(raw);\n}\n\n/** Parse raw JSONL text into events. Throws on malformed lines. */\nexport function parseTraceLines(raw: string): TraceEvent[] {\n const events: TraceEvent[] = [];\n const lines = raw.split(\"\\n\");\n for (let i = 0; i < lines.length; i += 1) {\n const line = (lines[i] ?? \"\").trim();\n if (line === \"\") continue;\n try {\n events.push(JSON.parse(line) as TraceEvent);\n } catch {\n throw new Error(`Malformed trace line ${i + 1}: ${line.slice(0, 120)}`);\n }\n }\n return events;\n}\n\n/**\n * Follow a trace file, invoking `onEvent` for each new complete line.\n *\n * Implemented with polling (not fs.watch) because appends from a separate\n * process are flaky to observe via inotify on some filesystems; a 250ms poll\n * is plenty for a human tailing a trace. Returns a stop function.\n */\nexport function followTraceFile(\n filePath: string,\n onEvent: (event: TraceEvent) => void,\n pollMs = 250,\n): () => void {\n let offset = fs.existsSync(filePath) ? fs.statSync(filePath).size : 0;\n let partial = \"\";\n\n const timer = setInterval(() => {\n if (!fs.existsSync(filePath)) return;\n const size = fs.statSync(filePath).size;\n if (size <= offset) return;\n\n const stream = fs.createReadStream(filePath, { start: offset, end: size - 1, encoding: \"utf8\" });\n let chunkData = \"\";\n stream.on(\"data\", (chunk) => {\n chunkData += chunk;\n });\n stream.on(\"end\", () => {\n offset = size;\n partial += chunkData;\n const lines = partial.split(\"\\n\");\n partial = lines.pop() ?? \"\";\n for (const line of lines) {\n const trimmed = line.trim();\n if (trimmed === \"\") continue;\n try {\n onEvent(JSON.parse(trimmed) as TraceEvent);\n } catch {\n // A malformed line while following is reported once, loudly.\n throw new Error(`Malformed trace line while following: ${trimmed.slice(0, 120)}`);\n }\n }\n });\n }, pollMs);\n\n return () => clearInterval(timer);\n}\n","import pc from \"picocolors\";\nimport type { TraceEvent } from \"./events.js\";\n\n/** Short local time (HH:MM:SS) for the human-readable trace view. */\nfunction shortTime(ts: string): string {\n const date = new Date(ts);\n return date.toLocaleTimeString(\"en-US\", { hour12: false });\n}\n\n/**\n * Pretty-print one trace event for `kohala trace`.\n *\n * The goal is a scannable audit log: status words are colorized, tool denials\n * and validator failures jump out in red, token accounting stays dim.\n */\nexport function formatTraceEvent(event: TraceEvent): string {\n const time = pc.dim(shortTime(event.ts));\n switch (event.type) {\n case \"run_started\":\n return `${time} ${pc.cyan(\"run_started\")} skill=${event.skill} (${event.scriptFilename}) mode=${event.runtimeMode} run=${event.runId}`;\n case \"tool_call\": {\n const verdict = event.allowed\n ? event.ok\n ? pc.green(\"ok\")\n : pc.red(\"error\")\n : pc.red(\"DENIED\");\n const errorSuffix = event.error ? ` ${pc.red(event.error)}` : \"\";\n return `${time} ${pc.magenta(\"tool_call\")} ${pc.bold(event.tool)} ${verdict} ${pc.dim(`${event.durationMs}ms`)} ${pc.dim(event.argsSummary)}${errorSuffix}`;\n }\n case \"tokens\":\n return `${time} ${pc.dim(`tokens +${event.tokens} run=${event.runTotal} day=${event.dayTotal} (${event.source})`)}`;\n case \"validator_result\": {\n const verdict = event.passed ? pc.green(\"passed\") : pc.red(\"FAILED\");\n return `${time} ${pc.yellow(\"validator\")} ${event.validator} ${verdict} ${pc.dim(event.detail)}`;\n }\n case \"repair_attempt\":\n return `${time} ${pc.yellow(`repair_attempt ${event.attempt}/${event.maxAttempts}`)} ${pc.dim(event.reason)}`;\n case \"run_finished\": {\n const color =\n event.status === \"succeeded\" ? pc.green : event.status === \"failed\" ? pc.red : pc.red;\n const detailSuffix = event.detail ? ` ${pc.dim(event.detail)}` : \"\";\n return `${time} ${color(`run_finished ${event.status}`)} tokens=${event.totalTokens} ${pc.dim(`${event.durationMs}ms`)}${detailSuffix}`;\n }\n }\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport type { Command } from \"commander\";\nimport pc from \"picocolors\";\nimport { createMemoryStore, type MemoryBackend } from \"../memory/create.js\";\nimport { serveHttp, serveStdio } from \"../mcp/server.js\";\nimport { loadManifest } from \"../manifest/load.js\";\n\n/**\n * `kohala memory serve` — run the open MCP memory server.\n *\n * Transports:\n * default — stdio, for MCP clients that spawn a child process\n * --http — streamable HTTP on 127.0.0.1:<port>/mcp (MCP Inspector etc.)\n *\n * Backends: file (default, .kohala/memory/<agent>/) or postgres (--url or\n * DATABASE_URL). Memory is always scoped to one agent, like the platform.\n */\nexport function registerMemoryCommand(program: Command): void {\n const memory = program.command(\"memory\").description(\"Memory server commands\");\n\n memory\n .command(\"serve\")\n .option(\"--agent <name>\", \"agent name to scope memory to (or run from an agent dir)\")\n .option(\"--backend <backend>\", \"file | postgres\", \"file\")\n .option(\"--url <url>\", \"postgres connection string (or set DATABASE_URL)\")\n .option(\"--http\", \"serve over streamable HTTP instead of stdio\")\n .option(\"--port <port>\", \"HTTP port (with --http)\", \"8787\")\n .description(\"Serve agent memory over the Model Context Protocol\")\n .action(\n async (options: {\n agent?: string;\n backend: string;\n url?: string;\n http?: boolean;\n port: string;\n }) => {\n if (options.backend !== \"file\" && options.backend !== \"postgres\") {\n throw new Error(`Unknown backend \"${options.backend}\" — use \"file\" or \"postgres\".`);\n }\n\n // Agent resolution: explicit --agent wins; otherwise, if the current\n // directory is an agent dir (has kohala.json), use its name.\n let agent = options.agent;\n let rootDir = process.cwd();\n if (!agent) {\n const manifestHere = path.join(process.cwd(), \"kohala.json\");\n if (fs.existsSync(manifestHere)) {\n agent = loadManifest(process.cwd()).name;\n // Memory for an agent dir lives in the parent workspace root.\n rootDir = path.dirname(process.cwd());\n } else {\n throw new Error(\n \"Pass --agent <name>, or run this from inside an agent directory (one containing kohala.json).\",\n );\n }\n }\n\n const store = await createMemoryStore({\n backend: options.backend as MemoryBackend,\n agent,\n rootDir,\n url: options.url ?? process.env.DATABASE_URL,\n });\n\n if (options.http) {\n const port = Number(options.port);\n await serveHttp(store, agent, port);\n // Log to stderr so stdout stays clean for any piping.\n console.error(\n pc.green(`MCP memory server for \"${agent}\" listening on http://127.0.0.1:${port}/mcp`),\n );\n console.error(pc.dim(`backend=${options.backend} — ctrl-c to stop`));\n } else {\n console.error(\n pc.dim(`MCP memory server for \"${agent}\" on stdio (backend=${options.backend})`),\n );\n await serveStdio(store, agent);\n }\n },\n );\n}\n","import http from \"node:http\";\nimport { z } from \"zod\";\nimport { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport { StreamableHTTPServerTransport } from \"@modelcontextprotocol/sdk/server/streamableHttp.js\";\nimport { DEFAULT_CATEGORY, type MemoryStore } from \"../memory/store.js\";\n\n/**\n * The open MCP memory server — `kohala memory serve`.\n *\n * Exposes the platform's four memory tools over the Model Context Protocol\n * with identical names and semantics (A.1), so an agent using this server\n * locally needs zero changes when it goes live:\n *\n * s3.put / s3.get / s3.list / s3.delete\n *\n * Also exposes a `memory://index` resource that lists all active assets.\n * Supported transports: stdio (default, for MCP clients that spawn a child\n * process) and streamable HTTP (for MCP Inspector and remote-style clients).\n */\n\n/** Server identity advertised over MCP. */\nconst SERVER_INFO = { name: \"kohala-memory\", version: \"0.1.0\" };\n\n/** Build a configured MCP server bound to one agent's MemoryStore. */\nexport function buildMemoryMcpServer(store: MemoryStore, agent: string): McpServer {\n const server = new McpServer(SERVER_INFO);\n\n server.registerTool(\n \"s3.put\",\n {\n title: \"Store memory asset\",\n description:\n `Store a value in ${agent}'s persistent memory under a logical key. ` +\n `Category defaults to \"${DEFAULT_CATEGORY}\" (run results).`,\n inputSchema: {\n key: z.string().min(1).describe(\"Logical key, e.g. weather/latest\"),\n body: z.string().describe(\"UTF-8 body to store\"),\n category: z.string().optional().describe(`Asset category (default \"${DEFAULT_CATEGORY}\")`),\n },\n },\n async ({ key, body, category }) => {\n const record = await store.put(key, Buffer.from(body, \"utf8\"), category);\n return { content: [{ type: \"text\", text: JSON.stringify({ record }, null, 2) }] };\n },\n );\n\n server.registerTool(\n \"s3.get\",\n {\n title: \"Fetch memory asset\",\n description: \"Fetch an asset by logical key (resolved first) or record id.\",\n inputSchema: {\n keyOrId: z.string().min(1).describe(\"Logical key or record id\"),\n },\n },\n async ({ keyOrId }) => {\n const asset = await store.get(keyOrId);\n if (!asset) {\n return {\n isError: true,\n content: [{ type: \"text\", text: `No active memory asset matches \"${keyOrId}\"` }],\n };\n }\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(\n { record: asset.record, body: asset.body.toString(\"utf8\") },\n null,\n 2,\n ),\n },\n ],\n };\n },\n );\n\n server.registerTool(\n \"s3.list\",\n {\n title: \"List memory assets\",\n description: \"List active assets for the agent, newest first, optionally by key prefix.\",\n inputSchema: {\n prefix: z.string().optional().describe(\"Only keys starting with this prefix\"),\n limit: z.number().int().positive().optional().describe(\"Max records (default 100)\"),\n },\n },\n async ({ prefix, limit }) => {\n const records = await store.list(prefix, limit);\n return { content: [{ type: \"text\", text: JSON.stringify({ records }, null, 2) }] };\n },\n );\n\n server.registerTool(\n \"s3.delete\",\n {\n title: \"Delete memory asset\",\n description: \"Remove an asset's body and deactivate its index entry (soft delete).\",\n inputSchema: {\n keyOrId: z.string().min(1).describe(\"Logical key or record id\"),\n },\n },\n async ({ keyOrId }) => {\n const record = await store.delete(keyOrId);\n if (!record) {\n return {\n isError: true,\n content: [{ type: \"text\", text: `No active memory asset matches \"${keyOrId}\"` }],\n };\n }\n return { content: [{ type: \"text\", text: JSON.stringify({ record }, null, 2) }] };\n },\n );\n\n // memory://index — a browsable listing of every active asset.\n server.registerResource(\n \"memory-index\",\n \"memory://index\",\n {\n title: `Memory index for ${agent}`,\n description: \"All active memory assets for this agent (key, category, timestamps).\",\n mimeType: \"application/json\",\n },\n async (uri) => {\n const records = await store.list(undefined, 1000);\n return {\n contents: [\n { uri: uri.href, mimeType: \"application/json\", text: JSON.stringify({ agent, records }, null, 2) },\n ],\n };\n },\n );\n\n return server;\n}\n\n/** Serve over stdio — the default transport for `kohala memory serve`. */\nexport async function serveStdio(store: MemoryStore, agent: string): Promise<void> {\n const server = buildMemoryMcpServer(store, agent);\n const transport = new StdioServerTransport();\n await server.connect(transport);\n}\n\n/**\n * Serve over streamable HTTP on 127.0.0.1:<port> at /mcp.\n *\n * Runs in stateless mode: each request gets a fresh server + transport pair,\n * which keeps the implementation simple and is exactly what MCP Inspector and\n * one-shot clients expect. Returns the http.Server for lifecycle control.\n */\nexport async function serveHttp(\n store: MemoryStore,\n agent: string,\n port: number,\n): Promise<http.Server> {\n const httpServer = http.createServer((request, response) => {\n void (async () => {\n const url = new URL(request.url ?? \"/\", \"http://127.0.0.1\");\n if (url.pathname !== \"/mcp\") {\n response.writeHead(404, { \"content-type\": \"application/json\" });\n response.end(JSON.stringify({ error: \"Not found. The MCP endpoint is POST /mcp\" }));\n return;\n }\n if (request.method !== \"POST\") {\n response.writeHead(405, { \"content-type\": \"application/json\" });\n response.end(\n JSON.stringify({ error: \"Stateless MCP server: only POST /mcp is supported\" }),\n );\n return;\n }\n let raw = \"\";\n request.on(\"data\", (chunk) => {\n raw += chunk;\n });\n request.on(\"end\", () => {\n void (async () => {\n let body: unknown;\n try {\n body = JSON.parse(raw);\n } catch {\n response.writeHead(400, { \"content-type\": \"application/json\" });\n response.end(JSON.stringify({ error: \"Request body is not valid JSON\" }));\n return;\n }\n const server = buildMemoryMcpServer(store, agent);\n const transport = new StreamableHTTPServerTransport({\n sessionIdGenerator: undefined, // stateless\n });\n response.on(\"close\", () => {\n void transport.close();\n void server.close();\n });\n await server.connect(transport);\n await transport.handleRequest(request, response, body);\n })();\n });\n })();\n });\n\n await new Promise<void>((resolve) => {\n httpServer.listen(port, \"127.0.0.1\", resolve);\n });\n return httpServer;\n}\n","import readline from \"node:readline\";\nimport type { Command } from \"commander\";\nimport pc from \"picocolors\";\nimport { saveApiKey } from \"../deploy/credentials.js\";\n\n/**\n * `kohala login` — save a pk_ API key to ~/.kohala/credentials.json (0600).\n * The KOHALA_API_KEY environment variable always takes precedence over the\n * saved key, which is the right default for CI.\n */\nexport function registerLoginCommand(program: Command): void {\n program\n .command(\"login\")\n .option(\"--api-key <key>\", \"provide the key non-interactively\")\n .description(\"Save your Kohala API key for `kohala deploy`\")\n .action(async (options: { apiKey?: string }) => {\n let apiKey = options.apiKey;\n if (!apiKey) {\n apiKey = await promptHidden(\n \"Paste your Kohala API key (starts with pk_, from kohala.ai account settings): \",\n );\n }\n if (!apiKey) {\n throw new Error(\"No API key provided.\");\n }\n const savedTo = saveApiKey(apiKey.trim());\n console.log(pc.green(`API key saved to ${savedTo} (permissions 600).`));\n console.log(pc.dim(\"Note: the KOHALA_API_KEY environment variable overrides this file.\"));\n });\n}\n\n/** Prompt without echoing the key back to the terminal. */\nfunction promptHidden(question: string): Promise<string> {\n return new Promise((resolve) => {\n const rl = readline.createInterface({ input: process.stdin, output: process.stderr });\n const stdin = process.stdin as NodeJS.ReadStream & { setRawMode?: (mode: boolean) => void };\n process.stderr.write(question);\n if (stdin.isTTY && stdin.setRawMode) {\n stdin.setRawMode(true);\n let value = \"\";\n const onData = (chunk: Buffer) => {\n const char = chunk.toString(\"utf8\");\n if (char === \"\\n\" || char === \"\\r\" || char === \"\\u0004\") {\n stdin.setRawMode?.(false);\n stdin.off(\"data\", onData);\n rl.close();\n process.stderr.write(\"\\n\");\n resolve(value);\n } else if (char === \"\\u0003\") {\n // ctrl-c\n stdin.setRawMode?.(false);\n rl.close();\n process.exit(130);\n } else if (char === \"\\u007f\") {\n value = value.slice(0, -1);\n } else {\n value += char;\n }\n };\n stdin.on(\"data\", onData);\n } else {\n rl.question(\"\", (answer) => {\n rl.close();\n resolve(answer);\n });\n }\n });\n}\n","import fs from \"node:fs\";\nimport os from \"node:os\";\nimport path from \"node:path\";\n\n/**\n * Credential storage for `kohala login` / `kohala deploy`.\n *\n * Precedence: the KOHALA_API_KEY environment variable always wins; otherwise\n * the key saved by `kohala login` in ~/.kohala/credentials.json is used.\n * The file is written with mode 600 (owner read/write only).\n */\n\n/** Path of the credentials file (~/.kohala/credentials.json). */\nexport function credentialsPath(): string {\n return path.join(os.homedir(), \".kohala\", \"credentials.json\");\n}\n\ninterface CredentialsFile {\n apiKey: string;\n}\n\n/** Persist a pk_ API key with restrictive permissions. */\nexport function saveApiKey(apiKey: string): string {\n if (!apiKey.startsWith(\"pk_\")) {\n throw new Error('Kohala API keys start with \"pk_\". Check the key and try again.');\n }\n const filePath = credentialsPath();\n fs.mkdirSync(path.dirname(filePath), { recursive: true });\n const payload: CredentialsFile = { apiKey };\n fs.writeFileSync(filePath, JSON.stringify(payload, null, 2), { encoding: \"utf8\", mode: 0o600 });\n fs.chmodSync(filePath, 0o600);\n return filePath;\n}\n\n/**\n * Resolve the API key: env var first, then the saved credentials file.\n * Returns null when neither is configured.\n */\nexport function resolveApiKey(env: NodeJS.ProcessEnv = process.env): string | null {\n if (env.KOHALA_API_KEY) return env.KOHALA_API_KEY;\n const filePath = credentialsPath();\n if (!fs.existsSync(filePath)) return null;\n try {\n const parsed = JSON.parse(fs.readFileSync(filePath, \"utf8\")) as CredentialsFile;\n return parsed.apiKey ?? null;\n } catch {\n throw new Error(\n `${filePath} is corrupted — delete it and run \"kohala login\" again.`,\n );\n }\n}\n","import path from \"node:path\";\nimport type { Command } from \"commander\";\nimport pc from \"picocolors\";\nimport { loadManifest } from \"../manifest/load.js\";\nimport { resolveApiKey } from \"../deploy/credentials.js\";\nimport {\n buildDeployPlan,\n DEFAULT_BASE_URL,\n DeployError,\n KohalaClient,\n} from \"../deploy/client.js\";\n\n/**\n * `kohala deploy <agent>` — push a locally-validated agent to the hosted\n * platform. Deploy is additive and idempotent on the agent name; it never\n * deletes anything remotely. `--dry-run` prints exactly what would be sent.\n */\nexport function registerDeployCommand(program: Command): void {\n program\n .command(\"deploy\")\n .argument(\"<agent>\", \"agent directory (containing kohala.json)\")\n .option(\"--dry-run\", \"print the payloads without sending anything\")\n .option(\"--base-url <url>\", \"API base URL\", DEFAULT_BASE_URL)\n .option(\"--run\", \"trigger a manual run after deploying\")\n .description(\"Deploy an agent to kohala.ai (idempotent on agent name)\")\n .action(\n async (\n agent: string,\n options: { dryRun?: boolean; baseUrl: string; run?: boolean },\n ) => {\n const agentDir = path.resolve(process.cwd(), agent);\n const manifest = loadManifest(agentDir);\n const plan = buildDeployPlan(manifest, agentDir);\n\n if (options.dryRun) {\n console.log(pc.cyan(\"Dry run — nothing will be sent. Deploy plan:\"));\n console.log(\"\");\n console.log(pc.bold(\"1. POST /api/v1/agents (idempotent on name)\"));\n console.log(JSON.stringify(plan.agent, null, 2));\n for (const skill of plan.skills) {\n console.log(\"\");\n console.log(pc.bold(`2. POST /api/v1/agents/:id/skills — \"${skill.name}\"`));\n console.log(\n JSON.stringify(\n { ...skill, code: `<${Buffer.byteLength(skill.code)} bytes of ${skill.scriptFilename}>` },\n null,\n 2,\n ),\n );\n }\n console.log(\"\");\n console.log(pc.bold(\"3. PUT /api/v1/agents/:id/quota\"));\n console.log(JSON.stringify(plan.quota, null, 2));\n if (options.run) {\n console.log(\"\");\n console.log(pc.bold(\"4. POST /api/v1/agents/:id/agent-runs/manual\"));\n }\n return;\n }\n\n const apiKey = resolveApiKey();\n if (!apiKey) {\n throw new Error(\n \"No API key configured. Run `kohala login` (or set KOHALA_API_KEY) first. Keys come from your kohala.ai account settings.\",\n );\n }\n\n const client = new KohalaClient(apiKey, options.baseUrl);\n console.log(pc.cyan(`Deploying \"${manifest.name}\" to ${options.baseUrl} ...`));\n\n const upserted = await client.upsertAgent(plan.agent);\n console.log(\n pc.green(` ✔ agent ${upserted.created ? \"created\" : \"updated\"} (id ${upserted.id})`),\n );\n\n for (const skill of plan.skills) {\n await client.upsertSkill(upserted.id, skill);\n console.log(pc.green(` ✔ skill \"${skill.name}\" uploaded (${skill.scriptFilename})`));\n }\n\n await client.setQuota(upserted.id, plan.quota);\n console.log(\n pc.green(\n ` ✔ quota set (perRun=${plan.quota.perRunTokens}, perDay=${plan.quota.perDayTokens})`,\n ),\n );\n\n if (options.run) {\n try {\n const runUrl = await client.triggerManualRun(upserted.id);\n console.log(pc.green(` ✔ manual run triggered: ${runUrl}`));\n } catch (error) {\n // Newly deployed agents start disabled on the platform; a manual\n // run returns 409 until the owner enables the agent. Explain the\n // fix instead of surfacing a raw API error — but keep a non-zero\n // exit so scripts relying on --run notice the run did not happen.\n if (error instanceof DeployError && error.status === 409) {\n console.error(\n pc.yellow(\n ` ✖ manual run not started: the agent is not enabled on the platform yet.`,\n ),\n );\n console.error(\n pc.dim(\n ` Deploy itself succeeded. Enable \"${manifest.name}\" in your kohala.ai dashboard, ` +\n `then re-run \\`kohala deploy ${agent} --run\\` (or trigger a run from the dashboard).`,\n ),\n );\n process.exitCode = 1;\n return;\n }\n throw error;\n }\n }\n\n console.log(\"\");\n console.log(pc.green(`Deployed. Deploys are additive — nothing was deleted remotely.`));\n },\n );\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport type { AgentManifest } from \"../manifest/schema.js\";\n\n/**\n * REST client for deploying agents to the hosted Kohala platform (A.5).\n *\n * Deploy flow (all idempotent / additive — deploy NEVER deletes remotely):\n * 1. POST /api/v1/agents (idempotent on name)\n * 2. POST /api/v1/agents/:id/skills (one per manifest skill)\n * 3. PUT /api/v1/agents/:id/quota (the caps)\n * 4. optional: POST /api/v1/agents/:id/agent-runs/manual\n */\n\n/** Default production API target; override with --base-url for staging. */\nexport const DEFAULT_BASE_URL = \"https://kohala.ai\";\n\n/** Payload for creating/updating the agent — the platform's field names. */\nexport interface AgentPayload {\n name: string;\n charter: string;\n toolAllowlist: string[];\n // The platform stores \"wrap\" under its own enum name \"script\" (verified\n // live 2026-08-10: \"llm\" round-trips as \"llm\"); this is a display-side\n // mapping, not data loss — send the manifest value as-is.\n runtimeMode: \"wrap\" | \"llm\";\n schedule?: string;\n}\n\n/** Payload for uploading one skill. */\nexport interface SkillPayload {\n name: string;\n scriptFilename: string;\n description: string;\n // The platform's canonical field for script source is `code` (BUG-067:\n // the old `scriptContent` field is not in the platform schema and was\n // silently dropped, leaving the skill without a runnable script asset).\n code: string;\n}\n\n/** Payload for the quota update — the platform's cap field names. */\nexport interface QuotaPayload {\n perRunTokens: number;\n perDayTokens: number;\n billingTokens?: number;\n billingPeriod?: \"day\" | \"week\" | \"month\";\n}\n\n/** Everything `kohala deploy` will send, assembled before any network call. */\nexport interface DeployPlan {\n agent: AgentPayload;\n skills: SkillPayload[];\n quota: QuotaPayload;\n}\n\n/** Map a validated manifest (+ its skill scripts on disk) onto API payloads. */\nexport function buildDeployPlan(manifest: AgentManifest, agentDir: string): DeployPlan {\n const skills: SkillPayload[] = Object.entries(manifest.skills).map(([name, scriptFilename]) => {\n const scriptPath = path.join(agentDir, \"skills\", scriptFilename);\n if (!fs.existsSync(scriptPath)) {\n throw new Error(\n `Skill \"${name}\" points at ${scriptFilename}, but ${scriptPath} does not exist.`,\n );\n }\n return {\n name,\n scriptFilename,\n description: `Skill \"${name}\" of agent \"${manifest.name}\"`,\n code: fs.readFileSync(scriptPath, \"utf8\"),\n };\n });\n\n return {\n agent: {\n name: manifest.name,\n charter: manifest.charter,\n toolAllowlist: manifest.toolAllowlist,\n runtimeMode: manifest.runtimeMode,\n ...(manifest.schedule ? { schedule: manifest.schedule } : {}),\n },\n skills,\n quota: {\n perRunTokens: manifest.caps.perRunTokens,\n perDayTokens: manifest.caps.perDayTokens,\n ...(manifest.caps.billingTokens !== undefined\n ? { billingTokens: manifest.caps.billingTokens }\n : {}),\n ...(manifest.caps.billingPeriod !== undefined\n ? { billingPeriod: manifest.caps.billingPeriod }\n : {}),\n },\n };\n}\n\n/** Error with a user-actionable message for known HTTP statuses. */\nexport class DeployError extends Error {\n constructor(\n readonly status: number,\n message: string,\n ) {\n super(message);\n this.name = \"DeployError\";\n }\n}\n\n/** Result of the agent upsert — the platform reports created vs updated. */\nexport interface AgentUpsertResult {\n id: string;\n created: boolean;\n}\n\n/** Thin authenticated HTTP client for the Kohala public REST API. */\nexport class KohalaClient {\n constructor(\n private readonly apiKey: string,\n private readonly baseUrl: string = DEFAULT_BASE_URL,\n ) {}\n\n private async request(method: string, apiPath: string, body?: unknown): Promise<unknown> {\n const response = await fetch(`${this.baseUrl}${apiPath}`, {\n method,\n headers: {\n \"content-type\": \"application/json\",\n authorization: `Bearer ${this.apiKey}`,\n },\n ...(body !== undefined ? { body: JSON.stringify(body) } : {}),\n });\n\n if (response.status === 401) {\n throw new DeployError(\n 401,\n \"401 Unauthorized: your API key was rejected. Check KOHALA_API_KEY or re-run `kohala login` with a fresh pk_ key from your Kohala account settings.\",\n );\n }\n if (response.status === 403) {\n throw new DeployError(\n 403,\n \"403 Forbidden: your plan does not allow this operation. Check your plan at https://kohala.ai or contact support.\",\n );\n }\n if (!response.ok) {\n const text = await response.text();\n throw new DeployError(\n response.status,\n `Kohala API error ${response.status} on ${method} ${apiPath}: ${text.slice(0, 500)}`,\n );\n }\n const text = await response.text();\n return text ? (JSON.parse(text) as unknown) : null;\n }\n\n /** Step 1: create or update the agent (idempotent on name). */\n async upsertAgent(payload: AgentPayload): Promise<AgentUpsertResult> {\n const data = (await this.request(\"POST\", \"/api/v1/agents\", payload)) as {\n id?: string;\n agentId?: string;\n created?: boolean;\n };\n const id = data.id ?? data.agentId;\n if (!id) {\n throw new DeployError(500, \"Platform response did not include an agent id\");\n }\n return { id, created: data.created ?? false };\n }\n\n /** Step 2: upload one skill (script content inline). */\n async upsertSkill(agentId: string, payload: SkillPayload): Promise<void> {\n const data = (await this.request(\"POST\", `/api/v1/agents/${agentId}/skills`, payload)) as {\n script?: { stage?: string };\n } | null;\n // BUG-067: a skill without a production-stage script asset is skipped by\n // every run. The platform confirms attachment via `script.stage`; treat\n // its absence as a hard failure rather than reporting a green tick.\n if (data?.script?.stage !== \"production\") {\n throw new DeployError(\n 500,\n `Platform accepted skill \"${payload.name}\" but did not attach a runnable script ` +\n `(expected script.stage \"production\" in the response). The deployed agent would ` +\n `no-op on every run — aborting.`,\n );\n }\n }\n\n /** Step 3: set the token caps. */\n async setQuota(agentId: string, payload: QuotaPayload): Promise<void> {\n await this.request(\"PUT\", `/api/v1/agents/${agentId}/quota`, payload);\n }\n\n /** Optional step 4 (--run): trigger a manual run and return its link. */\n async triggerManualRun(agentId: string): Promise<string> {\n const data = (await this.request(\"POST\", `/api/v1/agents/${agentId}/agent-runs/manual`)) as {\n runUrl?: string;\n url?: string;\n id?: string;\n };\n return data.runUrl ?? data.url ?? `${this.baseUrl}/agents/${agentId}/runs/${data.id ?? \"\"}`;\n }\n}\n","import type { Command } from \"commander\";\nimport pc from \"picocolors\";\nimport { findPython } from \"../emulator/python.js\";\nimport { detectLlmProvider } from \"../emulator/llm-client.js\";\nimport { resolveApiKey, credentialsPath } from \"../deploy/credentials.js\";\n\n/**\n * `kohala doctor` — check the local environment and report what works.\n * Nothing here is fatal; the doctor tells you what each missing piece limits.\n */\nexport function registerDoctorCommand(program: Command): void {\n program\n .command(\"doctor\")\n .description(\"Check your environment: Node, Python, LLM keys, API key, DATABASE_URL\")\n .action(async () => {\n const ok = (label: string, detail: string) =>\n console.log(`${pc.green(\"✔\")} ${label} ${pc.dim(detail)}`);\n const warn = (label: string, detail: string) =>\n console.log(`${pc.yellow(\"•\")} ${label} ${pc.dim(detail)}`);\n\n // Node version (package.json engines requires >= 20).\n const nodeMajor = Number(process.versions.node.split(\".\")[0]);\n if (nodeMajor >= 20) {\n ok(`node ${process.versions.node}`, \"(>= 20 required)\");\n } else {\n console.log(\n `${pc.red(\"✘\")} node ${process.versions.node} — the devkit requires Node 20 or newer.`,\n );\n }\n\n // Python (needed to run wrap-mode skills).\n try {\n const python = await findPython();\n ok(`python (${python})`, \"wrap-mode skills can run\");\n } catch {\n warn(\"python 3 not found\", \"wrap-mode `kohala run --local` will not work until installed\");\n }\n\n // LLM keys.\n // ANTHROPIC_API_KEY → llm.complete (wrap mode) + llm mode tool-use loop\n // GEMINI_API_KEY → llm.complete (wrap mode) only; llm mode needs Anthropic\n const provider = detectLlmProvider();\n const hasAnthropic = Boolean(process.env.ANTHROPIC_API_KEY);\n if (hasAnthropic) {\n ok(\"LLM key (anthropic)\", \"llm.complete and llm mode both available\");\n } else if (provider === \"gemini\") {\n ok(\"LLM key (gemini)\", \"llm.complete available in wrap mode\");\n warn(\n \"no ANTHROPIC_API_KEY\",\n \"llm mode (runtimeMode: \\\"llm\\\") requires Anthropic — GEMINI_API_KEY covers llm.complete only\",\n );\n } else {\n warn(\n \"no ANTHROPIC_API_KEY / GEMINI_API_KEY\",\n \"llm.complete and llm-mode runs will fail with NO_LLM_KEY\",\n );\n }\n\n // Kohala API key (needed only for deploy).\n const apiKey = resolveApiKey();\n if (apiKey) {\n const source = process.env.KOHALA_API_KEY ? \"KOHALA_API_KEY env\" : credentialsPath();\n ok(\"Kohala API key\", `from ${source} — kohala deploy ready`);\n } else {\n warn(\"no Kohala API key\", \"run `kohala login` before `kohala deploy` (local dev needs no account)\");\n }\n\n // DATABASE_URL (needed only for the postgres memory backend).\n if (process.env.DATABASE_URL) {\n ok(\"DATABASE_URL set\", \"postgres memory backend available\");\n } else {\n warn(\"DATABASE_URL not set\", \"memory uses the file backend (that is the default anyway)\");\n }\n\n console.log(\"\");\n console.log(pc.dim(\"Everything local works without an account — deploy is the only step that needs one.\"));\n });\n}\n"],"mappings":"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;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA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","names":["pc","program","path","pc","fs","path","path","fs","program","path","pc","path","pc","fs","path","fs","path","path","fs","record","crypto","crypto","crypto","path","execa","fs","path","fs","path","path","fs","version","fs","fs","crypto","path","execa","program","path","pc","fs","path","pc","fs","pc","program","path","fs","pc","fs","path","pc","http","z","z","http","program","path","fs","pc","pc","fs","path","program","pc","path","pc","fs","path","text","program","path","pc","pc","program","pc","require","pc"]}
|
|
1
|
+
{"version":3,"sources":["../../src/cli/index.ts","../../src/cli/init.ts","../../src/manifest/schema.ts","../../src/cli/validate.ts","../../src/manifest/load.ts","../../src/manifest/known-tools.ts","../../src/cli/run.ts","../../src/memory/file.ts","../../src/memory/store.ts","../../src/util/lock.ts","../../src/memory/postgres.ts","../../src/memory/create.ts","../../src/emulator/runner.ts","../../src/trace/writer.ts","../../src/emulator/tokens.ts","../../src/emulator/validators.ts","../../src/sdk/rpc.ts","../../src/sdk/dispatch.ts","../../src/emulator/allowlist.ts","../../src/emulator/llm-client.ts","../../src/emulator/llm-mode.ts","../../src/emulator/python.ts","../../src/cli/trace.ts","../../src/trace/reader.ts","../../src/trace/format.ts","../../src/cli/memory-serve.ts","../../src/mcp/server.ts","../../src/cli/login.ts","../../src/deploy/credentials.ts","../../src/cli/deploy.ts","../../src/deploy/client.ts","../../src/cli/doctor.ts"],"sourcesContent":["import { createRequire } from \"node:module\";\nimport { Command } from \"commander\";\nimport pc from \"picocolors\";\nimport { registerInitCommand } from \"./init.js\";\nimport { registerValidateCommand } from \"./validate.js\";\nimport { registerRunCommand } from \"./run.js\";\nimport { registerTraceCommand } from \"./trace.js\";\nimport { registerMemoryCommand } from \"./memory-serve.js\";\nimport { registerLoginCommand } from \"./login.js\";\nimport { registerDeployCommand } from \"./deploy.js\";\nimport { registerDoctorCommand } from \"./doctor.js\";\n\n/**\n * The `kohala` CLI entry point.\n *\n * Command files under src/cli/ are deliberately thin: they parse flags, call\n * into lib code (manifest/, emulator/, memory/, deploy/), and format output.\n * All behavior lives in the libraries so it is unit-testable without a TTY.\n */\n\nconst require = createRequire(import.meta.url);\n// Version comes straight from package.json so `kohala --version` can never drift.\nconst { version } = require(\"../../package.json\") as { version: string };\n\nconst program = new Command();\n\nprogram\n .name(\"kohala\")\n .description(\n \"Kohala Devkit — build and run agents entirely on your own machine, then push the same agent to Kohala when you want it hosted.\",\n )\n .version(version);\n\nregisterInitCommand(program);\nregisterValidateCommand(program);\nregisterRunCommand(program);\nregisterTraceCommand(program);\nregisterMemoryCommand(program);\nregisterLoginCommand(program);\nregisterDeployCommand(program);\nregisterDoctorCommand(program);\n\nprogram.parseAsync(process.argv).catch((error: Error) => {\n // Central failure path: every command failure lands here, loudly and red.\n console.error(pc.red(`\\n${error.message}`));\n process.exitCode = 1;\n});\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport type { Command } from \"commander\";\nimport pc from \"picocolors\";\nimport { manifestSchema } from \"../manifest/schema.js\";\n\n/**\n * `kohala init <name>` — scaffold a new agent from templates/.\n *\n * The scaffold is a complete, runnable agent: kohala.json, skills/main.py (a\n * working example that writes to memory), skills/_tools.py (the local SDK),\n * and a README. `kohala run <name> --local` works immediately after init.\n */\n\n/** Locate the templates directory relative to the built CLI bundle. */\nfunction templatesDir(): string {\n // dist/cli/index.js -> ../../templates ; src/cli/init.ts -> ../../templates\n const here = path.dirname(fileURLToPath(import.meta.url));\n const candidates = [\n path.resolve(here, \"..\", \"..\", \"templates\"),\n path.resolve(here, \"..\", \"..\", \"..\", \"templates\"),\n ];\n for (const candidate of candidates) {\n if (fs.existsSync(path.join(candidate, \"kohala.json\"))) return candidate;\n }\n throw new Error(`Could not locate the devkit templates directory (looked in: ${candidates.join(\", \")})`);\n}\n\n/** Recursively copy the template tree, substituting {{AGENT_NAME}}. */\nfunction copyTemplates(sourceDir: string, targetDir: string, agentName: string): void {\n fs.mkdirSync(targetDir, { recursive: true });\n for (const entry of fs.readdirSync(sourceDir, { withFileTypes: true })) {\n const sourcePath = path.join(sourceDir, entry.name);\n const targetPath = path.join(targetDir, entry.name);\n if (entry.isDirectory()) {\n copyTemplates(sourcePath, targetPath, agentName);\n } else {\n const contents = fs.readFileSync(sourcePath, \"utf8\");\n fs.writeFileSync(targetPath, contents.replaceAll(\"{{AGENT_NAME}}\", agentName), \"utf8\");\n }\n }\n}\n\nexport function registerInitCommand(program: Command): void {\n program\n .command(\"init\")\n .argument(\"<name>\", \"agent name (also the directory name)\")\n .description(\"Scaffold a new agent: kohala.json, a working skill, and the local SDK\")\n .action((name: string) => {\n const nameCheck = manifestSchema.shape.name.safeParse(name);\n if (!nameCheck.success) {\n throw new Error(\n `\"${name}\" is not a valid agent name: ${nameCheck.error.issues[0]?.message ?? \"invalid\"}`,\n );\n }\n const targetDir = path.resolve(process.cwd(), name);\n if (fs.existsSync(targetDir)) {\n throw new Error(`${targetDir} already exists — pick a new name or remove the directory.`);\n }\n copyTemplates(templatesDir(), targetDir, name);\n console.log(pc.green(`Created agent \"${name}\" in ${targetDir}`));\n console.log(\"\");\n console.log(\"Next steps:\");\n console.log(pc.cyan(` kohala validate ${name}`));\n console.log(pc.cyan(` kohala run ${name} --local`));\n console.log(pc.cyan(` kohala trace ${name}`));\n });\n}\n","import { z } from \"zod\";\n\n/**\n * Zod schema for `kohala.json` — the agent manifest.\n *\n * This is the devkit's half of the compatibility contract with the hosted\n * Kohala platform. Every field here maps 1:1 onto a platform field:\n *\n * | Manifest field | Platform field |\n * | -------------------- | ------------------------ |\n * | `name` | agent name (deploy is idempotent on name) |\n * | `charter` | `agentCharter` |\n * | `toolAllowlist` | `agentToolAllowlist` |\n * | `runtimeMode` | `agentRuntimeMode` |\n * | `skills` | `agentSkills` |\n * | `schedule` | `agentScheduleCron` |\n * | `caps.perRunTokens` | `agentPerRunTokenCap` |\n * | `caps.perDayTokens` | `agentPerDayTokenCap` |\n * | `caps.billingTokens` | `agentBillingCapTokens` |\n * | `caps.billingPeriod` | `agentBillingCapPeriod` |\n * | `validators` | agent validators |\n *\n * Do not rename fields here without a matching platform change — the whole\n * point of the devkit is that a local agent round-trips losslessly.\n */\n\n/** Billing periods accepted by the platform for `agentBillingCapPeriod`. */\nexport const BILLING_PERIODS = [\"day\", \"week\", \"month\"] as const;\n\n/**\n * `shape` validator — the run output must exist and be at least `minBytes`\n * bytes long. This is the platform's cheapest sanity check: \"did the agent\n * actually produce something?\"\n */\nexport const shapeValidatorSchema = z\n .object({\n type: z.literal(\"shape\"),\n minBytes: z.number().int().nonnegative(),\n })\n .strict();\n\n/**\n * `freshness` validator — a referenced memory asset (by logical key) must be\n * newer than `maxAgeHours`. The platform uses this to catch agents that\n * \"succeed\" without actually refreshing their data.\n */\nexport const freshnessValidatorSchema = z\n .object({\n type: z.literal(\"freshness\"),\n /** Logical memory key of the asset that must be fresh. */\n asset: z.string().min(1),\n maxAgeHours: z.number().positive(),\n })\n .strict();\n\n/**\n * `invariant` validator — the run output must match (or must NOT match) a\n * regular expression. `mustMatch: false` inverts the check.\n */\nexport const invariantValidatorSchema = z\n .object({\n type: z.literal(\"invariant\"),\n /** JavaScript-flavored regular expression source (no delimiters). */\n pattern: z.string().min(1),\n /** When false, the output must NOT match the pattern. Defaults to true. */\n mustMatch: z.boolean().default(true),\n })\n .strict();\n\n/** All validator types supported by the platform, with identical names. */\nexport const validatorSchema = z.discriminatedUnion(\"type\", [\n shapeValidatorSchema,\n freshnessValidatorSchema,\n invariantValidatorSchema,\n]);\n\n/**\n * Token caps. The local emulator enforces these exactly like the hosted\n * platform (see emulator/), but never bills anything — token counts are for\n * cap enforcement and trace visibility only.\n */\nexport const capsSchema = z\n .object({\n /** Hard token ceiling for a single shift (platform: agentPerRunTokenCap). */\n perRunTokens: z.number().int().positive(),\n /** Cumulative token ceiling per UTC day (platform: agentPerDayTokenCap). */\n perDayTokens: z.number().int().positive(),\n /** Billing-period token cap (platform: agentBillingCapTokens). Ignored locally. */\n billingTokens: z.number().int().positive().optional(),\n /** Billing period for billingTokens (platform: agentBillingCapPeriod). */\n billingPeriod: z.enum(BILLING_PERIODS).optional(),\n })\n .strict()\n .refine((caps) => caps.billingTokens === undefined || caps.billingPeriod !== undefined, {\n message: \"caps.billingPeriod is required when caps.billingTokens is set\",\n path: [\"billingPeriod\"],\n });\n\n/** Agent names double as deploy identity and directory names — keep them tame. */\nconst nameSchema = z\n .string()\n .min(1)\n .max(64)\n .regex(\n /^[a-z0-9][a-z0-9_-]*$/i,\n \"must start with a letter or digit and contain only letters, digits, '-' and '_'\",\n );\n\n/** Full manifest schema for kohala.json. */\nexport const manifestSchema = z\n .object({\n name: nameSchema,\n /** The agent's mission text (platform: agentCharter). */\n charter: z.string().min(1),\n /**\n * Tools the agent may call, e.g. [\"s3.put\", \"http.post_json\"].\n * Everything not on this list is denied loudly at runtime.\n */\n toolAllowlist: z.array(z.string().min(1)).default([]),\n /**\n * \"wrap\" — execute the skill script directly and validate its output.\n * \"llm\" — run a real tool-use loop against the developer's own LLM key.\n */\n runtimeMode: z.enum([\"wrap\", \"llm\"]),\n /** Map of skill name -> script filename, e.g. {\"collect\": \"main.py\"}. */\n skills: z.record(z.string().min(1), z.string().min(1)).default({}),\n /** Cron expression. Used only on deploy; local runs are always manual. */\n schedule: z.string().min(1).optional(),\n caps: capsSchema,\n validators: z.array(validatorSchema).default([]),\n })\n .strict();\n\n/** A parsed, validated kohala.json. */\nexport type AgentManifest = z.infer<typeof manifestSchema>;\n/** A single validator entry. */\nexport type AgentValidator = z.infer<typeof validatorSchema>;\n/** Token caps block. */\nexport type AgentCaps = z.infer<typeof capsSchema>;\n","import path from \"node:path\";\nimport type { Command } from \"commander\";\nimport pc from \"picocolors\";\nimport { loadManifest, ManifestError } from \"../manifest/load.js\";\nimport { unknownToolIds } from \"../manifest/known-tools.js\";\n\n/**\n * `kohala validate <agent>` — load and validate the agent's kohala.json,\n * printing every problem with a fix hint. Exit code 1 on any problem.\n */\nexport function registerValidateCommand(program: Command): void {\n program\n .command(\"validate\")\n .argument(\"<agent>\", \"agent directory (containing kohala.json)\")\n .option(\n \"--allow-unknown-tools\",\n \"do not fail on tool ids missing from the bundled catalog snapshot\",\n )\n .description(\"Validate an agent's kohala.json and print precise errors\")\n .action((agent: string, options: { allowUnknownTools?: boolean }) => {\n const agentDir = path.resolve(process.cwd(), agent);\n try {\n const manifest = loadManifest(agentDir);\n // Catch typo'd / unknown tool ids offline, mirroring the server-side\n // deploy gate (which enforces the live catalog authoritatively).\n const unknown = unknownToolIds(manifest.toolAllowlist);\n if (unknown.length > 0) {\n const msg =\n `toolAllowlist contains tool id(s) not in the Kohala tool catalog: ` +\n unknown.join(\", \");\n if (options.allowUnknownTools) {\n console.warn(pc.yellow(`warning: ${msg}`));\n } else {\n console.error(pc.red(msg));\n console.error(\n pc.dim(\n \" If these are new platform tools the bundled snapshot doesn't know yet, re-run with --allow-unknown-tools (the deploy endpoint will still verify against the live catalog).\",\n ),\n );\n process.exitCode = 1;\n return;\n }\n }\n console.log(pc.green(`kohala.json for \"${manifest.name}\" is valid.`));\n console.log(\n pc.dim(\n ` runtimeMode=${manifest.runtimeMode} skills=${Object.keys(manifest.skills).length} ` +\n `validators=${manifest.validators.length} allowlist=[${manifest.toolAllowlist.join(\", \")}]`,\n ),\n );\n } catch (error) {\n if (error instanceof ManifestError) {\n console.error(pc.red(error.message));\n for (const problem of error.problems) {\n console.error(pc.red(` • ${problem}`));\n }\n process.exitCode = 1;\n return;\n }\n throw error;\n }\n });\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport type { ZodError, ZodIssue } from \"zod\";\nimport { manifestSchema, type AgentManifest } from \"./schema.js\";\n\n/** Error thrown when a kohala.json cannot be read, parsed, or validated. */\nexport class ManifestError extends Error {\n /** One human-readable problem per line, each with a fix hint when we have one. */\n readonly problems: string[];\n\n constructor(message: string, problems: string[] = []) {\n super(message);\n this.name = \"ManifestError\";\n this.problems = problems;\n }\n}\n\n/**\n * Fix hints keyed by the top-level manifest field an issue occurred under.\n * These show up next to validation errors so a broken manifest is\n * self-explanatory without opening the docs.\n */\nconst FIELD_HINTS: Record<string, string> = {\n name: 'use a short identifier like \"my-agent\" (letters, digits, \"-\", \"_\")',\n charter: \"write the agent's mission as a non-empty string\",\n toolAllowlist: 'list allowed tool names, e.g. [\"s3.put\", \"http.post_json\"]',\n runtimeMode: 'must be \"wrap\" (script wrapper) or \"llm\" (tool-use loop)',\n skills: 'map skill name to script filename, e.g. {\"collect\": \"main.py\"}',\n schedule: 'use a cron expression like \"0 9 * * *\" (only used on deploy)',\n caps: \"set caps.perRunTokens and caps.perDayTokens as positive integers\",\n validators: 'each validator needs a \"type\" of \"shape\", \"freshness\" or \"invariant\"',\n};\n\n/** Turn one Zod issue into a \"path: message (hint: ...)\" line. */\nfunction formatIssue(issue: ZodIssue): string {\n const issuePath = issue.path.length > 0 ? issue.path.join(\".\") : \"(root)\";\n const topLevelField = String(issue.path[0] ?? \"\");\n const hint = FIELD_HINTS[topLevelField];\n const hintSuffix = hint ? ` (hint: ${hint})` : \"\";\n return `${issuePath}: ${issue.message}${hintSuffix}`;\n}\n\n/** Format a full ZodError into per-issue problem lines. */\nexport function formatManifestIssues(error: ZodError): string[] {\n return error.issues.map(formatIssue);\n}\n\n/** Absolute path of the kohala.json inside an agent directory. */\nexport function manifestPath(agentDir: string): string {\n return path.join(agentDir, \"kohala.json\");\n}\n\n/**\n * Load and validate the kohala.json inside `agentDir`.\n *\n * Fails loudly with a ManifestError that lists every problem plus a fix hint —\n * never returns a partially-valid manifest.\n */\nexport function loadManifest(agentDir: string): AgentManifest {\n const filePath = manifestPath(agentDir);\n if (!fs.existsSync(filePath)) {\n throw new ManifestError(\n `No kohala.json found at ${filePath}`,\n [`create one with: kohala init ${path.basename(agentDir) || \"<name>\"}`],\n );\n }\n\n let raw: string;\n try {\n raw = fs.readFileSync(filePath, \"utf8\");\n } catch (error) {\n throw new ManifestError(`Could not read ${filePath}: ${(error as Error).message}`);\n }\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch (error) {\n throw new ManifestError(`${filePath} is not valid JSON: ${(error as Error).message}`, [\n \"check for trailing commas or missing quotes\",\n ]);\n }\n\n const result = manifestSchema.safeParse(parsed);\n if (!result.success) {\n throw new ManifestError(`${filePath} failed validation`, formatManifestIssues(result.error));\n }\n return result.data;\n}\n","/**\n * Snapshot of the Kohala platform tool catalog (tool ids only), used by\n * `kohala validate` to catch unknown/typo tool ids OFFLINE before deploy.\n * The server-side deploy endpoint enforces the live catalog authoritatively;\n * this list is a best-effort snapshot and may lag new platform tools —\n * pass --allow-unknown-tools to bypass when the snapshot is stale.\n * Snapshot date: 2026-08-10.\n */\nexport const KNOWN_TOOL_IDS: ReadonlySet<string> = new Set([\n \"http.get\",\n \"http.brightdata\",\n \"run_python_script\",\n \"web.search\",\n \"image.generate\",\n \"code.run\",\n \"s3.put\",\n \"koan.publish\",\n \"report.publish\",\n \"email.send\",\n \"send_email\",\n \"email.user_send\",\n \"email.user_inbox\",\n \"calendar.user_events\",\n \"calendar.user_create_event\",\n \"whatsapp.user_send\",\n \"whatsapp.user_inbox\",\n \"linkedin.user_post\",\n \"linkedin.user_profile\",\n \"linkedin.org_posts\",\n \"linkedin.org_stats\",\n \"validate_output\",\n \"html.parse\",\n \"json.parse\",\n \"csv.parse\",\n \"canvas.message\",\n \"canvas.request_approval\",\n \"odoo.search_read\",\n \"odoo.read\",\n \"odoo.read_group\",\n \"odoo.create\",\n \"odoo.write\",\n \"odoo.unlink\",\n \"odoo.call_method\",\n \"odoo.message_post\",\n \"odoo.attachments.upload\",\n \"aftership.create_tracking\",\n \"aftership.get_tracking\",\n \"aftership.list_trackings\",\n \"aftership.update_tracking\",\n \"aftership.delete_tracking\",\n \"aftership.detect_courier\",\n \"fedex.track\",\n \"ups.track\",\n \"era5.point_history\",\n \"noaa.forecast\",\n \"noaa.alerts\",\n \"airlabs.flight\",\n \"airlabs.schedules\",\n \"adsb.aircraft_near\",\n \"adsb.by_callsign\",\n \"aftership.list_couriers\",\n \"ga.run_report\",\n \"ga.realtime_report\",\n \"ga.get_metadata\",\n \"ga.list_properties\",\n \"epicor.query\",\n \"epicor.list\",\n \"epicor.get\",\n \"epicor.create\",\n \"epicor.update\",\n \"epicor.call_method\",\n \"ideogram.generate\",\n \"ideogram.edit\",\n \"ideogram.remix\",\n \"ideogram.reframe\",\n \"ideogram.replace_background\",\n \"ideogram.upscale\",\n \"ideogram.describe\",\n \"elevenlabs.text_to_speech\",\n \"elevenlabs.speech_to_text\",\n \"elevenlabs.speech_to_speech\",\n \"elevenlabs.sound_effects\",\n \"elevenlabs.voice_isolator\",\n \"elevenlabs.music\",\n \"elevenlabs.dubbing\",\n \"elevenlabs.dubbing_result\",\n \"elevenlabs.voice_design\",\n \"elevenlabs.list_voices\",\n \"video.generate_social\",\n \"video.generate_cinematic\",\n \"video.generate_avatar\",\n \"video.status\",\n \"extract.fields\",\n \"extract.receipt\",\n \"extract.financial\",\n \"extract.legal\",\n \"extract.product_spec\",\n \"extract.menu\",\n \"extract.evaluate\",\n \"memory.search\",\n \"memory.remember\",\n \"http.post_json\",\n \"s3.list\",\n \"s3.get\",\n \"s3.delete\",\n \"feed.fetch\",\n \"text.diff\",\n \"data.diff\",\n \"pinecone.upsert\",\n \"pinecone.query\",\n \"pinecone.fetch\",\n \"pinecone.delete\",\n \"llm.complete\",\n \"pdf.extract\",\n \"geocode\",\n \"slack.message\",\n \"discord.message\",\n \"schedule.next_run\",\n \"schedule.last_run\",\n \"metrics.record\",\n \"vector.embed\",\n \"sms.send\",\n \"push.send\",\n \"webhook.post\",\n \"notify.send\",\n \"agent.handoff\",\n \"bus.publish\",\n \"bus.subscribe\",\n \"bus.list_subscriptions\",\n \"bus.unsubscribe\",\n \"invoice.record\",\n \"invoice.generate\",\n \"invoice.modify\",\n \"invoice.list\",\n \"invoice.publish_koan\",\n \"invoice.ap_run\",\n \"invoice.ap_sweep\",\n \"invoice.ar_sweep\",\n \"invoice.ar_draft\",\n \"invoice.send\",\n \"invoice.review\",\n \"invoice.calibrate\",\n \"invoice.settings\",\n \"invoice.status\",\n \"sales_agreement.record\",\n \"sales_agreement.review\",\n \"sales_agreement.list\",\n \"sales_agreement.publish_koan\",\n \"customers.list\",\n \"customers.add\",\n \"customers.get_brand_profile\",\n \"secrets.get\",\n \"secrets.set\",\n \"secrets.list\",\n \"secrets.delete\",\n \"aws.ec2_list\",\n \"aws.ec2_start\",\n \"aws.ec2_stop\",\n \"aws.s3_list\",\n \"aws.lambda_list\",\n \"aws.lambda_invoke\",\n \"aws.cloudwatch_alarms\",\n \"aws.cost_summary\",\n \"aws.rds_list\",\n \"aws.bedrock_models\",\n \"aws.grafana_list\",\n \"googleads.list_accounts\",\n \"googleads.search\",\n \"googleads.campaign_performance\",\n \"googleads.ad_group_performance\",\n \"googleads.keyword_performance\",\n \"googleads.budget_summary\",\n \"calendar.generate\",\n \"content.analyze\",\n \"finance.ar.summary\",\n \"finance.ar_aging\",\n \"finance.ar_pastdue_report\",\n \"finance.ar_overdue_notify\",\n \"finance.ap.summary\",\n \"finance.ap_aging\",\n \"finance.reporting.summary\",\n \"finance.trial_balance\",\n \"sales.pipeline.summary\",\n \"sales.pipeline_read\",\n \"inventory.stock.summary\",\n \"inventory.procurement_read\",\n \"slack.list_channels\",\n \"slack.post_message\",\n \"notion.search\",\n \"notion.append_page\",\n \"hubspot.list_engagements\",\n \"hubspot.log_call\",\n \"hubspot.update_deal\",\n \"linear.create_issue\",\n \"asana.create_task\",\n \"airtable.list_records\",\n \"airtable.create_record\",\n \"pandadoc.create_document\",\n \"canva.create_design\",\n \"canva.autofill_deck\",\n \"zapier.trigger_zap\",\n \"commitments.recall\",\n \"workspacesync.fanout\",\n \"dealdesk.draft\",\n \"pricing.catalog_list\",\n \"pricing.assumptions_list\",\n \"pricing.benchmark_list\",\n \"pricing.single_use_list\",\n \"pricing.reusable_tco_list\",\n \"pricing.monitoring_list\",\n \"pricing.simulate_save\"\n]);\n\n/** Return the declared tool ids that are not in the snapshot catalog. */\nexport function unknownToolIds(tools: readonly string[]): string[] {\n return tools.filter((t) => !KNOWN_TOOL_IDS.has(t));\n}\n","import path from \"node:path\";\nimport type { Command } from \"commander\";\nimport pc from \"picocolors\";\nimport { loadManifest } from \"../manifest/load.js\";\nimport { createMemoryStore } from \"../memory/create.js\";\nimport { runShift } from \"../emulator/runner.js\";\n\n/**\n * `kohala run <agent> --local` — run one shift against the local emulator.\n *\n * Local runs are always manual (the manifest's schedule only matters on\n * deploy). The emulator enforces admission, allowlist, caps, and validators\n * exactly like the hosted platform, but never meters anything.\n */\nexport function registerRunCommand(program: Command): void {\n program\n .command(\"run\")\n .argument(\"<agent>\", \"agent directory (containing kohala.json)\")\n .option(\"--local\", \"run against the local emulator (required for now)\")\n .option(\"--skill <name>\", \"which skill to run (defaults to the only skill)\")\n .option(\n \"--backend <backend>\",\n \"memory backend for this run: file | postgres\",\n \"file\",\n )\n .option(\"--url <url>\", \"postgres connection string (or set DATABASE_URL)\")\n .description(\"Run a shift against the local emulator\")\n .action(\n async (\n agent: string,\n options: { local?: boolean; skill?: string; backend: string; url?: string },\n ) => {\n if (!options.local) {\n throw new Error(\n \"Hosted runs start from the platform, not the CLI. Use --local to run against the local emulator, or `kohala deploy --run` to trigger a hosted run.\",\n );\n }\n if (options.backend !== \"file\" && options.backend !== \"postgres\") {\n throw new Error(`Unknown backend \"${options.backend}\" — use \"file\" or \"postgres\".`);\n }\n const rootDir = process.cwd();\n const agentDir = path.resolve(rootDir, agent);\n const manifest = loadManifest(agentDir);\n const store = await createMemoryStore({\n backend: options.backend,\n agent: manifest.name,\n rootDir,\n url: options.url ?? process.env.DATABASE_URL,\n });\n\n try {\n console.log(\n pc.cyan(`Running shift for \"${manifest.name}\" (${manifest.runtimeMode} mode)...`),\n );\n const result = await runShift({ rootDir, agentDir, manifest, store, skill: options.skill });\n\n console.log(\"\");\n if (result.status === \"succeeded\") {\n console.log(pc.green(`✔ Shift ${result.runId} succeeded`));\n } else {\n console.log(pc.red(`✘ Shift ${result.runId} ${result.status.replace(/_/g, \" \")}`));\n if (result.detail) console.log(pc.red(` ${result.detail}`));\n }\n console.log(pc.dim(` tokens used: ${result.totalTokens} (counted, never billed)`));\n for (const validator of result.validatorResults) {\n const mark = validator.passed ? pc.green(\"passed\") : pc.red(\"failed\");\n console.log(pc.dim(` validator ${validator.validator}: `) + mark + pc.dim(` — ${validator.detail}`));\n }\n if (result.output.trim() !== \"\") {\n console.log(\"\");\n console.log(pc.dim(\"── output ─────────────────────────────\"));\n console.log(result.output.trim());\n }\n console.log(\"\");\n console.log(pc.dim(`Full audit trail: kohala trace ${agent}`));\n if (result.status !== \"succeeded\") {\n process.exitCode = 1;\n }\n } finally {\n await store.close();\n }\n },\n );\n}\n","import crypto from \"node:crypto\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport {\n DEFAULT_CATEGORY,\n DEFAULT_LIST_LIMIT,\n type MemoryAsset,\n type MemoryRecord,\n type MemoryStore,\n} from \"./store.js\";\nimport { atomicWriteFile, withFileLock } from \"../util/lock.js\";\n\n/** Shape of the on-disk JSON index file. */\ninterface IndexFile {\n records: MemoryRecord[];\n}\n\n/** Directory holding one agent's file-backed memory. */\nexport function memoryDirFor(rootDir: string, agent: string): string {\n return path.join(rootDir, \".kohala\", \"memory\", agent);\n}\n\n/**\n * File-backed memory store — the default backend.\n *\n * Layout (per agent, mirroring the platform's per-agent asset tracking):\n *\n * .kohala/memory/<agent>/index.json — the asset index (key, category,\n * timestamps, active flag)\n * .kohala/memory/<agent>/bodies/<id> — raw body bytes, one file per asset\n *\n * The index is small and rewritten atomically on every mutation (write to a\n * temp file, then rename) so a crash can't leave a half-written index.\n */\nexport class FileMemoryStore implements MemoryStore {\n private readonly dir: string;\n private readonly indexPath: string;\n private readonly bodiesDir: string;\n\n constructor(rootDir: string, agent: string) {\n this.dir = memoryDirFor(rootDir, agent);\n this.indexPath = path.join(this.dir, \"index.json\");\n this.bodiesDir = path.join(this.dir, \"bodies\");\n fs.mkdirSync(this.bodiesDir, { recursive: true });\n }\n\n private readIndex(): IndexFile {\n if (!fs.existsSync(this.indexPath)) {\n return { records: [] };\n }\n const raw = fs.readFileSync(this.indexPath, \"utf8\");\n return JSON.parse(raw) as IndexFile;\n }\n\n private writeIndex(index: IndexFile): void {\n atomicWriteFile(this.indexPath, JSON.stringify(index, null, 2));\n }\n\n private bodyPath(id: string): string {\n return path.join(this.bodiesDir, id);\n }\n\n async put(key: string, body: Buffer, category: string = DEFAULT_CATEGORY): Promise<MemoryRecord> {\n // The index read-modify-write is guarded by an interprocess lock so a\n // concurrent run or MCP server can't clobber this update.\n return withFileLock(this.indexPath, () => {\n const index = this.readIndex();\n const now = new Date().toISOString();\n const existing = index.records.find((record) => record.active && record.key === key);\n\n if (existing) {\n // Logical keys are unique among active assets: overwrite in place.\n existing.category = category;\n existing.size = body.byteLength;\n existing.updatedAt = now;\n fs.writeFileSync(this.bodyPath(existing.id), body);\n this.writeIndex(index);\n return { ...existing };\n }\n\n const record: MemoryRecord = {\n id: crypto.randomUUID(),\n key,\n category,\n size: body.byteLength,\n createdAt: now,\n updatedAt: now,\n active: true,\n };\n fs.writeFileSync(this.bodyPath(record.id), body);\n index.records.push(record);\n this.writeIndex(index);\n return { ...record };\n });\n }\n\n async get(keyOrId: string): Promise<MemoryAsset | null> {\n const index = this.readIndex();\n // Platform resolution order: active logical key first, then record id.\n const record =\n index.records.find((entry) => entry.active && entry.key === keyOrId) ??\n index.records.find((entry) => entry.active && entry.id === keyOrId);\n if (!record) return null;\n const filePath = this.bodyPath(record.id);\n if (!fs.existsSync(filePath)) {\n throw new Error(\n `Memory index lists ${record.key} (${record.id}) but its body file is missing at ${filePath}`,\n );\n }\n return { record: { ...record }, body: fs.readFileSync(filePath) };\n }\n\n async list(prefix?: string, limit: number = DEFAULT_LIST_LIMIT): Promise<MemoryRecord[]> {\n const index = this.readIndex();\n return index.records\n .filter((record) => record.active && (prefix === undefined || record.key.startsWith(prefix)))\n .sort((a, b) => (a.updatedAt < b.updatedAt ? 1 : -1))\n .slice(0, limit)\n .map((record) => ({ ...record }));\n }\n\n async delete(keyOrId: string): Promise<MemoryRecord | null> {\n return withFileLock(this.indexPath, () => {\n const index = this.readIndex();\n const record =\n index.records.find((entry) => entry.active && entry.key === keyOrId) ??\n index.records.find((entry) => entry.active && entry.id === keyOrId);\n if (!record) return null;\n // Remove the body, deactivate the index entry (soft delete, like the platform).\n record.active = false;\n record.updatedAt = new Date().toISOString();\n const filePath = this.bodyPath(record.id);\n if (fs.existsSync(filePath)) {\n fs.unlinkSync(filePath);\n }\n this.writeIndex(index);\n return { ...record };\n });\n }\n\n async close(): Promise<void> {\n // Nothing to release for the file backend.\n }\n}\n","/**\n * The MemoryStore interface — the platform's memory surface, locally.\n *\n * Both the emulator (via the SDK RPC) and the MCP memory server sit on top of\n * this interface, so an agent sees identical memory semantics whether it is\n * talking to `kohala run --local`, `kohala memory serve`, or the hosted\n * platform:\n *\n * - `s3.put(key, body, category?)` — store under a logical key\n * - `s3.get(keyOrId)` — resolve by logical key first\n * - `s3.list(prefix?, limit?)` — list active assets for the agent\n * - `s3.delete(keyOrId)` — remove + deactivate\n */\n\n/** Index entry for one stored asset — mirrors how the platform tracks assets. */\nexport interface MemoryRecord {\n /** Stable unique id (UUID). `get`/`delete` accept this as a fallback to the key. */\n id: string;\n /** Logical key the agent chose, e.g. \"weather/latest\". */\n key: string;\n /** Asset category. Run results default to \"agentoutput\" on the platform. */\n category: string;\n /** Body size in bytes. */\n size: number;\n /** ISO-8601 creation time. */\n createdAt: string;\n /** ISO-8601 last-update time. */\n updatedAt: string;\n /** Deleted assets are deactivated, not erased from the index. */\n active: boolean;\n}\n\n/** Default category for run results, matching the platform. */\nexport const DEFAULT_CATEGORY = \"agentoutput\";\n\n/** Default `list` page size. */\nexport const DEFAULT_LIST_LIMIT = 100;\n\n/** A record plus its body, as returned by `get`. */\nexport interface MemoryAsset {\n record: MemoryRecord;\n body: Buffer;\n}\n\n/**\n * Storage backend contract. Implementations: FileMemoryStore (default) and\n * PostgresMemoryStore (optional, requires `pg`).\n */\nexport interface MemoryStore {\n /**\n * Store `body` under `key`. If an active record already exists for the key,\n * it is updated in place (same id, new body/category/updatedAt) — logical\n * keys are unique among active assets.\n */\n put(key: string, body: Buffer, category?: string): Promise<MemoryRecord>;\n\n /**\n * Fetch an asset. Resolution order matches the platform: active logical key\n * first, then record id. Returns null when nothing matches.\n */\n get(keyOrId: string): Promise<MemoryAsset | null>;\n\n /** List active assets, optionally filtered by key prefix, newest first. */\n list(prefix?: string, limit?: number): Promise<MemoryRecord[]>;\n\n /**\n * Remove + deactivate an asset: the body is deleted, the index entry stays\n * with `active: false` (mirroring the platform's soft-delete). Returns the\n * deactivated record, or null if nothing matched.\n */\n delete(keyOrId: string): Promise<MemoryRecord | null>;\n\n /** Release any underlying resources (DB connections, file handles). */\n close(): Promise<void>;\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\n\n/**\n * Minimal interprocess mutex built on atomic `mkdir`.\n *\n * The usage ledger and the file memory index are read-modify-write JSON\n * files that can be touched by overlapping processes (two `kohala run`s, or\n * `kohala memory serve` next to a run). `mkdir` is atomic on every platform\n * Node supports, so a lock directory gives us a portable mutex without any\n * dependencies.\n *\n * Locks are considered stale (crashed holder) after STALE_MS and are broken\n * loudly rather than waited on forever.\n */\n\nconst STALE_MS = 10_000;\nconst ACQUIRE_TIMEOUT_MS = 5_000;\nconst RETRY_DELAY_MS = 15;\n\nfunction sleep(ms: number): void {\n // Synchronous sleep keeps the locked sections synchronous (the callers are\n // sync fs code); Atomics.wait avoids burning CPU in the retry loop.\n const buffer = new SharedArrayBuffer(4);\n Atomics.wait(new Int32Array(buffer), 0, 0, ms);\n}\n\n/**\n * Run `fn` while holding an exclusive lock named after `filePath`.\n * Throws if the lock cannot be acquired within ACQUIRE_TIMEOUT_MS.\n */\nexport function withFileLock<T>(filePath: string, fn: () => T): T {\n const lockDir = `${filePath}.lock`;\n fs.mkdirSync(path.dirname(lockDir), { recursive: true });\n\n const deadline = Date.now() + ACQUIRE_TIMEOUT_MS;\n for (;;) {\n try {\n fs.mkdirSync(lockDir);\n break;\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== \"EEXIST\") throw error;\n // Break stale locks left behind by a crashed process.\n try {\n const age = Date.now() - fs.statSync(lockDir).mtimeMs;\n if (age > STALE_MS) {\n fs.rmdirSync(lockDir);\n continue;\n }\n } catch {\n // The holder released it between our checks — retry immediately.\n continue;\n }\n if (Date.now() > deadline) {\n throw new Error(\n `Timed out waiting for lock ${lockDir} — another kohala process is holding it. ` +\n `If no other process is running, delete the directory and retry.`,\n { cause: error },\n );\n }\n sleep(RETRY_DELAY_MS);\n }\n }\n\n try {\n return fn();\n } finally {\n try {\n fs.rmdirSync(lockDir);\n } catch {\n // Already removed (stale-broken by another waiter); nothing to do.\n }\n }\n}\n\n/** Atomically replace `filePath` with `content` (temp file + rename). */\nexport function atomicWriteFile(filePath: string, content: string): void {\n fs.mkdirSync(path.dirname(filePath), { recursive: true });\n const tempPath = `${filePath}.${process.pid}.tmp`;\n fs.writeFileSync(tempPath, content, \"utf8\");\n fs.renameSync(tempPath, filePath);\n}\n","import crypto from \"node:crypto\";\nimport {\n DEFAULT_CATEGORY,\n DEFAULT_LIST_LIMIT,\n type MemoryAsset,\n type MemoryRecord,\n type MemoryStore,\n} from \"./store.js\";\n\n/** Minimal structural type for the parts of `pg.Pool` we use. */\ninterface PgPoolLike {\n query(text: string, values?: unknown[]): Promise<{ rows: Record<string, unknown>[] }>;\n end(): Promise<void>;\n}\n\n/** One row of the kohala_memory table, as returned by pg. */\ninterface MemoryRow {\n id: string;\n key: string;\n category: string;\n body: Buffer | null;\n size: string | number;\n created_at: Date;\n updated_at: Date;\n active: boolean;\n}\n\nfunction rowToRecord(row: MemoryRow): MemoryRecord {\n return {\n id: row.id,\n key: row.key,\n category: row.category,\n size: Number(row.size),\n createdAt: new Date(row.created_at).toISOString(),\n updatedAt: new Date(row.updated_at).toISOString(),\n active: row.active,\n };\n}\n\n/**\n * Postgres-backed memory store.\n *\n * Design decision (documented per the build plan): the index AND the bodies\n * live in one table — bodies are stored as `bytea` in the same row. This\n * keeps the backend to a single table with no filesystem coupling, so any\n * plain Postgres URL works (no volume required).\n *\n * The table is created on first connect (idempotent migration). `pg` is an\n * optional peer dependency and is imported lazily so file-backend users never\n * need it installed.\n */\nexport class PostgresMemoryStore implements MemoryStore {\n private constructor(\n private readonly pool: PgPoolLike,\n private readonly agent: string,\n ) {}\n\n /** Connect, run the idempotent migration, and return a ready store. */\n static async connect(url: string, agent: string): Promise<PostgresMemoryStore> {\n let pgModule: typeof import(\"pg\");\n try {\n pgModule = await import(\"pg\");\n } catch {\n throw new Error(\n 'The postgres backend requires the optional \"pg\" package. Install it with: npm install pg',\n );\n }\n const PoolCtor = pgModule.default?.Pool ?? pgModule.Pool;\n const pool = new PoolCtor({ connectionString: url }) as unknown as PgPoolLike;\n\n // Idempotent migration on first connect — a single table holds the index\n // semantics from A.1 (key, category, timestamps, active flag) plus bodies.\n await pool.query(`\n CREATE TABLE IF NOT EXISTS kohala_memory (\n id UUID PRIMARY KEY,\n agent TEXT NOT NULL,\n key TEXT NOT NULL,\n category TEXT NOT NULL,\n body BYTEA,\n size BIGINT NOT NULL,\n created_at TIMESTAMPTZ NOT NULL,\n updated_at TIMESTAMPTZ NOT NULL,\n active BOOLEAN NOT NULL DEFAULT TRUE\n )\n `);\n await pool.query(`\n CREATE UNIQUE INDEX IF NOT EXISTS kohala_memory_active_key\n ON kohala_memory (agent, key) WHERE active\n `);\n\n return new PostgresMemoryStore(pool, agent);\n }\n\n async put(key: string, body: Buffer, category: string = DEFAULT_CATEGORY): Promise<MemoryRecord> {\n const now = new Date();\n const existing = await this.pool.query(\n \"SELECT * FROM kohala_memory WHERE agent = $1 AND key = $2 AND active\",\n [this.agent, key],\n );\n if (existing.rows.length > 0) {\n const row = existing.rows[0] as unknown as MemoryRow;\n const updated = await this.pool.query(\n `UPDATE kohala_memory SET category = $1, body = $2, size = $3, updated_at = $4\n WHERE id = $5 RETURNING *`,\n [category, body, body.byteLength, now, row.id],\n );\n return rowToRecord(updated.rows[0] as unknown as MemoryRow);\n }\n const inserted = await this.pool.query(\n `INSERT INTO kohala_memory (id, agent, key, category, body, size, created_at, updated_at, active)\n VALUES ($1, $2, $3, $4, $5, $6, $7, $7, TRUE) RETURNING *`,\n [crypto.randomUUID(), this.agent, key, category, body, body.byteLength, now],\n );\n return rowToRecord(inserted.rows[0] as unknown as MemoryRow);\n }\n\n async get(keyOrId: string): Promise<MemoryAsset | null> {\n // Platform resolution order: active logical key first, then record id.\n const byKey = await this.pool.query(\n \"SELECT * FROM kohala_memory WHERE agent = $1 AND key = $2 AND active\",\n [this.agent, keyOrId],\n );\n let row = byKey.rows[0] as unknown as MemoryRow | undefined;\n if (!row && isUuid(keyOrId)) {\n const byId = await this.pool.query(\n \"SELECT * FROM kohala_memory WHERE agent = $1 AND id = $2 AND active\",\n [this.agent, keyOrId],\n );\n row = byId.rows[0] as unknown as MemoryRow | undefined;\n }\n if (!row) return null;\n return { record: rowToRecord(row), body: row.body ?? Buffer.alloc(0) };\n }\n\n async list(prefix?: string, limit: number = DEFAULT_LIST_LIMIT): Promise<MemoryRecord[]> {\n const result = prefix\n ? await this.pool.query(\n `SELECT id, agent, key, category, NULL AS body, size, created_at, updated_at, active\n FROM kohala_memory WHERE agent = $1 AND active AND key LIKE $2 || '%'\n ORDER BY updated_at DESC LIMIT $3`,\n [this.agent, prefix, limit],\n )\n : await this.pool.query(\n `SELECT id, agent, key, category, NULL AS body, size, created_at, updated_at, active\n FROM kohala_memory WHERE agent = $1 AND active\n ORDER BY updated_at DESC LIMIT $2`,\n [this.agent, limit],\n );\n return result.rows.map((row) => rowToRecord(row as unknown as MemoryRow));\n }\n\n async delete(keyOrId: string): Promise<MemoryRecord | null> {\n const asset = await this.get(keyOrId);\n if (!asset) return null;\n // Remove the body, deactivate the row (soft delete, like the platform).\n const updated = await this.pool.query(\n `UPDATE kohala_memory SET active = FALSE, body = NULL, updated_at = $1\n WHERE id = $2 RETURNING *`,\n [new Date(), asset.record.id],\n );\n return rowToRecord(updated.rows[0] as unknown as MemoryRow);\n }\n\n async close(): Promise<void> {\n await this.pool.end();\n }\n}\n\n/** Loose UUID check so non-UUID keys never hit the uuid-typed id column. */\nfunction isUuid(value: string): boolean {\n return /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(value);\n}\n","import { FileMemoryStore } from \"./file.js\";\nimport { PostgresMemoryStore } from \"./postgres.js\";\nimport type { MemoryStore } from \"./store.js\";\n\n/** Supported backend names for `kohala memory serve --backend <name>`. */\nexport type MemoryBackend = \"file\" | \"postgres\";\n\n/** Options for creating a memory store for one agent. */\nexport interface CreateMemoryStoreOptions {\n backend: MemoryBackend;\n /** Agent name — memory is always scoped per agent, like on the platform. */\n agent: string;\n /** Workspace root for the file backend (defaults to process.cwd()). */\n rootDir?: string;\n /** Postgres connection string (required for the postgres backend). */\n url?: string;\n}\n\n/**\n * Create a MemoryStore for the requested backend.\n *\n * Fails loudly when the postgres backend is requested without a URL — there\n * is no silent fallback to the file backend.\n */\nexport async function createMemoryStore(options: CreateMemoryStoreOptions): Promise<MemoryStore> {\n if (options.backend === \"file\") {\n return new FileMemoryStore(options.rootDir ?? process.cwd(), options.agent);\n }\n if (!options.url) {\n throw new Error(\n \"The postgres backend needs a connection string. Pass --url or set DATABASE_URL.\",\n );\n }\n return PostgresMemoryStore.connect(options.url, options.agent);\n}\n","import crypto from \"node:crypto\";\nimport path from \"node:path\";\nimport { execa, ExecaError } from \"execa\";\nimport type { AgentManifest } from \"../manifest/schema.js\";\nimport type { MemoryStore } from \"../memory/store.js\";\nimport { TraceWriter } from \"../trace/writer.js\";\nimport type { RunStatus } from \"../trace/events.js\";\nimport { CapExceededError, TokenMeter } from \"./tokens.js\";\nimport { evaluateValidators, type ValidatorResult } from \"./validators.js\";\nimport { startSdkRpcServer } from \"../sdk/rpc.js\";\nimport { runLlmShift } from \"./llm-mode.js\";\nimport { findPython } from \"./python.js\";\n\n/**\n * The shift runner — executes one agent shift with the platform's exact\n * enforcement order (A.2):\n *\n * 1. Admission (per-day token cap, refused BEFORE any work)\n * 2. Tool allowlist (enforced on every tool call via the dispatcher)\n * 3. Per-run cap (projected before each LLM turn)\n * 4. Validators, with a bounded repair loop (max 2 attempts, platform default)\n *\n * Tokens are counted for cap enforcement and shown in the trace, but nothing\n * is ever charged — that is the \"no metering\" promise.\n */\n\n/** Platform default: at most 2 repair attempts after a validator failure. */\nexport const MAX_REPAIR_ATTEMPTS = 2;\n\n/** Inputs for one shift. */\nexport interface RunShiftOptions {\n /** Workspace root (where .kohala/ lives). */\n rootDir: string;\n /** The agent's directory (contains kohala.json and skills/). */\n agentDir: string;\n manifest: AgentManifest;\n store: MemoryStore;\n /** Skill to run; defaults to the only skill when there is exactly one. */\n skill?: string;\n}\n\n/** Outcome of one shift. */\nexport interface ShiftResult {\n runId: string;\n status: RunStatus;\n /** The run output (script stdout in wrap mode; final text in llm mode). */\n output: string;\n totalTokens: number;\n validatorResults: ValidatorResult[];\n /** Human-readable failure/abort detail, if any. */\n detail?: string;\n}\n\n/** Resolve which skill a shift should execute, failing loudly on ambiguity. */\nexport function resolveSkill(manifest: AgentManifest, requested?: string): [string, string] {\n const entries = Object.entries(manifest.skills);\n if (entries.length === 0) {\n throw new Error(`Agent \"${manifest.name}\" has no skills in kohala.json`);\n }\n if (requested) {\n const script = manifest.skills[requested];\n if (!script) {\n throw new Error(\n `Skill \"${requested}\" not found. Available skills: ${entries.map(([name]) => name).join(\", \")}`,\n );\n }\n return [requested, script];\n }\n if (entries.length === 1) {\n return entries[0] as [string, string];\n }\n throw new Error(\n `Agent \"${manifest.name}\" has ${entries.length} skills — pick one with --skill <name> ` +\n `(${entries.map(([name]) => name).join(\", \")})`,\n );\n}\n\n/** Run one shift end-to-end. Never throws for run-level failures — the result carries the status. */\nexport async function runShift(options: RunShiftOptions): Promise<ShiftResult> {\n const { rootDir, agentDir, manifest, store } = options;\n const runId = `run_${Date.now().toString(36)}_${crypto.randomBytes(3).toString(\"hex\")}`;\n const trace = new TraceWriter(rootDir, manifest.name);\n const meter = new TokenMeter(rootDir, manifest.name, manifest.caps);\n const startedAt = Date.now();\n const [skillName, scriptFilename] = resolveSkill(manifest, options.skill);\n\n const finish = (\n status: RunStatus,\n output: string,\n validatorResults: ValidatorResult[],\n detail?: string,\n ): ShiftResult => {\n trace.append({\n ts: new Date().toISOString(),\n runId,\n agent: manifest.name,\n type: \"run_finished\",\n status,\n totalTokens: meter.runTotal,\n durationMs: Date.now() - startedAt,\n ...(detail ? { detail } : {}),\n });\n return { runId, status, output, totalTokens: meter.runTotal, validatorResults, detail };\n };\n\n // 1. Admission: refuse the shift before any work if the per-day cap is spent.\n try {\n meter.admitRun();\n } catch (error) {\n if (error instanceof CapExceededError) {\n return finish(\"aborted_per_day_token_cap\", \"\", [], error.message);\n }\n throw error;\n }\n\n trace.append({\n ts: new Date().toISOString(),\n runId,\n agent: manifest.name,\n type: \"run_started\",\n runtimeMode: manifest.runtimeMode,\n skill: skillName,\n scriptFilename,\n });\n\n const context = { manifest, store, trace, meter, runId };\n\n // llm mode: a real tool-use loop against the developer's own key, with the\n // same bounded validator repair loop as wrap mode (A.2 step 4).\n if (manifest.runtimeMode === \"llm\") {\n try {\n let repairReason = \"\";\n for (let attempt = 0; attempt <= MAX_REPAIR_ATTEMPTS; attempt += 1) {\n if (attempt > 0) {\n trace.append({\n ts: new Date().toISOString(),\n runId,\n agent: manifest.name,\n type: \"repair_attempt\",\n attempt,\n maxAttempts: MAX_REPAIR_ATTEMPTS,\n reason: repairReason,\n });\n }\n const output = await runLlmShift(\n context,\n skillName,\n path.join(agentDir, \"skills\", scriptFilename),\n attempt > 0 ? repairReason : undefined,\n );\n const validatorResults = await evaluateValidators(manifest.validators, output, store);\n recordValidatorResults(trace, runId, manifest.name, validatorResults);\n const failures = validatorResults.filter((result) => !result.passed);\n if (failures.length === 0) {\n return finish(\"succeeded\", output, validatorResults);\n }\n repairReason = failures\n .map((failure) => `${failure.validator}: ${failure.detail}`)\n .join(\"; \");\n if (attempt === MAX_REPAIR_ATTEMPTS) {\n return finish(\n \"failed\",\n output,\n validatorResults,\n `validators failed after ${MAX_REPAIR_ATTEMPTS} repair attempts: ${repairReason}`,\n );\n }\n }\n throw new Error(\"repair loop exited without a result\");\n } catch (error) {\n if (error instanceof CapExceededError || meter.abortedWith) {\n const cap = (error instanceof CapExceededError ? error : meter.abortedWith) as CapExceededError;\n const status: RunStatus =\n cap.code === \"PER_RUN_TOKEN_CAP\" ? \"aborted_per_run_token_cap\" : \"aborted_per_day_token_cap\";\n return finish(status, \"\", [], cap.message);\n }\n return finish(\"error\", \"\", [], (error as Error).message);\n }\n }\n\n // wrap mode: execute the skill script directly and validate its output.\n const rpc = await startSdkRpcServer(context);\n try {\n let repairReason = \"\";\n for (let attempt = 0; attempt <= MAX_REPAIR_ATTEMPTS; attempt += 1) {\n if (attempt > 0) {\n trace.append({\n ts: new Date().toISOString(),\n runId,\n agent: manifest.name,\n type: \"repair_attempt\",\n attempt,\n maxAttempts: MAX_REPAIR_ATTEMPTS,\n reason: repairReason,\n });\n }\n\n const execution = await executeScript({\n agentDir,\n scriptFilename,\n rpcUrl: rpc.url,\n manifest,\n runId,\n repairAttempt: attempt,\n repairFeedback: repairReason,\n });\n\n if (!execution.ok) {\n // A cap abort inside the script (llm.complete denied) surfaces here.\n if (meter.abortedWith?.code === \"PER_RUN_TOKEN_CAP\") {\n return finish(\"aborted_per_run_token_cap\", execution.stdout, [], meter.abortedWith.message);\n }\n return finish(\"error\", execution.stdout, [], execution.errorDetail);\n }\n\n const validatorResults = await evaluateValidators(\n manifest.validators,\n execution.stdout,\n store,\n );\n recordValidatorResults(trace, runId, manifest.name, validatorResults);\n\n const failures = validatorResults.filter((result) => !result.passed);\n if (failures.length === 0) {\n return finish(\"succeeded\", execution.stdout, validatorResults);\n }\n repairReason = failures.map((failure) => `${failure.validator}: ${failure.detail}`).join(\"; \");\n if (attempt === MAX_REPAIR_ATTEMPTS) {\n return finish(\"failed\", execution.stdout, validatorResults, `validators failed after ${MAX_REPAIR_ATTEMPTS} repair attempts: ${repairReason}`);\n }\n }\n // Unreachable: the loop always returns.\n throw new Error(\"repair loop exited without a result\");\n } finally {\n await rpc.close();\n }\n}\n\nfunction recordValidatorResults(\n trace: TraceWriter,\n runId: string,\n agent: string,\n results: ValidatorResult[],\n): void {\n for (const result of results) {\n trace.append({\n ts: new Date().toISOString(),\n runId,\n agent,\n type: \"validator_result\",\n validator: result.validator,\n passed: result.passed,\n detail: result.detail,\n });\n }\n}\n\ninterface ExecuteScriptOptions {\n agentDir: string;\n scriptFilename: string;\n rpcUrl: string;\n manifest: AgentManifest;\n runId: string;\n repairAttempt: number;\n repairFeedback: string;\n}\n\ninterface ScriptExecution {\n ok: boolean;\n stdout: string;\n errorDetail?: string;\n}\n\n/**\n * Execute a skill script with the SDK environment. The script's stdout is the\n * run output that validators evaluate — stderr is passed through for\n * debugging and never treated as output.\n */\nasync function executeScript(options: ExecuteScriptOptions): Promise<ScriptExecution> {\n const python = await findPython();\n const scriptPath = path.join(options.agentDir, \"skills\", options.scriptFilename);\n try {\n const result = await execa(python, [scriptPath], {\n cwd: options.agentDir,\n env: {\n KOHALA_RPC_URL: options.rpcUrl,\n KOHALA_AGENT: options.manifest.name,\n KOHALA_RUN_ID: options.runId,\n KOHALA_REPAIR_ATTEMPT: String(options.repairAttempt),\n KOHALA_VALIDATOR_FEEDBACK: options.repairFeedback,\n },\n // Surface the script's stderr live so developers see their own logging.\n stderr: \"inherit\",\n reject: false,\n timeout: 10 * 60 * 1000,\n });\n if (result.exitCode !== 0) {\n return {\n ok: false,\n stdout: result.stdout ?? \"\",\n errorDetail: `script ${options.scriptFilename} exited with code ${result.exitCode}`,\n };\n }\n return { ok: true, stdout: result.stdout ?? \"\" };\n } catch (error) {\n const message = error instanceof ExecaError ? error.message : (error as Error).message;\n return { ok: false, stdout: \"\", errorDetail: message };\n }\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport type { TraceEvent } from \"./events.js\";\n\n/** Absolute path of an agent's JSONL trace file under the workspace root. */\nexport function traceFilePath(rootDir: string, agent: string): string {\n return path.join(rootDir, \".kohala\", \"trace\", `${agent}.jsonl`);\n}\n\n/**\n * Appends structured events to `.kohala/trace/<agent>.jsonl`.\n *\n * Writes are synchronous appends — one JSON object per line — so a crash\n * mid-run still leaves a readable audit trail up to the crash point,\n * mirroring the platform's append-only run records.\n */\nexport class TraceWriter {\n private readonly filePath: string;\n\n constructor(rootDir: string, agent: string) {\n this.filePath = traceFilePath(rootDir, agent);\n fs.mkdirSync(path.dirname(this.filePath), { recursive: true });\n }\n\n /** Append one event as a JSONL line. */\n append(event: TraceEvent): void {\n fs.appendFileSync(this.filePath, `${JSON.stringify(event)}\\n`, \"utf8\");\n }\n\n /** The file this writer appends to (used by `kohala trace`). */\n get file(): string {\n return this.filePath;\n }\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport type { AgentCaps } from \"../manifest/schema.js\";\nimport { atomicWriteFile, withFileLock } from \"../util/lock.js\";\n\n/**\n * Token accounting without billing.\n *\n * The emulator counts tokens exactly like the platform does for cap\n * enforcement — but it never charges anything. That is the devkit's\n * \"no metering\" promise: numbers show up in the trace, money never does.\n */\n\n/** Rough token estimate: ~4 characters per token, the platform's heuristic. */\nexport function estimateTokens(text: string): number {\n return Math.ceil(text.length / 4);\n}\n\n/** Current UTC day as YYYY-MM-DD — per-day caps reset on UTC midnight. */\nexport function utcDay(now: Date = new Date()): string {\n return now.toISOString().slice(0, 10);\n}\n\n/** Shape of the on-disk usage ledger (.kohala/usage/<agent>.json). */\ninterface UsageFile {\n /** Map of UTC day -> total tokens consumed by local runs that day. */\n days: Record<string, number>;\n}\n\nfunction usageFilePath(rootDir: string, agent: string): string {\n return path.join(rootDir, \".kohala\", \"usage\", `${agent}.json`);\n}\n\n/** Read the persisted per-day token totals for an agent. */\nexport function readUsage(rootDir: string, agent: string): UsageFile {\n const filePath = usageFilePath(rootDir, agent);\n if (!fs.existsSync(filePath)) return { days: {} };\n return JSON.parse(fs.readFileSync(filePath, \"utf8\")) as UsageFile;\n}\n\n/** Persist the per-day token totals for an agent (atomic replace). */\nfunction writeUsage(rootDir: string, agent: string, usage: UsageFile): void {\n atomicWriteFile(usageFilePath(rootDir, agent), JSON.stringify(usage, null, 2));\n}\n\n/** Thrown when a cap would be crossed. `code` mirrors the platform's abort codes. */\nexport class CapExceededError extends Error {\n constructor(\n readonly code: \"PER_DAY_TOKEN_CAP\" | \"PER_RUN_TOKEN_CAP\",\n message: string,\n ) {\n super(message);\n this.name = \"CapExceededError\";\n }\n}\n\n/**\n * Tracks token consumption for one shift and enforces both caps.\n *\n * Enforcement order mirrors the platform (A.2):\n * 1. `admitRun()` — admission check against the per-day cap BEFORE any work.\n * 2. `admitLlmTurn(projected)` — before each LLM turn, abort if the projected\n * total would cross the per-run cap.\n * 3. `add(tokens)` — record actual consumption and persist the day total.\n */\nexport class TokenMeter {\n /** Tokens consumed by this shift so far. */\n runTotal = 0;\n /** Set when a cap abort happened, so the runner can report the right status. */\n abortedWith: CapExceededError | null = null;\n\n constructor(\n private readonly rootDir: string,\n private readonly agent: string,\n private readonly caps: AgentCaps,\n ) {}\n\n /** Tokens already consumed today (UTC), across all local runs. */\n dayTotal(): number {\n const usage = readUsage(this.rootDir, this.agent);\n return usage.days[utcDay()] ?? 0;\n }\n\n /**\n * Admission: refuse the shift before any work if today's local runs have\n * already exhausted the per-day cap — the platform refuses the same way.\n */\n admitRun(): void {\n const today = this.dayTotal();\n if (today >= this.caps.perDayTokens) {\n const error = new CapExceededError(\n \"PER_DAY_TOKEN_CAP\",\n `PER_DAY_TOKEN_CAP: today's usage (${today} tokens) has reached the per-day cap of ${this.caps.perDayTokens}. The cap resets at UTC midnight.`,\n );\n this.abortedWith = error;\n throw error;\n }\n }\n\n /**\n * Pre-turn projection: abort the run if `projectedTokens` more would cross\n * the per-run cap. Called before every LLM turn (wrap-mode llm.complete\n * calls and llm-mode loop turns alike).\n */\n admitLlmTurn(projectedTokens: number): void {\n if (this.runTotal + projectedTokens > this.caps.perRunTokens) {\n const error = new CapExceededError(\n \"PER_RUN_TOKEN_CAP\",\n `PER_RUN_TOKEN_CAP: this turn is projected to use ~${projectedTokens} tokens, which would push the run total past the per-run cap of ${this.caps.perRunTokens} (used so far: ${this.runTotal}).`,\n );\n this.abortedWith = error;\n throw error;\n }\n }\n\n /**\n * Record actual consumption and persist it into today's ledger. Returns the\n * new day total. The read-modify-write is guarded by an interprocess lock so\n * overlapping runs can't lose each other's updates (which would undercount\n * usage and let concurrent runs slip past the day cap).\n */\n add(tokens: number): number {\n this.runTotal += tokens;\n return withFileLock(usageFilePath(this.rootDir, this.agent), () => {\n const usage = readUsage(this.rootDir, this.agent);\n const day = utcDay();\n usage.days[day] = (usage.days[day] ?? 0) + tokens;\n writeUsage(this.rootDir, this.agent, usage);\n return usage.days[day] as number;\n });\n }\n}\n","import type { AgentValidator } from \"../manifest/schema.js\";\nimport type { MemoryStore } from \"../memory/store.js\";\n\n/** Outcome of evaluating one validator. */\nexport interface ValidatorResult {\n validator: AgentValidator[\"type\"];\n passed: boolean;\n /** Human-readable explanation — shown in the trace and fed to repair attempts. */\n detail: string;\n}\n\n/**\n * Evaluate all manifest validators against a run's output, in order.\n *\n * Matches the platform's three validator types (A.3):\n * - `shape` — output must exist and be at least minBytes\n * - `freshness` — a referenced memory asset must be newer than maxAgeHours\n * - `invariant` — output must match / must not match a regex\n *\n * All validators are always evaluated (no short-circuit) so the trace shows\n * the complete picture, exactly like the platform's validator report.\n */\nexport async function evaluateValidators(\n validators: readonly AgentValidator[],\n output: string,\n store: MemoryStore,\n now: Date = new Date(),\n): Promise<ValidatorResult[]> {\n const results: ValidatorResult[] = [];\n for (const validator of validators) {\n switch (validator.type) {\n case \"shape\": {\n const bytes = Buffer.byteLength(output, \"utf8\");\n const passed = bytes >= validator.minBytes;\n results.push({\n validator: \"shape\",\n passed,\n detail: passed\n ? `output is ${bytes} bytes (>= ${validator.minBytes})`\n : `output is ${bytes} bytes, expected at least ${validator.minBytes}`,\n });\n break;\n }\n case \"freshness\": {\n const asset = await store.get(validator.asset);\n if (!asset) {\n results.push({\n validator: \"freshness\",\n passed: false,\n detail: `memory asset \"${validator.asset}\" does not exist`,\n });\n break;\n }\n const ageHours = (now.getTime() - new Date(asset.record.updatedAt).getTime()) / 3_600_000;\n const passed = ageHours <= validator.maxAgeHours;\n results.push({\n validator: \"freshness\",\n passed,\n detail: passed\n ? `asset \"${validator.asset}\" is ${ageHours.toFixed(2)}h old (<= ${validator.maxAgeHours}h)`\n : `asset \"${validator.asset}\" is ${ageHours.toFixed(2)}h old, must be newer than ${validator.maxAgeHours}h`,\n });\n break;\n }\n case \"invariant\": {\n let regex: RegExp;\n try {\n regex = new RegExp(validator.pattern);\n } catch (error) {\n results.push({\n validator: \"invariant\",\n passed: false,\n detail: `invalid regex \"${validator.pattern}\": ${(error as Error).message}`,\n });\n break;\n }\n const matched = regex.test(output);\n const passed = validator.mustMatch ? matched : !matched;\n results.push({\n validator: \"invariant\",\n passed,\n detail: passed\n ? `output ${validator.mustMatch ? \"matches\" : \"does not match\"} /${validator.pattern}/ as required`\n : `output ${matched ? \"matches\" : \"does not match\"} /${validator.pattern}/ but ${validator.mustMatch ? \"must match\" : \"must NOT match\"}`,\n });\n break;\n }\n }\n }\n return results;\n}\n","import http from \"node:http\";\nimport { ToolCallError, ToolDispatcher, type DispatchContext } from \"./dispatch.js\";\n\n/**\n * Loopback HTTP RPC server — the script <-> runtime boundary.\n *\n * Scaffolded Python scripts talk to the emulator over this loopback endpoint\n * (the same pattern the platform uses), NOT by importing emulator internals.\n * That keeps a locally-written script byte-identical when deployed: only the\n * KOHALA_RPC_URL environment variable changes.\n *\n * Protocol: POST / with JSON `{\"tool\": \"s3.put\", \"args\": {...}}`.\n * Success: 200 `{\"ok\": true, \"result\": ...}`\n * Failure: 200 `{\"ok\": false, \"error\": {\"code\": \"...\", \"message\": \"...\"}}`\n * (Tool failures are application-level, not transport-level, so the Python\n * SDK can raise a typed KohalaToolError with the platform's error codes.)\n */\n\n/** A running RPC server bound to 127.0.0.1 on an ephemeral port. */\nexport interface SdkRpcServer {\n /** Base URL, e.g. \"http://127.0.0.1:53412\" — passed to scripts as KOHALA_RPC_URL. */\n url: string;\n close(): Promise<void>;\n}\n\n/** Start the loopback RPC server for one shift. */\nexport async function startSdkRpcServer(context: DispatchContext): Promise<SdkRpcServer> {\n const dispatcher = new ToolDispatcher(context);\n\n const server = http.createServer((request, response) => {\n if (request.method !== \"POST\") {\n response.writeHead(405, { \"content-type\": \"application/json\" });\n response.end(JSON.stringify({ ok: false, error: { code: \"METHOD_NOT_ALLOWED\", message: \"POST only\" } }));\n return;\n }\n let raw = \"\";\n request.on(\"data\", (chunk) => {\n raw += chunk;\n });\n request.on(\"end\", () => {\n void (async () => {\n let payload: { tool?: unknown; args?: unknown };\n try {\n payload = JSON.parse(raw) as { tool?: unknown; args?: unknown };\n } catch {\n respond(response, { ok: false, error: { code: \"BAD_JSON\", message: \"Request body is not valid JSON\" } });\n return;\n }\n if (typeof payload.tool !== \"string\") {\n respond(response, { ok: false, error: { code: \"BAD_REQUEST\", message: 'Missing \"tool\" field' } });\n return;\n }\n try {\n const result = await dispatcher.call(\n payload.tool,\n (payload.args ?? {}) as Record<string, unknown>,\n );\n respond(response, { ok: true, result });\n } catch (error) {\n if (error instanceof ToolCallError) {\n respond(response, { ok: false, error: { code: error.code, message: error.message } });\n return;\n }\n respond(response, {\n ok: false,\n error: { code: \"INTERNAL\", message: (error as Error).message },\n });\n }\n })();\n });\n });\n\n await new Promise<void>((resolve) => {\n // Bind to loopback only — the RPC surface must never be reachable off-host.\n server.listen(0, \"127.0.0.1\", resolve);\n });\n const address = server.address();\n if (address === null || typeof address === \"string\") {\n throw new Error(\"Could not determine RPC server port\");\n }\n\n return {\n url: `http://127.0.0.1:${address.port}`,\n close: () =>\n new Promise<void>((resolve, reject) => {\n server.close((error) => (error ? reject(error) : resolve()));\n }),\n };\n}\n\nfunction respond(response: http.ServerResponse, body: unknown): void {\n const json = JSON.stringify(body);\n response.writeHead(200, { \"content-type\": \"application/json\" });\n response.end(json);\n}\n","import dns from \"node:dns/promises\";\nimport net from \"node:net\";\nimport { assertToolAllowed, ToolDeniedError } from \"../emulator/allowlist.js\";\nimport { CapExceededError, estimateTokens, type TokenMeter } from \"../emulator/tokens.js\";\nimport { completeText } from \"../emulator/llm-client.js\";\nimport type { AgentManifest } from \"../manifest/schema.js\";\nimport type { MemoryStore } from \"../memory/store.js\";\nimport type { TraceWriter } from \"../trace/writer.js\";\n\n/** Everything the dispatcher needs to execute tools for one shift. */\nexport interface DispatchContext {\n manifest: AgentManifest;\n store: MemoryStore;\n trace: TraceWriter;\n meter: TokenMeter;\n runId: string;\n}\n\n/** Structured tool error carried back to the caller (script or LLM loop). */\nexport interface ToolErrorShape {\n code: string;\n message: string;\n}\n\n/** Thrown by dispatch when a tool fails; carries a machine-readable code. */\nexport class ToolCallError extends Error {\n constructor(\n readonly code: string,\n message: string,\n ) {\n super(message);\n this.name = \"ToolCallError\";\n }\n}\n\n/** Truncated, non-sensitive one-line summary of tool args for the trace. */\nexport function summarizeArgs(args: unknown): string {\n const json = JSON.stringify(args) ?? \"{}\";\n return json.length > 200 ? `${json.slice(0, 200)}…` : json;\n}\n\n/**\n * SSRF guard for http.post_json — the same guard the platform applies.\n *\n * Checks the hostname pattern AND every IP the hostname resolves to (so a\n * public DNS name pointing at an internal address is still refused), for\n * both IPv4 and IPv6. Redirects are followed manually with each hop\n * re-validated.\n */\nfunction isBlockedHostname(hostname: string): boolean {\n const lower = hostname.toLowerCase().replace(/^\\[|\\]$/g, \"\");\n if (lower === \"localhost\" || lower.endsWith(\".localhost\")) return true;\n if (net.isIP(lower)) return isBlockedIp(lower);\n return false;\n}\n\nfunction isBlockedIp(ip: string): boolean {\n const version = net.isIP(ip);\n if (version === 4) {\n const octets = ip.split(\".\").map(Number);\n const [a = 0, b = 0] = octets;\n if (a === 0 || a === 10 || a === 127) return true; // this-net, private, loopback\n if (a === 169 && b === 254) return true; // link-local / cloud metadata\n if (a === 172 && b >= 16 && b <= 31) return true; // private\n if (a === 192 && b === 168) return true; // private\n if (a === 100 && b >= 64 && b <= 127) return true; // CGNAT\n return false;\n }\n if (version === 6) {\n const lower = ip.toLowerCase();\n if (lower === \"::\" || lower === \"::1\") return true; // unspecified, loopback\n if (lower.startsWith(\"fe8\") || lower.startsWith(\"fe9\") || lower.startsWith(\"fea\") || lower.startsWith(\"feb\"))\n return true; // link-local fe80::/10\n if (lower.startsWith(\"fc\") || lower.startsWith(\"fd\")) return true; // ULA fc00::/7\n if (lower.startsWith(\"::ffff:\")) {\n // IPv4-mapped — validate the embedded IPv4 address.\n const mapped = lower.slice(\"::ffff:\".length);\n return net.isIP(mapped) === 4 ? isBlockedIp(mapped) : true;\n }\n return false;\n }\n return true; // not a valid IP at all — refuse\n}\n\n/** Throw BLOCKED_HOST unless the hostname and all its resolved IPs are public. */\nasync function assertPublicHost(hostname: string): Promise<void> {\n if (isBlockedHostname(hostname)) {\n throw new ToolCallError(\n \"BLOCKED_HOST\",\n `http.post_json refuses internal/private hosts (\"${hostname}\") — same guard the platform applies.`,\n );\n }\n const bare = hostname.replace(/^\\[|\\]$/g, \"\");\n if (net.isIP(bare)) return; // literal IP already validated above\n let addresses: { address: string }[];\n try {\n addresses = await dns.lookup(bare, { all: true, verbatim: true });\n } catch {\n throw new ToolCallError(\"BAD_URL\", `http.post_json could not resolve host \"${hostname}\"`);\n }\n for (const { address } of addresses) {\n if (isBlockedIp(address)) {\n throw new ToolCallError(\n \"BLOCKED_HOST\",\n `http.post_json refuses \"${hostname}\" — it resolves to the internal/private address ${address}.`,\n );\n }\n }\n}\n\n/** Max redirect hops http.post_json will follow (each hop is re-validated). */\nconst MAX_REDIRECTS = 3;\n\n/**\n * Executes one tool call with the full platform semantics:\n * allowlist check -> execution -> trace `tool_call` event (allow/deny,\n * duration). Used by both the loopback RPC server (wrap mode) and the\n * llm-mode tool-use loop, so enforcement is identical in both paths.\n */\nexport class ToolDispatcher {\n constructor(private readonly context: DispatchContext) {}\n\n /** All tools the emulator knows how to execute. */\n static readonly KNOWN_TOOLS = [\n \"s3.put\",\n \"s3.get\",\n \"s3.list\",\n \"s3.delete\",\n \"http.post_json\",\n \"llm.complete\",\n \"notify.send\",\n \"metrics.record\",\n ] as const;\n\n /**\n * Execute `tool` with `args`. Always writes a tool_call trace event, whether\n * the call was allowed, denied, or failed.\n */\n async call(tool: string, args: Record<string, unknown>): Promise<unknown> {\n const { manifest, trace, runId } = this.context;\n const startedAt = Date.now();\n const base = {\n ts: new Date().toISOString(),\n runId,\n agent: manifest.name,\n type: \"tool_call\" as const,\n tool,\n argsSummary: summarizeArgs(args),\n };\n\n // 1. Allowlist — every tool call is checked; disallowed calls fail loudly.\n try {\n assertToolAllowed(manifest.toolAllowlist, tool);\n } catch (error) {\n trace.append({\n ...base,\n allowed: false,\n ok: false,\n durationMs: Date.now() - startedAt,\n error: (error as Error).message,\n });\n throw new ToolCallError(\"TOOL_DENIED\", (error as ToolDeniedError).message);\n }\n\n // 2. Execute.\n try {\n const result = await this.execute(tool, args);\n trace.append({ ...base, allowed: true, ok: true, durationMs: Date.now() - startedAt });\n return result;\n } catch (error) {\n const message = (error as Error).message;\n trace.append({\n ...base,\n allowed: true,\n ok: false,\n durationMs: Date.now() - startedAt,\n error: message,\n });\n if (error instanceof ToolCallError) throw error;\n if (error instanceof CapExceededError) throw new ToolCallError(error.code, message);\n throw new ToolCallError(\"TOOL_ERROR\", message);\n }\n }\n\n private async execute(tool: string, args: Record<string, unknown>): Promise<unknown> {\n const { store, meter, trace, manifest, runId } = this.context;\n switch (tool) {\n case \"s3.put\": {\n const key = requireString(args, \"key\");\n const body = requireString(args, \"body\");\n const category = optionalString(args, \"category\");\n const record = await store.put(key, Buffer.from(body, \"utf8\"), category);\n return { record };\n }\n case \"s3.get\": {\n const keyOrId = requireString(args, \"keyOrId\");\n const asset = await store.get(keyOrId);\n if (!asset) {\n throw new ToolCallError(\"NOT_FOUND\", `No active memory asset matches \"${keyOrId}\"`);\n }\n return { record: asset.record, body: asset.body.toString(\"utf8\") };\n }\n case \"s3.list\": {\n const prefix = optionalString(args, \"prefix\");\n const limit = typeof args.limit === \"number\" ? args.limit : undefined;\n const records = await store.list(prefix, limit);\n return { records };\n }\n case \"s3.delete\": {\n const keyOrId = requireString(args, \"keyOrId\");\n const record = await store.delete(keyOrId);\n if (!record) {\n throw new ToolCallError(\"NOT_FOUND\", `No active memory asset matches \"${keyOrId}\"`);\n }\n return { record };\n }\n case \"http.post_json\": {\n const url = requireString(args, \"url\");\n const headers = (args.headers ?? {}) as Record<string, string>;\n const requestBody = JSON.stringify(args.body ?? {});\n\n // Redirects are followed manually so every hop goes through the same\n // SSRF guard — a public URL redirecting to an internal address is\n // refused just like a direct request to it would be.\n let currentUrl = url;\n let response: Response;\n for (let hop = 0; ; hop += 1) {\n const parsed = safeParseUrl(currentUrl);\n if (!parsed || (parsed.protocol !== \"http:\" && parsed.protocol !== \"https:\")) {\n throw new ToolCallError(\n \"BAD_URL\",\n `http.post_json needs an http(s) URL, got \"${currentUrl}\"`,\n );\n }\n await assertPublicHost(parsed.hostname);\n response = await fetch(currentUrl, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\", ...headers },\n body: requestBody,\n redirect: \"manual\",\n });\n if (response.status < 300 || response.status >= 400) break;\n const location = response.headers.get(\"location\");\n if (!location) break;\n if (hop >= MAX_REDIRECTS) {\n throw new ToolCallError(\n \"TOO_MANY_REDIRECTS\",\n `http.post_json gave up after ${MAX_REDIRECTS} redirects (last: ${currentUrl})`,\n );\n }\n currentUrl = new URL(location, currentUrl).toString();\n }\n\n const text = await response.text();\n let json: unknown = null;\n try {\n json = JSON.parse(text);\n } catch {\n // Non-JSON responses come back as text only; that is not an error.\n }\n return { status: response.status, ok: response.ok, body: text, json };\n }\n case \"llm.complete\": {\n const prompt = requireString(args, \"prompt\");\n const model = optionalString(args, \"model\");\n // Pre-turn projection against the per-run cap (A.2 step 3): prompt\n // estimate + the max output we allow for one completion.\n const maxOutput = 1024;\n meter.admitLlmTurn(estimateTokens(prompt) + maxOutput);\n const completion = await completeText(prompt, model, maxOutput);\n const consumed = completion.inputTokens + completion.outputTokens;\n const dayTotal = meter.add(consumed);\n trace.append({\n ts: new Date().toISOString(),\n runId,\n agent: manifest.name,\n type: \"tokens\",\n tokens: consumed,\n runTotal: meter.runTotal,\n dayTotal,\n source: `llm.complete ${completion.provider}/${completion.model}`,\n });\n return {\n text: completion.text,\n model: completion.model,\n provider: completion.provider,\n inputTokens: completion.inputTokens,\n outputTokens: completion.outputTokens,\n };\n }\n case \"notify.send\": {\n // Locally, notifications just land in the trace (the tool_call event\n // records channel + message via argsSummary). Nothing is sent anywhere.\n requireString(args, \"channel\");\n requireString(args, \"message\");\n return { delivered: \"trace\" };\n }\n case \"metrics.record\": {\n // Locally, metrics are appended to the trace via the tool_call event.\n requireString(args, \"name\");\n if (typeof args.value !== \"number\") {\n throw new ToolCallError(\"BAD_ARGS\", \"metrics.record needs a numeric value\");\n }\n return { recorded: \"trace\" };\n }\n default:\n throw new ToolCallError(\n \"UNKNOWN_TOOL\",\n `Unknown tool \"${tool}\". Known tools: ${ToolDispatcher.KNOWN_TOOLS.join(\", \")}`,\n );\n }\n }\n}\n\nfunction requireString(args: Record<string, unknown>, name: string): string {\n const value = args[name];\n if (typeof value !== \"string\" || value.length === 0) {\n throw new ToolCallError(\"BAD_ARGS\", `Missing required string argument \"${name}\"`);\n }\n return value;\n}\n\nfunction optionalString(args: Record<string, unknown>, name: string): string | undefined {\n const value = args[name];\n if (value === undefined || value === null) return undefined;\n if (typeof value !== \"string\") {\n throw new ToolCallError(\"BAD_ARGS\", `Argument \"${name}\" must be a string when provided`);\n }\n return value;\n}\n\nfunction safeParseUrl(url: string): URL | null {\n try {\n return new URL(url);\n } catch {\n return null;\n }\n}\n","/**\n * Tool allowlist enforcement.\n *\n * The platform checks every tool call an agent makes against\n * `agentToolAllowlist`; the emulator applies the identical rule to\n * `toolAllowlist` from kohala.json. There are no implicit grants — a tool the\n * manifest does not list is denied loudly, and the denial is recorded in the\n * trace.\n */\n\n/** Thrown when a script or LLM loop calls a tool that is not allowlisted. */\nexport class ToolDeniedError extends Error {\n constructor(readonly tool: string, allowlist: readonly string[]) {\n super(\n `TOOL_DENIED: \"${tool}\" is not in the agent's toolAllowlist ` +\n `[${allowlist.join(\", \")}]. Add it to kohala.json if the agent should be able to use it.`,\n );\n this.name = \"ToolDeniedError\";\n }\n}\n\n/** True when the manifest allows this exact tool name. */\nexport function isToolAllowed(allowlist: readonly string[], tool: string): boolean {\n return allowlist.includes(tool);\n}\n\n/** Assert a tool is allowed; throws ToolDeniedError otherwise. */\nexport function assertToolAllowed(allowlist: readonly string[], tool: string): void {\n if (!isToolAllowed(allowlist, tool)) {\n throw new ToolDeniedError(tool, allowlist);\n }\n}\n","/**\n * Thin LLM client used by `llm.complete` (wrap mode) and the llm-mode loop.\n *\n * Uses the developer's OWN key from the environment — ANTHROPIC_API_KEY first,\n * then GEMINI_API_KEY. If neither is set the call fails with a clear\n * \"no key configured\" error. There is deliberately no mock fallback: silent\n * fake completions would hide real integration problems (Part B: errors fail\n * loudly).\n */\n\n/** Result of a single completion, with token usage for cap accounting. */\nexport interface CompletionResult {\n text: string;\n inputTokens: number;\n outputTokens: number;\n provider: \"anthropic\" | \"gemini\";\n model: string;\n}\n\n/** Thrown when no LLM API key is configured in the environment. */\nexport class NoLlmKeyError extends Error {\n constructor() {\n super(\n \"NO_LLM_KEY: no LLM key configured. Set ANTHROPIC_API_KEY (preferred) or \" +\n \"GEMINI_API_KEY in your environment — the devkit never mocks completions.\",\n );\n this.name = \"NoLlmKeyError\";\n }\n}\n\n/**\n * Default models per provider.\n *\n * Override at runtime with environment variables:\n * ANTHROPIC_MODEL — e.g. \"claude-3-5-haiku-latest\"\n * GEMINI_MODEL — e.g. \"gemini-2.0-flash\"\n * KOHALA_LLM_MODEL — provider-agnostic override (takes precedence)\n *\n * Defaults match the hosted platform so local behaviour is as close as\n * possible to what runs after `kohala deploy`.\n */\nconst DEFAULT_ANTHROPIC_MODEL = \"claude-sonnet-4-6\";\nconst DEFAULT_GEMINI_MODEL = \"gemini-flash-latest\";\n\n/** Which provider will handle completions given the current environment. */\nexport function detectLlmProvider(\n env: NodeJS.ProcessEnv = process.env,\n): \"anthropic\" | \"gemini\" | null {\n if (env.ANTHROPIC_API_KEY) return \"anthropic\";\n if (env.GEMINI_API_KEY) return \"gemini\";\n return null;\n}\n\n/**\n * Complete a prompt with the developer's own key.\n *\n * @param prompt - The user prompt to complete.\n * @param model - Optional model override (provider-native model name).\n * @param maxOutputTokens - Ceiling passed to the provider (defaults to 1024).\n */\nexport async function completeText(\n prompt: string,\n model?: string,\n maxOutputTokens = 1024,\n env: NodeJS.ProcessEnv = process.env,\n): Promise<CompletionResult> {\n const provider = detectLlmProvider(env);\n if (provider === \"anthropic\") {\n // Resolution order: explicit arg → KOHALA_LLM_MODEL → ANTHROPIC_MODEL → default\n const resolvedModel =\n model ??\n env.KOHALA_LLM_MODEL ??\n env.ANTHROPIC_MODEL ??\n DEFAULT_ANTHROPIC_MODEL;\n return completeAnthropic(prompt, resolvedModel, maxOutputTokens, env);\n }\n if (provider === \"gemini\") {\n // Resolution order: explicit arg → KOHALA_LLM_MODEL → GEMINI_MODEL → default\n const resolvedModel =\n model ??\n env.KOHALA_LLM_MODEL ??\n env.GEMINI_MODEL ??\n DEFAULT_GEMINI_MODEL;\n return completeGemini(prompt, resolvedModel, maxOutputTokens, env);\n }\n throw new NoLlmKeyError();\n}\n\nasync function completeAnthropic(\n prompt: string,\n model: string,\n maxOutputTokens: number,\n env: NodeJS.ProcessEnv,\n): Promise<CompletionResult> {\n const response = await fetch(\"https://api.anthropic.com/v1/messages\", {\n method: \"POST\",\n headers: {\n \"content-type\": \"application/json\",\n \"x-api-key\": env.ANTHROPIC_API_KEY as string,\n \"anthropic-version\": \"2023-06-01\",\n },\n body: JSON.stringify({\n model,\n max_tokens: maxOutputTokens,\n messages: [{ role: \"user\", content: prompt }],\n }),\n });\n if (!response.ok) {\n const body = await response.text();\n throw new Error(`Anthropic API error ${response.status}: ${body.slice(0, 300)}`);\n }\n const data = (await response.json()) as {\n content: { type: string; text?: string }[];\n usage: { input_tokens: number; output_tokens: number };\n };\n const text = data.content\n .filter((block) => block.type === \"text\")\n .map((block) => block.text ?? \"\")\n .join(\"\");\n return {\n text,\n inputTokens: data.usage.input_tokens,\n outputTokens: data.usage.output_tokens,\n provider: \"anthropic\",\n model,\n };\n}\n\nasync function completeGemini(\n prompt: string,\n model: string,\n maxOutputTokens: number,\n env: NodeJS.ProcessEnv,\n): Promise<CompletionResult> {\n const url = `https://generativelanguage.googleapis.com/v1beta/models/${model}:generateContent`;\n const response = await fetch(url, {\n method: \"POST\",\n headers: {\n \"content-type\": \"application/json\",\n \"x-goog-api-key\": env.GEMINI_API_KEY as string,\n },\n body: JSON.stringify({\n contents: [{ parts: [{ text: prompt }] }],\n generationConfig: { maxOutputTokens },\n }),\n });\n if (!response.ok) {\n const body = await response.text();\n throw new Error(`Gemini API error ${response.status}: ${body.slice(0, 300)}`);\n }\n const data = (await response.json()) as {\n candidates?: { content?: { parts?: { text?: string }[] } }[];\n usageMetadata?: { promptTokenCount?: number; candidatesTokenCount?: number };\n };\n const text = (data.candidates?.[0]?.content?.parts ?? []).map((part) => part.text ?? \"\").join(\"\");\n return {\n text,\n inputTokens: data.usageMetadata?.promptTokenCount ?? 0,\n outputTokens: data.usageMetadata?.candidatesTokenCount ?? 0,\n provider: \"gemini\",\n model,\n };\n}\n","import fs from \"node:fs\";\nimport { estimateTokens } from \"./tokens.js\";\nimport { ToolCallError, ToolDispatcher, type DispatchContext } from \"../sdk/dispatch.js\";\n\n/**\n * llm runtime mode — a real tool-use loop against the developer's own\n * Anthropic key (Anthropic first, per the build plan; Gemini support for\n * llm-mode can follow).\n *\n * The allowlisted tools are exposed to the model as tool definitions; every\n * tool invocation goes through the same ToolDispatcher as wrap mode, so\n * allowlist checks, tracing, and token accounting are identical. Before each\n * turn we project the next request's token cost against caps.perRunTokens and\n * abort with PER_RUN_TOKEN_CAP if it would cross (A.2 step 3).\n */\n\n/** Max loop turns as a hard safety stop, independent of token caps. */\nconst MAX_TURNS = 16;\n\n/** Per-turn output ceiling passed to the API. */\nconst MAX_OUTPUT_TOKENS = 1024;\n\n/** JSON Schema definitions for each platform tool, keyed by tool name. */\nconst TOOL_DEFINITIONS: Record<string, { description: string; input_schema: object }> = {\n \"s3.put\": {\n description:\n 'Store a value in agent memory under a logical key. Category defaults to \"agentoutput\".',\n input_schema: {\n type: \"object\",\n properties: {\n key: { type: \"string\" },\n body: { type: \"string\" },\n category: { type: \"string\" },\n },\n required: [\"key\", \"body\"],\n },\n },\n \"s3.get\": {\n description: \"Fetch a memory asset by logical key (or record id).\",\n input_schema: {\n type: \"object\",\n properties: { keyOrId: { type: \"string\" } },\n required: [\"keyOrId\"],\n },\n },\n \"s3.list\": {\n description: \"List active memory assets, optionally filtered by key prefix.\",\n input_schema: {\n type: \"object\",\n properties: { prefix: { type: \"string\" }, limit: { type: \"number\" } },\n },\n },\n \"s3.delete\": {\n description: \"Remove and deactivate a memory asset by key or id.\",\n input_schema: {\n type: \"object\",\n properties: { keyOrId: { type: \"string\" } },\n required: [\"keyOrId\"],\n },\n },\n \"http.post_json\": {\n description: \"POST a JSON body to an external http(s) URL and return the response.\",\n input_schema: {\n type: \"object\",\n properties: {\n url: { type: \"string\" },\n body: { type: \"object\" },\n headers: { type: \"object\" },\n },\n required: [\"url\"],\n },\n },\n \"notify.send\": {\n description: \"Send a notification (locally this is recorded in the audit trace).\",\n input_schema: {\n type: \"object\",\n properties: { channel: { type: \"string\" }, message: { type: \"string\" } },\n required: [\"channel\", \"message\"],\n },\n },\n \"metrics.record\": {\n description: \"Record a metric point (locally this is recorded in the audit trace).\",\n input_schema: {\n type: \"object\",\n properties: {\n name: { type: \"string\" },\n value: { type: \"number\" },\n tags: { type: \"object\" },\n },\n required: [\"name\", \"value\"],\n },\n },\n};\n\ninterface AnthropicContentBlock {\n type: string;\n text?: string;\n id?: string;\n name?: string;\n input?: Record<string, unknown>;\n tool_use_id?: string;\n content?: string;\n is_error?: boolean;\n}\n\ninterface AnthropicResponse {\n content: AnthropicContentBlock[];\n stop_reason: string;\n usage: { input_tokens: number; output_tokens: number };\n}\n\n/**\n * Run one llm-mode shift. Returns the model's final text output.\n *\n * The skill script file, if present, contributes its contents as task context\n * (llm-mode agents describe their task in the skill file; the charter is the\n * system prompt) — this mirrors how the platform prompts hosted llm agents.\n */\nexport async function runLlmShift(\n context: DispatchContext,\n skillName: string,\n scriptPath: string,\n repairFeedback?: string,\n): Promise<string> {\n const apiKey = process.env.ANTHROPIC_API_KEY;\n if (!apiKey) {\n // llm mode uses the Anthropic tool-use API specifically.\n // GEMINI_API_KEY enables llm.complete in wrap mode but not this loop.\n throw new Error(\n \"NO_LLM_KEY: llm mode requires ANTHROPIC_API_KEY. \" +\n \"GEMINI_API_KEY enables llm.complete calls inside wrap-mode skills, \" +\n \"but the llm-mode tool-use loop only supports Anthropic. \" +\n \"Set ANTHROPIC_API_KEY in your environment to use runtimeMode: \\\"llm\\\".\",\n );\n }\n // Resolution order: KOHALA_LLM_MODEL → ANTHROPIC_MODEL → default.\n // Default matches the hosted platform model so local behaviour is close to deployed.\n const model =\n process.env.KOHALA_LLM_MODEL ?? process.env.ANTHROPIC_MODEL ?? \"claude-sonnet-4-6\";\n const dispatcher = new ToolDispatcher(context);\n const { manifest, meter, trace, runId } = context;\n\n // Only allowlisted tools are exposed as definitions — the model cannot even\n // see tools it is not allowed to call.\n const tools = Object.entries(TOOL_DEFINITIONS)\n .filter(([name]) => manifest.toolAllowlist.includes(name))\n .map(([name, definition]) => ({ name: toApiToolName(name), ...definition }));\n\n const taskContext = fs.existsSync(scriptPath) ? fs.readFileSync(scriptPath, \"utf8\") : \"\";\n const messages: { role: \"user\" | \"assistant\"; content: unknown }[] = [\n {\n role: \"user\",\n content:\n `You are running one shift of the agent skill \"${skillName}\".\\n` +\n (taskContext ? `Task instructions:\\n${taskContext}\\n` : \"\") +\n (repairFeedback\n ? `\\nThis is a repair attempt. Your previous output failed validation:\\n${repairFeedback}\\nFix the problem this time.\\n`\n : \"\") +\n \"Use your tools as needed, then reply with a final text summary of what you did.\",\n },\n ];\n\n for (let turn = 0; turn < MAX_TURNS; turn += 1) {\n // Pre-turn projection (A.2 step 3): estimate the request we are about to\n // send plus the response ceiling, and abort before crossing the cap.\n const projected = estimateTokens(JSON.stringify(messages) + manifest.charter) + MAX_OUTPUT_TOKENS;\n meter.admitLlmTurn(projected);\n\n const response = await fetch(\"https://api.anthropic.com/v1/messages\", {\n method: \"POST\",\n headers: {\n \"content-type\": \"application/json\",\n \"x-api-key\": apiKey,\n \"anthropic-version\": \"2023-06-01\",\n },\n body: JSON.stringify({\n model,\n max_tokens: MAX_OUTPUT_TOKENS,\n system: manifest.charter,\n tools,\n messages,\n }),\n });\n if (!response.ok) {\n const body = await response.text();\n throw new Error(`Anthropic API error ${response.status}: ${body.slice(0, 300)}`);\n }\n const data = (await response.json()) as AnthropicResponse;\n\n const consumed = data.usage.input_tokens + data.usage.output_tokens;\n const dayTotal = meter.add(consumed);\n trace.append({\n ts: new Date().toISOString(),\n runId,\n agent: manifest.name,\n type: \"tokens\",\n tokens: consumed,\n runTotal: meter.runTotal,\n dayTotal,\n source: `llm-mode turn ${turn + 1} (${model})`,\n });\n\n const finalText = data.content\n .filter((block) => block.type === \"text\")\n .map((block) => block.text ?? \"\")\n .join(\"\");\n\n if (data.stop_reason !== \"tool_use\") {\n return finalText;\n }\n\n // Execute each requested tool through the shared dispatcher, then feed\n // results (or loud errors) back to the model.\n messages.push({ role: \"assistant\", content: data.content });\n const toolResults: AnthropicContentBlock[] = [];\n for (const block of data.content) {\n if (block.type !== \"tool_use\" || !block.id || !block.name) continue;\n const toolName = fromApiToolName(block.name);\n try {\n const result = await dispatcher.call(toolName, block.input ?? {});\n toolResults.push({\n type: \"tool_result\",\n tool_use_id: block.id,\n content: JSON.stringify(result).slice(0, 8000),\n });\n } catch (error) {\n const toolError = error as ToolCallError;\n toolResults.push({\n type: \"tool_result\",\n tool_use_id: block.id,\n content: `${toolError.code ?? \"TOOL_ERROR\"}: ${toolError.message}`,\n is_error: true,\n });\n }\n }\n messages.push({ role: \"user\", content: toolResults });\n }\n\n throw new Error(`llm-mode shift exceeded ${MAX_TURNS} turns without finishing`);\n}\n\n/**\n * Anthropic tool names must match [a-zA-Z0-9_-], so the platform's dotted\n * names are transported with \"__\" in place of \".\" and mapped back on dispatch.\n */\nfunction toApiToolName(name: string): string {\n return name.replace(/\\./g, \"__\");\n}\n\nfunction fromApiToolName(name: string): string {\n return name.replace(/__/g, \".\");\n}\n","import { execa } from \"execa\";\n\n/**\n * Python is an optional runtime dependency at use time (running skills),\n * never an install-time dependency. We look for `python3` first, then\n * `python`, and fail with an actionable message if neither exists.\n */\nlet cachedPython: string | null = null;\n\n/** Locate a working Python 3 interpreter or throw with install guidance. */\nexport async function findPython(): Promise<string> {\n if (cachedPython) return cachedPython;\n for (const candidate of [\"python3\", \"python\"]) {\n try {\n const result = await execa(candidate, [\"--version\"], { reject: false });\n if (result.exitCode === 0 && /Python 3/.test(`${result.stdout}${result.stderr}`)) {\n cachedPython = candidate;\n return candidate;\n }\n } catch {\n // Candidate not on PATH — try the next one.\n }\n }\n throw new Error(\n \"Python 3 is required to run agent skills but was not found on your PATH. \" +\n \"Install it from https://www.python.org/downloads/ (or via your package manager: \" +\n \"`brew install python3`, `apt install python3`), then re-run this command.\",\n );\n}\n\n/** Test-only: reset the cached interpreter path. */\nexport function resetPythonCache(): void {\n cachedPython = null;\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport type { Command } from \"commander\";\nimport pc from \"picocolors\";\nimport { followTraceFile, readTraceFile } from \"../trace/reader.js\";\nimport { formatTraceEvent } from \"../trace/format.js\";\nimport { traceFilePath } from \"../trace/writer.js\";\nimport { loadManifest } from \"../manifest/load.js\";\n\n/**\n * `kohala trace <agent>` — pretty-print (and optionally follow) the agent's\n * JSONL audit trace, the local twin of the platform's run records.\n */\nexport function registerTraceCommand(program: Command): void {\n program\n .command(\"trace\")\n .argument(\"<agent>\", \"agent directory or agent name\")\n .option(\"--follow\", \"keep watching for new events (like tail -f)\")\n .option(\"--json\", \"print raw JSONL events instead of the pretty view\")\n .description(\"Tail the audit trace for an agent\")\n .action((agent: string, options: { follow?: boolean; json?: boolean }) => {\n const rootDir = process.cwd();\n // Accept either a directory (read its manifest for the name) or a bare name.\n let agentName = agent;\n const agentDir = path.resolve(rootDir, agent);\n if (fs.existsSync(path.join(agentDir, \"kohala.json\"))) {\n agentName = loadManifest(agentDir).name;\n }\n const filePath = traceFilePath(rootDir, agentName);\n if (!fs.existsSync(filePath)) {\n throw new Error(\n `No trace found for \"${agentName}\" (looked at ${filePath}). Run the agent first: kohala run ${agent} --local`,\n );\n }\n\n const print = options.json\n ? (event: object) => console.log(JSON.stringify(event))\n : (event: object) => console.log(formatTraceEvent(event as Parameters<typeof formatTraceEvent>[0]));\n\n for (const event of readTraceFile(filePath)) {\n print(event);\n }\n\n if (options.follow) {\n console.error(pc.dim(`— following ${filePath} (ctrl-c to stop) —`));\n followTraceFile(filePath, print);\n }\n });\n}\n","import fs from \"node:fs\";\nimport type { TraceEvent } from \"./events.js\";\n\n/**\n * Parse the full contents of a JSONL trace file.\n *\n * Unparseable lines are surfaced as errors rather than skipped — a corrupt\n * audit trail should be loud, not silently truncated.\n */\nexport function readTraceFile(filePath: string): TraceEvent[] {\n const raw = fs.readFileSync(filePath, \"utf8\");\n return parseTraceLines(raw);\n}\n\n/** Parse raw JSONL text into events. Throws on malformed lines. */\nexport function parseTraceLines(raw: string): TraceEvent[] {\n const events: TraceEvent[] = [];\n const lines = raw.split(\"\\n\");\n for (let i = 0; i < lines.length; i += 1) {\n const line = (lines[i] ?? \"\").trim();\n if (line === \"\") continue;\n try {\n events.push(JSON.parse(line) as TraceEvent);\n } catch {\n throw new Error(`Malformed trace line ${i + 1}: ${line.slice(0, 120)}`);\n }\n }\n return events;\n}\n\n/**\n * Follow a trace file, invoking `onEvent` for each new complete line.\n *\n * Implemented with polling (not fs.watch) because appends from a separate\n * process are flaky to observe via inotify on some filesystems; a 250ms poll\n * is plenty for a human tailing a trace. Returns a stop function.\n */\nexport function followTraceFile(\n filePath: string,\n onEvent: (event: TraceEvent) => void,\n pollMs = 250,\n): () => void {\n let offset = fs.existsSync(filePath) ? fs.statSync(filePath).size : 0;\n let partial = \"\";\n\n const timer = setInterval(() => {\n if (!fs.existsSync(filePath)) return;\n const size = fs.statSync(filePath).size;\n if (size <= offset) return;\n\n const stream = fs.createReadStream(filePath, { start: offset, end: size - 1, encoding: \"utf8\" });\n let chunkData = \"\";\n stream.on(\"data\", (chunk) => {\n chunkData += chunk;\n });\n stream.on(\"end\", () => {\n offset = size;\n partial += chunkData;\n const lines = partial.split(\"\\n\");\n partial = lines.pop() ?? \"\";\n for (const line of lines) {\n const trimmed = line.trim();\n if (trimmed === \"\") continue;\n try {\n onEvent(JSON.parse(trimmed) as TraceEvent);\n } catch {\n // A malformed line while following is reported once, loudly.\n throw new Error(`Malformed trace line while following: ${trimmed.slice(0, 120)}`);\n }\n }\n });\n }, pollMs);\n\n return () => clearInterval(timer);\n}\n","import pc from \"picocolors\";\nimport type { TraceEvent } from \"./events.js\";\n\n/** Short local time (HH:MM:SS) for the human-readable trace view. */\nfunction shortTime(ts: string): string {\n const date = new Date(ts);\n return date.toLocaleTimeString(\"en-US\", { hour12: false });\n}\n\n/**\n * Pretty-print one trace event for `kohala trace`.\n *\n * The goal is a scannable audit log: status words are colorized, tool denials\n * and validator failures jump out in red, token accounting stays dim.\n */\nexport function formatTraceEvent(event: TraceEvent): string {\n const time = pc.dim(shortTime(event.ts));\n switch (event.type) {\n case \"run_started\":\n return `${time} ${pc.cyan(\"run_started\")} skill=${event.skill} (${event.scriptFilename}) mode=${event.runtimeMode} run=${event.runId}`;\n case \"tool_call\": {\n const verdict = event.allowed\n ? event.ok\n ? pc.green(\"ok\")\n : pc.red(\"error\")\n : pc.red(\"DENIED\");\n const errorSuffix = event.error ? ` ${pc.red(event.error)}` : \"\";\n return `${time} ${pc.magenta(\"tool_call\")} ${pc.bold(event.tool)} ${verdict} ${pc.dim(`${event.durationMs}ms`)} ${pc.dim(event.argsSummary)}${errorSuffix}`;\n }\n case \"tokens\":\n return `${time} ${pc.dim(`tokens +${event.tokens} run=${event.runTotal} day=${event.dayTotal} (${event.source})`)}`;\n case \"validator_result\": {\n const verdict = event.passed ? pc.green(\"passed\") : pc.red(\"FAILED\");\n return `${time} ${pc.yellow(\"validator\")} ${event.validator} ${verdict} ${pc.dim(event.detail)}`;\n }\n case \"repair_attempt\":\n return `${time} ${pc.yellow(`repair_attempt ${event.attempt}/${event.maxAttempts}`)} ${pc.dim(event.reason)}`;\n case \"run_finished\": {\n const color =\n event.status === \"succeeded\" ? pc.green : event.status === \"failed\" ? pc.red : pc.red;\n const detailSuffix = event.detail ? ` ${pc.dim(event.detail)}` : \"\";\n return `${time} ${color(`run_finished ${event.status}`)} tokens=${event.totalTokens} ${pc.dim(`${event.durationMs}ms`)}${detailSuffix}`;\n }\n }\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport type { Command } from \"commander\";\nimport pc from \"picocolors\";\nimport { createMemoryStore, type MemoryBackend } from \"../memory/create.js\";\nimport { serveHttp, serveStdio } from \"../mcp/server.js\";\nimport { loadManifest } from \"../manifest/load.js\";\n\n/**\n * `kohala memory serve` — run the open MCP memory server.\n *\n * Transports:\n * default — stdio, for MCP clients that spawn a child process\n * --http — streamable HTTP on 127.0.0.1:<port>/mcp (MCP Inspector etc.)\n *\n * Backends: file (default, .kohala/memory/<agent>/) or postgres (--url or\n * DATABASE_URL). Memory is always scoped to one agent, like the platform.\n */\nexport function registerMemoryCommand(program: Command): void {\n const memory = program.command(\"memory\").description(\"Memory server commands\");\n\n memory\n .command(\"serve\")\n .option(\"--agent <name>\", \"agent name to scope memory to (or run from an agent dir)\")\n .option(\"--backend <backend>\", \"file | postgres\", \"file\")\n .option(\"--url <url>\", \"postgres connection string (or set DATABASE_URL)\")\n .option(\"--http\", \"serve over streamable HTTP instead of stdio\")\n .option(\"--port <port>\", \"HTTP port (with --http)\", \"8787\")\n .description(\"Serve agent memory over the Model Context Protocol\")\n .action(\n async (options: {\n agent?: string;\n backend: string;\n url?: string;\n http?: boolean;\n port: string;\n }) => {\n if (options.backend !== \"file\" && options.backend !== \"postgres\") {\n throw new Error(`Unknown backend \"${options.backend}\" — use \"file\" or \"postgres\".`);\n }\n\n // Agent resolution: explicit --agent wins; otherwise, if the current\n // directory is an agent dir (has kohala.json), use its name.\n let agent = options.agent;\n let rootDir = process.cwd();\n if (!agent) {\n const manifestHere = path.join(process.cwd(), \"kohala.json\");\n if (fs.existsSync(manifestHere)) {\n agent = loadManifest(process.cwd()).name;\n // Memory for an agent dir lives in the parent workspace root.\n rootDir = path.dirname(process.cwd());\n } else {\n throw new Error(\n \"Pass --agent <name>, or run this from inside an agent directory (one containing kohala.json).\",\n );\n }\n }\n\n const store = await createMemoryStore({\n backend: options.backend as MemoryBackend,\n agent,\n rootDir,\n url: options.url ?? process.env.DATABASE_URL,\n });\n\n if (options.http) {\n const port = Number(options.port);\n await serveHttp(store, agent, port);\n // Log to stderr so stdout stays clean for any piping.\n console.error(\n pc.green(`MCP memory server for \"${agent}\" listening on http://127.0.0.1:${port}/mcp`),\n );\n console.error(pc.dim(`backend=${options.backend} — ctrl-c to stop`));\n } else {\n console.error(\n pc.dim(`MCP memory server for \"${agent}\" on stdio (backend=${options.backend})`),\n );\n await serveStdio(store, agent);\n }\n },\n );\n}\n","import http from \"node:http\";\nimport { z } from \"zod\";\nimport { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport { StreamableHTTPServerTransport } from \"@modelcontextprotocol/sdk/server/streamableHttp.js\";\nimport { DEFAULT_CATEGORY, type MemoryStore } from \"../memory/store.js\";\n\n/**\n * The open MCP memory server — `kohala memory serve`.\n *\n * Exposes the platform's four memory tools over the Model Context Protocol\n * with identical names and semantics (A.1), so an agent using this server\n * locally needs zero changes when it goes live:\n *\n * s3.put / s3.get / s3.list / s3.delete\n *\n * Also exposes a `memory://index` resource that lists all active assets.\n * Supported transports: stdio (default, for MCP clients that spawn a child\n * process) and streamable HTTP (for MCP Inspector and remote-style clients).\n */\n\n/** Server identity advertised over MCP. */\nconst SERVER_INFO = { name: \"kohala-memory\", version: \"0.1.0\" };\n\n/** Build a configured MCP server bound to one agent's MemoryStore. */\nexport function buildMemoryMcpServer(store: MemoryStore, agent: string): McpServer {\n const server = new McpServer(SERVER_INFO);\n\n server.registerTool(\n \"s3.put\",\n {\n title: \"Store memory asset\",\n description:\n `Store a value in ${agent}'s persistent memory under a logical key. ` +\n `Category defaults to \"${DEFAULT_CATEGORY}\" (run results).`,\n inputSchema: {\n key: z.string().min(1).describe(\"Logical key, e.g. weather/latest\"),\n body: z.string().describe(\"UTF-8 body to store\"),\n category: z.string().optional().describe(`Asset category (default \"${DEFAULT_CATEGORY}\")`),\n },\n },\n async ({ key, body, category }) => {\n const record = await store.put(key, Buffer.from(body, \"utf8\"), category);\n return { content: [{ type: \"text\", text: JSON.stringify({ record }, null, 2) }] };\n },\n );\n\n server.registerTool(\n \"s3.get\",\n {\n title: \"Fetch memory asset\",\n description: \"Fetch an asset by logical key (resolved first) or record id.\",\n inputSchema: {\n keyOrId: z.string().min(1).describe(\"Logical key or record id\"),\n },\n },\n async ({ keyOrId }) => {\n const asset = await store.get(keyOrId);\n if (!asset) {\n return {\n isError: true,\n content: [{ type: \"text\", text: `No active memory asset matches \"${keyOrId}\"` }],\n };\n }\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(\n { record: asset.record, body: asset.body.toString(\"utf8\") },\n null,\n 2,\n ),\n },\n ],\n };\n },\n );\n\n server.registerTool(\n \"s3.list\",\n {\n title: \"List memory assets\",\n description: \"List active assets for the agent, newest first, optionally by key prefix.\",\n inputSchema: {\n prefix: z.string().optional().describe(\"Only keys starting with this prefix\"),\n limit: z.number().int().positive().optional().describe(\"Max records (default 100)\"),\n },\n },\n async ({ prefix, limit }) => {\n const records = await store.list(prefix, limit);\n return { content: [{ type: \"text\", text: JSON.stringify({ records }, null, 2) }] };\n },\n );\n\n server.registerTool(\n \"s3.delete\",\n {\n title: \"Delete memory asset\",\n description: \"Remove an asset's body and deactivate its index entry (soft delete).\",\n inputSchema: {\n keyOrId: z.string().min(1).describe(\"Logical key or record id\"),\n },\n },\n async ({ keyOrId }) => {\n const record = await store.delete(keyOrId);\n if (!record) {\n return {\n isError: true,\n content: [{ type: \"text\", text: `No active memory asset matches \"${keyOrId}\"` }],\n };\n }\n return { content: [{ type: \"text\", text: JSON.stringify({ record }, null, 2) }] };\n },\n );\n\n // memory://index — a browsable listing of every active asset.\n server.registerResource(\n \"memory-index\",\n \"memory://index\",\n {\n title: `Memory index for ${agent}`,\n description: \"All active memory assets for this agent (key, category, timestamps).\",\n mimeType: \"application/json\",\n },\n async (uri) => {\n const records = await store.list(undefined, 1000);\n return {\n contents: [\n { uri: uri.href, mimeType: \"application/json\", text: JSON.stringify({ agent, records }, null, 2) },\n ],\n };\n },\n );\n\n return server;\n}\n\n/** Serve over stdio — the default transport for `kohala memory serve`. */\nexport async function serveStdio(store: MemoryStore, agent: string): Promise<void> {\n const server = buildMemoryMcpServer(store, agent);\n const transport = new StdioServerTransport();\n await server.connect(transport);\n}\n\n/**\n * Serve over streamable HTTP on 127.0.0.1:<port> at /mcp.\n *\n * Runs in stateless mode: each request gets a fresh server + transport pair,\n * which keeps the implementation simple and is exactly what MCP Inspector and\n * one-shot clients expect. Returns the http.Server for lifecycle control.\n */\nexport async function serveHttp(\n store: MemoryStore,\n agent: string,\n port: number,\n): Promise<http.Server> {\n const httpServer = http.createServer((request, response) => {\n void (async () => {\n const url = new URL(request.url ?? \"/\", \"http://127.0.0.1\");\n if (url.pathname !== \"/mcp\") {\n response.writeHead(404, { \"content-type\": \"application/json\" });\n response.end(JSON.stringify({ error: \"Not found. The MCP endpoint is POST /mcp\" }));\n return;\n }\n if (request.method !== \"POST\") {\n response.writeHead(405, { \"content-type\": \"application/json\" });\n response.end(\n JSON.stringify({ error: \"Stateless MCP server: only POST /mcp is supported\" }),\n );\n return;\n }\n let raw = \"\";\n request.on(\"data\", (chunk) => {\n raw += chunk;\n });\n request.on(\"end\", () => {\n void (async () => {\n let body: unknown;\n try {\n body = JSON.parse(raw);\n } catch {\n response.writeHead(400, { \"content-type\": \"application/json\" });\n response.end(JSON.stringify({ error: \"Request body is not valid JSON\" }));\n return;\n }\n const server = buildMemoryMcpServer(store, agent);\n const transport = new StreamableHTTPServerTransport({\n sessionIdGenerator: undefined, // stateless\n });\n response.on(\"close\", () => {\n void transport.close();\n void server.close();\n });\n await server.connect(transport);\n await transport.handleRequest(request, response, body);\n })();\n });\n })();\n });\n\n await new Promise<void>((resolve) => {\n httpServer.listen(port, \"127.0.0.1\", resolve);\n });\n return httpServer;\n}\n","import readline from \"node:readline\";\nimport type { Command } from \"commander\";\nimport pc from \"picocolors\";\nimport { saveApiKey } from \"../deploy/credentials.js\";\n\n/**\n * `kohala login` — save a pk_ API key to ~/.kohala/credentials.json (0600).\n * The KOHALA_API_KEY environment variable always takes precedence over the\n * saved key, which is the right default for CI.\n */\nexport function registerLoginCommand(program: Command): void {\n program\n .command(\"login\")\n .option(\"--api-key <key>\", \"provide the key non-interactively\")\n .description(\"Save your Kohala API key for `kohala deploy`\")\n .action(async (options: { apiKey?: string }) => {\n let apiKey = options.apiKey;\n if (!apiKey) {\n apiKey = await promptHidden(\n \"Paste your Kohala API key (starts with pk_, from kohala.ai account settings): \",\n );\n }\n if (!apiKey) {\n throw new Error(\"No API key provided.\");\n }\n const savedTo = saveApiKey(apiKey.trim());\n console.log(pc.green(`API key saved to ${savedTo} (permissions 600).`));\n console.log(pc.dim(\"Note: the KOHALA_API_KEY environment variable overrides this file.\"));\n });\n}\n\n/** Prompt without echoing the key back to the terminal. */\nfunction promptHidden(question: string): Promise<string> {\n return new Promise((resolve) => {\n const rl = readline.createInterface({ input: process.stdin, output: process.stderr });\n const stdin = process.stdin as NodeJS.ReadStream & { setRawMode?: (mode: boolean) => void };\n process.stderr.write(question);\n if (stdin.isTTY && stdin.setRawMode) {\n stdin.setRawMode(true);\n let value = \"\";\n const onData = (chunk: Buffer) => {\n const char = chunk.toString(\"utf8\");\n if (char === \"\\n\" || char === \"\\r\" || char === \"\\u0004\") {\n stdin.setRawMode?.(false);\n stdin.off(\"data\", onData);\n rl.close();\n process.stderr.write(\"\\n\");\n resolve(value);\n } else if (char === \"\\u0003\") {\n // ctrl-c\n stdin.setRawMode?.(false);\n rl.close();\n process.exit(130);\n } else if (char === \"\\u007f\") {\n value = value.slice(0, -1);\n } else {\n value += char;\n }\n };\n stdin.on(\"data\", onData);\n } else {\n rl.question(\"\", (answer) => {\n rl.close();\n resolve(answer);\n });\n }\n });\n}\n","import fs from \"node:fs\";\nimport os from \"node:os\";\nimport path from \"node:path\";\n\n/**\n * Credential storage for `kohala login` / `kohala deploy`.\n *\n * Precedence: the KOHALA_API_KEY environment variable always wins; otherwise\n * the key saved by `kohala login` in ~/.kohala/credentials.json is used.\n * The file is written with mode 600 (owner read/write only).\n */\n\n/** Path of the credentials file (~/.kohala/credentials.json). */\nexport function credentialsPath(): string {\n return path.join(os.homedir(), \".kohala\", \"credentials.json\");\n}\n\ninterface CredentialsFile {\n apiKey: string;\n}\n\n/** Persist a pk_ API key with restrictive permissions. */\nexport function saveApiKey(apiKey: string): string {\n if (!apiKey.startsWith(\"pk_\")) {\n throw new Error('Kohala API keys start with \"pk_\". Check the key and try again.');\n }\n const filePath = credentialsPath();\n fs.mkdirSync(path.dirname(filePath), { recursive: true });\n const payload: CredentialsFile = { apiKey };\n fs.writeFileSync(filePath, JSON.stringify(payload, null, 2), { encoding: \"utf8\", mode: 0o600 });\n fs.chmodSync(filePath, 0o600);\n return filePath;\n}\n\n/**\n * Resolve the API key: env var first, then the saved credentials file.\n * Returns null when neither is configured.\n */\nexport function resolveApiKey(env: NodeJS.ProcessEnv = process.env): string | null {\n if (env.KOHALA_API_KEY) return env.KOHALA_API_KEY;\n const filePath = credentialsPath();\n if (!fs.existsSync(filePath)) return null;\n try {\n const parsed = JSON.parse(fs.readFileSync(filePath, \"utf8\")) as CredentialsFile;\n return parsed.apiKey ?? null;\n } catch {\n throw new Error(\n `${filePath} is corrupted — delete it and run \"kohala login\" again.`,\n );\n }\n}\n","import path from \"node:path\";\nimport type { Command } from \"commander\";\nimport pc from \"picocolors\";\nimport { loadManifest } from \"../manifest/load.js\";\nimport { resolveApiKey } from \"../deploy/credentials.js\";\nimport {\n buildDeployPlan,\n DEFAULT_BASE_URL,\n DeployError,\n KohalaClient,\n} from \"../deploy/client.js\";\n\n/**\n * `kohala deploy <agent>` — push a locally-validated agent to the hosted\n * platform. Deploy is additive and idempotent on the agent name; it never\n * deletes anything remotely. `--dry-run` prints exactly what would be sent.\n */\nexport function registerDeployCommand(program: Command): void {\n program\n .command(\"deploy\")\n .argument(\"<agent>\", \"agent directory (containing kohala.json)\")\n .option(\"--dry-run\", \"print the payloads without sending anything\")\n .option(\"--base-url <url>\", \"API base URL\", DEFAULT_BASE_URL)\n .option(\"--run\", \"trigger a manual run after deploying\")\n .description(\"Deploy an agent to kohala.ai (idempotent on agent name)\")\n .action(\n async (\n agent: string,\n options: { dryRun?: boolean; baseUrl: string; run?: boolean },\n ) => {\n const agentDir = path.resolve(process.cwd(), agent);\n const manifest = loadManifest(agentDir);\n const plan = buildDeployPlan(manifest, agentDir);\n\n if (options.dryRun) {\n console.log(pc.cyan(\"Dry run — nothing will be sent. Deploy plan:\"));\n console.log(\"\");\n console.log(pc.bold(\"1. POST /api/v1/agents (idempotent on name)\"));\n console.log(JSON.stringify(plan.agent, null, 2));\n if (plan.agent.agentScheduleCron) {\n console.log(\"\");\n console.log(pc.bold(\"1b. PATCH /api/v1/agents/:id (persist schedule on updates)\"));\n console.log(\n JSON.stringify(\n {\n agentScheduleCron: plan.agent.agentScheduleCron,\n agentScheduleEnabled: true,\n },\n null,\n 2,\n ),\n );\n }\n for (const skill of plan.skills) {\n console.log(\"\");\n console.log(pc.bold(`2. POST /api/v1/agents/:id/skills — \"${skill.name}\"`));\n console.log(\n JSON.stringify(\n { ...skill, code: `<${Buffer.byteLength(skill.code)} bytes of ${skill.scriptFilename}>` },\n null,\n 2,\n ),\n );\n }\n console.log(\"\");\n console.log(pc.bold(\"3. PUT /api/v1/agents/:id/quota\"));\n console.log(JSON.stringify(plan.quota, null, 2));\n if (options.run) {\n console.log(\"\");\n console.log(pc.bold(\"4. POST /api/v1/agents/:id/agent-runs/manual\"));\n }\n return;\n }\n\n const apiKey = resolveApiKey();\n if (!apiKey) {\n throw new Error(\n \"No API key configured. Run `kohala login` (or set KOHALA_API_KEY) first. Keys come from your kohala.ai account settings.\",\n );\n }\n\n const client = new KohalaClient(apiKey, options.baseUrl);\n console.log(pc.cyan(`Deploying \"${manifest.name}\" to ${options.baseUrl} ...`));\n\n const upserted = await client.upsertAgent(plan.agent);\n console.log(\n pc.green(` ✔ agent ${upserted.created ? \"created\" : \"updated\"} (id ${upserted.id})`),\n );\n\n if (plan.agent.agentScheduleCron) {\n await client.setSchedule(upserted.id, plan.agent.agentScheduleCron);\n console.log(pc.green(` ✔ schedule set (${plan.agent.agentScheduleCron})`));\n }\n\n for (const skill of plan.skills) {\n await client.upsertSkill(upserted.id, skill);\n console.log(pc.green(` ✔ skill \"${skill.name}\" uploaded (${skill.scriptFilename})`));\n }\n\n await client.setQuota(upserted.id, plan.quota);\n console.log(\n pc.green(\n ` ✔ quota set (perRun=${plan.quota.perRunTokens}, perDay=${plan.quota.perDayTokens})`,\n ),\n );\n\n if (options.run) {\n try {\n const runUrl = await client.triggerManualRun(upserted.id);\n console.log(pc.green(` ✔ manual run triggered: ${runUrl}`));\n } catch (error) {\n // Newly deployed agents start disabled on the platform; a manual\n // run returns 409 until the owner enables the agent. Explain the\n // fix instead of surfacing a raw API error — but keep a non-zero\n // exit so scripts relying on --run notice the run did not happen.\n if (error instanceof DeployError && error.status === 409) {\n console.error(\n pc.yellow(\n ` ✖ manual run not started: the agent is not enabled on the platform yet.`,\n ),\n );\n console.error(\n pc.dim(\n ` Deploy itself succeeded. Enable \"${manifest.name}\" in your kohala.ai dashboard, ` +\n `then re-run \\`kohala deploy ${agent} --run\\` (or trigger a run from the dashboard).`,\n ),\n );\n process.exitCode = 1;\n return;\n }\n throw error;\n }\n }\n\n console.log(\"\");\n console.log(pc.green(`Deployed. Deploys are additive — nothing was deleted remotely.`));\n },\n );\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport type { AgentManifest } from \"../manifest/schema.js\";\n\n/**\n * REST client for deploying agents to the hosted Kohala platform (A.5).\n *\n * Deploy flow (all idempotent / additive — deploy NEVER deletes remotely):\n * 1. POST /api/v1/agents (idempotent on name)\n * 2. POST /api/v1/agents/:id/skills (one per manifest skill)\n * 3. PUT /api/v1/agents/:id/quota (the caps)\n * 4. optional: POST /api/v1/agents/:id/agent-runs/manual\n */\n\n/** Default production API target; override with --base-url for staging. */\nexport const DEFAULT_BASE_URL = \"https://kohala.ai\";\n\n/** Payload for creating/updating the agent — the platform's field names. */\nexport interface AgentPayload {\n name: string;\n charter: string;\n toolAllowlist: string[];\n // The platform stores \"wrap\" under its own enum name \"script\" (verified\n // live 2026-08-10: \"llm\" round-trips as \"llm\"); this is a display-side\n // mapping, not data loss — send the manifest value as-is.\n runtimeMode: \"wrap\" | \"llm\";\n // The platform's canonical schedule fields (BUG-069: the manifest's\n // `schedule` used to be sent as a top-level `schedule` key, which is not\n // in the platform schema and was silently dropped). Note the create path\n // honors these, but the upsert-on-existing-name path ignores them — deploy\n // therefore also PATCHes the schedule after the upsert (see setSchedule).\n agentScheduleCron?: string;\n agentScheduleEnabled?: boolean;\n}\n\n/** Payload for uploading one skill. */\nexport interface SkillPayload {\n name: string;\n scriptFilename: string;\n description: string;\n // The platform's canonical field for script source is `code` (BUG-067:\n // the old `scriptContent` field is not in the platform schema and was\n // silently dropped, leaving the skill without a runnable script asset).\n code: string;\n}\n\n/** Payload for the quota update — the platform's cap field names. */\nexport interface QuotaPayload {\n perRunTokens: number;\n perDayTokens: number;\n billingTokens?: number;\n billingPeriod?: \"day\" | \"week\" | \"month\";\n}\n\n/** Everything `kohala deploy` will send, assembled before any network call. */\nexport interface DeployPlan {\n agent: AgentPayload;\n skills: SkillPayload[];\n quota: QuotaPayload;\n}\n\n/** Map a validated manifest (+ its skill scripts on disk) onto API payloads. */\nexport function buildDeployPlan(manifest: AgentManifest, agentDir: string): DeployPlan {\n const skills: SkillPayload[] = Object.entries(manifest.skills).map(([name, scriptFilename]) => {\n const scriptPath = path.join(agentDir, \"skills\", scriptFilename);\n if (!fs.existsSync(scriptPath)) {\n throw new Error(\n `Skill \"${name}\" points at ${scriptFilename}, but ${scriptPath} does not exist.`,\n );\n }\n return {\n name,\n scriptFilename,\n description: `Skill \"${name}\" of agent \"${manifest.name}\"`,\n code: fs.readFileSync(scriptPath, \"utf8\"),\n };\n });\n\n return {\n agent: {\n name: manifest.name,\n charter: manifest.charter,\n toolAllowlist: manifest.toolAllowlist,\n runtimeMode: manifest.runtimeMode,\n ...(manifest.schedule\n ? { agentScheduleCron: manifest.schedule, agentScheduleEnabled: true }\n : {}),\n },\n skills,\n quota: {\n perRunTokens: manifest.caps.perRunTokens,\n perDayTokens: manifest.caps.perDayTokens,\n ...(manifest.caps.billingTokens !== undefined\n ? { billingTokens: manifest.caps.billingTokens }\n : {}),\n ...(manifest.caps.billingPeriod !== undefined\n ? { billingPeriod: manifest.caps.billingPeriod }\n : {}),\n },\n };\n}\n\n/** Error with a user-actionable message for known HTTP statuses. */\nexport class DeployError extends Error {\n constructor(\n readonly status: number,\n message: string,\n ) {\n super(message);\n this.name = \"DeployError\";\n }\n}\n\n/** Result of the agent upsert — the platform reports created vs updated. */\nexport interface AgentUpsertResult {\n id: string;\n created: boolean;\n}\n\n/** Thin authenticated HTTP client for the Kohala public REST API. */\nexport class KohalaClient {\n constructor(\n private readonly apiKey: string,\n private readonly baseUrl: string = DEFAULT_BASE_URL,\n ) {}\n\n private async request(method: string, apiPath: string, body?: unknown): Promise<unknown> {\n const response = await fetch(`${this.baseUrl}${apiPath}`, {\n method,\n headers: {\n \"content-type\": \"application/json\",\n authorization: `Bearer ${this.apiKey}`,\n },\n ...(body !== undefined ? { body: JSON.stringify(body) } : {}),\n });\n\n if (response.status === 401) {\n throw new DeployError(\n 401,\n \"401 Unauthorized: your API key was rejected. Check KOHALA_API_KEY or re-run `kohala login` with a fresh pk_ key from your Kohala account settings.\",\n );\n }\n if (response.status === 403) {\n throw new DeployError(\n 403,\n \"403 Forbidden: your plan does not allow this operation. Check your plan at https://kohala.ai or contact support.\",\n );\n }\n if (!response.ok) {\n const text = await response.text();\n throw new DeployError(\n response.status,\n `Kohala API error ${response.status} on ${method} ${apiPath}: ${text.slice(0, 500)}`,\n );\n }\n const text = await response.text();\n return text ? (JSON.parse(text) as unknown) : null;\n }\n\n /** Step 1: create or update the agent (idempotent on name). */\n async upsertAgent(payload: AgentPayload): Promise<AgentUpsertResult> {\n const data = (await this.request(\"POST\", \"/api/v1/agents\", payload)) as {\n id?: string;\n agentId?: string;\n created?: boolean;\n };\n const id = data.id ?? data.agentId;\n if (!id) {\n throw new DeployError(500, \"Platform response did not include an agent id\");\n }\n return { id, created: data.created ?? false };\n }\n\n /** Step 2: upload one skill (script content inline). */\n async upsertSkill(agentId: string, payload: SkillPayload): Promise<void> {\n const data = (await this.request(\"POST\", `/api/v1/agents/${agentId}/skills`, payload)) as {\n script?: { stage?: string };\n } | null;\n // BUG-067: a skill without a production-stage script asset is skipped by\n // every run. The platform confirms attachment via `script.stage`; treat\n // its absence as a hard failure rather than reporting a green tick.\n if (data?.script?.stage !== \"production\") {\n throw new DeployError(\n 500,\n `Platform accepted skill \"${payload.name}\" but did not attach a runnable script ` +\n `(expected script.stage \"production\" in the response). The deployed agent would ` +\n `no-op on every run — aborting.`,\n );\n }\n }\n\n /**\n * Step 2b (only when the manifest has a schedule): persist the cron.\n *\n * BUG-069: POST /agents honors agentScheduleCron on *create* but silently\n * ignores it when upserting an existing agent, so deploy PATCHes the\n * schedule explicitly and verifies it round-tripped. Never called without\n * a schedule — deploy is additive and must not disable existing schedules.\n */\n async setSchedule(agentId: string, cron: string): Promise<void> {\n const data = (await this.request(\"PATCH\", `/api/v1/agents/${agentId}`, {\n agentScheduleCron: cron,\n agentScheduleEnabled: true,\n })) as { agentScheduleCron?: string | null; agentScheduleEnabled?: boolean } | null;\n if (data?.agentScheduleCron !== cron || data?.agentScheduleEnabled !== true) {\n throw new DeployError(\n 500,\n `Platform did not persist the schedule \"${cron}\" (got ` +\n `agentScheduleCron=${JSON.stringify(data?.agentScheduleCron)}, ` +\n `agentScheduleEnabled=${JSON.stringify(data?.agentScheduleEnabled)}) — aborting.`,\n );\n }\n }\n\n /** Step 3: set the token caps. */\n async setQuota(agentId: string, payload: QuotaPayload): Promise<void> {\n await this.request(\"PUT\", `/api/v1/agents/${agentId}/quota`, payload);\n }\n\n /** Optional step 4 (--run): trigger a manual run and return its link. */\n async triggerManualRun(agentId: string): Promise<string> {\n const data = (await this.request(\"POST\", `/api/v1/agents/${agentId}/agent-runs/manual`)) as {\n runUrl?: string;\n url?: string;\n id?: string;\n };\n return data.runUrl ?? data.url ?? `${this.baseUrl}/agents/${agentId}/runs/${data.id ?? \"\"}`;\n }\n}\n","import type { Command } from \"commander\";\nimport pc from \"picocolors\";\nimport { findPython } from \"../emulator/python.js\";\nimport { detectLlmProvider } from \"../emulator/llm-client.js\";\nimport { resolveApiKey, credentialsPath } from \"../deploy/credentials.js\";\n\n/**\n * `kohala doctor` — check the local environment and report what works.\n * Nothing here is fatal; the doctor tells you what each missing piece limits.\n */\nexport function registerDoctorCommand(program: Command): void {\n program\n .command(\"doctor\")\n .description(\"Check your environment: Node, Python, LLM keys, API key, DATABASE_URL\")\n .action(async () => {\n const ok = (label: string, detail: string) =>\n console.log(`${pc.green(\"✔\")} ${label} ${pc.dim(detail)}`);\n const warn = (label: string, detail: string) =>\n console.log(`${pc.yellow(\"•\")} ${label} ${pc.dim(detail)}`);\n\n // Node version (package.json engines requires >= 20).\n const nodeMajor = Number(process.versions.node.split(\".\")[0]);\n if (nodeMajor >= 20) {\n ok(`node ${process.versions.node}`, \"(>= 20 required)\");\n } else {\n console.log(\n `${pc.red(\"✘\")} node ${process.versions.node} — the devkit requires Node 20 or newer.`,\n );\n }\n\n // Python (needed to run wrap-mode skills).\n try {\n const python = await findPython();\n ok(`python (${python})`, \"wrap-mode skills can run\");\n } catch {\n warn(\"python 3 not found\", \"wrap-mode `kohala run --local` will not work until installed\");\n }\n\n // LLM keys.\n // ANTHROPIC_API_KEY → llm.complete (wrap mode) + llm mode tool-use loop\n // GEMINI_API_KEY → llm.complete (wrap mode) only; llm mode needs Anthropic\n const provider = detectLlmProvider();\n const hasAnthropic = Boolean(process.env.ANTHROPIC_API_KEY);\n if (hasAnthropic) {\n ok(\"LLM key (anthropic)\", \"llm.complete and llm mode both available\");\n } else if (provider === \"gemini\") {\n ok(\"LLM key (gemini)\", \"llm.complete available in wrap mode\");\n warn(\n \"no ANTHROPIC_API_KEY\",\n \"llm mode (runtimeMode: \\\"llm\\\") requires Anthropic — GEMINI_API_KEY covers llm.complete only\",\n );\n } else {\n warn(\n \"no ANTHROPIC_API_KEY / GEMINI_API_KEY\",\n \"llm.complete and llm-mode runs will fail with NO_LLM_KEY\",\n );\n }\n\n // Kohala API key (needed only for deploy).\n const apiKey = resolveApiKey();\n if (apiKey) {\n const source = process.env.KOHALA_API_KEY ? \"KOHALA_API_KEY env\" : credentialsPath();\n ok(\"Kohala API key\", `from ${source} — kohala deploy ready`);\n } else {\n warn(\"no Kohala API key\", \"run `kohala login` before `kohala deploy` (local dev needs no account)\");\n }\n\n // DATABASE_URL (needed only for the postgres memory backend).\n if (process.env.DATABASE_URL) {\n ok(\"DATABASE_URL set\", \"postgres memory backend available\");\n } else {\n warn(\"DATABASE_URL not set\", \"memory uses the file backend (that is the default anyway)\");\n }\n\n console.log(\"\");\n console.log(pc.dim(\"Everything local works without an account — deploy is the only step that needs one.\"));\n });\n}\n"],"mappings":"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;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA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","names":["pc","program","path","pc","fs","path","path","fs","program","path","pc","path","pc","fs","path","fs","path","path","fs","record","crypto","crypto","crypto","path","execa","fs","path","fs","path","path","fs","version","fs","fs","crypto","path","execa","program","path","pc","fs","path","pc","fs","pc","program","path","fs","pc","fs","path","pc","http","z","z","http","program","path","fs","pc","pc","fs","path","program","pc","path","pc","fs","path","text","program","path","pc","pc","program","pc","require","pc"]}
|
package/docs/MANIFEST.md
CHANGED
|
@@ -37,7 +37,7 @@ is what goes live.
|
|
|
37
37
|
| `toolAllowlist` | `agentToolAllowlist` | Exactly the tools the agent may call. No implicit grants. |
|
|
38
38
|
| `runtimeMode` | `agentRuntimeMode` | `"wrap"` or `"llm"` (see below). |
|
|
39
39
|
| `skills` | `agentSkills` | Map of skill name → script filename in `skills/`. |
|
|
40
|
-
| `schedule` | `agentScheduleCron` | Cron expression. Only used on deploy; local runs are manual. |
|
|
40
|
+
| `schedule` | `agentScheduleCron` + `agentScheduleEnabled` | Cron expression. Only used on deploy; local runs are manual. Deploy also PATCHes the schedule after the agent upsert (the platform ignores schedule fields when updating an existing agent by name) and verifies it persisted. |
|
|
41
41
|
| `caps.perRunTokens` | `agentPerRunTokenCap` | Hard token ceiling per shift. |
|
|
42
42
|
| `caps.perDayTokens` | `agentPerDayTokenCap` | Cumulative ceiling per UTC day. |
|
|
43
43
|
| `caps.billingTokens` | `agentBillingCapTokens` | Billing-period cap. Ignored locally. |
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kohala/devkit",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.5",
|
|
4
4
|
"description": "Open-source CLI, local agent emulator, and open MCP memory server for Kohala agents. Build and run agents entirely on your own machine — then push the same agent to Kohala when you want it hosted.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|