@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.
@@ -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.74"
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.74",
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": "c36c84a01eeb6ebac5211c6ce485283977e484d1"
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.74",
4
+ "version": "0.7.76",
5
5
  "author": {
6
6
  "name": "Activeloop",
7
7
  "url": "https://deeplake.ai"
@@ -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
- <Default to writing exactly: none. When in any doubt at all, write none. Do NOT assume any base rate \u2014 not that next steps are usually warranted, nor that they usually are not; the right frequency depends entirely on the work and varies by session and use case. Judge THIS session purely on the gate below, never on how often the section "should" be filled. The bar is deliberately EXTREME: name a next step ONLY when failing to surface it would cause the project to MISS SOMETHING IMPORTANT WITH SUBSTANTIAL CONSEQUENCES \u2014 work silently lost, a known bug or regression shipping to users, data or state left corrupted/unsafe, a security or data-integrity hole left open, or a critical blocker/decision that a returning engineer would NOT rediscover on their own and would be materially harmed by not knowing. Before you write anything other than none, apply this gate: state to yourself the specific, concrete, substantial bad outcome that follows if the user NEVER sees this line. If you cannot name a concrete bad outcome \u2014 or a competent engineer would simply re-derive the work from the code, tests, comments, or git state \u2014 write none. A next step is NOT: a nice-to-have, a polish or cleanup item, a "could also" / "consider", the obvious natural continuation of the task, an open-ended exploration, a trivial or mechanical follow-up, or any administrative wrap-up (committing, pushing, opening/merging a PR, deploying, monitoring CI \u2014 treat ALL such wrap-up as ALREADY DONE). It is a flag raised solely because real, describable harm follows from silence. When (rarely) the gate is genuinely passed, write a single concrete imperative line that names the substantive work AND makes the stakes obvious (e.g. "Fix the uint32 class_label scan binding \u2014 reads silently return wrong values until corrected"). Administrative actions qualify ONLY when the session's core purpose itself was that release/ops task.>
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() {
@@ -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
- <Default to writing exactly: none. When in any doubt at all, write none. Do NOT assume any base rate \u2014 not that next steps are usually warranted, nor that they usually are not; the right frequency depends entirely on the work and varies by session and use case. Judge THIS session purely on the gate below, never on how often the section "should" be filled. The bar is deliberately EXTREME: name a next step ONLY when failing to surface it would cause the project to MISS SOMETHING IMPORTANT WITH SUBSTANTIAL CONSEQUENCES \u2014 work silently lost, a known bug or regression shipping to users, data or state left corrupted/unsafe, a security or data-integrity hole left open, or a critical blocker/decision that a returning engineer would NOT rediscover on their own and would be materially harmed by not knowing. Before you write anything other than none, apply this gate: state to yourself the specific, concrete, substantial bad outcome that follows if the user NEVER sees this line. If you cannot name a concrete bad outcome \u2014 or a competent engineer would simply re-derive the work from the code, tests, comments, or git state \u2014 write none. A next step is NOT: a nice-to-have, a polish or cleanup item, a "could also" / "consider", the obvious natural continuation of the task, an open-ended exploration, a trivial or mechanical follow-up, or any administrative wrap-up (committing, pushing, opening/merging a PR, deploying, monitoring CI \u2014 treat ALL such wrap-up as ALREADY DONE). It is a flag raised solely because real, describable harm follows from silence. When (rarely) the gate is genuinely passed, write a single concrete imperative line that names the substantive work AND makes the stakes obvious (e.g. "Fix the uint32 class_label scan binding \u2014 reads silently return wrong values until corrected"). Administrative actions qualify ONLY when the session's core purpose itself was that release/ops task.>
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.
@@ -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
- <Default to writing exactly: none. When in any doubt at all, write none. Do NOT assume any base rate \u2014 not that next steps are usually warranted, nor that they usually are not; the right frequency depends entirely on the work and varies by session and use case. Judge THIS session purely on the gate below, never on how often the section "should" be filled. The bar is deliberately EXTREME: name a next step ONLY when failing to surface it would cause the project to MISS SOMETHING IMPORTANT WITH SUBSTANTIAL CONSEQUENCES \u2014 work silently lost, a known bug or regression shipping to users, data or state left corrupted/unsafe, a security or data-integrity hole left open, or a critical blocker/decision that a returning engineer would NOT rediscover on their own and would be materially harmed by not knowing. Before you write anything other than none, apply this gate: state to yourself the specific, concrete, substantial bad outcome that follows if the user NEVER sees this line. If you cannot name a concrete bad outcome \u2014 or a competent engineer would simply re-derive the work from the code, tests, comments, or git state \u2014 write none. A next step is NOT: a nice-to-have, a polish or cleanup item, a "could also" / "consider", the obvious natural continuation of the task, an open-ended exploration, a trivial or mechanical follow-up, or any administrative wrap-up (committing, pushing, opening/merging a PR, deploying, monitoring CI \u2014 treat ALL such wrap-up as ALREADY DONE). It is a flag raised solely because real, describable harm follows from silence. When (rarely) the gate is genuinely passed, write a single concrete imperative line that names the substantive work AND makes the stakes obvious (e.g. "Fix the uint32 class_label scan binding \u2014 reads silently return wrong values until corrected"). Administrative actions qualify ONLY when the session's core purpose itself was that release/ops task.>
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
- <Default to writing exactly: none. When in any doubt at all, write none. Do NOT assume any base rate \u2014 not that next steps are usually warranted, nor that they usually are not; the right frequency depends entirely on the work and varies by session and use case. Judge THIS session purely on the gate below, never on how often the section "should" be filled. The bar is deliberately EXTREME: name a next step ONLY when failing to surface it would cause the project to MISS SOMETHING IMPORTANT WITH SUBSTANTIAL CONSEQUENCES \u2014 work silently lost, a known bug or regression shipping to users, data or state left corrupted/unsafe, a security or data-integrity hole left open, or a critical blocker/decision that a returning engineer would NOT rediscover on their own and would be materially harmed by not knowing. Before you write anything other than none, apply this gate: state to yourself the specific, concrete, substantial bad outcome that follows if the user NEVER sees this line. If you cannot name a concrete bad outcome \u2014 or a competent engineer would simply re-derive the work from the code, tests, comments, or git state \u2014 write none. A next step is NOT: a nice-to-have, a polish or cleanup item, a "could also" / "consider", the obvious natural continuation of the task, an open-ended exploration, a trivial or mechanical follow-up, or any administrative wrap-up (committing, pushing, opening/merging a PR, deploying, monitoring CI \u2014 treat ALL such wrap-up as ALREADY DONE). It is a flag raised solely because real, describable harm follows from silence. When (rarely) the gate is genuinely passed, write a single concrete imperative line that names the substantive work AND makes the stakes obvious (e.g. "Fix the uint32 class_label scan binding \u2014 reads silently return wrong values until corrected"). Administrative actions qualify ONLY when the session's core purpose itself was that release/ops task.>
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";
@@ -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
- <Default to writing exactly: none. When in any doubt at all, write none. Do NOT assume any base rate \u2014 not that next steps are usually warranted, nor that they usually are not; the right frequency depends entirely on the work and varies by session and use case. Judge THIS session purely on the gate below, never on how often the section "should" be filled. The bar is deliberately EXTREME: name a next step ONLY when failing to surface it would cause the project to MISS SOMETHING IMPORTANT WITH SUBSTANTIAL CONSEQUENCES \u2014 work silently lost, a known bug or regression shipping to users, data or state left corrupted/unsafe, a security or data-integrity hole left open, or a critical blocker/decision that a returning engineer would NOT rediscover on their own and would be materially harmed by not knowing. Before you write anything other than none, apply this gate: state to yourself the specific, concrete, substantial bad outcome that follows if the user NEVER sees this line. If you cannot name a concrete bad outcome \u2014 or a competent engineer would simply re-derive the work from the code, tests, comments, or git state \u2014 write none. A next step is NOT: a nice-to-have, a polish or cleanup item, a "could also" / "consider", the obvious natural continuation of the task, an open-ended exploration, a trivial or mechanical follow-up, or any administrative wrap-up (committing, pushing, opening/merging a PR, deploying, monitoring CI \u2014 treat ALL such wrap-up as ALREADY DONE). It is a flag raised solely because real, describable harm follows from silence. When (rarely) the gate is genuinely passed, write a single concrete imperative line that names the substantive work AND makes the stakes obvious (e.g. "Fix the uint32 class_label scan binding \u2014 reads silently return wrong values until corrected"). Administrative actions qualify ONLY when the session's core purpose itself was that release/ops task.>
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
- <Default to writing exactly: none. When in any doubt at all, write none. Do NOT assume any base rate \u2014 not that next steps are usually warranted, nor that they usually are not; the right frequency depends entirely on the work and varies by session and use case. Judge THIS session purely on the gate below, never on how often the section "should" be filled. The bar is deliberately EXTREME: name a next step ONLY when failing to surface it would cause the project to MISS SOMETHING IMPORTANT WITH SUBSTANTIAL CONSEQUENCES \u2014 work silently lost, a known bug or regression shipping to users, data or state left corrupted/unsafe, a security or data-integrity hole left open, or a critical blocker/decision that a returning engineer would NOT rediscover on their own and would be materially harmed by not knowing. Before you write anything other than none, apply this gate: state to yourself the specific, concrete, substantial bad outcome that follows if the user NEVER sees this line. If you cannot name a concrete bad outcome \u2014 or a competent engineer would simply re-derive the work from the code, tests, comments, or git state \u2014 write none. A next step is NOT: a nice-to-have, a polish or cleanup item, a "could also" / "consider", the obvious natural continuation of the task, an open-ended exploration, a trivial or mechanical follow-up, or any administrative wrap-up (committing, pushing, opening/merging a PR, deploying, monitoring CI \u2014 treat ALL such wrap-up as ALREADY DONE). It is a flag raised solely because real, describable harm follows from silence. When (rarely) the gate is genuinely passed, write a single concrete imperative line that names the substantive work AND makes the stakes obvious (e.g. "Fix the uint32 class_label scan binding \u2014 reads silently return wrong values until corrected"). Administrative actions qualify ONLY when the session's core purpose itself was that release/ops task.>
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";
@@ -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.74".length > 0 ? "0.7.74" : null;
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);
@@ -54,5 +54,5 @@
54
54
  }
55
55
  }
56
56
  },
57
- "version": "0.7.74"
57
+ "version": "0.7.76"
58
58
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hivemind",
3
- "version": "0.7.74",
3
+ "version": "0.7.76",
4
4
  "type": "module",
5
5
  "description": "Hivemind — cloud-backed persistent shared memory for AI agents, powered by DeepLake",
6
6
  "license": "Apache-2.0",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@deeplake/hivemind",
3
- "version": "0.7.74",
3
+ "version": "0.7.76",
4
4
  "description": "Cloud-backed persistent shared memory for AI agents powered by Deeplake",
5
5
  "type": "module",
6
6
  "repository": {
@@ -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
- <Default to writing exactly: none. When in any doubt at all, write none. Do NOT assume any base rate not that next steps are usually warranted, nor that they usually are not; the right frequency depends entirely on the work and varies by session and use case. Judge THIS session purely on the gate below, never on how often the section "should" be filled. The bar is deliberately EXTREME: name a next step ONLY when failing to surface it would cause the project to MISS SOMETHING IMPORTANT WITH SUBSTANTIAL CONSEQUENCES work silently lost, a known bug or regression shipping to users, data or state left corrupted/unsafe, a security or data-integrity hole left open, or a critical blocker/decision that a returning engineer would NOT rediscover on their own and would be materially harmed by not knowing. Before you write anything other than none, apply this gate: state to yourself the specific, concrete, substantial bad outcome that follows if the user NEVER sees this line. If you cannot name a concrete bad outcome — or a competent engineer would simply re-derive the work from the code, tests, comments, or git state — write none. A next step is NOT: a nice-to-have, a polish or cleanup item, a "could also" / "consider", the obvious natural continuation of the task, an open-ended exploration, a trivial or mechanical follow-up, or any administrative wrap-up (committing, pushing, opening/merging a PR, deploying, monitoring CI — treat ALL such wrap-up as ALREADY DONE). It is a flag raised solely because real, describable harm follows from silence. When (rarely) the gate is genuinely passed, write a single concrete imperative line that names the substantive work AND makes the stakes obvious (e.g. "Fix the uint32 class_label scan binding reads silently return wrong values until corrected"). Administrative actions qualify ONLY when the session's core purpose itself was that release/ops task.>
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.