@promptbook/cli 0.114.0-12 → 0.114.0-13
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/apps/agents-server/src/app/agents/[agentName]/AgentChatWrapper.tsx +7 -4
- package/apps/agents-server/src/app/agents/[agentName]/chat/AgentGoalChatPlannedMessages.tsx +23 -8
- package/apps/agents-server/src/app/agents/[agentName]/chat/CanonicalAgentChatSurface.tsx +14 -3
- package/apps/agents-server/src/app/agents/[agentName]/chat/page.tsx +2 -20
- package/apps/agents-server/src/app/agents/[agentName]/page.tsx +2 -1
- package/apps/agents-server/src/app/agents/[agentName]/projectReferenceActions.ts +61 -0
- package/apps/agents-server/src/components/AgentProjects/resolveLatestCompletedAgentMessageKey.ts +32 -0
- package/apps/agents-server/src/components/AgentProjects/useAgentProjectMarkdownReferences.ts +124 -2
- package/apps/agents-server/src/languages/ServerTranslationKeys.ts +3 -0
- package/apps/agents-server/src/languages/translations/czech.yaml +3 -0
- package/apps/agents-server/src/languages/translations/english.yaml +3 -0
- package/apps/agents-server/src/tools/agentGoalChatTimeoutToolFunctions.ts +24 -2
- package/apps/agents-server/src/tools/agentGoalChatTimeoutTools.ts +5 -4
- package/apps/agents-server/src/utils/agentGoalChat/agentGoalChatPlannedMessageActions.ts +38 -9
- package/apps/agents-server/src/utils/agentGoalChat/createAgentGoalChatNoteContent.ts +15 -6
- package/apps/agents-server/src/utils/agentProjects/listAgentProjectNames.ts +35 -0
- package/apps/agents-server/src/utils/agentProjects/listAgentProjects.ts +6 -23
- package/apps/agents-server/src/utils/agentProjects/resolveAgentChatProjectReferences.ts +25 -0
- package/apps/agents-server/src/utils/chatMessageChips/createAnsweredMessageChipToolCalls.ts +37 -0
- package/apps/agents-server/src/utils/chatMessageChips/createPlannedMessageChipToolCalls.ts +39 -0
- package/apps/agents-server/src/utils/chatMessageChips/createTouchedProjectChipToolCalls.ts +75 -0
- package/apps/agents-server/src/utils/localChatRunner/applyLocalAgentPlannedMessageCommands.ts +212 -0
- package/apps/agents-server/src/utils/localChatRunner/prepareLocalAgentPlannedMessagesSidecar.ts +66 -0
- package/apps/agents-server/src/utils/localChatRunner/processLocalUserChatJob.ts +110 -22
- package/apps/agents-server/src/utils/userChat/persistUserChatJobTerminalState.ts +5 -0
- package/apps/agents-server/src/utils/userChat/userChatJobRunReport.ts +30 -0
- package/apps/agents-server/src/utils/userChatTimeout/createTimeoutWakeUpMessage.ts +9 -1
- package/apps/agents-server/src/utils/userChatTimeout/userChatTimeoutStore/repeatFiredUserChatTimeout.ts +74 -0
- package/apps/agents-server/src/utils/userChatTimeout/userChatTimeoutStore.ts +1 -0
- package/apps/agents-server/src/utils/userChatTimeout/userChatTimeoutWorker.ts +63 -54
- package/esm/index.es.js +639 -80
- package/esm/index.es.js.map +1 -1
- package/esm/scripts/run-agent-messages/messages/buildAgentGoalChatPromptSection.d.ts +22 -4
- package/esm/scripts/run-agent-messages/messages/buildAgentMessagePrompt.d.ts +3 -3
- package/esm/scripts/run-agent-messages/messages/loadAgentPlannedMessagesSidecar.d.ts +10 -0
- package/esm/scripts/run-agent-messages/messages/resolveTouchedAgentProjects.d.ts +15 -0
- package/esm/src/book-3.0/AgentMessageRunReport.d.ts +28 -0
- package/esm/src/book-3.0/AgentPlannedMessagesSidecar.d.ts +94 -0
- package/esm/src/book-3.0/AgentPlannedMessagesSidecar.test.d.ts +1 -0
- package/esm/src/book-3.0/createAgentMessageSidecarBaseName.d.ts +13 -0
- package/esm/src/book-components/Chat/utils/agentProjectToolCall.d.ts +46 -0
- package/esm/src/book-components/Chat/utils/timeoutToolCallPresentation.d.ts +24 -0
- package/esm/src/utils/agent-message-runtime/parseAgentMessageRuntimeLogEvents.d.ts +59 -0
- package/esm/src/utils/agent-message-runtime/resolveAgentMessageTouchedProjectNames.d.ts +19 -0
- package/esm/src/utils/agent-message-runtime/resolveAgentMessageTouchedProjectNames.test.d.ts +1 -0
- package/esm/src/version.d.ts +1 -1
- package/package.json +1 -1
- package/src/book-3.0/AgentMessageRunReport.ts +76 -0
- package/src/book-3.0/AgentPlannedMessagesSidecar.ts +229 -0
- package/src/book-3.0/AgentTeamConversationWorkspace.ts +3 -5
- package/src/book-3.0/createAgentMessageSidecarBaseName.ts +20 -0
- package/src/book-components/Chat/Chat/Chat.module.css +6 -1
- package/src/book-components/Chat/Chat/renderToolCallDetails.tsx +1 -12
- package/src/book-components/Chat/utils/agentProjectToolCall.ts +74 -0
- package/src/book-components/Chat/utils/getToolCallChipletInfo.ts +28 -0
- package/src/book-components/Chat/utils/timeoutToolCallPresentation.ts +23 -3
- package/src/other/templates/getTemplatesPipelineCollection.ts +784 -738
- package/src/utils/agent-message-runtime/parseAgentMessageRuntimeLogEvents.ts +105 -0
- package/src/utils/agent-message-runtime/resolveAgentMessageRuntimeActivity.ts +6 -54
- package/src/utils/agent-message-runtime/resolveAgentMessageTouchedProjectNames.ts +147 -0
- package/src/version.ts +2 -2
- package/src/versions.txt +1 -0
- package/umd/index.umd.js +639 -80
- package/umd/index.umd.js.map +1 -1
- package/umd/scripts/run-agent-messages/messages/buildAgentGoalChatPromptSection.d.ts +22 -4
- package/umd/scripts/run-agent-messages/messages/buildAgentMessagePrompt.d.ts +3 -3
- package/umd/scripts/run-agent-messages/messages/loadAgentPlannedMessagesSidecar.d.ts +10 -0
- package/umd/scripts/run-agent-messages/messages/resolveTouchedAgentProjects.d.ts +15 -0
- package/umd/src/book-3.0/AgentMessageRunReport.d.ts +28 -0
- package/umd/src/book-3.0/AgentPlannedMessagesSidecar.d.ts +94 -0
- package/umd/src/book-3.0/AgentPlannedMessagesSidecar.test.d.ts +1 -0
- package/umd/src/book-3.0/createAgentMessageSidecarBaseName.d.ts +13 -0
- package/umd/src/book-components/Chat/utils/agentProjectToolCall.d.ts +46 -0
- package/umd/src/book-components/Chat/utils/timeoutToolCallPresentation.d.ts +24 -0
- package/umd/src/utils/agent-message-runtime/parseAgentMessageRuntimeLogEvents.d.ts +59 -0
- package/umd/src/utils/agent-message-runtime/resolveAgentMessageTouchedProjectNames.d.ts +19 -0
- package/umd/src/utils/agent-message-runtime/resolveAgentMessageTouchedProjectNames.test.d.ts +1 -0
- package/umd/src/version.d.ts +1 -1
- package/esm/apps/agents-server/src/utils/agentGoalChat/agentGoalChatConstants.d.ts +0 -12
- package/umd/apps/agents-server/src/utils/agentGoalChat/agentGoalChatConstants.d.ts +0 -12
|
@@ -6,6 +6,7 @@ import { AgentChat, ChatMessage, useSendMessageToLlmChat } from '@promptbook-loc
|
|
|
6
6
|
import { RemoteAgent } from '@promptbook-local/core';
|
|
7
7
|
import { ClientVersionMismatchError } from '@promptbook-local/utils';
|
|
8
8
|
import { useCallback, useEffect, useMemo, useState, type CSSProperties } from 'react';
|
|
9
|
+
import { AGENT_PROJECT_TOOL_CALL_NAME } from '../../../../../../src/book-components/Chat/utils/agentProjectToolCall';
|
|
9
10
|
import { string_agent_url } from '../../../../../../src/types/typeAliases';
|
|
10
11
|
import type { AgentProjectItemInfo } from '../../../components/AgentProjects/AgentProjectReferencesList';
|
|
11
12
|
import { useAgentProjectMarkdownReferences } from '../../../components/AgentProjects/useAgentProjectMarkdownReferences';
|
|
@@ -144,10 +145,6 @@ export function AgentChatWrapper(props: AgentChatWrapperProps) {
|
|
|
144
145
|
|
|
145
146
|
const { value: agent } = usePromise(agentPromise, [agentPromise]);
|
|
146
147
|
const teamAgentProfiles = useTeamAgentProfiles(agent?.capabilities);
|
|
147
|
-
const markdownInlineReferences = useAgentProjectMarkdownReferences({
|
|
148
|
-
agentPermanentId: agentName,
|
|
149
|
-
projects: projectReferences,
|
|
150
|
-
});
|
|
151
148
|
|
|
152
149
|
// Error state management
|
|
153
150
|
const [currentError, setCurrentError] = useState<FriendlyErrorMessage | null>(null);
|
|
@@ -157,6 +154,11 @@ export function AgentChatWrapper(props: AgentChatWrapperProps) {
|
|
|
157
154
|
const [githubAppStatus, setGithubAppStatus] = useState<GithubAppStatusResponse | null>(null);
|
|
158
155
|
const [calendarOAuthStatus, setCalendarOAuthStatus] = useState<CalendarOAuthStatusResponse | null>(null);
|
|
159
156
|
const [renderedMessages, setRenderedMessages] = useState<ReadonlyArray<ChatMessage>>([]);
|
|
157
|
+
const markdownInlineReferences = useAgentProjectMarkdownReferences({
|
|
158
|
+
agentPermanentId: agentName,
|
|
159
|
+
projects: projectReferences,
|
|
160
|
+
messages: renderedMessages,
|
|
161
|
+
});
|
|
160
162
|
const currentAgentPermanentId = useMemo(() => {
|
|
161
163
|
return typeof (agent as { permanentId?: unknown } | undefined)?.permanentId === 'string'
|
|
162
164
|
? ((agent as { permanentId?: string }).permanentId as string)
|
|
@@ -454,6 +456,7 @@ export function AgentChatWrapper(props: AgentChatWrapperProps) {
|
|
|
454
456
|
project_delete_file: t('chat.toolTitle.projectFileDeleter'),
|
|
455
457
|
project_create_branch: t('chat.toolTitle.projectBranchCreator'),
|
|
456
458
|
project_create_pull_request: t('chat.toolTitle.projectPullRequestCreator'),
|
|
459
|
+
[AGENT_PROJECT_TOOL_CALL_NAME]: t('chat.toolTitle.agentProjectTouched'),
|
|
457
460
|
}}
|
|
458
461
|
feedbackMode={toChatComponentFeedbackMode(feedbackMode)}
|
|
459
462
|
onFeedback={shouldEnableFeedback ? handleFeedback : undefined}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
-
import { Clock3Icon } from 'lucide-react';
|
|
3
|
+
import { Clock3Icon, RepeatIcon } from 'lucide-react';
|
|
4
4
|
import { useCallback, useEffect, useState } from 'react';
|
|
5
|
+
import { formatTimeoutDurationHuman } from '../../../../../../../src/book-components/Chat/utils/timeoutToolCallPresentation';
|
|
5
6
|
import { useServerLanguage } from '../../../../components/ServerLanguage/ServerLanguageProvider';
|
|
6
7
|
import { cancelAgentUserTimeout, fetchAgentUserTimeouts, type UserChatTimeout } from '../../../../utils/userChatClient';
|
|
7
8
|
import { formatChatTimeoutRemainingTime } from './formatChatTimeoutRemainingTime';
|
|
@@ -136,14 +137,28 @@ export function AgentGoalChatPlannedMessages({ agentName, currentTimestamp }: Ag
|
|
|
136
137
|
{plannedMessage.message ||
|
|
137
138
|
translateText('goalChat.plannedMessageDefaultLabel')}
|
|
138
139
|
</div>
|
|
139
|
-
<div className="mt-1
|
|
140
|
-
<
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
140
|
+
<div className="mt-1 flex flex-wrap items-center gap-x-3 gap-y-1 text-xs font-medium text-amber-700 dark:text-amber-300">
|
|
141
|
+
<span className="inline-flex items-center gap-1.5">
|
|
142
|
+
<Clock3Icon className="h-3.5 w-3.5" />
|
|
143
|
+
<span>
|
|
144
|
+
{formatChatTimeoutRemainingTime(plannedMessage.dueAt, currentTimestamp)}
|
|
145
|
+
</span>
|
|
146
|
+
<span className="text-slate-400 dark:text-slate-500">
|
|
147
|
+
{new Date(plannedMessage.dueAt).toLocaleString()}
|
|
148
|
+
</span>
|
|
146
149
|
</span>
|
|
150
|
+
{plannedMessage.recurrenceIntervalMs !== null && (
|
|
151
|
+
<span className="inline-flex items-center gap-1.5 text-slate-500 dark:text-slate-400">
|
|
152
|
+
<RepeatIcon className="h-3.5 w-3.5" />
|
|
153
|
+
<span>
|
|
154
|
+
{translateText('goalChat.plannedMessageIntervalLabel', {
|
|
155
|
+
interval: formatTimeoutDurationHuman(
|
|
156
|
+
plannedMessage.recurrenceIntervalMs,
|
|
157
|
+
),
|
|
158
|
+
})}
|
|
159
|
+
</span>
|
|
160
|
+
</span>
|
|
161
|
+
)}
|
|
147
162
|
</div>
|
|
148
163
|
</div>
|
|
149
164
|
<button
|
|
@@ -4,6 +4,7 @@ import { Chat } from '@promptbook-local/components';
|
|
|
4
4
|
import { useCallback, useMemo, type CSSProperties, type ReactNode } from 'react';
|
|
5
5
|
import type { ChatParticipant } from '../../../../../../../src/book-components/Chat/types/ChatParticipant';
|
|
6
6
|
import type { ChatSaveFormatHandlerOptions } from '../../../../../../../src/book-components/Chat/save/_common/ChatSaveFormatHandler';
|
|
7
|
+
import { AGENT_PROJECT_TOOL_CALL_NAME } from '../../../../../../../src/book-components/Chat/utils/agentProjectToolCall';
|
|
7
8
|
import type { AgentProjectItemInfo } from '../../../../components/AgentProjects/AgentProjectReferencesList';
|
|
8
9
|
import { useAgentProjectMarkdownReferences } from '../../../../components/AgentProjects/useAgentProjectMarkdownReferences';
|
|
9
10
|
import { useAgentBackground } from '../../../../components/AgentProfile/useAgentBackground';
|
|
@@ -143,6 +144,7 @@ export function CanonicalAgentChatSurface({
|
|
|
143
144
|
const markdownInlineReferences = useAgentProjectMarkdownReferences({
|
|
144
145
|
agentPermanentId: agentName,
|
|
145
146
|
projects: projectReferences,
|
|
147
|
+
messages: state.renderedMessages,
|
|
146
148
|
});
|
|
147
149
|
const chatBackgroundStyle = useMemo(
|
|
148
150
|
() =>
|
|
@@ -174,7 +176,10 @@ export function CanonicalAgentChatSurface({
|
|
|
174
176
|
],
|
|
175
177
|
);
|
|
176
178
|
const { language, t: translateText } = useServerLanguage();
|
|
177
|
-
const translations = useMemo(
|
|
179
|
+
const translations = useMemo(
|
|
180
|
+
() => createCanonicalAgentChatTranslations(translateText, isAgentGoalChat),
|
|
181
|
+
[isAgentGoalChat, translateText],
|
|
182
|
+
);
|
|
178
183
|
const frozenChatBannerLabel = useMemo(() => {
|
|
179
184
|
const sourceBannerLabel = readOnlySource ? getUserChatSourceBannerLabel(readOnlySource) : null;
|
|
180
185
|
if (sourceBannerLabel) {
|
|
@@ -431,7 +436,10 @@ function renderCanonicalAgentChatLoadingSkeleton(): ReactNode {
|
|
|
431
436
|
*
|
|
432
437
|
* @private function of CanonicalAgentChatPanel
|
|
433
438
|
*/
|
|
434
|
-
function createCanonicalAgentChatTranslations(
|
|
439
|
+
function createCanonicalAgentChatTranslations(
|
|
440
|
+
translateText: TranslateText,
|
|
441
|
+
isAgentGoalChat: boolean,
|
|
442
|
+
): CanonicalAgentChatTranslations {
|
|
435
443
|
return {
|
|
436
444
|
chatUiTranslations: {
|
|
437
445
|
inputPlaceholder: translateText('chat.inputPlaceholder'),
|
|
@@ -520,9 +528,12 @@ function createCanonicalAgentChatTranslations(translateText: TranslateText): Can
|
|
|
520
528
|
project_delete_file: translateText('chat.toolTitle.projectFileDeleter'),
|
|
521
529
|
project_create_branch: translateText('chat.toolTitle.projectBranchCreator'),
|
|
522
530
|
project_create_pull_request: translateText('chat.toolTitle.projectPullRequestCreator'),
|
|
531
|
+
[AGENT_PROJECT_TOOL_CALL_NAME]: translateText('chat.toolTitle.agentProjectTouched'),
|
|
523
532
|
},
|
|
524
533
|
timingTranslations: {
|
|
525
|
-
answerDurationLabel: translateText(
|
|
534
|
+
answerDurationLabel: translateText(
|
|
535
|
+
isAgentGoalChat ? 'goalChat.executionDurationLabel' : 'chat.answerDurationLabel',
|
|
536
|
+
),
|
|
526
537
|
},
|
|
527
538
|
feedbackTranslations: {
|
|
528
539
|
reportIssueButtonTitle: translateText('chat.feedback.reportIssueButtonTitle'),
|
|
@@ -4,8 +4,7 @@ import { ForbiddenPage } from '@/src/components/ForbiddenPage/ForbiddenPage';
|
|
|
4
4
|
import type { AgentProjectItemInfo } from '@/src/components/AgentProjects/AgentProjectReferencesList';
|
|
5
5
|
import { $provideServer } from '@/src/tools/$provideServer';
|
|
6
6
|
import { resolveAgentAccess } from '@/src/utils/agentAccess';
|
|
7
|
-
import {
|
|
8
|
-
import { listAgentProjectChatReferences } from '@/src/utils/agentProjects/listAgentProjectChatReferences';
|
|
7
|
+
import { resolveAgentChatProjectReferences } from '@/src/utils/agentProjects/resolveAgentChatProjectReferences';
|
|
9
8
|
import { loadChatConfiguration } from '@/src/utils/chatConfiguration';
|
|
10
9
|
import { ensureChatHistoryIdentity } from '@/src/utils/currentUserIdentity';
|
|
11
10
|
import { getCurrentUser } from '@/src/utils/getCurrentUser';
|
|
@@ -71,23 +70,6 @@ function buildCanonicalAgentChatPath(
|
|
|
71
70
|
return query ? `${pathname}?${query}` : pathname;
|
|
72
71
|
}
|
|
73
72
|
|
|
74
|
-
/**
|
|
75
|
-
* Resolves compact project references available to the agent chat surface.
|
|
76
|
-
*
|
|
77
|
-
* @param agentPermanentId - Permanent id of the agent owning the projects.
|
|
78
|
-
* @returns Display-only project references safe to send to the client.
|
|
79
|
-
*/
|
|
80
|
-
async function resolveAgentChatProjectReferences(
|
|
81
|
-
agentPermanentId: string,
|
|
82
|
-
): Promise<ReadonlyArray<AgentProjectItemInfo>> {
|
|
83
|
-
const projectAccess = await resolveAgentProjectsAccess(agentPermanentId);
|
|
84
|
-
if (!projectAccess.isProjectOverviewVisible) {
|
|
85
|
-
return [];
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
return await listAgentProjectChatReferences(agentPermanentId);
|
|
89
|
-
}
|
|
90
|
-
|
|
91
73
|
/**
|
|
92
74
|
* Handles agent chat page.
|
|
93
75
|
*/
|
|
@@ -149,7 +131,7 @@ export default async function AgentChatPage({
|
|
|
149
131
|
const providedServerPromise = $provideServer();
|
|
150
132
|
const agentProjectReferencesPromise = isHeadless
|
|
151
133
|
? Promise.resolve<ReadonlyArray<AgentProjectItemInfo>>([])
|
|
152
|
-
: resolveAgentChatProjectReferences(canonicalAgentId);
|
|
134
|
+
: resolveAgentChatProjectReferences({ agentPermanentId: canonicalAgentId });
|
|
153
135
|
const shareTargetPayloadPromise = shareTarget
|
|
154
136
|
? peekShareTargetPayload({
|
|
155
137
|
shareTargetId: shareTarget,
|
|
@@ -6,6 +6,7 @@ import { $provideServer } from '@/src/tools/$provideServer';
|
|
|
6
6
|
import { resolveAgentProjectsAccess } from '@/src/utils/agentProjects/agentProjectAccess';
|
|
7
7
|
import { buildAgentProjectsDashboardHref } from '@/src/utils/agentProjects/agentProjectHrefs';
|
|
8
8
|
import { listAgentProjectChatReferences } from '@/src/utils/agentProjects/listAgentProjectChatReferences';
|
|
9
|
+
import { resolveAgentChatProjectReferences } from '@/src/utils/agentProjects/resolveAgentChatProjectReferences';
|
|
9
10
|
import { isPublicAgentVisibility } from '@/src/utils/agentVisibility';
|
|
10
11
|
import { ensureChatHistoryIdentity } from '@/src/utils/currentUserIdentity';
|
|
11
12
|
import { createAgentEmailAddress } from '@/src/utils/email/agentEmailAddress';
|
|
@@ -689,7 +690,7 @@ export default async function AgentPage(props: AgentPageProps) {
|
|
|
689
690
|
|
|
690
691
|
const [pageData, projects] = await Promise.all([
|
|
691
692
|
loadAgentPageData(route.canonicalAgentId, Boolean(access.currentUser)),
|
|
692
|
-
|
|
693
|
+
resolveAgentChatProjectReferences({ agentPermanentId: route.canonicalAgentId, projectsAccess: access }),
|
|
693
694
|
]);
|
|
694
695
|
return renderAgentProfilePage(createAgentPageViewModel(route, pageData, projects));
|
|
695
696
|
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
'use server';
|
|
2
|
+
|
|
3
|
+
import { resolveAgentProjectsAccess } from '@/src/utils/agentProjects/agentProjectAccess';
|
|
4
|
+
import type { AgentProjectReferenceInfo } from '@/src/utils/agentProjects/AgentProjectReferenceInfo';
|
|
5
|
+
import { listAgentProjectNames } from '@/src/utils/agentProjects/listAgentProjectNames';
|
|
6
|
+
import { resolveAgentChatProjectReferences } from '@/src/utils/agentProjects/resolveAgentChatProjectReferences';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Reloads the project references of one open chat when the agent's set of projects changed.
|
|
10
|
+
*
|
|
11
|
+
* A chat renders every mention of a project as a project chip built from these references, so a project
|
|
12
|
+
* created while the chat stays open must reach the browser without a page reload. Building the references
|
|
13
|
+
* walks every project folder, therefore the project names the chat already knows decide whether that work
|
|
14
|
+
* is done at all.
|
|
15
|
+
*
|
|
16
|
+
* @param agentPermanentId - Permanent id of the agent owning the projects.
|
|
17
|
+
* @param knownProjectNames - Project directory names the open chat already renders.
|
|
18
|
+
* @returns Fresh project references, or `null` when the agent owns exactly the known projects.
|
|
19
|
+
*/
|
|
20
|
+
export async function $refreshAgentProjectChatReferencesAction(
|
|
21
|
+
agentPermanentId: string,
|
|
22
|
+
knownProjectNames: ReadonlyArray<string>,
|
|
23
|
+
): Promise<ReadonlyArray<AgentProjectReferenceInfo> | null> {
|
|
24
|
+
const projectsAccess = await resolveAgentProjectsAccess(agentPermanentId);
|
|
25
|
+
|
|
26
|
+
if (!projectsAccess.isProjectOverviewVisible) {
|
|
27
|
+
return [];
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const projectNames = await listAgentProjectNames(agentPermanentId);
|
|
31
|
+
|
|
32
|
+
if (areAgentProjectNamesEqual(projectNames, knownProjectNames)) {
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return await resolveAgentChatProjectReferences({ agentPermanentId, projectsAccess });
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Compares two collections of project directory names ignoring their order and letter case.
|
|
41
|
+
*
|
|
42
|
+
* @param firstProjectNames - Project names listed on the server.
|
|
43
|
+
* @param secondProjectNames - Project names reported by the open chat.
|
|
44
|
+
* @returns Whether both collections describe the same projects.
|
|
45
|
+
*/
|
|
46
|
+
function areAgentProjectNamesEqual(
|
|
47
|
+
firstProjectNames: ReadonlyArray<string>,
|
|
48
|
+
secondProjectNames: ReadonlyArray<string>,
|
|
49
|
+
): boolean {
|
|
50
|
+
if (firstProjectNames.length !== secondProjectNames.length) {
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const normalizedSecondProjectNames = new Set(
|
|
55
|
+
secondProjectNames.map((secondProjectName) => secondProjectName.toLowerCase()),
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
return firstProjectNames.every((firstProjectName) =>
|
|
59
|
+
normalizedSecondProjectNames.has(firstProjectName.toLowerCase()),
|
|
60
|
+
);
|
|
61
|
+
}
|
package/apps/agents-server/src/components/AgentProjects/resolveLatestCompletedAgentMessageKey.ts
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { ChatMessage } from '@promptbook-local/types';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Resolves a key identifying the newest finished agent answer in one chat.
|
|
5
|
+
*
|
|
6
|
+
* A finished agent turn is the only moment when the agent can have created a project, so this key is the
|
|
7
|
+
* signal telling the chat to reload its project references. Messages which are still being generated are
|
|
8
|
+
* ignored on purpose — their content keeps changing while the progress card updates, which says nothing
|
|
9
|
+
* about the projects on the server.
|
|
10
|
+
*
|
|
11
|
+
* @param messages - Messages currently rendered in the chat.
|
|
12
|
+
* @returns Key of the newest finished agent message, or `null` when the agent has answered nothing yet.
|
|
13
|
+
*/
|
|
14
|
+
export function resolveLatestCompletedAgentMessageKey(messages: ReadonlyArray<ChatMessage> | undefined): string | null {
|
|
15
|
+
if (!messages) {
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
for (let messageIndex = messages.length - 1; messageIndex >= 0; messageIndex--) {
|
|
20
|
+
const message = messages[messageIndex];
|
|
21
|
+
|
|
22
|
+
if (message === undefined || message.sender === 'USER' || message.isComplete === false) {
|
|
23
|
+
continue;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Note: Messages of chats which do not persist ids are identified by their position, which still
|
|
27
|
+
// moves forward with every new answer
|
|
28
|
+
return message.id === undefined ? `#${messageIndex}` : String(message.id);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return null;
|
|
32
|
+
}
|
package/apps/agents-server/src/components/AgentProjects/useAgentProjectMarkdownReferences.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
-
import type { MarkdownInlineReference } from '@promptbook-local/types';
|
|
3
|
+
import type { ChatMessage, MarkdownInlineReference } from '@promptbook-local/types';
|
|
4
4
|
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
5
|
+
import { $refreshAgentProjectChatReferencesAction } from '../../app/agents/[agentName]/projectReferenceActions';
|
|
5
6
|
import {
|
|
6
7
|
$startAgentProjectRuntimeAction,
|
|
7
8
|
$stopAgentProjectRuntimeAction,
|
|
@@ -13,6 +14,7 @@ import {
|
|
|
13
14
|
type AgentProjectMarkdownReferenceInfo,
|
|
14
15
|
} from '../../utils/agentProjects/createAgentProjectMarkdownReferences';
|
|
15
16
|
import { notifyError } from '../Notifications/notifications';
|
|
17
|
+
import { resolveLatestCompletedAgentMessageKey } from './resolveLatestCompletedAgentMessageKey';
|
|
16
18
|
|
|
17
19
|
/**
|
|
18
20
|
* Options used to build interactive project references for an Agents Server chat.
|
|
@@ -27,6 +29,14 @@ type UseAgentProjectMarkdownReferencesOptions = {
|
|
|
27
29
|
* Initial browser-safe project references loaded by the server page.
|
|
28
30
|
*/
|
|
29
31
|
readonly projects: ReadonlyArray<AgentProjectReferenceInfo>;
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Messages currently rendered in the chat.
|
|
35
|
+
*
|
|
36
|
+
* They are watched only to notice that the agent finished an answer, which is when a project it just
|
|
37
|
+
* created must become a chip without waiting for a page reload.
|
|
38
|
+
*/
|
|
39
|
+
readonly messages?: ReadonlyArray<ChatMessage>;
|
|
30
40
|
};
|
|
31
41
|
|
|
32
42
|
/**
|
|
@@ -38,7 +48,7 @@ type UseAgentProjectMarkdownReferencesOptions = {
|
|
|
38
48
|
export function useAgentProjectMarkdownReferences(
|
|
39
49
|
options: UseAgentProjectMarkdownReferencesOptions,
|
|
40
50
|
): ReadonlyArray<MarkdownInlineReference> {
|
|
41
|
-
const { agentPermanentId, projects } = options;
|
|
51
|
+
const { agentPermanentId, projects, messages } = options;
|
|
42
52
|
const [currentProjects, setCurrentProjects] = useState<ReadonlyArray<AgentProjectReferenceInfo>>(projects);
|
|
43
53
|
const previousProjectsRef = useRef(projects);
|
|
44
54
|
|
|
@@ -51,6 +61,13 @@ export function useAgentProjectMarkdownReferences(
|
|
|
51
61
|
setCurrentProjects(projects);
|
|
52
62
|
}, [projects]);
|
|
53
63
|
|
|
64
|
+
useRefreshedAgentProjectReferences({
|
|
65
|
+
agentPermanentId,
|
|
66
|
+
currentProjects,
|
|
67
|
+
messages,
|
|
68
|
+
setCurrentProjects,
|
|
69
|
+
});
|
|
70
|
+
|
|
54
71
|
/**
|
|
55
72
|
* Merges one action result into the local project reference state.
|
|
56
73
|
*/
|
|
@@ -143,6 +160,111 @@ export function useAgentProjectMarkdownReferences(
|
|
|
143
160
|
);
|
|
144
161
|
}
|
|
145
162
|
|
|
163
|
+
/**
|
|
164
|
+
* Options of the refresh keeping chat project references current while the chat stays open.
|
|
165
|
+
*
|
|
166
|
+
* @private type of `useAgentProjectMarkdownReferences`
|
|
167
|
+
*/
|
|
168
|
+
type UseRefreshedAgentProjectReferencesOptions = {
|
|
169
|
+
/**
|
|
170
|
+
* Permanent id of the agent owning the projects.
|
|
171
|
+
*/
|
|
172
|
+
readonly agentPermanentId: string;
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Project references the chat currently renders.
|
|
176
|
+
*/
|
|
177
|
+
readonly currentProjects: ReadonlyArray<AgentProjectReferenceInfo>;
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Messages currently rendered in the chat.
|
|
181
|
+
*/
|
|
182
|
+
readonly messages: ReadonlyArray<ChatMessage> | undefined;
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Replaces the project references the chat renders.
|
|
186
|
+
*/
|
|
187
|
+
readonly setCurrentProjects: (projects: ReadonlyArray<AgentProjectReferenceInfo>) => void;
|
|
188
|
+
};
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Reloads the project references after each finished agent answer which could have created a project.
|
|
192
|
+
*
|
|
193
|
+
* The server renders a chat with the projects existing at that moment, so an agent creating a project
|
|
194
|
+
* during the conversation would otherwise reference it as a plain link until the page is reloaded. The
|
|
195
|
+
* messages already present when the chat thread opens arrive together with their projects and never
|
|
196
|
+
* trigger a reload, and the server skips rebuilding the references while the agent owns the very same
|
|
197
|
+
* projects.
|
|
198
|
+
*
|
|
199
|
+
* @param options - Owning agent, current references, and the messages the chat renders.
|
|
200
|
+
*
|
|
201
|
+
* @private function of `useAgentProjectMarkdownReferences`
|
|
202
|
+
*/
|
|
203
|
+
function useRefreshedAgentProjectReferences({
|
|
204
|
+
agentPermanentId,
|
|
205
|
+
currentProjects,
|
|
206
|
+
messages,
|
|
207
|
+
setCurrentProjects,
|
|
208
|
+
}: UseRefreshedAgentProjectReferencesOptions): void {
|
|
209
|
+
const currentProjectsRef = useRef(currentProjects);
|
|
210
|
+
const isLatestCompletedAgentMessageKeyKnownRef = useRef(false);
|
|
211
|
+
const refreshedAgentMessageKeyRef = useRef<string | null>(null);
|
|
212
|
+
const hasRenderedChatMessages = messages !== undefined && messages.length > 0;
|
|
213
|
+
const latestCompletedAgentMessageKey = resolveLatestCompletedAgentMessageKey(messages);
|
|
214
|
+
|
|
215
|
+
useEffect(() => {
|
|
216
|
+
currentProjectsRef.current = currentProjects;
|
|
217
|
+
}, [currentProjects]);
|
|
218
|
+
|
|
219
|
+
useEffect(() => {
|
|
220
|
+
if (!hasRenderedChatMessages) {
|
|
221
|
+
// Note: An empty thread is also the state of a chat whose history is still being loaded
|
|
222
|
+
return undefined;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
if (!isLatestCompletedAgentMessageKeyKnownRef.current) {
|
|
226
|
+
// Note: The messages rendered when the chat opens were listed together with the server projects
|
|
227
|
+
isLatestCompletedAgentMessageKeyKnownRef.current = true;
|
|
228
|
+
refreshedAgentMessageKeyRef.current = latestCompletedAgentMessageKey;
|
|
229
|
+
return undefined;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
if (refreshedAgentMessageKeyRef.current === latestCompletedAgentMessageKey) {
|
|
233
|
+
return undefined;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
refreshedAgentMessageKeyRef.current = latestCompletedAgentMessageKey;
|
|
237
|
+
let isDisposed = false;
|
|
238
|
+
|
|
239
|
+
void (async () => {
|
|
240
|
+
const knownProjectNames = currentProjectsRef.current.map((project) => project.projectName);
|
|
241
|
+
|
|
242
|
+
try {
|
|
243
|
+
const refreshedProjects = await $refreshAgentProjectChatReferencesAction(
|
|
244
|
+
agentPermanentId,
|
|
245
|
+
knownProjectNames,
|
|
246
|
+
);
|
|
247
|
+
|
|
248
|
+
if (isDisposed || refreshedProjects === null) {
|
|
249
|
+
return;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
setCurrentProjects(refreshedProjects);
|
|
253
|
+
} catch (error) {
|
|
254
|
+
// Note: A chat stays usable without fresh projects, the chip then appears after the next answer
|
|
255
|
+
console.error('[agents-server:agent-projects] Failed to refresh chat project references', {
|
|
256
|
+
agentPermanentId,
|
|
257
|
+
error,
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
})();
|
|
261
|
+
|
|
262
|
+
return () => {
|
|
263
|
+
isDisposed = true;
|
|
264
|
+
};
|
|
265
|
+
}, [agentPermanentId, hasRenderedChatMessages, latestCompletedAgentMessageKey, setCurrentProjects]);
|
|
266
|
+
}
|
|
267
|
+
|
|
146
268
|
/**
|
|
147
269
|
* Selects a useful server-action error message without assuming a particular serialized error type.
|
|
148
270
|
*
|
|
@@ -17,10 +17,12 @@ export const SERVER_TRANSLATION_KEYS = [
|
|
|
17
17
|
'common.goalChat',
|
|
18
18
|
'goalChat.noticeTitle',
|
|
19
19
|
'goalChat.noticeDescription',
|
|
20
|
+
'goalChat.executionDurationLabel',
|
|
20
21
|
'goalChat.plannedMessagesTitle',
|
|
21
22
|
'goalChat.plannedMessagesEmptyLabel',
|
|
22
23
|
'goalChat.plannedMessagesLoadErrorLabel',
|
|
23
24
|
'goalChat.plannedMessageDefaultLabel',
|
|
25
|
+
'goalChat.plannedMessageIntervalLabel',
|
|
24
26
|
'goalChat.plannedMessageCancelLabel',
|
|
25
27
|
'goalChat.plannedMessageCancellingLabel',
|
|
26
28
|
'common.projects',
|
|
@@ -586,6 +588,7 @@ export const SERVER_TRANSLATION_KEYS = [
|
|
|
586
588
|
'chat.toolTitle.projectFileDeleter',
|
|
587
589
|
'chat.toolTitle.projectBranchCreator',
|
|
588
590
|
'chat.toolTitle.projectPullRequestCreator',
|
|
591
|
+
'chat.toolTitle.agentProjectTouched',
|
|
589
592
|
'chatTimeout.defaultLabel',
|
|
590
593
|
'chatTimeout.singleActiveLabel',
|
|
591
594
|
'chatTimeout.multipleActiveLabel',
|
|
@@ -11,10 +11,12 @@ common.book: Book
|
|
|
11
11
|
common.goalChat: Cíl
|
|
12
12
|
goalChat.noticeTitle: Toto je cílový chat agenta
|
|
13
13
|
goalChat.noticeDescription: Agent si sem píše sám a plánuje práci ke svému cíli, proto je toto vlákno pro lidi jen ke čtení.
|
|
14
|
+
goalChat.executionDurationLabel: 'běželo {duration}'
|
|
14
15
|
goalChat.plannedMessagesTitle: Naplánované zprávy
|
|
15
16
|
goalChat.plannedMessagesEmptyLabel: Žádné naplánované zprávy. Agent se probudí při nové zprávě nebo aktualizaci knihy.
|
|
16
17
|
goalChat.plannedMessagesLoadErrorLabel: Naplánované zprávy se nepodařilo načíst.
|
|
17
18
|
goalChat.plannedMessageDefaultLabel: Naplánované probuzení
|
|
19
|
+
goalChat.plannedMessageIntervalLabel: 'Opakování: {interval}'
|
|
18
20
|
goalChat.plannedMessageCancelLabel: Zrušit
|
|
19
21
|
goalChat.plannedMessageCancellingLabel: Ruším
|
|
20
22
|
common.projects: Projekty
|
|
@@ -580,6 +582,7 @@ chat.toolTitle.projectFileWriter: Zápis souboru projektu
|
|
|
580
582
|
chat.toolTitle.projectFileDeleter: Mazání souboru projektu
|
|
581
583
|
chat.toolTitle.projectBranchCreator: Vytvoření větve projektu
|
|
582
584
|
chat.toolTitle.projectPullRequestCreator: Vytvoření pull requestu
|
|
585
|
+
chat.toolTitle.agentProjectTouched: Projekt
|
|
583
586
|
chatTimeout.defaultLabel: Naplánovaný časovač
|
|
584
587
|
chatTimeout.singleActiveLabel: 1 aktivní časovač
|
|
585
588
|
chatTimeout.multipleActiveLabel: '{count} aktivní časovače'
|
|
@@ -11,10 +11,12 @@ common.book: Book
|
|
|
11
11
|
common.goalChat: Goal
|
|
12
12
|
goalChat.noticeTitle: This is the agent's goal chat
|
|
13
13
|
goalChat.noticeDescription: The agent writes here on its own to plan work towards its goal, so this thread is read-only for people.
|
|
14
|
+
goalChat.executionDurationLabel: 'executed for {duration}'
|
|
14
15
|
goalChat.plannedMessagesTitle: Planned messages
|
|
15
16
|
goalChat.plannedMessagesEmptyLabel: No planned messages. The agent will wake up when invoked by a new message or book update.
|
|
16
17
|
goalChat.plannedMessagesLoadErrorLabel: Failed to load planned messages.
|
|
17
18
|
goalChat.plannedMessageDefaultLabel: Planned wake-up
|
|
19
|
+
goalChat.plannedMessageIntervalLabel: Repeats every {interval}
|
|
18
20
|
goalChat.plannedMessageCancelLabel: Cancel
|
|
19
21
|
goalChat.plannedMessageCancellingLabel: Cancelling
|
|
20
22
|
common.projects: Projects
|
|
@@ -584,6 +586,7 @@ chat.toolTitle.projectFileWriter: Writing project file
|
|
|
584
586
|
chat.toolTitle.projectFileDeleter: Deleting project file
|
|
585
587
|
chat.toolTitle.projectBranchCreator: Creating project branch
|
|
586
588
|
chat.toolTitle.projectPullRequestCreator: Creating pull request
|
|
589
|
+
chat.toolTitle.agentProjectTouched: Project
|
|
587
590
|
chatTimeout.defaultLabel: Scheduled timeout
|
|
588
591
|
chatTimeout.singleActiveLabel: 1 active timeout
|
|
589
592
|
chatTimeout.multipleActiveLabel: '{count} active timeouts'
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { spaceTrim } from 'spacetrim';
|
|
2
|
+
import { formatTimeoutDurationHuman } from '../../../../src/book-components/Chat/utils/timeoutToolCallPresentation';
|
|
2
3
|
import type { string_javascript_name } from '../../../../src/types/string_person_fullname';
|
|
3
4
|
import type { ToolFunction } from '../../../../src/scripting/javascript/JavascriptExecutionToolsOptions';
|
|
4
5
|
import { createToolExecutionEnvelope } from '../../../../src/commitments/_common/toolExecutionEnvelope';
|
|
@@ -45,7 +46,9 @@ export function createAgentGoalChatTimeoutToolFunctions(
|
|
|
45
46
|
});
|
|
46
47
|
|
|
47
48
|
return createToolExecutionEnvelope({
|
|
48
|
-
assistantMessage: `Planned message ${JSON.stringify(
|
|
49
|
+
assistantMessage: `Planned message ${JSON.stringify(
|
|
50
|
+
result.timeoutId,
|
|
51
|
+
)} ${createPlannedMessageScheduleLabel(result)}.`,
|
|
49
52
|
toolResult: result,
|
|
50
53
|
});
|
|
51
54
|
} catch (error) {
|
|
@@ -147,7 +150,9 @@ function createPlannedMessagesAssistantSummary(
|
|
|
147
150
|
const visiblePlannedMessages = plannedMessages.slice(0, MAX_ASSISTANT_VISIBLE_PLANNED_MESSAGES);
|
|
148
151
|
const summaryRows = visiblePlannedMessages.map((plannedMessage, index) => {
|
|
149
152
|
const message = plannedMessage.message?.trim() || 'Wake up and continue working towards the current goal.';
|
|
150
|
-
return `${index + 1}. ${plannedMessage.timeoutId}
|
|
153
|
+
return `${index + 1}. ${plannedMessage.timeoutId} ${createPlannedMessageScheduleLabel(
|
|
154
|
+
plannedMessage,
|
|
155
|
+
)}: ${message}`;
|
|
151
156
|
});
|
|
152
157
|
const hiddenPlannedMessageCount = plannedMessages.length - visiblePlannedMessages.length;
|
|
153
158
|
|
|
@@ -164,6 +169,23 @@ function createPlannedMessagesAssistantSummary(
|
|
|
164
169
|
);
|
|
165
170
|
}
|
|
166
171
|
|
|
172
|
+
/**
|
|
173
|
+
* Describes when one planned message wakes the agent.
|
|
174
|
+
*
|
|
175
|
+
* @param plannedMessage - Planned message with its repeat interval and nearest execution time.
|
|
176
|
+
* @returns Schedule fragment such as `repeating every 5 minutes (next at ...)`.
|
|
177
|
+
*/
|
|
178
|
+
function createPlannedMessageScheduleLabel(plannedMessage: {
|
|
179
|
+
readonly dueAt: string;
|
|
180
|
+
readonly intervalMs: number | null;
|
|
181
|
+
}): string {
|
|
182
|
+
if (!plannedMessage.intervalMs) {
|
|
183
|
+
return `at ${plannedMessage.dueAt}`;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
return `repeating every ${formatTimeoutDurationHuman(plannedMessage.intervalMs)} (next at ${plannedMessage.dueAt})`;
|
|
187
|
+
}
|
|
188
|
+
|
|
167
189
|
/**
|
|
168
190
|
* Serializes one caught tool failure without crashing the surrounding model run.
|
|
169
191
|
*
|
|
@@ -27,13 +27,14 @@ export function createAgentGoalChatTimeoutTools(
|
|
|
27
27
|
tools.push({
|
|
28
28
|
name: AGENT_GOAL_CHAT_TIMEOUT_TOOL_NAMES.set,
|
|
29
29
|
description:
|
|
30
|
-
'Plan a message that
|
|
30
|
+
'Plan a message that repeatedly wakes you in your singleton goal chat, like `setInterval`. Use this for useful autonomous follow-up towards your current goal; the wake-up is not tied to the human conversation where you schedule it, and it keeps repeating until you cancel it. Do not plan a message that matches one you already planned.',
|
|
31
31
|
parameters: {
|
|
32
32
|
type: 'object',
|
|
33
33
|
properties: {
|
|
34
34
|
milliseconds: {
|
|
35
35
|
type: 'number',
|
|
36
|
-
description:
|
|
36
|
+
description:
|
|
37
|
+
'Repeat interval in milliseconds between two wake-ups by this planned message (at least 60000).',
|
|
37
38
|
},
|
|
38
39
|
message: {
|
|
39
40
|
type: 'string',
|
|
@@ -51,7 +52,7 @@ export function createAgentGoalChatTimeoutTools(
|
|
|
51
52
|
tools.push({
|
|
52
53
|
name: AGENT_GOAL_CHAT_TIMEOUT_TOOL_NAMES.list,
|
|
53
54
|
description:
|
|
54
|
-
'List your planned goal-chat messages, including their identifiers and execution times, across every conversation in which you were invoked.',
|
|
55
|
+
'List your planned goal-chat messages, including their identifiers, repeat intervals, and next execution times, across every conversation in which you were invoked. Keep the listed messages as they are unless they no longer match your goal.',
|
|
55
56
|
parameters: {
|
|
56
57
|
type: 'object',
|
|
57
58
|
properties: {
|
|
@@ -73,7 +74,7 @@ export function createAgentGoalChatTimeoutTools(
|
|
|
73
74
|
tools.push({
|
|
74
75
|
name: AGENT_GOAL_CHAT_TIMEOUT_TOOL_NAMES.cancel,
|
|
75
76
|
description:
|
|
76
|
-
'
|
|
77
|
+
'Stop one repeating planned goal-chat message by its timeout identifier. List planned messages first when the identifier is not known.',
|
|
77
78
|
parameters: {
|
|
78
79
|
type: 'object',
|
|
79
80
|
properties: {
|