@pikku/inspector 0.12.58 → 0.12.60
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 +127 -0
- package/dist/add/add-agent-scorer.d.ts +2 -0
- package/dist/add/add-agent-scorer.js +61 -0
- package/dist/add/add-agent.d.ts +4 -0
- package/dist/add/add-agent.js +442 -0
- package/dist/add/add-channel.d.ts +1 -1
- package/dist/add/add-functions.js +1 -1
- package/dist/add/add-keyed-wiring.js +1 -1
- package/dist/add/add-middleware.js +5 -5
- package/dist/add/add-personas.js +1 -1
- package/dist/add/add-wire-addon.js +10 -0
- package/dist/add/add-workflow.d.ts +1 -1
- package/dist/error-codes.d.ts +1 -0
- package/dist/error-codes.js +1 -0
- package/dist/inspector.js +1 -1
- package/dist/types.d.ts +27 -22
- 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/filter-inspector-state.js +1 -1
- package/dist/utils/filter-utils.d.ts +1 -1
- 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 +2 -2
- package/dist/utils/post-process.js +24 -12
- 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 +5 -3
- package/dist/utils/serialize-inspector-state.js +4 -4
- package/dist/utils/serialize-openapi-json.d.ts +2 -2
- package/dist/utils/workflow/derive-workflow-plan.d.ts +1 -1
- package/dist/utils/workflow/dsl/extract-dsl-workflow.d.ts +1 -1
- package/dist/utils/workflow/graph/convert-dsl-to-graph.d.ts +1 -1
- package/dist/utils/workflow/graph/finalize-workflows.js +1 -1
- package/dist/utils/workflow/graph/serialize-workflow-graph.js +1 -1
- package/dist/utils/workflow/graph/workflow-graph.types.d.ts +2 -1
- package/dist/visit.js +4 -4
- package/package.json +3 -3
- 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} +11 -17
- package/src/add/add-auth.ts +1 -1
- package/src/add/add-channel.ts +4 -1
- package/src/add/add-cli.ts +1 -1
- package/src/add/add-functions.ts +9 -4
- package/src/add/add-gateway.ts +1 -1
- package/src/add/add-http-route.ts +1 -1
- package/src/add/add-keyed-wiring.ts +1 -1
- package/src/add/add-middleware.ts +7 -5
- package/src/add/add-permission.ts +1 -1
- package/src/add/add-personas.test.ts +2 -2
- package/src/add/add-personas.ts +3 -2
- package/src/add/add-scenario-step.test.ts +2 -1
- package/src/add/add-scope.test.ts +19 -19
- package/src/add/add-scope.ts +1 -1
- package/src/add/add-system-role.test.ts +12 -12
- package/src/add/add-wire-addon.test.ts +31 -0
- package/src/add/add-wire-addon.ts +8 -0
- package/src/add/add-workflow-graph-input.test.ts +1 -1
- package/src/add/add-workflow.ts +4 -1
- package/src/add/addon-contracts.test.ts +1 -1
- package/src/error-codes.ts +1 -0
- package/src/inspector.ts +1 -1
- package/src/types.ts +33 -23
- 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 -1
- package/src/utils/filter-inspector-state.ts +2 -2
- package/src/utils/filter-utils.ts +1 -1
- 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 +76 -9
- package/src/utils/post-process.ts +36 -14
- package/src/utils/resolve-deploy-target.ts +1 -1
- package/src/utils/resolve-function-meta.ts +4 -1
- package/src/utils/resolve-function-types.ts +1 -1
- package/src/utils/resolve-versions.ts +5 -2
- package/src/utils/schema-generator.ts +3 -2
- package/src/utils/serialize-inspector-state.ts +9 -7
- package/src/utils/serialize-mcp-json.ts +1 -1
- package/src/utils/serialize-openapi-json.ts +2 -2
- package/src/utils/workflow/derive-workflow-plan.test.ts +1 -1
- package/src/utils/workflow/derive-workflow-plan.ts +1 -1
- package/src/utils/workflow/dsl/extract-approval-policy.test.ts +5 -2
- package/src/utils/workflow/dsl/extract-dsl-workflow.ts +2 -2
- package/src/utils/workflow/graph/convert-dsl-to-graph-skip.test.ts +1 -1
- package/src/utils/workflow/graph/convert-dsl-to-graph.ts +4 -1
- package/src/utils/workflow/graph/finalize-workflow-wires.ts +1 -1
- package/src/utils/workflow/graph/finalize-workflows.ts +6 -2
- package/src/utils/workflow/graph/serialize-workflow-graph.ts +1 -1
- package/src/utils/workflow/graph/workflow-graph.types.ts +2 -2
- package/src/visit.ts +4 -4
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -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
|
|
|
@@ -579,7 +573,7 @@ export const addAIAgent: AddWiring = (
|
|
|
579
573
|
tags,
|
|
580
574
|
checker
|
|
581
575
|
)
|
|
582
|
-
const
|
|
576
|
+
const agentMiddleware = resolveAgentMiddleware(state, obj, checker)
|
|
583
577
|
const permissions = resolvePermissions(state, obj, tags, checker)
|
|
584
578
|
|
|
585
579
|
state.serviceAggregation.usedFunctions.add(agentKey)
|
|
@@ -623,7 +617,7 @@ export const addAIAgent: AddWiring = (
|
|
|
623
617
|
workingMemorySchema,
|
|
624
618
|
middleware,
|
|
625
619
|
channelMiddleware,
|
|
626
|
-
|
|
620
|
+
agentMiddleware,
|
|
627
621
|
permissions,
|
|
628
622
|
}
|
|
629
623
|
|
|
@@ -632,10 +626,10 @@ export const addAIAgent: AddWiring = (
|
|
|
632
626
|
const funcMeta = state.functions.meta[agentKey]
|
|
633
627
|
if (funcMeta?.services) {
|
|
634
628
|
for (const svc of [
|
|
635
|
-
'
|
|
636
|
-
'
|
|
629
|
+
'agentStorage',
|
|
630
|
+
'agentRunState',
|
|
637
631
|
'agentRunService',
|
|
638
|
-
'
|
|
632
|
+
'agentRunner',
|
|
639
633
|
]) {
|
|
640
634
|
if (!funcMeta.services.services.includes(svc)) {
|
|
641
635
|
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/ecosystem/types'
|
|
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'
|
package/src/add/add-channel.ts
CHANGED
|
@@ -10,7 +10,10 @@ import {
|
|
|
10
10
|
makeContextBasedId,
|
|
11
11
|
} from '../utils/extract-function-name.js'
|
|
12
12
|
import { getPropertyAssignmentInitializer } from '../utils/type-utils.js'
|
|
13
|
-
import type {
|
|
13
|
+
import type {
|
|
14
|
+
ChannelMessageMeta,
|
|
15
|
+
ChannelMeta,
|
|
16
|
+
} from '@pikku/core/ecosystem/channel'
|
|
14
17
|
import type { InspectorState, AddWiring } from '../types.js'
|
|
15
18
|
import {
|
|
16
19
|
resolveMiddleware,
|
package/src/add/add-cli.ts
CHANGED
|
@@ -6,7 +6,7 @@ import type {
|
|
|
6
6
|
InspectorOptions,
|
|
7
7
|
InspectorState,
|
|
8
8
|
} from '../types.js'
|
|
9
|
-
import type { CLIProgramMeta, CLICommandMeta } from '@pikku/core/cli'
|
|
9
|
+
import type { CLIProgramMeta, CLICommandMeta } from '@pikku/core/ecosystem/cli'
|
|
10
10
|
import {
|
|
11
11
|
extractFunctionName,
|
|
12
12
|
makeContextBasedId,
|
package/src/add/add-functions.ts
CHANGED
|
@@ -8,9 +8,14 @@ import {
|
|
|
8
8
|
} from '../utils/extract-function-name.js'
|
|
9
9
|
import { extractFunctionNode } from '../utils/extract-function-node.js'
|
|
10
10
|
import { extractUsedWires } from '../utils/extract-services.js'
|
|
11
|
-
import type { AuditDurability
|
|
12
|
-
import type {
|
|
13
|
-
import {
|
|
11
|
+
import type { AuditDurability } from '@pikku/core/ecosystem/services'
|
|
12
|
+
import type { FunctionServicesMeta } from '@pikku/core/ecosystem/types'
|
|
13
|
+
import type { ScenarioSurface } from '@pikku/core/scenario'
|
|
14
|
+
import type { ScenarioStepKind } from '@pikku/core/ecosystem/scenario'
|
|
15
|
+
import {
|
|
16
|
+
formatVersionedId,
|
|
17
|
+
parseVersionedId,
|
|
18
|
+
} from '@pikku/core/ecosystem/types'
|
|
14
19
|
|
|
15
20
|
/** Binding keys a `pikkuScenarioStep` may declare, in report order. */
|
|
16
21
|
const SCENARIO_SURFACE_KEYS: readonly ScenarioSurface[] = [
|
|
@@ -44,7 +49,7 @@ import { ErrorCode } from '../error-codes.js'
|
|
|
44
49
|
import { findPiiPaths } from '../utils/check-pii-output.js'
|
|
45
50
|
import { findRevealedSecretSinks } from '../utils/check-secret-sinks.js'
|
|
46
51
|
import { isScenarioInstrumentationFunction } from './scenario-instrumentation.js'
|
|
47
|
-
import type { NodeType } from '@pikku/core/node'
|
|
52
|
+
import type { NodeType } from '@pikku/core/ecosystem/node'
|
|
48
53
|
|
|
49
54
|
const isValidVariableName = (name: string) => {
|
|
50
55
|
const regex = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/
|
package/src/add/add-gateway.ts
CHANGED
|
@@ -13,7 +13,7 @@ import { ensureInlineWiringFunction } from '../utils/ensure-function-metadata.js
|
|
|
13
13
|
import { resolveMiddleware } from '../utils/middleware.js'
|
|
14
14
|
import { extractWireNames } from '../utils/post-process.js'
|
|
15
15
|
import { resolveAddonName } from '../utils/resolve-addon-package.js'
|
|
16
|
-
import type { GatewayTransportType } from '@pikku/core/gateway'
|
|
16
|
+
import type { GatewayTransportType } from '@pikku/core/ecosystem/gateway'
|
|
17
17
|
|
|
18
18
|
import { ErrorCode } from '../error-codes.js'
|
|
19
19
|
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
getCommonWireMetaData,
|
|
5
5
|
} from '../utils/get-property-value.js'
|
|
6
6
|
import { pathToRegexp } from 'path-to-regexp'
|
|
7
|
-
import type { HTTPMethod } from '@pikku/core/http'
|
|
7
|
+
import type { HTTPMethod } from '@pikku/core/ecosystem/http'
|
|
8
8
|
import {
|
|
9
9
|
extractFunctionName,
|
|
10
10
|
makeContextBasedId,
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
import type { AddWiring, InspectorState } from '../types.js'
|
|
8
8
|
import { ErrorCode } from '../error-codes.js'
|
|
9
9
|
import { detectSchemaVendorOrError } from '../utils/detect-schema-vendor.js'
|
|
10
|
-
import { parseDurationString } from '@pikku/core'
|
|
10
|
+
import { parseDurationString } from '@pikku/core/ecosystem/types'
|
|
11
11
|
|
|
12
12
|
export interface KeyedWiringConfig {
|
|
13
13
|
functionName: string
|
|
@@ -698,12 +698,14 @@ export const addMiddleware: AddWiring = (logger, node, checker, state) => {
|
|
|
698
698
|
return
|
|
699
699
|
}
|
|
700
700
|
|
|
701
|
-
if (expression.text === '
|
|
701
|
+
if (expression.text === 'pikkuAgentMiddleware') {
|
|
702
702
|
const arg = args[0]
|
|
703
703
|
if (!arg) return
|
|
704
704
|
|
|
705
705
|
if (!ts.isObjectLiteralExpression(arg)) {
|
|
706
|
-
logger.error(
|
|
706
|
+
logger.error(
|
|
707
|
+
`• pikkuAgentMiddleware() requires an object literal argument.`
|
|
708
|
+
)
|
|
707
709
|
return
|
|
708
710
|
}
|
|
709
711
|
|
|
@@ -744,13 +746,13 @@ export const addMiddleware: AddWiring = (logger, node, checker, state) => {
|
|
|
744
746
|
pikkuFuncId = node.parent.name.text
|
|
745
747
|
} else {
|
|
746
748
|
logger.error(
|
|
747
|
-
`•
|
|
748
|
-
`Extract it to a const: const myMiddleware =
|
|
749
|
+
`• pikkuAgentMiddleware() must be assigned to a variable or object property. ` +
|
|
750
|
+
`Extract it to a const: const myMiddleware = pikkuAgentMiddleware(...)`
|
|
749
751
|
)
|
|
750
752
|
return
|
|
751
753
|
}
|
|
752
754
|
}
|
|
753
|
-
state.
|
|
755
|
+
state.agentMiddleware.definitions[pikkuFuncId] = {
|
|
754
756
|
services,
|
|
755
757
|
sourceFile: node.getSourceFile().fileName,
|
|
756
758
|
position: node.getStart(),
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as ts from 'typescript'
|
|
2
|
-
import type { FunctionWiresMeta } from '@pikku/core'
|
|
2
|
+
import type { FunctionWiresMeta } from '@pikku/core/ecosystem/types'
|
|
3
3
|
import type { AddWiring } from '../types.js'
|
|
4
4
|
import { extractFunctionName } from '../utils/extract-function-name.js'
|
|
5
5
|
import {
|
|
@@ -57,8 +57,8 @@ const inspectSources = async (sources: Record<string, string>) => {
|
|
|
57
57
|
/** The declared world every persona below is checked against. */
|
|
58
58
|
const withRoles = (...lines: string[]) =>
|
|
59
59
|
[
|
|
60
|
-
"import { defineScope } from '@pikku/core/scope'",
|
|
61
|
-
"import { defineSystemRole } from '@pikku/core/role'",
|
|
60
|
+
"import { defineScope } from '@pikku/core/ecosystem/scope'",
|
|
61
|
+
"import { defineSystemRole } from '@pikku/core/ecosystem/role'",
|
|
62
62
|
"import { definePersonas } from '@pikku/core/persona'",
|
|
63
63
|
'defineScope({ catalogue: { scopes: { read: {} } }, admin: {} })',
|
|
64
64
|
'defineSystemRole({',
|
package/src/add/add-personas.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import * as ts from 'typescript'
|
|
2
|
-
import { DISPOSITIONS } from '@pikku/core/virtual-user'
|
|
2
|
+
import { DISPOSITIONS } from '@pikku/core/ecosystem/virtual-user'
|
|
3
3
|
import { isRunnablePersona } from '@pikku/core/persona'
|
|
4
|
-
import type {
|
|
4
|
+
import type { PersonaMeta } from '@pikku/core/persona'
|
|
5
|
+
import type { PersonaAccountMeta } from '@pikku/core/ecosystem/persona'
|
|
5
6
|
import { ErrorCode } from '../error-codes.js'
|
|
6
7
|
import { claimSingleDeclaration } from '../utils/single-declaration.js'
|
|
7
8
|
import type { AddWiring, InspectorLogger } from '../types.js'
|
|
@@ -5,7 +5,8 @@ import { tmpdir } from 'node:os'
|
|
|
5
5
|
import { join } from 'node:path'
|
|
6
6
|
import { inspect } from '../inspector.js'
|
|
7
7
|
import type { InspectorLogger } from '../types.js'
|
|
8
|
-
import type {
|
|
8
|
+
import type { WorkflowStepMeta } from '@pikku/core/ecosystem/workflow'
|
|
9
|
+
import type { ScenarioStepMeta } from '@pikku/core/ecosystem/scenario'
|
|
9
10
|
|
|
10
11
|
function makeLogger(
|
|
11
12
|
criticals: Array<{ code: string; message: string }>
|
|
@@ -58,7 +58,7 @@ describe('addScope inspector', () => {
|
|
|
58
58
|
test('extracts a flat scope', async () => {
|
|
59
59
|
const { state, criticals } = await inspectSource(
|
|
60
60
|
[
|
|
61
|
-
"import { defineScope } from '@pikku/core/scope'",
|
|
61
|
+
"import { defineScope } from '@pikku/core/ecosystem/scope'",
|
|
62
62
|
'defineScope({',
|
|
63
63
|
' admin: {',
|
|
64
64
|
" displayName: 'Administration',",
|
|
@@ -81,7 +81,7 @@ describe('addScope inspector', () => {
|
|
|
81
81
|
test('extracts a displayName at every depth', async () => {
|
|
82
82
|
const { state, criticals } = await inspectSource(
|
|
83
83
|
[
|
|
84
|
-
"import { defineScope } from '@pikku/core/scope'",
|
|
84
|
+
"import { defineScope } from '@pikku/core/ecosystem/scope'",
|
|
85
85
|
'defineScope({',
|
|
86
86
|
' admin: {',
|
|
87
87
|
" displayName: 'Administration',",
|
|
@@ -109,7 +109,7 @@ describe('addScope inspector', () => {
|
|
|
109
109
|
test('extracts a nested scope tree', async () => {
|
|
110
110
|
const { state, criticals } = await inspectSource(
|
|
111
111
|
[
|
|
112
|
-
"import { defineScope } from '@pikku/core/scope'",
|
|
112
|
+
"import { defineScope } from '@pikku/core/ecosystem/scope'",
|
|
113
113
|
'defineScope({',
|
|
114
114
|
' admin: {',
|
|
115
115
|
' scopes: {',
|
|
@@ -139,7 +139,7 @@ describe('addScope inspector', () => {
|
|
|
139
139
|
test('records the source file', async () => {
|
|
140
140
|
const { state, file } = await inspectSource(
|
|
141
141
|
[
|
|
142
|
-
"import { defineScope } from '@pikku/core/scope'",
|
|
142
|
+
"import { defineScope } from '@pikku/core/ecosystem/scope'",
|
|
143
143
|
'defineScope({ admin: {} })',
|
|
144
144
|
].join('\n')
|
|
145
145
|
)
|
|
@@ -153,7 +153,7 @@ describe('addScope inspector', () => {
|
|
|
153
153
|
test('extracts several roots from one declaration', async () => {
|
|
154
154
|
const { state, criticals } = await inspectSource(
|
|
155
155
|
[
|
|
156
|
-
"import { defineScope } from '@pikku/core/scope'",
|
|
156
|
+
"import { defineScope } from '@pikku/core/ecosystem/scope'",
|
|
157
157
|
'defineScope({ admin: {}, billing: { scopes: { read: {} } } })',
|
|
158
158
|
].join('\n')
|
|
159
159
|
)
|
|
@@ -169,7 +169,7 @@ describe('addScope inspector', () => {
|
|
|
169
169
|
test('extracts several declarations', async () => {
|
|
170
170
|
const { state } = await inspectSource(
|
|
171
171
|
[
|
|
172
|
-
"import { defineScope } from '@pikku/core/scope'",
|
|
172
|
+
"import { defineScope } from '@pikku/core/ecosystem/scope'",
|
|
173
173
|
'defineScope({ admin: {} })',
|
|
174
174
|
'defineScope({ billing: {} })',
|
|
175
175
|
].join('\n')
|
|
@@ -188,11 +188,11 @@ describe('addScope inspector', () => {
|
|
|
188
188
|
test('declarations in separate files all survive', async () => {
|
|
189
189
|
const { state, criticals } = await inspectSources({
|
|
190
190
|
'user-admin.gen.ts': [
|
|
191
|
-
"import { defineScope } from '@pikku/core/scope'",
|
|
191
|
+
"import { defineScope } from '@pikku/core/ecosystem/scope'",
|
|
192
192
|
'defineScope({ admin: {} })',
|
|
193
193
|
].join('\n'),
|
|
194
194
|
'scopes.ts': [
|
|
195
|
-
"import { defineScope } from '@pikku/core/scope'",
|
|
195
|
+
"import { defineScope } from '@pikku/core/ecosystem/scope'",
|
|
196
196
|
'defineScope({ billing: {} })',
|
|
197
197
|
].join('\n'),
|
|
198
198
|
})
|
|
@@ -202,10 +202,10 @@ describe('addScope inspector', () => {
|
|
|
202
202
|
[],
|
|
203
203
|
`expected no duplicate critical, got ${JSON.stringify(criticals)}`
|
|
204
204
|
)
|
|
205
|
-
assert.deepEqual(
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
)
|
|
205
|
+
assert.deepEqual(state.scopes.definitions.map((d) => d.name).sort(), [
|
|
206
|
+
'admin',
|
|
207
|
+
'billing',
|
|
208
|
+
])
|
|
209
209
|
})
|
|
210
210
|
|
|
211
211
|
// The CLI scaffolds a scope tree of its own — `user-admin.gen.ts` declares the
|
|
@@ -214,11 +214,11 @@ describe('addScope inspector', () => {
|
|
|
214
214
|
test('a generated declaration neither claims the slot nor conflicts', async () => {
|
|
215
215
|
const { state, criticals } = await inspectSources({
|
|
216
216
|
'user-admin.gen.ts': [
|
|
217
|
-
"import { defineScope } from '@pikku/core/scope'",
|
|
217
|
+
"import { defineScope } from '@pikku/core/ecosystem/scope'",
|
|
218
218
|
'defineScope({ admin: {} })',
|
|
219
219
|
].join('\n'),
|
|
220
220
|
'scopes.ts': [
|
|
221
|
-
"import { defineScope } from '@pikku/core/scope'",
|
|
221
|
+
"import { defineScope } from '@pikku/core/ecosystem/scope'",
|
|
222
222
|
'defineScope({ billing: {} })',
|
|
223
223
|
].join('\n'),
|
|
224
224
|
})
|
|
@@ -238,7 +238,7 @@ describe('addScope inspector', () => {
|
|
|
238
238
|
test('is critical when a root embeds the separator', async () => {
|
|
239
239
|
const { criticals } = await inspectSource(
|
|
240
240
|
[
|
|
241
|
-
"import { defineScope } from '@pikku/core/scope'",
|
|
241
|
+
"import { defineScope } from '@pikku/core/ecosystem/scope'",
|
|
242
242
|
"defineScope({ 'admin:users': {} })",
|
|
243
243
|
].join('\n')
|
|
244
244
|
)
|
|
@@ -252,7 +252,7 @@ describe('addScope inspector', () => {
|
|
|
252
252
|
test('is critical when a root is the wildcard', async () => {
|
|
253
253
|
const { criticals } = await inspectSource(
|
|
254
254
|
[
|
|
255
|
-
"import { defineScope } from '@pikku/core/scope'",
|
|
255
|
+
"import { defineScope } from '@pikku/core/ecosystem/scope'",
|
|
256
256
|
"defineScope({ '*': {} })",
|
|
257
257
|
].join('\n')
|
|
258
258
|
)
|
|
@@ -266,7 +266,7 @@ describe('addScope inspector', () => {
|
|
|
266
266
|
test('is critical when a root key is not a literal', async () => {
|
|
267
267
|
const { criticals } = await inspectSource(
|
|
268
268
|
[
|
|
269
|
-
"import { defineScope } from '@pikku/core/scope'",
|
|
269
|
+
"import { defineScope } from '@pikku/core/ecosystem/scope'",
|
|
270
270
|
'const k = String(1)',
|
|
271
271
|
'defineScope({ [k]: {} } as any)',
|
|
272
272
|
].join('\n')
|
|
@@ -281,7 +281,7 @@ describe('addScope inspector', () => {
|
|
|
281
281
|
test('is critical when a root is not an object literal', async () => {
|
|
282
282
|
const { criticals } = await inspectSource(
|
|
283
283
|
[
|
|
284
|
-
"import { defineScope } from '@pikku/core/scope'",
|
|
284
|
+
"import { defineScope } from '@pikku/core/ecosystem/scope'",
|
|
285
285
|
"defineScope({ admin: 'nope' } as any)",
|
|
286
286
|
].join('\n')
|
|
287
287
|
)
|
|
@@ -296,7 +296,7 @@ describe('addScope inspector', () => {
|
|
|
296
296
|
describe('validateScopeReferences', () => {
|
|
297
297
|
const funcSource = (scopes: string, decls: string[] = []) =>
|
|
298
298
|
[
|
|
299
|
-
"import { defineScope } from '@pikku/core/scope'",
|
|
299
|
+
"import { defineScope } from '@pikku/core/ecosystem/scope'",
|
|
300
300
|
"import { pikkuSessionlessFunc } from '@pikku/core'",
|
|
301
301
|
...decls,
|
|
302
302
|
'export const f = pikkuSessionlessFunc({',
|
package/src/add/add-scope.ts
CHANGED
|
@@ -2,7 +2,7 @@ import * as ts from 'typescript'
|
|
|
2
2
|
import { getPropertyValue } from '../utils/get-property-value.js'
|
|
3
3
|
import type { AddWiring, InspectorLogger } from '../types.js'
|
|
4
4
|
import { ErrorCode } from '../error-codes.js'
|
|
5
|
-
import type { ScopeNodeMeta } from '@pikku/core/scope'
|
|
5
|
+
import type { ScopeNodeMeta } from '@pikku/core/ecosystem/scope'
|
|
6
6
|
|
|
7
7
|
const SEPARATOR = ':'
|
|
8
8
|
const WILDCARD = '*'
|
|
@@ -55,8 +55,8 @@ const inspectSources = async (sources: Record<string, string>) => {
|
|
|
55
55
|
}
|
|
56
56
|
|
|
57
57
|
const IMPORTS = [
|
|
58
|
-
"import { defineScope } from '@pikku/core/scope'",
|
|
59
|
-
"import { defineSystemRole } from '@pikku/core/role'",
|
|
58
|
+
"import { defineScope } from '@pikku/core/ecosystem/scope'",
|
|
59
|
+
"import { defineSystemRole } from '@pikku/core/ecosystem/role'",
|
|
60
60
|
]
|
|
61
61
|
|
|
62
62
|
const withScopes = (...lines: string[]) =>
|
|
@@ -118,10 +118,10 @@ describe('addSystemRole inspector', () => {
|
|
|
118
118
|
)
|
|
119
119
|
)
|
|
120
120
|
|
|
121
|
-
assert.deepEqual(
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
)
|
|
121
|
+
assert.deepEqual(state.systemRoles.definitions.map((r) => r.name).sort(), [
|
|
122
|
+
'admin',
|
|
123
|
+
'buyer',
|
|
124
|
+
])
|
|
125
125
|
})
|
|
126
126
|
|
|
127
127
|
// Roles follow scopes: a project scaffolding user-admin has a generated
|
|
@@ -132,7 +132,7 @@ describe('addSystemRole inspector', () => {
|
|
|
132
132
|
"defineSystemRole({ buyer: { scopes: ['catalogue:read'] } })"
|
|
133
133
|
),
|
|
134
134
|
'more-roles.ts': [
|
|
135
|
-
"import { defineSystemRole } from '@pikku/core/role'",
|
|
135
|
+
"import { defineSystemRole } from '@pikku/core/ecosystem/role'",
|
|
136
136
|
"defineSystemRole({ admin: { scopes: ['admin'] } })",
|
|
137
137
|
].join('\n'),
|
|
138
138
|
})
|
|
@@ -142,10 +142,10 @@ describe('addSystemRole inspector', () => {
|
|
|
142
142
|
[],
|
|
143
143
|
`expected no duplicate critical, got ${JSON.stringify(criticals)}`
|
|
144
144
|
)
|
|
145
|
-
assert.deepEqual(
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
)
|
|
145
|
+
assert.deepEqual(state.systemRoles.definitions.map((r) => r.name).sort(), [
|
|
146
|
+
'admin',
|
|
147
|
+
'buyer',
|
|
148
|
+
])
|
|
149
149
|
})
|
|
150
150
|
|
|
151
151
|
// A generated file is not the one place a person adds a role to, so it neither
|
|
@@ -153,7 +153,7 @@ describe('addSystemRole inspector', () => {
|
|
|
153
153
|
test('a generated declaration neither claims the slot nor conflicts', async () => {
|
|
154
154
|
const { state, criticals } = await inspectSources({
|
|
155
155
|
'roles.gen.ts': [
|
|
156
|
-
"import { defineSystemRole } from '@pikku/core/role'",
|
|
156
|
+
"import { defineSystemRole } from '@pikku/core/ecosystem/role'",
|
|
157
157
|
'defineSystemRole({ admin: { scopes: [] } })',
|
|
158
158
|
].join('\n'),
|
|
159
159
|
'roles.ts': withScopes(
|
|
@@ -61,11 +61,42 @@ describe('addWireAddon', () => {
|
|
|
61
61
|
secretOverrides: undefined,
|
|
62
62
|
variableOverrides: undefined,
|
|
63
63
|
credentialOverrides: undefined,
|
|
64
|
+
secretGrants: undefined,
|
|
65
|
+
credentialGrants: undefined,
|
|
64
66
|
globalSecrets: undefined,
|
|
65
67
|
globalCredentials: undefined,
|
|
66
68
|
})
|
|
67
69
|
})
|
|
68
70
|
|
|
71
|
+
test('captures the secrets and credentials the host lends an addon', () => {
|
|
72
|
+
const declarations = inspect(`
|
|
73
|
+
wireAddon({
|
|
74
|
+
name: 'graph',
|
|
75
|
+
package: '@pikku/addon-graph',
|
|
76
|
+
secretGrants: ['STRIPE_KEY', 'GITHUB_TOKEN'],
|
|
77
|
+
credentialGrants: ['slack'],
|
|
78
|
+
})
|
|
79
|
+
`)
|
|
80
|
+
|
|
81
|
+
assert.deepEqual(declarations.get('graph').secretGrants, [
|
|
82
|
+
'STRIPE_KEY',
|
|
83
|
+
'GITHUB_TOKEN',
|
|
84
|
+
])
|
|
85
|
+
assert.deepEqual(declarations.get('graph').credentialGrants, ['slack'])
|
|
86
|
+
})
|
|
87
|
+
|
|
88
|
+
test('drops a grant list that is not statically knowable', () => {
|
|
89
|
+
const declarations = inspect(`
|
|
90
|
+
wireAddon({
|
|
91
|
+
name: 'graph',
|
|
92
|
+
package: '@pikku/addon-graph',
|
|
93
|
+
secretGrants: someRuntimeList,
|
|
94
|
+
})
|
|
95
|
+
`)
|
|
96
|
+
|
|
97
|
+
assert.equal(declarations.get('graph').secretGrants, undefined)
|
|
98
|
+
})
|
|
99
|
+
|
|
69
100
|
test('captures the reason an addon was exempted from credential scoping', () => {
|
|
70
101
|
const declarations = inspect(`
|
|
71
102
|
wireAddon({
|