@wowyuarm/dsh-agent-team 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -2
- package/README.zh.md +10 -2
- package/package.json +32 -24
- package/packages/agent-team/lib/attachments.js +157 -0
- package/packages/agent-team/lib/index.js +280 -22
- package/packages/agent-team/lib/ledger.js +98 -22
- package/packages/agent-team/lib/recovery.js +87 -0
- package/packages/agent-team/lib/spec.js +27 -5
- package/packages/agent-team/lib/typert.host.js +313 -26
- package/packages/agent-team/lib/typert.remote-client.d.ts +9 -1
- package/packages/agent-team/lib/typert.remote-client.d.ts.map +1 -1
- package/packages/agent-team/lib/typert.remote-client.js +234 -17
- package/packages/agent-team/lib/types/attachments.d.ts +69 -0
- package/packages/agent-team/lib/types/attachments.d.ts.map +1 -0
- package/packages/agent-team/lib/types/index.d.ts +68 -6
- package/packages/agent-team/lib/types/index.d.ts.map +1 -1
- package/packages/agent-team/lib/types/ledger.d.ts +17 -1
- package/packages/agent-team/lib/types/ledger.d.ts.map +1 -1
- package/packages/agent-team/lib/types/recovery.d.ts +42 -0
- package/packages/agent-team/lib/types/recovery.d.ts.map +1 -0
- package/packages/agent-team/lib/types/spec.d.ts.map +1 -1
- package/packages/agent-team/lib/types/types.d.ts +94 -3
- package/packages/agent-team/lib/types/types.d.ts.map +1 -1
- package/packages/agent-team/preset/team-member/agent.cordis.yml +2 -2
- package/packages/client-agent-team/README.md +4 -3
- package/packages/client-agent-team/README.zh.md +4 -3
- package/packages/client-agent-team/lib/client.js +1791 -322
- package/packages/client-agent-team/lib/client.js.map +1 -1
- package/packages/client-agent-team/lib/types/client/TeamAgentsPanel.d.ts +5 -2
- package/packages/client-agent-team/lib/types/client/TeamAgentsPanel.d.ts.map +1 -1
- package/packages/client-agent-team/lib/types/client/TeamAgentsPanel.js +108 -59
- package/packages/client-agent-team/lib/types/client/TeamChannelPage.d.ts +7 -1
- package/packages/client-agent-team/lib/types/client/TeamChannelPage.d.ts.map +1 -1
- package/packages/client-agent-team/lib/types/client/TeamChannelPage.js +80 -19
- package/packages/client-agent-team/lib/types/client/TeamChannelsPanel.d.ts.map +1 -1
- package/packages/client-agent-team/lib/types/client/TeamChannelsPanel.js +38 -19
- package/packages/client-agent-team/lib/types/client/TeamComposer.d.ts +4 -1
- package/packages/client-agent-team/lib/types/client/TeamComposer.d.ts.map +1 -1
- package/packages/client-agent-team/lib/types/client/TeamComposer.js +61 -4
- package/packages/client-agent-team/lib/types/client/TeamConversation.d.ts +1 -1
- package/packages/client-agent-team/lib/types/client/TeamConversation.d.ts.map +1 -1
- package/packages/client-agent-team/lib/types/client/TeamConversation.js +3 -3
- package/packages/client-agent-team/lib/types/client/TeamMessage.d.ts +12 -2
- package/packages/client-agent-team/lib/types/client/TeamMessage.d.ts.map +1 -1
- package/packages/client-agent-team/lib/types/client/TeamMessage.js +152 -14
- package/packages/client-agent-team/lib/types/client/TeamRunDivider.d.ts +10 -0
- package/packages/client-agent-team/lib/types/client/TeamRunDivider.d.ts.map +1 -0
- package/packages/client-agent-team/lib/types/client/TeamRunDivider.js +12 -0
- package/packages/client-agent-team/lib/types/client/TeamThreadPage.d.ts +7 -0
- package/packages/client-agent-team/lib/types/client/TeamThreadPage.d.ts.map +1 -1
- package/packages/client-agent-team/lib/types/client/TeamThreadPage.js +93 -16
- package/packages/client-agent-team/lib/types/client/TeamWorkspaceBrowser.d.ts +1 -1
- package/packages/client-agent-team/lib/types/client/TeamWorkspaceBrowser.d.ts.map +1 -1
- package/packages/client-agent-team/lib/types/client/TeamWorkspaceBrowser.js +6 -5
- package/packages/client-agent-team/lib/types/client/attachment-preview.d.ts +22 -0
- package/packages/client-agent-team/lib/types/client/attachment-preview.d.ts.map +1 -0
- package/packages/client-agent-team/lib/types/client/attachment-preview.js +35 -0
- package/packages/client-agent-team/lib/types/client/drafts.d.ts +41 -0
- package/packages/client-agent-team/lib/types/client/drafts.d.ts.map +1 -0
- package/packages/client-agent-team/lib/types/client/drafts.js +144 -0
- package/packages/client-agent-team/lib/types/client/index.d.ts +2 -0
- package/packages/client-agent-team/lib/types/client/index.d.ts.map +1 -1
- package/packages/client-agent-team/lib/types/client/index.js +50 -10
- package/packages/client-agent-team/lib/types/client/locales.d.ts +34 -0
- package/packages/client-agent-team/lib/types/client/locales.d.ts.map +1 -1
- package/packages/client-agent-team/lib/types/client/locales.js +34 -0
- package/packages/client-agent-team/lib/types/client/multi-menu-field.d.ts +33 -0
- package/packages/client-agent-team/lib/types/client/multi-menu-field.d.ts.map +1 -0
- package/packages/client-agent-team/lib/types/client/multi-menu-field.js +30 -0
- package/packages/client-agent-team/lib/types/client/navigation.d.ts +16 -1
- package/packages/client-agent-team/lib/types/client/navigation.d.ts.map +1 -1
- package/packages/client-agent-team/lib/types/client/navigation.js +45 -8
- package/packages/client-agent-team/lib/types/client/sidebar-drag.d.ts +35 -0
- package/packages/client-agent-team/lib/types/client/sidebar-drag.d.ts.map +1 -0
- package/packages/client-agent-team/lib/types/client/sidebar-drag.js +70 -0
- package/packages/client-agent-team/lib/types/client/sidebar-order.d.ts +27 -0
- package/packages/client-agent-team/lib/types/client/sidebar-order.d.ts.map +1 -0
- package/packages/client-agent-team/lib/types/client/sidebar-order.js +170 -0
- package/packages/client-agent-team/lib/types/client/slots.d.ts +18 -2
- package/packages/client-agent-team/lib/types/client/slots.d.ts.map +1 -1
- package/packages/client-agent-team/lib/types/client/task-refs.d.ts +20 -0
- package/packages/client-agent-team/lib/types/client/task-refs.d.ts.map +1 -0
- package/packages/client-agent-team/lib/types/client/task-refs.js +58 -0
- package/packages/client-agent-team/lib/types/client/team-formatters.d.ts +15 -0
- package/packages/client-agent-team/lib/types/client/team-formatters.d.ts.map +1 -1
- package/packages/client-agent-team/lib/types/client/team-formatters.js +30 -2
- package/packages/client-agent-team/lib/types/client/team-separators.d.ts +8 -0
- package/packages/client-agent-team/lib/types/client/team-separators.d.ts.map +1 -1
- package/packages/client-agent-team/lib/types/client/team-separators.js +14 -0
- package/packages/tool-agent-team/lib/index.js +10 -6
- package/packages/tool-agent-team/lib/types/index.d.ts.map +1 -1
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Human presentation preference for the Team sidebar: the row order of the
|
|
3
|
+
* Channels and Agents lists. The order lives in this browser only — it is UI
|
|
4
|
+
* taste, never a shared Team fact, so nothing here touches the ledger.
|
|
5
|
+
*
|
|
6
|
+
* One deep module owns the whole concern: storage, reconcile against the
|
|
7
|
+
* current Remote order (drop removed refs, keep the user's relative order,
|
|
8
|
+
* append newcomers in default order), the single `moveSidebarItem` mutation
|
|
9
|
+
* behind whole-row drag, and a small subscription hook with snapshot-stable
|
|
10
|
+
* results for `useSyncExternalStore`.
|
|
11
|
+
*/
|
|
12
|
+
import { useCallback, useSyncExternalStore } from 'react';
|
|
13
|
+
const STORAGE_KEY = 'dsh.agent-team.sidebar-order';
|
|
14
|
+
function listKey(workspaceId, kind) {
|
|
15
|
+
return workspaceId === undefined ? undefined : `${workspaceId}|${kind}`;
|
|
16
|
+
}
|
|
17
|
+
const MEMORY_ONLY = Symbol('sidebar-order.memory');
|
|
18
|
+
/**
|
|
19
|
+
* Read-through parse cache over the raw persisted payload: repeated snapshots
|
|
20
|
+
* skip re-validating an unchanged payload, while anything written outside this
|
|
21
|
+
* module — another tab, devtools, a cleared store — is picked up because the
|
|
22
|
+
* raw comparison misses.
|
|
23
|
+
*/
|
|
24
|
+
let cachedRaw;
|
|
25
|
+
let cachedOrders = {};
|
|
26
|
+
/**
|
|
27
|
+
* Parse persisted orders defensively: private mode, quota errors, and stale
|
|
28
|
+
* or corrupted payloads all degrade to "no preference" instead of breaking
|
|
29
|
+
* the sidebar.
|
|
30
|
+
*/
|
|
31
|
+
function storedOrders() {
|
|
32
|
+
let raw = null;
|
|
33
|
+
try {
|
|
34
|
+
raw = typeof localStorage === 'undefined' ? null : localStorage.getItem(STORAGE_KEY);
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
raw = null;
|
|
38
|
+
}
|
|
39
|
+
if (cachedRaw !== undefined && raw !== null && raw === cachedRaw)
|
|
40
|
+
return cachedOrders;
|
|
41
|
+
if (raw === null) {
|
|
42
|
+
if (cachedRaw === MEMORY_ONLY)
|
|
43
|
+
return cachedOrders;
|
|
44
|
+
cachedRaw = raw;
|
|
45
|
+
cachedOrders = {};
|
|
46
|
+
return cachedOrders;
|
|
47
|
+
}
|
|
48
|
+
try {
|
|
49
|
+
const parsed = JSON.parse(raw);
|
|
50
|
+
if (parsed === null || typeof parsed !== 'object' || Array.isArray(parsed))
|
|
51
|
+
throw new Error('not an object');
|
|
52
|
+
const clean = {};
|
|
53
|
+
for (const [key, value] of Object.entries(parsed)) {
|
|
54
|
+
if (!Array.isArray(value) || !value.every(entry => typeof entry === 'string'))
|
|
55
|
+
continue;
|
|
56
|
+
clean[key] = value;
|
|
57
|
+
}
|
|
58
|
+
cachedRaw = raw;
|
|
59
|
+
cachedOrders = clean;
|
|
60
|
+
return cachedOrders;
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
return {};
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
function saveOrder(key, refs) {
|
|
67
|
+
const next = { ...structuredClone(storedOrders()), [key]: refs };
|
|
68
|
+
cachedOrders = next;
|
|
69
|
+
try {
|
|
70
|
+
if (typeof localStorage !== 'undefined') {
|
|
71
|
+
const raw = JSON.stringify(next);
|
|
72
|
+
localStorage.setItem(STORAGE_KEY, raw);
|
|
73
|
+
cachedRaw = raw;
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
catch {
|
|
78
|
+
// Private mode and quota failures do not block reordering; the session
|
|
79
|
+
// keeps serving the in-memory order below.
|
|
80
|
+
}
|
|
81
|
+
cachedRaw = MEMORY_ONLY;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Merge the saved personal order into the current Remote order: kept refs
|
|
85
|
+
* stay in the user's relative order with duplicates collapsed, removed refs
|
|
86
|
+
* disappear, and new refs join in their Remote default positions after the
|
|
87
|
+
* known ones.
|
|
88
|
+
*/
|
|
89
|
+
export function reconcileSidebarOrder(saved, current) {
|
|
90
|
+
const present = new Set(current);
|
|
91
|
+
const seen = new Set();
|
|
92
|
+
const merged = [];
|
|
93
|
+
for (const ref of saved) {
|
|
94
|
+
if (seen.has(ref) || !present.has(ref))
|
|
95
|
+
continue;
|
|
96
|
+
seen.add(ref);
|
|
97
|
+
merged.push(ref);
|
|
98
|
+
}
|
|
99
|
+
for (const ref of current) {
|
|
100
|
+
if (seen.has(ref))
|
|
101
|
+
continue;
|
|
102
|
+
seen.add(ref);
|
|
103
|
+
merged.push(ref);
|
|
104
|
+
}
|
|
105
|
+
return merged;
|
|
106
|
+
}
|
|
107
|
+
let revision = 0;
|
|
108
|
+
const listeners = new Set();
|
|
109
|
+
const snapshots = new Map();
|
|
110
|
+
function savedFingerprint(key) {
|
|
111
|
+
const saved = storedOrders()[key];
|
|
112
|
+
return saved === undefined ? '' : `f${saved.length}:${saved.join(',')}`;
|
|
113
|
+
}
|
|
114
|
+
function emitChange() {
|
|
115
|
+
revision += 1;
|
|
116
|
+
for (const listener of listeners)
|
|
117
|
+
listener();
|
|
118
|
+
}
|
|
119
|
+
function orderedSnapshot(workspaceId, kind, refs) {
|
|
120
|
+
const key = listKey(workspaceId, kind);
|
|
121
|
+
if (key === undefined)
|
|
122
|
+
return refs;
|
|
123
|
+
const signature = refs.join('\u0000');
|
|
124
|
+
const fingerprint = savedFingerprint(key);
|
|
125
|
+
const hit = snapshots.get(key);
|
|
126
|
+
if (hit !== undefined && hit.atRevision === revision && hit.signature === signature && hit.savedFingerprint === fingerprint) {
|
|
127
|
+
return hit.result;
|
|
128
|
+
}
|
|
129
|
+
const result = reconcileSidebarOrder(storedOrders()[key] ?? [], refs);
|
|
130
|
+
snapshots.set(key, { atRevision: revision, signature, savedFingerprint: fingerprint, result });
|
|
131
|
+
return result;
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Effective row order for one sidebar list: the user's saved order folded
|
|
135
|
+
* into the given Remote default order. Identity-stable across renders while
|
|
136
|
+
* neither the data nor this browser's preference changes.
|
|
137
|
+
*/
|
|
138
|
+
export function useSidebarOrder(workspaceId, kind, refs) {
|
|
139
|
+
const subscribe = useCallback((listener) => {
|
|
140
|
+
listeners.add(listener);
|
|
141
|
+
return () => { listeners.delete(listener); };
|
|
142
|
+
}, []);
|
|
143
|
+
return useSyncExternalStore(subscribe, () => orderedSnapshot(workspaceId, kind, refs), () => orderedSnapshot(workspaceId, kind, refs));
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* The only mutation path: move `movedRef` to the given side of `targetRef`
|
|
147
|
+
* inside the list's current effective order. Returns the new order, or
|
|
148
|
+
* `undefined` when the request cannot change anything (unknown refs, dropping
|
|
149
|
+
* a row onto itself, or an adjacent marker that would put it right back).
|
|
150
|
+
* Persistence and subscriber notification happen here.
|
|
151
|
+
*/
|
|
152
|
+
export function moveSidebarItem(workspaceId, kind, refs, movedRef, targetRef, marker) {
|
|
153
|
+
const key = listKey(workspaceId, kind);
|
|
154
|
+
const from = refs.indexOf(movedRef);
|
|
155
|
+
const nextFromTarget = refs.indexOf(targetRef);
|
|
156
|
+
if (key === undefined || from < 0 || nextFromTarget < 0 || movedRef === targetRef)
|
|
157
|
+
return undefined;
|
|
158
|
+
const next = [...refs];
|
|
159
|
+
const [item] = next.splice(from, 1);
|
|
160
|
+
if (item === undefined)
|
|
161
|
+
return undefined;
|
|
162
|
+
const insertAt = next.indexOf(targetRef) + (marker === 'after' ? 1 : 0);
|
|
163
|
+
if (insertAt === from)
|
|
164
|
+
return undefined;
|
|
165
|
+
next.splice(insertAt, 0, item);
|
|
166
|
+
saveOrder(key, next);
|
|
167
|
+
snapshots.delete(key);
|
|
168
|
+
emitChange();
|
|
169
|
+
return next;
|
|
170
|
+
}
|
|
@@ -1,18 +1,28 @@
|
|
|
1
1
|
import type { PropsLocale, PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots';
|
|
2
|
-
import type { AgentTeamAddMemberRequest, AgentTeamChannelRef, AgentTeamClientMemberStatus, AgentTeamCreateChannelRequest, AgentTeamCreateChannelResult, AgentTeamJoinChannelRequest, AgentTeamJoinChannelResult, AgentTeamMemberResult, AgentTeamMembersRequest, AgentTeamRemoveChannelMemberRequest, AgentTeamRemoveChannelMemberResult, AgentTeamReplyRequest, AgentTeamReplyResult, AgentTeamConfirmationRequired, AgentTeamThreadHistory, AgentTeamThreadHistoryRequest, AgentTeamThreadReadRequest, AgentTeamThreadReadResult, AgentTeamTaskRequest, AgentTeamTaskResult, AgentTeamSendMessageRequest, AgentTeamSendMessageResult, AgentTeamUpdateChannelRequest, AgentTeamUpdateChannelResult, AgentTeamUpdateMemberRequest, AgentTeamView, AgentTeamViewRequest } from '@wowyuarm/dsh-agent-team/types';
|
|
2
|
+
import type { AgentTeamAddMemberRequest, AgentTeamChannelRef, AgentTeamClientMemberStatus, AgentTeamCreateChannelRequest, AgentTeamCreateChannelResult, AgentTeamJoinChannelRequest, AgentTeamJoinChannelResult, AgentTeamGetAttachmentRequest, AgentTeamGetAttachmentResult, AgentTeamPutAttachmentRequest, AgentTeamPutAttachmentResult, AgentTeamMemberResult, AgentTeamRecoverMemberRequest, AgentTeamRecoverMemberResult, AgentTeamMembersRequest, AgentTeamRemoveChannelMemberRequest, AgentTeamRemoveChannelMemberResult, AgentTeamReplyRequest, AgentTeamResolveTaskRefsRequest, AgentTeamResolveTaskRefsResult, AgentTeamReplyResult, AgentTeamConfirmationRequired, AgentTeamThreadHistory, AgentTeamThreadHistoryRequest, AgentTeamThreadReadRequest, AgentTeamThreadReadResult, AgentTeamTaskRequest, AgentTeamTaskResult, AgentTeamSendMessageRequest, AgentTeamSendMessageResult, AgentTeamUpdateChannelRequest, AgentTeamUpdateChannelResult, AgentTeamUpdateMemberRequest, AgentTeamView, AgentTeamViewRequest } from '@wowyuarm/dsh-agent-team/types';
|
|
3
3
|
import type { RemoteResult } from '@deepseek-ai/dsh-typert-protocol';
|
|
4
4
|
import type { TeamNavigationActions, TeamNavigationSnapshot } from './navigation.ts';
|
|
5
5
|
import type { TeamChangeListener, TeamChangeScope } from './team-changes.ts';
|
|
6
|
+
import type { TeamDraftStore } from './drafts.ts';
|
|
6
7
|
export interface TeamNavigationSource {
|
|
7
8
|
getSnapshot: () => TeamNavigationSnapshot;
|
|
8
9
|
subscribe: (listener: () => void) => () => void;
|
|
9
10
|
}
|
|
10
11
|
/** Subscribe to one projection scope's invalidation stream; disposal aborts the shared poll. */
|
|
11
12
|
export type SubscribeTeamChanges = (scope: TeamChangeScope, listener: TeamChangeListener) => () => void;
|
|
13
|
+
/** One adapter-owned selectable reasoning effort of one model route. */
|
|
14
|
+
export interface TeamModelEffortOption {
|
|
15
|
+
readonly id: string;
|
|
16
|
+
readonly name: string;
|
|
17
|
+
}
|
|
12
18
|
/** One selectable model row inside one provider group of the Host catalog. */
|
|
13
19
|
export interface TeamModelOption {
|
|
14
20
|
readonly id: string;
|
|
15
21
|
readonly name: string;
|
|
22
|
+
/** Selectable reasoning levels when the adapter exposes them. */
|
|
23
|
+
readonly reasoning?: {
|
|
24
|
+
readonly efforts: readonly TeamModelEffortOption[];
|
|
25
|
+
};
|
|
16
26
|
}
|
|
17
27
|
/** Provider-grouped slice of the Host model catalog the editors render. */
|
|
18
28
|
export interface TeamModelProviderGroup {
|
|
@@ -38,25 +48,31 @@ export type TeamSidebarProps = PropsRuntime<'sidebar.workspaces'> & PropsLocale<
|
|
|
38
48
|
createChannel: (request: AgentTeamCreateChannelRequest) => Promise<RemoteResult<AgentTeamCreateChannelResult>>;
|
|
39
49
|
updateChannel: (request: AgentTeamUpdateChannelRequest) => Promise<RemoteResult<AgentTeamUpdateChannelResult>>;
|
|
40
50
|
updateMember: (request: AgentTeamUpdateMemberRequest) => Promise<RemoteResult<AgentTeamMemberResult>>;
|
|
51
|
+
recoverMember: (request: AgentTeamRecoverMemberRequest) => Promise<RemoteResult<AgentTeamRecoverMemberResult>>;
|
|
41
52
|
joinChannel: (request: AgentTeamJoinChannelRequest) => Promise<RemoteResult<AgentTeamJoinChannelResult>>;
|
|
42
53
|
removeChannelMember: (request: AgentTeamRemoveChannelMemberRequest) => Promise<RemoteResult<AgentTeamRemoveChannelMemberResult>>;
|
|
43
54
|
/** Session-independent Host model catalog (`llm.models`); needs no live Member. */
|
|
44
55
|
loadModels: () => Promise<RemoteResult<TeamModelCatalog>>;
|
|
45
|
-
/**
|
|
56
|
+
/** Embed the Member's Session conversation in the Team conversation seat. */
|
|
46
57
|
openMemberSession: (sessionId: AgentTeamClientMemberStatus['member']['sessionId']) => void;
|
|
47
58
|
selectedChannelRef?: AgentTeamChannelRef;
|
|
48
59
|
};
|
|
49
60
|
export type TeamConversationProps = PropsRuntime<'conversation'> & PropsLocale<'team'> & TeamNavigationActions & {
|
|
50
61
|
navigation: TeamNavigationSource;
|
|
62
|
+
/** Keyed composer draft cache; one store per Client context. */
|
|
63
|
+
drafts: TeamDraftStore;
|
|
51
64
|
loadChannels: (request: AgentTeamViewRequest) => Promise<RemoteResult<AgentTeamView>>;
|
|
52
65
|
readThread: (request: AgentTeamThreadReadRequest) => Promise<RemoteResult<AgentTeamThreadReadResult>>;
|
|
53
66
|
loadThreadHistory: (request: AgentTeamThreadHistoryRequest) => Promise<RemoteResult<AgentTeamThreadHistory>>;
|
|
54
67
|
subscribeChanges: SubscribeTeamChanges;
|
|
68
|
+
putAttachment: (request: AgentTeamPutAttachmentRequest) => Promise<RemoteResult<AgentTeamPutAttachmentResult>>;
|
|
69
|
+
getAttachment: (request: AgentTeamGetAttachmentRequest) => Promise<RemoteResult<AgentTeamGetAttachmentResult>>;
|
|
55
70
|
sendMessage: (request: AgentTeamSendMessageRequest) => Promise<RemoteResult<AgentTeamSendMessageResult>>;
|
|
56
71
|
joinChannel: (request: AgentTeamJoinChannelRequest) => Promise<RemoteResult<AgentTeamJoinChannelResult>>;
|
|
57
72
|
removeChannelMember: (request: AgentTeamRemoveChannelMemberRequest) => Promise<RemoteResult<AgentTeamRemoveChannelMemberResult>>;
|
|
58
73
|
reply: (request: AgentTeamReplyRequest) => Promise<RemoteResult<AgentTeamReplyResult | AgentTeamConfirmationRequired>>;
|
|
59
74
|
changeTask: (request: AgentTeamTaskRequest) => Promise<RemoteResult<AgentTeamTaskResult>>;
|
|
75
|
+
resolveTaskRefs: (request: AgentTeamResolveTaskRefsRequest) => Promise<RemoteResult<AgentTeamResolveTaskRefsResult>>;
|
|
60
76
|
loadMembers: (request: AgentTeamMembersRequest) => Promise<RemoteResult<readonly AgentTeamClientMemberStatus[]>>;
|
|
61
77
|
};
|
|
62
78
|
export type TeamSettingsProps = PropsRuntime<'sidebar.settings'> & PropsLocale<'team'> & {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"slots.d.ts","sourceRoot":"","sources":["../../../src/client/slots.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAA;AACjF,OAAO,KAAK,EACV,yBAAyB,EACzB,mBAAmB,EACnB,2BAA2B,EAC3B,6BAA6B,EAC7B,4BAA4B,EAC5B,2BAA2B,EAC3B,0BAA0B,EAC1B,qBAAqB,EACrB,uBAAuB,EACvB,mCAAmC,EACnC,kCAAkC,EAClC,qBAAqB,EACrB,oBAAoB,EACpB,6BAA6B,EAC7B,sBAAsB,EACtB,6BAA6B,EAC7B,0BAA0B,EAC1B,yBAAyB,EACzB,oBAAoB,EACpB,mBAAmB,EACnB,2BAA2B,EAC3B,0BAA0B,EAC1B,6BAA6B,EAC7B,4BAA4B,EAC5B,4BAA4B,EAC5B,aAAa,EACb,oBAAoB,EACrB,MAAM,gCAAgC,CAAA;AACvC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAA;AACpE,OAAO,KAAK,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAA;AACpF,OAAO,KAAK,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;
|
|
1
|
+
{"version":3,"file":"slots.d.ts","sourceRoot":"","sources":["../../../src/client/slots.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { AgentTeamChannelRef, AgentTeamTaskRef, AgentTeamThreadRef } from '@wowyuarm/dsh-agent-team/types';
|
|
2
|
+
/** Navigation facts for one branded Task ref, resolved once per session. */
|
|
3
|
+
export interface ResolvedTaskRef {
|
|
4
|
+
readonly taskRef: AgentTeamTaskRef;
|
|
5
|
+
readonly channelRef: AgentTeamChannelRef;
|
|
6
|
+
readonly threadRef: AgentTeamThreadRef;
|
|
7
|
+
readonly taskNumber: number;
|
|
8
|
+
}
|
|
9
|
+
/** React binding: re-renders the caller when any ref resolution lands. */
|
|
10
|
+
export declare const useResolvedTaskRefVersion: () => number;
|
|
11
|
+
export declare const cachedResolvedTaskRef: (taskRef: AgentTeamTaskRef) => ResolvedTaskRef | undefined;
|
|
12
|
+
/** Store one resolution (click path) and wake every rendered link. */
|
|
13
|
+
export declare const rememberResolvedTaskRef: (entry: ResolvedTaskRef) => void;
|
|
14
|
+
/**
|
|
15
|
+
* Batch-resolve unknown refs through the Host lookup. Concurrent callers
|
|
16
|
+
* deduplicate through the pending set; failures just clear the pending mark
|
|
17
|
+
* so a later interaction can retry.
|
|
18
|
+
*/
|
|
19
|
+
export declare const resolveUnknownTaskRefs: (refs: readonly AgentTeamTaskRef[], lookup: (taskRefs: readonly AgentTeamTaskRef[]) => Promise<readonly ResolvedTaskRef[]>) => Promise<void>;
|
|
20
|
+
//# sourceMappingURL=task-refs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"task-refs.d.ts","sourceRoot":"","sources":["../../../src/client/task-refs.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAA;AAE/G,4EAA4E;AAC5E,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,OAAO,EAAE,gBAAgB,CAAA;IAClC,QAAQ,CAAC,UAAU,EAAE,mBAAmB,CAAA;IACxC,QAAQ,CAAC,SAAS,EAAE,kBAAkB,CAAA;IACtC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;CAC5B;AAwBD,0EAA0E;AAC1E,eAAO,MAAM,yBAAyB,QAAO,MAAmE,CAAA;AAEhH,eAAO,MAAM,qBAAqB,GAAI,SAAS,gBAAgB,KAAG,eAAe,GAAG,SAAkC,CAAA;AAEtH,sEAAsE;AACtE,eAAO,MAAM,uBAAuB,GAAI,OAAO,eAAe,KAAG,IAIhE,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,GACjC,MAAM,SAAS,gBAAgB,EAAE,EACjC,QAAQ,CAAC,QAAQ,EAAE,SAAS,gBAAgB,EAAE,KAAK,OAAO,CAAC,SAAS,eAAe,EAAE,CAAC,KACrF,OAAO,CAAC,IAAI,CAmBd,CAAA"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { useSyncExternalStore } from 'react';
|
|
2
|
+
const resolved = new Map();
|
|
3
|
+
const pending = new Set();
|
|
4
|
+
/** Refs the Host did not recognize; never re-queried (no retry loops). */
|
|
5
|
+
const unresolvable = new Set();
|
|
6
|
+
const listeners = new Set();
|
|
7
|
+
let version = 0;
|
|
8
|
+
const emit = () => {
|
|
9
|
+
version += 1;
|
|
10
|
+
for (const listener of listeners)
|
|
11
|
+
listener();
|
|
12
|
+
};
|
|
13
|
+
const subscribe = (listener) => {
|
|
14
|
+
listeners.add(listener);
|
|
15
|
+
return () => { listeners.delete(listener); };
|
|
16
|
+
};
|
|
17
|
+
/** Stable snapshot token; the map is read directly after this changes. */
|
|
18
|
+
const getSnapshot = () => version;
|
|
19
|
+
/** React binding: re-renders the caller when any ref resolution lands. */
|
|
20
|
+
export const useResolvedTaskRefVersion = () => useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
|
|
21
|
+
export const cachedResolvedTaskRef = (taskRef) => resolved.get(taskRef);
|
|
22
|
+
/** Store one resolution (click path) and wake every rendered link. */
|
|
23
|
+
export const rememberResolvedTaskRef = (entry) => {
|
|
24
|
+
resolved.set(entry.taskRef, entry);
|
|
25
|
+
pending.delete(entry.taskRef);
|
|
26
|
+
emit();
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* Batch-resolve unknown refs through the Host lookup. Concurrent callers
|
|
30
|
+
* deduplicate through the pending set; failures just clear the pending mark
|
|
31
|
+
* so a later interaction can retry.
|
|
32
|
+
*/
|
|
33
|
+
export const resolveUnknownTaskRefs = async (refs, lookup) => {
|
|
34
|
+
const missing = refs.filter(taskRef => !resolved.has(taskRef) && !pending.has(taskRef) && !unresolvable.has(taskRef));
|
|
35
|
+
if (missing.length === 0)
|
|
36
|
+
return;
|
|
37
|
+
for (const taskRef of missing)
|
|
38
|
+
pending.add(taskRef);
|
|
39
|
+
try {
|
|
40
|
+
const entries = await lookup(missing);
|
|
41
|
+
for (const entry of entries) {
|
|
42
|
+
resolved.set(entry.taskRef, entry);
|
|
43
|
+
pending.delete(entry.taskRef);
|
|
44
|
+
}
|
|
45
|
+
// Refs the Host does not know are parked for the session: re-querying
|
|
46
|
+
// them on every render would loop and hammer the Host.
|
|
47
|
+
for (const taskRef of missing) {
|
|
48
|
+
if (!resolved.has(taskRef))
|
|
49
|
+
unresolvable.add(taskRef);
|
|
50
|
+
}
|
|
51
|
+
if (entries.length > 0)
|
|
52
|
+
emit();
|
|
53
|
+
}
|
|
54
|
+
finally {
|
|
55
|
+
for (const taskRef of missing)
|
|
56
|
+
pending.delete(taskRef);
|
|
57
|
+
}
|
|
58
|
+
};
|
|
@@ -13,6 +13,19 @@ export declare function taskStatusDot(status: AgentTeamTask['status']): 'ongoing
|
|
|
13
13
|
export declare function formatTaskTitle(body: string): string;
|
|
14
14
|
/** Deterministic avatar hue for one Member identity; stable across sessions and themes. */
|
|
15
15
|
export declare function memberHue(memberId: string): number;
|
|
16
|
+
/** One branded-ref occurrence inside a literal body segment. */
|
|
17
|
+
export interface RefSegment {
|
|
18
|
+
readonly text: string;
|
|
19
|
+
/** The full `task:`/`channel:`/`thread:` ref when this segment is a link. */
|
|
20
|
+
readonly ref?: string;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Split a literal text run into plain and branded-ref segments. The pattern
|
|
24
|
+
* anchors on the fixed ref prefixes plus the UUID shape, so ordinary prose
|
|
25
|
+
* containing a colon never linkifies. Refs render as navigation links; text
|
|
26
|
+
* without any ref comes back as one untouched segment.
|
|
27
|
+
*/
|
|
28
|
+
export declare function splitBrandedRefs(text: string): readonly RefSegment[];
|
|
16
29
|
export interface MentionSegment {
|
|
17
30
|
readonly text: string;
|
|
18
31
|
readonly mention: boolean;
|
|
@@ -50,4 +63,6 @@ export declare function formatActivity(activity: AgentTeamActivity, options: {
|
|
|
50
63
|
readonly actorName: (memberId: AgentTeamMemberId) => string;
|
|
51
64
|
readonly claims: readonly AgentTeamClaim[];
|
|
52
65
|
}): string;
|
|
66
|
+
/** Remove the machine-facing `[attachment] <path>` prompt lines from a body before display. */
|
|
67
|
+
export declare function stripAttachmentLines(body: string): string;
|
|
53
68
|
//# sourceMappingURL=team-formatters.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"team-formatters.d.ts","sourceRoot":"","sources":["../../../src/client/team-formatters.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,cAAc,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAA;AACzH,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAA;AAEvD,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,aAAa,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,qBAAqB,CAAC,GAAG,CAAC,GAAG,MAAM,CAQvG;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,cAAc,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,qBAAqB,CAAC,GAAG,CAAC,GAAG,MAAM,CAMtG;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,aAAa,CAAC,QAAQ,CAAC,GAAG,SAAS,GAAG,SAAS,GAAG,MAAM,GAAG,MAAM,GAAG,QAAQ,CAEjH;AAED,wEAAwE;AACxE,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAGpD;AAED,2FAA2F;AAC3F,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAIlD;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;IACzB,kFAAkF;IAClF,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CACvB;AAMD;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG;IAAE,QAAQ,EAAE,cAAc,EAAE,CAAC;IAAC,SAAS,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,CAwBtI;AAED,wEAAwE;AACxE,wBAAgB,cAAc,CAAC,QAAQ,EAAE,SAAS,iBAAiB,EAAE,EAAE,OAAO,EAAE,WAAW,CAAC,iBAAiB,EAAE,MAAM,CAAC,GAAG,MAAM,EAAE,CAEhI;AAKD;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAErD;AAID;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,OAAa,GAAG,MAAM,CAS9E;AAED,wBAAgB,cAAc,CAAC,QAAQ,EAAE,iBAAiB,EAAE,OAAO,EAAE;IACnE,QAAQ,CAAC,CAAC,EAAE,qBAAqB,CAAC,GAAG,CAAC,CAAA;IACtC,QAAQ,CAAC,SAAS,EAAE,CAAC,QAAQ,EAAE,iBAAiB,KAAK,MAAM,CAAA;IAC3D,QAAQ,CAAC,MAAM,EAAE,SAAS,cAAc,EAAE,CAAA;CAC3C,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"team-formatters.d.ts","sourceRoot":"","sources":["../../../src/client/team-formatters.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,cAAc,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAA;AACzH,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAA;AAEvD,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,aAAa,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,qBAAqB,CAAC,GAAG,CAAC,GAAG,MAAM,CAQvG;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,cAAc,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,qBAAqB,CAAC,GAAG,CAAC,GAAG,MAAM,CAMtG;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,aAAa,CAAC,QAAQ,CAAC,GAAG,SAAS,GAAG,SAAS,GAAG,MAAM,GAAG,MAAM,GAAG,QAAQ,CAEjH;AAED,wEAAwE;AACxE,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAGpD;AAED,2FAA2F;AAC3F,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAIlD;AAED,gEAAgE;AAChE,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,6EAA6E;IAC7E,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CACtB;AAID;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,UAAU,EAAE,CAWpE;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;IACzB,kFAAkF;IAClF,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CACvB;AAMD;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG;IAAE,QAAQ,EAAE,cAAc,EAAE,CAAC;IAAC,SAAS,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,CAwBtI;AAED,wEAAwE;AACxE,wBAAgB,cAAc,CAAC,QAAQ,EAAE,SAAS,iBAAiB,EAAE,EAAE,OAAO,EAAE,WAAW,CAAC,iBAAiB,EAAE,MAAM,CAAC,GAAG,MAAM,EAAE,CAEhI;AAKD;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAErD;AAID;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,OAAa,GAAG,MAAM,CAS9E;AAED,wBAAgB,cAAc,CAAC,QAAQ,EAAE,iBAAiB,EAAE,OAAO,EAAE;IACnE,QAAQ,CAAC,CAAC,EAAE,qBAAqB,CAAC,GAAG,CAAC,CAAA;IACtC,QAAQ,CAAC,SAAS,EAAE,CAAC,QAAQ,EAAE,iBAAiB,KAAK,MAAM,CAAA;IAC3D,QAAQ,CAAC,MAAM,EAAE,SAAS,cAAc,EAAE,CAAA;CAC3C,GAAG,MAAM,CAiBT;AAED,+FAA+F;AAC/F,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEzD"}
|
|
@@ -35,6 +35,27 @@ export function memberHue(memberId) {
|
|
|
35
35
|
hash = (hash * 31 + memberId.charCodeAt(index)) % 360;
|
|
36
36
|
return hash;
|
|
37
37
|
}
|
|
38
|
+
const BRANDED_REF_PATTERN = /\b(task|channel|thread):[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\b/gi;
|
|
39
|
+
/**
|
|
40
|
+
* Split a literal text run into plain and branded-ref segments. The pattern
|
|
41
|
+
* anchors on the fixed ref prefixes plus the UUID shape, so ordinary prose
|
|
42
|
+
* containing a colon never linkifies. Refs render as navigation links; text
|
|
43
|
+
* without any ref comes back as one untouched segment.
|
|
44
|
+
*/
|
|
45
|
+
export function splitBrandedRefs(text) {
|
|
46
|
+
const segments = [];
|
|
47
|
+
let cursor = 0;
|
|
48
|
+
for (const match of text.matchAll(BRANDED_REF_PATTERN)) {
|
|
49
|
+
const start = match.index ?? 0;
|
|
50
|
+
if (start > cursor)
|
|
51
|
+
segments.push({ text: text.slice(cursor, start) });
|
|
52
|
+
segments.push({ text: match[0], ref: match[0] });
|
|
53
|
+
cursor = start + match[0].length;
|
|
54
|
+
}
|
|
55
|
+
if (cursor < text.length)
|
|
56
|
+
segments.push({ text: text.slice(cursor) });
|
|
57
|
+
return segments;
|
|
58
|
+
}
|
|
38
59
|
function escapeRegExp(value) {
|
|
39
60
|
return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
40
61
|
}
|
|
@@ -107,8 +128,11 @@ export function formatMessageTime(occurredAt, now = new Date()) {
|
|
|
107
128
|
}
|
|
108
129
|
export function formatActivity(activity, options) {
|
|
109
130
|
const actor = options.actorName(activity.actor);
|
|
110
|
-
if (activity.kind === 'accept')
|
|
111
|
-
return
|
|
131
|
+
if (activity.kind === 'accept') {
|
|
132
|
+
return activity.completedClaimRefs !== undefined && activity.completedClaimRefs.length > 0
|
|
133
|
+
? options.t('activityAcceptedWithClaims', { actor, count: activity.completedClaimRefs.length })
|
|
134
|
+
: options.t('activityAccepted', { actor });
|
|
135
|
+
}
|
|
112
136
|
if (activity.kind === 'close')
|
|
113
137
|
return options.t('activityClosed', { actor });
|
|
114
138
|
if (activity.kind === 'reopen')
|
|
@@ -126,3 +150,7 @@ export function formatActivity(activity, options) {
|
|
|
126
150
|
return options.t('activityClaimsReleased', { actor, count: activity.claimRefs.length });
|
|
127
151
|
throw new Error(`unknown Team Activity kind: ${activity.kind}`);
|
|
128
152
|
}
|
|
153
|
+
/** Remove the machine-facing `[attachment] <path>` prompt lines from a body before display. */
|
|
154
|
+
export function stripAttachmentLines(body) {
|
|
155
|
+
return body.replaceAll(/^\[attachment\] .*$(\n)?/gm, '').replace(/\n+$/, '');
|
|
156
|
+
}
|
|
@@ -6,6 +6,14 @@ export type TimelineBlock<T> = {
|
|
|
6
6
|
readonly kind: 'day';
|
|
7
7
|
readonly label: string;
|
|
8
8
|
};
|
|
9
|
+
/** Same-sender messages at least this many minutes apart count as separate turns. */
|
|
10
|
+
export declare const RUN_GAP_MINUTES = 5;
|
|
11
|
+
/**
|
|
12
|
+
* Whether two adjacent same-sender run items are separated by a real waiting
|
|
13
|
+
* gap: only such gaps earn an explicit time divider, while rapid bursts stay
|
|
14
|
+
* merged into one seamless run.
|
|
15
|
+
*/
|
|
16
|
+
export declare function isRunGap(previousOccurredAt: string | undefined, occurredAt: string | undefined): boolean;
|
|
9
17
|
/** Local-calendar day key for one wall-clock instant; shared by bespoke loops. */
|
|
10
18
|
export declare function timelineDayKey(occurredAt: string): string;
|
|
11
19
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"team-separators.d.ts","sourceRoot":"","sources":["../../../src/client/team-separators.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAChF,MAAM,MAAM,aAAa,CAAC,CAAC,IACvB;IAAE,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC,EAAE,CAAA;CAAE,GACtD;IAAE,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAA;
|
|
1
|
+
{"version":3,"file":"team-separators.d.ts","sourceRoot":"","sources":["../../../src/client/team-separators.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAChF,MAAM,MAAM,aAAa,CAAC,CAAC,IACvB;IAAE,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC,EAAE,CAAA;CAAE,GACtD;IAAE,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAA;AAEpD,qFAAqF;AACrF,eAAO,MAAM,eAAe,IAAI,CAAA;AAEhC;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,kBAAkB,EAAE,MAAM,GAAG,SAAS,EAAE,UAAU,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAKxG;AAID,kFAAkF;AAClF,wBAAgB,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAEzD;AAOD;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,OAAa,GAAG,MAAM,CAG9E;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,KAAK,EAAE,SAAS,CAAC,EAAE,EAAE,QAAQ,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,MAAM,GAAG,SAAS,EAAE,YAAY,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,MAAM,GAAG,SAAS,GAAG,SAAS,aAAa,CAAC,CAAC,CAAC,EAAE,CA0B/K"}
|
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
/** Same-sender messages at least this many minutes apart count as separate turns. */
|
|
2
|
+
export const RUN_GAP_MINUTES = 5;
|
|
3
|
+
/**
|
|
4
|
+
* Whether two adjacent same-sender run items are separated by a real waiting
|
|
5
|
+
* gap: only such gaps earn an explicit time divider, while rapid bursts stay
|
|
6
|
+
* merged into one seamless run.
|
|
7
|
+
*/
|
|
8
|
+
export function isRunGap(previousOccurredAt, occurredAt) {
|
|
9
|
+
if (previousOccurredAt === undefined || occurredAt === undefined)
|
|
10
|
+
return false;
|
|
11
|
+
const previous = Date.parse(previousOccurredAt);
|
|
12
|
+
const at = Date.parse(occurredAt);
|
|
13
|
+
return !Number.isNaN(previous) && !Number.isNaN(at) && at - previous >= RUN_GAP_MINUTES * 60_000;
|
|
14
|
+
}
|
|
1
15
|
const pad = (value) => String(value).padStart(2, '0');
|
|
2
16
|
/** Local-calendar day key for one wall-clock instant; shared by bespoke loops. */
|
|
3
17
|
export function timelineDayKey(occurredAt) {
|
|
@@ -131,13 +131,14 @@ function threadResult(kind, snapshot, attention, facts, extra = {}) {
|
|
|
131
131
|
}
|
|
132
132
|
const teamMessage = markAgentTeamPreset(defineTool({
|
|
133
133
|
name: 'team_message',
|
|
134
|
-
description: 'Create a top-level Task or reply to one existing Task Thread. Read the Thread first; replies require its current revision. A top-level start may mention related Agents directly; in replies, only a Human can invite an unfollowed Agent. Pass Member refs in mentions and spell their handles inside the body; only mentioned Members render as mention chips.',
|
|
134
|
+
description: 'Create a top-level Task or reply to one existing Task Thread. Read the Thread first; replies require its current revision (an internal concurrency token carried by baseRevision, never quoted in bodies). A top-level start may mention related Agents directly; in replies, only a Human can invite an unfollowed Agent. Pass Member refs in mentions and spell their handles inside the body; only mentioned Members render as mention chips.',
|
|
135
135
|
parameters: {
|
|
136
136
|
action: { type: 'string', required: true, enum: ['start', 'reply'] },
|
|
137
137
|
channelRef: { type: 'string', description: "Full branded Channel ref exactly as returned by Team tools, including the 'channel:' prefix." },
|
|
138
138
|
taskRef: { type: 'string', description: "Full branded Task ref exactly as returned by Team tools, including the 'task:' prefix." },
|
|
139
|
-
body: { type: 'string', required: true }, baseRevision: { type: 'number', description: "Positive integer; use the current Thread revision as shown by the latest team_inbox or team_thread result for this Task." },
|
|
139
|
+
body: { type: 'string', required: true }, baseRevision: { type: 'number', description: "Positive integer; use the current Thread revision as shown by the latest team_inbox or team_thread result for this Task. The revision is an internal concurrency token, not a citable fact." },
|
|
140
140
|
mentions: { type: 'array', items: { type: 'string' }, description: 'Member refs to mention. Mentioned Agents receive the Message directly; write their handles in the body (any casing, optional @) so the mention renders inline.' },
|
|
141
|
+
attachments: { type: 'array', items: { type: 'string' }, description: 'Absolute file paths to share, e.g. screenshots or generated artifacts; images render as thumbnails for recipients. The Host validates each path and copies the file into the attachment cache, and members also receive one cached path per attachment; if any path fails validation the whole send is rejected.' },
|
|
141
142
|
},
|
|
142
143
|
output: {
|
|
143
144
|
schema: { type: 'object', additionalProperties: false, properties: {
|
|
@@ -154,11 +155,14 @@ const teamMessage = markAgentTeamPreset(defineTool({
|
|
|
154
155
|
const current = member(agent);
|
|
155
156
|
const host = service(agent);
|
|
156
157
|
const mentions = args.mentions;
|
|
158
|
+
const rawPaths = args.attachments;
|
|
159
|
+
const attachmentPaths = Array.isArray(rawPaths) ? rawPaths.filter((entry) => typeof entry === 'string' && entry.trim() !== '') : undefined;
|
|
160
|
+
const paths = attachmentPaths !== undefined && attachmentPaths.length > 0 ? { attachmentPaths } : {};
|
|
157
161
|
if (args.action === 'start') {
|
|
158
162
|
if (args.channelRef === undefined || args.taskRef !== undefined || args.baseRevision !== undefined)
|
|
159
163
|
throw new Error('start requires channelRef and does not accept taskRef or baseRevision');
|
|
160
164
|
const result = await host.sendMessageForAgent(agent, { requestId: requestId(agent.id, exec.callId), workspaceId: current.workspaceId,
|
|
161
|
-
channelRef: args.channelRef, body: args.body, ...(mentions === undefined ? {} : { recipients: mentions }) });
|
|
165
|
+
channelRef: args.channelRef, body: args.body, ...(mentions === undefined ? {} : { recipients: mentions }), ...paths });
|
|
162
166
|
return messageOutcome(result);
|
|
163
167
|
}
|
|
164
168
|
const baseRevision = args.baseRevision;
|
|
@@ -167,7 +171,7 @@ const teamMessage = markAgentTeamPreset(defineTool({
|
|
|
167
171
|
}
|
|
168
172
|
const result = await host.replyForAgent(agent, { requestId: requestId(agent.id, exec.callId), workspaceId: current.workspaceId,
|
|
169
173
|
taskRef: args.taskRef, body: args.body, baseRevision,
|
|
170
|
-
...(mentions === undefined ? {} : { recipients: mentions }) });
|
|
174
|
+
...(mentions === undefined ? {} : { recipients: mentions }), ...paths });
|
|
171
175
|
return messageOutcome(result);
|
|
172
176
|
},
|
|
173
177
|
}));
|
|
@@ -188,11 +192,11 @@ function messageOutcome(result) {
|
|
|
188
192
|
}
|
|
189
193
|
const teamClaim = defineTool({
|
|
190
194
|
name: 'team_claim',
|
|
191
|
-
description: 'List or mutate your Direction Claims. Read the Thread first; every mutation uses the current Thread revision.',
|
|
195
|
+
description: 'List or mutate your Direction Claims. Read the Thread first; every mutation uses the current Thread revision. A Claim is your one-sentence direction statement on a Task — "the angle I am taking" — so others can spot collisions and track progress: Tasks define scope (owned by Humans), Claims declare the angle (owned by you). Good direction: "Unify the four form dialogs on shared field components before wiring submits." Bad direction: a multi-paragraph plan with step order, file lists, or acceptance criteria — those belong in Thread messages, not the Claim.',
|
|
192
196
|
parameters: {
|
|
193
197
|
action: { type: 'string', required: true, enum: ['list', 'claim', 'done', 'release'] },
|
|
194
198
|
taskRef: { type: 'string', required: true, description: "Full branded Task ref exactly as returned by Team tools, including the 'task:' prefix." },
|
|
195
|
-
baseRevision: { type: 'number', description: "Positive integer; use the current Thread revision as shown by the latest team_inbox or team_thread result for this Task." }, direction: { type: 'string' },
|
|
199
|
+
baseRevision: { type: 'number', description: "Positive integer; use the current Thread revision as shown by the latest team_inbox or team_thread result for this Task. The revision is an internal concurrency token, not a citable fact." }, direction: { type: 'string' },
|
|
196
200
|
claimRef: { type: 'string', description: "Full branded Claim ref exactly as returned by team_claim, including the 'claim:' prefix." },
|
|
197
201
|
},
|
|
198
202
|
output: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAUlD,eAAO,MAAM,IAAI,8BAA8B,CAAA;AAC/C,eAAO,MAAM,MAAM,UAAY,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAUlD,eAAO,MAAM,IAAI,8BAA8B,CAAA;AAC/C,eAAO,MAAM,MAAM,UAAY,CAAA;AA4R/B,wBAAgB,KAAK,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI,CAMxC"}
|