cli-jaw 2.17.26 → 2.17.27
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/dist/src/core/config.js +23 -1
- package/dist/src/core/config.js.map +1 -1
- package/dist/src/core/db.js +188 -0
- package/dist/src/core/db.js.map +1 -1
- package/dist/src/memory/heartbeat-mention-watch.js +14 -22
- package/dist/src/memory/heartbeat-mention-watch.js.map +1 -1
- package/dist/src/memory/heartbeat.js +47 -1
- package/dist/src/memory/heartbeat.js.map +1 -1
- package/dist/src/memory/legacy-mention-watch-quarantine.js +93 -0
- package/dist/src/memory/legacy-mention-watch-quarantine.js.map +1 -0
- package/dist/src/memory/mention-watch-ledger.js +61 -0
- package/dist/src/memory/mention-watch-ledger.js.map +1 -0
- package/dist/src/messaging/send.js +30 -3
- package/dist/src/messaging/send.js.map +1 -1
- package/dist/src/routes/heartbeat.js +154 -1
- package/dist/src/routes/heartbeat.js.map +1 -1
- package/dist/src/slack/send-only-client.js +20 -0
- package/dist/src/slack/send-only-client.js.map +1 -1
- package/dist/src/slack/verified-workspace.js +45 -0
- package/dist/src/slack/verified-workspace.js.map +1 -0
- package/package.json +1 -1
- package/public/dist/assets/app-DUwWnKh3.js +55 -0
- package/public/dist/index.html +1 -1
- package/public/js/features/heartbeat.ts +14 -2
- package/public/dist/assets/app-DhDdCs_s.js +0 -55
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
import { loadHeartbeatFile, saveHeartbeatFile, isHeartbeatDestination, isHeartbeatMentionWatch } from '../core/config.js';
|
|
1
|
+
import { loadHeartbeatFile, saveHeartbeatFile, isHeartbeatDestination, isHeartbeatMentionWatch, settings } from '../core/config.js';
|
|
2
2
|
import { startHeartbeat } from '../memory/heartbeat.js';
|
|
3
3
|
import { validateHeartbeatScheduleInput } from '../memory/heartbeat-schedule.js';
|
|
4
|
+
import { approveLegacyFreshStart, quarantineState, detectLegacyMentionWatch } from '../memory/legacy-mention-watch-quarantine.js';
|
|
5
|
+
import { verifiedSlackWorkspace } from '../slack/verified-workspace.js';
|
|
4
6
|
import { getEmployees } from '../core/db.js';
|
|
5
7
|
import { stripUndefined } from '../core/strip-undefined.js';
|
|
6
8
|
/** Resolve the destination a PUT should persist.
|
|
@@ -81,6 +83,7 @@ export function registerHeartbeatRoutes(app, requireAuth) {
|
|
|
81
83
|
const existingById = new Map(loadHeartbeatFile().jobs.filter(job => job.id).map(job => [job.id, job]));
|
|
82
84
|
const employeeNames = new Set(getEmployees.all().map(employee => employee.name));
|
|
83
85
|
const idPrefix = `hb_${Date.now()}`;
|
|
86
|
+
const seenIds = new Set();
|
|
84
87
|
for (const [index, rawJob] of data.jobs.entries()) {
|
|
85
88
|
const job = (rawJob && typeof rawJob === 'object') ? rawJob : {};
|
|
86
89
|
const scheduleResult = validateHeartbeatScheduleInput(job["schedule"]);
|
|
@@ -97,6 +100,15 @@ export function registerHeartbeatRoutes(app, requireAuth) {
|
|
|
97
100
|
});
|
|
98
101
|
return;
|
|
99
102
|
}
|
|
103
|
+
// Two jobs under one id would share a mention-watch ledger namespace,
|
|
104
|
+
// so the second one inherits the first one's cursor and skips every
|
|
105
|
+
// message below it. Rejected rather than de-duplicated: silently
|
|
106
|
+
// dropping one of them loses a job the operator just asked to save.
|
|
107
|
+
if (seenIds.has(jobId)) {
|
|
108
|
+
res.status(400).json({ error: 'duplicate heartbeat job id', index, jobId });
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
seenIds.add(jobId);
|
|
100
112
|
const existing = existingById.get(jobId);
|
|
101
113
|
const runnerResult = normalizeHeartbeatPutRunnerFields(job, existing, employeeNames);
|
|
102
114
|
if (!runnerResult.ok) {
|
|
@@ -129,5 +141,146 @@ export function registerHeartbeatRoutes(app, requireAuth) {
|
|
|
129
141
|
startHeartbeat();
|
|
130
142
|
res.json(payload);
|
|
131
143
|
});
|
|
144
|
+
// Read the hold, so an operator can tell a held job from a broken one. The
|
|
145
|
+
// scheduler refuses a quarantined job on every tick and says why in the log,
|
|
146
|
+
// but a log line is not something the dashboard can show.
|
|
147
|
+
//
|
|
148
|
+
// Detection runs here rather than being assumed from startup. `startHeartbeat`
|
|
149
|
+
// is called after the server is already listening, so a request arriving in
|
|
150
|
+
// that window would find v1 rows with no marker yet and be told the job is
|
|
151
|
+
// fine. It is INSERT OR IGNORE, so calling it again is free.
|
|
152
|
+
app.get('/api/heartbeat/:jobId/mention-watch-hold', requireAuth, (req, res) => {
|
|
153
|
+
const jobId = String(req.params['jobId'] ?? '').trim();
|
|
154
|
+
if (!jobId) {
|
|
155
|
+
res.status(400).json({ error: 'jobId required' });
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
detectLegacyMentionWatch(Date.now());
|
|
159
|
+
const state = quarantineState(jobId);
|
|
160
|
+
res.json({ jobId, held: state?.status === 'pending', state });
|
|
161
|
+
});
|
|
162
|
+
// Release a held job with a NEW floor.
|
|
163
|
+
//
|
|
164
|
+
// A plain `enabled: true` PUT is deliberately not accepted as the approval:
|
|
165
|
+
// every shipped UI rebuilds a job from a fixed field set and omits
|
|
166
|
+
// `mentionWatch` entirely, so reading a save click as consent would let any
|
|
167
|
+
// unrelated edit lift the hold and replay the backlog.
|
|
168
|
+
//
|
|
169
|
+
// The order below is the crash-safety argument and is not interchangeable.
|
|
170
|
+
// `since` lives in heartbeat.json and the hold lives in SQLite, so the two
|
|
171
|
+
// cannot share a transaction. Writing the file first means a crash before the
|
|
172
|
+
// database step leaves the new floor saved and the job still held, which a
|
|
173
|
+
// retry fixes. The reverse lifts the hold while the OLD floor is still live.
|
|
174
|
+
app.post('/api/heartbeat/:jobId/mention-watch-fresh-start', requireAuth, async (req, res) => {
|
|
175
|
+
const jobId = String(req.params['jobId'] ?? '').trim();
|
|
176
|
+
if (!jobId) {
|
|
177
|
+
res.status(400).json({ error: 'jobId required' });
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
const since = String(req.body?.['since'] ?? '').trim();
|
|
181
|
+
// An empty floor is what makes this dangerous: the watch would walk
|
|
182
|
+
// backward through all reachable history and answer it again.
|
|
183
|
+
if (!since) {
|
|
184
|
+
res.status(400).json({ error: 'since required to restart a held mention watch', jobId });
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
// The ONE await comes first, before anything is read.
|
|
188
|
+
//
|
|
189
|
+
// Verification needs the network, and every decision after it reads state
|
|
190
|
+
// that a concurrent request can change. Snapshotting the hold and the file
|
|
191
|
+
// and THEN awaiting is what lets a losing approval resume with a stale
|
|
192
|
+
// whole-file copy and write its floor over the winner's — the DB tells it
|
|
193
|
+
// 'conflict' only after the file damage is already done. Doing the await
|
|
194
|
+
// up front leaves everything below it synchronous, so Node's single thread
|
|
195
|
+
// is the mutual exclusion.
|
|
196
|
+
//
|
|
197
|
+
// The workspace belongs in the record because the ledger is keyed by it: an
|
|
198
|
+
// approval granted while the token pointed at workspace A is otherwise
|
|
199
|
+
// indistinguishable from one granted under B, and the v2 rows the job goes
|
|
200
|
+
// on to write land in a namespace the operator was not looking at. Failing
|
|
201
|
+
// verification is a refusal, not a default.
|
|
202
|
+
const readBotToken = () => String(settings['slack']?.['botToken'] ?? '').trim();
|
|
203
|
+
const token = readBotToken();
|
|
204
|
+
const verified = token ? await verifiedSlackWorkspace(token) : null;
|
|
205
|
+
if (!verified) {
|
|
206
|
+
res.status(409).json({
|
|
207
|
+
error: 'cannot verify the Slack workspace for this token; approving would record a guessed namespace',
|
|
208
|
+
jobId,
|
|
209
|
+
});
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
// A settings write during that await can have swapped the token. The
|
|
213
|
+
// verified team id then describes the OLD credential while the job the
|
|
214
|
+
// approval is about to release runs under the new one — the recorded
|
|
215
|
+
// provenance and the namespace actually written would disagree, which is
|
|
216
|
+
// the exact confusion recording the workspace exists to prevent.
|
|
217
|
+
if (readBotToken() !== token) {
|
|
218
|
+
res.status(409).json({
|
|
219
|
+
error: 'the Slack bot token changed while verifying; retry so the approval records the workspace it will actually run under',
|
|
220
|
+
jobId,
|
|
221
|
+
});
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
// Everything from here down runs without yielding.
|
|
225
|
+
//
|
|
226
|
+
// Same startup-window reason as the GET: without this, a legacy job whose
|
|
227
|
+
// marker has not been written yet reads as 'never held' and 404s.
|
|
228
|
+
detectLegacyMentionWatch(Date.now());
|
|
229
|
+
const state = quarantineState(jobId);
|
|
230
|
+
if (!state) {
|
|
231
|
+
res.status(404).json({ error: 'no mention-watch hold for this job', jobId });
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
const file = loadHeartbeatFile();
|
|
235
|
+
const job = file.jobs.find(candidate => candidate.id === jobId);
|
|
236
|
+
if (!job?.mentionWatch) {
|
|
237
|
+
res.status(400).json({ error: 'job has no mention watch to restart', jobId });
|
|
238
|
+
return;
|
|
239
|
+
}
|
|
240
|
+
const resolution = JSON.stringify({ since, userId: job.mentionWatch.userId, workspaceId: verified.teamId });
|
|
241
|
+
// Already resolved with the same decision is the caller retrying after a
|
|
242
|
+
// lost response; a different one is a second, conflicting decision.
|
|
243
|
+
if (state.status === 'resolved') {
|
|
244
|
+
const outcome = approveLegacyFreshStart(jobId, resolution, Date.now());
|
|
245
|
+
if (outcome === 'conflict') {
|
|
246
|
+
res.status(409).json({ error: 'this hold was already cleared with a different floor', jobId, state });
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
249
|
+
// The recorded decision matching is not enough. The floor lives in the
|
|
250
|
+
// file, and an edit after the approval can have moved it — reporting
|
|
251
|
+
// this floor as in force while another one governs the scan is the one
|
|
252
|
+
// wrong answer available here. Rewriting silently is worse: it would
|
|
253
|
+
// undo a later deliberate change.
|
|
254
|
+
if ((job.mentionWatch.since ?? '') !== since) {
|
|
255
|
+
res.status(409).json({
|
|
256
|
+
error: 'the persisted floor no longer matches this approval',
|
|
257
|
+
jobId,
|
|
258
|
+
approvedSince: since,
|
|
259
|
+
persistedSince: job.mentionWatch.since ?? null,
|
|
260
|
+
});
|
|
261
|
+
return;
|
|
262
|
+
}
|
|
263
|
+
res.json({ jobId, outcome, since });
|
|
264
|
+
return;
|
|
265
|
+
}
|
|
266
|
+
const updated = file.jobs.map(candidate => (candidate.id === jobId
|
|
267
|
+
? { ...candidate, mentionWatch: { ...job.mentionWatch, since } }
|
|
268
|
+
: candidate));
|
|
269
|
+
// Step 1: the file, and only past this line is the new floor durable.
|
|
270
|
+
saveHeartbeatFile({ jobs: updated });
|
|
271
|
+
// Step 2: claim the hold, then archive and delete the v1 rows, as one unit.
|
|
272
|
+
const outcome = approveLegacyFreshStart(jobId, resolution, Date.now());
|
|
273
|
+
if (outcome === 'conflict') {
|
|
274
|
+
res.status(409).json({ error: 'this hold was already cleared with a different floor', jobId, state });
|
|
275
|
+
return;
|
|
276
|
+
}
|
|
277
|
+
if (outcome === 'not-pending') {
|
|
278
|
+
res.status(409).json({ error: 'the hold changed while restarting; retry', jobId });
|
|
279
|
+
return;
|
|
280
|
+
}
|
|
281
|
+
// Step 3: only now can the job be scheduled again.
|
|
282
|
+
startHeartbeat();
|
|
283
|
+
res.json({ jobId, outcome, since });
|
|
284
|
+
});
|
|
132
285
|
}
|
|
133
286
|
//# sourceMappingURL=heartbeat.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"heartbeat.js","sourceRoot":"","sources":["../../../src/routes/heartbeat.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"heartbeat.js","sourceRoot":"","sources":["../../../src/routes/heartbeat.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,sBAAsB,EAAE,uBAAuB,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAEpI,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,EAAE,8BAA8B,EAAE,MAAM,iCAAiC,CAAC;AACjF,OAAO,EAAE,uBAAuB,EAAE,eAAe,EAAE,wBAAwB,EAAE,MAAM,8CAA8C,CAAC;AAClI,OAAO,EAAE,sBAAsB,EAAE,MAAM,gCAAgC,CAAC;AACxE,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAE7C,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAK5D;;;;;;;;;gEASgE;AAChE,MAAM,UAAU,2BAA2B,CACvC,GAA4B,EAC5B,QAAiD;IAEjD,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,GAAG,EAAE,aAAa,CAAC,EAAE,CAAC;QAC5D,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,QAAQ,IAAI,SAAS,EAAE,CAAC;IAC5D,CAAC;IACD,MAAM,GAAG,GAAG,GAAG,CAAC,aAAa,CAAC,CAAC;IAC/B,IAAI,GAAG,KAAK,IAAI;QAAE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,SAAS,EAAE,CAAC;IAC9D,IAAI,CAAC,sBAAsB,CAAC,GAAG,CAAC;QAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,+BAA+B,EAAE,CAAC;IAC/F,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,GAAG,EAAE,CAAC;AAC1C,CAAC;AAED;;;;;;;;;0DAS0D;AAC1D,MAAM,UAAU,4BAA4B,CACxC,GAA4B,EAC5B,QAAkD;IAElD,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,GAAG,EAAE,cAAc,CAAC,EAAE,CAAC;QAC7D,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE,QAAQ,IAAI,SAAS,EAAE,CAAC;IAC7D,CAAC;IACD,MAAM,GAAG,GAAG,GAAG,CAAC,cAAc,CAAC,CAAC;IAChC,IAAI,GAAG,KAAK,IAAI;QAAE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE,SAAS,EAAE,CAAC;IAC/D,IAAI,CAAC,uBAAuB,CAAC,GAAG,CAAC;QAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,iCAAiC,EAAE,CAAC;IAClG,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE,GAAG,EAAE,CAAC;AAC3C,CAAC;AAED,MAAM,UAAU,iCAAiC,CAC7C,GAA4B,EAC5B,QAAkC,EAClC,aAAkC;IAElC,MAAM,SAAS,GAAG,CAAC,GAAuB,EAAW,EAAE,CACnD,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,CAAC;IAChF,MAAM,WAAW,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC;IACxC,MAAM,MAAM,GAAG,WAAW,IAAI,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC;IAC7D,MAAM,QAAQ,GAAG,SAAS,CAAC,UAAU,CAAC,CAAC;IACvC,MAAM,OAAO,GAAG,SAAS,CAAC,SAAS,CAAC,CAAC;IACrC,MAAM,YAAY,GAAG,SAAS,CAAC,cAAc,CAAC,CAAC;IAC/C,IAAI,MAAM,KAAK,SAAS,IAAI,MAAM,KAAK,MAAM,IAAI,MAAM,KAAK,UAAU,IAAI,MAAM,KAAK,QAAQ;QAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,0BAA0B,EAAE,CAAC;IACvJ,IAAI,MAAM,KAAK,UAAU,IAAI,CAAC,OAAO,QAAQ,KAAK,QAAQ,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,4BAA4B,EAAE,CAAC;IACvJ,IAAI,MAAM,KAAK,QAAQ,IAAI,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;QAClJ,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,0CAA0C,EAAE,CAAC;IAC5E,CAAC;IACD,IAAI,YAAY,KAAK,SAAS,IAAI,YAAY,KAAK,IAAI,IAAI,YAAY,KAAK,QAAQ,IAAI,YAAY,KAAK,cAAc,IAAI,YAAY,KAAK,QAAQ,EAAE,CAAC;QACnJ,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,iCAAiC,EAAE,CAAC;IACnE,CAAC;IACD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,cAAc,CAAC;YACtC,MAAM,EAAE,MAAM,IAAI,SAAS;YAC3B,QAAQ,EAAE,QAAQ,IAAI,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,QAAkB;YAC3D,OAAO,EAAE,OAAO,IAAI,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,OAAmB;YAC1D,YAAY,EAAE,YAAY,IAAI,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,YAA4C;SAChG,CAAC,EAAE,CAAC;AACT,CAAC;AAED,MAAM,UAAU,uBAAuB,CAAC,GAAY,EAAE,WAA2B;IAC7E,GAAG,CAAC,GAAG,CAAC,gBAAgB,EAAE,WAAW,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,iBAAiB,EAAE,CAAC,CAAC,CAAC;IAErF,GAAG,CAAC,GAAG,CAAC,gBAAgB,EAAE,WAAW,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;QAChD,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,CAAC;QACtB,IAAI,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YACrC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,qBAAqB,EAAE,CAAC,CAAC;YACvD,OAAO;QACX,CAAC;QACD,MAAM,cAAc,GAAG,EAAE,CAAC;QAC1B,MAAM,YAAY,GAAG,IAAI,GAAG,CAAC,iBAAiB,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC;QACvG,MAAM,aAAa,GAAG,IAAI,GAAG,CAAE,YAAY,CAAC,GAAG,EAAoB,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC;QACpG,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;QACpC,MAAM,OAAO,GAAG,IAAI,GAAG,EAAU,CAAC;QAClC,KAAK,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,CAAC;YAChD,MAAM,GAAG,GAAG,CAAC,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,MAAiC,CAAC,CAAC,CAAC,EAAE,CAAC;YAC5F,MAAM,cAAc,GAAG,8BAA8B,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC;YACvE,MAAM,KAAK,GAAG,OAAO,GAAG,CAAC,IAAI,CAAC,KAAK,QAAQ,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE;gBAC3D,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE;gBAClB,CAAC,CAAC,GAAG,QAAQ,IAAI,KAAK,EAAE,CAAC;YAC7B,IAAI,CAAC,cAAc,CAAC,EAAE,EAAE,CAAC;gBACrB,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;oBACjB,KAAK,EAAE,4BAA4B;oBACnC,IAAI,EAAE,cAAc,CAAC,IAAI;oBACzB,MAAM,EAAE,cAAc,CAAC,KAAK;oBAC5B,KAAK;oBACL,KAAK;iBACR,CAAC,CAAC;gBACH,OAAO;YACX,CAAC;YACD,sEAAsE;YACtE,oEAAoE;YACpE,iEAAiE;YACjE,oEAAoE;YACpE,IAAI,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;gBACrB,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,4BAA4B,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;gBAC5E,OAAO;YACX,CAAC;YACD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;YACnB,MAAM,QAAQ,GAAG,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;YACzC,MAAM,YAAY,GAAG,iCAAiC,CAAC,GAAG,EAAE,QAAQ,EAAE,aAAa,CAAC,CAAC;YACrF,IAAI,CAAC,YAAY,CAAC,EAAE,EAAE,CAAC;gBAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,YAAY,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;gBAAC,OAAO;YAAC,CAAC;YACpG,MAAM,UAAU,GAAG,2BAA2B,CAAC,GAAG,EAAE,QAAQ,EAAE,WAAW,CAAC,CAAC;YAC3E,IAAI,CAAC,UAAU,CAAC,EAAE,EAAE,CAAC;gBAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,UAAU,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;gBAAC,OAAO;YAAC,CAAC;YAChG,MAAM,WAAW,GAAG,4BAA4B,CAAC,GAAG,EAAE,QAAQ,EAAE,YAAY,CAAC,CAAC;YAC9E,IAAI,CAAC,WAAW,CAAC,EAAE,EAAE,CAAC;gBAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,WAAW,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;gBAAC,OAAO;YAAC,CAAC;YAClG,cAAc,CAAC,IAAI,CAAC,cAAc,CAAC;gBAC/B,EAAE,EAAE,KAAK;gBACT,IAAI,EAAE,OAAO,GAAG,CAAC,MAAM,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE;gBACxD,OAAO,EAAE,GAAG,CAAC,SAAS,CAAC,KAAK,KAAK;gBACjC,QAAQ,EAAE,cAAc,CAAC,QAAQ;gBACjC,MAAM,EAAE,OAAO,GAAG,CAAC,QAAQ,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE;gBAC9D,GAAG,YAAY,CAAC,MAAM;gBACtB,WAAW,EAAE,UAAU,CAAC,WAAW;gBACnC,YAAY,EAAE,WAAW,CAAC,YAAY;aACzC,CAAC,CAAC,CAAC;QACR,CAAC;QACD,MAAM,OAAO,GAAG,EAAE,IAAI,EAAE,cAAc,EAAE,CAAC;QACzC,iBAAiB,CAAC,OAAO,CAAC,CAAC;QAC3B,cAAc,EAAE,CAAC;QACjB,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACtB,CAAC,CAAC,CAAC;IAEH,2EAA2E;IAC3E,6EAA6E;IAC7E,0DAA0D;IAC1D,EAAE;IACF,+EAA+E;IAC/E,4EAA4E;IAC5E,2EAA2E;IAC3E,6DAA6D;IAC7D,GAAG,CAAC,GAAG,CAAC,0CAA0C,EAAE,WAAW,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;QAC1E,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QACvD,IAAI,CAAC,KAAK,EAAE,CAAC;YAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,gBAAgB,EAAE,CAAC,CAAC;YAAC,OAAO;QAAC,CAAC;QAC1E,wBAAwB,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;QACrC,MAAM,KAAK,GAAG,eAAe,CAAC,KAAK,CAAC,CAAC;QACrC,GAAG,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,KAAK,SAAS,EAAE,KAAK,EAAE,CAAC,CAAC;IAClE,CAAC,CAAC,CAAC;IAEH,uCAAuC;IACvC,EAAE;IACF,4EAA4E;IAC5E,mEAAmE;IACnE,4EAA4E;IAC5E,uDAAuD;IACvD,EAAE;IACF,2EAA2E;IAC3E,2EAA2E;IAC3E,8EAA8E;IAC9E,2EAA2E;IAC3E,6EAA6E;IAC7E,GAAG,CAAC,IAAI,CAAC,iDAAiD,EAAE,WAAW,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE;QACxF,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QACvD,IAAI,CAAC,KAAK,EAAE,CAAC;YAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,gBAAgB,EAAE,CAAC,CAAC;YAAC,OAAO;QAAC,CAAC;QAC1E,MAAM,KAAK,GAAG,MAAM,CAAE,GAAG,CAAC,IAA4C,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QAChG,oEAAoE;QACpE,8DAA8D;QAC9D,IAAI,CAAC,KAAK,EAAE,CAAC;YAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,gDAAgD,EAAE,KAAK,EAAE,CAAC,CAAC;YAAC,OAAO;QAAC,CAAC;QAEjH,sDAAsD;QACtD,EAAE;QACF,0EAA0E;QAC1E,2EAA2E;QAC3E,uEAAuE;QACvE,0EAA0E;QAC1E,yEAAyE;QACzE,2EAA2E;QAC3E,2BAA2B;QAC3B,EAAE;QACF,4EAA4E;QAC5E,uEAAuE;QACvE,2EAA2E;QAC3E,2EAA2E;QAC3E,4CAA4C;QAC5C,MAAM,YAAY,GAAG,GAAW,EAAE,CAC9B,MAAM,CAAE,QAAQ,CAAC,OAAO,CAAyC,EAAE,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QAClG,MAAM,KAAK,GAAG,YAAY,EAAE,CAAC;QAC7B,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,CAAC,MAAM,sBAAsB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QACpE,IAAI,CAAC,QAAQ,EAAE,CAAC;YACZ,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;gBACjB,KAAK,EAAE,8FAA8F;gBACrG,KAAK;aACR,CAAC,CAAC;YACH,OAAO;QACX,CAAC;QACD,qEAAqE;QACrE,uEAAuE;QACvE,qEAAqE;QACrE,yEAAyE;QACzE,iEAAiE;QACjE,IAAI,YAAY,EAAE,KAAK,KAAK,EAAE,CAAC;YAC3B,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;gBACjB,KAAK,EAAE,qHAAqH;gBAC5H,KAAK;aACR,CAAC,CAAC;YACH,OAAO;QACX,CAAC;QAED,mDAAmD;QACnD,EAAE;QACF,0EAA0E;QAC1E,kEAAkE;QAClE,wBAAwB,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;QACrC,MAAM,KAAK,GAAG,eAAe,CAAC,KAAK,CAAC,CAAC;QACrC,IAAI,CAAC,KAAK,EAAE,CAAC;YAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,oCAAoC,EAAE,KAAK,EAAE,CAAC,CAAC;YAAC,OAAO;QAAC,CAAC;QAErG,MAAM,IAAI,GAAG,iBAAiB,EAAE,CAAC;QACjC,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,SAAS,CAAC,EAAE,KAAK,KAAK,CAAC,CAAC;QAChE,IAAI,CAAC,GAAG,EAAE,YAAY,EAAE,CAAC;YACrB,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,qCAAqC,EAAE,KAAK,EAAE,CAAC,CAAC;YAC9E,OAAO;QACX,CAAC;QAED,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,CAAC,YAAY,CAAC,MAAM,EAAE,WAAW,EAAE,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;QAC5G,yEAAyE;QACzE,oEAAoE;QACpE,IAAI,KAAK,CAAC,MAAM,KAAK,UAAU,EAAE,CAAC;YAC9B,MAAM,OAAO,GAAG,uBAAuB,CAAC,KAAK,EAAE,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;YACvE,IAAI,OAAO,KAAK,UAAU,EAAE,CAAC;gBACzB,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,sDAAsD,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;gBACtG,OAAO;YACX,CAAC;YACD,uEAAuE;YACvE,qEAAqE;YACrE,uEAAuE;YACvE,qEAAqE;YACrE,kCAAkC;YAClC,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC,KAAK,IAAI,EAAE,CAAC,KAAK,KAAK,EAAE,CAAC;gBAC3C,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;oBACjB,KAAK,EAAE,qDAAqD;oBAC5D,KAAK;oBACL,aAAa,EAAE,KAAK;oBACpB,cAAc,EAAE,GAAG,CAAC,YAAY,CAAC,KAAK,IAAI,IAAI;iBACjD,CAAC,CAAC;gBACH,OAAO;YACX,CAAC;YACD,GAAG,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;YACpC,OAAO;QACX,CAAC;QAED,MAAM,OAAO,GAAmB,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,SAAS,CAAC,EAAE,KAAK,KAAK;YAC9E,CAAC,CAAC,EAAE,GAAG,SAAS,EAAE,YAAY,EAAE,EAAE,GAAG,GAAG,CAAC,YAAa,EAAE,KAAK,EAAE,EAAE;YACjE,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC;QAClB,sEAAsE;QACtE,iBAAiB,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;QACrC,4EAA4E;QAC5E,MAAM,OAAO,GAAG,uBAAuB,CAAC,KAAK,EAAE,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;QACvE,IAAI,OAAO,KAAK,UAAU,EAAE,CAAC;YACzB,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,sDAAsD,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;YACtG,OAAO;QACX,CAAC;QACD,IAAI,OAAO,KAAK,aAAa,EAAE,CAAC;YAC5B,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,0CAA0C,EAAE,KAAK,EAAE,CAAC,CAAC;YACnF,OAAO;QACX,CAAC;QACD,mDAAmD;QACnD,cAAc,EAAE,CAAC;QACjB,GAAG,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;IACxC,CAAC,CAAC,CAAC;AACP,CAAC"}
|
|
@@ -7,6 +7,7 @@ import { abortableDelay } from '../messaging/outbound-lifecycle.js';
|
|
|
7
7
|
import { chunkSlackMessage, toMrkdwn } from './format.js';
|
|
8
8
|
import { MAX_INLINE_RATE_LIMIT_MS, classifySendFailure, retryAfterMs } from '../messaging/retry.js';
|
|
9
9
|
import { redactOutboundPayload } from '../messaging/redact.js';
|
|
10
|
+
import { log } from '../core/logger.js';
|
|
10
11
|
export function invalidateSlackSendClient() {
|
|
11
12
|
// no-op: the token is read fresh from settings on every call.
|
|
12
13
|
// Present so runtime-settings.ts can invalidate symmetrically with Discord.
|
|
@@ -107,6 +108,25 @@ export async function sendSlackText(token, target, text, options = {}) {
|
|
|
107
108
|
return slackFailure(describeSlackError(result.error, result.data), result.status, result.retryAfterMs, result.grantedScopes);
|
|
108
109
|
}
|
|
109
110
|
}
|
|
111
|
+
// Recorded HERE, not only at `sendChannelOutput`, because most Slack posts
|
|
112
|
+
// never pass through that choke point: the dispatch settle path, the queued
|
|
113
|
+
// reply, the recovered-queue forwarder, and the generic forwarder all call
|
|
114
|
+
// this transport directly. Instrumenting only the choke point left those
|
|
115
|
+
// invisible — which is precisely the set a 'did one turn answer twice' audit
|
|
116
|
+
// needs, so a census over the other record could look complete while missing
|
|
117
|
+
// them.
|
|
118
|
+
//
|
|
119
|
+
// `chunks` matters: one logical answer over the Slack length limit becomes
|
|
120
|
+
// several posts, and counting posts instead of sends would read a long answer
|
|
121
|
+
// as a duplicate.
|
|
122
|
+
//
|
|
123
|
+
// No body, same reason as elsewhere: destination and shape, never the words.
|
|
124
|
+
log.event('slack.post', {
|
|
125
|
+
target: target.targetId,
|
|
126
|
+
...(target.threadId ? { threaded: true } : {}),
|
|
127
|
+
chunks: chunks.length,
|
|
128
|
+
result: 'ok',
|
|
129
|
+
});
|
|
110
130
|
// exactOptionalPropertyTypes: omit the key rather than sending undefined.
|
|
111
131
|
return firstTs ? { ok: true, ts: firstTs } : { ok: true };
|
|
112
132
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"send-only-client.js","sourceRoot":"","sources":["../../../src/slack/send-only-client.ts"],"names":[],"mappings":"AAAA,wDAAwD;AACxD,+EAA+E;AAC/E,iFAAiF;AAEjF,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAE7C,OAAO,EAAE,QAAQ,EAAE,kBAAkB,EAAE,YAAY,EAAmB,MAAM,UAAU,CAAC;AACvF,OAAO,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AACpE,OAAO,EAAE,iBAAiB,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAC1D,OAAO,EAAE,wBAAwB,EAAE,mBAAmB,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AACpG,OAAO,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"send-only-client.js","sourceRoot":"","sources":["../../../src/slack/send-only-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
// ─── Verified Slack workspace ────────────────────────
|
|
2
|
+
// The mention-watch ledger is keyed by (workspace, user), so a wrong workspace id
|
|
3
|
+
// hands one person cursor to another. That makes the SOURCE of the id part of the
|
|
4
|
+
// correctness argument.
|
|
5
|
+
//
|
|
6
|
+
// `settings.slack.teamId` is not that source. It is written only when empty and
|
|
7
|
+
// never re-checked against the token, so a token pointing at workspace B while the
|
|
8
|
+
// setting still says A yields rows filed under A.
|
|
9
|
+
//
|
|
10
|
+
// `initSlack` is not the entry point either: with no app token it returns before
|
|
11
|
+
// calling `auth.test` at all, and mention watch needs only a bot token. Depending
|
|
12
|
+
// on it would fail-close every outbound-only install that works today.
|
|
13
|
+
//
|
|
14
|
+
// So this asks Slack directly, once per token, and caches the answer against the
|
|
15
|
+
// token that produced it. A token change invalidates the cache by construction.
|
|
16
|
+
import { slackApi } from './api.js';
|
|
17
|
+
let cached = null;
|
|
18
|
+
/** Test seam. Never called in production paths. */
|
|
19
|
+
export function resetVerifiedSlackWorkspace() {
|
|
20
|
+
cached = null;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* The team id Slack itself reports for this token, or null when it cannot be
|
|
24
|
+
* established.
|
|
25
|
+
*
|
|
26
|
+
* Null is a refusal, not a default: a caller that keys durable state on this must
|
|
27
|
+
* skip the work rather than guess. One failed lookup skips one tick, which is
|
|
28
|
+
* recoverable; a guessed key writes into someone else ledger, which is not.
|
|
29
|
+
*/
|
|
30
|
+
export async function verifiedSlackWorkspace(token, opts = {}) {
|
|
31
|
+
const trimmed = token.trim();
|
|
32
|
+
if (!trimmed)
|
|
33
|
+
return null;
|
|
34
|
+
if (cached && cached.token === trimmed) {
|
|
35
|
+
return { teamId: cached.teamId, userId: cached.userId };
|
|
36
|
+
}
|
|
37
|
+
const auth = await slackApi(trimmed, 'auth.test', {}, opts.fetchImpl ? { fetchImpl: opts.fetchImpl } : {});
|
|
38
|
+
const teamId = String(auth.data?.team_id ?? '').trim();
|
|
39
|
+
if (!auth.ok || !teamId)
|
|
40
|
+
return null;
|
|
41
|
+
const userId = String(auth.data?.user_id ?? '').trim() || null;
|
|
42
|
+
cached = { token: trimmed, teamId, userId };
|
|
43
|
+
return { teamId, userId };
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=verified-workspace.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verified-workspace.js","sourceRoot":"","sources":["../../../src/slack/verified-workspace.ts"],"names":[],"mappings":"AAAA,wDAAwD;AACxD,kFAAkF;AAClF,kFAAkF;AAClF,wBAAwB;AACxB,EAAE;AACF,gFAAgF;AAChF,mFAAmF;AACnF,kDAAkD;AAClD,EAAE;AACF,iFAAiF;AACjF,kFAAkF;AAClF,uEAAuE;AACvE,EAAE;AACF,iFAAiF;AACjF,gFAAgF;AAEhF,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAKpC,IAAI,MAAM,GAAoB,IAAI,CAAC;AAEnC,mDAAmD;AACnD,MAAM,UAAU,2BAA2B;IACvC,MAAM,GAAG,IAAI,CAAC;AAClB,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,sBAAsB,CACxC,KAAa,EACb,OAA+C,EAAE;IAEjD,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;IAC7B,IAAI,CAAC,OAAO;QAAE,OAAO,IAAI,CAAC;IAC1B,IAAI,MAAM,IAAI,MAAM,CAAC,KAAK,KAAK,OAAO,EAAE,CAAC;QACrC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC;IAC5D,CAAC;IACD,MAAM,IAAI,GAAG,MAAM,QAAQ,CACvB,OAAO,EACP,WAAW,EACX,EAAE,EACF,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CACtD,CAAC;IACF,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IACvD,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IACrC,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,IAAI,IAAI,CAAC;IAC/D,MAAM,GAAG,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;IAC5C,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;AAC9B,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cli-jaw",
|
|
3
|
-
"version": "2.17.
|
|
3
|
+
"version": "2.17.27",
|
|
4
4
|
"description": "Personal AI assistant powered by Pi, Antigravity, AI-E, Claude, Claude E, Codex, Codex App, Cursor, Grok, Kiro, OpenCode, and Copilot — Web, Terminal, Telegram, and Discord interfaces with 107 built-in skills",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"keywords": [
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/vendor-render-kIxHrxDV.css"])))=>i.map(i=>d[i]);
|
|
2
|
+
import{n as e,r as t}from"./vendor-render-BpGO1zp3.js";import{t as n}from"./state-DxpgDKMO.js";import{a as r,i,n as a,r as o,t as s}from"./api-tVoG39dL.js";import{a as c,c as l,d as u,f as ee,i as te,l as ne,r as re,s as ie,t as ae,u as oe}from"./sidebar-FbI4udzs.js";import{t as d}from"./preload-helper-DFYRRz9w.js";import{A as se,C as ce,D as le,E as ue,F as de,I as fe,L as pe,M as f,O as p,R as m,S as me,b as he,f as ge,h as _e,l as ve,m as h,n as ye,p as be,u as xe,v as Se,y as Ce}from"./render-Cd4frZ2U.js";import{_ as we,d as Te,f as g,n as Ee,u as De}from"./iframe-renderer-LZp7Nqm1.js";import{O as Oe,T as ke,_,t as Ae,v}from"./message-history-Bp_sUDSx.js";import{n as je,s as y}from"./idb-cache-lOntwU3S.js";import{c as Me,f as Ne,o as Pe}from"./ui-Cd8etFwN.js";import{t as Fe}from"./locale-DC-ZsWOf.js";import{a as Ie,c as Le,i as Re,n as ze,o as Be,r as Ve,s as He,t as Ue}from"./slash-commands-FoQuZXga.js";import{i as We,o as Ge}from"./constants-DK-21dMG.js";import{A as Ke,C as qe,D as Je,E as Ye,F as Xe,I as Ze,L as Qe,M as $e,N as et,O as tt,P as nt,R as rt,S as b,T as it,a as at,c as ot,d as x,g as st,h as ct,i as lt,j as ut,k as dt,m as ft,o as pt,r as mt,s as ht,t as gt,u as S,v as _t,w as C,x as vt,y as yt,z as bt}from"./settings-core-C5qo8giT.js";import{t as xt}from"./provider-icons-CXA2mnPO.js";import{a as St,i as Ct,t as wt}from"./skills-DeG9lWF2.js";import{a as Tt,c as Et,d as Dt,f as Ot,g as kt,h as At,i as jt,l as Mt,m as Nt,n as Pt,o as Ft,p as It,r as Lt,s as Rt,t as w,u as zt}from"./settings-a0blK1fr.js";import{a as Bt,c as T,d as Vt,f as Ht,i as Ut,l as Wt,m as Gt,n as Kt,o as qt,p as Jt,r as Yt,s as Xt,t as Zt,u as E}from"./memory-V5caYbpS.js";import{n as Qt}from"./bgtask-badge-CT6s6rND.js";var $t=new Set([`.png`,`.jpg`,`.jpeg`,`.gif`,`.webp`,`.svg`]),en=new Set([`.mp4`,`.webm`,`.mov`,`.ogg`]);function tn(e){let t=String(e||``).split(/[\\/]/).pop()||``,n=t.lastIndexOf(`.`),r=n>0?t.slice(n).toLowerCase():``;return $t.has(r)?`image`:en.has(r)?`video`:`file`}var D=[],nn=8e3;function rn(e){return/^\/compact(?:\s|$)/i.test(String(e||``).trim())?300*1e3:1e4}var an={image:`chat.file.sentImage`,video:`chat.file.sentVideo`,file:`chat.file.sent`};function O(e){return m(an[tn(e)],{path:e})}function on(e,t=``){let n=e.map(O).join(`
|
|
3
|
+
`);return t?`${n}${m(`chat.file.sentWithMsg`,{text:t})}`:n}function sn(e,t){let n=t.map(O).join(`
|
|
4
|
+
`);return n?`${e}\n\n${n}`:e}function cn(e){let t=me();return t?new Promise(n=>{let r=`preview-send-${Date.now()}-${Math.random().toString(36).slice(2)}`,i=!1,a=()=>{window.removeEventListener(`message`,s),window.clearTimeout(c)},o=e=>{i||(i=!0,a(),n(e))},s=e=>{if(e.source!==window.parent||!he(e.origin))return;let t=e.data;!t||t.type!==`jaw-preview-send-result`||t.requestId!==r||o({ok:!!t.ok,status:Number.isInteger(t.status)?t.status:t.ok?200:502,data:t.data||(t.error?{error:t.error}:{}),viaRelay:!0})},c=window.setTimeout(()=>o(null),nn);window.addEventListener(`message`,s);try{window.parent.postMessage(h({type:`jaw-preview-send-message`,requestId:r,prompt:e}),t)}catch{o(null)}}):Promise.resolve(null)}async function ln(e){let t=await cn(e);if(t?.ok)return t;try{let t=await fetch(`${s}/api/message`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify(h({prompt:e}))}),n=await t.json().catch(()=>({}));return{ok:t.ok,status:t.status,data:n}}catch(e){return{ok:!1,status:0,data:{error:e.message}}}}async function un(e){let t,n,i=rn(e);if(typeof AbortSignal?.timeout==`function`)t=AbortSignal.timeout(i);else{let e=new AbortController;t=e.signal,n=setTimeout(()=>e.abort(),i)}let a=Fe(),o=await r(),c=await fetch(`${s}/api/command`,{method:`POST`,headers:{"Content-Type":`application/json`,"Accept-Language":a,...o?{Authorization:`Bearer ${o}`}:{}},body:JSON.stringify(h({text:e,locale:a})),signal:t});n&&clearTimeout(n);let l=await c.json().catch(()=>({}));return{ok:c.ok,status:c.status,result:l}}async function dn(e,t,n){let r=t.result;if(r?.code===`not_command`){if(n){await n();return}_(`user`,e),y({role:`user`,content:e,timestamp:Date.now()}),await i(`/api/message`,`POST`,h({prompt:e}));return}if(!t.ok&&!r?.text)throw Error(`HTTP ${t.status}`);if(r?.code===`clear_screen`){ye(),we().clear();let e=document.getElementById(`chatMessages`);e&&(e.innerHTML=``)}(r?.text||r?.recovery)&&v(fn(r),``,r.type),r?.steerPrompt&&await i(`/api/message`,`POST`,h({prompt:r.steerPrompt}))}function fn(e){let t=e.recovery;if(!t?.originalText)return e.text?f(e.text):``;let n=(t.suggestedCommands||[]).slice(0,5),r=n.length?`<div class="cmd-recovery-suggestions">${n.map(e=>`<code>${f(e)}</code>`).join(` `)}</div>`:``,i=f(t.originalText);return`${e.text?`<div>${f(e.text)}</div>`:``}
|
|
5
|
+
<div class="cmd-recovery" data-cmd-recovery>
|
|
6
|
+
<div class="cmd-recovery-label">${f(m(`cmd.recovery.originalPrompt`))}</div>
|
|
7
|
+
<pre class="cmd-recovery-text">${i}</pre>
|
|
8
|
+
${r}
|
|
9
|
+
<div class="cmd-recovery-actions">
|
|
10
|
+
<button type="button" class="cmd-recovery-btn" data-cmd-recovery-action="reinsert" data-cmd-text="${i}">${f(m(`cmd.artifact.action.reinsert`))}</button>
|
|
11
|
+
<button type="button" class="cmd-recovery-btn" data-cmd-recovery-action="copy" data-cmd-text="${i}">${f(m(`cmd.artifact.action.copy`))}</button>
|
|
12
|
+
</div>
|
|
13
|
+
</div>`}document.addEventListener(`click`,async e=>{let t=e.target?.closest(`[data-cmd-recovery-action]`);if(!t)return;let n=t.dataset.cmdRecoveryAction||``,r=t.dataset.cmdText||``;if(r){if(n===`reinsert`){let e=document.getElementById(`chatInput`);if(!e)return;e.value=r,e.focus(),e.selectionStart=e.selectionEnd=e.value.length,e.dispatchEvent(new Event(`input`,{bubbles:!0}));return}n===`copy`&&await le(r)}});var k=!1;async function A(e=`enter`){let t=document.getElementById(`chatInput`),r=document.getElementById(`btnSend`);if(!t||!r)return;let a=t.value.trim();if(!ve(e===`button`&&r.classList.contains(`stop-mode`)?``:a)){be();return}let s=e===`button`;if(r.classList.contains(`stop-mode`)&&s){o(`/api/stop`,`POST`,h({}));return}if(k||!a&&!n.attachedFiles.length)return;ne(),k=!0;let c=r,u=c.disabled;c.disabled=!0;try{await ft();let e=a.slice(1).trim().split(/\s+/)[0]||``,r=e.includes(`/`)||e.includes(`\\`),o=a.startsWith(`/`)&&!r;if(o&&!n.attachedFiles.length){if(t.value=``,M(),Ue(),He(a))return;try{await dn(a,await un(a))}catch(e){v(m(`chat.cmd.fail`,{msg:e.message}),``,`error`)}finally{l(`command`).catch(()=>{})}return}if(n.attachedFiles.length){let e=`📎 [${n.attachedFiles.map(e=>e.name).join(`, `)}] ${a}`;_(`user`,e),y({role:`user`,content:e,timestamp:Date.now()}),t.value=``,M();try{let e=await Promise.all(n.attachedFiles.map(e=>mn(e))),t=on(e,a);if(j(),o){Ue();try{let n=sn(a,e);await dn(n,await un(n),async()=>{await i(`/api/message`,`POST`,h({prompt:t}))})}catch(e){v(m(`chat.cmd.fail`,{msg:e.message}),``,`error`)}finally{l(`command`).catch(()=>{})}return}await i(`/api/message`,`POST`,h({prompt:t}))}catch(e){v(m(`chat.file.uploadFail`,{msg:e.message})),j()}}else{t.value=``,M();let e=await ln(a),n=e.data;if(e.status===409&&n.error===`duplicate`)return;if(!e.ok){v(`${p.error} ${f(n.error||m(`chat.requestFail`,{status:e.status}))}`,``,`error`);return}if(n.queued){let{updateQueueBadge:e}=await d(async()=>{let{updateQueueBadge:e}=await import(`./ui-yrn3s72A.js`);return{updateQueueBadge:e}},__vite__mapDeps([0]));e(n.pending||1)}else e.viaRelay?(y({role:`user`,content:a,timestamp:Date.now()}),n.continued&&v(m(`chat.continue`)),g(!0)):n.noPendingContinue?(_(`user`,a),y({role:`user`,content:a,timestamp:Date.now()}),g(!0)):n.continued?(_(`user`,a),y({role:`user`,content:a,timestamp:Date.now()}),v(m(`chat.continue`)),g(!0)):(_(`user`,a),y({role:`user`,content:a,timestamp:Date.now()}),g(!0))}}finally{k=!1,c.disabled=u}}function pn(e){e.key===`Enter`&&!e.shiftKey&&!e.isComposing&&(e.preventDefault(),A(`enter`))}async function mn(e){let t=await fetch(`${s}/api/upload`,{method:`POST`,headers:{"X-Filename":encodeURIComponent(e.name)},body:e});if(!t.ok)throw Error(`upload failed`);return(await t.json()).path}function hn(e){for(let t of e)n.attachedFiles.some(e=>e.name===t.name)||n.attachedFiles.push(t);_n(),document.getElementById(`chatInput`)?.focus()}function gn(e){n.attachedFiles.splice(e,1),_n()}function j(){D.forEach(e=>URL.revokeObjectURL(e)),D=[],n.attachedFiles=[],_n();let e=document.getElementById(`fileInput`);e&&(e.value=``)}function _n(){let e=document.getElementById(`filePreview`),t=document.getElementById(`filePreviewList`);if(e){if(D.forEach(e=>URL.revokeObjectURL(e)),D=[],!n.attachedFiles.length){e.classList.remove(`visible`),t&&(t.innerHTML=``);return}e.classList.add(`visible`),t&&(t.innerHTML=n.attachedFiles.map((e,t)=>{let n=(e.size/1024).toFixed(1),r=e.type.startsWith(`image/`),i=``;if(r){let t=URL.createObjectURL(e);D.push(t),i=`<img src="${t}" class="file-chip-thumb" alt="">`}return`<div class="file-chip">
|
|
14
|
+
${i}
|
|
15
|
+
<span class="file-chip-name">${p.paperclip} ${f(e.name)} (${n}KB)</span>
|
|
16
|
+
<button class="file-chip-remove" data-file-idx="${t}" title="Remove">${p.close}</button>
|
|
17
|
+
</div>`}).join(``))}}async function vn(){ye(),we().clear();let e=document.getElementById(`chatMessages`);e&&(e.innerHTML=``);let{cleanupToolActivity:t}=await d(async()=>{let{cleanupToolActivity:e}=await import(`./ui-yrn3s72A.js`);return{cleanupToolActivity:e}},__vite__mapDeps([0]));t(),je().catch(()=>{}),ne()}var yn=0;function bn(e){if(yn)return;let t=De();yn=requestAnimationFrame(()=>{if(yn=0,e.style.height=`auto`,e.style.height=e.scrollHeight+`px`,t){let e=document.getElementById(`chatMessages`);e&&(e.scrollTop=e.scrollHeight,Te())}})}function xn(){let e=document.getElementById(`chatInput`);e&&e.addEventListener(`input`,()=>bn(e))}function M(){let e=document.getElementById(`chatInput`),t=De();if(e&&(e.style.height=`auto`),t){let e=document.getElementById(`chatMessages`);e&&(e.scrollTop=e.scrollHeight,Te())}}function Sn(){let e=document.querySelector(`.chat-area`),t=document.getElementById(`dragOverlay`);if(!e||!t)return;let n=0;e.addEventListener(`dragenter`,e=>{e.preventDefault(),n++,t.classList.add(`visible`)}),e.addEventListener(`dragleave`,e=>{e.preventDefault(),n--,n<=0&&(n=0,t.classList.remove(`visible`))}),e.addEventListener(`dragover`,e=>e.preventDefault()),e.addEventListener(`drop`,e=>{e.preventDefault(),n=0,t.classList.remove(`visible`);let r=[...e.dataTransfer?.files||[]];r.length&&hn(r)}),document.getElementById(`fileInput`)?.addEventListener(`change`,e=>{let t=e.target,n=[...t.files||[]];n.length&&hn(n),t.value=``}),document.addEventListener(`paste`,e=>{let t=e.clipboardData?.items;if(!t)return;let n=[];for(let e of t){if(e.kind!==`file`)continue;let t=e.getAsFile();if(t)if(!t.name||t.name===`image.png`){let e=new Date().toISOString().replace(/[:.]/g,`-`),r=t.type.split(`/`)[1]||`png`,i=new File([t],`pasted-${e}.${r}`,{type:t.type});n.push(i)}else n.push(t)}n.length&&(e.preventDefault(),hn(n))})}async function Cn(e,t,r){if(!ve()){be();return}let a=document.getElementById(`chatInput`),o=a?.value.trim()||``,c=[...n.attachedFiles],l=[m(`chat.voice.label`)];c.length&&l.push(`📎 [${c.map(e=>e.name).join(`, `)}]`),o&&l.push(o),_(`user`,l.join(` `)),y({role:`user`,content:l.join(` `),timestamp:Date.now()}),a&&o&&(a.value=``,M()),c.length&&j();try{let n=await fetch(`${s}/api/voice`,{method:`POST`,headers:{"Content-Type":r,"X-Voice-Ext":t,"X-STT-Only":`true`},body:e});if(!n.ok){let e=await n.json().catch(()=>({}));throw Error(e.error||`HTTP ${n.status}`)}let a=await n.json().catch(()=>null);if(!a?.text)throw Error(`Empty STT result`);v(`${p.mic} STT (${f(a.engine||``)}, ${a.elapsed?.toFixed(1)}s): "${f(a.text.slice(0,100))}"`,``,`info`);let l=[];c.length&&(l=await Promise.all(c.map(e=>mn(e))));let u=[];for(let e of l)u.push(O(e));u.push(`🎤 ${a.text}`),o&&u.push(o),await i(`/api/message`,`POST`,h({prompt:u.join(`
|
|
18
|
+
`)}))}catch(e){v(m(`voice.sttFail`,{msg:e.message}),``,`error`)}}var wn={sun:0,mon:1,tue:2,wed:3,thu:4,fri:5,sat:6},Tn={jan:1,feb:2,mar:3,apr:4,may:5,jun:6,jul:7,aug:8,sep:9,oct:10,nov:11,dec:12};function En(e){let t=typeof e==`string`?e.trim():``;if(t)try{return new Intl.DateTimeFormat(`en-US`,{timeZone:t}).format(new Date),t}catch{return}}function Dn(e){let t=e&&typeof e==`object`?e:{},n=t.kind,r=typeof t.timeZone==`string`?t.timeZone.trim():``,i=En(t.timeZone);if(r&&!i)return{ok:!1,code:`invalid_timezone`,error:`invalid timeZone "${r}"`};if(n===`cron`){let e=typeof t.cron==`string`?t.cron.trim().replace(/\s+/g,` `):``;if(!e)return{ok:!1,code:`invalid_cron`,error:`cron expression required`};let n=On(e);return n?{ok:!1,code:`invalid_cron`,error:n}:{ok:!0,schedule:i?{kind:`cron`,cron:e,timeZone:i}:{kind:`cron`,cron:e}}}if(n==null||n===`every`){let e=typeof t.minutes==`number`?t.minutes:Number(t.minutes);if(!Number.isInteger(e)||e<1)return{ok:!1,code:`invalid_minutes`,error:`minutes must be an integer >= 1`};let n=Math.max(1,Math.floor(e));return{ok:!0,schedule:i?{kind:`every`,minutes:n,timeZone:i}:{kind:`every`,minutes:n}}}return{ok:!1,code:`invalid_kind`,error:`invalid heartbeat schedule kind "${String(n)}"`}}function On(e){try{let[t,n,r,i,a]=kn(e);return N(t,{min:0,max:59}),N(n,{min:0,max:23}),N(r,{min:1,max:31}),N(i,{min:1,max:12,aliases:Tn}),N(a,{min:0,max:7,aliases:wn,normalize:Nn}),null}catch(e){return e.message}}function kn(e){let t=String(e||``).trim().replace(/\s+/g,` `).split(` `);if(t.length!==5)throw Error(`cron must have 5 fields, got ${t.length}`);return t}function N(e,t){for(let n of e.split(`,`))An(n.trim(),t)}function An(e,t){if(!e)throw Error(`empty cron segment`);let n=e;if(e.includes(`/`)){let[t,r,...i]=e.split(`/`);if(!t||!r||i.length>0)throw Error(`invalid cron step segment "${e}"`);n=t,Mn(r,`invalid cron step "${r}"`)}if(n!==`*`){if(n.includes(`-`)){let[e,r,...i]=n.split(`-`);if(!e||!r||i.length>0||jn(e,t)>jn(r,t))throw Error(`invalid cron range "${n}"`);return}jn(n,t)}}function jn(e,t){let n=e.trim().toLowerCase(),r=t.aliases?.[n]??Number(n);if(!Number.isInteger(r))throw Error(`invalid cron value "${e}"`);let i=t.normalize?t.normalize(r):r;if(!Pn(i,t.min,t.max))throw Error(`cron value "${e}" out of range ${t.min}-${t.max}`);return i}function Mn(e,t){let n=Number(e);if(!Number.isInteger(n)||n<=0)throw Error(t);return n}function Nn(e){return e===7?0:e}function Pn(e,t,n){return e>=t&&e<=n}async function Fn(){n.heartbeatJobs=((await a(`/api/heartbeat`))?.jobs||[]).map(I),n.heartbeatErrors=L(n.heartbeatJobs),P(),document.getElementById(`heartbeatModal`)?.classList.add(`open`)}function In(e){e&&e.target!==e.currentTarget||document.getElementById(`heartbeatModal`)?.classList.remove(`open`)}function P(){let e=document.getElementById(`hbJobsList`);if(!e)return;let t=n.heartbeatJobs.map(I);n.heartbeatJobs=t,n.heartbeatErrors=L(t),t.length===0?e.innerHTML=`<p style="color:var(--text-dim);font-size:12px;text-align:center">${m(`hb.empty`)}</p>`:e.innerHTML=t.map((e,t)=>{let r=Hn(e.schedule),i=r.kind===`cron`,a=n.heartbeatErrors[e.id],o=a||Yn(r),s=a?`hb-schedule-meta hb-error`:`hb-schedule-meta hb-help`,c=i?`<input type="text" value="${f(r.cron)}" placeholder="${f(m(`hb.cronPlaceholder`))}"
|
|
19
|
+
data-hb-cron="${t}">`:`<input type="number" value="${r.minutes}" min="1" data-hb-minutes="${t}">`,l=i?`<span class="hb-chip">${f(m(`hb.cronLabel`))}</span>`:`<span class="hb-chip">${f(m(`hb.minutesLabel`))}</span>`;return`
|
|
20
|
+
<div class="hb-job-card">
|
|
21
|
+
<div class="hb-job-header">
|
|
22
|
+
<input type="text" value="${f(String(e.name||``))}" placeholder="${f(m(`hb.name`))}"
|
|
23
|
+
data-hb-name="${t}">
|
|
24
|
+
<button class="hb-toggle ${e.enabled?`on`:`off`}"
|
|
25
|
+
data-hb-toggle="${t}" aria-label="${f(String(e.name||`job`)+` toggle`)}"></button>
|
|
26
|
+
<button class="hb-del" data-hb-remove="${t}">${p.close}</button>
|
|
27
|
+
</div>
|
|
28
|
+
<div class="hb-job-schedule">
|
|
29
|
+
<select data-hb-kind="${t}">
|
|
30
|
+
<option value="every"${i?``:` selected`}>${f(m(`hb.kindEvery`))}</option>
|
|
31
|
+
<option value="cron"${i?` selected`:``}>${f(m(`hb.kindCron`))}</option>
|
|
32
|
+
</select>
|
|
33
|
+
${c}
|
|
34
|
+
${l}
|
|
35
|
+
<input type="text" value="${f(r.timeZone||``)}" placeholder="${f(Kn())}"
|
|
36
|
+
data-hb-timezone="${t}">
|
|
37
|
+
</div>
|
|
38
|
+
<p class="${s}">${f(o)}</p>
|
|
39
|
+
<textarea class="hb-prompt" rows="2" placeholder="${f(m(`hb.prompt`))}"
|
|
40
|
+
data-hb-prompt="${t}">${f(String(e.prompt||``))}</textarea>
|
|
41
|
+
</div>
|
|
42
|
+
`}).join(``);let r=t.filter(e=>e.enabled).length,i=document.getElementById(`hbSidebarBtn`);i&&(i.innerHTML=`${p.heartPulse} Heartbeat (${r})`)}var Ln=0;function Rn(){n.heartbeatJobs.push({id:`hb_${Date.now()}_${Ln++}`,name:``,enabled:!0,schedule:Wn({kind:`every`,minutes:5}),prompt:``}),P(),F()}function zn(e){n.heartbeatJobs.splice(e,1),P(),F()}function Bn(e){let t=n.heartbeatJobs[e];t&&(t.enabled=!t.enabled,P(),F())}async function F(){let e=n.heartbeatJobs.map(I);if(n.heartbeatJobs=e,n.heartbeatErrors=L(e),Object.keys(n.heartbeatErrors).length>0){P();return}let t=await i(`/api/heartbeat`,`PUT`,{jobs:e});t?.jobs&&(n.heartbeatJobs=t.jobs.map(I),n.heartbeatErrors=L(n.heartbeatJobs),P())}async function Vn(){try{let e=((await a(`/api/heartbeat`))?.jobs||[]).map(I).filter(e=>e.enabled).length,t=document.getElementById(`hbSidebarBtn`);t&&(t.innerHTML=`${p.heartPulse} Heartbeat (${e})`)}catch{}}function I(e){return{id:String(e.id||`hb_${Date.now()}_${Ln++}`),name:String(e.name||``),enabled:e.enabled!==!1,schedule:Hn(e.schedule),prompt:String(e.prompt||``)}}function Hn(e){let t=Un(e?.timeZone);if(e?.kind===`cron`){let n=typeof e.cron==`string`?e.cron.trim().replace(/\s+/g,` `):`0 9 * * *`;return t?{kind:`cron`,cron:n,timeZone:t}:{kind:`cron`,cron:n}}let n=typeof e?.minutes==`number`&&Number.isFinite(e.minutes)&&e.minutes>0?Math.max(1,Math.floor(e.minutes)):5;return t?{kind:`every`,minutes:n,timeZone:t}:{kind:`every`,minutes:n}}function Un(e){return(typeof e==`string`?e.trim():``)||void 0}function Wn(e){let t=Gn();return t?{...e,timeZone:t}:e}function Gn(){try{return Intl.DateTimeFormat().resolvedOptions().timeZone||void 0}catch{return}}function Kn(){let e=Gn();return e?`${m(`hb.timezoneAuto`)} ${e}`:m(`hb.timezoneAuto`)}function L(e){let t={};for(let n of e){let e=qn(n);e&&(t[n.id]=e)}return t}function qn(e){let t=Dn(e.schedule);return t.ok?null:Jn(t.code,t.error)}function Jn(e,t){switch(e){case`invalid_cron`:return m(`hb.invalidCron`);case`invalid_timezone`:return m(`hb.invalidTimeZone`);case`invalid_minutes`:return m(`hb.invalidMinutes`);default:return t||m(`hb.invalidSchedule`)}}function Yn(e){let t=e.timeZone||Gn()||`Asia/Seoul`;return e.kind===`cron`?m(`hb.scheduleHintCron`,{cron:`0 9 * * *`,timeZone:t}):m(`hb.scheduleHintEvery`,{minutes:e.minutes,timeZone:t})}var R=`jaw.uiTheme`,z=null;function Xn(e){return e===`dark`||e===`light`||e===`auto`}function Zn(e){return e===`light`||e===`auto`&&typeof window<`u`&&window.matchMedia&&window.matchMedia(`(prefers-color-scheme: light)`).matches?`light`:`dark`}function Qn(n){let r=n===`light`?e:t;z||(z=document.createElement(`style`),z.id=`hljsTheme`,document.head.appendChild(z)),z.textContent=r}function $n(){!localStorage.getItem(R)&&localStorage.getItem(`theme`)&&(localStorage.setItem(R,localStorage.getItem(`theme`)),localStorage.removeItem(`theme`));let e=tr(),t=localStorage.getItem(R),n=window.matchMedia(`(prefers-color-scheme: light)`).matches?`light`:`dark`;B(e||t||n),document.getElementById(`toggleTheme`)?.addEventListener(`click`,er),window.addEventListener(`message`,rr),window.matchMedia(`(prefers-color-scheme: dark)`).addEventListener(`change`,()=>{let e=localStorage.getItem(R);(!e||e===`auto`)&&B(e||`auto`)}),window.addEventListener(`storage`,e=>{e.key===R&&e.newValue&&B(e.newValue)})}function er(){let e=(document.documentElement.getAttribute(`data-theme`)||`dark`)===`dark`?`light`:`dark`;B(e),localStorage.setItem(R,e)}function B(e){let t=Zn(e);document.documentElement.setAttribute(`data-theme`,t);let n=document.getElementById(`toggleTheme`);n&&n.classList.toggle(`is-light`,t===`light`),Qn(t),Ee(),ue()}function tr(){let e=new URLSearchParams(window.location.search).get(`jawTheme`);return Xn(e)?e:null}function nr(e){if(e===window.location.origin)return!0;try{let t=new URL(e).hostname;return t===`localhost`||t===`127.0.0.1`||t===`::1`||t===`[::1]`}catch{return!1}}function rr(e){if(window.parent===window||e.source!==window.parent||!nr(e.origin))return;let t=e.data;!t||t.type!==`jaw-preview-theme-sync`||!Xn(t.theme)||B(t.theme)}var ir=new Set([`j`,`k`,`i`,`n`,`p`]);function ar(e){if(e.altKey&&!e.ctrlKey&&!e.metaKey){let t=e.key.toLowerCase();return(t.length!==1||!ir.has(t))&&e.code?.startsWith(`Key`)&&(t=e.code.slice(3).toLowerCase()),ir.has(t)}return e.ctrlKey&&!e.metaKey&&!e.altKey?e.code===`Backquote`:!!(e.metaKey&&!e.ctrlKey&&!e.altKey&&(!e.shiftKey&&(e.code===`Backquote`||e.code===`KeyB`||e.code===`KeyJ`)||e.shiftKey&&(e.code===`KeyB`||e.code===`KeyD`||e.code===`KeyE`)))}function or(){window.parent!==window&&document.addEventListener(`keydown`,e=>{if(ar(e)){e.preventDefault();try{window.parent.postMessage({type:`jaw-preview-shortcut`,key:e.key,code:e.code,altKey:e.altKey,ctrlKey:e.ctrlKey,metaKey:e.metaKey,shiftKey:e.shiftKey},`*`)}catch{}}})}var sr=50,cr=30,lr=80,ur=500,V=null,dr=!1;function fr(){if(dr||!(`ontouchstart`in window))return;dr=!0;let e=document.querySelector(`.chat-area`);e&&(e.addEventListener(`touchstart`,pr,{passive:!0}),e.addEventListener(`touchend`,mr,{passive:!0}))}function pr(e){let t=e.touches[0],n=window.innerWidth,r=null;t.clientX<cr?r=`left`:t.clientX>n-cr&&(r=`right`),V={startX:t.clientX,startY:t.clientY,startTime:Date.now(),isEdge:r}}function mr(e){if(!V)return;let t=e.changedTouches[0],n=t.clientX-V.startX,r=Math.abs(t.clientY-V.startY),i=Date.now()-V.startTime,a=V;V=null,!(r>lr||i>ur||Math.abs(n)<sr)&&(n>0&&a.isEdge===`left`&&re(),n<0&&a.isEdge===`right`&&te())}var H=!1,U=null,W=[],hr=null,gr=null,_r=0,G=!1,K=`stopped`,vr=15e3;function yr(){if(typeof MediaRecorder>`u`)return``;for(let e of[`audio/webm;codecs=opus`,`audio/mp4`,`audio/ogg;codecs=opus`])if(MediaRecorder.isTypeSupported(e))return e;return``}function br(e){let t=e;switch(t.name){case`NotAllowedError`:return m(`voice.micDenied`);case`NotFoundError`:return m(`voice.micNotFound`);case`NotReadableError`:case`AbortError`:return m(`voice.micBusy`);case`TimeoutError`:return Tr();default:return t instanceof TypeError||!navigator.mediaDevices?m(`voice.httpsRequired`):m(`voice.micDenied`)}}function xr(){let e=document;return e.permissionsPolicy||e.featurePolicy||null}function Sr(){try{return xr()?.allowsFeature?.(`microphone`)===!1}catch{return!1}}async function Cr(){try{return navigator.permissions?.query?(await navigator.permissions.query({name:`microphone`})).state:null}catch{return null}}function wr(){let e=new URL(window.location.href),t=new URL(e.href);e.hostname===`127.0.0.1`?t.hostname=`localhost`:e.hostname===`localhost`&&(t.hostname=`127.0.0.1`);let n=t.origin===e.origin?``:t.origin;return{origin:e.origin,alternateOrigin:n}}function Tr(){let e=wr();return e.alternateOrigin?m(`voice.requestTimeoutLoopback`,e):m(`voice.requestTimeout`,e)}function Er(e){let t=e;return t.name===`NotSupportedError`?m(`voice.unsupported`):t.name===`NotReadableError`||t.name===`AbortError`?m(`voice.micBusy`):t instanceof TypeError?m(`voice.httpsRequired`):m(`voice.interrupted`)}function q(e){if(window.parent!==window)try{window.parent.postMessage({type:`jaw-preview-stt-recording`,action:e},`*`)}catch{}}function Dr(){return new DOMException(`Timed out waiting for microphone permission prompt`,`TimeoutError`)}async function Or(){let e=!1,t=null,n=navigator.mediaDevices.getUserMedia({audio:!0}).then(t=>e?(t.getTracks().forEach(e=>e.stop()),null):t,t=>{if(e)return null;throw t}),r=new Promise((n,r)=>{t=setTimeout(()=>{e=!0,r(Dr())},vr)});try{let e=await Promise.race([n,r]);if(!e)throw Dr();return e}finally{t!==null&&clearTimeout(t)}}async function kr(){if(n.isRecording||G)return;if(typeof MediaRecorder>`u`||!navigator.mediaDevices?.getUserMedia){v(m(`voice.unsupported`),``,`error`);return}if(Sr()){v(m(`voice.policyBlocked`),``,`error`);return}if(await Cr()===`denied`){v(m(`voice.permissionDeniedBrowser`,wr()),``,`error`);return}G=!0,H=!1,K=`stopped`,Y(!1),q(`request`);let e=null;try{e=await Or(),hr=e}catch(e){G=!1,Y(!1),q(`failed`),v(br(e),``,`error`);return}try{let t=yr(),r=new MediaRecorder(e,t?{mimeType:t}:{});U=r,W=[],r.ondataavailable=e=>{e.data.size>0&&W.push(e.data)},r.onerror=()=>{H=!0,K=`failed`,n.isRecording=!1,Pr(),Y(!1),r.state===`recording`?r.stop():(W=[],J(),U=null,q(`failed`)),v(m(`voice.interrupted`),``,`error`)},r.onstop=async()=>{let e=K,n=H||e!==`stopped`;if(K=`stopped`,n){W=[],J(),U=null,H=!1,q(e);return}let i=r.mimeType||t||`audio/webm`,a=i.includes(`mp4`)?`.m4a`:i.includes(`ogg`)?`.ogg`:`.webm`,o=new Blob(W,{type:i});if(W=[],J(),U=null,H=!1,q(`stopped`),o.size>20*1024*1024){v(m(`voice.tooLarge`),``,`error`);return}if(o.size<1e3){v(m(`voice.tooShort`),``,`error`);return}await Cn(o,a,i)},r.start(),n.isRecording=!0,G=!1,_r=Date.now(),Y(!0),Nr(),q(`started`)}catch(e){G=!1,n.isRecording=!1,W=[],U=null,J(),Y(!1),q(`failed`),v(Er(e),``,`error`)}}function Ar(){!n.isRecording||!U||(K=`stopped`,U.state===`recording`?U.stop():(J(),U=null,q(`stopped`)),n.isRecording=!1,Pr(),Y(!1))}function jr(){!n.isRecording||!U||(H=!0,K=`cancelled`,U.state===`recording`?U.stop():(W=[],J(),U=null,q(`cancelled`)),n.isRecording=!1,Pr(),Y(!1))}function Mr(){n.isRecording?Ar():kr()}function J(){hr?.getTracks().forEach(e=>e.stop()),hr=null}function Nr(){let e=document.getElementById(`voiceTimer`);e&&(e.style.display=`inline`,gr=setInterval(()=>{let t=Math.floor((Date.now()-_r)/1e3);e.textContent=`${String(Math.floor(t/60)).padStart(2,`0`)}:${String(t%60).padStart(2,`0`)}`},500))}function Pr(){gr&&=(clearInterval(gr),null);let e=document.getElementById(`voiceTimer`);e&&(e.style.display=`none`,e.textContent=`00:00`)}function Y(e){let t=document.getElementById(`btnVoice`),n=document.getElementById(`btnVoiceCancel`),r=G&&!e;t&&(t.classList.toggle(`recording`,e),t.classList.toggle(`arming`,r),t.innerHTML=e?p.stop:p.mic,t.title=m(r?`voice.requesting`:e?`voice.stop`:`voice.start`),t.toggleAttribute(`aria-busy`,r),t instanceof HTMLButtonElement&&(t.disabled=r)),n&&(n.style.display=e?`inline-block`:`none`)}window.parent;var Fr=null,Ir=``,X=null,Lr=!1;function Rr(){let e=document.getElementById(`chatSearchInput`),t=document.getElementById(`chatSearchClose`),n=document.getElementById(`chatSearchResults`),r=document.getElementById(`chatSearchCount`);!e||!t||!n||!r||Lr||(Lr=!0,window.addEventListener(`message`,e=>{e.data?.type===`jaw-preview-search`&&zr()}),e.addEventListener(`input`,()=>{let t=e.value.trim();if(Fr&&clearTimeout(Fr),!t){qr(n,r);return}Fr=setTimeout(()=>void Vr(t,n,r),250)}),e.addEventListener(`keydown`,e=>{if(e.key===`Escape`){Z();return}e.key===`Enter`&&(e.preventDefault(),n.querySelector(`.chat-search-result`)?.click()),e.key===`ArrowDown`&&(e.preventDefault(),Kr(n,1)),e.key===`ArrowUp`&&(e.preventDefault(),Kr(n,-1))}),n.addEventListener(`wheel`,e=>{let t=n,r=t.scrollTop===0&&e.deltaY<0,i=t.scrollTop+t.clientHeight>=t.scrollHeight&&e.deltaY>0;!r&&!i&&e.stopPropagation(),(r||i)&&e.preventDefault()},{passive:!1}),t.addEventListener(`click`,Z))}function zr(){let e=document.getElementById(`chatSearch`),t=document.getElementById(`chatSearchInput`);!e||!t||(e.classList.contains(`open`)?Z():(e.classList.add(`open`),t.focus(),Br()))}function Z(){let e=document.getElementById(`chatSearch`),t=document.getElementById(`chatSearchInput`),n=document.getElementById(`chatSearchResults`),r=document.getElementById(`chatSearchCount`);e&&(e.classList.remove(`open`),t&&(t.value=``),n&&r&&qr(n,r),Ir=``)}function Br(){X=new Map,a(`/api/messages${Ae()}`).then(e=>{e&&(X=new Map,e.forEach((e,t)=>X.set(e.id,t)))}).catch(()=>{})}async function Vr(e,t,n){Ir=e;let r=await a(_e(`/api/messages/search?q=${encodeURIComponent(e)}&limit=20`));if(!(!r||Ir!==e)){if(n.textContent=r.length>0?`${r.length} found`:`no results`,r.length===0){t.classList.remove(`has-results`),t.innerHTML=``;return}t.innerHTML=r.map(t=>Hr(t,e)).join(``),t.classList.add(`has-results`),t.querySelectorAll(`.chat-search-result`).forEach(e=>{e.addEventListener(`click`,()=>{Gr(Number(e.dataset.msgId))})})}}function Hr(e,t){let n=e.role===`assistant`?`agent`:e.role,r=n===`agent`?e.cli||`agent`:`you`,i=e.match_field===`tool_log`,a=i?`<span class="chat-search-result-badge">tool</span>`:``,o=Wr(i?Ur(e.tool_log,t):e.content,t),s=Jr(e.created_at);return`<div class="chat-search-result" data-msg-id="${e.id}" tabindex="-1">
|
|
43
|
+
<div class="chat-search-result-meta">
|
|
44
|
+
<span class="chat-search-result-role ${n}">${f(r)}</span>
|
|
45
|
+
${a}
|
|
46
|
+
<span>${f(s)}</span>
|
|
47
|
+
</div>
|
|
48
|
+
<div class="chat-search-result-snippet">${o}</div>
|
|
49
|
+
</div>`}function Ur(e,t){if(!e)return``;try{let n=JSON.parse(e),r=t.toLowerCase();for(let e of n){let t=`${e.label||``} ${e.detail||``}`;if(t.toLowerCase().includes(r))return t}}catch{}return e.slice(0,300)}function Wr(e,t){let n=e.toLowerCase().indexOf(t.toLowerCase());if(n===-1)return f(e.slice(0,120));let r=Math.max(0,n-40),i=Math.min(e.length,n+t.length+80),a=f(e.slice(r,n)),o=f(e.slice(n,n+t.length)),s=f(e.slice(n+t.length,i));return`${r>0?`…`:``}${a}<mark>${o}</mark>${s}${i<e.length?`…`:``}`}function Gr(e){if(!X)return;let t=X.get(e);t!=null&&(we().scrollToIndex(t,`center`),requestAnimationFrame(()=>{setTimeout(()=>{let e=document.getElementById(`chatMessages`);if(!e)return;e.querySelectorAll(`.msg.search-highlight`).forEach(e=>e.classList.remove(`search-highlight`));let n=e.querySelectorAll(`.msg`);for(let e of n){let n=e.getAttribute(`data-turn-index`);if(n!=null&&Number(n)===t){e.classList.add(`search-highlight`);break}}},150)}))}function Kr(e,t){let n=Array.from(e.querySelectorAll(`.chat-search-result`));if(n.length===0)return;let r=e.querySelector(`.chat-search-result.active`),i=r?n.indexOf(r)+t:0;i<0&&(i=n.length-1),i>=n.length&&(i=0),n.forEach(e=>e.classList.remove(`active`)),n[i].classList.add(`active`),n[i].scrollIntoView({block:`nearest`}),n[i].click()}function qr(e,t){e.classList.remove(`has-results`),e.innerHTML=``,t.textContent=``}function Jr(e){try{let t=new Date(e),n=new Date;return t.toDateString()===n.toDateString()?t.toLocaleTimeString([],{hour:`2-digit`,minute:`2-digit`}):t.toLocaleDateString([],{month:`short`,day:`numeric`})+` `+t.toLocaleTimeString([],{hour:`2-digit`,minute:`2-digit`})}catch{return``}}var Yr=!1;function Xr(){if(Yr)return;Yr=!0;let e=document.createElement(`div`);e.id=`mediaLightbox`,e.className=`media-lightbox hidden`,e.innerHTML=`<div class="media-lightbox-backdrop"></div>
|
|
50
|
+
<div class="media-lightbox-content">
|
|
51
|
+
<img class="media-lightbox-img" alt="" />
|
|
52
|
+
<div class="media-lightbox-controls">
|
|
53
|
+
<button class="media-lightbox-open" aria-label="Open in browser">↗ Open</button>
|
|
54
|
+
<button class="media-lightbox-close" aria-label="Close">✕</button>
|
|
55
|
+
</div></div>`,document.body.appendChild(e);let t=``,n=()=>e.classList.add(`hidden`),r=()=>{t&&window.open(t,`_blank`)};e.querySelector(`.media-lightbox-backdrop`).addEventListener(`click`,n),e.querySelector(`.media-lightbox-close`).addEventListener(`click`,n),e.querySelector(`.media-lightbox-open`).addEventListener(`click`,r),e.querySelector(`.media-lightbox-img`).addEventListener(`dblclick`,r),document.addEventListener(`keydown`,t=>{t.key===`Escape`&&!e.classList.contains(`hidden`)&&n()}),document.addEventListener(`click`,n=>{let r=n.target;(r.classList.contains(`chat-inline-img`)||r.closest(`.file-preview-list`)&&r.tagName===`IMG`)&&(t=r.src,e.querySelector(`.media-lightbox-img`).src=t,e.classList.remove(`hidden`))})}var Zr=`jaw:stale-bundle-reload-pending`;function Qr(e){let t=typeof e==`string`?e:e instanceof Error||typeof e?.message==`string`?e.message:``;if(!/(failed to fetch dynamically imported module|error loading dynamically imported module|importing a module script failed|chunkloaderror)/i.test(t))return!1;console.warn(`[stale-bundle] detected dynamic import failure:`,t);try{if(sessionStorage.getItem(Zr)===`1`)return!0;sessionStorage.setItem(Zr,`1`)}catch{}let n=()=>window.location.reload();return`serviceWorker`in navigator?(navigator.serviceWorker.getRegistration().then(e=>e?.update()).catch(()=>{}).finally(n),!0):(n(),!0)}window.addEventListener(`unhandledrejection`,e=>{if(Qr(e.reason)){e.preventDefault();return}console.error(`[unhandled]`,e.reason),e.preventDefault()}),window.addEventListener(`error`,e=>{if(Qr(e.error||e.message)){e.preventDefault();return}console.error(`[error]`,e.message,e.filename,e.lineno)});var{loadEmployees:$r,addEmployee:ei,deleteEmployee:ti,updateEmployee:Q,onEmpCliChange:ni,onEmpRoleChange:ri}=await d(async()=>{let{loadEmployees:e,addEmployee:t,deleteEmployee:n,updateEmployee:r,onEmpCliChange:i,onEmpRoleChange:a}=await import(`./employees-DCju7V1x.js`);return{loadEmployees:e,addEmployee:t,deleteEmployee:n,updateEmployee:r,onEmpCliChange:i,onEmpRoleChange:a}},__vite__mapDeps([0]));function ii(e){if(e===window.location.origin)return!0;try{let t=new URL(e).hostname;return t===`localhost`||t===`127.0.0.1`||t===`::1`||t===`[::1]`}catch{return!1}}function ai(e){let t=(e.ctrlKey||e.metaKey)&&e.shiftKey&&e.code===`Space`,n=e.altKey&&!e.ctrlKey&&!e.metaKey&&!e.shiftKey&&e.code===`KeyM`;return t||n}document.getElementById(`btnSend`)?.addEventListener(`click`,()=>{A(`button`)});var oi=document.getElementById(`chatInput`);oi?.addEventListener(`keydown`,e=>{Ve(e)||pn(e)});var $=0;oi?.addEventListener(`input`,e=>{e.isComposing||($&&cancelAnimationFrame($),$=requestAnimationFrame(()=>{Be(e.target?.value||``),$=0}))}),oi?.addEventListener(`cmd-execute`,()=>{A(`cmd-execute`)}),document.getElementById(`cmdDropdown`)?.addEventListener(`click`,ze),document.addEventListener(`click`,Re),u(),Qt(),document.getElementById(`filePreviewClear`)?.addEventListener(`click`,j),document.getElementById(`filePreviewList`)?.addEventListener(`click`,e=>{let t=e.target?.closest(`[data-file-idx]`);t&&gn(+(t.dataset.fileIdx||`0`))}),document.querySelector(`.btn-attach`)?.addEventListener(`click`,()=>{document.getElementById(`fileInput`)?.click()}),document.getElementById(`btnVoice`)?.addEventListener(`click`,()=>Mr()),document.getElementById(`btnVoiceCancel`)?.addEventListener(`click`,()=>jr()),window.addEventListener(`message`,e=>{if(window.parent===window||e.source!==window.parent||!ii(e.origin))return;let t=e.data;!t||t.type!==`jaw-preview-stt-toggle`||Mr()}),document.getElementById(`memorySidebarBtn`)?.addEventListener(`click`,Ut),document.getElementById(`btnClearChat`)?.addEventListener(`click`,vn),document.getElementById(`hbSidebarBtn`)?.addEventListener(`click`,Fn),document.getElementById(`langSelect`)?.addEventListener(`change`,async e=>{let t=e.target.value;[`ko`,`en`,`zh`,`ja`].includes(t)&&(await pe(t),ie())}),document.querySelector(`.tab-bar`)?.addEventListener(`click`,e=>{let t=e.target?.closest(`.tab-btn`);if(!t)return;let n=[...t.parentElement?.children||[]].filter(e=>e.classList.contains(`tab-btn`)).indexOf(t),r=[`agents`,`skills`,`settings`];r[n]&&Ne(r[n],t)}),document.querySelector(`.sidebar-save-bar .btn-save`)?.addEventListener(`click`,Pe);function si(e){let t=(e instanceof HTMLSelectElement?e:document.getElementById(`selCliProvider`))?.value||``,n=document.getElementById(`providerAiE`);!t||!n||Array.from(n.options).some(e=>e.value===t)&&(n.value=t)}document.getElementById(`selCli`)?.addEventListener(`change`,()=>pt()),document.getElementById(`selCliProvider`)?.addEventListener(`change`,e=>{si(e.target),pt(),S()}),document.getElementById(`selModel`)?.addEventListener(`change`,()=>S()),document.getElementById(`selEffort`)?.addEventListener(`change`,()=>S()),document.getElementById(`flushCli`)?.addEventListener(`change`,()=>ht()),document.getElementById(`flushModel`)?.addEventListener(`change`,()=>ht()),document.querySelector(`[data-action="addEmployee"]`)?.addEventListener(`click`,ei),document.getElementById(`employeesList`)?.addEventListener(`click`,e=>{let t=e.target?.closest(`[data-emp-delete]`);if(t){ti(t.dataset.empDelete||``);return}}),document.getElementById(`employeesList`)?.addEventListener(`change`,e=>{let t=e.target,n=t.closest(`[data-emp-name]`);if(n){Q(n.dataset.empName||``,{name:t.value});return}let r=t.closest(`[data-emp-cli]`);if(r){ni(r.dataset.empCli||``,t.value);return}let i=t.closest(`[data-emp-model]`);if(i){if(t.value===`__custom__`){let e=prompt(m(`model.promptInput`));if(e?.trim()){let n=document.createElement(`option`);n.value=e.trim(),n.textContent=e.trim();let r=t.querySelector(`option[value="__custom__"]`);r&&t.insertBefore(n,r),t.value=e.trim(),Q(i.dataset.empModel||``,{model:e.trim()})}else t.value=`default`}else Q(i.dataset.empModel||``,{model:t.value});return}let a=t.closest(`[data-emp-role]`);if(a){ri(a.dataset.empRole||``,t.value);return}let o=t.closest(`[data-emp-custom]`);if(o){Q(o.dataset.empCustom||``,{role:t.value});return}}),document.getElementById(`skillsList`)?.addEventListener(`click`,e=>{let t=e.target?.closest(`[data-skill-id]`);t&&St(t.dataset.skillId||``,t.dataset.skillEnabled===`true`)}),document.querySelector(`#tabSkills`)?.addEventListener(`click`,e=>{let t=e.target?.closest(`.skill-filter`);t&&wt(t.dataset.filter||`all`,t)}),document.getElementById(`skillSearchInput`)?.addEventListener(`input`,e=>{Ct(e.target.value)}),document.querySelector(`[data-action="openPrompt"]`)?.addEventListener(`click`,Lt),document.getElementById(`tgOff`)?.addEventListener(`click`,()=>Qe(!1)),document.getElementById(`tgOn`)?.addEventListener(`click`,()=>Qe(!0)),document.getElementById(`tgForwardOff`)?.addEventListener(`click`,()=>Ze(!1)),document.getElementById(`tgForwardOn`)?.addEventListener(`click`,()=>Ze(!0)),document.getElementById(`tgMentionOff`)?.addEventListener(`click`,()=>rt(!1)),document.getElementById(`tgMentionOn`)?.addEventListener(`click`,()=>rt(!0)),document.getElementById(`tgToken`)?.addEventListener(`change`,Xe),document.getElementById(`tgChatIds`)?.addEventListener(`change`,Xe),document.getElementById(`chTelegram`)?.addEventListener(`click`,()=>b(`telegram`)),document.getElementById(`chDiscord`)?.addEventListener(`click`,()=>b(`discord`)),document.getElementById(`dcOff`)?.addEventListener(`click`,()=>ut(!1)),document.getElementById(`dcOn`)?.addEventListener(`click`,()=>ut(!0)),document.getElementById(`dcForwardOff`)?.addEventListener(`click`,()=>et(!1)),document.getElementById(`dcForwardOn`)?.addEventListener(`click`,()=>et(!0)),document.getElementById(`dcAllowBotsOff`)?.addEventListener(`click`,()=>$e(!1)),document.getElementById(`dcAllowBotsOn`)?.addEventListener(`click`,()=>$e(!0)),document.getElementById(`dcMentionOff`)?.addEventListener(`click`,()=>nt(!1)),document.getElementById(`dcMentionOn`)?.addEventListener(`click`,()=>nt(!0)),document.getElementById(`dcToken`)?.addEventListener(`change`,Ke),document.getElementById(`dcGuildId`)?.addEventListener(`change`,Ke),document.getElementById(`dcChannelIds`)?.addEventListener(`change`,Ke),document.getElementById(`chSlack`)?.addEventListener(`click`,()=>b(`slack`)),document.getElementById(`slOff`)?.addEventListener(`click`,()=>it(!1)),document.getElementById(`slOn`)?.addEventListener(`click`,()=>it(!0)),document.getElementById(`slForwardOff`)?.addEventListener(`click`,()=>Je(!1)),document.getElementById(`slForwardOn`)?.addEventListener(`click`,()=>Je(!0)),document.getElementById(`slAllowBotsOff`)?.addEventListener(`click`,()=>Ye(!1)),document.getElementById(`slAllowBotsOn`)?.addEventListener(`click`,()=>Ye(!0)),document.getElementById(`slMentionOff`)?.addEventListener(`click`,()=>tt(!1)),document.getElementById(`slMentionOn`)?.addEventListener(`click`,()=>tt(!0)),document.getElementById(`slThreadOff`)?.addEventListener(`click`,()=>dt(!1)),document.getElementById(`slThreadOn`)?.addEventListener(`click`,()=>dt(!0)),document.getElementById(`slBotToken`)?.addEventListener(`change`,C),document.getElementById(`slAppToken`)?.addEventListener(`change`,C),document.getElementById(`slTeamId`)?.addEventListener(`change`,C),document.getElementById(`slChannelIds`)?.addEventListener(`change`,C),document.getElementById(`slAttachPort`)?.addEventListener(`change`,C),bt(),qe(),document.getElementById(`fallbackOrderList`)?.addEventListener(`change`,vt);function ci(e){let t=document.getElementById(`codexFastOn`),n=document.getElementById(`codexFastOff`);t&&n&&(t.classList.toggle(`active`,e),n.classList.toggle(`active`,!e)),x()}document.getElementById(`codexFastOn`)?.addEventListener(`click`,()=>ci(!0)),document.getElementById(`codexFastOff`)?.addEventListener(`click`,()=>ci(!1));function li(e){let t=document.getElementById(`codexCtxOn`),n=document.getElementById(`codexCtxOff`),r=document.getElementById(`codexCtxValues`);t&&n&&(t.classList.toggle(`active`,e),n.classList.toggle(`active`,!e)),r&&(r.style.display=e?``:`none`),x()}document.getElementById(`codexCtxOn`)?.addEventListener(`click`,()=>li(!0)),document.getElementById(`codexCtxOff`)?.addEventListener(`click`,()=>li(!1)),document.getElementById(`codexCtxWindow`)?.addEventListener(`change`,x),document.getElementById(`codexCtxCompact`)?.addEventListener(`change`,x);function ui(e){let t=document.getElementById(`claude1mOn`),n=document.getElementById(`claude1mOff`),r=document.getElementById(`modelClaude`),i=e;if(r){let t=r.value||``;if(e&&!t.endsWith(`[1m]`)){let e=t+`[1m]`;Array.from(r.options).some(t=>t.value===e)?r.value=e:i=!1}else if(!e&&t.endsWith(`[1m]`)){let e=t.replace(/\[1m\]$/,``);Array.from(r.options).some(t=>t.value===e)?r.value=e:i=!0}else i=t.endsWith(`[1m]`)}t&&n&&(t.classList.toggle(`active`,i),n.classList.toggle(`active`,!i)),x()}document.getElementById(`claude1mOn`)?.addEventListener(`click`,()=>ui(!0)),document.getElementById(`claude1mOff`)?.addEventListener(`click`,()=>ui(!1));function di(e){return e.split(/[^a-zA-Z0-9]+/).filter(Boolean).map(e=>e.charAt(0).toUpperCase()+e.slice(1)).join(``)}function fi(){for(let e of We()){let t=di(e),n=document.getElementById(`model`+t);n&&n.addEventListener(`change`,function(){mt(e,this)});let r=document.getElementById(`customModel`+t);r&&r.addEventListener(`change`,function(){gt(e,this)});let i=document.getElementById(`effort`+t);i&&i.addEventListener(`change`,x)}document.getElementById(`providerAiE`)?.addEventListener(`change`,ot)}document.querySelector(`[data-action="openMcpModal"]`)?.addEventListener(`click`,_t),document.querySelector(`[data-action="syncMcp"]`)?.addEventListener(`click`,yt),document.querySelector(`[data-action="installMcp"]`)?.addEventListener(`click`,st),ct(),document.querySelector(`[data-action="refreshCli"]`)?.addEventListener(`click`,()=>{Ot()?Nt(!0):Mt()}),document.getElementById(`cliStatusInterval`)?.addEventListener(`change`,function(){kt(this.value)}),document.getElementById(`promptModal`)?.addEventListener(`click`,e=>w(e)),document.querySelector(`#promptModal .modal-box`)?.addEventListener(`click`,e=>e.stopPropagation()),document.querySelector(`[data-action="closePrompt"]`)?.addEventListener(`click`,()=>w()),document.querySelector(`[data-action="cancelPrompt"]`)?.addEventListener(`click`,()=>w()),document.querySelector(`[data-action="savePrompt"]`)?.addEventListener(`click`,Tt),document.addEventListener(`keydown`,e=>{e.key===`Escape`&&!n.isRecording&&w()}),document.querySelector(`[data-action="openTemplates"]`)?.addEventListener(`click`,jt),document.querySelector(`[data-action="saveTemplate"]`)?.addEventListener(`click`,Ft),document.querySelector(`[data-action="closeTemplate"]`)?.addEventListener(`click`,()=>Pt()),document.getElementById(`templateModal`)?.addEventListener(`click`,e=>Pt(e)),document.querySelector(`#templateModal .modal-box`)?.addEventListener(`click`,e=>e.stopPropagation()),document.getElementById(`templateBack`)?.addEventListener(`click`,Rt),document.getElementById(`templateDevToggle`)?.addEventListener(`click`,Et);var{openPiSettingsModal:pi,closePiSettingsModal:mi,registerPiProfile:hi,onPiModeChange:gi,syncPiModelDropdown:_i,getCachedPi:vi}=await d(async()=>{let{openPiSettingsModal:e,closePiSettingsModal:t,registerPiProfile:n,onPiModeChange:r,syncPiModelDropdown:i,getCachedPi:a}=await import(`./pi-settings-5HVg1sXJ.js`);return{openPiSettingsModal:e,closePiSettingsModal:t,registerPiProfile:n,onPiModeChange:r,syncPiModelDropdown:i,getCachedPi:a}},[]);document.getElementById(`btnPiSettings`)?.addEventListener(`click`,pi),document.getElementById(`piSettingsModal`)?.addEventListener(`click`,e=>{e.target===e.currentTarget&&mi()}),document.querySelector(`#piSettingsModal .modal-box`)?.addEventListener(`click`,e=>e.stopPropagation()),document.querySelector(`[data-action="closePiSettings"]`)?.addEventListener(`click`,mi),document.getElementById(`btnPiRegister`)?.addEventListener(`click`,()=>void hi()),document.getElementById(`piMode`)?.addEventListener(`change`,gi),document.getElementById(`providerPi`)?.addEventListener(`change`,async()=>{let e=document.getElementById(`providerPi`);if(e?.value){_i(e.value,vi());let{savePerCli:t}=await d(async()=>{let{savePerCli:e}=await import(`./settings-core-Cm-CmVLA.js`);return{savePerCli:e}},__vite__mapDeps([0]));await t()}}),document.getElementById(`heartbeatModal`)?.addEventListener(`click`,e=>In(e)),document.querySelector(`#heartbeatModal .modal-box`)?.addEventListener(`click`,e=>e.stopPropagation()),document.querySelector(`[data-action="closeHeartbeat"]`)?.addEventListener(`click`,()=>In()),document.querySelector(`[data-action="addHeartbeat"]`)?.addEventListener(`click`,Rn),document.getElementById(`hbJobsList`)?.addEventListener(`click`,e=>{let t=e.target?.closest(`[data-hb-toggle]`);if(t){Bn(+(t.dataset.hbToggle||`0`));return}let n=e.target?.closest(`[data-hb-remove]`);if(n){zn(+(n.dataset.hbRemove||`0`));return}}),document.getElementById(`hbJobsList`)?.addEventListener(`change`,e=>{let t=e.target,r=t.closest(`[data-hb-name]`);if(r){n.heartbeatJobs[+(r.dataset.hbName||`0`)].name=t.value,F();return}let i=t.closest(`[data-hb-kind]`);if(i){let e=+(i.dataset.hbKind||`0`),r=n.heartbeatJobs[e]?.schedule,a=typeof r?.timeZone==`string`?r.timeZone:void 0;n.heartbeatJobs[e].schedule=t.value===`cron`?{kind:`cron`,cron:typeof r?.cron==`string`&&r.cron.trim()?r.cron:`0 9 * * *`,...a?{timeZone:a}:{}}:{kind:`every`,minutes:typeof r?.minutes==`number`&&r.minutes>0?Math.floor(r.minutes):5,...a?{timeZone:a}:{}},P(),F();return}let a=t.closest(`[data-hb-minutes]`);if(a){let e=+(a.dataset.hbMinutes||`0`),r=n.heartbeatJobs[e]?.schedule,i=Math.max(1,Math.floor(Number(t.value)||5)),o=typeof r?.timeZone==`string`?r.timeZone:void 0;n.heartbeatJobs[e].schedule={kind:`every`,minutes:i,...o?{timeZone:o}:{}},P(),F();return}let o=t.closest(`[data-hb-cron]`);if(o){let e=+(o.dataset.hbCron||`0`),r=n.heartbeatJobs[e]?.schedule,i=typeof r?.timeZone==`string`?r.timeZone:void 0,a=t.value.trim().replace(/\s+/g,` `);n.heartbeatJobs[e].schedule={kind:`cron`,cron:a,...i?{timeZone:i}:{}},P(),F();return}let s=t.closest(`[data-hb-timezone]`);if(s){let e=+(s.dataset.hbTimezone||`0`),r=n.heartbeatJobs[e]?.schedule;r?.kind===`cron`?n.heartbeatJobs[e].schedule={kind:`cron`,cron:typeof r.cron==`string`&&r.cron.trim()?r.cron:`0 9 * * *`,...t.value.trim()?{timeZone:t.value.trim()}:{}}:n.heartbeatJobs[e].schedule={kind:`every`,minutes:typeof r?.minutes==`number`&&r.minutes>0?Math.floor(r.minutes):5,...t.value.trim()?{timeZone:t.value.trim()}:{}},P(),F();return}let c=t.closest(`[data-hb-prompt]`);if(c){n.heartbeatJobs[+(c.dataset.hbPrompt||`0`)].prompt=t.value,F();return}}),document.getElementById(`memoryModal`)?.addEventListener(`click`,e=>Zt(e)),document.querySelector(`#memoryModal .modal-box`)?.addEventListener(`click`,e=>e.stopPropagation()),document.querySelector(`[data-action="closeMemory"]`)?.addEventListener(`click`,()=>Zt()),document.getElementById(`memTabBtnSettings`)?.addEventListener(`click`,()=>E(`settings`)),document.getElementById(`memTabBtnAdvOps`)?.addEventListener(`click`,()=>E(`status`)),document.getElementById(`memTabBtnFiles`)?.addEventListener(`click`,()=>E(`files`)),document.getElementById(`memOn`)?.addEventListener(`click`,()=>Wt(!0)),document.getElementById(`memOff`)?.addEventListener(`click`,()=>Wt(!1)),document.getElementById(`memFlushEvery`)?.addEventListener(`change`,T),document.getElementById(`memRetention`)?.addEventListener(`change`,T),document.getElementById(`memFlushLang`)?.addEventListener(`change`,T),document.getElementById(`memFlushNowBtn`)?.addEventListener(`click`,Ht),document.getElementById(`advBootstrapBtn`)?.addEventListener(`click`,Xt),document.getElementById(`advReindexBtn`)?.addEventListener(`click`,qt),document.getElementById(`advReimportBtn`)?.addEventListener(`click`,Xt),document.getElementById(`advOpenCorruptedBtn`)?.addEventListener(`click`,Yt),document.getElementById(`advStatusBanner`)?.addEventListener(`click`,e=>{e.target?.id===`advUpgradeSoulBtn`&&Jt(),e.target?.id===`advSynthesizeSoulBtn`&&Vt()}),document.getElementById(`basicMemoryFiles`)?.addEventListener(`click`,e=>{let t=e.target?.closest(`[data-mem-delete]`);if(t){e.stopPropagation(),Kt(t.dataset.memDelete||``);return}let n=e.target?.closest(`[data-mem-view]`);if(n){Gt(n.dataset.memView||``);return}if(e.target?.closest(`[data-mem-back]`)){Ut();return}});async function yi(){se(),xt(),$n(),or(),Se(),Ce(),await fe();let e=await ge({cancelRecording:jr});if(e===`redirect`)return;ee(xe);let t=document.getElementById(`langSelect`);if(t&&(t.value=de()),Le(),e===`hub`){oe(),c();return}if(Rr(),Xr(),document.getElementById(`chatSearchTrigger`)?.addEventListener(`click`,zr),oe(),c(),await Ge(),fi(),Sn(),xn(),await Ie(),await at(),lt(),At(),Dt(),zt(),Ot()&&Nt(),ae(),$r(),Vn(),Bt(),ke(),await Oe(),Me(),fr(),window.location.hash===`#settings`){let e=document.getElementById(`tabBtnSettings`);e&&Ne(`settings`,e)}try{sessionStorage.removeItem(Zr)}catch{}setTimeout(()=>{document.querySelector(`.mermaid-pending, [data-mermaid-code-raw], .diagram-widget-pending`)&&ce()},3e3),`serviceWorker`in navigator&&!It()&&navigator.serviceWorker.register(`/sw.js`).catch(()=>{})}yi().catch(e=>{console.error(`[bootstrap]`,e)}),document.addEventListener(`keydown`,e=>{(e.ctrlKey||e.metaKey)&&e.key===`f`&&(e.preventDefault(),e.stopPropagation(),zr())},!0),document.addEventListener(`keydown`,e=>{if(e.key===`Escape`){if(document.getElementById(`chatSearch`)?.classList.contains(`open`)){e.preventDefault(),Z();return}if(n.isRecording){e.preventDefault(),jr();return}document.querySelectorAll(`.modal-overlay.open`).forEach(e=>{e.classList.remove(`open`)})}ai(e)&&(e.preventDefault(),Mr())}),document.getElementById(`mobileMenuLeft`)?.addEventListener(`click`,re),document.getElementById(`mobileMenuRight`)?.addEventListener(`click`,te);
|
package/public/dist/index.html
CHANGED
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
href="https://fonts.googleapis.com/css2?family=Chakra+Petch:wght@400;500;600;700&family=Outfit:wght@400;500;600;700&display=swap"
|
|
32
32
|
rel="stylesheet">
|
|
33
33
|
<!-- Vite handles module bundling in dev (HMR) and production (build) -->
|
|
34
|
-
<script type="module" crossorigin src="/dist/assets/app-
|
|
34
|
+
<script type="module" crossorigin src="/dist/assets/app-DUwWnKh3.js"></script>
|
|
35
35
|
<link rel="stylesheet" crossorigin href="/dist/assets/vendor-render-kIxHrxDV.css">
|
|
36
36
|
<link rel="stylesheet" crossorigin href="/dist/assets/app-DuyLYRC6.css">
|
|
37
37
|
</head>
|
|
@@ -80,9 +80,21 @@ export function renderHeartbeatJobs(): void {
|
|
|
80
80
|
if (btn) btn.innerHTML = `${ICONS.heartPulse} Heartbeat (${active})`;
|
|
81
81
|
}
|
|
82
82
|
|
|
83
|
+
/** Ids must be unique across one save.
|
|
84
|
+
*
|
|
85
|
+
* `Date.now()` alone is not enough. `normalizeHeartbeatJob` runs inside a
|
|
86
|
+
* `.map()`, so two jobs missing an id in the same millisecond both become
|
|
87
|
+
* `hb_<same-ms>`; two quick clicks on add-job collide the same way. The server
|
|
88
|
+
* rejects a duplicate id now — two jobs under one id share one mention-watch
|
|
89
|
+
* ledger namespace and the second inherits the first's cursor — so a collision
|
|
90
|
+
* that used to silently merge two jobs would fail the entire save. */
|
|
91
|
+
let idCounter = 0;
|
|
92
|
+
|
|
83
93
|
export function addHeartbeatJob(): void {
|
|
84
94
|
(state.heartbeatJobs as HeartbeatJob[]).push({
|
|
85
|
-
|
|
95
|
+
// Same-millisecond collision matters here too: two quick clicks on
|
|
96
|
+
// 'add job' would otherwise produce one id twice.
|
|
97
|
+
id: `hb_${Date.now()}_${idCounter++}`,
|
|
86
98
|
name: '',
|
|
87
99
|
enabled: true,
|
|
88
100
|
schedule: withBrowserTimeZone({ kind: 'every', minutes: 5 }),
|
|
@@ -134,7 +146,7 @@ export async function initHeartbeatBadge(): Promise<void> {
|
|
|
134
146
|
|
|
135
147
|
function normalizeHeartbeatJob(job: HeartbeatJob): HeartbeatJob {
|
|
136
148
|
return {
|
|
137
|
-
id: String(job.id || `hb_${Date.now()}`),
|
|
149
|
+
id: String(job.id || `hb_${Date.now()}_${idCounter++}`),
|
|
138
150
|
name: String(job.name || ''),
|
|
139
151
|
enabled: job.enabled !== false,
|
|
140
152
|
schedule: normalizeSchedule(job.schedule),
|