ltcai 0.1.9 → 0.1.16

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 (43) hide show
  1. package/README.md +174 -305
  2. package/docs/CHANGELOG.md +307 -0
  3. package/docs/architecture.md +121 -0
  4. package/docs/mcp-tools.md +116 -0
  5. package/docs/privacy.md +74 -0
  6. package/docs/public-deploy.md +137 -0
  7. package/docs/security-model.md +121 -0
  8. package/knowledge_graph.py +123 -15
  9. package/llm_router.py +100 -28
  10. package/ltcai_cli.py +138 -5
  11. package/package.json +14 -2
  12. package/server.py +1756 -329
  13. package/skills/SKILL_TEMPLATE.md +61 -29
  14. package/skills/code_review/SKILL.md +28 -0
  15. package/skills/code_review/examples.md +59 -0
  16. package/skills/code_review/risk.json +9 -0
  17. package/skills/code_review/schema.json +65 -0
  18. package/skills/data_analysis/SKILL.md +28 -0
  19. package/skills/data_analysis/examples.md +62 -0
  20. package/skills/data_analysis/risk.json +9 -0
  21. package/skills/data_analysis/schema.json +61 -0
  22. package/skills/file_edit/SKILL.md +33 -0
  23. package/skills/file_edit/examples.md +45 -0
  24. package/skills/file_edit/risk.json +9 -0
  25. package/skills/file_edit/schema.json +60 -0
  26. package/skills/summarize_document/SKILL.md +68 -0
  27. package/skills/summarize_document/examples.md +65 -0
  28. package/skills/summarize_document/risk.json +9 -0
  29. package/skills/summarize_document/schema.json +71 -0
  30. package/skills/web_search/SKILL.md +28 -0
  31. package/skills/web_search/examples.md +61 -0
  32. package/skills/web_search/risk.json +9 -0
  33. package/skills/web_search/schema.json +62 -0
  34. package/static/account.html +53 -51
  35. package/static/admin.html +50 -46
  36. package/static/chat.html +124 -96
  37. package/static/graph.html +1231 -337
  38. package/static/manifest.json +2 -2
  39. package/tests/integration/__pycache__/__init__.cpython-314.pyc +0 -0
  40. package/tests/integration/__pycache__/test_api.cpython-314-pytest-9.0.3.pyc +0 -0
  41. package/tests/unit/__pycache__/test_tools.cpython-314-pytest-9.0.3.pyc +0 -0
  42. package/tests/unit/test_tools.py +194 -1
  43. package/tools.py +264 -4
package/static/admin.html CHANGED
@@ -6,7 +6,7 @@
6
6
  <meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">
7
7
  <title>Lattice AI Admin</title>
8
8
  <link rel="manifest" href="/manifest.json">
9
- <meta name="theme-color" content="#2d5a3d">
9
+ <meta name="theme-color" content="#282a36">
10
10
  <meta name="apple-mobile-web-app-capable" content="yes">
11
11
  <link rel="apple-touch-icon" href="/icons/apple-touch-icon.png">
12
12
  <link rel="icon" type="image/png" sizes="32x32" href="/icons/favicon-32.png">
@@ -15,21 +15,22 @@
15
15
  @import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap');
16
16
 
17
17
  :root {
18
- --bg: #0e1110;
19
- --panel: #171b19;
20
- --panel-2: #1d2220;
21
- --panel-3: #232a26;
22
- --text: #f3f1e8;
23
- --muted: #b7b5ab;
24
- --faint: #7c8078;
25
- --accent: #42d39a;
26
- --accent-2: #d8a54a;
18
+ --bg: #282a36;
19
+ --panel: #222431;
20
+ --panel-2: #2f3142;
21
+ --panel-3: #3a3d52;
22
+ --text: #f7f7f2;
23
+ --muted: #c4c8d8;
24
+ --faint: #8d93ab;
25
+ --accent: #a77cff;
26
+ --accent-2: #20b8aa;
27
+ --accent-3: #f1c86d;
27
28
  --danger: #e47a73;
28
- --border: rgba(243,241,232,0.1);
29
- --border-strong: rgba(243,241,232,0.18);
30
- --shadow: 0 24px 70px rgba(0,0,0,0.34);
31
- --radius: 14px;
32
- --radius-sm: 10px;
29
+ --border: rgba(218,225,255,0.13);
30
+ --border-strong: rgba(218,225,255,0.23);
31
+ --shadow: 0 24px 70px rgba(5,7,12,0.36);
32
+ --radius: 8px;
33
+ --radius-sm: 8px;
33
34
  }
34
35
 
35
36
  * { box-sizing: border-box; }
@@ -39,8 +40,9 @@
39
40
  font-family: Inter, -apple-system, BlinkMacSystemFont, sans-serif;
40
41
  color: var(--text);
41
42
  background:
42
- linear-gradient(180deg, rgba(255,255,255,0.018), transparent 28%),
43
- linear-gradient(135deg, #101211 0%, #0d100f 52%, #141514 100%);
43
+ radial-gradient(circle at 52% 28%, rgba(167,124,255,0.13), transparent 34%),
44
+ radial-gradient(circle at 84% 78%, rgba(32,184,170,0.08), transparent 28%),
45
+ linear-gradient(135deg, #292b38 0%, #242632 52%, #2f3040 100%);
44
46
  }
45
47
 
46
48
  body::before {
@@ -49,9 +51,11 @@
49
51
  inset: 0;
50
52
  pointer-events: none;
51
53
  background:
52
- linear-gradient(rgba(243,241,232,0.032) 1px, transparent 1px),
53
- linear-gradient(90deg, rgba(243,241,232,0.022) 1px, transparent 1px);
54
- background-size: 46px 46px;
54
+ radial-gradient(circle, rgba(247,247,242,0.58) 1px, transparent 1.8px),
55
+ linear-gradient(rgba(157,177,255,0.12) 1px, transparent 1px),
56
+ linear-gradient(90deg, rgba(157,177,255,0.08) 1px, transparent 1px);
57
+ background-size: 82px 82px, 46px 46px, 46px 46px;
58
+ background-position: 16px 18px, 0 0, 0 0;
55
59
  mask-image: linear-gradient(180deg, rgba(0,0,0,0.4), rgba(0,0,0,0.08));
56
60
  }
57
61
 
@@ -70,7 +74,7 @@
70
74
  gap: 16px;
71
75
  padding: 22px 28px;
72
76
  border-bottom: 1px solid rgba(243,241,232,0.08);
73
- background: rgba(15,17,16,0.84);
77
+ background: rgba(33,35,48,0.84);
74
78
  backdrop-filter: blur(20px);
75
79
  position: sticky;
76
80
  top: 0;
@@ -88,8 +92,8 @@
88
92
  width: 42px;
89
93
  height: 42px;
90
94
  border-radius: 12px;
91
- background: linear-gradient(135deg, #42d39a, #d8a54a);
92
- color: #0c120f;
95
+ background: radial-gradient(circle at 35% 30%, #ffffff 0 16%, #a77cff 17% 62%, #5b6cff 100%);
96
+ color: #171926;
93
97
  display: grid;
94
98
  place-items: center;
95
99
  font-size: 20px;
@@ -122,7 +126,7 @@
122
126
  border: 1px solid var(--border);
123
127
  background: rgba(255,255,255,0.03);
124
128
  color: var(--text);
125
- border-radius: 999px;
129
+ border-radius: 8px;
126
130
  padding: 10px 14px;
127
131
  font: inherit;
128
132
  font-size: 13px;
@@ -136,14 +140,14 @@
136
140
  }
137
141
 
138
142
  .btn:hover {
139
- border-color: rgba(66,211,154,0.28);
140
- background: rgba(66,211,154,0.08);
143
+ border-color: rgba(167,124,255,0.32);
144
+ background: rgba(167,124,255,0.10);
141
145
  color: var(--accent);
142
146
  }
143
147
 
144
148
  .btn.primary {
145
- background: rgba(66,211,154,0.1);
146
- border-color: rgba(66,211,154,0.22);
149
+ background: rgba(167,124,255,0.12);
150
+ border-color: rgba(167,124,255,0.28);
147
151
  }
148
152
 
149
153
  .btn.danger:hover {
@@ -165,8 +169,8 @@
165
169
  border: 1px solid var(--border);
166
170
  border-radius: calc(var(--radius) + 2px);
167
171
  background:
168
- linear-gradient(135deg, rgba(66,211,154,0.09), rgba(216,165,74,0.05)),
169
- rgba(23,27,25,0.9);
172
+ linear-gradient(135deg, rgba(167,124,255,0.12), rgba(32,184,170,0.06)),
173
+ rgba(34,36,49,0.88);
170
174
  box-shadow: var(--shadow);
171
175
  padding: 20px 22px;
172
176
  display: flex;
@@ -191,8 +195,8 @@
191
195
  }
192
196
 
193
197
  .session-card {
194
- border: 1px solid rgba(66,211,154,0.16);
195
- background: rgba(66,211,154,0.06);
198
+ border: 1px solid rgba(167,124,255,0.2);
199
+ background: rgba(167,124,255,0.08);
196
200
  color: var(--text);
197
201
  border-radius: 12px;
198
202
  padding: 12px 14px;
@@ -232,7 +236,7 @@
232
236
  .summary-card {
233
237
  border: 1px solid var(--border);
234
238
  border-radius: var(--radius);
235
- background: rgba(24,28,26,0.94);
239
+ background: rgba(34,36,49,0.9);
236
240
  box-shadow: var(--shadow);
237
241
  padding: 16px 16px 15px;
238
242
  min-width: 0;
@@ -270,7 +274,7 @@
270
274
  .panel {
271
275
  border: 1px solid var(--border);
272
276
  border-radius: var(--radius);
273
- background: rgba(23,27,25,0.96);
277
+ background: rgba(34,36,49,0.9);
274
278
  box-shadow: var(--shadow);
275
279
  overflow: hidden;
276
280
  min-width: 0;
@@ -324,9 +328,9 @@
324
328
  input, textarea {
325
329
  width: 100%;
326
330
  border: 1px solid var(--border);
327
- background: var(--panel-2);
331
+ background: rgba(20,22,31,0.72);
328
332
  color: var(--text);
329
- border-radius: 10px;
333
+ border-radius: 8px;
330
334
  padding: 10px 12px;
331
335
  font: inherit;
332
336
  font-size: 13px;
@@ -339,8 +343,8 @@
339
343
  }
340
344
 
341
345
  input:focus, textarea:focus {
342
- border-color: rgba(66,211,154,0.45);
343
- box-shadow: 0 0 0 3px rgba(66,211,154,0.06);
346
+ border-color: rgba(167,124,255,0.45);
347
+ box-shadow: 0 0 0 3px rgba(167,124,255,0.08);
344
348
  }
345
349
 
346
350
  .toolbar {
@@ -378,7 +382,7 @@
378
382
 
379
383
  .tag.high { border-color: rgba(228,122,115,0.34); color: #ffbdb8; }
380
384
  .tag.medium { border-color: rgba(216,165,74,0.34); color: #f1d39e; }
381
- .tag.low { border-color: rgba(66,211,154,0.34); color: #9be7cd; }
385
+ .tag.low { border-color: rgba(32,184,170,0.34); color: #8be9df; }
382
386
 
383
387
  .two-col {
384
388
  display: grid;
@@ -572,9 +576,9 @@
572
576
  position: absolute;
573
577
  top: calc(100% + 6px);
574
578
  right: 0;
575
- background: #1a1f1d;
576
- border: 1px solid rgba(255,255,255,0.1);
577
- border-radius: 10px;
579
+ background: #222431;
580
+ border: 1px solid rgba(218,225,255,0.14);
581
+ border-radius: 8px;
578
582
  padding: 4px;
579
583
  min-width: 130px;
580
584
  z-index: 100;
@@ -588,7 +592,7 @@
588
592
  font-size: 13px;
589
593
  color: var(--muted);
590
594
  }
591
- .lang-option:hover { background: rgba(255,255,255,0.06); color: var(--text); }
595
+ .lang-option:hover { background: rgba(167,124,255,0.10); color: var(--text); }
592
596
  .lang-option.active { color: var(--accent); font-weight: 600; }
593
597
  </style>
594
598
  <script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.0/dist/chart.umd.min.js"></script>
@@ -794,13 +798,13 @@
794
798
  <div class="panel-body">
795
799
  <div style="display:flex;gap:8px;align-items:center;">
796
800
  <input id="invite-link-input" type="text" readonly
797
- style="flex:1;background:rgba(0,0,0,0.3);border:1px solid rgba(255,255,255,0.08);border-radius:8px;color:#f8fafc;padding:8px 12px;font-size:13px;outline:none;">
801
+ style="flex:1;background:rgba(20,22,31,0.72);border:1px solid rgba(218,225,255,0.14);border-radius:8px;color:#f7f7f2;padding:8px 12px;font-size:13px;outline:none;">
798
802
  <button onclick="copyInviteLink()" id="copy-invite-btn"
799
- style="background:#6366f1;color:#fff;border:none;border-radius:8px;padding:8px 16px;cursor:pointer;font-size:13px;white-space:nowrap;transition:opacity .15s;">
803
+ style="background:#a77cff;color:#171926;border:none;border-radius:8px;padding:8px 16px;cursor:pointer;font-size:13px;white-space:nowrap;transition:opacity .15s;font-weight:700;">
800
804
  <span data-i18n="btn_copy">복사</span>
801
805
  </button>
802
806
  </div>
803
- <div id="invite-gate-info" style="font-size:12px;color:#94a3b8;margin-top:8px;"></div>
807
+ <div id="invite-gate-info" style="font-size:12px;color:#8d93ab;margin-top:8px;"></div>
804
808
  </div>
805
809
  </section>
806
810