@agimon-ai/doompi-team 0.0.1-alpha.49 → 0.0.1-alpha.50
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agimon-ai/doompi-team",
|
|
3
|
-
"version": "0.0.1-alpha.
|
|
3
|
+
"version": "0.0.1-alpha.50",
|
|
4
4
|
"description": "Asynchronous named subagents, team runs, intercom, and model policy for Pi coding agents.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"agent-team",
|
|
@@ -56,13 +56,13 @@
|
|
|
56
56
|
"@deepseek-ai/cordis": "4.0.1",
|
|
57
57
|
"typebox": "1.3.19",
|
|
58
58
|
"yaml": "2.9.0",
|
|
59
|
-
"@agimon-ai/doompi-cache": "0.0.1-alpha.
|
|
60
|
-
"@agimon-ai/doompi-
|
|
61
|
-
"@agimon-ai/doompi-
|
|
62
|
-
"@agimon-ai/doompi-
|
|
63
|
-
"@agimon-ai/doompi-
|
|
64
|
-
"@agimon-ai/doompi-
|
|
65
|
-
"@agimon-ai/doompi-web-contracts": "0.0.1-alpha.
|
|
59
|
+
"@agimon-ai/doompi-cache": "0.0.1-alpha.16",
|
|
60
|
+
"@agimon-ai/doompi-extension-contracts": "0.0.1-alpha.49",
|
|
61
|
+
"@agimon-ai/doompi-telemetry": "0.0.1-alpha.49",
|
|
62
|
+
"@agimon-ai/doompi-ui": "0.0.1-alpha.50",
|
|
63
|
+
"@agimon-ai/doompi-web-components": "0.0.1-alpha.10",
|
|
64
|
+
"@agimon-ai/doompi-config": "0.0.1-alpha.49",
|
|
65
|
+
"@agimon-ai/doompi-web-contracts": "0.0.1-alpha.13"
|
|
66
66
|
},
|
|
67
67
|
"devDependencies": {
|
|
68
68
|
"@earendil-works/pi-agent-core": "0.84.4",
|
|
@@ -4,12 +4,12 @@ import { useStore } from '@tanstack/react-store';
|
|
|
4
4
|
import { useEffect, useState } from 'react';
|
|
5
5
|
import type { SubagentRun } from '../types/webSubagents.ts';
|
|
6
6
|
import { agentThreadTab } from './AgentThreadPanel.tsx';
|
|
7
|
+
import { subagentsTab } from './SubagentsPanel.tsx';
|
|
7
8
|
import { openCatalog } from './catalogStore.ts';
|
|
8
9
|
import { formatRunDuration } from './format.ts';
|
|
9
10
|
import { activityRuns, isTerminalRun, subagents } from './subagentsStore.ts';
|
|
10
11
|
|
|
11
12
|
const TICK_MS = 10_000;
|
|
12
|
-
const SUBAGENTS_TAB = 'subagents';
|
|
13
13
|
|
|
14
14
|
const STATE_TONE: Readonly<Record<SubagentRun['state'], DotTone>> = {
|
|
15
15
|
queued: 'muted',
|
|
@@ -36,7 +36,7 @@ function detail(run: SubagentRun): string {
|
|
|
36
36
|
* row that opens the run's own conversation in a temporary tab. This replaces
|
|
37
37
|
* the runtime's footer one-liner, which only says whether anything is running.
|
|
38
38
|
*/
|
|
39
|
-
export function AgentsActivitySection({ sessionId,
|
|
39
|
+
export function AgentsActivitySection({ sessionId, openTransientTab }: WebPluginSlotProps) {
|
|
40
40
|
const runs = useStore(subagents.store, (state) => activityRuns(subagents.select(state, sessionId)));
|
|
41
41
|
const [now, setNow] = useState(() => Date.now());
|
|
42
42
|
|
|
@@ -59,7 +59,7 @@ export function AgentsActivitySection({ sessionId, openTab, openTransientTab }:
|
|
|
59
59
|
onClick={() => {
|
|
60
60
|
if (sessionId === null) return;
|
|
61
61
|
openCatalog(sessionId);
|
|
62
|
-
|
|
62
|
+
openTransientTab(subagentsTab());
|
|
63
63
|
}}
|
|
64
64
|
>
|
|
65
65
|
launch an agent
|
|
@@ -7,10 +7,9 @@ import {
|
|
|
7
7
|
toolTone,
|
|
8
8
|
} from '@agimon-ai/doompi-web-components';
|
|
9
9
|
import type { ToolMessageRenderProps } from '@agimon-ai/doompi-web-contracts';
|
|
10
|
+
import { subagentsTab } from './SubagentsPanel.tsx';
|
|
10
11
|
import { shapeResult, subagentCallDetail } from './toolText.ts';
|
|
11
12
|
|
|
12
|
-
const SUBAGENTS_TAB = 'subagents';
|
|
13
|
-
|
|
14
13
|
const CLOSING = {
|
|
15
14
|
running: { tone: 'running', text: 'running' },
|
|
16
15
|
failed: { tone: 'error', text: 'failed' },
|
|
@@ -23,7 +22,7 @@ const CLOSING = {
|
|
|
23
22
|
* the framed text lines with the closing status line in the body, and the
|
|
24
23
|
* subagents tab one click away while a run is on the go.
|
|
25
24
|
*/
|
|
26
|
-
export function SubagentToolMessage({ args, output, running, isError,
|
|
25
|
+
export function SubagentToolMessage({ args, output, running, isError, openTransientTab }: ToolMessageRenderProps) {
|
|
27
26
|
const action = typeof args.action === 'string' ? args.action : '';
|
|
28
27
|
const detail = subagentCallDetail(args);
|
|
29
28
|
const collapsed = shapeResult(output, { expanded: false, isPartial: running, isError });
|
|
@@ -54,7 +53,7 @@ export function SubagentToolMessage({ args, output, running, isError, openTab }:
|
|
|
54
53
|
variant="link"
|
|
55
54
|
size="xs"
|
|
56
55
|
data-testid="tool-result-subagent-open"
|
|
57
|
-
onClick={() =>
|
|
56
|
+
onClick={() => openTransientTab(subagentsTab())}
|
|
58
57
|
className="self-start px-0"
|
|
59
58
|
>
|
|
60
59
|
open subagents
|
|
@@ -19,7 +19,7 @@ import {
|
|
|
19
19
|
STATUS_EDGE,
|
|
20
20
|
StatusBadge,
|
|
21
21
|
} from '@agimon-ai/doompi-web-components';
|
|
22
|
-
import type { SessionFrameSender, WebPluginSlotProps } from '@agimon-ai/doompi-web-contracts';
|
|
22
|
+
import type { SessionFrameSender, TransientTab, WebPluginSlotProps } from '@agimon-ai/doompi-web-contracts';
|
|
23
23
|
import { useStore } from '@tanstack/react-store';
|
|
24
24
|
import { type KeyboardEvent as ReactKeyboardEvent, useEffect, useState } from 'react';
|
|
25
25
|
import type { SubagentRun } from '../types/webSubagents.ts';
|
|
@@ -40,6 +40,9 @@ import {
|
|
|
40
40
|
visibleRuns,
|
|
41
41
|
} from './subagentsStore.ts';
|
|
42
42
|
|
|
43
|
+
/** One fleet tab per session; the fleet is singular, so the id needs nothing else. */
|
|
44
|
+
export const SUBAGENTS_TAB_ID = 'subagents-fleet';
|
|
45
|
+
|
|
43
46
|
const TICK_MS = 10_000;
|
|
44
47
|
|
|
45
48
|
/**
|
|
@@ -477,3 +480,8 @@ export function SubagentsPanel({
|
|
|
477
480
|
</div>
|
|
478
481
|
);
|
|
479
482
|
}
|
|
483
|
+
|
|
484
|
+
/** The temporary tab the fleet opens in; opening it again only focuses it. */
|
|
485
|
+
export function subagentsTab(): TransientTab {
|
|
486
|
+
return { id: SUBAGENTS_TAB_ID, label: 'subagents', panel: SubagentsPanel };
|
|
487
|
+
}
|
package/src/web/index.ts
CHANGED
|
@@ -1,38 +1,55 @@
|
|
|
1
1
|
import { defineWebPlugin } from '@agimon-ai/doompi-web-contracts';
|
|
2
|
-
import { useStore } from '@tanstack/react-store';
|
|
3
2
|
import { AgentsActivitySection } from './AgentsActivitySection.tsx';
|
|
4
|
-
import {
|
|
3
|
+
import { subagentsTab } from './SubagentsPanel.tsx';
|
|
5
4
|
import { openCatalog, subagentCatalogChannel } from './catalogStore.ts';
|
|
6
5
|
import { RUN_ACTIONS_SLOT } from './runActionsSlot.ts';
|
|
7
|
-
import { subagentRunsChannel, subagents
|
|
6
|
+
import { activityRuns, isTerminalRun, subagentRunsChannel, subagents } from './subagentsStore.ts';
|
|
8
7
|
import { teamToolRenderers } from './toolRenderers.ts';
|
|
9
8
|
|
|
10
|
-
/** The tab badge: every run the session's fleet currently shows. */
|
|
11
|
-
export function useSubagentsBadge(sessionId: string | null): number {
|
|
12
|
-
return useStore(subagents.store, (state) => visibleRuns(subagents.select(state, sessionId)).length);
|
|
13
|
-
}
|
|
14
|
-
|
|
15
9
|
const AGENTS_GROUP = { key: 'a', label: 'agents', detail: 'subagent resources and runs' };
|
|
16
10
|
|
|
11
|
+
// The group is the only way into the fleet now, so it stays visible while the
|
|
12
|
+
// session is idle: a launcher that appears only once something runs cannot be
|
|
13
|
+
// used to start anything.
|
|
14
|
+
const agentsActivitySource = {
|
|
15
|
+
subscribe(listener: () => void) {
|
|
16
|
+
const subscription = subagents.store.subscribe(listener);
|
|
17
|
+
return () => subscription.unsubscribe();
|
|
18
|
+
},
|
|
19
|
+
isActive(sessionId: string | null) {
|
|
20
|
+
return activityRuns(subagents.select(subagents.store.state, sessionId)).some((run) => !isTerminalRun(run));
|
|
21
|
+
},
|
|
22
|
+
};
|
|
23
|
+
|
|
17
24
|
/** The named export the generated plugin registry imports. */
|
|
18
25
|
export const webPlugin = defineWebPlugin({
|
|
19
26
|
id: 'subagents',
|
|
20
|
-
tabs: [{ id: 'subagents', label: 'subagents', panel: SubagentsPanel, useBadge: useSubagentsBadge }],
|
|
21
27
|
channels: [subagentRunsChannel, subagentCatalogChannel],
|
|
22
|
-
|
|
28
|
+
// No declared tab: the fleet is a panel the reader opens from the dock's
|
|
29
|
+
// agents group, and closes when they are done with it.
|
|
30
|
+
activityGroups: [
|
|
31
|
+
{
|
|
32
|
+
name: 'agents',
|
|
33
|
+
keys: 'a r',
|
|
34
|
+
statusKey: 'doom-team-agents',
|
|
35
|
+
activeSource: agentsActivitySource,
|
|
36
|
+
transientTab: subagentsTab,
|
|
37
|
+
order: 10,
|
|
38
|
+
},
|
|
39
|
+
],
|
|
23
40
|
// The TUI's SPC a r and SPC a l: the runs, and the catalog to launch from.
|
|
24
41
|
leaderBindings: [
|
|
25
42
|
{
|
|
26
43
|
id: 'subagents.fleet',
|
|
27
44
|
path: [AGENTS_GROUP, { key: 'r', label: 'runs', detail: 'runs in this session' }],
|
|
28
|
-
run: (context) => context.
|
|
45
|
+
run: (context) => context.openTransientTab(subagentsTab()),
|
|
29
46
|
},
|
|
30
47
|
{
|
|
31
48
|
id: 'subagents.catalog',
|
|
32
49
|
path: [AGENTS_GROUP, { key: 'l', label: 'launch', detail: 'pick an agent and launch it' }],
|
|
33
50
|
run: (context) => {
|
|
34
51
|
if (context.sessionId !== null) openCatalog(context.sessionId);
|
|
35
|
-
context.
|
|
52
|
+
context.openTransientTab(subagentsTab());
|
|
36
53
|
},
|
|
37
54
|
},
|
|
38
55
|
],
|