@loicngr/kobo 1.7.7 → 1.7.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/AGENTS.md +29 -0
- package/README.md +62 -4
- package/dist/mcp-server/kobo-tasks-server.js +27 -0
- package/dist/server/routes/health.js +14 -0
- package/dist/server/routes/workspaces.js +60 -16
- package/dist/server/services/agent/engines/claude-code/capabilities.js +7 -0
- package/dist/server/services/agent/engines/codex/capabilities.js +18 -0
- package/dist/server/services/agent/engines/codex/client.js +36 -0
- package/dist/server/services/agent/engines/codex/engine.js +276 -0
- package/dist/server/services/agent/engines/codex/event-mapper.js +473 -0
- package/dist/server/services/agent/engines/codex/jsonrpc/peer.js +60 -0
- package/dist/server/services/agent/engines/codex/jsonrpc/transport.js +31 -0
- package/dist/server/services/agent/engines/codex/options-builder.js +81 -0
- package/dist/server/services/agent/engines/codex/protocol/types.js +11 -0
- package/dist/server/services/agent/engines/codex/server-requests.js +99 -0
- package/dist/server/services/agent/engines/codex/spawn.js +27 -0
- package/dist/server/services/agent/engines/registry.js +2 -0
- package/dist/server/services/agent/orchestrator.js +1 -1
- package/dist/server/services/auto-loop-service.js +16 -2
- package/dist/server/services/pr-watcher-service.js +84 -33
- package/dist/server/services/review-template-service.js +24 -31
- package/dist/server/services/settings-service.js +140 -6
- package/dist/server/services/skill-suite-prompts.js +80 -0
- package/dist/server/utils/git-ops.js +69 -15
- package/dist/server/utils/paths.js +7 -0
- package/dist/shared/auto-loop-prompts.js +18 -1
- package/dist/shared/codex-models.js +43 -0
- package/dist/shared/project-colors.js +23 -0
- package/dist/shared/skill-suite-prompts.js +66 -0
- package/package.json +2 -1
- package/src/client/dist/spa/assets/ActivityFeed-CKjFT9t6.js +8 -0
- package/src/client/dist/spa/assets/{ActivityFeed-tE4LVYck.css → ActivityFeed-WjiQ9716.css} +1 -1
- package/src/client/dist/spa/assets/{ClosePopup-DTcbxsC0.js → ClosePopup-DMnQG6nw.js} +1 -1
- package/src/client/dist/spa/assets/CreatePage-BhFrUkEN.js +2 -0
- package/src/client/dist/spa/assets/CreatePage-ZyBHUbl0.css +1 -0
- package/src/client/dist/spa/assets/{DiffViewer-D-uNbBq0.js → DiffViewer-BSnvba7W.js} +3 -3
- package/src/client/dist/spa/assets/HealthPage-DZYZWGHp.js +1 -0
- package/src/client/dist/spa/assets/MainLayout-C45J7rSF.css +1 -0
- package/src/client/dist/spa/assets/MainLayout-CMuiNpet.js +37 -0
- package/src/client/dist/spa/assets/QChip-BgzxI33B.js +36 -0
- package/src/client/dist/spa/assets/{QExpansionItem-BGg74no1.js → QExpansionItem-Fij7yBbG.js} +1 -1
- package/src/client/dist/spa/assets/{QItemSection-CQUDd0Vg.js → QItemSection-Bz1ZDJO5.js} +1 -1
- package/src/client/dist/spa/assets/{QMenu-D6uqosRg.js → QMenu-CMoolewZ.js} +1 -1
- package/src/client/dist/spa/assets/QRadio-4HnR_A-K.js +1 -0
- package/src/client/dist/spa/assets/{QTooltip-DUGPNNeQ.js → QTooltip-CbLXk2Bs.js} +1 -1
- package/src/client/dist/spa/assets/{SearchPage-C07dgzT9.js → SearchPage-CBSgEvVF.js} +1 -1
- package/src/client/dist/spa/assets/SettingsPage-C7TkcKXU.css +1 -0
- package/src/client/dist/spa/assets/SettingsPage-pY-zbPxn.js +9 -0
- package/src/client/dist/spa/assets/{TouchPan-DvVlszwO.js → TouchPan-DiBNjOPH.js} +1 -1
- package/src/client/dist/spa/assets/{WorkspacePage-CRIcsASQ.css → WorkspacePage-B4YnZ6re.css} +1 -1
- package/src/client/dist/spa/assets/WorkspacePage-BTHvQga-.js +4 -0
- package/src/client/dist/spa/assets/{build-path-tree-CCMckvpr.js → build-path-tree-BmBqRiCQ.js} +1 -1
- package/src/client/dist/spa/assets/{cssMode-D6XTTdwy.js → cssMode-ypFF7quM.js} +1 -1
- package/src/client/dist/spa/assets/{editor.api-6hDVHddO.js → editor.api-DtpZuH_B.js} +1 -1
- package/src/client/dist/spa/assets/{editor.main-DsLU1RWu.js → editor.main-C7a7L2WP.js} +3 -3
- package/src/client/dist/spa/assets/{AutoLoopChip-CkSzkC0C.js → engineFeatures-BxAOQcPU.js} +1 -1
- package/src/client/dist/spa/assets/{expand-template-Crz1uiBt.js → expand-template-GaEux9_o.js} +1 -1
- package/src/client/dist/spa/assets/{formatters-guwb-rzl.js → formatters-h0XBETG5.js} +1 -1
- package/src/client/dist/spa/assets/{freemarker2-Bn1f0t2U.js → freemarker2-DUBmhe3W.js} +1 -1
- package/src/client/dist/spa/assets/{handlebars-O92Cbq66.js → handlebars-_XEXkADl.js} +1 -1
- package/src/client/dist/spa/assets/{html-Ck95BMBU.js → html-D8gmyhgI.js} +1 -1
- package/src/client/dist/spa/assets/{htmlMode-DDYhH2FJ.js → htmlMode-B84S5YOM.js} +1 -1
- package/src/client/dist/spa/assets/i18n-DLoe3l25.js +1 -0
- package/src/client/dist/spa/assets/index-Dx_W9yYo.js +2 -0
- package/src/client/dist/spa/assets/{javascript-Cy2ddqHg.js → javascript-500DcdS9.js} +1 -1
- package/src/client/dist/spa/assets/{jsonMode-BIfVcp5z.js → jsonMode-DmrWg6b7.js} +1 -1
- package/src/client/dist/spa/assets/kobo-commands-DCoQW_NQ.js +9 -0
- package/src/client/dist/spa/assets/{liquid-B287eegh.js → liquid-CfPJszlt.js} +1 -1
- package/src/client/dist/spa/assets/{mdx-B8HSzGai.js → mdx-DtjLwENT.js} +1 -1
- package/src/client/dist/spa/assets/{monaco.contribution-CofcHzEf.js → monaco.contribution-CxiO5UJd.js} +2 -2
- package/src/client/dist/spa/assets/{notifications-BPnKFW60.js → notifications-CEyiPnmw.js} +1 -1
- package/src/client/dist/spa/assets/permissionModes-CPZlEHoF.js +1 -0
- package/src/client/dist/spa/assets/project-color-C4vMEn4C.js +1 -0
- package/src/client/dist/spa/assets/{purify.es-BCEwTYRx.js → purify.es-C92_EGvT.js} +1 -1
- package/src/client/dist/spa/assets/{python-csaKR6_U.js → python-BS46_AMt.js} +1 -1
- package/src/client/dist/spa/assets/{razor-C2wEv-nX.js → razor-Ce9zcIFo.js} +1 -1
- package/src/client/dist/spa/assets/{render-chat-markdown-Bjcei0vn.js → render-chat-markdown-BvJwlMiW.js} +1 -1
- package/src/client/dist/spa/assets/{tsMode-DGLVs57K.js → tsMode-Cr9FJjYY.js} +1 -1
- package/src/client/dist/spa/assets/{typescript-w0GWHzZ3.js → typescript-Ov3wChBg.js} +1 -1
- package/src/client/dist/spa/assets/{use-panel-CbJ44rqY.js → use-panel-lBh91vcW.js} +1 -1
- package/src/client/dist/spa/assets/{xml-CTn-vnEd.js → xml-euA4jBI1.js} +1 -1
- package/src/client/dist/spa/assets/{yaml-CTyUSvLZ.js → yaml-BuPSq_BT.js} +1 -1
- package/src/client/dist/spa/index.html +5 -5
- package/src/mcp-server/kobo-tasks-server.ts +27 -0
- package/src/client/dist/spa/assets/ActivityFeed-DlPVoOGb.js +0 -7
- package/src/client/dist/spa/assets/CreatePage-BoRappO3.css +0 -1
- package/src/client/dist/spa/assets/CreatePage-DpCVNwYk.js +0 -2
- package/src/client/dist/spa/assets/HealthPage-xZ0PP4F-.js +0 -1
- package/src/client/dist/spa/assets/MainLayout-DdkKM2ba.js +0 -37
- package/src/client/dist/spa/assets/MainLayout-drolsINz.css +0 -1
- package/src/client/dist/spa/assets/QChip-erWIZgxW.js +0 -1
- package/src/client/dist/spa/assets/QRadio-DJxOyOA3.js +0 -1
- package/src/client/dist/spa/assets/QTabPanels-ClPY9y4T.js +0 -1
- package/src/client/dist/spa/assets/SettingsPage-CLNmI0Rr.css +0 -1
- package/src/client/dist/spa/assets/SettingsPage-D0CZNqkA.js +0 -9
- package/src/client/dist/spa/assets/WorkspacePage-CKeCLPi0.js +0 -4
- package/src/client/dist/spa/assets/i18n-BLgknHpf.js +0 -1
- package/src/client/dist/spa/assets/index-CdHDdk1y.js +0 -2
- package/src/client/dist/spa/assets/kobo-commands-w8VepGvD.js +0 -11
- package/src/client/dist/spa/assets/models-Bd_v3W7Q.js +0 -1
- /package/src/client/dist/spa/assets/{QBtn-DEuWKHbR.js → QBtn-CaJSOyt8.js} +0 -0
- /package/src/client/dist/spa/assets/{vue-i18n-DI-gS-CC.js → vue-i18n-CKCtKE87.js} +0 -0
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
import { getPackageVersion } from '../../../../utils/paths.js';
|
|
2
|
+
import { CODEX_CAPABILITIES } from './capabilities.js';
|
|
3
|
+
import { createAppServerClient } from './client.js';
|
|
4
|
+
import { createMapperState, emitSessionStarted, handleAgentMessageDelta, handleItemCompleted, handleItemStarted, handleRateLimitsUpdated, handleTurnCompleted, QUOTA_PATTERN, tryEmitQuota, } from './event-mapper.js';
|
|
5
|
+
import { buildCodexOptions } from './options-builder.js';
|
|
6
|
+
import { buildResponseForResolve, handleServerRequest } from './server-requests.js';
|
|
7
|
+
import { spawnAppServer } from './spawn.js';
|
|
8
|
+
/**
|
|
9
|
+
* Heuristic for detecting a stale/expired thread id on `thread/resume`.
|
|
10
|
+
* Canonical wording isn't captured yet — when matched, the engine emits
|
|
11
|
+
* `error/resume_failed` so the orchestrator can restart with a fresh thread.
|
|
12
|
+
*/
|
|
13
|
+
export const RESUME_FAILED_PATTERN = /(thread\b.*\bnot found|session\b.*\bnot found|no\s+(such\s+)?thread|thread.*expired|conversation\b.*\bnot found|invalid\s+thread\s+id)/i;
|
|
14
|
+
export function createCodexEngine() {
|
|
15
|
+
return {
|
|
16
|
+
id: 'codex',
|
|
17
|
+
displayName: 'OpenAI Codex',
|
|
18
|
+
capabilities: CODEX_CAPABILITIES,
|
|
19
|
+
async start(options, onEvent) {
|
|
20
|
+
const { threadParams, input, isResume, collaborationMode } = buildCodexOptions({
|
|
21
|
+
prompt: options.prompt,
|
|
22
|
+
model: options.model,
|
|
23
|
+
effort: options.effort,
|
|
24
|
+
agentPermissionMode: options.agentPermissionMode ?? 'bypass',
|
|
25
|
+
resumeFromEngineSessionId: options.resumeFromEngineSessionId,
|
|
26
|
+
workingDir: options.workingDir,
|
|
27
|
+
mcpServers: options.mcpServers,
|
|
28
|
+
});
|
|
29
|
+
const mapperState = createMapperState();
|
|
30
|
+
const abortController = new AbortController();
|
|
31
|
+
const pendingByCallId = new Map();
|
|
32
|
+
let iteratorRunning = false;
|
|
33
|
+
let userInterrupted = false;
|
|
34
|
+
let discoveredSessionId = options.resumeFromEngineSessionId;
|
|
35
|
+
const safeEmit = (ev) => {
|
|
36
|
+
try {
|
|
37
|
+
onEvent(ev);
|
|
38
|
+
}
|
|
39
|
+
catch (err) {
|
|
40
|
+
console.error('[codex-engine] onEvent handler threw:', err);
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
const child = spawnAppServer({ cwd: options.workingDir, signal: abortController.signal });
|
|
44
|
+
if (child.stderr) {
|
|
45
|
+
child.stderr.setEncoding('utf8');
|
|
46
|
+
child.stderr.on('data', (chunk) => {
|
|
47
|
+
const text = chunk.toString();
|
|
48
|
+
if (QUOTA_PATTERN.test(text)) {
|
|
49
|
+
tryEmitQuota(mapperState, safeEmit, text.trim());
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
console.warn('[codex] stderr:', text.trimEnd());
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
let resolveTurnDone;
|
|
57
|
+
let rejectTurnDone;
|
|
58
|
+
const turnDonePromise = new Promise((resolve, reject) => {
|
|
59
|
+
resolveTurnDone = resolve;
|
|
60
|
+
rejectTurnDone = reject;
|
|
61
|
+
});
|
|
62
|
+
abortController.signal.addEventListener('abort', () => {
|
|
63
|
+
const err = new Error('AbortError');
|
|
64
|
+
err.name = 'AbortError';
|
|
65
|
+
rejectTurnDone(err);
|
|
66
|
+
});
|
|
67
|
+
const client = createAppServerClient({
|
|
68
|
+
stdin: child.stdin,
|
|
69
|
+
stdout: child.stdout,
|
|
70
|
+
clientInfo: { name: 'kobo', version: getPackageVersion() },
|
|
71
|
+
onNotification(method, params) {
|
|
72
|
+
// Ignored notifications — harmless bookkeeping by the server
|
|
73
|
+
if (method === 'mcpServer/startupStatus/updated' ||
|
|
74
|
+
method === 'thread/started' ||
|
|
75
|
+
method === 'thread/status/changed' ||
|
|
76
|
+
method === 'remoteControl/status/changed' ||
|
|
77
|
+
method === 'turn/started') {
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
if (method === 'item/started') {
|
|
81
|
+
const n = params;
|
|
82
|
+
for (const ev of handleItemStarted(n.item, mapperState))
|
|
83
|
+
safeEmit(ev);
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
if (method === 'item/completed') {
|
|
87
|
+
const n = params;
|
|
88
|
+
for (const ev of handleItemCompleted(n.item, mapperState))
|
|
89
|
+
safeEmit(ev);
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
if (method === 'item/agentMessage/delta') {
|
|
93
|
+
const n = params;
|
|
94
|
+
for (const ev of handleAgentMessageDelta(n, mapperState))
|
|
95
|
+
safeEmit(ev);
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
if (method === 'turn/completed') {
|
|
99
|
+
const n = params;
|
|
100
|
+
for (const ev of handleTurnCompleted(n, mapperState))
|
|
101
|
+
safeEmit(ev);
|
|
102
|
+
resolveTurnDone();
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
if (method === 'thread/tokenUsage/updated') {
|
|
106
|
+
const p = params;
|
|
107
|
+
if (p?.tokenUsage?.last) {
|
|
108
|
+
const last = p.tokenUsage.last;
|
|
109
|
+
safeEmit({
|
|
110
|
+
kind: 'usage',
|
|
111
|
+
inputTokens: last.inputTokens,
|
|
112
|
+
outputTokens: last.outputTokens + last.reasoningOutputTokens,
|
|
113
|
+
cacheRead: last.cachedInputTokens,
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
if (method === 'account/rateLimits/updated') {
|
|
119
|
+
for (const ev of handleRateLimitsUpdated(params, mapperState))
|
|
120
|
+
safeEmit(ev);
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
if (method === 'error') {
|
|
124
|
+
const n = params;
|
|
125
|
+
const msg = n?.message ?? 'unknown error';
|
|
126
|
+
if (QUOTA_PATTERN.test(msg)) {
|
|
127
|
+
tryEmitQuota(mapperState, safeEmit, msg);
|
|
128
|
+
}
|
|
129
|
+
else {
|
|
130
|
+
mapperState.sawErrorResult = true;
|
|
131
|
+
safeEmit({ kind: 'error', category: 'other', message: msg });
|
|
132
|
+
}
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
},
|
|
136
|
+
onServerRequest(id, method, params) {
|
|
137
|
+
handleServerRequest({
|
|
138
|
+
requestId: id,
|
|
139
|
+
method,
|
|
140
|
+
params,
|
|
141
|
+
emit: safeEmit,
|
|
142
|
+
register(callId, pending) {
|
|
143
|
+
pendingByCallId.set(callId, pending);
|
|
144
|
+
},
|
|
145
|
+
respondError: (reqId, code, message) => client.peer.respondError(reqId, code, message),
|
|
146
|
+
});
|
|
147
|
+
},
|
|
148
|
+
onError(err) {
|
|
149
|
+
console.error('[codex] JSON-RPC transport error:', err);
|
|
150
|
+
rejectTurnDone(err);
|
|
151
|
+
},
|
|
152
|
+
});
|
|
153
|
+
const iteratorPromise = (async () => {
|
|
154
|
+
iteratorRunning = true;
|
|
155
|
+
try {
|
|
156
|
+
await client.connect();
|
|
157
|
+
if (isResume && options.resumeFromEngineSessionId) {
|
|
158
|
+
await client.resumeThread({
|
|
159
|
+
threadId: options.resumeFromEngineSessionId,
|
|
160
|
+
cwd: options.workingDir,
|
|
161
|
+
persistExtendedHistory: false,
|
|
162
|
+
...(threadParams.model != null ? { model: threadParams.model } : {}),
|
|
163
|
+
...(threadParams.approvalPolicy != null ? { approvalPolicy: threadParams.approvalPolicy } : {}),
|
|
164
|
+
...(threadParams.sandbox != null ? { sandbox: threadParams.sandbox } : {}),
|
|
165
|
+
...(threadParams.modelReasoningEffort != null
|
|
166
|
+
? { modelReasoningEffort: threadParams.modelReasoningEffort }
|
|
167
|
+
: {}),
|
|
168
|
+
...(threadParams.config != null ? { config: threadParams.config } : {}),
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
else {
|
|
172
|
+
const startResp = await client.startThread(threadParams);
|
|
173
|
+
discoveredSessionId = startResp.thread.id;
|
|
174
|
+
}
|
|
175
|
+
for (const ev of emitSessionStarted(discoveredSessionId, mapperState))
|
|
176
|
+
safeEmit(ev);
|
|
177
|
+
// collaborationMode is sticky server-side — always send it explicitly,
|
|
178
|
+
// never omit (would leave a Bypass turn stuck in a previous Plan mode).
|
|
179
|
+
await client.startTurn({
|
|
180
|
+
threadId: discoveredSessionId,
|
|
181
|
+
input,
|
|
182
|
+
collaborationMode,
|
|
183
|
+
});
|
|
184
|
+
await turnDonePromise;
|
|
185
|
+
const reason = mapperState.sawErrorResult
|
|
186
|
+
? 'error'
|
|
187
|
+
: mapperState.sawTurnInterrupted
|
|
188
|
+
? 'killed'
|
|
189
|
+
: 'completed';
|
|
190
|
+
safeEmit({
|
|
191
|
+
kind: 'session:ended',
|
|
192
|
+
reason,
|
|
193
|
+
exitCode: reason === 'completed' ? 0 : null,
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
catch (err) {
|
|
197
|
+
const error = err;
|
|
198
|
+
const message = error.message ?? String(err);
|
|
199
|
+
const isAbort = userInterrupted || error.name === 'AbortError' || abortController.signal.aborted;
|
|
200
|
+
const isResumeAttempt = options.resumeFromEngineSessionId !== undefined;
|
|
201
|
+
if (isAbort) {
|
|
202
|
+
safeEmit({ kind: 'session:ended', reason: 'killed', exitCode: null });
|
|
203
|
+
}
|
|
204
|
+
else if (QUOTA_PATTERN.test(message)) {
|
|
205
|
+
tryEmitQuota(mapperState, safeEmit, message);
|
|
206
|
+
safeEmit({ kind: 'session:ended', reason: 'error', exitCode: null });
|
|
207
|
+
}
|
|
208
|
+
else if (isResumeAttempt && RESUME_FAILED_PATTERN.test(message)) {
|
|
209
|
+
safeEmit({ kind: 'error', category: 'resume_failed', message });
|
|
210
|
+
safeEmit({ kind: 'session:ended', reason: 'error', exitCode: null });
|
|
211
|
+
}
|
|
212
|
+
else {
|
|
213
|
+
safeEmit({ kind: 'error', category: 'spawn_failed', message });
|
|
214
|
+
safeEmit({ kind: 'session:ended', reason: 'error', exitCode: null });
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
finally {
|
|
218
|
+
iteratorRunning = false;
|
|
219
|
+
client.close();
|
|
220
|
+
try {
|
|
221
|
+
child.kill('SIGTERM');
|
|
222
|
+
}
|
|
223
|
+
catch {
|
|
224
|
+
// best-effort
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
})();
|
|
228
|
+
const engineProcess = {
|
|
229
|
+
get pid() {
|
|
230
|
+
return child.pid;
|
|
231
|
+
},
|
|
232
|
+
get engineSessionId() {
|
|
233
|
+
return discoveredSessionId;
|
|
234
|
+
},
|
|
235
|
+
isAlive() {
|
|
236
|
+
return iteratorRunning;
|
|
237
|
+
},
|
|
238
|
+
sendMessage() {
|
|
239
|
+
throw new Error('sendMessage not supported in Codex app-server single-shot mode');
|
|
240
|
+
},
|
|
241
|
+
interrupt() {
|
|
242
|
+
userInterrupted = true;
|
|
243
|
+
abortController.abort();
|
|
244
|
+
if (discoveredSessionId) {
|
|
245
|
+
client.interruptTurn({ threadId: discoveredSessionId }).catch(() => { });
|
|
246
|
+
}
|
|
247
|
+
},
|
|
248
|
+
async stop() {
|
|
249
|
+
abortController.abort();
|
|
250
|
+
try {
|
|
251
|
+
await iteratorPromise;
|
|
252
|
+
}
|
|
253
|
+
catch {
|
|
254
|
+
// swallow — best effort
|
|
255
|
+
}
|
|
256
|
+
try {
|
|
257
|
+
child.stdin?.end();
|
|
258
|
+
}
|
|
259
|
+
catch {
|
|
260
|
+
// swallow
|
|
261
|
+
}
|
|
262
|
+
},
|
|
263
|
+
resolvePendingUserInput(callId, response) {
|
|
264
|
+
const pending = pendingByCallId.get(callId);
|
|
265
|
+
if (!pending)
|
|
266
|
+
return false;
|
|
267
|
+
pendingByCallId.delete(callId);
|
|
268
|
+
const result = buildResponseForResolve(pending, response);
|
|
269
|
+
client.peer.respond(pending.requestId, result);
|
|
270
|
+
return true;
|
|
271
|
+
},
|
|
272
|
+
};
|
|
273
|
+
return engineProcess;
|
|
274
|
+
},
|
|
275
|
+
};
|
|
276
|
+
}
|