@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.
- package/CHANGELOG.md +373 -0
- package/OPTIMIZATION-PLAN.md +19 -19
- package/dist/add/add-agent-scorer.d.ts +2 -0
- package/dist/add/{add-ai-scorer.js → add-agent-scorer.js} +4 -4
- package/dist/add/{add-ai-agent.d.ts → add-agent.d.ts} +1 -1
- package/dist/add/{add-ai-agent.js → add-agent.js} +11 -11
- package/dist/add/add-auth.js +1 -1
- package/dist/add/add-cli.js +5 -0
- package/dist/add/add-functions.js +10 -1
- package/dist/add/add-http-route.js +18 -18
- package/dist/add/add-keyed-wiring.d.ts +2 -0
- package/dist/add/add-keyed-wiring.js +3 -1
- package/dist/add/add-middleware.js +5 -5
- package/dist/add/add-personas.js +3 -0
- package/dist/add/add-secret.js +1 -0
- package/dist/add/add-variable.js +1 -0
- package/dist/add/add-wire-remote-addon.js +2 -1
- package/dist/add/add-workflow-graph.js +63 -6
- package/dist/error-codes.d.ts +3 -1
- package/dist/error-codes.js +3 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +1 -0
- package/dist/inspector.js +13 -3
- package/dist/types.d.ts +10 -5
- package/dist/utils/annotate-http-route-auth.js +2 -1
- package/dist/utils/check-secret-sinks.js +2 -1
- package/dist/utils/compute-required-schemas.d.ts +1 -1
- package/dist/utils/contract-hashes.d.ts +2 -1
- package/dist/utils/contract-hashes.js +1 -1
- package/dist/utils/extract-function-name.js +1 -1
- package/dist/utils/extract-services.d.ts +1 -1
- package/dist/utils/extract-surface-usage.d.ts +29 -0
- package/dist/utils/extract-surface-usage.js +97 -0
- package/dist/utils/filter-inspector-state.js +53 -16
- package/dist/utils/filter-utils.d.ts +1 -1
- package/dist/utils/get-property-value.js +42 -3
- package/dist/utils/load-addon-functions-meta.js +31 -0
- package/dist/utils/middleware.d.ts +2 -2
- package/dist/utils/middleware.js +5 -5
- package/dist/utils/permissions.d.ts +1 -1
- package/dist/utils/post-process.d.ts +28 -8
- package/dist/utils/post-process.js +83 -18
- package/dist/utils/resolve-deploy-target.d.ts +1 -1
- package/dist/utils/resolve-function-meta.d.ts +1 -1
- package/dist/utils/resolve-function-types.d.ts +1 -1
- package/dist/utils/resolve-versions.js +1 -1
- package/dist/utils/schema-generator.d.ts +1 -1
- package/dist/utils/serialize-inspector-state.d.ts +4 -3
- package/dist/utils/serialize-inspector-state.js +6 -4
- package/dist/utils/serialize-openapi-json.d.ts +1 -1
- package/dist/utils/validate-auth-sessionless.js +2 -1
- package/dist/utils/workflow/graph/finalize-workflows.js +1 -1
- package/dist/utils/workflow/graph/serialize-workflow-graph.d.ts +6 -1
- package/dist/utils/workflow/graph/serialize-workflow-graph.js +26 -2
- package/dist/utils/workflow/graph/workflow-graph.types.d.ts +9 -0
- package/dist/visit.js +4 -4
- package/package.json +10 -10
- package/run-tests.sh +0 -0
- package/src/add/{add-ai-scorer.test.ts → add-agent-scorer.test.ts} +11 -11
- package/src/add/{add-ai-scorer.ts → add-agent-scorer.ts} +4 -4
- package/src/add/{add-ai-agent.test.ts → add-agent.test.ts} +1 -1
- package/src/add/{add-ai-agent.ts → add-agent.ts} +13 -21
- package/src/add/add-auth.ts +2 -2
- package/src/add/add-cli.ts +6 -0
- package/src/add/add-credential.ts +3 -6
- package/src/add/add-file-with-factory.ts +2 -6
- package/src/add/add-functions.ts +23 -25
- package/src/add/add-http-route-ref.test.ts +149 -0
- package/src/add/add-http-route.ts +25 -28
- package/src/add/add-keyed-wiring.ts +8 -7
- package/src/add/add-middleware.ts +7 -5
- package/src/add/add-permission.ts +1 -1
- package/src/add/add-personas.test.ts +24 -0
- package/src/add/add-personas.ts +3 -1
- package/src/add/add-scenario-step.test.ts +35 -0
- package/src/add/add-scope.test.ts +4 -4
- package/src/add/add-scope.ts +4 -8
- package/src/add/add-secret.ts +1 -0
- package/src/add/add-system-role.test.ts +8 -8
- package/src/add/add-system-role.ts +2 -4
- package/src/add/add-variable.ts +1 -0
- package/src/add/add-wire-remote-addon.ts +4 -1
- package/src/add/add-workflow-graph-foreach.test.ts +174 -0
- package/src/add/add-workflow-graph.ts +78 -6
- package/src/add/add-workflow-sleep-expression.test.ts +3 -4
- package/src/add/addon-contracts.test.ts +1 -1
- package/src/add/config-value-metadata.test.ts +94 -0
- package/src/add/secret-sink-check.test.ts +4 -1
- package/src/error-codes.ts +3 -1
- package/src/index.ts +3 -4
- package/src/inspector.ts +20 -3
- package/src/types.ts +10 -7
- package/src/utils/annotate-http-route-auth.test.ts +5 -7
- package/src/utils/annotate-http-route-auth.ts +2 -1
- package/src/utils/check-secret-sinks.ts +4 -1
- package/src/utils/compute-required-schemas.ts +1 -1
- package/src/utils/contract-hashes.test.ts +1 -1
- package/src/utils/contract-hashes.ts +3 -2
- package/src/utils/extract-function-name.ts +1 -1
- package/src/utils/extract-services.ts +4 -2
- package/src/utils/extract-surface-usage.test.ts +147 -0
- package/src/utils/extract-surface-usage.ts +121 -0
- package/src/utils/filter-inspector-state.test.ts +138 -12
- package/src/utils/filter-inspector-state.ts +82 -21
- package/src/utils/filter-utils.ts +1 -1
- package/src/utils/get-property-value.ts +43 -5
- package/src/utils/load-addon-functions-meta.ts +40 -0
- package/src/utils/middleware.test.ts +23 -23
- package/src/utils/middleware.ts +6 -6
- package/src/utils/permissions.ts +1 -1
- package/src/utils/post-process.test.ts +68 -11
- package/src/utils/post-process.ts +91 -28
- package/src/utils/resolve-deploy-target.ts +1 -1
- package/src/utils/resolve-function-meta.ts +1 -1
- package/src/utils/resolve-function-types.ts +1 -1
- package/src/utils/resolve-versions.ts +1 -1
- package/src/utils/schema-generator.ts +2 -1
- package/src/utils/serialize-inspector-state.ts +10 -7
- package/src/utils/serialize-mcp-json.ts +1 -1
- package/src/utils/serialize-openapi-json.ts +1 -1
- package/src/utils/validate-auth-sessionless.ts +2 -1
- package/src/utils/validate-tags-resolve-to-middleware.test.ts +4 -1
- package/src/utils/workflow/dsl/extract-approval-policy.test.ts +4 -1
- package/src/utils/workflow/graph/convert-dsl-to-graph-skip.test.ts +1 -1
- package/src/utils/workflow/graph/finalize-workflows.ts +6 -2
- package/src/utils/workflow/graph/serialize-workflow-graph.ts +34 -3
- package/src/utils/workflow/graph/workflow-graph.types.ts +10 -0
- package/src/visit.ts +4 -4
- package/tsconfig.tsbuildinfo +1 -1
- package/dist/add/add-ai-scorer.d.ts +0 -2
- package/dist/utils/secret-brokers.d.ts +0 -2
- 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
|
-
|
|
283
|
-
definitions: InspectorState['
|
|
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
|
-
|
|
153
|
-
definitions: state.
|
|
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
|
-
|
|
330
|
-
definitions: data.
|
|
331
|
+
agentMiddleware: {
|
|
332
|
+
definitions: data.agentMiddleware?.definitions || {},
|
|
331
333
|
},
|
|
332
334
|
permissions: {
|
|
333
335
|
definitions: data.permissions.definitions,
|
|
@@ -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
|
|
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 {
|
|
32
|
-
import {
|
|
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
|
-
|
|
92
|
-
|
|
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.
|
|
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.
|
|
38
|
+
"@openapi-contrib/json-schema-to-openapi-schema": "^4.3.4",
|
|
39
39
|
"openapi-types": "^12.1.3",
|
|
40
|
-
"path-to-regexp": "^8.
|
|
41
|
-
"ts-json-schema-generator": "2.9.1-next.
|
|
42
|
-
"tsx": "^4.
|
|
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
|
|
44
|
+
"zod": "^4.4.3",
|
|
45
45
|
"zod-to-ts": "^2.1.0"
|
|
46
46
|
},
|
|
47
47
|
"peerDependencies": {
|
|
48
|
-
"@pikku/core": "^0.12.
|
|
48
|
+
"@pikku/core": "^0.12.85"
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|
|
51
|
-
"@pikku/core": "^0.12.
|
|
52
|
-
"@types/node": "^24.
|
|
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-
|
|
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('
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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
|
-
* `
|
|
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
|
-
|
|
14
|
-
|
|
13
|
+
pikkuAgentScorer: 'fast',
|
|
14
|
+
pikkuAgentJudge: 'slow',
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
export const
|
|
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-
|
|
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
|
-
|
|
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
|
|
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
|
|
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 === '
|
|
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
|
|
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 !== '
|
|
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
|
-
|
|
|
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
|
-
|
|
|
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
|
|
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
|
-
|
|
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
|
-
'
|
|
636
|
-
'
|
|
627
|
+
'agentStorage',
|
|
628
|
+
'agentRunState',
|
|
637
629
|
'agentRunService',
|
|
638
|
-
'
|
|
630
|
+
'agentRunner',
|
|
639
631
|
]) {
|
|
640
632
|
if (!funcMeta.services.services.includes(svc)) {
|
|
641
633
|
funcMeta.services.services.push(svc)
|
package/src/add/add-auth.ts
CHANGED
|
@@ -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({ ... })`, `
|
|
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
|
*/
|
package/src/add/add-cli.ts
CHANGED
|
@@ -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
|
-
|
|
|
43
|
-
| null
|
|
42
|
+
string | null
|
|
44
43
|
const descriptionValue = getPropertyValue(obj, 'description') as
|
|
45
|
-
|
|
|
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
|
-
|
|
|
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.
|
|
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.
|
|
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)) {
|