@voxagent/bridge 0.3.5 → 0.4.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 +27 -0
- package/dist/cli.js +22 -2
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +26 -2
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +46 -1
- package/dist/config.js.map +1 -1
- package/dist/drivers/claude.d.ts.map +1 -1
- package/dist/drivers/claude.js +6 -1
- package/dist/drivers/claude.js.map +1 -1
- package/dist/drivers/codex.d.ts.map +1 -1
- package/dist/drivers/codex.js +30 -1
- package/dist/drivers/codex.js.map +1 -1
- package/dist/drivers/types.d.ts +9 -0
- package/dist/drivers/types.d.ts.map +1 -1
- package/dist/protocol.d.ts +103 -2
- package/dist/protocol.d.ts.map +1 -1
- package/dist/protocol.js.map +1 -1
- package/dist/room.d.ts +20 -0
- package/dist/room.d.ts.map +1 -1
- package/dist/room.js +220 -8
- package/dist/room.js.map +1 -1
- package/dist/trigger/addressing.d.ts +40 -0
- package/dist/trigger/addressing.d.ts.map +1 -0
- package/dist/trigger/addressing.js +90 -0
- package/dist/trigger/addressing.js.map +1 -0
- package/dist/trigger/decide.d.ts +33 -0
- package/dist/trigger/decide.d.ts.map +1 -0
- package/dist/trigger/decide.js +133 -0
- package/dist/trigger/decide.js.map +1 -0
- package/dist/trigger/effort.d.ts +26 -0
- package/dist/trigger/effort.d.ts.map +1 -0
- package/dist/trigger/effort.js +66 -0
- package/dist/trigger/effort.js.map +1 -0
- package/dist/trigger/engine.d.ts +120 -0
- package/dist/trigger/engine.d.ts.map +1 -0
- package/dist/trigger/engine.js +515 -0
- package/dist/trigger/engine.js.map +1 -0
- package/dist/trigger/jev.d.ts +52 -0
- package/dist/trigger/jev.d.ts.map +1 -0
- package/dist/trigger/jev.js +204 -0
- package/dist/trigger/jev.js.map +1 -0
- package/dist/trigger/questions.d.ts +43 -0
- package/dist/trigger/questions.d.ts.map +1 -0
- package/dist/trigger/questions.js +243 -0
- package/dist/trigger/questions.js.map +1 -0
- package/dist/trigger/types.d.ts +175 -0
- package/dist/trigger/types.d.ts.map +1 -0
- package/dist/trigger/types.js +29 -0
- package/dist/trigger/types.js.map +1 -0
- package/package.json +11 -10
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file TypeSafe jev ("System One") client.
|
|
3
|
+
*
|
|
4
|
+
* Raw HTTP on purpose: the bridge is launched via `npx`, `undici` is already
|
|
5
|
+
* a dependency, and the wire format is three fields in, one map out.
|
|
6
|
+
*
|
|
7
|
+
* POST https://api.typesafe.ai/v1/systemone
|
|
8
|
+
* { model, state, questions } → { model, answers, usage }
|
|
9
|
+
*
|
|
10
|
+
* All questions in one request are evaluated in parallel server-side, so the
|
|
11
|
+
* whole question set costs one round-trip.
|
|
12
|
+
*/
|
|
13
|
+
import { request } from 'undici';
|
|
14
|
+
import { log } from '../logging.js';
|
|
15
|
+
import { ADDRESSEE_OPTIONS, EFFORT_LEVELS, RELATION_OPTIONS, RISK_LEVELS, buildQuestions, buildState, } from './questions.js';
|
|
16
|
+
export const DEFAULT_JEV_BASE_URL = 'https://api.typesafe.ai';
|
|
17
|
+
/**
|
|
18
|
+
* Pinned, not `jev-latest`: thresholds in `decide.ts` are tuned against one
|
|
19
|
+
* version's calibration. Bump deliberately and re-run the eval.
|
|
20
|
+
*/
|
|
21
|
+
export const DEFAULT_JEV_MODEL = 'jev-1.13.0';
|
|
22
|
+
export const DEFAULT_JEV_TIMEOUT_MS = 900;
|
|
23
|
+
function asProbability(value) {
|
|
24
|
+
const n = typeof value === 'number' ? value : Number.NaN;
|
|
25
|
+
if (!Number.isFinite(n))
|
|
26
|
+
throw new Error('jev answer is not a number');
|
|
27
|
+
return Math.min(1, Math.max(0, n));
|
|
28
|
+
}
|
|
29
|
+
function parseNoul(raw, key) {
|
|
30
|
+
if (!raw || raw.type !== 'noul')
|
|
31
|
+
throw new Error(`jev response missing noul "${key}"`);
|
|
32
|
+
return asProbability(raw.noul);
|
|
33
|
+
}
|
|
34
|
+
function parseChoice(raw, key, options) {
|
|
35
|
+
if (!raw || raw.type !== 'choice' || typeof raw.choice !== 'string') {
|
|
36
|
+
throw new Error(`jev response missing choice "${key}"`);
|
|
37
|
+
}
|
|
38
|
+
const rawProbabilities = (raw.probabilities ?? {});
|
|
39
|
+
const probabilities = {};
|
|
40
|
+
for (const option of options) {
|
|
41
|
+
const value = rawProbabilities[option];
|
|
42
|
+
probabilities[option] = typeof value === 'number' ? asProbability(value) : 0;
|
|
43
|
+
}
|
|
44
|
+
return {
|
|
45
|
+
choice: raw.choice,
|
|
46
|
+
confidence: typeof raw.confidence === 'number' ? asProbability(raw.confidence) : 0,
|
|
47
|
+
probabilities,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
function parseScore(raw, key, levels) {
|
|
51
|
+
if (!raw || raw.type !== 'score' || typeof raw.score !== 'number') {
|
|
52
|
+
throw new Error(`jev response missing score "${key}"`);
|
|
53
|
+
}
|
|
54
|
+
const rawProbabilities = (raw.probabilities ?? {});
|
|
55
|
+
const probabilities = [];
|
|
56
|
+
for (let level = 0; level < levels; level += 1) {
|
|
57
|
+
const value = rawProbabilities[String(level)];
|
|
58
|
+
probabilities.push(typeof value === 'number' ? asProbability(value) : 0);
|
|
59
|
+
}
|
|
60
|
+
return {
|
|
61
|
+
score: Math.min(levels - 1, Math.max(0, raw.score)),
|
|
62
|
+
confidence: typeof raw.confidence === 'number' ? asProbability(raw.confidence) : 0,
|
|
63
|
+
probabilities,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
const WARMUP_MAX_CALLS = 4;
|
|
67
|
+
const WARMUP_TIMEOUT_MS = 6000;
|
|
68
|
+
const WARMUP_INPUT = {
|
|
69
|
+
utterance: {
|
|
70
|
+
entryId: 'warmup',
|
|
71
|
+
speaker: 'Host',
|
|
72
|
+
speakerIdentity: 'warmup',
|
|
73
|
+
text: 'okay, let us get started.',
|
|
74
|
+
timestampMs: 0,
|
|
75
|
+
},
|
|
76
|
+
window: [],
|
|
77
|
+
room: { id: 'warmup', name: 'warmup', participants: ['Host'] },
|
|
78
|
+
run: { status: 'idle', activePromptText: null, spokenSoFar: '', activeToolName: null },
|
|
79
|
+
agent: { names: ['Vox'], backend: 'claude', workspace: 'workspace', tools: [], hostName: 'Host' },
|
|
80
|
+
pendingNudgeText: null,
|
|
81
|
+
lastAgentText: null,
|
|
82
|
+
lastAgentSpokeAtMs: null,
|
|
83
|
+
nowMs: 0,
|
|
84
|
+
};
|
|
85
|
+
/** Exported for tests and the eval script. */
|
|
86
|
+
export function parseAnswers(answers, runActive) {
|
|
87
|
+
return {
|
|
88
|
+
addressee: parseChoice(answers.addressee, 'addressee', ADDRESSEE_OPTIONS),
|
|
89
|
+
thoughtComplete: parseNoul(answers.thought_complete, 'thought_complete'),
|
|
90
|
+
isRequest: parseNoul(answers.is_request, 'is_request'),
|
|
91
|
+
agentCapable: parseNoul(answers.agent_capable, 'agent_capable'),
|
|
92
|
+
hypotheticalOrQuoted: parseNoul(answers.hypothetical_or_quoted, 'hypothetical_or_quoted'),
|
|
93
|
+
relation: runActive
|
|
94
|
+
? parseChoice(answers.relation_to_running_turn, 'relation_to_running_turn', RELATION_OPTIONS)
|
|
95
|
+
: null,
|
|
96
|
+
effort: parseScore(answers.effort, 'effort', EFFORT_LEVELS),
|
|
97
|
+
risk: parseScore(answers.risk, 'risk', RISK_LEVELS),
|
|
98
|
+
humansDisagree: parseNoul(answers.humans_disagree, 'humans_disagree'),
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
export class JevClassifier {
|
|
102
|
+
options;
|
|
103
|
+
baseUrl;
|
|
104
|
+
model;
|
|
105
|
+
timeoutMs;
|
|
106
|
+
constructor(options) {
|
|
107
|
+
this.options = options;
|
|
108
|
+
this.baseUrl = (options.baseUrl ?? DEFAULT_JEV_BASE_URL).replace(/\/+$/, '');
|
|
109
|
+
this.model = options.model ?? DEFAULT_JEV_MODEL;
|
|
110
|
+
this.timeoutMs = options.timeoutMs ?? DEFAULT_JEV_TIMEOUT_MS;
|
|
111
|
+
}
|
|
112
|
+
async classify(input, timeoutMs = this.timeoutMs) {
|
|
113
|
+
const runActive = input.run.status !== 'idle';
|
|
114
|
+
const startedAtMs = Date.now();
|
|
115
|
+
const response = await request(`${this.baseUrl}/v1/systemone`, {
|
|
116
|
+
method: 'POST',
|
|
117
|
+
headers: {
|
|
118
|
+
'content-type': 'application/json',
|
|
119
|
+
authorization: `Bearer ${this.options.apiKey}`,
|
|
120
|
+
},
|
|
121
|
+
body: JSON.stringify({
|
|
122
|
+
model: this.model,
|
|
123
|
+
state: buildState(input),
|
|
124
|
+
questions: buildQuestions(runActive),
|
|
125
|
+
}),
|
|
126
|
+
signal: AbortSignal.timeout(timeoutMs),
|
|
127
|
+
headersTimeout: timeoutMs,
|
|
128
|
+
bodyTimeout: timeoutMs,
|
|
129
|
+
});
|
|
130
|
+
if (response.statusCode !== 200) {
|
|
131
|
+
const detail = await response.body.text().catch(() => '');
|
|
132
|
+
throw new Error(`jev returned ${response.statusCode}: ${detail.slice(0, 200)}`);
|
|
133
|
+
}
|
|
134
|
+
const body = (await response.body.json());
|
|
135
|
+
if (!body.answers)
|
|
136
|
+
throw new Error('jev response has no answers');
|
|
137
|
+
return {
|
|
138
|
+
answers: parseAnswers(body.answers, runActive),
|
|
139
|
+
latencyMs: Date.now() - startedAtMs,
|
|
140
|
+
model: body.model ?? this.model,
|
|
141
|
+
inputTokens: body.usage?.input_tokens ?? 0,
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
/** Repeats a throwaway classify until one lands inside the live budget. */
|
|
145
|
+
async warmClassifyPath() {
|
|
146
|
+
const latenciesMs = [];
|
|
147
|
+
for (let call = 0; call < WARMUP_MAX_CALLS; call += 1) {
|
|
148
|
+
try {
|
|
149
|
+
const { latencyMs } = await this.classify(WARMUP_INPUT, WARMUP_TIMEOUT_MS);
|
|
150
|
+
latenciesMs.push(latencyMs);
|
|
151
|
+
if (latencyMs <= this.timeoutMs / 2)
|
|
152
|
+
break;
|
|
153
|
+
}
|
|
154
|
+
catch (error) {
|
|
155
|
+
log.debug('trigger_jev_warmup_call_failed', {
|
|
156
|
+
message: error instanceof Error ? error.message : String(error),
|
|
157
|
+
});
|
|
158
|
+
break;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
return latenciesMs;
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Checks the key, then warms the REAL classify path before anyone speaks.
|
|
165
|
+
*
|
|
166
|
+
* Measured against the live API: the first ~3 `/v1/systemone` calls of a
|
|
167
|
+
* process take 0.7-2 s, then settle around 300 ms. Pinging `/v1/models`
|
|
168
|
+
* alone does not fix that. Left cold, the first utterances of every meeting
|
|
169
|
+
* would blow the timeout, and three in a row trip the engine's circuit
|
|
170
|
+
* breaker — so the agent would open each session deaf to everything but
|
|
171
|
+
* the wake phrase. Costs a few thousand input tokens, once.
|
|
172
|
+
*/
|
|
173
|
+
async warmUp() {
|
|
174
|
+
try {
|
|
175
|
+
const response = await request(`${this.baseUrl}/v1/models`, {
|
|
176
|
+
method: 'GET',
|
|
177
|
+
headers: { authorization: `Bearer ${this.options.apiKey}` },
|
|
178
|
+
signal: AbortSignal.timeout(5000),
|
|
179
|
+
});
|
|
180
|
+
await response.body.dump();
|
|
181
|
+
if (response.statusCode === 200) {
|
|
182
|
+
const latenciesMs = await this.warmClassifyPath();
|
|
183
|
+
log.info('trigger_jev_ready', {
|
|
184
|
+
model: this.model,
|
|
185
|
+
timeoutMs: this.timeoutMs,
|
|
186
|
+
warmupLatenciesMs: latenciesMs,
|
|
187
|
+
});
|
|
188
|
+
return true;
|
|
189
|
+
}
|
|
190
|
+
log.warn('trigger_jev_key_rejected', {
|
|
191
|
+
status: response.statusCode,
|
|
192
|
+
hint: 'Check TYPESAFE_API_KEY. Falling back to the wake phrase ("hey Vox") until it works.',
|
|
193
|
+
});
|
|
194
|
+
return false;
|
|
195
|
+
}
|
|
196
|
+
catch (error) {
|
|
197
|
+
log.warn('trigger_jev_unreachable', {
|
|
198
|
+
message: error instanceof Error ? error.message : String(error),
|
|
199
|
+
});
|
|
200
|
+
return false;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
//# sourceMappingURL=jev.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jev.js","sourceRoot":"","sources":["../../src/trigger/jev.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file The jev questions and the `state` they're asked about.
|
|
3
|
+
*
|
|
4
|
+
* jev is not fine-tuned — `state`, `instructions` and `criteria` are the only
|
|
5
|
+
* steering there is, so every wording change here is a behaviour change. Run
|
|
6
|
+
* `pnpm --filter @voxagent/bridge trigger:eval` after editing.
|
|
7
|
+
*
|
|
8
|
+
* Writing rules (from TypeSafe's docs): one gut-check judgment per question,
|
|
9
|
+
* no compound conditions, unambiguous yes/no boundaries, and compose in code
|
|
10
|
+
* (`decide.ts`) rather than in prose.
|
|
11
|
+
*/
|
|
12
|
+
import type { ClassifyInput } from './types.js';
|
|
13
|
+
/** Lines of context jev sees. More than the LLM gets — jev input is cheap. */
|
|
14
|
+
export declare const STATE_WINDOW_LINES = 40;
|
|
15
|
+
export declare const ADDRESSEE_OPTIONS: readonly ["agent", "specific_person", "group", "nobody"];
|
|
16
|
+
export declare const RELATION_OPTIONS: readonly ["adds_detail", "redirects", "unrelated", "stop_talking", "abort_work", "backchannel"];
|
|
17
|
+
export declare const EFFORT_LEVELS = 4;
|
|
18
|
+
export declare const RISK_LEVELS = 3;
|
|
19
|
+
type Question = {
|
|
20
|
+
type: 'noul';
|
|
21
|
+
instructions: string;
|
|
22
|
+
criteria?: {
|
|
23
|
+
true: string;
|
|
24
|
+
false: string;
|
|
25
|
+
};
|
|
26
|
+
} | {
|
|
27
|
+
type: 'choice';
|
|
28
|
+
instructions: string;
|
|
29
|
+
criteria: Record<string, unknown>;
|
|
30
|
+
} | {
|
|
31
|
+
type: 'score';
|
|
32
|
+
instructions: string;
|
|
33
|
+
criteria: string[];
|
|
34
|
+
};
|
|
35
|
+
export declare function buildQuestions(runActive: boolean): Record<string, Question>;
|
|
36
|
+
/**
|
|
37
|
+
* Serializes everything jev needs into one JSON string. The REST API takes
|
|
38
|
+
* `state` as text; JSON keeps field names stable so `instructions` can refer
|
|
39
|
+
* to them (`newest_utterance`, `agent.status`, ...).
|
|
40
|
+
*/
|
|
41
|
+
export declare function buildState(input: ClassifyInput): string;
|
|
42
|
+
export {};
|
|
43
|
+
//# sourceMappingURL=questions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"questions.d.ts","sourceRoot":"","sources":["../../src/trigger/questions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAkB,MAAM,YAAY,CAAC;AAEhE,8EAA8E;AAC9E,eAAO,MAAM,kBAAkB,KAAK,CAAC;AAIrC,eAAO,MAAM,iBAAiB,0DAA2D,CAAC;AAC1F,eAAO,MAAM,gBAAgB,iGAOnB,CAAC;AACX,eAAO,MAAM,aAAa,IAAI,CAAC;AAC/B,eAAO,MAAM,WAAW,IAAI,CAAC;AAE7B,KAAK,QAAQ,GACT;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,GAClF;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,GAC3E;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC;AA8IhE,wBAAgB,cAAc,CAAC,SAAS,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAI3E;AAkDD;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,aAAa,GAAG,MAAM,CAuCvD"}
|
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file The jev questions and the `state` they're asked about.
|
|
3
|
+
*
|
|
4
|
+
* jev is not fine-tuned — `state`, `instructions` and `criteria` are the only
|
|
5
|
+
* steering there is, so every wording change here is a behaviour change. Run
|
|
6
|
+
* `pnpm --filter @voxagent/bridge trigger:eval` after editing.
|
|
7
|
+
*
|
|
8
|
+
* Writing rules (from TypeSafe's docs): one gut-check judgment per question,
|
|
9
|
+
* no compound conditions, unambiguous yes/no boundaries, and compose in code
|
|
10
|
+
* (`decide.ts`) rather than in prose.
|
|
11
|
+
*/
|
|
12
|
+
/** Lines of context jev sees. More than the LLM gets — jev input is cheap. */
|
|
13
|
+
export const STATE_WINDOW_LINES = 40;
|
|
14
|
+
const MAX_LINE_CHARS = 400;
|
|
15
|
+
const MAX_TAIL_CHARS = 300;
|
|
16
|
+
export const ADDRESSEE_OPTIONS = ['agent', 'specific_person', 'group', 'nobody'];
|
|
17
|
+
export const RELATION_OPTIONS = [
|
|
18
|
+
'adds_detail',
|
|
19
|
+
'redirects',
|
|
20
|
+
'unrelated',
|
|
21
|
+
'stop_talking',
|
|
22
|
+
'abort_work',
|
|
23
|
+
'backchannel',
|
|
24
|
+
];
|
|
25
|
+
export const EFFORT_LEVELS = 4;
|
|
26
|
+
export const RISK_LEVELS = 3;
|
|
27
|
+
const FOCUS = 'Judge only `newest_utterance`. Everything else in the state is context for that judgment.';
|
|
28
|
+
const BASE_QUESTIONS = {
|
|
29
|
+
addressee: {
|
|
30
|
+
type: 'choice',
|
|
31
|
+
instructions: `Who is the speaker of newest_utterance talking to? ${FOCUS} The AI agent is a participant in this voice meeting; its names are in agent.names. Speech-to-text sometimes mis-hears "Vox" as "box", "fox" or "vocs" — treat those as the name ONLY where a name would naturally go, such as "hey box, ..." or "box, can you ...", never when the word is just part of a sentence.`,
|
|
32
|
+
criteria: {
|
|
33
|
+
agent: {
|
|
34
|
+
what: 'The speaker is talking TO the AI agent: giving it an instruction, asking it a question, answering a question the agent just asked, or reacting to what the agent is saying or doing right now.',
|
|
35
|
+
not_for: [
|
|
36
|
+
'Talking ABOUT the agent or about AI agents in general ("the agent is slow today", "our agent loop needs retries", "I asked Vox to do that earlier").',
|
|
37
|
+
'A nameless "can you..." or "could you..." said in reply to another HUMAN who spoke just before, while the agent is idle and has not been part of the exchange. There, "you" is that human, not the agent.',
|
|
38
|
+
],
|
|
39
|
+
examples: [
|
|
40
|
+
'Vox, can you pull up the deploy logs?',
|
|
41
|
+
'Yeah, the second option. (right after the agent offered two options)',
|
|
42
|
+
'Can you also add a test for that? (while the agent is editing code)',
|
|
43
|
+
],
|
|
44
|
+
},
|
|
45
|
+
specific_person: {
|
|
46
|
+
what: 'The speaker is talking to one particular human in the meeting, by name or because they are clearly continuing an exchange with that person. This includes a nameless "you" when the speaker is answering a human who spoke moments earlier and the agent was not involved.',
|
|
47
|
+
examples: [
|
|
48
|
+
'Priya, can you check that?',
|
|
49
|
+
'What do you think, Sam?',
|
|
50
|
+
'Can you check what happened? (said right after a colleague reported a problem, agent idle and not part of the exchange)',
|
|
51
|
+
],
|
|
52
|
+
},
|
|
53
|
+
group: {
|
|
54
|
+
what: 'The speaker is talking to the humans in the meeting generally, including open questions that anyone might answer.',
|
|
55
|
+
examples: ['Does anyone remember why we pinned that version?', 'Let us move on to the roadmap.'],
|
|
56
|
+
},
|
|
57
|
+
nobody: {
|
|
58
|
+
what: 'Thinking aloud, muttering, filler, reading something out loud, a false start, or speech not directed at anyone.',
|
|
59
|
+
examples: ['Hmm, where did I put that file.', 'Okay so... right.'],
|
|
60
|
+
},
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
thought_complete: {
|
|
64
|
+
type: 'noul',
|
|
65
|
+
instructions: 'The speaker of newest_utterance has finished their thought: someone could respond now without cutting them off mid-sentence.',
|
|
66
|
+
criteria: {
|
|
67
|
+
true: 'A complete sentence, question, command, or a complete short reply such as "yes" or "the second one".',
|
|
68
|
+
false: 'It trails off, ends on a conjunction, preposition or article, or is only a greeting or name with the actual request still to come ("Hey Vox", "Can you", "So I was thinking we could").',
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
is_request: {
|
|
72
|
+
type: 'noul',
|
|
73
|
+
instructions: 'In newest_utterance the speaker is asking for something to be done, looked up, or answered.',
|
|
74
|
+
criteria: {
|
|
75
|
+
true: 'A question that wants an answer, or an instruction to do something.',
|
|
76
|
+
false: 'A statement, opinion, acknowledgement, small talk, or a rhetorical question.',
|
|
77
|
+
},
|
|
78
|
+
},
|
|
79
|
+
agent_capable: {
|
|
80
|
+
type: 'noul',
|
|
81
|
+
instructions: 'What newest_utterance asks for is something the AI agent described in agent.can_do could actually do or answer.',
|
|
82
|
+
criteria: {
|
|
83
|
+
true: 'It concerns code, files, the repository, running commands, searching the web, the agent\'s listed tools, or recalling what was said in this meeting.',
|
|
84
|
+
false: 'It needs a human: a personal opinion, a decision only a person can make, a physical action, or knowledge private to a participant.',
|
|
85
|
+
},
|
|
86
|
+
},
|
|
87
|
+
hypothetical_or_quoted: {
|
|
88
|
+
type: 'noul',
|
|
89
|
+
instructions: 'newest_utterance mentions asking the AI agent to do something, but NOT as a live instruction for right now.',
|
|
90
|
+
criteria: {
|
|
91
|
+
true: 'Hypothetical, conditional, negated, about the past or future, or quoting/reading someone else ("I was going to ask Vox to refactor this", "don\'t ask it yet", "if we had Vox deploy that...", "then he said hey Vox run the tests").',
|
|
92
|
+
false: 'A live instruction or question meant for the agent now, or an utterance that does not involve the agent at all.',
|
|
93
|
+
},
|
|
94
|
+
},
|
|
95
|
+
effort: {
|
|
96
|
+
type: 'score',
|
|
97
|
+
instructions: 'If the AI agent handled newest_utterance, how much work would it take? When the scope is unclear, prefer the higher level.',
|
|
98
|
+
criteria: [
|
|
99
|
+
'Conversational: answerable from the meeting conversation alone, a greeting, a clarification, or a yes/no. No tools needed.',
|
|
100
|
+
'Quick lookup: read one file, run one command, one web search, or a short factual answer about the codebase.',
|
|
101
|
+
'Multi-step task: edit code across a few places, write and run tests, investigate a bug with several steps.',
|
|
102
|
+
'Deep work: architecture or design decisions, a large refactor, debugging something subtle, or anything high-stakes where being wrong is expensive.',
|
|
103
|
+
],
|
|
104
|
+
},
|
|
105
|
+
risk: {
|
|
106
|
+
type: 'score',
|
|
107
|
+
instructions: 'If the AI agent acted on newest_utterance, how reversible would the result be?',
|
|
108
|
+
criteria: [
|
|
109
|
+
'Read-only: answering, explaining, searching, reading files, summarising.',
|
|
110
|
+
'Reversible change: editing files in the workspace, creating files, installing a dependency, running tests.',
|
|
111
|
+
'Hard to undo or outward-facing: deleting data or branches, force-pushing, deploying, sending messages or emails, spending money, changing production.',
|
|
112
|
+
],
|
|
113
|
+
},
|
|
114
|
+
humans_disagree: {
|
|
115
|
+
type: 'noul',
|
|
116
|
+
instructions: 'In recent_transcript, two or more human participants have given conflicting instructions about what the AI agent should do, and nobody has conceded yet.',
|
|
117
|
+
criteria: {
|
|
118
|
+
true: 'One person wants the agent to do X, another wants Y instead or wants it not to, and the conflict is still open.',
|
|
119
|
+
false: 'No conflict, a conflict that was already resolved, or a disagreement that is not about what the agent should do.',
|
|
120
|
+
},
|
|
121
|
+
},
|
|
122
|
+
};
|
|
123
|
+
const RELATION_QUESTION = {
|
|
124
|
+
type: 'choice',
|
|
125
|
+
instructions: `The AI agent is busy right now (see agent.status, agent.working_on and agent.saying_now). How does newest_utterance relate to what the agent is doing? ${FOCUS}`,
|
|
126
|
+
criteria: {
|
|
127
|
+
adds_detail: {
|
|
128
|
+
what: 'Extra information, a constraint, or a correction for the SAME task the agent is already working on. The task should continue.',
|
|
129
|
+
examples: ['Oh, and use TypeScript for that.', 'It is in the payments folder, not billing.'],
|
|
130
|
+
},
|
|
131
|
+
redirects: {
|
|
132
|
+
what: 'The speaker wants the agent to drop the current task and do something different instead.',
|
|
133
|
+
examples: ['Actually forget that, check the failing test first.', 'No, I meant the staging config.'],
|
|
134
|
+
},
|
|
135
|
+
unrelated: {
|
|
136
|
+
what: 'A new, separate request for the agent that does not replace the current task. It can wait until the current one finishes.',
|
|
137
|
+
examples: ['After that, can you also bump the version?'],
|
|
138
|
+
},
|
|
139
|
+
stop_talking: {
|
|
140
|
+
what: 'The speaker has heard enough and wants the agent to stop SPEAKING, but has not asked it to abandon the work.',
|
|
141
|
+
examples: ['Okay okay, got it.', 'That is enough detail, thanks.', 'Right, I understand.'],
|
|
142
|
+
},
|
|
143
|
+
abort_work: {
|
|
144
|
+
what: 'The speaker wants the agent to stop WORKING: cancel the task entirely.',
|
|
145
|
+
examples: ['Cancel that.', 'Stop, do not do that.', 'Never mind, leave it.'],
|
|
146
|
+
},
|
|
147
|
+
backchannel: {
|
|
148
|
+
what: 'A listening noise or brief acknowledgement that expects nothing, or speech between humans that is not about the agent\'s current task.',
|
|
149
|
+
examples: ['Mm-hm.', 'Yeah.', 'Right.', 'Interesting.'],
|
|
150
|
+
},
|
|
151
|
+
},
|
|
152
|
+
};
|
|
153
|
+
export function buildQuestions(runActive) {
|
|
154
|
+
return runActive
|
|
155
|
+
? { ...BASE_QUESTIONS, relation_to_running_turn: RELATION_QUESTION }
|
|
156
|
+
: BASE_QUESTIONS;
|
|
157
|
+
}
|
|
158
|
+
function clip(text, max) {
|
|
159
|
+
const trimmed = text.trim();
|
|
160
|
+
return trimmed.length <= max ? trimmed : `${trimmed.slice(0, max - 1)}…`;
|
|
161
|
+
}
|
|
162
|
+
function tail(text, max) {
|
|
163
|
+
const trimmed = text.trim();
|
|
164
|
+
return trimmed.length <= max ? trimmed : `…${trimmed.slice(trimmed.length - max + 1)}`;
|
|
165
|
+
}
|
|
166
|
+
function secondsAgo(nowMs, thenMs) {
|
|
167
|
+
return Math.max(0, Math.round((nowMs - thenMs) / 1000));
|
|
168
|
+
}
|
|
169
|
+
function describeStatus(input) {
|
|
170
|
+
switch (input.run.status) {
|
|
171
|
+
case 'thinking':
|
|
172
|
+
return 'busy: thinking about a request';
|
|
173
|
+
case 'speaking':
|
|
174
|
+
return 'busy: speaking aloud to the room right now';
|
|
175
|
+
case 'acting':
|
|
176
|
+
return input.run.activeToolName
|
|
177
|
+
? `busy: running a tool (${input.run.activeToolName})`
|
|
178
|
+
: 'busy: running a tool';
|
|
179
|
+
default:
|
|
180
|
+
return 'idle: not doing anything';
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
function describeAgent(input) {
|
|
184
|
+
const { agent } = input;
|
|
185
|
+
const backend = agent.backend === 'claude' ? 'Claude Code' : 'Codex';
|
|
186
|
+
const tools = agent.tools.length > 0 ? ` Extra tools: ${agent.tools.slice(0, 12).join(', ')}.` : '';
|
|
187
|
+
return (`An AI coding agent (${backend}) running on ${agent.hostName}'s machine in the "${agent.workspace}" workspace. ` +
|
|
188
|
+
'It can read and edit files there, run shell commands and tests, search the web, and recall what was said in this meeting. ' +
|
|
189
|
+
`It hears the meeting through a transcript and replies by voice.${tools}`);
|
|
190
|
+
}
|
|
191
|
+
function toStateLine(line, nowMs) {
|
|
192
|
+
return {
|
|
193
|
+
speaker: line.fromAgent ? `${line.speaker} (the AI agent)` : line.speaker,
|
|
194
|
+
text: clip(line.text, MAX_LINE_CHARS),
|
|
195
|
+
seconds_ago: secondsAgo(nowMs, line.timestampMs),
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Serializes everything jev needs into one JSON string. The REST API takes
|
|
200
|
+
* `state` as text; JSON keeps field names stable so `instructions` can refer
|
|
201
|
+
* to them (`newest_utterance`, `agent.status`, ...).
|
|
202
|
+
*/
|
|
203
|
+
export function buildState(input) {
|
|
204
|
+
const { nowMs, run, room, utterance } = input;
|
|
205
|
+
const humans = room.participants.length > 0 ? room.participants : [utterance.speaker];
|
|
206
|
+
const agent = {
|
|
207
|
+
names: input.agent.names,
|
|
208
|
+
can_do: describeAgent(input),
|
|
209
|
+
status: describeStatus(input),
|
|
210
|
+
};
|
|
211
|
+
if (run.status !== 'idle') {
|
|
212
|
+
if (run.activePromptText)
|
|
213
|
+
agent.working_on = clip(run.activePromptText, MAX_LINE_CHARS);
|
|
214
|
+
if (run.spokenSoFar.trim())
|
|
215
|
+
agent.saying_now = tail(run.spokenSoFar, MAX_TAIL_CHARS);
|
|
216
|
+
}
|
|
217
|
+
if (input.lastAgentText && input.lastAgentSpokeAtMs !== null) {
|
|
218
|
+
agent.last_said = tail(input.lastAgentText, MAX_TAIL_CHARS);
|
|
219
|
+
agent.seconds_since_agent_spoke = secondsAgo(nowMs, input.lastAgentSpokeAtMs);
|
|
220
|
+
}
|
|
221
|
+
if (input.pendingNudgeText) {
|
|
222
|
+
agent.pending_offer = `The agent is showing an on-screen prompt asking whether this was meant for it: "${clip(input.pendingNudgeText, 200)}"`;
|
|
223
|
+
}
|
|
224
|
+
return JSON.stringify({
|
|
225
|
+
agent,
|
|
226
|
+
meeting: {
|
|
227
|
+
humans,
|
|
228
|
+
human_count: humans.length,
|
|
229
|
+
host: input.agent.hostName,
|
|
230
|
+
},
|
|
231
|
+
recent_transcript: input.window
|
|
232
|
+
.slice(-STATE_WINDOW_LINES)
|
|
233
|
+
.map((line) => toStateLine(line, nowMs)),
|
|
234
|
+
newest_utterance: {
|
|
235
|
+
speaker: utterance.speaker,
|
|
236
|
+
text: clip(utterance.text, MAX_LINE_CHARS * 2),
|
|
237
|
+
...(utterance.confidence !== undefined
|
|
238
|
+
? { speech_to_text_confidence: Number(utterance.confidence.toFixed(2)) }
|
|
239
|
+
: {}),
|
|
240
|
+
},
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
//# sourceMappingURL=questions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"questions.js","sourceRoot":"","sources":["../../src/trigger/questions.ts"],"names":[],"mappings":"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"}
|