@kadi.build/core 0.9.0 → 0.11.0

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.
Files changed (45) hide show
  1. package/README.md +424 -1
  2. package/agent.json +19 -0
  3. package/dist/agent-json.d.ts +231 -0
  4. package/dist/agent-json.d.ts.map +1 -0
  5. package/dist/agent-json.js +554 -0
  6. package/dist/agent-json.js.map +1 -0
  7. package/dist/client.d.ts +34 -0
  8. package/dist/client.d.ts.map +1 -1
  9. package/dist/client.js +50 -0
  10. package/dist/client.js.map +1 -1
  11. package/dist/errors.d.ts +1 -1
  12. package/dist/errors.d.ts.map +1 -1
  13. package/dist/errors.js.map +1 -1
  14. package/dist/index.d.ts +5 -1
  15. package/dist/index.d.ts.map +1 -1
  16. package/dist/index.js +8 -0
  17. package/dist/index.js.map +1 -1
  18. package/dist/process-manager.d.ts +235 -0
  19. package/dist/process-manager.d.ts.map +1 -0
  20. package/dist/process-manager.js +647 -0
  21. package/dist/process-manager.js.map +1 -0
  22. package/dist/stdio-framing.d.ts +88 -0
  23. package/dist/stdio-framing.d.ts.map +1 -0
  24. package/dist/stdio-framing.js +194 -0
  25. package/dist/stdio-framing.js.map +1 -0
  26. package/dist/transports/stdio.d.ts.map +1 -1
  27. package/dist/transports/stdio.js +3 -181
  28. package/dist/transports/stdio.js.map +1 -1
  29. package/dist/types.d.ts +256 -0
  30. package/dist/types.d.ts.map +1 -1
  31. package/dist/utils.d.ts +107 -0
  32. package/dist/utils.d.ts.map +1 -0
  33. package/dist/utils.js +212 -0
  34. package/dist/utils.js.map +1 -0
  35. package/package.json +3 -1
  36. package/scripts/symlink.mjs +131 -0
  37. package/src/agent-json.ts +655 -0
  38. package/src/client.ts +56 -0
  39. package/src/errors.ts +15 -0
  40. package/src/index.ts +32 -0
  41. package/src/process-manager.ts +821 -0
  42. package/src/stdio-framing.ts +227 -0
  43. package/src/transports/stdio.ts +4 -221
  44. package/src/types.ts +277 -0
  45. package/src/utils.ts +246 -0
package/README.md CHANGED
@@ -1,11 +1,14 @@
1
1
  # kadi-core
2
2
 
3
- TypeScript SDK for building KADI agents. Register tools, connect to brokers, load abilities, publish events.
3
+ TypeScript SDK for building KADI agents. Register tools, connect to brokers, load abilities, publish events, manage agent configuration, and run background processes.
4
4
 
5
5
  kadi-core lets you:
6
6
  - **Expose functions** as callable tools over the network
7
7
  - **Discover and invoke** remote services without hardcoding URLs
8
8
  - **Communicate via events** across your service mesh
9
+ - **Manage agent.json** configuration across projects, abilities, and global scope
10
+ - **Run background processes** with headless, piped, and JSON-RPC bridge modes
11
+ - **Install as an ability** — use kadi-core itself as a dependency in any agent
9
12
 
10
13
  ## Install
11
14
 
@@ -54,6 +57,9 @@ Now another agent can load and use it:
54
57
  - [Events from Abilities](#events-from-abilities)
55
58
  - [Broker Events (Pub/Sub)](#broker-events-pubsub)
56
59
  - [Serving as an Ability](#serving-as-an-ability)
60
+ - [Agent.json Management](#agentjson-management)
61
+ - [Process Manager](#process-manager)
62
+ - [Installing as an Ability](#installing-as-an-ability)
57
63
  - [Error Handling](#error-handling)
58
64
  - [API Reference](#api-reference)
59
65
  - [Troubleshooting](#troubleshooting)
@@ -400,6 +406,264 @@ await client.serve('broker');
400
406
 
401
407
  ---
402
408
 
409
+ ## Agent.json Management
410
+
411
+ The `AgentJsonManager` provides unified read/write/delete access to `agent.json` files across three scopes:
412
+
413
+ | Scope | Location | Use Case |
414
+ |-------|----------|----------|
415
+ | **Project** | `./agent.json` | Your agent's own configuration |
416
+ | **Ability** | `./abilities/<name>@<version>/agent.json` | Installed ability configuration |
417
+ | **Home** | `~/.kadi/agent.json` | Global CLI / user-level configuration |
418
+
419
+ ### Via KadiClient
420
+
421
+ The client exposes a lazy `agentJson` property — no extra instantiation needed:
422
+
423
+ ```typescript
424
+ const client = new KadiClient({ name: 'my-agent' });
425
+
426
+ // Read the full project config
427
+ const config = await client.agentJson.readProject();
428
+
429
+ // Read a nested field with dot-path notation
430
+ const target = await client.agentJson.readProject('deploy.local.target');
431
+
432
+ // Write a nested field (deep-merges into existing data)
433
+ await client.agentJson.writeProject('deploy.staging', {
434
+ target: 'akash',
435
+ replicas: 2,
436
+ });
437
+
438
+ // Delete a field
439
+ await client.agentJson.deleteProject('deploy.staging');
440
+ ```
441
+
442
+ ### Standalone Usage
443
+
444
+ You can also use `AgentJsonManager` directly without a client:
445
+
446
+ ```typescript
447
+ import { AgentJsonManager } from '@kadi.build/core';
448
+
449
+ const ajm = new AgentJsonManager({
450
+ projectRoot: '/path/to/my-agent', // Optional, auto-detects via agent-lock.json
451
+ kadiHome: '~/.kadi', // Optional, defaults to ~/.kadi
452
+ createOnWrite: true, // Create file if missing on write (default: true)
453
+ });
454
+
455
+ const config = await ajm.readProject();
456
+ ```
457
+
458
+ ### Reading Ability Config
459
+
460
+ ```typescript
461
+ // Read full config for an installed ability (resolves highest semver by default)
462
+ const calcConfig = await client.agentJson.readAbility('calculator');
463
+
464
+ // Read a specific field
465
+ const scripts = await client.agentJson.readAbility('calculator', {
466
+ field: 'scripts.start',
467
+ });
468
+
469
+ // Pin to a specific version (useful when multiple versions are installed)
470
+ const old = await client.agentJson.readAbility('calculator', {
471
+ version: '1.0.0',
472
+ });
473
+ ```
474
+
475
+ ### Global Home Config
476
+
477
+ ```typescript
478
+ // Read global KADI configuration
479
+ const homeConfig = await client.agentJson.readHome();
480
+ const defaultBroker = await client.agentJson.readHome('brokers.default');
481
+
482
+ // Write to global config
483
+ await client.agentJson.writeHome('brokers.staging', 'wss://staging.example.com/kadi');
484
+ ```
485
+
486
+ ### Discovery
487
+
488
+ ```typescript
489
+ // List all installed abilities (reads agent-lock.json)
490
+ const abilities = await client.agentJson.listAbilities();
491
+ // [{ name: 'calculator', version: '1.0.0', path: '/abs/path/abilities/calculator@1.0.0' }, ...]
492
+
493
+ // Check if an ability is installed
494
+ const has = await client.agentJson.hasAbility('calculator');
495
+
496
+ // Get all installed versions of an ability
497
+ const versions = await client.agentJson.getAbilityVersions('calculator');
498
+ // ['1.0.0', '2.0.0']
499
+
500
+ // Get resolved paths for all three scopes
501
+ const paths = await client.agentJson.getPaths();
502
+ // { project: '/abs/path/agent.json', home: '/home/user/.kadi/agent.json' }
503
+ ```
504
+
505
+ ---
506
+
507
+ ## Process Manager
508
+
509
+ The `ProcessManager` spawns and supervises background child processes in three modes:
510
+
511
+ | Mode | Communication | Use Case |
512
+ |------|--------------|----------|
513
+ | **headless** | None | Fire-and-forget tasks (docker build, git clone) |
514
+ | **piped** | stdout/stderr streaming | Tasks where you need live output (deploys, logs) |
515
+ | **bridge** | JSON-RPC 2.0 over stdio | Interactive workers (inference engines, language servers) |
516
+
517
+ ### Via KadiClient
518
+
519
+ ```typescript
520
+ const client = new KadiClient({ name: 'my-agent' });
521
+
522
+ // Headless — fire and forget
523
+ const build = await client.processes.spawn('build', {
524
+ command: 'docker',
525
+ args: ['build', '-t', 'myapp', '.'],
526
+ mode: 'headless',
527
+ });
528
+
529
+ // Check status later
530
+ const status = client.processes.getStatus('build');
531
+ console.log(status); // 'running' | 'exited' | 'killed' | 'errored'
532
+ ```
533
+
534
+ ### Piped Mode — Live Output
535
+
536
+ ```typescript
537
+ const deploy = await client.processes.spawn('deploy', {
538
+ command: 'kadi',
539
+ args: ['deploy', '--target', 'akash'],
540
+ mode: 'piped',
541
+ cwd: '/path/to/project',
542
+ env: { KADI_ENV: 'production' },
543
+ });
544
+
545
+ // Stream stdout/stderr in real time
546
+ deploy.on('stdout', (chunk) => process.stdout.write(chunk));
547
+ deploy.on('stderr', (chunk) => process.stderr.write(chunk));
548
+ deploy.on('exit', ({ exitCode }) => console.log('Deploy exited:', exitCode));
549
+
550
+ // Get buffered output later
551
+ const output = deploy.getOutput();
552
+ console.log(output.stdout); // Full stdout string
553
+ console.log(output.stderr); // Full stderr string
554
+ ```
555
+
556
+ ### Bridge Mode — JSON-RPC Workers
557
+
558
+ Bridge mode wraps the child process in the same Content-Length framed JSON-RPC protocol used by stdio transports. This lets you send requests to the child and receive responses:
559
+
560
+ ```typescript
561
+ const worker = await client.processes.spawn('inference', {
562
+ command: 'python3',
563
+ args: ['worker.py'],
564
+ mode: 'bridge',
565
+ });
566
+
567
+ // Send a JSON-RPC request and await the response
568
+ const result = await worker.request('run-inference', {
569
+ model: 'llama3',
570
+ prompt: 'Explain kadi in one sentence',
571
+ });
572
+ console.log(result);
573
+
574
+ // Fire-and-forget notification (no response expected)
575
+ worker.notify('update-config', { temperature: 0.7 });
576
+
577
+ // Listen for notifications from the worker
578
+ worker.on('notification', ({ method, params }) => {
579
+ console.log(`Worker says: ${method}`, params);
580
+ });
581
+ ```
582
+
583
+ ### Lifecycle Management
584
+
585
+ ```typescript
586
+ // List all managed processes
587
+ const all = client.processes.list();
588
+ const running = client.processes.list({ mode: 'piped' }); // Filter by mode
589
+
590
+ // Get a handle to an existing process
591
+ const proc = client.processes.get('build');
592
+
593
+ // Get detailed info
594
+ const info = proc.getInfo();
595
+ // { id: 'build', pid: 12345, mode: 'piped', state: 'running', startedAt: ... }
596
+
597
+ // Kill a single process (SIGTERM → grace period → SIGKILL)
598
+ await proc.kill();
599
+
600
+ // Kill all managed processes
601
+ await client.processes.killAll();
602
+
603
+ // Wait for a process to exit
604
+ const exitInfo = await proc.waitForExit();
605
+ console.log(exitInfo.exitCode, exitInfo.signal);
606
+
607
+ // Clean up exited/errored entries
608
+ client.processes.prune();
609
+
610
+ // Graceful shutdown — kills all and cleans up
611
+ await client.processes.shutdown();
612
+ ```
613
+
614
+ ### Timeout Auto-Kill
615
+
616
+ Processes can have an automatic timeout. When the timeout fires, the process is killed:
617
+
618
+ ```typescript
619
+ const task = await client.processes.spawn('migration', {
620
+ command: 'node',
621
+ args: ['migrate.js'],
622
+ mode: 'piped',
623
+ timeout: 60000, // Kill after 60 seconds if still running
624
+ });
625
+ ```
626
+
627
+ ### Standalone Usage
628
+
629
+ ```typescript
630
+ import { ProcessManager } from '@kadi.build/core';
631
+
632
+ const pm = new ProcessManager();
633
+
634
+ const worker = await pm.spawn('worker', {
635
+ command: 'python3',
636
+ args: ['worker.py'],
637
+ mode: 'bridge',
638
+ });
639
+
640
+ const result = await worker.request('echo', { message: 'hello' });
641
+ await pm.shutdown();
642
+ ```
643
+
644
+ ---
645
+
646
+ ## Installing as an Ability
647
+
648
+ kadi-core v0.10.0 ships its own `agent.json` with `type: "ability"`, so it can be installed into any agent project using the standard `kadi install` workflow:
649
+
650
+ ```bash
651
+ kadi install kadi-core
652
+ ```
653
+
654
+ After installation, a `postinstall` script creates a symlink at `node_modules/@kadi.build/core` pointing to the installed ability directory. This means your code can use the standard import path regardless of where the ability lives on disk:
655
+
656
+ ```typescript
657
+ import { KadiClient, z } from '@kadi.build/core';
658
+ ```
659
+
660
+ This is particularly useful for:
661
+ - **Python agents** (via `kadi-core-py`) that need a reference to kadi-core's protocol definitions
662
+ - **Polyglot projects** that install abilities via `kadi install` rather than `npm install`
663
+ - **Deployed agents** where abilities are resolved from `agent-lock.json`
664
+
665
+ ---
666
+
403
667
  ## Error Handling
404
668
 
405
669
  All errors are `KadiError` with structured codes and context:
@@ -430,6 +694,17 @@ try {
430
694
  | `BROKER_TIMEOUT` | Request to broker timed out |
431
695
  | `INVALID_CONFIG` | Configuration error (missing required fields, etc.) |
432
696
  | `LOCKFILE_NOT_FOUND` | `loadNative/loadStdio` when agent-lock.json doesn't exist |
697
+ | `AGENT_JSON_NOT_FOUND` | `readProject/readAbility/readHome` when agent.json doesn't exist |
698
+ | `AGENT_JSON_PARSE_ERROR` | agent.json exists but contains invalid JSON |
699
+ | `AGENT_JSON_WRITE_ERROR` | Failed to write agent.json (permissions, disk, etc.) |
700
+ | `AGENT_JSON_FIELD_NOT_FOUND` | Dot-path field doesn't exist in agent.json |
701
+ | `AGENT_JSON_VERSION_AMBIGUOUS` | Multiple versions installed and no version specified |
702
+ | `PROCESS_ALREADY_EXISTS` | `spawn()` with an ID that's already in use |
703
+ | `PROCESS_NOT_FOUND` | `get()` / `getStatus()` with an unknown process ID |
704
+ | `PROCESS_NOT_RUNNING` | `request()` / `notify()` on an exited process |
705
+ | `PROCESS_BRIDGE_ERROR` | JSON-RPC communication error in bridge mode |
706
+ | `PROCESS_SPAWN_FAILED` | Child process failed to start (bad command, permissions) |
707
+ | `PROCESS_TIMEOUT` | Process exceeded its configured timeout |
433
708
 
434
709
  ---
435
710
 
@@ -472,6 +747,13 @@ new KadiClient(config: ClientConfig)
472
747
  | `serve(mode)` | Serve as ability (`'stdio'` or `'broker'`) |
473
748
  | `getConnectedBrokers()` | List connected broker names |
474
749
 
750
+ **Properties:**
751
+
752
+ | Property | Type | Description |
753
+ |----------|------|-------------|
754
+ | `agentJson` | `AgentJsonManager` | Lazy-initialized agent.json manager. See [Agent.json Management](#agentjson-management) |
755
+ | `processes` | `ProcessManager` | Lazy-initialized process manager. See [Process Manager](#process-manager) |
756
+
475
757
  ### LoadedAbility
476
758
 
477
759
  Returned by `loadNative()`, `loadStdio()`, `loadBroker()`:
@@ -500,6 +782,97 @@ interface BrokerEvent {
500
782
  }
501
783
  ```
502
784
 
785
+ ### AgentJsonManager
786
+
787
+ ```typescript
788
+ new AgentJsonManager(options?: AgentJsonManagerOptions)
789
+ ```
790
+
791
+ **Options:**
792
+
793
+ | Option | Type | Default | Description |
794
+ |--------|------|---------|-------------|
795
+ | `projectRoot` | `string` | auto-detect | Path to agent project root |
796
+ | `kadiHome` | `string` | `~/.kadi` | Path to KADI home directory |
797
+ | `createOnWrite` | `boolean` | `true` | Create agent.json if missing on write |
798
+
799
+ **Methods:**
800
+
801
+ | Method | Returns | Description |
802
+ |--------|---------|-------------|
803
+ | `readProject(field?)` | `Promise<unknown>` | Read project agent.json (optional dot-path field) |
804
+ | `readAbility(name, options?)` | `Promise<unknown>` | Read an installed ability's agent.json |
805
+ | `readHome(field?)` | `Promise<unknown>` | Read global ~/.kadi/agent.json |
806
+ | `writeProject(path, value)` | `Promise<void>` | Write/deep-merge a field in project agent.json |
807
+ | `writeAbility(name, path, value, version?)` | `Promise<void>` | Write a field in an ability's agent.json |
808
+ | `writeHome(path, value)` | `Promise<void>` | Write a field in global agent.json |
809
+ | `deleteProject(path)` | `Promise<boolean>` | Delete a field from project agent.json |
810
+ | `deleteAbility(name, path, version?)` | `Promise<boolean>` | Delete a field from an ability's agent.json |
811
+ | `deleteHome(path)` | `Promise<boolean>` | Delete a field from global agent.json |
812
+ | `listAbilities()` | `Promise<AbilityInfo[]>` | List all installed abilities |
813
+ | `hasAbility(name)` | `Promise<boolean>` | Check if an ability is installed |
814
+ | `getAbilityVersions(name)` | `Promise<string[]>` | Get installed versions of an ability |
815
+ | `getPaths()` | `Promise<AgentJsonPaths>` | Get resolved file paths for all scopes |
816
+
817
+ ### ProcessManager
818
+
819
+ ```typescript
820
+ new ProcessManager()
821
+ ```
822
+
823
+ **Methods:**
824
+
825
+ | Method | Returns | Description |
826
+ |--------|---------|-------------|
827
+ | `spawn(id, options)` | `Promise<ManagedProcess>` | Spawn a new background process |
828
+ | `get(id)` | `ManagedProcess` | Get handle to an existing process (throws if not found) |
829
+ | `getStatus(id)` | `ProcessState` | Get process state: `'running'` \| `'exited'` \| `'killed'` \| `'errored'` |
830
+ | `list(options?)` | `ManagedProcess[]` | List all managed processes (optional mode filter) |
831
+ | `kill(id)` | `Promise<void>` | Kill a process by ID |
832
+ | `killAll()` | `Promise<void>` | Kill all managed processes |
833
+ | `shutdown()` | `Promise<void>` | Kill all and clean up |
834
+ | `prune()` | `number` | Remove exited/errored entries, returns count pruned |
835
+
836
+ **SpawnOptions:**
837
+
838
+ | Option | Type | Default | Description |
839
+ |--------|------|---------|-------------|
840
+ | `command` | `string` | required | Command to run |
841
+ | `args` | `string[]` | `[]` | Command arguments |
842
+ | `mode` | `ProcessMode` | required | `'headless'` \| `'piped'` \| `'bridge'` |
843
+ | `cwd` | `string` | `process.cwd()` | Working directory |
844
+ | `env` | `Record<string, string>` | inherited | Environment variables |
845
+ | `timeout` | `number` | none | Auto-kill after N milliseconds |
846
+ | `killGracePeriod` | `number` | `5000` | Time between SIGTERM and SIGKILL |
847
+
848
+ ### ManagedProcess
849
+
850
+ Returned by `ProcessManager.spawn()`. Extends `EventEmitter`.
851
+
852
+ | Property/Method | Description |
853
+ |-----------------|-------------|
854
+ | `id` | Unique process identifier |
855
+ | `pid` | OS process ID |
856
+ | `mode` | `'headless'` \| `'piped'` \| `'bridge'` |
857
+ | `state` | Current state: `'running'` \| `'exited'` \| `'killed'` \| `'errored'` |
858
+ | `request(method, params?)` | **Bridge only.** Send JSON-RPC request, returns `Promise<unknown>` |
859
+ | `notify(method, params?)` | **Bridge only.** Send JSON-RPC notification (no response) |
860
+ | `write(data)` | Write raw data to stdin |
861
+ | `kill()` | Kill the process (SIGTERM → grace → SIGKILL) |
862
+ | `waitForExit()` | `Promise<ProcessExitInfo>` — resolves when process exits |
863
+ | `getOutput()` | **Piped only.** Get buffered `{ stdout, stderr }` |
864
+ | `getInfo()` | Get `ProcessInfo` snapshot |
865
+
866
+ **Events:**
867
+
868
+ | Event | Payload | Modes |
869
+ |-------|---------|-------|
870
+ | `stdout` | `string` | piped |
871
+ | `stderr` | `string` | piped |
872
+ | `exit` | `ProcessExitInfo` | all |
873
+ | `error` | `Error` | all |
874
+ | `notification` | `{ method, params }` | bridge |
875
+
503
876
  ---
504
877
 
505
878
  ## Troubleshooting
@@ -530,6 +903,19 @@ Increase the timeout:
530
903
  await client.invokeRemote('slow-tool', params, { timeout: 60000 });
531
904
  ```
532
905
 
906
+ ### AGENT_JSON_NOT_FOUND errors
907
+
908
+ The manager can't find `agent.json` at the expected path. Either:
909
+ - Ensure you're running from inside a project with `agent.json` and `agent-lock.json`
910
+ - Pass an explicit `projectRoot` when constructing `AgentJsonManager`
911
+
912
+ ### PROCESS_BRIDGE_ERROR in bridge mode
913
+
914
+ The child process isn't speaking the expected Content-Length framed JSON-RPC protocol. Ensure:
915
+ 1. The child writes `Content-Length: <n>\r\n\r\n<json>` to stdout
916
+ 2. The child reads the same framing from stdin
917
+ 3. No other output is mixed into stdout (use stderr for logging)
918
+
533
919
  ---
534
920
 
535
921
  ## Advanced: Building CLI Tools
@@ -575,6 +961,43 @@ const calcPath = resolveAbilityPath('calculator', root);
575
961
  // '/path/to/project/abilities/calculator@1.0.0'
576
962
  ```
577
963
 
964
+ ### Dot-Path Utilities
965
+
966
+ Low-level helpers for nested object access (used internally by `AgentJsonManager`):
967
+
968
+ ```typescript
969
+ import { getByPath, setByPath, deleteByPath, deepMerge } from '@kadi.build/core';
970
+
971
+ const obj = { deploy: { local: { target: 'docker' } } };
972
+
973
+ getByPath(obj, 'deploy.local.target'); // 'docker'
974
+ setByPath(obj, 'deploy.staging.target', 'akash');
975
+ deleteByPath(obj, 'deploy.local');
976
+
977
+ // Deep merge (objects merged recursively, arrays replaced)
978
+ const merged = deepMerge(
979
+ { deploy: { replicas: 1, target: 'docker' } },
980
+ { deploy: { replicas: 3 } },
981
+ );
982
+ // { deploy: { replicas: 3, target: 'docker' } }
983
+ ```
984
+
985
+ ### Stdio Framing
986
+
987
+ For building custom Content-Length framed JSON-RPC protocols (used internally by stdio transport and bridge mode):
988
+
989
+ ```typescript
990
+ import { StdioMessageReader, StdioMessageWriter } from '@kadi.build/core';
991
+
992
+ // Wrap a readable stream (e.g., child.stdout)
993
+ const reader = new StdioMessageReader(childProcess.stdout);
994
+ reader.onMessage((msg) => console.log('Received:', msg));
995
+
996
+ // Wrap a writable stream (e.g., child.stdin)
997
+ const writer = new StdioMessageWriter(childProcess.stdin);
998
+ writer.write({ jsonrpc: '2.0', method: 'ping', params: {} });
999
+ ```
1000
+
578
1001
  ---
579
1002
 
580
1003
  ## Related
package/agent.json ADDED
@@ -0,0 +1,19 @@
1
+ {
2
+ "name": "kadi-core",
3
+ "version": "0.11.0",
4
+ "type": "ability",
5
+ "license": "MIT",
6
+ "description": "Core SDK for building KADI agents — provides client, transports, agent.json management, and process management",
7
+ "entrypoint": "dist/index.js",
8
+ "repo": "https://gitlab.com/humin-game-lab/agent-abilities/kadi-core.git",
9
+ "lib": "https://gitlab.com/humin-game-lab/agent-abilities/kadi-core/-/archive/v0.11.0/kadi-core-v0.11.0.zip",
10
+ "abilities": {},
11
+
12
+ "scripts": {
13
+ "preflight": "echo 'kadi-core v0.11.0 checking environment...'",
14
+ "setup": "npm install && npm run build",
15
+ "postinstall": "node scripts/symlink.mjs",
16
+ "start": "echo 'kadi-core is a library — import it in your code'",
17
+ "stop": "echo 'kadi-core stopped'"
18
+ }
19
+ }