File size: 3,595 Bytes
68d7816 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 | import { fromCallback, setup } from 'xstate';
import { createDecorator, IInstantiationService } from '#/_base/di/instantiation';
import {
AgentActorService,
type AgentActorContext,
type AgentActorRestoreEvent,
} from '#/agent/actorService/agentActorService';
import { IAgentContextMemoryService } from '#/agent/contextMemory/contextMemory';
import { IAgentScopeContext } from '#/agent/scopeContext/scopeContext';
import { IAgentToolRegistryService } from '#/agent/toolRegistry/toolRegistry';
import { IFlagService } from '#/app/flag/flag';
import { IAgentReminderService } from '#/features/reminder/reminderService';
import { IEventDispatcher } from '#/state/eventDispatcher';
import { NOTIFY_USER_FLAG_ID } from './flag';
import {
NOTIFY_USER_NUDGE_VARIANT,
lastMidResponsePosition,
renderMidResponseHint,
renderNotifyUserNudge,
shouldNudgeMidResponse,
shouldNudgeNotifyUser,
toolCallsSinceLastNotify,
toolCallsSincePosition,
} from './notifyUserNudge';
import { NOTIFY_USER_TOOL_NAME } from './tools/notify-user/notify-user';
interface NotifyUserNudgeActorContext {
readonly runtime: AgentActorContext<null>;
}
const notifyUserNudgeReminders = fromCallback(({
input,
}: {
input: {
readonly runtime: AgentActorContext<null>;
};
}) => {
const runtime = input.runtime;
if (!runtime.get(IFlagService).enabled(NOTIFY_USER_FLAG_ID)) return () => {};
const registration = runtime.get(IAgentReminderService).register(
NOTIFY_USER_NUDGE_VARIANT,
({ lastInjectedAt }): string | undefined => {
if (!runtime.get(IFlagService).enabled(NOTIFY_USER_FLAG_ID)) return undefined;
if (runtime.get(IAgentToolRegistryService).resolve(NOTIFY_USER_TOOL_NAME) === undefined) {
return undefined;
}
const history = runtime.get(IAgentContextMemoryService).get();
const streak = toolCallsSinceLastNotify(history);
const callsSinceLastNudge =
lastInjectedAt === null ? null : toolCallsSincePosition(history, lastInjectedAt);
if (shouldNudgeNotifyUser(streak, callsSinceLastNudge)) return renderNotifyUserNudge(streak);
if (shouldNudgeMidResponse(lastMidResponsePosition(history), lastInjectedAt)) {
return renderMidResponseHint();
}
return undefined;
},
);
return () => {
registration.dispose();
};
});
const notifyUserNudgeActorLogic = setup({
types: {} as {
context: NotifyUserNudgeActorContext;
input: AgentActorContext<null>;
events: AgentActorRestoreEvent;
},
actors: { notifyUserNudgeReminders },
}).createMachine({
context: ({ input }) => ({ runtime: input }),
initial: 'beforeRestore',
states: {
beforeRestore: {
on: { 'runtime.restore': 'active' },
},
active: {
invoke: {
src: 'notifyUserNudgeReminders',
input: ({ context }) => ({ runtime: context.runtime }),
},
},
},
});
export interface IAgentNotifyUserNudgeService {
readonly _serviceBrand: undefined;
}
export const IAgentNotifyUserNudgeService = createDecorator<IAgentNotifyUserNudgeService>(
'agentNotifyUserNudgeService',
);
export class AgentNotifyUserNudgeService
extends AgentActorService<null>
implements IAgentNotifyUserNudgeService
{
declare readonly _serviceBrand: undefined;
constructor(
@IEventDispatcher dispatcher: IEventDispatcher,
@IAgentScopeContext scopeContext: IAgentScopeContext,
@IInstantiationService instantiation: IInstantiationService,
) {
super(dispatcher, scopeContext, instantiation);
this.attachActor(notifyUserNudgeActorLogic, { id: 'notifyUserNudge' });
}
}
|