@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.
Files changed (103) hide show
  1. package/CHANGELOG.md +127 -0
  2. package/dist/add/add-agent-scorer.d.ts +2 -0
  3. package/dist/add/add-agent-scorer.js +61 -0
  4. package/dist/add/add-agent.d.ts +4 -0
  5. package/dist/add/add-agent.js +442 -0
  6. package/dist/add/add-channel.d.ts +1 -1
  7. package/dist/add/add-functions.js +1 -1
  8. package/dist/add/add-keyed-wiring.js +1 -1
  9. package/dist/add/add-middleware.js +5 -5
  10. package/dist/add/add-personas.js +1 -1
  11. package/dist/add/add-wire-addon.js +10 -0
  12. package/dist/add/add-workflow.d.ts +1 -1
  13. package/dist/error-codes.d.ts +1 -0
  14. package/dist/error-codes.js +1 -0
  15. package/dist/inspector.js +1 -1
  16. package/dist/types.d.ts +27 -22
  17. package/dist/utils/compute-required-schemas.d.ts +1 -1
  18. package/dist/utils/contract-hashes.d.ts +2 -1
  19. package/dist/utils/contract-hashes.js +1 -1
  20. package/dist/utils/extract-function-name.js +1 -1
  21. package/dist/utils/extract-services.d.ts +1 -1
  22. package/dist/utils/filter-inspector-state.js +1 -1
  23. package/dist/utils/filter-utils.d.ts +1 -1
  24. package/dist/utils/middleware.d.ts +2 -2
  25. package/dist/utils/middleware.js +5 -5
  26. package/dist/utils/permissions.d.ts +1 -1
  27. package/dist/utils/post-process.d.ts +2 -2
  28. package/dist/utils/post-process.js +24 -12
  29. package/dist/utils/resolve-deploy-target.d.ts +1 -1
  30. package/dist/utils/resolve-function-meta.d.ts +1 -1
  31. package/dist/utils/resolve-function-types.d.ts +1 -1
  32. package/dist/utils/resolve-versions.js +1 -1
  33. package/dist/utils/schema-generator.d.ts +1 -1
  34. package/dist/utils/serialize-inspector-state.d.ts +5 -3
  35. package/dist/utils/serialize-inspector-state.js +4 -4
  36. package/dist/utils/serialize-openapi-json.d.ts +2 -2
  37. package/dist/utils/workflow/derive-workflow-plan.d.ts +1 -1
  38. package/dist/utils/workflow/dsl/extract-dsl-workflow.d.ts +1 -1
  39. package/dist/utils/workflow/graph/convert-dsl-to-graph.d.ts +1 -1
  40. package/dist/utils/workflow/graph/finalize-workflows.js +1 -1
  41. package/dist/utils/workflow/graph/serialize-workflow-graph.js +1 -1
  42. package/dist/utils/workflow/graph/workflow-graph.types.d.ts +2 -1
  43. package/dist/visit.js +4 -4
  44. package/package.json +3 -3
  45. package/src/add/{add-ai-scorer.test.ts → add-agent-scorer.test.ts} +11 -11
  46. package/src/add/{add-ai-scorer.ts → add-agent-scorer.ts} +4 -4
  47. package/src/add/{add-ai-agent.test.ts → add-agent.test.ts} +1 -1
  48. package/src/add/{add-ai-agent.ts → add-agent.ts} +11 -17
  49. package/src/add/add-auth.ts +1 -1
  50. package/src/add/add-channel.ts +4 -1
  51. package/src/add/add-cli.ts +1 -1
  52. package/src/add/add-functions.ts +9 -4
  53. package/src/add/add-gateway.ts +1 -1
  54. package/src/add/add-http-route.ts +1 -1
  55. package/src/add/add-keyed-wiring.ts +1 -1
  56. package/src/add/add-middleware.ts +7 -5
  57. package/src/add/add-permission.ts +1 -1
  58. package/src/add/add-personas.test.ts +2 -2
  59. package/src/add/add-personas.ts +3 -2
  60. package/src/add/add-scenario-step.test.ts +2 -1
  61. package/src/add/add-scope.test.ts +19 -19
  62. package/src/add/add-scope.ts +1 -1
  63. package/src/add/add-system-role.test.ts +12 -12
  64. package/src/add/add-wire-addon.test.ts +31 -0
  65. package/src/add/add-wire-addon.ts +8 -0
  66. package/src/add/add-workflow-graph-input.test.ts +1 -1
  67. package/src/add/add-workflow.ts +4 -1
  68. package/src/add/addon-contracts.test.ts +1 -1
  69. package/src/error-codes.ts +1 -0
  70. package/src/inspector.ts +1 -1
  71. package/src/types.ts +33 -23
  72. package/src/utils/compute-required-schemas.ts +1 -1
  73. package/src/utils/contract-hashes.test.ts +1 -1
  74. package/src/utils/contract-hashes.ts +3 -2
  75. package/src/utils/extract-function-name.ts +1 -1
  76. package/src/utils/extract-services.ts +4 -1
  77. package/src/utils/filter-inspector-state.ts +2 -2
  78. package/src/utils/filter-utils.ts +1 -1
  79. package/src/utils/middleware.test.ts +23 -23
  80. package/src/utils/middleware.ts +6 -6
  81. package/src/utils/permissions.ts +1 -1
  82. package/src/utils/post-process.test.ts +76 -9
  83. package/src/utils/post-process.ts +36 -14
  84. package/src/utils/resolve-deploy-target.ts +1 -1
  85. package/src/utils/resolve-function-meta.ts +4 -1
  86. package/src/utils/resolve-function-types.ts +1 -1
  87. package/src/utils/resolve-versions.ts +5 -2
  88. package/src/utils/schema-generator.ts +3 -2
  89. package/src/utils/serialize-inspector-state.ts +9 -7
  90. package/src/utils/serialize-mcp-json.ts +1 -1
  91. package/src/utils/serialize-openapi-json.ts +2 -2
  92. package/src/utils/workflow/derive-workflow-plan.test.ts +1 -1
  93. package/src/utils/workflow/derive-workflow-plan.ts +1 -1
  94. package/src/utils/workflow/dsl/extract-approval-policy.test.ts +5 -2
  95. package/src/utils/workflow/dsl/extract-dsl-workflow.ts +2 -2
  96. package/src/utils/workflow/graph/convert-dsl-to-graph-skip.test.ts +1 -1
  97. package/src/utils/workflow/graph/convert-dsl-to-graph.ts +4 -1
  98. package/src/utils/workflow/graph/finalize-workflow-wires.ts +1 -1
  99. package/src/utils/workflow/graph/finalize-workflows.ts +6 -2
  100. package/src/utils/workflow/graph/serialize-workflow-graph.ts +1 -1
  101. package/src/utils/workflow/graph/workflow-graph.types.ts +2 -2
  102. package/src/visit.ts +4 -4
  103. 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-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
 
@@ -579,7 +573,7 @@ export const addAIAgent: AddWiring = (
579
573
  tags,
580
574
  checker
581
575
  )
582
- const aiMiddleware = resolveAIMiddleware(state, obj, checker)
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
- aiMiddleware,
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
- 'aiStorage',
636
- 'aiRunState',
629
+ 'agentStorage',
630
+ 'agentRunState',
637
631
  'agentRunService',
638
- 'aiAgentRunner',
632
+ 'agentRunner',
639
633
  ]) {
640
634
  if (!funcMeta.services.services.includes(svc)) {
641
635
  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/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'
@@ -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 { ChannelMessageMeta, ChannelMeta } from '@pikku/core/channel'
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,
@@ -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,
@@ -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, FunctionServicesMeta } from '@pikku/core'
12
- import type { ScenarioStepKind, ScenarioSurface } from '@pikku/core/workflow'
13
- import { formatVersionedId, parseVersionedId } from '@pikku/core'
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_$]*$/
@@ -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 === 'pikkuAIMiddleware') {
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(`• pikkuAIMiddleware() requires an object literal argument.`)
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
- `• pikkuAIMiddleware() must be assigned to a variable or object property. ` +
748
- `Extract it to a const: const myMiddleware = pikkuAIMiddleware(...)`
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.aiMiddleware.definitions[pikkuFuncId] = {
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({',
@@ -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 { PersonaAccountMeta, PersonaMeta } from '@pikku/core/persona'
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 { ScenarioStepMeta, WorkflowStepMeta } from '@pikku/core/workflow'
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
- state.scopes.definitions.map((d) => d.name).sort(),
207
- ['admin', 'billing']
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({',
@@ -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
- state.systemRoles.definitions.map((r) => r.name).sort(),
123
- ['admin', 'buyer']
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
- state.systemRoles.definitions.map((r) => r.name).sort(),
147
- ['admin', 'buyer']
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({