nexus-ai-pro 2.18.0 → 2.20.2

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 (81) hide show
  1. package/API_STABILITY.md +64 -1
  2. package/CHANGELOG.md +113 -1
  3. package/README.md +11 -3
  4. package/dist/agent/capabilities.d.ts +3 -0
  5. package/dist/agent/openapi.d.ts +139 -0
  6. package/dist/agent/openapi.js +455 -0
  7. package/dist/capabilities/negotiate.js +5 -0
  8. package/dist/decisions/completion.d.ts +48 -0
  9. package/dist/decisions/completion.js +195 -0
  10. package/dist/decisions/core.d.ts +525 -0
  11. package/dist/decisions/core.js +493 -0
  12. package/dist/decisions/index.d.ts +9 -0
  13. package/dist/decisions/index.js +3 -0
  14. package/dist/decisions/integrations.d.ts +142 -0
  15. package/dist/decisions/integrations.js +170 -0
  16. package/dist/decisions/mock.d.ts +32 -0
  17. package/dist/decisions/mock.js +47 -0
  18. package/dist/decisions/typesafe.d.ts +45 -0
  19. package/dist/decisions/typesafe.js +144 -0
  20. package/dist/evaluate/emulate.d.ts +73 -6
  21. package/dist/evaluate/emulate.js +114 -12
  22. package/dist/index.d.ts +1 -1
  23. package/dist/optimizer/densifier.js +20 -11
  24. package/dist/protocols/a2a-grpc.js +1 -1
  25. package/dist/protocols/a2a-proto.d.ts +2 -2
  26. package/dist/protocols/a2a-proto.js +76 -1
  27. package/dist/protocols/a2a.d.ts +121 -0
  28. package/dist/protocols/a2a.js +88 -29
  29. package/dist/providers/google.js +28 -0
  30. package/dist/providers/ollama.js +23 -0
  31. package/dist/providers/openai.d.ts +6 -0
  32. package/dist/providers/openai.js +26 -0
  33. package/dist/types/lifecycle.d.ts +1 -1
  34. package/dist/types/messages.d.ts +9 -0
  35. package/dist/types/providers.d.ts +2 -0
  36. package/dist/types/response.d.ts +17 -0
  37. package/dist/types/tracing.d.ts +1 -1
  38. package/dist/version.d.ts +1 -1
  39. package/dist/version.js +1 -1
  40. package/dist/workflow/chains.d.ts +13 -1
  41. package/dist/workflow/chains.js +40 -0
  42. package/dist-cjs/agent/capabilities.d.ts +3 -0
  43. package/dist-cjs/agent/openapi.d.ts +139 -0
  44. package/dist-cjs/agent/openapi.js +461 -0
  45. package/dist-cjs/capabilities/negotiate.js +5 -0
  46. package/dist-cjs/decisions/completion.d.ts +48 -0
  47. package/dist-cjs/decisions/completion.js +198 -0
  48. package/dist-cjs/decisions/core.d.ts +525 -0
  49. package/dist-cjs/decisions/core.js +509 -0
  50. package/dist-cjs/decisions/index.d.ts +9 -0
  51. package/dist-cjs/decisions/index.js +27 -0
  52. package/dist-cjs/decisions/integrations.d.ts +142 -0
  53. package/dist-cjs/decisions/integrations.js +178 -0
  54. package/dist-cjs/decisions/mock.d.ts +32 -0
  55. package/dist-cjs/decisions/mock.js +51 -0
  56. package/dist-cjs/decisions/typesafe.d.ts +45 -0
  57. package/dist-cjs/decisions/typesafe.js +148 -0
  58. package/dist-cjs/evaluate/emulate.d.ts +73 -6
  59. package/dist-cjs/evaluate/emulate.js +116 -13
  60. package/dist-cjs/index.d.ts +1 -1
  61. package/dist-cjs/optimizer/densifier.js +20 -11
  62. package/dist-cjs/protocols/a2a-grpc.js +1 -1
  63. package/dist-cjs/protocols/a2a-proto.d.ts +2 -2
  64. package/dist-cjs/protocols/a2a-proto.js +76 -1
  65. package/dist-cjs/protocols/a2a.d.ts +121 -0
  66. package/dist-cjs/protocols/a2a.js +88 -29
  67. package/dist-cjs/providers/google.js +28 -0
  68. package/dist-cjs/providers/ollama.js +23 -0
  69. package/dist-cjs/providers/openai.d.ts +6 -0
  70. package/dist-cjs/providers/openai.js +26 -0
  71. package/dist-cjs/types/lifecycle.d.ts +1 -1
  72. package/dist-cjs/types/messages.d.ts +9 -0
  73. package/dist-cjs/types/providers.d.ts +2 -0
  74. package/dist-cjs/types/response.d.ts +17 -0
  75. package/dist-cjs/types/tracing.d.ts +1 -1
  76. package/dist-cjs/version.d.ts +1 -1
  77. package/dist-cjs/version.js +1 -1
  78. package/dist-cjs/workflow/chains.d.ts +13 -1
  79. package/dist-cjs/workflow/chains.js +40 -0
  80. package/llms.txt +2 -1
  81. package/package.json +54 -2
@@ -0,0 +1,195 @@
1
+ import { DecisionError, } from './core.js';
2
+ const LOGPROB_OPTIONS = 20;
3
+ export function completionDecisions(client, options) {
4
+ const method = options.method ?? 'auto';
5
+ const sampled = new Set();
6
+ const info = {
7
+ name: options.name ?? options.model,
8
+ capabilities: {
9
+ types: ['yes-no', 'choice', 'score'],
10
+ maxOptions: 255,
11
+ maxLevels: 10,
12
+ defaultModel: options.model,
13
+ },
14
+ chargedByItsCalls: true,
15
+ };
16
+ const ask = async (model, state, question, context, usage) => {
17
+ const codes = codesOf(question);
18
+ const prompt = promptOf(state, question, codes, options.instructions);
19
+ const request = (extra) => ({
20
+ model,
21
+ messages: [
22
+ {
23
+ role: 'system',
24
+ content: 'You answer one question about a state with exactly one of the codes given, and nothing else.',
25
+ },
26
+ { role: 'user', content: prompt },
27
+ ],
28
+ signal: context.signal,
29
+ ...(context.tenantId !== undefined ? { tenantId: context.tenantId } : {}),
30
+ ...extra,
31
+ });
32
+ const readable = codes.length <= LOGPROB_OPTIONS && codes.every((code) => code.length === 1);
33
+ if (method !== 'sampling' && readable && !sampled.has(model)) {
34
+ let response;
35
+ try {
36
+ response = await client.complete(request({ temperature: 0, maxTokens: 2, logprobs: { top: 20 } }));
37
+ }
38
+ catch (error) {
39
+ if (method === 'logprobs' || !refusedOption(error))
40
+ throw error;
41
+ }
42
+ if (response) {
43
+ usage.add(response);
44
+ const weights = weightsFrom(response.logprobs, codes);
45
+ if (weights)
46
+ return distributionOf(question, codes, weights);
47
+ if (method === 'logprobs') {
48
+ throw new DecisionError(`"${model}" reported no log probabilities for the codes it was given`, 'DECISION_FAILED');
49
+ }
50
+ }
51
+ sampled.add(model);
52
+ }
53
+ if (!readable && method === 'logprobs') {
54
+ throw new DecisionError(`A question of ${codes.length} options cannot be read from one token's ${LOGPROB_OPTIONS} alternatives`, 'DECISION_UNSUPPORTED');
55
+ }
56
+ const count = Math.max(1, Math.floor(options.samples ?? 8));
57
+ const answers = await Promise.all(Array.from({ length: count }, () => client.complete(request({ temperature: options.temperature ?? 1, maxTokens: 4 })).then((response) => {
58
+ usage.add(response);
59
+ return codeIn(response.content, codes);
60
+ })));
61
+ const weights = codes.map((code) => answers.filter((answer) => answer === code).length);
62
+ if (weights.every((weight) => weight === 0)) {
63
+ throw new DecisionError(`"${model}" answered none of ${count} samples with a code it was given`, 'DECISION_FAILED');
64
+ }
65
+ return distributionOf(question, codes, weights);
66
+ };
67
+ return {
68
+ info,
69
+ sampledModels: sampled,
70
+ async decide(request, context) {
71
+ const totals = new Totals();
72
+ const entries = Object.entries(request.questions);
73
+ const distributions = {};
74
+ const limit = Math.max(1, Math.floor(options.concurrency ?? 8));
75
+ let next = 0;
76
+ const worker = async () => {
77
+ while (next < entries.length) {
78
+ const [name, question] = entries[next++];
79
+ distributions[name] = await ask(request.model, request.state, question, context, totals);
80
+ }
81
+ };
82
+ await Promise.all(Array.from({ length: Math.min(limit, entries.length) }, worker));
83
+ return {
84
+ model: request.model,
85
+ distributions,
86
+ usage: totals.usage(),
87
+ ...(totals.cost() ? { cost: totals.cost() } : {}),
88
+ };
89
+ },
90
+ };
91
+ }
92
+ class Totals {
93
+ inputTokens = 0;
94
+ outputTokens = 0;
95
+ calls = 0;
96
+ amount = 0;
97
+ priced = false;
98
+ add(response) {
99
+ this.calls += 1;
100
+ this.inputTokens += response.meta.usage?.inputTokens ?? 0;
101
+ this.outputTokens += response.meta.usage?.outputTokens ?? 0;
102
+ if (response.meta.cost) {
103
+ this.amount += response.meta.cost.amount;
104
+ this.priced = true;
105
+ }
106
+ }
107
+ usage() {
108
+ return { inputTokens: this.inputTokens, outputTokens: this.outputTokens, calls: this.calls };
109
+ }
110
+ cost() {
111
+ return this.priced ? { amount: this.amount, currency: 'USD', basis: 'estimated' } : undefined;
112
+ }
113
+ }
114
+ function codesOf(question) {
115
+ if (question.type === 'yes-no')
116
+ return ['Y', 'N'];
117
+ if (question.type === 'score')
118
+ return question.levels.map((_, level) => String(level));
119
+ return question.options.length <= 26
120
+ ? question.options.map((_, index) => String.fromCharCode(65 + index))
121
+ : question.options.map((_, index) => String(index + 1));
122
+ }
123
+ function promptOf(state, question, codes, instructions) {
124
+ const text = typeof state === 'string' ? state : JSON.stringify(state, null, 2);
125
+ const lines = [`State:\n${text}`, ''];
126
+ if (instructions)
127
+ lines.push(instructions, '');
128
+ if (question.type === 'yes-no') {
129
+ lines.push(`Question: ${question.question ?? 'Is the statement true of the state?'}`);
130
+ lines.push(`Y: yes${question.criteria?.yes ? `, ${question.criteria.yes}` : ''}`);
131
+ lines.push(`N: no${question.criteria?.no ? `, ${question.criteria.no}` : ''}`);
132
+ }
133
+ else if (question.type === 'choice') {
134
+ lines.push(`Question: ${question.question ?? 'Which option fits the state?'}`);
135
+ question.options.forEach((option, index) => {
136
+ lines.push(`${codes[index]}: ${option.name}${option.description ? `, ${option.description}` : ''}`);
137
+ });
138
+ }
139
+ else {
140
+ lines.push(`Question: ${question.question ?? 'Which level fits the state?'}`);
141
+ question.levels.forEach((level, index) => {
142
+ lines.push(`${codes[index]}: ${level}`);
143
+ });
144
+ }
145
+ lines.push('', `Answer with one code: ${codes.join(', ')}.`);
146
+ return lines.join('\n');
147
+ }
148
+ function codeOf(token) {
149
+ return token.replace(/^[\s"'`*(]+|[\s"'`*).:,]+$/g, '').toUpperCase();
150
+ }
151
+ function weightsFrom(logprobs, codes) {
152
+ const first = logprobs?.find((item) => item.token.trim() !== '');
153
+ if (!first)
154
+ return undefined;
155
+ const candidates = first.top?.length ? first.top : [{ token: first.token, logprob: first.logprob }];
156
+ const weights = codes.map(() => 0);
157
+ let found = false;
158
+ for (const candidate of candidates) {
159
+ const index = matchCode(candidate.token, codes);
160
+ if (index < 0 || !Number.isFinite(candidate.logprob))
161
+ continue;
162
+ weights[index] = weights[index] + Math.exp(candidate.logprob);
163
+ found = true;
164
+ }
165
+ return found ? weights : undefined;
166
+ }
167
+ function codeIn(content, codes) {
168
+ const head = content.trim().split(/[\s:,.)]+/)[0] ?? '';
169
+ return codes[matchCode(head, codes)];
170
+ }
171
+ function matchCode(token, codes) {
172
+ const code = codeOf(token);
173
+ const index = codes.indexOf(code);
174
+ if (index >= 0 || codes.length !== 2 || codes[0] !== 'Y' || codes[1] !== 'N')
175
+ return index;
176
+ if (code === 'YES' || code === 'TRUE')
177
+ return 0;
178
+ return code === 'NO' || code === 'FALSE' ? 1 : -1;
179
+ }
180
+ function distributionOf(question, codes, weights) {
181
+ const total = weights.reduce((sum, weight) => sum + weight, 0);
182
+ const share = (index) => (total > 0 ? (weights[index] ?? 0) / total : 1 / codes.length);
183
+ if (question.type === 'yes-no')
184
+ return { type: 'yes-no', yes: share(0) };
185
+ if (question.type === 'score')
186
+ return { type: 'score', probabilities: codes.map((_, index) => share(index)) };
187
+ return {
188
+ type: 'choice',
189
+ probabilities: Object.fromEntries(question.options.map((option, index) => [option.name, share(index)])),
190
+ };
191
+ }
192
+ function refusedOption(error) {
193
+ const status = error?.status;
194
+ return status === 400 || status === 422;
195
+ }