@puredesktop/puredesktop-ui-bridge 2.1.8 → 2.1.9
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 +35 -5
- package/src/agents/mcpServerPresets.test.ts +105 -0
- package/src/agents/mcpServerPresets.ts +380 -0
- package/src/agents/runtime/index.ts +7 -0
- package/src/agents/runtime/mapAgentSnapshot.ts +11 -8
- package/src/agents/runtime/pendingAsks.test.ts +117 -0
- package/src/agents/runtime/pendingAsks.ts +110 -0
- package/src/bridge/agentScopeDefaults.ts +65 -0
- package/src/bridge/agentTypes.ts +36 -2
- package/src/bridge/agents.d.mts +6 -0
- package/src/bridge/agents.mjs +10 -0
- package/src/bridge/agents.ts +4 -0
- package/src/bridge/credentials.d.mts +62 -0
- package/src/bridge/credentials.mjs +53 -0
- package/src/bridge/events.d.mts +1 -0
- package/src/bridge/events.mjs +1 -0
- package/src/bridge/googleAuth.ts +7 -152
- package/src/bridge/mcpClient.d.mts +74 -0
- package/src/bridge/mcpClient.mjs +79 -0
- package/src/bridge/methods.d.mts +22 -0
- package/src/bridge/methods.mjs +23 -0
- package/src/bridge/notifications.d.mts +12 -0
- package/src/bridge/notifications.mjs +36 -0
- package/src/bridge/operations.d.mts +44 -0
- package/src/bridge/operations.mjs +40 -0
- package/src/bridge/react/usePlatformAgentSessionDrive.test.tsx +29 -10
- package/src/bridge/react/usePlatformAgentSessionDrive.tsx +10 -81
- package/src/bridge/react/usePlatformAppSettings.test.tsx +105 -105
- package/src/bridge/react/usePlatformAppSettings.tsx +104 -104
- package/src/bridge/react/usePlatformJsonStore.test.tsx +152 -152
- package/src/bridge/react/usePlatformJsonStore.tsx +149 -149
- package/src/bridge/react/usePlatformOperations.tsx +75 -0
- package/src/bridge/storage.d.mts +17 -4
- package/src/bridge/storage.mjs +6 -3
- package/src/components/agents/AgentComposer.tsx +10 -6
- package/src/components/agents/AgentDrawerPanel.test.tsx +2 -205
- package/src/components/agents/AgentDrawerPanel.tsx +23 -64
- package/src/components/agents/AgentMessageBubble.tsx +59 -33
- package/src/components/agents/AgentMessageList.tsx +4 -9
- package/src/components/agents/AgentQuestionPromptList.tsx +34 -212
- package/src/components/agents/AgentToolApprovalActions.tsx +13 -11
- package/src/components/agents/AgentToolPendingList.tsx +6 -6
- package/src/components/agents/AgentToolPendingReview.tsx +6 -6
- package/src/components/agents/QuestionRequestList.tsx +278 -0
- package/src/components/agents/agentPanelStyles.ts +9 -33
- package/src/components/agents/agentTypes.ts +25 -43
- package/src/components/agents/index.ts +4 -0
- package/src/components/assets/asset-library/sidebar/AssetLibraryList.tsx +10 -4
- package/src/components/chrome/WorkspaceTabStrip.tsx +4 -3
- package/src/components/common/chat/ChatBox.tsx +9 -9
- package/src/components/common/chat/ChatModelMenu.tsx +34 -4
- package/src/components/common/chat/ChatThread.tsx +23 -7
- package/src/components/common/connections/ProviderConnection.test.tsx +208 -0
- package/src/components/common/connections/ProviderConnection.tsx +277 -0
- package/src/components/common/connections/index.ts +5 -0
- package/src/components/common/containers/AppFrame.tsx +26 -19
- package/src/components/common/containers/AppHeader.tsx +20 -20
- package/src/components/common/documents/DocumentSwitcher.tsx +63 -58
- package/src/components/common/dropdown/MenuDropdownItem.tsx +14 -2
- package/src/components/common/dropdown/MenuPortal.tsx +3 -1
- package/src/components/common/dropdown/menuViewportPosition.test.ts +20 -10
- package/src/components/common/dropdown/menuViewportPosition.ts +35 -27
- package/src/components/common/overlays/Modal.tsx +13 -2
- package/src/components/editor/EditorLinkPromptDialog.tsx +1 -1
- package/src/ics/generateIcs.test.ts +153 -0
- package/src/ics/generateIcs.ts +197 -0
- package/src/index.ts +3 -0
- package/src/net/httpRetry.test.ts +117 -0
- package/src/net/httpRetry.ts +111 -0
- package/src/theme/appAccents.ts +6 -0
- package/src/theme/appIdentityCss.mjs +11 -0
- package/src/theme/appIdentityCss.ts +11 -0
- package/src/theme/themes/dark.ts +3 -1
- package/src/theme/themes/light.ts +3 -1
- package/src/bridge/googleProviderConfig.ts +0 -73
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest'
|
|
2
|
+
import type { PlatformAgentMessage } from '../../bridge/agentTypes.js'
|
|
3
|
+
import {
|
|
4
|
+
derivePendingAsks,
|
|
5
|
+
sessionPendingAskCalls,
|
|
6
|
+
type PendingAskSession,
|
|
7
|
+
} from './pendingAsks.js'
|
|
8
|
+
|
|
9
|
+
function pendingMessages(
|
|
10
|
+
calls: Array<{ id: string; name: string }>,
|
|
11
|
+
): PlatformAgentMessage[] {
|
|
12
|
+
return [
|
|
13
|
+
{ role: 'user', content: 'do the thing' },
|
|
14
|
+
{
|
|
15
|
+
role: 'assistant',
|
|
16
|
+
content: '',
|
|
17
|
+
toolCalls: calls.map(call => ({ ...call, arguments: {} })),
|
|
18
|
+
},
|
|
19
|
+
]
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function session(
|
|
23
|
+
overrides: Partial<PendingAskSession> = {},
|
|
24
|
+
): PendingAskSession {
|
|
25
|
+
return {
|
|
26
|
+
scope: 'global',
|
|
27
|
+
sessionId: 'parent-1',
|
|
28
|
+
state: 'pending_tools',
|
|
29
|
+
messages: pendingMessages([{ id: 'call-1', name: 'harness.invoke_agent' }]),
|
|
30
|
+
...overrides,
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
describe('sessionPendingAskCalls', () => {
|
|
35
|
+
it('lists unresolved pending calls', () => {
|
|
36
|
+
expect(sessionPendingAskCalls(session())).toEqual([
|
|
37
|
+
{ id: 'call-1', name: 'harness.invoke_agent', arguments: {} },
|
|
38
|
+
])
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
it('an accepted call is in flight, not an ask', () => {
|
|
42
|
+
expect(
|
|
43
|
+
sessionPendingAskCalls(
|
|
44
|
+
session({ acceptedPendingToolCallIds: ['call-1'] }),
|
|
45
|
+
),
|
|
46
|
+
).toEqual([])
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
it('a settled session has no asks', () => {
|
|
50
|
+
expect(
|
|
51
|
+
sessionPendingAskCalls(session({ state: 'awaiting_user' })),
|
|
52
|
+
).toEqual([])
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
it('policy-approved calls are not asks when a policy is supplied', () => {
|
|
56
|
+
expect(
|
|
57
|
+
sessionPendingAskCalls(
|
|
58
|
+
session({
|
|
59
|
+
toolPolicy: {
|
|
60
|
+
allowedTargetApps: [],
|
|
61
|
+
routeReadinessMs: 1_000,
|
|
62
|
+
handlerResponseMs: 1_000,
|
|
63
|
+
approvalOverrides: { 'harness.invoke_agent': false },
|
|
64
|
+
},
|
|
65
|
+
}),
|
|
66
|
+
),
|
|
67
|
+
).toEqual([])
|
|
68
|
+
})
|
|
69
|
+
})
|
|
70
|
+
|
|
71
|
+
describe('derivePendingAsks', () => {
|
|
72
|
+
it('an active child delegation ask outranks the parent ask', () => {
|
|
73
|
+
const asks = derivePendingAsks(session(), [
|
|
74
|
+
{
|
|
75
|
+
status: 'running',
|
|
76
|
+
childAppSlug: 'writer',
|
|
77
|
+
child: session({
|
|
78
|
+
scope: 'app',
|
|
79
|
+
sessionId: 'child-1',
|
|
80
|
+
appSlug: 'writer',
|
|
81
|
+
messages: pendingMessages([
|
|
82
|
+
{ id: 'call-2', name: 'writer.createDocument' },
|
|
83
|
+
]),
|
|
84
|
+
}),
|
|
85
|
+
},
|
|
86
|
+
])
|
|
87
|
+
|
|
88
|
+
expect(asks).toHaveLength(2)
|
|
89
|
+
expect(asks[0]).toEqual({
|
|
90
|
+
session: { scope: 'app', sessionId: 'child-1', appSlug: 'writer' },
|
|
91
|
+
origin: 'child',
|
|
92
|
+
childAppSlug: 'writer',
|
|
93
|
+
calls: [{ id: 'call-2', name: 'writer.createDocument', arguments: {} }],
|
|
94
|
+
})
|
|
95
|
+
expect(asks[1]).toEqual(
|
|
96
|
+
expect.objectContaining({ origin: 'parent' }),
|
|
97
|
+
)
|
|
98
|
+
})
|
|
99
|
+
|
|
100
|
+
it('settled delegations and unreadable children are ignored', () => {
|
|
101
|
+
const asks = derivePendingAsks(session(), [
|
|
102
|
+
{
|
|
103
|
+
status: 'completed',
|
|
104
|
+
childAppSlug: 'writer',
|
|
105
|
+
child: session({ sessionId: 'child-done' }),
|
|
106
|
+
},
|
|
107
|
+
{ status: 'running', childAppSlug: 'book', child: null },
|
|
108
|
+
])
|
|
109
|
+
expect(asks).toEqual([expect.objectContaining({ origin: 'parent' })])
|
|
110
|
+
})
|
|
111
|
+
|
|
112
|
+
it('no asks anywhere yields an empty list', () => {
|
|
113
|
+
expect(
|
|
114
|
+
derivePendingAsks(session({ state: 'awaiting_user' })),
|
|
115
|
+
).toEqual([])
|
|
116
|
+
})
|
|
117
|
+
})
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
PlatformAgentMessage,
|
|
3
|
+
PlatformAgentSessionScope,
|
|
4
|
+
PlatformAgentSessionToolPolicy,
|
|
5
|
+
} from '../../bridge/agentTypes.js'
|
|
6
|
+
import type { AgentUiToolCall } from '../../components/agents/agentTypes.js'
|
|
7
|
+
import { derivePendingToolCalls } from './pendingToolCalls.js'
|
|
8
|
+
import { toolRequiresApproval } from './toolRequiresApproval.js'
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* The one pending-asks selector (docs/09-missions.md §Card states): both the
|
|
12
|
+
* agent drawer and the mission card derive "what is this run waiting on the
|
|
13
|
+
* human for?" from here — manual pending calls minus accepted, with active
|
|
14
|
+
* child-delegation asks taking precedence over the parent's. No surface
|
|
15
|
+
* keeps its own derivation that can disagree. Approving from either surface
|
|
16
|
+
* is the same operation against the same session.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
export interface PendingAskSession {
|
|
20
|
+
scope: PlatformAgentSessionScope
|
|
21
|
+
sessionId: string
|
|
22
|
+
appSlug?: string
|
|
23
|
+
state: string
|
|
24
|
+
messages: readonly PlatformAgentMessage[]
|
|
25
|
+
acceptedPendingToolCallIds?: readonly string[]
|
|
26
|
+
/** When supplied, calls the policy auto-approves are not asks. */
|
|
27
|
+
toolPolicy?: PlatformAgentSessionToolPolicy
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export interface PendingAskDelegation {
|
|
31
|
+
status: string
|
|
32
|
+
childAppSlug: string
|
|
33
|
+
/** The delegated child's session, when the caller could read it. */
|
|
34
|
+
child?: PendingAskSession | null
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export interface PendingAsk {
|
|
38
|
+
session: {
|
|
39
|
+
scope: PlatformAgentSessionScope
|
|
40
|
+
sessionId: string
|
|
41
|
+
appSlug?: string
|
|
42
|
+
}
|
|
43
|
+
/** Child asks come from an active delegated app agent. */
|
|
44
|
+
origin: 'child' | 'parent'
|
|
45
|
+
childAppSlug?: string
|
|
46
|
+
calls: AgentUiToolCall[]
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* One session's slice of the contract: unresolved manual calls, minus the
|
|
51
|
+
* accepted-but-still-settling ones (an accepted call is IN FLIGHT — a
|
|
52
|
+
* delegation or app tool holds it open — not waiting on the human).
|
|
53
|
+
*/
|
|
54
|
+
export function sessionPendingAskCalls(
|
|
55
|
+
session: Pick<
|
|
56
|
+
PendingAskSession,
|
|
57
|
+
'state' | 'messages' | 'acceptedPendingToolCallIds' | 'toolPolicy'
|
|
58
|
+
>,
|
|
59
|
+
): AgentUiToolCall[] {
|
|
60
|
+
const accepted = new Set(session.acceptedPendingToolCallIds ?? [])
|
|
61
|
+
return derivePendingToolCalls(session.messages, session.state)
|
|
62
|
+
.filter(call => !accepted.has(call.id))
|
|
63
|
+
.filter(call =>
|
|
64
|
+
session.toolPolicy
|
|
65
|
+
? toolRequiresApproval(call.name, session.toolPolicy)
|
|
66
|
+
: true,
|
|
67
|
+
)
|
|
68
|
+
.map(call => ({ id: call.id, name: call.name, arguments: call.arguments }))
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function sessionRef(session: PendingAskSession): PendingAsk['session'] {
|
|
72
|
+
return {
|
|
73
|
+
scope: session.scope,
|
|
74
|
+
sessionId: session.sessionId,
|
|
75
|
+
...(session.appSlug ? { appSlug: session.appSlug } : {}),
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function delegationIsActive(status: string): boolean {
|
|
80
|
+
return status === 'pending' || status === 'running'
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* All open asks for one run, child-first: while a delegated app agent is
|
|
85
|
+
* asking, that ask IS the run's current question — a parent-level
|
|
86
|
+
* `harness.invoke_agent` ask shown instead would be stale.
|
|
87
|
+
*/
|
|
88
|
+
export function derivePendingAsks(
|
|
89
|
+
parent: PendingAskSession,
|
|
90
|
+
delegations: readonly PendingAskDelegation[] = [],
|
|
91
|
+
): PendingAsk[] {
|
|
92
|
+
const asks: PendingAsk[] = []
|
|
93
|
+
for (const delegation of delegations) {
|
|
94
|
+
if (!delegationIsActive(delegation.status)) continue
|
|
95
|
+
if (!delegation.child) continue
|
|
96
|
+
const calls = sessionPendingAskCalls(delegation.child)
|
|
97
|
+
if (calls.length === 0) continue
|
|
98
|
+
asks.push({
|
|
99
|
+
session: sessionRef(delegation.child),
|
|
100
|
+
origin: 'child',
|
|
101
|
+
childAppSlug: delegation.childAppSlug,
|
|
102
|
+
calls,
|
|
103
|
+
})
|
|
104
|
+
}
|
|
105
|
+
const parentCalls = sessionPendingAskCalls(parent)
|
|
106
|
+
if (parentCalls.length > 0) {
|
|
107
|
+
asks.push({ session: sessionRef(parent), origin: 'parent', calls: parentCalls })
|
|
108
|
+
}
|
|
109
|
+
return asks
|
|
110
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
PlatformAgentSessionConfigPatch,
|
|
3
|
+
PlatformAgentSessionScope,
|
|
4
|
+
} from './agentTypes.js'
|
|
5
|
+
import {
|
|
6
|
+
getPlatformPreferences,
|
|
7
|
+
patchPlatformPreferences,
|
|
8
|
+
} from './preferences.mjs'
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Persist session-config changes as scope defaults in shell preferences
|
|
12
|
+
* (`agentSessionDefaults.global` / `.apps[slug]`) — layer 3 of the approval
|
|
13
|
+
* ladder (docs/08-agent-orchestration.md). Every NEW session in the scope
|
|
14
|
+
* inherits these, mission runs and delegated children included; this is what
|
|
15
|
+
* makes "always allow" stick beyond one conversation.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
interface StoredScopeDefaults {
|
|
19
|
+
global?: PlatformAgentSessionConfigPatch
|
|
20
|
+
apps?: Record<string, PlatformAgentSessionConfigPatch>
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function mergeScopeDefaultPatch(
|
|
24
|
+
base: PlatformAgentSessionConfigPatch | undefined,
|
|
25
|
+
patch: PlatformAgentSessionConfigPatch,
|
|
26
|
+
): PlatformAgentSessionConfigPatch {
|
|
27
|
+
const toolPolicy =
|
|
28
|
+
patch.toolPolicy || base?.toolPolicy
|
|
29
|
+
? {
|
|
30
|
+
...base?.toolPolicy,
|
|
31
|
+
...patch.toolPolicy,
|
|
32
|
+
approvalOverrides: {
|
|
33
|
+
...base?.toolPolicy?.approvalOverrides,
|
|
34
|
+
...patch.toolPolicy?.approvalOverrides,
|
|
35
|
+
},
|
|
36
|
+
}
|
|
37
|
+
: undefined
|
|
38
|
+
return { ...base, ...patch, ...(toolPolicy ? { toolPolicy } : {}) }
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export async function patchAgentSessionScopeDefaults(
|
|
42
|
+
scope: PlatformAgentSessionScope,
|
|
43
|
+
appSlug: string | undefined,
|
|
44
|
+
patch: PlatformAgentSessionConfigPatch,
|
|
45
|
+
): Promise<void> {
|
|
46
|
+
const prefs = (await getPlatformPreferences()) as {
|
|
47
|
+
agentSessionDefaults?: StoredScopeDefaults
|
|
48
|
+
}
|
|
49
|
+
const stored = prefs.agentSessionDefaults ?? {}
|
|
50
|
+
if (scope === 'global') {
|
|
51
|
+
await patchPlatformPreferences({
|
|
52
|
+
agentSessionDefaults: {
|
|
53
|
+
...stored,
|
|
54
|
+
global: mergeScopeDefaultPatch(stored.global, patch),
|
|
55
|
+
},
|
|
56
|
+
})
|
|
57
|
+
return
|
|
58
|
+
}
|
|
59
|
+
if (!appSlug) return
|
|
60
|
+
const apps = { ...(stored.apps ?? {}) }
|
|
61
|
+
apps[appSlug] = mergeScopeDefaultPatch(apps[appSlug], patch)
|
|
62
|
+
await patchPlatformPreferences({
|
|
63
|
+
agentSessionDefaults: { ...stored, apps },
|
|
64
|
+
})
|
|
65
|
+
}
|
package/src/bridge/agentTypes.ts
CHANGED
|
@@ -89,12 +89,12 @@ export interface PlatformAgentSessionToolPolicy {
|
|
|
89
89
|
}
|
|
90
90
|
|
|
91
91
|
export interface PlatformAgentSessionConfig {
|
|
92
|
-
modelId
|
|
92
|
+
modelId?: string
|
|
93
93
|
/** Appended after the app's agents.md base prompt. */
|
|
94
94
|
sessionPrompt?: string
|
|
95
95
|
/** Full system prompt override. When set, replaces agents.md and sessionPrompt. */
|
|
96
96
|
systemPrompt?: string
|
|
97
|
-
toolPolicy?: PlatformAgentSessionToolPolicy
|
|
97
|
+
toolPolicy?: Partial<PlatformAgentSessionToolPolicy>
|
|
98
98
|
}
|
|
99
99
|
|
|
100
100
|
export interface PlatformAgentSessionMetadata {
|
|
@@ -199,6 +199,40 @@ export interface PlatformReadAgentJobRequest {
|
|
|
199
199
|
jobId: string
|
|
200
200
|
}
|
|
201
201
|
|
|
202
|
+
export type PlatformAgentDelegationStatus =
|
|
203
|
+
| 'pending'
|
|
204
|
+
| 'running'
|
|
205
|
+
| 'completed'
|
|
206
|
+
| 'failed'
|
|
207
|
+
| 'cancelled'
|
|
208
|
+
|
|
209
|
+
export interface PlatformAgentDelegationRecord {
|
|
210
|
+
version: 1
|
|
211
|
+
delegationId: string
|
|
212
|
+
parentJobId?: string
|
|
213
|
+
parentScope?: PlatformAgentSessionScope
|
|
214
|
+
parentAppSlug?: string
|
|
215
|
+
parentSessionId: string
|
|
216
|
+
parentRunId: string
|
|
217
|
+
parentToolCallId: string
|
|
218
|
+
childSessionId: string
|
|
219
|
+
childAppSlug: string
|
|
220
|
+
childJobId?: string
|
|
221
|
+
status: PlatformAgentDelegationStatus
|
|
222
|
+
resultJson?: unknown
|
|
223
|
+
error?: string
|
|
224
|
+
createdAt: string
|
|
225
|
+
updatedAt: string
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
export interface PlatformListAgentDelegationsRequest {
|
|
229
|
+
parentJobId?: string
|
|
230
|
+
childJobId?: string
|
|
231
|
+
parentSessionId?: string
|
|
232
|
+
childSessionId?: string
|
|
233
|
+
status?: PlatformAgentDelegationStatus
|
|
234
|
+
}
|
|
235
|
+
|
|
202
236
|
export interface PlatformCancelAgentJobRequest
|
|
203
237
|
extends PlatformReadAgentJobRequest {
|
|
204
238
|
reason?: string
|
package/src/bridge/agents.d.mts
CHANGED
|
@@ -23,8 +23,10 @@ import type {
|
|
|
23
23
|
PlatformCreateAgentSessionRequest,
|
|
24
24
|
PlatformCreateAgentJobRequest,
|
|
25
25
|
PlatformCancelAgentJobRequest,
|
|
26
|
+
PlatformAgentDelegationRecord,
|
|
26
27
|
PlatformAgentJobRecord,
|
|
27
28
|
PlatformListAgentSessionsRequest,
|
|
29
|
+
PlatformListAgentDelegationsRequest,
|
|
28
30
|
PlatformListAgentJobsRequest,
|
|
29
31
|
PlatformReadAgentSessionRequest,
|
|
30
32
|
PlatformReadAgentJobRequest,
|
|
@@ -71,6 +73,10 @@ export function runAgentJobNow(
|
|
|
71
73
|
request: PlatformReadAgentJobRequest,
|
|
72
74
|
): Promise<PlatformAgentJobRecord>
|
|
73
75
|
|
|
76
|
+
export function listAgentDelegations(
|
|
77
|
+
request?: PlatformListAgentDelegationsRequest,
|
|
78
|
+
): Promise<PlatformAgentDelegationRecord[]>
|
|
79
|
+
|
|
74
80
|
export function sendAgentSessionMessage(
|
|
75
81
|
request: PlatformSendAgentSessionMessageRequest,
|
|
76
82
|
): Promise<PlatformAgentSessionDriveResult>
|
package/src/bridge/agents.mjs
CHANGED
|
@@ -78,6 +78,16 @@ export async function runAgentJobNow(request) {
|
|
|
78
78
|
return bridge.call(PLATFORM_BRIDGE_METHODS.AGENTS_JOBS_RUN_NOW, [request])
|
|
79
79
|
}
|
|
80
80
|
|
|
81
|
+
/**
|
|
82
|
+
* @param {import('./agentTypes.js').PlatformListAgentDelegationsRequest} [request]
|
|
83
|
+
* @returns {Promise<import('./agentTypes.js').PlatformAgentDelegationRecord[]>}
|
|
84
|
+
*/
|
|
85
|
+
export async function listAgentDelegations(request = {}) {
|
|
86
|
+
return bridge.call(PLATFORM_BRIDGE_METHODS.AGENTS_DELEGATIONS_LIST, [
|
|
87
|
+
request,
|
|
88
|
+
])
|
|
89
|
+
}
|
|
90
|
+
|
|
81
91
|
/**
|
|
82
92
|
* Send a user message on a session; shell drives the run until awaiting user,
|
|
83
93
|
* manual pending tools, or terminal state.
|
package/src/bridge/agents.ts
CHANGED
|
@@ -8,6 +8,7 @@ export {
|
|
|
8
8
|
createAgentSession,
|
|
9
9
|
deleteAgentSession,
|
|
10
10
|
interruptAgentSession,
|
|
11
|
+
listAgentDelegations,
|
|
11
12
|
listAgentJobs,
|
|
12
13
|
listAgentSessions,
|
|
13
14
|
onAgentRunEvent,
|
|
@@ -29,6 +30,8 @@ export {
|
|
|
29
30
|
export type {
|
|
30
31
|
PlatformAgentMessage,
|
|
31
32
|
PlatformAgentMessageAttachment,
|
|
33
|
+
PlatformAgentDelegationRecord,
|
|
34
|
+
PlatformAgentDelegationStatus,
|
|
32
35
|
PlatformAgentJobRecord,
|
|
33
36
|
PlatformAgentJobSchedule,
|
|
34
37
|
PlatformAgentJobStatus,
|
|
@@ -47,6 +50,7 @@ export type {
|
|
|
47
50
|
PlatformCreateAgentSessionRequest,
|
|
48
51
|
PlatformCreateAgentJobRequest,
|
|
49
52
|
PlatformListAgentSessionsRequest,
|
|
53
|
+
PlatformListAgentDelegationsRequest,
|
|
50
54
|
PlatformListAgentJobsRequest,
|
|
51
55
|
PlatformReadAgentJobRequest,
|
|
52
56
|
PlatformReadAgentSessionRequest,
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
export interface CredentialStorageStatus {
|
|
2
|
+
encryptionAvailable: boolean
|
|
3
|
+
backend: string | null
|
|
4
|
+
secure: boolean
|
|
5
|
+
warning?: string
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export interface CredentialEntryStatus {
|
|
9
|
+
id: string
|
|
10
|
+
label: string
|
|
11
|
+
description?: string
|
|
12
|
+
configured: boolean
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/** Redacted OAuth connection state — never contains secret material. */
|
|
16
|
+
export interface OAuthCredentialStatus {
|
|
17
|
+
id: string
|
|
18
|
+
kind: 'oauth'
|
|
19
|
+
provider: 'google'
|
|
20
|
+
configured: boolean
|
|
21
|
+
connected: boolean
|
|
22
|
+
email?: string
|
|
23
|
+
scopes: string[]
|
|
24
|
+
needsReconnect: boolean
|
|
25
|
+
updatedAt?: string
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function readCredentialStorageStatus(): Promise<CredentialStorageStatus>
|
|
29
|
+
|
|
30
|
+
export function listCredentials(): Promise<CredentialEntryStatus[]>
|
|
31
|
+
|
|
32
|
+
export function setCredential(request: {
|
|
33
|
+
id: string
|
|
34
|
+
value: string
|
|
35
|
+
}): Promise<{ ok: true }>
|
|
36
|
+
|
|
37
|
+
export function deleteCredential(request: { id: string }): Promise<{ ok: true }>
|
|
38
|
+
|
|
39
|
+
export function readCredentialStatus(request: {
|
|
40
|
+
id: string
|
|
41
|
+
}): Promise<OAuthCredentialStatus>
|
|
42
|
+
|
|
43
|
+
export function setCredentialOAuthConfig(request: {
|
|
44
|
+
id: string
|
|
45
|
+
clientId: string
|
|
46
|
+
clientSecret: string
|
|
47
|
+
scopes?: string[]
|
|
48
|
+
}): Promise<{ ok: true }>
|
|
49
|
+
|
|
50
|
+
export function connectCredentialOAuth(request: {
|
|
51
|
+
id: string
|
|
52
|
+
scopes?: string[]
|
|
53
|
+
}): Promise<{ email?: string }>
|
|
54
|
+
|
|
55
|
+
export function disconnectCredential(request: {
|
|
56
|
+
id: string
|
|
57
|
+
forget?: boolean
|
|
58
|
+
}): Promise<{ ok: true }>
|
|
59
|
+
|
|
60
|
+
export function readCredentialOAuthAccessToken(request: {
|
|
61
|
+
id: string
|
|
62
|
+
}): Promise<{ accessToken: string; expiresAt: number }>
|
|
@@ -20,3 +20,56 @@ export async function setCredential(request) {
|
|
|
20
20
|
export async function deleteCredential(request) {
|
|
21
21
|
return bridge.call(PLATFORM_BRIDGE_METHODS.CREDENTIALS_DELETE, [request])
|
|
22
22
|
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Redacted OAuth connection state — the only credential state apps may read.
|
|
26
|
+
* @param {{ id: string }} request
|
|
27
|
+
* @returns {Promise<{ id: string, configured: boolean, connected: boolean, email?: string, scopes: string[], needsReconnect: boolean, updatedAt?: string }>}
|
|
28
|
+
*/
|
|
29
|
+
export async function readCredentialStatus(request) {
|
|
30
|
+
return bridge.call(PLATFORM_BRIDGE_METHODS.CREDENTIALS_STATUS, [request])
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Write-only OAuth client config; the secret is never echoed back.
|
|
35
|
+
* @param {{ id: string, clientId: string, clientSecret: string, scopes?: string[] }} request
|
|
36
|
+
* @returns {Promise<{ ok: true }>}
|
|
37
|
+
*/
|
|
38
|
+
export async function setCredentialOAuthConfig(request) {
|
|
39
|
+
return bridge.call(PLATFORM_BRIDGE_METHODS.CREDENTIALS_SET_OAUTH_CONFIG, [
|
|
40
|
+
request,
|
|
41
|
+
])
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Runs the full OAuth flow in the shell (browser + loopback + token
|
|
46
|
+
* exchange); no token or secret ever reaches the caller.
|
|
47
|
+
* @param {{ id: string, scopes?: string[] }} request
|
|
48
|
+
* @returns {Promise<{ email?: string }>}
|
|
49
|
+
*/
|
|
50
|
+
export async function connectCredentialOAuth(request) {
|
|
51
|
+
return bridge.call(PLATFORM_BRIDGE_METHODS.CREDENTIALS_CONNECT_OAUTH, [
|
|
52
|
+
request,
|
|
53
|
+
])
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Clears tokens + identity; pass `forget: true` to also drop the client config.
|
|
58
|
+
* @param {{ id: string, forget?: boolean }} request
|
|
59
|
+
* @returns {Promise<{ ok: true }>}
|
|
60
|
+
*/
|
|
61
|
+
export async function disconnectCredential(request) {
|
|
62
|
+
return bridge.call(PLATFORM_BRIDGE_METHODS.CREDENTIALS_DISCONNECT, [request])
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Short-lived access token for providers that call the API directly.
|
|
67
|
+
* Refreshed transparently in the shell; refresh tokens never cross the bridge.
|
|
68
|
+
* @param {{ id: string }} request
|
|
69
|
+
* @returns {Promise<{ accessToken: string, expiresAt: number }>}
|
|
70
|
+
*/
|
|
71
|
+
export async function readCredentialOAuthAccessToken(request) {
|
|
72
|
+
return bridge.call(PLATFORM_BRIDGE_METHODS.CREDENTIALS_OAUTH_ACCESS_TOKEN, [
|
|
73
|
+
request,
|
|
74
|
+
])
|
|
75
|
+
}
|
package/src/bridge/events.d.mts
CHANGED
|
@@ -8,6 +8,7 @@ export declare const PLATFORM_BRIDGE_EVENTS: {
|
|
|
8
8
|
readonly DEBUG_TEST: 'debug.test'
|
|
9
9
|
readonly SCHEDULE_FIRE: 'schedule.fire'
|
|
10
10
|
readonly WINDOW_CAMERA_SHORTCUT: 'window.cameraShortcut'
|
|
11
|
+
readonly OPERATIONS_CHANGED: 'operations.changed'
|
|
11
12
|
}
|
|
12
13
|
|
|
13
14
|
export type PlatformBridgeEventName =
|