From 0634f2048c7c9a474aab1d8104b964b3bf70a064 Mon Sep 17 00:00:00 2001 From: tanaka takashi Date: Sat, 4 Jul 2026 17:21:32 +0900 Subject: feat(P1-002): migrate offline JSONL import/export to dedicated CLI - Replace the MCP import_messages tool with standalone CLI commands: iny-convmem-mcp --data-dir --import iny-convmem-mcp --data-dir --export - Add src/cli/{import,export,cli.h} and a CTest process test (tiny-convmem-mcp.cli) covering round-trip, manifest generation, overwrite/reject policies, and include_deleted export. - Fix Debug heap corruption in iny_store_import() by deep-copying imported messages instead of taking ownership of caller-allocated records, which were later freed by the caller. - Remove the now-redundant src/mcp/tools/import_messages.c and keep the tool registry at 7 MCP tools. - Update docs/development-plan.md (P1-002 complete) and docs/implementation-status.md with CLI test coverage. --- src/app/main.c | 88 +++++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 81 insertions(+), 7 deletions(-) (limited to 'src/app/main.c') diff --git a/src/app/main.c b/src/app/main.c index f73b314..415e999 100644 --- a/src/app/main.c +++ b/src/app/main.c @@ -2,6 +2,7 @@ #include #include +#include "cli/cli.h" #include "mcp/server.h" #include "storage/store.h" #include "sys/system.h" @@ -11,7 +12,75 @@ static void usage(FILE *stream) { - fprintf(stream, "Usage: tiny-convmem-mcp --data-dir \n"); + fprintf(stream, + "Usage: tiny-convmem-mcp --data-dir [command]\n" + "Commands:\n" + " (none) Run the MCP server (default)\n" + " --import [--policy overwrite|reject]\n" + " Import a JSONL export into the store\n" + " --export [--session ] [--include-deleted]\n" + " Export the store to a JSONL file (- for stdout)\n"); +} + +static const char * +find_argument(const tiny_sys_arguments_t *arguments, const char *name) +{ + size_t index; + for (index = 1; index + 1 < arguments->count; ++index) + { + if (strcmp(arguments->values[index], name) == 0) + { + return arguments->values[index + 1]; + } + } + return NULL; +} + +static int +flag_present(const tiny_sys_arguments_t *arguments, const char *name) +{ + size_t index; + for (index = 1; index < arguments->count; ++index) + { + if (strcmp(arguments->values[index], name) == 0) + { + return 1; + } + } + return 0; +} + +static int +run_server(tiny_store_t *store) +{ + int result = tiny_convmem_server_run(stdin, stdout, store); + if (result != 0) + { + fprintf(stderr, "tiny-convmem-mcp stopped with error code %d\n", result); + } + return result; +} + +static int +run_cli_command(tiny_store_t *store, const tiny_sys_arguments_t *arguments) +{ + tiny_cli_options_t options = { 0 }; + options.data_dir = arguments->values[2]; + options.import_path = find_argument(arguments, "--import"); + options.export_path = find_argument(arguments, "--export"); + options.session_id = find_argument(arguments, "--session"); + options.policy_name = find_argument(arguments, "--policy"); + options.include_deleted = flag_present(arguments, "--include-deleted"); + + if (options.import_path) + { + return tiny_cli_import(store, &options); + } + if (options.export_path) + { + return tiny_cli_export(store, &options); + } + return 2; } static int @@ -21,17 +90,26 @@ run(const tiny_sys_arguments_t *arguments) tiny_store_t *store = NULL; tiny_store_status_t status; int result; + int server_mode = 0; if (arguments->count == 2 && strcmp(arguments->values[1], "--help") == 0) { usage(stdout); return 0; } - if (arguments->count != 3 || strcmp(arguments->values[1], "--data-dir") != 0 + if (arguments->count < 3 || strcmp(arguments->values[1], "--data-dir") != 0 || arguments->values[2][0] == '\0') { usage(stderr); return 2; } + server_mode = (arguments->count == 3) + || (arguments->count == 5 && strcmp(arguments->values[3], "--import") != 0 + && strcmp(arguments->values[3], "--export") != 0); + if (!server_mode && arguments->count < 5) + { + usage(stderr); + return 2; + } absolute = tiny_sys_path_absolute(arguments->values[2]); if (absolute == NULL) { @@ -45,12 +123,8 @@ run(const tiny_sys_arguments_t *arguments) fprintf(stderr, "unable to open conversation store: %s\n", tiny_store_status_name(status)); return status == TINY_STORE_BUSY ? 3 : 1; } - result = tiny_convmem_server_run(stdin, stdout, store); + result = server_mode ? run_server(store) : run_cli_command(store, arguments); tiny_store_close(store); - if (result != 0) - { - fprintf(stderr, "tiny-convmem-mcp stopped with error code %d\n", result); - } return result; } -- cgit v1.2.3