MCPcopy Create free account
hub / github.com/antirez/ds4 / run_agent_non_interactive

Function run_agent_non_interactive

ds4_agent.c:9638–9787  ·  view source on GitHub ↗

Headless mode is intentionally just another front-end for the same worker. * With -p/--prompt it is a one-shot execution. Without -p it becomes a small * stdin protocol: announce readiness on stderr, collect bytes until stdin has * been quiet for 200 ms, submit that buffer as one prompt, and keep reading so * later input can be queued while the model is still working. */

Source from the content-addressed store, hash-verified

9636/* Classify a possible terminal cursor-position reply (ESC[row;colR). User
9637 * keystrokes can arrive interleaved with these replies, so we only swallow bytes
9638 * when they are definitely part of a complete CPR sequence. */
9639static cpr_state cpr_candidate_state(const char *buf, size_t len) {
9640 if (len == 0) return CPR_PARTIAL;
9641 if ((unsigned char)buf[0] != 0x1b) return CPR_INVALID;
9642 if (len == 1) return CPR_PARTIAL;
9643 if (buf[1] != '[') return CPR_INVALID;
9644 if (len == 2) return CPR_PARTIAL;
9645
9646 size_t p = 2;
9647 if (buf[p] < '0' || buf[p] > '9') return CPR_INVALID;
9648 while (p < len && buf[p] >= '0' && buf[p] <= '9') p++;
9649 if (p == len) return CPR_PARTIAL;
9650 if (buf[p++] != ';') return CPR_INVALID;
9651 if (p == len) return CPR_PARTIAL;
9652 if (buf[p] < '0' || buf[p] > '9') return CPR_INVALID;
9653 while (p < len && buf[p] >= '0' && buf[p] <= '9') p++;
9654 if (p == len) return CPR_PARTIAL;
9655 return p + 1 == len && buf[p] == 'R' ? CPR_COMPLETE : CPR_INVALID;
9656}
9657
9658static void editor_flush_cpr_candidate(agent_editor *ed) {
9659 if (!ed->cpr_len) return;
9660 linenoiseEditQueueInput(&ed->edit, ed->cpr_buf, ed->cpr_len);
9661 ed->cpr_len = 0;
9662}
9663
9664static bool agent_tail_ends_with(const char *tail, size_t tail_len,
9665 const char *seq, size_t seq_len) {
9666 return tail_len >= seq_len &&
9667 memcmp(tail + tail_len - seq_len, seq, seq_len) == 0;
9668}
9669
9670static bool agent_tail_has_seq_prefix(const char *tail, size_t tail_len,
9671 const char *seq, size_t seq_len) {
9672 size_t max = tail_len < seq_len - 1 ? tail_len : seq_len - 1;
9673 for (size_t n = max; n > 0; n--) {
9674 if (memcmp(tail + tail_len - n, seq, n) == 0) return true;
9675 }
9676 return false;
9677}
9678
9679/* Track bracketed paste markers outside linenoise. The nonblocking event loop
9680 * may receive a paste in chunks; pausing linenoiseEditFeed() until ESC[201~
9681 * arrives prevents pasted newlines from being interpreted as Enter. */
9682static void editor_track_bracketed_paste(agent_editor *ed, char c) {
9683 static const char start[] = "\x1b[200~";
9684 static const char end[] = "\x1b[201~";
9685
9686 if (ed->paste_tail_len == sizeof(ed->paste_tail)) {
9687 memmove(ed->paste_tail, ed->paste_tail + 1, sizeof(ed->paste_tail) - 1);
9688 ed->paste_tail_len--;
9689 }
9690 ed->paste_tail[ed->paste_tail_len++] = c;
9691
9692 /* The blocking linenoise() path waits inside linenoiseEditPaste() until it
9693 * sees ESC[201~. In the agent the outer event loop reads stdin in
9694 * non-blocking chunks; if we let linenoise start parsing ESC[200~ before
9695 * the closing marker has arrived, pasted newlines can be interpreted as

Callers 1

mainFunction · 0.85

Calls 15

agent_worker_initFunction · 0.85
set_nonblockFunction · 0.85
agent_worker_freeFunction · 0.85
worker_is_initializedFunction · 0.85
worker_is_idleFunction · 0.85
worker_submitFunction · 0.85
drain_wake_fdFunction · 0.85
worker_consumeFunction · 0.85

Tested by

no test coverage detected