@vectorize-io/self-driving-agents 0.0.17 → 0.0.19
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/dist/cli.js +33 -5
- package/dist/tests/cli.test.js +31 -5
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -125,6 +125,33 @@ function enableKnowledgeTools() {
|
|
|
125
125
|
pc.enableKnowledgeTools = true;
|
|
126
126
|
writeFileSync(OPENCLAW_CONFIG_PATH, JSON.stringify(config, null, 2) + "\n");
|
|
127
127
|
}
|
|
128
|
+
// SDA agents are isolated per-agent only — no channel/user. The plugin's default
|
|
129
|
+
// (["agent","channel","user"]) produces banks like "marketing-seo::unknown::anonymous"
|
|
130
|
+
// for local sessions where channel/sender aren't populated.
|
|
131
|
+
async function ensureOpenClawAgentGranularity() {
|
|
132
|
+
const config = readOpenClawConfig();
|
|
133
|
+
if (!config)
|
|
134
|
+
return;
|
|
135
|
+
const pc = config.plugins?.entries?.["hindsight-openclaw"]?.config;
|
|
136
|
+
if (!pc)
|
|
137
|
+
return;
|
|
138
|
+
const current = pc.dynamicBankGranularity;
|
|
139
|
+
const desired = ["agent"];
|
|
140
|
+
const matches = Array.isArray(current) && current.length === 1 && current[0] === "agent";
|
|
141
|
+
if (matches)
|
|
142
|
+
return;
|
|
143
|
+
if (current && current.length > 0) {
|
|
144
|
+
const ok = await p.confirm({
|
|
145
|
+
message: `Plugin has dynamicBankGranularity=${color.yellow(JSON.stringify(current))}. SDA agents need ${color.cyan('["agent"]')}. Override?`,
|
|
146
|
+
initialValue: true,
|
|
147
|
+
});
|
|
148
|
+
if (p.isCancel(ok) || !ok)
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
pc.dynamicBankGranularity = desired;
|
|
152
|
+
writeFileSync(OPENCLAW_CONFIG_PATH, JSON.stringify(config, null, 2) + "\n");
|
|
153
|
+
p.log.success("Set dynamicBankGranularity = [\"agent\"] for per-agent bank isolation");
|
|
154
|
+
}
|
|
128
155
|
const MIN_PLUGIN_VERSION = "0.7.2";
|
|
129
156
|
function getInstalledPluginVersion() {
|
|
130
157
|
try {
|
|
@@ -178,7 +205,7 @@ function resolveFromPlugin(agentId) {
|
|
|
178
205
|
bankId = pc.bankId;
|
|
179
206
|
}
|
|
180
207
|
else {
|
|
181
|
-
const granularity = pc.dynamicBankGranularity || ["agent"
|
|
208
|
+
const granularity = pc.dynamicBankGranularity || ["agent"];
|
|
182
209
|
const fieldMap = {
|
|
183
210
|
agent: agentId,
|
|
184
211
|
channel: "unknown",
|
|
@@ -627,7 +654,7 @@ async function promptClaudeConfig(agentId, opts = { askBankId: true }) {
|
|
|
627
654
|
apiUrl = urlInput;
|
|
628
655
|
p.log.warn("Make sure your Hindsight instance is publicly accessible from Claude's servers.");
|
|
629
656
|
}
|
|
630
|
-
const tokenInput = await p.
|
|
657
|
+
const tokenInput = await p.password({ message: "Hindsight API token:" });
|
|
631
658
|
if (p.isCancel(tokenInput)) {
|
|
632
659
|
p.cancel("Cancelled.");
|
|
633
660
|
process.exit(0);
|
|
@@ -724,10 +751,12 @@ async function main() {
|
|
|
724
751
|
if (harness === "openclaw") {
|
|
725
752
|
await ensurePlugin();
|
|
726
753
|
enableKnowledgeTools();
|
|
754
|
+
await ensureOpenClawAgentGranularity();
|
|
727
755
|
({ apiUrl, bankId, apiToken } = resolveFromPlugin(agentId));
|
|
728
756
|
}
|
|
729
757
|
else if (harness === "nemoclaw") {
|
|
730
758
|
await ensureNemoClawPlugin(sandbox, agentId);
|
|
759
|
+
await ensureOpenClawAgentGranularity();
|
|
731
760
|
({ apiUrl, bankId, apiToken } = resolveFromPlugin(agentId));
|
|
732
761
|
}
|
|
733
762
|
else if (harness === "hermes") {
|
|
@@ -779,7 +808,7 @@ async function main() {
|
|
|
779
808
|
p.cancel("Cancelled.");
|
|
780
809
|
process.exit(0);
|
|
781
810
|
}
|
|
782
|
-
const tokenInput = await p.
|
|
811
|
+
const tokenInput = await p.password({ message: "Hindsight API token:" });
|
|
783
812
|
if (p.isCancel(tokenInput)) {
|
|
784
813
|
p.cancel("Cancelled.");
|
|
785
814
|
process.exit(0);
|
|
@@ -794,7 +823,7 @@ async function main() {
|
|
|
794
823
|
p.cancel("Cancelled.");
|
|
795
824
|
process.exit(0);
|
|
796
825
|
}
|
|
797
|
-
const tokenInput = await p.
|
|
826
|
+
const tokenInput = await p.password({ message: "Hindsight API token:" });
|
|
798
827
|
if (p.isCancel(tokenInput)) {
|
|
799
828
|
p.cancel("Cancelled.");
|
|
800
829
|
process.exit(0);
|
|
@@ -990,7 +1019,6 @@ async function main() {
|
|
|
990
1019
|
p.log.info([
|
|
991
1020
|
`Agent: ${color.bold(agentId)}`,
|
|
992
1021
|
`Source: ${color.dim(source)}`,
|
|
993
|
-
`Bank: ${color.dim(bankId)}`,
|
|
994
1022
|
`API: ${color.dim(apiUrl)}`,
|
|
995
1023
|
`Workspace: ${color.dim(workspaceDir)}`,
|
|
996
1024
|
].join("\n"));
|
package/dist/tests/cli.test.js
CHANGED
|
@@ -43,7 +43,7 @@ function resolveFromPluginConfig(agentId, pc) {
|
|
|
43
43
|
bankId = pc.bankId;
|
|
44
44
|
}
|
|
45
45
|
else {
|
|
46
|
-
const granularity = pc.dynamicBankGranularity || ["agent"
|
|
46
|
+
const granularity = pc.dynamicBankGranularity || ["agent"];
|
|
47
47
|
const fieldMap = {
|
|
48
48
|
agent: agentId,
|
|
49
49
|
channel: "unknown",
|
|
@@ -221,9 +221,11 @@ describe("resolveFromPluginConfig", () => {
|
|
|
221
221
|
});
|
|
222
222
|
expect(result.bankId).toBe("my-agent::unknown::anonymous");
|
|
223
223
|
});
|
|
224
|
-
it("uses default granularity when not specified", () => {
|
|
224
|
+
it("uses default granularity (agent-only) when not specified", () => {
|
|
225
|
+
// SDA forces ["agent"] in plugin config, so the dry-run preview default
|
|
226
|
+
// mirrors that. Multi-field granularity must be opted into explicitly.
|
|
225
227
|
const result = resolveFromPluginConfig("my-agent", {});
|
|
226
|
-
expect(result.bankId).toBe("my-agent
|
|
228
|
+
expect(result.bankId).toBe("my-agent");
|
|
227
229
|
});
|
|
228
230
|
it("uses static bankId when dynamicBankId is false", () => {
|
|
229
231
|
const result = resolveFromPluginConfig("my-agent", {
|
|
@@ -243,8 +245,8 @@ describe("resolveFromPluginConfig", () => {
|
|
|
243
245
|
expect(result.apiUrl).toBe("https://api.hindsight.vectorize.io");
|
|
244
246
|
expect(result.apiToken).toBe("hsk_abc");
|
|
245
247
|
// dynamicBankId=false but no bankId set, so falls through to dynamic path
|
|
246
|
-
// with bankIdPrefix
|
|
247
|
-
expect(result.bankId).toBe("my-sandbox-marketing-seo
|
|
248
|
+
// with bankIdPrefix and the agent-only default granularity
|
|
249
|
+
expect(result.bankId).toBe("my-sandbox-marketing-seo");
|
|
248
250
|
});
|
|
249
251
|
it("resolves nemoclaw-style config with static bankId", () => {
|
|
250
252
|
const result = resolveFromPluginConfig("marketing-seo", {
|
|
@@ -622,6 +624,30 @@ describe("claude-code allowed-tools merge", () => {
|
|
|
622
624
|
expect(merged).toHaveLength(HINDSIGHT_TOOLS.length);
|
|
623
625
|
});
|
|
624
626
|
});
|
|
627
|
+
describe("openclaw dynamicBankGranularity enforcement", () => {
|
|
628
|
+
function decide(current) {
|
|
629
|
+
if (Array.isArray(current) && current.length === 1 && current[0] === "agent") {
|
|
630
|
+
return "noop";
|
|
631
|
+
}
|
|
632
|
+
if (Array.isArray(current) && current.length > 0) {
|
|
633
|
+
return "ask-confirm";
|
|
634
|
+
}
|
|
635
|
+
return "set-fresh";
|
|
636
|
+
}
|
|
637
|
+
it("sets [agent] when not configured (fresh install)", () => {
|
|
638
|
+
expect(decide(undefined)).toBe("set-fresh");
|
|
639
|
+
expect(decide(null)).toBe("set-fresh");
|
|
640
|
+
expect(decide([])).toBe("set-fresh");
|
|
641
|
+
});
|
|
642
|
+
it("noop when already [agent]", () => {
|
|
643
|
+
expect(decide(["agent"])).toBe("noop");
|
|
644
|
+
});
|
|
645
|
+
it("asks confirmation when set to a different value", () => {
|
|
646
|
+
expect(decide(["agent", "channel", "user"])).toBe("ask-confirm");
|
|
647
|
+
expect(decide(["channel"])).toBe("ask-confirm");
|
|
648
|
+
expect(decide(["agent", "project"])).toBe("ask-confirm");
|
|
649
|
+
});
|
|
650
|
+
});
|
|
625
651
|
describe("claude-code Hindsight config persistence", () => {
|
|
626
652
|
// Mirrors the config-write logic: if existing config has a connection
|
|
627
653
|
// (hindsightApiUrl or llmProvider), don't prompt; otherwise prompt.
|