icoa-cli 2.19.100 → 2.19.101
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/commands/ai4ctf.js +1 -700
- package/dist/commands/connect.js +1 -66
- package/dist/commands/ctf.js +1 -620
- package/dist/commands/ctf4ai-demo.js +1 -525
- package/dist/commands/env.js +1 -738
- package/dist/commands/exam.js +1 -2353
- package/dist/commands/files.js +1 -52
- package/dist/commands/hint.js +1 -119
- package/dist/commands/lang.js +1 -155
- package/dist/commands/log.js +1 -165
- package/dist/commands/note.js +1 -40
- package/dist/commands/ref.js +1 -68
- package/dist/commands/setup.js +1 -122
- package/dist/commands/shell.js +1 -55
- package/dist/commands/theme.js +1 -50
- package/dist/index.js +1 -225
- package/dist/lib/access.js +1 -246
- package/dist/lib/budget.js +1 -42
- package/dist/lib/colors.js +1 -21
- package/dist/lib/config.js +1 -60
- package/dist/lib/ctfd-client.js +1 -274
- package/dist/lib/demo-exam.js +1 -249
- package/dist/lib/demo-flags.js +1 -27
- package/dist/lib/demo-stats.js +1 -65
- package/dist/lib/exam-client.js +1 -57
- package/dist/lib/exam-setup.js +1 -23
- package/dist/lib/exam-state.js +1 -112
- package/dist/lib/gemini.js +1 -235
- package/dist/lib/i18n.js +1 -273
- package/dist/lib/log-sync.js +1 -110
- package/dist/lib/logger.js +1 -59
- package/dist/lib/paper-upgrade.js +1 -117
- package/dist/lib/platform.js +1 -86
- package/dist/lib/sandbox.js +1 -93
- package/dist/lib/terminal.js +1 -49
- package/dist/lib/theme.js +1 -108
- package/dist/lib/translation.js +1 -66
- package/dist/lib/ui.js +1 -80
- package/dist/lib/update-check.js +1 -102
- package/dist/postinstall.js +1 -48
- package/dist/repl.js +1 -1281
- package/dist/types/index.d.ts +1 -1
- package/dist/types/index.js +1 -38
- package/package.json +6 -2
- package/translations/sw/i18n-snippet.ts +1 -0
package/dist/lib/access.js
CHANGED
|
@@ -1,246 +1 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { execSync } from 'node:child_process';
|
|
3
|
-
import { hostname, platform, arch, networkInterfaces } from 'node:os';
|
|
4
|
-
import { getConfig, saveConfig, getIcoaDir } from './config.js';
|
|
5
|
-
import { readFileSync, writeFileSync, existsSync } from 'node:fs';
|
|
6
|
-
import { join } from 'node:path';
|
|
7
|
-
// SHA-256 hashes of 100 pre-generated access tokens (ICOA-XXXX-XXXX-XXXX)
|
|
8
|
-
const TOKEN_HASHES = new Set([
|
|
9
|
-
"93490bf664679467b4ab5af12e240175364b7af988b72cb7d000e309b7c68c15",
|
|
10
|
-
"cba7a6f075a4bd8c2fc973336cc0b1966669fc481381a065ce670730bbe0b7d3",
|
|
11
|
-
"f6773f614341acb8d2c35e8f466f2876095a2c8026a207e77de621050fa64559",
|
|
12
|
-
"d060ab36056fdac449a561fd3340c4b79ad4cde10c9a21c3397aa74574583a2b",
|
|
13
|
-
"523c11774e103298c15eb9d138872295194078f2d29486d0a6bd210436a592c3",
|
|
14
|
-
"1e16864067470f0a97088f067d8df4b655753ff498a91353b5f9b75989b6be39",
|
|
15
|
-
"f1031aac52879c776d4db5ba43eb25bb40f1a841b91304f8adf65a838fb8c666",
|
|
16
|
-
"bcd9e25014633ec6556345ab43d0cd213c454bb10d4ea0bd5be5ba02e1a6622c",
|
|
17
|
-
"9239ba9c3db74eadbb6dd05949c2a3cbe1b22e14e375ab3ca93d050e2e2ce38b",
|
|
18
|
-
"80fc0a899ed4d37138ae3172dafd466de2d3b1ce9630d67e6b00bec9315964d7",
|
|
19
|
-
"33ed35ce028824519d3a013ca326d6a58b1ca3723ec182527a7367e1ffc2712b",
|
|
20
|
-
"7e90933e760ce5e8df48bdb6bab0e95962bdc1098fceedecf617c0dac37b2a11",
|
|
21
|
-
"33fa6e3639a691b217ed0f927a8e2e2aef5eaa15eab7bd90c57874c2df2a28ac",
|
|
22
|
-
"67013663fb4536a47f6ea46b434fb7a00574bd4fc4f579e9439ba07f748db31b",
|
|
23
|
-
"10c83ad26fc965fcb1d228018f6b54d331e4a2e6087603920b75b500e191c5e4",
|
|
24
|
-
"3079268d847dc7eb196ce8cdc0af8a8506b9636539a1b7cce53dc5cb3f4cbe15",
|
|
25
|
-
"985eb5309c546d2f9d5018976973d6da06a374b897c73c830fc9d1305e78efa0",
|
|
26
|
-
"3a7326d4a7f40cc356b17769f4c5fc0d832d926aff9f067efd60f34c053bf9ef",
|
|
27
|
-
"129f408a98ad6c1b13924cf2c831c752b0c726bf1975d6b46f212a178ced52e1",
|
|
28
|
-
"ec44bc0b4eb6a929b969caaa561492527c369cc07efa50e40c2c6c16162f0c2c",
|
|
29
|
-
"07610942d9da62dd5b91c0ba48602bc44973a9d374ed10ab6c708151677ec626",
|
|
30
|
-
"8ce3165bb8e23f3b67ac53b39191aca3e2f0a620b7f932fe6a43e2c42315efcc",
|
|
31
|
-
"69938b605e652afc1cf8bc7c0dcf6a99820878367dfb3b2ec954ba90b36014f5",
|
|
32
|
-
"660377ce87d378285ab7263fdad86208c8563367d2cc36b4c1402520e45dd5f0",
|
|
33
|
-
"bef8a3727dffc94861a1dfa7d6a336ceac30aab9f0679dcab662cb9f682079dd",
|
|
34
|
-
"02318a3597b64a2c7de56b01fc25f33cc4142c76315136186df680f490681294",
|
|
35
|
-
"b7179114b42b90e9557399ae505050111b6afc55f9295d3ee84d5db6873470c5",
|
|
36
|
-
"e227ec0a6b22773500b35bee46f21bc6bc6a00fb001d54e71479f15b8fdfd72b",
|
|
37
|
-
"1c9802ae1e932d55e73994ce173a996d170e4d274aeccb1b784c9d9b69913f3d",
|
|
38
|
-
"5ed51694773bd1b46a085d10e9a369786a997c50b72ec2bdb6e68921ffca5c51",
|
|
39
|
-
"478e457279a41e9b76a3dc5894418e38246d2af31e0f4776dda8aa89c74c88c8",
|
|
40
|
-
"a7ec7e047c0e62862e9be64b0a65d3d7894d41efe6eb16ca6cfca45d8007f16f",
|
|
41
|
-
"88cf2b75604486ac5f1a0db9afbab28e8e866f9ea00f3e4b4353a7ecc81f6b55",
|
|
42
|
-
"dc4daa9ef4149f122979ffd5a8b23bca3cbb83b24a87ba99a1d00dc09e39936e",
|
|
43
|
-
"cffd9a3637b5ae30c27cae4ae42dc21374caa27dd818b5d361f112406bf3c0e7",
|
|
44
|
-
"33b3e85a964f606e857280ba379de46508f9343cbe1d2722abebbed21b82a106",
|
|
45
|
-
"a3754074df08f9c9407c73e680eac1868175cee3beac3f0e7d2bd211bdf51f58",
|
|
46
|
-
"f9eb5fd82f3360e22ad45d4797f3a95b907a766ef5a61d856bf959b60a4930dc",
|
|
47
|
-
"1c53d3145cb38501a2422bf70f55a0c206b68c14e46da31e0e3dc63c7bee78d6",
|
|
48
|
-
"20bc5f2dedbf6423a543ba25183fab3c7268cdd2762e080f6d0b3387c4b3cad8",
|
|
49
|
-
"654faf29e2a177dba2409db4942007630674b86d3ff87d2b11d428e8b4d0db7f",
|
|
50
|
-
"c27979d019266887a1b86225d3c85b2d4553e85814ab2d791547ffc3f9dc664a",
|
|
51
|
-
"74f982351453468e39aff8373cb2649d57344b8002b85fc9c0df118d051817fc",
|
|
52
|
-
"891e59d7896f29a9af2bd1a9aec98ae2ebcc57d9685027e3f07067734e603923",
|
|
53
|
-
"4a8a234bbad11dc98aa27871ed69d351385f9476af0c15b8b426cfa5630cc3db",
|
|
54
|
-
"e42c967f02a434a061152d86d68fa0a3da70235f6f8262a792abeeace14fc419",
|
|
55
|
-
"c1560c78197abd62252f8932abf73d5f7506fcd157e98390230aec81fdf5e5ac",
|
|
56
|
-
"afa2cc8fe8b9b8785921f2e649d90d239f729223b2ce7460c0f22d79427c7b5e",
|
|
57
|
-
"d574f129616c989797b3a4a7988e9d4ca3afb59ed1de67136d459307b9a1807a",
|
|
58
|
-
"94b1c1e2fab8c51bb76d9d7bc07d23f8b509919009feb141f12562cab696d49a",
|
|
59
|
-
"79bf74936c7274d1ee529fb888f30fbf2a33a15308bedb8c77c1c50793790b42",
|
|
60
|
-
"2ee8962250f82c51fdbbf170c6c7fa9b69dca336434714ba607c6f816034cb08",
|
|
61
|
-
"6e8e665df73c6934d5b432f5aa898ba33cc9a40d630b049404a23fa5d2776298",
|
|
62
|
-
"3561d1bd9ae8c916eace5bdd1eb788cd743ad461cff58acf58ed5b2064b30b7b",
|
|
63
|
-
"46a48aa8aef9f09dabb9cf340dacc1889cf3eeebc49c6d2f26ff017cd087857c",
|
|
64
|
-
"561e0536b3cf214a4bf41b2bfb2209c8d659990a871e44bef9bc0136613a4ab9",
|
|
65
|
-
"7c1f3e331c8f59cc6dab7e310d9ad151628f72e5ca3db5a6ff592c8c976c1974",
|
|
66
|
-
"fb9d9d484edfa2c0a531a3e08074f52b6988f1082606f1eecaf0c58f117dbf3d",
|
|
67
|
-
"2810e928a4ce6e2ae016751a7e8b73496de47fe1926abe6ff486bc0eed23e3d7",
|
|
68
|
-
"723c3ede92f08e9ac12b7dc0b9e6a857ab0426d3418524f4eb50ad69f0228ccd",
|
|
69
|
-
"66a07cdf0c9d56558ad4f853203071b56adfa990a4fb065b49c10108f4996fe7",
|
|
70
|
-
"dc826253950962dbc2e5699dc5c138490c4233a23b39a5cf471a931cbbc689b8",
|
|
71
|
-
"ec29a6c60c70a25a5a238ba1d03407dadafee78c01bc9f921549da428c4fbc03",
|
|
72
|
-
"0564c17382a344aa22b5452989d2950f514bbd366e7b8289a458a4604c987641",
|
|
73
|
-
"157ca17a0c1fc9faed3c2557cdf83323210a40020e72497e8e48e1d0055e54c7",
|
|
74
|
-
"e643beaf8a92e574da88b9efa424852d34261be06496ca78d08acd84c38861b7",
|
|
75
|
-
"df982789a1598f53bbcf44f1b2991c86bfd7713b36b04a06cf52640cfc9c579d",
|
|
76
|
-
"e135e4dd1aebe24484909d56fb47619eb975f9790ef4541fdc87f63a3478ecf4",
|
|
77
|
-
"823235bafe4f9e523cc4ffeb16789a2e2d6b246ab5c248335eba364d54474241",
|
|
78
|
-
"a314bda9257484bbbabc1159b957d3aae1de0bca777bcd1462fdc52abf5a62fe",
|
|
79
|
-
"65f6699712af969820645bbe271f66fe92f5da41fd834e329dadeae7801bc112",
|
|
80
|
-
"17e812f25ef6d73de97b3464ca3fd2109433d9b5bc567e4e74feda35bf660492",
|
|
81
|
-
"37ff30e4c4384b810bd86e4472e9ada4b447cd6057daf8df3f923fac3b8b3d77",
|
|
82
|
-
"c55f13e79ce2bb698606f787551591e050e33e576cb845a2f40b03edac56f819",
|
|
83
|
-
"2124d3353d3f105c3780c937f1eaf377f756e59c6ab6a97ef780a718f3a47c7b",
|
|
84
|
-
"e581535019c839a7c383d0eca3de97a6a5701025d4a24ea56f01932f910cb99c",
|
|
85
|
-
"eb089f8a27da4b94b79e5d125ed6205849b1909d0a6c1d0f51c351be2d5b8466",
|
|
86
|
-
"36ee22c148c0282e112950f8e9939fed4b95d2f8a52c9cd2fd3744070df54333",
|
|
87
|
-
"c81b6509d23e889c5b5ec79fdfaf64fed1bf00ced8f4b224aa37b5a37821ccfe",
|
|
88
|
-
"b529c4de4a2fff86266d9b0318f15246ed30f4641b4156778ff9f3fca3099e32",
|
|
89
|
-
"647c2aa42b094baf52537a8f7ffb015b7aa212c67ca779853d263d420760d8b6",
|
|
90
|
-
"8043ea259b8bbb2bf488643376c2a2b9a3864e5617ea9ac5dc72966e289c07c2",
|
|
91
|
-
"bba0397ebaf1a6093a8adb117e84198bb5d2dcf9e8e7792221af9215cda8c10b",
|
|
92
|
-
"978ec66df04567ef8e4f02aa67b903535859f7bf24a5b63298cae1c938a72ab7",
|
|
93
|
-
"124befb26711b599a311b0b0d7352b6e980a594cd56c8447e32c1aba26818fd1",
|
|
94
|
-
"990ddff1fd05882796d2081ebc0d966a39c04af7120a9440562d71db2f48d65d",
|
|
95
|
-
"f396be48a42c9cca6b6fec0a8ee7f5d15f93a57fba3baf04ab5a7d86af68bea5",
|
|
96
|
-
"4f2487f0af254ea067e853bb6874d80d05c46f6322ca6e3a8815b37931533aea",
|
|
97
|
-
"dbacdcc317d0cc436dd93c8be4d1471c712bcc567bda8e9a47dc0c1543d33e19",
|
|
98
|
-
"6658cb8824afdf853e9cf3e667ac9d6bf566d54cc0f3b81ad62f7d7eeadff530",
|
|
99
|
-
"b2c4ea7f091911a1c3733e42a52c75d3ee1666ceb62faa4e8ddb15c8a4b12b14",
|
|
100
|
-
"0f29f04bebfe26d9b0ef7b802e3b2c725e85cdc03407915a3d5753436977f24e",
|
|
101
|
-
"7eadf05c33f72431c7414e60e4068051143154d647452e3888de4c61316950ea",
|
|
102
|
-
"45237d7cbb04c768d25f2dd13708f448f3c50af5262015d468ccbdb51fe0c090",
|
|
103
|
-
"21f14816d480bc5c2e5f0a3387a0897d928e926a4341df3d32d65416b6e387f1",
|
|
104
|
-
"a39bd710b9489e8bef21362c8df87ed76008939e89dbf8e6708a2c574f0727e0",
|
|
105
|
-
"cf365a79503e1457c23cd1ea8c9fa8c398d168288f90b5c1920af798508c2b56",
|
|
106
|
-
"d123f90b3a932edf596fd561e74fc8cc0adc481c3be118a7fa6a5834cd7b787c",
|
|
107
|
-
"cde02309ad295648d86fa4acefdf7224809abb2ab9b025f14ae41e021512c5ed",
|
|
108
|
-
"39835a1337c2afd9a9690cb9946752899a110df312d9d3aa68e10f85fad49dea",
|
|
109
|
-
]);
|
|
110
|
-
// Check if first run or version upgrade
|
|
111
|
-
export function isFirstRunOrUpgrade(currentVersion) {
|
|
112
|
-
const config = getConfig();
|
|
113
|
-
return config.lastVersion !== currentVersion;
|
|
114
|
-
}
|
|
115
|
-
export function markVersionSeen(version) {
|
|
116
|
-
saveConfig({ lastVersion: version });
|
|
117
|
-
}
|
|
118
|
-
// Free commands that don't require token
|
|
119
|
-
const FREE_COMMANDS = new Set(['ref', 'help', 'exit', 'quit', 'q', 'clear', 'cls', 'activate']);
|
|
120
|
-
function hashToken(token) {
|
|
121
|
-
return createHash('sha256').update(token.trim().toUpperCase()).digest('hex');
|
|
122
|
-
}
|
|
123
|
-
export function validateToken(token) {
|
|
124
|
-
return TOKEN_HASHES.has(hashToken(token));
|
|
125
|
-
}
|
|
126
|
-
export function isActivated() {
|
|
127
|
-
const config = getConfig();
|
|
128
|
-
return !!(config.accessToken && TOKEN_HASHES.has(hashToken(config.accessToken)));
|
|
129
|
-
}
|
|
130
|
-
export function getDeviceFingerprint() {
|
|
131
|
-
const parts = [hostname(), platform(), arch()];
|
|
132
|
-
// Add hardware UUID where possible
|
|
133
|
-
try {
|
|
134
|
-
if (platform() === 'darwin') {
|
|
135
|
-
const out = execSync('ioreg -rd1 -c IOPlatformExpertDevice | grep IOPlatformUUID', { encoding: 'utf-8' });
|
|
136
|
-
const match = out.match(/"([A-F0-9-]+)"/);
|
|
137
|
-
if (match)
|
|
138
|
-
parts.push(match[1]);
|
|
139
|
-
}
|
|
140
|
-
else if (platform() === 'linux') {
|
|
141
|
-
if (existsSync('/etc/machine-id')) {
|
|
142
|
-
parts.push(readFileSync('/etc/machine-id', 'utf-8').trim());
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
else if (platform() === 'win32') {
|
|
146
|
-
const out = execSync('powershell -Command "(Get-CimInstance Win32_ComputerSystemProduct).UUID"', { encoding: 'utf-8' });
|
|
147
|
-
parts.push(out.trim());
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
catch {
|
|
151
|
-
// Fallback: use first non-internal MAC address
|
|
152
|
-
const nets = networkInterfaces();
|
|
153
|
-
for (const ifaces of Object.values(nets)) {
|
|
154
|
-
if (!ifaces)
|
|
155
|
-
continue;
|
|
156
|
-
for (const iface of ifaces) {
|
|
157
|
-
if (!iface.internal && iface.mac !== '00:00:00:00:00:00') {
|
|
158
|
-
parts.push(iface.mac);
|
|
159
|
-
break;
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
if (parts.length > 3)
|
|
163
|
-
break;
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
return createHash('sha256').update(parts.join('|')).digest('hex');
|
|
167
|
-
}
|
|
168
|
-
export function activateToken(token) {
|
|
169
|
-
if (!validateToken(token))
|
|
170
|
-
return 'invalid';
|
|
171
|
-
const fingerprint = getDeviceFingerprint();
|
|
172
|
-
const bindingFile = join(getIcoaDir(), 'token-bindings.json');
|
|
173
|
-
// Load existing bindings
|
|
174
|
-
let bindings = {};
|
|
175
|
-
if (existsSync(bindingFile)) {
|
|
176
|
-
try {
|
|
177
|
-
bindings = JSON.parse(readFileSync(bindingFile, 'utf-8'));
|
|
178
|
-
}
|
|
179
|
-
catch { /* ignore */ }
|
|
180
|
-
}
|
|
181
|
-
const tokenHash = hashToken(token);
|
|
182
|
-
const existingDevice = bindings[tokenHash];
|
|
183
|
-
if (existingDevice && existingDevice !== fingerprint) {
|
|
184
|
-
// Token already bound to a different device
|
|
185
|
-
return 'already_bound';
|
|
186
|
-
}
|
|
187
|
-
// Bind token to this device
|
|
188
|
-
bindings[tokenHash] = fingerprint;
|
|
189
|
-
writeFileSync(bindingFile, JSON.stringify(bindings, null, 2));
|
|
190
|
-
saveConfig({ accessToken: token.trim().toUpperCase(), deviceFingerprint: fingerprint });
|
|
191
|
-
return 'ok';
|
|
192
|
-
}
|
|
193
|
-
export function isDeviceMatch() {
|
|
194
|
-
const config = getConfig();
|
|
195
|
-
if (!config.deviceFingerprint)
|
|
196
|
-
return true; // Legacy: no fingerprint yet
|
|
197
|
-
return config.deviceFingerprint === getDeviceFingerprint();
|
|
198
|
-
}
|
|
199
|
-
export function isFreeCommand(cmd) {
|
|
200
|
-
return FREE_COMMANDS.has(cmd.toLowerCase());
|
|
201
|
-
}
|
|
202
|
-
// Session tracking for anti-cheat
|
|
203
|
-
const SESSION_FILE = () => join(getIcoaDir(), 'session-state.json');
|
|
204
|
-
function getDefaultSession() {
|
|
205
|
-
return {
|
|
206
|
-
startedAt: new Date().toISOString(),
|
|
207
|
-
lastExitAt: null,
|
|
208
|
-
lastResumeAt: null,
|
|
209
|
-
exitCount: 0,
|
|
210
|
-
totalAwaySeconds: 0,
|
|
211
|
-
};
|
|
212
|
-
}
|
|
213
|
-
export function getSession() {
|
|
214
|
-
const file = SESSION_FILE();
|
|
215
|
-
if (!existsSync(file))
|
|
216
|
-
return getDefaultSession();
|
|
217
|
-
try {
|
|
218
|
-
return { ...getDefaultSession(), ...JSON.parse(readFileSync(file, 'utf-8')) };
|
|
219
|
-
}
|
|
220
|
-
catch {
|
|
221
|
-
return getDefaultSession();
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
export function saveSession(session) {
|
|
225
|
-
const current = getSession();
|
|
226
|
-
const merged = { ...current, ...session };
|
|
227
|
-
writeFileSync(SESSION_FILE(), JSON.stringify(merged, null, 2));
|
|
228
|
-
}
|
|
229
|
-
export function recordExit() {
|
|
230
|
-
const session = getSession();
|
|
231
|
-
session.lastExitAt = new Date().toISOString();
|
|
232
|
-
session.exitCount++;
|
|
233
|
-
saveSession(session);
|
|
234
|
-
}
|
|
235
|
-
export function recordResume() {
|
|
236
|
-
const session = getSession();
|
|
237
|
-
if (!session.lastExitAt)
|
|
238
|
-
return null;
|
|
239
|
-
const exitTime = new Date(session.lastExitAt).getTime();
|
|
240
|
-
const now = Date.now();
|
|
241
|
-
const awaySeconds = Math.round((now - exitTime) / 1000);
|
|
242
|
-
session.lastResumeAt = new Date().toISOString();
|
|
243
|
-
session.totalAwaySeconds += awaySeconds;
|
|
244
|
-
saveSession(session);
|
|
245
|
-
return { awaySeconds, exitCount: session.exitCount };
|
|
246
|
-
}
|
|
1
|
+
import{createHash as e}from"node:crypto";import{execSync as c}from"node:child_process";import{hostname as a,platform as f,arch as d,networkInterfaces as b}from"node:os";import{getConfig as t,saveConfig as n,getIcoaDir as o}from"./config.js";import{readFileSync as r,writeFileSync as i,existsSync as s}from"node:fs";import{join as u}from"node:path";const p=new Set(["93490bf664679467b4ab5af12e240175364b7af988b72cb7d000e309b7c68c15","cba7a6f075a4bd8c2fc973336cc0b1966669fc481381a065ce670730bbe0b7d3","f6773f614341acb8d2c35e8f466f2876095a2c8026a207e77de621050fa64559","d060ab36056fdac449a561fd3340c4b79ad4cde10c9a21c3397aa74574583a2b","523c11774e103298c15eb9d138872295194078f2d29486d0a6bd210436a592c3","1e16864067470f0a97088f067d8df4b655753ff498a91353b5f9b75989b6be39","f1031aac52879c776d4db5ba43eb25bb40f1a841b91304f8adf65a838fb8c666","bcd9e25014633ec6556345ab43d0cd213c454bb10d4ea0bd5be5ba02e1a6622c","9239ba9c3db74eadbb6dd05949c2a3cbe1b22e14e375ab3ca93d050e2e2ce38b","80fc0a899ed4d37138ae3172dafd466de2d3b1ce9630d67e6b00bec9315964d7","33ed35ce028824519d3a013ca326d6a58b1ca3723ec182527a7367e1ffc2712b","7e90933e760ce5e8df48bdb6bab0e95962bdc1098fceedecf617c0dac37b2a11","33fa6e3639a691b217ed0f927a8e2e2aef5eaa15eab7bd90c57874c2df2a28ac","67013663fb4536a47f6ea46b434fb7a00574bd4fc4f579e9439ba07f748db31b","10c83ad26fc965fcb1d228018f6b54d331e4a2e6087603920b75b500e191c5e4","3079268d847dc7eb196ce8cdc0af8a8506b9636539a1b7cce53dc5cb3f4cbe15","985eb5309c546d2f9d5018976973d6da06a374b897c73c830fc9d1305e78efa0","3a7326d4a7f40cc356b17769f4c5fc0d832d926aff9f067efd60f34c053bf9ef","129f408a98ad6c1b13924cf2c831c752b0c726bf1975d6b46f212a178ced52e1","ec44bc0b4eb6a929b969caaa561492527c369cc07efa50e40c2c6c16162f0c2c","07610942d9da62dd5b91c0ba48602bc44973a9d374ed10ab6c708151677ec626","8ce3165bb8e23f3b67ac53b39191aca3e2f0a620b7f932fe6a43e2c42315efcc","69938b605e652afc1cf8bc7c0dcf6a99820878367dfb3b2ec954ba90b36014f5","660377ce87d378285ab7263fdad86208c8563367d2cc36b4c1402520e45dd5f0","bef8a3727dffc94861a1dfa7d6a336ceac30aab9f0679dcab662cb9f682079dd","02318a3597b64a2c7de56b01fc25f33cc4142c76315136186df680f490681294","b7179114b42b90e9557399ae505050111b6afc55f9295d3ee84d5db6873470c5","e227ec0a6b22773500b35bee46f21bc6bc6a00fb001d54e71479f15b8fdfd72b","1c9802ae1e932d55e73994ce173a996d170e4d274aeccb1b784c9d9b69913f3d","5ed51694773bd1b46a085d10e9a369786a997c50b72ec2bdb6e68921ffca5c51","478e457279a41e9b76a3dc5894418e38246d2af31e0f4776dda8aa89c74c88c8","a7ec7e047c0e62862e9be64b0a65d3d7894d41efe6eb16ca6cfca45d8007f16f","88cf2b75604486ac5f1a0db9afbab28e8e866f9ea00f3e4b4353a7ecc81f6b55","dc4daa9ef4149f122979ffd5a8b23bca3cbb83b24a87ba99a1d00dc09e39936e","cffd9a3637b5ae30c27cae4ae42dc21374caa27dd818b5d361f112406bf3c0e7","33b3e85a964f606e857280ba379de46508f9343cbe1d2722abebbed21b82a106","a3754074df08f9c9407c73e680eac1868175cee3beac3f0e7d2bd211bdf51f58","f9eb5fd82f3360e22ad45d4797f3a95b907a766ef5a61d856bf959b60a4930dc","1c53d3145cb38501a2422bf70f55a0c206b68c14e46da31e0e3dc63c7bee78d6","20bc5f2dedbf6423a543ba25183fab3c7268cdd2762e080f6d0b3387c4b3cad8","654faf29e2a177dba2409db4942007630674b86d3ff87d2b11d428e8b4d0db7f","c27979d019266887a1b86225d3c85b2d4553e85814ab2d791547ffc3f9dc664a","74f982351453468e39aff8373cb2649d57344b8002b85fc9c0df118d051817fc","891e59d7896f29a9af2bd1a9aec98ae2ebcc57d9685027e3f07067734e603923","4a8a234bbad11dc98aa27871ed69d351385f9476af0c15b8b426cfa5630cc3db","e42c967f02a434a061152d86d68fa0a3da70235f6f8262a792abeeace14fc419","c1560c78197abd62252f8932abf73d5f7506fcd157e98390230aec81fdf5e5ac","afa2cc8fe8b9b8785921f2e649d90d239f729223b2ce7460c0f22d79427c7b5e","d574f129616c989797b3a4a7988e9d4ca3afb59ed1de67136d459307b9a1807a","94b1c1e2fab8c51bb76d9d7bc07d23f8b509919009feb141f12562cab696d49a","79bf74936c7274d1ee529fb888f30fbf2a33a15308bedb8c77c1c50793790b42","2ee8962250f82c51fdbbf170c6c7fa9b69dca336434714ba607c6f816034cb08","6e8e665df73c6934d5b432f5aa898ba33cc9a40d630b049404a23fa5d2776298","3561d1bd9ae8c916eace5bdd1eb788cd743ad461cff58acf58ed5b2064b30b7b","46a48aa8aef9f09dabb9cf340dacc1889cf3eeebc49c6d2f26ff017cd087857c","561e0536b3cf214a4bf41b2bfb2209c8d659990a871e44bef9bc0136613a4ab9","7c1f3e331c8f59cc6dab7e310d9ad151628f72e5ca3db5a6ff592c8c976c1974","fb9d9d484edfa2c0a531a3e08074f52b6988f1082606f1eecaf0c58f117dbf3d","2810e928a4ce6e2ae016751a7e8b73496de47fe1926abe6ff486bc0eed23e3d7","723c3ede92f08e9ac12b7dc0b9e6a857ab0426d3418524f4eb50ad69f0228ccd","66a07cdf0c9d56558ad4f853203071b56adfa990a4fb065b49c10108f4996fe7","dc826253950962dbc2e5699dc5c138490c4233a23b39a5cf471a931cbbc689b8","ec29a6c60c70a25a5a238ba1d03407dadafee78c01bc9f921549da428c4fbc03","0564c17382a344aa22b5452989d2950f514bbd366e7b8289a458a4604c987641","157ca17a0c1fc9faed3c2557cdf83323210a40020e72497e8e48e1d0055e54c7","e643beaf8a92e574da88b9efa424852d34261be06496ca78d08acd84c38861b7","df982789a1598f53bbcf44f1b2991c86bfd7713b36b04a06cf52640cfc9c579d","e135e4dd1aebe24484909d56fb47619eb975f9790ef4541fdc87f63a3478ecf4","823235bafe4f9e523cc4ffeb16789a2e2d6b246ab5c248335eba364d54474241","a314bda9257484bbbabc1159b957d3aae1de0bca777bcd1462fdc52abf5a62fe","65f6699712af969820645bbe271f66fe92f5da41fd834e329dadeae7801bc112","17e812f25ef6d73de97b3464ca3fd2109433d9b5bc567e4e74feda35bf660492","37ff30e4c4384b810bd86e4472e9ada4b447cd6057daf8df3f923fac3b8b3d77","c55f13e79ce2bb698606f787551591e050e33e576cb845a2f40b03edac56f819","2124d3353d3f105c3780c937f1eaf377f756e59c6ab6a97ef780a718f3a47c7b","e581535019c839a7c383d0eca3de97a6a5701025d4a24ea56f01932f910cb99c","eb089f8a27da4b94b79e5d125ed6205849b1909d0a6c1d0f51c351be2d5b8466","36ee22c148c0282e112950f8e9939fed4b95d2f8a52c9cd2fd3744070df54333","c81b6509d23e889c5b5ec79fdfaf64fed1bf00ced8f4b224aa37b5a37821ccfe","b529c4de4a2fff86266d9b0318f15246ed30f4641b4156778ff9f3fca3099e32","647c2aa42b094baf52537a8f7ffb015b7aa212c67ca779853d263d420760d8b6","8043ea259b8bbb2bf488643376c2a2b9a3864e5617ea9ac5dc72966e289c07c2","bba0397ebaf1a6093a8adb117e84198bb5d2dcf9e8e7792221af9215cda8c10b","978ec66df04567ef8e4f02aa67b903535859f7bf24a5b63298cae1c938a72ab7","124befb26711b599a311b0b0d7352b6e980a594cd56c8447e32c1aba26818fd1","990ddff1fd05882796d2081ebc0d966a39c04af7120a9440562d71db2f48d65d","f396be48a42c9cca6b6fec0a8ee7f5d15f93a57fba3baf04ab5a7d86af68bea5","4f2487f0af254ea067e853bb6874d80d05c46f6322ca6e3a8815b37931533aea","dbacdcc317d0cc436dd93c8be4d1471c712bcc567bda8e9a47dc0c1543d33e19","6658cb8824afdf853e9cf3e667ac9d6bf566d54cc0f3b81ad62f7d7eeadff530","b2c4ea7f091911a1c3733e42a52c75d3ee1666ceb62faa4e8ddb15c8a4b12b14","0f29f04bebfe26d9b0ef7b802e3b2c725e85cdc03407915a3d5753436977f24e","7eadf05c33f72431c7414e60e4068051143154d647452e3888de4c61316950ea","45237d7cbb04c768d25f2dd13708f448f3c50af5262015d468ccbdb51fe0c090","21f14816d480bc5c2e5f0a3387a0897d928e926a4341df3d32d65416b6e387f1","a39bd710b9489e8bef21362c8df87ed76008939e89dbf8e6708a2c574f0727e0","cf365a79503e1457c23cd1ea8c9fa8c398d168288f90b5c1920af798508c2b56","d123f90b3a932edf596fd561e74fc8cc0adc481c3be118a7fa6a5834cd7b787c","cde02309ad295648d86fa4acefdf7224809abb2ab9b025f14ae41e021512c5ed","39835a1337c2afd9a9690cb9946752899a110df312d9d3aa68e10f85fad49dea"]);export function isFirstRunOrUpgrade(e){return t().lastVersion!==e}export function markVersionSeen(e){n({lastVersion:e})}const l=new Set(["ref","help","exit","quit","q","clear","cls","activate"]);function m(c){return e("sha256").update(c.trim().toUpperCase()).digest("hex")}export function validateToken(e){return p.has(m(e))}export function isActivated(){const e=t();return!(!e.accessToken||!p.has(m(e.accessToken)))}export function getDeviceFingerprint(){const t=[a(),f(),d()];try{if("darwin"===f()){const e=c("ioreg -rd1 -c IOPlatformExpertDevice | grep IOPlatformUUID",{encoding:"utf-8"}).match(/"([A-F0-9-]+)"/);e&&t.push(e[1])}else if("linux"===f())s("/etc/machine-id")&&t.push(r("/etc/machine-id","utf-8").trim());else if("win32"===f()){const e=c('powershell -Command "(Get-CimInstance Win32_ComputerSystemProduct).UUID"',{encoding:"utf-8"});t.push(e.trim())}}catch{const e=b();for(const c of Object.values(e))if(c){for(const e of c)if(!e.internal&&"00:00:00:00:00:00"!==e.mac){t.push(e.mac);break}if(t.length>3)break}}return e("sha256").update(t.join("|")).digest("hex")}export function activateToken(e){if(!validateToken(e))return"invalid";const c=getDeviceFingerprint(),a=u(o(),"token-bindings.json");let f={};if(s(a))try{f=JSON.parse(r(a,"utf-8"))}catch{}const d=m(e),b=f[d];return b&&b!==c?"already_bound":(f[d]=c,i(a,JSON.stringify(f,null,2)),n({accessToken:e.trim().toUpperCase(),deviceFingerprint:c}),"ok")}export function isDeviceMatch(){const e=t();return!e.deviceFingerprint||e.deviceFingerprint===getDeviceFingerprint()}export function isFreeCommand(e){return l.has(e.toLowerCase())}const g=()=>u(o(),"session-state.json");function x(){return{startedAt:(new Date).toISOString(),lastExitAt:null,lastResumeAt:null,exitCount:0,totalAwaySeconds:0}}export function getSession(){const e=g();if(!s(e))return x();try{return{...x(),...JSON.parse(r(e,"utf-8"))}}catch{return x()}}export function saveSession(e){const c={...getSession(),...e};i(g(),JSON.stringify(c,null,2))}export function recordExit(){const e=getSession();e.lastExitAt=(new Date).toISOString(),e.exitCount++,saveSession(e)}export function recordResume(){const e=getSession();if(!e.lastExitAt)return null;const c=new Date(e.lastExitAt).getTime(),a=Date.now(),f=Math.round((a-c)/1e3);return e.lastResumeAt=(new Date).toISOString(),e.totalAwaySeconds+=f,saveSession(e),{awaySeconds:f,exitCount:e.exitCount}}
|
package/dist/lib/budget.js
CHANGED
|
@@ -1,42 +1 @@
|
|
|
1
|
-
import
|
|
2
|
-
export function checkBudget(level) {
|
|
3
|
-
const budget = getBudget();
|
|
4
|
-
const key = level.toLowerCase();
|
|
5
|
-
return {
|
|
6
|
-
allowed: budget[key] > 0,
|
|
7
|
-
remaining: budget[key],
|
|
8
|
-
};
|
|
9
|
-
}
|
|
10
|
-
export function deductBudget(level, tokensUsed) {
|
|
11
|
-
const budget = getBudget();
|
|
12
|
-
const key = level.toLowerCase();
|
|
13
|
-
budget[key] = Math.max(0, budget[key] - 1);
|
|
14
|
-
budget.tokensUsed += tokensUsed;
|
|
15
|
-
saveBudget(budget);
|
|
16
|
-
}
|
|
17
|
-
export function getBudgetDisplay() {
|
|
18
|
-
const budget = getBudget();
|
|
19
|
-
return [
|
|
20
|
-
` Level A (General Guidance): ${budget.a}/50`,
|
|
21
|
-
` Level B (Deep Analysis): ${budget.b}/10`,
|
|
22
|
-
` Level C (Critical Assist): ${budget.c}/2`,
|
|
23
|
-
` Token Usage: ${budget.tokensUsed.toLocaleString()}/${budget.tokenCap.toLocaleString()}`,
|
|
24
|
-
].join('\n');
|
|
25
|
-
}
|
|
26
|
-
export function isTokenCapReached() {
|
|
27
|
-
const budget = getBudget();
|
|
28
|
-
return budget.tokensUsed >= budget.tokenCap;
|
|
29
|
-
}
|
|
30
|
-
export function addTokenUsage(tokensUsed) {
|
|
31
|
-
const budget = getBudget();
|
|
32
|
-
budget.tokensUsed += tokensUsed;
|
|
33
|
-
saveBudget(budget);
|
|
34
|
-
}
|
|
35
|
-
export function getTokenUsage() {
|
|
36
|
-
const budget = getBudget();
|
|
37
|
-
return {
|
|
38
|
-
used: budget.tokensUsed,
|
|
39
|
-
cap: budget.tokenCap,
|
|
40
|
-
remaining: Math.max(0, budget.tokenCap - budget.tokensUsed),
|
|
41
|
-
};
|
|
42
|
-
}
|
|
1
|
+
import{getBudget as e,saveBudget as t}from"./config.js";export function checkBudget(t){const n=e(),o=t.toLowerCase();return{allowed:n[o]>0,remaining:n[o]}}export function deductBudget(n,o){const s=e(),a=n.toLowerCase();s[a]=Math.max(0,s[a]-1),s.tokensUsed+=o,t(s)}export function getBudgetDisplay(){const t=e();return[` Level A (General Guidance): ${t.a}/50`,` Level B (Deep Analysis): ${t.b}/10`,` Level C (Critical Assist): ${t.c}/2`,` Token Usage: ${t.tokensUsed.toLocaleString()}/${t.tokenCap.toLocaleString()}`].join("\n")}export function isTokenCapReached(){const t=e();return t.tokensUsed>=t.tokenCap}export function addTokenUsage(n){const o=e();o.tokensUsed+=n,t(o)}export function getTokenUsage(){const t=e();return{used:t.tokensUsed,cap:t.tokenCap,remaining:Math.max(0,t.tokenCap-t.tokensUsed)}}
|
package/dist/lib/colors.js
CHANGED
|
@@ -1,21 +1 @@
|
|
|
1
|
-
|
|
2
|
-
// Use c.* helpers when you need brand-accurate truecolor (e.g. the orange
|
|
3
|
-
// accent #CC7832). For generic success/error/warning, chalk.green/.red/.yellow
|
|
4
|
-
// remain fine — they render as the terminal's Darcula 16-color when using an
|
|
5
|
-
// ICOA theme and as close-enough defaults elsewhere.
|
|
6
|
-
const tc = (r, g, b) => (s) => `\x1b[38;2;${r};${g};${b}m${s}\x1b[39m`;
|
|
7
|
-
export const c = {
|
|
8
|
-
fg: tc(169, 183, 198), // #A9B7C6 body text
|
|
9
|
-
muted: tc(85, 85, 85), // #555555 comments / secondary
|
|
10
|
-
red: tc(255, 107, 104), // #FF6B68 error
|
|
11
|
-
green: tc(168, 192, 35), // #A8C023 success
|
|
12
|
-
yellow: tc(214, 191, 85), // #D6BF55 warning
|
|
13
|
-
blue: tc(126, 174, 241), // #7EAEF1 link
|
|
14
|
-
cyan: tc(40, 123, 222), // #287BDE command / path
|
|
15
|
-
orange: tc(204, 120, 50), // #CC7832 brand accent
|
|
16
|
-
white: tc(255, 255, 255), // #FFFFFF highlight
|
|
17
|
-
};
|
|
18
|
-
export const DARCULA_BG_HEX = '#2B2B2B';
|
|
19
|
-
export const DARCULA_FG_HEX = '#A9B7C6';
|
|
20
|
-
export const DARCULA_BG_RGB = [43, 43, 43];
|
|
21
|
-
export const DARCULA_FG_RGB = [169, 183, 198];
|
|
1
|
+
const e=(e,o,t)=>n=>`[38;2;${e};${o};${t}m${n}[39m`;export const c={fg:e(169,183,198),muted:e(85,85,85),red:e(255,107,104),green:e(168,192,35),yellow:e(214,191,85),blue:e(126,174,241),cyan:e(40,123,222),orange:e(204,120,50),white:e(255,255,255)};export const DARCULA_BG_HEX="#2B2B2B";export const DARCULA_FG_HEX="#A9B7C6";export const DARCULA_BG_RGB=[43,43,43];export const DARCULA_FG_RGB=[169,183,198];
|
package/dist/lib/config.js
CHANGED
|
@@ -1,60 +1 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { join } from 'node:path';
|
|
3
|
-
import { homedir } from 'node:os';
|
|
4
|
-
import { randomUUID } from 'node:crypto';
|
|
5
|
-
import { DEFAULT_CONFIG, DEFAULT_BUDGET } from '../types/index.js';
|
|
6
|
-
const ICOA_DIR = join(homedir(), '.icoa');
|
|
7
|
-
const CONFIG_FILE = join(ICOA_DIR, 'config.json');
|
|
8
|
-
const BUDGET_FILE = join(ICOA_DIR, 'budget.json');
|
|
9
|
-
function ensureDir() {
|
|
10
|
-
if (!existsSync(ICOA_DIR)) {
|
|
11
|
-
mkdirSync(ICOA_DIR, { recursive: true });
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
|
-
export function getConfig() {
|
|
15
|
-
ensureDir();
|
|
16
|
-
if (!existsSync(CONFIG_FILE)) {
|
|
17
|
-
const config = { ...DEFAULT_CONFIG, sessionId: randomUUID() };
|
|
18
|
-
writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2));
|
|
19
|
-
return config;
|
|
20
|
-
}
|
|
21
|
-
try {
|
|
22
|
-
const raw = readFileSync(CONFIG_FILE, 'utf-8');
|
|
23
|
-
return { ...DEFAULT_CONFIG, ...JSON.parse(raw) };
|
|
24
|
-
}
|
|
25
|
-
catch {
|
|
26
|
-
return { ...DEFAULT_CONFIG, sessionId: randomUUID() };
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
export function saveConfig(config) {
|
|
30
|
-
ensureDir();
|
|
31
|
-
const current = getConfig();
|
|
32
|
-
const merged = { ...current, ...config };
|
|
33
|
-
writeFileSync(CONFIG_FILE, JSON.stringify(merged, null, 2));
|
|
34
|
-
}
|
|
35
|
-
export function getBudget() {
|
|
36
|
-
ensureDir();
|
|
37
|
-
if (!existsSync(BUDGET_FILE)) {
|
|
38
|
-
writeFileSync(BUDGET_FILE, JSON.stringify(DEFAULT_BUDGET, null, 2));
|
|
39
|
-
return { ...DEFAULT_BUDGET };
|
|
40
|
-
}
|
|
41
|
-
try {
|
|
42
|
-
const raw = readFileSync(BUDGET_FILE, 'utf-8');
|
|
43
|
-
return { ...DEFAULT_BUDGET, ...JSON.parse(raw) };
|
|
44
|
-
}
|
|
45
|
-
catch {
|
|
46
|
-
return { ...DEFAULT_BUDGET };
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
export function saveBudget(budget) {
|
|
50
|
-
ensureDir();
|
|
51
|
-
writeFileSync(BUDGET_FILE, JSON.stringify(budget, null, 2));
|
|
52
|
-
}
|
|
53
|
-
export function getIcoaDir() {
|
|
54
|
-
ensureDir();
|
|
55
|
-
return ICOA_DIR;
|
|
56
|
-
}
|
|
57
|
-
export function isConnected() {
|
|
58
|
-
const config = getConfig();
|
|
59
|
-
return !!(config.ctfdUrl && config.token);
|
|
60
|
-
}
|
|
1
|
+
import{mkdirSync as t,readFileSync as n,writeFileSync as o,existsSync as r}from"node:fs";import{join as e}from"node:path";import{homedir as i}from"node:os";import{randomUUID as s}from"node:crypto";import{DEFAULT_CONFIG as f,DEFAULT_BUDGET as u}from"../types/index.js";const c=e(i(),".icoa"),g=e(c,"config.json"),p=e(c,"budget.json");function d(){r(c)||t(c,{recursive:!0})}export function getConfig(){if(d(),!r(g)){const t={...f,sessionId:s()};return o(g,JSON.stringify(t,null,2)),t}try{const t=n(g,"utf-8");return{...f,...JSON.parse(t)}}catch{return{...f,sessionId:s()}}}export function saveConfig(t){d();const n={...getConfig(),...t};o(g,JSON.stringify(n,null,2))}export function getBudget(){if(d(),!r(p))return o(p,JSON.stringify(u,null,2)),{...u};try{const t=n(p,"utf-8");return{...u,...JSON.parse(t)}}catch{return{...u}}}export function saveBudget(t){d(),o(p,JSON.stringify(t,null,2))}export function getIcoaDir(){return d(),c}export function isConnected(){const t=getConfig();return!(!t.ctfdUrl||!t.token)}
|