@dev-mainsequence/codex-plugin 0.4.2 → 0.7.10

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.
Files changed (34) hide show
  1. package/.codex-plugin/plugin.json +3 -3
  2. package/.mcp.json +2 -1
  3. package/README.md +30 -4
  4. package/assets/mainsequence-mark.svg +453 -0
  5. package/build-info.json +3 -3
  6. package/dist/hosts/discovery.js +138 -24
  7. package/dist/hosts/messaging.js +63 -0
  8. package/dist/hosts/panel/panel.html +250 -125
  9. package/dist/hosts/workspace.js +107 -0
  10. package/dist/panel-server.js +115 -27
  11. package/dist/vendor/devtools/index.js +41 -1
  12. package/dist/vendor/devtools/package.json +1 -1
  13. package/dist/vendor/devtools/shared/actions.js +36 -7
  14. package/dist/vendor/devtools/shared/agentAssets.js +38 -0
  15. package/dist/vendor/devtools/shared/agentDelivery.js +477 -0
  16. package/dist/vendor/devtools/shared/agentIcon.js +43 -0
  17. package/dist/vendor/devtools/shared/agents.js +13 -6
  18. package/dist/vendor/devtools/shared/arguments.js +16 -9
  19. package/dist/vendor/devtools/shared/deployments.js +214 -0
  20. package/dist/vendor/devtools/shared/mcp.js +124 -25
  21. package/dist/vendor/devtools/shared/mcpTransport.js +64 -21
  22. package/dist/vendor/devtools/shared/organizationProjectWorkspace.js +8 -3
  23. package/dist/vendor/devtools/shared/projectTools.js +437 -0
  24. package/dist/vendor/devtools/shared/repositories.js +2 -2
  25. package/dist/vendor/devtools/shared/session.js +46 -15
  26. package/dist/vendor/devtools/shared/sharedTransport.js +506 -0
  27. package/dist/vendor/devtools/shared/stateDirectory.js +44 -0
  28. package/dist/vendor/devtools/shared/workingDirectory.js +13 -0
  29. package/dist/vendor/devtools/shared/workspaceSettings.js +96 -0
  30. package/docs/agents-tools-panel.md +523 -12
  31. package/docs/conversational-mcp.md +15 -2
  32. package/package.json +3 -3
  33. package/skills/mainsequence-mcp/SKILL.md +18 -3
  34. package/skills/ms/assets/mainsequence-mark.svg +453 -0
@@ -14,7 +14,10 @@ class DiscoveryError extends Error {
14
14
  }
15
15
  }
16
16
  exports.DiscoveryError = DiscoveryError;
17
- const invalid = () => new DiscoveryError('INVALID_REQUEST', 'Choose an environment or item from the current directory.');
17
+ // Every refusal names the argument and what would be accepted: the model reads these, and
18
+ // one generic sentence for five different mistakes was indistinguishable from a broken host.
19
+ const invalid = (message) => new DiscoveryError('INVALID_REQUEST', message);
20
+ const shown = (value) => JSON.stringify(typeof value === 'string' ? value.slice(0, 80) : value === undefined ? 'missing' : value).slice(0, 100);
18
21
  function success(result) {
19
22
  if (result.status !== 'success')
20
23
  throw new DiscoveryError(result.error?.code || 'API_ERROR', result.summary);
@@ -26,15 +29,31 @@ function account(value) {
26
29
  return { backend: text(value.backend), authenticated: value.authenticated === true, username: text(value.username, 300),
27
30
  source: text(value.source, 40), checked: value.checked === true, expiresAt: text(value.expiresAt, 100) };
28
31
  }
32
+ const environmentLabel = (context, uid) => `${context.environments.get(uid) || 'environment'} (${uid})`;
33
+ /** A release the context has seen, in this environment. Says where it was seen instead when it belongs elsewhere. */
34
+ function knownRelease(context, environmentUid, value, kind) {
35
+ if (!uuid(value))
36
+ throw invalid(`releaseUid must be a release UUID from mainsequence_view connections or mainsequence_discover tools, not ${shown(value)}.`);
37
+ const uid = value.toLowerCase();
38
+ if (context.releases.get(environmentUid)?.has(uid))
39
+ return uid;
40
+ const elsewhere = [...context.releases].find(([, set]) => set.has(uid))?.[0];
41
+ if (elsewhere)
42
+ throw invalid(`Release ${uid} belongs to ${environmentLabel(context, elsewhere)}; pass environmentUid ${shown(elsewhere)} instead of ${shown(environmentUid)}.`);
43
+ throw invalid(`Release ${uid} is not a ${kind} MCP of ${environmentLabel(context, environmentUid)} in this chat. Read mainsequence_view with view "connections" (saved) or mainsequence_discover with catalog "tools" first, then use its releaseUid.`);
44
+ }
29
45
  /** Host presentation only. Every domain operation goes through the public devtools dispatcher. */
30
- function createDiscovery() {
46
+ function createDiscovery(dependencies) {
31
47
  const contexts = new Map();
48
+ // A view preference only; authorization still uses the current context and devtools.
49
+ const selectedEnvironments = new Map();
50
+ const accountKey = (backend, username) => JSON.stringify([backend, username]);
32
51
  function prune() {
33
52
  for (const [id, context] of contexts)
34
53
  if (context.expires < Date.now())
35
54
  contexts.delete(id);
36
55
  }
37
- async function status(dispatch) {
56
+ async function status(dispatch, conversationId) {
38
57
  prune();
39
58
  const local = account(success(await dispatch({ action: 'auth-status' })));
40
59
  const base = { account: local, environments: [], contextId: null, issue: null };
@@ -49,12 +68,14 @@ function createDiscovery() {
49
68
  .map(item => ({ uid: item.uid, name: text(item.name, 300), isProduction: item.isProduction }));
50
69
  const final = account(success(await dispatch({ action: 'auth-status' })));
51
70
  if (final.backend !== verified.backend || !final.authenticated)
52
- throw new DiscoveryError('CONTEXT_CHANGED', 'The backend or session changed. Refresh MainSequence.');
71
+ throw new DiscoveryError('CONTEXT_CHANGED', `The backend changed from ${verified.backend} to ${final.backend || 'none'} while opening. Refresh MainSequence.`);
53
72
  while (contexts.size >= 32)
54
73
  contexts.delete(contexts.keys().next().value);
55
74
  const id = (0, node_crypto_1.randomUUID)();
56
- contexts.set(id, { backend: verified.backend, account: verified.username, environments: new Set(available.map(e => e.uid)), releases: new Map(), expires: Date.now() + 30 * 60_000 });
57
- return { ...base, contextId: id, environments: available };
75
+ contexts.set(id, { backend: verified.backend, account: verified.username, conversationId, environments: new Map(available.map(e => [e.uid.toLowerCase(), e.name])), releases: new Map(), agents: new Map(), projects: new Map(), expires: Date.now() + 30 * 60_000 });
76
+ const selected = selectedEnvironments.get(accountKey(verified.backend, verified.username));
77
+ return { ...base, contextId: id, environments: available,
78
+ selectedEnvironmentUid: available.some(environment => environment.uid === selected) ? selected : null };
58
79
  }
59
80
  catch (error) {
60
81
  if (!(error instanceof DiscoveryError))
@@ -66,50 +87,65 @@ function createDiscovery() {
66
87
  prune();
67
88
  const context = contexts.get(String(args.contextId));
68
89
  if (!context)
69
- throw new DiscoveryError('CONTEXT_CHANGED', 'Refresh MainSequence to load the current account and environments.');
70
- if (!uuid(args.environmentUid) || !context.environments.has(args.environmentUid.toLowerCase()))
71
- throw invalid();
90
+ throw new DiscoveryError('CONTEXT_CHANGED', `contextId ${shown(args.contextId)} is unknown to this server (contexts live 30 minutes in the chat's server process). Call mainsequence_open again and use its contextId.`);
91
+ if (!uuid(args.environmentUid) || !context.environments.has(args.environmentUid.toLowerCase())) {
92
+ throw invalid(`environmentUid ${shown(args.environmentUid)} is not one of this account's environments: ${[...context.environments].map(([uid, name]) => `${name} = ${uid}`).join('; ')}.`);
93
+ }
94
+ const environmentUid = args.environmentUid.toLowerCase();
72
95
  async function verify() {
73
96
  // Host settings may change while the panel is open. Devtools binds domain
74
97
  // requests to the verified account; this local check invalidates the old view.
75
98
  const current = account(success(await dispatch({ action: 'auth-status' })));
76
99
  if (!current.authenticated || current.backend !== context.backend) {
77
100
  contexts.delete(String(args.contextId));
78
- throw new DiscoveryError('CONTEXT_CHANGED', 'The account or backend changed. Refresh MainSequence.');
101
+ throw new DiscoveryError('CONTEXT_CHANGED', current.authenticated ? `The backend changed from ${context.backend} to ${current.backend}. Refresh MainSequence.` : `No MainSequence session is available for ${context.backend} any more. Sign in again, then refresh MainSequence.`);
79
102
  }
80
103
  }
81
104
  await verify();
82
105
  let answer;
83
106
  try {
84
- answer = await run(context, args.environmentUid.toLowerCase());
107
+ answer = await run(context, environmentUid);
85
108
  }
86
109
  catch (error) {
87
110
  if (error instanceof DiscoveryError && ['AUTH_REJECTED', 'NOT_AUTHENTICATED'].includes(error.code)) {
88
111
  contexts.delete(String(args.contextId));
89
- throw new DiscoveryError('CONTEXT_CHANGED', 'The account or session changed. Refresh MainSequence.');
112
+ throw new DiscoveryError('CONTEXT_CHANGED', `The account or session changed (${error.code}: ${error.message}). Refresh MainSequence and retry once.`);
90
113
  }
91
114
  throw error;
92
115
  }
93
116
  await verify();
117
+ const key = accountKey(context.backend, context.account);
118
+ while (selectedEnvironments.size >= 32 && !selectedEnvironments.has(key))
119
+ selectedEnvironments.delete(selectedEnvironments.keys().next().value);
120
+ selectedEnvironments.set(key, environmentUid);
94
121
  return answer;
95
122
  }
123
+ function page(args) {
124
+ if (args.search !== undefined && (typeof args.search !== 'string' || args.search.length > 300))
125
+ throw invalid(`search must be a string of at most 300 characters, not ${shown(args.search)}.`);
126
+ if (args.offset !== undefined && (!Number.isSafeInteger(args.offset) || Number(args.offset) < 0))
127
+ throw invalid(`offset must be a non-negative integer, not ${shown(args.offset)}.`);
128
+ }
96
129
  async function discover(dispatch, args) {
97
- if (!['agents', 'tools'].includes(String(args.catalog)) || (args.search !== undefined && (typeof args.search !== 'string' || args.search.length > 300))
98
- || (args.offset !== undefined && (!Number.isSafeInteger(args.offset) || Number(args.offset) < 0)))
99
- throw invalid();
130
+ if (!['agents', 'tools'].includes(String(args.catalog)))
131
+ throw invalid(`catalog must be "agents" or "tools", not ${shown(args.catalog)}.`);
132
+ page(args);
100
133
  return scoped(dispatch, args, async (context, environmentUid) => {
101
134
  const search = text(args.search, 300).trim(), offset = Number(args.offset || 0), limit = 20;
102
135
  // Agent semantic search is a ranked result set, not an offset-paginated directory.
103
136
  if (args.catalog === 'agents' && search && offset)
104
- throw invalid();
137
+ throw invalid('Agent search returns one ranked result set; omit offset when search is set.');
105
138
  const selection = { backend: context.backend, environmentUid, expectedAccount: context.account };
106
139
  if (args.catalog === 'agents') {
107
- const output = success(await dispatch({ action: 'agents-list', ...selection, search, limit, offset }));
140
+ const output = success(await dispatch({ action: 'agents-list', ...selection, search, limit, offset, includeIcons: true }));
108
141
  const results = output.results.map(item => {
109
142
  return { uid: item.uid, name: text(item.name, 300), description: text(item.description), runtimeState: text(item.runtimeState, 100),
110
- repositoryBranch: text(item.repositoryBranch, 300), responseKinds: item.responseKinds.slice(0, 10),
143
+ repositoryBranch: text(item.repositoryBranch, 300), responseKinds: item.responseKinds.slice(0, 10), icon: item.icon ?? null,
111
144
  defaults: { provider: text(item.defaults.provider, 100), model: text(item.defaults.model, 100), thinking: text(item.defaults.thinking, 100) } };
112
145
  });
146
+ const known = context.agents.get(environmentUid) || new Set();
147
+ results.forEach(item => known.add(item.uid));
148
+ context.agents.set(environmentUid, known);
113
149
  return { catalog: 'agents', environmentUid, count: output.count, offset: output.offset, limit, semantic: output.semantic, results };
114
150
  }
115
151
  const output = success(await dispatch({ action: 'mcp-discover', ...selection, search, limit, offset, enrichNames: true }));
@@ -118,21 +154,99 @@ function createDiscovery() {
118
154
  return { uid: item.resource_release_uid, name: text(item.name, 300) || text(item.display_name, 300) || item.resource_release_uid,
119
155
  repository: text(item.display_name, 300), environmentName: text(item.mcp_connection.organization_environment_name, 300), saved: saved.has(item.resource_release_uid) };
120
156
  });
121
- context.releases.set(environmentUid, new Set(results.map(item => item.uid)));
157
+ const known = context.releases.get(environmentUid) || new Set();
158
+ results.forEach(item => known.add(item.uid));
159
+ context.releases.set(environmentUid, known);
122
160
  return { catalog: 'tools', environmentUid, count: output.count, offset, limit, semantic: false, results };
123
161
  });
124
162
  }
125
163
  async function tools(dispatch, args) {
126
164
  return scoped(dispatch, args, async (context, environmentUid) => {
127
- if (!uuid(args.releaseUid) || !context.releases.get(environmentUid)?.has(args.releaseUid.toLowerCase()))
128
- throw invalid();
165
+ const releaseUid = knownRelease(context, environmentUid, args.releaseUid, 'saved or discovered');
129
166
  // mcp-tools checks existing saved metadata and current access. It never adds a connection or invokes a project tool.
130
- const output = success(await dispatch({ action: 'mcp-tools', backend: context.backend, environmentUid, releaseUid: args.releaseUid, expectedAccount: context.account }));
131
- return { releaseUid: args.releaseUid, tools: output.tools.map(item => {
167
+ const output = success(await dispatch({ action: 'mcp-tools', backend: context.backend, environmentUid, releaseUid, expectedAccount: context.account }));
168
+ return { releaseUid, tools: output.tools.map(item => {
132
169
  return { name: text(item.name, 300), description: text(item.description), inputSchema: item.inputSchema,
133
170
  annotations: Object.fromEntries(['readOnlyHint', 'destructiveHint', 'idempotentHint', 'openWorldHint'].filter(k => typeof row(item.annotations)[k] === 'boolean').map(k => [k, row(item.annotations)[k]])) };
134
171
  }) };
135
172
  });
136
173
  }
137
- return { status, discover, tools };
174
+ async function messageSelection(dispatch, args, conversationId) {
175
+ return scoped(dispatch, args, async (context, environmentUid) => {
176
+ if (context.conversationId !== conversationId)
177
+ throw invalid('This contextId was opened from another chat; agent messages are bound to the chat that opened MainSequence. Call mainsequence_open in this chat and use its contextId.');
178
+ if (!uuid(args.agentUid) || !context.agents.get(environmentUid)?.has(args.agentUid.toLowerCase())) {
179
+ throw invalid(`agentUid ${shown(args.agentUid)} is not an agent of ${environmentLabel(context, environmentUid)} seen in this chat. Read mainsequence_discover with catalog "agents" first and use a uid from its results.`);
180
+ }
181
+ return { backend: context.backend, account: context.account, environmentUid, agentUid: args.agentUid.toLowerCase() };
182
+ });
183
+ }
184
+ async function view(dispatch, args, signal) {
185
+ return scoped(dispatch, args, async (context, environmentUid) => {
186
+ const selection = { backend: context.backend, expectedAccount: context.account, environmentUid };
187
+ if (args.view === 'agent' || args.view === 'assets') {
188
+ const ids = args.view === 'assets' ? args.agentUids : [args.agentUid];
189
+ if (!Array.isArray(ids) || ids.length > 20 || ids.some(id => !uuid(id) || !context.agents.get(environmentUid)?.has(id.toLowerCase()))) {
190
+ throw invalid(`${args.view === 'assets' ? 'agentUids (at most 20)' : 'agentUid'} must name agents of ${environmentLabel(context, environmentUid)} seen in this chat; read mainsequence_discover with catalog "agents" first.`);
191
+ }
192
+ // Old open panels must not trigger another directory or individual icon reads.
193
+ if (args.view === 'assets')
194
+ return { assets: {} };
195
+ const { agent } = success(await dispatch({ action: 'agent-get', ...selection, agentUid: String(args.agentUid), includeIcons: true }));
196
+ return { agent };
197
+ }
198
+ if (args.view === 'connections') {
199
+ const connections = success(await dispatch({ action: 'mcp-list', ...selection, readOnly: true }));
200
+ const known = context.releases.get(environmentUid) || new Set();
201
+ const results = connections.map(item => { known.add(item.resource_release_uid); return { uid: item.resource_release_uid, name: text(item.name, 300) || text(item.display_name, 300) || item.resource_release_uid, saved: true }; });
202
+ context.releases.set(environmentUid, known);
203
+ return { results, count: results.length };
204
+ }
205
+ if (args.view === 'projects') {
206
+ page(args);
207
+ const result = success(await dispatch({ action: 'organization-projects', ...selection, search: text(args.search, 300), offset: Number(args.offset || 0), limit: 20 }));
208
+ context.projects.set(environmentUid, new Set(result.results.map(p => p.uid)));
209
+ return result;
210
+ }
211
+ if (args.view === 'project') {
212
+ if (!uuid(args.projectUid) || !context.projects.get(environmentUid)?.has(args.projectUid))
213
+ throw invalid(`projectUid ${shown(args.projectUid)} is not a project of ${environmentLabel(context, environmentUid)} seen in this chat; read mainsequence_view with view "projects" first.`);
214
+ return success(await dispatch({ action: 'organization-project', ...selection, projectUid: args.projectUid }));
215
+ }
216
+ if (args.view === 'repositories' && dependencies)
217
+ return { results: await dependencies.repositories(context.backend, context.account, signal) };
218
+ if (args.view === 'preferences' && dependencies)
219
+ return { preferences: await dependencies.preferences() };
220
+ throw invalid(`view must be one of agent, assets, connections, projects, project, repositories or preferences, not ${shown(args.view)}.`);
221
+ });
222
+ }
223
+ async function connection(dispatch, args) {
224
+ return scoped(dispatch, args, async (context, environmentUid) => {
225
+ if (!['connect', 'disconnect'].includes(String(args.action)))
226
+ throw invalid(`action must be "connect" or "disconnect", not ${shown(args.action)}.`);
227
+ const releaseUid = knownRelease(context, environmentUid, args.releaseUid, 'discovered');
228
+ const result = await dispatch({ action: args.action === 'connect' ? 'mcp-add' : 'mcp-remove', backend: context.backend, expectedAccount: context.account, environmentUid, releaseUid });
229
+ if (result.status !== 'success')
230
+ throw new DiscoveryError(result.error?.code || 'API_ERROR', result.summary);
231
+ return { summary: result.summary, connected: args.action === 'connect' };
232
+ });
233
+ }
234
+ async function invoke(dispatch, args) {
235
+ return scoped(dispatch, args, async (context, environmentUid) => {
236
+ const releaseUid = knownRelease(context, environmentUid, args.releaseUid, 'saved or discovered');
237
+ if (typeof args.tool !== 'string' || !args.tool.trim() || args.tool.length > 300)
238
+ throw invalid(`tool must be a tool name from mainsequence_tools (a non-empty string of at most 300 characters), not ${shown(args.tool)}.`);
239
+ // An omitted argument object means no arguments; anything else must be the tool's input object.
240
+ const input = args.arguments === undefined ? {} : args.arguments;
241
+ if (!input || typeof input !== 'object' || Array.isArray(input))
242
+ throw invalid(`arguments must be a JSON object matching the tool's inputSchema (omit it for no arguments), not ${shown(args.arguments)}.`);
243
+ const output = await dispatch({ action: 'mcp-call', backend: context.backend, expectedAccount: context.account, environmentUid, releaseUid, tool: args.tool, arguments: input });
244
+ // Preserve remote MCP failures and uncertain effects through the native tool
245
+ // boundary. Authentication changes still invalidate the scoped panel.
246
+ if (output.error && ['AUTH_REJECTED', 'NOT_AUTHENTICATED'].includes(output.error.code))
247
+ throw new DiscoveryError(output.error.code, output.summary);
248
+ return { result: output.data, ...(output.status === 'success' ? {} : { error: output.error || { code: 'API_ERROR', message: output.summary }, effects: output.effects }) };
249
+ });
250
+ }
251
+ return { status, discover, tools, messageSelection, view, connection, invoke, scoped };
138
252
  }
@@ -0,0 +1,63 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.conversationIdentity = conversationIdentity;
4
+ exports.createMessaging = createMessaging;
5
+ const devtools_1 = require("../vendor/devtools/index.js");
6
+ const discovery_1 = require("./discovery.js");
7
+ /** This identity is supplied by Codex, never by a model/app tool argument. */
8
+ function conversationIdentity(meta) {
9
+ if (!meta || typeof meta !== 'object' || Array.isArray(meta))
10
+ return;
11
+ const { threadId, thread_id } = meta;
12
+ if (threadId !== undefined && thread_id !== undefined && threadId !== thread_id)
13
+ return;
14
+ const value = threadId ?? thread_id;
15
+ return typeof value === 'string' && value.trim() && value.length <= 512 ? value : undefined;
16
+ }
17
+ function createMessaging(discovery, createDispatch, options = {}) {
18
+ const delivery = new devtools_1.AgentDelivery({ ...options, createDispatch });
19
+ async function scope(dispatch, conversationId) {
20
+ if (!conversationId)
21
+ throw new discovery_1.DiscoveryError('CONVERSATION_REQUIRED', 'Open MainSequence inside a Codex chat to send or recover messages.');
22
+ const local = await dispatch({ action: 'auth-status' });
23
+ if (local.status !== 'success' || !local.data?.authenticated || !local.data.backend)
24
+ throw new discovery_1.DiscoveryError('NOT_AUTHENTICATED', 'Refresh your shared MainSequence session.');
25
+ const result = await dispatch({ action: 'auth-status', backend: local.data.backend, check: true });
26
+ if (result.status !== 'success' || !result.data?.authenticated || !result.data.username)
27
+ throw new discovery_1.DiscoveryError('NOT_AUTHENTICATED', 'The shared MainSequence account could not be verified.');
28
+ return { host: 'codex', conversationId, backend: result.data.backend, account: result.data.username };
29
+ }
30
+ async function call(name, args, dispatch, conversationId, signal) {
31
+ const target = await scope(dispatch, conversationId);
32
+ if (name === 'mainsequence_agent_prepare') {
33
+ const selected = await discovery.messageSelection(dispatch, args, target.conversationId);
34
+ return { conversation: await delivery.prepare(target, { ...selected, conversationKey: args.conversationKey }, signal) };
35
+ }
36
+ if (name === 'mainsequence_stage_message') {
37
+ const selected = await discovery.messageSelection(dispatch, args, target.conversationId);
38
+ if (selected.backend !== target.backend || selected.account !== target.account)
39
+ throw new discovery_1.DiscoveryError('CONTEXT_CHANGED', 'The selected account changed. Refresh MainSequence.');
40
+ return { request: await delivery.stage(target, { ...selected, requestId: args.requestId, message: args.message, conversationKey: args.conversationKey, taskRequestId: args.taskRequestId, responseKind: args.responseKind }, signal) };
41
+ }
42
+ if (name === 'mainsequence_agent_task')
43
+ return { request: await delivery.task(target, args.requestId, args.action, signal) };
44
+ if (name === 'mainsequence_submission')
45
+ return { request: await delivery.submission(target, args.requestId, args.outcome, signal) };
46
+ if ((name === 'mainsequence_agent_status' && !['list', 'get', 'wait'].includes(String(args.action)))
47
+ || (name === 'mainsequence_agent_request' && !['deliver', 'cancel'].includes(String(args.action))))
48
+ throw new devtools_1.ToolingError('INVALID_REQUEST', 'Use the matching delivery or read-only status tool.');
49
+ const id = args.requestId;
50
+ switch (args.action) {
51
+ case 'list':
52
+ if (id !== undefined)
53
+ throw new devtools_1.ToolingError('INVALID_REQUEST', 'List takes no request ID.');
54
+ return { requests: await delivery.list(target, signal) };
55
+ case 'get': return { request: await delivery.get(target, id, signal) };
56
+ case 'deliver': return { request: await delivery.deliver(target, id, signal) };
57
+ case 'wait': return { request: await delivery.wait(target, id, signal) };
58
+ case 'cancel': return { request: await delivery.cancel(target, id, signal) };
59
+ default: throw new devtools_1.ToolingError('INVALID_REQUEST', 'Choose list, get, deliver, wait or cancel.');
60
+ }
61
+ }
62
+ return { call };
63
+ }