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
.tsfile withDeno.readTextFile() extractModelType()— regex forModelType.create("...")extractModelVersion()— regex forversion: "..."extractMethods()— regex formethods: { methodName: { description: "..." } }extractMethodArguments()— regex forz.object({ field: z.string()... })extractResources()— regex forresources: { key: { description: "..." } }extractFiles()— regex forfiles: { key: { description: "..." } }fileNameset torelative(modelsDir, filePath)(nomodels/prefix)
Workflow extraction (YAML-based, @std/yaml already in deno.json):
- Read each workflow
.yamlfile withDeno.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
deno check— type checkingdeno lint— lintingdeno fmt— formattingdeno run test— all tests pass (existing + new)deno run compile— binary compiles- Manual:
swamp extension push --dry-runon an extension with models/workflows
Closed
No activity in this phase yet.
Sign in to post a ripple.