@kindgi/sdk 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/dist/client.d.ts CHANGED
@@ -15,6 +15,12 @@ export type { KindgiClient } from '@kindgi/client';
15
15
  * browser, pass `apiUrl` and `auth`. `@kindgi/client`'s `createClient` is
16
16
  * the explicit form underneath.
17
17
  *
18
+ * The options are found on first use, not here: a module-scope
19
+ * `const kindgi = createClient()` is safe to import where the runtime's
20
+ * settings aren't set, as a production build (`next build`) imports every
21
+ * module. When they're missing, the first use (`kindgi.runs`, …) throws
22
+ * the error that says what to set; once they're set, the next use works.
23
+ *
18
24
  * @example
19
25
  * ```ts
20
26
  * import { createClient } from '@kindgi/sdk/client';
@@ -28,6 +34,8 @@ export { KindgiApiError, fromWire, notImplementedInPreview, notYetWired } from '
28
34
  export type { AuthError, ConflictError, GuardrailViolation, GuardrailViolationError, InvalidRequestError, NetworkError, NotFoundError, NotImplementedInPreviewError, NotYetWiredError, RateLimitedError, ServerError, KindgiError, } from '@kindgi/client';
29
35
  export { readSse, unwrapSseData } from '@kindgi/client';
30
36
  export type { SseEvent, SseReadOptions } from '@kindgi/client';
37
+ export { verifySignedExport } from '@kindgi/client';
38
+ export type { ExportSigningKey, SignedExportEnvelope, SignedExportVerification, VerifySignedExportOptions, } from '@kindgi/client';
31
39
  export { followRun, subscribeToRun } from '@kindgi/client';
32
40
  export type { FollowRunOptions, RunProgress, RunProgressEvent, SubscribeToRunOptions, } from '@kindgi/client';
33
41
  export { comparisonOf } from '@kindgi/client';
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAwBA,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAIlE,YAAY,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAEnD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,YAAY,CAAC,OAAO,GAAE,OAAO,CAAC,aAAa,CAAM,GAAG,YAAY,CAE/E;AAGD,YAAY,EACV,qBAAqB,EACrB,aAAa,EACb,gBAAgB,EAChB,cAAc,EACd,kBAAkB,EAClB,YAAY,EACZ,kBAAkB,EAClB,cAAc,EACd,eAAe,EACf,cAAc,EACd,eAAe,EACf,WAAW,EACX,gBAAgB,EAChB,gBAAgB,EAChB,aAAa,EACb,kBAAkB,EAClB,gBAAgB,EAChB,aAAa,EACb,kBAAkB,EAClB,kBAAkB,EAClB,mBAAmB,EACnB,UAAU,EACV,WAAW,EACX,mBAAmB,EACnB,YAAY,EACZ,WAAW,EACX,UAAU,EACV,WAAW,EACX,kBAAkB,EAClB,eAAe,EACf,gBAAgB,EAChB,UAAU,EACV,SAAS,EACT,iBAAiB,EACjB,kBAAkB,EAClB,qBAAqB,EACrB,YAAY,EACZ,aAAa,EACb,iBAAiB,EACjB,kBAAkB,EAClB,UAAU,EACV,UAAU,EACV,WAAW,EACX,UAAU,EACV,aAAa,EACb,cAAc,EACd,gBAAgB,EAChB,oBAAoB,EACpB,mBAAmB,EACnB,iBAAiB,EACjB,eAAe,EACf,gBAAgB,EAChB,qBAAqB,EACrB,cAAc,EACd,eAAe,EACf,kBAAkB,EAClB,cAAc,EACd,cAAc,EACd,cAAc,EACd,cAAc,EACd,eAAe,EACf,qBAAqB,EACrB,GAAG,EACH,UAAU,EACV,eAAe,EACf,cAAc,EACd,aAAa,EACb,oBAAoB,EACpB,mBAAmB,EACnB,gBAAgB,EAChB,eAAe,EACf,WAAW,EACX,YAAY,EACZ,kBAAkB,EAClB,WAAW,EACX,YAAY,EACZ,0BAA0B,EAC1B,UAAU,EACV,iBAAiB,EACjB,WAAW,EACX,SAAS,EACT,gBAAgB,EAChB,WAAW,EACX,iBAAiB,EACjB,UAAU,EACV,WAAW,EACX,cAAc,EACd,qBAAqB,GACtB,MAAM,gBAAgB,CAAC;AAGxB,OAAO,EAAE,cAAc,EAAE,QAAQ,EAAE,uBAAuB,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAChG,YAAY,EACV,SAAS,EACT,aAAa,EACb,kBAAkB,EAClB,uBAAuB,EACvB,mBAAmB,EACnB,YAAY,EACZ,aAAa,EACb,4BAA4B,EAC5B,gBAAgB,EAChB,gBAAgB,EAChB,WAAW,EACX,WAAW,GACZ,MAAM,gBAAgB,CAAC;AAGxB,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AACxD,YAAY,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAG/D,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAC3D,YAAY,EACV,gBAAgB,EAChB,WAAW,EACX,gBAAgB,EAChB,qBAAqB,GACtB,MAAM,gBAAgB,CAAC;AAGxB,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,YAAY,EACV,mBAAmB,EACnB,oBAAoB,EACpB,gBAAgB,EAChB,sBAAsB,EACtB,uBAAuB,GACxB,MAAM,gBAAgB,CAAC"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAwBA,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAIlE,YAAY,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAEnD;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAgB,YAAY,CAAC,OAAO,GAAE,OAAO,CAAC,aAAa,CAAM,GAAG,YAAY,CA6B/E;AAGD,YAAY,EACV,qBAAqB,EACrB,aAAa,EACb,gBAAgB,EAChB,cAAc,EACd,kBAAkB,EAClB,YAAY,EACZ,kBAAkB,EAClB,cAAc,EACd,eAAe,EACf,cAAc,EACd,eAAe,EACf,WAAW,EACX,gBAAgB,EAChB,gBAAgB,EAChB,aAAa,EACb,kBAAkB,EAClB,gBAAgB,EAChB,aAAa,EACb,kBAAkB,EAClB,kBAAkB,EAClB,mBAAmB,EACnB,UAAU,EACV,WAAW,EACX,mBAAmB,EACnB,YAAY,EACZ,WAAW,EACX,UAAU,EACV,WAAW,EACX,kBAAkB,EAClB,eAAe,EACf,gBAAgB,EAChB,UAAU,EACV,SAAS,EACT,iBAAiB,EACjB,kBAAkB,EAClB,qBAAqB,EACrB,YAAY,EACZ,aAAa,EACb,iBAAiB,EACjB,kBAAkB,EAClB,UAAU,EACV,UAAU,EACV,WAAW,EACX,UAAU,EACV,aAAa,EACb,cAAc,EACd,gBAAgB,EAChB,oBAAoB,EACpB,mBAAmB,EACnB,iBAAiB,EACjB,eAAe,EACf,gBAAgB,EAChB,qBAAqB,EACrB,cAAc,EACd,eAAe,EACf,kBAAkB,EAClB,cAAc,EACd,cAAc,EACd,cAAc,EACd,cAAc,EACd,eAAe,EACf,qBAAqB,EACrB,GAAG,EACH,UAAU,EACV,eAAe,EACf,cAAc,EACd,aAAa,EACb,oBAAoB,EACpB,mBAAmB,EACnB,gBAAgB,EAChB,eAAe,EACf,WAAW,EACX,YAAY,EACZ,kBAAkB,EAClB,WAAW,EACX,YAAY,EACZ,0BAA0B,EAC1B,UAAU,EACV,iBAAiB,EACjB,WAAW,EACX,SAAS,EACT,gBAAgB,EAChB,WAAW,EACX,iBAAiB,EACjB,UAAU,EACV,WAAW,EACX,cAAc,EACd,qBAAqB,GACtB,MAAM,gBAAgB,CAAC;AAGxB,OAAO,EAAE,cAAc,EAAE,QAAQ,EAAE,uBAAuB,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAChG,YAAY,EACV,SAAS,EACT,aAAa,EACb,kBAAkB,EAClB,uBAAuB,EACvB,mBAAmB,EACnB,YAAY,EACZ,aAAa,EACb,4BAA4B,EAC5B,gBAAgB,EAChB,gBAAgB,EAChB,WAAW,EACX,WAAW,GACZ,MAAM,gBAAgB,CAAC;AAGxB,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AACxD,YAAY,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAG/D,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACpD,YAAY,EACV,gBAAgB,EAChB,oBAAoB,EACpB,wBAAwB,EACxB,yBAAyB,GAC1B,MAAM,gBAAgB,CAAC;AAGxB,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAC3D,YAAY,EACV,gBAAgB,EAChB,WAAW,EACX,gBAAgB,EAChB,qBAAqB,GACtB,MAAM,gBAAgB,CAAC;AAGxB,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,YAAY,EACV,mBAAmB,EACnB,oBAAoB,EACpB,gBAAgB,EAChB,sBAAsB,EACtB,uBAAuB,GACxB,MAAM,gBAAgB,CAAC"}
package/dist/client.js CHANGED
@@ -36,6 +36,12 @@ import { resolveClientOptions } from './runtime-config.js';
36
36
  * browser, pass `apiUrl` and `auth`. `@kindgi/client`'s `createClient` is
37
37
  * the explicit form underneath.
38
38
  *
39
+ * The options are found on first use, not here: a module-scope
40
+ * `const kindgi = createClient()` is safe to import where the runtime's
41
+ * settings aren't set, as a production build (`next build`) imports every
42
+ * module. When they're missing, the first use (`kindgi.runs`, …) throws
43
+ * the error that says what to set; once they're set, the next use works.
44
+ *
39
45
  * @example
40
46
  * ```ts
41
47
  * import { createClient } from '@kindgi/sdk/client';
@@ -44,12 +50,41 @@ import { resolveClientOptions } from './runtime-config.js';
44
50
  * ```
45
51
  */
46
52
  export function createClient(options = {}) {
47
- return createKindgiClient(resolveClientOptions(options));
53
+ let client;
54
+ // A failed lookup isn't kept: the env may be set by the next use.
55
+ const resolved = () => {
56
+ client ??= createKindgiClient(resolveClientOptions(options));
57
+ return client;
58
+ };
59
+ return new Proxy({}, {
60
+ get(_target, key) {
61
+ // Never resolve to answer whether the client is a promise (`await`,
62
+ // `return` from an async function), or for a symbol a tool inspects.
63
+ if (client === undefined && (key === 'then' || typeof key === 'symbol'))
64
+ return undefined;
65
+ return Reflect.get(resolved(), key);
66
+ },
67
+ // A write (a test swapping a resource) is a use: it lands on the client.
68
+ // A property defined non-configurable (`defineProperty`'s default) throws:
69
+ // a proxy can't hold one its target doesn't. Define it `configurable: true`.
70
+ set: (_target, key, value) => Reflect.set(resolved(), key, value),
71
+ defineProperty: (_target, key, descriptor) => Reflect.defineProperty(resolved(), key, descriptor),
72
+ deleteProperty: (_target, key) => Reflect.deleteProperty(resolved(), key),
73
+ has: (_target, key) => key in resolved(),
74
+ ownKeys: () => Reflect.ownKeys(resolved()),
75
+ getOwnPropertyDescriptor(_target, key) {
76
+ const descriptor = Reflect.getOwnPropertyDescriptor(resolved(), key);
77
+ // The target holds none of the client's fields, so none may be reported fixed.
78
+ return descriptor === undefined ? undefined : { ...descriptor, configurable: true };
79
+ },
80
+ });
48
81
  }
49
82
  // ---- Error surface ----
50
83
  export { KindgiApiError, fromWire, notImplementedInPreview, notYetWired } from '@kindgi/client';
51
84
  // ---- Streaming helpers (SSE parser + resume) ----
52
85
  export { readSse, unwrapSseData } from '@kindgi/client';
86
+ // ---- Signed exports: check one where it's read ----
87
+ export { verifySignedExport } from '@kindgi/client';
53
88
  // ---- Following a run (browser-safe: a page follows a run with a public token) ----
54
89
  export { followRun, subscribeToRun } from '@kindgi/client';
55
90
  // ---- Comparisons (a test set compared with a version): the typed result ----
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,iCAAiC;AAEjC;;;;;;;;;;;;;;;;;GAiBG;AAEH,6CAA6C;AAC7C,OAAO,EAAE,YAAY,IAAI,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAGpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAI3D;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,UAAU,YAAY,CAAC,UAAkC,EAAE;IAC/D,OAAO,kBAAkB,CAAC,oBAAoB,CAAC,OAAO,CAAC,CAAC,CAAC;AAC3D,CAAC;AA8FD,0BAA0B;AAC1B,OAAO,EAAE,cAAc,EAAE,QAAQ,EAAE,uBAAuB,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAgBhG,oDAAoD;AACpD,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAGxD,qFAAqF;AACrF,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAQ3D,+EAA+E;AAC/E,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC"}
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,iCAAiC;AAEjC;;;;;;;;;;;;;;;;;GAiBG;AAEH,6CAA6C;AAC7C,OAAO,EAAE,YAAY,IAAI,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAGpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAI3D;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,MAAM,UAAU,YAAY,CAAC,UAAkC,EAAE;IAC/D,IAAI,MAAgC,CAAC;IACrC,kEAAkE;IAClE,MAAM,QAAQ,GAAG,GAAiB,EAAE;QAClC,MAAM,KAAK,kBAAkB,CAAC,oBAAoB,CAAC,OAAO,CAAC,CAAC,CAAC;QAC7D,OAAO,MAAM,CAAC;IAChB,CAAC,CAAC;IACF,OAAO,IAAI,KAAK,CAAC,EAAkB,EAAE;QACnC,GAAG,CAAC,OAAO,EAAE,GAAG;YACd,oEAAoE;YACpE,qEAAqE;YACrE,IAAI,MAAM,KAAK,SAAS,IAAI,CAAC,GAAG,KAAK,MAAM,IAAI,OAAO,GAAG,KAAK,QAAQ,CAAC;gBAAE,OAAO,SAAS,CAAC;YAC1F,OAAO,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE,GAAG,CAAC,CAAC;QACtC,CAAC;QACD,yEAAyE;QACzE,2EAA2E;QAC3E,6EAA6E;QAC7E,GAAG,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE,GAAG,EAAE,KAAK,CAAC;QACjE,cAAc,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,UAAU,EAAE,EAAE,CAC3C,OAAO,CAAC,cAAc,CAAC,QAAQ,EAAE,EAAE,GAAG,EAAE,UAAU,CAAC;QACrD,cAAc,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,EAAE,CAAC,OAAO,CAAC,cAAc,CAAC,QAAQ,EAAE,EAAE,GAAG,CAAC;QACzE,GAAG,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,EAAE,CAAC,GAAG,IAAI,QAAQ,EAAE;QACxC,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC;QAC1C,wBAAwB,CAAC,OAAO,EAAE,GAAG;YACnC,MAAM,UAAU,GAAG,OAAO,CAAC,wBAAwB,CAAC,QAAQ,EAAE,EAAE,GAAG,CAAC,CAAC;YACrE,+EAA+E;YAC/E,OAAO,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,GAAG,UAAU,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC;QACtF,CAAC;KACF,CAAC,CAAC;AACL,CAAC;AA8FD,0BAA0B;AAC1B,OAAO,EAAE,cAAc,EAAE,QAAQ,EAAE,uBAAuB,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAgBhG,oDAAoD;AACpD,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAGxD,sDAAsD;AACtD,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAQpD,qFAAqF;AACrF,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAQ3D,+EAA+E;AAC/E,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kindgi/sdk",
3
- "version": "0.1.4",
3
+ "version": "0.1.5",
4
4
  "description": "@kindgi/sdk — the authoring SDK for Kindgi™. Facade over the individual @kindgi/* packages + @kindgi/client. Unifies pack authoring (defineTool / defineCheck / defineAgent / defineFlow) and client callsites (createClient) behind three sub-paths: /define, /client, /types. Re-export facade; zero behavior.",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -55,15 +55,15 @@
55
55
  "README.md"
56
56
  ],
57
57
  "dependencies": {
58
- "@kindgi/agents": "0.1.4",
59
- "@kindgi/client": "0.1.4",
60
- "@kindgi/crypto": "0.1.4",
61
- "@kindgi/flow": "0.1.4",
62
- "@kindgi/guardrails": "0.1.4",
63
- "@kindgi/handler-runtime": "0.1.4",
64
- "@kindgi/schema": "0.1.4",
65
- "@kindgi/tools": "0.1.4",
66
- "@kindgi/types": "0.1.4"
58
+ "@kindgi/agents": "0.1.5",
59
+ "@kindgi/client": "0.1.5",
60
+ "@kindgi/crypto": "0.1.5",
61
+ "@kindgi/flow": "0.1.5",
62
+ "@kindgi/guardrails": "0.1.5",
63
+ "@kindgi/handler-runtime": "0.1.5",
64
+ "@kindgi/schema": "0.1.5",
65
+ "@kindgi/tools": "0.1.5",
66
+ "@kindgi/types": "0.1.5"
67
67
  },
68
68
  "peerDependencies": {
69
69
  "zod": "^4.0.0"
@@ -12,7 +12,7 @@ description: >
12
12
  kindgi-authoring-guardrails.
13
13
  type: core
14
14
  library: "@kindgi/sdk"
15
- version: "0.4.4"
15
+ version: "0.4.5"
16
16
  sdk_version: "0.0.0"
17
17
  pack_languages: [node]
18
18
  sources:
@@ -160,6 +160,34 @@ export default defined.value;
160
160
  retries the turn fails as before, with `toolRetries` on the error. A
161
161
  tenant's `tool-errors` policy can lower these (fewer retries, fewer
162
162
  kinds), never raise them.
163
+ - **`retrieval`** — what the agent reads from memory before each turn.
164
+ Empty = no memory. Each intent is
165
+ `{ types: ['acme.preference'], scope, mode?, limit? }`, with `scope`
166
+ one of `'same-user'`, `'same-conversation'`, `'same-project'`,
167
+ `'tenant'` (always within what the run may see), and `mode` absent
168
+ (newest first), `'keyword'`, `'semantic'` or `'both'`. Retrieved facts
169
+ reach the model as data in a `<memory>` block, never as instructions.
170
+ `semantic`/`both` need embeddings on the runtime
171
+ (`KINDGI_MEMORY_EMBEDDINGS`): without them a `semantic` intent fails
172
+ the turn (`semantic-unavailable`). `{ source: 'conversations', scope:
173
+ 'same-user' }` recalls this agent's earlier conversations: the people's
174
+ own words only, unless `roles: ['user', 'agent']` (its own earlier
175
+ answers come back marked unverified). `same-segment`/`same-project`
176
+ recall other people's conversations, and publishing warns.
177
+ `same-user` memory (facts, recall or `remember`) is the run's end user's:
178
+ pass `participantId` on every run. A run without one reads and keeps
179
+ none (its result warns `memory-needs-participant`), never the memory of
180
+ the user a key acts for, who may serve many people.
181
+ - **`memory`** — `{ remember: { types, scope, keepDays? } }` gives the
182
+ turn the built-in tool `kindgi_remember` (name it exactly so in the
183
+ instructions; built-ins have no dots). The model picks the type, the
184
+ text, an optional `key` and an expiry; never the scope. A fact wider
185
+ than one person, or text that reads like an instruction, waits for a
186
+ person's approval. Remembering is a tool call, so use a model with
187
+ reliable tool calling. `{ instructionTypes: ['acme.policy'] }` turns a
188
+ retrieved, verified fact of those types into an instruction
189
+ ("Policies (verified)"). See
190
+ https://docs.kindgi.com/v0.1/guides/agents/give-an-agent-memory/.
163
191
 
164
192
  ## What a turn receives
165
193
 
@@ -15,7 +15,7 @@ description: >
15
15
  kindgi-authoring-agents.
16
16
  type: core
17
17
  library: "@kindgi/sdk"
18
- version: "0.3.6"
18
+ version: "0.3.8"
19
19
  sdk_version: "0.0.0"
20
20
  pack_languages: [node]
21
21
  sources:
@@ -55,7 +55,11 @@ before the response is stored.
55
55
  - **Built-in checks** (`BUILT_IN_CHECK_IDS` in `@kindgi/guardrails`):
56
56
  `must-cite`, `never-call-tool`, `max-tool-calls`, `output-matches`,
57
57
  `tool-order`, `required-substring`, `forbidden-substring`. A guardrail
58
- can name one of these instead of shipping its own check.
58
+ can name one of these (`check: 'forbidden-substring'`) instead of
59
+ shipping its own check, and the runtime runs the built-in. Their ids
60
+ are reserved: a pack that ships its own check under one is refused
61
+ (`reserved-check-id`), so name yours `<pack>.checks.<name>`. See
62
+ "Using a built-in check" below for each one's `config`.
59
63
 
60
64
  `@kindgi/sdk` exports `defineCheck` but no helper for the guardrail
61
65
  itself: a pack file default-exports the declaration as a plain object.
@@ -119,6 +123,46 @@ How the pack tooling reads this file:
119
123
  declares no config gets them all), and a config that doesn't fit
120
124
  refused, naming where.
121
125
 
126
+ ## Using a built-in check
127
+
128
+ Name the built-in as the guardrail's `check`, give its `config`, and ship
129
+ no check implementation:
130
+
131
+ ```ts
132
+ // guardrails/no-guarantees/index.ts
133
+ export default {
134
+ id: 'acme.no-guarantees',
135
+ name: 'Never promise a guarantee',
136
+ kind: 'zero-llm',
137
+ check: 'forbidden-substring',
138
+ config: { patterns: ['guaranteed', 'we promise'] },
139
+ action: { 'on-violation': 'halt' },
140
+ severity: 'error',
141
+ };
142
+ ```
143
+
144
+ Each built-in's `config` (tool lists hold tool ids, as in
145
+ `acme.fetch-precedent`; a setting without `?` is required):
146
+
147
+ | Check | Fails when | `config` |
148
+ | --- | --- | --- |
149
+ | `must-cite` | the answer is empty, or has fewer than `minCitations` matches of `sourcePattern` | `minCitations?: integer ≥ 1` (1), `sourcePattern?: string` (a regex; `[…]`-style citations by default) |
150
+ | `never-call-tool` | the turn called any tool in `tools` | `tools: (string \| { id, version? })[]`, one or more |
151
+ | `max-tool-calls` | the turn made more than `max` tool calls | `max?: integer ≥ 0` (10) |
152
+ | `output-matches` | the answer doesn't match `pattern` (with `negate: true`, it does) | `pattern: string` (a regex), `flags?: string` (letters `dgimsuyv`), `negate?: boolean` |
153
+ | `tool-order` | the tools in `sequence` weren't called in that order (others may come between) | `sequence: string[]`, one or more |
154
+ | `required-substring` | the answer is empty, or lacks any of `patterns` | `patterns: string[]`, one or more non-empty (plain text), `caseSensitive?: boolean` (false) |
155
+ | `forbidden-substring` | the answer contains any of `patterns` | `patterns: string[]`, one or more non-empty (plain text), `caseSensitive?: boolean` (false) |
156
+
157
+ A config the check doesn't take is refused: a required setting left out,
158
+ the wrong type, a setting the check doesn't know, or a regex that doesn't
159
+ compile. Registering it answers `422 guardrail-config-invalid` (each
160
+ problem in `details.issues`); deploying a pack with one fails with
161
+ `deployment-validation-failed`; one that still reaches a turn is a check
162
+ that can't run (`invalid-check-config`), so a `halt` guardrail stops the
163
+ turn. Each built-in's JSON Schema is its registered check's
164
+ `configSchema`.
165
+
122
166
  ## Validating a declaration in-process
123
167
 
124
168
  `defineGuardrail(spec, checks)` from `@kindgi/guardrails` validates a
@@ -17,9 +17,9 @@ description: >
17
17
  `kindgi secrets set` flow.
18
18
  type: core
19
19
  library: "@kindgi/sdk"
20
- version: "0.3.0"
20
+ version: "0.3.2"
21
21
  sdk_version: "0.0.0"
22
- pack_languages: [node, python]
22
+ pack_languages: [node, python, java, scala]
23
23
  ---
24
24
 
25
25
  # Wiring an MCP server for a Kindgi pack
@@ -28,7 +28,8 @@ pack_languages: [node, python]
28
28
  > (`@kindgi/cli`), not a global command. Run it through the project's
29
29
  > package manager — `pnpm exec kindgi …`, `npx --no kindgi …` (npm),
30
30
  > `yarn kindgi …` or `bun run kindgi …`. A Python pack (`[tool.kindgi]` in
31
- > `pyproject.toml`) has no Node project: run the `kindgi` on `PATH`.
31
+ > `pyproject.toml`) has no Node project: run the `kindgi` on `PATH`. A Java
32
+ > or Scala pack (`kindgi.config.json`) runs the CLI it pins: `./kindgiw …`.
32
33
  > Commands below are written `kindgi …` for brevity.
33
34
 
34
35
  If the user has an external resource (Postgres DB, GitHub org, Notion
@@ -89,7 +90,8 @@ Three moving parts:
89
90
  (`"command": "pnpm", "args": ["exec", "kindgi", "mcp-launch", …]`;
90
91
  npm: `npx --no kindgi …`) — never a global `kindgi`, never a
91
92
  download. A Python pack has no Node project, so its entries run the
92
- `kindgi` on `PATH` (`"command": "kindgi", "args": ["mcp-launch", …]`).
93
+ `kindgi` on `PATH` (`"command": "kindgi", "args": ["mcp-launch", …]`). A
94
+ Java or Scala pack's run the CLI it pins (`"command": "./kindgiw"`).
93
95
  The file is safe to commit — it references secrets by NAME, not
94
96
  value.
95
97
  3. **The launcher** — `kindgi mcp-launch` is what the coding agent
@@ -23,9 +23,9 @@ description: >
23
23
  kindgi-getting-started.
24
24
  type: core
25
25
  library: "@kindgi/sdk"
26
- version: "0.9.8"
26
+ version: "0.9.11"
27
27
  sdk_version: "0.0.0"
28
- pack_languages: [node, python]
28
+ pack_languages: [node, python, java, scala]
29
29
  sources:
30
30
  - packages/adapters/model-anthropic/src/provider.ts
31
31
  - packages/adapters/model-gemini/src/provider.ts
@@ -41,7 +41,8 @@ sources:
41
41
  > (`@kindgi/cli`), not a global command. Run it through the project's
42
42
  > package manager — `pnpm exec kindgi …`, `npx --no kindgi …` (npm),
43
43
  > `yarn kindgi …` or `bun run kindgi …`. A Python pack (`[tool.kindgi]` in
44
- > `pyproject.toml`) has no Node project: run the `kindgi` on `PATH`.
44
+ > `pyproject.toml`) has no Node project: run the `kindgi` on `PATH`. A Java
45
+ > or Scala pack (`kindgi.config.json`) runs the CLI it pins: `./kindgiw …`.
45
46
  > Commands below are written `kindgi …` for brevity.
46
47
 
47
48
  An **agent** is a versioned declaration; it needs a **provider** to run.
@@ -76,8 +77,9 @@ Three moving parts:
76
77
  1. **API key on disk** — in `kindgi dev` (environment `local`) the dotenv
77
78
  secret binding reads the project's own env files: `.env`, then
78
79
  `.env.local` on top (change the list with `dev.envFiles` in
79
- `kindgi.config.ts`, or `envFiles` under `[tool.kindgi.dev]` in a Python
80
- pack's `pyproject.toml`). A key already in the app's `.env` just works.
80
+ `kindgi.config.ts`, `envFiles` under `[tool.kindgi.dev]` in a Python
81
+ pack's `pyproject.toml`, or `dev.envFiles` in a Java or Scala pack's
82
+ `kindgi.config.json`). A key already in the app's `.env` just works.
81
83
  `kindgi secrets set` (interactive, no-echo) writes `.env.local`. For
82
84
  non-sensitive values (log levels, region names, feature flags),
83
85
  `kindgi env set NAME VALUE --env=local` writes the same file with a
@@ -131,8 +133,9 @@ credential on argv.
131
133
  kindgi providers register --preset=anthropic # Opus 5.5, Sonnet 5.5 (default), Haiku 5.5, Haiku 4.5
132
134
  kindgi providers register --preset=anthropic --models=claude-sonnet-5-5 # just one
133
135
  ```
134
- Don't pin `claude-haiku-4-5`: Anthropic retires it on or after 2026-10-15,
135
- and a turn routed to it then fails; `claude-haiku-5-5` replaces it. Each
136
+ Before pinning a Claude model, check its status on Anthropic's model
137
+ deprecations page (https://platform.claude.com/docs/en/about-claude/model-deprecations): a turn routed to a retired model fails. Prefer the
138
+ preset's default. Each
136
139
  preset names a default model (`metadata.defaultModel`, marked `(default)`
137
140
  when it registers), which an agent with no preference gets. A preset
138
141
  registered before 0.1.4 has none: unregister it and register it again.
@@ -164,12 +167,15 @@ providers: [
164
167
  preset = "anthropic"
165
168
  models = ["claude-sonnet-5-5"]
166
169
  ```
170
+ In a Java or Scala pack's `kindgi.config.json`, the same keys:
171
+ `"providers": [{"preset": "anthropic", "models": ["claude-sonnet-5-5"]}]`.
167
172
  - A preset entry takes `models`, `project`, `secret` (the key's name, in place
168
- of the preset's) and `maxOutputTokens`, spelled the same in `pyproject.toml`;
173
+ of the preset's) and `maxOutputTokens`, spelled the same in `pyproject.toml`
174
+ and `kindgi.config.json`;
169
175
  a `spec` entry is a `--spec` body. A
170
176
  key is always a secret's name (`secret_ref`); a credential in
171
177
  `adapter_config` is refused.
172
- - Each boot prints `Providers from kindgi.config.ts:` with one line each:
178
+ - Each boot prints `Providers from kindgi.config.ts:` (the pack's config file) with one line each:
173
179
  `registered`, `unchanged`, `registered again (changed in kindgi.config.ts)`,
174
180
  `unregistered (no longer in kindgi.config.ts)`, or ⚠ `not registered: <KEY>
175
181
  is not in .env, .env.local` (set the key, then restart: the config isn't
@@ -535,7 +541,8 @@ Or skip step 2: `kindgi providers register --preset=gemini --project=<your-gcp-p
535
541
  registers both models above.
536
542
  Then pin it from an agent with `preferredProvider: 'gemini'` (and a model
537
543
  with `preferredModel`; in Python, `preferred_provider="gemini"` and
538
- `preferred_model=…`), or let the router pick by capability.
544
+ `preferred_model=…`; in Java, `.set("preferredProvider", "gemini")`), or let
545
+ the router pick by capability.
539
546
 
540
547
  ## How the router picks between multiple providers + models
541
548
 
@@ -550,7 +557,8 @@ tenant policy), then sorts survivors in this order:
550
557
  - Only `preferredModel` set → promote any provider exposing that model.
551
558
  - Only `preferredProvider` set → promote every model of that provider.
552
559
  `defineAgent` takes both (`preferredProvider`, `preferredModel`), and
553
- so does a Python `Agent` (`preferred_provider=`, `preferred_model=`).
560
+ so does a Python `Agent` (`preferred_provider=`, `preferred_model=`) and
561
+ a Java `Agent.define(…)` (`set("preferredProvider", …)`).
554
562
  2. **`capability.prefer[]` weights.** If the agent's capability
555
563
  declares `prefer: [{feature: 'thinking', weight: 3}, ...]`, tuples
556
564
  with matching model features (or provider attributes) get higher
@@ -649,7 +657,8 @@ defineAgent({
649
657
  be the FULL npm package name of the adapter — `"@kindgi/adapter-model-anthropic"`,
650
658
  NOT `"anthropic"`. Adapters are registered with the runtime under
651
659
  their full package names, and a short name matches none of them, so
652
- the registration fails. The model adapters are
660
+ registering is refused: the runtime has no adapter by that name
661
+ (`✗ /adapter_id: …`). The model adapters are
653
662
  `@kindgi/adapter-model-anthropic`, `@kindgi/adapter-model-gemini`,
654
663
  `@kindgi/adapter-model-openai-compat` and
655
664
  `@kindgi/adapter-model-in-process`; `kindgi providers presets` shows
@@ -686,8 +695,9 @@ defineAgent({
686
695
  Then re-register.
687
696
 
688
697
  6. **Key not found by the runtime.** `kindgi dev` reads the env files
689
- at the PACK ROOT (the directory with `kindgi.config.ts`, or a Python
690
- pack's `pyproject.toml` with `[tool.kindgi]`) — `.env` and
698
+ at the PACK ROOT (the directory with `kindgi.config.ts`, a Python
699
+ pack's `pyproject.toml` with `[tool.kindgi]`, or a Java or Scala pack's
700
+ `kindgi.config.json`) — `.env` and
691
701
  `.env.local`, or whatever `dev.envFiles` lists; the boot log prints
692
702
  which files it found. A `KINDGI_`-prefixed name is Kindgi runtime
693
703
  config and never resolves as a secret. Outside `kindgi dev`, the
@@ -716,6 +726,21 @@ defineAgent({
716
726
  that names nothing registered, and the tenant's policy. `kindgi
717
727
  providers list` shows what is registered.
718
728
 
729
+ 10. **A setting the adapter can't use.** Registering checks the spec
730
+ against its adapter (no network call, no key read) and refuses what
731
+ it can't use: `422 provider-config-invalid`, nothing stored, one line
732
+ per problem with its JSON-pointer path:
733
+ ```text
734
+ Error [invalid-request]: Provider "ollama" doesn't fit adapter @kindgi/adapter-model-openai-compat: adapter_config.api must be one of responses, chat-completions.
735
+ ✗ /adapter_config/api: adapter_config.api must be one of responses, chat-completions.
736
+ ```
737
+ Fix each `✗` line's setting and register again. A key the adapter
738
+ needs is checked too (`✗ /secret_ref: …`); whether the key works, or
739
+ the endpoint answers, isn't (the first turn finds out). A
740
+ registration stored before 0.1.5 wasn't checked: `kindgi doctor`
741
+ names its problems (`GET /v1/providers/<id>/check`); unregister it
742
+ and register it again.
743
+
719
744
  ## Verifying end-to-end
720
745
 
721
746
  ```sh
@@ -12,7 +12,7 @@ description: >
12
12
  authoring agents is covered by kindgi-authoring-agents.
13
13
  type: core
14
14
  library: "@kindgi/sdk"
15
- version: "0.4.4"
15
+ version: "0.4.5"
16
16
  sdk_version: "0.0.0"
17
17
  pack_languages: [node]
18
18
  sources:
@@ -115,6 +115,16 @@ The handler gets the **parsed** input, typed `z.infer` of `input` (Zod's output
115
115
 
116
116
  The output side is the reverse: the advertised output schema requires every field, defaulted ones included. Return them all.
117
117
 
118
+ ### Logging from the handler
119
+
120
+ `ctx.log` is a logger bound to the call: its records carry the run's ids, the tool's id and the trace id. It has `info`, `warn`, `error`, `debug` and `trace`, each `(message, fields?)`. The pack service sets it; a context your own code builds (a test's) may not, so write `ctx.log?.`:
121
+
122
+ ```ts
123
+ ctx.log?.info('refund issued', { orderId, amountCents });
124
+ ```
125
+
126
+ Put values in `fields`, never in the message. Log ids, amounts and outcomes, never what a person typed (a refund's reason, a message, an address): the log is read by whoever operates the runtime, not only by the person the data is about. Docs: https://docs.kindgi.com/v0.1/guides/tools/write-a-tool/#log-from-a-tool
127
+
118
128
  ### Configuration and secrets
119
129
 
120
130
  A secret that belongs to the tenant — an API key a customer gives you — is declared, and read from `ctx.secrets`:
@@ -132,6 +142,32 @@ const defined = defineTool({
132
142
 
133
143
  The runtime resolves every declared secret on every call, for the call's tenant, in its env (`KINDGI_ENV`; in `kindgi dev`, `local`: the pack's `.env` and `.env.local`). It checks each value against its schema, and fails the call, naming the secret, when one is missing or doesn't match. Every declared secret is required, so in a runtime call `ctx.secrets` holds them all; it's optional in the type because a unit test builds its own context and passes `secrets: { CITATOR_KEY: '…' }`.
134
144
 
145
+ A value that differs per tenant, org or project but isn't secret (a base URL, a region, an account id) is an **env value**: declared in `needsSpec.env`, read from `ctx.env`:
146
+
147
+ ```ts
148
+ const defined = defineTool({
149
+ // …id, description, version, input, output, effects…
150
+ needsSpec: {
151
+ env: {
152
+ ORDERS_BASE_URL: { type: 'string', pattern: '^https://' },
153
+ ORDERS_REGION: { type: 'string', enum: ['eu', 'us'], default: 'eu' },
154
+ },
155
+ },
156
+ handler: async ({ orderId }, ctx) => ({
157
+ url: `${ctx.env?.ORDERS_BASE_URL}/${ctx.env?.ORDERS_REGION}/orders/${orderId}`,
158
+ }),
159
+ });
160
+ ```
161
+
162
+ - **Which value a call gets:** its project's, else its org's, else the tenant's, in the runtime's env; a schema `default` makes a name optional. The values a call used are recorded with it, so a retry or a resume sees the same ones.
163
+ - **Setting them:** `kindgi env set ORDERS_REGION us --scope=project:<project-id> --env=local` (or `--scope=tenant`, for every project). Changing a value that's already set takes `--force`.
164
+ - **A declared value nobody set** stops the call before the tool runs. For a tool `acme-orders.needs-account` that declares `ACME_ACCOUNT_ID`, the message reads:
165
+ ```text
166
+ precondition-failed: Tool "acme-orders.needs-account" was not run: env-value-missing: tool "acme-orders.needs-account" needs env value "ACME_ACCOUNT_ID" in env "local", and none is set for project e889c1f5-eae7-45dc-8669-5bd029a5d85c, its org, or the tenant. Set it: kindgi env set ACME_ACCOUNT_ID <value> --scope=project:e889c1f5-eae7-45dc-8669-5bd029a5d85c --env=local (or --scope=tenant, for every project)
167
+ ```
168
+ - **Not secret:** env values are recorded with each run that uses them and shown in its journal. A credential is a secret (`needsSpec.secrets`), never an env value.
169
+ - **In a unit test:** pass `env: { … }` in the context `invokeTool` gets.
170
+
135
171
  Everything else comes from the process environment: `process.env.CITATOR_URL`. The pack service runs with the pack's env files in `kindgi dev`, and with the container's environment in an image. Declare the names your code reads in `kindgi.config.ts`, `env: { required: ['CITATOR_URL'], optional: [...] }`: a deployment injects exactly those, a pack service missing a required one isn't ready and says which, and `kindgi dev` warns about it. Values per environment go in `environments.<name>.env`, secrets only as references.
136
172
 
137
173
  ## Declarative HTTP spec
@@ -176,6 +212,15 @@ export default defined.value;
176
212
 
177
213
  So declare `mutating: false` on every tool that only reads, and never on one that writes.
178
214
 
215
+ A tool that writes also says what it writes, in `effects`, beside `mutating: true`:
216
+
217
+ ```ts
218
+ effects: [{ kind: 'writes', resource: 'acme:refunds' }],
219
+ mutating: true,
220
+ ```
221
+
222
+ The kinds are `reads`, `writes`, `deletes`, `network`, `spawns-run`, `emits-event`, `external-side-effect` and `sensitive-data-egress` (`EFFECT_KINDS` in `@kindgi/tools`); `defineTool` refuses any other. `resource` is free text naming what the tool touches. A read-only tool keeps `effects: []`.
223
+
179
224
  ## Tool id convention
180
225
 
181
226
  `<pack-id>.<tool-name>` — kebab-case, dot-namespaced. The `<pack-id>`
@@ -210,6 +255,25 @@ range at run start. Compatible tool updates (patch, minor) reach the
210
255
  agent without editing agent source; breaking updates (major) require
211
256
  the agent-author to opt in.
212
257
 
258
+ ## Testing a tool
259
+
260
+ Put a tool's tests beside it, `tools/<tool>/index.test.ts`. Discovery skips `*.test.*` and `*.spec.*` files (`.ts`, `.js`, `.mjs`, `.cjs`), so the indexer never loads a test as a primitive: don't move tests elsewhere to keep them out. `invokeTool(tool, input, ctx)` from `@kindgi/sdk/define` calls the tool the way Kindgi does, schemas included, and returns a `Result`. Its `ctx` needs a `tenantId` and an `abortSignal` (`ToolContext` in `@kindgi/tools`); the rest is optional. vitest doesn't typecheck, so a context missing them still passes the test: run `tsc --noEmit` too.
261
+
262
+ ```ts
263
+ import { invokeTool } from '@kindgi/sdk/define';
264
+ import type { TenantId } from '@kindgi/sdk/types';
265
+
266
+ const ctx = { tenantId: 'test' as TenantId, abortSignal: new AbortController().signal };
267
+ // add `env: { STORE_URL: '…' }` for a tool that reads a declared env value
268
+ const result = await invokeTool(lookupOrder, { orderId: 'ord_1001' }, ctx);
269
+ ```
270
+
271
+ `kindgi test` runs the pack's tests with vitest (`vitest run`; `--watch` keeps watching).
272
+
273
+ ## Shared code
274
+
275
+ Code several tools share (schemas, a client, helpers) goes outside `tools/`, for example in `lib/` beside it. Discovery loads every `.ts`, `.js` and `.mjs` file under `tools/` (tests aside) as a primitive, so a helper there fails the index. Don't put it in the app's own source either: import the app's functions from where they are, and keep what's Kindgi's in the pack's folder.
276
+
213
277
  ## Wiring the tool onto an agent
214
278
 
215
279
  Agents reference tools via `ToolRef[]`, NOT `string[]`. Each entry is
@@ -14,9 +14,9 @@ description: >
14
14
  diagnostic output into durable input for framework improvement.
15
15
  type: core
16
16
  library: "@kindgi/sdk"
17
- version: "0.4.0"
17
+ version: "0.4.2"
18
18
  sdk_version: "0.0.0"
19
- pack_languages: [node, python]
19
+ pack_languages: [node, python, java, scala]
20
20
  ---
21
21
 
22
22
  # Capturing framework feedback
@@ -25,7 +25,8 @@ pack_languages: [node, python]
25
25
  > (`@kindgi/cli`), not a global command. Run it through the project's
26
26
  > package manager — `pnpm exec kindgi …`, `npx --no kindgi …` (npm),
27
27
  > `yarn kindgi …` or `bun run kindgi …`. A Python pack (`[tool.kindgi]` in
28
- > `pyproject.toml`) has no Node project: run the `kindgi` on `PATH`.
28
+ > `pyproject.toml`) has no Node project: run the `kindgi` on `PATH`. A Java
29
+ > or Scala pack (`kindgi.config.json`) runs the CLI it pins: `./kindgiw …`.
29
30
  > Commands below are written `kindgi …` for brevity.
30
31
 
31
32
  You just spent time diagnosing a Kindgi-framework issue. That diagnostic