@pikku/inspector 0.12.42 → 0.12.43
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 +98 -0
- package/dist/add/add-addon-bans.js +1 -0
- package/dist/add/add-ai-agent.d.ts +3 -1
- package/dist/add/add-ai-agent.js +82 -0
- package/dist/add/add-credential.js +3 -1
- package/dist/add/add-functions.js +10 -9
- package/dist/add/add-gateway.js +3 -0
- package/dist/add/add-http-route.js +2 -2
- package/dist/add/add-mcp-prompt.js +0 -1
- package/dist/add/add-mcp-resource.js +0 -1
- package/dist/add/add-permission.d.ts +1 -1
- package/dist/add/add-permission.js +3 -177
- package/dist/add/add-queue-worker.js +3 -0
- package/dist/add/add-schedule.js +3 -0
- package/dist/add/add-scope.d.ts +2 -0
- package/dist/add/add-scope.js +146 -0
- package/dist/add/add-trigger.js +3 -0
- package/dist/add/add-wire-remote-addon.d.ts +10 -0
- package/dist/add/add-wire-remote-addon.js +66 -0
- package/dist/add/add-workflow-graph.js +32 -3
- package/dist/error-codes.d.ts +3 -0
- package/dist/error-codes.js +4 -0
- package/dist/inspector.js +11 -5
- package/dist/types.d.ts +19 -13
- package/dist/utils/custom-types-generator.js +2 -1
- package/dist/utils/ensure-function-metadata.d.ts +15 -0
- package/dist/utils/ensure-function-metadata.js +24 -0
- package/dist/utils/filter-inspector-state.js +9 -0
- package/dist/utils/get-property-value.d.ts +7 -2
- package/dist/utils/get-property-value.js +48 -1
- package/dist/utils/load-addon-functions-meta.js +81 -6
- package/dist/utils/permissions.d.ts +1 -21
- package/dist/utils/permissions.js +17 -108
- package/dist/utils/post-process.d.ts +30 -1
- package/dist/utils/post-process.js +150 -72
- package/dist/utils/serialize-inspector-state.d.ts +13 -8
- package/dist/utils/serialize-inspector-state.js +12 -6
- package/dist/utils/serialize-permissions-groups-meta.d.ts +0 -2
- package/dist/utils/serialize-permissions-groups-meta.js +0 -26
- package/dist/utils/workflow/derive-workflow-plan.js +9 -3
- package/dist/utils/workflow/dsl/extract-dsl-workflow.js +56 -1
- package/dist/utils/workflow/dsl/patterns.d.ts +4 -0
- package/dist/utils/workflow/dsl/patterns.js +11 -0
- package/dist/utils/workflow/graph/convert-dsl-to-graph.js +14 -0
- package/dist/utils/workflow/graph/finalize-workflows.d.ts +7 -0
- package/dist/utils/workflow/graph/finalize-workflows.js +11 -2
- package/dist/utils/workflow/graph/serialize-workflow-graph.d.ts +2 -0
- package/dist/utils/workflow/graph/serialize-workflow-graph.js +4 -0
- package/dist/utils/workflow/graph/workflow-graph.types.d.ts +6 -2
- package/dist/visit.js +4 -0
- package/package.json +3 -3
- package/src/add/add-addon-bans.ts +1 -0
- package/src/add/add-ai-agent.test.ts +87 -0
- package/src/add/add-ai-agent.ts +122 -0
- package/src/add/add-credential.ts +6 -0
- package/src/add/add-functions.ts +10 -12
- package/src/add/add-gateway.ts +11 -0
- package/src/add/add-http-route.ts +2 -8
- package/src/add/add-mcp-prompt.ts +0 -1
- package/src/add/add-mcp-resource.ts +0 -1
- package/src/add/add-permission.ts +4 -242
- package/src/add/add-queue-worker.ts +11 -0
- package/src/add/add-schedule.ts +11 -0
- package/src/add/add-scope.test.ts +346 -0
- package/src/add/add-scope.ts +225 -0
- package/src/add/add-trigger.ts +11 -0
- package/src/add/add-wire-remote-addon.ts +77 -0
- package/src/add/add-workflow-graph-input.test.ts +94 -0
- package/src/add/add-workflow-graph-notes.test.ts +74 -0
- package/src/add/add-workflow-graph.ts +35 -3
- package/src/add/inline-wiring-function.test.ts +104 -0
- package/src/add/validate-workflow-graph-addons.test.ts +102 -0
- package/src/error-codes.ts +5 -0
- package/src/inspector.ts +14 -4
- package/src/types.ts +16 -17
- package/src/utils/custom-types-generator.test.ts +26 -1
- package/src/utils/custom-types-generator.ts +2 -1
- package/src/utils/ensure-function-metadata.ts +42 -0
- package/src/utils/filter-inspector-state.test.ts +0 -2
- package/src/utils/filter-inspector-state.ts +9 -0
- package/src/utils/get-property-value.test.ts +141 -0
- package/src/utils/get-property-value.ts +62 -1
- package/src/utils/load-addon-functions-meta.test.ts +157 -0
- package/src/utils/load-addon-functions-meta.ts +94 -6
- package/src/utils/load-addon-scopes.test.ts +138 -0
- package/src/utils/permissions.test.ts +7 -232
- package/src/utils/permissions.ts +20 -160
- package/src/utils/post-process.test.ts +269 -4
- package/src/utils/post-process.ts +216 -95
- package/src/utils/serialize-inspector-state.ts +22 -25
- package/src/utils/serialize-permissions-groups-meta.ts +0 -28
- package/src/utils/workflow/derive-workflow-plan.test.ts +41 -3
- package/src/utils/workflow/derive-workflow-plan.ts +11 -4
- package/src/utils/workflow/dsl/extract-dsl-workflow.ts +66 -0
- package/src/utils/workflow/dsl/patterns.ts +18 -0
- package/src/utils/workflow/graph/convert-dsl-to-graph.ts +15 -0
- package/src/utils/workflow/graph/finalize-workflows.test.ts +50 -0
- package/src/utils/workflow/graph/finalize-workflows.ts +13 -2
- package/src/utils/workflow/graph/serialize-workflow-graph.ts +6 -0
- package/src/utils/workflow/graph/workflow-graph.types.ts +8 -0
- package/src/visit.ts +4 -0
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -80,11 +80,20 @@ function computeStepHashes(graph, functionsMeta) {
|
|
|
80
80
|
node.stepHash = hashString(`${node.nodeId}:${meta?.contractHash ?? ''}`, 12);
|
|
81
81
|
}
|
|
82
82
|
}
|
|
83
|
-
|
|
83
|
+
/**
|
|
84
|
+
* Hash of graph topology only. `notes` (node- and graph-level) is deliberately
|
|
85
|
+
* excluded so editing documentation never changes the hash / marks the workflow
|
|
86
|
+
* as a new version.
|
|
87
|
+
*/
|
|
88
|
+
export function computeGraphHash(graph) {
|
|
89
|
+
const nodesForHash = Object.fromEntries(Object.entries(graph.nodes).map(([nodeId, node]) => {
|
|
90
|
+
const { notes: _notes, ...rest } = node;
|
|
91
|
+
return [nodeId, rest];
|
|
92
|
+
}));
|
|
84
93
|
return hashString(canonicalJSON({
|
|
85
94
|
source: graph.source,
|
|
86
95
|
context: graph.context,
|
|
87
|
-
nodes:
|
|
96
|
+
nodes: nodesForHash,
|
|
88
97
|
entryNodeIds: graph.entryNodeIds,
|
|
89
98
|
}), 12);
|
|
90
99
|
}
|
|
@@ -14,10 +14,12 @@ export declare function serializeWorkflowGraph(definition: {
|
|
|
14
14
|
input?: (ref: any) => Record<string, unknown>;
|
|
15
15
|
next?: string | string[] | Record<string, string | string[]>;
|
|
16
16
|
onError?: string | string[];
|
|
17
|
+
notes?: string;
|
|
17
18
|
}>;
|
|
18
19
|
}, options?: {
|
|
19
20
|
description?: string;
|
|
20
21
|
tags?: string[];
|
|
22
|
+
notes?: string[];
|
|
21
23
|
}): SerializedWorkflowGraph;
|
|
22
24
|
/**
|
|
23
25
|
* Deserialize a workflow graph from JSON to runtime format
|
|
@@ -108,6 +108,9 @@ export function serializeWorkflowGraph(definition, options) {
|
|
|
108
108
|
next: serializeNext(node.next),
|
|
109
109
|
onError: node.onError,
|
|
110
110
|
};
|
|
111
|
+
if (node.notes !== undefined) {
|
|
112
|
+
funcNode.notes = node.notes;
|
|
113
|
+
}
|
|
111
114
|
nodes[nodeId] = funcNode;
|
|
112
115
|
// Entry nodes have no incoming edges
|
|
113
116
|
if (!hasIncomingEdge.has(nodeId)) {
|
|
@@ -120,6 +123,7 @@ export function serializeWorkflowGraph(definition, options) {
|
|
|
120
123
|
source: 'graph',
|
|
121
124
|
description: options?.description,
|
|
122
125
|
tags: options?.tags,
|
|
126
|
+
notes: options?.notes,
|
|
123
127
|
nodes,
|
|
124
128
|
entryNodeIds,
|
|
125
129
|
};
|
|
@@ -51,7 +51,7 @@ export type SerializedNext = string | string[] | {
|
|
|
51
51
|
conditions: BranchCondition[];
|
|
52
52
|
/** Default target if no conditions match */
|
|
53
53
|
default?: string | string[];
|
|
54
|
-
}
|
|
54
|
+
} | Record<string, string | string[]>;
|
|
55
55
|
/**
|
|
56
56
|
* Node execution options
|
|
57
57
|
*/
|
|
@@ -66,7 +66,7 @@ export interface NodeOptions {
|
|
|
66
66
|
/**
|
|
67
67
|
* Flow node types for control flow (no RPC call)
|
|
68
68
|
*/
|
|
69
|
-
export type FlowType = 'sleep' | 'branch' | 'parallel' | 'fanout' | 'inline' | 'switch' | 'filter' | 'arrayPredicate' | 'return' | 'cancel' | 'set';
|
|
69
|
+
export type FlowType = 'sleep' | 'approval' | 'branch' | 'parallel' | 'fanout' | 'inline' | 'switch' | 'filter' | 'arrayPredicate' | 'return' | 'cancel' | 'set';
|
|
70
70
|
import type { ContextVariable, WorkflowContext, WorkflowPlannedStep } from '@pikku/core/workflow';
|
|
71
71
|
export type { ContextVariable, WorkflowContext };
|
|
72
72
|
/**
|
|
@@ -83,6 +83,8 @@ interface BaseNode {
|
|
|
83
83
|
onError?: string | string[];
|
|
84
84
|
/** Execution options */
|
|
85
85
|
options?: NodeOptions;
|
|
86
|
+
/** Free-text node documentation. Non-semantic — excluded from graphHash. */
|
|
87
|
+
notes?: string;
|
|
86
88
|
}
|
|
87
89
|
/**
|
|
88
90
|
* Function node - calls an RPC
|
|
@@ -154,6 +156,8 @@ export interface SerializedWorkflowGraph {
|
|
|
154
156
|
context?: WorkflowContext;
|
|
155
157
|
/** Serialized nodes */
|
|
156
158
|
nodes: Record<string, SerializedGraphNode>;
|
|
159
|
+
/** Graph-level free-text notes (e.g. imported sticky notes). Non-semantic — excluded from graphHash. */
|
|
160
|
+
notes?: string[];
|
|
157
161
|
/** Entry node(s) - first nodes to execute */
|
|
158
162
|
entryNodeIds: string[];
|
|
159
163
|
/** Hash of graph topology (nodes, edges, input mappings) */
|
package/dist/visit.js
CHANGED
|
@@ -15,12 +15,14 @@ import { addChannel } from './add/add-channel.js';
|
|
|
15
15
|
import { addGateway } from './add/add-gateway.js';
|
|
16
16
|
import { addRPCInvocations } from './add/add-rpc-invocations.js';
|
|
17
17
|
import { addWireAddon } from './add/add-wire-addon.js';
|
|
18
|
+
import { addWireRemoteAddon } from './add/add-wire-remote-addon.js';
|
|
18
19
|
import { addMiddleware } from './add/add-middleware.js';
|
|
19
20
|
import { addPermission } from './add/add-permission.js';
|
|
20
21
|
import { addCLI, addCLIRenderers } from './add/add-cli.js';
|
|
21
22
|
import { addAuth } from './add/add-auth.js';
|
|
22
23
|
import { addSecret } from './add/add-secret.js';
|
|
23
24
|
import { addCredential } from './add/add-credential.js';
|
|
25
|
+
import { addScope } from './add/add-scope.js';
|
|
24
26
|
import { addVariable } from './add/add-variable.js';
|
|
25
27
|
import { addWorkflowGraph } from './add/add-workflow-graph.js';
|
|
26
28
|
import { addAIAgent } from './add/add-ai-agent.js';
|
|
@@ -36,6 +38,7 @@ export const visitSetup = (logger, checker, node, state, options) => {
|
|
|
36
38
|
addFileWithFactory(node, checker, state.serverLifecycleFactories, 'ServerLifecycle');
|
|
37
39
|
addRPCInvocations(node, state, logger);
|
|
38
40
|
addWireAddon(node, state, logger);
|
|
41
|
+
addWireRemoteAddon(node, state, logger);
|
|
39
42
|
addMiddleware(logger, node, checker, state, options);
|
|
40
43
|
addPermission(logger, node, checker, state, options);
|
|
41
44
|
addApprovalDescription(logger, node, checker, state, options);
|
|
@@ -64,6 +67,7 @@ export const visitRoutes = (logger, checker, node, state, options) => {
|
|
|
64
67
|
addAuth(logger, node, checker, state, nextOptions);
|
|
65
68
|
addSecret(logger, node, checker, state, nextOptions);
|
|
66
69
|
addCredential(logger, node, checker, state, nextOptions);
|
|
70
|
+
addScope(logger, node, checker, state, nextOptions);
|
|
67
71
|
addVariable(logger, node, checker, state, nextOptions);
|
|
68
72
|
addHTTPRoute(logger, node, checker, state, nextOptions);
|
|
69
73
|
addHTTPRoutes(logger, node, checker, state, nextOptions);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pikku/inspector",
|
|
3
|
-
"version": "0.12.
|
|
3
|
+
"version": "0.12.43",
|
|
4
4
|
"author": "yasser.fadl@gmail.com",
|
|
5
5
|
"license": "BUSL-1.1",
|
|
6
6
|
"type": "module",
|
|
@@ -44,10 +44,10 @@
|
|
|
44
44
|
"zod-to-ts": "^2.1.0"
|
|
45
45
|
},
|
|
46
46
|
"peerDependencies": {
|
|
47
|
-
"@pikku/core": "^0.12.
|
|
47
|
+
"@pikku/core": "^0.12.64"
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {
|
|
50
|
-
"@pikku/core": "^0.12.
|
|
50
|
+
"@pikku/core": "^0.12.64",
|
|
51
51
|
"@types/node": "^24.11.0"
|
|
52
52
|
},
|
|
53
53
|
"engines": {
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { describe, test } from 'node:test'
|
|
2
|
+
import assert from 'node:assert'
|
|
3
|
+
import * as ts from 'typescript'
|
|
4
|
+
|
|
5
|
+
import { resolveWorkflowReferences } from './add-ai-agent.js'
|
|
6
|
+
import type { InspectorLogger } from '../types.js'
|
|
7
|
+
|
|
8
|
+
function createSourceFile(code: string): ts.SourceFile {
|
|
9
|
+
return ts.createSourceFile('test.ts', code, ts.ScriptTarget.ESNext, true)
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function getObjectLiteral(
|
|
13
|
+
sourceFile: ts.SourceFile
|
|
14
|
+
): ts.ObjectLiteralExpression {
|
|
15
|
+
let result: ts.ObjectLiteralExpression | undefined
|
|
16
|
+
ts.forEachChild(sourceFile, function visit(node) {
|
|
17
|
+
if (ts.isObjectLiteralExpression(node) && !result) {
|
|
18
|
+
result = node
|
|
19
|
+
}
|
|
20
|
+
ts.forEachChild(node, visit)
|
|
21
|
+
})
|
|
22
|
+
if (!result) throw new Error('No object literal found')
|
|
23
|
+
return result
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function createLogger(): {
|
|
27
|
+
logger: InspectorLogger
|
|
28
|
+
criticals: Array<{ code: unknown; message: string }>
|
|
29
|
+
} {
|
|
30
|
+
const criticals: Array<{ code: unknown; message: string }> = []
|
|
31
|
+
const logger = {
|
|
32
|
+
info: () => {},
|
|
33
|
+
error: () => {},
|
|
34
|
+
warn: () => {},
|
|
35
|
+
debug: () => {},
|
|
36
|
+
diagnostic: () => {},
|
|
37
|
+
critical: (code: unknown, message: string) =>
|
|
38
|
+
criticals.push({ code, message }),
|
|
39
|
+
hasCriticalErrors: () => criticals.length > 0,
|
|
40
|
+
} as unknown as InspectorLogger
|
|
41
|
+
return { logger, criticals }
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
describe('resolveWorkflowReferences', () => {
|
|
45
|
+
test('returns null when no workflows property exists', () => {
|
|
46
|
+
const obj = getObjectLiteral(createSourceFile('const x = { name: "a" }'))
|
|
47
|
+
const { logger } = createLogger()
|
|
48
|
+
assert.strictEqual(
|
|
49
|
+
resolveWorkflowReferences(obj, {} as any, 'a', logger),
|
|
50
|
+
null
|
|
51
|
+
)
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
test('returns null for an empty workflows array', () => {
|
|
55
|
+
const obj = getObjectLiteral(
|
|
56
|
+
createSourceFile('const x = { workflows: [] }')
|
|
57
|
+
)
|
|
58
|
+
const { logger } = createLogger()
|
|
59
|
+
assert.strictEqual(
|
|
60
|
+
resolveWorkflowReferences(obj, {} as any, 'a', logger),
|
|
61
|
+
null
|
|
62
|
+
)
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
test('resolves ref() and workflow() string-literal references', () => {
|
|
66
|
+
const obj = getObjectLiteral(
|
|
67
|
+
createSourceFile(
|
|
68
|
+
`const x = { workflows: [ref('buildReport'), workflow('country_capitals')] }`
|
|
69
|
+
)
|
|
70
|
+
)
|
|
71
|
+
const { logger, criticals } = createLogger()
|
|
72
|
+
const result = resolveWorkflowReferences(obj, {} as any, 'planner', logger)
|
|
73
|
+
assert.deepStrictEqual(result, ['buildReport', 'country_capitals'])
|
|
74
|
+
assert.strictEqual(criticals.length, 0)
|
|
75
|
+
})
|
|
76
|
+
|
|
77
|
+
test('flags a raw string literal as a critical error', () => {
|
|
78
|
+
const obj = getObjectLiteral(
|
|
79
|
+
createSourceFile(`const x = { workflows: ['buildReport'] }`)
|
|
80
|
+
)
|
|
81
|
+
const { logger, criticals } = createLogger()
|
|
82
|
+
const result = resolveWorkflowReferences(obj, {} as any, 'planner', logger)
|
|
83
|
+
assert.strictEqual(result, null)
|
|
84
|
+
assert.strictEqual(criticals.length, 1)
|
|
85
|
+
assert.match(criticals[0].message, /string literal/)
|
|
86
|
+
})
|
|
87
|
+
})
|
package/src/add/add-ai-agent.ts
CHANGED
|
@@ -142,6 +142,114 @@ function resolveAgentReferences(
|
|
|
142
142
|
return resolved.length > 0 ? resolved : null
|
|
143
143
|
}
|
|
144
144
|
|
|
145
|
+
export function resolveWorkflowReferences(
|
|
146
|
+
obj: ts.ObjectLiteralExpression,
|
|
147
|
+
checker: ts.TypeChecker,
|
|
148
|
+
agentName: string,
|
|
149
|
+
logger: InspectorLogger
|
|
150
|
+
): string[] | null {
|
|
151
|
+
const property = obj.properties.find(
|
|
152
|
+
(p) =>
|
|
153
|
+
ts.isPropertyAssignment(p) &&
|
|
154
|
+
ts.isIdentifier(p.name) &&
|
|
155
|
+
p.name.text === 'workflows'
|
|
156
|
+
)
|
|
157
|
+
|
|
158
|
+
if (!property || !ts.isPropertyAssignment(property)) {
|
|
159
|
+
return null
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
const initializer = property.initializer
|
|
163
|
+
if (!ts.isArrayLiteralExpression(initializer)) {
|
|
164
|
+
return null
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
const resolved: string[] = []
|
|
168
|
+
|
|
169
|
+
for (const element of initializer.elements) {
|
|
170
|
+
if (ts.isStringLiteral(element)) {
|
|
171
|
+
logger.critical(
|
|
172
|
+
ErrorCode.INVALID_VALUE,
|
|
173
|
+
`AI agent '${agentName}' workflows array contains a string literal '${element.text}'. ` +
|
|
174
|
+
`Use a workflow reference instead (e.g., ref('<workflowName>') or import the pikkuWorkflowGraph variable).`
|
|
175
|
+
)
|
|
176
|
+
continue
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
if (ts.isCallExpression(element) && ts.isIdentifier(element.expression)) {
|
|
180
|
+
const calleeName = element.expression.text
|
|
181
|
+
if (calleeName === 'ref' || calleeName === 'workflow') {
|
|
182
|
+
const [firstArg] = element.arguments
|
|
183
|
+
if (firstArg && ts.isStringLiteral(firstArg)) {
|
|
184
|
+
resolved.push(firstArg.text)
|
|
185
|
+
continue
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
if (ts.isIdentifier(element)) {
|
|
191
|
+
const name = resolveIdentifierToWorkflowName(element, checker)
|
|
192
|
+
if (name) {
|
|
193
|
+
resolved.push(name)
|
|
194
|
+
continue
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
logger.critical(
|
|
198
|
+
ErrorCode.INVALID_VALUE,
|
|
199
|
+
`AI agent '${agentName}' workflows array contains identifier '${element.text}' ` +
|
|
200
|
+
`that could not be resolved to a pikkuWorkflowGraph.`
|
|
201
|
+
)
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
return resolved.length > 0 ? resolved : null
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
function resolveIdentifierToWorkflowName(
|
|
209
|
+
identifier: ts.Identifier,
|
|
210
|
+
checker: ts.TypeChecker
|
|
211
|
+
): string | null {
|
|
212
|
+
const symbol = checker.getSymbolAtLocation(identifier)
|
|
213
|
+
if (!symbol) return null
|
|
214
|
+
|
|
215
|
+
let resolved = symbol
|
|
216
|
+
if (resolved.flags & ts.SymbolFlags.Alias) {
|
|
217
|
+
resolved = checker.getAliasedSymbol(resolved) ?? resolved
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
const decl = resolved.valueDeclaration ?? resolved.declarations?.[0]
|
|
221
|
+
if (!decl) return null
|
|
222
|
+
|
|
223
|
+
if (ts.isVariableDeclaration(decl) && decl.initializer) {
|
|
224
|
+
if (
|
|
225
|
+
ts.isCallExpression(decl.initializer) &&
|
|
226
|
+
ts.isIdentifier(decl.initializer.expression) &&
|
|
227
|
+
(decl.initializer.expression.text === 'pikkuWorkflowGraph' ||
|
|
228
|
+
decl.initializer.expression.text === 'pikkuWorkflow' ||
|
|
229
|
+
decl.initializer.expression.text === 'pikkuWorkflowComplex')
|
|
230
|
+
) {
|
|
231
|
+
const firstArg = decl.initializer.arguments[0]
|
|
232
|
+
if (firstArg && ts.isObjectLiteralExpression(firstArg)) {
|
|
233
|
+
for (const prop of firstArg.properties) {
|
|
234
|
+
if (
|
|
235
|
+
ts.isPropertyAssignment(prop) &&
|
|
236
|
+
ts.isIdentifier(prop.name) &&
|
|
237
|
+
prop.name.text === 'name' &&
|
|
238
|
+
ts.isStringLiteral(prop.initializer)
|
|
239
|
+
) {
|
|
240
|
+
return prop.initializer.text
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
if (ts.isIdentifier(decl.name)) {
|
|
245
|
+
return decl.name.text
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
return null
|
|
251
|
+
}
|
|
252
|
+
|
|
145
253
|
function resolveIdentifierToRpcName(
|
|
146
254
|
identifier: ts.Identifier,
|
|
147
255
|
checker: ts.TypeChecker
|
|
@@ -293,6 +401,19 @@ export const addAIAgent: AddWiring = (
|
|
|
293
401
|
logger
|
|
294
402
|
)
|
|
295
403
|
|
|
404
|
+
const workflowsValue = resolveWorkflowReferences(
|
|
405
|
+
obj,
|
|
406
|
+
checker,
|
|
407
|
+
nameValue || '',
|
|
408
|
+
logger
|
|
409
|
+
)
|
|
410
|
+
|
|
411
|
+
if (workflowsValue) {
|
|
412
|
+
for (const workflowName of workflowsValue) {
|
|
413
|
+
state.workflows.invokedWorkflows.add(workflowName)
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
|
|
296
417
|
if (!nameValue) {
|
|
297
418
|
logger.critical(
|
|
298
419
|
ErrorCode.MISSING_NAME,
|
|
@@ -460,6 +581,7 @@ export const addAIAgent: AddWiring = (
|
|
|
460
581
|
}),
|
|
461
582
|
...(toolsValue !== null && { tools: toolsValue }),
|
|
462
583
|
...(agentsValue !== null && { agents: agentsValue }),
|
|
584
|
+
...(workflowsValue !== null && { workflows: workflowsValue }),
|
|
463
585
|
tags,
|
|
464
586
|
inputSchema,
|
|
465
587
|
outputSchema,
|
|
@@ -2,6 +2,7 @@ import * as ts from 'typescript'
|
|
|
2
2
|
import {
|
|
3
3
|
getPropertyValue,
|
|
4
4
|
getArrayPropertyValue,
|
|
5
|
+
getRecordPropertyValue,
|
|
5
6
|
assertStringLiteralProperty,
|
|
6
7
|
} from '../utils/get-property-value.js'
|
|
7
8
|
import type { AddWiring } from '../types.js'
|
|
@@ -133,6 +134,10 @@ export const addCredential: AddWiring = (
|
|
|
133
134
|
const tokenUrl = getPropertyValue(oauth2Obj, 'tokenUrl') as string | null
|
|
134
135
|
const scopes = getArrayPropertyValue(oauth2Obj, 'scopes')
|
|
135
136
|
const pkce = getPropertyValue(oauth2Obj, 'pkce') as boolean | null
|
|
137
|
+
const additionalParams = getRecordPropertyValue(
|
|
138
|
+
oauth2Obj,
|
|
139
|
+
'additionalParams'
|
|
140
|
+
)
|
|
136
141
|
|
|
137
142
|
if (appCredentialSecretId && authorizationUrl && tokenUrl && scopes) {
|
|
138
143
|
oauth2 = {
|
|
@@ -142,6 +147,7 @@ export const addCredential: AddWiring = (
|
|
|
142
147
|
tokenUrl,
|
|
143
148
|
scopes,
|
|
144
149
|
pkce: pkce || undefined,
|
|
150
|
+
additionalParams: additionalParams || undefined,
|
|
145
151
|
}
|
|
146
152
|
}
|
|
147
153
|
}
|
package/src/add/add-functions.ts
CHANGED
|
@@ -12,6 +12,7 @@ import type { FunctionServicesMeta } from '@pikku/core'
|
|
|
12
12
|
import { formatVersionedId, parseVersionedId } from '@pikku/core'
|
|
13
13
|
import {
|
|
14
14
|
getPropertyValue,
|
|
15
|
+
getArrayPropertyValue,
|
|
15
16
|
getCommonWireMetaData,
|
|
16
17
|
} from '../utils/get-property-value.js'
|
|
17
18
|
import { canonicalJSON, hashString } from '../utils/hash.js'
|
|
@@ -426,6 +427,7 @@ export const addFunctions: AddWiring = (
|
|
|
426
427
|
let workflowQueued: boolean | undefined
|
|
427
428
|
let workflowRetries: number | undefined
|
|
428
429
|
let workflowTimeout: string | undefined
|
|
430
|
+
let scopes: string[] | undefined
|
|
429
431
|
let version: number | undefined
|
|
430
432
|
let objectNode: ts.ObjectLiteralExpression | undefined
|
|
431
433
|
let nodeDisplayName: string | null = null
|
|
@@ -530,6 +532,7 @@ export const addFunctions: AddWiring = (
|
|
|
530
532
|
workflowTimeout = getPropertyValue(firstArg, 'workflowTimeout') as
|
|
531
533
|
| string
|
|
532
534
|
| undefined
|
|
535
|
+
scopes = getArrayPropertyValue(firstArg, 'scopes') ?? undefined
|
|
533
536
|
|
|
534
537
|
// Extract approvalDescription identifier reference
|
|
535
538
|
for (const prop of firstArg.properties) {
|
|
@@ -1029,17 +1032,6 @@ export const addFunctions: AddWiring = (
|
|
|
1029
1032
|
if (newMiddleware.length > 0) {
|
|
1030
1033
|
middleware = [...(middleware || []), ...newMiddleware]
|
|
1031
1034
|
}
|
|
1032
|
-
const existingPermissionTags = new Set(
|
|
1033
|
-
(permissions || [])
|
|
1034
|
-
.filter((p) => p.type === 'tag')
|
|
1035
|
-
.map((p) => (p as any).tag)
|
|
1036
|
-
)
|
|
1037
|
-
const newPermissions = tagEntries.filter(
|
|
1038
|
-
(e) => !existingPermissionTags.has(e.tag)
|
|
1039
|
-
)
|
|
1040
|
-
if (newPermissions.length > 0) {
|
|
1041
|
-
permissions = [...(permissions || []), ...newPermissions]
|
|
1042
|
-
}
|
|
1043
1035
|
}
|
|
1044
1036
|
|
|
1045
1037
|
const implementationHash = computeImplementationHash({
|
|
@@ -1094,6 +1086,7 @@ export const addFunctions: AddWiring = (
|
|
|
1094
1086
|
workflowQueued: workflowQueued === true ? true : undefined,
|
|
1095
1087
|
workflowRetries: workflowRetries ?? undefined,
|
|
1096
1088
|
workflowTimeout: workflowTimeout ?? undefined,
|
|
1089
|
+
scopes: scopes ?? undefined,
|
|
1097
1090
|
implementationHash,
|
|
1098
1091
|
version,
|
|
1099
1092
|
title,
|
|
@@ -1147,7 +1140,6 @@ export const addFunctions: AddWiring = (
|
|
|
1147
1140
|
inputSchema: inputNames[0] ?? null,
|
|
1148
1141
|
outputSchema: outputNames[0] ?? null,
|
|
1149
1142
|
middleware,
|
|
1150
|
-
permissions,
|
|
1151
1143
|
}
|
|
1152
1144
|
state.serviceAggregation.usedFunctions.add(pikkuFuncId)
|
|
1153
1145
|
extractWireNames(middleware).forEach((n) =>
|
|
@@ -1192,6 +1184,12 @@ export const addFunctions: AddWiring = (
|
|
|
1192
1184
|
|
|
1193
1185
|
if (remote) {
|
|
1194
1186
|
state.rpc.invokedFunctions.add(pikkuFuncId)
|
|
1187
|
+
// The consumer-facing surface a wireRemoteAddon imports (mirrors exposedMeta)
|
|
1188
|
+
state.rpc.remoteMeta[name] = pikkuFuncId
|
|
1189
|
+
state.rpc.remoteFiles.set(name, {
|
|
1190
|
+
path: node.getSourceFile().fileName,
|
|
1191
|
+
exportedName,
|
|
1192
|
+
})
|
|
1195
1193
|
}
|
|
1196
1194
|
|
|
1197
1195
|
if (expose) {
|
package/src/add/add-gateway.ts
CHANGED
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
makeContextBasedId,
|
|
10
10
|
} from '../utils/extract-function-name.js'
|
|
11
11
|
import { getPropertyAssignmentInitializer } from '../utils/type-utils.js'
|
|
12
|
+
import { ensureInlineWiringFunction } from '../utils/ensure-function-metadata.js'
|
|
12
13
|
import { resolveMiddleware } from '../utils/middleware.js'
|
|
13
14
|
import { extractWireNames } from '../utils/post-process.js'
|
|
14
15
|
import { resolveAddonName } from '../utils/resolve-addon-package.js'
|
|
@@ -83,6 +84,16 @@ export const addGateway: AddWiring = (
|
|
|
83
84
|
return
|
|
84
85
|
}
|
|
85
86
|
|
|
87
|
+
// Register metadata for a func inlined into the wiring (see helper).
|
|
88
|
+
ensureInlineWiringFunction(
|
|
89
|
+
state,
|
|
90
|
+
pikkuFuncId,
|
|
91
|
+
nameValue,
|
|
92
|
+
funcInitializer,
|
|
93
|
+
checker,
|
|
94
|
+
extracted.isHelper
|
|
95
|
+
)
|
|
96
|
+
|
|
86
97
|
const middleware = resolveMiddleware(state, obj, tags, checker)
|
|
87
98
|
|
|
88
99
|
state.serviceAggregation.usedFunctions.add(pikkuFuncId)
|
|
@@ -19,7 +19,7 @@ import type {
|
|
|
19
19
|
InspectorState,
|
|
20
20
|
} from '../types.js'
|
|
21
21
|
import { resolveHTTPMiddlewareFromObject } from '../utils/middleware.js'
|
|
22
|
-
import {
|
|
22
|
+
import { resolvePermissions } from '../utils/permissions.js'
|
|
23
23
|
import { extractWireNames } from '../utils/post-process.js'
|
|
24
24
|
import { ensureFunctionMetadata } from '../utils/ensure-function-metadata.js'
|
|
25
25
|
import { resolveFunctionMeta } from '../utils/resolve-function-meta.js'
|
|
@@ -381,13 +381,7 @@ export function registerHTTPRoute({
|
|
|
381
381
|
)
|
|
382
382
|
|
|
383
383
|
// Resolve permissions
|
|
384
|
-
const permissions =
|
|
385
|
-
state,
|
|
386
|
-
fullRoute,
|
|
387
|
-
obj,
|
|
388
|
-
tags,
|
|
389
|
-
checker
|
|
390
|
-
)
|
|
384
|
+
const permissions = resolvePermissions(state, obj, tags, checker)
|
|
391
385
|
|
|
392
386
|
state.serviceAggregation.usedFunctions.add(funcName)
|
|
393
387
|
if (refAddonTarget) {
|