@kindgi/sdk 0.1.5-rc.0 → 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';
@@ -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,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"}
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,7 +50,34 @@ 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';
@@ -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,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"}
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.5-rc.0",
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.5-rc.0",
59
- "@kindgi/client": "0.1.5-rc.0",
60
- "@kindgi/crypto": "0.1.5-rc.0",
61
- "@kindgi/flow": "0.1.5-rc.0",
62
- "@kindgi/guardrails": "0.1.5-rc.0",
63
- "@kindgi/handler-runtime": "0.1.5-rc.0",
64
- "@kindgi/schema": "0.1.5-rc.0",
65
- "@kindgi/tools": "0.1.5-rc.0",
66
- "@kindgi/types": "0.1.5-rc.0"
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"
@@ -174,6 +174,10 @@ export default defined.value;
174
174
  own words only, unless `roles: ['user', 'agent']` (its own earlier
175
175
  answers come back marked unverified). `same-segment`/`same-project`
176
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.
177
181
  - **`memory`** — `{ remember: { types, scope, keepDays? } }` gives the
178
182
  turn the built-in tool `kindgi_remember` (name it exactly so in the
179
183
  instructions; built-ins have no dots). The model picks the type, the
@@ -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`:
@@ -202,6 +212,15 @@ export default defined.value;
202
212
 
203
213
  So declare `mutating: false` on every tool that only reads, and never on one that writes.
204
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
+
205
224
  ## Tool id convention
206
225
 
207
226
  `<pack-id>.<tool-name>` — kebab-case, dot-namespaced. The `<pack-id>`
@@ -236,6 +255,25 @@ range at run start. Compatible tool updates (patch, minor) reach the
236
255
  agent without editing agent source; breaking updates (major) require
237
256
  the agent-author to opt in.
238
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
+
239
277
  ## Wiring the tool onto an agent
240
278
 
241
279
  Agents reference tools via `ToolRef[]`, NOT `string[]`. Each entry is
@@ -169,6 +169,10 @@ brief_writer = Agent(
169
169
  fails the turn (`semantic-unavailable`). `{"source": "conversations",
170
170
  "scope": "same-user"}` recalls this agent's earlier conversations: the
171
171
  people's own words only, unless `"roles": ["user", "agent"]`.
172
+ `same-user` memory (facts, recall or `remember`) is the run's end user's:
173
+ pass `participantId` on every run. A run without one reads and keeps
174
+ none (its result warns `memory-needs-participant`), never the memory of
175
+ the user a key acts for, who may serve many people.
172
176
  - **`memory`** — `{"remember": {"types": ["acme.preference"], "scope":
173
177
  "same-user", "keepDays": 30}}` gives the turn the built-in tool
174
178
  `kindgi_remember` (name it exactly so in the instructions). The model
@@ -14,7 +14,7 @@ description: >
14
14
  kindgi-python-getting-started.
15
15
  type: core
16
16
  library: "kindgi (Python)"
17
- version: "0.1.2"
17
+ version: "0.1.3"
18
18
  sdk_version: "0.0.0"
19
19
  pack_languages: [python]
20
20
  sources:
@@ -121,6 +121,14 @@ def verify_citation(citation: Citation, ctx: ToolContext) -> Verdict:
121
121
  (`kindgi env set NAME <value> --scope=project:<id> --env=<env>`).
122
122
  Strings, and not secret. Empty from an older runtime.
123
123
  - `ctx.config` — **reserved, empty today**.
124
+ - `ctx.log` — a logger bound to the call (its records carry the run's ids,
125
+ the tool's id and the trace id): `ctx.log.info("refund issued",
126
+ {"orderId": order_id, "amountCents": amount_cents})`, or the fields as
127
+ keywords. Values go in the fields, never in the message. Log ids,
128
+ amounts and outcomes, never what a person typed (a refund's reason, a
129
+ message, an address): the log is read by whoever operates the runtime.
130
+ `ToolContext.for_test(…)` logs nothing unless you pass it `log=`. Docs:
131
+ https://docs.kindgi.com/v0.1/guides/tools/write-a-tool/#log-from-a-tool
124
132
 
125
133
  ## Configuration and secrets
126
134
 
package/src/client.ts CHANGED
@@ -43,6 +43,12 @@ export type { KindgiClient } from '@kindgi/client';
43
43
  * browser, pass `apiUrl` and `auth`. `@kindgi/client`'s `createClient` is
44
44
  * the explicit form underneath.
45
45
  *
46
+ * The options are found on first use, not here: a module-scope
47
+ * `const kindgi = createClient()` is safe to import where the runtime's
48
+ * settings aren't set, as a production build (`next build`) imports every
49
+ * module. When they're missing, the first use (`kindgi.runs`, …) throws
50
+ * the error that says what to set; once they're set, the next use works.
51
+ *
46
52
  * @example
47
53
  * ```ts
48
54
  * import { createClient } from '@kindgi/sdk/client';
@@ -51,7 +57,34 @@ export type { KindgiClient } from '@kindgi/client';
51
57
  * ```
52
58
  */
53
59
  export function createClient(options: Partial<ClientOptions> = {}): KindgiClient {
54
- return createKindgiClient(resolveClientOptions(options));
60
+ let client: KindgiClient | undefined;
61
+ // A failed lookup isn't kept: the env may be set by the next use.
62
+ const resolved = (): KindgiClient => {
63
+ client ??= createKindgiClient(resolveClientOptions(options));
64
+ return client;
65
+ };
66
+ return new Proxy({} as KindgiClient, {
67
+ get(_target, key) {
68
+ // Never resolve to answer whether the client is a promise (`await`,
69
+ // `return` from an async function), or for a symbol a tool inspects.
70
+ if (client === undefined && (key === 'then' || typeof key === 'symbol')) return undefined;
71
+ return Reflect.get(resolved(), key);
72
+ },
73
+ // A write (a test swapping a resource) is a use: it lands on the client.
74
+ // A property defined non-configurable (`defineProperty`'s default) throws:
75
+ // a proxy can't hold one its target doesn't. Define it `configurable: true`.
76
+ set: (_target, key, value) => Reflect.set(resolved(), key, value),
77
+ defineProperty: (_target, key, descriptor) =>
78
+ Reflect.defineProperty(resolved(), key, descriptor),
79
+ deleteProperty: (_target, key) => Reflect.deleteProperty(resolved(), key),
80
+ has: (_target, key) => key in resolved(),
81
+ ownKeys: () => Reflect.ownKeys(resolved()),
82
+ getOwnPropertyDescriptor(_target, key) {
83
+ const descriptor = Reflect.getOwnPropertyDescriptor(resolved(), key);
84
+ // The target holds none of the client's fields, so none may be reported fixed.
85
+ return descriptor === undefined ? undefined : { ...descriptor, configurable: true };
86
+ },
87
+ });
55
88
  }
56
89
 
57
90
  // ---- Resource client types + per-resource input shapes ----