File size: 3,493 Bytes
2b64d42 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 | import { describe, it } from 'node:test';
import assert from 'node:assert/strict';
import { neutralizeCascadeIdentity } from '../src/handlers/chat.js';
// Cascade's planner system prompt teaches the upstream model to refer to
// itself as "Cascade", to claim it was "made by Codeium" or "by Windsurf",
// and to talk about "Cascade's workspace". Claude Code (and any caller
// expecting Anthropic-equivalent output) must not see those leaks.
//
// neutralizeCascadeIdentity rewrites the most common Cascade-isms back to
// the requested model identity. Patterns are deliberately conservative:
// only obvious self-reference is rewritten — generic mentions of the word
// "cascade" in user code or technical prose are left alone.
describe('neutralizeCascadeIdentity', () => {
const model = 'claude-opus-4-7';
it('rewrites first-person identity claims', () => {
assert.equal(
neutralizeCascadeIdentity('I am Cascade and I will help.', model),
`I am ${model} and I will help.`
);
assert.equal(
neutralizeCascadeIdentity("I'm Cascade, ready to help.", model),
`I'm ${model}, ready to help.`
);
assert.equal(
neutralizeCascadeIdentity('Hi! my name is Cascade.', model),
`Hi! my name is ${model}.`
);
});
it('rewrites third-person self-reference', () => {
assert.equal(
neutralizeCascadeIdentity('Cascade is an AI coding assistant built by Windsurf.', model),
`${model} is an AI assistant built by Anthropic.`
);
assert.equal(
neutralizeCascadeIdentity('As Cascade, I will check that.', model),
`As ${model}, I will check that.`
);
assert.equal(
neutralizeCascadeIdentity('Acting as Cascade, I will check that.', model),
`As ${model}, I will check that.`
);
});
it('rewrites provider attribution variants', () => {
assert.equal(
neutralizeCascadeIdentity('I was developed by Codeium.', model),
'I was developed by Anthropic.'
);
assert.equal(
neutralizeCascadeIdentity('I was created by Windsurf.', model),
'I was created by Anthropic.'
);
assert.equal(
neutralizeCascadeIdentity('I was built by Windsurf.', model),
'I was built by Anthropic.'
);
assert.equal(
neutralizeCascadeIdentity("Codeium's Cascade can help with that.", model),
`${model} can help with that.`
);
assert.equal(
neutralizeCascadeIdentity('Windsurf Cascade is here.', model),
`${model} is here.`
);
});
it('rewrites Cascade workspace narration', () => {
assert.equal(
neutralizeCascadeIdentity("Let me check Cascade's workspace.", model),
'Let me check the workspace.'
);
assert.equal(
neutralizeCascadeIdentity('I will use the Cascade workspace.', model),
'I will use the workspace.'
);
});
it('leaves unrelated text unchanged', () => {
const text = 'The waterfall flows down a cascade of rocks.';
assert.equal(neutralizeCascadeIdentity(text, model), text);
});
it('returns text unchanged when modelName has no known provider mapping', () => {
const text = 'I am Cascade.';
assert.equal(neutralizeCascadeIdentity(text, 'mystery-model'), text);
});
it('returns falsy inputs unchanged', () => {
assert.equal(neutralizeCascadeIdentity('', model), '');
assert.equal(neutralizeCascadeIdentity(null, model), null);
assert.equal(neutralizeCascadeIdentity('I am Cascade.', null), 'I am Cascade.');
});
});
|