atris 3.30.12 → 3.31.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +16 -3
- package/FOR_AGENTS.md +81 -0
- package/README.md +3 -1
- package/atris/atris.md +51 -19
- package/atris/skills/README.md +1 -0
- package/atris/skills/blocks/SKILL.md +134 -0
- package/atris/skills/clawhub/philosophy-of-work/SKILL.md +56 -0
- package/atris/skills/youtube/SKILL.md +31 -11
- package/atris.md +7 -0
- package/ax +95 -3
- package/bin/atris.js +126 -153
- package/commands/autoland.js +319 -0
- package/commands/autopilot.js +94 -4
- package/commands/business.js +1 -1
- package/commands/clean.js +72 -9
- package/commands/codex-goal.js +72 -22
- package/commands/computer.js +48 -3
- package/commands/gm.js +1 -1
- package/commands/harvest.js +179 -0
- package/commands/init.js +1 -1
- package/commands/land.js +442 -0
- package/commands/loop-front.js +122 -4
- package/commands/member.js +519 -19
- package/commands/mission.js +3330 -290
- package/commands/play.js +1 -1
- package/commands/pulse.js +65 -7
- package/commands/run.js +3 -3
- package/commands/strings.js +301 -0
- package/commands/task.js +575 -102
- package/commands/truth.js +170 -0
- package/commands/xp.js +32 -8
- package/commands/youtube.js +72 -5
- package/decks/README.md +6 -12
- package/lib/auto-accept-certified.js +10 -0
- package/lib/autoland.js +283 -0
- package/lib/context-gatherer.js +0 -8
- package/lib/mission-artifact.js +504 -0
- package/lib/mission-room.js +846 -0
- package/lib/next-moves.js +212 -6
- package/lib/pulse.js +74 -1
- package/lib/runner-command.js +20 -8
- package/lib/runs-prune.js +242 -0
- package/lib/task-proof.js +1 -1
- package/package.json +3 -3
- package/decks/atris-seed-pitch-v3.json +0 -118
- package/decks/atris-seed-pitch-v4-skeleton.json +0 -106
- package/decks/atris-seed-pitch-v5.json +0 -109
- package/decks/atris-seed-pitch-v6.json +0 -137
- package/decks/atris-seed-pitch-v7.json +0 -133
- package/decks/mark-pincus-narrative.json +0 -102
- package/decks/mark-pincus-sourcery.json +0 -94
- package/decks/yash-applied-compute-detailed.json +0 -150
- package/decks/yash-applied-compute-generalist.json +0 -82
- package/decks/yash-applied-compute-narrative.json +0 -54
- package/lib/ax-chat-input.js +0 -164
- package/lib/ax-goal.js +0 -307
- package/lib/ax-prefs.js +0 -63
- package/lib/ax-shimmer.js +0 -63
package/lib/ax-goal.js
DELETED
|
@@ -1,307 +0,0 @@
|
|
|
1
|
-
const GOAL_CLEAR_ALIASES = new Set(['clear', 'stop', 'off', 'reset', 'none', 'cancel']);
|
|
2
|
-
const GOAL_ACHIEVED_RE = /^\s*GOAL_ACHIEVED:\s*(.+)$/im;
|
|
3
|
-
const GOAL_JSON_RE = /\{[\s\S]*"achieved"\s*:\s*(true|false)[\s\S]*\}/i;
|
|
4
|
-
|
|
5
|
-
function parseTokenBudget(raw) {
|
|
6
|
-
const text = String(raw || '').trim().toUpperCase();
|
|
7
|
-
const match = text.match(/^(\d+(?:\.\d+)?)([KMB])?$/);
|
|
8
|
-
if (!match) return null;
|
|
9
|
-
let value = Number(match[1]);
|
|
10
|
-
if (match[2] === 'K') value *= 1000;
|
|
11
|
-
if (match[2] === 'M') value *= 1000000;
|
|
12
|
-
if (match[2] === 'B') value *= 1000000000;
|
|
13
|
-
return Math.round(value);
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
function parseGoalCommand(line) {
|
|
17
|
-
const raw = String(line || '').trim();
|
|
18
|
-
const lower = raw.toLowerCase();
|
|
19
|
-
if (!lower.startsWith('/goal')) return null;
|
|
20
|
-
|
|
21
|
-
const rest = raw.slice(5).trim();
|
|
22
|
-
if (!rest) return { action: 'status' };
|
|
23
|
-
|
|
24
|
-
const firstWord = rest.split(/\s+/)[0].toLowerCase();
|
|
25
|
-
if (GOAL_CLEAR_ALIASES.has(firstWord)) return { action: 'clear' };
|
|
26
|
-
|
|
27
|
-
let condition = rest;
|
|
28
|
-
let tokenBudget = null;
|
|
29
|
-
const tokensMatch = condition.match(/^--tokens\s+(\S+)\s+([\s\S]+)$/i);
|
|
30
|
-
if (tokensMatch) {
|
|
31
|
-
tokenBudget = parseTokenBudget(tokensMatch[1]);
|
|
32
|
-
condition = tokensMatch[2].trim();
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
const maxTurnsMatch = condition.match(/\b(?:max|stop after|within)\s+(\d+)\s+turns?\b/i);
|
|
36
|
-
const maxTurns = maxTurnsMatch ? Number(maxTurnsMatch[1]) : null;
|
|
37
|
-
|
|
38
|
-
if (!condition) return { action: 'status' };
|
|
39
|
-
return { action: 'set', condition, maxTurns, tokenBudget };
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
function createGoalState(condition, options = {}) {
|
|
43
|
-
return {
|
|
44
|
-
active: true,
|
|
45
|
-
condition: String(condition || '').trim(),
|
|
46
|
-
maxTurns: Number.isFinite(options.maxTurns) ? options.maxTurns : null,
|
|
47
|
-
tokenBudget: Number.isFinite(options.tokenBudget) ? options.tokenBudget : null,
|
|
48
|
-
turns: 0,
|
|
49
|
-
evalTurns: 0,
|
|
50
|
-
tokensUsed: 0,
|
|
51
|
-
creditsUsed: 0,
|
|
52
|
-
startedAt: Date.now(),
|
|
53
|
-
lastReason: 'Goal started — working toward the condition.',
|
|
54
|
-
achieved: false,
|
|
55
|
-
achievedAt: null,
|
|
56
|
-
};
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
function goalElapsedMs(goal) {
|
|
60
|
-
const end = goal.achievedAt || Date.now();
|
|
61
|
-
return Math.max(0, end - (goal.startedAt || end));
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
function truncateGoalText(text, limit = 72) {
|
|
65
|
-
const value = String(text || '').trim();
|
|
66
|
-
if (value.length <= limit) return value;
|
|
67
|
-
return `${value.slice(0, limit - 1)}…`;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
function compactGoalHistory(history = [], limit = 8) {
|
|
71
|
-
return history
|
|
72
|
-
.slice(-limit)
|
|
73
|
-
.map(turn => `${turn.role}: ${String(turn.content || '').slice(0, 900)}`)
|
|
74
|
-
.join('\n');
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
function buildGoalDirective(goal, options = {}) {
|
|
78
|
-
const condition = goal.condition;
|
|
79
|
-
const reason = goal.lastReason && goal.turns > 0
|
|
80
|
-
? `\nEvaluator guidance from last turn: ${goal.lastReason}`
|
|
81
|
-
: '';
|
|
82
|
-
return [
|
|
83
|
-
'Work autonomously toward this completion condition:',
|
|
84
|
-
condition,
|
|
85
|
-
'',
|
|
86
|
-
'Use local tools as needed. Do not ask the user for permission between steps.',
|
|
87
|
-
'Do not declare the goal achieved yourself — a separate evaluator decides that.',
|
|
88
|
-
reason,
|
|
89
|
-
options.continue ? '\nContinue from the recent conversation below.' : '',
|
|
90
|
-
].filter(Boolean).join('\n');
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
function buildGoalEvalPrompt(goal, history, lastOutput) {
|
|
94
|
-
return [
|
|
95
|
-
'You are a strict goal evaluator for a coding agent session.',
|
|
96
|
-
'Reply with JSON only: {"achieved": true|false, "reason": "short reason"}',
|
|
97
|
-
'Judge only from observable evidence in the transcript and latest output.',
|
|
98
|
-
'If the condition requires command output or file contents, require proof in the transcript.',
|
|
99
|
-
'',
|
|
100
|
-
`Goal condition: ${goal.condition}`,
|
|
101
|
-
'',
|
|
102
|
-
'Recent conversation:',
|
|
103
|
-
compactGoalHistory(history),
|
|
104
|
-
'',
|
|
105
|
-
'Latest assistant output:',
|
|
106
|
-
String(lastOutput || '').slice(0, 4000),
|
|
107
|
-
].join('\n');
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
function parseGoalEvalResponse(text) {
|
|
111
|
-
const raw = String(text || '').trim();
|
|
112
|
-
if (!raw) return null;
|
|
113
|
-
|
|
114
|
-
const marker = raw.match(GOAL_ACHIEVED_RE);
|
|
115
|
-
if (marker) {
|
|
116
|
-
return { achieved: true, reason: marker[1].trim() };
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
const jsonMatch = raw.match(GOAL_JSON_RE);
|
|
120
|
-
if (!jsonMatch) return null;
|
|
121
|
-
try {
|
|
122
|
-
const parsed = JSON.parse(jsonMatch[0]);
|
|
123
|
-
return {
|
|
124
|
-
achieved: parsed.achieved === true,
|
|
125
|
-
reason: String(parsed.reason || '').trim() || (parsed.achieved ? 'Condition met.' : 'Condition not met yet.'),
|
|
126
|
-
};
|
|
127
|
-
} catch {
|
|
128
|
-
return null;
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
function parseGoalAchievedMarker(text) {
|
|
133
|
-
const marker = String(text || '').match(GOAL_ACHIEVED_RE);
|
|
134
|
-
if (!marker) return null;
|
|
135
|
-
return { achieved: true, reason: marker[1].trim() };
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
function accumulateGoalUsage(goal, result, creditsFromState) {
|
|
139
|
-
if (!goal || !result) return;
|
|
140
|
-
const credits = typeof creditsFromState === 'function' ? creditsFromState(result) : null;
|
|
141
|
-
if (Number.isFinite(credits) && credits > 0) {
|
|
142
|
-
goal.creditsUsed += credits;
|
|
143
|
-
}
|
|
144
|
-
const approxTokens = Math.max(0, Math.round(String(result.output || '').length / 4));
|
|
145
|
-
goal.tokensUsed += approxTokens;
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
function goalBudgetExceeded(goal) {
|
|
149
|
-
if (!goal || !Number.isFinite(goal.tokenBudget)) return false;
|
|
150
|
-
return goal.tokensUsed >= goal.tokenBudget;
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
function goalTurnLimitReached(goal) {
|
|
154
|
-
if (!goal || !Number.isFinite(goal.maxTurns)) return false;
|
|
155
|
-
return goal.turns >= goal.maxTurns;
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
function clearGoalState(goal) {
|
|
159
|
-
if (!goal) return null;
|
|
160
|
-
goal.active = false;
|
|
161
|
-
return goal;
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
function finishGoalAchieved(goal, reason) {
|
|
165
|
-
goal.active = false;
|
|
166
|
-
goal.achieved = true;
|
|
167
|
-
goal.achievedAt = Date.now();
|
|
168
|
-
goal.lastReason = reason || 'Condition met.';
|
|
169
|
-
return goal;
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
function formatGoalCounter(goal) {
|
|
173
|
-
const turns = `${goal.turns}${Number.isFinite(goal.maxTurns) ? `/${goal.maxTurns}` : ''}`;
|
|
174
|
-
const duration = `${Math.max(1, Math.round(goalElapsedMs(goal) / 1000))}s`;
|
|
175
|
-
const usage = [];
|
|
176
|
-
if (goal.creditsUsed > 0) usage.push(`${goal.creditsUsed} credits`);
|
|
177
|
-
if (goal.tokensUsed > 0) usage.push(`~${goal.tokensUsed} tokens`);
|
|
178
|
-
return { turns, duration, usage: usage.join(' · ') };
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
function formatGoalStatus(goal, options = {}) {
|
|
182
|
-
const paint = options.paint || ((text) => String(text));
|
|
183
|
-
if (!goal) {
|
|
184
|
-
return 'No active goal. Set one with /goal <condition>.';
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
const counter = formatGoalCounter(goal);
|
|
188
|
-
const lines = [];
|
|
189
|
-
|
|
190
|
-
if (goal.active) {
|
|
191
|
-
lines.push(paint('◎ /goal active', [options.bold, options.magenta]));
|
|
192
|
-
lines.push(paint(goal.condition, [options.bold]));
|
|
193
|
-
lines.push(paint(`turn ${counter.turns} · ${counter.duration}${counter.usage ? ` · ${counter.usage}` : ''}`, [options.muted]));
|
|
194
|
-
if (goal.lastReason) lines.push(paint(`reason: ${goal.lastReason}`, [options.muted]));
|
|
195
|
-
if (Number.isFinite(goal.tokenBudget)) {
|
|
196
|
-
lines.push(paint(`budget: ~${goal.tokensUsed}/${goal.tokenBudget} tokens`, [options.muted]));
|
|
197
|
-
}
|
|
198
|
-
return lines.join('\n');
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
if (goal.achieved) {
|
|
202
|
-
lines.push(paint('✦ /goal achieved', [options.bold, options.ok || options.magenta]));
|
|
203
|
-
lines.push(paint(goal.condition, [options.bold]));
|
|
204
|
-
lines.push(paint(`${counter.turns} turns · ${counter.duration}${counter.usage ? ` · ${counter.usage}` : ''}`, [options.muted]));
|
|
205
|
-
if (goal.lastReason) lines.push(paint(`reason: ${goal.lastReason}`, [options.muted]));
|
|
206
|
-
return lines.join('\n');
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
lines.push(paint('Goal stopped.', [options.muted]));
|
|
210
|
-
lines.push(paint(goal.condition, [options.bold]));
|
|
211
|
-
lines.push(paint(`turn ${counter.turns} · ${counter.duration}`, [options.muted]));
|
|
212
|
-
if (goal.lastReason) lines.push(paint(`reason: ${goal.lastReason}`, [options.muted]));
|
|
213
|
-
return lines.join('\n');
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
function formatGoalActiveBanner(goal, options = {}) {
|
|
217
|
-
if (!goal || !goal.active) return '';
|
|
218
|
-
const paint = options.paint || ((text) => String(text));
|
|
219
|
-
const counter = formatGoalCounter(goal);
|
|
220
|
-
return paint(
|
|
221
|
-
`◎ /goal active · ${truncateGoalText(goal.condition, 56)} · turn ${counter.turns}${Number.isFinite(goal.maxTurns) ? `/${goal.maxTurns}` : ''} · ${counter.duration}`,
|
|
222
|
-
[options.bold, options.magenta]
|
|
223
|
-
);
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
function formatGoalAchieved(goal, options = {}) {
|
|
227
|
-
const paint = options.paint || ((text) => String(text));
|
|
228
|
-
const counter = formatGoalCounter(goal);
|
|
229
|
-
return [
|
|
230
|
-
paint('✦ Goal achieved', [options.bold, options.magenta]),
|
|
231
|
-
paint(goal.condition, [options.bold, options.accent]),
|
|
232
|
-
paint(`${counter.turns} turns · ${counter.duration}${counter.usage ? ` · ${counter.usage}` : ''}`, [options.muted]),
|
|
233
|
-
goal.lastReason ? paint(`reason: ${goal.lastReason}`, [options.muted]) : '',
|
|
234
|
-
].filter(Boolean).join('\n');
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
function formatGoalContinue(goal, options = {}) {
|
|
238
|
-
const paint = options.paint || ((text) => String(text));
|
|
239
|
-
return paint(`◎ continuing goal · turn ${goal.turns + 1}${Number.isFinite(goal.maxTurns) ? `/${goal.maxTurns}` : ''} · ${goal.lastReason}`, [options.magenta]);
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
function formatGoalStopped(goal, reason, options = {}) {
|
|
243
|
-
const paint = options.paint || ((text) => String(text));
|
|
244
|
-
const counter = formatGoalCounter(goal);
|
|
245
|
-
return [
|
|
246
|
-
paint('◎ Goal stopped', [options.bold, options.muted]),
|
|
247
|
-
paint(reason, [options.muted]),
|
|
248
|
-
paint(`${counter.turns} turns · ${counter.duration}`, [options.muted]),
|
|
249
|
-
].join('\n');
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
async function evaluateGoalTurn(goal, ctx = {}, deps = {}) {
|
|
253
|
-
const marker = parseGoalAchievedMarker(ctx.lastOutput);
|
|
254
|
-
if (marker) return marker;
|
|
255
|
-
|
|
256
|
-
if (typeof deps.evaluateGoal === 'function') {
|
|
257
|
-
return deps.evaluateGoal(goal, ctx);
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
if (typeof deps.postTurn !== 'function') {
|
|
261
|
-
return { achieved: false, reason: goal.lastReason || 'Condition not met yet.' };
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
const evalOutput = { isTTY: false, write() {} };
|
|
265
|
-
try {
|
|
266
|
-
const result = await deps.postTurn(buildGoalEvalPrompt(goal, ctx.history || [], ctx.lastOutput), {
|
|
267
|
-
...(ctx.turnOptions || {}),
|
|
268
|
-
mode: 'fast',
|
|
269
|
-
history: [],
|
|
270
|
-
output: evalOutput,
|
|
271
|
-
showProgress: false,
|
|
272
|
-
goalEval: true,
|
|
273
|
-
});
|
|
274
|
-
const parsed = parseGoalEvalResponse(result.output);
|
|
275
|
-
if (parsed) return parsed;
|
|
276
|
-
} catch (error) {
|
|
277
|
-
return { achieved: false, reason: `Evaluator unavailable: ${error.message}` };
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
return { achieved: false, reason: goal.lastReason || 'Condition not met yet.' };
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
module.exports = {
|
|
284
|
-
GOAL_CLEAR_ALIASES,
|
|
285
|
-
accumulateGoalUsage,
|
|
286
|
-
buildGoalDirective,
|
|
287
|
-
buildGoalEvalPrompt,
|
|
288
|
-
clearGoalState,
|
|
289
|
-
compactGoalHistory,
|
|
290
|
-
createGoalState,
|
|
291
|
-
evaluateGoalTurn,
|
|
292
|
-
finishGoalAchieved,
|
|
293
|
-
formatGoalAchieved,
|
|
294
|
-
formatGoalActiveBanner,
|
|
295
|
-
formatGoalContinue,
|
|
296
|
-
formatGoalCounter,
|
|
297
|
-
formatGoalStatus,
|
|
298
|
-
formatGoalStopped,
|
|
299
|
-
goalBudgetExceeded,
|
|
300
|
-
goalElapsedMs,
|
|
301
|
-
goalTurnLimitReached,
|
|
302
|
-
parseGoalAchievedMarker,
|
|
303
|
-
parseGoalCommand,
|
|
304
|
-
parseGoalEvalResponse,
|
|
305
|
-
parseTokenBudget,
|
|
306
|
-
truncateGoalText,
|
|
307
|
-
};
|
package/lib/ax-prefs.js
DELETED
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
const fs = require('fs');
|
|
2
|
-
const os = require('os');
|
|
3
|
-
const path = require('path');
|
|
4
|
-
|
|
5
|
-
const MEMBER_SLUG = 'ax';
|
|
6
|
-
const PREFS_PATH = path.join(os.homedir(), '.atris', 'ax.json');
|
|
7
|
-
const TRUTHY = new Set(['1', 'true', 'yes', 'on']);
|
|
8
|
-
|
|
9
|
-
function truthy(value) {
|
|
10
|
-
return TRUTHY.has(String(value || '').trim().toLowerCase());
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
function loadAxPrefs() {
|
|
14
|
-
try {
|
|
15
|
-
if (!fs.existsSync(PREFS_PATH)) {
|
|
16
|
-
return { member_slug: MEMBER_SLUG, bypass_permissions: false };
|
|
17
|
-
}
|
|
18
|
-
const parsed = JSON.parse(fs.readFileSync(PREFS_PATH, 'utf8'));
|
|
19
|
-
return {
|
|
20
|
-
member_slug: MEMBER_SLUG,
|
|
21
|
-
bypass_permissions: parsed.bypass_permissions === true,
|
|
22
|
-
};
|
|
23
|
-
} catch {
|
|
24
|
-
return { member_slug: MEMBER_SLUG, bypass_permissions: false };
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
function saveAxPrefs(prefs) {
|
|
29
|
-
fs.mkdirSync(path.dirname(PREFS_PATH), { recursive: true });
|
|
30
|
-
fs.writeFileSync(PREFS_PATH, `${JSON.stringify({
|
|
31
|
-
member_slug: MEMBER_SLUG,
|
|
32
|
-
bypass_permissions: prefs.bypass_permissions === true,
|
|
33
|
-
updated_at: new Date().toISOString(),
|
|
34
|
-
}, null, 2)}\n`);
|
|
35
|
-
return loadAxPrefs();
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
function setBypassPermissions(enabled, { persist = true } = {}) {
|
|
39
|
-
const next = { member_slug: MEMBER_SLUG, bypass_permissions: enabled === true };
|
|
40
|
-
return persist ? saveAxPrefs(next) : next;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
function resolveBypassPermissions(options = {}) {
|
|
44
|
-
if (options.bypassPermissions === true) return true;
|
|
45
|
-
if (options.bypassPermissions === false) return false;
|
|
46
|
-
if (truthy(process.env.AX_BYPASS_PERMISSIONS)) return true;
|
|
47
|
-
if (truthy(process.env.AX_SAFE_PERMISSIONS)) return false;
|
|
48
|
-
return loadAxPrefs().bypass_permissions === true;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
function permissionsLabel(options = {}) {
|
|
52
|
-
return resolveBypassPermissions(options) ? 'bypass' : 'safe';
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
module.exports = {
|
|
56
|
-
MEMBER_SLUG,
|
|
57
|
-
PREFS_PATH,
|
|
58
|
-
loadAxPrefs,
|
|
59
|
-
saveAxPrefs,
|
|
60
|
-
setBypassPermissions,
|
|
61
|
-
resolveBypassPermissions,
|
|
62
|
-
permissionsLabel,
|
|
63
|
-
};
|
package/lib/ax-shimmer.js
DELETED
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
const ANSI = {
|
|
2
|
-
reset: '\x1b[0m',
|
|
3
|
-
dim: '\x1b[2m',
|
|
4
|
-
muted: '\x1b[90m',
|
|
5
|
-
white: '\x1b[37m',
|
|
6
|
-
bright: '\x1b[97m',
|
|
7
|
-
};
|
|
8
|
-
|
|
9
|
-
function useColor(options = {}) {
|
|
10
|
-
if (options.color === false) return false;
|
|
11
|
-
if (process.env.NO_COLOR) return false;
|
|
12
|
-
return Boolean(options.color || options.isTTY);
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
function paint(text, codes, options = {}) {
|
|
16
|
-
if (!useColor(options)) return String(text);
|
|
17
|
-
const styles = codes.filter(Boolean);
|
|
18
|
-
if (!styles.length) return String(text);
|
|
19
|
-
return `${styles.join('')}${text}${ANSI.reset}`;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
const SHIMMER_TICK_STEP = 0.44;
|
|
23
|
-
|
|
24
|
-
function shimmerStyleForDistance(dist) {
|
|
25
|
-
// Obelisk .shimmer-text: pure grayscale luminance sweep — no bold, no hue.
|
|
26
|
-
const t = Math.min(Math.max(dist, 0) / 3.4, 1);
|
|
27
|
-
if (t <= 0.2) return [ANSI.bright];
|
|
28
|
-
if (t <= 0.48) return [ANSI.white];
|
|
29
|
-
if (t <= 0.72) return [ANSI.muted];
|
|
30
|
-
return [ANSI.dim, ANSI.muted];
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
function renderShimmerText(text, tick = 0, options = {}) {
|
|
34
|
-
const value = String(text || '');
|
|
35
|
-
if (!value) return '';
|
|
36
|
-
if (!useColor(options)) return value;
|
|
37
|
-
|
|
38
|
-
const len = Math.max(1, value.length);
|
|
39
|
-
const cycle = len + 12;
|
|
40
|
-
const head = (Number(tick) * SHIMMER_TICK_STEP) % cycle;
|
|
41
|
-
|
|
42
|
-
let out = '';
|
|
43
|
-
for (let i = 0; i < value.length; i += 1) {
|
|
44
|
-
const char = value[i];
|
|
45
|
-
if (char === ' ') {
|
|
46
|
-
out += ' ';
|
|
47
|
-
continue;
|
|
48
|
-
}
|
|
49
|
-
let dist = Math.abs(i - head);
|
|
50
|
-
if (dist > cycle / 2) dist = cycle - dist;
|
|
51
|
-
out += paint(char, shimmerStyleForDistance(dist), options);
|
|
52
|
-
}
|
|
53
|
-
return out;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
module.exports = {
|
|
57
|
-
ANSI,
|
|
58
|
-
SHIMMER_TICK_STEP,
|
|
59
|
-
paint,
|
|
60
|
-
renderShimmerText,
|
|
61
|
-
shimmerStyleForDistance,
|
|
62
|
-
useColor,
|
|
63
|
-
};
|