total-recall-brain 3.46.2 → 3.47.1
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/total-recall.mjs +5 -0
- package/frontend/dist/assets/index-CpsWeV4X.css +1 -0
- package/frontend/dist/assets/{index-D1goIPjC.js → index-poecbHSl.js} +100 -100
- package/frontend/dist/brand/total-recall-lockup-transparent.png +0 -0
- package/frontend/dist/index.html +2 -2
- package/frontend/dist/sw.js +1 -1
- package/frontend/src/App.tsx +15 -81
- package/frontend/src/components/DashboardOverview.tsx +164 -0
- package/frontend/src/components/brand/BrandMark.tsx +8 -6
- package/frontend/src/components/plugins/PluginWorkspace.tsx +112 -57
- package/frontend/src/components/workspace/PluginHome.tsx +3 -3
- package/frontend/src/index.css +43 -11
- package/package.json +1 -1
- package/scaffold/.agent/skills/total-recall/plugins/auth/package-lock.json +4 -4
- package/scaffold/.agent/skills/total-recall/plugins/auth/package.json +3 -2
- package/scaffold/.agent/skills/total-recall/plugins/auth/plugin.json +30 -5
- package/scaffold/.agent/skills/total-recall/plugins/auth/skills/auth/SKILL.md +35 -0
- package/scaffold/.agent/skills/total-recall/plugins/auth/ui/home.js +494 -79
- package/scaffold/.agent/skills/total-recall/plugins/automations/package-lock.json +4 -4
- package/scaffold/.agent/skills/total-recall/plugins/automations/package.json +3 -2
- package/scaffold/.agent/skills/total-recall/plugins/automations/plugin.json +33 -8
- package/scaffold/.agent/skills/total-recall/plugins/automations/skills/automations/SKILL.md +29 -0
- package/scaffold/.agent/skills/total-recall/plugins/automations/ui/chunks/dream-consolidation.md +17 -0
- package/scaffold/.agent/skills/total-recall/plugins/code-quality/package-lock.json +4 -4
- package/scaffold/.agent/skills/total-recall/plugins/code-quality/package.json +3 -2
- package/scaffold/.agent/skills/total-recall/plugins/code-quality/plugin.json +31 -4
- package/scaffold/.agent/skills/total-recall/plugins/code-quality/skills/code-quality/SKILL.md +27 -0
- package/scaffold/.agent/skills/total-recall/plugins/composable-cli/package-lock.json +4 -4
- package/scaffold/.agent/skills/total-recall/plugins/composable-cli/package.json +1 -1
- package/scaffold/.agent/skills/total-recall/plugins/composable-cli/plugin.json +17 -3
- package/scaffold/.agent/skills/total-recall/plugins/embeddings/package-lock.json +4 -4
- package/scaffold/.agent/skills/total-recall/plugins/embeddings/package.json +3 -2
- package/scaffold/.agent/skills/total-recall/plugins/embeddings/plugin.json +24 -4
- package/scaffold/.agent/skills/total-recall/plugins/embeddings/skills/embeddings/SKILL.md +25 -0
- package/scaffold/.agent/skills/total-recall/plugins/git/package-lock.json +6 -6
- package/scaffold/.agent/skills/total-recall/plugins/git/package.json +3 -2
- package/scaffold/.agent/skills/total-recall/plugins/git/plugin.json +300 -58
- package/scaffold/.agent/skills/total-recall/plugins/git/skills/git/SKILL.md +36 -0
- package/scaffold/.agent/skills/total-recall/plugins/git/src/ops/commit-memory.mjs +5 -33
- package/scaffold/.agent/skills/total-recall/plugins/git/ui/chunks/git-fleet-ops.md +16 -0
- package/scaffold/.agent/skills/total-recall/plugins/git/ui/chunks/git-publish.md +16 -0
- package/scaffold/.agent/skills/total-recall/plugins/mesh/package-lock.json +4 -4
- package/scaffold/.agent/skills/total-recall/plugins/mesh/package.json +3 -2
- package/scaffold/.agent/skills/total-recall/plugins/mesh/plugin.json +47 -14
- package/scaffold/.agent/skills/total-recall/plugins/mesh/skills/mesh/SKILL.md +36 -0
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/cli.mjs +6 -3
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/package.json +1 -1
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/plugin.json +5 -2
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/cascade.mjs +4 -2
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/coordinator.mjs +28 -9
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/dispatch.mjs +7 -1
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/model-selection.mjs +59 -0
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/remote-operation.mjs +3 -3
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/router.mjs +9 -3
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/src/worker.mjs +50 -6
- package/scaffold/.agent/skills/total-recall/plugins/meta-harness/ui/chunks/session-controls.md +16 -0
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/cli.mjs +175 -17
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/package-lock.json +6 -6
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/package.json +3 -2
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/plugin.json +242 -31
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/skills/openwiki/SKILL.md +32 -0
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/src/config.mjs +41 -15
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/src/generate.mjs +29 -22
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/src/graph.mjs +20 -33
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/src/lint.mjs +42 -49
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/src/markdown-links.mjs +112 -0
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/src/mesh-vaults.mjs +3 -2
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/src/refresh.mjs +219 -65
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/src/search.mjs +2 -1
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/src/upstream-watcher.mjs +21 -3
- package/scaffold/.agent/skills/total-recall/plugins/openwiki/ui/panel.js +51 -2
- package/scaffold/.agent/skills/total-recall/plugins/security/package-lock.json +4 -4
- package/scaffold/.agent/skills/total-recall/plugins/security/package.json +1 -1
- package/scaffold/.agent/skills/total-recall/plugins/security/plugin.json +22 -5
- package/scaffold/.agent/skills/total-recall/plugins/ssss/package.json +3 -2
- package/scaffold/.agent/skills/total-recall/plugins/ssss/plugin.json +169 -37
- package/scaffold/.agent/skills/total-recall/plugins/ssss/skills/ssss/SKILL.md +30 -0
- package/src/cli/context.mjs +6 -2
- package/src/cli/plugin/create.mjs +2 -1
- package/src/cli/plugin/monetization.mjs +66 -32
- package/src/cli/plugin/search.mjs +25 -3
- package/src/cli/preflight.mjs +40 -6
- package/src/core/context-compactor.mjs +2 -0
- package/src/core/gate-mode.mjs +13 -24
- package/src/core/plugin-distribution.mjs +35 -1
- package/src/core/preflight-gate.mjs +28 -8
- package/src/core/preflight-receipt.mjs +11 -0
- package/src/server/routes/vault.mjs +1 -0
- package/frontend/dist/assets/index-BRYE1jmv.css +0 -1
|
@@ -2,15 +2,29 @@
|
|
|
2
2
|
"$schema": "https://github.com/gregiteen/total-recall/blob/main/metadata.plugin.schema.json",
|
|
3
3
|
"id": "ssss",
|
|
4
4
|
"name": "SSSS",
|
|
5
|
-
"version": "0.2.
|
|
5
|
+
"version": "0.2.1",
|
|
6
6
|
"description": "Canonical SSSS distribution, scaffolding and validation for Total Recall installations.",
|
|
7
7
|
"license": "MIT",
|
|
8
|
-
"use_cases": [
|
|
9
|
-
|
|
8
|
+
"use_cases": [
|
|
9
|
+
"software-development",
|
|
10
|
+
"state-conformance"
|
|
11
|
+
],
|
|
12
|
+
"distribution": {
|
|
13
|
+
"tier": "core",
|
|
14
|
+
"license": "open"
|
|
15
|
+
},
|
|
10
16
|
"gate": {
|
|
11
|
-
"tasks": [
|
|
17
|
+
"tasks": [
|
|
18
|
+
"Validate SSSS documents and registries",
|
|
19
|
+
"Scaffold a standalone SSSS project",
|
|
20
|
+
"Run the SSSS conformance suites",
|
|
21
|
+
"Restore a missing SSSS skill or scaffold"
|
|
22
|
+
],
|
|
12
23
|
"owned_commands": [
|
|
13
|
-
{
|
|
24
|
+
{
|
|
25
|
+
"pattern": "npx\\s+(--yes\\s+)?@gregiteen/ssss-cli\\s+new\\b",
|
|
26
|
+
"use": "total-recall ssss scaffold --directory <folder> --json"
|
|
27
|
+
}
|
|
14
28
|
]
|
|
15
29
|
},
|
|
16
30
|
"cli": {
|
|
@@ -19,65 +33,183 @@
|
|
|
19
33
|
"handler": "cli.mjs",
|
|
20
34
|
"subcommands": [
|
|
21
35
|
{
|
|
22
|
-
"name": "status",
|
|
23
|
-
"
|
|
24
|
-
"
|
|
36
|
+
"name": "status",
|
|
37
|
+
"description": "Inspect the installed engine, skill and full scaffold",
|
|
38
|
+
"effect": "read",
|
|
39
|
+
"output": "json",
|
|
40
|
+
"args": [
|
|
41
|
+
{
|
|
42
|
+
"name": "scope",
|
|
43
|
+
"flag": "--scope",
|
|
44
|
+
"label": "Brain scope",
|
|
45
|
+
"type": "choice",
|
|
46
|
+
"options": [
|
|
47
|
+
"auto",
|
|
48
|
+
"project",
|
|
49
|
+
"global"
|
|
50
|
+
]
|
|
51
|
+
}
|
|
52
|
+
]
|
|
25
53
|
},
|
|
26
54
|
{
|
|
27
|
-
"name": "repair",
|
|
28
|
-
"
|
|
29
|
-
"
|
|
55
|
+
"name": "repair",
|
|
56
|
+
"description": "Restore missing or previously repinned managed SSSS installation files",
|
|
57
|
+
"effect": "write",
|
|
58
|
+
"output": "json",
|
|
59
|
+
"args": [
|
|
60
|
+
{
|
|
61
|
+
"name": "scope",
|
|
62
|
+
"flag": "--scope",
|
|
63
|
+
"label": "Brain scope",
|
|
64
|
+
"type": "choice",
|
|
65
|
+
"options": [
|
|
66
|
+
"auto",
|
|
67
|
+
"project",
|
|
68
|
+
"global"
|
|
69
|
+
]
|
|
70
|
+
}
|
|
71
|
+
]
|
|
30
72
|
},
|
|
31
73
|
{
|
|
32
|
-
"name": "validate",
|
|
33
|
-
"
|
|
74
|
+
"name": "validate",
|
|
75
|
+
"description": "Validate a document against the effective SSSS registry",
|
|
76
|
+
"effect": "read",
|
|
77
|
+
"output": "json",
|
|
34
78
|
"args": [
|
|
35
|
-
{
|
|
36
|
-
|
|
79
|
+
{
|
|
80
|
+
"name": "file",
|
|
81
|
+
"flag": "--file",
|
|
82
|
+
"label": "Document path",
|
|
83
|
+
"type": "string",
|
|
84
|
+
"required": true
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
"name": "extension",
|
|
88
|
+
"flag": "--extension",
|
|
89
|
+
"label": "Extension registry path",
|
|
90
|
+
"type": "string"
|
|
91
|
+
}
|
|
37
92
|
]
|
|
38
93
|
},
|
|
39
94
|
{
|
|
40
|
-
"name": "registry",
|
|
41
|
-
"
|
|
95
|
+
"name": "registry",
|
|
96
|
+
"description": "Verify the effective registry against a lock file",
|
|
97
|
+
"effect": "read",
|
|
98
|
+
"output": "json",
|
|
42
99
|
"args": [
|
|
43
|
-
{
|
|
44
|
-
|
|
100
|
+
{
|
|
101
|
+
"name": "lock",
|
|
102
|
+
"flag": "--lock",
|
|
103
|
+
"label": "Registry lock path",
|
|
104
|
+
"type": "string",
|
|
105
|
+
"required": true
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
"name": "extension",
|
|
109
|
+
"flag": "--extension",
|
|
110
|
+
"label": "Extension registry path",
|
|
111
|
+
"type": "string"
|
|
112
|
+
}
|
|
45
113
|
]
|
|
46
114
|
},
|
|
47
115
|
{
|
|
48
|
-
"name": "scaffold",
|
|
49
|
-
"
|
|
116
|
+
"name": "scaffold",
|
|
117
|
+
"description": "Create a complete canonical SSSS project",
|
|
118
|
+
"effect": "write",
|
|
119
|
+
"output": "json",
|
|
50
120
|
"args": [
|
|
51
|
-
{
|
|
52
|
-
|
|
53
|
-
|
|
121
|
+
{
|
|
122
|
+
"name": "directory",
|
|
123
|
+
"flag": "--directory",
|
|
124
|
+
"label": "New project directory",
|
|
125
|
+
"type": "string",
|
|
126
|
+
"required": true
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
"name": "extension",
|
|
130
|
+
"flag": "--extension",
|
|
131
|
+
"label": "Extension registry name",
|
|
132
|
+
"type": "string"
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
"name": "withTotalRecall",
|
|
136
|
+
"flag": "--with-total-recall",
|
|
137
|
+
"label": "Include Total Recall wiring",
|
|
138
|
+
"type": "boolean"
|
|
139
|
+
}
|
|
54
140
|
]
|
|
55
141
|
},
|
|
56
142
|
{
|
|
57
|
-
"name": "conformance",
|
|
58
|
-
"
|
|
143
|
+
"name": "conformance",
|
|
144
|
+
"description": "Run the canonical reference engine conformance suite",
|
|
145
|
+
"effect": "read",
|
|
146
|
+
"output": "json"
|
|
59
147
|
}
|
|
60
148
|
]
|
|
61
149
|
},
|
|
62
|
-
"status": {
|
|
63
|
-
|
|
64
|
-
"
|
|
65
|
-
|
|
66
|
-
|
|
150
|
+
"status": {
|
|
151
|
+
"command": "status",
|
|
152
|
+
"refresh_seconds": 60
|
|
153
|
+
},
|
|
154
|
+
"runtime": {
|
|
155
|
+
"modules": {
|
|
156
|
+
"installation": "runtime/installation.cjs",
|
|
157
|
+
"project-scaffold": "runtime/project-scaffold.mjs"
|
|
158
|
+
}
|
|
159
|
+
},
|
|
67
160
|
"capability": {
|
|
68
161
|
"entry": "capability/index.mjs",
|
|
69
|
-
"exports": [
|
|
162
|
+
"exports": [
|
|
163
|
+
"canonicalToolchain",
|
|
164
|
+
"scaffoldProject",
|
|
165
|
+
"validateDocument",
|
|
166
|
+
"verifyRegistry",
|
|
167
|
+
"runConformance"
|
|
168
|
+
]
|
|
70
169
|
},
|
|
71
170
|
"branding": {
|
|
72
|
-
"name": "SSSS",
|
|
73
|
-
"
|
|
171
|
+
"name": "SSSS",
|
|
172
|
+
"color": "#b98439",
|
|
173
|
+
"accent": "#f4c97a",
|
|
174
|
+
"font": "ibm-plex",
|
|
175
|
+
"density": "compact",
|
|
176
|
+
"radius": "sm",
|
|
177
|
+
"header": "ledger-rule",
|
|
178
|
+
"logo": "ui/logo.svg"
|
|
179
|
+
},
|
|
180
|
+
"auth": {
|
|
181
|
+
"plugin": "auth",
|
|
182
|
+
"methods": [
|
|
183
|
+
"passkey",
|
|
184
|
+
"google-oauth2"
|
|
185
|
+
],
|
|
186
|
+
"session_verification": true
|
|
74
187
|
},
|
|
75
|
-
"auth": { "plugin": "auth", "methods": ["passkey", "google-oauth2"], "session_verification": true },
|
|
76
188
|
"ui": {
|
|
77
189
|
"design_tokens": "DESIGN.md",
|
|
78
190
|
"home": "home",
|
|
79
191
|
"elements": [
|
|
80
|
-
{
|
|
192
|
+
{
|
|
193
|
+
"id": "home",
|
|
194
|
+
"kind": "panel",
|
|
195
|
+
"tag": "tr-ssss-home",
|
|
196
|
+
"module": "ui/home.js",
|
|
197
|
+
"description": "SSSS installation ledger with document, registry, scaffold and conformance checks"
|
|
198
|
+
}
|
|
81
199
|
]
|
|
82
|
-
}
|
|
200
|
+
},
|
|
201
|
+
"reuse": {
|
|
202
|
+
"commands": [
|
|
203
|
+
"total-recall auth session",
|
|
204
|
+
"total-recall decision status"
|
|
205
|
+
],
|
|
206
|
+
"owned": "SSSS canonical toolchain, schema/document validation, registry verification, project scaffolding, and conformance checks."
|
|
207
|
+
},
|
|
208
|
+
"skills": [
|
|
209
|
+
{
|
|
210
|
+
"id": "ssss",
|
|
211
|
+
"path": "./skills/ssss/SKILL.md",
|
|
212
|
+
"description": "Canonical SSSS distribution, scaffolding and validation for Total Recall installations."
|
|
213
|
+
}
|
|
214
|
+
]
|
|
83
215
|
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: ssss
|
|
3
|
+
description: "Canonical SSSS distribution, scaffolding and validation for Total Recall installations."
|
|
4
|
+
version: 0.2.0
|
|
5
|
+
repo_scoped: false
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# SSSS
|
|
9
|
+
|
|
10
|
+
Canonical SSSS distribution, scaffolding and validation for Total Recall installations.
|
|
11
|
+
|
|
12
|
+
## When to Use
|
|
13
|
+
|
|
14
|
+
Use the `ssss` Total Recall plugin (`total-recall ssss`) instead of ad-hoc scripts or raw commands whenever working on ssss tasks.
|
|
15
|
+
|
|
16
|
+
## Commands
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
total-recall ssss --help
|
|
20
|
+
total-recall ssss status # Inspect the installed engine, skill and full scaffold
|
|
21
|
+
total-recall ssss repair # Restore missing or previously repinned managed SSSS installation files
|
|
22
|
+
total-recall ssss validate # Validate a document against the effective SSSS registry
|
|
23
|
+
total-recall ssss registry # Verify the effective registry against a lock file
|
|
24
|
+
total-recall ssss scaffold # Create a complete canonical SSSS project
|
|
25
|
+
total-recall ssss conformance # Run the canonical reference engine conformance suite
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Owned Raw Commands
|
|
29
|
+
|
|
30
|
+
This plugin owns: `npx\s+(--yes\s+)?@gregiteen/ssss-cli\s+new\b`.
|
package/src/cli/context.mjs
CHANGED
|
@@ -100,9 +100,13 @@ async function printCompacted({ query, actions, budget, format, version, rulesHa
|
|
|
100
100
|
// Measure the actual floor through the same encoder; leave room for the changed budget digits on retry.
|
|
101
101
|
const floor = await compact(error.requiredBudget);
|
|
102
102
|
const requiredBudget = estimateTokens(`${output(floor)}\n`) + 16;
|
|
103
|
+
const requiredIds = Array.isArray(error.requiredIds) ? error.requiredIds : [];
|
|
104
|
+
const requiredPreview = requiredIds.length
|
|
105
|
+
? ` required_set:${requiredIds.slice(0, 6).join(',')}${requiredIds.length > 6 ? `,+${requiredIds.length - 6}` : ''}`
|
|
106
|
+
: '';
|
|
103
107
|
console.log(format === 'json'
|
|
104
|
-
? JSON.stringify({ ready: false, reason: 'budget-overflow', context: '', stats: { version, budget, required_budget: requiredBudget, overage: requiredBudget - budget, rules: error.ruleCount, token_measurement: 'estimated_chars_divided_by_four' } })
|
|
105
|
-
: `ready:false reason:budget-overflow budget:${budget} required_budget:${requiredBudget} overage:${requiredBudget - budget} rules:${error.ruleCount} version:${version}\nThis budget cannot hold all ${error.ruleCount} applicable rules even compacted; \`total-recall rules audit\` lists them by size. Retry with --budget ${requiredBudget}; do not act until ready:true.`);
|
|
108
|
+
? JSON.stringify({ ready: false, reason: 'budget-overflow', context: '', stats: { version, budget, required_budget: requiredBudget, overage: requiredBudget - budget, rules: error.ruleCount, required_ids: requiredIds, token_measurement: 'estimated_chars_divided_by_four' } })
|
|
109
|
+
: `ready:false reason:budget-overflow budget:${budget} required_budget:${requiredBudget} overage:${requiredBudget - budget} rules:${error.ruleCount}${requiredPreview} version:${version}\nThis budget cannot hold all ${error.ruleCount} applicable rules even compacted; \`total-recall rules audit\` lists them by size. Retry with --budget ${requiredBudget}; do not act until ready:true.`);
|
|
106
110
|
process.exitCode = 2;
|
|
107
111
|
return false;
|
|
108
112
|
}
|
|
@@ -274,7 +274,7 @@ export async function createPlugin(args = []) {
|
|
|
274
274
|
};
|
|
275
275
|
}
|
|
276
276
|
|
|
277
|
-
const withSkill = args.includes("--
|
|
277
|
+
const withSkill = !args.includes("--no-skill");
|
|
278
278
|
const isCapability = args.includes("--capability") || Boolean(fromSkillPath);
|
|
279
279
|
|
|
280
280
|
if (withCli || isCapability || withTask) {
|
|
@@ -386,6 +386,7 @@ export default run;
|
|
|
386
386
|
name: ${id}
|
|
387
387
|
description: "${pluginDesc}"
|
|
388
388
|
version: 0.1.0
|
|
389
|
+
repo_scoped: false
|
|
389
390
|
---
|
|
390
391
|
|
|
391
392
|
# ${pluginName}
|
|
@@ -59,43 +59,50 @@ export async function managePluginLicense(args = []) {
|
|
|
59
59
|
const TR = process.env.TOTAL_RECALL_BIN || 'total-recall';
|
|
60
60
|
const amount = mon.price_cents || 1000;
|
|
61
61
|
const currency = (mon.currency || 'USD').toLowerCase();
|
|
62
|
-
const
|
|
63
|
-
const
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
62
|
+
const baseUrl = (process.env.TR_STORE_BASE_URL || 'http://127.0.0.1:3000').replace(/\/+$/, '');
|
|
63
|
+
const sIdx = args.indexOf('--success-url');
|
|
64
|
+
const cIdx = args.indexOf('--cancel-url');
|
|
65
|
+
const successUrl = (sIdx !== -1 && args[sIdx + 1]) || `${baseUrl}/plugins/success?plugin=${encodeURIComponent(pluginId)}`;
|
|
66
|
+
const cancelUrl = (cIdx !== -1 && args[cIdx + 1]) || `${baseUrl}/plugins/cancel?plugin=${encodeURIComponent(pluginId)}`;
|
|
67
|
+
const stripeArgs = [
|
|
68
|
+
'stripe', 'checkout',
|
|
69
|
+
'--amount', String(amount),
|
|
70
|
+
'--currency', currency,
|
|
71
|
+
'--name', `${plugin.manifest.name} License`,
|
|
72
|
+
'--success-url', successUrl,
|
|
73
|
+
'--cancel-url', cancelUrl,
|
|
74
|
+
'--json'
|
|
75
|
+
];
|
|
76
|
+
if (mon.recipient?.account_id) stripeArgs.push('--account', mon.recipient.account_id);
|
|
77
|
+
const script = TR.endsWith('.mjs');
|
|
78
|
+
const stripeRes = spawnSync(script ? process.execPath : TR, [
|
|
79
|
+
...(script ? [TR] : []),
|
|
80
|
+
...stripeArgs
|
|
81
|
+
], { encoding: 'utf8', timeout: 15000 });
|
|
82
|
+
if (stripeRes.status === 0 && stripeRes.stdout) {
|
|
83
|
+
let parsed = {};
|
|
84
|
+
try { parsed = JSON.parse(stripeRes.stdout); } catch {}
|
|
85
|
+
const url = parsed.url || parsed.checkout_url || parsed.data?.url;
|
|
86
|
+
if (url) {
|
|
87
|
+
if (json) {
|
|
88
|
+
console.log(JSON.stringify({ plugin: pluginId, checkout_url: url, session_id: parsed.id || parsed.session_id || null, amount, currency }));
|
|
89
|
+
} else {
|
|
90
|
+
console.log(`\n💳 Stripe Checkout Session Created:`);
|
|
91
|
+
console.log(` Plugin: ${plugin.manifest.name}`);
|
|
92
|
+
console.log(` Amount: $${(amount / 100).toFixed(2)} ${currency.toUpperCase()}`);
|
|
93
|
+
console.log(` Checkout URL: ${url}\n`);
|
|
89
94
|
}
|
|
95
|
+
return;
|
|
90
96
|
}
|
|
91
|
-
}
|
|
97
|
+
}
|
|
98
|
+
const errDetail = (stripeRes.stderr || stripeRes.stdout || stripeRes.error?.message || 'Stripe checkout failed').trim();
|
|
92
99
|
if (json) {
|
|
93
|
-
console.log(JSON.stringify({ plugin: pluginId, price_formatted: mon.priceFormatted, requires_purchase: true }));
|
|
100
|
+
console.log(JSON.stringify({ ok: false, plugin: pluginId, error: errDetail, price_formatted: mon.priceFormatted, requires_purchase: true }));
|
|
94
101
|
} else {
|
|
95
|
-
console.
|
|
96
|
-
console.
|
|
97
|
-
console.log(` Activate license after purchase: total-recall plugin license ${pluginId} activate --stdin\n`);
|
|
102
|
+
console.error(`❌ Stripe checkout failed for '${pluginId}': ${errDetail}`);
|
|
103
|
+
console.error(` Activate an existing license with: total-recall plugin license ${pluginId} activate --stdin`);
|
|
98
104
|
}
|
|
105
|
+
process.exitCode = 1;
|
|
99
106
|
return;
|
|
100
107
|
}
|
|
101
108
|
|
|
@@ -105,6 +112,33 @@ export async function managePluginLicense(args = []) {
|
|
|
105
112
|
else console.log(`ℹ️ Plugin '${pluginId}' does not require a commercial license (${mon.model}).`);
|
|
106
113
|
return;
|
|
107
114
|
}
|
|
115
|
+
const sessIdx = args.indexOf('--session-id');
|
|
116
|
+
const sessionId = sessIdx !== -1 ? args[sessIdx + 1] : null;
|
|
117
|
+
if (sessionId) {
|
|
118
|
+
const TR = process.env.TOTAL_RECALL_BIN || 'total-recall';
|
|
119
|
+
const script = TR.endsWith('.mjs');
|
|
120
|
+
const vRes = spawnSync(script ? process.execPath : TR, [
|
|
121
|
+
...(script ? [TR] : []),
|
|
122
|
+
'stripe', 'verify-entitlement',
|
|
123
|
+
'--session-id', sessionId,
|
|
124
|
+
'--consumer', pluginId,
|
|
125
|
+
'--amount', String(mon.price_cents || 1000),
|
|
126
|
+
'--currency', (mon.currency || 'USD').toLowerCase(),
|
|
127
|
+
'--json'
|
|
128
|
+
], { encoding: 'utf8', timeout: 15000 });
|
|
129
|
+
let vParsed = null;
|
|
130
|
+
try { vParsed = vRes.stdout ? JSON.parse(vRes.stdout) : null; } catch {}
|
|
131
|
+
if (vRes.status !== 0 || !vParsed?.entitled) {
|
|
132
|
+
const msg = vParsed?.error || (vRes.stderr || vRes.stdout || 'Stripe entitlement verification failed').trim();
|
|
133
|
+
if (json) console.log(JSON.stringify({ verified: false, plugin: pluginId, session_id: sessionId, error: msg }));
|
|
134
|
+
else console.error(`❌ Stripe entitlement check failed for '${pluginId}': ${msg}`);
|
|
135
|
+
process.exitCode = 1;
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
if (json) console.log(JSON.stringify({ verified: true, plugin: pluginId, session_id: sessionId, status: 'active', entitlement: vParsed }));
|
|
139
|
+
else console.log(`✅ Stripe entitlement verified active for '${pluginId}' (session ${sessionId}).`);
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
108
142
|
const secretKey = mon.license_key_secret;
|
|
109
143
|
const currentKey = secretKey ? await getSecret(defaultBrainDir(), secretKey, { actor: 'plugin-license' }) : null;
|
|
110
144
|
if (!currentKey?.found || !currentKey?.value) {
|
|
@@ -2,17 +2,18 @@ import { listAvailableBundled } from '../../core/plugin-store.mjs';
|
|
|
2
2
|
|
|
3
3
|
function parseArgs(args) {
|
|
4
4
|
const isJson = args.includes('--json');
|
|
5
|
+
const isStore = args.includes('--store');
|
|
5
6
|
let useCase = null;
|
|
6
7
|
const words = [];
|
|
7
8
|
for (let i = 0; i < args.length; i++) {
|
|
8
|
-
if (args[i] === '--json') continue;
|
|
9
|
+
if (args[i] === '--json' || args[i] === '--store') continue;
|
|
9
10
|
if (args[i] === '--use-case' && args[i + 1]) {
|
|
10
11
|
useCase = args[++i];
|
|
11
12
|
continue;
|
|
12
13
|
}
|
|
13
14
|
words.push(args[i]);
|
|
14
15
|
}
|
|
15
|
-
return { isJson, useCase, query: words.join(' ').toLowerCase().trim() };
|
|
16
|
+
return { isJson, isStore, useCase, query: words.join(' ').toLowerCase().trim() };
|
|
16
17
|
}
|
|
17
18
|
|
|
18
19
|
/**
|
|
@@ -108,7 +109,28 @@ export async function listPeers(args = []) {
|
|
|
108
109
|
|
|
109
110
|
/** `plugin search <query>` — bundled plugins plus whatever mesh peers share. */
|
|
110
111
|
export async function searchPlugins(args = []) {
|
|
111
|
-
const { isJson, useCase, query } = parseArgs(args);
|
|
112
|
+
const { isJson, isStore, useCase, query } = parseArgs(args);
|
|
113
|
+
if (isStore) {
|
|
114
|
+
const base = (process.env.TR_STORE_URL || 'http://127.0.0.1:3000').replace(/\/+$/, '');
|
|
115
|
+
const params = new URLSearchParams();
|
|
116
|
+
if (query) params.set('q', query);
|
|
117
|
+
if (useCase) params.set('use_case', useCase);
|
|
118
|
+
const res = await fetch(`${base}/api/store/plugins${params.toString() ? `?${params}` : ''}`);
|
|
119
|
+
if (!res.ok) throw new Error(`Store catalog unavailable (HTTP ${res.status})`);
|
|
120
|
+
const data = await res.json();
|
|
121
|
+
const storePlugins = data.plugins || [];
|
|
122
|
+
if (isJson) {
|
|
123
|
+
console.log(JSON.stringify({ store: storePlugins }, null, 2));
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
console.log(`\n🛒 Store plugins matching "${query || '*'}"${useCase ? ` (use case: ${useCase})` : ''}\n`);
|
|
127
|
+
if (storePlugins.length === 0) {
|
|
128
|
+
console.log('No store plugins found.\n');
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
for (const p of storePlugins) printPlugin(p, `store:${p.id}`);
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
112
134
|
const bundled = listAvailableBundled(process.cwd()).filter((p) => matches(p, query, useCase));
|
|
113
135
|
const { listPeerPlugins } = await import('../../core/plugin-peers.mjs');
|
|
114
136
|
const peers = await listPeerPlugins();
|
package/src/cli/preflight.mjs
CHANGED
|
@@ -7,7 +7,7 @@ import { globalBrainDirFor, isBrainEnabled } from '../core/brain-registry.mjs';
|
|
|
7
7
|
import { GATE_MODES, gateConfigPath, projectBrainDir, readGateLayers, resolveGateMode, writeGateMode } from '../core/gate-mode.mjs';
|
|
8
8
|
import { installHarnessHooks, loadGateAdapters } from '../core/harness-hooks.mjs';
|
|
9
9
|
import { ackDirectory, capsuleVerb, decide, gatePackageBroken, isAckCommand, isCheckCommand, isRouteCommand, isSubagentPayload, nativeToolOf, sessionOf, SWEEP_CONSULT_MS, whenGateFails } from '../core/preflight-gate.mjs';
|
|
10
|
-
import { ACK_COMMAND, acknowledge, checkAgentReceipt, checkAnyReceipt, findRoot, forgetCapsuleDeliveries, lastArrivalMs, lastCapsuleDelivery, lastConsultMs, lastRoutedMs, lastRouteWarnedMs, lastSessionAck, markArrival, markDelegated, markRouted, markRouteWarned, markSessionAck, noteCaller, recordDecision, sessionHasStanding, sessionKey, readDecisions, takeCaller } from '../core/preflight-receipt.mjs';
|
|
10
|
+
import { ACK_COMMAND, acknowledge, checkAgentReceipt, checkAnyReceipt, findRoot, forgetCapsuleDeliveries, lastArrivalMs, lastCapsuleDelivery, lastConsultMs, lastRoutedMs, lastRouteSelection, lastRouteWarnedMs, lastSessionAck, markArrival, markDelegated, markRouted, markRouteSelection, markRouteWarned, markSessionAck, noteCaller, recordDecision, sessionHasStanding, sessionKey, readDecisions, takeCaller } from '../core/preflight-receipt.mjs';
|
|
11
11
|
|
|
12
12
|
const USAGE = `Usage: total-recall preflight <command>
|
|
13
13
|
ack --task "<task>" [--action read,edit,test] [--json] Record a receipt after context ready:true and rules verify, and print the capsule.
|
|
@@ -19,9 +19,9 @@ const USAGE = `Usage: total-recall preflight <command>
|
|
|
19
19
|
remind [--json] Prompt-hook entry: advisory text when the receipt is missing; always exits 0
|
|
20
20
|
session-start Session-hook entry: after compaction or clear, the next ack prints the capsule; always exits 0
|
|
21
21
|
install [--harness <id>|--all] [--dry-run] Install the gate for a harness, or for every harness here. Install and update do this. No off switch.
|
|
22
|
-
mode [
|
|
23
|
-
Show
|
|
24
|
-
|
|
22
|
+
mode [enforce] [--plugin <id>|--router] [--repo] [--json]
|
|
23
|
+
Show gate enforcement status. All plugin and routing gates are permanently
|
|
24
|
+
enforced; off, warn, and clear bypasses are disabled.
|
|
25
25
|
coverage [--dir <folder>] [--json] List plugins as declared or missing; exit 1 on a gap. Default: the shared plugin folder
|
|
26
26
|
verify | report Harness adapters, owned by the cli-agents plugin
|
|
27
27
|
Aliases: total-recall tr-preflight --ack | --check. A receipt lasts 30 minutes (config preflight_max_age_minutes).
|
|
@@ -397,6 +397,33 @@ function projectBrainRoot(dir) {
|
|
|
397
397
|
return brain && isBrainEnabled(brain.brainDir) ? brain.projectRoot : null;
|
|
398
398
|
}
|
|
399
399
|
|
|
400
|
+
/** How long a route's selection binds when the receipt names no window: the default receipt lifetime. */
|
|
401
|
+
const ROUTE_SELECTION_MS = 30 * 60000;
|
|
402
|
+
|
|
403
|
+
/**
|
|
404
|
+
* Records which harness a router command selected, so the gate can deny writes from the others.
|
|
405
|
+
* Called after the router plugin's own command runs, with what it printed. Output that is not a
|
|
406
|
+
* route result records nothing. Bookkeeping only: it never throws.
|
|
407
|
+
* @returns {string|null|undefined} the selected harness, null when the route chose none, undefined when nothing was recorded
|
|
408
|
+
*/
|
|
409
|
+
export function noteRouteSelection({ manifest, args = [], stdout = '', cwd = process.cwd() } = {}) {
|
|
410
|
+
try {
|
|
411
|
+
const router = manifest?.gate?.router;
|
|
412
|
+
if (!router?.pattern) return undefined;
|
|
413
|
+
const command = `${manifest.cli?.command || manifest.id} ${args.map(String).join(' ')}`;
|
|
414
|
+
if (!new RegExp(`(?:^|\\s)(?:${router.pattern})(\\s|$)`).test(command)) return undefined;
|
|
415
|
+
const text = String(stdout || '').trim();
|
|
416
|
+
let result;
|
|
417
|
+
try { result = JSON.parse(text); } catch { result = JSON.parse(text.split('\n').pop()); }
|
|
418
|
+
if (!result || typeof result !== 'object' || !('selected' in result)) return undefined;
|
|
419
|
+
const selected = typeof result.selected === 'string' && result.selected ? result.selected : null;
|
|
420
|
+
const root = findRoot(cwd);
|
|
421
|
+
markRouted(root);
|
|
422
|
+
markRouteSelection(root, selected);
|
|
423
|
+
return selected;
|
|
424
|
+
} catch { return undefined; }
|
|
425
|
+
}
|
|
426
|
+
|
|
400
427
|
/** The gate's answer to a call. Nothing here may throw, because an answer is all that keeps its repair reachable. */
|
|
401
428
|
function evaluate(call, options = {}) {
|
|
402
429
|
try {
|
|
@@ -450,6 +477,13 @@ function judge(call, { harness, readablePaths, session = null, subagent = false,
|
|
|
450
477
|
ownerHealthy: (plugin, use) => ownerRuns(plugin, use, root),
|
|
451
478
|
// A subagent or a run the router started reports to whoever routed the work.
|
|
452
479
|
dispatched: runByRouter || subagent || Boolean(session && !ownAck),
|
|
480
|
+
// Only a named harness can be told apart from the one the router chose.
|
|
481
|
+
harness: harness && harness !== 'generic' ? harness : null,
|
|
482
|
+
routerRun: runByRouter,
|
|
483
|
+
selection: (receipt) => {
|
|
484
|
+
const chosen = lastRouteSelection(root);
|
|
485
|
+
return chosen && Date.now() - chosen.at < (limit ?? receipt?.limitMs ?? ROUTE_SELECTION_MS) ? chosen : null;
|
|
486
|
+
},
|
|
453
487
|
check,
|
|
454
488
|
recentConsult: () => {
|
|
455
489
|
const now = Date.now();
|
|
@@ -569,14 +603,14 @@ async function mode(args) {
|
|
|
569
603
|
const repo = args.includes('--repo');
|
|
570
604
|
const brain = repo ? projectBrainDir(root) : globalBrainDirFor();
|
|
571
605
|
if (value !== undefined) {
|
|
572
|
-
if (value !== '
|
|
606
|
+
if (value !== 'enforce') return fail(`✖ Plugin and routing gates are permanently enforced and have no "${value}" bypass.`);
|
|
573
607
|
const plugin = flag(args, '--plugin');
|
|
574
608
|
const router = args.includes('--router');
|
|
575
609
|
if (plugin && router) return fail('Choose --plugin or --router, not both.');
|
|
576
610
|
if (plugin && !plugins.includes(plugin)) return fail(`No plugin here declares raw commands under "${plugin}". Declared: ${plugins.join(', ') || 'none'}.`);
|
|
577
611
|
if (router && !declared.router) return fail('No plugin here declares a router.');
|
|
578
612
|
if (repo && !fs.existsSync(brain)) return fail(`${root} has no project brain to hold this setting. Run total-recall init there, or leave off --repo.`);
|
|
579
|
-
writeGateMode(brain, { mode:
|
|
613
|
+
writeGateMode(brain, { mode: 'enforce', plugin, router });
|
|
580
614
|
}
|
|
581
615
|
const layers = readGateLayers({ globalBrainDir: globalBrainDirFor(), root });
|
|
582
616
|
const { adapters } = await loadGateAdapters(root);
|
|
@@ -106,6 +106,7 @@ export function compactRules(items, { budget, expand = [], header, complete = fa
|
|
|
106
106
|
const error = new Error(`Budget ${budget} cannot hold the capsule header; the minimum is ${floor}`);
|
|
107
107
|
error.requiredBudget = floor;
|
|
108
108
|
error.ruleCount = items.length;
|
|
109
|
+
error.requiredIds = items.map(item => item.slug);
|
|
109
110
|
throw error;
|
|
110
111
|
}
|
|
111
112
|
|
|
@@ -127,6 +128,7 @@ export function compactRules(items, { budget, expand = [], header, complete = fa
|
|
|
127
128
|
const error = new Error(`Budget ${budget} cannot hold every rule; the minimum is ${completeFloor}`);
|
|
128
129
|
error.requiredBudget = completeFloor;
|
|
129
130
|
error.ruleCount = items.length;
|
|
131
|
+
error.requiredIds = items.map(item => item.slug);
|
|
130
132
|
throw error;
|
|
131
133
|
}
|
|
132
134
|
}
|