@adecore/agents-react 0.24.1 → 0.25.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chat/index.d.ts +4 -7
- package/dist/chat/index.js +4 -7
- package/dist/chat/logic/continue-after-stop.d.ts +3 -0
- package/dist/chat/logic/continue-after-stop.js +28 -0
- package/dist/chat/logic/thread-cards.d.ts +0 -1
- package/dist/chat/logic/thread-cards.js +0 -4
- package/dist/chat/preferences.d.ts +0 -1
- package/dist/chat/preferences.js +0 -3
- package/dist/chat/stash.d.ts +6 -0
- package/dist/chat/stash.js +13 -0
- package/dist/chat/ui/Composer.js +26 -5
- package/dist/chat/ui/EditDiff.js +4 -3
- package/dist/chat/ui/Pickers.js +1 -1
- package/dist/chat/ui/UnifiedDiff.js +4 -3
- package/dist/chat/ui/composer/ComposerControls.d.ts +1 -0
- package/dist/chat/ui/composer/ComposerControls.js +3 -3
- package/dist/chat/ui/composer/use-composer-submit.d.ts +3 -1
- package/dist/chat/ui/composer/use-composer-submit.js +22 -4
- package/dist/chat/ui/composer/use-continuable-turn.d.ts +2 -0
- package/dist/chat/ui/composer/use-continuable-turn.js +12 -0
- package/dist/chat/ui/composer/use-notice.d.ts +3 -1
- package/dist/chat/ui/composer/use-notice.js +8 -6
- package/dist/chat/ui/diff/ReviewDiff.js +2 -2
- package/dist/chat/ui/index.d.ts +9 -28
- package/dist/chat/ui/index.js +8 -27
- package/dist/chat/ui/intelligent-ui/UiReply.js +20 -2
- package/dist/chat/ui/intelligent-ui/node-text.d.ts +3 -1
- package/dist/chat/ui/intelligent-ui/node-text.js +32 -0
- package/dist/chat/ui/intelligent-ui/registry.js +15 -5
- package/dist/chat/ui/intelligent-ui/render-context.d.ts +6 -0
- package/dist/chat/ui/intelligent-ui/renderers/base-land.d.ts +1 -0
- package/dist/chat/ui/intelligent-ui/renderers/base-land.js +6 -0
- package/dist/chat/ui/intelligent-ui/renderers/binding.d.ts +6 -0
- package/dist/chat/ui/intelligent-ui/renderers/binding.js +10 -0
- package/dist/chat/ui/intelligent-ui/renderers/content.d.ts +2 -0
- package/dist/chat/ui/intelligent-ui/renderers/content.js +68 -6
- package/dist/chat/ui/intelligent-ui/renderers/inputs.d.ts +2 -0
- package/dist/chat/ui/intelligent-ui/renderers/inputs.js +40 -13
- package/dist/chat/ui/intelligent-ui/renderers/map-slots.d.ts +20 -0
- package/dist/chat/ui/intelligent-ui/renderers/map-slots.js +87 -0
- package/dist/chat/ui/intelligent-ui/renderers/map-style.d.ts +18 -0
- package/dist/chat/ui/intelligent-ui/renderers/map-style.js +72 -0
- package/dist/chat/ui/intelligent-ui/renderers/map-view.d.ts +15 -0
- package/dist/chat/ui/intelligent-ui/renderers/map-view.js +213 -0
- package/dist/chat/ui/intelligent-ui/renderers/map.d.ts +3 -0
- package/dist/chat/ui/intelligent-ui/renderers/map.js +113 -0
- package/dist/chat/ui/intelligent-ui/renderers/place-point.d.ts +3 -0
- package/dist/chat/ui/intelligent-ui/renderers/place-point.js +13 -0
- package/dist/chat/ui/intelligent-ui/renderers/text.d.ts +2 -0
- package/dist/chat/ui/intelligent-ui/renderers/text.js +14 -1
- package/dist/chat/ui/intelligent-ui/use-in-view.d.ts +1 -0
- package/dist/chat/ui/intelligent-ui/use-in-view.js +17 -0
- package/dist/chat/ui/rows/WorkRows.js +3 -3
- package/dist/host.d.ts +16 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/lazy.js +5 -7
- package/dist/locales/en/agent-chat.d.ts +47 -0
- package/dist/locales/en/agent-chat.js +48 -1
- package/dist/locales/nl/agent-chat.d.ts +47 -0
- package/dist/locales/nl/agent-chat.js +48 -1
- package/dist/prompts/index.d.ts +3 -5
- package/dist/prompts/index.js +3 -5
- package/dist/providers/index.d.ts +3 -9
- package/dist/providers/index.js +3 -9
- package/dist/state/index.d.ts +2 -2
- package/dist/state/index.js +2 -2
- package/dist/state/usage.d.ts +0 -1
- package/dist/state/usage.js +0 -3
- package/dist/theme.css +10 -0
- package/package.json +9 -8
- package/src/chat/index.ts +2 -23
- package/src/chat/logic/continue-after-stop.ts +32 -0
- package/src/chat/logic/thread-cards.ts +0 -5
- package/src/chat/preferences.ts +0 -4
- package/src/chat/stash.ts +17 -0
- package/src/chat/ui/Composer.tsx +33 -5
- package/src/chat/ui/EditDiff.tsx +6 -5
- package/src/chat/ui/Pickers.tsx +1 -0
- package/src/chat/ui/UnifiedDiff.tsx +6 -5
- package/src/chat/ui/composer/ComposerControls.tsx +13 -3
- package/src/chat/ui/composer/use-composer-submit.ts +25 -5
- package/src/chat/ui/composer/use-continuable-turn.ts +14 -0
- package/src/chat/ui/composer/use-notice.ts +14 -7
- package/src/chat/ui/diff/ReviewDiff.tsx +3 -3
- package/src/chat/ui/index.ts +9 -49
- package/src/chat/ui/intelligent-ui/UiReply.tsx +24 -1
- package/src/chat/ui/intelligent-ui/node-text.ts +34 -1
- package/src/chat/ui/intelligent-ui/registry.ts +33 -5
- package/src/chat/ui/intelligent-ui/render-context.ts +14 -0
- package/src/chat/ui/intelligent-ui/renderers/base-land.ts +7 -0
- package/src/chat/ui/intelligent-ui/renderers/binding.ts +14 -0
- package/src/chat/ui/intelligent-ui/renderers/content.tsx +144 -9
- package/src/chat/ui/intelligent-ui/renderers/inputs.tsx +79 -17
- package/src/chat/ui/intelligent-ui/renderers/map-slots.ts +105 -0
- package/src/chat/ui/intelligent-ui/renderers/map-style.ts +96 -0
- package/src/chat/ui/intelligent-ui/renderers/map-view.tsx +251 -0
- package/src/chat/ui/intelligent-ui/renderers/map.tsx +226 -0
- package/src/chat/ui/intelligent-ui/renderers/place-point.ts +16 -0
- package/src/chat/ui/intelligent-ui/renderers/text.tsx +28 -1
- package/src/chat/ui/intelligent-ui/use-in-view.ts +18 -0
- package/src/chat/ui/rows/WorkRows.tsx +3 -3
- package/src/host.ts +28 -0
- package/src/index.ts +2 -12
- package/src/lazy.tsx +5 -7
- package/src/locales/en/agent-chat.ts +48 -1
- package/src/locales/nl/agent-chat.ts +48 -1
- package/src/prompts/index.ts +3 -18
- package/src/providers/index.ts +3 -9
- package/src/state/index.ts +1 -16
- package/src/state/usage.ts +0 -4
- package/src/stylesheets.d.ts +2 -0
- package/src/theme.css +10 -0
package/dist/prompts/index.d.ts
CHANGED
|
@@ -1,11 +1,9 @@
|
|
|
1
|
-
export { focusPromptStart
|
|
1
|
+
export { focusPromptStart } from './logic/focus.js';
|
|
2
2
|
export { PROMPT_SHORTCUTS, pageKey, type PromptKeyEvent } from './logic/keys.js';
|
|
3
|
-
export { type PendingPrompt, type PromptAction, emptyPromptDraft,
|
|
3
|
+
export { type PendingPrompt, type PromptAction, emptyPromptDraft, orderPrompts, type PromptAnswer, type PromptDraft } from './logic/prompts.js';
|
|
4
4
|
export { type HostPrompt, type PromptSubject, type ChatPromptClients, type PromptViewProps, type ApprovalButtonSpec, promptIdOf, promptCreatedAt, isBlockingSubject, answerPrompt } from './logic/subjects.js';
|
|
5
5
|
export { useFocusAfterAnswer, type FocusAfterAnswer } from './logic/useFocusAfterAnswer.js';
|
|
6
6
|
export { usePromptSession, type PromptSession } from './logic/usePromptSession.js';
|
|
7
|
-
export {
|
|
8
|
-
export { PromptPrimary, ApprovalActions, QuestionActions, type ApprovalButton } from './ui/PromptActions.js';
|
|
7
|
+
export { PromptPrimary, ApprovalActions, type ApprovalButton } from './ui/PromptActions.js';
|
|
9
8
|
export { PROMPT_SURFACE, PromptCard, type PromptCardKind } from './ui/PromptCard.js';
|
|
10
9
|
export { PromptView } from './ui/PromptView.js';
|
|
11
|
-
export { QuestionBody } from './ui/QuestionBody.js';
|
package/dist/prompts/index.js
CHANGED
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
// Public API: exports.test.ts snapshots this list, so a name added or dropped here is an API change.
|
|
2
|
-
export { focusPromptStart
|
|
2
|
+
export { focusPromptStart } from './logic/focus.js';
|
|
3
3
|
export { PROMPT_SHORTCUTS, pageKey } from './logic/keys.js';
|
|
4
|
-
export { emptyPromptDraft,
|
|
4
|
+
export { emptyPromptDraft, orderPrompts } from './logic/prompts.js';
|
|
5
5
|
export { promptIdOf, promptCreatedAt, isBlockingSubject, answerPrompt } from './logic/subjects.js';
|
|
6
6
|
export { useFocusAfterAnswer } from './logic/useFocusAfterAnswer.js';
|
|
7
7
|
export { usePromptSession } from './logic/usePromptSession.js';
|
|
8
|
-
export {
|
|
9
|
-
export { PromptPrimary, ApprovalActions, QuestionActions } from './ui/PromptActions.js';
|
|
8
|
+
export { PromptPrimary, ApprovalActions } from './ui/PromptActions.js';
|
|
10
9
|
export { PROMPT_SURFACE, PromptCard } from './ui/PromptCard.js';
|
|
11
10
|
export { PromptView } from './ui/PromptView.js';
|
|
12
|
-
export { QuestionBody } from './ui/QuestionBody.js';
|
|
@@ -2,15 +2,9 @@ export { AccountDot } from '../agents/AccountDot.js';
|
|
|
2
2
|
export { AgentIcon } from '../agents/AgentIcon.js';
|
|
3
3
|
export { ModelOptionControl } from '../agents/ModelOptionControl.js';
|
|
4
4
|
export { ProviderLogo } from '../agents/ProviderLogo.js';
|
|
5
|
-
export { type AccountEntry, accountsOfKind,
|
|
5
|
+
export { type AccountEntry, accountsOfKind, ACCOUNT_TONE_CLASSES, accountStatusLine, canContinueOn, type AccountTone } from '../agents/accounts.js';
|
|
6
6
|
export { modelName, useModelName, shortModelName } from '../agents/model-name.js';
|
|
7
|
-
export {
|
|
8
|
-
export {
|
|
9
|
-
export { AccountColors } from './AccountColors.js';
|
|
10
|
-
export { AccountDetail } from './AccountDetail.js';
|
|
11
|
-
export { AccountVariables } from './AccountVariables.js';
|
|
12
|
-
export { AddAccountForm } from './AddAccountForm.js';
|
|
13
|
-
export { CliDetail } from './CliDetail.js';
|
|
7
|
+
export { carryOptions } from '../agents/model-options.js';
|
|
8
|
+
export { type ModelRequirement } from '../agents/model-requirement.js';
|
|
14
9
|
export { ProvidersPane } from './ProvidersPane.js';
|
|
15
|
-
export { saveAccounts, saveAccount, removeAccount, createAccount, linkAccount } from './account-actions.js';
|
|
16
10
|
export { CliMark, CliTile } from './parts.js';
|
package/dist/providers/index.js
CHANGED
|
@@ -3,15 +3,9 @@ export { AccountDot } from '../agents/AccountDot.js';
|
|
|
3
3
|
export { AgentIcon } from '../agents/AgentIcon.js';
|
|
4
4
|
export { ModelOptionControl } from '../agents/ModelOptionControl.js';
|
|
5
5
|
export { ProviderLogo } from '../agents/ProviderLogo.js';
|
|
6
|
-
export { accountsOfKind,
|
|
6
|
+
export { accountsOfKind, ACCOUNT_TONE_CLASSES, accountStatusLine, canContinueOn } from '../agents/accounts.js';
|
|
7
7
|
export { modelName, useModelName, shortModelName } from '../agents/model-name.js';
|
|
8
|
-
export {
|
|
9
|
-
export {
|
|
10
|
-
export { AccountColors } from './AccountColors.js';
|
|
11
|
-
export { AccountDetail } from './AccountDetail.js';
|
|
12
|
-
export { AccountVariables } from './AccountVariables.js';
|
|
13
|
-
export { AddAccountForm } from './AddAccountForm.js';
|
|
14
|
-
export { CliDetail } from './CliDetail.js';
|
|
8
|
+
export { carryOptions } from '../agents/model-options.js';
|
|
9
|
+
export {} from '../agents/model-requirement.js';
|
|
15
10
|
export { ProvidersPane } from './ProvidersPane.js';
|
|
16
|
-
export { saveAccounts, saveAccount, removeAccount, createAccount, linkAccount } from './account-actions.js';
|
|
17
11
|
export { CliMark, CliTile } from './parts.js';
|
package/dist/state/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { type ChatState, type ChatsById, type ChatStatuses, type ChatSink,
|
|
1
|
+
export { type ChatState, type ChatsById, type ChatStatuses, type ChatSink, waitingRequestsOf, applyEvent, useChats, chatSink, useChatRow, type ChatHistoryPage, type ChatPage } from './chats.js';
|
|
2
2
|
export { useProviderAccountsStore, useProviderAccounts, providerAccountsOf, knownAccounts, watchProviderAccounts, type ProviderAccountsRow } from './provider-accounts.js';
|
|
3
3
|
export { useProvidersStore, useProviders, providersOf, providerSinkFor, type ProvidersRow } from './providers.js';
|
|
4
|
-
export { type UsageMetric, USAGE_PREFERENCES_KEY,
|
|
4
|
+
export { type UsageMetric, USAGE_PREFERENCES_KEY, dayOf, windowFor, reloadUsagePreferences, useUsageStore, type UsagePeriod, type UsageView } from './usage.js';
|
package/dist/state/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// Public API: exports.test.ts snapshots this list, so a name added or dropped here is an API change.
|
|
2
|
-
export {
|
|
2
|
+
export { waitingRequestsOf, applyEvent, useChats, chatSink, useChatRow } from './chats.js';
|
|
3
3
|
export { useProviderAccountsStore, useProviderAccounts, providerAccountsOf, knownAccounts, watchProviderAccounts } from './provider-accounts.js';
|
|
4
4
|
export { useProvidersStore, useProviders, providersOf, providerSinkFor } from './providers.js';
|
|
5
|
-
export { USAGE_PREFERENCES_KEY,
|
|
5
|
+
export { USAGE_PREFERENCES_KEY, dayOf, windowFor, reloadUsagePreferences, useUsageStore } from './usage.js';
|
package/dist/state/usage.d.ts
CHANGED
package/dist/state/usage.js
CHANGED
|
@@ -14,9 +14,6 @@ export let USAGE_PREFERENCES_KEY = storageKey();
|
|
|
14
14
|
onChatStorageConfiguration(() => {
|
|
15
15
|
USAGE_PREFERENCES_KEY = storageKey();
|
|
16
16
|
});
|
|
17
|
-
export function usagePreferencesKey() {
|
|
18
|
-
return storageKey();
|
|
19
|
-
}
|
|
20
17
|
const DEFAULTS = { period: '7d', metric: 'cost', currency: 'USD' };
|
|
21
18
|
function parsePreferences(raw) {
|
|
22
19
|
try {
|
package/dist/theme.css
CHANGED
|
@@ -27,6 +27,9 @@
|
|
|
27
27
|
--chart-4: #eda100;
|
|
28
28
|
--chart-5: #e87ba4;
|
|
29
29
|
--chart-6: #008300;
|
|
30
|
+
/* The two grounds of the map a page draws without tiles. */
|
|
31
|
+
--map-land: #f2f1ed;
|
|
32
|
+
--map-water: #d3dde5;
|
|
30
33
|
}
|
|
31
34
|
|
|
32
35
|
[data-theme="dark"] {
|
|
@@ -46,6 +49,8 @@
|
|
|
46
49
|
--chart-4: #c98500;
|
|
47
50
|
--chart-5: #d55181;
|
|
48
51
|
--chart-6: #008300;
|
|
52
|
+
--map-land: #2c3135;
|
|
53
|
+
--map-water: #1a2026;
|
|
49
54
|
}
|
|
50
55
|
|
|
51
56
|
/* Output and diffs take the terminal's colors when the app loads `@adecore/terminal/terminal.css`,
|
|
@@ -56,6 +61,9 @@
|
|
|
56
61
|
--chat-added: var(--term-ansi-green, var(--positive));
|
|
57
62
|
--chat-removed: var(--term-ansi-red, var(--status-error));
|
|
58
63
|
--chart-1: var(--accent);
|
|
64
|
+
/* The number of a place on a map and in its list: the ink on the ground, so it reads on either. */
|
|
65
|
+
--map-marker: var(--text);
|
|
66
|
+
--map-marker-text: var(--surface);
|
|
59
67
|
}
|
|
60
68
|
|
|
61
69
|
@theme inline {
|
|
@@ -73,6 +81,8 @@
|
|
|
73
81
|
--color-chat-output: var(--chat-output);
|
|
74
82
|
--color-chat-added: var(--chat-added);
|
|
75
83
|
--color-chat-removed: var(--chat-removed);
|
|
84
|
+
--color-map-marker: var(--map-marker);
|
|
85
|
+
--color-map-marker-text: var(--map-marker-text);
|
|
76
86
|
}
|
|
77
87
|
|
|
78
88
|
@layer components {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adecore/agents-react",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.25.0",
|
|
4
4
|
"description": "React agent chat threads, composers, approvals, provider accounts and usage views.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -67,11 +67,11 @@
|
|
|
67
67
|
"test:visuals": "bun --config=integration.bunfig.toml --conditions=source test ./src/chat/visual-viewport.integration.test.ts"
|
|
68
68
|
},
|
|
69
69
|
"dependencies": {
|
|
70
|
-
"@adecore/agent-contracts": "0.
|
|
71
|
-
"@adecore/editor": "0.
|
|
72
|
-
"@adecore/editor-react": "0.
|
|
73
|
-
"@adecore/intelligent-ui": "0.
|
|
74
|
-
"@adecore/merge": "0.
|
|
70
|
+
"@adecore/agent-contracts": "0.25.0",
|
|
71
|
+
"@adecore/editor": "0.25.0",
|
|
72
|
+
"@adecore/editor-react": "0.25.0",
|
|
73
|
+
"@adecore/intelligent-ui": "0.25.0",
|
|
74
|
+
"@adecore/merge": "0.25.0",
|
|
75
75
|
"@codemirror/commands": "^6.11.1",
|
|
76
76
|
"@codemirror/language": "^6.12.4",
|
|
77
77
|
"@codemirror/state": "^6.7.6",
|
|
@@ -83,6 +83,7 @@
|
|
|
83
83
|
"@tanstack/react-virtual": "^3.14.13",
|
|
84
84
|
"clsx": "^2.1.1",
|
|
85
85
|
"lucide-react": "^1.47.0",
|
|
86
|
+
"maplibre-gl": "^6.14.0",
|
|
86
87
|
"mermaid": "^12.2.0",
|
|
87
88
|
"react-markdown": "^10.1.0",
|
|
88
89
|
"remark-breaks": "^4.0.0",
|
|
@@ -93,14 +94,14 @@
|
|
|
93
94
|
"zustand": "^5.0.15"
|
|
94
95
|
},
|
|
95
96
|
"peerDependencies": {
|
|
96
|
-
"@adecore/ui": "^0.
|
|
97
|
+
"@adecore/ui": "^0.25.0",
|
|
97
98
|
"i18next": "^26.4.2",
|
|
98
99
|
"react": "^19.3.0",
|
|
99
100
|
"react-dom": "^19.3.0",
|
|
100
101
|
"react-i18next": "^17.0.15"
|
|
101
102
|
},
|
|
102
103
|
"devDependencies": {
|
|
103
|
-
"@adecore/ui": "0.
|
|
104
|
+
"@adecore/ui": "0.25.0",
|
|
104
105
|
"@types/bun": "^1.4.2",
|
|
105
106
|
"@types/react": "^19.3.0",
|
|
106
107
|
"@types/react-dom": "^19.3.0",
|
package/src/chat/index.ts
CHANGED
|
@@ -1,18 +1,6 @@
|
|
|
1
1
|
// Public API: exports.test.ts snapshots this list, so a name added or dropped here is an API change.
|
|
2
2
|
export { type AccountChoice, useAccountChoice } from './account-choice';
|
|
3
3
|
export { transportActions, actionsOf, useChatActions } from './actions';
|
|
4
|
-
export { backgroundCounts } from './activity';
|
|
5
|
-
export {
|
|
6
|
-
isImageAttachment,
|
|
7
|
-
fileBadge,
|
|
8
|
-
formatBytes,
|
|
9
|
-
checkAttachmentLimits,
|
|
10
|
-
filesOf,
|
|
11
|
-
readAttachments,
|
|
12
|
-
readStoredAttachments,
|
|
13
|
-
uploadPreviewUrl,
|
|
14
|
-
uploadBytes
|
|
15
|
-
} from './attachments';
|
|
16
4
|
export { type ChatSendExtras, ChatClient } from './chat-client';
|
|
17
5
|
export type { ProjectChat } from './chat-references';
|
|
18
6
|
export { sendFromComposer, type ComposerSend } from './composer-send';
|
|
@@ -36,24 +24,17 @@ export {
|
|
|
36
24
|
export { handbackReportOf } from './logic/handback';
|
|
37
25
|
export { limitView, type LimitView } from './logic/limit';
|
|
38
26
|
export type { TickKind, ScrubberTick } from './logic/scrubber';
|
|
39
|
-
export { type TimedRow,
|
|
27
|
+
export { type TimedRow, withTimedRows, timedRowsOf } from './logic/thread-cards';
|
|
40
28
|
export { EMPTY_TARGET, readTimelineTarget, type TimelineTarget } from './logic/timeline-target';
|
|
41
29
|
export { type TimelineRow, summarizeGroup, deriveTimelineRows, type SubagentBranch, type BaseMoved } from './logic/timeline';
|
|
42
|
-
export { toolSummary,
|
|
30
|
+
export { toolSummary, type FileChange } from './logic/tools';
|
|
43
31
|
export {
|
|
44
32
|
MENTION_DRAG_TYPE,
|
|
45
33
|
LEGACY_MENTION_DRAG_TYPE,
|
|
46
|
-
MENTION_DRAG_TYPES,
|
|
47
34
|
carriesMentions,
|
|
48
35
|
droppedMentions,
|
|
49
36
|
writeMentionDrag,
|
|
50
|
-
findMentionQuery,
|
|
51
|
-
findSkillQuery,
|
|
52
|
-
insertMention,
|
|
53
|
-
insertSkill,
|
|
54
|
-
presentMentions,
|
|
55
37
|
chipText,
|
|
56
|
-
tokenizeChips,
|
|
57
38
|
type MentionQuery,
|
|
58
39
|
type ChipSegment
|
|
59
40
|
} from './mentions';
|
|
@@ -66,7 +47,6 @@ export {
|
|
|
66
47
|
useChatPreferences,
|
|
67
48
|
readChatPreferences,
|
|
68
49
|
CHAT_PREFERENCES_KEY,
|
|
69
|
-
chatPreferencesKey,
|
|
70
50
|
reloadChatPreferences,
|
|
71
51
|
rememberChatPreferences,
|
|
72
52
|
rememberReadingWidth,
|
|
@@ -93,6 +73,5 @@ export {
|
|
|
93
73
|
type SubagentStep,
|
|
94
74
|
type SubagentTrail
|
|
95
75
|
} from './subagent-view';
|
|
96
|
-
export { THUMBNAIL_PX, useUploadThumbnail } from './thumbnails';
|
|
97
76
|
export { stepTimelineMessage, jumpToTimelineItem, type TurnTarget, registerTurnJumper, jumpToTimelineTurn, type ItemJumpOptions } from './timeline-scroll';
|
|
98
77
|
export { type StatusWord, statusLookOf, taskStatusWord, type StatusLook, type TaskState } from '../agents/status-look';
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { abortedByEnd, abortedByMachine, type ChatInfo, type ChatItem } from '@adecore/agent-contracts';
|
|
2
|
+
|
|
3
|
+
/* English like the other prompts the CLI gets, and it reaches the thread as the person's own message, which it is. */
|
|
4
|
+
export const CONTINUE_PROMPT = 'Continue.';
|
|
5
|
+
|
|
6
|
+
/*
|
|
7
|
+
* The turn a person stopped last, when nothing has happened since and Continue can pick it up; null otherwise.
|
|
8
|
+
* A paused queue, a limit and a paused goal have their own way out, a turn the machine ended has its own resume,
|
|
9
|
+
* and a request that waits on a person comes first.
|
|
10
|
+
*/
|
|
11
|
+
export function continuableTurn(info: ChatInfo, items: readonly ChatItem[]): string | null {
|
|
12
|
+
if (
|
|
13
|
+
info.activeTurnId !== null ||
|
|
14
|
+
info.status === 'needs-you' ||
|
|
15
|
+
(info.queue ?? []).length > 0 ||
|
|
16
|
+
info.limit !== undefined ||
|
|
17
|
+
info.goal?.status === 'paused'
|
|
18
|
+
) {
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
const index = items.findLastIndex((item) => item.kind === 'turn');
|
|
22
|
+
const turn = items[index];
|
|
23
|
+
if (turn?.kind !== 'turn' || turn.state !== 'aborted' || turn.limit !== undefined || abortedByMachine(turn, items) || abortedByEnd(turn, items)) {
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
// A message of this turn sits after the turn item too, so only one sent after the turn ended counts.
|
|
27
|
+
const endedAt = turn.endedAt ?? turn.createdAt;
|
|
28
|
+
if (items.slice(index + 1).some((item) => item.kind === 'user' && item.createdAt > endedAt)) {
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
return turn.id;
|
|
32
|
+
}
|
|
@@ -92,8 +92,3 @@ export function withTimedRows(rows: TimelineRow[], timed: readonly TimedRow[]):
|
|
|
92
92
|
export function timedRowsOf(cards: readonly ThreadCard[], visuals: readonly ChatVisual[] | null, heldFrom: number | null = null): TimedRow[] {
|
|
93
93
|
return [...(visuals === null ? [] : visualRows(visuals, heldFrom)), ...cardRows(cards)];
|
|
94
94
|
}
|
|
95
|
-
|
|
96
|
-
/* The thread's rows with an app's cards among them, the way `withTimedRows` places them. */
|
|
97
|
-
export function withThreadCards(rows: TimelineRow[], cards: readonly ThreadCard[]): TimelineRow[] {
|
|
98
|
-
return withTimedRows(rows, cardRows(cards));
|
|
99
|
-
}
|
package/src/chat/preferences.ts
CHANGED
|
@@ -143,10 +143,6 @@ onChatStorageConfiguration(() => {
|
|
|
143
143
|
CHAT_PREFERENCES_KEY = storageKey();
|
|
144
144
|
});
|
|
145
145
|
|
|
146
|
-
export function chatPreferencesKey(): string {
|
|
147
|
-
return storageKey();
|
|
148
|
-
}
|
|
149
|
-
|
|
150
146
|
/* Reads the remembered default again, once another window of the same origin wrote it. */
|
|
151
147
|
export function reloadChatPreferences(): void {
|
|
152
148
|
useChatPreferences.setState(storage.read(), true);
|
package/src/chat/stash.ts
CHANGED
|
@@ -26,6 +26,8 @@ export interface StashedPrompt {
|
|
|
26
26
|
text: string;
|
|
27
27
|
mentions: string[];
|
|
28
28
|
skills: string[];
|
|
29
|
+
/* Chats of the project picked with `@`; an entry from before this field has none. */
|
|
30
|
+
chats: string[];
|
|
29
31
|
attachments: StashedAttachment[];
|
|
30
32
|
/* A quote that knew its reply, kept apart from the text so it can lead back to it in the chat it came from. */
|
|
31
33
|
quote?: StashedQuote;
|
|
@@ -83,6 +85,7 @@ export function parseStash(raw: string | null): StashedPrompt[] {
|
|
|
83
85
|
text: entry.text as string,
|
|
84
86
|
mentions: strings(entry.mentions),
|
|
85
87
|
skills: strings(entry.skills),
|
|
88
|
+
chats: strings(entry.chats),
|
|
86
89
|
attachments: attachments(entry.attachments),
|
|
87
90
|
...stashedQuoteField(entry.quote),
|
|
88
91
|
createdAt: typeof entry.createdAt === 'number' ? entry.createdAt : 0
|
|
@@ -113,11 +116,25 @@ export function stashedFrom(draft: ChatDraft, id: string, now: number, chatId: s
|
|
|
113
116
|
...(kept ? { quote: { text: draft.quote, chatId, itemId: draft.quoteSource! } } : {}),
|
|
114
117
|
mentions: [...draft.mentions],
|
|
115
118
|
skills: [...draft.skills],
|
|
119
|
+
chats: [...draft.chats],
|
|
116
120
|
attachments: draft.attachments.map((attachment) => ({ name: attachment.name, mime: attachment.mime, size: uploadBytes(attachment) })),
|
|
117
121
|
createdAt: now
|
|
118
122
|
};
|
|
119
123
|
}
|
|
120
124
|
|
|
125
|
+
/* The limit of `chats` in a send. */
|
|
126
|
+
export const STASH_CHATS_LIMIT = 16;
|
|
127
|
+
|
|
128
|
+
/*
|
|
129
|
+
* The attached chats a composer may take back: the ones it can still reference, never its own chat, in the
|
|
130
|
+
* order they were picked. `dropped` counts the chats left out because the project no longer has them.
|
|
131
|
+
*/
|
|
132
|
+
export function restorableChats(stashed: readonly string[], referable: ReadonlySet<string>, chatId: string): { chats: string[]; dropped: number } {
|
|
133
|
+
const others = stashed.filter((id) => id !== chatId);
|
|
134
|
+
const chats = others.filter((id) => referable.has(id));
|
|
135
|
+
return { chats: chats.slice(0, STASH_CHATS_LIMIT), dropped: others.length - chats.length };
|
|
136
|
+
}
|
|
137
|
+
|
|
121
138
|
const storage = persistedJson<StashedPrompt[]>(storageKey, parseStash, [], () => chatStorageLegacyKeys('stash'));
|
|
122
139
|
|
|
123
140
|
/* Prompts put aside for later can move to another chat, so the shelf is shared across chats. */
|
package/src/chat/ui/Composer.tsx
CHANGED
|
@@ -36,6 +36,7 @@ import { useComposerDraft } from './composer/use-composer-draft';
|
|
|
36
36
|
import { useComposerMenus } from './composer/use-composer-menus';
|
|
37
37
|
import { useComposerSubmit } from './composer/use-composer-submit';
|
|
38
38
|
import { LEAVE_DROPS_TO_THE_CARD, useDraftFiles } from './composer/use-draft-files';
|
|
39
|
+
import { useContinuableTurn } from './composer/use-continuable-turn';
|
|
39
40
|
import { useNotice } from './composer/use-notice';
|
|
40
41
|
import { usePendingRequests } from './composer/use-pending-requests';
|
|
41
42
|
import { usePromptHistory } from './composer/use-prompt-history';
|
|
@@ -96,7 +97,11 @@ export function Composer({ chatId, info, focused, answerPromptsElsewhere, disabl
|
|
|
96
97
|
const files = useDraftFiles({ capabilities, providerName: provider?.name, writable, draft: box, inputRef, setNotice: notice.setNotice });
|
|
97
98
|
const controls = useChatControls({ chatId, info, notice, onRetarget });
|
|
98
99
|
const guard = promptGuard(withQuote(draft.quote, draft.text));
|
|
99
|
-
const
|
|
100
|
+
const continuable = useContinuableTurn(chatId, info);
|
|
101
|
+
// The stopped turn something went out for, since the chat takes a moment to answer and Continue must not stand there meanwhile.
|
|
102
|
+
const [sentFor, setSentFor] = useState<string | null>(null);
|
|
103
|
+
const extraPrompts = host.prompts.useExtra(scope.id, chatId);
|
|
104
|
+
const { submit, continueTurn, restoreStashed, toggleStash } = useComposerSubmit({
|
|
100
105
|
chatId,
|
|
101
106
|
writable,
|
|
102
107
|
guard,
|
|
@@ -109,7 +114,23 @@ export function Composer({ chatId, info, focused, answerPromptsElsewhere, disabl
|
|
|
109
114
|
hold,
|
|
110
115
|
inputRef,
|
|
111
116
|
setNotice: notice.setNotice,
|
|
112
|
-
onSend
|
|
117
|
+
onSend: (text, extras) => {
|
|
118
|
+
setSentFor(continuable);
|
|
119
|
+
const sent = onSend(text, extras);
|
|
120
|
+
// A send the host did not take leaves Continue where it was; the original promise still reaches its caller.
|
|
121
|
+
void Promise.resolve(sent).then(
|
|
122
|
+
(taken) => {
|
|
123
|
+
if (taken === false) {
|
|
124
|
+
setSentFor(null);
|
|
125
|
+
}
|
|
126
|
+
},
|
|
127
|
+
(error: unknown) => {
|
|
128
|
+
setSentFor(null);
|
|
129
|
+
throw error;
|
|
130
|
+
}
|
|
131
|
+
);
|
|
132
|
+
return sent;
|
|
133
|
+
}
|
|
113
134
|
});
|
|
114
135
|
const { takingBack, takeBack } = useTakeBack({
|
|
115
136
|
chatId,
|
|
@@ -231,7 +252,7 @@ export function Composer({ chatId, info, focused, answerPromptsElsewhere, disabl
|
|
|
231
252
|
quote={draft.quote}
|
|
232
253
|
source={draft.quoteSource}
|
|
233
254
|
onRemove={box.removeQuote}
|
|
234
|
-
onSourceGone={() => notice.setNotice(t('rows.user.quoteGone'))}
|
|
255
|
+
onSourceGone={() => notice.setNotice(t('rows.user.quoteGone'), 'info')}
|
|
235
256
|
/>
|
|
236
257
|
)}
|
|
237
258
|
{draft.chats.length > 0 && <DraftChats chats={draft.chats} onRemove={box.removeChat} />}
|
|
@@ -263,7 +284,10 @@ export function Composer({ chatId, info, focused, answerPromptsElsewhere, disabl
|
|
|
263
284
|
onPaste={files.onPaste}
|
|
264
285
|
/>
|
|
265
286
|
{notice.notice && (
|
|
266
|
-
<div
|
|
287
|
+
<div
|
|
288
|
+
className={clsx('px-5 pb-1 text-xs @max-md/composer:px-3.5', notice.tone === 'error' ? 'text-status-error' : 'text-text-muted')}
|
|
289
|
+
role={notice.tone === 'error' ? 'alert' : 'status'}
|
|
290
|
+
>
|
|
267
291
|
{notice.notice}
|
|
268
292
|
</div>
|
|
269
293
|
)}
|
|
@@ -290,7 +314,11 @@ export function Composer({ chatId, info, focused, answerPromptsElsewhere, disabl
|
|
|
290
314
|
disabled: empty || !writable || guard.tooLong,
|
|
291
315
|
label: t(sendLabelKey(busy, steerable, sendDelivery)),
|
|
292
316
|
kbd: sendShortcut(sendKey, draft.text.includes('\n')),
|
|
293
|
-
onSend: (alternate) => submit(alternate ? 'alternate' : 'default')
|
|
317
|
+
onSend: (alternate) => submit(alternate ? 'alternate' : 'default'),
|
|
318
|
+
onContinue:
|
|
319
|
+
continuable !== null && continuable !== sentFor && empty && writable && pending.length === 0 && extraPrompts.length === 0
|
|
320
|
+
? continueTurn
|
|
321
|
+
: null
|
|
294
322
|
}}
|
|
295
323
|
dictationToolbar={setDictationToolbar}
|
|
296
324
|
onFiles={(picked) => {
|
package/src/chat/ui/EditDiff.tsx
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { useMemo } from 'react';
|
|
2
|
+
import { LazyBoundary } from '@adecore/ui';
|
|
2
3
|
import { useTranslation } from 'react-i18next';
|
|
3
4
|
import { lazyNamed } from '../../lazy';
|
|
4
5
|
import { diffSourceBudget, legacyDiffBudget } from './diff/diff-source-budget';
|
|
@@ -22,9 +23,9 @@ export default function EditDiff({ change, allowEditor = true, maxHeight }: { ch
|
|
|
22
23
|
const omitted = <DiffOmitted path={change.path} />;
|
|
23
24
|
const fallback = legacyAllowed ? (
|
|
24
25
|
<DiffFallbackBoundary fallback={omitted} resetKeys={[change.path, change.before, change.after]}>
|
|
25
|
-
<
|
|
26
|
+
<LazyBoundary fallback={<div className="px-3 py-2 text-xs text-text-faint">{t('work.loadingDiff')}</div>}>
|
|
26
27
|
<LegacyEditDiff change={change} maxHeight={maxHeight} />
|
|
27
|
-
</
|
|
28
|
+
</LazyBoundary>
|
|
28
29
|
</DiffFallbackBoundary>
|
|
29
30
|
) : (
|
|
30
31
|
omitted
|
|
@@ -38,9 +39,9 @@ export default function EditDiff({ change, allowEditor = true, maxHeight }: { ch
|
|
|
38
39
|
const unavailable = <DiffUnavailable path={change.path} />;
|
|
39
40
|
return (
|
|
40
41
|
<DiffFallbackBoundary fallback={unavailable} resetKeys={[change.path, change.before, change.after, loadEngine]}>
|
|
41
|
-
<
|
|
42
|
+
<LazyBoundary fallback={<div className="px-3 py-2 text-xs text-text-faint">{t('work.loadingDiff')}</div>}>
|
|
42
43
|
<EditorEditDiff change={change} loadEngine={loadEngine!} fallback={unavailable} maxHeight={maxHeight} sourceChecked />
|
|
43
|
-
</
|
|
44
|
+
</LazyBoundary>
|
|
44
45
|
</DiffFallbackBoundary>
|
|
45
46
|
);
|
|
46
47
|
}
|
package/src/chat/ui/Pickers.tsx
CHANGED
|
@@ -273,6 +273,7 @@ export function StashPicker({ onRestore }: { onRestore(prompt: StashedPrompt): v
|
|
|
273
273
|
{prompt.attachments.length > 0 && (
|
|
274
274
|
<span className="text-text-faint">{t('pickers.stash.files', { count: prompt.attachments.length })}</span>
|
|
275
275
|
)}
|
|
276
|
+
{prompt.chats.length > 0 && <span className="text-text-faint">{t('pickers.stash.chats', { count: prompt.chats.length })}</span>}
|
|
276
277
|
</Popover.Close>
|
|
277
278
|
<IconButton
|
|
278
279
|
icon={Trash2}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { useMemo } from 'react';
|
|
2
|
+
import { LazyBoundary } from '@adecore/ui';
|
|
2
3
|
import { useTranslation } from 'react-i18next';
|
|
3
4
|
import { lazyNamed } from '../../lazy';
|
|
4
5
|
import { diffSourceBudget, legacyDiffBudget, patchSourceBudget } from './diff/diff-source-budget';
|
|
@@ -27,9 +28,9 @@ export default function UnifiedDiff(props: UnifiedDiffProps) {
|
|
|
27
28
|
const omitted = <DiffOmitted path={change.path} />;
|
|
28
29
|
const fallback = legacyAllowed ? (
|
|
29
30
|
<DiffFallbackBoundary fallback={omitted} resetKeys={[change.path, change.diff, oldText, newText, diffStyle]}>
|
|
30
|
-
<
|
|
31
|
+
<LazyBoundary fallback={<div className="px-3 py-2 text-xs text-text-faint">{t('work.loadingDiff')}</div>}>
|
|
31
32
|
<LegacyUnifiedDiff {...props} />
|
|
32
|
-
</
|
|
33
|
+
</LazyBoundary>
|
|
33
34
|
</DiffFallbackBoundary>
|
|
34
35
|
) : (
|
|
35
36
|
omitted
|
|
@@ -46,7 +47,7 @@ export default function UnifiedDiff(props: UnifiedDiffProps) {
|
|
|
46
47
|
const unavailable = <DiffUnavailable path={change.path} />;
|
|
47
48
|
return (
|
|
48
49
|
<DiffFallbackBoundary fallback={unavailable} resetKeys={[change.path, change.diff, oldText, newText, ignoreWhitespace, diffStyle, loadEngine]}>
|
|
49
|
-
<
|
|
50
|
+
<LazyBoundary fallback={<div className="px-3 py-2 text-xs text-text-faint">{t('work.loadingDiff')}</div>}>
|
|
50
51
|
<EditorPatchDiff
|
|
51
52
|
change={change}
|
|
52
53
|
sourceChecked
|
|
@@ -59,7 +60,7 @@ export default function UnifiedDiff(props: UnifiedDiffProps) {
|
|
|
59
60
|
loadEngine={loadEngine!}
|
|
60
61
|
fallback={unavailable}
|
|
61
62
|
/>
|
|
62
|
-
</
|
|
63
|
+
</LazyBoundary>
|
|
63
64
|
</DiffFallbackBoundary>
|
|
64
65
|
);
|
|
65
66
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { useRef, type Ref } from 'react';
|
|
2
2
|
import { useTranslation } from 'react-i18next';
|
|
3
|
-
import { ArrowUp, Plus, Square } from 'lucide-react';
|
|
3
|
+
import { ArrowUp, Play, Plus, Square } from 'lucide-react';
|
|
4
4
|
import type { ChatInfo } from '@adecore/agent-contracts';
|
|
5
|
-
import { ErrorBoundary, Icon, Tooltip, type Shortcut } from '@adecore/ui';
|
|
5
|
+
import { Button, ErrorBoundary, Icon, Tooltip, type Shortcut } from '@adecore/ui';
|
|
6
6
|
import { useChatHost } from '../../../host';
|
|
7
7
|
import { useChatScope } from '../../../scope';
|
|
8
8
|
import { useProviders } from '../../../state/providers';
|
|
@@ -20,6 +20,8 @@ interface SendProps {
|
|
|
20
20
|
label: string;
|
|
21
21
|
kbd: Shortcut;
|
|
22
22
|
onSend(alternate: boolean): void;
|
|
23
|
+
/* Set when a person stopped the last turn and the box is empty: Continue stands where the send button would. */
|
|
24
|
+
onContinue: (() => void) | null;
|
|
23
25
|
}
|
|
24
26
|
|
|
25
27
|
interface ComposerControlsProps {
|
|
@@ -130,7 +132,15 @@ export function ComposerControls({
|
|
|
130
132
|
</button>
|
|
131
133
|
</Tooltip>
|
|
132
134
|
)}
|
|
133
|
-
{send.
|
|
135
|
+
{send.onContinue !== null && (
|
|
136
|
+
<Tooltip label={t('composer.continueHint')}>
|
|
137
|
+
<Button variant="primary" shape="pill" disabled={controls.configurationPending} onClick={send.onContinue}>
|
|
138
|
+
<Icon icon={Play} size={14} />
|
|
139
|
+
{t('composer.continue')}
|
|
140
|
+
</Button>
|
|
141
|
+
</Tooltip>
|
|
142
|
+
)}
|
|
143
|
+
{send.onContinue === null && send.visible && (
|
|
134
144
|
<Tooltip label={send.label} kbd={send.kbd} name>
|
|
135
145
|
<button
|
|
136
146
|
className="flex h-9 w-9 shrink-0 items-center justify-center rounded-full bg-accent text-accent-text hover:brightness-90 disabled:opacity-50 disabled:hover:brightness-100"
|