@chrysb/alphaclaw 0.3.5-beta.0 → 0.4.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.
Files changed (64) hide show
  1. package/bin/alphaclaw.js +66 -32
  2. package/lib/public/assets/icons/google_icon.svg +8 -0
  3. package/lib/public/css/explorer.css +254 -6
  4. package/lib/public/js/app.js +165 -100
  5. package/lib/public/js/components/channels.js +1 -0
  6. package/lib/public/js/components/credentials-modal.js +36 -8
  7. package/lib/public/js/components/file-tree.js +267 -88
  8. package/lib/public/js/components/file-viewer/constants.js +6 -0
  9. package/lib/public/js/components/file-viewer/diff-viewer.js +46 -0
  10. package/lib/public/js/components/file-viewer/editor-surface.js +120 -0
  11. package/lib/public/js/components/file-viewer/frontmatter-panel.js +56 -0
  12. package/lib/public/js/components/file-viewer/index.js +202 -0
  13. package/lib/public/js/components/file-viewer/markdown-split-view.js +51 -0
  14. package/lib/public/js/components/file-viewer/media-preview.js +44 -0
  15. package/lib/public/js/components/file-viewer/scroll-sync.js +95 -0
  16. package/lib/public/js/components/file-viewer/sqlite-viewer.js +167 -0
  17. package/lib/public/js/components/file-viewer/status-banners.js +64 -0
  18. package/lib/public/js/components/file-viewer/storage.js +58 -0
  19. package/lib/public/js/components/file-viewer/toolbar.js +119 -0
  20. package/lib/public/js/components/file-viewer/use-editor-selection-restore.js +93 -0
  21. package/lib/public/js/components/file-viewer/use-file-diff.js +60 -0
  22. package/lib/public/js/components/file-viewer/use-file-loader.js +312 -0
  23. package/lib/public/js/components/file-viewer/use-file-viewer-draft-sync.js +32 -0
  24. package/lib/public/js/components/file-viewer/use-file-viewer-hotkeys.js +25 -0
  25. package/lib/public/js/components/file-viewer/use-file-viewer.js +471 -0
  26. package/lib/public/js/components/file-viewer/utils.js +11 -0
  27. package/lib/public/js/components/gateway.js +83 -30
  28. package/lib/public/js/components/google/account-row.js +98 -0
  29. package/lib/public/js/components/google/add-account-modal.js +93 -0
  30. package/lib/public/js/components/google/index.js +439 -0
  31. package/lib/public/js/components/google/use-google-accounts.js +41 -0
  32. package/lib/public/js/components/icons.js +39 -0
  33. package/lib/public/js/components/sidebar-git-panel.js +115 -25
  34. package/lib/public/js/components/sidebar.js +91 -75
  35. package/lib/public/js/components/usage-tab.js +4 -1
  36. package/lib/public/js/components/watchdog-tab.js +6 -0
  37. package/lib/public/js/lib/api.js +88 -8
  38. package/lib/public/js/lib/browse-file-policies.js +52 -0
  39. package/lib/public/js/lib/syntax-highlighters/index.js +6 -5
  40. package/lib/public/shared/browse-file-policies.json +13 -0
  41. package/lib/scripts/git +40 -0
  42. package/lib/scripts/git-askpass +6 -0
  43. package/lib/server/constants.js +20 -0
  44. package/lib/server/google-state.js +187 -0
  45. package/lib/server/helpers.js +12 -4
  46. package/lib/server/onboarding/github.js +21 -2
  47. package/lib/server/onboarding/index.js +1 -3
  48. package/lib/server/onboarding/openclaw.js +3 -0
  49. package/lib/server/onboarding/workspace.js +40 -0
  50. package/lib/server/routes/browse/constants.js +51 -0
  51. package/lib/server/routes/browse/file-helpers.js +43 -0
  52. package/lib/server/routes/browse/git.js +131 -0
  53. package/lib/server/routes/browse/index.js +660 -0
  54. package/lib/server/routes/browse/path-utils.js +53 -0
  55. package/lib/server/routes/browse/sqlite.js +140 -0
  56. package/lib/server/routes/google.js +414 -213
  57. package/lib/server/routes/proxy.js +11 -5
  58. package/lib/setup/core-prompts/TOOLS.md +0 -4
  59. package/lib/setup/gitignore +3 -0
  60. package/lib/setup/hourly-git-sync.sh +28 -1
  61. package/package.json +1 -1
  62. package/lib/public/js/components/file-viewer.js +0 -1095
  63. package/lib/public/js/components/google.js +0 -228
  64. package/lib/server/routes/browse.js +0 -500
package/bin/alphaclaw.js CHANGED
@@ -626,37 +626,7 @@ try {
626
626
  } catch {}
627
627
 
628
628
  // ---------------------------------------------------------------------------
629
- // 10. Configure gog credentials (if env vars present)
630
- // ---------------------------------------------------------------------------
631
-
632
- if (process.env.GOG_CLIENT_CREDENTIALS_JSON && process.env.GOG_REFRESH_TOKEN) {
633
- try {
634
- const tmpCreds = `/tmp/gog-creds-${process.pid}.json`;
635
- const tmpToken = `/tmp/gog-token-${process.pid}.json`;
636
- fs.writeFileSync(tmpCreds, process.env.GOG_CLIENT_CREDENTIALS_JSON);
637
- execSync(`gog auth credentials set "${tmpCreds}"`, { stdio: "ignore" });
638
- fs.unlinkSync(tmpCreds);
639
- fs.writeFileSync(
640
- tmpToken,
641
- JSON.stringify({
642
- email: process.env.GOG_ACCOUNT || "",
643
- refresh_token: process.env.GOG_REFRESH_TOKEN,
644
- }),
645
- );
646
- execSync(`gog auth tokens import "${tmpToken}"`, { stdio: "ignore" });
647
- fs.unlinkSync(tmpToken);
648
- console.log(
649
- `[alphaclaw] gog CLI configured for ${process.env.GOG_ACCOUNT || "account"}`,
650
- );
651
- } catch (e) {
652
- console.log(`[alphaclaw] gog credentials setup skipped: ${e.message}`);
653
- }
654
- } else {
655
- console.log("[alphaclaw] Google credentials not set -- skipping gog setup");
656
- }
657
-
658
- // ---------------------------------------------------------------------------
659
- // 11. Reconcile channels if already onboarded
629
+ // 10. Reconcile channels if already onboarded
660
630
  // ---------------------------------------------------------------------------
661
631
 
662
632
  const configPath = path.join(openclawDir, "openclaw.json");
@@ -753,6 +723,25 @@ if (fs.existsSync(configPath)) {
753
723
  stdio: "ignore",
754
724
  env: gitEnv,
755
725
  });
726
+ try {
727
+ execSync("git show-ref --verify --quiet refs/heads/main", {
728
+ cwd: openclawDir,
729
+ stdio: "ignore",
730
+ });
731
+ try {
732
+ execSync("git rev-parse --abbrev-ref --symbolic-full-name main@{upstream}", {
733
+ cwd: openclawDir,
734
+ stdio: "ignore",
735
+ });
736
+ } catch {
737
+ execSync("git branch --set-upstream-to=origin/main main", {
738
+ cwd: openclawDir,
739
+ stdio: "ignore",
740
+ env: gitEnv,
741
+ });
742
+ console.log("[alphaclaw] Set main upstream to origin/main");
743
+ }
744
+ } catch {}
756
745
  const remoteConfig = String(
757
746
  execSync(`git show "origin/${branch}:openclaw.json"`, {
758
747
  cwd: openclawDir,
@@ -871,7 +860,52 @@ try {
871
860
  }
872
861
 
873
862
  // ---------------------------------------------------------------------------
874
- // 13. Start Express server
863
+ // 13. Install git auth shim
864
+ // ---------------------------------------------------------------------------
865
+
866
+ try {
867
+ const gitAskPassSrc = path.join(__dirname, "..", "lib", "scripts", "git-askpass");
868
+ const gitAskPassDest = "/tmp/alphaclaw-git-askpass.sh";
869
+ const gitShimTemplatePath = path.join(__dirname, "..", "lib", "scripts", "git");
870
+ const gitShimDest = "/usr/local/bin/git";
871
+
872
+ if (fs.existsSync(gitAskPassSrc)) {
873
+ fs.copyFileSync(gitAskPassSrc, gitAskPassDest);
874
+ fs.chmodSync(gitAskPassDest, 0o755);
875
+ }
876
+
877
+ if (fs.existsSync(gitShimTemplatePath)) {
878
+ let realGitPath = "/usr/bin/git";
879
+ try {
880
+ const gitCandidates = String(
881
+ execSync("which -a git", {
882
+ stdio: ["ignore", "pipe", "ignore"],
883
+ encoding: "utf8",
884
+ }),
885
+ )
886
+ .split("\n")
887
+ .map((candidate) => candidate.trim())
888
+ .filter(Boolean);
889
+ const normalizedShimDest = path.resolve(gitShimDest);
890
+ const selectedCandidate = gitCandidates.find(
891
+ (candidatePath) => path.resolve(candidatePath) !== normalizedShimDest,
892
+ );
893
+ if (selectedCandidate) realGitPath = selectedCandidate;
894
+ } catch {}
895
+
896
+ const gitShimTemplate = fs.readFileSync(gitShimTemplatePath, "utf8");
897
+ const gitShimContent = gitShimTemplate
898
+ .replace("@@REAL_GIT@@", realGitPath)
899
+ .replace("@@OPENCLAW_REPO_ROOT@@", openclawDir);
900
+ fs.writeFileSync(gitShimDest, gitShimContent, { mode: 0o755 });
901
+ console.log("[alphaclaw] git auth shim installed");
902
+ }
903
+ } catch (e) {
904
+ console.log(`[alphaclaw] git auth shim skipped: ${e.message}`);
905
+ }
906
+
907
+ // ---------------------------------------------------------------------------
908
+ // 14. Start Express server
875
909
  // ---------------------------------------------------------------------------
876
910
 
877
911
  console.log("[alphaclaw] Setup complete -- starting server");
@@ -0,0 +1,8 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" role="img" aria-labelledby="title">
2
+ <title>Google</title>
3
+ <path d="M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92c-.26 1.37-1.04 2.53-2.21 3.31v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.09z" fill="#4285F4"/>
4
+ <path d="M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z" fill="#34A853"/>
5
+ <path d="M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z" fill="#FBBC05"/>
6
+ <path d="M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z" fill="#EA4335"/>
7
+ <path d="M1 1h22v22H1z" fill="none"/>
8
+ </svg>
@@ -216,6 +216,28 @@
216
216
  background: var(--bg-hover);
217
217
  }
218
218
 
219
+ .tree-folder.active {
220
+ background: var(--bg-active);
221
+ color: var(--accent);
222
+ }
223
+
224
+ .tree-folder.active .arrow {
225
+ color: var(--accent);
226
+ }
227
+
228
+ .tree-folder-toggle {
229
+ border: 0;
230
+ margin: 0;
231
+ padding: 0;
232
+ background: transparent;
233
+ color: inherit;
234
+ display: inline-flex;
235
+ align-items: center;
236
+ justify-content: center;
237
+ cursor: pointer;
238
+ flex: 0 0 auto;
239
+ }
240
+
219
241
  .arrow {
220
242
  font-size: 10px;
221
243
  transition: transform 0.15s;
@@ -259,6 +281,10 @@
259
281
  color: #ff7ac6;
260
282
  }
261
283
 
284
+ .file-icon-audio {
285
+ color: #f5a6ff;
286
+ }
287
+
262
288
  .file-icon-shell {
263
289
  color: #71f8a7;
264
290
  }
@@ -561,6 +587,37 @@
561
587
  flex-shrink: 0;
562
588
  }
563
589
 
590
+ .file-viewer-icon-action {
591
+ display: inline-flex;
592
+ align-items: center;
593
+ justify-content: center;
594
+ width: 28px;
595
+ height: 28px;
596
+ margin-right: 10px;
597
+ border: 1px solid var(--border);
598
+ border-radius: 8px;
599
+ background: rgba(255, 255, 255, 0.02);
600
+ color: var(--text-muted);
601
+ transition: border-color 0.12s ease, color 0.12s ease, background 0.12s ease;
602
+ }
603
+
604
+ .file-viewer-icon-action:hover {
605
+ border-color: rgba(148, 163, 184, 0.45);
606
+ color: var(--text);
607
+ background: rgba(148, 163, 184, 0.08);
608
+ }
609
+
610
+ .file-viewer-icon-action.is-disabled {
611
+ opacity: 0.45;
612
+ cursor: not-allowed;
613
+ }
614
+
615
+ .file-viewer-icon-action-icon {
616
+ width: 14px;
617
+ height: 14px;
618
+ flex-shrink: 0;
619
+ }
620
+
564
621
  .file-viewer-view-toggle {
565
622
  display: flex;
566
623
  align-items: center;
@@ -929,6 +986,187 @@
929
986
  color: var(--text-muted);
930
987
  }
931
988
 
989
+ .file-viewer-image-shell {
990
+ flex: 1 1 auto;
991
+ min-height: 0;
992
+ height: 100%;
993
+ display: flex;
994
+ align-items: center;
995
+ justify-content: center;
996
+ padding: 18px;
997
+ overflow: auto;
998
+ }
999
+
1000
+ .file-viewer-image {
1001
+ max-width: 100%;
1002
+ max-height: 100%;
1003
+ width: auto;
1004
+ height: auto;
1005
+ border-radius: 8px;
1006
+ border: 1px solid var(--border);
1007
+ background: rgba(255, 255, 255, 0.02);
1008
+ box-shadow: 0 8px 30px rgba(0, 0, 0, 0.35);
1009
+ }
1010
+
1011
+ .file-viewer-audio-shell {
1012
+ flex: 1 1 auto;
1013
+ min-height: 0;
1014
+ height: 100%;
1015
+ display: flex;
1016
+ align-items: center;
1017
+ justify-content: center;
1018
+ padding: 18px;
1019
+ overflow: auto;
1020
+ }
1021
+
1022
+ .file-viewer-audio-player {
1023
+ width: min(640px, 100%);
1024
+ }
1025
+
1026
+ .file-viewer-sqlite-shell {
1027
+ flex: 1 1 auto;
1028
+ min-height: 0;
1029
+ height: 100%;
1030
+ overflow: auto;
1031
+ padding: 14px 16px 22px;
1032
+ }
1033
+
1034
+ .file-viewer-sqlite-header {
1035
+ font-size: 12px;
1036
+ color: var(--text-dim);
1037
+ margin-bottom: 10px;
1038
+ }
1039
+
1040
+ .file-viewer-sqlite-footer {
1041
+ margin-top: 10px;
1042
+ text-align: center;
1043
+ font-size: 12px;
1044
+ color: var(--text-dim);
1045
+ }
1046
+
1047
+ .file-viewer-sqlite-list {
1048
+ flex: 0 0 240px;
1049
+ display: flex;
1050
+ flex-direction: column;
1051
+ gap: 8px;
1052
+ }
1053
+
1054
+ .file-viewer-sqlite-layout {
1055
+ display: flex;
1056
+ gap: 12px;
1057
+ align-items: stretch;
1058
+ min-height: 0;
1059
+ }
1060
+
1061
+ .file-viewer-sqlite-card {
1062
+ width: 100%;
1063
+ text-align: left;
1064
+ cursor: pointer;
1065
+ display: flex;
1066
+ align-items: center;
1067
+ border: 1px solid var(--border);
1068
+ border-radius: 8px;
1069
+ padding: 7px 10px;
1070
+ background: rgba(255, 255, 255, 0.02);
1071
+ font: inherit;
1072
+ }
1073
+
1074
+ .file-viewer-sqlite-card:hover {
1075
+ background: rgba(255, 255, 255, 0.04);
1076
+ }
1077
+
1078
+ .file-viewer-sqlite-card.is-active {
1079
+ border-color: rgba(99, 235, 255, 0.45);
1080
+ background: rgba(99, 235, 255, 0.08);
1081
+ }
1082
+
1083
+ .file-viewer-sqlite-title {
1084
+ width: 100%;
1085
+ display: flex;
1086
+ align-items: center;
1087
+ justify-content: space-between;
1088
+ gap: 10px;
1089
+ font-size: 12px;
1090
+ color: var(--text);
1091
+ margin-bottom: 0;
1092
+ }
1093
+
1094
+ .file-viewer-sqlite-type {
1095
+ font-size: 10px;
1096
+ letter-spacing: 0.06em;
1097
+ text-transform: uppercase;
1098
+ color: var(--text-dim);
1099
+ }
1100
+
1101
+ .file-viewer-sqlite-table-shell {
1102
+ flex: 1;
1103
+ min-width: 0;
1104
+ border: 1px solid var(--border);
1105
+ border-radius: 8px;
1106
+ padding: 10px;
1107
+ background: rgba(255, 255, 255, 0.015);
1108
+ display: flex;
1109
+ flex-direction: column;
1110
+ min-height: 0;
1111
+ }
1112
+
1113
+ .file-viewer-sqlite-table-header {
1114
+ display: flex;
1115
+ align-items: center;
1116
+ justify-content: space-between;
1117
+ gap: 10px;
1118
+ }
1119
+
1120
+ .file-viewer-sqlite-table-name {
1121
+ font-size: 12px;
1122
+ color: var(--text);
1123
+ font-weight: 600;
1124
+ }
1125
+
1126
+ .file-viewer-sqlite-table-nav {
1127
+ display: inline-flex;
1128
+ gap: 6px;
1129
+ }
1130
+
1131
+ .file-viewer-sqlite-table-meta {
1132
+ margin-top: 4px;
1133
+ margin-bottom: 8px;
1134
+ font-size: 11px;
1135
+ color: var(--text-dim);
1136
+ }
1137
+
1138
+ .file-viewer-sqlite-table-wrap {
1139
+ min-height: 0;
1140
+ overflow: auto;
1141
+ }
1142
+
1143
+ .file-viewer-sqlite-table {
1144
+ width: 100%;
1145
+ border-collapse: collapse;
1146
+ table-layout: fixed;
1147
+ }
1148
+
1149
+ .file-viewer-sqlite-table th,
1150
+ .file-viewer-sqlite-table td {
1151
+ border: 1px solid var(--border);
1152
+ padding: 6px 8px;
1153
+ font-size: 11px;
1154
+ color: var(--text-muted);
1155
+ text-align: left;
1156
+ white-space: nowrap;
1157
+ overflow: hidden;
1158
+ text-overflow: ellipsis;
1159
+ }
1160
+
1161
+ .file-viewer-sqlite-table th {
1162
+ color: var(--text);
1163
+ background: rgba(255, 255, 255, 0.04);
1164
+ }
1165
+
1166
+ .file-viewer-sqlite-table-empty {
1167
+ color: var(--text-dim);
1168
+ }
1169
+
932
1170
  .file-viewer-state-error {
933
1171
  color: #f87171;
934
1172
  }
@@ -1045,20 +1283,30 @@
1045
1283
  text-overflow: ellipsis;
1046
1284
  }
1047
1285
 
1048
- .sidebar-git-dirty {
1049
- font-size: 10px;
1050
- text-transform: uppercase;
1051
- letter-spacing: 0.06em;
1286
+ .sidebar-git-sync-status {
1287
+ font-size: 12px;
1288
+ font-weight: 600;
1289
+ line-height: 1;
1052
1290
  }
1053
1291
 
1054
- .sidebar-git-dirty.is-clean {
1292
+ .sidebar-git-sync-status.is-up-to-date {
1055
1293
  color: #71f8a7;
1056
1294
  }
1057
1295
 
1058
- .sidebar-git-dirty.is-dirty {
1296
+ .sidebar-git-sync-status.is-ahead,
1297
+ .sidebar-git-sync-status.is-diverged {
1059
1298
  color: #f3a86a;
1060
1299
  }
1061
1300
 
1301
+ .sidebar-git-sync-status.is-behind {
1302
+ color: #93c5fd;
1303
+ }
1304
+
1305
+ .sidebar-git-sync-status.is-no-upstream,
1306
+ .sidebar-git-sync-status.is-upstream-gone {
1307
+ color: var(--text-dim);
1308
+ }
1309
+
1062
1310
  .sidebar-git-meta {
1063
1311
  color: var(--text-muted);
1064
1312
  }