@vellumai/assistant 0.3.14 → 0.3.15
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/Dockerfile +1 -1
- package/package.json +1 -1
- package/src/__tests__/guardian-control-plane-policy.test.ts +1 -3
- package/src/__tests__/guardian-outbound-http.test.ts +8 -8
- package/src/__tests__/notification-routing-intent.test.ts +0 -1
- package/src/__tests__/recording-intent-fallback.test.ts +0 -1
- package/src/__tests__/recording-intent-handler.test.ts +6 -3
- package/src/__tests__/recording-intent.test.ts +2 -2
- package/src/__tests__/recording-state-machine.test.ts +11 -11
- package/src/daemon/handlers/config-channels.ts +6 -6
- package/src/daemon/handlers/index.ts +1 -1
- package/src/daemon/handlers/misc.ts +1 -1
- package/src/daemon/handlers/sessions.ts +7 -7
- package/src/daemon/recording-executor.ts +1 -1
- package/src/daemon/recording-intent.ts +1 -1
- package/src/daemon/session-tool-setup.ts +1 -1
- package/src/memory/conversation-attention-store.ts +5 -5
- package/src/runtime/guardian-outbound-actions.ts +9 -9
- package/src/runtime/http-server.ts +7 -7
- package/src/runtime/routes/conversation-attention-routes.ts +3 -3
- package/src/runtime/routes/integration-routes.ts +5 -5
- package/src/schedule/scheduler.ts +1 -1
- package/src/tools/executor.ts +1 -1
package/Dockerfile
CHANGED
package/package.json
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
import { afterAll,
|
|
1
|
+
import { afterAll, beforeEach, describe, expect, mock, test } from 'bun:test';
|
|
2
2
|
|
|
3
|
-
import type { PolicyContext } from '../permissions/types.js';
|
|
4
|
-
import { RiskLevel } from '../permissions/types.js';
|
|
5
3
|
import type { ToolExecutionResult, ToolLifecycleEvent, ToolPermissionDeniedEvent } from '../tools/types.js';
|
|
6
4
|
|
|
7
5
|
// ── Module mocks (must precede real imports) ─────────────────────────
|
|
@@ -92,20 +92,20 @@ globalThis.fetch = (async (input: string | URL | Request, init?: RequestInit) =>
|
|
|
92
92
|
// Now import modules under test (after mocks are in place)
|
|
93
93
|
// ---------------------------------------------------------------------------
|
|
94
94
|
|
|
95
|
+
import { getDb, initializeDb, resetDb } from '../memory/db.js';
|
|
96
|
+
import {
|
|
97
|
+
updateSessionDelivery,
|
|
98
|
+
} from '../runtime/channel-guardian-service.js';
|
|
95
99
|
import {
|
|
96
|
-
startOutbound,
|
|
97
|
-
resendOutbound,
|
|
98
100
|
cancelOutbound,
|
|
101
|
+
resendOutbound,
|
|
102
|
+
startOutbound,
|
|
99
103
|
} from '../runtime/guardian-outbound-actions.js';
|
|
100
104
|
import {
|
|
101
|
-
handleStartOutbound,
|
|
102
|
-
handleResendOutbound,
|
|
103
105
|
handleCancelOutbound,
|
|
106
|
+
handleResendOutbound,
|
|
107
|
+
handleStartOutbound,
|
|
104
108
|
} from '../runtime/routes/integration-routes.js';
|
|
105
|
-
import {
|
|
106
|
-
updateSessionDelivery,
|
|
107
|
-
} from '../runtime/channel-guardian-service.js';
|
|
108
|
-
import { getDb, initializeDb, resetDb } from '../memory/db.js';
|
|
109
109
|
|
|
110
110
|
// Initialize the database (creates all tables)
|
|
111
111
|
initializeDb();
|
|
@@ -18,7 +18,6 @@ mock.module('../util/logger.js', () => ({
|
|
|
18
18
|
}));
|
|
19
19
|
|
|
20
20
|
import { enforceRoutingIntent } from '../notifications/decision-engine.js';
|
|
21
|
-
import type { RoutingIntent } from '../notifications/signal.js';
|
|
22
21
|
import type { NotificationChannel, NotificationDecision } from '../notifications/types.js';
|
|
23
22
|
|
|
24
23
|
// -- Helpers -----------------------------------------------------------------
|
|
@@ -83,6 +83,7 @@ let mockIntentResult: RecordingIntentResult = { kind: 'none' };
|
|
|
83
83
|
// Capture real function references BEFORE mock.module replaces the module.
|
|
84
84
|
// require() at this point returns the real module since mock.module has not
|
|
85
85
|
// been called yet for this specifier.
|
|
86
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
86
87
|
const _realRecordingIntentMod = require('../daemon/recording-intent.js');
|
|
87
88
|
const _realResolveRecordingIntent = _realRecordingIntentMod.resolveRecordingIntent;
|
|
88
89
|
const _realStripDynamicNames = _realRecordingIntentMod.stripDynamicNames;
|
|
@@ -125,6 +126,7 @@ let executorCalled = false;
|
|
|
125
126
|
|
|
126
127
|
let _realExecuteRecordingIntent: ((...args: any[]) => any) | null = null;
|
|
127
128
|
try {
|
|
129
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
128
130
|
const _mod = require('../daemon/recording-executor.js');
|
|
129
131
|
_realExecuteRecordingIntent = _mod.executeRecordingIntent;
|
|
130
132
|
} catch {
|
|
@@ -152,7 +154,7 @@ mock.module('../daemon/recording-executor.js', () => ({
|
|
|
152
154
|
// handlers/recording.js, it gets the real behavior.
|
|
153
155
|
|
|
154
156
|
let recordingStartCalled = false;
|
|
155
|
-
let
|
|
157
|
+
let _recordingStopCalled = false;
|
|
156
158
|
let recordingRestartCalled = false;
|
|
157
159
|
let recordingPauseCalled = false;
|
|
158
160
|
let recordingResumeCalled = false;
|
|
@@ -167,6 +169,7 @@ let _realRecordingHandlers: any = {};
|
|
|
167
169
|
let _realResetRecordingState: ((...args: any[]) => any) | null = null;
|
|
168
170
|
|
|
169
171
|
try {
|
|
172
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
170
173
|
const _mod = require('../daemon/handlers/recording.js');
|
|
171
174
|
_realHandleRecordingStart = _mod.handleRecordingStart;
|
|
172
175
|
_realHandleRecordingStop = _mod.handleRecordingStop;
|
|
@@ -190,7 +193,7 @@ mock.module('../daemon/handlers/recording.js', () => ({
|
|
|
190
193
|
},
|
|
191
194
|
handleRecordingStop: (...args: any[]) => {
|
|
192
195
|
if ((globalThis as any).__riHandlerUseMockIntent) {
|
|
193
|
-
|
|
196
|
+
_recordingStopCalled = true;
|
|
194
197
|
return 'mock-recording-id';
|
|
195
198
|
}
|
|
196
199
|
return _realHandleRecordingStop?.(...args);
|
|
@@ -420,7 +423,7 @@ function resetMockState(): void {
|
|
|
420
423
|
mockExecuteResult = { handled: false };
|
|
421
424
|
mockAssistantName = null;
|
|
422
425
|
recordingStartCalled = false;
|
|
423
|
-
|
|
426
|
+
_recordingStopCalled = false;
|
|
424
427
|
recordingRestartCalled = false;
|
|
425
428
|
recordingPauseCalled = false;
|
|
426
429
|
recordingResumeCalled = false;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { describe,
|
|
1
|
+
import { beforeEach,describe, expect, mock, test } from 'bun:test';
|
|
2
|
+
|
|
2
3
|
import {
|
|
3
4
|
resolveRecordingIntent,
|
|
4
|
-
type RecordingIntentResult,
|
|
5
5
|
} from '../daemon/recording-intent.js';
|
|
6
6
|
|
|
7
7
|
// ─── resolveRecordingIntent ─────────────────────────────────────────────────
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
-
import { describe, test, expect, beforeEach, mock } from 'bun:test';
|
|
3
1
|
import * as net from 'node:net';
|
|
4
2
|
|
|
3
|
+
import { beforeEach, describe, expect, mock,test } from 'bun:test';
|
|
4
|
+
|
|
5
5
|
// ─── Mocks (must be before any imports that depend on them) ─────────────────
|
|
6
6
|
|
|
7
7
|
const noop = () => {};
|
|
@@ -66,8 +66,8 @@ mock.module('../memory/attachments-store.js', () => ({
|
|
|
66
66
|
}));
|
|
67
67
|
|
|
68
68
|
// Mock node:fs
|
|
69
|
-
mock.module('node:fs', () => {
|
|
70
|
-
const realFs =
|
|
69
|
+
mock.module('node:fs', async () => {
|
|
70
|
+
const realFs = await import('fs');
|
|
71
71
|
return {
|
|
72
72
|
...realFs,
|
|
73
73
|
existsSync: (p: string) => {
|
|
@@ -89,19 +89,19 @@ mock.module('../daemon/video-thumbnail.js', () => ({
|
|
|
89
89
|
// ─── Imports (after mocks) ──────────────────────────────────────────────────
|
|
90
90
|
|
|
91
91
|
import {
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
handleRecordingRestart,
|
|
92
|
+
__resetRecordingState,
|
|
93
|
+
getActiveRestartToken,
|
|
95
94
|
handleRecordingPause,
|
|
95
|
+
handleRecordingRestart,
|
|
96
96
|
handleRecordingResume,
|
|
97
|
+
handleRecordingStart,
|
|
98
|
+
handleRecordingStop,
|
|
97
99
|
isRecordingIdle,
|
|
98
|
-
getActiveRestartToken,
|
|
99
100
|
recordingHandlers,
|
|
100
|
-
__resetRecordingState,
|
|
101
101
|
} from '../daemon/handlers/recording.js';
|
|
102
|
-
import { executeRecordingIntent } from '../daemon/recording-executor.js';
|
|
103
102
|
import type { HandlerContext } from '../daemon/handlers/shared.js';
|
|
104
103
|
import type { RecordingStatus } from '../daemon/ipc-contract/computer-use.js';
|
|
104
|
+
import { executeRecordingIntent } from '../daemon/recording-executor.js';
|
|
105
105
|
import { DebouncerMap } from '../util/debounce.js';
|
|
106
106
|
|
|
107
107
|
// ─── Test helpers ───────────────────────────────────────────────────────────
|
|
@@ -996,7 +996,7 @@ describe('deferred restart prevents race condition', () => {
|
|
|
996
996
|
|
|
997
997
|
test('stop-ack timeout cleans up deferred restart state', () => {
|
|
998
998
|
// This test uses a real timer via bun's jest-compatible API
|
|
999
|
-
const { ctx,
|
|
999
|
+
const { ctx, fakeSocket } = createCtx();
|
|
1000
1000
|
const conversationId = 'conv-deferred-timeout';
|
|
1001
1001
|
ctx.socketToSession.set(fakeSocket, conversationId);
|
|
1002
1002
|
|
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
import * as net from 'node:net';
|
|
2
2
|
|
|
3
|
+
import type { ChannelId } from '../../channels/types.js';
|
|
3
4
|
import * as externalConversationStore from '../../memory/external-conversation-store.js';
|
|
4
5
|
import {
|
|
5
6
|
createVerificationChallenge,
|
|
7
|
+
findActiveSession,
|
|
6
8
|
getGuardianBinding,
|
|
7
9
|
getPendingChallenge,
|
|
8
10
|
revokeBinding as revokeGuardianBinding,
|
|
9
11
|
revokePendingChallenges,
|
|
10
|
-
findActiveSession,
|
|
11
12
|
} from '../../runtime/channel-guardian-service.js';
|
|
12
13
|
import { type ChannelReadinessService, createReadinessService } from '../../runtime/channel-readiness-service.js';
|
|
13
14
|
import {
|
|
14
|
-
startOutbound,
|
|
15
|
-
resendOutbound,
|
|
16
15
|
cancelOutbound,
|
|
16
|
+
resendOutbound,
|
|
17
|
+
startOutbound,
|
|
17
18
|
} from '../../runtime/guardian-outbound-actions.js';
|
|
18
19
|
import { normalizeAssistantId } from '../../util/platform.js';
|
|
19
|
-
import type { ChannelId } from '../../channels/types.js';
|
|
20
20
|
import type {
|
|
21
21
|
ChannelReadinessRequest,
|
|
22
22
|
GuardianVerificationRequest,
|
|
@@ -34,10 +34,10 @@ export type GuardianVerificationResult = Omit<GuardianVerificationResponse, 'typ
|
|
|
34
34
|
// ---------------------------------------------------------------------------
|
|
35
35
|
|
|
36
36
|
export {
|
|
37
|
+
DESTINATION_RATE_WINDOW_MS,
|
|
38
|
+
MAX_SENDS_PER_DESTINATION_WINDOW,
|
|
37
39
|
MAX_SENDS_PER_SESSION,
|
|
38
40
|
RESEND_COOLDOWN_MS,
|
|
39
|
-
MAX_SENDS_PER_DESTINATION_WINDOW,
|
|
40
|
-
DESTINATION_RATE_WINDOW_MS,
|
|
41
41
|
} from '../../runtime/guardian-outbound-actions.js';
|
|
42
42
|
|
|
43
43
|
// ---------------------------------------------------------------------------
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as net from 'node:net';
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { type Confidence, recordConversationSeenSignal, type SignalType } from '../../memory/conversation-attention-store.js';
|
|
4
4
|
import { updateDeliveryClientOutcome } from '../../notifications/deliveries-store.js';
|
|
5
5
|
import type { ClientMessage } from '../ipc-protocol.js';
|
|
6
6
|
import { handleRideShotgunStart, handleRideShotgunStop } from '../ride-shotgun-handler.js';
|
|
@@ -22,8 +22,8 @@ import type {
|
|
|
22
22
|
TaskSubmit,
|
|
23
23
|
} from '../ipc-protocol.js';
|
|
24
24
|
import { executeRecordingIntent } from '../recording-executor.js';
|
|
25
|
-
import { classifyRecordingIntentFallback, containsRecordingKeywords } from '../recording-intent-fallback.js';
|
|
26
25
|
import { resolveRecordingIntent } from '../recording-intent.js';
|
|
26
|
+
import { classifyRecordingIntentFallback, containsRecordingKeywords } from '../recording-intent-fallback.js';
|
|
27
27
|
import { buildSessionErrorMessage,classifySessionError } from '../session-error.js';
|
|
28
28
|
import { handleCuSessionCreate } from './computer-use.js';
|
|
29
29
|
import { handleRecordingPause, handleRecordingRestart, handleRecordingResume, handleRecordingStart, handleRecordingStop, isRecordingIdle } from './recording.js';
|
|
@@ -36,8 +36,8 @@ import type {
|
|
|
36
36
|
} from '../ipc-protocol.js';
|
|
37
37
|
import { normalizeThreadType } from '../ipc-protocol.js';
|
|
38
38
|
import { executeRecordingIntent } from '../recording-executor.js';
|
|
39
|
-
import { classifyRecordingIntentFallback, containsRecordingKeywords } from '../recording-intent-fallback.js';
|
|
40
39
|
import { resolveRecordingIntent } from '../recording-intent.js';
|
|
40
|
+
import { classifyRecordingIntentFallback, containsRecordingKeywords } from '../recording-intent-fallback.js';
|
|
41
41
|
import { buildSessionErrorMessage,classifySessionError } from '../session-error.js';
|
|
42
42
|
import { generateVideoThumbnail } from '../video-thumbnail.js';
|
|
43
43
|
import { handleRecordingPause, handleRecordingRestart, handleRecordingResume, handleRecordingStart, handleRecordingStop } from './recording.js';
|
|
@@ -479,12 +479,12 @@ export function handleSessionList(socket: net.Socket, ctx: HandlerContext, offse
|
|
|
479
479
|
const originInterface = parseInterfaceId(c.originInterface);
|
|
480
480
|
const attn = attentionStates.get(c.id);
|
|
481
481
|
const assistantAttention = attn ? {
|
|
482
|
-
hasUnseenLatestAssistantMessage: attn.latestAssistantMessageAt
|
|
483
|
-
(attn.lastSeenAssistantMessageAt
|
|
484
|
-
...(attn.latestAssistantMessageAt
|
|
485
|
-
...(attn.lastSeenAssistantMessageAt
|
|
486
|
-
...(attn.lastSeenConfidence
|
|
487
|
-
...(attn.lastSeenSignalType
|
|
482
|
+
hasUnseenLatestAssistantMessage: attn.latestAssistantMessageAt != null &&
|
|
483
|
+
(attn.lastSeenAssistantMessageAt == null || attn.lastSeenAssistantMessageAt < attn.latestAssistantMessageAt),
|
|
484
|
+
...(attn.latestAssistantMessageAt != null ? { latestAssistantMessageAt: attn.latestAssistantMessageAt } : {}),
|
|
485
|
+
...(attn.lastSeenAssistantMessageAt != null ? { lastSeenAssistantMessageAt: attn.lastSeenAssistantMessageAt } : {}),
|
|
486
|
+
...(attn.lastSeenConfidence != null ? { lastSeenConfidence: attn.lastSeenConfidence } : {}),
|
|
487
|
+
...(attn.lastSeenSignalType != null ? { lastSeenSignalType: attn.lastSeenSignalType } : {}),
|
|
488
488
|
} : undefined;
|
|
489
489
|
return {
|
|
490
490
|
id: c.id,
|
|
@@ -5,7 +5,6 @@
|
|
|
5
5
|
|
|
6
6
|
import type * as net from 'node:net';
|
|
7
7
|
|
|
8
|
-
import type { HandlerContext } from './handlers/shared.js';
|
|
9
8
|
import {
|
|
10
9
|
handleRecordingPause,
|
|
11
10
|
handleRecordingRestart,
|
|
@@ -14,6 +13,7 @@ import {
|
|
|
14
13
|
handleRecordingStop,
|
|
15
14
|
isRecordingIdle,
|
|
16
15
|
} from './handlers/recording.js';
|
|
16
|
+
import type { HandlerContext } from './handlers/shared.js';
|
|
17
17
|
import type { RecordingIntentResult } from './recording-intent.js';
|
|
18
18
|
|
|
19
19
|
export interface RecordingExecutionContext {
|
|
@@ -383,7 +383,7 @@ function isInterrogative(text: string, dynamicNames?: string[]): boolean {
|
|
|
383
383
|
* If `dynamicNames` are provided, they are stripped from the beginning of the
|
|
384
384
|
* text before classification (e.g., "Nova, record my screen" -> "record my screen").
|
|
385
385
|
*/
|
|
386
|
-
function
|
|
386
|
+
function _classifyRecordingIntent(
|
|
387
387
|
taskText: string,
|
|
388
388
|
dynamicNames?: string[],
|
|
389
389
|
): RecordingIntentClass {
|
|
@@ -25,8 +25,8 @@ import { requestComputerControlTool } from '../tools/computer-use/request-comput
|
|
|
25
25
|
import type { ProxyApprovalCallback, ProxyApprovalRequest } from '../tools/network/script-proxy/index.js';
|
|
26
26
|
import { getAllToolDefinitions } from '../tools/registry.js';
|
|
27
27
|
import { allUiSurfaceTools } from '../tools/ui-surface/definitions.js';
|
|
28
|
-
import { projectSkillTools, type SkillProjectionCache } from './session-skill-tools.js';
|
|
29
28
|
import type { GuardianRuntimeContext } from './session-runtime-assembly.js';
|
|
29
|
+
import { projectSkillTools, type SkillProjectionCache } from './session-skill-tools.js';
|
|
30
30
|
import type { SurfaceSessionContext } from './session-surfaces.js';
|
|
31
31
|
import {
|
|
32
32
|
surfaceProxyResolver,
|
|
@@ -13,7 +13,7 @@ import { getLogger } from '../util/logger.js';
|
|
|
13
13
|
import { getDb } from './db.js';
|
|
14
14
|
import { conversationAssistantAttentionState, conversationAttentionEvents, conversations, messages } from './schema.js';
|
|
15
15
|
|
|
16
|
-
const
|
|
16
|
+
const _log = getLogger('conversation-attention-store');
|
|
17
17
|
|
|
18
18
|
// ── Types ────────────────────────────────────────────────────────────
|
|
19
19
|
|
|
@@ -138,7 +138,7 @@ export function projectAssistantMessage(params: {
|
|
|
138
138
|
}
|
|
139
139
|
|
|
140
140
|
// Monotonic: only advance if the new message is strictly later
|
|
141
|
-
if (existing.latestAssistantMessageAt
|
|
141
|
+
if (existing.latestAssistantMessageAt != null && messageAt <= existing.latestAssistantMessageAt) {
|
|
142
142
|
return;
|
|
143
143
|
}
|
|
144
144
|
|
|
@@ -251,8 +251,8 @@ export function recordConversationSeenSignal(params: {
|
|
|
251
251
|
// Only advance the seen cursor if there is a latest assistant message to mark as seen,
|
|
252
252
|
// and the seen cursor hasn't already reached or passed it (monotonic invariant).
|
|
253
253
|
const shouldAdvanceSeen =
|
|
254
|
-
state.latestAssistantMessageAt
|
|
255
|
-
(state.lastSeenAssistantMessageAt
|
|
254
|
+
state.latestAssistantMessageAt != null &&
|
|
255
|
+
(state.lastSeenAssistantMessageAt == null ||
|
|
256
256
|
state.latestAssistantMessageAt > state.lastSeenAssistantMessageAt);
|
|
257
257
|
|
|
258
258
|
// Guard seen metadata monotonicity: only update lastSeen* metadata when the
|
|
@@ -260,7 +260,7 @@ export function recordConversationSeenSignal(params: {
|
|
|
260
260
|
// Out-of-order delivery (e.g. delayed channel callbacks) must not regress
|
|
261
261
|
// the projected channel/source/confidence metadata.
|
|
262
262
|
const isNewerSignal =
|
|
263
|
-
state.lastSeenEventAt
|
|
263
|
+
state.lastSeenEventAt == null || eventObservedAt >= state.lastSeenEventAt;
|
|
264
264
|
|
|
265
265
|
const updates: Record<string, unknown> = {
|
|
266
266
|
updatedAt: now,
|
|
@@ -7,8 +7,16 @@
|
|
|
7
7
|
* IPC handler (config-channels.ts) and the HTTP route layer (integration-routes.ts).
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
import { randomBytes
|
|
10
|
+
import { createHash,randomBytes } from 'node:crypto';
|
|
11
11
|
|
|
12
|
+
import { startGuardianVerificationCall } from '../calls/call-domain.js';
|
|
13
|
+
import type { ChannelId } from '../channels/types.js';
|
|
14
|
+
import { getGatewayInternalBaseUrl } from '../config/env.js';
|
|
15
|
+
import { sendMessage as sendSms } from '../messaging/providers/sms/client.js';
|
|
16
|
+
import { getCredentialMetadata } from '../tools/credentials/metadata-store.js';
|
|
17
|
+
import { getLogger } from '../util/logger.js';
|
|
18
|
+
import { normalizePhoneNumber } from '../util/phone.js';
|
|
19
|
+
import { normalizeAssistantId, readHttpToken } from '../util/platform.js';
|
|
12
20
|
import {
|
|
13
21
|
countRecentSendsToDestination,
|
|
14
22
|
createOutboundSession,
|
|
@@ -22,14 +30,6 @@ import {
|
|
|
22
30
|
composeVerificationTelegram,
|
|
23
31
|
GUARDIAN_VERIFY_TEMPLATE_KEYS,
|
|
24
32
|
} from './guardian-verification-templates.js';
|
|
25
|
-
import { startGuardianVerificationCall } from '../calls/call-domain.js';
|
|
26
|
-
import { sendMessage as sendSms } from '../messaging/providers/sms/client.js';
|
|
27
|
-
import { getGatewayInternalBaseUrl } from '../config/env.js';
|
|
28
|
-
import { getCredentialMetadata } from '../tools/credentials/metadata-store.js';
|
|
29
|
-
import { normalizePhoneNumber } from '../util/phone.js';
|
|
30
|
-
import { normalizeAssistantId, readHttpToken } from '../util/platform.js';
|
|
31
|
-
import { getLogger } from '../util/logger.js';
|
|
32
|
-
import type { ChannelId } from '../channels/types.js';
|
|
33
33
|
|
|
34
34
|
const log = getLogger('guardian-outbound-actions');
|
|
35
35
|
|
|
@@ -29,7 +29,7 @@ import {
|
|
|
29
29
|
} from '../config/env.js';
|
|
30
30
|
import type { ServerMessage } from '../daemon/ipc-contract.js';
|
|
31
31
|
import { PairingStore } from '../daemon/pairing-store.js';
|
|
32
|
-
import { type Confidence,
|
|
32
|
+
import { type Confidence, getAttentionStateByConversationIds, recordConversationSeenSignal,type SignalType } from '../memory/conversation-attention-store.js';
|
|
33
33
|
import * as conversationStore from '../memory/conversation-store.js';
|
|
34
34
|
import * as externalConversationStore from '../memory/external-conversation-store.js';
|
|
35
35
|
import { consumeCallback, consumeCallbackError } from '../security/oauth-callback-registry.js';
|
|
@@ -549,12 +549,12 @@ export class RuntimeHttpServer {
|
|
|
549
549
|
const originChannel = parseChannelId(c.originChannel);
|
|
550
550
|
const attn = attentionStates.get(c.id);
|
|
551
551
|
const assistantAttention = attn ? {
|
|
552
|
-
hasUnseenLatestAssistantMessage: attn.latestAssistantMessageAt
|
|
553
|
-
(attn.lastSeenAssistantMessageAt
|
|
554
|
-
...(attn.latestAssistantMessageAt
|
|
555
|
-
...(attn.lastSeenAssistantMessageAt
|
|
556
|
-
...(attn.lastSeenConfidence
|
|
557
|
-
...(attn.lastSeenSignalType
|
|
552
|
+
hasUnseenLatestAssistantMessage: attn.latestAssistantMessageAt != null &&
|
|
553
|
+
(attn.lastSeenAssistantMessageAt == null || attn.lastSeenAssistantMessageAt < attn.latestAssistantMessageAt),
|
|
554
|
+
...(attn.latestAssistantMessageAt != null ? { latestAssistantMessageAt: attn.latestAssistantMessageAt } : {}),
|
|
555
|
+
...(attn.lastSeenAssistantMessageAt != null ? { lastSeenAssistantMessageAt: attn.lastSeenAssistantMessageAt } : {}),
|
|
556
|
+
...(attn.lastSeenConfidence != null ? { lastSeenConfidence: attn.lastSeenConfidence } : {}),
|
|
557
|
+
...(attn.lastSeenSignalType != null ? { lastSeenSignalType: attn.lastSeenSignalType } : {}),
|
|
558
558
|
} : undefined;
|
|
559
559
|
return {
|
|
560
560
|
id: c.id,
|
|
@@ -61,9 +61,9 @@ export function handleListConversationAttention(url: URL): Response {
|
|
|
61
61
|
const results = pageStates.map((attn) => {
|
|
62
62
|
const conv = conversationMap.get(attn.conversationId);
|
|
63
63
|
const convSource = conv?.source ?? 'user';
|
|
64
|
-
const hasUnseen = attn.latestAssistantMessageAt
|
|
65
|
-
(attn.lastSeenAssistantMessageAt
|
|
66
|
-
const state: 'seen' | 'unseen' | 'no_assistant_message' = attn.latestAssistantMessageAt
|
|
64
|
+
const hasUnseen = attn.latestAssistantMessageAt != null &&
|
|
65
|
+
(attn.lastSeenAssistantMessageAt == null || attn.lastSeenAssistantMessageAt < attn.latestAssistantMessageAt);
|
|
66
|
+
const state: 'seen' | 'unseen' | 'no_assistant_message' = attn.latestAssistantMessageAt == null
|
|
67
67
|
? 'no_assistant_message'
|
|
68
68
|
: hasUnseen ? 'unseen' : 'seen';
|
|
69
69
|
|
|
@@ -21,11 +21,6 @@ import {
|
|
|
21
21
|
createGuardianChallenge,
|
|
22
22
|
getGuardianStatus,
|
|
23
23
|
} from '../../daemon/handlers/config-channels.js';
|
|
24
|
-
import {
|
|
25
|
-
startOutbound,
|
|
26
|
-
resendOutbound,
|
|
27
|
-
cancelOutbound,
|
|
28
|
-
} from '../guardian-outbound-actions.js';
|
|
29
24
|
import {
|
|
30
25
|
clearTelegramConfig,
|
|
31
26
|
getTelegramConfig,
|
|
@@ -33,6 +28,11 @@ import {
|
|
|
33
28
|
setTelegramConfig,
|
|
34
29
|
setupTelegram,
|
|
35
30
|
} from '../../daemon/handlers/config-telegram.js';
|
|
31
|
+
import {
|
|
32
|
+
cancelOutbound,
|
|
33
|
+
resendOutbound,
|
|
34
|
+
startOutbound,
|
|
35
|
+
} from '../guardian-outbound-actions.js';
|
|
36
36
|
|
|
37
37
|
/**
|
|
38
38
|
* GET /v1/integrations/telegram/config
|
|
@@ -2,7 +2,7 @@ import { createConversation } from '../memory/conversation-store.js';
|
|
|
2
2
|
import { GENERATING_TITLE, queueGenerateConversationTitle } from '../memory/conversation-title-service.js';
|
|
3
3
|
import { invalidateAssistantInferredItemsForConversation } from '../memory/task-memory-cleanup.js';
|
|
4
4
|
import { runSequencesOnce } from '../sequence/engine.js';
|
|
5
|
-
import { claimDueReminders, completeReminder, failReminder,
|
|
5
|
+
import { claimDueReminders, completeReminder, failReminder, type RoutingIntent,setReminderConversationId } from '../tools/reminder/reminder-store.js';
|
|
6
6
|
import { getLogger } from '../util/logger.js';
|
|
7
7
|
import { runWatchersOnce, type WatcherEscalator,type WatcherNotifier } from '../watcher/engine.js';
|
|
8
8
|
import { hasSetConstructs } from './recurrence-engine.js';
|
package/src/tools/executor.ts
CHANGED
|
@@ -15,8 +15,8 @@ import { PermissionDeniedError,ToolError } from '../util/errors.js';
|
|
|
15
15
|
import { pathExists, safeStatSync } from '../util/fs.js';
|
|
16
16
|
import { getLogger } from '../util/logger.js';
|
|
17
17
|
import { resolveExecutionTarget } from './execution-target.js';
|
|
18
|
-
import { enforceGuardianOnlyPolicy } from './guardian-control-plane-policy.js';
|
|
19
18
|
import { executeWithTimeout,safeTimeoutMs } from './execution-timeout.js';
|
|
19
|
+
import { enforceGuardianOnlyPolicy } from './guardian-control-plane-policy.js';
|
|
20
20
|
import { buildPolicyContext } from './policy-context.js';
|
|
21
21
|
import { getAllTools,getTool } from './registry.js';
|
|
22
22
|
import { applyEdit } from './shared/filesystem/edit-engine.js';
|