@ggui-ai/negotiator 0.2.0-alpha.3 → 0.3.0-rc.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +25 -19
- package/dist/contract-validators.d.ts +20 -16
- package/dist/contract-validators.d.ts.map +1 -1
- package/dist/contract-validators.js +11 -8
- package/dist/ensure-conforming-contract.d.ts +70 -0
- package/dist/ensure-conforming-contract.d.ts.map +1 -0
- package/dist/ensure-conforming-contract.js +115 -0
- package/dist/index.d.ts +22 -20
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +21 -14
- package/dist/llm-caller.d.ts +9 -9
- package/dist/llm-caller.d.ts.map +1 -1
- package/dist/llm-caller.js +8 -8
- package/dist/llm-rerank.d.ts +9 -8
- package/dist/llm-rerank.d.ts.map +1 -1
- package/dist/llm-rerank.js +4 -25
- package/dist/normalize-draft.d.ts +33 -0
- package/dist/normalize-draft.d.ts.map +1 -0
- package/dist/normalize-draft.js +167 -0
- package/dist/normalize-schema.d.ts.map +1 -1
- package/dist/normalize-schema.js +12 -0
- package/dist/preserve-seed-surfaces.d.ts +40 -0
- package/dist/preserve-seed-surfaces.d.ts.map +1 -0
- package/dist/preserve-seed-surfaces.js +57 -0
- package/dist/synth-bench/cache-key-probe.d.ts +3 -0
- package/dist/synth-bench/cache-key-probe.d.ts.map +1 -0
- package/dist/synth-bench/cache-key-probe.js +177 -0
- package/dist/synth-bench/cli-llm.d.ts +20 -0
- package/dist/synth-bench/cli-llm.d.ts.map +1 -0
- package/dist/synth-bench/cli-llm.js +97 -0
- package/dist/synth-bench/corpus.d.ts +52 -0
- package/dist/synth-bench/corpus.d.ts.map +1 -1
- package/dist/synth-bench/corpus.js +314 -5
- package/dist/synth-bench/round-trip-score.d.ts +87 -0
- package/dist/synth-bench/round-trip-score.d.ts.map +1 -0
- package/dist/synth-bench/round-trip-score.js +105 -0
- package/dist/synth-bench/run-bench-cli.js +6 -82
- package/dist/synth-bench/run-bench.js +2 -2
- package/dist/synth-bench/run-repair-bench-cli.d.ts +3 -0
- package/dist/synth-bench/run-repair-bench-cli.d.ts.map +1 -0
- package/dist/synth-bench/run-repair-bench-cli.js +86 -0
- package/dist/synth-bench/run-repair-bench.d.ts +94 -0
- package/dist/synth-bench/run-repair-bench.d.ts.map +1 -0
- package/dist/synth-bench/run-repair-bench.js +172 -0
- package/dist/synthesize-contract.d.ts +40 -9
- package/dist/synthesize-contract.d.ts.map +1 -1
- package/dist/synthesize-contract.js +266 -47
- package/package.json +9 -7
- package/src/contract-validators.ts +21 -17
- package/src/ensure-conforming-contract.ts +175 -0
- package/src/index.ts +22 -33
- package/src/llm-caller.ts +9 -9
- package/src/llm-rerank.ts +12 -17
- package/src/normalize-draft.ts +182 -0
- package/src/normalize-schema.ts +11 -0
- package/src/preserve-seed-surfaces.ts +61 -0
- package/src/synth-bench/cache-key-probe.ts +213 -0
- package/src/synth-bench/cli-llm.ts +140 -0
- package/src/synth-bench/corpus.ts +343 -5
- package/src/synth-bench/round-trip-score.ts +169 -0
- package/src/synth-bench/run-bench-cli.ts +13 -115
- package/src/synth-bench/run-bench.ts +2 -2
- package/src/synth-bench/run-repair-bench-cli.ts +119 -0
- package/src/synth-bench/run-repair-bench.ts +266 -0
- package/src/synthesize-contract.ts +323 -57
- package/dist/decision-input.d.ts +0 -51
- package/dist/decision-input.d.ts.map +0 -1
- package/dist/decision-input.js +0 -17
- package/dist/decision.d.ts +0 -58
- package/dist/decision.d.ts.map +0 -1
- package/dist/decision.js +0 -501
- package/dist/intent.d.ts +0 -22
- package/dist/intent.d.ts.map +0 -1
- package/dist/intent.js +0 -28
- package/dist/negotiate.d.ts +0 -142
- package/dist/negotiate.d.ts.map +0 -1
- package/dist/negotiate.js +0 -163
- package/dist/pure.d.ts +0 -30
- package/dist/pure.d.ts.map +0 -1
- package/dist/pure.js +0 -43
- package/dist/rag-search.d.ts +0 -73
- package/dist/rag-search.d.ts.map +0 -1
- package/dist/rag-search.js +0 -192
- package/dist/render.d.ts +0 -57
- package/dist/render.d.ts.map +0 -1
- package/dist/render.js +0 -25
- package/dist/suggestion.d.ts +0 -38
- package/dist/suggestion.d.ts.map +0 -1
- package/dist/suggestion.js +0 -47
- package/dist/types.d.ts +0 -30
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js +0 -13
- package/src/decision-input.ts +0 -52
- package/src/decision.ts +0 -581
- package/src/intent.ts +0 -37
- package/src/negotiate.ts +0 -314
- package/src/pure.ts +0 -46
- package/src/rag-search.ts +0 -274
- package/src/render.ts +0 -56
- package/src/suggestion.ts +0 -73
- package/src/types.ts +0 -31
package/README.md
CHANGED
|
@@ -1,11 +1,19 @@
|
|
|
1
1
|
# @ggui-ai/negotiator
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Contract-synthesis + match-judge engine for
|
|
4
|
+
[ggui](https://github.com/ggui-ai/ggui)'s handshake.
|
|
4
5
|
|
|
5
|
-
Given an agent's
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
Given an agent's draft contract + intent, this package synthesizes (or
|
|
7
|
+
repairs) a conforming `DataContract`, judges blueprint-match candidates for
|
|
8
|
+
reuse, and validates contract structure + novelty — the primitives the
|
|
9
|
+
handshake composes to always return a valid contract.
|
|
10
|
+
|
|
11
|
+
> The handshake **decision** itself (find-similar → reuse vs synth-create)
|
|
12
|
+
> lives in the shared `decideHandshake` core in
|
|
13
|
+
> [`@ggui-ai/mcp-server-handlers`](../mcp-server-handlers), which composes
|
|
14
|
+
> the primitives below. The former in-package `negotiate()` RAG+decision
|
|
15
|
+
> pipeline was retired in favor of that unified, adapter-injected core —
|
|
16
|
+
> one decision spine; LLM and storage bindings plug in per deployment.
|
|
9
17
|
|
|
10
18
|
The package is deployment-agnostic. It composes the storage interfaces
|
|
11
19
|
defined in `@ggui-ai/mcp-server-core` (`EmbeddingProvider`, `VectorStore`),
|
|
@@ -20,28 +28,26 @@ pnpm add @ggui-ai/negotiator
|
|
|
20
28
|
|
|
21
29
|
## What's in the box
|
|
22
30
|
|
|
23
|
-
- **`negotiate(deps, input)`** — top-level orchestrator. Runs RAG search over
|
|
24
|
-
registered blueprints, reads render state, fast-paths exact blueprint
|
|
25
|
-
hits, and otherwise calls the decision LLM.
|
|
26
|
-
- **`makeDecision(...)`** — the decision step in isolation: pick an action
|
|
27
|
-
(`create` / `update` / `replace`) and a blueprint from the
|
|
28
|
-
candidate set.
|
|
29
31
|
- **`synthesizeContract(...)`** — cold-path contract synthesizer. Turns an
|
|
30
32
|
agent intent into a `DataContract` (props / context / action / stream
|
|
31
33
|
specs, plus gadget references), with a repair loop and a schema-validation
|
|
32
34
|
gate.
|
|
33
|
-
- **`
|
|
34
|
-
|
|
35
|
-
-
|
|
36
|
-
|
|
35
|
+
- **`ensureConformingContract(...)`** — the create-path guarantee: validates
|
|
36
|
+
an untrusted draft and, on errors, deterministically normalizes or
|
|
37
|
+
LLM-repairs it so the handshake always returns a contract that passes the
|
|
38
|
+
backstop. Never throws.
|
|
39
|
+
- **`rerankCandidates(...)`** — LLM judge that re-ranks blueprint-match
|
|
40
|
+
retrieval candidates (the semantic-match decision used by
|
|
41
|
+
`decideHandshake`).
|
|
42
|
+
- **`validateContractRedundancy` / `validateContractNovelty`** — advisory
|
|
37
43
|
validators for the actions-vs-context placement rule.
|
|
38
44
|
|
|
39
45
|
```ts
|
|
40
|
-
import {
|
|
46
|
+
import { ensureConformingContract } from "@ggui-ai/negotiator";
|
|
41
47
|
|
|
42
|
-
const result = await
|
|
43
|
-
// result.
|
|
44
|
-
// result.
|
|
48
|
+
const result = await ensureConformingContract({ llm }, { intent, draft });
|
|
49
|
+
// result.origin — "agent" (clean) | "synth" (repaired)
|
|
50
|
+
// result.contract — a DataContract guaranteed to pass the handshake backstop
|
|
45
51
|
```
|
|
46
52
|
|
|
47
53
|
## License
|
|
@@ -3,9 +3,12 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Two detectors live here:
|
|
5
5
|
*
|
|
6
|
-
* - {@link
|
|
7
|
-
* flag over-specified contracts without any runtime dependency.
|
|
8
|
-
*
|
|
6
|
+
* - {@link validateContractRedundancy} — pure redundancy heuristics that
|
|
7
|
+
* flag over-specified contracts without any runtime dependency.
|
|
8
|
+
* (Deliberately NOT named `validateContractStructure` — that name is
|
|
9
|
+
* owned by `@ggui-ai/protocol`'s normative structural validator,
|
|
10
|
+
* which returns `ContractViolation`s; this one returns advisory
|
|
11
|
+
* findings.) The load-bearing finding is `redundant-action`: an empty-payload
|
|
9
12
|
* `actionSpec` entry whose name parses as a mutator of an existing
|
|
10
13
|
* `contextSpec` slot. Real example that motivated this module: a
|
|
11
14
|
* synthesizer emitted both `actionSpec.increment` (empty payload)
|
|
@@ -59,39 +62,40 @@ export interface ContractValidationResult {
|
|
|
59
62
|
}
|
|
60
63
|
/**
|
|
61
64
|
* Dependencies the novelty detector needs. Embedding provider + vector
|
|
62
|
-
* store are the same seams the
|
|
63
|
-
* novelty check operates over the production index without any
|
|
64
|
-
* infrastructure.
|
|
65
|
+
* store are the same seams the handshake's find-similar retrieval uses,
|
|
66
|
+
* so the novelty check operates over the production index without any
|
|
67
|
+
* extra infrastructure.
|
|
65
68
|
*/
|
|
66
69
|
export interface ContractValidationNoveltyDeps {
|
|
67
70
|
readonly embedding: EmbeddingProvider;
|
|
68
71
|
readonly vectorStore: VectorStore;
|
|
69
72
|
/** Tenant / partition the nearest-neighbor query runs against. Same
|
|
70
|
-
* semantics as `
|
|
73
|
+
* semantics as the `scope` argument on `VectorStore.query` — the
|
|
74
|
+
* tenant / index partition, typically `appId`. */
|
|
71
75
|
readonly scope: string;
|
|
72
76
|
}
|
|
73
77
|
export interface ContractValidationNoveltyOptions {
|
|
74
78
|
/**
|
|
75
79
|
* Cosine distance threshold above which the contract is flagged as
|
|
76
|
-
* novel. Distance is `1 - cosine_similarity`. Default `0.8
|
|
77
|
-
*
|
|
78
|
-
*
|
|
79
|
-
*
|
|
80
|
-
* still flag for review.
|
|
80
|
+
* novel. Distance is `1 - cosine_similarity`. Default `0.8`: a
|
|
81
|
+
* contract whose nearest stored neighbor sits beyond distance 0.8
|
|
82
|
+
* is effectively outside retrieval range, with a small buffer below
|
|
83
|
+
* the hard one-tail boundary (distance 0.85) so contracts that
|
|
84
|
+
* hover near retrieval but slightly above still flag for review.
|
|
81
85
|
*/
|
|
82
86
|
readonly thresholdCosine?: number;
|
|
83
87
|
}
|
|
84
88
|
/**
|
|
85
|
-
* Run the synchronous
|
|
89
|
+
* Run the synchronous redundancy detector against `contract`.
|
|
86
90
|
*
|
|
87
|
-
*
|
|
91
|
+
* One finding kind:
|
|
88
92
|
* - `redundant-action`: empty-payload action whose name parses as a
|
|
89
93
|
* mutator of an existing context slot.
|
|
90
94
|
*
|
|
91
|
-
* Returns an empty findings array for contracts that don't trip
|
|
95
|
+
* Returns an empty findings array for contracts that don't trip the
|
|
92
96
|
* heuristic.
|
|
93
97
|
*/
|
|
94
|
-
export declare function
|
|
98
|
+
export declare function validateContractRedundancy(contract: DataContract): ContractValidationResult;
|
|
95
99
|
/**
|
|
96
100
|
* Validate the actions-vs-context placement rule: actions drive agent
|
|
97
101
|
* turns, context observes state. Findings 1-3 are advisory `warn`;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"contract-validators.d.ts","sourceRoot":"","sources":["../src/contract-validators.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"contract-validators.d.ts","sourceRoot":"","sources":["../src/contract-validators.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAc,MAAM,mBAAmB,CAAC;AAElE,OAAO,KAAK,EACV,iBAAiB,EACjB,WAAW,EACZ,MAAM,0BAA0B,CAAC;AAMlC;;;;;;;;;GASG;AACH,MAAM,MAAM,6BAA6B,GACrC,kBAAkB,GAClB,aAAa,GACb,mCAAmC,GACnC,2BAA2B,GAC3B,6BAA6B,GAC7B,4BAA4B,GAC5B,8BAA8B,GAC9B,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;AAElB;;;;;;GAMG;AACH,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,IAAI,EAAE,6BAA6B,CAAC;IAC7C,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC;IACpC,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,QAAQ,EAAE,SAAS,yBAAyB,EAAE,CAAC;CACzD;AAED;;;;;GAKG;AACH,MAAM,WAAW,6BAA6B;IAC5C,QAAQ,CAAC,SAAS,EAAE,iBAAiB,CAAC;IACtC,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAC;IAClC;;sDAEkD;IAClD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,gCAAgC;IAC/C;;;;;;;OAOG;IACH,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;CACnC;AAwJD;;;;;;;;;GASG;AACH,wBAAgB,0BAA0B,CACxC,QAAQ,EAAE,YAAY,GACrB,wBAAwB,CAkC1B;AAsCD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAgB,wBAAwB,CACtC,QAAQ,EAAE,YAAY,GACrB,wBAAwB,CA8D1B;AAiCD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,yBAAyB,CACvC,QAAQ,EAAE,YAAY,EACtB,MAAM,EAAE,MAAM,GACb,wBAAwB,CAoC1B;AAQD;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,uBAAuB,CAC3C,QAAQ,EAAE,YAAY,EACtB,IAAI,EAAE,6BAA6B,EACnC,OAAO,GAAE,gCAAqC,GAC7C,OAAO,CAAC,wBAAwB,CAAC,CAkCnC;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,wBAAwB,GAC/B,MAAM,CAKR"}
|
|
@@ -3,9 +3,12 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Two detectors live here:
|
|
5
5
|
*
|
|
6
|
-
* - {@link
|
|
7
|
-
* flag over-specified contracts without any runtime dependency.
|
|
8
|
-
*
|
|
6
|
+
* - {@link validateContractRedundancy} — pure redundancy heuristics that
|
|
7
|
+
* flag over-specified contracts without any runtime dependency.
|
|
8
|
+
* (Deliberately NOT named `validateContractStructure` — that name is
|
|
9
|
+
* owned by `@ggui-ai/protocol`'s normative structural validator,
|
|
10
|
+
* which returns `ContractViolation`s; this one returns advisory
|
|
11
|
+
* findings.) The load-bearing finding is `redundant-action`: an empty-payload
|
|
9
12
|
* `actionSpec` entry whose name parses as a mutator of an existing
|
|
10
13
|
* `contextSpec` slot. Real example that motivated this module: a
|
|
11
14
|
* synthesizer emitted both `actionSpec.increment` (empty payload)
|
|
@@ -167,19 +170,19 @@ function isEmptyPayloadSchema(schema) {
|
|
|
167
170
|
return Object.keys(schema.properties).length === 0;
|
|
168
171
|
}
|
|
169
172
|
// =============================================================================
|
|
170
|
-
//
|
|
173
|
+
// Redundancy validator (synchronous, dependency-free)
|
|
171
174
|
// =============================================================================
|
|
172
175
|
/**
|
|
173
|
-
* Run the synchronous
|
|
176
|
+
* Run the synchronous redundancy detector against `contract`.
|
|
174
177
|
*
|
|
175
|
-
*
|
|
178
|
+
* One finding kind:
|
|
176
179
|
* - `redundant-action`: empty-payload action whose name parses as a
|
|
177
180
|
* mutator of an existing context slot.
|
|
178
181
|
*
|
|
179
|
-
* Returns an empty findings array for contracts that don't trip
|
|
182
|
+
* Returns an empty findings array for contracts that don't trip the
|
|
180
183
|
* heuristic.
|
|
181
184
|
*/
|
|
182
|
-
export function
|
|
185
|
+
export function validateContractRedundancy(contract) {
|
|
183
186
|
const findings = [];
|
|
184
187
|
const actionSpec = contract.actionSpec;
|
|
185
188
|
const contextSpec = contract.contextSpec;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `ensureConformingContract` — the negotiator's create-path guarantee.
|
|
3
|
+
*
|
|
4
|
+
* Given the agent's PROPOSED draft, return a contract that is
|
|
5
|
+
* GUARANTEED to pass the deterministic gate (`lintContract` with zero
|
|
6
|
+
* errors), so the handshake backstop (`validateContract`) never throws
|
|
7
|
+
* on it. This is the "Propose vs Commit" forgiving-handshake core
|
|
8
|
+
* shared by every negotiator implementation (OSS llm-backed + cloud
|
|
9
|
+
* bedrock) so the behavior cannot drift between deployments:
|
|
10
|
+
*
|
|
11
|
+
* - draft already conforms → return it verbatim (origin: 'agent')
|
|
12
|
+
* - draft has errors → repair-in-place via the bounded LLM loop,
|
|
13
|
+
* seeded with the draft + the deterministic
|
|
14
|
+
* findings, looping until the gate is green
|
|
15
|
+
* (origin: 'synth')
|
|
16
|
+
* - repair impossible → minimal conforming contract (`{}`) + loud
|
|
17
|
+
* (LLM down / provider error findings; STILL origin 'synth';
|
|
18
|
+
* can't synth / budget NEVER throws.
|
|
19
|
+
* exhausted)
|
|
20
|
+
*
|
|
21
|
+
* Determinism lives in the GATE (`lintContract`), never in the repair.
|
|
22
|
+
* The repair LLM is non-deterministic, but the loop only exits when the
|
|
23
|
+
* deterministic gate is green — the same shape ui-gen uses to tolerate
|
|
24
|
+
* non-deterministic code generation behind a deterministic self_check.
|
|
25
|
+
*
|
|
26
|
+
* Cache/blueprint matching is NOT this function's job — the caller
|
|
27
|
+
* (negotiator `decide()`) runs its deployment-specific cache match
|
|
28
|
+
* FIRST and only falls through to here on a miss. That preserves the
|
|
29
|
+
* "cache-first, repair-second" ordering the negotiator contract
|
|
30
|
+
* mandates.
|
|
31
|
+
*/
|
|
32
|
+
import { type DataContract, type GadgetDescriptor, type SuggestionFinding } from '@ggui-ai/protocol';
|
|
33
|
+
import type { LLMCaller } from './llm-caller.js';
|
|
34
|
+
export interface EnsureConformingResult {
|
|
35
|
+
/** A contract guaranteed to pass `lintContract` with zero errors. */
|
|
36
|
+
readonly contract: DataContract;
|
|
37
|
+
/**
|
|
38
|
+
* - `'agent'` — the draft was already conforming; returned verbatim.
|
|
39
|
+
* - `'synth'` — the draft had errors; this is the repaired result
|
|
40
|
+
* (or the minimal-conforming fallback when repair was impossible).
|
|
41
|
+
*/
|
|
42
|
+
readonly origin: 'agent' | 'synth';
|
|
43
|
+
/**
|
|
44
|
+
* How the conforming contract was produced — finer-grained than
|
|
45
|
+
* `origin`, for telemetry (the efficiency tiers):
|
|
46
|
+
* - `verbatim` — draft was clean; returned as-is (origin agent).
|
|
47
|
+
* - `normalized` — deterministic fix only, NO LLM (origin synth).
|
|
48
|
+
* - `llm-repair` — the bounded LLM repair loop ran (origin synth).
|
|
49
|
+
* - `fallback-empty`— unrepairable; minimal `{}` contract (origin synth).
|
|
50
|
+
*/
|
|
51
|
+
readonly method: 'verbatim' | 'normalized' | 'llm-repair' | 'fallback-empty';
|
|
52
|
+
/**
|
|
53
|
+
* Findings surfaced to the agent. On `origin: 'agent'`, any hygiene
|
|
54
|
+
* warnings on the (valid) draft. On `origin: 'synth'`, the ERROR
|
|
55
|
+
* findings that rejected the agent's draft — so the agent-side model
|
|
56
|
+
* learns what it got wrong, even though we repaired it.
|
|
57
|
+
*/
|
|
58
|
+
readonly findings: readonly SuggestionFinding[];
|
|
59
|
+
/** Operator- + LLM-readable explanation. */
|
|
60
|
+
readonly reasoning: string;
|
|
61
|
+
}
|
|
62
|
+
export declare function ensureConformingContract(deps: {
|
|
63
|
+
readonly llm: LLMCaller;
|
|
64
|
+
}, args: {
|
|
65
|
+
/** Untrusted: the agent's draft may not be a valid DataContract. */
|
|
66
|
+
readonly draft: unknown;
|
|
67
|
+
readonly intent: string;
|
|
68
|
+
readonly appGadgets?: readonly GadgetDescriptor[];
|
|
69
|
+
}): Promise<EnsureConformingResult>;
|
|
70
|
+
//# sourceMappingURL=ensure-conforming-contract.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ensure-conforming-contract.d.ts","sourceRoot":"","sources":["../src/ensure-conforming-contract.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,OAAO,EAGL,KAAK,YAAY,EACjB,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,EACvB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAIjD,MAAM,WAAW,sBAAsB;IACrC,qEAAqE;IACrE,QAAQ,CAAC,QAAQ,EAAE,YAAY,CAAC;IAChC;;;;OAIG;IACH,QAAQ,CAAC,MAAM,EAAE,OAAO,GAAG,OAAO,CAAC;IACnC;;;;;;;OAOG;IACH,QAAQ,CAAC,MAAM,EAAE,UAAU,GAAG,YAAY,GAAG,YAAY,GAAG,gBAAgB,CAAC;IAC7E;;;;;OAKG;IACH,QAAQ,CAAC,QAAQ,EAAE,SAAS,iBAAiB,EAAE,CAAC;IAChD,4CAA4C;IAC5C,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAKD,wBAAsB,wBAAwB,CAC5C,IAAI,EAAE;IAAE,QAAQ,CAAC,GAAG,EAAE,SAAS,CAAA;CAAE,EACjC,IAAI,EAAE;IACJ,oEAAoE;IACpE,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,UAAU,CAAC,EAAE,SAAS,gBAAgB,EAAE,CAAC;CACnD,GACA,OAAO,CAAC,sBAAsB,CAAC,CA4FjC"}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `ensureConformingContract` — the negotiator's create-path guarantee.
|
|
3
|
+
*
|
|
4
|
+
* Given the agent's PROPOSED draft, return a contract that is
|
|
5
|
+
* GUARANTEED to pass the deterministic gate (`lintContract` with zero
|
|
6
|
+
* errors), so the handshake backstop (`validateContract`) never throws
|
|
7
|
+
* on it. This is the "Propose vs Commit" forgiving-handshake core
|
|
8
|
+
* shared by every negotiator implementation (OSS llm-backed + cloud
|
|
9
|
+
* bedrock) so the behavior cannot drift between deployments:
|
|
10
|
+
*
|
|
11
|
+
* - draft already conforms → return it verbatim (origin: 'agent')
|
|
12
|
+
* - draft has errors → repair-in-place via the bounded LLM loop,
|
|
13
|
+
* seeded with the draft + the deterministic
|
|
14
|
+
* findings, looping until the gate is green
|
|
15
|
+
* (origin: 'synth')
|
|
16
|
+
* - repair impossible → minimal conforming contract (`{}`) + loud
|
|
17
|
+
* (LLM down / provider error findings; STILL origin 'synth';
|
|
18
|
+
* can't synth / budget NEVER throws.
|
|
19
|
+
* exhausted)
|
|
20
|
+
*
|
|
21
|
+
* Determinism lives in the GATE (`lintContract`), never in the repair.
|
|
22
|
+
* The repair LLM is non-deterministic, but the loop only exits when the
|
|
23
|
+
* deterministic gate is green — the same shape ui-gen uses to tolerate
|
|
24
|
+
* non-deterministic code generation behind a deterministic self_check.
|
|
25
|
+
*
|
|
26
|
+
* Cache/blueprint matching is NOT this function's job — the caller
|
|
27
|
+
* (negotiator `decide()`) runs its deployment-specific cache match
|
|
28
|
+
* FIRST and only falls through to here on a miss. That preserves the
|
|
29
|
+
* "cache-first, repair-second" ordering the negotiator contract
|
|
30
|
+
* mandates.
|
|
31
|
+
*/
|
|
32
|
+
import { lintContract, dataContractSchema, } from '@ggui-ai/protocol';
|
|
33
|
+
import { synthesizeContract } from './synthesize-contract.js';
|
|
34
|
+
import { normalizeDraft } from './normalize-draft.js';
|
|
35
|
+
/** Trivially-valid last-resort contract — all four specs omitted. */
|
|
36
|
+
const EMPTY_CONTRACT = {};
|
|
37
|
+
export async function ensureConformingContract(deps, args) {
|
|
38
|
+
const lint = lintContract(args.draft);
|
|
39
|
+
const warnFindings = lint.warnings.map((w) => ({
|
|
40
|
+
code: w.code,
|
|
41
|
+
severity: 'warn',
|
|
42
|
+
path: w.path,
|
|
43
|
+
message: w.message,
|
|
44
|
+
}));
|
|
45
|
+
// Fast path — draft already conforms. Deterministic, no LLM call.
|
|
46
|
+
// `lint.errors.length === 0` implies the shape phase passed, so the
|
|
47
|
+
// strict parse cannot throw — it just re-derives the typed DataContract
|
|
48
|
+
// from the untrusted input (validator returns the typed shape; no cast).
|
|
49
|
+
if (lint.errors.length === 0) {
|
|
50
|
+
return {
|
|
51
|
+
contract: dataContractSchema.parse(args.draft),
|
|
52
|
+
origin: 'agent',
|
|
53
|
+
method: 'verbatim',
|
|
54
|
+
findings: warnFindings,
|
|
55
|
+
reasoning: 'agent draft passed validateContract; accepted verbatim (origin: agent)',
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
const errorFindings = lint.errors.map((e) => ({
|
|
59
|
+
code: e.code,
|
|
60
|
+
severity: 'error',
|
|
61
|
+
path: e.path,
|
|
62
|
+
message: e.message,
|
|
63
|
+
}));
|
|
64
|
+
// L3 — deterministic normalization tier. Most agent malformations are
|
|
65
|
+
// mechanical (stray illegal wrapper keys, non-canonical schema types).
|
|
66
|
+
// Fix them WITHOUT an LLM: strip + canonicalize, re-lint, and if the
|
|
67
|
+
// draft now conforms, return it verbatim-but-cleaned. Faithful (no
|
|
68
|
+
// reshape risk — the agent's specs are preserved exactly) and free (no
|
|
69
|
+
// LLM call). Semantic deficiencies fall through to the repair loop.
|
|
70
|
+
const normalized = normalizeDraft(args.draft);
|
|
71
|
+
const normLint = lintContract(normalized);
|
|
72
|
+
if (normLint.errors.length === 0) {
|
|
73
|
+
return {
|
|
74
|
+
contract: dataContractSchema.parse(normalized),
|
|
75
|
+
origin: 'synth',
|
|
76
|
+
method: 'normalized',
|
|
77
|
+
findings: errorFindings,
|
|
78
|
+
reasoning: 'normalized the agent draft deterministically (stripped invalid keys / canonicalized schema types, no LLM) to pass validateContract',
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
// Repair loop on the NORMALIZED draft (mechanical errors already
|
|
82
|
+
// fixed) with only the REMAINING (semantic) findings — so the LLM
|
|
83
|
+
// patches what reasoning is genuinely needed for, from a clean start.
|
|
84
|
+
const synth = await synthesizeContract(deps, args.intent, {
|
|
85
|
+
...(args.appGadgets ? { appGadgets: args.appGadgets } : {}),
|
|
86
|
+
draft: normalized,
|
|
87
|
+
draftFindings: normLint.errors.map((e) => ({
|
|
88
|
+
code: e.code,
|
|
89
|
+
path: e.path,
|
|
90
|
+
message: e.message,
|
|
91
|
+
})),
|
|
92
|
+
});
|
|
93
|
+
if (synth.contract !== null &&
|
|
94
|
+
lintContract(synth.contract).errors.length === 0) {
|
|
95
|
+
return {
|
|
96
|
+
contract: synth.contract,
|
|
97
|
+
origin: 'synth',
|
|
98
|
+
method: 'llm-repair',
|
|
99
|
+
findings: errorFindings,
|
|
100
|
+
reasoning: `repaired the agent draft to pass validateContract — ${synth.reason}`,
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
// Repair impossible (LLM down, provider can't synthesize, or the
|
|
104
|
+
// repair budget exhausted). We still MUST return a conforming
|
|
105
|
+
// contract — the handshake never hard-fails. Minimal conforming
|
|
106
|
+
// contract + loud findings so the agent can re-issue a corrected
|
|
107
|
+
// contract via ggui_render override if it needs the declared specs.
|
|
108
|
+
return {
|
|
109
|
+
contract: EMPTY_CONTRACT,
|
|
110
|
+
origin: 'synth',
|
|
111
|
+
method: 'fallback-empty',
|
|
112
|
+
findings: errorFindings,
|
|
113
|
+
reasoning: `could not repair the agent draft within budget (${synth.reason}); returning a minimal conforming contract — re-issue a corrected contract via ggui_render override if you need the declared specs`,
|
|
114
|
+
};
|
|
115
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,36 +1,38 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @ggui-ai/negotiator — open-source
|
|
2
|
+
* @ggui-ai/negotiator — open-source contract-synthesis + match-judge
|
|
3
|
+
* engine for ggui's handshake.
|
|
3
4
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
5
|
+
* Given an agent's draft contract + intent, this package:
|
|
6
|
+
* - synthesizes / repairs a conforming `DataContract`
|
|
7
|
+
* (`synthesizeContract`, `ensureConformingContract`) so the
|
|
8
|
+
* handshake always returns a valid contract;
|
|
9
|
+
* - judges blueprint-match candidates for reuse (`rerankCandidates`);
|
|
10
|
+
* - validates contract structure + novelty (`contract-validators`);
|
|
11
|
+
* - hashes contracts into identity + variant keys (`hashContract`,
|
|
12
|
+
* `buildVariant`) and normalizes untrusted drafts (`normalizeDraft`).
|
|
13
|
+
*
|
|
14
|
+
* The HANDSHAKE DECISION itself (find-similar → reuse vs synth-create)
|
|
15
|
+
* lives in the shared `decideHandshake` core in
|
|
16
|
+
* `@ggui-ai/mcp-server-handlers`, which composes these primitives; the
|
|
17
|
+
* former in-package `negotiate()` RAG+decision pipeline was retired in
|
|
18
|
+
* favor of that unified, adapter-injected core.
|
|
6
19
|
*
|
|
7
20
|
* Composes the storage seams defined in `@ggui-ai/mcp-server-core`
|
|
8
|
-
* (`EmbeddingProvider`, `VectorStore
|
|
9
|
-
*
|
|
10
|
-
* managed embedding service or vector store) live behind those seams
|
|
11
|
-
* so this package stays deployment-agnostic.
|
|
21
|
+
* (`EmbeddingProvider`, `VectorStore`) so this package stays
|
|
22
|
+
* deployment-agnostic.
|
|
12
23
|
*
|
|
13
24
|
* This barrel stays narrow — it exports only the minimum surface
|
|
14
25
|
* consumers need. Each additive export carries semver weight.
|
|
15
26
|
*/
|
|
16
27
|
export { hashContract, buildVariant } from './contract-hash.js';
|
|
17
|
-
export { computeIntentId, shouldSuppressSuggestion } from './intent.js';
|
|
18
|
-
export { detectDataPatterns, buildSuggestion } from './suggestion.js';
|
|
19
|
-
export type { NegotiatorSuggestion } from './suggestion.js';
|
|
20
|
-
export { inferInteractionMode, inferJsonSchemaType } from './pure.js';
|
|
21
|
-
export { ragSearch } from './rag-search.js';
|
|
22
|
-
export type { RagSearchDeps, RagSearchInput, RagSearchResult, } from './rag-search.js';
|
|
23
|
-
export type { NegotiatorOption } from './types.js';
|
|
24
28
|
export type { LLMCaller, LLMCallerConfig, ToolSchema } from './llm-caller.js';
|
|
25
|
-
export type { RenderState, RenderEntry } from './render.js';
|
|
26
|
-
export type { NegotiatorDecisionInput } from './decision-input.js';
|
|
27
|
-
export { DECISION_SYSTEM_PROMPT, buildDecisionUserMessage, makeDecision, } from './decision.js';
|
|
28
|
-
export { negotiate } from './negotiate.js';
|
|
29
|
-
export type { NegotiateDeps, NegotiateInput, NegotiateConfig, NegotiateResult, } from './negotiate.js';
|
|
30
29
|
export { rerankCandidates } from './llm-rerank.js';
|
|
31
30
|
export type { RerankCandidate, RerankDecision, RerankQuery, } from './llm-rerank.js';
|
|
32
31
|
export { synthesizeContract } from './synthesize-contract.js';
|
|
33
32
|
export type { SynthesizeContractResult } from './synthesize-contract.js';
|
|
34
|
-
export {
|
|
33
|
+
export { ensureConformingContract } from './ensure-conforming-contract.js';
|
|
34
|
+
export type { EnsureConformingResult } from './ensure-conforming-contract.js';
|
|
35
|
+
export { normalizeDraft } from './normalize-draft.js';
|
|
36
|
+
export { validateContractRedundancy, validateContractNovelty, formatValidationFindings, } from './contract-validators.js';
|
|
35
37
|
export type { ContractValidationFinding, ContractValidationFindingKind, ContractValidationResult, ContractValidationNoveltyDeps, ContractValidationNoveltyOptions, } from './contract-validators.js';
|
|
36
38
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAChE,YAAY,EAAE,SAAS,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC9E,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,YAAY,EACV,eAAe,EACf,cAAc,EACd,WAAW,GACZ,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAC9D,YAAY,EAAE,wBAAwB,EAAE,MAAM,0BAA0B,CAAC;AACzE,OAAO,EAAE,wBAAwB,EAAE,MAAM,iCAAiC,CAAC;AAC3E,YAAY,EAAE,sBAAsB,EAAE,MAAM,iCAAiC,CAAC;AAC9E,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EACL,0BAA0B,EAC1B,uBAAuB,EACvB,wBAAwB,GACzB,MAAM,0BAA0B,CAAC;AAClC,YAAY,EACV,yBAAyB,EACzB,6BAA6B,EAC7B,wBAAwB,EACxB,6BAA6B,EAC7B,gCAAgC,GACjC,MAAM,0BAA0B,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,25 +1,32 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @ggui-ai/negotiator — open-source
|
|
2
|
+
* @ggui-ai/negotiator — open-source contract-synthesis + match-judge
|
|
3
|
+
* engine for ggui's handshake.
|
|
3
4
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
5
|
+
* Given an agent's draft contract + intent, this package:
|
|
6
|
+
* - synthesizes / repairs a conforming `DataContract`
|
|
7
|
+
* (`synthesizeContract`, `ensureConformingContract`) so the
|
|
8
|
+
* handshake always returns a valid contract;
|
|
9
|
+
* - judges blueprint-match candidates for reuse (`rerankCandidates`);
|
|
10
|
+
* - validates contract structure + novelty (`contract-validators`);
|
|
11
|
+
* - hashes contracts into identity + variant keys (`hashContract`,
|
|
12
|
+
* `buildVariant`) and normalizes untrusted drafts (`normalizeDraft`).
|
|
13
|
+
*
|
|
14
|
+
* The HANDSHAKE DECISION itself (find-similar → reuse vs synth-create)
|
|
15
|
+
* lives in the shared `decideHandshake` core in
|
|
16
|
+
* `@ggui-ai/mcp-server-handlers`, which composes these primitives; the
|
|
17
|
+
* former in-package `negotiate()` RAG+decision pipeline was retired in
|
|
18
|
+
* favor of that unified, adapter-injected core.
|
|
6
19
|
*
|
|
7
20
|
* Composes the storage seams defined in `@ggui-ai/mcp-server-core`
|
|
8
|
-
* (`EmbeddingProvider`, `VectorStore
|
|
9
|
-
*
|
|
10
|
-
* managed embedding service or vector store) live behind those seams
|
|
11
|
-
* so this package stays deployment-agnostic.
|
|
21
|
+
* (`EmbeddingProvider`, `VectorStore`) so this package stays
|
|
22
|
+
* deployment-agnostic.
|
|
12
23
|
*
|
|
13
24
|
* This barrel stays narrow — it exports only the minimum surface
|
|
14
25
|
* consumers need. Each additive export carries semver weight.
|
|
15
26
|
*/
|
|
16
27
|
export { hashContract, buildVariant } from './contract-hash.js';
|
|
17
|
-
export { computeIntentId, shouldSuppressSuggestion } from './intent.js';
|
|
18
|
-
export { detectDataPatterns, buildSuggestion } from './suggestion.js';
|
|
19
|
-
export { inferInteractionMode, inferJsonSchemaType } from './pure.js';
|
|
20
|
-
export { ragSearch } from './rag-search.js';
|
|
21
|
-
export { DECISION_SYSTEM_PROMPT, buildDecisionUserMessage, makeDecision, } from './decision.js';
|
|
22
|
-
export { negotiate } from './negotiate.js';
|
|
23
28
|
export { rerankCandidates } from './llm-rerank.js';
|
|
24
29
|
export { synthesizeContract } from './synthesize-contract.js';
|
|
25
|
-
export {
|
|
30
|
+
export { ensureConformingContract } from './ensure-conforming-contract.js';
|
|
31
|
+
export { normalizeDraft } from './normalize-draft.js';
|
|
32
|
+
export { validateContractRedundancy, validateContractNovelty, formatValidationFindings, } from './contract-validators.js';
|
package/dist/llm-caller.d.ts
CHANGED
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* `LLMCaller` — the
|
|
2
|
+
* `LLMCaller` — the negotiator's LLM dispatcher.
|
|
3
3
|
*
|
|
4
4
|
* Narrow abstraction over "call a chat model, optionally with a forced
|
|
5
5
|
* tool-use schema for guaranteed-JSON structured output." Kept public
|
|
6
6
|
* so OSS consumers of `@ggui-ai/negotiator` can bring their own LLM
|
|
7
7
|
* provider (Anthropic direct, OpenAI, Google, a local model, a
|
|
8
|
-
* community LiteLLM wrapper) without touching the
|
|
8
|
+
* community LiteLLM wrapper) without touching the synthesis / judge
|
|
9
9
|
* source.
|
|
10
10
|
*
|
|
11
11
|
* **Why this lives in `@ggui-ai/negotiator`, not
|
|
12
12
|
* `@ggui-ai/mcp-server-core`.** `mcp-server-core` contains the
|
|
13
13
|
* storage + runtime seams an MCP server implementer binds against
|
|
14
14
|
* (`VectorStore`, `EmbeddingProvider`, `KeyValueStore`,
|
|
15
|
-
* `BlueprintProvider
|
|
16
|
-
*
|
|
17
|
-
* lifting it to `mcp-server-core` would grow the
|
|
18
|
-
* speculatively. If a second consumer outside the
|
|
19
|
-
* surfaces later, the "where does `LLMCaller` live?"
|
|
20
|
-
* re-opened at that point.
|
|
15
|
+
* `BlueprintProvider`). `LLMCaller` is an engine-internal
|
|
16
|
+
* dispatcher — one level below the synthesis + judge primitives this
|
|
17
|
+
* package exports — so lifting it to `mcp-server-core` would grow the
|
|
18
|
+
* public seam count speculatively. If a second consumer outside the
|
|
19
|
+
* negotiator surfaces later, the "where does `LLMCaller` live?"
|
|
20
|
+
* question can be re-opened at that point.
|
|
21
21
|
*
|
|
22
22
|
* Normative semantics:
|
|
23
23
|
* - `call(systemPrompt, userMessage, maxTokens?)` returns the raw
|
|
@@ -41,7 +41,7 @@ export interface ToolSchema {
|
|
|
41
41
|
description: string;
|
|
42
42
|
input_schema: Record<string, unknown>;
|
|
43
43
|
}
|
|
44
|
-
/** Chat-model dispatcher consumed by the negotiator
|
|
44
|
+
/** Chat-model dispatcher consumed by the negotiator's synthesis + judge primitives. */
|
|
45
45
|
export interface LLMCaller {
|
|
46
46
|
/**
|
|
47
47
|
* Call the model in plain-text mode. `maxTokens` defaults to
|
package/dist/llm-caller.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"llm-caller.d.ts","sourceRoot":"","sources":["../src/llm-caller.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AAEH,6DAA6D;AAC7D,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACvC;AAED,
|
|
1
|
+
{"version":3,"file":"llm-caller.d.ts","sourceRoot":"","sources":["../src/llm-caller.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AAEH,6DAA6D;AAC7D,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACvC;AAED,uFAAuF;AACvF,MAAM,WAAW,SAAS;IACxB;;;OAGG;IACH,IAAI,CACF,YAAY,EAAE,MAAM,EACpB,WAAW,EAAE,MAAM,EACnB,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,MAAM,CAAC,CAAC;IAEnB;;;;;OAKG;IACH,cAAc,CAAC,CAAC,CAAC,EACf,YAAY,EAAE,MAAM,EACpB,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE,UAAU,EAChB,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,CAAC,CAAC,CAAC;CACf;AAED;;;;;GAKG;AACH,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,WAAW,GAAG,QAAQ,GAAG,QAAQ,GAAG,YAAY,GAAG,SAAS,CAAC;IACvE,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB"}
|
package/dist/llm-caller.js
CHANGED
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* `LLMCaller` — the
|
|
2
|
+
* `LLMCaller` — the negotiator's LLM dispatcher.
|
|
3
3
|
*
|
|
4
4
|
* Narrow abstraction over "call a chat model, optionally with a forced
|
|
5
5
|
* tool-use schema for guaranteed-JSON structured output." Kept public
|
|
6
6
|
* so OSS consumers of `@ggui-ai/negotiator` can bring their own LLM
|
|
7
7
|
* provider (Anthropic direct, OpenAI, Google, a local model, a
|
|
8
|
-
* community LiteLLM wrapper) without touching the
|
|
8
|
+
* community LiteLLM wrapper) without touching the synthesis / judge
|
|
9
9
|
* source.
|
|
10
10
|
*
|
|
11
11
|
* **Why this lives in `@ggui-ai/negotiator`, not
|
|
12
12
|
* `@ggui-ai/mcp-server-core`.** `mcp-server-core` contains the
|
|
13
13
|
* storage + runtime seams an MCP server implementer binds against
|
|
14
14
|
* (`VectorStore`, `EmbeddingProvider`, `KeyValueStore`,
|
|
15
|
-
* `BlueprintProvider
|
|
16
|
-
*
|
|
17
|
-
* lifting it to `mcp-server-core` would grow the
|
|
18
|
-
* speculatively. If a second consumer outside the
|
|
19
|
-
* surfaces later, the "where does `LLMCaller` live?"
|
|
20
|
-
* re-opened at that point.
|
|
15
|
+
* `BlueprintProvider`). `LLMCaller` is an engine-internal
|
|
16
|
+
* dispatcher — one level below the synthesis + judge primitives this
|
|
17
|
+
* package exports — so lifting it to `mcp-server-core` would grow the
|
|
18
|
+
* public seam count speculatively. If a second consumer outside the
|
|
19
|
+
* negotiator surfaces later, the "where does `LLMCaller` live?"
|
|
20
|
+
* question can be re-opened at that point.
|
|
21
21
|
*
|
|
22
22
|
* Normative semantics:
|
|
23
23
|
* - `call(systemPrompt, userMessage, maxTokens?)` returns the raw
|
package/dist/llm-rerank.d.ts
CHANGED
|
@@ -12,7 +12,6 @@
|
|
|
12
12
|
* judge restores precision. Combined break-even hit rate is ~10%;
|
|
13
13
|
* realistic workloads observe 30-70%.
|
|
14
14
|
*/
|
|
15
|
-
import { summarizeContract } from '@ggui-ai/protocol';
|
|
16
15
|
import type { LLMCaller, ToolSchema } from './llm-caller.js';
|
|
17
16
|
/**
|
|
18
17
|
* One candidate blueprint for the LLM judge to consider.
|
|
@@ -28,7 +27,7 @@ export interface RerankCandidate {
|
|
|
28
27
|
readonly cachedIntent: string;
|
|
29
28
|
/**
|
|
30
29
|
* One-line summary of the blueprint's contract surface. Format
|
|
31
|
-
* matches `summarizeContract()`
|
|
30
|
+
* matches `@ggui-ai/protocol`'s `summarizeContract()` — `slots=...; actions=...;
|
|
32
31
|
* streams=...; props=...` so the judge sees the structural shape
|
|
33
32
|
* without the JSON noise.
|
|
34
33
|
*/
|
|
@@ -49,10 +48,13 @@ export interface RerankDecision {
|
|
|
49
48
|
*/
|
|
50
49
|
readonly matchId: string | null;
|
|
51
50
|
/**
|
|
52
|
-
* Confidence on `[0, 1]
|
|
53
|
-
*
|
|
54
|
-
*
|
|
55
|
-
*
|
|
51
|
+
* Confidence on `[0, 1]` — how strongly the matched candidate is in
|
|
52
|
+
* the same task-and-shape family as the request, NOT how completely
|
|
53
|
+
* its fields cover the request. Field/slot/action deltas are
|
|
54
|
+
* reconciled and reported to the agent separately; they never lower
|
|
55
|
+
* this score. Caller compares against a threshold (e.g. 0.6) before
|
|
56
|
+
* treating the decision as a hit. Returned even when matchId is null
|
|
57
|
+
* so callers can log "judge declined with confidence X."
|
|
56
58
|
*/
|
|
57
59
|
readonly confidence: number;
|
|
58
60
|
/**
|
|
@@ -79,9 +81,8 @@ export interface RerankQuery {
|
|
|
79
81
|
readonly intent: string;
|
|
80
82
|
readonly contractSummary: string;
|
|
81
83
|
}
|
|
82
|
-
declare const RERANK_SYSTEM_PROMPT = "You match user UI requests against previously-generated UI blueprints. Each blueprint was produced for a past request and stored. Decide whether any candidate
|
|
84
|
+
declare const RERANK_SYSTEM_PROMPT = "You match user UI requests against previously-generated UI blueprints. Each blueprint was produced for a past request and stored. Decide whether any candidate belongs to the SAME FAMILY as the current request \u2014 i.e. it would serve as a reasonable starting point that the requester can refine, not a pixel-exact replica.\n\nMATCH means the candidate is the same intended user task AND the same broad UI shape (component types, layout pattern). A candidate still MATCHES when the current request adds or omits fields, slots, or actions relative to the cached blueprint \u2014 a superset, a subset, or an overlapping wire surface all still match. Added or omitted fields/slots/actions DO NOT block a match and are NOT yours to judge: those wire-surface deltas are reconciled and reported to the agent separately, after you decide. Judge similarity of task and shape, never coverage of fields.\n\nNO-MATCH means the candidate is a fundamentally different thing \u2014 a different intended task (haiku composer vs tweet draft, login vs signup), a different UI shape (form vs list vs dashboard), OR a conflicting load-bearing fixed VALUE baked into the blueprint (calendar pinned to Jan vs a request for Mar \u2014 same contract shape, but the fixed value conflicts). Reserve NO-MATCH for these; do not decline a candidate merely because its fields, slots, or actions differ from the request.\n\nVisual style differences alone (minimal vs ornate, dense vs spacious) DO NOT block a match \u2014 the user can refine those after they get a working UI.\n\nOutput exactly ONE tool call with your decision. confidence is a number in [0, 1] measuring how strongly the candidate is in the same task-and-shape family as the request (not how completely its fields cover the request). matchId is a string from the candidate ids, or null when no candidate matches. reason is a short sentence the operator can use to debug.";
|
|
83
85
|
declare const RERANK_TOOL: ToolSchema;
|
|
84
|
-
export { summarizeContract };
|
|
85
86
|
/**
|
|
86
87
|
* Run the rerank judge against a query + candidate list.
|
|
87
88
|
*
|