@pikku/inspector 0.12.59 → 0.12.61

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 (132) hide show
  1. package/CHANGELOG.md +373 -0
  2. package/OPTIMIZATION-PLAN.md +19 -19
  3. package/dist/add/add-agent-scorer.d.ts +2 -0
  4. package/dist/add/{add-ai-scorer.js → add-agent-scorer.js} +4 -4
  5. package/dist/add/{add-ai-agent.d.ts → add-agent.d.ts} +1 -1
  6. package/dist/add/{add-ai-agent.js → add-agent.js} +11 -11
  7. package/dist/add/add-auth.js +1 -1
  8. package/dist/add/add-cli.js +5 -0
  9. package/dist/add/add-functions.js +10 -1
  10. package/dist/add/add-http-route.js +18 -18
  11. package/dist/add/add-keyed-wiring.d.ts +2 -0
  12. package/dist/add/add-keyed-wiring.js +3 -1
  13. package/dist/add/add-middleware.js +5 -5
  14. package/dist/add/add-personas.js +3 -0
  15. package/dist/add/add-secret.js +1 -0
  16. package/dist/add/add-variable.js +1 -0
  17. package/dist/add/add-wire-remote-addon.js +2 -1
  18. package/dist/add/add-workflow-graph.js +63 -6
  19. package/dist/error-codes.d.ts +3 -1
  20. package/dist/error-codes.js +3 -1
  21. package/dist/index.d.ts +3 -1
  22. package/dist/index.js +1 -0
  23. package/dist/inspector.js +13 -3
  24. package/dist/types.d.ts +10 -5
  25. package/dist/utils/annotate-http-route-auth.js +2 -1
  26. package/dist/utils/check-secret-sinks.js +2 -1
  27. package/dist/utils/compute-required-schemas.d.ts +1 -1
  28. package/dist/utils/contract-hashes.d.ts +2 -1
  29. package/dist/utils/contract-hashes.js +1 -1
  30. package/dist/utils/extract-function-name.js +1 -1
  31. package/dist/utils/extract-services.d.ts +1 -1
  32. package/dist/utils/extract-surface-usage.d.ts +29 -0
  33. package/dist/utils/extract-surface-usage.js +97 -0
  34. package/dist/utils/filter-inspector-state.js +53 -16
  35. package/dist/utils/filter-utils.d.ts +1 -1
  36. package/dist/utils/get-property-value.js +42 -3
  37. package/dist/utils/load-addon-functions-meta.js +31 -0
  38. package/dist/utils/middleware.d.ts +2 -2
  39. package/dist/utils/middleware.js +5 -5
  40. package/dist/utils/permissions.d.ts +1 -1
  41. package/dist/utils/post-process.d.ts +28 -8
  42. package/dist/utils/post-process.js +83 -18
  43. package/dist/utils/resolve-deploy-target.d.ts +1 -1
  44. package/dist/utils/resolve-function-meta.d.ts +1 -1
  45. package/dist/utils/resolve-function-types.d.ts +1 -1
  46. package/dist/utils/resolve-versions.js +1 -1
  47. package/dist/utils/schema-generator.d.ts +1 -1
  48. package/dist/utils/serialize-inspector-state.d.ts +4 -3
  49. package/dist/utils/serialize-inspector-state.js +6 -4
  50. package/dist/utils/serialize-openapi-json.d.ts +1 -1
  51. package/dist/utils/validate-auth-sessionless.js +2 -1
  52. package/dist/utils/workflow/graph/finalize-workflows.js +1 -1
  53. package/dist/utils/workflow/graph/serialize-workflow-graph.d.ts +6 -1
  54. package/dist/utils/workflow/graph/serialize-workflow-graph.js +26 -2
  55. package/dist/utils/workflow/graph/workflow-graph.types.d.ts +9 -0
  56. package/dist/visit.js +4 -4
  57. package/package.json +10 -10
  58. package/run-tests.sh +0 -0
  59. package/src/add/{add-ai-scorer.test.ts → add-agent-scorer.test.ts} +11 -11
  60. package/src/add/{add-ai-scorer.ts → add-agent-scorer.ts} +4 -4
  61. package/src/add/{add-ai-agent.test.ts → add-agent.test.ts} +1 -1
  62. package/src/add/{add-ai-agent.ts → add-agent.ts} +13 -21
  63. package/src/add/add-auth.ts +2 -2
  64. package/src/add/add-cli.ts +6 -0
  65. package/src/add/add-credential.ts +3 -6
  66. package/src/add/add-file-with-factory.ts +2 -6
  67. package/src/add/add-functions.ts +23 -25
  68. package/src/add/add-http-route-ref.test.ts +149 -0
  69. package/src/add/add-http-route.ts +25 -28
  70. package/src/add/add-keyed-wiring.ts +8 -7
  71. package/src/add/add-middleware.ts +7 -5
  72. package/src/add/add-permission.ts +1 -1
  73. package/src/add/add-personas.test.ts +24 -0
  74. package/src/add/add-personas.ts +3 -1
  75. package/src/add/add-scenario-step.test.ts +35 -0
  76. package/src/add/add-scope.test.ts +4 -4
  77. package/src/add/add-scope.ts +4 -8
  78. package/src/add/add-secret.ts +1 -0
  79. package/src/add/add-system-role.test.ts +8 -8
  80. package/src/add/add-system-role.ts +2 -4
  81. package/src/add/add-variable.ts +1 -0
  82. package/src/add/add-wire-remote-addon.ts +4 -1
  83. package/src/add/add-workflow-graph-foreach.test.ts +174 -0
  84. package/src/add/add-workflow-graph.ts +78 -6
  85. package/src/add/add-workflow-sleep-expression.test.ts +3 -4
  86. package/src/add/addon-contracts.test.ts +1 -1
  87. package/src/add/config-value-metadata.test.ts +94 -0
  88. package/src/add/secret-sink-check.test.ts +4 -1
  89. package/src/error-codes.ts +3 -1
  90. package/src/index.ts +3 -4
  91. package/src/inspector.ts +20 -3
  92. package/src/types.ts +10 -7
  93. package/src/utils/annotate-http-route-auth.test.ts +5 -7
  94. package/src/utils/annotate-http-route-auth.ts +2 -1
  95. package/src/utils/check-secret-sinks.ts +4 -1
  96. package/src/utils/compute-required-schemas.ts +1 -1
  97. package/src/utils/contract-hashes.test.ts +1 -1
  98. package/src/utils/contract-hashes.ts +3 -2
  99. package/src/utils/extract-function-name.ts +1 -1
  100. package/src/utils/extract-services.ts +4 -2
  101. package/src/utils/extract-surface-usage.test.ts +147 -0
  102. package/src/utils/extract-surface-usage.ts +121 -0
  103. package/src/utils/filter-inspector-state.test.ts +138 -12
  104. package/src/utils/filter-inspector-state.ts +82 -21
  105. package/src/utils/filter-utils.ts +1 -1
  106. package/src/utils/get-property-value.ts +43 -5
  107. package/src/utils/load-addon-functions-meta.ts +40 -0
  108. package/src/utils/middleware.test.ts +23 -23
  109. package/src/utils/middleware.ts +6 -6
  110. package/src/utils/permissions.ts +1 -1
  111. package/src/utils/post-process.test.ts +68 -11
  112. package/src/utils/post-process.ts +91 -28
  113. package/src/utils/resolve-deploy-target.ts +1 -1
  114. package/src/utils/resolve-function-meta.ts +1 -1
  115. package/src/utils/resolve-function-types.ts +1 -1
  116. package/src/utils/resolve-versions.ts +1 -1
  117. package/src/utils/schema-generator.ts +2 -1
  118. package/src/utils/serialize-inspector-state.ts +10 -7
  119. package/src/utils/serialize-mcp-json.ts +1 -1
  120. package/src/utils/serialize-openapi-json.ts +1 -1
  121. package/src/utils/validate-auth-sessionless.ts +2 -1
  122. package/src/utils/validate-tags-resolve-to-middleware.test.ts +4 -1
  123. package/src/utils/workflow/dsl/extract-approval-policy.test.ts +4 -1
  124. package/src/utils/workflow/graph/convert-dsl-to-graph-skip.test.ts +1 -1
  125. package/src/utils/workflow/graph/finalize-workflows.ts +6 -2
  126. package/src/utils/workflow/graph/serialize-workflow-graph.ts +34 -3
  127. package/src/utils/workflow/graph/workflow-graph.types.ts +10 -0
  128. package/src/visit.ts +4 -4
  129. package/tsconfig.tsbuildinfo +1 -1
  130. package/dist/add/add-ai-scorer.d.ts +0 -2
  131. package/dist/utils/secret-brokers.d.ts +0 -2
  132. package/dist/utils/secret-brokers.js +0 -9
@@ -1,5 +1,5 @@
1
1
  import type { SecretUsage } from './extract-secret-usage.js';
2
- import type { JSONValue } from '@pikku/core';
2
+ import type { JSONValue } from '@pikku/core/utils';
3
3
  import type { InspectorDiagnostic, InspectorFeature, InspectorState } from '../types.js';
4
4
  /**
5
5
  * Serializable version of InspectorState that can be saved to JSON
@@ -242,6 +242,7 @@ export interface SerializableInspectorState {
242
242
  files: string[];
243
243
  usage: Record<string, SecretUsage>;
244
244
  };
245
+ surfaceUsage: InspectorState['surfaceUsage'];
245
246
  credentials: {
246
247
  definitions: InspectorState['credentials']['definitions'];
247
248
  files: string[];
@@ -279,8 +280,8 @@ export interface SerializableInspectorState {
279
280
  InspectorState['channelMiddleware']['tagMiddleware'] extends Map<string, infer V> ? V : never
280
281
  ]>;
281
282
  };
282
- aiMiddleware: {
283
- definitions: InspectorState['aiMiddleware']['definitions'];
283
+ agentMiddleware: {
284
+ definitions: InspectorState['agentMiddleware']['definitions'];
284
285
  };
285
286
  permissions: {
286
287
  definitions: InspectorState['permissions']['definitions'];
@@ -118,6 +118,7 @@ export function serializeInspectorState(state) {
118
118
  files: Array.from(state.secrets.files),
119
119
  usage: Object.fromEntries(state.secrets.usage),
120
120
  },
121
+ surfaceUsage: state.surfaceUsage,
121
122
  credentials: {
122
123
  definitions: state.credentials.definitions,
123
124
  files: Array.from(state.credentials.files),
@@ -149,8 +150,8 @@ export function serializeInspectorState(state) {
149
150
  instances: state.channelMiddleware.instances,
150
151
  tagMiddleware: Array.from(state.channelMiddleware.tagMiddleware.entries()),
151
152
  },
152
- aiMiddleware: {
153
- definitions: state.aiMiddleware.definitions,
153
+ agentMiddleware: {
154
+ definitions: state.agentMiddleware.definitions,
154
155
  },
155
156
  permissions: {
156
157
  definitions: state.permissions.definitions,
@@ -295,6 +296,7 @@ export function deserializeInspectorState(data) {
295
296
  files: new Set(data.secrets?.files || []),
296
297
  usage: new Map(Object.entries(data.secrets?.usage || {})),
297
298
  },
299
+ surfaceUsage: data.surfaceUsage || {},
298
300
  credentials: {
299
301
  definitions: data.credentials?.definitions || [],
300
302
  files: new Set(data.credentials?.files || []),
@@ -326,8 +328,8 @@ export function deserializeInspectorState(data) {
326
328
  instances: data.channelMiddleware?.instances || {},
327
329
  tagMiddleware: new Map(data.channelMiddleware?.tagMiddleware || []),
328
330
  },
329
- aiMiddleware: {
330
- definitions: data.aiMiddleware?.definitions || {},
331
+ agentMiddleware: {
332
+ definitions: data.agentMiddleware?.definitions || {},
331
333
  },
332
334
  permissions: {
333
335
  definitions: data.permissions.definitions,
@@ -1,4 +1,4 @@
1
- import type { FunctionsMeta } from '@pikku/core';
1
+ import type { FunctionsMeta } from '@pikku/core/services';
2
2
  import type { HTTPWiringsMeta } from '@pikku/core/http';
3
3
  import type { InspectorLogger } from '../types.js';
4
4
  interface ErrorDetails {
@@ -1,7 +1,8 @@
1
1
  import { getPropertyValue } from './get-property-value.js';
2
2
  import { ErrorCode } from '../error-codes.js';
3
+ import { resolveFunctionMeta } from './resolve-function-meta.js';
3
4
  export function validateAuthSessionless(logger, obj, state, funcName, wireDescription, inheritedAuth) {
4
- const fnMeta = state.functions.meta[funcName];
5
+ const fnMeta = resolveFunctionMeta(state, funcName);
5
6
  if (!fnMeta)
6
7
  return true;
7
8
  const routeAuth = getPropertyValue(obj, 'auth');
@@ -1,4 +1,4 @@
1
- import { isVersionedId, formatVersionedId, parseVersionedId } from '@pikku/core';
1
+ import { isVersionedId, formatVersionedId, parseVersionedId, } from '@pikku/core/utils';
2
2
  import { canonicalJSON, hashString } from '../../hash.js';
3
3
  import { convertDslToGraph } from './convert-dsl-to-graph.js';
4
4
  import { deriveWorkflowPlan } from '../derive-workflow-plan.js';
@@ -11,7 +11,12 @@ export declare function serializeWorkflowGraph(definition: {
11
11
  func: {
12
12
  name?: string;
13
13
  };
14
- input?: (ref: any) => Record<string, unknown>;
14
+ input?: (ref: any, template?: any, $item?: any) => Record<string, unknown>;
15
+ forEach?: string | {
16
+ nodeId: string;
17
+ path?: string;
18
+ } | ((ref: any) => unknown);
19
+ mode?: 'parallel' | 'sequential';
15
20
  next?: string | string[] | Record<string, string | string[]>;
16
21
  onError?: string | string[];
17
22
  notes?: string;
@@ -1,4 +1,4 @@
1
- import { isRef } from '@pikku/core/workflow';
1
+ import { isRef, template } from '@pikku/core/workflow';
2
2
  /**
3
3
  * Convert a RefValue (from runtime) to DataRef (serialized)
4
4
  */
@@ -23,6 +23,22 @@ function serializeInputMapping(input) {
23
23
  }
24
24
  return result;
25
25
  }
26
+ /**
27
+ * Convert a `forEach` source — a bare node id, a ref, or a `(ref) => ref(...)`
28
+ * callback — to the serialized DataRef form
29
+ */
30
+ function serializeForEach(forEach, createRef) {
31
+ if (forEach === undefined)
32
+ return undefined;
33
+ if (typeof forEach === 'string')
34
+ return { $ref: forEach };
35
+ if (typeof forEach === 'function') {
36
+ return serializeForEach(forEach(createRef), createRef);
37
+ }
38
+ if (isRef(forEach))
39
+ return convertRef(forEach);
40
+ return undefined;
41
+ }
26
42
  /**
27
43
  * Convert next config from runtime format to serialized format
28
44
  * Runtime uses Record<string, string | string[]> for branching with graph.branch()
@@ -59,6 +75,7 @@ export function serializeWorkflowGraph(definition, options) {
59
75
  nodeId,
60
76
  path,
61
77
  });
78
+ const createItemRef = (path) => createRef('$item', path);
62
79
  // Track which nodes have incoming edges
63
80
  const hasIncomingEdge = new Set();
64
81
  // First pass: identify nodes with incoming edges
@@ -88,7 +105,7 @@ export function serializeWorkflowGraph(definition, options) {
88
105
  // Evaluate input callback to get the mapping
89
106
  let input = {};
90
107
  if (node.input) {
91
- const rawInput = node.input(createRef);
108
+ const rawInput = node.input(createRef, template, createItemRef);
92
109
  input = serializeInputMapping(rawInput);
93
110
  }
94
111
  // Get RPC name from func
@@ -100,6 +117,13 @@ export function serializeWorkflowGraph(definition, options) {
100
117
  next: serializeNext(node.next),
101
118
  onError: node.onError,
102
119
  };
120
+ const forEach = serializeForEach(node.forEach, createRef);
121
+ if (forEach) {
122
+ funcNode.forEach = forEach;
123
+ if (node.mode !== undefined) {
124
+ funcNode.mode = node.mode;
125
+ }
126
+ }
103
127
  if (node.notes !== undefined) {
104
128
  funcNode.notes = node.notes;
105
129
  }
@@ -90,11 +90,20 @@ interface BaseNode {
90
90
  /**
91
91
  * Function node - calls an RPC
92
92
  */
93
+ /** How the per-item instances of a `forEach` node run */
94
+ export type ForEachMode = 'parallel' | 'sequential';
93
95
  export interface FunctionNode extends BaseNode {
94
96
  /** RPC function name */
95
97
  rpcName: string;
96
98
  /** Input mapping - values can be literals or DataRefs */
97
99
  input?: Record<string, unknown | DataRef>;
100
+ /**
101
+ * Run this node once per element of the referenced array. The node's own
102
+ * result becomes the ordered array of per-item results.
103
+ */
104
+ forEach?: DataRef;
105
+ /** How the per-item instances run. Defaults to 'parallel'. */
106
+ mode?: ForEachMode;
98
107
  /** Output variable name for storing result */
99
108
  outputVar?: string;
100
109
  /** Hash of nodeId + RPC input/output schemas for version detection */
package/dist/visit.js CHANGED
@@ -28,8 +28,8 @@ import { addPersonas } from './add/add-personas.js';
28
28
  import { addVariable } from './add/add-variable.js';
29
29
  import { addWorkflowGraph } from './add/add-workflow-graph.js';
30
30
  import { addFeature } from './add/add-feature.js';
31
- import { addAIAgent } from './add/add-ai-agent.js';
32
- import { addAIScorer } from './add/add-ai-scorer.js';
31
+ import { addAgent } from './add/add-agent.js';
32
+ import { addAgentScorer } from './add/add-agent-scorer.js';
33
33
  import { addApprovalDescription } from './add/add-approval-description.js';
34
34
  export const visitSetup = (logger, checker, node, state, options) => {
35
35
  addFileExtendsCoreType(node, checker, state.singletonServicesTypeImportMap, 'CoreSingletonServices', state);
@@ -88,7 +88,7 @@ export const visitRoutes = (logger, checker, node, state, options) => {
88
88
  addMCPPrompt(logger, node, checker, state, nextOptions);
89
89
  addWorkflowGraph(logger, node, checker, state, nextOptions);
90
90
  addFeature(logger, node, checker, state, nextOptions);
91
- addAIAgent(logger, node, checker, state, nextOptions);
92
- addAIScorer(logger, node, checker, state, nextOptions);
91
+ addAgent(logger, node, checker, state, nextOptions);
92
+ addAgentScorer(logger, node, checker, state, nextOptions);
93
93
  ts.forEachChild(node, (child) => visitRoutes(logger, checker, child, state, nextOptions));
94
94
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pikku/inspector",
3
- "version": "0.12.59",
3
+ "version": "0.12.61",
4
4
  "description": "TypeScript inspector for Pikku — discovers functions and wirings to drive code generation",
5
5
  "author": "yasser.fadl@gmail.com",
6
6
  "license": "BUSL-1.1",
@@ -35,23 +35,23 @@
35
35
  "prepublishOnly": "yarn build"
36
36
  },
37
37
  "dependencies": {
38
- "@openapi-contrib/json-schema-to-openapi-schema": "^4.3.1",
38
+ "@openapi-contrib/json-schema-to-openapi-schema": "^4.3.4",
39
39
  "openapi-types": "^12.1.3",
40
- "path-to-regexp": "^8.3.0",
41
- "ts-json-schema-generator": "2.9.1-next.16",
42
- "tsx": "^4.21.0",
40
+ "path-to-regexp": "^8.4.2",
41
+ "ts-json-schema-generator": "2.9.1-next.18",
42
+ "tsx": "^4.23.12",
43
43
  "typescript": "^6.0.3",
44
- "zod": "^4.3.6",
44
+ "zod": "^4.4.3",
45
45
  "zod-to-ts": "^2.1.0"
46
46
  },
47
47
  "peerDependencies": {
48
- "@pikku/core": "^0.12.83"
48
+ "@pikku/core": "^0.12.85"
49
49
  },
50
50
  "devDependencies": {
51
- "@pikku/core": "^0.12.83",
52
- "@types/node": "^24.11.0"
51
+ "@pikku/core": "^0.12.85",
52
+ "@types/node": "^24.13.3"
53
53
  },
54
54
  "engines": {
55
55
  "node": ">=24"
56
56
  }
57
- }
57
+ }
package/run-tests.sh CHANGED
File without changes
@@ -23,7 +23,7 @@ const makeLogger = (criticals: Array<{ code: ErrorCode; message: string }>) =>
23
23
  }) satisfies InspectorLogger
24
24
 
25
25
  const inspectSources = async (sources: Record<string, string>) => {
26
- const rootDir = await mkdtemp(join(tmpdir(), 'pikku-add-ai-scorer-'))
26
+ const rootDir = await mkdtemp(join(tmpdir(), 'pikku-add-agent-scorer-'))
27
27
  const files: Record<string, string> = {}
28
28
  for (const [name, source] of Object.entries(sources)) {
29
29
  files[name] = join(rootDir, name)
@@ -43,16 +43,16 @@ const inspectSources = async (sources: Record<string, string>) => {
43
43
  const inspectSource = (source: string) =>
44
44
  inspectSources({ 'grading.scorer.ts': source })
45
45
 
46
- describe('addAIScorer', () => {
46
+ describe('addAgentScorer', () => {
47
47
  test('reads the lane off which constructor was called, not off a field', async () => {
48
48
  const { state, criticals } = await inspectSource(
49
49
  [
50
- `export const brevity = pikkuAIScorer({`,
50
+ `export const brevity = pikkuAgentScorer({`,
51
51
  ` name: 'brevity',`,
52
52
  ` description: 'Shorter answers score higher',`,
53
53
  ` score: () => ({ score: 1 }),`,
54
54
  `})`,
55
- `export const helpfulness = pikkuAIJudge({`,
55
+ `export const helpfulness = pikkuAgentJudge({`,
56
56
  ` name: 'helpfulness',`,
57
57
  ` description: 'Does the answer help',`,
58
58
  ` model: 'claude-opus-5',`,
@@ -69,7 +69,7 @@ describe('addAIScorer', () => {
69
69
  test('defaults an unstated sample rate to grading every run', async () => {
70
70
  const { state } = await inspectSource(
71
71
  [
72
- `export const brevity = pikkuAIScorer({`,
72
+ `export const brevity = pikkuAgentScorer({`,
73
73
  ` name: 'brevity',`,
74
74
  ` description: 'Shorter answers score higher',`,
75
75
  ` score: () => ({ score: 1 }),`,
@@ -84,7 +84,7 @@ describe('addAIScorer', () => {
84
84
  test('carries the sample rate and the reference requirement into the meta', async () => {
85
85
  const { state } = await inspectSource(
86
86
  [
87
- `export const correctness = pikkuAIJudge({`,
87
+ `export const correctness = pikkuAgentJudge({`,
88
88
  ` name: 'correctness',`,
89
89
  ` description: 'Is the answer right',`,
90
90
  ` model: 'claude-opus-5',`,
@@ -105,7 +105,7 @@ describe('addAIScorer', () => {
105
105
  test('rejects a sample rate that is not a fraction', async () => {
106
106
  const { state, criticals } = await inspectSource(
107
107
  [
108
- `export const brevity = pikkuAIScorer({`,
108
+ `export const brevity = pikkuAgentScorer({`,
109
109
  ` name: 'brevity',`,
110
110
  ` description: 'Shorter answers score higher',`,
111
111
  ` sampleRate: 50,`,
@@ -122,7 +122,7 @@ describe('addAIScorer', () => {
122
122
  test('a scorer with no description is refused, since the meta is what names it', async () => {
123
123
  const { criticals } = await inspectSource(
124
124
  [
125
- `export const brevity = pikkuAIScorer({`,
125
+ `export const brevity = pikkuAgentScorer({`,
126
126
  ` name: 'brevity',`,
127
127
  ` score: () => ({ score: 1 }),`,
128
128
  `})`,
@@ -135,7 +135,7 @@ describe('addAIScorer', () => {
135
135
  test('records where a scorer was declared, so codegen can import it back', async () => {
136
136
  const { state } = await inspectSource(
137
137
  [
138
- `export const brevity = pikkuAIScorer({`,
138
+ `export const brevity = pikkuAgentScorer({`,
139
139
  ` name: 'brevity',`,
140
140
  ` description: 'Shorter answers score higher',`,
141
141
  ` score: () => ({ score: 1 }),`,
@@ -153,7 +153,7 @@ describe('addAIScorer', () => {
153
153
 
154
154
  describe('an agent asking to be graded', () => {
155
155
  const scorerFile = [
156
- `export const brevity = pikkuAIScorer({`,
156
+ `export const brevity = pikkuAgentScorer({`,
157
157
  ` name: 'brevity',`,
158
158
  ` description: 'Shorter answers score higher',`,
159
159
  ` score: () => ({ score: 1 }),`,
@@ -162,7 +162,7 @@ describe('an agent asking to be graded', () => {
162
162
 
163
163
  const agent = (scorers: string) =>
164
164
  [
165
- `export const assistant = pikkuAIAgent({`,
165
+ `export const assistant = pikkuAgent({`,
166
166
  ` name: 'assistant',`,
167
167
  ` description: 'Answers questions',`,
168
168
  ` goal: 'Answer the question.',`,
@@ -5,16 +5,16 @@ import { extractFunctionName } from '../utils/extract-function-name.js'
5
5
  import { ErrorCode } from '../error-codes.js'
6
6
 
7
7
  /**
8
- * `pikkuAIScorer` grades in code and `pikkuAIJudge` grades with a model, which
8
+ * `pikkuAgentScorer` grades in code and `pikkuAgentJudge` grades with a model, which
9
9
  * is the whole difference between the two lanes — so the lane is read off which
10
10
  * constructor was called rather than from a field an author could contradict.
11
11
  */
12
12
  const LANES: Record<string, 'fast' | 'slow'> = {
13
- pikkuAIScorer: 'fast',
14
- pikkuAIJudge: 'slow',
13
+ pikkuAgentScorer: 'fast',
14
+ pikkuAgentJudge: 'slow',
15
15
  }
16
16
 
17
- export const addAIScorer: AddWiring = (logger, node, checker, state) => {
17
+ export const addAgentScorer: AddWiring = (logger, node, checker, state) => {
18
18
  if (!ts.isCallExpression(node)) return
19
19
 
20
20
  const expression = node.expression
@@ -2,7 +2,7 @@ import { describe, test } from 'node:test'
2
2
  import assert from 'node:assert'
3
3
  import * as ts from 'typescript'
4
4
 
5
- import { resolveWorkflowReferences } from './add-ai-agent.js'
5
+ import { resolveWorkflowReferences } from './add-agent.js'
6
6
  import type { InspectorLogger } from '../types.js'
7
7
 
8
8
  function createSourceFile(code: string): ts.SourceFile {
@@ -12,7 +12,7 @@ import {
12
12
  import {
13
13
  resolveMiddleware,
14
14
  resolveChannelMiddleware,
15
- resolveAIMiddleware,
15
+ resolveAgentMiddleware,
16
16
  } from '../utils/middleware.js'
17
17
  import { resolvePermissions } from '../utils/permissions.js'
18
18
  import { ErrorCode } from '../error-codes.js'
@@ -119,7 +119,7 @@ function resolveAgentReferences(
119
119
  logger.critical(
120
120
  ErrorCode.INVALID_VALUE,
121
121
  `AI agent '${agentName}' agents array contains a string literal '${element.text}'. ` +
122
- `Use an agent reference instead (e.g., import the pikkuAIAgent variable).`
122
+ `Use an agent reference instead (e.g., import the pikkuAgent variable).`
123
123
  )
124
124
  continue
125
125
  }
@@ -134,7 +134,7 @@ function resolveAgentReferences(
134
134
  logger.critical(
135
135
  ErrorCode.INVALID_VALUE,
136
136
  `AI agent '${agentName}' agents array contains identifier '${element.text}' ` +
137
- `that could not be resolved to a pikkuAIAgent.`
137
+ `that could not be resolved to a pikkuAgent.`
138
138
  )
139
139
  }
140
140
  }
@@ -319,7 +319,7 @@ function resolveIdentifierToAgentName(
319
319
  if (
320
320
  ts.isCallExpression(decl.initializer) &&
321
321
  ts.isIdentifier(decl.initializer.expression) &&
322
- decl.initializer.expression.text === 'pikkuAIAgent'
322
+ decl.initializer.expression.text === 'pikkuAgent'
323
323
  ) {
324
324
  if (ts.isIdentifier(decl.name)) {
325
325
  return decl.name.text
@@ -363,13 +363,7 @@ function resolveScorerNames(
363
363
  return names.length > 0 ? names : null
364
364
  }
365
365
 
366
- export const addAIAgent: AddWiring = (
367
- logger,
368
- node,
369
- checker,
370
- state,
371
- options
372
- ) => {
366
+ export const addAgent: AddWiring = (logger, node, checker, state, options) => {
373
367
  if (!ts.isCallExpression(node)) {
374
368
  return
375
369
  }
@@ -378,7 +372,7 @@ export const addAIAgent: AddWiring = (
378
372
  const firstArg = args[0]
379
373
  const expression = node.expression
380
374
 
381
- if (!ts.isIdentifier(expression) || expression.text !== 'pikkuAIAgent') {
375
+ if (!ts.isIdentifier(expression) || expression.text !== 'pikkuAgent') {
382
376
  return
383
377
  }
384
378
 
@@ -401,14 +395,12 @@ export const addAIAgent: AddWiring = (
401
395
 
402
396
  const roleValue = getPropertyValue(obj, 'role') as string | null
403
397
  const personalityValue = getPropertyValue(obj, 'personality') as
404
- | string
405
- | null
398
+ string | null
406
399
  const goalValue = getPropertyValue(obj, 'goal') as string | null
407
400
 
408
401
  const maxStepsValue = getPropertyValue(obj, 'maxSteps') as number | null
409
402
  const temperatureValue = getPropertyValue(obj, 'temperature') as
410
- | number
411
- | null
403
+ number | null
412
404
  const toolChoiceValue = getPropertyValue(obj, 'toolChoice') as string | null
413
405
  const scorersValue = resolveScorerNames(obj, nameValue || '', logger)
414
406
  const toolsValue = resolveToolReferences(
@@ -579,7 +571,7 @@ export const addAIAgent: AddWiring = (
579
571
  tags,
580
572
  checker
581
573
  )
582
- const aiMiddleware = resolveAIMiddleware(state, obj, checker)
574
+ const agentMiddleware = resolveAgentMiddleware(state, obj, checker)
583
575
  const permissions = resolvePermissions(state, obj, tags, checker)
584
576
 
585
577
  state.serviceAggregation.usedFunctions.add(agentKey)
@@ -623,7 +615,7 @@ export const addAIAgent: AddWiring = (
623
615
  workingMemorySchema,
624
616
  middleware,
625
617
  channelMiddleware,
626
- aiMiddleware,
618
+ agentMiddleware,
627
619
  permissions,
628
620
  }
629
621
 
@@ -632,10 +624,10 @@ export const addAIAgent: AddWiring = (
632
624
  const funcMeta = state.functions.meta[agentKey]
633
625
  if (funcMeta?.services) {
634
626
  for (const svc of [
635
- 'aiStorage',
636
- 'aiRunState',
627
+ 'agentStorage',
628
+ 'agentRunState',
637
629
  'agentRunService',
638
- 'aiAgentRunner',
630
+ 'agentRunner',
639
631
  ]) {
640
632
  if (!funcMeta.services.services.includes(svc)) {
641
633
  funcMeta.services.services.push(svc)
@@ -1,5 +1,5 @@
1
1
  import * as ts from 'typescript'
2
- import type { FunctionServicesMeta } from '@pikku/core'
2
+ import type { FunctionServicesMeta } from '@pikku/core/function'
3
3
  import type { AddWiring } from '../types.js'
4
4
  import { ErrorCode } from '../error-codes.js'
5
5
  import { extractServicesFromFunction } from '../utils/extract-services.js'
@@ -89,7 +89,7 @@ const readArrayProp = (
89
89
 
90
90
  /**
91
91
  * Read the callee name of a `plugins: [...]` entry. better-auth plugins are
92
- * factory calls (`bearer()`, `twoFactor({ ... })`, `admin()`); the entry's id
92
+ * factory calls (`bearer()`, `twoFactor({ ... })`, `ban()`); the entry's id
93
93
  * is the called function's name. Member-expression callees (`foo.bar()`) and
94
94
  * non-call entries are ignored.
95
95
  */
@@ -630,6 +630,12 @@ function processOptions(
630
630
  }
631
631
  break
632
632
 
633
+ case 'type':
634
+ if (ts.isStringLiteral(optProp.initializer)) {
635
+ option.type = optProp.initializer.text
636
+ }
637
+ break
638
+
633
639
  case 'default':
634
640
  // Extract default value from expression
635
641
  if (ts.isStringLiteral(optProp.initializer)) {
@@ -39,11 +39,9 @@ export const addCredential: AddWiring = (
39
39
 
40
40
  const nameValue = getPropertyValue(obj, 'name') as string | null
41
41
  const displayNameValue = getPropertyValue(obj, 'displayName') as
42
- | string
43
- | null
42
+ string | null
44
43
  const descriptionValue = getPropertyValue(obj, 'description') as
45
- | string
46
- | null
44
+ string | null
47
45
  const typeValue = getPropertyValue(obj, 'type') as string | null
48
46
  const docsUrlValue = getPropertyValue(obj, 'docsUrl') as string | null
49
47
 
@@ -126,8 +124,7 @@ export const addCredential: AddWiring = (
126
124
  'appCredentialSecretId'
127
125
  ) as string | null
128
126
  const tokenSecretId = getPropertyValue(oauth2Obj, 'tokenSecretId') as
129
- | string
130
- | null
127
+ string | null
131
128
  const authorizationUrl = getPropertyValue(
132
129
  oauth2Obj,
133
130
  'authorizationUrl'
@@ -61,9 +61,7 @@ export const addFileWithFactory = (
61
61
  if (state && callExpression.arguments.length > 0) {
62
62
  const firstArg = callExpression.arguments[0]
63
63
  let functionNode:
64
- | ts.ArrowFunction
65
- | ts.FunctionExpression
66
- | undefined
64
+ ts.ArrowFunction | ts.FunctionExpression | undefined
67
65
 
68
66
  if (ts.isArrowFunction(firstArg)) {
69
67
  functionNode = firstArg
@@ -179,9 +177,7 @@ export const addFileWithFactory = (
179
177
  node.initializer
180
178
  ) {
181
179
  let functionNode:
182
- | ts.ArrowFunction
183
- | ts.FunctionExpression
184
- | undefined
180
+ ts.ArrowFunction | ts.FunctionExpression | undefined
185
181
  if (ts.isArrowFunction(node.initializer)) {
186
182
  functionNode = node.initializer
187
183
  } else if (ts.isFunctionExpression(node.initializer)) {