diff --git a/README.md b/README.md index 68cccb2..56197fd 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,7 @@ Forked from [nasrulhadi/proxy-commandcode](https://github.com/nasrulhadi/proxy-c | Usage | `finish-step`/`finish` usage mapped to OpenAI `usage` (sync body; extra stream chunk with empty `choices`) | | Finish reason | `length` / `tool_calls` / `content_filter` mapped from the upstream reason | | Request shape | Tool-call `input` sent as an object; consecutive tool results merged; `developer` role folded into `system`; image parts use `{image, mediaType}`; `temperature` and `max_completion_tokens` passed through; `x-session-id` and `x-cli-environment` headers sent | +| System prompt | A request with no (or a blank) system message gets a one-line default (`PCMC_DEFAULT_SYSTEM`, default `You are a helpful assistant.`); otherwise the gateway injects the ~7.3K-token `cmd` agent prompt on every call | | CLI version | `x-command-code-version` tracks `command-code@latest` on npm (checked at start and every 6 h, default `1.66.0`); set `PCMC_VERSION` to pin | | Runtime | Logs to stdout only (no `proxy.log`, no ANSI without a TTY); Windows `netstat`/`taskkill` port handling removed; graceful `SIGTERM`; `Dockerfile` + `npm test` | diff --git a/server.js b/server.js index 98ad2b7..32a9b8b 100644 --- a/server.js +++ b/server.js @@ -19,6 +19,11 @@ const DEFAULT_CC_VERSION = '1.66.0'; const PINNED_VERSION = process.env.PCMC_VERSION || ''; const VERSION_REFRESH_MS = 6 * 60 * 60 * 1000; const DEBUG = process.env.PCMC_DEBUG === '1'; +// With no system prompt the gateway substitutes the ~7.3K-token `cmd` agent +// prompt (CLI tools, commit rules, taste file), which costs tokens on every call +// and makes the model act as a coding agent. A blank system is rejected by some +// models, so always send a real one. +const DEFAULT_SYSTEM = (process.env.PCMC_DEFAULT_SYSTEM || '').trim() || 'You are a helpful assistant.'; let ccVersion = PINNED_VERSION || DEFAULT_CC_VERSION; @@ -135,7 +140,7 @@ function transform(oaiBody) { })); const params = { - model, system: systemText || undefined, messages, tools: tools.length > 0 ? tools : undefined, + model, system: systemText.trim() ? systemText : DEFAULT_SYSTEM, messages, tools: tools.length > 0 ? tools : undefined, max_tokens: oaiBody.max_completion_tokens || oaiBody.max_tokens || 32000, // The gateway rejects stream:false; always stream upstream and buffer here. stream: true, diff --git a/test/transform.test.js b/test/transform.test.js index e989fbb..9077728 100644 --- a/test/transform.test.js +++ b/test/transform.test.js @@ -12,6 +12,16 @@ test('builds the strict envelope and always streams upstream', () => { assert.deepEqual(body.params.messages, [{ role: 'user', content: [{ type: 'text', text: 'hi' }] }]); }); +test('sends a default system prompt when none or a blank one is given', () => { + for (const messages of [ + [{ role: 'user', content: 'q' }], + [{ role: 'system', content: ' ' }, { role: 'user', content: 'q' }], + ]) { + const body = JSON.parse(transform({ messages })); + assert.equal(body.params.system, 'You are a helpful assistant.'); + } +}); + test('maps system/developer to params.system', () => { const body = JSON.parse(transform({ messages: [ { role: 'system', content: 'a' }, { role: 'developer', content: [{ type: 'text', text: 'b' }] }, { role: 'user', content: 'q' },