@kohala/devkit 0.1.0 → 0.1.2
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 +58 -0
- package/CODE_OF_CONDUCT.md +37 -0
- package/CONTRIBUTING.md +53 -0
- package/README.md +26 -3
- package/SECURITY.md +28 -0
- package/dist/cli/index.js +248 -9
- package/dist/cli/index.js.map +1 -1
- package/docs/DEPLOY.md +48 -0
- package/docs/EMULATOR.md +93 -0
- package/docs/MANIFEST.md +84 -0
- package/docs/MEMORY.md +81 -0
- package/docs/QUICKSTART.md +70 -0
- package/examples/llm-notes/README.md +18 -0
- package/examples/llm-notes/kohala.json +16 -0
- package/examples/llm-notes/skills/task.md +7 -0
- package/examples/rss-digest/README.md +13 -0
- package/examples/rss-digest/kohala.json +17 -0
- package/examples/rss-digest/skills/_tools.py +125 -0
- package/examples/rss-digest/skills/main.py +49 -0
- package/examples/weather-logger/README.md +12 -0
- package/examples/weather-logger/kohala.json +19 -0
- package/examples/weather-logger/skills/_tools.py +125 -0
- package/examples/weather-logger/skills/main.py +39 -0
- package/package.json +7 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,57 @@
|
|
|
1
1
|
# @kohala/devkit
|
|
2
2
|
|
|
3
|
+
## 0.1.2 (unreleased)
|
|
4
|
+
|
|
5
|
+
- **`kohala validate` now rejects tool ids not in the bundled platform
|
|
6
|
+
catalog snapshot** (BUG-033). A typo'd tool id (e.g. `htpp.geet`) used to
|
|
7
|
+
pass validation and only fail at deploy/run time; it now fails validation
|
|
8
|
+
offline with the offending id(s) named. Pass `--allow-unknown-tools` to
|
|
9
|
+
bypass when the snapshot lags newly added platform tools — the deploy
|
|
10
|
+
endpoint still verifies against the live catalog authoritatively.
|
|
11
|
+
|
|
12
|
+
- **Docs: LLM model-override env vars and `memory serve` agent scoping**
|
|
13
|
+
(BUG-047, BUG-035). The README now documents `KOHALA_LLM_MODEL`,
|
|
14
|
+
`ANTHROPIC_MODEL`, and `GEMINI_MODEL`, and clarifies that
|
|
15
|
+
`kohala memory serve` is always scoped to one agent (run it inside an
|
|
16
|
+
agent directory or pass `--agent <name>`).
|
|
17
|
+
|
|
18
|
+
- **Repo hygiene: removed Replit workspace scaffolding from the repository**
|
|
19
|
+
(BUG-016). `.replit`, `replit.md`, `attached_assets/`, and `artifacts/`
|
|
20
|
+
are no longer tracked in the public repo.
|
|
21
|
+
|
|
22
|
+
## 0.1.1
|
|
23
|
+
|
|
24
|
+
Bug fixes.
|
|
25
|
+
|
|
26
|
+
- **Default models updated to match the hosted platform** (BUG-040).
|
|
27
|
+
Local llm-mode now defaults to `claude-sonnet-4-6` (Anthropic) and
|
|
28
|
+
`gemini-flash-latest` (Gemini) — the same models the platform runs — so
|
|
29
|
+
cap tuning and output behaviour carry over after `kohala deploy`. Override
|
|
30
|
+
locally with `ANTHROPIC_MODEL`, `GEMINI_MODEL`, or `KOHALA_LLM_MODEL`.
|
|
31
|
+
|
|
32
|
+
- **Default Gemini model changed from `gemini-2.0-flash` to
|
|
33
|
+
`gemini-flash-latest`** (BUG-041). The previous default hit quota limits
|
|
34
|
+
on new free-tier Gemini keys; the new default works on fresh keys.
|
|
35
|
+
Override with `GEMINI_MODEL` or `KOHALA_LLM_MODEL`.
|
|
36
|
+
|
|
37
|
+
- **`kohala doctor` now correctly distinguishes llm-mode availability from
|
|
38
|
+
`llm.complete` availability** (BUG-042). `GEMINI_API_KEY` enables
|
|
39
|
+
`llm.complete` in wrap-mode skills but not the llm-mode tool-use loop
|
|
40
|
+
(which requires `ANTHROPIC_API_KEY`). The doctor now reports each case
|
|
41
|
+
separately so the output matches what actually works.
|
|
42
|
+
|
|
43
|
+
- **`kohala run` error message is now specific when `runtimeMode: "llm"` is
|
|
44
|
+
used without an Anthropic key** (BUG-042). The previous message suggested
|
|
45
|
+
that `GEMINI_API_KEY` would work; the new message explains the distinction.
|
|
46
|
+
|
|
47
|
+
- **`docs/` and `examples/` included in the published tarball** (BUG-034).
|
|
48
|
+
The README links to both; they now ship inside the package so installed
|
|
49
|
+
users can read them without cloning the repository.
|
|
50
|
+
|
|
51
|
+
- **`kohala memory serve` documentation clarified** (BUG-035). The command
|
|
52
|
+
requires either `--agent <name>` or to be run from inside an agent
|
|
53
|
+
directory. The docs now show both forms.
|
|
54
|
+
|
|
3
55
|
## 0.1.0
|
|
4
56
|
|
|
5
57
|
Initial release.
|
|
@@ -13,3 +65,9 @@ Initial release.
|
|
|
13
65
|
- Stdlib-only Python script SDK over a loopback RPC boundary
|
|
14
66
|
- Deploy client for the kohala.ai REST API (idempotent, additive,
|
|
15
67
|
`--dry-run`)
|
|
68
|
+
|
|
69
|
+
### SDK compatibility note (BUG-015)
|
|
70
|
+
|
|
71
|
+
0.1.0 was released against `@kohala/sdk` 0.1.x. The SDK published 0.2.0 on
|
|
72
|
+
2026-07-20 with updated method signatures. The emulator and deploy client
|
|
73
|
+
work against any SDK version; this note tracks awareness of the divergence.
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# Code of Conduct
|
|
2
|
+
|
|
3
|
+
## Our pledge
|
|
4
|
+
|
|
5
|
+
We as members, contributors, and maintainers pledge to make participation in
|
|
6
|
+
the Kohala Devkit project a harassment-free experience for everyone,
|
|
7
|
+
regardless of age, body size, visible or invisible disability, ethnicity, sex
|
|
8
|
+
characteristics, gender identity and expression, level of experience,
|
|
9
|
+
education, socio-economic status, nationality, personal appearance, race,
|
|
10
|
+
religion, or sexual identity and orientation.
|
|
11
|
+
|
|
12
|
+
## Our standards
|
|
13
|
+
|
|
14
|
+
Examples of behavior that contributes to a positive environment:
|
|
15
|
+
|
|
16
|
+
- Being respectful of differing opinions, viewpoints, and experiences
|
|
17
|
+
- Giving and gracefully accepting constructive feedback
|
|
18
|
+
- Focusing on what is best for the community and the project
|
|
19
|
+
|
|
20
|
+
Examples of unacceptable behavior:
|
|
21
|
+
|
|
22
|
+
- Harassment, trolling, insulting or derogatory comments, personal attacks
|
|
23
|
+
- Publishing others' private information without explicit permission
|
|
24
|
+
- Other conduct which could reasonably be considered inappropriate in a
|
|
25
|
+
professional setting
|
|
26
|
+
|
|
27
|
+
## Enforcement
|
|
28
|
+
|
|
29
|
+
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
|
30
|
+
reported to the maintainers at conduct@kohala.ai. All complaints will be
|
|
31
|
+
reviewed and investigated promptly and fairly. Maintainers are obligated to
|
|
32
|
+
respect the privacy and security of the reporter of any incident.
|
|
33
|
+
|
|
34
|
+
## Attribution
|
|
35
|
+
|
|
36
|
+
This Code of Conduct is adapted from the
|
|
37
|
+
[Contributor Covenant](https://www.contributor-covenant.org), version 2.1.
|
package/CONTRIBUTING.md
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# Contributing to the Kohala Devkit
|
|
2
|
+
|
|
3
|
+
Thanks for helping! The devkit is deliberately small and boring — please keep
|
|
4
|
+
it that way.
|
|
5
|
+
|
|
6
|
+
## Setup
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
git clone https://github.com/kohala-ai/devkit
|
|
10
|
+
cd devkit
|
|
11
|
+
npm install # or pnpm install
|
|
12
|
+
npm run build
|
|
13
|
+
node dist/cli/index.js --version
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
Python 3 must be on your PATH to run the end-to-end tests.
|
|
17
|
+
|
|
18
|
+
## Development loop
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
npm run typecheck # strict tsc, no emit
|
|
22
|
+
npm run lint # eslint
|
|
23
|
+
npm test # vitest (unit + CLI e2e)
|
|
24
|
+
npm run build # tsup -> dist/
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Ground rules
|
|
28
|
+
|
|
29
|
+
- **Errors fail loudly.** No silent fallbacks, no mock LLM responses, no
|
|
30
|
+
swallowed exceptions. If something can't work, say so with an actionable
|
|
31
|
+
message.
|
|
32
|
+
- **Platform parity is the product.** Tool names, manifest fields, cap codes
|
|
33
|
+
(`PER_RUN_TOKEN_CAP`, `PER_DAY_TOKEN_CAP`, `TOOL_DENIED`), and enforcement
|
|
34
|
+
order must match the hosted platform. Don't rename things casually.
|
|
35
|
+
- **Dependency budget.** Runtime deps are limited to: commander, zod,
|
|
36
|
+
@modelcontextprotocol/sdk, execa, picocolors, ora. `pg` stays an optional
|
|
37
|
+
peer. New runtime dependencies need a strong justification in the PR.
|
|
38
|
+
- **The Python SDK stays stdlib-only.** Scaffolded agents must run without a
|
|
39
|
+
single `pip install`.
|
|
40
|
+
- Keep CLI command files thin; put behavior in the library modules where it
|
|
41
|
+
can be unit-tested.
|
|
42
|
+
|
|
43
|
+
## Submitting changes
|
|
44
|
+
|
|
45
|
+
1. Fork, branch, make the change, add/adjust tests.
|
|
46
|
+
2. Add a changeset: `npx changeset` (pick patch/minor and write one line).
|
|
47
|
+
3. Open a PR. CI runs typecheck, lint, tests, and build on Node 20 and 22.
|
|
48
|
+
|
|
49
|
+
## Releases
|
|
50
|
+
|
|
51
|
+
Releases are automated with [changesets](https://github.com/changesets/changesets):
|
|
52
|
+
merged changesets accumulate, and the release workflow versions, tags, and
|
|
53
|
+
publishes to npm.
|
package/README.md
CHANGED
|
@@ -55,9 +55,11 @@ skill scripts).
|
|
|
55
55
|
```
|
|
56
56
|
|
|
57
57
|
- `runtimeMode: "wrap"` executes your script directly and validates its
|
|
58
|
-
output (stdout).
|
|
59
|
-
-
|
|
60
|
-
|
|
58
|
+
output (stdout). Use `llm.complete` from the script SDK to call an LLM
|
|
59
|
+
mid-script (needs `ANTHROPIC_API_KEY` or `GEMINI_API_KEY`).
|
|
60
|
+
- `runtimeMode: "llm"` runs a real Anthropic tool-use loop — requires
|
|
61
|
+
`ANTHROPIC_API_KEY`. `GEMINI_API_KEY` works for `llm.complete` in wrap
|
|
62
|
+
mode but not for this loop. The devkit never mocks completions.
|
|
61
63
|
|
|
62
64
|
## Docs
|
|
63
65
|
|
|
@@ -91,3 +93,24 @@ See [CONTRIBUTING.md](CONTRIBUTING.md). Bug reports and PRs welcome.
|
|
|
91
93
|
## License
|
|
92
94
|
|
|
93
95
|
[MIT](LICENSE)
|
|
96
|
+
|
|
97
|
+
### LLM model overrides (local emulator)
|
|
98
|
+
|
|
99
|
+
`kohala run` in LLM mode picks its model from environment variables:
|
|
100
|
+
|
|
101
|
+
| Variable | Effect |
|
|
102
|
+
| --- | --- |
|
|
103
|
+
| `KOHALA_LLM_MODEL` | Provider-agnostic override — takes precedence over the two below. |
|
|
104
|
+
| `ANTHROPIC_MODEL` | Anthropic model id (e.g. `claude-3-5-haiku-latest`). |
|
|
105
|
+
| `GEMINI_MODEL` | Gemini model id (e.g. `gemini-2.0-flash`). |
|
|
106
|
+
|
|
107
|
+
Unset, the emulator uses its built-in defaults.
|
|
108
|
+
|
|
109
|
+
### Memory server scoping
|
|
110
|
+
|
|
111
|
+
`kohala memory serve` is always scoped to ONE agent. Either run it from inside
|
|
112
|
+
an agent directory (one containing `kohala.json`) or pass `--agent <name>`:
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
kohala memory serve --agent my-agent --backend file
|
|
116
|
+
```
|
package/SECURITY.md
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# Security Policy
|
|
2
|
+
|
|
3
|
+
## Supported versions
|
|
4
|
+
|
|
5
|
+
Only the latest published version of `@kohala/devkit` receives security
|
|
6
|
+
fixes.
|
|
7
|
+
|
|
8
|
+
## Reporting a vulnerability
|
|
9
|
+
|
|
10
|
+
Please email **security@kohala.ai** with a description of the issue, steps to
|
|
11
|
+
reproduce, and the version affected. Do **not** open a public GitHub issue
|
|
12
|
+
for security reports.
|
|
13
|
+
|
|
14
|
+
We aim to acknowledge reports within 3 business days.
|
|
15
|
+
|
|
16
|
+
## Scope notes
|
|
17
|
+
|
|
18
|
+
- The devkit runs agent scripts **you** wrote on **your** machine, with your
|
|
19
|
+
own credentials. It does not sandbox skill scripts — treat third-party
|
|
20
|
+
agent code like any other code you execute locally.
|
|
21
|
+
- The `http.post_json` tool refuses private/internal targets: it validates
|
|
22
|
+
the hostname, every IP it resolves to (IPv4 and IPv6, including
|
|
23
|
+
IPv4-mapped, link-local, ULA, and CGNAT ranges), and re-validates each
|
|
24
|
+
redirect hop. A determined attacker with DNS rebinding at request time may
|
|
25
|
+
still find gaps — do not treat it as a hardened network boundary.
|
|
26
|
+
- `kohala login` stores your API key at `~/.kohala/credentials.json` with
|
|
27
|
+
mode 600. The `KOHALA_API_KEY` environment variable always takes
|
|
28
|
+
precedence and is the recommended mechanism in CI.
|
package/dist/cli/index.js
CHANGED
|
@@ -190,12 +190,240 @@ function loadManifest(agentDir) {
|
|
|
190
190
|
return result.data;
|
|
191
191
|
}
|
|
192
192
|
|
|
193
|
+
// src/manifest/known-tools.ts
|
|
194
|
+
var KNOWN_TOOL_IDS = /* @__PURE__ */ new Set([
|
|
195
|
+
"http.get",
|
|
196
|
+
"http.brightdata",
|
|
197
|
+
"run_python_script",
|
|
198
|
+
"web.search",
|
|
199
|
+
"image.generate",
|
|
200
|
+
"code.run",
|
|
201
|
+
"s3.put",
|
|
202
|
+
"koan.publish",
|
|
203
|
+
"report.publish",
|
|
204
|
+
"email.send",
|
|
205
|
+
"send_email",
|
|
206
|
+
"email.user_send",
|
|
207
|
+
"email.user_inbox",
|
|
208
|
+
"calendar.user_events",
|
|
209
|
+
"calendar.user_create_event",
|
|
210
|
+
"whatsapp.user_send",
|
|
211
|
+
"whatsapp.user_inbox",
|
|
212
|
+
"linkedin.user_post",
|
|
213
|
+
"linkedin.user_profile",
|
|
214
|
+
"linkedin.org_posts",
|
|
215
|
+
"linkedin.org_stats",
|
|
216
|
+
"validate_output",
|
|
217
|
+
"html.parse",
|
|
218
|
+
"json.parse",
|
|
219
|
+
"csv.parse",
|
|
220
|
+
"canvas.message",
|
|
221
|
+
"canvas.request_approval",
|
|
222
|
+
"odoo.search_read",
|
|
223
|
+
"odoo.read",
|
|
224
|
+
"odoo.read_group",
|
|
225
|
+
"odoo.create",
|
|
226
|
+
"odoo.write",
|
|
227
|
+
"odoo.unlink",
|
|
228
|
+
"odoo.call_method",
|
|
229
|
+
"odoo.message_post",
|
|
230
|
+
"odoo.attachments.upload",
|
|
231
|
+
"aftership.create_tracking",
|
|
232
|
+
"aftership.get_tracking",
|
|
233
|
+
"aftership.list_trackings",
|
|
234
|
+
"aftership.update_tracking",
|
|
235
|
+
"aftership.delete_tracking",
|
|
236
|
+
"aftership.detect_courier",
|
|
237
|
+
"fedex.track",
|
|
238
|
+
"ups.track",
|
|
239
|
+
"era5.point_history",
|
|
240
|
+
"noaa.forecast",
|
|
241
|
+
"noaa.alerts",
|
|
242
|
+
"airlabs.flight",
|
|
243
|
+
"airlabs.schedules",
|
|
244
|
+
"adsb.aircraft_near",
|
|
245
|
+
"adsb.by_callsign",
|
|
246
|
+
"aftership.list_couriers",
|
|
247
|
+
"ga.run_report",
|
|
248
|
+
"ga.realtime_report",
|
|
249
|
+
"ga.get_metadata",
|
|
250
|
+
"ga.list_properties",
|
|
251
|
+
"epicor.query",
|
|
252
|
+
"epicor.list",
|
|
253
|
+
"epicor.get",
|
|
254
|
+
"epicor.create",
|
|
255
|
+
"epicor.update",
|
|
256
|
+
"epicor.call_method",
|
|
257
|
+
"ideogram.generate",
|
|
258
|
+
"ideogram.edit",
|
|
259
|
+
"ideogram.remix",
|
|
260
|
+
"ideogram.reframe",
|
|
261
|
+
"ideogram.replace_background",
|
|
262
|
+
"ideogram.upscale",
|
|
263
|
+
"ideogram.describe",
|
|
264
|
+
"elevenlabs.text_to_speech",
|
|
265
|
+
"elevenlabs.speech_to_text",
|
|
266
|
+
"elevenlabs.speech_to_speech",
|
|
267
|
+
"elevenlabs.sound_effects",
|
|
268
|
+
"elevenlabs.voice_isolator",
|
|
269
|
+
"elevenlabs.music",
|
|
270
|
+
"elevenlabs.dubbing",
|
|
271
|
+
"elevenlabs.dubbing_result",
|
|
272
|
+
"elevenlabs.voice_design",
|
|
273
|
+
"elevenlabs.list_voices",
|
|
274
|
+
"video.generate_social",
|
|
275
|
+
"video.generate_cinematic",
|
|
276
|
+
"video.generate_avatar",
|
|
277
|
+
"video.status",
|
|
278
|
+
"extract.fields",
|
|
279
|
+
"extract.receipt",
|
|
280
|
+
"extract.financial",
|
|
281
|
+
"extract.legal",
|
|
282
|
+
"extract.product_spec",
|
|
283
|
+
"extract.menu",
|
|
284
|
+
"extract.evaluate",
|
|
285
|
+
"memory.search",
|
|
286
|
+
"memory.remember",
|
|
287
|
+
"http.post_json",
|
|
288
|
+
"s3.list",
|
|
289
|
+
"s3.get",
|
|
290
|
+
"s3.delete",
|
|
291
|
+
"feed.fetch",
|
|
292
|
+
"text.diff",
|
|
293
|
+
"data.diff",
|
|
294
|
+
"pinecone.upsert",
|
|
295
|
+
"pinecone.query",
|
|
296
|
+
"pinecone.fetch",
|
|
297
|
+
"pinecone.delete",
|
|
298
|
+
"llm.complete",
|
|
299
|
+
"pdf.extract",
|
|
300
|
+
"geocode",
|
|
301
|
+
"slack.message",
|
|
302
|
+
"discord.message",
|
|
303
|
+
"schedule.next_run",
|
|
304
|
+
"schedule.last_run",
|
|
305
|
+
"metrics.record",
|
|
306
|
+
"vector.embed",
|
|
307
|
+
"sms.send",
|
|
308
|
+
"push.send",
|
|
309
|
+
"webhook.post",
|
|
310
|
+
"notify.send",
|
|
311
|
+
"agent.handoff",
|
|
312
|
+
"bus.publish",
|
|
313
|
+
"bus.subscribe",
|
|
314
|
+
"bus.list_subscriptions",
|
|
315
|
+
"bus.unsubscribe",
|
|
316
|
+
"invoice.record",
|
|
317
|
+
"invoice.generate",
|
|
318
|
+
"invoice.modify",
|
|
319
|
+
"invoice.list",
|
|
320
|
+
"invoice.publish_koan",
|
|
321
|
+
"invoice.ap_run",
|
|
322
|
+
"invoice.ap_sweep",
|
|
323
|
+
"invoice.ar_sweep",
|
|
324
|
+
"invoice.ar_draft",
|
|
325
|
+
"invoice.send",
|
|
326
|
+
"invoice.review",
|
|
327
|
+
"invoice.calibrate",
|
|
328
|
+
"invoice.settings",
|
|
329
|
+
"invoice.status",
|
|
330
|
+
"sales_agreement.record",
|
|
331
|
+
"sales_agreement.review",
|
|
332
|
+
"sales_agreement.list",
|
|
333
|
+
"sales_agreement.publish_koan",
|
|
334
|
+
"customers.list",
|
|
335
|
+
"customers.add",
|
|
336
|
+
"customers.get_brand_profile",
|
|
337
|
+
"secrets.get",
|
|
338
|
+
"secrets.set",
|
|
339
|
+
"secrets.list",
|
|
340
|
+
"secrets.delete",
|
|
341
|
+
"aws.ec2_list",
|
|
342
|
+
"aws.ec2_start",
|
|
343
|
+
"aws.ec2_stop",
|
|
344
|
+
"aws.s3_list",
|
|
345
|
+
"aws.lambda_list",
|
|
346
|
+
"aws.lambda_invoke",
|
|
347
|
+
"aws.cloudwatch_alarms",
|
|
348
|
+
"aws.cost_summary",
|
|
349
|
+
"aws.rds_list",
|
|
350
|
+
"aws.bedrock_models",
|
|
351
|
+
"aws.grafana_list",
|
|
352
|
+
"googleads.list_accounts",
|
|
353
|
+
"googleads.search",
|
|
354
|
+
"googleads.campaign_performance",
|
|
355
|
+
"googleads.ad_group_performance",
|
|
356
|
+
"googleads.keyword_performance",
|
|
357
|
+
"googleads.budget_summary",
|
|
358
|
+
"calendar.generate",
|
|
359
|
+
"content.analyze",
|
|
360
|
+
"finance.ar.summary",
|
|
361
|
+
"finance.ar_aging",
|
|
362
|
+
"finance.ar_pastdue_report",
|
|
363
|
+
"finance.ar_overdue_notify",
|
|
364
|
+
"finance.ap.summary",
|
|
365
|
+
"finance.ap_aging",
|
|
366
|
+
"finance.reporting.summary",
|
|
367
|
+
"finance.trial_balance",
|
|
368
|
+
"sales.pipeline.summary",
|
|
369
|
+
"sales.pipeline_read",
|
|
370
|
+
"inventory.stock.summary",
|
|
371
|
+
"inventory.procurement_read",
|
|
372
|
+
"slack.list_channels",
|
|
373
|
+
"slack.post_message",
|
|
374
|
+
"notion.search",
|
|
375
|
+
"notion.append_page",
|
|
376
|
+
"hubspot.list_engagements",
|
|
377
|
+
"hubspot.log_call",
|
|
378
|
+
"hubspot.update_deal",
|
|
379
|
+
"linear.create_issue",
|
|
380
|
+
"asana.create_task",
|
|
381
|
+
"airtable.list_records",
|
|
382
|
+
"airtable.create_record",
|
|
383
|
+
"pandadoc.create_document",
|
|
384
|
+
"canva.create_design",
|
|
385
|
+
"canva.autofill_deck",
|
|
386
|
+
"zapier.trigger_zap",
|
|
387
|
+
"commitments.recall",
|
|
388
|
+
"workspacesync.fanout",
|
|
389
|
+
"dealdesk.draft",
|
|
390
|
+
"pricing.catalog_list",
|
|
391
|
+
"pricing.assumptions_list",
|
|
392
|
+
"pricing.benchmark_list",
|
|
393
|
+
"pricing.single_use_list",
|
|
394
|
+
"pricing.reusable_tco_list",
|
|
395
|
+
"pricing.monitoring_list",
|
|
396
|
+
"pricing.simulate_save"
|
|
397
|
+
]);
|
|
398
|
+
function unknownToolIds(tools) {
|
|
399
|
+
return tools.filter((t) => !KNOWN_TOOL_IDS.has(t));
|
|
400
|
+
}
|
|
401
|
+
|
|
193
402
|
// src/cli/validate.ts
|
|
194
403
|
function registerValidateCommand(program2) {
|
|
195
|
-
program2.command("validate").argument("<agent>", "agent directory (containing kohala.json)").
|
|
404
|
+
program2.command("validate").argument("<agent>", "agent directory (containing kohala.json)").option(
|
|
405
|
+
"--allow-unknown-tools",
|
|
406
|
+
"do not fail on tool ids missing from the bundled catalog snapshot"
|
|
407
|
+
).description("Validate an agent's kohala.json and print precise errors").action((agent, options) => {
|
|
196
408
|
const agentDir = path3.resolve(process.cwd(), agent);
|
|
197
409
|
try {
|
|
198
410
|
const manifest = loadManifest(agentDir);
|
|
411
|
+
const unknown = unknownToolIds(manifest.toolAllowlist);
|
|
412
|
+
if (unknown.length > 0) {
|
|
413
|
+
const msg = `toolAllowlist contains tool id(s) not in the Kohala tool catalog: ` + unknown.join(", ");
|
|
414
|
+
if (options.allowUnknownTools) {
|
|
415
|
+
console.warn(pc2.yellow(`warning: ${msg}`));
|
|
416
|
+
} else {
|
|
417
|
+
console.error(pc2.red(msg));
|
|
418
|
+
console.error(
|
|
419
|
+
pc2.dim(
|
|
420
|
+
" 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)."
|
|
421
|
+
)
|
|
422
|
+
);
|
|
423
|
+
process.exitCode = 1;
|
|
424
|
+
return;
|
|
425
|
+
}
|
|
426
|
+
}
|
|
199
427
|
console.log(pc2.green(`kohala.json for "${manifest.name}" is valid.`));
|
|
200
428
|
console.log(
|
|
201
429
|
pc2.dim(
|
|
@@ -725,8 +953,8 @@ var NoLlmKeyError = class extends Error {
|
|
|
725
953
|
this.name = "NoLlmKeyError";
|
|
726
954
|
}
|
|
727
955
|
};
|
|
728
|
-
var DEFAULT_ANTHROPIC_MODEL = "claude-
|
|
729
|
-
var DEFAULT_GEMINI_MODEL = "gemini-
|
|
956
|
+
var DEFAULT_ANTHROPIC_MODEL = "claude-sonnet-4-6";
|
|
957
|
+
var DEFAULT_GEMINI_MODEL = "gemini-flash-latest";
|
|
730
958
|
function detectLlmProvider(env = process.env) {
|
|
731
959
|
if (env.ANTHROPIC_API_KEY) return "anthropic";
|
|
732
960
|
if (env.GEMINI_API_KEY) return "gemini";
|
|
@@ -735,10 +963,12 @@ function detectLlmProvider(env = process.env) {
|
|
|
735
963
|
async function completeText(prompt, model, maxOutputTokens = 1024, env = process.env) {
|
|
736
964
|
const provider = detectLlmProvider(env);
|
|
737
965
|
if (provider === "anthropic") {
|
|
738
|
-
|
|
966
|
+
const resolvedModel = model ?? env.KOHALA_LLM_MODEL ?? env.ANTHROPIC_MODEL ?? DEFAULT_ANTHROPIC_MODEL;
|
|
967
|
+
return completeAnthropic(prompt, resolvedModel, maxOutputTokens, env);
|
|
739
968
|
}
|
|
740
969
|
if (provider === "gemini") {
|
|
741
|
-
|
|
970
|
+
const resolvedModel = model ?? env.KOHALA_LLM_MODEL ?? env.GEMINI_MODEL ?? DEFAULT_GEMINI_MODEL;
|
|
971
|
+
return completeGemini(prompt, resolvedModel, maxOutputTokens, env);
|
|
742
972
|
}
|
|
743
973
|
throw new NoLlmKeyError();
|
|
744
974
|
}
|
|
@@ -1211,9 +1441,11 @@ var TOOL_DEFINITIONS = {
|
|
|
1211
1441
|
async function runLlmShift(context, skillName, scriptPath, repairFeedback) {
|
|
1212
1442
|
const apiKey = process.env.ANTHROPIC_API_KEY;
|
|
1213
1443
|
if (!apiKey) {
|
|
1214
|
-
throw new
|
|
1444
|
+
throw new Error(
|
|
1445
|
+
'NO_LLM_KEY: llm mode requires ANTHROPIC_API_KEY. GEMINI_API_KEY enables llm.complete calls inside wrap-mode skills, but the llm-mode tool-use loop only supports Anthropic. Set ANTHROPIC_API_KEY in your environment to use runtimeMode: "llm".'
|
|
1446
|
+
);
|
|
1215
1447
|
}
|
|
1216
|
-
const model = process.env.KOHALA_LLM_MODEL ?? "claude-
|
|
1448
|
+
const model = process.env.KOHALA_LLM_MODEL ?? process.env.ANTHROPIC_MODEL ?? "claude-sonnet-4-6";
|
|
1217
1449
|
const dispatcher = new ToolDispatcher(context);
|
|
1218
1450
|
const { manifest, meter, trace, runId } = context;
|
|
1219
1451
|
const tools = Object.entries(TOOL_DEFINITIONS).filter(([name]) => manifest.toolAllowlist.includes(name)).map(([name, definition]) => ({ name: toApiToolName(name), ...definition }));
|
|
@@ -2198,8 +2430,15 @@ function registerDoctorCommand(program2) {
|
|
|
2198
2430
|
warn("python 3 not found", "wrap-mode `kohala run --local` will not work until installed");
|
|
2199
2431
|
}
|
|
2200
2432
|
const provider = detectLlmProvider();
|
|
2201
|
-
|
|
2202
|
-
|
|
2433
|
+
const hasAnthropic = Boolean(process.env.ANTHROPIC_API_KEY);
|
|
2434
|
+
if (hasAnthropic) {
|
|
2435
|
+
ok("LLM key (anthropic)", "llm.complete and llm mode both available");
|
|
2436
|
+
} else if (provider === "gemini") {
|
|
2437
|
+
ok("LLM key (gemini)", "llm.complete available in wrap mode");
|
|
2438
|
+
warn(
|
|
2439
|
+
"no ANTHROPIC_API_KEY",
|
|
2440
|
+
'llm mode (runtimeMode: "llm") requires Anthropic \u2014 GEMINI_API_KEY covers llm.complete only'
|
|
2441
|
+
);
|
|
2203
2442
|
} else {
|
|
2204
2443
|
warn(
|
|
2205
2444
|
"no ANTHROPIC_API_KEY / GEMINI_API_KEY",
|