kbot meets cpp 1/3
This commit is contained in:
parent
d9ebde911f
commit
2f7c18adb5
@ -1,8 +1,8 @@
|
||||
cmake_minimum_required(VERSION 3.20)
|
||||
|
||||
project(polymech-cli
|
||||
project(kbot-cli
|
||||
VERSION 0.1.0
|
||||
DESCRIPTION "Polymech C++ CLI"
|
||||
DESCRIPTION "KBot C++ CLI"
|
||||
LANGUAGES CXX C
|
||||
)
|
||||
|
||||
@ -112,6 +112,9 @@ add_executable(${PROJECT_NAME}
|
||||
src/sys_metrics.cpp
|
||||
)
|
||||
|
||||
# Output file name is kbot.exe / kbot (not kbot-cli)
|
||||
set_target_properties(${PROJECT_NAME} PROPERTIES OUTPUT_NAME "kbot")
|
||||
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE CLI11::CLI11 tomlplusplus::tomlplusplus logger html postgres http json polymech ipc geo gadm_reader grid search enrichers kbot)
|
||||
|
||||
target_include_directories(${PROJECT_NAME} PRIVATE
|
||||
|
||||
@ -28,77 +28,6 @@ polymech-cli --help
|
||||
polymech-cli --version
|
||||
```
|
||||
|
||||
## Worker Mode & Gridsearch
|
||||
|
||||
The `worker` subcommand is designed to be spawned by the Node.js frontend orchestrator (`GridSearchUdsManager`) for background gridsearch execution. It accepts length-prefixed JSON frames over a Unix Domain Socket (UDS) or a local TCP port on Windows.
|
||||
|
||||
```bash
|
||||
polymech-cli worker --uds <path_or_port> --daemon --user-uid <id> --config <path>
|
||||
```
|
||||
|
||||
### IPC Resiliency and Logging
|
||||
The C++ worker pipeline incorporates extensive feedback and retry instrumentation:
|
||||
|
||||
1. **Watchdog Heartbeats (`ping` / `pong`)**
|
||||
- The Node orchestrator sweeps the active worker pool every 15 seconds. It explicitly logs when a ping is sent and when a `pong` (or other active events like `log`, `job_progress`, or `ack`) are received.
|
||||
- If a C++ worker stops responding to IPC events for 60 seconds (hanging thread or deadlock), it is automatically killed (`SIGKILL`) and evicted from the pool.
|
||||
|
||||
2. **Socket Traceability**
|
||||
- The UDS socket actively traps unexpected closures and TCP faults (like `ECONNRESET`). If the pipe breaks mid-job, explicit socket `error` event handlers in the Node orchestrator will instantly fail the job and log the stack trace, preventing indefinite client-side UI hangs, especially during heavy re-runs.
|
||||
|
||||
3. **Persistent Crash Logging (`logs/uds.json`)**
|
||||
- The C++ worker initializes a multi-sink logger (`logger::init_uds`). It pumps standard logs to `stderr` while simultaneously persisting an append-only file trace to `server/logs/uds.json`.
|
||||
- The file sink guarantees synchronization to disk aggressively (every 1 second, and immediately on `info` severity). If the worker process vanishes or crashes, `uds.json` acts as the black-box flight recorder for post-mortem debugging.
|
||||
|
||||
4. **Job Specification Transparency**
|
||||
- Gridsearch payloads (including `retry` and `expand` endpoints) aggressively log their input shape (`guided` bounds flag, `enrichers` subset) within the Node console before passing work to the C++ orchestrator. This allows for clear traceability from UI action -> Node submission -> C++ execution.
|
||||
|
||||
5. **Thread Safety & Frame Synchronization (Mutexes)**
|
||||
- The UDS socket handles dual-direction asynchronous streams. The background execution graph (powered by Taskflow) emits high-frequency events (`location`, `waypoint-start`) via `GridsearchCallbacks`. Concurrently, the orchestrator Node.js process sends periodic commands (`ping`, `cancel`) that the C++ socket loop must instantly acknowledge.
|
||||
- To prevent overlapping payload frames (which corrupt the critical 4-byte `len` header), a global `g_uds_socket_mutex` is strictly enforced. It guarantees that direct UI acknowledgments (`pong`, `cancel_ack`) and background logging (`uds_sink` / Taskflow events) never interleave their `asio::write` bursts onto the pipe.
|
||||
|
||||
### IPC Framing & Payload Protocol
|
||||
Communication runs strictly via length-prefixed JSON frames. This safeguards against TCP fragmentation during heavy event streams.
|
||||
|
||||
**Binary Frame Format:**
|
||||
`[4-byte Unsigned Little-Endian Integer (Payload Length)] [UTF-8 JSON Object]`
|
||||
|
||||
#### Control Commands (Node → C++)
|
||||
If the JSON object contains an `"action"` field, it is handled synchronously on the socket thread:
|
||||
- **Health Check:** `{"action": "ping"}`
|
||||
→ *Replies:* `{"type": "pong", "data": {"memoryMb": 120, "cpuTimeMs": 4500}}`
|
||||
- **Cancellation:** `{"action": "cancel", "jobId": "job_123"}`
|
||||
→ Worker sets the atomic cancellation token to safely halt the target `taskflow`, instantly replying `{"type": "cancel_ack", "data": "job_123"}`
|
||||
- **Daemon Teardown:** `{"action": "stop"}`
|
||||
→ Flushes all streams and exits cleanly.
|
||||
|
||||
#### Gridsearch Payload (Node → C++)
|
||||
If no `"action"` field exists, the message is treated as a gridsearch spec and pushed into a lock-free `ConcurrentQueue` for the background execution graph:
|
||||
```json
|
||||
{
|
||||
"jobId": "run_9a8bc7",
|
||||
"configPath": "config/postgres.toml",
|
||||
"cacheDir": "../packages/gadm/cache",
|
||||
"enrich": true,
|
||||
"guided": {
|
||||
"areas": [{ "gid": "ESP.6_1", "level": 1 }],
|
||||
"settings": { "gridMode": "hex", "cellSize": 5.0 }
|
||||
},
|
||||
"search": {
|
||||
"types": ["restaurant"],
|
||||
"limitPerArea": 500
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Event Streaming (C++ → Node)
|
||||
As the gridsearch pipeline executes, the `GridsearchCallbacks` emit standard length-prefixed events directly back to the active UDS socket:
|
||||
- **`ack`**: Acknowledges job was successfully dequeued (`{"type": "ack", "data": {"jobId": "..."}}`).
|
||||
- **`log`**: Passthrough of all internal C++ `spdlog` messages using the custom `uds_sink` adapter.
|
||||
- **`location` / `node`**: Raw geolocation geometries and enriched contact details streamed incrementally.
|
||||
- **`job_progress`**: Phase updates (Grid Generation → Search → Enrichment).
|
||||
- **`job_result`**: The final statistical and timer summary (EnumMs, SearchMs, Total Emails, etc).
|
||||
- **`error`**: Unrecoverable boundary parsing or database initialization faults.
|
||||
|
||||
## License
|
||||
|
||||
|
||||
Binary file not shown.
@ -1,58 +0,0 @@
|
||||
MSBuild version 18.4.0+6e61e96ac for .NET Framework
|
||||
|
||||
libcurl_object.vcxproj -> C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\build\release\_deps\curl-build\lib\libcurl_object.dir\Debug\libcurl_object.lib
|
||||
Catch2.vcxproj -> C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\build\release\_deps\catch2-build\src\Debug\Catch2d.lib
|
||||
Catch2WithMain.vcxproj -> C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\build\release\_deps\catch2-build\src\Debug\Catch2Maind.lib
|
||||
lexbor_static.vcxproj -> C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\build\release\_deps\lexbor-build\Debug\lexbor_static.lib
|
||||
html.vcxproj -> C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\build\release\packages\html\Debug\html.lib
|
||||
libcurl_static.vcxproj -> C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\build\release\_deps\curl-build\lib\Debug\libcurl-d.lib
|
||||
http.vcxproj -> C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\build\release\packages\http\Debug\http.lib
|
||||
json.vcxproj -> C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\build\release\packages\json\Debug\json.lib
|
||||
spdlog.vcxproj -> C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\build\release\_deps\spdlog-build\Debug\spdlogd.lib
|
||||
logger.vcxproj -> C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\build\release\packages\logger\Debug\logger.lib
|
||||
enrichers.vcxproj -> C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\build\release\packages\enrichers\Debug\enrichers.lib
|
||||
geo.vcxproj -> C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\build\release\packages\geo\Debug\geo.lib
|
||||
gadm_reader.vcxproj -> C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\build\release\packages\gadm_reader\Debug\gadm_reader.lib
|
||||
grid.vcxproj -> C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\build\release\packages\grid\Debug\grid.lib
|
||||
ipc.vcxproj -> C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\build\release\packages\ipc\Debug\ipc.lib
|
||||
azure.cpp
|
||||
C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\build\release\_deps\liboai-src\liboai\include\components\chat.h(836,60): warning C4003: not enough arguments for function-like macro invocation 'max' [C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\build\release\_deps\liboai-build\oai.vcxproj]
|
||||
(compiling source file '../liboai-src/liboai/components/azure.cpp')
|
||||
|
||||
C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\build\release\_deps\liboai-src\liboai\include\components\chat.h(836,60): error C2589: '(': illegal token on right side of '::' [C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\build\release\_deps\liboai-build\oai.vcxproj]
|
||||
(compiling source file '../liboai-src/liboai/components/azure.cpp')
|
||||
|
||||
C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\build\release\_deps\liboai-src\liboai\include\components\chat.h(836,60): error C2059: syntax error: ')' [C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\build\release\_deps\liboai-build\oai.vcxproj]
|
||||
(compiling source file '../liboai-src/liboai/components/azure.cpp')
|
||||
|
||||
chat.cpp
|
||||
C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\build\release\_deps\liboai-src\liboai\include\components\chat.h(836,60): warning C4003: not enough arguments for function-like macro invocation 'max' [C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\build\release\_deps\liboai-build\oai.vcxproj]
|
||||
(compiling source file '../liboai-src/liboai/components/chat.cpp')
|
||||
|
||||
C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\build\release\_deps\liboai-src\liboai\include\components\chat.h(836,60): error C2589: '(': illegal token on right side of '::' [C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\build\release\_deps\liboai-build\oai.vcxproj]
|
||||
(compiling source file '../liboai-src/liboai/components/chat.cpp')
|
||||
|
||||
C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\build\release\_deps\liboai-src\liboai\include\components\chat.h(836,60): error C2059: syntax error: ')' [C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\build\release\_deps\liboai-build\oai.vcxproj]
|
||||
(compiling source file '../liboai-src/liboai/components/chat.cpp')
|
||||
|
||||
Generating Code...
|
||||
postgres.vcxproj -> C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\build\release\packages\postgres\Debug\postgres.lib
|
||||
polymech.vcxproj -> C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\build\release\packages\polymech\Debug\polymech.lib
|
||||
search.vcxproj -> C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\build\release\packages\search\Debug\search.lib
|
||||
test_enrichers.vcxproj -> C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\dist\test_enrichers.exe
|
||||
test_functional.vcxproj -> C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\dist\test_functional.exe
|
||||
test_gadm_reader.vcxproj -> C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\dist\test_gadm_reader.exe
|
||||
test_geo.vcxproj -> C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\dist\test_geo.exe
|
||||
test_grid.vcxproj -> C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\dist\test_grid.exe
|
||||
test_gridsearch_ipc.vcxproj -> C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\dist\test_gridsearch_ipc.exe
|
||||
test_html.vcxproj -> C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\dist\test_html.exe
|
||||
test_http.vcxproj -> C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\dist\test_http.exe
|
||||
test_ipc.vcxproj -> C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\dist\test_ipc.exe
|
||||
test_json.vcxproj -> C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\dist\test_json.exe
|
||||
test_logger.vcxproj -> C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\dist\test_logger.exe
|
||||
test_polymech.vcxproj -> C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\dist\test_polymech.exe
|
||||
test_polymech_e2e.vcxproj -> C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\dist\test_polymech_e2e.exe
|
||||
test_postgres.vcxproj -> C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\dist\test_postgres.exe
|
||||
test_postgres_live.vcxproj -> C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\dist\test_postgres_live.exe
|
||||
test_search.vcxproj -> C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\dist\test_search.exe
|
||||
test_supabase.vcxproj -> C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\dist\test_supabase.exe
|
||||
@ -1,147 +0,0 @@
|
||||
MSBuild version 18.4.0+6e61e96ac for .NET Framework
|
||||
Build started 3/29/2026 10:04:05 PM.
|
||||
|
||||
Project "C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\build\release\packages\kbot\kbot.vcxproj" on node 1 (default targets).
|
||||
Project "C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\build\release\packages\kbot\kbot.vcxproj" (1) is building "C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\build\release\ZERO_CHECK.vcxproj" (2) on node 1 (default targets).
|
||||
PrepareForBuild:
|
||||
Structured output is enabled. The formatting of compiler diagnostics will reflect the error hierarchy. See https://aka.ms/cpp/structured-output for more details.
|
||||
InitializeBuildStatus:
|
||||
Creating "x64\Debug\ZERO_CHECK\ZERO_CHECK.tlog\unsuccessfulbuild" because "AlwaysCreate" was specified.
|
||||
Touching "x64\Debug\ZERO_CHECK\ZERO_CHECK.tlog\unsuccessfulbuild".
|
||||
CustomBuild:
|
||||
All outputs are up-to-date.
|
||||
FinalizeBuildStatus:
|
||||
Deleting file "x64\Debug\ZERO_CHECK\ZERO_CHECK.tlog\unsuccessfulbuild".
|
||||
Touching "x64\Debug\ZERO_CHECK\ZERO_CHECK.tlog\ZERO_CHECK.lastbuildstate".
|
||||
Done Building Project "C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\build\release\ZERO_CHECK.vcxproj" (default targets).
|
||||
Project "C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\build\release\packages\kbot\kbot.vcxproj" (1) is building "C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\build\release\packages\json\json.vcxproj" (3) on node 1 (default targets).
|
||||
PrepareForBuild:
|
||||
Structured output is enabled. The formatting of compiler diagnostics will reflect the error hierarchy. See https://aka.ms/cpp/structured-output for more details.
|
||||
InitializeBuildStatus:
|
||||
Creating "json.dir\Debug\json.tlog\unsuccessfulbuild" because "AlwaysCreate" was specified.
|
||||
Touching "json.dir\Debug\json.tlog\unsuccessfulbuild".
|
||||
CustomBuild:
|
||||
All outputs are up-to-date.
|
||||
ClCompile:
|
||||
All outputs are up-to-date.
|
||||
Lib:
|
||||
All outputs are up-to-date.
|
||||
json.vcxproj -> C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\build\release\packages\json\Debug\json.lib
|
||||
FinalizeBuildStatus:
|
||||
Deleting file "json.dir\Debug\json.tlog\unsuccessfulbuild".
|
||||
Touching "json.dir\Debug\json.tlog\json.lastbuildstate".
|
||||
Done Building Project "C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\build\release\packages\json\json.vcxproj" (default targets).
|
||||
Project "C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\build\release\packages\kbot\kbot.vcxproj" (1) is building "C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\build\release\_deps\curl-build\lib\libcurl_static.vcxproj" (4) on node 1 (default targets).
|
||||
Project "C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\build\release\_deps\curl-build\lib\libcurl_static.vcxproj" (4) is building "C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\build\release\_deps\curl-build\lib\libcurl_object.vcxproj" (5) on node 1 (default targets).
|
||||
PrepareForBuild:
|
||||
Structured output is enabled. The formatting of compiler diagnostics will reflect the error hierarchy. See https://aka.ms/cpp/structured-output for more details.
|
||||
InitializeBuildStatus:
|
||||
Creating "libcurl_object.dir\Debug\libcurl_object.tlog\unsuccessfulbuild" because "AlwaysCreate" was specified.
|
||||
Touching "libcurl_object.dir\Debug\libcurl_object.tlog\unsuccessfulbuild".
|
||||
CustomBuild:
|
||||
All outputs are up-to-date.
|
||||
ClCompile:
|
||||
All outputs are up-to-date.
|
||||
Lib:
|
||||
All outputs are up-to-date.
|
||||
libcurl_object.vcxproj -> C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\build\release\_deps\curl-build\lib\libcurl_object.dir\Debug\libcurl_object.lib
|
||||
FinalizeBuildStatus:
|
||||
Deleting file "libcurl_object.dir\Debug\libcurl_object.tlog\unsuccessfulbuild".
|
||||
Touching "libcurl_object.dir\Debug\libcurl_object.tlog\libcurl_object.lastbuildstate".
|
||||
Done Building Project "C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\build\release\_deps\curl-build\lib\libcurl_object.vcxproj" (default targets).
|
||||
PrepareForBuild:
|
||||
Structured output is enabled. The formatting of compiler diagnostics will reflect the error hierarchy. See https://aka.ms/cpp/structured-output for more details.
|
||||
InitializeBuildStatus:
|
||||
Creating "libcurl_static.dir\Debug\libcurl_static.tlog\unsuccessfulbuild" because "AlwaysCreate" was specified.
|
||||
Touching "libcurl_static.dir\Debug\libcurl_static.tlog\unsuccessfulbuild".
|
||||
CustomBuild:
|
||||
All outputs are up-to-date.
|
||||
Lib:
|
||||
All outputs are up-to-date.
|
||||
libcurl_static.vcxproj -> C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\build\release\_deps\curl-build\lib\Debug\libcurl-d.lib
|
||||
FinalizeBuildStatus:
|
||||
Deleting file "libcurl_static.dir\Debug\libcurl_static.tlog\unsuccessfulbuild".
|
||||
Touching "libcurl_static.dir\Debug\libcurl_static.tlog\libcurl_static.lastbuildstate".
|
||||
Done Building Project "C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\build\release\_deps\curl-build\lib\libcurl_static.vcxproj" (default targets).
|
||||
Project "C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\build\release\packages\kbot\kbot.vcxproj" (1) is building "C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\build\release\packages\logger\logger.vcxproj" (6) on node 1 (default targets).
|
||||
Project "C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\build\release\packages\logger\logger.vcxproj" (6) is building "C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\build\release\_deps\spdlog-build\spdlog.vcxproj" (7) on node 1 (default targets).
|
||||
PrepareForBuild:
|
||||
Structured output is enabled. The formatting of compiler diagnostics will reflect the error hierarchy. See https://aka.ms/cpp/structured-output for more details.
|
||||
InitializeBuildStatus:
|
||||
Creating "spdlog.dir\Debug\spdlog.tlog\unsuccessfulbuild" because "AlwaysCreate" was specified.
|
||||
Touching "spdlog.dir\Debug\spdlog.tlog\unsuccessfulbuild".
|
||||
CustomBuild:
|
||||
All outputs are up-to-date.
|
||||
ClCompile:
|
||||
All outputs are up-to-date.
|
||||
Lib:
|
||||
All outputs are up-to-date.
|
||||
spdlog.vcxproj -> C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\build\release\_deps\spdlog-build\Debug\spdlogd.lib
|
||||
FinalizeBuildStatus:
|
||||
Deleting file "spdlog.dir\Debug\spdlog.tlog\unsuccessfulbuild".
|
||||
Touching "spdlog.dir\Debug\spdlog.tlog\spdlog.lastbuildstate".
|
||||
Done Building Project "C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\build\release\_deps\spdlog-build\spdlog.vcxproj" (default targets).
|
||||
PrepareForBuild:
|
||||
Structured output is enabled. The formatting of compiler diagnostics will reflect the error hierarchy. See https://aka.ms/cpp/structured-output for more details.
|
||||
InitializeBuildStatus:
|
||||
Creating "logger.dir\Debug\logger.tlog\unsuccessfulbuild" because "AlwaysCreate" was specified.
|
||||
Touching "logger.dir\Debug\logger.tlog\unsuccessfulbuild".
|
||||
CustomBuild:
|
||||
All outputs are up-to-date.
|
||||
ClCompile:
|
||||
All outputs are up-to-date.
|
||||
Lib:
|
||||
All outputs are up-to-date.
|
||||
logger.vcxproj -> C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\build\release\packages\logger\Debug\logger.lib
|
||||
FinalizeBuildStatus:
|
||||
Deleting file "logger.dir\Debug\logger.tlog\unsuccessfulbuild".
|
||||
Touching "logger.dir\Debug\logger.tlog\logger.lastbuildstate".
|
||||
Done Building Project "C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\build\release\packages\logger\logger.vcxproj" (default targets).
|
||||
Project "C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\build\release\packages\kbot\kbot.vcxproj" (1) is building "C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\build\release\packages\liboai\liboai\oai.vcxproj" (8) on node 1 (default targets).
|
||||
PrepareForBuild:
|
||||
Structured output is enabled. The formatting of compiler diagnostics will reflect the error hierarchy. See https://aka.ms/cpp/structured-output for more details.
|
||||
InitializeBuildStatus:
|
||||
Creating "oai.dir\Debug\oai.tlog\unsuccessfulbuild" because "AlwaysCreate" was specified.
|
||||
Touching "oai.dir\Debug\oai.tlog\unsuccessfulbuild".
|
||||
CustomBuild:
|
||||
All outputs are up-to-date.
|
||||
ClCompile:
|
||||
All outputs are up-to-date.
|
||||
Lib:
|
||||
All outputs are up-to-date.
|
||||
oai.vcxproj -> C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\build\release\packages\liboai\liboai\Debug\oaid.lib
|
||||
FinalizeBuildStatus:
|
||||
Deleting file "oai.dir\Debug\oai.tlog\unsuccessfulbuild".
|
||||
Touching "oai.dir\Debug\oai.tlog\oai.lastbuildstate".
|
||||
Done Building Project "C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\build\release\packages\liboai\liboai\oai.vcxproj" (default targets).
|
||||
PrepareForBuild:
|
||||
Structured output is enabled. The formatting of compiler diagnostics will reflect the error hierarchy. See https://aka.ms/cpp/structured-output for more details.
|
||||
InitializeBuildStatus:
|
||||
Touching "kbot.dir\Debug\kbot.tlog\unsuccessfulbuild".
|
||||
CustomBuild:
|
||||
All outputs are up-to-date.
|
||||
ClCompile:
|
||||
C:\Program Files\Microsoft Visual Studio\18\Community\VC\Tools\MSVC\14.50.35717\bin\HostX64\x64\CL.exe /c /I"C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\packages\kbot" /I"C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\build\release\_deps\taskflow-src" /I"C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\packages\logger\include" /I"C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\build\release\_deps\spdlog-src\include" /I"C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\packages\json\include" /I"C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\build\release\_deps\rapidjson-src\include" /I"C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\packages\liboai\liboai\include" /I"C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\build\release\_deps\nlohmann_json-src\include" /I"C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\build\release\_deps\curl-src\include" /Zi /nologo /W1 /WX- /diagnostics:column /Od /Ob0 /D _MBCS /D WIN32 /D _WINDOWS /D SPDLOG_COMPILED_LIB /D CURL_STATICLIB /D "CMAKE_INTDIR=\"Debug\"" /EHsc /RTC1 /MDd /std:c++17 /Fo"kbot.dir\Debug\\" /Fd"C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\build\release\packages\kbot\Debug\kbot.pdb" /external:W1 /TP /errorReport:queue /utf-8 "C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\packages\kbot\llm_client.cpp"
|
||||
llm_client.cpp
|
||||
C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\packages\kbot\llm_client.cpp(64,19): error C2039: 'SetBaseUrl': is not a member of 'liboai::Authorization' [C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\build\release\packages\kbot\kbot.vcxproj]
|
||||
C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\packages\liboai\liboai\include\core\authorization.h(22,8):
|
||||
see declaration of 'liboai::Authorization'
|
||||
|
||||
C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\packages\kbot\llm_client.cpp(69,22): warning C4834: discarding return value of function with [[nodiscard]] attribute [C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\build\release\packages\kbot\kbot.vcxproj]
|
||||
Done Building Project "C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\build\release\packages\kbot\kbot.vcxproj" (default targets) -- FAILED.
|
||||
|
||||
Build FAILED.
|
||||
|
||||
"C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\build\release\packages\kbot\kbot.vcxproj" (default target) (1) ->
|
||||
(ClCompile target) ->
|
||||
C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\packages\kbot\llm_client.cpp(69,22): warning C4834: discarding return value of function with [[nodiscard]] attribute [C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\build\release\packages\kbot\kbot.vcxproj]
|
||||
|
||||
|
||||
"C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\build\release\packages\kbot\kbot.vcxproj" (default target) (1) ->
|
||||
(ClCompile target) ->
|
||||
C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\packages\kbot\llm_client.cpp(64,19): error C2039: 'SetBaseUrl': is not a member of 'liboai::Authorization' [C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\build\release\packages\kbot\kbot.vcxproj]
|
||||
|
||||
1 Warning(s)
|
||||
1 Error(s)
|
||||
|
||||
Time Elapsed 00:00:02.01
|
||||
Binary file not shown.
@ -1,25 +0,0 @@
|
||||
MSBuild version 18.4.0+6e61e96ac for .NET Framework
|
||||
|
||||
libcurl_object.vcxproj -> C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\build\release\_deps\curl-build\lib\libcurl_object.dir\Debug\libcurl_object.lib
|
||||
libcurl_static.vcxproj -> C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\build\release\_deps\curl-build\lib\Debug\libcurl-d.lib
|
||||
azure.cpp
|
||||
C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\build\release\_deps\liboai-src\liboai\include\components\chat.h(836,60): warning C4003: not enough arguments for function-like macro invocation 'max' [C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\build\release\_deps\liboai-build\oai.vcxproj]
|
||||
(compiling source file '../liboai-src/liboai/components/azure.cpp')
|
||||
|
||||
C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\build\release\_deps\liboai-src\liboai\include\components\chat.h(836,60): error C2589: '(': illegal token on right side of '::' [C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\build\release\_deps\liboai-build\oai.vcxproj]
|
||||
(compiling source file '../liboai-src/liboai/components/azure.cpp')
|
||||
|
||||
C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\build\release\_deps\liboai-src\liboai\include\components\chat.h(836,60): error C2059: syntax error: ')' [C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\build\release\_deps\liboai-build\oai.vcxproj]
|
||||
(compiling source file '../liboai-src/liboai/components/azure.cpp')
|
||||
|
||||
chat.cpp
|
||||
C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\build\release\_deps\liboai-src\liboai\include\components\chat.h(836,60): warning C4003: not enough arguments for function-like macro invocation 'max' [C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\build\release\_deps\liboai-build\oai.vcxproj]
|
||||
(compiling source file '../liboai-src/liboai/components/chat.cpp')
|
||||
|
||||
C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\build\release\_deps\liboai-src\liboai\include\components\chat.h(836,60): error C2589: '(': illegal token on right side of '::' [C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\build\release\_deps\liboai-build\oai.vcxproj]
|
||||
(compiling source file '../liboai-src/liboai/components/chat.cpp')
|
||||
|
||||
C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\build\release\_deps\liboai-src\liboai\include\components\chat.h(836,60): error C2059: syntax error: ')' [C:\Users\zx\Desktop\polymech\polymech-mono\packages\kbot\cpp\build\release\_deps\liboai-build\oai.vcxproj]
|
||||
(compiling source file '../liboai-src/liboai/components/chat.cpp')
|
||||
|
||||
Generating Code...
|
||||
@ -1,18 +1,22 @@
|
||||
/**
|
||||
* orchestrator/test-ipc.mjs
|
||||
*
|
||||
* Integration test: spawn the C++ worker, exchange messages, verify responses.
|
||||
* Integration test: spawn the C++ worker in UDS mode, exchange messages, verify responses.
|
||||
*
|
||||
* Run: node orchestrator/test-ipc.mjs
|
||||
* Needs: npm run build (to compile the C++ binary first)
|
||||
* Run: npm run test:ipc
|
||||
*/
|
||||
|
||||
import { spawnWorker } from './spawn.mjs';
|
||||
import { spawn } from 'node:child_process';
|
||||
import { resolve, dirname } from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import net from 'node:net';
|
||||
import { randomUUID } from 'node:crypto';
|
||||
import { existsSync, unlinkSync } from 'node:fs';
|
||||
|
||||
const __dirname = dirname(fileURLToPath(import.meta.url));
|
||||
const EXE = resolve(__dirname, '..', 'dist', 'polymech-cli.exe');
|
||||
const IS_WIN = process.platform === 'win32';
|
||||
const EXE_NAME = IS_WIN ? 'kbot.exe' : 'kbot';
|
||||
const EXE = resolve(__dirname, '..', 'dist', EXE_NAME);
|
||||
|
||||
let passed = 0;
|
||||
let failed = 0;
|
||||
@ -28,24 +32,109 @@ function assert(condition, label) {
|
||||
}
|
||||
|
||||
async function run() {
|
||||
console.log('\n🔧 IPC Integration Tests\n');
|
||||
console.log('\n🔧 IPC [UDS] Integration Tests\n');
|
||||
|
||||
if (!existsSync(EXE)) {
|
||||
console.error(`❌ Binary not found at ${EXE}`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const CPP_UDS_ARG = IS_WIN ? '4001' : '/tmp/kbot-test-ipc.sock';
|
||||
if (!IS_WIN && existsSync(CPP_UDS_ARG)) {
|
||||
unlinkSync(CPP_UDS_ARG);
|
||||
}
|
||||
|
||||
// ── 1. Spawn & ready ────────────────────────────────────────────────────
|
||||
console.log('1. Spawn worker and wait for ready signal');
|
||||
const worker = spawnWorker(EXE);
|
||||
console.log('1. Spawn worker (UDS mode) and wait for ready signal');
|
||||
const workerProc = spawn(EXE, ['worker', '--uds', CPP_UDS_ARG], { stdio: 'pipe' });
|
||||
|
||||
workerProc.stderr.on('data', d => {
|
||||
const txt = d.toString().trim();
|
||||
if (txt) console.error(`[worker:stderr] ${txt}`);
|
||||
});
|
||||
|
||||
const readyMsg = await worker.ready;
|
||||
let socket;
|
||||
for (let i = 0; i < 15; i++) {
|
||||
try {
|
||||
await new Promise((res, rej) => {
|
||||
if (IS_WIN) {
|
||||
socket = net.connect({ port: 4001, host: '127.0.0.1' });
|
||||
} else {
|
||||
socket = net.connect(CPP_UDS_ARG);
|
||||
}
|
||||
socket.once('connect', res);
|
||||
socket.once('error', rej);
|
||||
});
|
||||
break;
|
||||
} catch (e) {
|
||||
if (i === 14) throw e;
|
||||
await new Promise(r => setTimeout(r, 400));
|
||||
}
|
||||
}
|
||||
assert(true, 'Socket connected successfully');
|
||||
|
||||
// Pending request map: id → { resolve, reject, timer }
|
||||
const pending = new Map();
|
||||
let readyResolve;
|
||||
const readyPromise = new Promise(res => { readyResolve = res; });
|
||||
|
||||
let buffer = Buffer.alloc(0);
|
||||
socket.on('data', chunk => {
|
||||
buffer = Buffer.concat([buffer, chunk]);
|
||||
while (buffer.length >= 4) {
|
||||
const len = buffer.readUInt32LE(0);
|
||||
if (buffer.length >= 4 + len) {
|
||||
const payload = buffer.toString('utf8', 4, 4 + len);
|
||||
buffer = buffer.subarray(4 + len);
|
||||
try {
|
||||
const msg = JSON.parse(payload);
|
||||
if (msg.type === 'ready') {
|
||||
readyResolve(msg);
|
||||
} else if (msg.id && pending.has(msg.id)) {
|
||||
const p = pending.get(msg.id);
|
||||
clearTimeout(p.timer);
|
||||
pending.delete(msg.id);
|
||||
p.resolve(msg);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('[orchestrator] frame parse error', e);
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
function request(msg, timeoutMs = 5000) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const id = msg.id || randomUUID();
|
||||
msg.id = id;
|
||||
const timer = setTimeout(() => {
|
||||
pending.delete(id);
|
||||
reject(new Error(`IPC request timed out`));
|
||||
}, timeoutMs);
|
||||
pending.set(id, { resolve, reject, timer });
|
||||
|
||||
const str = JSON.stringify(msg);
|
||||
const lenBuf = Buffer.alloc(4);
|
||||
lenBuf.writeUInt32LE(Buffer.byteLength(str));
|
||||
socket.write(lenBuf);
|
||||
socket.write(str);
|
||||
});
|
||||
}
|
||||
|
||||
const readyMsg = await readyPromise;
|
||||
assert(readyMsg.type === 'ready', 'Worker sends ready message on startup');
|
||||
|
||||
// ── 2. Ping / Pong ─────────────────────────────────────────────────────
|
||||
console.log('2. Ping → Pong');
|
||||
const pong = await worker.request({ type: 'ping' });
|
||||
const pong = await request({ type: 'ping' });
|
||||
assert(pong.type === 'pong', `Response type is "pong" (got "${pong.type}")`);
|
||||
|
||||
// ── 3. Job echo ─────────────────────────────────────────────────────────
|
||||
console.log('3. Job → Job Result (echo payload)');
|
||||
const payload = { action: 'resize', width: 1024, format: 'webp' };
|
||||
const jobResult = await worker.request({ type: 'job', payload });
|
||||
const jobResult = await request({ type: 'job', payload });
|
||||
assert(jobResult.type === 'job_result', `Response type is "job_result" (got "${jobResult.type}")`);
|
||||
assert(
|
||||
jobResult.payload?.action === 'resize' && jobResult.payload?.width === 1024,
|
||||
@ -54,14 +143,14 @@ async function run() {
|
||||
|
||||
// ── 4. Unknown type → error ─────────────────────────────────────────────
|
||||
console.log('4. Unknown type → error response');
|
||||
const errResp = await worker.request({ type: 'nonsense' });
|
||||
const errResp = await request({ type: 'nonsense' });
|
||||
assert(errResp.type === 'error', `Response type is "error" (got "${errResp.type}")`);
|
||||
|
||||
// ── 5. Multiple rapid requests ──────────────────────────────────────────
|
||||
console.log('5. Multiple concurrent requests');
|
||||
const promises = [];
|
||||
for (let i = 0; i < 10; i++) {
|
||||
promises.push(worker.request({ type: 'ping', payload: { seq: i } }));
|
||||
promises.push(request({ type: 'ping', payload: { seq: i } }));
|
||||
}
|
||||
const results = await Promise.all(promises);
|
||||
assert(results.length === 10, `All 10 responses received`);
|
||||
@ -69,12 +158,13 @@ async function run() {
|
||||
|
||||
// ── 6. Graceful shutdown ────────────────────────────────────────────────
|
||||
console.log('6. Graceful shutdown');
|
||||
const shutdownRes = await worker.shutdown();
|
||||
const shutdownRes = await request({ type: 'shutdown' });
|
||||
assert(shutdownRes.type === 'shutdown_ack', `Shutdown acknowledged (got "${shutdownRes.type}")`);
|
||||
|
||||
// Wait a beat for process exit
|
||||
await new Promise(r => setTimeout(r, 200));
|
||||
assert(worker.process.exitCode === 0, `Worker exited with code 0 (got ${worker.process.exitCode})`);
|
||||
socket.destroy();
|
||||
assert(workerProc.exitCode === 0, `Worker exited with code 0 (got ${workerProc.exitCode})`);
|
||||
|
||||
// ── Summary ─────────────────────────────────────────────────────────────
|
||||
console.log(`\n────────────────────────────────`);
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "mono-cpp",
|
||||
"name": "kbot-cpp",
|
||||
"version": "1.0.0",
|
||||
"description": "Cross-platform C++ CLI built with CMake.",
|
||||
"description": "KBot C++ CLI built with CMake.",
|
||||
"directories": {
|
||||
"test": "tests"
|
||||
},
|
||||
@ -15,14 +15,12 @@
|
||||
"test:release": "ctest --test-dir build/release -C Release --output-on-failure",
|
||||
"clean": "cmake -E rm -rf build dist",
|
||||
"rebuild": "npm run clean && npm run build",
|
||||
"run": ".\\dist\\polymech-cli.exe --help",
|
||||
"worker": ".\\dist\\polymech-cli.exe worker",
|
||||
"test:ipc": "node orchestrator/test-gridsearch-ipc.mjs",
|
||||
"gridsearch": ".\\dist\\polymech-cli.exe gridsearch ABW recycling --dry-run",
|
||||
"gridsearch:settings": ".\\dist\\polymech-cli.exe gridsearch --settings config/gridsearch-sample.json --dry-run",
|
||||
"gridsearch:settings:live": ".\\dist\\polymech-cli.exe gridsearch --settings config/gridsearch-sample.json",
|
||||
"gridsearch:enrich": ".\\dist\\polymech-cli.exe gridsearch --settings config/gridsearch-sample.json --enrich",
|
||||
"gridsearch:enrich-test": ".\\dist\\polymech-cli.exe gridsearch --settings config/gridsearch-test-bcn.json --enrich --persistence-postgres",
|
||||
"run": ".\\dist\\kbot.exe --help",
|
||||
"worker": ".\\dist\\kbot.exe worker",
|
||||
"worker:uds": ".\\dist\\kbot.exe worker --uds \\\\.\\pipe\\kbot-worker",
|
||||
"kbot:ai": ".\\dist\\kbot.exe kbot ai --prompt \"hi\"",
|
||||
"kbot:run": ".\\dist\\kbot.exe kbot run --list",
|
||||
"test:ipc": "node orchestrator/test-ipc.mjs",
|
||||
"test:gridsearch-ipc": "node orchestrator/test-gridsearch-ipc.mjs",
|
||||
"test:gridsearch-filter-ipc": "cmake --build build/release --target test_gridsearch_ipc && .\\dist\\test_gridsearch_ipc.exe",
|
||||
"test:ipc:daemon": "node orchestrator/test-gridsearch-ipc-daemon.mjs",
|
||||
|
||||
@ -8,7 +8,7 @@ namespace polymech {
|
||||
namespace kbot {
|
||||
|
||||
int run_kbot_ai_pipeline(const KBotOptions& opts, const KBotCallbacks& cb) {
|
||||
logger::info("Starting kbot ai pipeline (stub)");
|
||||
logger::debug("Starting kbot ai pipeline");
|
||||
if (opts.dry_run) {
|
||||
logger::info("Dry run triggered for kbot ai");
|
||||
}
|
||||
@ -18,14 +18,14 @@ int run_kbot_ai_pipeline(const KBotOptions& opts, const KBotCallbacks& cb) {
|
||||
tf::Taskflow taskflow;
|
||||
|
||||
taskflow.emplace([opts, cb](){
|
||||
logger::info("Executing kbot ai completion via LLMClient...");
|
||||
logger::debug("Executing kbot ai completion via LLMClient...");
|
||||
LLMClient client(opts);
|
||||
|
||||
std::string target_prompt = opts.prompt.empty() ? "Respond with 'Hello from KBot C++ AI Pipeline!'" : opts.prompt;
|
||||
LLMResponse res = client.execute_chat(target_prompt);
|
||||
|
||||
if (res.success) {
|
||||
logger::info("AI Response:\n" + res.text);
|
||||
std::cout << res.text << "\n";
|
||||
if (cb.onEvent) {
|
||||
cb.onEvent("ai_progress", "{\"message\":\"Task completion received\"}");
|
||||
}
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
#include "llm_client.h"
|
||||
#include "logger/logger.h"
|
||||
#include <liboai.h>
|
||||
#include <nlohmann/json.hpp>
|
||||
#include <iostream>
|
||||
|
||||
namespace polymech {
|
||||
@ -43,17 +44,17 @@ LLMClient::~LLMClient() = default;
|
||||
LLMResponse LLMClient::execute_chat(const std::string& prompt) {
|
||||
LLMResponse res;
|
||||
|
||||
logger::info("LLMClient::execute_chat: Starting. api_key length: " + std::to_string(api_key_.length()));
|
||||
logger::debug("LLMClient::execute_chat: Starting. api_key length: " + std::to_string(api_key_.length()));
|
||||
if (api_key_.empty()) {
|
||||
res.success = false;
|
||||
res.error = "API Key is empty.";
|
||||
return res;
|
||||
}
|
||||
|
||||
logger::info("LLMClient::execute_chat: base_url_: " + base_url_);
|
||||
logger::debug("LLMClient::execute_chat: base_url_: " + base_url_);
|
||||
liboai::OpenAI oai_impl(base_url_.empty() ? "https://api.openai.com/v1" : base_url_);
|
||||
|
||||
logger::info("LLMClient::execute_chat: Setting API Key");
|
||||
logger::debug("LLMClient::execute_chat: Setting API Key");
|
||||
bool success = oai_impl.auth.SetKey(api_key_);
|
||||
if (!success) {
|
||||
res.success = false;
|
||||
@ -62,24 +63,37 @@ LLMResponse LLMClient::execute_chat(const std::string& prompt) {
|
||||
}
|
||||
|
||||
std::string target_model = model_.empty() ? "gpt-4o" : model_;
|
||||
logger::info("LLMClient::execute_chat: Target model: " + target_model);
|
||||
logger::debug("LLMClient::execute_chat: Target model: " + target_model);
|
||||
|
||||
logger::info("LLMClient::execute_chat: Init Conversation");
|
||||
logger::debug("LLMClient::execute_chat: Init Conversation");
|
||||
liboai::Conversation convo;
|
||||
convo.AddUserData(prompt);
|
||||
|
||||
logger::info("LLMClient::execute_chat: Calling create()");
|
||||
logger::debug("LLMClient::execute_chat: Calling create()");
|
||||
try {
|
||||
liboai::Response response = oai_impl.ChatCompletion->create(
|
||||
target_model,
|
||||
convo
|
||||
);
|
||||
logger::info("LLMClient::execute_chat: Got response with status: " + std::to_string(response.status_code));
|
||||
logger::debug("LLMClient::execute_chat: Got response with status: " + std::to_string(response.status_code));
|
||||
|
||||
if (!response.raw_json.contains("choices") || response.raw_json["choices"].empty()) {
|
||||
// liboai may not populate raw_json for custom base URLs — parse content directly.
|
||||
nlohmann::json j;
|
||||
bool json_ok = false;
|
||||
if (!response.raw_json.empty() && response.raw_json.contains("choices")) {
|
||||
j = response.raw_json;
|
||||
json_ok = true;
|
||||
} else if (!response.content.empty()) {
|
||||
try {
|
||||
j = nlohmann::json::parse(response.content);
|
||||
json_ok = j.contains("choices");
|
||||
} catch (...) {}
|
||||
}
|
||||
|
||||
if (!json_ok || j["choices"].empty()) {
|
||||
res.success = false;
|
||||
if (response.raw_json.contains("error")) {
|
||||
res.error = "API Error: " + response.raw_json["error"].dump();
|
||||
if (json_ok && j.contains("error")) {
|
||||
res.error = "API Error: " + j["error"].dump();
|
||||
} else {
|
||||
res.error = "Invalid response format: no choices found. Raw: " + response.content;
|
||||
}
|
||||
@ -87,7 +101,7 @@ LLMResponse LLMClient::execute_chat(const std::string& prompt) {
|
||||
}
|
||||
|
||||
res.success = true;
|
||||
res.text = response.raw_json["choices"][0]["message"]["content"].get<std::string>();
|
||||
res.text = j["choices"][0]["message"]["content"].get<std::string>();
|
||||
|
||||
} catch (std::exception& e) {
|
||||
logger::error("LLMClient::execute_chat: Exception caught: " + std::string(e.what()));
|
||||
|
||||
@ -29,7 +29,7 @@
|
||||
#endif
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
CLI::App app{"polymech-cli — Polymech C++ CLI", "polymech-cli"};
|
||||
CLI::App app{"kbot — KBot C++ CLI", "kbot"};
|
||||
app.set_version_flag("-v,--version", PROJECT_VERSION);
|
||||
|
||||
std::string log_level = "info";
|
||||
@ -89,11 +89,9 @@ int main(int argc, char *argv[]) {
|
||||
worker_cmd->add_option("--user-uid", daemon_uid, "User ID to bind this daemon to (needed for place owner)");
|
||||
worker_cmd->add_option("--uds", uds_path, "Run over Unix Domain Socket / Named Pipe at the given path");
|
||||
|
||||
// Subcommand: gridsearch — Run a full gridsearch pipeline
|
||||
auto* gs_cmd = polymech::setup_cmd_gridsearch(app);
|
||||
|
||||
// Subcommand: kbot — AI workflows & task configurations
|
||||
auto* kbot_cmd = polymech::setup_cmd_kbot(app);
|
||||
(void)kbot_cmd;
|
||||
|
||||
CLI11_PARSE(app, argc, argv);
|
||||
|
||||
@ -294,11 +292,6 @@ int main(int argc, char *argv[]) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// ── gridsearch subcommand ──────────────────────────────────────────────
|
||||
if (gs_cmd->parsed()) {
|
||||
return polymech::run_cmd_gridsearch();
|
||||
}
|
||||
|
||||
// ── kbot subcommand ──────────────────────────────────────────────────
|
||||
if (polymech::is_kbot_ai_parsed()) {
|
||||
return polymech::run_cmd_kbot_ai();
|
||||
|
||||
Loading…
Reference in New Issue
Block a user