Skip to main content
← Back to list
01Issue
FeatureClosedSwamp Club
AssigneesNone

feat: send content metadata from CLI during extension push

Opened by swampadmin · 3/22/2025

Context

The swamp-club server (after systeminit/swamp-club#168) will accept an optional contentMetadata field in the confirm push request. The swamp CLI already has all model .ts and workflow .yaml source files in memory during push. We should extract metadata from those files and send it with the confirm call, avoiding redundant server-side archive parsing.

Depends on: systeminit/swamp-club#168

Changes

1. New types — src/domain/extensions/extension_content.ts

Define types matching what swamp-club expects (from extension-content.ts in PR systeminit/swamp-club#145):

export interface ExtractedArgument { name: string; type: string; description: string; required: boolean }
export interface ExtractedMethod { name: string; description: string; arguments: ExtractedArgument[] }
export interface ExtractedResource { key: string; description: string; lifetime: string }
export interface ExtractedFile { key: string; description: string; contentType: string }
export interface ExtractedModel { fileName: string; type: string; version: string; methods: ExtractedMethod[]; resources: ExtractedResource[]; files: ExtractedFile[] }
export interface ExtractedWorkflowStep { name: string; description: string; taskType: string; modelIdOrName: string; methodName: string }
export interface ExtractedWorkflowJob { name: string; description: string; steps: ExtractedWorkflowStep[] }
export interface ExtractedWorkflow { id: string; name: string; description: string; jobs: ExtractedWorkflowJob[] }
export interface ExtensionContentMetadata { models: ExtractedModel[]; workflows: ExtractedWorkflow[] }

2. New extractor — src/domain/extensions/extension_content_extractor.ts

Follows existing domain patterns (analyzeExtensionSafety, resolveLocalImports).

Function signature:

export async function extractContentMetadata(
  modelFiles: string[],
  modelsDir: string,
  workflowFiles: Array<{ sourcePath: string; archiveName: string }>,
): Promise<ExtensionContentMetadata>

Model extraction (regex-based, same approach as swamp-club PR #145):

  • Read each model .ts file with Deno.readTextFile()
  • extractModelType() — regex for ModelType.create("...")
  • extractModelVersion() — regex for version: "..."
  • extractMethods() — regex for methods: { methodName: { description: "..." } }
  • extractMethodArguments() — regex for z.object({ field: z.string()... })
  • extractResources() — regex for resources: { key: { description: "..." } }
  • extractFiles() — regex for files: { key: { description: "..." } }
  • fileName set to relative(modelsDir, filePath) (no models/ prefix)

Workflow extraction (YAML-based, @std/yaml already in deno.json):

  • Read each workflow .yaml file with Deno.readTextFile()
  • Parse with parseYaml()
  • Extract id, name, description, jobs, steps (same logic as swamp-club PR)

Error handling: Non-fatal per file. If a single model/workflow fails to parse, skip it and continue. Log at debug level. Never throw — return partial results.

3. New tests — src/domain/extensions/extension_content_extractor_test.ts

Test cases:

  • Extracts model type from ModelType.create("ec2-instance")
  • Extracts version from version: "1.0.0"
  • Extracts methods with descriptions and arguments
  • Extracts resources and files
  • Handles models with no methods (returns null, skipped)
  • Parses workflow YAML with jobs and steps
  • Skips unparseable files gracefully (returns partial results)
  • Empty input returns { models: [], workflows: [] }

4. Update API client — src/infrastructure/http/extension_api_client.ts

Add contentMetadata to confirm push only:

export interface ConfirmPushMetadata extends PushMetadata {
  contentMetadata?: ExtensionContentMetadata;
}

Update confirmPush method signature to accept ConfirmPushMetadata. initiatePush stays unchanged (uses PushMetadata).

5. Wire into push command — src/cli/commands/extension_push.ts

Insert extraction after step 12 (bundling), before step 14 (archive creation). All model and workflow files are available at this point.

No user-facing output changes. Extraction results are debug-level only (visible with --verbose or SWAMP_LOG=debug), consistent with other internal operations in the push command.

In step 17, include content metadata in the confirm call only:

const confirmResult = await extensionClient.confirmPush(
  { ...pushMetadata, contentMetadata },
  credentials.apiKey,
);

Files touched

File Action
src/domain/extensions/extension_content.ts New — types
src/domain/extensions/extension_content_extractor.ts New — extraction logic
src/domain/extensions/extension_content_extractor_test.ts New — tests
src/infrastructure/http/extension_api_client.ts Modify — add ConfirmPushMetadata
src/cli/commands/extension_push.ts Modify — call extractor, pass to confirm

Verification

  1. deno check — type checking
  2. deno lint — linting
  3. deno fmt — formatting
  4. deno run test — all tests pass (existing + new)
  5. deno run compile — binary compiles
  6. Manual: swamp extension push --dry-run on an extension with models/workflows
02Bog Flow
OPENTRIAGEDIN PROGRESSCLOSED

Closed

No activity in this phase yet.

03Sludge Pulse

Sign in to post a ripple.