@ggui-ai/negotiator 0.1.0-rc.1

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.
Files changed (91) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +49 -0
  3. package/dist/contract-hash.d.ts +54 -0
  4. package/dist/contract-hash.d.ts.map +1 -0
  5. package/dist/contract-hash.js +96 -0
  6. package/dist/contract-validators.d.ts +171 -0
  7. package/dist/contract-validators.d.ts.map +1 -0
  8. package/dist/contract-validators.js +478 -0
  9. package/dist/decision-input.d.ts +48 -0
  10. package/dist/decision-input.d.ts.map +1 -0
  11. package/dist/decision-input.js +14 -0
  12. package/dist/decision.d.ts +54 -0
  13. package/dist/decision.d.ts.map +1 -0
  14. package/dist/decision.js +500 -0
  15. package/dist/index.d.ts +36 -0
  16. package/dist/index.d.ts.map +1 -0
  17. package/dist/index.js +25 -0
  18. package/dist/intent.d.ts +22 -0
  19. package/dist/intent.d.ts.map +1 -0
  20. package/dist/intent.js +28 -0
  21. package/dist/llm-caller.d.ts +70 -0
  22. package/dist/llm-caller.d.ts.map +1 -0
  23. package/dist/llm-caller.js +38 -0
  24. package/dist/llm-rerank.d.ts +101 -0
  25. package/dist/llm-rerank.d.ts.map +1 -0
  26. package/dist/llm-rerank.js +178 -0
  27. package/dist/negotiate.d.ts +141 -0
  28. package/dist/negotiate.d.ts.map +1 -0
  29. package/dist/negotiate.js +161 -0
  30. package/dist/normalize-schema.d.ts +22 -0
  31. package/dist/normalize-schema.d.ts.map +1 -0
  32. package/dist/normalize-schema.js +191 -0
  33. package/dist/pure.d.ts +30 -0
  34. package/dist/pure.d.ts.map +1 -0
  35. package/dist/pure.js +43 -0
  36. package/dist/rag-search.d.ts +73 -0
  37. package/dist/rag-search.d.ts.map +1 -0
  38. package/dist/rag-search.js +192 -0
  39. package/dist/rerank-eval/pairs.d.ts +28 -0
  40. package/dist/rerank-eval/pairs.d.ts.map +1 -0
  41. package/dist/rerank-eval/pairs.js +531 -0
  42. package/dist/rerank-eval/run-probe-cli.d.ts +3 -0
  43. package/dist/rerank-eval/run-probe-cli.d.ts.map +1 -0
  44. package/dist/rerank-eval/run-probe-cli.js +146 -0
  45. package/dist/rerank-eval/run-probe.d.ts +68 -0
  46. package/dist/rerank-eval/run-probe.d.ts.map +1 -0
  47. package/dist/rerank-eval/run-probe.js +113 -0
  48. package/dist/session.d.ts +42 -0
  49. package/dist/session.d.ts.map +1 -0
  50. package/dist/session.js +21 -0
  51. package/dist/suggestion.d.ts +38 -0
  52. package/dist/suggestion.d.ts.map +1 -0
  53. package/dist/suggestion.js +47 -0
  54. package/dist/synth-bench/corpus.d.ts +106 -0
  55. package/dist/synth-bench/corpus.d.ts.map +1 -0
  56. package/dist/synth-bench/corpus.js +994 -0
  57. package/dist/synth-bench/run-bench-cli.d.ts +3 -0
  58. package/dist/synth-bench/run-bench-cli.d.ts.map +1 -0
  59. package/dist/synth-bench/run-bench-cli.js +181 -0
  60. package/dist/synth-bench/run-bench.d.ts +101 -0
  61. package/dist/synth-bench/run-bench.d.ts.map +1 -0
  62. package/dist/synth-bench/run-bench.js +374 -0
  63. package/dist/synthesize-contract.d.ts +131 -0
  64. package/dist/synthesize-contract.d.ts.map +1 -0
  65. package/dist/synthesize-contract.js +948 -0
  66. package/dist/types.d.ts +30 -0
  67. package/dist/types.d.ts.map +1 -0
  68. package/dist/types.js +13 -0
  69. package/package.json +74 -0
  70. package/src/contract-hash.ts +102 -0
  71. package/src/contract-validators.ts +604 -0
  72. package/src/decision-input.ts +49 -0
  73. package/src/decision.ts +581 -0
  74. package/src/index.ts +63 -0
  75. package/src/intent.ts +37 -0
  76. package/src/llm-caller.ts +82 -0
  77. package/src/llm-rerank.ts +280 -0
  78. package/src/negotiate.ts +312 -0
  79. package/src/normalize-schema.ts +193 -0
  80. package/src/pure.ts +46 -0
  81. package/src/rag-search.ts +274 -0
  82. package/src/rerank-eval/pairs.ts +624 -0
  83. package/src/rerank-eval/run-probe-cli.ts +197 -0
  84. package/src/rerank-eval/run-probe.ts +198 -0
  85. package/src/session.ts +41 -0
  86. package/src/suggestion.ts +73 -0
  87. package/src/synth-bench/corpus.ts +1126 -0
  88. package/src/synth-bench/run-bench-cli.ts +237 -0
  89. package/src/synth-bench/run-bench.ts +525 -0
  90. package/src/synthesize-contract.ts +1161 -0
  91. package/src/types.ts +31 -0
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Negotiator types — open RAG-result projection shape.
3
+ *
4
+ * `NegotiatorOption` is the projected result shape `ragSearch`
5
+ * returns: one entry per candidate blueprint, with the contract
6
+ * + pro/con reasoning + pool provenance. The V3 decision engine
7
+ * reads these to populate `NegotiatorDecisionInput.blueprintCandidates`.
8
+ *
9
+ * `DataContract` is imported from `@ggui-ai/protocol` (already
10
+ * public). Do NOT re-export it — callers should import contract
11
+ * types from the protocol package directly.
12
+ */
13
+ import type { DataContract } from '@ggui-ai/protocol';
14
+ /** RAG-projected blueprint option surfaced to the decision engine. */
15
+ export interface NegotiatorOption {
16
+ id: string;
17
+ type: 'brainstorm' | 'blueprint';
18
+ pattern?: string;
19
+ blueprintId?: string;
20
+ description: string;
21
+ pros: string[];
22
+ cons: string[];
23
+ renderTime: 'instant' | 'standard';
24
+ contract: DataContract;
25
+ /** Stored contract hash from embedding index — deterministic pool key. */
26
+ contractHash?: string;
27
+ /** Which pool this blueprint's code lives in. */
28
+ poolSource?: 'shared' | 'private';
29
+ }
30
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEtD,sEAAsE;AACtE,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,YAAY,GAAG,WAAW,CAAC;IACjC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,UAAU,EAAE,SAAS,GAAG,UAAU,CAAC;IACnC,QAAQ,EAAE,YAAY,CAAC;IACvB,0EAA0E;IAC1E,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,iDAAiD;IACjD,UAAU,CAAC,EAAE,QAAQ,GAAG,SAAS,CAAC;CACnC"}
package/dist/types.js ADDED
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Negotiator types — open RAG-result projection shape.
3
+ *
4
+ * `NegotiatorOption` is the projected result shape `ragSearch`
5
+ * returns: one entry per candidate blueprint, with the contract
6
+ * + pro/con reasoning + pool provenance. The V3 decision engine
7
+ * reads these to populate `NegotiatorDecisionInput.blueprintCandidates`.
8
+ *
9
+ * `DataContract` is imported from `@ggui-ai/protocol` (already
10
+ * public). Do NOT re-export it — callers should import contract
11
+ * types from the protocol package directly.
12
+ */
13
+ export {};
package/package.json ADDED
@@ -0,0 +1,74 @@
1
+ {
2
+ "name": "@ggui-ai/negotiator",
3
+ "version": "0.1.0-rc.1",
4
+ "description": "UI decision engine for ggui. Given an agent's signal and the current session state, decides which UI to render (create / update / compose / replace) and synthesizes the data contract. Deployment-agnostic: concrete embedding and vector-store bindings plug in via the storage interfaces from @ggui-ai/mcp-server-core.",
5
+ "license": "Apache-2.0",
6
+ "keywords": [
7
+ "ggui",
8
+ "mcp",
9
+ "generative-ui",
10
+ "ai-agents",
11
+ "decision-engine"
12
+ ],
13
+ "homepage": "https://github.com/ggui-ai/ggui/tree/main/packages/negotiator",
14
+ "repository": {
15
+ "type": "git",
16
+ "url": "https://github.com/ggui-ai/ggui.git",
17
+ "directory": "packages/negotiator"
18
+ },
19
+ "publishConfig": {
20
+ "access": "public"
21
+ },
22
+ "files": [
23
+ "LICENSE",
24
+ "dist",
25
+ "src",
26
+ "!**/*.test.ts",
27
+ "!**/*.test.tsx",
28
+ "!**/*.test-d.ts",
29
+ "!**/*.test-d.tsx",
30
+ "!**/*.test.js",
31
+ "!**/*.test.d.ts",
32
+ "!**/*.test.d.ts.map",
33
+ "!**/*.test.js.map",
34
+ "!**/*.test-d.js",
35
+ "!**/*.test-d.d.ts",
36
+ "!**/__tests__/**",
37
+ "!**/*.spec.ts",
38
+ "!**/*.spec.tsx"
39
+ ],
40
+ "type": "module",
41
+ "main": "dist/index.js",
42
+ "types": "dist/index.d.ts",
43
+ "exports": {
44
+ ".": {
45
+ "types": "./dist/index.d.ts",
46
+ "import": "./dist/index.js"
47
+ }
48
+ },
49
+ "dependencies": {
50
+ "@ggui-ai/mcp-server-core": "0.1.0-rc.1",
51
+ "@ggui-ai/protocol": "0.1.0-rc.1"
52
+ },
53
+ "devDependencies": {
54
+ "@types/node": "^24.0.0",
55
+ "typescript": "^5.0.0",
56
+ "vitest": "^3.0.0"
57
+ },
58
+ "bugs": {
59
+ "url": "https://github.com/ggui-ai/ggui/issues"
60
+ },
61
+ "engines": {
62
+ "node": ">=20.0.0"
63
+ },
64
+ "author": "ggui contributors <hello@ggui.ai>",
65
+ "scripts": {
66
+ "build": "tsc -p tsconfig.build.json",
67
+ "dev": "tsc --watch",
68
+ "typecheck": "tsc --noEmit",
69
+ "test": "vitest run",
70
+ "test:watch": "vitest",
71
+ "probe-rerank": "tsx src/rerank-eval/run-probe-cli.ts",
72
+ "bench-synth": "tsx src/synth-bench/run-bench-cli.ts"
73
+ }
74
+ }
@@ -0,0 +1,102 @@
1
+ /**
2
+ * Contract Hashing — deterministic cache key from data contract.
3
+ *
4
+ * Uses RFC 8785 (JSON Canonicalization Scheme) for deterministic
5
+ * serialization, then SHA-256 for the hash.
6
+ *
7
+ * What's in the hash: intent only (the semantic identity).
8
+ * What's NOT in the hash: props, actions, stream (including per-channel source), adaptations.
9
+ *
10
+ * Why intent-only: The LLM generates slightly different prop descriptions
11
+ * each call, but the INTENT is deterministic (provided by the agent or
12
+ * generated once). Same intent = same component = same cached code.
13
+ * Props are passed at render time, not baked into the component.
14
+ *
15
+ * The `interaction` field was removed from `DataContract` in pre-launch
16
+ * cleanup (the four-spec surface — props/action/context/stream —
17
+ * describes the wire exhaustively); this function used to factor it in
18
+ * but no longer does. Old goldens were rotated when the field went away.
19
+ */
20
+
21
+ import { createHash } from 'node:crypto';
22
+ import type { DataContract } from '@ggui-ai/protocol';
23
+
24
+ /**
25
+ * RFC 8785 JSON Canonicalization Scheme.
26
+ *
27
+ * Produces deterministic JSON by:
28
+ * - Sorting object keys lexicographically (recursive)
29
+ * - Normalizing numbers (no trailing zeros, no +0)
30
+ * - Removing undefined values
31
+ * - No whitespace
32
+ */
33
+ function canonicalize(value: unknown): string {
34
+ if (value === null || value === undefined) return 'null';
35
+ if (typeof value === 'boolean') return value ? 'true' : 'false';
36
+ if (typeof value === 'number') {
37
+ if (!isFinite(value)) return 'null';
38
+ return Object.is(value, -0) ? '0' : String(value);
39
+ }
40
+ if (typeof value === 'string') return JSON.stringify(value);
41
+ if (Array.isArray(value)) {
42
+ return '[' + value.map((v) => canonicalize(v)).join(',') + ']';
43
+ }
44
+ if (typeof value === 'object') {
45
+ const obj = value as Record<string, unknown>;
46
+ const keys = Object.keys(obj)
47
+ .filter((k) => obj[k] !== undefined)
48
+ .sort();
49
+ const entries = keys.map((k) => JSON.stringify(k) + ':' + canonicalize(obj[k]));
50
+ return '{' + entries.join(',') + '}';
51
+ }
52
+ return 'null';
53
+ }
54
+
55
+ /**
56
+ * Hash a data contract to a deterministic cache key.
57
+ *
58
+ * Hashes intent only — the semantic identity of the UI. Props,
59
+ * actions, stream specs are for code generation, not caching.
60
+ *
61
+ * `intent` is passed separately because `DataContract` itself does
62
+ * not carry an `intent` field — the outer pipeline owns intent
63
+ * (`story.intent` on `ggui_push`, the operator prompt for harness
64
+ * benchmarks). Threading intent into the hash keeps cache identity
65
+ * stable across negotiations: different intents produce different
66
+ * generated code (labels, copy, layout) even when the wire surface is
67
+ * identical.
68
+ *
69
+ * The `contract` argument is retained on the signature for forward
70
+ * compatibility — future cache-key fields (e.g., a structural
71
+ * fingerprint of the four specs) can be folded in without breaking
72
+ * call sites — but is not consulted by the current implementation.
73
+ *
74
+ * @param contract - The data contract from negotiation (unused today)
75
+ * @param intent - The outer pipeline's intent (story.intent on
76
+ * ggui_push). Empty/falsy values are dropped from the hash input.
77
+ * @returns Contract hash prefixed with `ch_` (e.g., `ch_a3f8b2c1e9d04567`)
78
+ */
79
+ export function hashContract(
80
+ _contract: DataContract,
81
+ intent: string,
82
+ ): string {
83
+ const input: Record<string, unknown> = {};
84
+ if (intent) input.intent = intent;
85
+ const canonical = canonicalize(input);
86
+ const hash = createHash('sha256').update(canonical).digest('hex');
87
+ return `ch_${hash.slice(0, 16)}`;
88
+ }
89
+
90
+ /**
91
+ * Build a variant key from shell type and device category.
92
+ *
93
+ * @param shellType - Shell type (default: 'universal')
94
+ * @param deviceCategory - Device category (default: 'universal')
95
+ * @returns Variant string (e.g., 'fullscreen:mobile', 'universal:universal')
96
+ */
97
+ export function buildVariant(
98
+ shellType = 'universal',
99
+ deviceCategory = 'universal',
100
+ ): string {
101
+ return `${shellType}:${deviceCategory}`;
102
+ }