From 595358de8b9a17cb131f38a66d2285521106dcbd Mon Sep 17 00:00:00 2001 From: Ricky Schema Cascade Date: Mon, 25 May 2026 15:18:05 +0200 Subject: [PATCH 1/3] feat(persona-kit): typed persona.ts authoring that compiles to persona.json MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add definePersona() + typed authoring types in persona-kit, giving IDE autocomplete for integration trigger event names across all five known providers (github, linear, slack, notion, jira) via the existing KNOWN_TRIGGERS registry. The `KnownTriggerName

| (string & {})` pattern keeps off-registry events and unknown providers valid, so the runtime stays the source of truth. Add an `agentworkforce persona compile ` CLI command that esbuild-bundles the file, imports the default export, validates it with parsePersonaSpec, and writes the raw authored spec to a sibling persona.json. persona.json remains the runtime artifact — loaders and the deploy bundler are unchanged. Convert examples/review-agent to persona.ts as the demo (regenerated persona.json is semantically identical) and add tests for the typed helper and the compiler round-trip. Implemented by codex-2; reviewed and verified (persona-kit + cli tests, root typecheck incl. examples) before commit. Co-Authored-By: Claude Opus 4.7 (1M context) --- examples/review-agent/persona.json | 33 +++++-- examples/review-agent/persona.ts | 39 ++++++++ packages/cli/package.json | 1 + packages/cli/src/cli.ts | 13 +++ packages/cli/src/persona-compile.test.ts | 93 ++++++++++++++++++ packages/cli/src/persona-compile.ts | 117 +++++++++++++++++++++++ packages/persona-kit/src/define.test.ts | 59 ++++++++++++ packages/persona-kit/src/define.ts | 85 ++++++++++++++++ packages/persona-kit/src/index.ts | 10 ++ pnpm-lock.yaml | 3 + 10 files changed, 446 insertions(+), 7 deletions(-) create mode 100644 examples/review-agent/persona.ts create mode 100644 packages/cli/src/persona-compile.test.ts create mode 100644 packages/cli/src/persona-compile.ts create mode 100644 packages/persona-kit/src/define.test.ts create mode 100644 packages/persona-kit/src/define.ts 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/src/define.test.ts b/packages/persona-kit/src/define.test.ts new file mode 100644 index 00000000..38a1b276 --- /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.created' }] }, + slack: { triggers: [{ on: 'app_mention' }] }, + notion: { 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..557b1686 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, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 521fc70d..d471abf1 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 From c2b9d6034fdd1517b753933e6fa269017358cb66 Mon Sep 17 00:00:00 2001 From: Ricky Schema Cascade Date: Mon, 25 May 2026 16:27:31 +0200 Subject: [PATCH 2/3] feat(persona-kit): vendor relayfile trigger catalog --- packages/persona-kit/package.json | 3 + .../persona-kit/schemas/persona.schema.json | 2 +- .../scripts/sync-known-triggers.mjs | 44 ++ .../src/__fixtures__/personas/full.json | 9 +- .../integration-source-workspace.json | 2 +- packages/persona-kit/src/define.test.ts | 6 +- packages/persona-kit/src/index.ts | 2 + .../src/known-triggers.generated.test.ts | 20 + .../src/known-triggers.generated.ts | 523 ++++++++++++++++++ packages/persona-kit/src/triggers.test.ts | 7 +- packages/persona-kit/src/triggers.ts | 30 +- packages/persona-kit/src/types.ts | 4 +- pnpm-lock.yaml | 231 ++++++++ 13 files changed, 846 insertions(+), 37 deletions(-) create mode 100644 packages/persona-kit/scripts/sync-known-triggers.mjs create mode 100644 packages/persona-kit/src/known-triggers.generated.test.ts create mode 100644 packages/persona-kit/src/known-triggers.generated.ts diff --git a/packages/persona-kit/package.json b/packages/persona-kit/package.json index e0054f56..85e96e17 100644 --- a/packages/persona-kit/package.json +++ b/packages/persona-kit/package.json @@ -33,12 +33,15 @@ "typecheck": "tsc -p tsconfig.json --noEmit", "test": "tsc -p tsconfig.json && node --test dist/*.test.js", "emit:schema": "node ./scripts/emit-schema.mjs", + "sync:known-triggers": "node ./scripts/sync-known-triggers.mjs", + "check:known-triggers": "node ./scripts/sync-known-triggers.mjs --check", "lint": "tsc -p tsconfig.json --noEmit" }, "dependencies": { "@relayfile/local-mount": "^0.7.24" }, "devDependencies": { + "@relayfile/adapter-core": "0.3.12", "ts-json-schema-generator": "^2.3.0" } } 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/scripts/sync-known-triggers.mjs b/packages/persona-kit/scripts/sync-known-triggers.mjs new file mode 100644 index 00000000..04d80b94 --- /dev/null +++ b/packages/persona-kit/scripts/sync-known-triggers.mjs @@ -0,0 +1,44 @@ +import { readFile, writeFile } from 'node:fs/promises'; +import { dirname, resolve } from 'node:path'; +import { fileURLToPath } from 'node:url'; + +import { + ADAPTERS_WITHOUT_KNOWN_TRIGGERS, + KNOWN_TRIGGER_CATALOG +} from '@relayfile/adapter-core'; + +const packageRoot = resolve(dirname(fileURLToPath(import.meta.url)), '..'); +const outputPath = resolve(packageRoot, 'src/known-triggers.generated.ts'); +const check = process.argv.includes('--check'); + +const contents = `/** + * Vendored from @relayfile/adapter-core's generated trigger catalog. + * Regenerate with \`pnpm --filter @agentworkforce/persona-kit sync:known-triggers\`. + * + * Event names are emitted verbatim from adapter supportedEvents() methods or + * mapping.yaml webhooks keys. Do not normalize names across providers: the + * cloud runtime matches persona triggers against each adapter's real event.type. + */ + +export const KNOWN_TRIGGER_CATALOG = ${JSON.stringify(KNOWN_TRIGGER_CATALOG, null, 2)} as const satisfies Record< + string, + readonly string[] +>; + +export const ADAPTERS_WITHOUT_KNOWN_TRIGGERS = ${JSON.stringify(ADAPTERS_WITHOUT_KNOWN_TRIGGERS, null, 2)} as const; + +export type KnownProviderName = keyof typeof KNOWN_TRIGGER_CATALOG; +export type KnownTriggerName

= + (typeof KNOWN_TRIGGER_CATALOG)[P][number]; +`; + +if (check) { + const current = await readFile(outputPath, 'utf8'); + if (current !== contents) { + throw new Error( + 'known trigger catalog is out of sync; run `pnpm --filter @agentworkforce/persona-kit sync:known-triggers`' + ); + } +} else { + await writeFile(outputPath, contents); +} 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 index 38a1b276..4d48bf77 100644 --- a/packages/persona-kit/src/define.test.ts +++ b/packages/persona-kit/src/define.test.ts @@ -22,9 +22,9 @@ test('definePersona returns authored specs that parse successfully', () => { { on: 'off_registry.github_event' } ] }, - linear: { triggers: [{ on: 'issue.created' }] }, - slack: { triggers: [{ on: 'app_mention' }] }, - notion: { triggers: [{ on: 'page.updated' }] }, + 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' }] } }, diff --git a/packages/persona-kit/src/index.ts b/packages/persona-kit/src/index.ts index 557b1686..fa69554f 100644 --- a/packages/persona-kit/src/index.ts +++ b/packages/persona-kit/src/index.ts @@ -93,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/known-triggers.generated.test.ts b/packages/persona-kit/src/known-triggers.generated.test.ts new file mode 100644 index 00000000..405b1e43 --- /dev/null +++ b/packages/persona-kit/src/known-triggers.generated.test.ts @@ -0,0 +1,20 @@ +import test from 'node:test'; +import assert from 'node:assert/strict'; + +import { + ADAPTERS_WITHOUT_KNOWN_TRIGGERS as ADAPTER_CORE_WITHOUT_KNOWN_TRIGGERS, + KNOWN_TRIGGER_CATALOG as ADAPTER_CORE_TRIGGER_CATALOG +} from '@relayfile/adapter-core'; + +import { + ADAPTERS_WITHOUT_KNOWN_TRIGGERS, + KNOWN_TRIGGER_CATALOG +} from './known-triggers.generated.js'; + +test('vendored trigger catalog stays in sync with @relayfile/adapter-core', () => { + assert.deepEqual(KNOWN_TRIGGER_CATALOG, ADAPTER_CORE_TRIGGER_CATALOG); + assert.deepEqual( + ADAPTERS_WITHOUT_KNOWN_TRIGGERS, + ADAPTER_CORE_WITHOUT_KNOWN_TRIGGERS + ); +}); diff --git a/packages/persona-kit/src/known-triggers.generated.ts b/packages/persona-kit/src/known-triggers.generated.ts new file mode 100644 index 00000000..1cbcae4c --- /dev/null +++ b/packages/persona-kit/src/known-triggers.generated.ts @@ -0,0 +1,523 @@ +/** + * Vendored from @relayfile/adapter-core's generated trigger catalog. + * Regenerate with `pnpm --filter @agentworkforce/persona-kit sync:known-triggers`. + * + * Event names are emitted verbatim from adapter supportedEvents() methods or + * mapping.yaml webhooks keys. Do not normalize names across providers: the + * cloud runtime matches persona triggers against each adapter's real event.type. + */ + +export const KNOWN_TRIGGER_CATALOG = { + "airtable": [ + "base.create", + "base.delete", + "base.update", + "record.create", + "record.delete", + "record.update", + "table.create", + "table.delete", + "table.update" + ], + "asana": [ + "project.added", + "project.changed", + "project.deleted", + "project.removed", + "section.added", + "section.changed", + "section.deleted", + "section.removed", + "task.added", + "task.changed", + "task.completed", + "task.deleted", + "task.removed", + "workspace.added", + "workspace.changed", + "workspace.deleted", + "workspace.removed" + ], + "calendly": [ + "event_type.canceled", + "event_type.created", + "event_type.deleted", + "event_type.updated", + "invitee.canceled", + "invitee.created", + "invitee.deleted", + "invitee.updated", + "scheduled_event.canceled", + "scheduled_event.created", + "scheduled_event.deleted", + "scheduled_event.updated" + ], + "clickup": [ + "folder.created", + "folder.deleted", + "folder.updated", + "list.created", + "list.deleted", + "list.updated", + "space.created", + "space.deleted", + "space.updated", + "task.created", + "task.deleted", + "task.updated" + ], + "confluence": [ + "page.created", + "page.deleted", + "page.updated", + "space.created", + "space.deleted", + "space.updated" + ], + "github": [ + "check_run.completed", + "issues.closed", + "issues.opened", + "pull_request.closed", + "pull_request.opened", + "pull_request.synchronize", + "pull_request_review.submitted", + "pull_request_review_comment.created" + ], + "gitlab": [ + "build.canceled", + "build.created", + "build.failed", + "build.manual", + "build.pending", + "build.running", + "build.skipped", + "build.success", + "deployment.canceled", + "deployment.created", + "deployment.failed", + "deployment.running", + "deployment.success", + "issue.close", + "issue.open", + "issue.reopen", + "issue.update", + "job.canceled", + "job.created", + "job.failed", + "job.manual", + "job.pending", + "job.running", + "job.skipped", + "job.success", + "merge_request.approved", + "merge_request.close", + "merge_request.merge", + "merge_request.open", + "merge_request.reopen", + "merge_request.unapproved", + "merge_request.update", + "note.Commit", + "note.Issue", + "note.MergeRequest", + "note.Snippet", + "pipeline.canceled", + "pipeline.created", + "pipeline.failed", + "pipeline.manual", + "pipeline.pending", + "pipeline.running", + "pipeline.skipped", + "pipeline.success", + "pipeline.waiting_for_resource", + "push", + "tag_push" + ], + "google-calendar": [ + "calendar.exists", + "calendar.not_exists", + "calendar.sync" + ], + "hubspot": [ + "company.associationChange", + "company.created", + "company.deleted", + "company.merged", + "company.propertyChange", + "contact.associationChange", + "contact.created", + "contact.deleted", + "contact.merged", + "contact.propertyChange", + "deal.associationChange", + "deal.created", + "deal.deleted", + "deal.merged", + "deal.propertyChange", + "ticket.associationChange", + "ticket.created", + "ticket.deleted", + "ticket.merged", + "ticket.propertyChange" + ], + "intercom": [ + "company.archived", + "company.closed", + "company.created", + "company.deleted", + "company.reopened", + "company.updated", + "contact.archived", + "contact.closed", + "contact.created", + "contact.deleted", + "contact.reopened", + "contact.updated", + "conversation.archived", + "conversation.closed", + "conversation.created", + "conversation.deleted", + "conversation.reopened", + "conversation.updated" + ], + "jira": [ + "comment.created", + "comment.deleted", + "comment.updated", + "issue.created", + "issue.deleted", + "issue.updated", + "project.created", + "project.deleted", + "project.updated", + "sprint.created", + "sprint.deleted", + "sprint.updated" + ], + "linear": [ + "comment.create", + "comment.remove", + "comment.update", + "cycle.create", + "cycle.remove", + "cycle.update", + "issue.create", + "issue.remove", + "issue.update", + "milestone.create", + "milestone.remove", + "milestone.update", + "project.create", + "project.remove", + "project.update", + "roadmap.create", + "roadmap.remove", + "roadmap.update" + ], + "mailgun": [ + "event.accepted", + "event.clicked", + "event.complained", + "event.delivered", + "event.failed", + "event.opened", + "event.permanent_fail", + "event.stored", + "event.unsubscribed", + "list.created", + "list.updated", + "message.accepted", + "message.delivered", + "message.failed", + "message.stored" + ], + "mixpanel": [ + "cohort.create", + "cohort.delete", + "cohort.merge", + "cohort.update", + "event.create", + "event.delete", + "event.merge", + "event.update", + "profile.create", + "profile.delete", + "profile.merge", + "profile.update" + ], + "pipedrive": [ + "activity.created", + "activity.deleted", + "activity.updated", + "deal.created", + "deal.deleted", + "deal.lost", + "deal.updated", + "deal.won", + "organization.created", + "organization.deleted", + "organization.updated", + "person.created", + "person.deleted", + "person.updated" + ], + "salesforce": [ + "Account.created", + "Account.deleted", + "Account.updated", + "Account.upserted", + "Case.closed", + "Case.created", + "Case.deleted", + "Case.updated", + "Case.upserted", + "Contact.created", + "Contact.deleted", + "Contact.updated", + "Contact.upserted", + "Lead.converted", + "Lead.created", + "Lead.deleted", + "Lead.updated", + "Lead.upserted", + "Opportunity.created", + "Opportunity.deleted", + "Opportunity.updated", + "Opportunity.upserted" + ], + "segment": [ + "group.create", + "group.update", + "group.upsert", + "identify.create", + "identify.update", + "identify.upsert", + "page.create", + "page.update", + "page.upsert", + "track.create", + "track.update", + "track.upsert" + ], + "sendgrid": [ + "contact.create", + "contact.delete", + "contact.update", + "event.bounce", + "event.click", + "event.deferred", + "event.delivered", + "event.dropped", + "event.group_resubscribe", + "event.group_unsubscribe", + "event.open", + "event.processed", + "event.spamreport", + "event.unsubscribe", + "mail.create", + "mail.delete", + "mail.update" + ], + "shopify": [ + "customer.cancel", + "customer.create", + "customer.delete", + "customer.fulfill", + "customer.paid", + "customer.update", + "fulfillment.cancel", + "fulfillment.create", + "fulfillment.delete", + "fulfillment.fulfill", + "fulfillment.paid", + "fulfillment.update", + "order.cancel", + "order.create", + "order.delete", + "order.fulfill", + "order.paid", + "order.update", + "product.cancel", + "product.create", + "product.delete", + "product.fulfill", + "product.paid", + "product.update" + ], + "slack": [ + "channel.archived", + "channel.created", + "channel.deleted", + "channel.member_joined", + "channel.member_left", + "channel.renamed", + "channel.unarchived", + "group.archived", + "group.deleted", + "group.renamed", + "group.unarchived", + "message.created", + "message.deleted", + "message.updated", + "reaction.added", + "reaction.removed", + "user.changed", + "user.joined" + ], + "stripe": [ + "charge.failed", + "charge.refunded", + "charge.succeeded", + "charge.updated", + "customer.created", + "customer.deleted", + "customer.subscription.created", + "customer.subscription.deleted", + "customer.subscription.updated", + "customer.updated", + "invoice.created", + "invoice.finalized", + "invoice.paid", + "invoice.payment_failed", + "invoice.updated", + "invoice.voided", + "payment_intent.canceled", + "payment_intent.created", + "payment_intent.payment_failed", + "payment_intent.requires_action", + "payment_intent.succeeded" + ], + "teams": [ + "channel.created", + "channel.deleted", + "channel.updated", + "chat.created", + "chat.deleted", + "chat.updated", + "chat_message.created", + "chat_message.deleted", + "chat_message.updated", + "member.created", + "member.deleted", + "member.updated", + "message.created", + "message.deleted", + "message.updated", + "reply.created", + "reply.deleted", + "reply.updated", + "team.deleted", + "team.updated" + ], + "zendesk": [ + "organization.created", + "organization.deleted", + "organization.updated", + "ticket.created", + "ticket.deleted", + "ticket.updated", + "user.created", + "user.deleted", + "user.updated" + ] +} as const satisfies Record< + string, + readonly string[] +>; + +export const ADAPTERS_WITHOUT_KNOWN_TRIGGERS = [ + { + "packageName": "@relayfile/azure-blob", + "packagePath": "packages/azure-blob", + "provider": "azure-blob", + "reason": "No supportedEvents() implementation and no mapping.yaml webhooks block" + }, + { + "packageName": "@relayfile/box", + "packagePath": "packages/box", + "provider": "box", + "reason": "No supportedEvents() implementation and no mapping.yaml webhooks block" + }, + { + "packageName": "@relayfile/adapter-docker-hub", + "packagePath": "packages/docker-hub", + "provider": "docker-hub", + "reason": "No supportedEvents() implementation and no mapping.yaml webhooks block" + }, + { + "packageName": "@relayfile/dropbox", + "packagePath": "packages/dropbox", + "provider": "dropbox", + "reason": "No supportedEvents() implementation and no mapping.yaml webhooks block" + }, + { + "packageName": "@relayfile/gcs", + "packagePath": "packages/gcs", + "provider": "gcs", + "reason": "No supportedEvents() implementation and no mapping.yaml webhooks block" + }, + { + "packageName": "@relayfile/gmail", + "packagePath": "packages/gmail", + "provider": "gmail", + "reason": "No supportedEvents() implementation and no mapping.yaml webhooks block" + }, + { + "packageName": "@relayfile/google-drive", + "packagePath": "packages/google-drive", + "provider": "google-drive", + "reason": "No supportedEvents() implementation and no mapping.yaml webhooks block" + }, + { + "packageName": "@relayfile/adapter-granola", + "packagePath": "packages/granola", + "provider": "granola", + "reason": "No supportedEvents() implementation and no mapping.yaml webhooks block" + }, + { + "packageName": "@relayfile/adapter-notion", + "packagePath": "packages/notion", + "provider": "notion", + "reason": "No supportedEvents() implementation and no mapping.yaml webhooks block" + }, + { + "packageName": "@relayfile/onedrive", + "packagePath": "packages/onedrive", + "provider": "onedrive", + "reason": "No supportedEvents() implementation and no mapping.yaml webhooks block" + }, + { + "packageName": "@relayfile/postgres", + "packagePath": "packages/postgres", + "provider": "postgres", + "reason": "No supportedEvents() implementation and no mapping.yaml webhooks block" + }, + { + "packageName": "@relayfile/redis", + "packagePath": "packages/redis", + "provider": "redis", + "reason": "No supportedEvents() implementation and no mapping.yaml webhooks block" + }, + { + "packageName": "@relayfile/s3", + "packagePath": "packages/s3", + "provider": "s3", + "reason": "No supportedEvents() implementation and no mapping.yaml webhooks block" + }, + { + "packageName": "@relayfile/sharepoint", + "packagePath": "packages/sharepoint", + "provider": "sharepoint", + "reason": "No supportedEvents() implementation and no mapping.yaml webhooks block" + }, + { + "packageName": "@relayfile/adapter-x", + "packagePath": "packages/x", + "provider": "x", + "reason": "No supportedEvents() implementation and no mapping.yaml webhooks block" + } +] as const; + +export type KnownProviderName = keyof typeof KNOWN_TRIGGER_CATALOG; +export type KnownTriggerName

= + (typeof KNOWN_TRIGGER_CATALOG)[P][number]; 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..29a0f868 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 './known-triggers.generated.js'; /** * 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 './known-triggers.generated.js'; 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 d471abf1..935a365d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -96,6 +96,9 @@ importers: specifier: ^0.7.24 version: 0.7.24 devDependencies: + '@relayfile/adapter-core': + specifier: 0.3.12 + version: 0.3.12(@relayfile/sdk@0.7.40) ts-json-schema-generator: specifier: ^2.3.0 version: 2.9.0 @@ -843,10 +846,37 @@ packages: resolution: {integrity: sha512-C5eVSepGrlQY5b1yg+LfROLYhDW/w1WFVsuitRzvbXMr+qpFYFHLoMNxa9R0Q6ZiP02r6EXSazii2VNo2LZ0Vg==} engines: {node: '>=22'} + '@relayfile/adapter-core@0.3.12': + resolution: {integrity: sha512-moxFEJ3ZxXeHneMD1YgFGBgJGPsqCAdFcgH+cNLBXyJd2/+d7A8hPiGV36lXs3WG3W2eEVFdyCf5LSyhC+9CDg==} + 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'} @@ -854,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==} @@ -1086,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==} @@ -1124,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'} @@ -1190,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'} @@ -1211,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'} @@ -1229,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'} @@ -1390,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'} @@ -1560,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'} @@ -1587,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'} @@ -1818,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'} @@ -1829,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'} @@ -2986,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.12(@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 @@ -3285,6 +3416,8 @@ snapshots: transitivePeerDependencies: - supports-color + boolbase@1.0.0: {} + bowser@2.14.1: {} brace-expansion@5.0.6: @@ -3321,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: {} @@ -3376,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 @@ -3386,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: @@ -3400,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: {} @@ -3611,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 @@ -3619,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 @@ -3733,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: {} @@ -3762,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: {} @@ -4033,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 From 5bc0daf0b188d7b73058acfa760adb5cd6a2196f Mon Sep 17 00:00:00 2001 From: Ricky Schema Cascade Date: Mon, 25 May 2026 17:05:22 +0200 Subject: [PATCH 3/3] refactor(persona-kit): consume @relayfile/adapter-core/triggers, drop vendored catalog --- packages/persona-kit/package.json | 4 +- .../scripts/sync-known-triggers.mjs | 44 -- .../src/known-triggers.generated.test.ts | 20 - .../src/known-triggers.generated.ts | 523 ------------------ packages/persona-kit/src/triggers.ts | 4 +- pnpm-lock.yaml | 12 +- 6 files changed, 9 insertions(+), 598 deletions(-) delete mode 100644 packages/persona-kit/scripts/sync-known-triggers.mjs delete mode 100644 packages/persona-kit/src/known-triggers.generated.test.ts delete mode 100644 packages/persona-kit/src/known-triggers.generated.ts diff --git a/packages/persona-kit/package.json b/packages/persona-kit/package.json index 85e96e17..a2a0f495 100644 --- a/packages/persona-kit/package.json +++ b/packages/persona-kit/package.json @@ -33,15 +33,13 @@ "typecheck": "tsc -p tsconfig.json --noEmit", "test": "tsc -p tsconfig.json && node --test dist/*.test.js", "emit:schema": "node ./scripts/emit-schema.mjs", - "sync:known-triggers": "node ./scripts/sync-known-triggers.mjs", - "check:known-triggers": "node ./scripts/sync-known-triggers.mjs --check", "lint": "tsc -p tsconfig.json --noEmit" }, "dependencies": { + "@relayfile/adapter-core": "^0.3.13", "@relayfile/local-mount": "^0.7.24" }, "devDependencies": { - "@relayfile/adapter-core": "0.3.12", "ts-json-schema-generator": "^2.3.0" } } diff --git a/packages/persona-kit/scripts/sync-known-triggers.mjs b/packages/persona-kit/scripts/sync-known-triggers.mjs deleted file mode 100644 index 04d80b94..00000000 --- a/packages/persona-kit/scripts/sync-known-triggers.mjs +++ /dev/null @@ -1,44 +0,0 @@ -import { readFile, writeFile } from 'node:fs/promises'; -import { dirname, resolve } from 'node:path'; -import { fileURLToPath } from 'node:url'; - -import { - ADAPTERS_WITHOUT_KNOWN_TRIGGERS, - KNOWN_TRIGGER_CATALOG -} from '@relayfile/adapter-core'; - -const packageRoot = resolve(dirname(fileURLToPath(import.meta.url)), '..'); -const outputPath = resolve(packageRoot, 'src/known-triggers.generated.ts'); -const check = process.argv.includes('--check'); - -const contents = `/** - * Vendored from @relayfile/adapter-core's generated trigger catalog. - * Regenerate with \`pnpm --filter @agentworkforce/persona-kit sync:known-triggers\`. - * - * Event names are emitted verbatim from adapter supportedEvents() methods or - * mapping.yaml webhooks keys. Do not normalize names across providers: the - * cloud runtime matches persona triggers against each adapter's real event.type. - */ - -export const KNOWN_TRIGGER_CATALOG = ${JSON.stringify(KNOWN_TRIGGER_CATALOG, null, 2)} as const satisfies Record< - string, - readonly string[] ->; - -export const ADAPTERS_WITHOUT_KNOWN_TRIGGERS = ${JSON.stringify(ADAPTERS_WITHOUT_KNOWN_TRIGGERS, null, 2)} as const; - -export type KnownProviderName = keyof typeof KNOWN_TRIGGER_CATALOG; -export type KnownTriggerName

= - (typeof KNOWN_TRIGGER_CATALOG)[P][number]; -`; - -if (check) { - const current = await readFile(outputPath, 'utf8'); - if (current !== contents) { - throw new Error( - 'known trigger catalog is out of sync; run `pnpm --filter @agentworkforce/persona-kit sync:known-triggers`' - ); - } -} else { - await writeFile(outputPath, contents); -} diff --git a/packages/persona-kit/src/known-triggers.generated.test.ts b/packages/persona-kit/src/known-triggers.generated.test.ts deleted file mode 100644 index 405b1e43..00000000 --- a/packages/persona-kit/src/known-triggers.generated.test.ts +++ /dev/null @@ -1,20 +0,0 @@ -import test from 'node:test'; -import assert from 'node:assert/strict'; - -import { - ADAPTERS_WITHOUT_KNOWN_TRIGGERS as ADAPTER_CORE_WITHOUT_KNOWN_TRIGGERS, - KNOWN_TRIGGER_CATALOG as ADAPTER_CORE_TRIGGER_CATALOG -} from '@relayfile/adapter-core'; - -import { - ADAPTERS_WITHOUT_KNOWN_TRIGGERS, - KNOWN_TRIGGER_CATALOG -} from './known-triggers.generated.js'; - -test('vendored trigger catalog stays in sync with @relayfile/adapter-core', () => { - assert.deepEqual(KNOWN_TRIGGER_CATALOG, ADAPTER_CORE_TRIGGER_CATALOG); - assert.deepEqual( - ADAPTERS_WITHOUT_KNOWN_TRIGGERS, - ADAPTER_CORE_WITHOUT_KNOWN_TRIGGERS - ); -}); diff --git a/packages/persona-kit/src/known-triggers.generated.ts b/packages/persona-kit/src/known-triggers.generated.ts deleted file mode 100644 index 1cbcae4c..00000000 --- a/packages/persona-kit/src/known-triggers.generated.ts +++ /dev/null @@ -1,523 +0,0 @@ -/** - * Vendored from @relayfile/adapter-core's generated trigger catalog. - * Regenerate with `pnpm --filter @agentworkforce/persona-kit sync:known-triggers`. - * - * Event names are emitted verbatim from adapter supportedEvents() methods or - * mapping.yaml webhooks keys. Do not normalize names across providers: the - * cloud runtime matches persona triggers against each adapter's real event.type. - */ - -export const KNOWN_TRIGGER_CATALOG = { - "airtable": [ - "base.create", - "base.delete", - "base.update", - "record.create", - "record.delete", - "record.update", - "table.create", - "table.delete", - "table.update" - ], - "asana": [ - "project.added", - "project.changed", - "project.deleted", - "project.removed", - "section.added", - "section.changed", - "section.deleted", - "section.removed", - "task.added", - "task.changed", - "task.completed", - "task.deleted", - "task.removed", - "workspace.added", - "workspace.changed", - "workspace.deleted", - "workspace.removed" - ], - "calendly": [ - "event_type.canceled", - "event_type.created", - "event_type.deleted", - "event_type.updated", - "invitee.canceled", - "invitee.created", - "invitee.deleted", - "invitee.updated", - "scheduled_event.canceled", - "scheduled_event.created", - "scheduled_event.deleted", - "scheduled_event.updated" - ], - "clickup": [ - "folder.created", - "folder.deleted", - "folder.updated", - "list.created", - "list.deleted", - "list.updated", - "space.created", - "space.deleted", - "space.updated", - "task.created", - "task.deleted", - "task.updated" - ], - "confluence": [ - "page.created", - "page.deleted", - "page.updated", - "space.created", - "space.deleted", - "space.updated" - ], - "github": [ - "check_run.completed", - "issues.closed", - "issues.opened", - "pull_request.closed", - "pull_request.opened", - "pull_request.synchronize", - "pull_request_review.submitted", - "pull_request_review_comment.created" - ], - "gitlab": [ - "build.canceled", - "build.created", - "build.failed", - "build.manual", - "build.pending", - "build.running", - "build.skipped", - "build.success", - "deployment.canceled", - "deployment.created", - "deployment.failed", - "deployment.running", - "deployment.success", - "issue.close", - "issue.open", - "issue.reopen", - "issue.update", - "job.canceled", - "job.created", - "job.failed", - "job.manual", - "job.pending", - "job.running", - "job.skipped", - "job.success", - "merge_request.approved", - "merge_request.close", - "merge_request.merge", - "merge_request.open", - "merge_request.reopen", - "merge_request.unapproved", - "merge_request.update", - "note.Commit", - "note.Issue", - "note.MergeRequest", - "note.Snippet", - "pipeline.canceled", - "pipeline.created", - "pipeline.failed", - "pipeline.manual", - "pipeline.pending", - "pipeline.running", - "pipeline.skipped", - "pipeline.success", - "pipeline.waiting_for_resource", - "push", - "tag_push" - ], - "google-calendar": [ - "calendar.exists", - "calendar.not_exists", - "calendar.sync" - ], - "hubspot": [ - "company.associationChange", - "company.created", - "company.deleted", - "company.merged", - "company.propertyChange", - "contact.associationChange", - "contact.created", - "contact.deleted", - "contact.merged", - "contact.propertyChange", - "deal.associationChange", - "deal.created", - "deal.deleted", - "deal.merged", - "deal.propertyChange", - "ticket.associationChange", - "ticket.created", - "ticket.deleted", - "ticket.merged", - "ticket.propertyChange" - ], - "intercom": [ - "company.archived", - "company.closed", - "company.created", - "company.deleted", - "company.reopened", - "company.updated", - "contact.archived", - "contact.closed", - "contact.created", - "contact.deleted", - "contact.reopened", - "contact.updated", - "conversation.archived", - "conversation.closed", - "conversation.created", - "conversation.deleted", - "conversation.reopened", - "conversation.updated" - ], - "jira": [ - "comment.created", - "comment.deleted", - "comment.updated", - "issue.created", - "issue.deleted", - "issue.updated", - "project.created", - "project.deleted", - "project.updated", - "sprint.created", - "sprint.deleted", - "sprint.updated" - ], - "linear": [ - "comment.create", - "comment.remove", - "comment.update", - "cycle.create", - "cycle.remove", - "cycle.update", - "issue.create", - "issue.remove", - "issue.update", - "milestone.create", - "milestone.remove", - "milestone.update", - "project.create", - "project.remove", - "project.update", - "roadmap.create", - "roadmap.remove", - "roadmap.update" - ], - "mailgun": [ - "event.accepted", - "event.clicked", - "event.complained", - "event.delivered", - "event.failed", - "event.opened", - "event.permanent_fail", - "event.stored", - "event.unsubscribed", - "list.created", - "list.updated", - "message.accepted", - "message.delivered", - "message.failed", - "message.stored" - ], - "mixpanel": [ - "cohort.create", - "cohort.delete", - "cohort.merge", - "cohort.update", - "event.create", - "event.delete", - "event.merge", - "event.update", - "profile.create", - "profile.delete", - "profile.merge", - "profile.update" - ], - "pipedrive": [ - "activity.created", - "activity.deleted", - "activity.updated", - "deal.created", - "deal.deleted", - "deal.lost", - "deal.updated", - "deal.won", - "organization.created", - "organization.deleted", - "organization.updated", - "person.created", - "person.deleted", - "person.updated" - ], - "salesforce": [ - "Account.created", - "Account.deleted", - "Account.updated", - "Account.upserted", - "Case.closed", - "Case.created", - "Case.deleted", - "Case.updated", - "Case.upserted", - "Contact.created", - "Contact.deleted", - "Contact.updated", - "Contact.upserted", - "Lead.converted", - "Lead.created", - "Lead.deleted", - "Lead.updated", - "Lead.upserted", - "Opportunity.created", - "Opportunity.deleted", - "Opportunity.updated", - "Opportunity.upserted" - ], - "segment": [ - "group.create", - "group.update", - "group.upsert", - "identify.create", - "identify.update", - "identify.upsert", - "page.create", - "page.update", - "page.upsert", - "track.create", - "track.update", - "track.upsert" - ], - "sendgrid": [ - "contact.create", - "contact.delete", - "contact.update", - "event.bounce", - "event.click", - "event.deferred", - "event.delivered", - "event.dropped", - "event.group_resubscribe", - "event.group_unsubscribe", - "event.open", - "event.processed", - "event.spamreport", - "event.unsubscribe", - "mail.create", - "mail.delete", - "mail.update" - ], - "shopify": [ - "customer.cancel", - "customer.create", - "customer.delete", - "customer.fulfill", - "customer.paid", - "customer.update", - "fulfillment.cancel", - "fulfillment.create", - "fulfillment.delete", - "fulfillment.fulfill", - "fulfillment.paid", - "fulfillment.update", - "order.cancel", - "order.create", - "order.delete", - "order.fulfill", - "order.paid", - "order.update", - "product.cancel", - "product.create", - "product.delete", - "product.fulfill", - "product.paid", - "product.update" - ], - "slack": [ - "channel.archived", - "channel.created", - "channel.deleted", - "channel.member_joined", - "channel.member_left", - "channel.renamed", - "channel.unarchived", - "group.archived", - "group.deleted", - "group.renamed", - "group.unarchived", - "message.created", - "message.deleted", - "message.updated", - "reaction.added", - "reaction.removed", - "user.changed", - "user.joined" - ], - "stripe": [ - "charge.failed", - "charge.refunded", - "charge.succeeded", - "charge.updated", - "customer.created", - "customer.deleted", - "customer.subscription.created", - "customer.subscription.deleted", - "customer.subscription.updated", - "customer.updated", - "invoice.created", - "invoice.finalized", - "invoice.paid", - "invoice.payment_failed", - "invoice.updated", - "invoice.voided", - "payment_intent.canceled", - "payment_intent.created", - "payment_intent.payment_failed", - "payment_intent.requires_action", - "payment_intent.succeeded" - ], - "teams": [ - "channel.created", - "channel.deleted", - "channel.updated", - "chat.created", - "chat.deleted", - "chat.updated", - "chat_message.created", - "chat_message.deleted", - "chat_message.updated", - "member.created", - "member.deleted", - "member.updated", - "message.created", - "message.deleted", - "message.updated", - "reply.created", - "reply.deleted", - "reply.updated", - "team.deleted", - "team.updated" - ], - "zendesk": [ - "organization.created", - "organization.deleted", - "organization.updated", - "ticket.created", - "ticket.deleted", - "ticket.updated", - "user.created", - "user.deleted", - "user.updated" - ] -} as const satisfies Record< - string, - readonly string[] ->; - -export const ADAPTERS_WITHOUT_KNOWN_TRIGGERS = [ - { - "packageName": "@relayfile/azure-blob", - "packagePath": "packages/azure-blob", - "provider": "azure-blob", - "reason": "No supportedEvents() implementation and no mapping.yaml webhooks block" - }, - { - "packageName": "@relayfile/box", - "packagePath": "packages/box", - "provider": "box", - "reason": "No supportedEvents() implementation and no mapping.yaml webhooks block" - }, - { - "packageName": "@relayfile/adapter-docker-hub", - "packagePath": "packages/docker-hub", - "provider": "docker-hub", - "reason": "No supportedEvents() implementation and no mapping.yaml webhooks block" - }, - { - "packageName": "@relayfile/dropbox", - "packagePath": "packages/dropbox", - "provider": "dropbox", - "reason": "No supportedEvents() implementation and no mapping.yaml webhooks block" - }, - { - "packageName": "@relayfile/gcs", - "packagePath": "packages/gcs", - "provider": "gcs", - "reason": "No supportedEvents() implementation and no mapping.yaml webhooks block" - }, - { - "packageName": "@relayfile/gmail", - "packagePath": "packages/gmail", - "provider": "gmail", - "reason": "No supportedEvents() implementation and no mapping.yaml webhooks block" - }, - { - "packageName": "@relayfile/google-drive", - "packagePath": "packages/google-drive", - "provider": "google-drive", - "reason": "No supportedEvents() implementation and no mapping.yaml webhooks block" - }, - { - "packageName": "@relayfile/adapter-granola", - "packagePath": "packages/granola", - "provider": "granola", - "reason": "No supportedEvents() implementation and no mapping.yaml webhooks block" - }, - { - "packageName": "@relayfile/adapter-notion", - "packagePath": "packages/notion", - "provider": "notion", - "reason": "No supportedEvents() implementation and no mapping.yaml webhooks block" - }, - { - "packageName": "@relayfile/onedrive", - "packagePath": "packages/onedrive", - "provider": "onedrive", - "reason": "No supportedEvents() implementation and no mapping.yaml webhooks block" - }, - { - "packageName": "@relayfile/postgres", - "packagePath": "packages/postgres", - "provider": "postgres", - "reason": "No supportedEvents() implementation and no mapping.yaml webhooks block" - }, - { - "packageName": "@relayfile/redis", - "packagePath": "packages/redis", - "provider": "redis", - "reason": "No supportedEvents() implementation and no mapping.yaml webhooks block" - }, - { - "packageName": "@relayfile/s3", - "packagePath": "packages/s3", - "provider": "s3", - "reason": "No supportedEvents() implementation and no mapping.yaml webhooks block" - }, - { - "packageName": "@relayfile/sharepoint", - "packagePath": "packages/sharepoint", - "provider": "sharepoint", - "reason": "No supportedEvents() implementation and no mapping.yaml webhooks block" - }, - { - "packageName": "@relayfile/adapter-x", - "packagePath": "packages/x", - "provider": "x", - "reason": "No supportedEvents() implementation and no mapping.yaml webhooks block" - } -] as const; - -export type KnownProviderName = keyof typeof KNOWN_TRIGGER_CATALOG; -export type KnownTriggerName

= - (typeof KNOWN_TRIGGER_CATALOG)[P][number]; diff --git a/packages/persona-kit/src/triggers.ts b/packages/persona-kit/src/triggers.ts index 29a0f868..b90c9299 100644 --- a/packages/persona-kit/src/triggers.ts +++ b/packages/persona-kit/src/triggers.ts @@ -1,5 +1,5 @@ import type { PersonaSpec } from './types.js'; -import { KNOWN_TRIGGER_CATALOG } from './known-triggers.generated.js'; +import { KNOWN_TRIGGER_CATALOG } from '@relayfile/adapter-core/triggers'; /** * Known event names per Relayfile provider, used by the deploy CLI to lint @@ -15,7 +15,7 @@ export { KNOWN_TRIGGER_CATALOG, type KnownProviderName, type KnownTriggerName -} from './known-triggers.generated.js'; +} from '@relayfile/adapter-core/triggers'; export type TriggerLintLevel = 'warning'; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 935a365d..0920b568 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -92,13 +92,13 @@ 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 devDependencies: - '@relayfile/adapter-core': - specifier: 0.3.12 - version: 0.3.12(@relayfile/sdk@0.7.40) ts-json-schema-generator: specifier: ^2.3.0 version: 2.9.0 @@ -846,8 +846,8 @@ packages: resolution: {integrity: sha512-C5eVSepGrlQY5b1yg+LfROLYhDW/w1WFVsuitRzvbXMr+qpFYFHLoMNxa9R0Q6ZiP02r6EXSazii2VNo2LZ0Vg==} engines: {node: '>=22'} - '@relayfile/adapter-core@0.3.12': - resolution: {integrity: sha512-moxFEJ3ZxXeHneMD1YgFGBgJGPsqCAdFcgH+cNLBXyJd2/+d7A8hPiGV36lXs3WG3W2eEVFdyCf5LSyhC+9CDg==} + '@relayfile/adapter-core@0.3.13': + resolution: {integrity: sha512-4mi4b/qRS2vGZR/bew7A+LWs55bPHi9ZTH27IJVBCVZj0o6/rEzDuY1ber2HGi7yx6or6knuHs6d9XtxjCBvPg==} engines: {node: '>=18'} hasBin: true peerDependencies: @@ -3094,7 +3094,7 @@ snapshots: '@relayburn/sdk-linux-arm64-gnu': 2.5.2 '@relayburn/sdk-linux-x64-gnu': 2.5.2 - '@relayfile/adapter-core@0.3.12(@relayfile/sdk@0.7.40)': + '@relayfile/adapter-core@0.3.13(@relayfile/sdk@0.7.40)': dependencies: '@relayfile/sdk': 0.7.40 '@scalar/postman-to-openapi': 0.6.3