@pikku/cli 0.12.92 → 0.12.96
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/console-app/assets/{index-DDpIMCpy.js → index-CeQodYfg.js} +151 -149
- package/console-app/assets/{index-D0HG8q0B.css → index-CyYHTGWZ.css} +1 -1
- package/console-app/index.html +2 -2
- package/dist/.pikku/agent/pikku-agent-types.gen.d.ts +1 -1
- package/dist/.pikku/channel/pikku-channel-types.gen.d.ts +1 -1
- package/dist/.pikku/channel/pikku-channel-types.gen.js +1 -1
- package/dist/.pikku/cli/pikku-cli-channel.d.ts +13 -15
- package/dist/.pikku/cli/pikku-cli-channel.js +72 -3
- package/dist/.pikku/cli/pikku-cli-client.gen.d.ts +14 -4
- package/dist/.pikku/cli/pikku-cli-client.gen.js +20 -10
- package/dist/.pikku/cli/pikku-cli-contracts-meta.gen.d.ts +1 -1
- package/dist/.pikku/cli/pikku-cli-contracts-meta.gen.js +1 -1
- package/dist/.pikku/cli/pikku-cli-types.gen.d.ts +1 -1
- package/dist/.pikku/cli/pikku-cli-types.gen.js +1 -1
- package/dist/.pikku/cli/pikku-cli-wirings-meta.gen.js +1 -1
- package/dist/.pikku/cli/pikku-cli-wirings-meta.gen.json +156 -2
- package/dist/.pikku/cli/pikku-cli-wirings.gen.d.ts +1 -1
- package/dist/.pikku/cli/pikku-cli-wirings.gen.js +1 -1
- package/dist/.pikku/cli/pikku-cli.gen.d.ts +1 -1
- package/dist/.pikku/cli/pikku-cli.gen.js +1 -1
- package/dist/.pikku/console/pikku-node-types.gen.d.ts +1 -1
- package/dist/.pikku/function/pikku-function-types.gen.d.ts +55 -20
- package/dist/.pikku/function/pikku-function-types.gen.js +27 -1
- package/dist/.pikku/function/pikku-functions-meta.gen.js +1 -1
- package/dist/.pikku/function/pikku-functions-meta.gen.json +176 -13
- package/dist/.pikku/function/pikku-functions.gen.js +11 -1
- package/dist/.pikku/http/pikku-http-types.gen.d.ts +1 -1
- package/dist/.pikku/http/pikku-http-types.gen.js +1 -1
- package/dist/.pikku/mcp/pikku-mcp-types.gen.d.ts +1 -1
- package/dist/.pikku/mcp/pikku-mcp-types.gen.js +1 -1
- package/dist/.pikku/pikku-bootstrap-scenarios.gen.d.ts +1 -1
- package/dist/.pikku/pikku-bootstrap-scenarios.gen.js +1 -1
- package/dist/.pikku/pikku-bootstrap.gen.d.ts +1 -1
- package/dist/.pikku/pikku-bootstrap.gen.js +1 -1
- package/dist/.pikku/pikku-meta-service.gen.d.ts +1 -1
- package/dist/.pikku/pikku-meta-service.gen.js +1 -1
- package/dist/.pikku/pikku-services.gen.d.ts +1 -1
- package/dist/.pikku/pikku-types.gen.d.ts +1 -1
- package/dist/.pikku/pikku-types.gen.js +1 -1
- package/dist/.pikku/queue/pikku-queue-types.gen.d.ts +1 -1
- package/dist/.pikku/queue/pikku-queue-types.gen.js +1 -1
- package/dist/.pikku/queue/pikku-queue-workers-wirings-meta.gen.js +1 -1
- package/dist/.pikku/queue/pikku-queue-workers-wirings.gen.d.ts +1 -1
- package/dist/.pikku/queue/pikku-queue-workers-wirings.gen.js +1 -1
- package/dist/.pikku/rpc/pikku-rpc-wirings-meta.internal.gen.js +1 -1
- package/dist/.pikku/rpc/pikku-rpc-wirings-meta.internal.gen.json +9 -0
- package/dist/.pikku/scenarios/pikku-scenario-functions-meta.gen.js +1 -1
- package/dist/.pikku/scenarios/pikku-scenario-functions.gen.d.ts +1 -1
- package/dist/.pikku/scenarios/pikku-scenario-wirings-meta.gen.js +1 -1
- package/dist/.pikku/scenarios/pikku-scenario-wirings.gen.d.ts +1 -1
- package/dist/.pikku/scenarios/schemas/register.gen.d.ts +1 -1
- package/dist/.pikku/scenarios/schemas/register.gen.js +1 -1
- package/dist/.pikku/scheduler/pikku-scheduler-types.gen.d.ts +1 -1
- package/dist/.pikku/scheduler/pikku-scheduler-types.gen.js +1 -1
- package/dist/.pikku/schemas/register.gen.js +21 -3
- package/dist/.pikku/schemas/schemas/KnowledgeIndexInput.schema.json +1 -0
- package/dist/.pikku/schemas/schemas/KnowledgeIndexOutput.schema.json +1 -0
- package/dist/.pikku/schemas/schemas/KnowledgeValidateInput.schema.json +1 -0
- package/dist/.pikku/schemas/schemas/KnowledgeValidateOutput.schema.json +1 -0
- package/dist/.pikku/schemas/schemas/PersonaRunInput.schema.json +1 -0
- package/dist/.pikku/schemas/schemas/PersonaSyncInput.schema.json +1 -0
- package/dist/.pikku/schemas/schemas/PikkuCLIConfig.schema.json +1 -1
- package/dist/.pikku/schemas/schemas/PikkuPersonasInput.schema.json +1 -0
- package/dist/.pikku/schemas/schemas/PikkuRolesInput.schema.json +1 -0
- package/dist/.pikku/schemas/schemas/RolesAuditInput.schema.json +1 -0
- package/dist/.pikku/schemas/schemas/RolesPruneInput.schema.json +1 -0
- package/dist/.pikku/scopes/pikku-personas-meta.gen.json +1 -0
- package/dist/.pikku/scopes/pikku-personas.gen.d.ts +36 -0
- package/dist/.pikku/scopes/pikku-personas.gen.js +17 -0
- package/dist/.pikku/scopes/pikku-roles-meta.gen.json +1 -0
- package/dist/.pikku/scopes/pikku-roles.gen.d.ts +30 -0
- package/dist/.pikku/scopes/pikku-roles.gen.js +18 -0
- package/dist/.pikku/scopes/pikku-scope-types.gen.d.ts +4 -2
- package/dist/.pikku/scopes/pikku-scope-types.gen.js +3 -2
- package/dist/.pikku/scopes/pikku-scopes.gen.d.ts +1 -1
- package/dist/.pikku/secrets/pikku-secret-types.gen.d.ts +2 -2
- package/dist/.pikku/secrets/pikku-secret-types.gen.js +2 -2
- package/dist/.pikku/secrets/pikku-secrets.gen.d.ts +1 -1
- package/dist/.pikku/secrets/pikku-secrets.gen.js +1 -1
- package/dist/.pikku/trigger/pikku-trigger-types.gen.d.ts +1 -1
- package/dist/.pikku/trigger/pikku-trigger-types.gen.js +1 -1
- package/dist/.pikku/variables/pikku-variable-types.gen.d.ts +2 -2
- package/dist/.pikku/variables/pikku-variable-types.gen.js +2 -2
- package/dist/.pikku/variables/pikku-variables.gen.d.ts +1 -1
- package/dist/.pikku/variables/pikku-variables.gen.js +1 -1
- package/dist/.pikku/workflow/meta/allWorkflow.gen.json +27 -3
- package/dist/.pikku/workflow/pikku-personas.gen.d.ts +15 -0
- package/dist/.pikku/workflow/pikku-personas.gen.js +17 -0
- package/dist/.pikku/workflow/pikku-workflow-types.gen.d.ts +96 -19
- package/dist/.pikku/workflow/pikku-workflow-types.gen.js +22 -2
- package/dist/.pikku/workflow/pikku-workflow-wirings-meta.gen.js +1 -1
- package/dist/.pikku/workflow/pikku-workflow-wirings.gen.js +1 -1
- package/dist/bin/pikku-bin.mjs +2 -2
- package/dist/bin/pikku.js +0 -0
- package/dist/src/cli.wiring.js +124 -2
- package/dist/src/deploy/analyzer/analyzer.js +14 -0
- package/dist/src/deploy/analyzer/manifest.d.ts +11 -0
- package/dist/src/fabric/functions/validate.function.js +20 -11
- package/dist/src/functions/commands/bootstrap.js +3 -0
- package/dist/src/functions/commands/dev-ai-runner.d.ts +16 -4
- package/dist/src/functions/commands/dev-ai-runner.js +63 -29
- package/dist/src/functions/commands/dev.js +9 -4
- package/dist/src/functions/commands/enable.js +15 -19
- package/dist/src/functions/commands/{scenario-environment.d.ts → environment.d.ts} +9 -6
- package/dist/src/functions/commands/{scenario-environment.js → environment.js} +5 -4
- package/dist/src/functions/commands/knowledge-index.d.ts +30 -0
- package/dist/src/functions/commands/knowledge-index.js +11 -0
- package/dist/src/functions/commands/knowledge-validate.d.ts +33 -0
- package/dist/src/functions/commands/knowledge-validate.js +11 -0
- package/dist/src/functions/commands/new-addon.d.ts +18 -0
- package/dist/src/functions/commands/new-addon.js +52 -36
- package/dist/src/functions/commands/persona-sync.d.ts +33 -0
- package/dist/src/functions/commands/persona-sync.js +151 -0
- package/dist/src/functions/commands/persona.d.ts +58 -0
- package/dist/src/functions/commands/persona.js +217 -0
- package/dist/src/functions/commands/roles-audit.d.ts +1 -0
- package/dist/src/functions/commands/roles-audit.js +37 -0
- package/dist/src/functions/commands/roles-prune.d.ts +16 -0
- package/dist/src/functions/commands/roles-prune.js +52 -0
- package/dist/src/functions/commands/roles-shared.d.ts +40 -0
- package/dist/src/functions/commands/roles-shared.js +77 -0
- package/dist/src/functions/commands/scenario-browser.d.ts +3 -3
- package/dist/src/functions/commands/scenario-browser.js +1 -1
- package/dist/src/functions/commands/scenario-ladder.d.ts +44 -2
- package/dist/src/functions/commands/scenario-ladder.js +51 -2
- package/dist/src/functions/commands/scenario.d.ts +7 -0
- package/dist/src/functions/commands/scenario.js +79 -17
- package/dist/src/functions/commands/scopes-shared.d.ts +8 -0
- package/dist/src/functions/commands/scopes-shared.js +1 -1
- package/dist/src/functions/commands/serve.js +7 -3
- package/dist/src/functions/commands/virtual-user-formatter.d.ts +30 -0
- package/dist/src/functions/commands/virtual-user-formatter.js +65 -0
- package/dist/src/functions/db/local-db.js +38 -1
- package/dist/src/functions/knowledge/render.d.ts +3 -0
- package/dist/src/functions/knowledge/render.js +66 -0
- package/dist/src/functions/knowledge/schemas.d.ts +51 -0
- package/dist/src/functions/knowledge/schemas.js +25 -0
- package/dist/src/functions/validate/workspace-validate.js +1 -1
- package/dist/src/functions/wirings/ai-agent/pikku-command-public-agent.js +2 -1
- package/dist/src/functions/wirings/ai-agent/serialize-public-agent.js +1 -0
- package/dist/src/functions/wirings/auth/serialize-auth-gen.d.ts +2 -2
- package/dist/src/functions/wirings/auth/serialize-auth-gen.js +8 -8
- package/dist/src/functions/wirings/cli/serialize-channel-cli-client.d.ts +7 -3
- package/dist/src/functions/wirings/cli/serialize-channel-cli-client.js +32 -18
- package/dist/src/functions/wirings/cli/serialize-channel-cli.js +63 -6
- package/dist/src/functions/wirings/console/serialize-console-functions.js +4 -7
- package/dist/src/functions/wirings/credentials/serialize-credentials-types.js +8 -1
- package/dist/src/functions/wirings/functions/serialize-function-types.js +88 -28
- package/dist/src/functions/wirings/middleware/serialize-middleware-imports.js +25 -9
- package/dist/src/functions/wirings/package/serialize-package-types.js +5 -3
- package/dist/src/functions/wirings/personas/pikku-command-personas.d.ts +7 -0
- package/dist/src/functions/wirings/personas/pikku-command-personas.js +43 -0
- package/dist/src/functions/wirings/personas/serialize-personas-types.d.ts +18 -0
- package/dist/src/functions/wirings/personas/serialize-personas-types.js +76 -0
- package/dist/src/functions/wirings/realtime/pikku-command-events-scaffold.js +2 -1
- package/dist/src/functions/wirings/roles/pikku-command-roles.d.ts +7 -0
- package/dist/src/functions/wirings/roles/pikku-command-roles.js +33 -0
- package/dist/src/functions/wirings/roles/serialize-roles-types.d.ts +14 -0
- package/dist/src/functions/wirings/roles/serialize-roles-types.js +55 -0
- package/dist/src/functions/wirings/rpc/pikku-command-public-rpc.js +2 -1
- package/dist/src/functions/wirings/scenarios/register-scenario-instrumentation.d.ts +3 -3
- package/dist/src/functions/wirings/scenarios/register-scenario-instrumentation.js +3 -3
- package/dist/src/functions/wirings/scopes/serialize-scopes-types.d.ts +1 -1
- package/dist/src/functions/wirings/scopes/serialize-scopes-types.js +1 -1
- package/dist/src/functions/wirings/secrets/serialize-secrets-types.js +10 -3
- package/dist/src/functions/wirings/user-admin/pikku-command-user-admin-functions.js +2 -1
- package/dist/src/functions/wirings/user-admin/serialize-user-admin-functions.js +2 -2
- package/dist/src/functions/wirings/variables/serialize-variables-types.js +8 -1
- package/dist/src/functions/wirings/workflow/pikku-command-workflow-routes.js +2 -1
- package/dist/src/functions/wirings/workflow/pikku-command-workflow.js +13 -13
- package/dist/src/functions/wirings/workflow/serialize-personas.d.ts +10 -0
- package/dist/src/functions/wirings/workflow/serialize-personas.js +46 -0
- package/dist/src/functions/wirings/workflow/serialize-scenario-step-map.js +11 -2
- package/dist/src/functions/wirings/workflow/serialize-workflow-types.js +165 -29
- package/dist/src/functions/workflows/all.workflow.js +7 -1
- package/dist/src/server/content-signing-jwt.d.ts +13 -0
- package/dist/src/server/content-signing-jwt.js +51 -0
- package/dist/src/server/dev-server-runner.interface.d.ts +10 -2
- package/dist/src/server/node-server-runner.d.ts +2 -2
- package/dist/src/server/node-server-runner.js +2 -1
- package/dist/src/services.d.ts +3 -1
- package/dist/src/services.js +2 -1
- package/dist/src/utils/pikku-cli-config.js +45 -2
- package/dist/src/utils/resolve-personas.d.ts +32 -0
- package/dist/src/utils/resolve-personas.js +46 -0
- package/dist/src/utils/resolve-scaffold-feature.d.ts +19 -0
- package/dist/src/utils/resolve-scaffold-feature.js +49 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +17 -13
- package/dist/.pikku/schemas/schemas/ScenarioRunInput.schema.json +0 -1
- package/dist/.pikku/workflow/pikku-scenario-actors.gen.d.ts +0 -19
- package/dist/.pikku/workflow/pikku-scenario-actors.gen.js +0 -17
- package/dist/src/functions/wirings/workflow/serialize-scenario-actors.d.ts +0 -2
- package/dist/src/functions/wirings/workflow/serialize-scenario-actors.js +0 -40
- package/dist/src/utils/resolve-scenario-actors.d.ts +0 -23
- package/dist/src/utils/resolve-scenario-actors.js +0 -74
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
* Workflow orchestrators dispatch to step units via queue or RPC (inline).
|
|
8
8
|
*/
|
|
9
9
|
import { resolveDeployTarget, } from '@pikku/inspector';
|
|
10
|
+
import { relative } from 'node:path';
|
|
10
11
|
import { isScenarioFunction, withoutScenarios, withoutScenarioWorkflows, } from '../../functions/wirings/scenarios/scenario-partition.js';
|
|
11
12
|
export function analyzeDeployment(state, options) {
|
|
12
13
|
const serverlessIncompatible = new Set(options.serverlessIncompatible ?? []);
|
|
@@ -353,10 +354,22 @@ export function analyzeDeployment(state, options) {
|
|
|
353
354
|
}
|
|
354
355
|
}
|
|
355
356
|
// ── Secrets & Variables ────────────────────────────────────────────
|
|
357
|
+
const readSecretIds = new Set();
|
|
358
|
+
const unresolvedSecretReads = [];
|
|
359
|
+
for (const [file, usage] of state.secrets.usage ?? []) {
|
|
360
|
+
for (const key of usage.keys) {
|
|
361
|
+
readSecretIds.add(key);
|
|
362
|
+
}
|
|
363
|
+
for (const read of usage.dynamic) {
|
|
364
|
+
unresolvedSecretReads.push(`${relative(state.rootDir, file)}:${read}`);
|
|
365
|
+
}
|
|
366
|
+
}
|
|
356
367
|
const secrets = state.secrets.definitions.map((s) => ({
|
|
357
368
|
secretId: s.secretId,
|
|
358
369
|
displayName: s.displayName,
|
|
359
370
|
description: s.description,
|
|
371
|
+
allowedHosts: s.allowedHosts,
|
|
372
|
+
read: readSecretIds.has(s.secretId),
|
|
360
373
|
}));
|
|
361
374
|
const variables = state.variables.definitions.map((v) => ({
|
|
362
375
|
variableId: v.variableId,
|
|
@@ -374,6 +387,7 @@ export function analyzeDeployment(state, options) {
|
|
|
374
387
|
mcpEndpoints,
|
|
375
388
|
workflows,
|
|
376
389
|
secrets,
|
|
390
|
+
unresolvedSecretReads: unresolvedSecretReads.sort(),
|
|
377
391
|
variables,
|
|
378
392
|
};
|
|
379
393
|
}
|
|
@@ -101,7 +101,13 @@ export interface SecretDeclaration {
|
|
|
101
101
|
secretId: string;
|
|
102
102
|
displayName: string;
|
|
103
103
|
description?: string;
|
|
104
|
+
/** Hosts this secret may be sent to. Absent means unrestricted. */
|
|
105
|
+
allowedHosts?: string[];
|
|
106
|
+
/** True when some code reads this secret with a statically resolvable key. */
|
|
107
|
+
read?: boolean;
|
|
104
108
|
}
|
|
109
|
+
/** Secret reads whose key the inspector could not resolve, as `file:line:source`. */
|
|
110
|
+
export type UnresolvedSecretRead = string;
|
|
105
111
|
export interface VariableDeclaration {
|
|
106
112
|
variableId: string;
|
|
107
113
|
displayName: string;
|
|
@@ -118,5 +124,10 @@ export interface DeploymentManifest {
|
|
|
118
124
|
mcpEndpoints: MCPEndpointDefinition[];
|
|
119
125
|
workflows: WorkflowDefinition[];
|
|
120
126
|
secrets: SecretDeclaration[];
|
|
127
|
+
/**
|
|
128
|
+
* Reads with a non-literal key. A deployment can only narrow a unit's secret
|
|
129
|
+
* scope to the declared set when this is empty.
|
|
130
|
+
*/
|
|
131
|
+
unresolvedSecretReads: UnresolvedSecretRead[];
|
|
121
132
|
variables: VariableDeclaration[];
|
|
122
133
|
}
|
|
@@ -6,6 +6,7 @@ import { createRequire } from 'node:module';
|
|
|
6
6
|
import { pikkuSessionlessFunc } from '../../../.pikku/pikku-types.gen.js';
|
|
7
7
|
import { added, changed, removed, dim } from '../lib/output.js';
|
|
8
8
|
import { typeCheckFrontends } from '../lib/frontend-typecheck.js';
|
|
9
|
+
import { runKnowledgeValidate } from '@pikku/knowledge';
|
|
9
10
|
const FindingSchema = z.object({
|
|
10
11
|
id: z.string(),
|
|
11
12
|
severity: z.enum(['error', 'warn', 'info']),
|
|
@@ -243,7 +244,7 @@ export async function runValidate(startDir = process.cwd(), opts = {}) {
|
|
|
243
244
|
key: 'console',
|
|
244
245
|
severity: 'error',
|
|
245
246
|
surface: 'app introspection (console:getFunctionsMeta and friends) — the sandbox builder shows no functions',
|
|
246
|
-
value: '
|
|
247
|
+
value: 'true',
|
|
247
248
|
},
|
|
248
249
|
{
|
|
249
250
|
key: 'rpc',
|
|
@@ -255,13 +256,13 @@ export async function runValidate(startDir = process.cwd(), opts = {}) {
|
|
|
255
256
|
key: 'agent',
|
|
256
257
|
severity: 'error',
|
|
257
258
|
surface: 'the agent endpoints (/rpc/agent/:agentName) — the agent playground 404s',
|
|
258
|
-
value: '
|
|
259
|
+
value: 'true',
|
|
259
260
|
},
|
|
260
261
|
{
|
|
261
262
|
key: 'workflow',
|
|
262
263
|
severity: 'error',
|
|
263
264
|
surface: 'the workflow endpoints (/workflow/:workflowName/start) — triggering a workflow 404s',
|
|
264
|
-
value: '
|
|
265
|
+
value: 'true',
|
|
265
266
|
},
|
|
266
267
|
{
|
|
267
268
|
key: 'events',
|
|
@@ -312,16 +313,21 @@ export async function runValidate(startDir = process.cwd(), opts = {}) {
|
|
|
312
313
|
// ── required project files ────────────────────────────────────────────
|
|
313
314
|
// These files must exist and be committed — they are seeded from the sandbox
|
|
314
315
|
// but belong to the project so the AI agent can read and update them.
|
|
315
|
-
for (const relPath of [
|
|
316
|
-
'db/annotations.ts',
|
|
317
|
-
'knowledge/design-language.md',
|
|
318
|
-
'knowledge/security.md',
|
|
319
|
-
'knowledge/technology.md',
|
|
320
|
-
]) {
|
|
316
|
+
for (const relPath of ['db/annotations.ts']) {
|
|
321
317
|
if (!existsSync(join(root, relPath))) {
|
|
322
318
|
w(`missing-required-file-${relPath.replace(/[^a-z0-9]/gi, '-')}`, `${relPath} is missing — this file must be committed to the project`, join(root, relPath), lines(`Create ${relPath} and commit it.`, 'The starter-template ships a stub you can copy as a starting point.'));
|
|
323
319
|
}
|
|
324
320
|
}
|
|
321
|
+
// ── knowledge base ─────────────────────────────────────────────────────
|
|
322
|
+
// Delegated to the shared checker rather than asserting a list of filenames.
|
|
323
|
+
// The three flat files this used to require (design-language.md, security.md,
|
|
324
|
+
// technology.md) are not a knowledge base — they are three documents nothing
|
|
325
|
+
// can link into, and the profile now organises the same content into sections
|
|
326
|
+
// of notes. Fabric adds decisions/design/ on top of what is checked here.
|
|
327
|
+
const knowledge = await runKnowledgeValidate(root, join(root, typeof pikkuConfig?.outDir === 'string' ? pikkuConfig.outDir : '.pikku'));
|
|
328
|
+
for (const finding of knowledge.findings) {
|
|
329
|
+
findings.push({ ...finding, path: join(root, finding.path) });
|
|
330
|
+
}
|
|
325
331
|
const rootPkgPath = join(root, 'package.json');
|
|
326
332
|
const rootPkg = await readJsonSafe(rootPkgPath);
|
|
327
333
|
if (!rootPkg) {
|
|
@@ -671,11 +677,14 @@ export async function runValidate(startDir = process.cwd(), opts = {}) {
|
|
|
671
677
|
// nothing — flagging it told every fresh scaffold to import a dialect it
|
|
672
678
|
// must not use.
|
|
673
679
|
const constructsKysely = /new\s+Kysely\s*[<(]/.test(servicesText);
|
|
674
|
-
if (dbEngine !== 'postgres' &&
|
|
680
|
+
if (dbEngine !== 'postgres' &&
|
|
681
|
+
usesKysely &&
|
|
682
|
+
constructsKysely &&
|
|
683
|
+
!usesLibsql) {
|
|
675
684
|
e('services-wrong-db-adapter', 'services.ts uses Kysely but not LibsqlWebDialect — Fabric injects a Turso/libSQL DATABASE_URL at runtime, not a PostgreSQL URL', servicesPath, 'Import LibsqlWebDialect from @pikku/kysely-sqlite and replace the dialect: new Kysely({ dialect: new LibsqlWebDialect({ url: databaseUrl }) })');
|
|
676
685
|
}
|
|
677
686
|
if (usesProcessEnv) {
|
|
678
|
-
info('services-process-env', 'services.ts reads process.env directly — prefer variables.get() for portable secret/variable access', servicesPath, 'Replace process.env.SOME_VAR with await variables.get("SOME_VAR") — declare the binding with
|
|
687
|
+
info('services-process-env', 'services.ts reads process.env directly — prefer variables.get() for portable secret/variable access', servicesPath, 'Replace process.env.SOME_VAR with await variables.get("SOME_VAR") — declare the binding with defineVariable/defineSecret; process.env is fine for optional/non-secret config');
|
|
679
688
|
}
|
|
680
689
|
if (dbEngine !== 'postgres' &&
|
|
681
690
|
usesLibsql &&
|
|
@@ -5,6 +5,9 @@ export const bootstrap = pikkuVoidFunc({
|
|
|
5
5
|
await getInspectorState(false, true, true);
|
|
6
6
|
// Before function types: they import ScopeId from the scopes codegen.
|
|
7
7
|
await rpc.invoke('pikkuScopes', { bootstrap: true });
|
|
8
|
+
// Before function types too: personas import SystemRoleName.
|
|
9
|
+
await rpc.invoke('pikkuRoles', { bootstrap: true });
|
|
10
|
+
await rpc.invoke('pikkuPersonas', { bootstrap: true });
|
|
8
11
|
await rpc.invoke('pikkuFunctionTypesSplit', { bootstrap: true });
|
|
9
12
|
// Stub auth.types.ts (if better-auth is used) so the pikkuBetterAuth
|
|
10
13
|
// re-export resolves before any user file is imported.
|
|
@@ -7,10 +7,22 @@ import type { AIAgentRunnerService } from '@pikku/core/services';
|
|
|
7
7
|
* has no equivalent, so agents 503 with AIProviderNotConfiguredError unless we
|
|
8
8
|
* construct one here. When an OpenAI-compatible base URL + key are present
|
|
9
9
|
* (fabric injects LITELLM_PROXY_URL/LITELLM_API_KEY; the standard OPENAI_*
|
|
10
|
-
* vars are also honored) we point
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
10
|
+
* vars are also honored) we point one provider at it and register it under
|
|
11
|
+
* `'*'`, so every provider prefix resolves to it. The CLI ships the SDK rather
|
|
12
|
+
* than asking the project for it — behind a proxy one openai-compatible
|
|
13
|
+
* provider answers for `openai/…`, `anthropic/…` and `google/…` alike, so there
|
|
14
|
+
* was never a per-vendor package worth making somebody install. The project's
|
|
15
|
+
* own copies still win when it has them. Returns undefined when no AI env is
|
|
16
|
+
* configured (agents stay disabled, with the clear downstream error) or when
|
|
17
|
+
* the SDK packages cannot be loaded from either place.
|
|
18
|
+
*
|
|
19
|
+
* Audio does not work here: `@ai-sdk/openai-compatible` exposes only
|
|
20
|
+
* language/embedding/image models, so a voice agent under `pikku dev` throws
|
|
21
|
+
* `Provider does not support transcription models`. Fixing that means the full
|
|
22
|
+
* `@ai-sdk/openai` provider, which assumes OpenAI's own request specifics — a
|
|
23
|
+
* bad default for a path whose entire purpose is fronting arbitrary gateways.
|
|
24
|
+
* If it becomes worth it, delegate just `transcription`/`speech` to the full
|
|
25
|
+
* provider and leave everything else on this one.
|
|
14
26
|
*/
|
|
15
27
|
export declare function createDevAIAgentRunner({ logger, projectRoot, variables, }: {
|
|
16
28
|
logger: Logger;
|
|
@@ -1,19 +1,6 @@
|
|
|
1
1
|
import { createRequire } from 'module';
|
|
2
2
|
import { join } from 'path';
|
|
3
3
|
import { pathToFileURL } from 'url';
|
|
4
|
-
// Provider prefixes a fabric/proxy baseURL fronts. Models are written as
|
|
5
|
-
// `openai/gpt-4o-mini`, `openai/deepseek-v4-flash`, etc. — the runner splits on
|
|
6
|
-
// the first `/`, so the prefix only selects the provider entry and the bare
|
|
7
|
-
// model name is forwarded to the OpenAI-compatible proxy, which routes it.
|
|
8
|
-
const PROXY_PROVIDER_NAMES = [
|
|
9
|
-
'openai',
|
|
10
|
-
'anthropic',
|
|
11
|
-
'google',
|
|
12
|
-
'gemini',
|
|
13
|
-
'deepseek',
|
|
14
|
-
'xai',
|
|
15
|
-
'litellm',
|
|
16
|
-
];
|
|
17
4
|
/**
|
|
18
5
|
* Build the AI agent runner for `pikku dev` from env.
|
|
19
6
|
*
|
|
@@ -21,10 +8,22 @@ const PROXY_PROVIDER_NAMES = [
|
|
|
21
8
|
* has no equivalent, so agents 503 with AIProviderNotConfiguredError unless we
|
|
22
9
|
* construct one here. When an OpenAI-compatible base URL + key are present
|
|
23
10
|
* (fabric injects LITELLM_PROXY_URL/LITELLM_API_KEY; the standard OPENAI_*
|
|
24
|
-
* vars are also honored) we point
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
11
|
+
* vars are also honored) we point one provider at it and register it under
|
|
12
|
+
* `'*'`, so every provider prefix resolves to it. The CLI ships the SDK rather
|
|
13
|
+
* than asking the project for it — behind a proxy one openai-compatible
|
|
14
|
+
* provider answers for `openai/…`, `anthropic/…` and `google/…` alike, so there
|
|
15
|
+
* was never a per-vendor package worth making somebody install. The project's
|
|
16
|
+
* own copies still win when it has them. Returns undefined when no AI env is
|
|
17
|
+
* configured (agents stay disabled, with the clear downstream error) or when
|
|
18
|
+
* the SDK packages cannot be loaded from either place.
|
|
19
|
+
*
|
|
20
|
+
* Audio does not work here: `@ai-sdk/openai-compatible` exposes only
|
|
21
|
+
* language/embedding/image models, so a voice agent under `pikku dev` throws
|
|
22
|
+
* `Provider does not support transcription models`. Fixing that means the full
|
|
23
|
+
* `@ai-sdk/openai` provider, which assumes OpenAI's own request specifics — a
|
|
24
|
+
* bad default for a path whose entire purpose is fronting arbitrary gateways.
|
|
25
|
+
* If it becomes worth it, delegate just `transcription`/`speech` to the full
|
|
26
|
+
* provider and leave everything else on this one.
|
|
28
27
|
*/
|
|
29
28
|
export async function createDevAIAgentRunner({ logger, projectRoot, variables, }) {
|
|
30
29
|
// Pair the URL with its matching key — coalescing each var independently could
|
|
@@ -43,28 +42,63 @@ export async function createDevAIAgentRunner({ logger, projectRoot, variables, }
|
|
|
43
42
|
logger.debug('pikku dev: no AI provider env (OPENAI_BASE_URL/OPENAI_API_KEY or LITELLM_PROXY_URL/LITELLM_API_KEY) — AI agents disabled');
|
|
44
43
|
return undefined;
|
|
45
44
|
}
|
|
46
|
-
//
|
|
47
|
-
//
|
|
48
|
-
|
|
45
|
+
// The project's own copies win, so an app that pins an `ai` version gets a
|
|
46
|
+
// runner built from that one rather than a second copy alongside it. The
|
|
47
|
+
// CLI's are the fallback: this function exists for projects that have not
|
|
48
|
+
// installed an AI SDK at all, and behind a proxy a single openai-compatible
|
|
49
|
+
// provider reaches every model, so making someone add three packages before
|
|
50
|
+
// agents work in dev buys nothing.
|
|
51
|
+
const fromProject = createRequire(pathToFileURL(join(projectRoot, 'package.json')).href);
|
|
52
|
+
//
|
|
53
|
+
// Both come from the same place or neither does. A provider built against one
|
|
54
|
+
// copy of `@ai-sdk/provider` handed to a runner built against another is the
|
|
55
|
+
// one combination that fails at call time rather than at load time, with an
|
|
56
|
+
// error about the model spec that names neither package.
|
|
57
|
+
const loadPair = async () => {
|
|
58
|
+
const project = ['@pikku/ai-vercel', '@ai-sdk/openai-compatible'].map((name) => {
|
|
59
|
+
try {
|
|
60
|
+
return pathToFileURL(fromProject.resolve(name)).href;
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
return undefined;
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
const [runner, provider] = project.every(Boolean)
|
|
67
|
+
? project
|
|
68
|
+
: ['@pikku/ai-vercel', '@ai-sdk/openai-compatible'];
|
|
69
|
+
return Promise.all([import(runner), import(provider)]);
|
|
70
|
+
};
|
|
49
71
|
let VercelAIAgentRunner;
|
|
50
72
|
let createOpenAICompatible;
|
|
51
73
|
try {
|
|
52
|
-
;
|
|
53
|
-
({ VercelAIAgentRunner } =
|
|
54
|
-
({ createOpenAICompatible } =
|
|
74
|
+
const [runnerModule, providerModule] = await loadPair();
|
|
75
|
+
({ VercelAIAgentRunner } = runnerModule);
|
|
76
|
+
({ createOpenAICompatible } = providerModule);
|
|
55
77
|
}
|
|
56
78
|
catch (error) {
|
|
57
|
-
logger.warn(`pikku dev: AI provider env is set but the AI SDK packages could not be loaded
|
|
79
|
+
logger.warn(`pikku dev: AI provider env is set but the AI SDK packages could not be loaded — AI agents disabled: ${error instanceof Error ? error.message : String(error)}`);
|
|
58
80
|
return undefined;
|
|
59
81
|
}
|
|
60
|
-
|
|
61
|
-
|
|
82
|
+
// One provider under '*', so every prefix a model might name resolves to the
|
|
83
|
+
// proxy — including ones nobody thought to list. This was a hardcoded array
|
|
84
|
+
// of seven names, which silently excluded everything else.
|
|
85
|
+
//
|
|
86
|
+
// `supportsStructuredOutputs` defaults to false, and the default fails in the
|
|
87
|
+
// worst available way: an `outputSchema` is dropped, the call degrades to
|
|
88
|
+
// bare `json_object`, and the model returns well-formed JSON with whatever
|
|
89
|
+
// keys it felt like. Nothing errors — the caller reads `undefined` off every
|
|
90
|
+
// field it asked for and behaves as though the model said nothing. Anything
|
|
91
|
+
// fronting this URL that is worth calling speaks `json_schema`; the ones that
|
|
92
|
+
// do not now fail loudly on the first schema'd call, which is the outcome we
|
|
93
|
+
// want over silently ignoring the schema.
|
|
94
|
+
const buildProviders = (key) => ({
|
|
95
|
+
'*': createOpenAICompatible({
|
|
62
96
|
name: 'pikku-dev',
|
|
63
97
|
baseURL,
|
|
64
98
|
apiKey: key,
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
};
|
|
99
|
+
supportsStructuredOutputs: true,
|
|
100
|
+
}),
|
|
101
|
+
});
|
|
68
102
|
logger.info(`pikku dev: AI agent runner wired to ${baseURL}`);
|
|
69
103
|
return new VercelAIAgentRunner(buildProviders(apiKey), buildProviders);
|
|
70
104
|
}
|
|
@@ -16,6 +16,8 @@ import { startCoverageService } from './start-coverage.js';
|
|
|
16
16
|
import { createDevAIAgentRunner } from './dev-ai-runner.js';
|
|
17
17
|
import { resolveConsoleMount } from './serve-console.js';
|
|
18
18
|
import { serverReadyLine } from '../../server/server-ready.js';
|
|
19
|
+
import { createEphemeralContentSigningJWT } from '../../server/content-signing-jwt.js';
|
|
20
|
+
import { resolveScaffoldFeature } from '../../utils/resolve-scaffold-feature.js';
|
|
19
21
|
export const dev = pikkuSessionlessFunc({
|
|
20
22
|
remote: true,
|
|
21
23
|
func: async ({ logger, config, getInspectorState, invalidateInspectorState, variables, devServerRunner, }, { port, watch, hmr, coverage, test }, { rpc }) => {
|
|
@@ -122,7 +124,7 @@ export const dev = pikkuSessionlessFunc({
|
|
|
122
124
|
// project — an app bootstrap is what a deployed bundle imports, and coverage
|
|
123
125
|
// endpoints have no business in one.
|
|
124
126
|
if (config.scaffold?.scenarios) {
|
|
125
|
-
registerScenarioInstrumentation(config.scaffold.scenarios
|
|
127
|
+
registerScenarioInstrumentation(resolveScaffoldFeature('scenarios', config.scaffold.scenarios).auth);
|
|
126
128
|
}
|
|
127
129
|
const configModule = await loadUserModule(pikkuConfigFactory.file);
|
|
128
130
|
const servicesModule = await loadUserModule(singletonServicesFactory.file);
|
|
@@ -150,8 +152,11 @@ export const dev = pikkuSessionlessFunc({
|
|
|
150
152
|
sizeLimit: userConfig.content.sizeLimit,
|
|
151
153
|
}
|
|
152
154
|
: undefined;
|
|
153
|
-
const
|
|
154
|
-
?
|
|
155
|
+
const contentSigningJWT = localContentConfig
|
|
156
|
+
? createEphemeralContentSigningJWT()
|
|
157
|
+
: undefined;
|
|
158
|
+
const localContent = localContentConfig && contentSigningJWT
|
|
159
|
+
? new LocalContent(localContentConfig, logger, contentSigningJWT)
|
|
155
160
|
: undefined;
|
|
156
161
|
const schedulerService = new InMemorySchedulerService();
|
|
157
162
|
const aiStorage = kysely
|
|
@@ -239,7 +244,7 @@ export const dev = pikkuSessionlessFunc({
|
|
|
239
244
|
port: resolvedPort,
|
|
240
245
|
content: localContentConfig,
|
|
241
246
|
...(consoleMount ? { staticMounts: [consoleMount] } : {}),
|
|
242
|
-
}, logger);
|
|
247
|
+
}, logger, { contentSigningJWT });
|
|
243
248
|
const lifecycle = await loadLifecycle();
|
|
244
249
|
await pikkuServer.init();
|
|
245
250
|
await lifecycle?.beforeStart?.(resolvedServices);
|
|
@@ -1,15 +1,12 @@
|
|
|
1
1
|
import { readFile, writeFile } from 'fs/promises';
|
|
2
2
|
import { join } from 'path';
|
|
3
3
|
import { pikkuVoidFunc } from '#pikku';
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
events: 'auth',
|
|
11
|
-
remoteRpc: 'no-auth',
|
|
12
|
-
};
|
|
4
|
+
/**
|
|
5
|
+
* Remote RPC workers carry no auth dimension — `serialize-remote-rpc.ts`
|
|
6
|
+
* hardcodes `auth: false` on what it generates — so enabling it writes a bare
|
|
7
|
+
* `true` and there is nothing to opt out of.
|
|
8
|
+
*/
|
|
9
|
+
const NO_AUTH_DIMENSION = new Set(['remoteRpc']);
|
|
13
10
|
async function enableFeature(feature, logger, config, data) {
|
|
14
11
|
const noAuth = data?.noAuth ?? false;
|
|
15
12
|
const configPath = join(config.configDir, 'pikku.config.json');
|
|
@@ -21,18 +18,17 @@ async function enableFeature(feature, logger, config, data) {
|
|
|
21
18
|
if (!json.scaffold.pikkuDir) {
|
|
22
19
|
json.scaffold.pikkuDir = 'pikku';
|
|
23
20
|
}
|
|
24
|
-
//
|
|
25
|
-
//
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
? 'no-auth'
|
|
32
|
-
: FEATURE_DEFAULTS[feature];
|
|
21
|
+
// `true` is enabled AND authenticated. Only an explicit --no-auth writes the
|
|
22
|
+
// object form, so a feature can never be turned on public by accident.
|
|
23
|
+
//
|
|
24
|
+
// The console is an admin surface — every RPC requires a session, so
|
|
25
|
+
// --no-auth is ignored for it.
|
|
26
|
+
const wantsPublic = noAuth && feature !== 'console' && !NO_AUTH_DIMENSION.has(feature);
|
|
27
|
+
const value = feature === 'webhook' ? true : wantsPublic ? { auth: false } : true;
|
|
33
28
|
json.scaffold[feature] = value;
|
|
34
29
|
await writeFile(configPath, JSON.stringify(json, null, 2) + '\n', 'utf-8');
|
|
35
|
-
logger.info(`Enabled scaffold.${feature} =
|
|
30
|
+
logger.info(`Enabled scaffold.${feature} = ${JSON.stringify(value)} in ${configPath}` +
|
|
31
|
+
(wantsPublic ? ' (public — no session required)' : ''));
|
|
36
32
|
}
|
|
37
33
|
export const enableRpc = pikkuVoidFunc({
|
|
38
34
|
func: async ({ logger, config }, data) => enableFeature('rpc', logger, config, data),
|
|
@@ -1,22 +1,25 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Resolving `pikku scenario run <environment>`
|
|
2
|
+
* Resolving `pikku scenario run <environment>` and `pikku persona run
|
|
3
|
+
* <environment>` to the URLs the run targets.
|
|
3
4
|
*
|
|
4
5
|
* The configured environment is the base; `--api-url`/`--app-url` override it
|
|
5
6
|
* for one invocation, which is what makes a suite runnable against a target
|
|
6
7
|
* that only exists at run time (a freshly provisioned sandbox) without writing
|
|
7
8
|
* a pikku.config.json per deployment.
|
|
8
9
|
*/
|
|
9
|
-
/** One entry of `
|
|
10
|
-
export interface
|
|
10
|
+
/** One entry of `environments` in pikku.config.json. */
|
|
11
|
+
export interface PikkuEnvironment {
|
|
11
12
|
apiUrl: string;
|
|
12
13
|
signInPath?: string;
|
|
13
14
|
rpcPath?: string;
|
|
14
15
|
appUrl?: string;
|
|
16
|
+
/** Real consequences: only an `accountable` persona may run against it. */
|
|
17
|
+
production?: boolean;
|
|
15
18
|
}
|
|
16
|
-
export interface
|
|
19
|
+
export interface ResolveEnvironmentOptions {
|
|
17
20
|
/** The name given on the command line. Must exist in config. */
|
|
18
21
|
environment: string;
|
|
19
|
-
environments: Record<string,
|
|
22
|
+
environments: Record<string, PikkuEnvironment>;
|
|
20
23
|
/** `--api-url`, overriding the configured `apiUrl`. */
|
|
21
24
|
apiUrl?: string;
|
|
22
25
|
/** `--app-url`, overriding the configured `appUrl`. */
|
|
@@ -29,4 +32,4 @@ export interface ResolveScenarioEnvironmentOptions {
|
|
|
29
32
|
* all see the same target. The environment is still looked up by name: the
|
|
30
33
|
* flags override fields on a configured environment, they do not invent one.
|
|
31
34
|
*/
|
|
32
|
-
export declare const
|
|
35
|
+
export declare const resolveEnvironment: ({ environment, environments, apiUrl, appUrl, spawn, }: ResolveEnvironmentOptions) => PikkuEnvironment;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Resolving `pikku scenario run <environment>`
|
|
2
|
+
* Resolving `pikku scenario run <environment>` and `pikku persona run
|
|
3
|
+
* <environment>` to the URLs the run targets.
|
|
3
4
|
*
|
|
4
5
|
* The configured environment is the base; `--api-url`/`--app-url` override it
|
|
5
6
|
* for one invocation, which is what makes a suite runnable against a target
|
|
@@ -35,14 +36,14 @@ const assertAbsoluteUrl = (flag, value) => {
|
|
|
35
36
|
* all see the same target. The environment is still looked up by name: the
|
|
36
37
|
* flags override fields on a configured environment, they do not invent one.
|
|
37
38
|
*/
|
|
38
|
-
export const
|
|
39
|
+
export const resolveEnvironment = ({ environment, environments, apiUrl, appUrl, spawn = false, }) => {
|
|
39
40
|
const configured = environments[environment];
|
|
40
41
|
if (!configured) {
|
|
41
42
|
const known = Object.keys(environments);
|
|
42
|
-
throw new Error(`Unknown
|
|
43
|
+
throw new Error(`Unknown environment '${environment}'. ` +
|
|
43
44
|
(known.length
|
|
44
45
|
? `Configured environments: ${known.join(', ')}`
|
|
45
|
-
: `Add
|
|
46
|
+
: `Add environments to pikku.config.json, e.g. { "${environment}": { "apiUrl": "https://app.example.com/api" } }`));
|
|
46
47
|
}
|
|
47
48
|
const resolved = { ...configured };
|
|
48
49
|
if (apiUrl !== undefined) {
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { renderKnowledgeIndex } from '../knowledge/render.js';
|
|
2
|
+
export declare const knowledgeIndex: import("#pikku").PikkuFunctionConfig<{
|
|
3
|
+
check?: boolean | undefined;
|
|
4
|
+
}, {
|
|
5
|
+
ok: boolean;
|
|
6
|
+
check: boolean;
|
|
7
|
+
files: {
|
|
8
|
+
path: string;
|
|
9
|
+
action: "unchanged" | "created" | "updated";
|
|
10
|
+
}[];
|
|
11
|
+
}, "rpc" | "session", import("#pikku").PikkuFunctionSessionless<{
|
|
12
|
+
check?: boolean | undefined;
|
|
13
|
+
}, {
|
|
14
|
+
ok: boolean;
|
|
15
|
+
check: boolean;
|
|
16
|
+
files: {
|
|
17
|
+
path: string;
|
|
18
|
+
action: "unchanged" | "created" | "updated";
|
|
19
|
+
}[];
|
|
20
|
+
}, "rpc" | "session", import("#pikku").WiredServices> | import("#pikku").PikkuFunction<{
|
|
21
|
+
check?: boolean | undefined;
|
|
22
|
+
}, {
|
|
23
|
+
ok: boolean;
|
|
24
|
+
check: boolean;
|
|
25
|
+
files: {
|
|
26
|
+
path: string;
|
|
27
|
+
action: "unchanged" | "created" | "updated";
|
|
28
|
+
}[];
|
|
29
|
+
}, "rpc" | "session", import("#pikku").WiredServices>, undefined, undefined>;
|
|
30
|
+
export { renderKnowledgeIndex };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { pikkuSessionlessFunc } from '#pikku';
|
|
2
|
+
import { runKnowledgeIndex } from '@pikku/knowledge';
|
|
3
|
+
import { renderKnowledgeIndex } from '../knowledge/render.js';
|
|
4
|
+
import { KnowledgeIndexInputSchema, KnowledgeIndexOutputSchema, } from '../knowledge/schemas.js';
|
|
5
|
+
export const knowledgeIndex = pikkuSessionlessFunc({
|
|
6
|
+
description: "Refresh every index.md so each section lists the notes actually in it, replacing only the generated block and leaving each index's prose alone.",
|
|
7
|
+
input: KnowledgeIndexInputSchema,
|
|
8
|
+
output: KnowledgeIndexOutputSchema,
|
|
9
|
+
func: async ({ config }, { check }) => runKnowledgeIndex(config.rootDir, check ?? false),
|
|
10
|
+
});
|
|
11
|
+
export { renderKnowledgeIndex };
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { renderKnowledgeValidate } from '../knowledge/render.js';
|
|
2
|
+
export declare const knowledgeValidate: import("#pikku").PikkuFunctionConfig<Record<string, never>, {
|
|
3
|
+
ok: boolean;
|
|
4
|
+
notes: number;
|
|
5
|
+
findings: {
|
|
6
|
+
id: string;
|
|
7
|
+
severity: "warn" | "error" | "info";
|
|
8
|
+
message: string;
|
|
9
|
+
path: string;
|
|
10
|
+
fixHint: string;
|
|
11
|
+
}[];
|
|
12
|
+
}, "rpc" | "session", import("#pikku").PikkuFunctionSessionless<Record<string, never>, {
|
|
13
|
+
ok: boolean;
|
|
14
|
+
notes: number;
|
|
15
|
+
findings: {
|
|
16
|
+
id: string;
|
|
17
|
+
severity: "warn" | "error" | "info";
|
|
18
|
+
message: string;
|
|
19
|
+
path: string;
|
|
20
|
+
fixHint: string;
|
|
21
|
+
}[];
|
|
22
|
+
}, "rpc" | "session", import("#pikku").WiredServices> | import("#pikku").PikkuFunction<Record<string, never>, {
|
|
23
|
+
ok: boolean;
|
|
24
|
+
notes: number;
|
|
25
|
+
findings: {
|
|
26
|
+
id: string;
|
|
27
|
+
severity: "warn" | "error" | "info";
|
|
28
|
+
message: string;
|
|
29
|
+
path: string;
|
|
30
|
+
fixHint: string;
|
|
31
|
+
}[];
|
|
32
|
+
}, "rpc" | "session", import("#pikku").WiredServices>, undefined, undefined>;
|
|
33
|
+
export { renderKnowledgeValidate };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { pikkuSessionlessFunc } from '#pikku';
|
|
2
|
+
import { runKnowledgeValidate } from '@pikku/knowledge';
|
|
3
|
+
import { renderKnowledgeValidate } from '../knowledge/render.js';
|
|
4
|
+
import { KnowledgeValidateInputSchema, KnowledgeValidateOutputSchema, } from '../knowledge/schemas.js';
|
|
5
|
+
export const knowledgeValidate = pikkuSessionlessFunc({
|
|
6
|
+
description: 'Check the knowledge base against the app-project profile: every note typed, every section indexed, every slice gated, and every resource: pointing at something that still exists.',
|
|
7
|
+
input: KnowledgeValidateInputSchema,
|
|
8
|
+
output: KnowledgeValidateOutputSchema,
|
|
9
|
+
func: async ({ config }) => runKnowledgeValidate(config.rootDir, config.outDir),
|
|
10
|
+
});
|
|
11
|
+
export { renderKnowledgeValidate };
|
|
@@ -9,6 +9,24 @@
|
|
|
9
9
|
* the only option there.
|
|
10
10
|
*/
|
|
11
11
|
export declare function resolveAddonDepProtocol(baseDir: string): string;
|
|
12
|
+
export interface AddonVars {
|
|
13
|
+
name: string;
|
|
14
|
+
camelName: string;
|
|
15
|
+
pascalName: string;
|
|
16
|
+
screamingName: string;
|
|
17
|
+
displayName: string;
|
|
18
|
+
description: string;
|
|
19
|
+
category: string;
|
|
20
|
+
addonDepProtocol: string;
|
|
21
|
+
}
|
|
22
|
+
export declare function getAddonFiles(vars: AddonVars, flags: {
|
|
23
|
+
secret: boolean;
|
|
24
|
+
variable: boolean;
|
|
25
|
+
oauth: boolean;
|
|
26
|
+
credential?: 'apikey' | 'bearer' | 'oauth2';
|
|
27
|
+
/** Delegated login: credential is the upstream token + expiry, checked per call. */
|
|
28
|
+
delegated?: boolean;
|
|
29
|
+
}): Record<string, string>;
|
|
12
30
|
export declare const pikkuNewAddon: import("#pikku").PikkuFunctionConfig<{
|
|
13
31
|
name: string;
|
|
14
32
|
displayName?: string;
|