diff --git a/examples/review-agent/persona.json b/examples/review-agent/persona.json index 4c69399b..325ec883 100644 --- a/examples/review-agent/persona.json +++ b/examples/review-agent/persona.json @@ -1,26 +1,45 @@ { "id": "review-agent", "intent": "review", - "tags": ["review"], + "tags": [ + "review" + ], "description": "Reviews opened PRs, responds to @mentions in comments, attempts autofix on red CI.", "cloud": true, "useSubscription": true, "integrations": { "github": { "triggers": [ - { "on": "pull_request.opened" }, - { "on": "issue_comment.created", "match": "@mention" }, - { "on": "pull_request_review_comment.created", "match": "@mention" }, - { "on": "check_run.completed", "where": "conclusion=failure" } + { + "on": "pull_request.opened" + }, + { + "on": "issue_comment.created", + "match": "@mention" + }, + { + "on": "pull_request_review_comment.created", + "match": "@mention" + }, + { + "on": "check_run.completed", + "where": "conclusion=failure" + } ] }, "slack": { - "triggers": [{ "on": "app_mention" }] + "triggers": [ + { + "on": "app_mention" + } + ] } }, "memory": { "enabled": true, - "scopes": ["workspace"] + "scopes": [ + "workspace" + ] }, "onEvent": "./agent.ts", "harness": "codex", diff --git a/examples/review-agent/persona.ts b/examples/review-agent/persona.ts new file mode 100644 index 00000000..4389ebf0 --- /dev/null +++ b/examples/review-agent/persona.ts @@ -0,0 +1,39 @@ +import { definePersona } from '@agentworkforce/persona-kit'; + +export default definePersona({ + id: 'review-agent', + intent: 'review', + tags: ['review'], + description: + 'Reviews opened PRs, responds to @mentions in comments, attempts autofix on red CI.', + cloud: true, + useSubscription: true, + integrations: { + github: { + triggers: [ + { on: 'pull_request.opened' }, + { on: 'issue_comment.created', match: '@mention' }, + { on: 'pull_request_review_comment.created', match: '@mention' }, + { on: 'check_run.completed', where: 'conclusion=failure' } + ] + }, + slack: { + triggers: [{ on: 'app_mention' }] + } + }, + memory: { + enabled: true, + scopes: ['workspace'] + }, + onEvent: './agent.ts', + harness: 'codex', + model: 'gpt-5.4', + systemPrompt: + 'Review pull requests for correctness, regression risk, security concerns, and missing tests. Be concise and concrete.', + harnessSettings: { + reasoning: 'medium', + timeoutSeconds: 1200, + sandboxMode: 'workspace-write', + workspaceWriteNetworkAccess: true + } +}); diff --git a/packages/cli/package.json b/packages/cli/package.json index 4a756d62..d94f250a 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -16,6 +16,7 @@ "@agentworkforce/workload-router": "workspace:*", "@relayburn/sdk": "^2.5.2", "@relayfile/local-mount": "^0.7.24", + "esbuild": "^0.25.0", "ora": "^9.4.0" }, "repository": { diff --git a/packages/cli/src/cli.ts b/packages/cli/src/cli.ts index 646d7397..e5e6eddb 100644 --- a/packages/cli/src/cli.ts +++ b/packages/cli/src/cli.ts @@ -87,6 +87,7 @@ import { type PersonaSource } from './local-personas.js'; import { installPersonas, type PersonaInstallResult } from './persona-install.js'; +import { runPersonaCompileCommand } from './persona-compile.js'; import { pickPersona, type PickCandidate, type PickResult } from './persona-picker.js'; import { recordRecent, loadRecents, runPersonaPickerTui, type TuiCandidate } from './persona-tui.js'; @@ -191,6 +192,9 @@ Commands: including which cascade layer defined it (cwd, user, dir:, library). Flags: --json emit the resolved PersonaSpec as JSON + persona compile + Compile a typed persona.ts authoring file to sibling + persona.json after validating it with persona-kit. install [flags] Copy persona JSON files from an npm package or local package directory into @@ -4268,6 +4272,15 @@ export async function main(): Promise { runShow(rest); } + if (subcommand === 'persona') { + try { + await runPersonaCompileCommand(rest); + return; + } catch (err) { + die((err as Error)?.message ?? String(err), false); + } + } + if (subcommand === 'install') { runPersonaInstall(rest); } diff --git a/packages/cli/src/persona-compile.test.ts b/packages/cli/src/persona-compile.test.ts new file mode 100644 index 00000000..cf11d344 --- /dev/null +++ b/packages/cli/src/persona-compile.test.ts @@ -0,0 +1,93 @@ +import test from 'node:test'; +import assert from 'node:assert/strict'; +import { mkdtempSync, readFileSync, rmSync, writeFileSync } from 'node:fs'; +import { tmpdir } from 'node:os'; +import { join } from 'node:path'; + +import { compilePersonaFile } from './persona-compile.js'; + +test('compilePersonaFile bundles persona.ts, validates it, and writes persona.json', async () => { + const root = mkdtempSync(join(tmpdir(), 'aw-persona-compile-')); + try { + const inputPath = join(root, 'persona.ts'); + const outputPath = join(root, 'persona.json'); + writeFileSync( + inputPath, + `import { definePersona } from '@agentworkforce/persona-kit'; + +export default definePersona({ + id: 'compiled-persona', + intent: 'review', + description: 'Compiled persona fixture.', + inputs: { + TARGET: 'repo' + }, + integrations: { + github: { + triggers: [ + { on: 'pull_request.opened' }, + { on: 'off_registry.github_event' } + ] + }, + linear: { triggers: [{ on: 'issue.updated' }] }, + slack: { triggers: [{ on: 'message.channels' }] }, + notion: { triggers: [{ on: 'page.created' }] }, + jira: { triggers: [{ on: 'issue.created' }] }, + unknown: { triggers: [{ on: 'whatever.happened' }] } + }, + onEvent: './agent.ts', + harnessSettings: { + reasoning: 'medium', + timeoutSeconds: 60 + } +}); +`, + 'utf8' + ); + + const result = await compilePersonaFile(inputPath); + const compiled = JSON.parse(readFileSync(outputPath, 'utf8')) as { + id: string; + inputs?: Record; + integrations?: Record }>; + }; + + assert.equal(result.personaId, 'compiled-persona'); + assert.equal(result.outputPath, outputPath); + assert.equal(compiled.id, 'compiled-persona'); + assert.equal(compiled.inputs?.TARGET, 'repo'); + assert.equal( + compiled.integrations?.github.triggers?.[1].on, + 'off_registry.github_event' + ); + assert.equal(compiled.integrations?.unknown.triggers?.[0].on, 'whatever.happened'); + } finally { + rmSync(root, { recursive: true, force: true }); + } +}); + +test('compilePersonaFile fails loudly when validation rejects the authored spec', async () => { + const root = mkdtempSync(join(tmpdir(), 'aw-persona-compile-invalid-')); + try { + const inputPath = join(root, 'persona.ts'); + writeFileSync( + inputPath, + `export default { + id: 'bad', + intent: 'review', + description: 'Bad persona fixture.', + harnessSettings: { reasoning: 'turbo', timeoutSeconds: 60 }, + onEvent: './agent.ts' +}; +`, + 'utf8' + ); + + await assert.rejects( + () => compilePersonaFile(inputPath), + /harnessSettings\.reasoning must be low\|medium\|high/ + ); + } finally { + rmSync(root, { recursive: true, force: true }); + } +}); diff --git a/packages/cli/src/persona-compile.ts b/packages/cli/src/persona-compile.ts new file mode 100644 index 00000000..df4e5fc0 --- /dev/null +++ b/packages/cli/src/persona-compile.ts @@ -0,0 +1,117 @@ +import { builtinModules } from 'node:module'; +import { mkdir, mkdtemp, rm, stat, writeFile } from 'node:fs/promises'; +import { tmpdir } from 'node:os'; +import { basename, dirname, join, resolve } from 'node:path'; +import { fileURLToPath, pathToFileURL } from 'node:url'; + +import { isIntent, isObject, parsePersonaSpec } from '@agentworkforce/persona-kit'; +import { build } from 'esbuild'; + +export interface PersonaCompileResult { + inputPath: string; + outputPath: string; + personaId: string; +} + +const NODE_EXTERNALS = [ + ...builtinModules, + ...builtinModules.map((name) => `node:${name}`), + 'node:*' +]; + +export async function compilePersonaFile( + inputPath: string, + outputPath?: string +): Promise { + const absInput = resolve(inputPath); + await assertReadableFile(absInput, 'persona compile input'); + + const absOutput = resolve(outputPath ?? join(dirname(absInput), 'persona.json')); + const tempDir = await mkdtemp(join(tmpdir(), 'agentworkforce-persona-compile-')); + const bundledPath = join(tempDir, `${basename(absInput).replace(/\W+/g, '-')}.mjs`); + + try { + await build({ + entryPoints: [absInput], + outfile: bundledPath, + bundle: true, + format: 'esm', + platform: 'node', + target: 'node20', + sourcemap: 'inline', + logLevel: 'silent', + external: NODE_EXTERNALS, + resolveExtensions: ['.ts', '.mts', '.cts', '.tsx', '.js', '.mjs', '.cjs', '.jsx', '.json'], + nodePaths: packageNodePaths() + }); + + const mod = await import(pathToFileURL(bundledPath).href); + const spec = mod.default as unknown; + if (!isObject(spec)) { + throw new Error('persona compile: default export must be a persona object'); + } + if (typeof spec.intent !== 'string') { + throw new Error('persona compile: default export must include a string intent'); + } + if (!isIntent(spec.intent)) { + throw new Error(`persona compile: intent "${spec.intent}" is invalid`); + } + const parsed = parsePersonaSpec(spec, spec.intent); + + await mkdir(dirname(absOutput), { recursive: true }); + await writeFile(absOutput, JSON.stringify(spec, null, 2) + '\n', 'utf8'); + + return { + inputPath: absInput, + outputPath: absOutput, + personaId: parsed.id + }; + } finally { + await rm(tempDir, { recursive: true, force: true }); + } +} + +export async function runPersonaCompileCommand(args: string[]): Promise { + const [action, personaPath, ...rest] = args; + if (!action || action === '-h' || action === '--help') { + process.stdout.write('Usage: agentworkforce persona compile \n'); + process.exit(action ? 0 : 1); + } + if (action !== 'compile') { + throw new Error(`persona: unknown action "${action}". Expected: compile`); + } + if (!personaPath) { + throw new Error('persona compile: missing '); + } + if (rest.length > 0) { + throw new Error(`persona compile: unexpected argument "${rest[0]}"`); + } + + const result = await compilePersonaFile(personaPath); + process.stdout.write( + `Compiled ${result.inputPath} -> ${result.outputPath} (${result.personaId})\n` + ); +} + +async function assertReadableFile(abs: string, label: string): Promise { + try { + const st = await stat(abs); + if (!st.isFile()) { + throw new Error(`${label}: ${abs} is not a regular file`); + } + } catch (err) { + if ((err as NodeJS.ErrnoException).code === 'ENOENT') { + throw new Error(`${label}: file not found at ${abs}`); + } + throw err; + } +} + +function packageNodePaths(): string[] { + const here = dirname(fileURLToPath(import.meta.url)); + return [ + join(here, '..', 'node_modules'), + join(here, '..', '..', 'node_modules'), + join(process.cwd(), 'node_modules') + ]; +} diff --git a/packages/persona-kit/package.json b/packages/persona-kit/package.json index e0054f56..a2a0f495 100644 --- a/packages/persona-kit/package.json +++ b/packages/persona-kit/package.json @@ -36,6 +36,7 @@ "lint": "tsc -p tsconfig.json --noEmit" }, "dependencies": { + "@relayfile/adapter-core": "^0.3.13", "@relayfile/local-mount": "^0.7.24" }, "devDependencies": { diff --git a/packages/persona-kit/schemas/persona.schema.json b/packages/persona-kit/schemas/persona.schema.json index ab5b1e83..bf74f7e8 100644 --- a/packages/persona-kit/schemas/persona.schema.json +++ b/packages/persona-kit/schemas/persona.schema.json @@ -477,7 +477,7 @@ "required": [ "on" ], - "description": "A single event trigger declared by an integration. `on` is a Relayfile- adapter-normalized event name (e.g. `pull_request.opened`, `issue.created`, `app_mention`). `match` and `where` are filter sugars the deploy CLI lints against a known registry; unknown values warn but do not fail parse, so the cloud runtime stays the source of truth.\n\nExamples: { on: \"pull_request.opened\" } { on: \"issue_comment.created\", match: \"@mention\" } { on: \"check_run.completed\", where: \"conclusion=failure\" }" + "description": "A single event trigger declared by an integration. `on` is a Relayfile- adapter-normalized event name (e.g. `pull_request.opened`, `issue.create`, `message.created`). `match` and `where` are filter sugars the deploy CLI lints against a known registry; unknown values warn but do not fail parse, so the cloud runtime stays the source of truth.\n\nExamples: { on: \"pull_request.opened\" } { on: \"pull_request_review_comment.created\", match: \"@mention\" } { on: \"check_run.completed\", where: \"conclusion=failure\" }" }, "PersonaSchedule": { "type": "object", diff --git a/packages/persona-kit/src/__fixtures__/personas/full.json b/packages/persona-kit/src/__fixtures__/personas/full.json index 5b5ebb23..3d60d78d 100644 --- a/packages/persona-kit/src/__fixtures__/personas/full.json +++ b/packages/persona-kit/src/__fixtures__/personas/full.json @@ -27,15 +27,14 @@ "scope": { "repo": "AgentWorkforce/workforce" }, "triggers": [ { "on": "pull_request.opened" }, - { "on": "issue_comment.created", "match": "@mention" }, + { "on": "pull_request_review_comment.created", "match": "@mention" }, { "on": "check_run.completed", "where": "conclusion=failure" } ] }, - "linear": { "triggers": [{ "on": "issue.created" }] }, - "slack": { "triggers": [{ "on": "app_mention" }] }, + "linear": { "triggers": [{ "on": "issue.create" }] }, + "slack": { "triggers": [{ "on": "message.created" }] }, "notion": { - "scope": { "database": "db_123" }, - "triggers": [{ "on": "page.updated" }] + "scope": { "database": "db_123" } }, "jira": { "scope": { "project": "ENG" }, diff --git a/packages/persona-kit/src/__fixtures__/personas/integration-source-workspace.json b/packages/persona-kit/src/__fixtures__/personas/integration-source-workspace.json index 9bfe19b2..acca1fc9 100644 --- a/packages/persona-kit/src/__fixtures__/personas/integration-source-workspace.json +++ b/packages/persona-kit/src/__fixtures__/personas/integration-source-workspace.json @@ -13,7 +13,7 @@ "integrations": { "slack": { "source": { "kind": "workspace" }, - "triggers": [{ "on": "app_mention" }] + "triggers": [{ "on": "message.created" }] } } } diff --git a/packages/persona-kit/src/define.test.ts b/packages/persona-kit/src/define.test.ts new file mode 100644 index 00000000..4d48bf77 --- /dev/null +++ b/packages/persona-kit/src/define.test.ts @@ -0,0 +1,59 @@ +import test from 'node:test'; +import assert from 'node:assert/strict'; + +import { definePersona, parsePersonaSpec } from './index.js'; + +test('definePersona returns authored specs that parse successfully', () => { + const persona = definePersona({ + id: 'typed-author', + intent: 'review', + description: 'Typed authoring fixture.', + inputs: { + TOPIC: 'pull requests', + TARGET_REPO: { + description: 'Repository to inspect.', + default: 'AgentWorkforce/workforce' + } + }, + integrations: { + github: { + triggers: [ + { on: 'pull_request.opened' }, + { on: 'off_registry.github_event' } + ] + }, + linear: { triggers: [{ on: 'issue.create' }] }, + slack: { triggers: [{ on: 'message.created' }] }, + confluence: { triggers: [{ on: 'page.updated' }] }, + jira: { triggers: [{ on: 'comment.created' }] }, + customProvider: { triggers: [{ on: 'custom.event' }] } + }, + onEvent: './agent.ts', + harnessSettings: { reasoning: 'medium', timeoutSeconds: 300 } + }); + + const parsed = parsePersonaSpec(persona, 'review'); + + assert.equal(parsed.id, 'typed-author'); + assert.equal(parsed.skills.length, 0); + assert.equal(parsed.inputs?.TOPIC.default, 'pull requests'); + assert.equal( + parsed.integrations?.github.triggers?.[1].on, + 'off_registry.github_event' + ); + assert.equal(parsed.integrations?.customProvider.triggers?.[0].on, 'custom.event'); +}); + +test('definePersona type allows interactive personas without onEvent', () => { + const persona = definePersona({ + id: 'interactive-author', + intent: 'documentation', + description: 'Interactive authoring fixture.', + harness: 'codex', + model: 'gpt-5.4', + systemPrompt: 'Write accurate docs.', + harnessSettings: { reasoning: 'low', timeoutSeconds: 120 } + }); + + assert.equal(persona.harness, 'codex'); +}); diff --git a/packages/persona-kit/src/define.ts b/packages/persona-kit/src/define.ts new file mode 100644 index 00000000..87ef435f --- /dev/null +++ b/packages/persona-kit/src/define.ts @@ -0,0 +1,85 @@ +import type { + Harness, + HarnessSettings, + IntegrationSource, + McpServerSpec, + PersonaInputSpec, + PersonaMemory, + PersonaMount, + PersonaPermissions, + PersonaSchedule, + PersonaSkill, + SidecarMdMode, + WatchRule +} from './types.js'; +import type { KnownProviderName, KnownTriggerName } from './triggers.js'; + +export type TriggerNameFor

= P extends KnownProviderName + ? KnownTriggerName

| (string & {}) + : string; + +export interface TypedTrigger

{ + on: TriggerNameFor

; + match?: string; + where?: string; +} + +export interface TypedIntegrationConfig

{ + source?: IntegrationSource; + scope?: Record; + triggers?: readonly TypedTrigger

[]; +} + +export type TypedIntegrations = { + [P in KnownProviderName]?: TypedIntegrationConfig

; +} & { + [provider: string]: TypedIntegrationConfig | undefined; +}; + +export interface PersonaDefinitionBase { + id: string; + intent: string; + tags?: readonly string[]; + description: string; + skills?: readonly PersonaSkill[]; + inputs?: Record; + harnessSettings: HarnessSettings; + env?: Record; + mcpServers?: Record; + permissions?: PersonaPermissions; + mount?: PersonaMount; + claudeMd?: string; + claudeMdMode?: SidecarMdMode; + agentsMd?: string; + agentsMdMode?: SidecarMdMode; + claudeMdContent?: string; + agentsMdContent?: string; + cloud?: boolean; + useSubscription?: boolean; + integrations?: TypedIntegrations; + schedules?: readonly PersonaSchedule[]; + watch?: readonly WatchRule[]; + memory?: PersonaMemory; +} + +type InteractivePersonaDefinition = PersonaDefinitionBase & { + onEvent?: undefined; + harness: Harness; + model: string; + systemPrompt: string; +}; + +type HandlerPersonaDefinition = PersonaDefinitionBase & { + onEvent: string; + harness?: Harness; + model?: string; + systemPrompt?: string; +}; + +export type PersonaDefinition = + | InteractivePersonaDefinition + | HandlerPersonaDefinition; + +export function definePersona(input: T): T { + return input; +} diff --git a/packages/persona-kit/src/index.ts b/packages/persona-kit/src/index.ts index 34e08b38..fa69554f 100644 --- a/packages/persona-kit/src/index.ts +++ b/packages/persona-kit/src/index.ts @@ -47,6 +47,16 @@ export type { WatchRule } from './types.js'; +// Typed persona authoring +export { + definePersona, + type PersonaDefinition, + type TriggerNameFor, + type TypedIntegrationConfig, + type TypedIntegrations, + type TypedTrigger +} from './define.js'; + // Parsers + sidecar resolver export { assertInputName, @@ -83,6 +93,8 @@ export { // Trigger registry + lint helper export { + ADAPTERS_WITHOUT_KNOWN_TRIGGERS, + KNOWN_TRIGGER_CATALOG, KNOWN_TRIGGERS, lintTriggers, type KnownProviderName, diff --git a/packages/persona-kit/src/triggers.test.ts b/packages/persona-kit/src/triggers.test.ts index 8db2f8d4..fcb73dbd 100644 --- a/packages/persona-kit/src/triggers.test.ts +++ b/packages/persona-kit/src/triggers.test.ts @@ -27,7 +27,8 @@ test('KNOWN_TRIGGERS ships a non-empty list per shipped provider', () => { `provider ${provider} must declare at least one known trigger` ); for (const name of names) { - assert.ok(name.includes('.') || name.includes('_'), `trigger "${name}" should look like an event name`); + assert.equal(typeof name, 'string'); + assert.notEqual(name, '', `provider ${provider} must not declare an empty trigger name`); } } }); @@ -42,10 +43,10 @@ test('lintTriggers returns no issues for known providers and known triggers', () github: { triggers: [ { on: 'pull_request.opened' }, - { on: 'issue_comment.created' } + { on: 'pull_request_review_comment.created' } ] }, - linear: { triggers: [{ on: 'issue.created' }] } + linear: { triggers: [{ on: 'issue.create' }] } }) ); assert.deepEqual(issues, []); diff --git a/packages/persona-kit/src/triggers.ts b/packages/persona-kit/src/triggers.ts index f42a7e50..b90c9299 100644 --- a/packages/persona-kit/src/triggers.ts +++ b/packages/persona-kit/src/triggers.ts @@ -1,4 +1,5 @@ import type { PersonaSpec } from './types.js'; +import { KNOWN_TRIGGER_CATALOG } from '@relayfile/adapter-core/triggers'; /** * Known event names per Relayfile provider, used by the deploy CLI to lint @@ -6,30 +7,15 @@ import type { PersonaSpec } from './types.js'; * authoritative source of truth — unknown names here produce a warning, * not a failure, so adding a new event upstream doesn't gate workforce * releases. - * - * This file ships intentionally sparse in v1; the full per-provider list - * lands when the Relayfile adapter packages publish their normalized - * event catalogs. */ -export const KNOWN_TRIGGERS = { - github: [ - 'pull_request.opened', - 'pull_request.synchronize', - 'pull_request.closed', - 'pull_request_review_comment.created', - 'issue_comment.created', - 'issues.opened', - 'check_run.completed', - 'workflow_run.completed' - ], - linear: ['issue.created', 'issue.updated', 'comment.created'], - slack: ['app_mention', 'message.channels'], - notion: ['page.updated', 'page.created'], - jira: ['issue.created', 'issue.updated', 'comment.created'] -} as const satisfies Record; +export const KNOWN_TRIGGERS = KNOWN_TRIGGER_CATALOG; -export type KnownProviderName = keyof typeof KNOWN_TRIGGERS; -export type KnownTriggerName

= (typeof KNOWN_TRIGGERS)[P][number]; +export { + ADAPTERS_WITHOUT_KNOWN_TRIGGERS, + KNOWN_TRIGGER_CATALOG, + type KnownProviderName, + type KnownTriggerName +} from '@relayfile/adapter-core/triggers'; export type TriggerLintLevel = 'warning'; diff --git a/packages/persona-kit/src/types.ts b/packages/persona-kit/src/types.ts index 4ec5b49a..0ab95f9f 100644 --- a/packages/persona-kit/src/types.ts +++ b/packages/persona-kit/src/types.ts @@ -146,13 +146,13 @@ export type McpServerSpec = /** * A single event trigger declared by an integration. `on` is a Relayfile- * adapter-normalized event name (e.g. `pull_request.opened`, - * `issue.created`, `app_mention`). `match` and `where` are filter sugars + * `issue.create`, `message.created`). `match` and `where` are filter sugars * the deploy CLI lints against a known registry; unknown values warn but * do not fail parse, so the cloud runtime stays the source of truth. * * Examples: * { on: "pull_request.opened" } - * { on: "issue_comment.created", match: "@mention" } + * { on: "pull_request_review_comment.created", match: "@mention" } * { on: "check_run.completed", where: "conclusion=failure" } */ export interface PersonaIntegrationTrigger { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 521fc70d..0920b568 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -44,6 +44,9 @@ importers: '@relayfile/local-mount': specifier: ^0.7.24 version: 0.7.24 + esbuild: + specifier: ^0.25.0 + version: 0.25.12 ora: specifier: ^9.4.0 version: 9.4.0 @@ -89,6 +92,9 @@ importers: packages/persona-kit: dependencies: + '@relayfile/adapter-core': + specifier: ^0.3.13 + version: 0.3.13(@relayfile/sdk@0.7.40) '@relayfile/local-mount': specifier: ^0.7.24 version: 0.7.24 @@ -840,10 +846,37 @@ packages: resolution: {integrity: sha512-C5eVSepGrlQY5b1yg+LfROLYhDW/w1WFVsuitRzvbXMr+qpFYFHLoMNxa9R0Q6ZiP02r6EXSazii2VNo2LZ0Vg==} engines: {node: '>=22'} + '@relayfile/adapter-core@0.3.13': + resolution: {integrity: sha512-4mi4b/qRS2vGZR/bew7A+LWs55bPHi9ZTH27IJVBCVZj0o6/rEzDuY1ber2HGi7yx6or6knuHs6d9XtxjCBvPg==} + engines: {node: '>=18'} + hasBin: true + peerDependencies: + '@relayfile/sdk': '>=0.6.0 <1' + + '@relayfile/core@0.7.40': + resolution: {integrity: sha512-vY48SxZgahnvE0CHDyy/iny17ypnfbX5myVPtocZVNpMiz4dS1iabO70WR+uYVgSiIZR7MpKTPFSs3SxEjQWag==} + engines: {node: '>=18'} + '@relayfile/local-mount@0.7.24': resolution: {integrity: sha512-h2ac/frfSFgjrKDSBCkmMHjphx19XZrHrSjaI29wlTzSblfiE65MQST47lS6Fm1+K9yap+W+msUi8JRIYYWFEw==} engines: {node: '>=18'} + '@relayfile/sdk@0.7.40': + resolution: {integrity: sha512-9qPQ/qSexD11x/CKZlbZUFC7KDdxJ2yYBQd1nuzcoHNqnvErplq5bDBy5Dqr1AXID9i1Q7sMxnY8M1raMTQsAg==} + engines: {node: '>=18'} + + '@scalar/helpers@0.5.1': + resolution: {integrity: sha512-9VvPfv8b+YZVIFwR3SWeq4Y8ij/kU3/kf2M6NKcbf2iVyh63d8s0ssap5m/nOhiz/Puidv/29MAJlJCA0LRssA==} + engines: {node: '>=22'} + + '@scalar/openapi-types@0.7.0': + resolution: {integrity: sha512-kN0PwlJW0de4bwQ4ib+mBHzKJUvBCyR/gwU4zLEq6SCbj+GfgYUh+2a0/yl1WYVUiSkkwFsHjfmQ8KjhR3HK0Q==} + engines: {node: '>=22'} + + '@scalar/postman-to-openapi@0.6.3': + resolution: {integrity: sha512-Y/tMuRZG34wEfpTxDfXFp5o2X3ibb5ojGWupGJ9ZxkThCx7rOGydnszJPzEbgDK3eF6nJ6UuE7bCTpIEutYnPw==} + engines: {node: '>=22'} + '@smithy/config-resolver@4.5.1': resolution: {integrity: sha512-abXk3LhODsvRHsk0ZS9ztrg/fZatTa9Z/z4pgx65YSLR+rY6kvUG/1IgcDKEUciR8MfdnkT5oPeHJTy/HhzDIQ==} engines: {node: '>=18.0.0'} @@ -851,6 +884,7 @@ packages: '@smithy/core@3.24.1': resolution: {integrity: sha512-3mT7o4qQyUWttYnVK3A0Z/u3Xha3E81tXn32Tz6vjZiUXhBrkEivpw1hBYfh84iFF9CSzkBU9Y1DJ3Q6RQ231g==} engines: {node: '>=18.0.0'} + deprecated: Deprecated due to bug in browser bundling instructions https://github.com/smithy-lang/smithy-typescript/issues/2025 '@smithy/credential-provider-imds@4.3.1': resolution: {integrity: sha512-0S/acwHnqX4WrjXzhdiDRxsG2s9SC0cpPIK9nZ1R6UOHd+j7uL28+4bHu22urbLk2TVw3fkp6na/+fkUt/pLNQ==} @@ -1083,6 +1117,9 @@ packages: resolution: {integrity: sha512-oP5VkATKlNwcgvxi0vM0p/D3n2C3EReYVX+DNYs5TjZFn/oQt2j+4sVJtSMr18pdRr8wjTcBl6LoV+FUwzPmNA==} engines: {node: '>=18'} + boolbase@1.0.0: + resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} + bowser@2.14.1: resolution: {integrity: sha512-tzPjzCxygAKWFOJP011oxFHs57HzIhOEracIgAePE4pqB3LikALKnSzUyU4MGs9/iCEUuHlAJTjTc5M+u7YEGg==} @@ -1121,6 +1158,13 @@ packages: resolution: {integrity: sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==} engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} + cheerio-select@2.1.0: + resolution: {integrity: sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==} + + cheerio@1.2.0: + resolution: {integrity: sha512-WDrybc/gKFpTYQutKIK6UvfcuxijIZfMfXaYm8NMsPQxSYvf+13fXUJ4rztGGbJcBQ/GF55gvrZ0Bc0bj/mqvg==} + engines: {node: '>=20.18.1'} + chownr@3.0.0: resolution: {integrity: sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==} engines: {node: '>=18'} @@ -1187,6 +1231,13 @@ packages: resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} engines: {node: '>= 8'} + css-select@5.2.2: + resolution: {integrity: sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==} + + css-what@6.2.2: + resolution: {integrity: sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==} + engines: {node: '>= 6'} + debug@4.4.3: resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} engines: {node: '>=6.0'} @@ -1208,6 +1259,19 @@ packages: resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} engines: {node: '>=8'} + dom-serializer@2.0.0: + resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==} + + domelementtype@2.3.0: + resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==} + + domhandler@5.0.3: + resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==} + engines: {node: '>= 4'} + + domutils@3.2.2: + resolution: {integrity: sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==} + dotenv@17.4.2: resolution: {integrity: sha512-nI4U3TottKAcAD9LLud4Cb7b2QztQMUEfHbvhTH09bqXTxnSie8WnjPALV/WMCrJZ6UV/qHJ6L03OqO3LcdYZw==} engines: {node: '>=12'} @@ -1226,6 +1290,21 @@ packages: resolution: {integrity: sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==} engines: {node: '>= 0.8'} + encoding-sniffer@0.2.1: + resolution: {integrity: sha512-5gvq20T6vfpekVtqrYQsSCFZ1wEg5+wW0/QaZMWkFr6BqD3NfKs0rLCx4rrVlSWJeZb5NBJgVLswK/w2MWU+Gw==} + + entities@4.5.0: + resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} + engines: {node: '>=0.12'} + + entities@6.0.1: + resolution: {integrity: sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==} + engines: {node: '>=0.12'} + + entities@7.0.1: + resolution: {integrity: sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==} + engines: {node: '>=0.12'} + es-define-property@1.0.1: resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} engines: {node: '>= 0.4'} @@ -1387,10 +1466,17 @@ packages: resolution: {integrity: sha512-RWzP96k/yv0PQfyXnWjs6zot20TqfpfsNXhOnev8d1InAxubW93L11/oNUc3tQqn2G0bSdAOBpX+2uDFHV7kdQ==} engines: {node: '>=16.9.0'} + htmlparser2@10.1.0: + resolution: {integrity: sha512-VTZkM9GWRAtEpveh7MSF6SjjrpNVNNVJfFup7xTY3UpFtm67foy9HDVXneLtFVt4pMz5kZtgNcvCniNFb1hlEQ==} + http-errors@2.0.1: resolution: {integrity: sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==} engines: {node: '>= 0.8'} + iconv-lite@0.6.3: + resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} + engines: {node: '>=0.10.0'} + iconv-lite@0.7.2: resolution: {integrity: sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==} engines: {node: '>=0.10.0'} @@ -1557,6 +1643,9 @@ packages: resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} engines: {node: '>=0.10.0'} + nth-check@2.1.1: + resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} + object-assign@4.1.1: resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} engines: {node: '>=0.10.0'} @@ -1584,6 +1673,15 @@ packages: resolution: {integrity: sha512-1Y1A//QUXEZK7YKz+rD9WydcE1+EuPr6ZBgKecAB8tmoW6UFv0NREVJe1p+jRxtThkcbbKkfwIbWJe/IeE6m2Q==} engines: {node: '>=0.10.0'} + parse5-htmlparser2-tree-adapter@7.1.0: + resolution: {integrity: sha512-ruw5xyKs6lrpo9x9rCZqZZnIUntICjQAd0Wsmp396Ul9lN/h+ifgVV1x1gZHi8euej6wTfpqX8j+BFQxF0NS/g==} + + parse5-parser-stream@7.1.2: + resolution: {integrity: sha512-JyeQc9iwFLn5TbvvqACIF/VXG6abODeB3Fwmv/TGdLk2LfbWkaySGY72at4+Ty7EkPZj854u4CrICqNk2qIbow==} + + parse5@7.3.0: + resolution: {integrity: sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==} + parseurl@1.3.3: resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} engines: {node: '>= 0.8'} @@ -1815,6 +1913,10 @@ packages: undici-types@6.21.0: resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} + undici@7.25.0: + resolution: {integrity: sha512-xXnp4kTyor2Zq+J1FfPI6Eq3ew5h6Vl0F/8d9XU5zZQf1tX9s2Su1/3PiMmUANFULpmksxkClamIZcaUqryHsQ==} + engines: {node: '>=20.18.1'} + unpipe@1.0.0: resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} engines: {node: '>= 0.8'} @@ -1826,6 +1928,15 @@ packages: resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} engines: {node: '>= 0.8'} + whatwg-encoding@3.1.1: + resolution: {integrity: sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==} + engines: {node: '>=18'} + deprecated: Use @exodus/bytes instead for a more spec-conformant and faster implementation + + whatwg-mimetype@4.0.0: + resolution: {integrity: sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==} + engines: {node: '>=18'} + which@2.0.2: resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} engines: {node: '>= 8'} @@ -2983,11 +3094,34 @@ snapshots: '@relayburn/sdk-linux-arm64-gnu': 2.5.2 '@relayburn/sdk-linux-x64-gnu': 2.5.2 + '@relayfile/adapter-core@0.3.13(@relayfile/sdk@0.7.40)': + dependencies: + '@relayfile/sdk': 0.7.40 + '@scalar/postman-to-openapi': 0.6.3 + cheerio: 1.2.0 + minimatch: 10.2.5 + yaml: 2.9.0 + + '@relayfile/core@0.7.40': {} + '@relayfile/local-mount@0.7.24': dependencies: '@parcel/watcher': 2.5.6 ignore: 7.0.5 + '@relayfile/sdk@0.7.40': + dependencies: + '@relayfile/core': 0.7.40 + + '@scalar/helpers@0.5.1': {} + + '@scalar/openapi-types@0.7.0': {} + + '@scalar/postman-to-openapi@0.6.3': + dependencies: + '@scalar/helpers': 0.5.1 + '@scalar/openapi-types': 0.7.0 + '@smithy/config-resolver@4.5.1': dependencies: '@smithy/core': 3.24.1 @@ -3282,6 +3416,8 @@ snapshots: transitivePeerDependencies: - supports-color + boolbase@1.0.0: {} + bowser@2.14.1: {} brace-expansion@5.0.6: @@ -3318,6 +3454,29 @@ snapshots: chalk@5.6.2: {} + cheerio-select@2.1.0: + dependencies: + boolbase: 1.0.0 + css-select: 5.2.2 + css-what: 6.2.2 + domelementtype: 2.3.0 + domhandler: 5.0.3 + domutils: 3.2.2 + + cheerio@1.2.0: + dependencies: + cheerio-select: 2.1.0 + dom-serializer: 2.0.0 + domhandler: 5.0.3 + domutils: 3.2.2 + encoding-sniffer: 0.2.1 + htmlparser2: 10.1.0 + parse5: 7.3.0 + parse5-htmlparser2-tree-adapter: 7.1.0 + parse5-parser-stream: 7.1.2 + undici: 7.25.0 + whatwg-mimetype: 4.0.0 + chownr@3.0.0: {} cjs-module-lexer@2.2.0: {} @@ -3373,6 +3532,16 @@ snapshots: shebang-command: 2.0.0 which: 2.0.2 + css-select@5.2.2: + dependencies: + boolbase: 1.0.0 + css-what: 6.2.2 + domhandler: 5.0.3 + domutils: 3.2.2 + nth-check: 2.1.1 + + css-what@6.2.2: {} + debug@4.4.3: dependencies: ms: 2.1.3 @@ -3383,6 +3552,24 @@ snapshots: detect-libc@2.1.2: {} + dom-serializer@2.0.0: + dependencies: + domelementtype: 2.3.0 + domhandler: 5.0.3 + entities: 4.5.0 + + domelementtype@2.3.0: {} + + domhandler@5.0.3: + dependencies: + domelementtype: 2.3.0 + + domutils@3.2.2: + dependencies: + dom-serializer: 2.0.0 + domelementtype: 2.3.0 + domhandler: 5.0.3 + dotenv@17.4.2: {} dunder-proto@1.0.1: @@ -3397,6 +3584,17 @@ snapshots: encodeurl@2.0.0: {} + encoding-sniffer@0.2.1: + dependencies: + iconv-lite: 0.6.3 + whatwg-encoding: 3.1.1 + + entities@4.5.0: {} + + entities@6.0.1: {} + + entities@7.0.1: {} + es-define-property@1.0.1: {} es-errors@1.3.0: {} @@ -3608,6 +3806,13 @@ snapshots: hono@4.12.18: {} + htmlparser2@10.1.0: + dependencies: + domelementtype: 2.3.0 + domhandler: 5.0.3 + domutils: 3.2.2 + entities: 7.0.1 + http-errors@2.0.1: dependencies: depd: 2.0.0 @@ -3616,6 +3821,10 @@ snapshots: statuses: 2.0.2 toidentifier: 1.0.1 + iconv-lite@0.6.3: + dependencies: + safer-buffer: 2.1.2 + iconv-lite@0.7.2: dependencies: safer-buffer: 2.1.2 @@ -3730,6 +3939,10 @@ snapshots: normalize-path@3.0.0: {} + nth-check@2.1.1: + dependencies: + boolbase: 1.0.0 + object-assign@4.1.1: {} object-inspect@1.13.4: {} @@ -3759,6 +3972,19 @@ snapshots: parse-passwd@1.0.0: {} + parse5-htmlparser2-tree-adapter@7.1.0: + dependencies: + domhandler: 5.0.3 + parse5: 7.3.0 + + parse5-parser-stream@7.1.2: + dependencies: + parse5: 7.3.0 + + parse5@7.3.0: + dependencies: + entities: 6.0.1 + parseurl@1.3.3: {} path-expression-matcher@1.5.0: {} @@ -4030,12 +4256,20 @@ snapshots: undici-types@6.21.0: {} + undici@7.25.0: {} + unpipe@1.0.0: {} util-deprecate@1.0.2: {} vary@1.1.2: {} + whatwg-encoding@3.1.1: + dependencies: + iconv-lite: 0.6.3 + + whatwg-mimetype@4.0.0: {} + which@2.0.2: dependencies: isexe: 2.0.0