Vendored sashidown, OpenAI-compatible env (OPENAI_*), and bootstrap scripts. Co-authored-by: Cursor <cursoragent@cursor.com>
66 lines
1.6 KiB
C
66 lines
1.6 KiB
C
#include "mm_tool.h"
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
typedef struct {
|
|
int n_ready;
|
|
int n_text;
|
|
char name[64];
|
|
char path[256];
|
|
} sink_t;
|
|
|
|
static void on_ev(const ctl_event_t *ev, void *ud) {
|
|
sink_t *s = ud;
|
|
if (ev->type == CTL_EV_TEXT)
|
|
s->n_text++;
|
|
if (ev->type == CTL_EV_CALL_READY && ev->call) {
|
|
s->n_ready++;
|
|
snprintf(s->name, sizeof(s->name), "%s", ev->call->name);
|
|
if (ev->call->nargs > 0 && ev->call->args[0].value)
|
|
snprintf(s->path, sizeof(s->path), "%s", ev->call->args[0].value);
|
|
}
|
|
}
|
|
|
|
static int expect(int c, const char *m) {
|
|
if (!c) {
|
|
fprintf(stderr, "FAIL: %s\n", m);
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
int main(void) {
|
|
sink_t s = {0};
|
|
mm_scan_t *mm = mm_scan_create(on_ev, &s);
|
|
const char *msg =
|
|
"我来读一下。\n"
|
|
"<minimax:tool_call>\n"
|
|
"invoke read_file\n"
|
|
"<arg name=\"path\">./README.md</arg>\n"
|
|
"</minimax:tool_call>\n"
|
|
"读完了。\n";
|
|
/* byte-at-a-time */
|
|
for (size_t i = 0; msg[i]; i++)
|
|
mm_scan_feed(mm, &msg[i], 1);
|
|
mm_scan_finish(mm);
|
|
int ok = 1;
|
|
ok &= expect(s.n_ready == 1, "one ready");
|
|
ok &= expect(strcmp(s.name, "read_file") == 0, "name");
|
|
ok &= expect(strcmp(s.path, "./README.md") == 0, "path");
|
|
ok &= expect(s.n_text >= 1, "text emitted");
|
|
/* truncated: no execute */
|
|
sink_t s2 = {0};
|
|
mm_scan_t *mm2 = mm_scan_create(on_ev, &s2);
|
|
const char *trunc = "<minimax:tool_call>\ninvoke read_file\n";
|
|
mm_scan_feed(mm2, trunc, strlen(trunc));
|
|
mm_scan_finish(mm2);
|
|
ok &= expect(s2.n_ready == 0, "trunc no ready");
|
|
mm_scan_destroy(mm);
|
|
mm_scan_destroy(mm2);
|
|
if (!ok)
|
|
return 1;
|
|
printf("test_mm_tool: OK\n");
|
|
return 0;
|
|
}
|