@undefineds.co/models 0.2.15 → 0.2.16
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 +6 -4
- package/dist/agent.providers.js +11 -0
- package/dist/ai-config/index.d.ts +7 -0
- package/dist/ai-config/index.js +13 -0
- package/dist/approval.schema.d.ts +6 -0
- package/dist/approval.schema.js +3 -0
- package/dist/discovery/models.json +29 -0
- package/dist/discovery/providers.json +10 -0
- package/dist/grant.schema.d.ts +28 -0
- package/dist/grant.schema.js +22 -5
- package/dist/index.d.ts +1 -1
- package/dist/namespaces.js +11 -0
- package/dist/schema.d.ts +34 -0
- package/dist/sidecar/persistence-mapping.d.ts +2 -2
- package/dist/sidecar/sidecar-events.d.ts +186 -0
- package/dist/sidecar/sidecar-events.js +10 -0
- package/dist/vocab/sidecar.vocab.d.ts +17 -0
- package/dist/vocab/sidecar.vocab.js +17 -0
- package/dist/watch/index.d.ts +55 -0
- package/dist/watch/index.js +359 -12
- package/package.json +3 -3
package/dist/watch/index.js
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
export const DEFAULT_WATCH_SECRETARY_REACTION_WINDOW_MS = 5000;
|
|
2
|
+
export const MIN_WATCH_SECRETARY_REACTION_WINDOW_MS = 5000;
|
|
3
|
+
export const MAX_WATCH_SECRETARY_REACTION_WINDOW_MS = 60000;
|
|
1
4
|
export const WATCH_HOME_DIRNAME = 'watch';
|
|
2
5
|
export const WATCH_SESSIONS_DIRNAME = 'sessions';
|
|
3
6
|
export const WATCH_SESSION_FILE_NAME = 'session.json';
|
|
@@ -136,6 +139,97 @@ function normalizeAcpPermissionOptions(value) {
|
|
|
136
139
|
}
|
|
137
140
|
return value.filter((item) => isRecord(item));
|
|
138
141
|
}
|
|
142
|
+
export function normalizeWatchApprovalOptions(value) {
|
|
143
|
+
return normalizeAcpPermissionOptions(value)
|
|
144
|
+
.map((option) => {
|
|
145
|
+
const optionId = typeof option.optionId === 'string' && option.optionId.trim()
|
|
146
|
+
? option.optionId.trim()
|
|
147
|
+
: undefined;
|
|
148
|
+
const label = firstNonEmpty([
|
|
149
|
+
typeof option.name === 'string' ? option.name : undefined,
|
|
150
|
+
typeof option.label === 'string' ? option.label : undefined,
|
|
151
|
+
optionId,
|
|
152
|
+
]);
|
|
153
|
+
if (!optionId || !label) {
|
|
154
|
+
return null;
|
|
155
|
+
}
|
|
156
|
+
const kind = typeof option.kind === 'string' && option.kind.trim()
|
|
157
|
+
? option.kind.trim()
|
|
158
|
+
: undefined;
|
|
159
|
+
const description = firstNonEmpty([
|
|
160
|
+
typeof option.description === 'string' ? option.description : undefined,
|
|
161
|
+
typeof option.detail === 'string' ? option.detail : undefined,
|
|
162
|
+
]);
|
|
163
|
+
return {
|
|
164
|
+
optionId,
|
|
165
|
+
label,
|
|
166
|
+
...(kind ? { kind } : {}),
|
|
167
|
+
...(description ? { description } : {}),
|
|
168
|
+
};
|
|
169
|
+
})
|
|
170
|
+
.filter((option) => option !== null);
|
|
171
|
+
}
|
|
172
|
+
function normalizeDurationMs(value, unit) {
|
|
173
|
+
const numeric = typeof value === 'number'
|
|
174
|
+
? value
|
|
175
|
+
: typeof value === 'string' && value.trim()
|
|
176
|
+
? Number(value)
|
|
177
|
+
: Number.NaN;
|
|
178
|
+
if (!Number.isFinite(numeric) || numeric <= 0) {
|
|
179
|
+
return undefined;
|
|
180
|
+
}
|
|
181
|
+
const milliseconds = unit === 'ms'
|
|
182
|
+
? numeric
|
|
183
|
+
: unit === 'seconds'
|
|
184
|
+
? numeric * 1000
|
|
185
|
+
: numeric > 10000
|
|
186
|
+
? numeric
|
|
187
|
+
: numeric * 1000;
|
|
188
|
+
return Math.round(milliseconds);
|
|
189
|
+
}
|
|
190
|
+
function normalizeIsoDatetime(value) {
|
|
191
|
+
if (value instanceof Date) {
|
|
192
|
+
return Number.isFinite(value.getTime()) ? value.toISOString() : undefined;
|
|
193
|
+
}
|
|
194
|
+
if (typeof value === 'number' && Number.isFinite(value)) {
|
|
195
|
+
const date = new Date(value);
|
|
196
|
+
return Number.isFinite(date.getTime()) ? date.toISOString() : undefined;
|
|
197
|
+
}
|
|
198
|
+
if (typeof value !== 'string' || !value.trim()) {
|
|
199
|
+
return undefined;
|
|
200
|
+
}
|
|
201
|
+
const date = new Date(value);
|
|
202
|
+
return Number.isFinite(date.getTime()) ? date.toISOString() : undefined;
|
|
203
|
+
}
|
|
204
|
+
function extractWatchApprovalTimeoutMs(params, raw) {
|
|
205
|
+
const meta = isRecord(params._meta)
|
|
206
|
+
? params._meta
|
|
207
|
+
: isRecord(raw._meta)
|
|
208
|
+
? raw._meta
|
|
209
|
+
: {};
|
|
210
|
+
return normalizeDurationMs(params.timeoutMs ?? meta.timeoutMs, 'ms')
|
|
211
|
+
?? normalizeDurationMs(params.timeoutMillis ?? params.timeoutMilliseconds ?? meta.timeoutMillis ?? meta.timeoutMilliseconds, 'ms')
|
|
212
|
+
?? normalizeDurationMs(params.timeoutSeconds ?? params.timeoutSec ?? meta.timeoutSeconds ?? meta.timeoutSec, 'seconds')
|
|
213
|
+
?? normalizeDurationMs(params.timeout ?? meta.timeout, 'auto');
|
|
214
|
+
}
|
|
215
|
+
function extractWatchApprovalExpiresAt(params, raw) {
|
|
216
|
+
const meta = isRecord(params._meta)
|
|
217
|
+
? params._meta
|
|
218
|
+
: isRecord(raw._meta)
|
|
219
|
+
? raw._meta
|
|
220
|
+
: {};
|
|
221
|
+
return normalizeIsoDatetime(params.expiresAt ?? params.deadline ?? params.expires ?? meta.expiresAt ?? meta.deadline ?? meta.expires);
|
|
222
|
+
}
|
|
223
|
+
function extractWatchApprovalMetadata(raw, params) {
|
|
224
|
+
const approvalOptions = normalizeWatchApprovalOptions(params.options);
|
|
225
|
+
const timeoutMs = extractWatchApprovalTimeoutMs(params, raw);
|
|
226
|
+
const expiresAt = extractWatchApprovalExpiresAt(params, raw);
|
|
227
|
+
return {
|
|
228
|
+
...(approvalOptions.length > 0 ? { approvalOptions } : {}),
|
|
229
|
+
...(timeoutMs ? { timeoutMs } : {}),
|
|
230
|
+
...(expiresAt ? { expiresAt } : {}),
|
|
231
|
+
};
|
|
232
|
+
}
|
|
139
233
|
function selectAcpPermissionOption(options, decision) {
|
|
140
234
|
if (decision === 'cancel') {
|
|
141
235
|
return undefined;
|
|
@@ -262,9 +356,251 @@ export function resolveWatchAutoApprovalDecision(input) {
|
|
|
262
356
|
}
|
|
263
357
|
return null;
|
|
264
358
|
}
|
|
359
|
+
export function createFallbackWatchSecretaryRecommendation(input) {
|
|
360
|
+
if (input.mode === 'manual' || input.request.kind === 'user-input') {
|
|
361
|
+
return null;
|
|
362
|
+
}
|
|
363
|
+
const decision = resolveWatchAutoApprovalDecision({
|
|
364
|
+
mode: input.mode,
|
|
365
|
+
request: input.request,
|
|
366
|
+
});
|
|
367
|
+
const secretaryDecision = decision === 'accept_for_session' ? 'accept' : decision;
|
|
368
|
+
if (!secretaryDecision) {
|
|
369
|
+
return null;
|
|
370
|
+
}
|
|
371
|
+
return {
|
|
372
|
+
kind: input.request.kind,
|
|
373
|
+
canAutoDecide: true,
|
|
374
|
+
decision: secretaryDecision,
|
|
375
|
+
confidence: input.mode === 'auto' ? 0.7 : 0.6,
|
|
376
|
+
reason: 'Matched local fallback policy while AI secretary was unavailable.',
|
|
377
|
+
reactionWindowMs: 0,
|
|
378
|
+
source: 'fallback',
|
|
379
|
+
};
|
|
380
|
+
}
|
|
381
|
+
export function parseWatchSecretaryRecommendation(text, options) {
|
|
382
|
+
const raw = parseJsonObjectFromText(text);
|
|
383
|
+
if (!raw) {
|
|
384
|
+
return null;
|
|
385
|
+
}
|
|
386
|
+
const canAutoDecide = booleanFromUnknown(raw.canAutoDecide
|
|
387
|
+
?? raw.can_auto_decide
|
|
388
|
+
?? raw.autoApprove
|
|
389
|
+
?? raw.auto_approve
|
|
390
|
+
?? raw.canAnswer
|
|
391
|
+
?? raw.can_answer);
|
|
392
|
+
const confidence = normalizeConfidence(raw.confidence ?? raw.confidenceScore ?? raw.confidence_score);
|
|
393
|
+
const reason = stringFromUnknown(raw.reason ?? raw.rationale ?? raw.explanation);
|
|
394
|
+
const fallbackReactionWindowMs = options.defaultReactionWindowMs ?? DEFAULT_WATCH_SECRETARY_REACTION_WINDOW_MS;
|
|
395
|
+
const reactionWindowMs = confidence !== undefined
|
|
396
|
+
? computeWatchSecretaryReactionWindowMs(confidence, fallbackReactionWindowMs)
|
|
397
|
+
: normalizeReactionWindowMs(raw.reactionWindowMs
|
|
398
|
+
?? raw.reaction_window_ms
|
|
399
|
+
?? raw.reviewWindowMs
|
|
400
|
+
?? raw.review_window_ms
|
|
401
|
+
?? raw.autoDecisionDelayMs
|
|
402
|
+
?? raw.auto_decision_delay_ms, fallbackReactionWindowMs);
|
|
403
|
+
if (options.request.kind === 'user-input') {
|
|
404
|
+
const answers = normalizeSecretaryUserInputAnswers(options.request.questions, raw.answers ?? raw.answer ?? raw.userInputAnswers ?? raw.user_input_answers);
|
|
405
|
+
return {
|
|
406
|
+
kind: 'user-input',
|
|
407
|
+
canAutoDecide: canAutoDecide === true && !!answers,
|
|
408
|
+
...(confidence !== undefined ? { confidence } : {}),
|
|
409
|
+
...(reason ? { reason } : {}),
|
|
410
|
+
...(reactionWindowMs !== undefined ? { reactionWindowMs } : {}),
|
|
411
|
+
...(answers ? { answers } : {}),
|
|
412
|
+
source: 'model',
|
|
413
|
+
};
|
|
414
|
+
}
|
|
415
|
+
const decision = normalizeSecretaryApprovalDecision(raw.decision ?? raw.recommendedDecision ?? raw.recommended_decision);
|
|
416
|
+
if (!decision) {
|
|
417
|
+
return {
|
|
418
|
+
kind: options.request.kind,
|
|
419
|
+
canAutoDecide: false,
|
|
420
|
+
...(confidence !== undefined ? { confidence } : {}),
|
|
421
|
+
...(reason ? { reason } : {}),
|
|
422
|
+
...(reactionWindowMs !== undefined ? { reactionWindowMs } : {}),
|
|
423
|
+
source: 'model',
|
|
424
|
+
};
|
|
425
|
+
}
|
|
426
|
+
return {
|
|
427
|
+
kind: options.request.kind,
|
|
428
|
+
canAutoDecide: canAutoDecide === true,
|
|
429
|
+
decision,
|
|
430
|
+
...(confidence !== undefined ? { confidence } : {}),
|
|
431
|
+
...(reason ? { reason } : {}),
|
|
432
|
+
...(reactionWindowMs !== undefined ? { reactionWindowMs } : {}),
|
|
433
|
+
source: 'model',
|
|
434
|
+
};
|
|
435
|
+
}
|
|
436
|
+
export function watchApprovalDecisionLabel(decision) {
|
|
437
|
+
if (decision === 'accept') {
|
|
438
|
+
return 'Allow once';
|
|
439
|
+
}
|
|
440
|
+
if (decision === 'accept_for_session') {
|
|
441
|
+
return 'Grant';
|
|
442
|
+
}
|
|
443
|
+
if (decision === 'decline') {
|
|
444
|
+
return 'Deny';
|
|
445
|
+
}
|
|
446
|
+
return 'Cancel';
|
|
447
|
+
}
|
|
448
|
+
export function watchUserInputAnswersSummary(answers) {
|
|
449
|
+
return Object.entries(answers)
|
|
450
|
+
.map(([key, value]) => `${key}: ${value.answers.join(', ')}`)
|
|
451
|
+
.join('; ');
|
|
452
|
+
}
|
|
453
|
+
export function parseWatchGrantCoverageDecision(text) {
|
|
454
|
+
const raw = parseJsonObjectFromText(text);
|
|
455
|
+
if (!raw) {
|
|
456
|
+
return null;
|
|
457
|
+
}
|
|
458
|
+
const covers = booleanFromUnknown(raw.covers ?? raw.covered ?? raw.applies ?? raw.allowed);
|
|
459
|
+
if (covers === undefined) {
|
|
460
|
+
return null;
|
|
461
|
+
}
|
|
462
|
+
const confidence = normalizeConfidence(raw.confidence ?? raw.confidenceScore ?? raw.confidence_score);
|
|
463
|
+
const reason = stringFromUnknown(raw.reason ?? raw.rationale ?? raw.explanation);
|
|
464
|
+
return {
|
|
465
|
+
covers,
|
|
466
|
+
...(confidence !== undefined ? { confidence } : {}),
|
|
467
|
+
...(reason ? { reason } : {}),
|
|
468
|
+
source: 'model',
|
|
469
|
+
};
|
|
470
|
+
}
|
|
265
471
|
function isRecord(value) {
|
|
266
472
|
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
267
473
|
}
|
|
474
|
+
function stringFromUnknown(value) {
|
|
475
|
+
return typeof value === 'string' && value.trim() ? value.trim() : undefined;
|
|
476
|
+
}
|
|
477
|
+
function normalizeStringList(value) {
|
|
478
|
+
const source = typeof value === 'string'
|
|
479
|
+
? value.split(',')
|
|
480
|
+
: Array.isArray(value)
|
|
481
|
+
? value
|
|
482
|
+
: [];
|
|
483
|
+
return source
|
|
484
|
+
.map((entry) => typeof entry === 'string' ? entry.trim() : '')
|
|
485
|
+
.filter(Boolean);
|
|
486
|
+
}
|
|
487
|
+
function booleanFromUnknown(value) {
|
|
488
|
+
if (typeof value === 'boolean') {
|
|
489
|
+
return value;
|
|
490
|
+
}
|
|
491
|
+
if (typeof value === 'string') {
|
|
492
|
+
const normalized = value.trim().toLowerCase();
|
|
493
|
+
if (['true', 'yes', 'y', '1'].includes(normalized)) {
|
|
494
|
+
return true;
|
|
495
|
+
}
|
|
496
|
+
if (['false', 'no', 'n', '0'].includes(normalized)) {
|
|
497
|
+
return false;
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
return undefined;
|
|
501
|
+
}
|
|
502
|
+
function normalizeConfidence(value) {
|
|
503
|
+
if (typeof value === 'number' && Number.isFinite(value)) {
|
|
504
|
+
if (value > 1 && value <= 100) {
|
|
505
|
+
return Math.max(0, Math.min(1, value / 100));
|
|
506
|
+
}
|
|
507
|
+
return Math.max(0, Math.min(1, value));
|
|
508
|
+
}
|
|
509
|
+
if (typeof value === 'string' && value.trim()) {
|
|
510
|
+
const parsed = Number(value);
|
|
511
|
+
return Number.isFinite(parsed) ? normalizeConfidence(parsed) : undefined;
|
|
512
|
+
}
|
|
513
|
+
return undefined;
|
|
514
|
+
}
|
|
515
|
+
function normalizeReactionWindowMs(value, fallback) {
|
|
516
|
+
const parsed = normalizeDurationMs(value ?? fallback, 'ms');
|
|
517
|
+
if (parsed === undefined) {
|
|
518
|
+
return undefined;
|
|
519
|
+
}
|
|
520
|
+
return Math.max(0, Math.min(MAX_WATCH_SECRETARY_REACTION_WINDOW_MS, parsed));
|
|
521
|
+
}
|
|
522
|
+
export function computeWatchSecretaryReactionWindowMs(confidence, fallback = DEFAULT_WATCH_SECRETARY_REACTION_WINDOW_MS) {
|
|
523
|
+
if (typeof confidence !== 'number' || !Number.isFinite(confidence)) {
|
|
524
|
+
return Math.max(0, Math.min(MAX_WATCH_SECRETARY_REACTION_WINDOW_MS, fallback));
|
|
525
|
+
}
|
|
526
|
+
const normalized = Math.max(0, Math.min(1, confidence));
|
|
527
|
+
const window = Math.round(MIN_WATCH_SECRETARY_REACTION_WINDOW_MS
|
|
528
|
+
+ (1 - normalized) * (MAX_WATCH_SECRETARY_REACTION_WINDOW_MS - MIN_WATCH_SECRETARY_REACTION_WINDOW_MS));
|
|
529
|
+
return Math.max(MIN_WATCH_SECRETARY_REACTION_WINDOW_MS, Math.min(MAX_WATCH_SECRETARY_REACTION_WINDOW_MS, window));
|
|
530
|
+
}
|
|
531
|
+
function normalizeSecretaryApprovalDecision(value) {
|
|
532
|
+
if (typeof value !== 'string') {
|
|
533
|
+
return undefined;
|
|
534
|
+
}
|
|
535
|
+
const normalized = value.trim().toLowerCase().replace(/-/g, '_');
|
|
536
|
+
if (['accept', 'allow', 'allow_once', 'approve', 'yes', 'accept_for_session', 'allow_always', 'grant', 'session', 'approve_for_session'].includes(normalized)) {
|
|
537
|
+
return 'accept';
|
|
538
|
+
}
|
|
539
|
+
if (['decline', 'deny', 'reject', 'reject_once', 'reject_always', 'no'].includes(normalized)) {
|
|
540
|
+
return 'decline';
|
|
541
|
+
}
|
|
542
|
+
if (['cancel', 'abort'].includes(normalized)) {
|
|
543
|
+
return 'cancel';
|
|
544
|
+
}
|
|
545
|
+
return undefined;
|
|
546
|
+
}
|
|
547
|
+
function parseJsonObjectFromText(text) {
|
|
548
|
+
const trimmed = text.trim();
|
|
549
|
+
if (!trimmed) {
|
|
550
|
+
return null;
|
|
551
|
+
}
|
|
552
|
+
for (const candidate of [
|
|
553
|
+
trimmed,
|
|
554
|
+
extractFencedJson(trimmed),
|
|
555
|
+
extractBracedJson(trimmed),
|
|
556
|
+
]) {
|
|
557
|
+
if (!candidate) {
|
|
558
|
+
continue;
|
|
559
|
+
}
|
|
560
|
+
try {
|
|
561
|
+
const parsed = JSON.parse(candidate);
|
|
562
|
+
return recordFromUnknown(parsed);
|
|
563
|
+
}
|
|
564
|
+
catch {
|
|
565
|
+
// Try the next extraction shape.
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
return null;
|
|
569
|
+
}
|
|
570
|
+
function extractFencedJson(text) {
|
|
571
|
+
const match = text.match(/```(?:json)?\s*([\s\S]*?)```/iu);
|
|
572
|
+
return match?.[1]?.trim() || null;
|
|
573
|
+
}
|
|
574
|
+
function extractBracedJson(text) {
|
|
575
|
+
const start = text.indexOf('{');
|
|
576
|
+
const end = text.lastIndexOf('}');
|
|
577
|
+
return start !== -1 && end > start ? text.slice(start, end + 1) : null;
|
|
578
|
+
}
|
|
579
|
+
function normalizeSecretaryUserInputAnswers(questions, rawAnswers) {
|
|
580
|
+
const source = recordFromUnknown(rawAnswers);
|
|
581
|
+
if (!source) {
|
|
582
|
+
return undefined;
|
|
583
|
+
}
|
|
584
|
+
const answers = {};
|
|
585
|
+
for (const question of questions) {
|
|
586
|
+
const raw = source[question.id] ?? source[question.header] ?? source[question.question];
|
|
587
|
+
const normalizedAnswers = normalizeSecretaryAnswerValues(raw);
|
|
588
|
+
if (normalizedAnswers.length > 0) {
|
|
589
|
+
answers[question.id] = { answers: normalizedAnswers };
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
return Object.keys(answers).length > 0 ? answers : undefined;
|
|
593
|
+
}
|
|
594
|
+
function normalizeSecretaryAnswerValues(value) {
|
|
595
|
+
const answerRecord = recordFromUnknown(value);
|
|
596
|
+
if (answerRecord) {
|
|
597
|
+
return normalizeSecretaryAnswerValues(answerRecord.answers ?? answerRecord.value ?? answerRecord.answer);
|
|
598
|
+
}
|
|
599
|
+
const values = Array.isArray(value) ? value : [value];
|
|
600
|
+
return values
|
|
601
|
+
.map((entry) => typeof entry === 'string' ? entry.trim() : '')
|
|
602
|
+
.filter(Boolean);
|
|
603
|
+
}
|
|
268
604
|
function firstNonEmpty(values) {
|
|
269
605
|
for (const value of values) {
|
|
270
606
|
if (typeof value === 'string' && value.trim()) {
|
|
@@ -433,6 +769,7 @@ export function normalizeCodexAppServerInteractionRequest(message) {
|
|
|
433
769
|
const params = (typeof message.params === 'object' && message.params !== null
|
|
434
770
|
? message.params
|
|
435
771
|
: {});
|
|
772
|
+
const approvalMetadata = extractWatchApprovalMetadata(message, params);
|
|
436
773
|
if (method === 'item/commandExecution/requestApproval') {
|
|
437
774
|
const command = typeof params.command === 'string' ? params.command : undefined;
|
|
438
775
|
const cwd = typeof params.cwd === 'string' ? params.cwd : undefined;
|
|
@@ -441,6 +778,7 @@ export function normalizeCodexAppServerInteractionRequest(message) {
|
|
|
441
778
|
message: command || 'Codex requests command approval',
|
|
442
779
|
command,
|
|
443
780
|
cwd,
|
|
781
|
+
...approvalMetadata,
|
|
444
782
|
raw: message,
|
|
445
783
|
};
|
|
446
784
|
}
|
|
@@ -450,6 +788,7 @@ export function normalizeCodexAppServerInteractionRequest(message) {
|
|
|
450
788
|
kind: 'file-change-approval',
|
|
451
789
|
message: reason && reason.trim() ? reason : 'Codex requests file-change approval',
|
|
452
790
|
...(reason ? { reason } : {}),
|
|
791
|
+
...approvalMetadata,
|
|
453
792
|
raw: message,
|
|
454
793
|
};
|
|
455
794
|
}
|
|
@@ -460,6 +799,7 @@ export function normalizeCodexAppServerInteractionRequest(message) {
|
|
|
460
799
|
kind: 'permissions-approval',
|
|
461
800
|
message: reason && reason.trim() ? reason : 'Codex requests additional permissions',
|
|
462
801
|
permissions,
|
|
802
|
+
...approvalMetadata,
|
|
463
803
|
raw: message,
|
|
464
804
|
};
|
|
465
805
|
}
|
|
@@ -480,6 +820,7 @@ export function normalizeCodexAppServerInteractionRequest(message) {
|
|
|
480
820
|
return {
|
|
481
821
|
kind: 'codex-approval',
|
|
482
822
|
message: 'Codex requests approval',
|
|
823
|
+
...approvalMetadata,
|
|
483
824
|
raw: message,
|
|
484
825
|
};
|
|
485
826
|
}
|
|
@@ -542,6 +883,7 @@ export function normalizeAcpInteractionRequest(message) {
|
|
|
542
883
|
const method = typeof message.method === 'string' ? message.method.toLowerCase() : '';
|
|
543
884
|
const params = (recordFromUnknown(message.params) ?? {});
|
|
544
885
|
if (method === 'session/request_permission' || Array.isArray(params.options)) {
|
|
886
|
+
const approvalMetadata = extractWatchApprovalMetadata(message, params);
|
|
545
887
|
const toolCall = (recordFromUnknown(params.toolCall) ?? {});
|
|
546
888
|
const toolKind = typeof toolCall.kind === 'string' ? toolCall.kind : '';
|
|
547
889
|
const command = extractAcpCommand(toolCall.rawInput);
|
|
@@ -563,6 +905,7 @@ export function normalizeAcpInteractionRequest(message) {
|
|
|
563
905
|
message: command ?? messageText,
|
|
564
906
|
...(command ? { command } : {}),
|
|
565
907
|
...(cwd ? { cwd } : {}),
|
|
908
|
+
...approvalMetadata,
|
|
566
909
|
raw: message,
|
|
567
910
|
};
|
|
568
911
|
}
|
|
@@ -571,6 +914,7 @@ export function normalizeAcpInteractionRequest(message) {
|
|
|
571
914
|
kind: 'file-change-approval',
|
|
572
915
|
message: messageText,
|
|
573
916
|
reason: messageText,
|
|
917
|
+
...approvalMetadata,
|
|
574
918
|
raw: message,
|
|
575
919
|
};
|
|
576
920
|
}
|
|
@@ -578,6 +922,7 @@ export function normalizeAcpInteractionRequest(message) {
|
|
|
578
922
|
kind: 'permissions-approval',
|
|
579
923
|
message: messageText,
|
|
580
924
|
permissions: recordFromUnknown(toolCall.rawInput) ?? {},
|
|
925
|
+
...approvalMetadata,
|
|
581
926
|
raw: message,
|
|
582
927
|
};
|
|
583
928
|
}
|
|
@@ -788,6 +1133,7 @@ function maybeWatchApprovalEvent(json, lowerType) {
|
|
|
788
1133
|
kind: 'permissions-approval',
|
|
789
1134
|
message: message || 'Approval required',
|
|
790
1135
|
permissions: json.permissions,
|
|
1136
|
+
...extractWatchApprovalMetadata(json, json),
|
|
791
1137
|
raw: json,
|
|
792
1138
|
},
|
|
793
1139
|
}
|
|
@@ -1048,13 +1394,14 @@ export function buildWatchThreadMetadata(record) {
|
|
|
1048
1394
|
backendSessionId: record.backendSessionId,
|
|
1049
1395
|
};
|
|
1050
1396
|
}
|
|
1051
|
-
function pushWatchTranscriptMessage(messages, role, content, createdAt) {
|
|
1397
|
+
function pushWatchTranscriptMessage(messages, role, source, content, createdAt) {
|
|
1052
1398
|
const normalized = content?.replace(/\r/g, '').trimEnd();
|
|
1053
1399
|
if (!normalized) {
|
|
1054
1400
|
return;
|
|
1055
1401
|
}
|
|
1056
1402
|
messages.push({
|
|
1057
1403
|
role,
|
|
1404
|
+
source,
|
|
1058
1405
|
content: normalized,
|
|
1059
1406
|
createdAt,
|
|
1060
1407
|
});
|
|
@@ -1065,7 +1412,7 @@ function flushWatchAssistantMessage(messages, state, fallbackTimestamp) {
|
|
|
1065
1412
|
state.assistantTimestamp = undefined;
|
|
1066
1413
|
return;
|
|
1067
1414
|
}
|
|
1068
|
-
pushWatchTranscriptMessage(messages, 'assistant', state.assistantText, state.assistantTimestamp ?? fallbackTimestamp);
|
|
1415
|
+
pushWatchTranscriptMessage(messages, 'assistant', 'primary-agent', state.assistantText, state.assistantTimestamp ?? fallbackTimestamp);
|
|
1069
1416
|
state.assistantText = '';
|
|
1070
1417
|
state.assistantTimestamp = undefined;
|
|
1071
1418
|
}
|
|
@@ -1079,7 +1426,7 @@ function appendWatchTranscriptEvent(messages, state, entry, event) {
|
|
|
1079
1426
|
}
|
|
1080
1427
|
if (event.type === 'assistant.done') {
|
|
1081
1428
|
if (event.text && !state.assistantText) {
|
|
1082
|
-
pushWatchTranscriptMessage(messages, 'assistant', event.text, entry.timestamp);
|
|
1429
|
+
pushWatchTranscriptMessage(messages, 'assistant', 'primary-agent', event.text, entry.timestamp);
|
|
1083
1430
|
return;
|
|
1084
1431
|
}
|
|
1085
1432
|
flushWatchAssistantMessage(messages, state, entry.timestamp);
|
|
@@ -1087,18 +1434,18 @@ function appendWatchTranscriptEvent(messages, state, entry, event) {
|
|
|
1087
1434
|
}
|
|
1088
1435
|
flushWatchAssistantMessage(messages, state, entry.timestamp);
|
|
1089
1436
|
if (event.type === 'tool.call') {
|
|
1090
|
-
pushWatchTranscriptMessage(messages, 'system', `[tool] ${event.name}${event.arguments ? ` ${JSON.stringify(event.arguments)}` : ''}`, entry.timestamp);
|
|
1437
|
+
pushWatchTranscriptMessage(messages, 'system', 'tool', `[tool] ${event.name}${event.arguments ? ` ${JSON.stringify(event.arguments)}` : ''}`, entry.timestamp);
|
|
1091
1438
|
return;
|
|
1092
1439
|
}
|
|
1093
1440
|
if (event.type === 'approval.required') {
|
|
1094
|
-
pushWatchTranscriptMessage(messages, 'system', `[approval] ${event.message}`, entry.timestamp);
|
|
1441
|
+
pushWatchTranscriptMessage(messages, 'system', 'secretary', `[approval] ${event.message}`, entry.timestamp);
|
|
1095
1442
|
return;
|
|
1096
1443
|
}
|
|
1097
1444
|
if (event.type === 'input.required') {
|
|
1098
|
-
pushWatchTranscriptMessage(messages, 'system', `[input] ${event.message}`, entry.timestamp);
|
|
1445
|
+
pushWatchTranscriptMessage(messages, 'system', 'secretary', `[input] ${event.message}`, entry.timestamp);
|
|
1099
1446
|
return;
|
|
1100
1447
|
}
|
|
1101
|
-
pushWatchTranscriptMessage(messages, 'system', `[note] ${event.message}`, entry.timestamp);
|
|
1448
|
+
pushWatchTranscriptMessage(messages, 'system', 'system', `[note] ${event.message}`, entry.timestamp);
|
|
1102
1449
|
}
|
|
1103
1450
|
function appendWatchTranscriptRawEntry(messages, entry) {
|
|
1104
1451
|
const trimmed = entry.line.trim();
|
|
@@ -1109,7 +1456,7 @@ function appendWatchTranscriptRawEntry(messages, entry) {
|
|
|
1109
1456
|
const parsed = JSON.parse(trimmed);
|
|
1110
1457
|
const type = typeof parsed.type === 'string' ? parsed.type : '';
|
|
1111
1458
|
if (type === 'user.turn' && typeof parsed.text === 'string') {
|
|
1112
|
-
pushWatchTranscriptMessage(messages, 'user', parsed.text, entry.timestamp);
|
|
1459
|
+
pushWatchTranscriptMessage(messages, 'user', 'user', parsed.text, entry.timestamp);
|
|
1113
1460
|
return;
|
|
1114
1461
|
}
|
|
1115
1462
|
if (type === 'turn.start') {
|
|
@@ -1117,24 +1464,24 @@ function appendWatchTranscriptRawEntry(messages, entry) {
|
|
|
1117
1464
|
const args = Array.isArray(parsed.args)
|
|
1118
1465
|
? parsed.args.filter((value) => typeof value === 'string')
|
|
1119
1466
|
: [];
|
|
1120
|
-
pushWatchTranscriptMessage(messages, 'system', `[turn] ${[command, ...args].join(' ').trim()}`, entry.timestamp);
|
|
1467
|
+
pushWatchTranscriptMessage(messages, 'system', 'system', `[turn] ${[command, ...args].join(' ').trim()}`, entry.timestamp);
|
|
1121
1468
|
return;
|
|
1122
1469
|
}
|
|
1123
1470
|
if (type === 'credentials.resolve') {
|
|
1124
1471
|
const requested = typeof parsed.requestedCredentialSource === 'string' ? parsed.requestedCredentialSource : 'auto';
|
|
1125
1472
|
const resolved = typeof parsed.resolvedCredentialSource === 'string' ? parsed.resolvedCredentialSource : requested;
|
|
1126
|
-
pushWatchTranscriptMessage(messages, 'system', `[credentials] ${requested} -> ${resolved}`, entry.timestamp);
|
|
1473
|
+
pushWatchTranscriptMessage(messages, 'system', 'system', `[credentials] ${requested} -> ${resolved}`, entry.timestamp);
|
|
1127
1474
|
return;
|
|
1128
1475
|
}
|
|
1129
1476
|
if (type === 'process.error' && typeof parsed.message === 'string') {
|
|
1130
|
-
pushWatchTranscriptMessage(messages, 'system', `[error] ${parsed.message}`, entry.timestamp);
|
|
1477
|
+
pushWatchTranscriptMessage(messages, 'system', 'system', `[error] ${parsed.message}`, entry.timestamp);
|
|
1131
1478
|
return;
|
|
1132
1479
|
}
|
|
1133
1480
|
}
|
|
1134
1481
|
catch {
|
|
1135
1482
|
// Keep original line when it is not structured JSON.
|
|
1136
1483
|
}
|
|
1137
|
-
pushWatchTranscriptMessage(messages, 'system', entry.stream === 'stderr' ? `stderr> ${trimmed}` : trimmed, entry.timestamp);
|
|
1484
|
+
pushWatchTranscriptMessage(messages, 'system', entry.stream === 'stderr' ? 'system' : 'primary-agent', entry.stream === 'stderr' ? `stderr> ${trimmed}` : trimmed, entry.timestamp);
|
|
1138
1485
|
}
|
|
1139
1486
|
export function buildWatchTranscriptMessages(entries) {
|
|
1140
1487
|
const messages = [];
|
package/package.json
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@undefineds.co/models",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.16",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
6
8
|
"exports": {
|
|
7
9
|
".": {
|
|
8
10
|
"types": "./dist/index.d.ts",
|
|
@@ -69,8 +71,6 @@
|
|
|
69
71
|
"typescript": "^5.4.0",
|
|
70
72
|
"vitest": "^1.6.0"
|
|
71
73
|
},
|
|
72
|
-
"main": "./dist/index.js",
|
|
73
|
-
"types": "./dist/index.d.ts",
|
|
74
74
|
"files": [
|
|
75
75
|
"dist",
|
|
76
76
|
"README.md",
|