@ashdev/codex-plugin-sync-echo 1.39.9 → 1.39.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -545,7 +545,7 @@ function createSyncPlugin(options) {
|
|
|
545
545
|
// package.json
|
|
546
546
|
var package_default = {
|
|
547
547
|
name: "@ashdev/codex-plugin-sync-echo",
|
|
548
|
-
version: "1.39.
|
|
548
|
+
version: "1.39.10",
|
|
549
549
|
description: "Echo sync plugin for testing and debugging the Codex plugin sync protocol",
|
|
550
550
|
main: "dist/index.js",
|
|
551
551
|
bin: "dist/index.js",
|
|
@@ -584,7 +584,7 @@ var package_default = {
|
|
|
584
584
|
node: ">=22.0.0"
|
|
585
585
|
},
|
|
586
586
|
dependencies: {
|
|
587
|
-
"@ashdev/codex-plugin-sdk": "^1.39.
|
|
587
|
+
"@ashdev/codex-plugin-sdk": "^1.39.10"
|
|
588
588
|
},
|
|
589
589
|
devDependencies: {
|
|
590
590
|
"@biomejs/biome": "^2.4.4",
|
package/dist/index.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../node_modules/@ashdev/codex-plugin-sdk/src/types/rpc.ts", "../node_modules/@ashdev/codex-plugin-sdk/src/errors.ts", "../node_modules/@ashdev/codex-plugin-sdk/src/request-context.ts", "../node_modules/@ashdev/codex-plugin-sdk/src/host-rpc.ts", "../node_modules/@ashdev/codex-plugin-sdk/src/logger.ts", "../node_modules/@ashdev/codex-plugin-sdk/src/server.ts", "../node_modules/@ashdev/codex-plugin-sdk/src/storage.ts", "../package.json", "../src/manifest.ts", "../src/recorder.ts", "../src/index.ts"],
|
|
4
|
-
"sourcesContent": [null, null, null, null, null, null, null, "{\n \"name\": \"@ashdev/codex-plugin-sync-echo\",\n \"version\": \"1.39.9\",\n \"description\": \"Echo sync plugin for testing and debugging the Codex plugin sync protocol\",\n \"main\": \"dist/index.js\",\n \"bin\": \"dist/index.js\",\n \"type\": \"module\",\n \"files\": [\n \"dist\",\n \"README.md\"\n ],\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"https://github.com/AshDevFr/codex.git\",\n \"directory\": \"plugins/sync-echo\"\n },\n \"scripts\": {\n \"build\": \"esbuild src/index.ts --bundle --platform=node --target=node22 --format=esm --outfile=dist/index.js --sourcemap --banner:js='#!/usr/bin/env node'\",\n \"dev\": \"npm run build -- --watch\",\n \"clean\": \"rm -rf dist\",\n \"start\": \"node dist/index.js\",\n \"lint\": \"biome check .\",\n \"lint:fix\": \"biome check --write .\",\n \"typecheck\": \"tsc --noEmit\",\n \"test\": \"vitest run --passWithNoTests\",\n \"test:watch\": \"vitest\",\n \"prepublishOnly\": \"npm run lint && npm run build\"\n },\n \"keywords\": [\n \"codex\",\n \"plugin\",\n \"sync\",\n \"echo\",\n \"testing\"\n ],\n \"author\": \"Codex\",\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \">=22.0.0\"\n },\n \"dependencies\": {\n \"@ashdev/codex-plugin-sdk\": \"^1.39.9\"\n },\n \"devDependencies\": {\n \"@biomejs/biome\": \"^2.4.4\",\n \"@types/node\": \"^22.0.0\",\n \"esbuild\": \"^0.27.3\",\n \"typescript\": \"^5.9.3\",\n \"vitest\": \"^4.0.18\"\n }\n}\n", "import type { PluginManifest } from \"@ashdev/codex-plugin-sdk\";\nimport packageJson from \"../package.json\" with { type: \"json\" };\n\n// Default config values\nexport const DEFAULT_PULL_COUNT = 3;\nexport const DEFAULT_MAX_PAYLOAD_FILES = 500;\n\nexport const manifest = {\n name: \"sync-echo\",\n displayName: \"Echo Sync Plugin\",\n version: packageJson.version,\n description:\n \"Test sync plugin that echoes back push payloads and returns deterministic pull entries. Records every request/response to files for debugging.\",\n author: \"Codex\",\n homepage: \"https://github.com/AshDevFr/codex\",\n protocolVersion: \"1.0\",\n capabilities: {\n userReadSync: true,\n // Opt in to the per-book detailed progress payload so it can be inspected.\n wantsDetailedProgress: true,\n // Opt in to enriched series data (tags/genres/metadata/custom metadata) so\n // the enrichment toggles appear and the payloads can be inspected.\n wantsFullMetadata: true,\n },\n configSchema: {\n description: \"Configuration options for the Echo sync test plugin\",\n fields: [\n {\n key: \"pullCount\",\n label: \"Pull Entry Count\",\n description: \"How many deterministic entries pullProgress should return (1-50).\",\n type: \"number\" as const,\n required: false,\n default: DEFAULT_PULL_COUNT,\n example: 5,\n },\n {\n key: \"recordPayloads\",\n label: \"Record Payloads\",\n description:\n \"Write each request and its response to JSON files under the plugin's data directory for debugging.\",\n type: \"boolean\" as const,\n required: false,\n default: true,\n },\n {\n key: \"maxPayloadFiles\",\n label: \"Max Payload Files\",\n description:\n \"Maximum number of recorded payload files to keep; oldest are pruned. Only used when payload recording is enabled.\",\n type: \"number\" as const,\n required: false,\n default: DEFAULT_MAX_PAYLOAD_FILES,\n example: 500,\n },\n ],\n },\n userConfigSchema: {\n description:\n \"Per-user settings for the Echo sync plugin. These are sent to the plugin as user config on each sync.\",\n fields: [\n {\n key: \"syncRules\",\n label: \"Sync Rules (JSON)\",\n description:\n 'Optional per-user JSON rules the plugin applies (e.g. {\"skipTags\":[\"Ecchi\"]}). Echoed back in the recorded payloads so you can confirm it reaches the plugin.',\n type: \"json\" as const,\n required: false,\n },\n ],\n },\n userDescription:\n \"A debug sync plugin: it accepts any push, returns canned reading entries on pull, and records all protocol traffic to files. No external account needed.\",\n} as const satisfies PluginManifest & {\n capabilities: { userReadSync: true };\n};\n", "/**\n * Payload Recorder - debug helper for echo plugins.\n *\n * Writes every request and its matching response to paired JSON files under the\n * plugin's host-provided file-storage directory (`InitializeParams.dataDir`), so\n * the host -> plugin protocol traffic can be inspected without trawling the\n * server logs. This is intended for the echo (test/debug) plugins only.\n *\n * Files for one call share a sortable basename and differ only by suffix:\n *\n * {yyyy-MM-dd-HH-mm-ss}-{id}-{method}-request.json\n * {yyyy-MM-dd-HH-mm-ss}-{id}-{method}-response.json\n *\n * Timestamps are UTC + 24-hour + zero-padded, so lexical sort == chronological\n * sort regardless of the server's timezone. `{id}` is a zero-padded monotonic\n * per-process counter that breaks ties within the same second and pairs the two\n * files. Each file is a JSON envelope holding the payload plus a snapshot of the\n * active config (credentials redacted).\n *\n * All filesystem I/O is best-effort: a failure is logged and swallowed so a disk\n * problem never breaks an RPC response.\n *\n * NOTE: this module is intentionally duplicated across the echo plugins to keep\n * the published SDK surface small. Keep the copies in sync.\n */\n\nimport { mkdir, readdir, rm, writeFile } from \"node:fs/promises\";\nimport { tmpdir } from \"node:os\";\nimport { join } from \"node:path\";\n\n/** Minimal logger contract (compatible with the SDK `Logger`). */\nexport interface RecorderLogger {\n info(message: string): void;\n warn(message: string): void;\n debug(message: string): void;\n}\n\nexport interface PayloadRecorderOptions {\n /** Plugin name, used for the fallback directory and the file envelope. */\n pluginName: string;\n /** Host-provided file-storage directory (`InitializeParams.dataDir`). */\n dataDir?: string;\n /** Whether recording is on (default: true). */\n enabled?: boolean;\n /** Maximum number of files to keep; oldest are pruned (default: 500). */\n maxFiles?: number;\n /** Active config snapshot to embed in each file (should be pre-redacted). */\n configSnapshot: unknown;\n /** Logger for diagnostics. */\n logger: RecorderLogger;\n /** Clock injection for tests (default: `() => new Date()`). */\n now?: () => Date;\n}\n\n/** Keys whose values are dropped from on-disk config snapshots. */\nconst SECRET_KEY_RE = /token|secret|password|api[-_]?key|credential/i;\nconst REDACTED = \"[REDACTED]\";\n\nconst DEFAULT_MAX_FILES = 500;\n\nfunction pad(value: number, width: number): string {\n return String(value).padStart(width, \"0\");\n}\n\n/** Format a date as `yyyy-MM-dd-HH-mm-ss` in UTC. */\nfunction utcStamp(date: Date): string {\n const y = date.getUTCFullYear();\n const mo = pad(date.getUTCMonth() + 1, 2);\n const d = pad(date.getUTCDate(), 2);\n const h = pad(date.getUTCHours(), 2);\n const mi = pad(date.getUTCMinutes(), 2);\n const s = pad(date.getUTCSeconds(), 2);\n return `${y}-${mo}-${d}-${h}-${mi}-${s}`;\n}\n\n/** Replace non-alphanumeric runs with `_` so a method is filename-safe. */\nfunction sanitizeMethod(method: string): string {\n return method.replace(/[^a-z0-9]+/gi, \"_\").replace(/^_+|_+$/g, \"\");\n}\n\n/**\n * Recursively copy a config object, replacing values under secret-like keys\n * with `[REDACTED]`. Arrays and primitives are returned as-is.\n */\nfunction redactObject(value: unknown): unknown {\n if (Array.isArray(value)) {\n return value.map(redactObject);\n }\n if (value && typeof value === \"object\") {\n const out: Record<string, unknown> = {};\n for (const [key, val] of Object.entries(value as Record<string, unknown>)) {\n out[key] = SECRET_KEY_RE.test(key) ? REDACTED : redactObject(val);\n }\n return out;\n }\n return value;\n}\n\n/**\n * Build a redacted config snapshot from initialize params. Credentials are\n * never included (they are passed separately, not via config); secret-like\n * config keys are additionally redacted as a defensive measure.\n */\nexport function redactConfig(input: {\n adminConfig?: Record<string, unknown>;\n userConfig?: Record<string, unknown>;\n}): { adminConfig: unknown; userConfig: unknown } {\n return {\n adminConfig: redactObject(input.adminConfig ?? {}),\n userConfig: redactObject(input.userConfig ?? {}),\n };\n}\n\ninterface Envelope {\n timestamp: string;\n plugin: string;\n method: string;\n direction: \"request\" | \"response\";\n id: number;\n config: unknown;\n payload: unknown;\n}\n\nexport class PayloadRecorder {\n private readonly pluginName: string;\n private readonly enabled: boolean;\n private readonly maxFiles: number;\n private readonly configSnapshot: unknown;\n private readonly logger: RecorderLogger;\n private readonly now: () => Date;\n private readonly dir: string;\n private readonly usingFallback: boolean;\n private seq = 0;\n private ready: Promise<boolean> | null = null;\n\n constructor(opts: PayloadRecorderOptions) {\n this.pluginName = opts.pluginName;\n this.enabled = opts.enabled ?? true;\n this.maxFiles = opts.maxFiles ?? DEFAULT_MAX_FILES;\n this.configSnapshot = opts.configSnapshot;\n this.logger = opts.logger;\n this.now = opts.now ?? (() => new Date());\n\n if (opts.dataDir) {\n this.dir = join(opts.dataDir, \"payloads\");\n this.usingFallback = false;\n } else {\n this.dir = join(tmpdir(), `codex-${opts.pluginName}`, \"payloads\");\n this.usingFallback = true;\n }\n }\n\n /** Absolute directory payloads are written to (for logging/tests). */\n get directory(): string {\n return this.dir;\n }\n\n /** Lazily create the payloads directory once; returns false if unusable. */\n private ensureDir(): Promise<boolean> {\n if (!this.ready) {\n this.ready = mkdir(this.dir, { recursive: true })\n .then(() => {\n if (this.usingFallback) {\n this.logger.warn(`No dataDir provided; recording payloads under temp dir ${this.dir}`);\n } else {\n this.logger.debug(`Recording payloads to ${this.dir}`);\n }\n return true;\n })\n .catch((err: unknown) => {\n const msg = err instanceof Error ? err.message : \"unknown error\";\n this.logger.warn(`Failed to create payload dir ${this.dir}: ${msg}`);\n return false;\n });\n }\n return this.ready;\n }\n\n /**\n * Record a request and its response under one shared, sortable basename.\n * Best-effort: never throws.\n */\n async record(method: string, request: unknown, response: unknown): Promise<void> {\n if (!this.enabled) return;\n if (!(await this.ensureDir())) return;\n\n const id = ++this.seq;\n const date = this.now();\n const base = `${utcStamp(date)}-${pad(id, 4)}-${sanitizeMethod(method)}`;\n const iso = date.toISOString();\n\n await this.writeFile(`${base}-request.json`, {\n timestamp: iso,\n plugin: this.pluginName,\n method,\n direction: \"request\",\n id,\n config: this.configSnapshot,\n payload: request,\n });\n await this.writeFile(`${base}-response.json`, {\n timestamp: iso,\n plugin: this.pluginName,\n method,\n direction: \"response\",\n id,\n config: this.configSnapshot,\n payload: response,\n });\n\n await this.prune();\n }\n\n private async writeFile(name: string, envelope: Envelope): Promise<void> {\n try {\n await writeFile(join(this.dir, name), JSON.stringify(envelope, null, 2), \"utf8\");\n } catch (err) {\n const msg = err instanceof Error ? err.message : \"unknown error\";\n this.logger.warn(`Failed to write payload file ${name}: ${msg}`);\n }\n }\n\n /** Keep at most `maxFiles` files, deleting the oldest (lexical == chrono). */\n private async prune(): Promise<void> {\n if (this.maxFiles <= 0) return;\n try {\n const files = (await readdir(this.dir)).filter((f) => f.endsWith(\".json\")).sort();\n const excess = files.length - this.maxFiles;\n if (excess <= 0) return;\n for (const file of files.slice(0, excess)) {\n await rm(join(this.dir, file), { force: true });\n }\n } catch (err) {\n const msg = err instanceof Error ? err.message : \"unknown error\";\n this.logger.warn(`Failed to prune payload dir ${this.dir}: ${msg}`);\n }\n }\n}\n", "/**\n * Echo Sync Plugin for Codex\n *\n * A minimal test/debug sync plugin. It does not talk to any external service:\n * it accepts any push (echoing every entry back as created/updated), returns\n * deterministic, fully-populated entries on pull, and reports canned status.\n *\n * Its main purpose is debugging the host -> plugin sync protocol: it declares\n * `wantsDetailedProgress` so it receives the per-book detailed progress payload,\n * and records every request and its response to JSON files under the plugin's\n * data directory (see `recorder.ts`).\n */\n\nimport {\n createLogger,\n createSyncPlugin,\n type ExternalUserInfo,\n type InitializeParams,\n type SyncEntry,\n type SyncEntryResult,\n type SyncProvider,\n type SyncPullRequest,\n type SyncPullResponse,\n type SyncPushRequest,\n type SyncPushResponse,\n type SyncStatusResponse,\n} from \"@ashdev/codex-plugin-sdk\";\nimport { DEFAULT_MAX_PAYLOAD_FILES, DEFAULT_PULL_COUNT, manifest } from \"./manifest.js\";\nimport { PayloadRecorder, redactConfig } from \"./recorder.js\";\n\nconst logger = createLogger({ name: \"sync-echo\", level: \"debug\" });\n\n// Plugin configuration (set during initialization)\nconst config = {\n pullCount: DEFAULT_PULL_COUNT,\n};\n\n// Payload recorder (set during initialization)\nlet recorder: PayloadRecorder | null = null;\n\n/** Record a request/response pair (best-effort) and return the response. */\nasync function rec<T>(method: string, params: unknown, response: T): Promise<T> {\n await recorder?.record(method, params, response);\n return response;\n}\n\n/** Set the payload recorder (exported for testing) */\nexport function setRecorder(r: PayloadRecorder | null): void {\n recorder = r;\n}\n\n/** Set the pull entry count (exported for testing) */\nexport function setPullCount(count: number): void {\n config.pullCount = count;\n}\n\nconst STATUSES: SyncEntry[\"status\"][] = [\n \"reading\",\n \"completed\",\n \"on_hold\",\n \"plan_to_read\",\n \"dropped\",\n];\n\n/**\n * Build a deterministic, fully-populated sync entry for the given index. Every\n * optional field is set so the host's pull-ingest path is exercised end to end.\n */\nfunction makeEntry(i: number): SyncEntry {\n const day = String((i % 28) + 1).padStart(2, \"0\");\n return {\n externalId: String(1000 + i),\n status: STATUSES[i % STATUSES.length],\n progress: {\n chapters: i + 1,\n volumes: i + 1,\n pages: (i + 1) * 20,\n totalChapters: 100,\n totalVolumes: 12,\n maxVolume: i + 1,\n maxChapter: i + 1.5,\n readBooks: [\n {\n volume: i + 1,\n chapter: i + 1.5,\n completed: i % 2 === 0,\n currentPage: (i + 1) * 10,\n progressPercentage: 0.5,\n },\n ],\n },\n score: 70 + (i % 30),\n startedAt: `2026-01-${day}T00:00:00.000Z`,\n completedAt: `2026-02-${day}T00:00:00.000Z`,\n notes: `Echo note for entry ${i}`,\n latestUpdatedAt: `2026-03-${day}T00:00:00.000Z`,\n title: `Echo Series ${i + 1}`,\n };\n}\n\n/** Exported for testing */\nexport const provider: SyncProvider = {\n async getUserInfo(): Promise<ExternalUserInfo> {\n return rec<ExternalUserInfo>(\"sync/getUserInfo\", null, {\n externalId: \"echo-user-1\",\n username: \"echo_user\",\n avatarUrl: \"https://picsum.photos/100/100\",\n profileUrl: \"https://echo.example.com/user/echo_user\",\n });\n },\n\n async pushProgress(params: SyncPushRequest): Promise<SyncPushResponse> {\n logger.info(`Push received: ${params.entries.length} entries`);\n\n // Echo every entry back as a success, alternating created/updated so both\n // result statuses are exercised. Nothing is ever rejected.\n const success: SyncEntryResult[] = params.entries.map((entry, i) => ({\n externalId: entry.externalId,\n status: i % 2 === 0 ? \"created\" : \"updated\",\n }));\n\n return rec<SyncPushResponse>(\"sync/pushProgress\", params, {\n success,\n failed: [],\n });\n },\n\n async pullProgress(params: SyncPullRequest): Promise<SyncPullResponse> {\n const requested = params.limit ?? config.pullCount;\n const count = Math.min(Math.max(0, requested), config.pullCount);\n const entries = Array.from({ length: count }, (_, i) => makeEntry(i));\n\n logger.info(`Pull returning ${entries.length} deterministic entries`);\n\n return rec<SyncPullResponse>(\"sync/pullProgress\", params, {\n entries,\n hasMore: false,\n });\n },\n\n async status(): Promise<SyncStatusResponse> {\n return rec<SyncStatusResponse>(\"sync/status\", null, {\n lastSyncAt: \"2026-03-01T00:00:00.000Z\",\n externalCount: config.pullCount,\n pendingPush: 0,\n pendingPull: 0,\n conflicts: 0,\n });\n },\n};\n\n// =============================================================================\n// Plugin Initialization\n// =============================================================================\n\ncreateSyncPlugin({\n manifest,\n provider,\n logLevel: \"debug\",\n onInitialize(params: InitializeParams) {\n // Honor the host-supplied log level (Codex `plugins.log_level` config).\n if (params.logLevel) logger.setLevel(params.logLevel);\n const pullCount = params.adminConfig?.pullCount;\n if (typeof pullCount === \"number\") {\n config.pullCount = Math.min(Math.max(1, Math.floor(pullCount)), 50);\n }\n\n // Set up payload recording (on by default for this debug plugin)\n const recordPayloads = params.adminConfig?.recordPayloads !== false;\n const maxPayloadFiles =\n typeof params.adminConfig?.maxPayloadFiles === \"number\"\n ? params.adminConfig.maxPayloadFiles\n : DEFAULT_MAX_PAYLOAD_FILES;\n recorder = new PayloadRecorder({\n pluginName: manifest.name,\n dataDir: params.dataDir,\n enabled: recordPayloads,\n maxFiles: maxPayloadFiles,\n configSnapshot: redactConfig({\n adminConfig: params.adminConfig,\n userConfig: params.userConfig,\n }),\n logger,\n });\n\n logger.info(\n `Echo sync plugin initialized (pullCount: ${config.pullCount}, recordPayloads: ${recordPayloads})`,\n );\n },\n});\n\nlogger.info(\"Echo sync plugin started\");\n"],
|
|
4
|
+
"sourcesContent": [null, null, null, null, null, null, null, "{\n \"name\": \"@ashdev/codex-plugin-sync-echo\",\n \"version\": \"1.39.10\",\n \"description\": \"Echo sync plugin for testing and debugging the Codex plugin sync protocol\",\n \"main\": \"dist/index.js\",\n \"bin\": \"dist/index.js\",\n \"type\": \"module\",\n \"files\": [\n \"dist\",\n \"README.md\"\n ],\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"https://github.com/AshDevFr/codex.git\",\n \"directory\": \"plugins/sync-echo\"\n },\n \"scripts\": {\n \"build\": \"esbuild src/index.ts --bundle --platform=node --target=node22 --format=esm --outfile=dist/index.js --sourcemap --banner:js='#!/usr/bin/env node'\",\n \"dev\": \"npm run build -- --watch\",\n \"clean\": \"rm -rf dist\",\n \"start\": \"node dist/index.js\",\n \"lint\": \"biome check .\",\n \"lint:fix\": \"biome check --write .\",\n \"typecheck\": \"tsc --noEmit\",\n \"test\": \"vitest run --passWithNoTests\",\n \"test:watch\": \"vitest\",\n \"prepublishOnly\": \"npm run lint && npm run build\"\n },\n \"keywords\": [\n \"codex\",\n \"plugin\",\n \"sync\",\n \"echo\",\n \"testing\"\n ],\n \"author\": \"Codex\",\n \"license\": \"MIT\",\n \"engines\": {\n \"node\": \">=22.0.0\"\n },\n \"dependencies\": {\n \"@ashdev/codex-plugin-sdk\": \"^1.39.10\"\n },\n \"devDependencies\": {\n \"@biomejs/biome\": \"^2.4.4\",\n \"@types/node\": \"^22.0.0\",\n \"esbuild\": \"^0.27.3\",\n \"typescript\": \"^5.9.3\",\n \"vitest\": \"^4.0.18\"\n }\n}\n", "import type { PluginManifest } from \"@ashdev/codex-plugin-sdk\";\nimport packageJson from \"../package.json\" with { type: \"json\" };\n\n// Default config values\nexport const DEFAULT_PULL_COUNT = 3;\nexport const DEFAULT_MAX_PAYLOAD_FILES = 500;\n\nexport const manifest = {\n name: \"sync-echo\",\n displayName: \"Echo Sync Plugin\",\n version: packageJson.version,\n description:\n \"Test sync plugin that echoes back push payloads and returns deterministic pull entries. Records every request/response to files for debugging.\",\n author: \"Codex\",\n homepage: \"https://github.com/AshDevFr/codex\",\n protocolVersion: \"1.0\",\n capabilities: {\n userReadSync: true,\n // Opt in to the per-book detailed progress payload so it can be inspected.\n wantsDetailedProgress: true,\n // Opt in to enriched series data (tags/genres/metadata/custom metadata) so\n // the enrichment toggles appear and the payloads can be inspected.\n wantsFullMetadata: true,\n },\n configSchema: {\n description: \"Configuration options for the Echo sync test plugin\",\n fields: [\n {\n key: \"pullCount\",\n label: \"Pull Entry Count\",\n description: \"How many deterministic entries pullProgress should return (1-50).\",\n type: \"number\" as const,\n required: false,\n default: DEFAULT_PULL_COUNT,\n example: 5,\n },\n {\n key: \"recordPayloads\",\n label: \"Record Payloads\",\n description:\n \"Write each request and its response to JSON files under the plugin's data directory for debugging.\",\n type: \"boolean\" as const,\n required: false,\n default: true,\n },\n {\n key: \"maxPayloadFiles\",\n label: \"Max Payload Files\",\n description:\n \"Maximum number of recorded payload files to keep; oldest are pruned. Only used when payload recording is enabled.\",\n type: \"number\" as const,\n required: false,\n default: DEFAULT_MAX_PAYLOAD_FILES,\n example: 500,\n },\n ],\n },\n userConfigSchema: {\n description:\n \"Per-user settings for the Echo sync plugin. These are sent to the plugin as user config on each sync.\",\n fields: [\n {\n key: \"syncRules\",\n label: \"Sync Rules (JSON)\",\n description:\n 'Optional per-user JSON rules the plugin applies (e.g. {\"skipTags\":[\"Ecchi\"]}). Echoed back in the recorded payloads so you can confirm it reaches the plugin.',\n type: \"json\" as const,\n required: false,\n },\n ],\n },\n userDescription:\n \"A debug sync plugin: it accepts any push, returns canned reading entries on pull, and records all protocol traffic to files. No external account needed.\",\n} as const satisfies PluginManifest & {\n capabilities: { userReadSync: true };\n};\n", "/**\n * Payload Recorder - debug helper for echo plugins.\n *\n * Writes every request and its matching response to paired JSON files under the\n * plugin's host-provided file-storage directory (`InitializeParams.dataDir`), so\n * the host -> plugin protocol traffic can be inspected without trawling the\n * server logs. This is intended for the echo (test/debug) plugins only.\n *\n * Files for one call share a sortable basename and differ only by suffix:\n *\n * {yyyy-MM-dd-HH-mm-ss}-{id}-{method}-request.json\n * {yyyy-MM-dd-HH-mm-ss}-{id}-{method}-response.json\n *\n * Timestamps are UTC + 24-hour + zero-padded, so lexical sort == chronological\n * sort regardless of the server's timezone. `{id}` is a zero-padded monotonic\n * per-process counter that breaks ties within the same second and pairs the two\n * files. Each file is a JSON envelope holding the payload plus a snapshot of the\n * active config (credentials redacted).\n *\n * All filesystem I/O is best-effort: a failure is logged and swallowed so a disk\n * problem never breaks an RPC response.\n *\n * NOTE: this module is intentionally duplicated across the echo plugins to keep\n * the published SDK surface small. Keep the copies in sync.\n */\n\nimport { mkdir, readdir, rm, writeFile } from \"node:fs/promises\";\nimport { tmpdir } from \"node:os\";\nimport { join } from \"node:path\";\n\n/** Minimal logger contract (compatible with the SDK `Logger`). */\nexport interface RecorderLogger {\n info(message: string): void;\n warn(message: string): void;\n debug(message: string): void;\n}\n\nexport interface PayloadRecorderOptions {\n /** Plugin name, used for the fallback directory and the file envelope. */\n pluginName: string;\n /** Host-provided file-storage directory (`InitializeParams.dataDir`). */\n dataDir?: string;\n /** Whether recording is on (default: true). */\n enabled?: boolean;\n /** Maximum number of files to keep; oldest are pruned (default: 500). */\n maxFiles?: number;\n /** Active config snapshot to embed in each file (should be pre-redacted). */\n configSnapshot: unknown;\n /** Logger for diagnostics. */\n logger: RecorderLogger;\n /** Clock injection for tests (default: `() => new Date()`). */\n now?: () => Date;\n}\n\n/** Keys whose values are dropped from on-disk config snapshots. */\nconst SECRET_KEY_RE = /token|secret|password|api[-_]?key|credential/i;\nconst REDACTED = \"[REDACTED]\";\n\nconst DEFAULT_MAX_FILES = 500;\n\nfunction pad(value: number, width: number): string {\n return String(value).padStart(width, \"0\");\n}\n\n/** Format a date as `yyyy-MM-dd-HH-mm-ss` in UTC. */\nfunction utcStamp(date: Date): string {\n const y = date.getUTCFullYear();\n const mo = pad(date.getUTCMonth() + 1, 2);\n const d = pad(date.getUTCDate(), 2);\n const h = pad(date.getUTCHours(), 2);\n const mi = pad(date.getUTCMinutes(), 2);\n const s = pad(date.getUTCSeconds(), 2);\n return `${y}-${mo}-${d}-${h}-${mi}-${s}`;\n}\n\n/** Replace non-alphanumeric runs with `_` so a method is filename-safe. */\nfunction sanitizeMethod(method: string): string {\n return method.replace(/[^a-z0-9]+/gi, \"_\").replace(/^_+|_+$/g, \"\");\n}\n\n/**\n * Recursively copy a config object, replacing values under secret-like keys\n * with `[REDACTED]`. Arrays and primitives are returned as-is.\n */\nfunction redactObject(value: unknown): unknown {\n if (Array.isArray(value)) {\n return value.map(redactObject);\n }\n if (value && typeof value === \"object\") {\n const out: Record<string, unknown> = {};\n for (const [key, val] of Object.entries(value as Record<string, unknown>)) {\n out[key] = SECRET_KEY_RE.test(key) ? REDACTED : redactObject(val);\n }\n return out;\n }\n return value;\n}\n\n/**\n * Build a redacted config snapshot from initialize params. Credentials are\n * never included (they are passed separately, not via config); secret-like\n * config keys are additionally redacted as a defensive measure.\n */\nexport function redactConfig(input: {\n adminConfig?: Record<string, unknown>;\n userConfig?: Record<string, unknown>;\n}): { adminConfig: unknown; userConfig: unknown } {\n return {\n adminConfig: redactObject(input.adminConfig ?? {}),\n userConfig: redactObject(input.userConfig ?? {}),\n };\n}\n\ninterface Envelope {\n timestamp: string;\n plugin: string;\n method: string;\n direction: \"request\" | \"response\";\n id: number;\n config: unknown;\n payload: unknown;\n}\n\nexport class PayloadRecorder {\n private readonly pluginName: string;\n private readonly enabled: boolean;\n private readonly maxFiles: number;\n private readonly configSnapshot: unknown;\n private readonly logger: RecorderLogger;\n private readonly now: () => Date;\n private readonly dir: string;\n private readonly usingFallback: boolean;\n private seq = 0;\n private ready: Promise<boolean> | null = null;\n\n constructor(opts: PayloadRecorderOptions) {\n this.pluginName = opts.pluginName;\n this.enabled = opts.enabled ?? true;\n this.maxFiles = opts.maxFiles ?? DEFAULT_MAX_FILES;\n this.configSnapshot = opts.configSnapshot;\n this.logger = opts.logger;\n this.now = opts.now ?? (() => new Date());\n\n if (opts.dataDir) {\n this.dir = join(opts.dataDir, \"payloads\");\n this.usingFallback = false;\n } else {\n this.dir = join(tmpdir(), `codex-${opts.pluginName}`, \"payloads\");\n this.usingFallback = true;\n }\n }\n\n /** Absolute directory payloads are written to (for logging/tests). */\n get directory(): string {\n return this.dir;\n }\n\n /** Lazily create the payloads directory once; returns false if unusable. */\n private ensureDir(): Promise<boolean> {\n if (!this.ready) {\n this.ready = mkdir(this.dir, { recursive: true })\n .then(() => {\n if (this.usingFallback) {\n this.logger.warn(`No dataDir provided; recording payloads under temp dir ${this.dir}`);\n } else {\n this.logger.debug(`Recording payloads to ${this.dir}`);\n }\n return true;\n })\n .catch((err: unknown) => {\n const msg = err instanceof Error ? err.message : \"unknown error\";\n this.logger.warn(`Failed to create payload dir ${this.dir}: ${msg}`);\n return false;\n });\n }\n return this.ready;\n }\n\n /**\n * Record a request and its response under one shared, sortable basename.\n * Best-effort: never throws.\n */\n async record(method: string, request: unknown, response: unknown): Promise<void> {\n if (!this.enabled) return;\n if (!(await this.ensureDir())) return;\n\n const id = ++this.seq;\n const date = this.now();\n const base = `${utcStamp(date)}-${pad(id, 4)}-${sanitizeMethod(method)}`;\n const iso = date.toISOString();\n\n await this.writeFile(`${base}-request.json`, {\n timestamp: iso,\n plugin: this.pluginName,\n method,\n direction: \"request\",\n id,\n config: this.configSnapshot,\n payload: request,\n });\n await this.writeFile(`${base}-response.json`, {\n timestamp: iso,\n plugin: this.pluginName,\n method,\n direction: \"response\",\n id,\n config: this.configSnapshot,\n payload: response,\n });\n\n await this.prune();\n }\n\n private async writeFile(name: string, envelope: Envelope): Promise<void> {\n try {\n await writeFile(join(this.dir, name), JSON.stringify(envelope, null, 2), \"utf8\");\n } catch (err) {\n const msg = err instanceof Error ? err.message : \"unknown error\";\n this.logger.warn(`Failed to write payload file ${name}: ${msg}`);\n }\n }\n\n /** Keep at most `maxFiles` files, deleting the oldest (lexical == chrono). */\n private async prune(): Promise<void> {\n if (this.maxFiles <= 0) return;\n try {\n const files = (await readdir(this.dir)).filter((f) => f.endsWith(\".json\")).sort();\n const excess = files.length - this.maxFiles;\n if (excess <= 0) return;\n for (const file of files.slice(0, excess)) {\n await rm(join(this.dir, file), { force: true });\n }\n } catch (err) {\n const msg = err instanceof Error ? err.message : \"unknown error\";\n this.logger.warn(`Failed to prune payload dir ${this.dir}: ${msg}`);\n }\n }\n}\n", "/**\n * Echo Sync Plugin for Codex\n *\n * A minimal test/debug sync plugin. It does not talk to any external service:\n * it accepts any push (echoing every entry back as created/updated), returns\n * deterministic, fully-populated entries on pull, and reports canned status.\n *\n * Its main purpose is debugging the host -> plugin sync protocol: it declares\n * `wantsDetailedProgress` so it receives the per-book detailed progress payload,\n * and records every request and its response to JSON files under the plugin's\n * data directory (see `recorder.ts`).\n */\n\nimport {\n createLogger,\n createSyncPlugin,\n type ExternalUserInfo,\n type InitializeParams,\n type SyncEntry,\n type SyncEntryResult,\n type SyncProvider,\n type SyncPullRequest,\n type SyncPullResponse,\n type SyncPushRequest,\n type SyncPushResponse,\n type SyncStatusResponse,\n} from \"@ashdev/codex-plugin-sdk\";\nimport { DEFAULT_MAX_PAYLOAD_FILES, DEFAULT_PULL_COUNT, manifest } from \"./manifest.js\";\nimport { PayloadRecorder, redactConfig } from \"./recorder.js\";\n\nconst logger = createLogger({ name: \"sync-echo\", level: \"debug\" });\n\n// Plugin configuration (set during initialization)\nconst config = {\n pullCount: DEFAULT_PULL_COUNT,\n};\n\n// Payload recorder (set during initialization)\nlet recorder: PayloadRecorder | null = null;\n\n/** Record a request/response pair (best-effort) and return the response. */\nasync function rec<T>(method: string, params: unknown, response: T): Promise<T> {\n await recorder?.record(method, params, response);\n return response;\n}\n\n/** Set the payload recorder (exported for testing) */\nexport function setRecorder(r: PayloadRecorder | null): void {\n recorder = r;\n}\n\n/** Set the pull entry count (exported for testing) */\nexport function setPullCount(count: number): void {\n config.pullCount = count;\n}\n\nconst STATUSES: SyncEntry[\"status\"][] = [\n \"reading\",\n \"completed\",\n \"on_hold\",\n \"plan_to_read\",\n \"dropped\",\n];\n\n/**\n * Build a deterministic, fully-populated sync entry for the given index. Every\n * optional field is set so the host's pull-ingest path is exercised end to end.\n */\nfunction makeEntry(i: number): SyncEntry {\n const day = String((i % 28) + 1).padStart(2, \"0\");\n return {\n externalId: String(1000 + i),\n status: STATUSES[i % STATUSES.length],\n progress: {\n chapters: i + 1,\n volumes: i + 1,\n pages: (i + 1) * 20,\n totalChapters: 100,\n totalVolumes: 12,\n maxVolume: i + 1,\n maxChapter: i + 1.5,\n readBooks: [\n {\n volume: i + 1,\n chapter: i + 1.5,\n completed: i % 2 === 0,\n currentPage: (i + 1) * 10,\n progressPercentage: 0.5,\n },\n ],\n },\n score: 70 + (i % 30),\n startedAt: `2026-01-${day}T00:00:00.000Z`,\n completedAt: `2026-02-${day}T00:00:00.000Z`,\n notes: `Echo note for entry ${i}`,\n latestUpdatedAt: `2026-03-${day}T00:00:00.000Z`,\n title: `Echo Series ${i + 1}`,\n };\n}\n\n/** Exported for testing */\nexport const provider: SyncProvider = {\n async getUserInfo(): Promise<ExternalUserInfo> {\n return rec<ExternalUserInfo>(\"sync/getUserInfo\", null, {\n externalId: \"echo-user-1\",\n username: \"echo_user\",\n avatarUrl: \"https://picsum.photos/100/100\",\n profileUrl: \"https://echo.example.com/user/echo_user\",\n });\n },\n\n async pushProgress(params: SyncPushRequest): Promise<SyncPushResponse> {\n logger.info(`Push received: ${params.entries.length} entries`);\n\n // Echo every entry back as a success, alternating created/updated so both\n // result statuses are exercised. Nothing is ever rejected.\n const success: SyncEntryResult[] = params.entries.map((entry, i) => ({\n externalId: entry.externalId,\n status: i % 2 === 0 ? \"created\" : \"updated\",\n }));\n\n return rec<SyncPushResponse>(\"sync/pushProgress\", params, {\n success,\n failed: [],\n });\n },\n\n async pullProgress(params: SyncPullRequest): Promise<SyncPullResponse> {\n const requested = params.limit ?? config.pullCount;\n const count = Math.min(Math.max(0, requested), config.pullCount);\n const entries = Array.from({ length: count }, (_, i) => makeEntry(i));\n\n logger.info(`Pull returning ${entries.length} deterministic entries`);\n\n return rec<SyncPullResponse>(\"sync/pullProgress\", params, {\n entries,\n hasMore: false,\n });\n },\n\n async status(): Promise<SyncStatusResponse> {\n return rec<SyncStatusResponse>(\"sync/status\", null, {\n lastSyncAt: \"2026-03-01T00:00:00.000Z\",\n externalCount: config.pullCount,\n pendingPush: 0,\n pendingPull: 0,\n conflicts: 0,\n });\n },\n};\n\n// =============================================================================\n// Plugin Initialization\n// =============================================================================\n\ncreateSyncPlugin({\n manifest,\n provider,\n logLevel: \"debug\",\n onInitialize(params: InitializeParams) {\n // Honor the host-supplied log level (Codex `plugins.log_level` config).\n if (params.logLevel) logger.setLevel(params.logLevel);\n const pullCount = params.adminConfig?.pullCount;\n if (typeof pullCount === \"number\") {\n config.pullCount = Math.min(Math.max(1, Math.floor(pullCount)), 50);\n }\n\n // Set up payload recording (on by default for this debug plugin)\n const recordPayloads = params.adminConfig?.recordPayloads !== false;\n const maxPayloadFiles =\n typeof params.adminConfig?.maxPayloadFiles === \"number\"\n ? params.adminConfig.maxPayloadFiles\n : DEFAULT_MAX_PAYLOAD_FILES;\n recorder = new PayloadRecorder({\n pluginName: manifest.name,\n dataDir: params.dataDir,\n enabled: recordPayloads,\n maxFiles: maxPayloadFiles,\n configSnapshot: redactConfig({\n adminConfig: params.adminConfig,\n userConfig: params.userConfig,\n }),\n logger,\n });\n\n logger.info(\n `Echo sync plugin initialized (pullCount: ${config.pullCount}, recordPayloads: ${recordPayloads})`,\n );\n },\n});\n\nlogger.info(\"Echo sync plugin started\");\n"],
|
|
5
5
|
"mappings": "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",
|
|
6
6
|
"names": ["manifest", "logger", "response", "manifest", "provider", "success"]
|
|
7
7
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ashdev/codex-plugin-sync-echo",
|
|
3
|
-
"version": "1.39.
|
|
3
|
+
"version": "1.39.10",
|
|
4
4
|
"description": "Echo sync plugin for testing and debugging the Codex plugin sync protocol",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"bin": "dist/index.js",
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"node": ">=22.0.0"
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
|
-
"@ashdev/codex-plugin-sdk": "^1.39.
|
|
42
|
+
"@ashdev/codex-plugin-sdk": "^1.39.10"
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
45
45
|
"@biomejs/biome": "^2.4.4",
|