QVAC-13559 feat[api]: sdk "dynamic" tools mode#745
Conversation
615c9e7 to
1e7b0f7
Compare
06b0ae7 to
c1e85c2
Compare
Tier-based Approval Status |
96e46e2 to
5094f21
Compare
| @@ -0,0 +1,202 @@ | |||
| /* eslint-disable */ | |||
| // @ts-nocheck | |||
There was a problem hiding this comment.
@opaninakuffo initially I just copied sdk/examples/llamacpp-native-tools.ts and replaced the logic with "dynamic" tools handling - should remove so to pass both checks?
There was a problem hiding this comment.
removed comments, now both lint and type checks pass ✔️
| properties: Record<string, unknown>; | ||
| required?: string[]; | ||
| }; | ||
| }>, |
There was a problem hiding this comment.
we have numerous existing tool tests. Can we modify some of those to be dynamic instead?
There was a problem hiding this comment.
I've assumed current tools tests cover available logic and if removed it would end with decreased coverage - I mean to remove a test in order to replace with a dynamic tools one it's required to "prove" it's useless, because a newly added "dynamic" tools one would go another code path 🤔
I will take a look if any test do same stuff, if possible to merge
There was a problem hiding this comment.
improved tests:
- extended available
createToolsTestfunction to reuse withtoolsModeparam (removed prev added helper) - removed
toolModeUnsettest case as already covered by e.g.toolsSimpleFunction
|
please update |
…ic-tools-interface-support
| const modelConfig = getModelConfig(modelId); | ||
| const systemPromptFromHistory = extractSystemPrompt(history); | ||
| const configHash = generateConfigHash(systemPromptFromHistory, tools); | ||
| const toolsModeForHash = (modelConfig as { toolsMode?: string }).toolsMode; |
There was a problem hiding this comment.
isn't this the same than the toolsMode constant in the outer scope?
There was a problem hiding this comment.
@simon-iribarren yes, I but I've decided to follow current logic since there are 2 model configs right now and kvCache "branch" has it's own, like
const modelConfig = getModelConfig(modelId);
// <...>
if (kvCache) {
const modelConfig = getModelConfig(modelId);
// at this point using toolsMode from the "second" confighence this is just for consistency - otherwise prob we should refactor to have a single modelConfig?
…ic-tools-interface-support
- Remove `CompletionDebugStats` schema and `debugStats` from `CompletionRun`, `statsEventSchema`, and `buildStreamResult`. - Drop the runtime-debug-stats extraction and the `// @ts-expect-error test-error` workaround in `completion-stream.ts`. Those required an addon-side patch that is not in scope here. - Delete the `agentic-tools.ts` example. It was the only consumer of the debug-stats fields and the source of CodeQL findings (ReDoS on `<think>`/`<tool_call>`, double-unescape, weak URL hostname check). `llamacpp-dynamic-tools.ts` remains as the canonical dynamic-tools example.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
- The PR introduced `validation: "custom"` + a `validator` callback in tools tests, but `@tetherto/qvac-test-suite@0.6.0`'s `Expectation` union does not include `"custom"`. Add a local `ToolsExpectation` extension that augments `Expectation` with the custom-validator shape, used by both the test definitions and the executor. The `TestDefinition` cast at construction keeps the runtime payload compatible with the test framework. - Two `createToolsTest` call sites (`toolsSimpleFunction`, `toolsMultipleFunctions`) passed `["smoke"]` as the 5th positional arg, which collides with the `expectation` slot. Add the explicit `undefined` between `toolsMode` and the `suites` argument so the array reaches the `suites` parameter. - The executor's `"custom"` branch now invokes the validator directly and shapes a `TestResult`, instead of forwarding to `ValidationHelpers.validate` (which only handles the built-in validation kinds). Both issues only surfaced once the `test-e2e-smoke` label was applied — the e2e workflow's tests-qvac typecheck leg is label-gated, so prior pushes never typechecked these files.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
The plugin's `transformLlmConfig` was missing the SDK-to-addon translation for `toolsMode`. Without it, the addon receives `tools_mode` as a CLI-style flag, which it does not recognize, and load fails with `commonParamsParse: invalid argument: --tools-mode`. This translation existed in commit 2840f4d but was lost during a later main merge that brought in the new addon constructor shape (PR #1688). Reinstating the original mapping: toolsMode: "dynamic" → tools_compact: "true" toolsMode: "static" → tools_compact: "false"
QVAC E2E —
|
| promptTokens: z.number().optional(), | ||
| generatedTokens: z.number().optional(), |
There was a problem hiding this comment.
generatedTokens & promptTokens arent mapped through from the addon, kindly link
| if (!canSlice && savedCount > 0) { | ||
| if (savedCount > 0 && savedCount <= history.length) { | ||
| cachedMessageCounts.delete(cachePathToUse); | ||
| } | ||
|
|
There was a problem hiding this comment.
Old code deleted stale counts (!canSlice && savedCount > 0 ⇒ savedCount > history.length). New code deletes valid counts (savedCount > 0 && savedCount <= history.length) and leaves stale ones in place. Combined with the fact that savedCount is no longer used for slicing at all, the cachedMessageCounts map has been quietly demoted from "track how much we've cached so we can resend the delta" to "we toggle a bit and then immediately overwrite it via recordCacheSaveCount." Either:
- the map is now load-bearing only for the missing-cache-file failure path of
recordCacheSaveCount, in which case the predicate should match the old "stale" intent(savedCount > history.length), or - the slicing-by-savedCount behavior should be restored for the cache-hit path, or
- the map and
recordCacheSaveCountshould be removed entirely if they're truly dead.
Kindly document with whichever option as the current state is now contradictory with previous.
Suggestionsfrom Cursor:
|
Description
Adds support for dynamic tools mode with
@qvac/llm-llamacppaddonChanges:
package.json: Upgraded@qvac/llm-llamacppto ^0.17.0toolsModeconfiguration inteface'static'mode (default): Tools are prepended to history (existing behavior)'dynamic'mode: Tools exist in a user prompt scope and then removed from kv-cachehow to check it works:
addon implementation