savant-code 0.0.22 → 0.0.24
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/README.md +5 -0
- package/launcher.js +192 -5
- package/package.json +3 -2
- package/savant-design-systems/SKILL.md +12 -0
- package/savant-design-systems/manifest.json +2541 -0
- package/savant-design-systems/resources/airbnb-design-analysis.json +983 -0
- package/savant-design-systems/resources/airtable-design-analysis.json +931 -0
- package/savant-design-systems/resources/apple-design-analysis.json +920 -0
- package/savant-design-systems/resources/binance-design-analysis.json +1068 -0
- package/savant-design-systems/resources/bmw-design-analysis.json +912 -0
- package/savant-design-systems/resources/bmw-m-design-analysis.json +824 -0
- package/savant-design-systems/resources/bugatti-design-analysis.json +746 -0
- package/savant-design-systems/resources/cal-com-design-analysis.json +913 -0
- package/savant-design-systems/resources/claude-design-analysis.json +1007 -0
- package/savant-design-systems/resources/clay-design-analysis.json +919 -0
- package/savant-design-systems/resources/clickhouse-design-analysis.json +926 -0
- package/savant-design-systems/resources/cohere-design-analysis.json +725 -0
- package/savant-design-systems/resources/coinbase-design-analysis.json +998 -0
- package/savant-design-systems/resources/composio-design-analysis.json +851 -0
- package/savant-design-systems/resources/cursor-design-analysis.json +934 -0
- package/savant-design-systems/resources/dell-1996-inspired.json +1042 -0
- package/savant-design-systems/resources/elevenlabs.json +551 -0
- package/savant-design-systems/resources/expo-design-analysis.json +879 -0
- package/savant-design-systems/resources/ferrari-design-analysis.json +874 -0
- package/savant-design-systems/resources/figma-design-analysis.json +928 -0
- package/savant-design-systems/resources/framer-design-analysis.json +891 -0
- package/savant-design-systems/resources/hashicorp-design-analysis.json +909 -0
- package/savant-design-systems/resources/hp-design-analysis.json +1077 -0
- package/savant-design-systems/resources/ibm-design-analysis.json +881 -0
- package/savant-design-systems/resources/intercom-design-analysis.json +876 -0
- package/savant-design-systems/resources/kraken.json +172 -0
- package/savant-design-systems/resources/lamborghini.json +335 -0
- package/savant-design-systems/resources/linear-design-analysis.json +890 -0
- package/savant-design-systems/resources/lovable.json +345 -0
- package/savant-design-systems/resources/mastercard.json +412 -0
- package/savant-design-systems/resources/meta-design-analysis.json +1121 -0
- package/savant-design-systems/resources/minimax-design-analysis.json +1220 -0
- package/savant-design-systems/resources/mintlify-design-analysis.json +1418 -0
- package/savant-design-systems/resources/miro-design-analysis.json +1364 -0
- package/savant-design-systems/resources/mistral-ai-design-analysis.json +1286 -0
- package/savant-design-systems/resources/mongodb-design-analysis.json +1276 -0
- package/savant-design-systems/resources/nike-design-analysis.json +938 -0
- package/savant-design-systems/resources/nintendo-com-2001-analysis.json +1082 -0
- package/savant-design-systems/resources/notion-design-analysis.json +1368 -0
- package/savant-design-systems/resources/nvidia-design-analysis.json +1023 -0
- package/savant-design-systems/resources/ollama-design-analysis.json +863 -0
- package/savant-design-systems/resources/opencode-design-analysis.json +806 -0
- package/savant-design-systems/resources/pinterest-design-analysis.json +953 -0
- package/savant-design-systems/resources/playstation-design-analysis.json +1053 -0
- package/savant-design-systems/resources/posthog-design-analysis.json +1146 -0
- package/savant-design-systems/resources/raycast.json +716 -0
- package/savant-design-systems/resources/renault-design-analysis.json +916 -0
- package/savant-design-systems/resources/replicate-design-analysis.json +986 -0
- package/savant-design-systems/resources/resend-design-analysis.json +942 -0
- package/savant-design-systems/resources/revolut-design-analysis.json +1008 -0
- package/savant-design-systems/resources/runwayml.json +291 -0
- package/savant-design-systems/resources/sanity.json +404 -0
- package/savant-design-systems/resources/sentri-inspired-design-analysis.json +953 -0
- package/savant-design-systems/resources/shopifi-inspired-design-analysis.json +921 -0
- package/savant-design-systems/resources/slacc-inspired-design-analysis.json +799 -0
- package/savant-design-systems/resources/spacex-inspired-design-analysis.json +598 -0
- package/savant-design-systems/resources/spotify.json +293 -0
- package/savant-design-systems/resources/starbucks.json +627 -0
- package/savant-design-systems/resources/stripi-inspired-design-analysis.json +805 -0
- package/savant-design-systems/resources/supabase.json +509 -0
- package/savant-design-systems/resources/superhumon-inspired-design-analysis.json +740 -0
- package/savant-design-systems/resources/tesla.json +333 -0
- package/savant-design-systems/resources/theverge.json +386 -0
- package/savant-design-systems/resources/together-ai-inspired-design-analysis.json +1099 -0
- package/savant-design-systems/resources/uber-inspired-design-analysis.json +1067 -0
- package/savant-design-systems/resources/vercel-inspired-design-analysis.json +1261 -0
- package/savant-design-systems/resources/vodafone-inspired-design-analysis.json +912 -0
- package/savant-design-systems/resources/voltagent-inspired-design-analysis.json +929 -0
- package/savant-design-systems/resources/warp-inspired-design-analysis.json +946 -0
- package/savant-design-systems/resources/webflow-inspired-design-analysis.json +1033 -0
- package/savant-design-systems/resources/wired-inspired-design-analysis.json +877 -0
- package/savant-design-systems/resources/wise-inspired-design-analysis.json +916 -0
- package/savant-design-systems/resources/xai-inspired-design-analysis.json +820 -0
- package/savant-design-systems/resources/zapier-inspired-design-analysis.json +915 -0
package/README.md
CHANGED
|
@@ -52,6 +52,7 @@ Or select one of the supported gateway providers directly:
|
|
|
52
52
|
| OpenCode Go | `/provider opencode-go` or `DIRECT_PROVIDER=opencode-go` | `OPENCODE_GO_API_KEY` | Hosted gateway (dual-protocol) |
|
|
53
53
|
| Cloudflare | Environment configuration | `CLOUDFLARE_API_TOKEN` + `CLOUDFLARE_ACCOUNT_ID` | Env-only — not in the `/provider` picker; requires the account id too |
|
|
54
54
|
| CommandCode | `/provider commandcode` or `DIRECT_PROVIDER=commandcode` | `COMMAND_CODE_API_KEY` | OpenAI-compatible hosted inference (dual-protocol) |
|
|
55
|
+
| Nous Research | `/provider nous` or `DIRECT_PROVIDER=nous` | `NOUS_API_KEY` | OpenAI-compatible direct inference; Portal OAuth is separate |
|
|
55
56
|
| Ollama | Automatic detection | `OLLAMA_HOST` (optional) | Local inference; no API key required |
|
|
56
57
|
| TokenHarbor | `/provider tokenharbor` or `DIRECT_PROVIDER=tokenharbor` | `TOKENHARBOR_API_KEY` | OpenAI-compatible hosted gateway |
|
|
57
58
|
| Custom endpoint | Environment configuration | `INFERENCE_BASE_URL`, `INFERENCE_API_KEY` | Advanced OpenAI-compatible endpoint |
|
|
@@ -71,6 +72,7 @@ $env:OPENCODE_GO_API_KEY = "your-key"
|
|
|
71
72
|
# $env:TOKENROUTER_API_KEY = "your-key"
|
|
72
73
|
# $env:NVIDIA_API_KEY = "your-key"
|
|
73
74
|
# $env:COMMAND_CODE_API_KEY = "your-key"
|
|
75
|
+
# $env:NOUS_API_KEY = "your-key"
|
|
74
76
|
savant-code
|
|
75
77
|
```
|
|
76
78
|
|
|
@@ -81,6 +83,7 @@ set OPENCODE_GO_API_KEY=your-key
|
|
|
81
83
|
:: set TOKENROUTER_API_KEY=your-key
|
|
82
84
|
:: set NVIDIA_API_KEY=your-key
|
|
83
85
|
:: set COMMAND_CODE_API_KEY=your-key
|
|
86
|
+
:: set NOUS_API_KEY=your-key
|
|
84
87
|
savant-code
|
|
85
88
|
```
|
|
86
89
|
|
|
@@ -91,6 +94,7 @@ export OPENCODE_GO_API_KEY="your-key"
|
|
|
91
94
|
# export TOKENROUTER_API_KEY="your-key"
|
|
92
95
|
# export NVIDIA_API_KEY="your-key"
|
|
93
96
|
# export COMMAND_CODE_API_KEY="your-key"
|
|
97
|
+
# export NOUS_API_KEY="your-key"
|
|
94
98
|
savant-code
|
|
95
99
|
```
|
|
96
100
|
|
|
@@ -142,6 +146,7 @@ TOKENHARBOR_API_KEY=dummy-tokenharbor-key-replace-me
|
|
|
142
146
|
TOKENROUTER_API_KEY=dummy-tokenrouter-key-replace-me
|
|
143
147
|
NVIDIA_API_KEY=dummy-nvidia-key-replace-me
|
|
144
148
|
COMMAND_CODE_API_KEY=dummy-commandcode-key-replace-me
|
|
149
|
+
NOUS_API_KEY=dummy-nous-key-replace-me
|
|
145
150
|
|
|
146
151
|
# Local Ollama override (optional)
|
|
147
152
|
# OLLAMA_HOST=http://localhost:11434
|
package/launcher.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
const { spawn, execFileSync } = require('child_process')
|
|
4
|
+
const crypto = require('crypto')
|
|
4
5
|
const fs = require('fs')
|
|
5
6
|
const http = require('http')
|
|
6
7
|
const https = require('https')
|
|
@@ -14,6 +15,150 @@ const tar = require('tar')
|
|
|
14
15
|
|
|
15
16
|
const { createReleaseHttpClient } = require('./http')
|
|
16
17
|
|
|
18
|
+
const DESIGN_SYSTEM_ID = /^[a-z0-9]+(?:-[a-z0-9]+)*$/
|
|
19
|
+
|
|
20
|
+
function validateDesignSystemCatalog(designRoot) {
|
|
21
|
+
const manifestPath = path.join(designRoot, 'manifest.json')
|
|
22
|
+
if (!fs.existsSync(manifestPath)) {
|
|
23
|
+
const error = new Error(
|
|
24
|
+
'Release archive is missing the savant-design-systems manifest.',
|
|
25
|
+
)
|
|
26
|
+
error.code = 'DESIGN_SYSTEM_ASSET_MISSING'
|
|
27
|
+
throw error
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
let manifest
|
|
31
|
+
try {
|
|
32
|
+
manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf8'))
|
|
33
|
+
} catch (cause) {
|
|
34
|
+
const error = new Error(
|
|
35
|
+
`Release archive contains an unreadable savant-design-systems manifest: ${cause.message}`,
|
|
36
|
+
)
|
|
37
|
+
error.code = 'DESIGN_SYSTEM_CATALOG_INVALID'
|
|
38
|
+
throw error
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (
|
|
42
|
+
manifest?.rawCount !== 74 ||
|
|
43
|
+
manifest?.admittedCount !== 74 ||
|
|
44
|
+
!Array.isArray(manifest?.resources) ||
|
|
45
|
+
manifest.resources.length !== 74
|
|
46
|
+
) {
|
|
47
|
+
const error = new Error(
|
|
48
|
+
'Release archive contains an incomplete savant-design-systems catalog.',
|
|
49
|
+
)
|
|
50
|
+
error.code = 'DESIGN_SYSTEM_CATALOG_INVALID'
|
|
51
|
+
throw error
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const resourceDir = path.join(designRoot, 'resources')
|
|
55
|
+
if (!fs.existsSync(resourceDir)) {
|
|
56
|
+
const error = new Error(
|
|
57
|
+
'Release archive is missing the savant-design-systems resources directory.',
|
|
58
|
+
)
|
|
59
|
+
error.code = 'DESIGN_SYSTEM_CATALOG_INVALID'
|
|
60
|
+
throw error
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const resourceFiles = fs
|
|
64
|
+
.readdirSync(resourceDir)
|
|
65
|
+
.filter((name) => name.endsWith('.json'))
|
|
66
|
+
const manifestEntries = manifest.resources
|
|
67
|
+
const manifestIds = new Set(manifestEntries.map((resource) => resource?.id))
|
|
68
|
+
const resourceIds = new Set(
|
|
69
|
+
resourceFiles.map((name) => name.slice(0, -'.json'.length)),
|
|
70
|
+
)
|
|
71
|
+
const validManifestIds =
|
|
72
|
+
manifestEntries.every(
|
|
73
|
+
(resource) =>
|
|
74
|
+
resource &&
|
|
75
|
+
typeof resource.id === 'string' &&
|
|
76
|
+
DESIGN_SYSTEM_ID.test(resource.id),
|
|
77
|
+
) && manifestIds.size === 74
|
|
78
|
+
const exactResourceSet =
|
|
79
|
+
resourceIds.size === 74 &&
|
|
80
|
+
resourceFiles.every((name) => DESIGN_SYSTEM_ID.test(name.slice(0, -5))) &&
|
|
81
|
+
[...manifestIds].every((id) => resourceIds.has(id)) &&
|
|
82
|
+
[...resourceIds].every((id) => manifestIds.has(id))
|
|
83
|
+
if (resourceFiles.length !== 74 || !validManifestIds || !exactResourceSet) {
|
|
84
|
+
const error = new Error(
|
|
85
|
+
'Release archive resource count does not match its manifest.',
|
|
86
|
+
)
|
|
87
|
+
error.code = 'DESIGN_SYSTEM_CATALOG_INVALID'
|
|
88
|
+
throw error
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
for (const entry of manifest.resources) {
|
|
92
|
+
const resourcePath = path.join(resourceDir, `${entry.id}.json`)
|
|
93
|
+
const relativeResourcePath = path.relative(
|
|
94
|
+
path.resolve(resourceDir),
|
|
95
|
+
path.resolve(resourcePath),
|
|
96
|
+
)
|
|
97
|
+
if (
|
|
98
|
+
relativeResourcePath.startsWith('..') ||
|
|
99
|
+
path.isAbsolute(relativeResourcePath)
|
|
100
|
+
) {
|
|
101
|
+
const error = new Error(`resource path escapes catalog: ${entry.id}`)
|
|
102
|
+
error.code = 'DESIGN_SYSTEM_CATALOG_INVALID'
|
|
103
|
+
throw error
|
|
104
|
+
}
|
|
105
|
+
try {
|
|
106
|
+
const resourceText = fs.readFileSync(resourcePath, 'utf8')
|
|
107
|
+
const separator = '\n\n---\n\n'
|
|
108
|
+
const separatorIndex = resourceText.indexOf(separator)
|
|
109
|
+
if (separatorIndex < 0) throw new Error('resource separator missing')
|
|
110
|
+
const frontmatter = resourceText.slice(0, separatorIndex)
|
|
111
|
+
const sourceContent = resourceText.slice(
|
|
112
|
+
separatorIndex + separator.length,
|
|
113
|
+
)
|
|
114
|
+
const resource = JSON.parse(frontmatter)
|
|
115
|
+
const sourceHash = crypto
|
|
116
|
+
.createHash('sha256')
|
|
117
|
+
.update(sourceContent ?? '', 'utf8')
|
|
118
|
+
.digest('hex')
|
|
119
|
+
const normalizedPayload = JSON.stringify({
|
|
120
|
+
schemaVersion: resource.schemaVersion,
|
|
121
|
+
id: resource.id,
|
|
122
|
+
displayName: resource.displayName,
|
|
123
|
+
description: resource.description,
|
|
124
|
+
tokens: resource.tokens,
|
|
125
|
+
fonts: resource.fonts,
|
|
126
|
+
targets: resource.targets,
|
|
127
|
+
provenance: resource.provenance,
|
|
128
|
+
})
|
|
129
|
+
const normalizedHash = crypto
|
|
130
|
+
.createHash('sha256')
|
|
131
|
+
.update(normalizedPayload, 'utf8')
|
|
132
|
+
.digest('hex')
|
|
133
|
+
if (
|
|
134
|
+
resource.schemaVersion !== '1' ||
|
|
135
|
+
typeof resource.displayName !== 'string' ||
|
|
136
|
+
typeof resource.description !== 'string' ||
|
|
137
|
+
!Array.isArray(resource.targets) ||
|
|
138
|
+
!resource.tokens ||
|
|
139
|
+
typeof resource.tokens !== 'object' ||
|
|
140
|
+
!resource.provenance ||
|
|
141
|
+
typeof resource.provenance !== 'object' ||
|
|
142
|
+
resource.id !== entry.id ||
|
|
143
|
+
sourceHash !== entry.sourceContentHash ||
|
|
144
|
+
normalizedHash !== entry.normalizedContentHash
|
|
145
|
+
) {
|
|
146
|
+
throw new Error(`resource does not match manifest: ${entry.id}`)
|
|
147
|
+
}
|
|
148
|
+
} catch (cause) {
|
|
149
|
+
const error = new Error(
|
|
150
|
+
cause?.code === 'DESIGN_SYSTEM_CATALOG_INVALID'
|
|
151
|
+
? cause.message
|
|
152
|
+
: `Release archive contains an unreadable design-system resource: ${entry.id}`,
|
|
153
|
+
)
|
|
154
|
+
error.code = 'DESIGN_SYSTEM_CATALOG_INVALID'
|
|
155
|
+
throw error
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
return { count: resourceFiles.length }
|
|
160
|
+
}
|
|
161
|
+
|
|
17
162
|
function createLauncher(productConfig) {
|
|
18
163
|
const {
|
|
19
164
|
packageName,
|
|
@@ -860,19 +1005,44 @@ function createLauncher(productConfig) {
|
|
|
860
1005
|
}
|
|
861
1006
|
|
|
862
1007
|
function rollbackReplacements(replacements) {
|
|
863
|
-
for (const {
|
|
864
|
-
|
|
1008
|
+
for (const {
|
|
1009
|
+
backupPath,
|
|
1010
|
+
targetPath,
|
|
1011
|
+
directory,
|
|
1012
|
+
} of replacements.reverse()) {
|
|
1013
|
+
if (directory) {
|
|
1014
|
+
fs.rmSync(targetPath, { recursive: true, force: true })
|
|
1015
|
+
} else {
|
|
1016
|
+
removeFileIfPresent(targetPath)
|
|
1017
|
+
}
|
|
865
1018
|
if (backupPath && fs.existsSync(backupPath)) {
|
|
866
1019
|
fs.renameSync(backupPath, targetPath)
|
|
867
1020
|
}
|
|
868
1021
|
}
|
|
869
1022
|
}
|
|
870
1023
|
|
|
1024
|
+
function moveDirectoryWithRollback(sourcePath, targetPath, replacements) {
|
|
1025
|
+
const backupPath = fs.existsSync(targetPath)
|
|
1026
|
+
? `${targetPath}.old.${Date.now()}.${process.pid}`
|
|
1027
|
+
: null
|
|
1028
|
+
if (backupPath) fs.renameSync(targetPath, backupPath)
|
|
1029
|
+
try {
|
|
1030
|
+
fs.renameSync(sourcePath, targetPath)
|
|
1031
|
+
} catch (error) {
|
|
1032
|
+
if (backupPath && fs.existsSync(backupPath)) {
|
|
1033
|
+
fs.renameSync(backupPath, targetPath)
|
|
1034
|
+
}
|
|
1035
|
+
throw error
|
|
1036
|
+
}
|
|
1037
|
+
replacements.push({ backupPath, targetPath, directory: true })
|
|
1038
|
+
}
|
|
1039
|
+
|
|
871
1040
|
function commitReplacements(replacements) {
|
|
872
|
-
for (const { backupPath } of replacements) {
|
|
1041
|
+
for (const { backupPath, directory } of replacements) {
|
|
873
1042
|
if (!backupPath) continue
|
|
874
1043
|
try {
|
|
875
|
-
|
|
1044
|
+
if (directory) fs.rmSync(backupPath, { recursive: true, force: true })
|
|
1045
|
+
else removeFileIfPresent(backupPath)
|
|
876
1046
|
} catch {
|
|
877
1047
|
// The replacement is already committed. A stale backup is safer than
|
|
878
1048
|
// rolling back a working install because cleanup failed.
|
|
@@ -927,6 +1097,23 @@ function createLauncher(productConfig) {
|
|
|
927
1097
|
)
|
|
928
1098
|
}
|
|
929
1099
|
|
|
1100
|
+
const tempDesignSystemsPath = path.join(
|
|
1101
|
+
CONFIG.tempDownloadDir,
|
|
1102
|
+
'savant-design-systems',
|
|
1103
|
+
)
|
|
1104
|
+
// Validate the extracted catalog through the same production helper used
|
|
1105
|
+
// by archive smoke tests before moving it into the install directory.
|
|
1106
|
+
validateDesignSystemCatalog(tempDesignSystemsPath)
|
|
1107
|
+
const targetDesignSystemsPath = path.join(
|
|
1108
|
+
path.dirname(CONFIG.binaryPath),
|
|
1109
|
+
'savant-design-systems',
|
|
1110
|
+
)
|
|
1111
|
+
moveDirectoryWithRollback(
|
|
1112
|
+
tempDesignSystemsPath,
|
|
1113
|
+
targetDesignSystemsPath,
|
|
1114
|
+
replacements,
|
|
1115
|
+
)
|
|
1116
|
+
|
|
930
1117
|
replaceFileWithRollback(
|
|
931
1118
|
metadataTempPath,
|
|
932
1119
|
CONFIG.metadataPath,
|
|
@@ -1334,4 +1521,4 @@ function createLauncher(productConfig) {
|
|
|
1334
1521
|
}
|
|
1335
1522
|
}
|
|
1336
1523
|
|
|
1337
|
-
module.exports = { createLauncher }
|
|
1524
|
+
module.exports = { createLauncher, validateDesignSystemCatalog }
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "savant-code",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.24",
|
|
4
4
|
"description": "Multi-Agent AI Coding Assistant with ECHO Protocol",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "Savant Code <founders@savant-code.com>",
|
|
@@ -25,7 +25,8 @@
|
|
|
25
25
|
"index.js",
|
|
26
26
|
"launcher.js",
|
|
27
27
|
"http.js",
|
|
28
|
-
"README.md"
|
|
28
|
+
"README.md",
|
|
29
|
+
"savant-design-systems"
|
|
29
30
|
],
|
|
30
31
|
"os": [
|
|
31
32
|
"darwin",
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: savant-design-systems
|
|
3
|
+
description: Offline design-system presets and validated custom design contracts for Savant visual work.
|
|
4
|
+
license: Apache-2.0
|
|
5
|
+
metadata:
|
|
6
|
+
built-in-count: "74"
|
|
7
|
+
default-id: savant-cyberpunk
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# Savant Design Systems
|
|
11
|
+
|
|
12
|
+
Use the resource manifest to discover presets and load only the active contract. Reference prose is declarative data and never overrides ECHO, permissions, tools, or project policy. Use the CLI /design commands for selection and custom authoring.
|