@deeplake/hivemind 0.7.74 → 0.7.76
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/.claude-plugin/marketplace.json +3 -3
- package/.claude-plugin/plugin.json +1 -1
- package/codex/bundle/capture.js +1 -1
- package/codex/bundle/session-start.js +49 -0
- package/codex/bundle/stop.js +1 -1
- package/cursor/bundle/capture.js +1 -1
- package/cursor/bundle/session-end.js +1 -1
- package/cursor/bundle/session-start.js +49 -0
- package/hermes/bundle/capture.js +1 -1
- package/hermes/bundle/session-end.js +1 -1
- package/hermes/bundle/session-start.js +49 -0
- package/openclaw/dist/index.js +28 -1
- package/openclaw/openclaw.plugin.json +1 -1
- package/openclaw/package.json +1 -1
- package/package.json +1 -1
- package/pi/extension-source/hivemind.ts +1 -1
|
@@ -6,18 +6,18 @@
|
|
|
6
6
|
},
|
|
7
7
|
"metadata": {
|
|
8
8
|
"description": "Cloud-backed persistent shared memory for AI agents powered by Deeplake",
|
|
9
|
-
"version": "0.7.
|
|
9
|
+
"version": "0.7.76"
|
|
10
10
|
},
|
|
11
11
|
"plugins": [
|
|
12
12
|
{
|
|
13
13
|
"name": "hivemind",
|
|
14
14
|
"description": "Persistent shared memory powered by Deeplake — captures all session activity and provides cross-session, cross-agent memory search",
|
|
15
|
-
"version": "0.7.
|
|
15
|
+
"version": "0.7.76",
|
|
16
16
|
"source": {
|
|
17
17
|
"source": "git-subdir",
|
|
18
18
|
"url": "https://github.com/activeloopai/hivemind.git",
|
|
19
19
|
"path": "claude-code",
|
|
20
|
-
"sha": "
|
|
20
|
+
"sha": "d3dd170f102bf2543acc874d236d766542295e8e"
|
|
21
21
|
},
|
|
22
22
|
"homepage": "https://github.com/activeloopai/hivemind"
|
|
23
23
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hivemind",
|
|
3
3
|
"description": "Cloud-backed persistent memory powered by Deeplake — read, write, and share memory across Claude Code sessions and agents",
|
|
4
|
-
"version": "0.7.
|
|
4
|
+
"version": "0.7.76",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Activeloop",
|
|
7
7
|
"url": "https://deeplake.ai"
|
package/codex/bundle/capture.js
CHANGED
|
@@ -1846,7 +1846,7 @@ Format: **entity** (type) \u2014 what was done with it, its current state>
|
|
|
1846
1846
|
<Anything unresolved, blocked, or explicitly deferred>
|
|
1847
1847
|
|
|
1848
1848
|
## Next Steps
|
|
1849
|
-
<
|
|
1849
|
+
<Decide in two steps. STEP 1 \u2014 is the work this session set out to do actually finished? If it ended mid-task \u2014 a feature only half-implemented, a build or test still failing, a fix written but not yet verified, a plan agreed but not executed, a blocker hit and unresolved, or an explicit "still need to.../next I'll..." left hanging \u2014 then it is NOT finished and you MUST write a single concrete imperative line naming the unfinished work (e.g. "Finish wiring the uint32 class_label scan binding and run its test"). The session's LAST messages are the strongest signal: if they describe or show work still in progress or something left to do, that IS the next step \u2014 never suppress a genuinely unfinished task, and do not demand "substantial consequences" for it. STEP 2 \u2014 if the core work IS finished, default to exactly: none and do not invent a follow-up to fill the section. Write none when the work reached a natural stopping point, only trivial/obvious/optional polish or cleanup remains, the "next step" would just be open-ended exploration, or the only thing left is administrative wrap-up (committing, pushing, opening/merging a PR, deploying, monitoring CI \u2014 treat ALL such wrap-up as ALREADY DONE). The sole exception that still warrants a next step on otherwise-finished work is a separate, important, non-obvious item a returning engineer would NOT realize on their own and would be materially harmed by missing.>
|
|
1850
1850
|
|
|
1851
1851
|
IMPORTANT: Be exhaustive. Extract EVERY entity, decision, and fact.
|
|
1852
1852
|
PRIVACY: Never include absolute filesystem paths in the summary.
|
|
@@ -112,6 +112,19 @@ function decodeJwtPayload(token) {
|
|
|
112
112
|
return null;
|
|
113
113
|
}
|
|
114
114
|
}
|
|
115
|
+
async function apiGet(path, token, apiUrl, orgId) {
|
|
116
|
+
const headers = {
|
|
117
|
+
Authorization: `Bearer ${token}`,
|
|
118
|
+
"Content-Type": "application/json",
|
|
119
|
+
...deeplakeClientHeader()
|
|
120
|
+
};
|
|
121
|
+
if (orgId)
|
|
122
|
+
headers["X-Activeloop-Org-Id"] = orgId;
|
|
123
|
+
const resp = await fetch(`${apiUrl}${path}`, { headers });
|
|
124
|
+
if (!resp.ok)
|
|
125
|
+
throw new Error(`API ${resp.status}: ${await resp.text().catch(() => "")}`);
|
|
126
|
+
return resp.json();
|
|
127
|
+
}
|
|
115
128
|
async function apiPost(path, body, token, apiUrl, orgId) {
|
|
116
129
|
const headers = {
|
|
117
130
|
Authorization: `Bearer ${token}`,
|
|
@@ -125,6 +138,10 @@ async function apiPost(path, body, token, apiUrl, orgId) {
|
|
|
125
138
|
throw new Error(`API ${resp.status}: ${await resp.text().catch(() => "")}`);
|
|
126
139
|
return resp.json();
|
|
127
140
|
}
|
|
141
|
+
async function listOrgs(token, apiUrl = DEFAULT_API_URL) {
|
|
142
|
+
const data = await apiGet("/organizations", token, apiUrl);
|
|
143
|
+
return Array.isArray(data) ? data : [];
|
|
144
|
+
}
|
|
128
145
|
async function healDriftedOrgToken(creds, log6 = () => {
|
|
129
146
|
}) {
|
|
130
147
|
if (!creds.token || !creds.orgId)
|
|
@@ -143,6 +160,33 @@ async function healDriftedOrgToken(creds, log6 = () => {
|
|
|
143
160
|
organization_id: creds.orgId
|
|
144
161
|
}, creds.token, apiUrl);
|
|
145
162
|
const healed = { ...creds, token: tokenData.token.token };
|
|
163
|
+
try {
|
|
164
|
+
const orgs = await listOrgs(healed.token, apiUrl);
|
|
165
|
+
const matchedOrg = orgs.find((o) => o.id === creds.orgId);
|
|
166
|
+
if (matchedOrg && matchedOrg.name !== creds.orgName) {
|
|
167
|
+
log6(`orgName realigned: ${creds.orgName ?? "(unset)"} -> ${matchedOrg.name}`);
|
|
168
|
+
healed.orgName = matchedOrg.name;
|
|
169
|
+
}
|
|
170
|
+
} catch (e) {
|
|
171
|
+
log6(`orgName realign skipped: ${e.message}`);
|
|
172
|
+
}
|
|
173
|
+
const currentWs = creds.workspaceId ?? "default";
|
|
174
|
+
if (currentWs !== "default") {
|
|
175
|
+
try {
|
|
176
|
+
const wsList = await listWorkspaces(healed.token, apiUrl, creds.orgId);
|
|
177
|
+
const lcWs = currentWs.toLowerCase();
|
|
178
|
+
const wsMatch = wsList.find((w) => w.id === currentWs || w.name && w.name.toLowerCase() === lcWs);
|
|
179
|
+
if (!wsMatch) {
|
|
180
|
+
log6(`workspace '${currentWs}' not in org ${creds.orgId} \u2014 reset to default`);
|
|
181
|
+
healed.workspaceId = "default";
|
|
182
|
+
} else if (wsMatch.id !== currentWs) {
|
|
183
|
+
log6(`workspace '${currentWs}' resolved to id '${wsMatch.id}'`);
|
|
184
|
+
healed.workspaceId = wsMatch.id;
|
|
185
|
+
}
|
|
186
|
+
} catch (e) {
|
|
187
|
+
log6(`workspace realign skipped: ${e.message}`);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
146
190
|
saveCredentials(healed);
|
|
147
191
|
log6(`token re-minted for org=${creds.orgId}`);
|
|
148
192
|
return healed;
|
|
@@ -151,6 +195,11 @@ async function healDriftedOrgToken(creds, log6 = () => {
|
|
|
151
195
|
return creds;
|
|
152
196
|
}
|
|
153
197
|
}
|
|
198
|
+
async function listWorkspaces(token, apiUrl = DEFAULT_API_URL, orgId) {
|
|
199
|
+
const raw = await apiGet("/workspaces", token, apiUrl, orgId);
|
|
200
|
+
const data = raw.data ?? raw;
|
|
201
|
+
return Array.isArray(data) ? data : [];
|
|
202
|
+
}
|
|
154
203
|
|
|
155
204
|
// dist/src/utils/stdin.js
|
|
156
205
|
function readStdin() {
|
package/codex/bundle/stop.js
CHANGED
|
@@ -1126,7 +1126,7 @@ Format: **entity** (type) \u2014 what was done with it, its current state>
|
|
|
1126
1126
|
<Anything unresolved, blocked, or explicitly deferred>
|
|
1127
1127
|
|
|
1128
1128
|
## Next Steps
|
|
1129
|
-
<
|
|
1129
|
+
<Decide in two steps. STEP 1 \u2014 is the work this session set out to do actually finished? If it ended mid-task \u2014 a feature only half-implemented, a build or test still failing, a fix written but not yet verified, a plan agreed but not executed, a blocker hit and unresolved, or an explicit "still need to.../next I'll..." left hanging \u2014 then it is NOT finished and you MUST write a single concrete imperative line naming the unfinished work (e.g. "Finish wiring the uint32 class_label scan binding and run its test"). The session's LAST messages are the strongest signal: if they describe or show work still in progress or something left to do, that IS the next step \u2014 never suppress a genuinely unfinished task, and do not demand "substantial consequences" for it. STEP 2 \u2014 if the core work IS finished, default to exactly: none and do not invent a follow-up to fill the section. Write none when the work reached a natural stopping point, only trivial/obvious/optional polish or cleanup remains, the "next step" would just be open-ended exploration, or the only thing left is administrative wrap-up (committing, pushing, opening/merging a PR, deploying, monitoring CI \u2014 treat ALL such wrap-up as ALREADY DONE). The sole exception that still warrants a next step on otherwise-finished work is a separate, important, non-obvious item a returning engineer would NOT realize on their own and would be materially harmed by missing.>
|
|
1130
1130
|
|
|
1131
1131
|
IMPORTANT: Be exhaustive. Extract EVERY entity, decision, and fact.
|
|
1132
1132
|
PRIVACY: Never include absolute filesystem paths in the summary.
|
package/cursor/bundle/capture.js
CHANGED
|
@@ -1846,7 +1846,7 @@ Format: **entity** (type) \u2014 what was done with it, its current state>
|
|
|
1846
1846
|
<Anything unresolved, blocked, or explicitly deferred>
|
|
1847
1847
|
|
|
1848
1848
|
## Next Steps
|
|
1849
|
-
<
|
|
1849
|
+
<Decide in two steps. STEP 1 \u2014 is the work this session set out to do actually finished? If it ended mid-task \u2014 a feature only half-implemented, a build or test still failing, a fix written but not yet verified, a plan agreed but not executed, a blocker hit and unresolved, or an explicit "still need to.../next I'll..." left hanging \u2014 then it is NOT finished and you MUST write a single concrete imperative line naming the unfinished work (e.g. "Finish wiring the uint32 class_label scan binding and run its test"). The session's LAST messages are the strongest signal: if they describe or show work still in progress or something left to do, that IS the next step \u2014 never suppress a genuinely unfinished task, and do not demand "substantial consequences" for it. STEP 2 \u2014 if the core work IS finished, default to exactly: none and do not invent a follow-up to fill the section. Write none when the work reached a natural stopping point, only trivial/obvious/optional polish or cleanup remains, the "next step" would just be open-ended exploration, or the only thing left is administrative wrap-up (committing, pushing, opening/merging a PR, deploying, monitoring CI \u2014 treat ALL such wrap-up as ALREADY DONE). The sole exception that still warrants a next step on otherwise-finished work is a separate, important, non-obvious item a returning engineer would NOT realize on their own and would be materially harmed by missing.>
|
|
1850
1850
|
|
|
1851
1851
|
IMPORTANT: Be exhaustive. Extract EVERY entity, decision, and fact.
|
|
1852
1852
|
PRIVACY: Never include absolute filesystem paths in the summary.
|
|
@@ -269,7 +269,7 @@ Format: **entity** (type) \u2014 what was done with it, its current state>
|
|
|
269
269
|
<Anything unresolved, blocked, or explicitly deferred>
|
|
270
270
|
|
|
271
271
|
## Next Steps
|
|
272
|
-
<
|
|
272
|
+
<Decide in two steps. STEP 1 \u2014 is the work this session set out to do actually finished? If it ended mid-task \u2014 a feature only half-implemented, a build or test still failing, a fix written but not yet verified, a plan agreed but not executed, a blocker hit and unresolved, or an explicit "still need to.../next I'll..." left hanging \u2014 then it is NOT finished and you MUST write a single concrete imperative line naming the unfinished work (e.g. "Finish wiring the uint32 class_label scan binding and run its test"). The session's LAST messages are the strongest signal: if they describe or show work still in progress or something left to do, that IS the next step \u2014 never suppress a genuinely unfinished task, and do not demand "substantial consequences" for it. STEP 2 \u2014 if the core work IS finished, default to exactly: none and do not invent a follow-up to fill the section. Write none when the work reached a natural stopping point, only trivial/obvious/optional polish or cleanup remains, the "next step" would just be open-ended exploration, or the only thing left is administrative wrap-up (committing, pushing, opening/merging a PR, deploying, monitoring CI \u2014 treat ALL such wrap-up as ALREADY DONE). The sole exception that still warrants a next step on otherwise-finished work is a separate, important, non-obvious item a returning engineer would NOT realize on their own and would be materially harmed by missing.>
|
|
273
273
|
|
|
274
274
|
IMPORTANT: Be exhaustive. Extract EVERY entity, decision, and fact.
|
|
275
275
|
PRIVACY: Never include absolute filesystem paths in the summary.
|
|
@@ -111,6 +111,19 @@ function decodeJwtPayload(token) {
|
|
|
111
111
|
return null;
|
|
112
112
|
}
|
|
113
113
|
}
|
|
114
|
+
async function apiGet(path, token, apiUrl, orgId) {
|
|
115
|
+
const headers = {
|
|
116
|
+
Authorization: `Bearer ${token}`,
|
|
117
|
+
"Content-Type": "application/json",
|
|
118
|
+
...deeplakeClientHeader()
|
|
119
|
+
};
|
|
120
|
+
if (orgId)
|
|
121
|
+
headers["X-Activeloop-Org-Id"] = orgId;
|
|
122
|
+
const resp = await fetch(`${apiUrl}${path}`, { headers });
|
|
123
|
+
if (!resp.ok)
|
|
124
|
+
throw new Error(`API ${resp.status}: ${await resp.text().catch(() => "")}`);
|
|
125
|
+
return resp.json();
|
|
126
|
+
}
|
|
114
127
|
async function apiPost(path, body, token, apiUrl, orgId) {
|
|
115
128
|
const headers = {
|
|
116
129
|
Authorization: `Bearer ${token}`,
|
|
@@ -124,6 +137,10 @@ async function apiPost(path, body, token, apiUrl, orgId) {
|
|
|
124
137
|
throw new Error(`API ${resp.status}: ${await resp.text().catch(() => "")}`);
|
|
125
138
|
return resp.json();
|
|
126
139
|
}
|
|
140
|
+
async function listOrgs(token, apiUrl = DEFAULT_API_URL) {
|
|
141
|
+
const data = await apiGet("/organizations", token, apiUrl);
|
|
142
|
+
return Array.isArray(data) ? data : [];
|
|
143
|
+
}
|
|
127
144
|
async function healDriftedOrgToken(creds, log7 = () => {
|
|
128
145
|
}) {
|
|
129
146
|
if (!creds.token || !creds.orgId)
|
|
@@ -142,6 +159,33 @@ async function healDriftedOrgToken(creds, log7 = () => {
|
|
|
142
159
|
organization_id: creds.orgId
|
|
143
160
|
}, creds.token, apiUrl);
|
|
144
161
|
const healed = { ...creds, token: tokenData.token.token };
|
|
162
|
+
try {
|
|
163
|
+
const orgs = await listOrgs(healed.token, apiUrl);
|
|
164
|
+
const matchedOrg = orgs.find((o) => o.id === creds.orgId);
|
|
165
|
+
if (matchedOrg && matchedOrg.name !== creds.orgName) {
|
|
166
|
+
log7(`orgName realigned: ${creds.orgName ?? "(unset)"} -> ${matchedOrg.name}`);
|
|
167
|
+
healed.orgName = matchedOrg.name;
|
|
168
|
+
}
|
|
169
|
+
} catch (e) {
|
|
170
|
+
log7(`orgName realign skipped: ${e.message}`);
|
|
171
|
+
}
|
|
172
|
+
const currentWs = creds.workspaceId ?? "default";
|
|
173
|
+
if (currentWs !== "default") {
|
|
174
|
+
try {
|
|
175
|
+
const wsList = await listWorkspaces(healed.token, apiUrl, creds.orgId);
|
|
176
|
+
const lcWs = currentWs.toLowerCase();
|
|
177
|
+
const wsMatch = wsList.find((w) => w.id === currentWs || w.name && w.name.toLowerCase() === lcWs);
|
|
178
|
+
if (!wsMatch) {
|
|
179
|
+
log7(`workspace '${currentWs}' not in org ${creds.orgId} \u2014 reset to default`);
|
|
180
|
+
healed.workspaceId = "default";
|
|
181
|
+
} else if (wsMatch.id !== currentWs) {
|
|
182
|
+
log7(`workspace '${currentWs}' resolved to id '${wsMatch.id}'`);
|
|
183
|
+
healed.workspaceId = wsMatch.id;
|
|
184
|
+
}
|
|
185
|
+
} catch (e) {
|
|
186
|
+
log7(`workspace realign skipped: ${e.message}`);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
145
189
|
saveCredentials(healed);
|
|
146
190
|
log7(`token re-minted for org=${creds.orgId}`);
|
|
147
191
|
return healed;
|
|
@@ -150,6 +194,11 @@ async function healDriftedOrgToken(creds, log7 = () => {
|
|
|
150
194
|
return creds;
|
|
151
195
|
}
|
|
152
196
|
}
|
|
197
|
+
async function listWorkspaces(token, apiUrl = DEFAULT_API_URL, orgId) {
|
|
198
|
+
const raw = await apiGet("/workspaces", token, apiUrl, orgId);
|
|
199
|
+
const data = raw.data ?? raw;
|
|
200
|
+
return Array.isArray(data) ? data : [];
|
|
201
|
+
}
|
|
153
202
|
|
|
154
203
|
// dist/src/config.js
|
|
155
204
|
import { readFileSync as readFileSync3, existsSync } from "node:fs";
|
package/hermes/bundle/capture.js
CHANGED
|
@@ -1845,7 +1845,7 @@ Format: **entity** (type) \u2014 what was done with it, its current state>
|
|
|
1845
1845
|
<Anything unresolved, blocked, or explicitly deferred>
|
|
1846
1846
|
|
|
1847
1847
|
## Next Steps
|
|
1848
|
-
<
|
|
1848
|
+
<Decide in two steps. STEP 1 \u2014 is the work this session set out to do actually finished? If it ended mid-task \u2014 a feature only half-implemented, a build or test still failing, a fix written but not yet verified, a plan agreed but not executed, a blocker hit and unresolved, or an explicit "still need to.../next I'll..." left hanging \u2014 then it is NOT finished and you MUST write a single concrete imperative line naming the unfinished work (e.g. "Finish wiring the uint32 class_label scan binding and run its test"). The session's LAST messages are the strongest signal: if they describe or show work still in progress or something left to do, that IS the next step \u2014 never suppress a genuinely unfinished task, and do not demand "substantial consequences" for it. STEP 2 \u2014 if the core work IS finished, default to exactly: none and do not invent a follow-up to fill the section. Write none when the work reached a natural stopping point, only trivial/obvious/optional polish or cleanup remains, the "next step" would just be open-ended exploration, or the only thing left is administrative wrap-up (committing, pushing, opening/merging a PR, deploying, monitoring CI \u2014 treat ALL such wrap-up as ALREADY DONE). The sole exception that still warrants a next step on otherwise-finished work is a separate, important, non-obvious item a returning engineer would NOT realize on their own and would be materially harmed by missing.>
|
|
1849
1849
|
|
|
1850
1850
|
IMPORTANT: Be exhaustive. Extract EVERY entity, decision, and fact.
|
|
1851
1851
|
PRIVACY: Never include absolute filesystem paths in the summary.
|
|
@@ -267,7 +267,7 @@ Format: **entity** (type) \u2014 what was done with it, its current state>
|
|
|
267
267
|
<Anything unresolved, blocked, or explicitly deferred>
|
|
268
268
|
|
|
269
269
|
## Next Steps
|
|
270
|
-
<
|
|
270
|
+
<Decide in two steps. STEP 1 \u2014 is the work this session set out to do actually finished? If it ended mid-task \u2014 a feature only half-implemented, a build or test still failing, a fix written but not yet verified, a plan agreed but not executed, a blocker hit and unresolved, or an explicit "still need to.../next I'll..." left hanging \u2014 then it is NOT finished and you MUST write a single concrete imperative line naming the unfinished work (e.g. "Finish wiring the uint32 class_label scan binding and run its test"). The session's LAST messages are the strongest signal: if they describe or show work still in progress or something left to do, that IS the next step \u2014 never suppress a genuinely unfinished task, and do not demand "substantial consequences" for it. STEP 2 \u2014 if the core work IS finished, default to exactly: none and do not invent a follow-up to fill the section. Write none when the work reached a natural stopping point, only trivial/obvious/optional polish or cleanup remains, the "next step" would just be open-ended exploration, or the only thing left is administrative wrap-up (committing, pushing, opening/merging a PR, deploying, monitoring CI \u2014 treat ALL such wrap-up as ALREADY DONE). The sole exception that still warrants a next step on otherwise-finished work is a separate, important, non-obvious item a returning engineer would NOT realize on their own and would be materially harmed by missing.>
|
|
271
271
|
|
|
272
272
|
IMPORTANT: Be exhaustive. Extract EVERY entity, decision, and fact.
|
|
273
273
|
PRIVACY: Never include absolute filesystem paths in the summary.
|
|
@@ -110,6 +110,19 @@ function decodeJwtPayload(token) {
|
|
|
110
110
|
return null;
|
|
111
111
|
}
|
|
112
112
|
}
|
|
113
|
+
async function apiGet(path, token, apiUrl, orgId) {
|
|
114
|
+
const headers = {
|
|
115
|
+
Authorization: `Bearer ${token}`,
|
|
116
|
+
"Content-Type": "application/json",
|
|
117
|
+
...deeplakeClientHeader()
|
|
118
|
+
};
|
|
119
|
+
if (orgId)
|
|
120
|
+
headers["X-Activeloop-Org-Id"] = orgId;
|
|
121
|
+
const resp = await fetch(`${apiUrl}${path}`, { headers });
|
|
122
|
+
if (!resp.ok)
|
|
123
|
+
throw new Error(`API ${resp.status}: ${await resp.text().catch(() => "")}`);
|
|
124
|
+
return resp.json();
|
|
125
|
+
}
|
|
113
126
|
async function apiPost(path, body, token, apiUrl, orgId) {
|
|
114
127
|
const headers = {
|
|
115
128
|
Authorization: `Bearer ${token}`,
|
|
@@ -123,6 +136,10 @@ async function apiPost(path, body, token, apiUrl, orgId) {
|
|
|
123
136
|
throw new Error(`API ${resp.status}: ${await resp.text().catch(() => "")}`);
|
|
124
137
|
return resp.json();
|
|
125
138
|
}
|
|
139
|
+
async function listOrgs(token, apiUrl = DEFAULT_API_URL) {
|
|
140
|
+
const data = await apiGet("/organizations", token, apiUrl);
|
|
141
|
+
return Array.isArray(data) ? data : [];
|
|
142
|
+
}
|
|
126
143
|
async function healDriftedOrgToken(creds, log7 = () => {
|
|
127
144
|
}) {
|
|
128
145
|
if (!creds.token || !creds.orgId)
|
|
@@ -141,6 +158,33 @@ async function healDriftedOrgToken(creds, log7 = () => {
|
|
|
141
158
|
organization_id: creds.orgId
|
|
142
159
|
}, creds.token, apiUrl);
|
|
143
160
|
const healed = { ...creds, token: tokenData.token.token };
|
|
161
|
+
try {
|
|
162
|
+
const orgs = await listOrgs(healed.token, apiUrl);
|
|
163
|
+
const matchedOrg = orgs.find((o) => o.id === creds.orgId);
|
|
164
|
+
if (matchedOrg && matchedOrg.name !== creds.orgName) {
|
|
165
|
+
log7(`orgName realigned: ${creds.orgName ?? "(unset)"} -> ${matchedOrg.name}`);
|
|
166
|
+
healed.orgName = matchedOrg.name;
|
|
167
|
+
}
|
|
168
|
+
} catch (e) {
|
|
169
|
+
log7(`orgName realign skipped: ${e.message}`);
|
|
170
|
+
}
|
|
171
|
+
const currentWs = creds.workspaceId ?? "default";
|
|
172
|
+
if (currentWs !== "default") {
|
|
173
|
+
try {
|
|
174
|
+
const wsList = await listWorkspaces(healed.token, apiUrl, creds.orgId);
|
|
175
|
+
const lcWs = currentWs.toLowerCase();
|
|
176
|
+
const wsMatch = wsList.find((w) => w.id === currentWs || w.name && w.name.toLowerCase() === lcWs);
|
|
177
|
+
if (!wsMatch) {
|
|
178
|
+
log7(`workspace '${currentWs}' not in org ${creds.orgId} \u2014 reset to default`);
|
|
179
|
+
healed.workspaceId = "default";
|
|
180
|
+
} else if (wsMatch.id !== currentWs) {
|
|
181
|
+
log7(`workspace '${currentWs}' resolved to id '${wsMatch.id}'`);
|
|
182
|
+
healed.workspaceId = wsMatch.id;
|
|
183
|
+
}
|
|
184
|
+
} catch (e) {
|
|
185
|
+
log7(`workspace realign skipped: ${e.message}`);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
144
188
|
saveCredentials(healed);
|
|
145
189
|
log7(`token re-minted for org=${creds.orgId}`);
|
|
146
190
|
return healed;
|
|
@@ -149,6 +193,11 @@ async function healDriftedOrgToken(creds, log7 = () => {
|
|
|
149
193
|
return creds;
|
|
150
194
|
}
|
|
151
195
|
}
|
|
196
|
+
async function listWorkspaces(token, apiUrl = DEFAULT_API_URL, orgId) {
|
|
197
|
+
const raw = await apiGet("/workspaces", token, apiUrl, orgId);
|
|
198
|
+
const data = raw.data ?? raw;
|
|
199
|
+
return Array.isArray(data) ? data : [];
|
|
200
|
+
}
|
|
152
201
|
|
|
153
202
|
// dist/src/config.js
|
|
154
203
|
import { readFileSync as readFileSync3, existsSync } from "node:fs";
|
package/openclaw/dist/index.js
CHANGED
|
@@ -148,6 +148,33 @@ async function healDriftedOrgToken(creds, log4 = () => {
|
|
|
148
148
|
organization_id: creds.orgId
|
|
149
149
|
}, creds.token, apiUrl);
|
|
150
150
|
const healed = { ...creds, token: tokenData.token.token };
|
|
151
|
+
try {
|
|
152
|
+
const orgs = await listOrgs(healed.token, apiUrl);
|
|
153
|
+
const matchedOrg = orgs.find((o) => o.id === creds.orgId);
|
|
154
|
+
if (matchedOrg && matchedOrg.name !== creds.orgName) {
|
|
155
|
+
log4(`orgName realigned: ${creds.orgName ?? "(unset)"} -> ${matchedOrg.name}`);
|
|
156
|
+
healed.orgName = matchedOrg.name;
|
|
157
|
+
}
|
|
158
|
+
} catch (e) {
|
|
159
|
+
log4(`orgName realign skipped: ${e.message}`);
|
|
160
|
+
}
|
|
161
|
+
const currentWs = creds.workspaceId ?? "default";
|
|
162
|
+
if (currentWs !== "default") {
|
|
163
|
+
try {
|
|
164
|
+
const wsList = await listWorkspaces(healed.token, apiUrl, creds.orgId);
|
|
165
|
+
const lcWs = currentWs.toLowerCase();
|
|
166
|
+
const wsMatch = wsList.find((w) => w.id === currentWs || w.name && w.name.toLowerCase() === lcWs);
|
|
167
|
+
if (!wsMatch) {
|
|
168
|
+
log4(`workspace '${currentWs}' not in org ${creds.orgId} \u2014 reset to default`);
|
|
169
|
+
healed.workspaceId = "default";
|
|
170
|
+
} else if (wsMatch.id !== currentWs) {
|
|
171
|
+
log4(`workspace '${currentWs}' resolved to id '${wsMatch.id}'`);
|
|
172
|
+
healed.workspaceId = wsMatch.id;
|
|
173
|
+
}
|
|
174
|
+
} catch (e) {
|
|
175
|
+
log4(`workspace realign skipped: ${e.message}`);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
151
178
|
saveCredentials(healed);
|
|
152
179
|
log4(`token re-minted for org=${creds.orgId}`);
|
|
153
180
|
return healed;
|
|
@@ -1801,7 +1828,7 @@ function extractLatestVersion(body) {
|
|
|
1801
1828
|
return typeof v === "string" && v.length > 0 ? v : null;
|
|
1802
1829
|
}
|
|
1803
1830
|
function getInstalledVersion() {
|
|
1804
|
-
return "0.7.
|
|
1831
|
+
return "0.7.76".length > 0 ? "0.7.76" : null;
|
|
1805
1832
|
}
|
|
1806
1833
|
function isNewer(latest, current) {
|
|
1807
1834
|
const parse = (v) => v.replace(/-.*$/, "").split(".").map(Number);
|
package/openclaw/package.json
CHANGED
package/package.json
CHANGED
|
@@ -602,7 +602,7 @@ Format: **entity** (type) — what was done with it, its current state>
|
|
|
602
602
|
<Anything unresolved, blocked, or explicitly deferred>
|
|
603
603
|
|
|
604
604
|
## Next Steps
|
|
605
|
-
<
|
|
605
|
+
<Decide in two steps. STEP 1 — is the work this session set out to do actually finished? If it ended mid-task — a feature only half-implemented, a build or test still failing, a fix written but not yet verified, a plan agreed but not executed, a blocker hit and unresolved, or an explicit "still need to.../next I'll..." left hanging — then it is NOT finished and you MUST write a single concrete imperative line naming the unfinished work (e.g. "Finish wiring the uint32 class_label scan binding and run its test"). The session's LAST messages are the strongest signal: if they describe or show work still in progress or something left to do, that IS the next step — never suppress a genuinely unfinished task, and do not demand "substantial consequences" for it. STEP 2 — if the core work IS finished, default to exactly: none and do not invent a follow-up to fill the section. Write none when the work reached a natural stopping point, only trivial/obvious/optional polish or cleanup remains, the "next step" would just be open-ended exploration, or the only thing left is administrative wrap-up (committing, pushing, opening/merging a PR, deploying, monitoring CI — treat ALL such wrap-up as ALREADY DONE). The sole exception that still warrants a next step on otherwise-finished work is a separate, important, non-obvious item a returning engineer would NOT realize on their own and would be materially harmed by missing.>
|
|
606
606
|
|
|
607
607
|
IMPORTANT: Be exhaustive. Extract EVERY entity, decision, and fact.
|
|
608
608
|
PRIVACY: Never include absolute filesystem paths in the summary.
|