@leejungkiin/awkit 1.6.6 → 1.7.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/bin/awk.js +186 -8
- package/package.json +5 -3
- package/schemas/onboarding-screen.schema.json +108 -0
- package/scripts/__pycache__/openrouter_image_gen.cpython-311.pyc +0 -0
- package/scripts/automation-gate.js +8 -7
- package/scripts/cockpit-quota.js +93 -0
- package/scripts/exec-rtk.js +50 -0
- package/scripts/openrouter_image_gen.py +772 -0
- package/scripts/video-analyzer.js +172 -0
- package/skills/CATALOG.md +3 -2
- package/skills/TRIGGER_INDEX.md +1 -1
- package/skills/ai-sprite-maker/SKILL.md +27 -6
- package/skills/ai-sprite-maker/scripts/__pycache__/remove_chroma_key.cpython-311.pyc +0 -0
- package/skills/ai-sprite-maker/scripts/remove_chroma_key.py +440 -0
- package/skills/awf-caveman/SKILL.md +65 -0
- package/skills/expo-build-optimizer/SKILL.md +33 -0
- package/skills/ios-app-store-audit/SKILL.md +48 -0
- package/skills/ios-expert-coder/SKILL.md +45 -0
- package/skills/marketing-spec-writer/SKILL.md +51 -0
- package/skills/marketing-spec-writer/templates/MARKETING_SPEC.md +53 -0
- package/skills/mascot-designer/SKILL.md +66 -0
- package/skills/mascot-designer/examples/witny-case-study.md +35 -0
- package/skills/orchestrator/SKILL.md +20 -0
- package/skills/review/SKILL.md +87 -0
- package/skills/short-maker/scripts/google-flow-cli/README.md +227 -115
- package/skills/short-maker/scripts/google-flow-cli/gflow/api/client.py +32 -3
- package/skills/short-maker/scripts/google-flow-cli/gflow/api/models.py +4 -2
- package/skills/short-maker/scripts/google-flow-cli/gflow/cli/main.py +33 -6
- package/skills/short-maker/scripts/google-flow-cli/pyproject.toml +1 -1
- package/skills/storyboard-to-scene-pack/SKILL.md +102 -0
- package/skills/storyboard-to-scene-pack/agents/openai.yaml +4 -0
- package/skills/storyboard-to-scene-pack/assets/preview-template/index.html +101 -0
- package/skills/storyboard-to-scene-pack/references/continuity-checklist.md +32 -0
- package/skills/storyboard-to-scene-pack/references/scene-prompt-template.md +19 -0
- package/skills/storyboard-to-scene-pack/references/storyboard-sheet-template.md +14 -0
- package/skills/verification-gate/SKILL.md +4 -0
- package/templates/help.html +21 -0
- package/templates/project-identity/android.json +24 -0
- package/templates/project-identity/backend-nestjs.json +24 -0
- package/templates/project-identity/expo.json +24 -0
- package/templates/project-identity/ios.json +24 -0
- package/templates/project-identity/web-nextjs.json +24 -0
- package/templates/specs/design-template.md +71 -161
- package/templates/specs/requirements-template.md +133 -65
- package/workflows/ui/create-spec-architect.md +80 -50
- package/workflows/ui/image-gen.md +118 -0
- package/skills/code-review/SKILL.md +0 -115
package/bin/awk.js
CHANGED
|
@@ -41,6 +41,8 @@ const { generateClaudeRules, generateClaudeSkills } = require('./claude-generato
|
|
|
41
41
|
const { generateCursorRules, generateCursorSkills } = require('./cursor-generators');
|
|
42
42
|
const { cmdGate } = require('../scripts/automation-gate');
|
|
43
43
|
const { cmdObsidian } = require('../scripts/obsidian-sync');
|
|
44
|
+
const { cmdQuota } = require('../scripts/cockpit-quota');
|
|
45
|
+
const { cmdVideo } = require('../scripts/video-analyzer');
|
|
44
46
|
|
|
45
47
|
// ─── Platform Definitions ──────────────────────────────────────────────────
|
|
46
48
|
|
|
@@ -55,6 +57,7 @@ const PLATFORMS = {
|
|
|
55
57
|
skills: 'skills',
|
|
56
58
|
schemas: 'schemas',
|
|
57
59
|
templates: 'templates',
|
|
60
|
+
scripts: 'scripts',
|
|
58
61
|
},
|
|
59
62
|
supportsCustomModes: false,
|
|
60
63
|
supportsSubagents: false,
|
|
@@ -736,6 +739,15 @@ function cmdInstall(args = []) {
|
|
|
736
739
|
ok(`${tmplCount} templates installed`);
|
|
737
740
|
}
|
|
738
741
|
|
|
742
|
+
// 8.5 Copy scripts (always overwrite)
|
|
743
|
+
if (plat.dirs.scripts) {
|
|
744
|
+
info('Installing scripts...');
|
|
745
|
+
const scriptsSrc = path.join(AWK_ROOT, 'scripts');
|
|
746
|
+
const scriptsDest = path.join(target, plat.dirs.scripts);
|
|
747
|
+
const scriptsCount = copyDirRecursive(scriptsSrc, scriptsDest);
|
|
748
|
+
ok(`${scriptsCount} scripts installed`);
|
|
749
|
+
}
|
|
750
|
+
|
|
739
751
|
// 9. Save version
|
|
740
752
|
fs.writeFileSync(plat.versionFile, AWK_VERSION);
|
|
741
753
|
ok(`Version ${AWK_VERSION} saved`);
|
|
@@ -986,6 +998,18 @@ function cmdDoctor() {
|
|
|
986
998
|
warn('schemas/ directory missing'); issues++;
|
|
987
999
|
}
|
|
988
1000
|
|
|
1001
|
+
// 4.5. Check RTK Integration
|
|
1002
|
+
try {
|
|
1003
|
+
const { checkRtk } = require('../scripts/exec-rtk');
|
|
1004
|
+
if (checkRtk()) {
|
|
1005
|
+
ok('RTK (Rust Token Killer) is installed and active');
|
|
1006
|
+
} else {
|
|
1007
|
+
warn('RTK (Rust Token Killer) not found. Run "awkit rtk setup" to optimize token usage.');
|
|
1008
|
+
}
|
|
1009
|
+
} catch (e) {
|
|
1010
|
+
warn(`RTK check failed: ${e.message}`);
|
|
1011
|
+
}
|
|
1012
|
+
|
|
989
1013
|
// 5. Check version
|
|
990
1014
|
if (fs.existsSync(TARGETS.versionFile)) {
|
|
991
1015
|
const v = fs.readFileSync(TARGETS.versionFile, 'utf8').trim();
|
|
@@ -2019,6 +2043,10 @@ function cmdHelp() {
|
|
|
2019
2043
|
log(` ${C.green}update${C.reset} Pull latest + reinstall`);
|
|
2020
2044
|
log(` ${C.green}lint${C.reset} Run skill & workflow guards (check length, frontmatter)`);
|
|
2021
2045
|
log(` ${C.green}doctor${C.reset} Check installation health`);
|
|
2046
|
+
log(` ${C.green}rtk setup${C.reset} Auto-install and configure RTK wrapper`);
|
|
2047
|
+
log(` ${C.green}credentials list${C.reset} List stored API keys`);
|
|
2048
|
+
log(` ${C.green}credentials set${C.reset} <k> <v> Set API key (e.g., gemini_api_key, openrouter_api_key)`);
|
|
2049
|
+
log(` ${C.green}set-openrouter${C.reset} <key> Shorthand for setting OpenRouter API Key`);
|
|
2022
2050
|
log('');
|
|
2023
2051
|
|
|
2024
2052
|
// Project Init
|
|
@@ -2034,6 +2062,13 @@ function cmdHelp() {
|
|
|
2034
2062
|
log(`${C.bold}🧹 Maintenance${C.reset}`);
|
|
2035
2063
|
log(line);
|
|
2036
2064
|
log(` ${C.green}serve${C.reset} [dir] [-p <port>] Start local HTTP server for assets in CWD`);
|
|
2065
|
+
log(` ${C.green}video${C.reset} <file.mp4> [pmt] Phân tích video/screen record bằng Gemini API`);
|
|
2066
|
+
log(` ${C.gray} --pro${C.reset} Dùng Gemini 3.1 Pro (Chất lượng cao nhất)`);
|
|
2067
|
+
log(` ${C.gray} --flash${C.reset} Dùng Gemini 3 Flash (Nhanh & Tiết kiệm)`);
|
|
2068
|
+
log(` ${C.gray} --debug${C.reset} Dùng prompt tìm lỗi, crash, log`);
|
|
2069
|
+
log(` ${C.gray} --uiux${C.reset} Dùng prompt đánh giá giao diện, animation`);
|
|
2070
|
+
log(` ${C.gray} --clone${C.reset} Dùng prompt bóc băng cấu trúc app đối thủ`);
|
|
2071
|
+
log(` ${C.green}quota${C.reset} Check AI Model Quota from Cockpit extension`);
|
|
2037
2072
|
log(` ${C.green}browser clean${C.reset} Clean browser recordings`);
|
|
2038
2073
|
log(` ${C.gray} --days <N>${C.reset} Keep recordings from last N days (default: 7)`);
|
|
2039
2074
|
log(` ${C.gray} --all${C.reset} Delete all recordings`);
|
|
@@ -2349,6 +2384,24 @@ function buildProjectIdentity(projectName, projectType, cwd, date) {
|
|
|
2349
2384
|
git: {
|
|
2350
2385
|
autoCommit: true,
|
|
2351
2386
|
autoPush: true
|
|
2387
|
+
},
|
|
2388
|
+
obsidian: {
|
|
2389
|
+
enabled: false,
|
|
2390
|
+
path: "",
|
|
2391
|
+
autoSync: false
|
|
2392
|
+
},
|
|
2393
|
+
mcp: {
|
|
2394
|
+
"pixel-mcp": {
|
|
2395
|
+
enabled: false
|
|
2396
|
+
}
|
|
2397
|
+
}
|
|
2398
|
+
},
|
|
2399
|
+
modelPolicy: {
|
|
2400
|
+
mode: "auto",
|
|
2401
|
+
defaultTier: "STANDARD",
|
|
2402
|
+
tierOverrides: {
|
|
2403
|
+
"*.plist|*.json|*.env": "LIGHT",
|
|
2404
|
+
"docs/*": "LIGHT"
|
|
2352
2405
|
}
|
|
2353
2406
|
},
|
|
2354
2407
|
projectStage: 'development',
|
|
@@ -2574,16 +2627,51 @@ async function cmdInit(forceFlag = false) {
|
|
|
2574
2627
|
git: {
|
|
2575
2628
|
autoCommit: true,
|
|
2576
2629
|
autoPush: true
|
|
2630
|
+
},
|
|
2631
|
+
obsidian: {
|
|
2632
|
+
enabled: false,
|
|
2633
|
+
path: "",
|
|
2634
|
+
autoSync: false
|
|
2635
|
+
},
|
|
2636
|
+
mcp: {
|
|
2637
|
+
"pixel-mcp": {
|
|
2638
|
+
enabled: false
|
|
2639
|
+
}
|
|
2577
2640
|
}
|
|
2578
2641
|
};
|
|
2579
2642
|
fs.writeFileSync(identityPath, JSON.stringify(currentIdentity, null, 2) + '\n');
|
|
2580
2643
|
ok('Added Automation config placeholder to .project-identity');
|
|
2581
|
-
} else
|
|
2582
|
-
|
|
2583
|
-
currentIdentity.automation.autoQA
|
|
2584
|
-
|
|
2585
|
-
|
|
2586
|
-
|
|
2644
|
+
} else {
|
|
2645
|
+
let changed = false;
|
|
2646
|
+
if (currentIdentity.automation.autoQA === undefined) {
|
|
2647
|
+
// Update existing automation block with new QA fields
|
|
2648
|
+
currentIdentity.automation.autoQA = true;
|
|
2649
|
+
currentIdentity.automation.maxSelfCorrectionLoops = 3;
|
|
2650
|
+
changed = true;
|
|
2651
|
+
}
|
|
2652
|
+
if (!currentIdentity.automation.obsidian) {
|
|
2653
|
+
currentIdentity.automation.obsidian = { enabled: false, path: "", autoSync: false };
|
|
2654
|
+
changed = true;
|
|
2655
|
+
}
|
|
2656
|
+
if (!currentIdentity.automation.mcp) {
|
|
2657
|
+
currentIdentity.automation.mcp = { "pixel-mcp": { enabled: false } };
|
|
2658
|
+
changed = true;
|
|
2659
|
+
}
|
|
2660
|
+
if (!currentIdentity.modelPolicy) {
|
|
2661
|
+
currentIdentity.modelPolicy = {
|
|
2662
|
+
mode: "auto",
|
|
2663
|
+
defaultTier: "STANDARD",
|
|
2664
|
+
tierOverrides: {
|
|
2665
|
+
"*.plist|*.json|*.env": "LIGHT",
|
|
2666
|
+
"docs/*": "LIGHT"
|
|
2667
|
+
}
|
|
2668
|
+
};
|
|
2669
|
+
changed = true;
|
|
2670
|
+
}
|
|
2671
|
+
if (changed) {
|
|
2672
|
+
fs.writeFileSync(identityPath, JSON.stringify(currentIdentity, null, 2) + '\n');
|
|
2673
|
+
ok('Updated Automation/ModelPolicy config with defaults in .project-identity');
|
|
2674
|
+
}
|
|
2587
2675
|
}
|
|
2588
2676
|
} catch (_) { /* ignore */ }
|
|
2589
2677
|
|
|
@@ -3042,7 +3130,7 @@ function credentialsHelp() {
|
|
|
3042
3130
|
log(` ${C.green}awkit credentials remove${C.reset} <key> Remove a credential`);
|
|
3043
3131
|
log(` ${C.green}awkit credentials setup${C.reset} Interactive setup wizard`);
|
|
3044
3132
|
log('');
|
|
3045
|
-
log(` ${C.gray}Known keys: gemini_api_key, lucylab_bearer${C.reset}`);
|
|
3133
|
+
log(` ${C.gray}Known keys: gemini_api_key, openrouter_api_key, lucylab_bearer${C.reset}`);
|
|
3046
3134
|
log(` ${C.gray}Config: ${CREDENTIALS_CONFIG_PATH}${C.reset}`);
|
|
3047
3135
|
log('');
|
|
3048
3136
|
}
|
|
@@ -3089,6 +3177,20 @@ async function credentialsSetup() {
|
|
|
3089
3177
|
dim('Kept existing LucyLab Bearer');
|
|
3090
3178
|
}
|
|
3091
3179
|
|
|
3180
|
+
log('');
|
|
3181
|
+
|
|
3182
|
+
// OpenRouter API Key
|
|
3183
|
+
log(`${C.gray} OpenRouter API Key for Premium Image Generation (GPT-5.4)${C.reset}`);
|
|
3184
|
+
log(`${C.gray} Get your key at: https://openrouter.ai/keys${C.reset}`);
|
|
3185
|
+
const openrouterKey = sanitize(await question(` ${C.yellow}OpenRouter API Key${config.openrouter_api_key ? ` [${config.openrouter_api_key.slice(0, 8)}...]` : ''}: ${C.reset}`));
|
|
3186
|
+
if (openrouterKey) {
|
|
3187
|
+
config.openrouter_api_key = openrouterKey;
|
|
3188
|
+
ok('OpenRouter API Key saved');
|
|
3189
|
+
} else if (config.openrouter_api_key) {
|
|
3190
|
+
dim('Kept existing OpenRouter API Key');
|
|
3191
|
+
}
|
|
3192
|
+
|
|
3193
|
+
log('');
|
|
3092
3194
|
credentialsSave(config);
|
|
3093
3195
|
log('');
|
|
3094
3196
|
ok(`Credentials saved to ${CREDENTIALS_CONFIG_PATH}`);
|
|
@@ -3759,6 +3861,65 @@ function cmdGitnexus(args) {
|
|
|
3759
3861
|
}
|
|
3760
3862
|
}
|
|
3761
3863
|
|
|
3864
|
+
// ─── RTK Integration ──────────────────────────────────────────────────────────
|
|
3865
|
+
|
|
3866
|
+
async function cmdRtkSetup() {
|
|
3867
|
+
log(`${C.cyan}${C.bold}╔═══════════════════════════════════════════════════════╗${C.reset}`);
|
|
3868
|
+
log(`${C.cyan}${C.bold}║ ⚙️ RTK Auto-Setup & Configuration ║${C.reset}`);
|
|
3869
|
+
log(`${C.cyan}${C.bold}╚═══════════════════════════════════════════════════════╝${C.reset}`);
|
|
3870
|
+
|
|
3871
|
+
log(`\nChecking dependencies...`);
|
|
3872
|
+
try {
|
|
3873
|
+
execSync('which cargo', { stdio: 'ignore' });
|
|
3874
|
+
ok('Cargo is installed.');
|
|
3875
|
+
} catch (_) {
|
|
3876
|
+
err('Cargo/Rust not found. Please install Rust (https://rustup.rs/) and retry.');
|
|
3877
|
+
return;
|
|
3878
|
+
}
|
|
3879
|
+
|
|
3880
|
+
log(`\nInstalling RTK (Rust Token Killer) via Cargo...`);
|
|
3881
|
+
try {
|
|
3882
|
+
execSync('cargo install --git https://github.com/rtk-ai/rtk', { stdio: 'inherit' });
|
|
3883
|
+
ok('RTK successfully installed/updated via Cargo.');
|
|
3884
|
+
} catch (e) {
|
|
3885
|
+
err(`Failed to install RTK: ${e.message}`);
|
|
3886
|
+
return;
|
|
3887
|
+
}
|
|
3888
|
+
|
|
3889
|
+
const zshrcPath = path.join(HOME, '.zshrc');
|
|
3890
|
+
log(`\nConfiguring Shell Aliases in ~/.zshrc...`);
|
|
3891
|
+
if (fs.existsSync(zshrcPath)) {
|
|
3892
|
+
const zshrc = fs.readFileSync(zshrcPath, 'utf8');
|
|
3893
|
+
const aliasBlock = `
|
|
3894
|
+
# RTK Alias for AI Agents (AWKit)
|
|
3895
|
+
alias git="rtk git"
|
|
3896
|
+
alias npm="rtk npm"
|
|
3897
|
+
alias pnpm="rtk pnpm"
|
|
3898
|
+
alias yarn="rtk yarn"
|
|
3899
|
+
alias cargo="rtk cargo"
|
|
3900
|
+
`;
|
|
3901
|
+
if (zshrc.includes('alias git="rtk git"')) {
|
|
3902
|
+
ok('Aliases already present in ~/.zshrc.');
|
|
3903
|
+
} else {
|
|
3904
|
+
fs.appendFileSync(zshrcPath, aliasBlock, 'utf8');
|
|
3905
|
+
ok('Shell aliases successfully added to ~/.zshrc.');
|
|
3906
|
+
log(`\n${C.cyan}Please reload your shell (source ~/.zshrc) to apply shifts.${C.reset}`);
|
|
3907
|
+
}
|
|
3908
|
+
} else {
|
|
3909
|
+
warn('~/.zshrc not found. Skipping alias setup.');
|
|
3910
|
+
}
|
|
3911
|
+
}
|
|
3912
|
+
|
|
3913
|
+
async function cmdRtk(args) {
|
|
3914
|
+
const action = args[0];
|
|
3915
|
+
if (action === 'setup') {
|
|
3916
|
+
await cmdRtkSetup();
|
|
3917
|
+
} else {
|
|
3918
|
+
err(`Unknown rtk command: ${action || ''}`);
|
|
3919
|
+
log(` Available: setup`);
|
|
3920
|
+
}
|
|
3921
|
+
}
|
|
3922
|
+
|
|
3762
3923
|
// ─── Native HTTP Server ───────────────────────────────────────────────────────
|
|
3763
3924
|
|
|
3764
3925
|
function cmdServe(args) {
|
|
@@ -3918,9 +4079,21 @@ const [, , command, ...args] = process.argv;
|
|
|
3918
4079
|
case 'creds':
|
|
3919
4080
|
cmdCredentials(args);
|
|
3920
4081
|
break;
|
|
4082
|
+
case 'set-openrouter': {
|
|
4083
|
+
const key = args[0];
|
|
4084
|
+
if (!key) {
|
|
4085
|
+
err('Usage: awkit set-openrouter <api_key>');
|
|
4086
|
+
return;
|
|
4087
|
+
}
|
|
4088
|
+
cmdCredentials(['set', 'openrouter_api_key', key]);
|
|
4089
|
+
break;
|
|
4090
|
+
}
|
|
3921
4091
|
case 'serve':
|
|
3922
4092
|
cmdServe(args);
|
|
3923
4093
|
break;
|
|
4094
|
+
case 'rtk':
|
|
4095
|
+
await cmdRtk(args);
|
|
4096
|
+
break;
|
|
3924
4097
|
case 'gitnexus':
|
|
3925
4098
|
case 'gn':
|
|
3926
4099
|
cmdGitnexus(args);
|
|
@@ -3928,13 +4101,18 @@ const [, , command, ...args] = process.argv;
|
|
|
3928
4101
|
case 'gate':
|
|
3929
4102
|
cmdGate(args);
|
|
3930
4103
|
break;
|
|
3931
|
-
case 'obsidian':
|
|
3932
4104
|
case 'obs':
|
|
3933
4105
|
cmdObsidian(args);
|
|
3934
4106
|
break;
|
|
4107
|
+
case 'quota':
|
|
4108
|
+
cmdQuota(args);
|
|
4109
|
+
break;
|
|
3935
4110
|
case 'admin':
|
|
3936
4111
|
cmdAdmin();
|
|
3937
4112
|
break;
|
|
4113
|
+
case 'video':
|
|
4114
|
+
await cmdVideo(args);
|
|
4115
|
+
break;
|
|
3938
4116
|
case 'restart':
|
|
3939
4117
|
await cmdRestart();
|
|
3940
4118
|
break;
|
package/package.json
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@leejungkiin/awkit",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.7.0",
|
|
4
4
|
"description": "Antigravity Workflow Kit v1.6 Unified AI agent orchestration system with Mindful Checkpoints.",
|
|
5
5
|
"main": "bin/awk.js",
|
|
6
|
+
"private": false,
|
|
6
7
|
"bin": {
|
|
7
8
|
"awkit": "bin/awk.js",
|
|
8
9
|
"ag": "bin/awk.js"
|
|
@@ -38,7 +39,8 @@
|
|
|
38
39
|
"CHANGELOG.md"
|
|
39
40
|
],
|
|
40
41
|
"dependencies": {
|
|
41
|
-
"@
|
|
42
|
-
"@
|
|
42
|
+
"@duytransipher/gitnexus": "latest",
|
|
43
|
+
"@google/genai": "^1.50.1",
|
|
44
|
+
"@leejungkiin/awkit-symphony": "^0.1.0"
|
|
43
45
|
}
|
|
44
46
|
}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"title": "Onboarding Quiz Funnel Configuration",
|
|
4
|
+
"description": "Schema for defining a highly-converting, behaviorally-driven onboarding quiz funnel.",
|
|
5
|
+
"type": "object",
|
|
6
|
+
"required": ["funnelId", "screens"],
|
|
7
|
+
"properties": {
|
|
8
|
+
"funnelId": {
|
|
9
|
+
"type": "string",
|
|
10
|
+
"description": "Unique identifier for this onboarding funnel."
|
|
11
|
+
},
|
|
12
|
+
"defaultMascotId": {
|
|
13
|
+
"type": "string",
|
|
14
|
+
"description": "ID of the default mascot to use if a screen doesn't override it."
|
|
15
|
+
},
|
|
16
|
+
"screens": {
|
|
17
|
+
"type": "array",
|
|
18
|
+
"description": "An ordered array of screens the user will navigate through.",
|
|
19
|
+
"items": {
|
|
20
|
+
"$ref": "#/definitions/Screen"
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
"definitions": {
|
|
25
|
+
"Screen": {
|
|
26
|
+
"type": "object",
|
|
27
|
+
"required": ["id", "phase", "type", "title"],
|
|
28
|
+
"properties": {
|
|
29
|
+
"id": {
|
|
30
|
+
"type": "string",
|
|
31
|
+
"description": "Unique identifier for the screen."
|
|
32
|
+
},
|
|
33
|
+
"phase": {
|
|
34
|
+
"type": "string",
|
|
35
|
+
"enum": ["hook", "therapy", "objection", "labor_illusion", "reveal", "paywall"],
|
|
36
|
+
"description": "The psychological phase this screen belongs to."
|
|
37
|
+
},
|
|
38
|
+
"type": {
|
|
39
|
+
"type": "string",
|
|
40
|
+
"enum": ["intro", "single_choice", "multi_choice", "slider", "loading_simulation", "summary", "paywall"],
|
|
41
|
+
"description": "The functional UI type of the screen."
|
|
42
|
+
},
|
|
43
|
+
"title": {
|
|
44
|
+
"type": "string",
|
|
45
|
+
"description": "Main heading or question displayed to the user."
|
|
46
|
+
},
|
|
47
|
+
"subtitle": {
|
|
48
|
+
"type": "string",
|
|
49
|
+
"description": "Secondary text providing context or reassurance."
|
|
50
|
+
},
|
|
51
|
+
"mascotState": {
|
|
52
|
+
"type": "string",
|
|
53
|
+
"enum": ["none", "greeting", "thinking", "encouraging", "empathizing", "analyzing", "presenting", "celebrating", "idle"],
|
|
54
|
+
"description": "The emotional state of the virtual coach to display."
|
|
55
|
+
},
|
|
56
|
+
"progressSpeed": {
|
|
57
|
+
"type": "string",
|
|
58
|
+
"enum": ["fast", "normal", "slow", "jump"],
|
|
59
|
+
"description": "Manipulative progress bar speed for this screen."
|
|
60
|
+
},
|
|
61
|
+
"options": {
|
|
62
|
+
"type": "array",
|
|
63
|
+
"description": "Choices presented to the user (for single_choice or multi_choice types).",
|
|
64
|
+
"items": {
|
|
65
|
+
"$ref": "#/definitions/Option"
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
"loadingConfiguration": {
|
|
69
|
+
"type": "object",
|
|
70
|
+
"description": "Configuration specifically for labor_illusion screens.",
|
|
71
|
+
"properties": {
|
|
72
|
+
"durationMs": { "type": "integer" },
|
|
73
|
+
"fakeSteps": {
|
|
74
|
+
"type": "array",
|
|
75
|
+
"items": { "type": "string" }
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
},
|
|
81
|
+
"Option": {
|
|
82
|
+
"type": "object",
|
|
83
|
+
"required": ["id", "label"],
|
|
84
|
+
"properties": {
|
|
85
|
+
"id": {
|
|
86
|
+
"type": "string"
|
|
87
|
+
},
|
|
88
|
+
"label": {
|
|
89
|
+
"type": "string",
|
|
90
|
+
"description": "The text displayed on the button."
|
|
91
|
+
},
|
|
92
|
+
"icon": {
|
|
93
|
+
"type": "string",
|
|
94
|
+
"description": "Optional icon identifier for the option."
|
|
95
|
+
},
|
|
96
|
+
"tagsToApply": {
|
|
97
|
+
"type": "array",
|
|
98
|
+
"description": "List of tags to assign to the user if they select this option.",
|
|
99
|
+
"items": { "type": "string" }
|
|
100
|
+
},
|
|
101
|
+
"reinforcementMessage": {
|
|
102
|
+
"type": "string",
|
|
103
|
+
"description": "An intermittent reinforcement message to show after selecting this option (e.g., '70% of our users feel the same way.')."
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
Binary file
|
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
const fs = require('fs');
|
|
19
19
|
const path = require('path');
|
|
20
20
|
const { execSync } = require('child_process');
|
|
21
|
+
const { execRtkSync } = require('./exec-rtk');
|
|
21
22
|
|
|
22
23
|
// Lazy-load obsidian-sync to avoid circular dependencies
|
|
23
24
|
let _autoSyncObsidian = null;
|
|
@@ -174,8 +175,8 @@ function execGitCommit(message) {
|
|
|
174
175
|
}
|
|
175
176
|
|
|
176
177
|
try {
|
|
177
|
-
|
|
178
|
-
|
|
178
|
+
execRtkSync('git add -A', { stdio: 'inherit' });
|
|
179
|
+
execRtkSync(`git commit -m "${message.replace(/"/g, '\\"')}"`, { stdio: 'inherit' });
|
|
179
180
|
ok(`Committed: ${message}`);
|
|
180
181
|
return true;
|
|
181
182
|
} catch (e) {
|
|
@@ -198,13 +199,13 @@ function execGitPush() {
|
|
|
198
199
|
}
|
|
199
200
|
|
|
200
201
|
try {
|
|
201
|
-
|
|
202
|
+
execRtkSync('git push', { stdio: 'inherit' });
|
|
202
203
|
ok('Pushed successfully.');
|
|
203
204
|
return true;
|
|
204
205
|
} catch (e) {
|
|
205
206
|
warn('Push failed. Retrying with git pull --rebase...');
|
|
206
207
|
try {
|
|
207
|
-
|
|
208
|
+
execRtkSync('git pull --rebase && git push', { stdio: 'inherit' });
|
|
208
209
|
ok('Pushed successfully after rebase.');
|
|
209
210
|
return true;
|
|
210
211
|
} catch (e2) {
|
|
@@ -231,7 +232,7 @@ function execGitAuto(message) {
|
|
|
231
232
|
if (tgGate.allowed) {
|
|
232
233
|
info('Triggering Telegram notification...');
|
|
233
234
|
try {
|
|
234
|
-
|
|
235
|
+
execRtkSync(`awkit tg send "✅ Pushed: ${message.replace(/"/g, '\\"')}"`, { stdio: 'inherit' });
|
|
235
236
|
} catch (_) {
|
|
236
237
|
dim('Telegram notification skipped (not configured or failed).');
|
|
237
238
|
}
|
|
@@ -255,7 +256,7 @@ function execTrelloAction(action, args) {
|
|
|
255
256
|
|
|
256
257
|
try {
|
|
257
258
|
const cmd = `awkit trello ${action} ${args.map(a => `"${a}"`).join(' ')}`;
|
|
258
|
-
|
|
259
|
+
execRtkSync(cmd, { stdio: 'inherit' });
|
|
259
260
|
// Trigger Obsidian sync after successful trello action
|
|
260
261
|
getAutoSyncObsidian()();
|
|
261
262
|
return true;
|
|
@@ -277,7 +278,7 @@ function execTelegramSend(args) {
|
|
|
277
278
|
|
|
278
279
|
try {
|
|
279
280
|
const cmd = `awkit tg send ${args.map(a => `"${a}"`).join(' ')}`;
|
|
280
|
-
|
|
281
|
+
execRtkSync(cmd, { stdio: 'inherit' });
|
|
281
282
|
return true;
|
|
282
283
|
} catch (e) {
|
|
283
284
|
err(`Telegram send failed: ${e.message}`);
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
const fs = require('fs');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const os = require('os');
|
|
4
|
+
|
|
5
|
+
const C = {
|
|
6
|
+
reset: '\x1b[0m',
|
|
7
|
+
green: '\x1b[32m',
|
|
8
|
+
yellow: '\x1b[33m',
|
|
9
|
+
red: '\x1b[31m',
|
|
10
|
+
cyan: '\x1b[36m',
|
|
11
|
+
bold: '\x1b[1m',
|
|
12
|
+
gray: '\x1b[90m',
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
function cmdQuota(args) {
|
|
16
|
+
const quotaDir = path.join(os.homedir(), '.antigravity_cockpit', 'cache', 'quota_api_v1_plugin', 'authorized');
|
|
17
|
+
|
|
18
|
+
if (!fs.existsSync(quotaDir)) {
|
|
19
|
+
console.log(`${C.yellow}⚠️ Cockpit quota cache not found at ${quotaDir}${C.reset}`);
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const files = fs.readdirSync(quotaDir).filter(f => f.endsWith('.json'));
|
|
24
|
+
if (files.length === 0) {
|
|
25
|
+
console.log(`${C.yellow}⚠️ No authorized quota files found. Make sure Cockpit extension is logged in.${C.reset}`);
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
let allAccounts = [];
|
|
30
|
+
|
|
31
|
+
for (const file of files) {
|
|
32
|
+
try {
|
|
33
|
+
const data = JSON.parse(fs.readFileSync(path.join(quotaDir, file), 'utf8'));
|
|
34
|
+
if (data && data.email && data.payload && data.payload.models) {
|
|
35
|
+
allAccounts.push(data);
|
|
36
|
+
}
|
|
37
|
+
} catch (e) {
|
|
38
|
+
// ignore parse error
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (allAccounts.length === 0) {
|
|
43
|
+
console.log(`${C.yellow}⚠️ Quota files unreadable.${C.reset}`);
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Sort by most recently updated
|
|
48
|
+
allAccounts.sort((a, b) => (b.updatedAt || 0) - (a.updatedAt || 0));
|
|
49
|
+
|
|
50
|
+
console.log(`${C.cyan}${C.bold}🚀 AI Model Quota Status (Antigravity Cockpit)${C.reset}\n`);
|
|
51
|
+
|
|
52
|
+
for (const account of allAccounts) {
|
|
53
|
+
const timeAgoMs = Date.now() - (account.updatedAt || Date.now());
|
|
54
|
+
const timeAgoMins = Math.round(Math.max(0, timeAgoMs) / 60000);
|
|
55
|
+
console.log(`${C.bold}📧 Account: ${account.email}${C.reset} ${C.gray}(Updated ${timeAgoMins} mins ago)${C.reset}`);
|
|
56
|
+
|
|
57
|
+
const models = Object.values(account.payload.models).filter(m => m.quotaInfo && m.quotaInfo.remainingFraction !== undefined);
|
|
58
|
+
|
|
59
|
+
if (models.length === 0) {
|
|
60
|
+
console.log(` ${C.gray}No models found with quota info.${C.reset}\n`);
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Sort by displayName length to pad
|
|
65
|
+
const maxLen = Math.max(...models.map(m => (m.displayName || m.model).length));
|
|
66
|
+
|
|
67
|
+
// Sort models by displayName for consistent viewing
|
|
68
|
+
models.sort((a, b) => (a.displayName || a.model).localeCompare(b.displayName || b.model));
|
|
69
|
+
|
|
70
|
+
for (const m of models) {
|
|
71
|
+
const name = (m.displayName || m.model).padEnd(maxLen);
|
|
72
|
+
const fraction = m.quotaInfo.remainingFraction;
|
|
73
|
+
const pct = (fraction * 100).toFixed(2).padStart(6, ' ') + '%';
|
|
74
|
+
|
|
75
|
+
let color = C.green;
|
|
76
|
+
if (fraction <= 0.2) color = C.red;
|
|
77
|
+
else if (fraction < 0.5) color = C.yellow;
|
|
78
|
+
|
|
79
|
+
let resetTimeStr = '';
|
|
80
|
+
if (m.quotaInfo.resetTime) {
|
|
81
|
+
const resetDate = new Date(m.quotaInfo.resetTime);
|
|
82
|
+
if (resetDate.getTime() > Date.now()) {
|
|
83
|
+
resetTimeStr = ` (Resets: ${resetDate.toLocaleTimeString()})`;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
console.log(` ${name} : ${color}${pct}${C.reset}${C.gray}${resetTimeStr}${C.reset}`);
|
|
88
|
+
}
|
|
89
|
+
console.log('');
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
module.exports = { cmdQuota };
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
const { execSync } = require('child_process');
|
|
2
|
+
|
|
3
|
+
let hasRtkCache = null;
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Check if rtk binary is available in the current environment PATH.
|
|
7
|
+
* @returns {boolean}
|
|
8
|
+
*/
|
|
9
|
+
function checkRtk() {
|
|
10
|
+
if (hasRtkCache !== null) return hasRtkCache;
|
|
11
|
+
try {
|
|
12
|
+
execSync('which rtk', { stdio: 'ignore' });
|
|
13
|
+
hasRtkCache = true;
|
|
14
|
+
} catch (_) {
|
|
15
|
+
hasRtkCache = false;
|
|
16
|
+
}
|
|
17
|
+
return hasRtkCache;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Execute command with rtk prefix if available and eligible.
|
|
22
|
+
* @param {string} command
|
|
23
|
+
* @param {object} options
|
|
24
|
+
* @returns {Buffer|string}
|
|
25
|
+
*/
|
|
26
|
+
function execRtkSync(command, options = {}) {
|
|
27
|
+
if (!checkRtk()) {
|
|
28
|
+
return execSync(command, options);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const trimmed = command.trim();
|
|
32
|
+
if (trimmed.startsWith('rtk ')) {
|
|
33
|
+
return execSync(command, options);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Only compress developer commands known to be verbose
|
|
37
|
+
const eligiblePrefixes = ['git ', 'npm ', 'cargo ', 'yarn ', 'pnpm ', 'grep ', 'find ', 'awkit trello '];
|
|
38
|
+
const isEligible = eligiblePrefixes.some(prefix => trimmed.startsWith(prefix));
|
|
39
|
+
|
|
40
|
+
if (isEligible) {
|
|
41
|
+
return execSync(`rtk ${command}`, options);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return execSync(command, options);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
module.exports = {
|
|
48
|
+
execRtkSync,
|
|
49
|
+
checkRtk
|
|
50
|
+
};
|