atris 3.56.0 → 3.56.1
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/atris/skills/engines/SKILL.md +11 -3
- package/atris/skills/x-search/SKILL.md +20 -1
- package/atris/skills/youtube/SKILL.md +51 -43
- package/bin/atris.js +119 -87
- package/commands/autopilot-front.js +29 -13
- package/commands/brainstorm.js +77 -476
- package/commands/business.js +13 -1
- package/commands/fleet-report.js +2 -2
- package/commands/human-missions.js +26 -2
- package/commands/init.js +2 -35
- package/commands/integrations.js +100 -0
- package/commands/land.js +53 -23
- package/commands/later.js +52 -0
- package/commands/log.js +79 -30
- package/commands/mission.js +117 -22
- package/commands/next.js +153 -63
- package/commands/now.js +80 -38
- package/commands/recap.js +66 -4
- package/commands/run-front.js +20 -5
- package/commands/spaceship.js +52 -12
- package/commands/status.js +30 -7
- package/commands/task.js +56 -19
- package/commands/terminal.js +5 -5
- package/commands/workflow.js +18 -5
- package/commands/x-search.js +123 -13
- package/commands/youtube.js +639 -36
- package/lib/account-bound.js +7 -0
- package/lib/apply-gate.js +94 -0
- package/lib/context-gatherer.js +55 -8
- package/lib/engine-ask.js +16 -6
- package/lib/first-minute.js +552 -26
- package/lib/known-commands.js +1 -1
- package/lib/runner-command.js +5 -3
- package/lib/scratch-root.js +44 -0
- package/package.json +1 -1
- package/utils/auth.js +9 -0
package/commands/x-search.js
CHANGED
|
@@ -2,9 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
const { apiRequestJson } = require('../utils/api');
|
|
4
4
|
const { ensureBilledCommandAuth } = require('./auth');
|
|
5
|
+
const applyGate = require('../lib/apply-gate');
|
|
5
6
|
|
|
6
7
|
const DEFAULT_TIMEOUT_MS = 120000;
|
|
7
8
|
const COST_HINT = '5 credits per search';
|
|
9
|
+
const APPLY_NEXT_MESSAGE =
|
|
10
|
+
'next: write one apply (change + receipt) for this query.';
|
|
8
11
|
|
|
9
12
|
function showXSearchHelp(output = console.log, commandName = 'atris x-search') {
|
|
10
13
|
output('');
|
|
@@ -13,6 +16,7 @@ function showXSearchHelp(output = console.log, commandName = 'atris x-search') {
|
|
|
13
16
|
output('');
|
|
14
17
|
output(`Search X/Twitter via Atris (${COST_HINT}).`);
|
|
15
18
|
output('Requires login. Same auth path as atris youtube process.');
|
|
19
|
+
output('Empty or failed search refunds the credits.');
|
|
16
20
|
output('');
|
|
17
21
|
output('Options:');
|
|
18
22
|
output(' --limit <n> Max results hint (search only)');
|
|
@@ -213,6 +217,58 @@ function resultErrorText(result) {
|
|
|
213
217
|
}
|
|
214
218
|
}
|
|
215
219
|
|
|
220
|
+
function unwrapXSearchPayload(data) {
|
|
221
|
+
return data?.data && typeof data.data === 'object' ? data.data : data;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
function xSearchContent(data) {
|
|
225
|
+
const payload = unwrapXSearchPayload(data);
|
|
226
|
+
return payload?.content != null ? String(payload.content).trim() : '';
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
function xSearchCitations(data) {
|
|
230
|
+
const payload = unwrapXSearchPayload(data);
|
|
231
|
+
if (Array.isArray(payload?.citations)) return payload.citations;
|
|
232
|
+
if (Array.isArray(data?.citations)) return data.citations;
|
|
233
|
+
return [];
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
function xSearchCredits(data) {
|
|
237
|
+
if (!data || typeof data !== 'object') {
|
|
238
|
+
return { used: undefined, remaining: undefined, refunded: undefined };
|
|
239
|
+
}
|
|
240
|
+
const payload = unwrapXSearchPayload(data) || {};
|
|
241
|
+
const used = data.credits_used !== undefined ? data.credits_used : payload.credits_used;
|
|
242
|
+
const remaining = data.credits_remaining !== undefined
|
|
243
|
+
? data.credits_remaining
|
|
244
|
+
: payload.credits_remaining;
|
|
245
|
+
let refunded = data.credits_refunded !== undefined
|
|
246
|
+
? data.credits_refunded
|
|
247
|
+
: payload.credits_refunded;
|
|
248
|
+
if (refunded === undefined && (data.refunded === true || payload.refunded === true)) {
|
|
249
|
+
refunded = true;
|
|
250
|
+
}
|
|
251
|
+
return { used, remaining, refunded };
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
function creditsWereRefunded(credits) {
|
|
255
|
+
if (!credits) return false;
|
|
256
|
+
if (credits.used === 0) return true;
|
|
257
|
+
if (credits.refunded === true) return true;
|
|
258
|
+
return typeof credits.refunded === 'number' && credits.refunded > 0;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
function formatCreditsLines(credits) {
|
|
262
|
+
const lines = [];
|
|
263
|
+
if (credits.used !== undefined || credits.remaining !== undefined) {
|
|
264
|
+
lines.push(`Credits: ${credits.used !== undefined ? credits.used : '?'} used, ${credits.remaining !== undefined ? credits.remaining : '?'} remaining`);
|
|
265
|
+
}
|
|
266
|
+
if (creditsWereRefunded(credits)) {
|
|
267
|
+
lines.push('credits refunded');
|
|
268
|
+
}
|
|
269
|
+
return lines;
|
|
270
|
+
}
|
|
271
|
+
|
|
216
272
|
function xSearchFailureError(result) {
|
|
217
273
|
const hint = result.status === 401
|
|
218
274
|
? ' Run "atris login --force".'
|
|
@@ -221,7 +277,13 @@ function xSearchFailureError(result) {
|
|
|
221
277
|
: result.status === 502
|
|
222
278
|
? ' xAI is unavailable; retry in a few seconds.'
|
|
223
279
|
: '';
|
|
224
|
-
|
|
280
|
+
const credits = xSearchCredits(result.data);
|
|
281
|
+
const refundHint = result.status === 502 && creditsWereRefunded(credits)
|
|
282
|
+
? ' credits refunded.'
|
|
283
|
+
: '';
|
|
284
|
+
const lines = [`X search failed (${result.status}): ${resultErrorText(result)}.${hint}${refundHint}`];
|
|
285
|
+
lines.push(...formatCreditsLines(credits));
|
|
286
|
+
return new Error(lines.join('\n'));
|
|
225
287
|
}
|
|
226
288
|
|
|
227
289
|
async function ensureToken(deps = {}) {
|
|
@@ -265,13 +327,35 @@ async function runXSearch(options, deps = {}) {
|
|
|
265
327
|
return result.data;
|
|
266
328
|
}
|
|
267
329
|
|
|
330
|
+
function xSearchApplySource(options) {
|
|
331
|
+
if (options?.mode === 'person') return options.name;
|
|
332
|
+
return options?.query;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
function xSearchApplyRel(source) {
|
|
336
|
+
return applyGate.applySidecarRel('x-search', applyGate.applySlug(source));
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
function xSearchHasResults(data) {
|
|
340
|
+
return Boolean(xSearchContent(data)) || xSearchCitations(data).length > 0;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
function ensureXSearchApply({ cwd, source, now, output } = {}) {
|
|
344
|
+
return applyGate.ensureApply({
|
|
345
|
+
cwd,
|
|
346
|
+
source,
|
|
347
|
+
rel: source ? xSearchApplyRel(source) : null,
|
|
348
|
+
now,
|
|
349
|
+
output,
|
|
350
|
+
incompleteMessage: APPLY_NEXT_MESSAGE,
|
|
351
|
+
required: false,
|
|
352
|
+
});
|
|
353
|
+
}
|
|
354
|
+
|
|
268
355
|
function formatXSearchResult(data) {
|
|
269
356
|
const lines = [];
|
|
270
|
-
const
|
|
271
|
-
const
|
|
272
|
-
const citations = Array.isArray(payload?.citations)
|
|
273
|
-
? payload.citations
|
|
274
|
-
: (Array.isArray(data?.citations) ? data.citations : []);
|
|
357
|
+
const content = xSearchContent(data);
|
|
358
|
+
const citations = xSearchCitations(data);
|
|
275
359
|
|
|
276
360
|
if (content) {
|
|
277
361
|
lines.push(content);
|
|
@@ -289,18 +373,25 @@ function formatXSearchResult(data) {
|
|
|
289
373
|
}
|
|
290
374
|
}
|
|
291
375
|
|
|
292
|
-
const
|
|
293
|
-
|
|
294
|
-
? data.credits_remaining
|
|
295
|
-
: payload?.credits_remaining;
|
|
296
|
-
if (used !== undefined || remaining !== undefined) {
|
|
376
|
+
const creditLines = formatCreditsLines(xSearchCredits(data));
|
|
377
|
+
if (creditLines.length) {
|
|
297
378
|
lines.push('');
|
|
298
|
-
lines.push(
|
|
379
|
+
lines.push(...creditLines);
|
|
299
380
|
}
|
|
300
381
|
|
|
301
382
|
return lines.join('\n');
|
|
302
383
|
}
|
|
303
384
|
|
|
385
|
+
function formatEmptyXSearchResult(data) {
|
|
386
|
+
const lines = ['no results'];
|
|
387
|
+
const creditLines = formatCreditsLines(xSearchCredits(data));
|
|
388
|
+
if (creditLines.length) {
|
|
389
|
+
lines.push('');
|
|
390
|
+
lines.push(...creditLines);
|
|
391
|
+
}
|
|
392
|
+
return lines.join('\n');
|
|
393
|
+
}
|
|
394
|
+
|
|
304
395
|
async function xSearchCommand(argv = process.argv.slice(3), deps = {}) {
|
|
305
396
|
const output = deps.output || ((line = '') => console.log(line));
|
|
306
397
|
let options;
|
|
@@ -319,7 +410,23 @@ async function xSearchCommand(argv = process.argv.slice(3), deps = {}) {
|
|
|
319
410
|
let status = 0;
|
|
320
411
|
try {
|
|
321
412
|
const data = await runXSearch(options, deps);
|
|
322
|
-
|
|
413
|
+
const hasResults = xSearchHasResults(data);
|
|
414
|
+
if (options.json) {
|
|
415
|
+
output(JSON.stringify(data, null, 2));
|
|
416
|
+
} else {
|
|
417
|
+
output(hasResults ? formatXSearchResult(data) : formatEmptyXSearchResult(data));
|
|
418
|
+
}
|
|
419
|
+
if (hasResults) {
|
|
420
|
+
const ensureApply = deps.ensureApply || ensureXSearchApply;
|
|
421
|
+
status = ensureApply({
|
|
422
|
+
cwd: deps.cwd || process.cwd(),
|
|
423
|
+
source: xSearchApplySource(options),
|
|
424
|
+
now: deps.applyNow,
|
|
425
|
+
output,
|
|
426
|
+
});
|
|
427
|
+
} else {
|
|
428
|
+
status = 2;
|
|
429
|
+
}
|
|
323
430
|
} catch (err) {
|
|
324
431
|
output(err.message);
|
|
325
432
|
status = 1;
|
|
@@ -332,9 +439,12 @@ async function xSearchCommand(argv = process.argv.slice(3), deps = {}) {
|
|
|
332
439
|
|
|
333
440
|
module.exports = {
|
|
334
441
|
DEFAULT_TIMEOUT_MS,
|
|
442
|
+
APPLY_NEXT_MESSAGE,
|
|
335
443
|
parseXSearchArgs,
|
|
336
444
|
buildSearchPayload,
|
|
337
445
|
buildPersonPayload,
|
|
338
446
|
formatXSearchResult,
|
|
447
|
+
xSearchHasResults,
|
|
448
|
+
xSearchApplyRel,
|
|
339
449
|
xSearchCommand,
|
|
340
450
|
};
|