@tokensmind/agent-network 0.1.0 → 0.1.3

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.
Files changed (62) hide show
  1. package/README.md +81 -7
  2. package/openclaw.plugin.json +2 -2
  3. package/package.json +18 -8
  4. package/skills/tokensmind-agent-network/SKILL.md +145 -0
  5. package/skills/tokensmind-agent-network/package.json +4 -0
  6. package/skills/{tokensmind-agent-network-runtime → tokensmind-agent-network}/scripts/action_support.py +3 -1
  7. package/skills/{tokensmind-agent-network-runtime → tokensmind-agent-network}/scripts/agent_network_runtime.py +61 -9
  8. package/skills/{tokensmind-agent-network-runtime → tokensmind-agent-network}/scripts/lib/action-executor.js +12 -1
  9. package/skills/{tokensmind-agent-network-runtime → tokensmind-agent-network}/scripts/lib/action-validation.js +5 -0
  10. package/skills/tokensmind-agent-network/scripts/lib/agent-actions.js +91 -0
  11. package/skills/{tokensmind-agent-network-runtime → tokensmind-agent-network}/scripts/lib/api-client.js +14 -2
  12. package/skills/{tokensmind-agent-network-runtime → tokensmind-agent-network}/scripts/lib/contact-action.js +1 -1
  13. package/skills/tokensmind-agent-network/scripts/lib/memory-actions.js +112 -0
  14. package/skills/{tokensmind-agent-network-runtime → tokensmind-agent-network}/scripts/lib/runtime/connector.js +8 -19
  15. package/skills/{tokensmind-agent-network-runtime → tokensmind-agent-network}/scripts/lib/runtime/credentialStore.js +60 -11
  16. package/skills/{tokensmind-agent-network-runtime → tokensmind-agent-network}/scripts/lib/runtime/requestPolicy.js +0 -11
  17. package/skills/tokensmind-agent-network/scripts/lib/runtime/systemCredentialStore.js +245 -0
  18. package/skills/tokensmind-agent-network/scripts/lib/runtime/systemCredentialSupport.js +71 -0
  19. package/skills/tokensmind-agent-network/scripts/memory_actions.py +131 -0
  20. package/skills/{tokensmind-agent-network-runtime → tokensmind-agent-network}/scripts/python_runtime/connector.py +8 -8
  21. package/skills/{tokensmind-agent-network-runtime → tokensmind-agent-network}/scripts/python_runtime/credential_store.py +56 -12
  22. package/skills/{tokensmind-agent-network-runtime → tokensmind-agent-network}/scripts/python_runtime/request_policy.py +1 -13
  23. package/skills/tokensmind-agent-network/scripts/python_runtime/system_credential_store.py +250 -0
  24. package/src/action-executor.js +12 -1
  25. package/src/action-validation.js +5 -0
  26. package/src/agent-actions.js +53 -6
  27. package/src/api-client.js +14 -2
  28. package/src/contact-action.js +1 -1
  29. package/src/index.js +4 -2
  30. package/src/memory-actions.js +112 -0
  31. package/src/runtime/connector.js +8 -19
  32. package/src/runtime/credentialStore.js +60 -11
  33. package/src/runtime/requestPolicy.js +0 -11
  34. package/src/runtime/systemCredentialStore.js +143 -74
  35. package/src/runtime/systemCredentialSupport.js +71 -0
  36. package/skills/tokensmind-agent-network-runtime/SKILL.md +0 -55
  37. package/skills/tokensmind-agent-network-runtime/scripts/lib/agent-actions.js +0 -44
  38. package/skills/tokensmind-agent-network-runtime/scripts/lib/runtime/systemCredentialStore.js +0 -176
  39. package/skills/tokensmind-agent-network-runtime/scripts/python_runtime/system_credential_store.py +0 -143
  40. /package/skills/{tokensmind-agent-network-runtime → tokensmind-agent-network}/scripts/action_executor.py +0 -0
  41. /package/skills/{tokensmind-agent-network-runtime → tokensmind-agent-network}/scripts/action_validation.py +0 -0
  42. /package/skills/{tokensmind-agent-network-runtime → tokensmind-agent-network}/scripts/agent-network-runtime.mjs +0 -0
  43. /package/skills/{tokensmind-agent-network-runtime → tokensmind-agent-network}/scripts/governance_actions.py +0 -0
  44. /package/skills/{tokensmind-agent-network-runtime → tokensmind-agent-network}/scripts/lib/action-context.js +0 -0
  45. /package/skills/{tokensmind-agent-network-runtime → tokensmind-agent-network}/scripts/lib/action-errors.js +0 -0
  46. /package/skills/{tokensmind-agent-network-runtime → tokensmind-agent-network}/scripts/lib/governance-actions.js +0 -0
  47. /package/skills/{tokensmind-agent-network-runtime → tokensmind-agent-network}/scripts/lib/messaging-actions.js +0 -0
  48. /package/skills/{tokensmind-agent-network-runtime → tokensmind-agent-network}/scripts/lib/runtime/browser.js +0 -0
  49. /package/skills/{tokensmind-agent-network-runtime → tokensmind-agent-network}/scripts/lib/runtime/constants.js +0 -0
  50. /package/skills/{tokensmind-agent-network-runtime → tokensmind-agent-network}/scripts/lib/runtime/crypto.js +0 -0
  51. /package/skills/{tokensmind-agent-network-runtime → tokensmind-agent-network}/scripts/lib/runtime/deviceAuthorization.js +0 -0
  52. /package/skills/{tokensmind-agent-network-runtime → tokensmind-agent-network}/scripts/lib/runtime/httpClient.js +0 -0
  53. /package/skills/{tokensmind-agent-network-runtime → tokensmind-agent-network}/scripts/lib/runtime/portableStore.js +0 -0
  54. /package/skills/{tokensmind-agent-network-runtime → tokensmind-agent-network}/scripts/lib/workflow-store.js +0 -0
  55. /package/skills/{tokensmind-agent-network-runtime → tokensmind-agent-network}/scripts/python_runtime/__init__.py +0 -0
  56. /package/skills/{tokensmind-agent-network-runtime → tokensmind-agent-network}/scripts/python_runtime/browser.py +0 -0
  57. /package/skills/{tokensmind-agent-network-runtime → tokensmind-agent-network}/scripts/python_runtime/constants.py +0 -0
  58. /package/skills/{tokensmind-agent-network-runtime → tokensmind-agent-network}/scripts/python_runtime/crypto.py +0 -0
  59. /package/skills/{tokensmind-agent-network-runtime → tokensmind-agent-network}/scripts/python_runtime/device_authorization.py +0 -0
  60. /package/skills/{tokensmind-agent-network-runtime → tokensmind-agent-network}/scripts/python_runtime/errors.py +0 -0
  61. /package/skills/{tokensmind-agent-network-runtime → tokensmind-agent-network}/scripts/python_runtime/http_client.py +0 -0
  62. /package/skills/{tokensmind-agent-network-runtime → tokensmind-agent-network}/scripts/python_runtime/portable_store.py +0 -0
@@ -1,12 +1,28 @@
1
1
  import { actionFailure, requireInput } from './action-errors.js';
2
- import { optionalLimit, text } from './action-validation.js';
2
+ import { text } from './action-validation.js';
3
+
4
+ function profileTags(value) {
5
+ if (value === undefined || value === null) return [];
6
+ if (!Array.isArray(value) || value.some((item) => typeof item !== 'string')) {
7
+ requireInput(['agent.tags'], 'agent.tags must be an array of strings.');
8
+ }
9
+ return value;
10
+ }
3
11
 
4
12
  export async function searchAgents(context) {
5
13
  const query = text(context.input.query);
6
- const limit = optionalLimit(context.input.limit);
7
- const params = new URLSearchParams({ limit: String(limit) });
8
- if (query) params.set('q', query);
9
- return context.get(`/agent-network-api/agents?${params}`);
14
+ if (!query) requireInput(['query']);
15
+ try {
16
+ return await context.get(`/agent-network-api/agents?q=${encodeURIComponent(query)}`);
17
+ } catch (error) {
18
+ const code = error?.code;
19
+ if (!['AGENT_REQUIRED', 'AGENT_PROFILE_REQUIRED'].includes(code)) throw error;
20
+ actionFailure(
21
+ code,
22
+ 'Create the account Agent profile with ensure_agent before searching.',
23
+ { nextOperation: 'ensure_agent' },
24
+ );
25
+ }
10
26
  }
11
27
 
12
28
  export async function getMyAgent(context) {
@@ -25,7 +41,21 @@ function profileInput(input) {
25
41
  const name = text(profile.name);
26
42
  const description = text(profile.description);
27
43
  if (!name || !description) requireInput(['agent.name', 'agent.description']);
28
- return { name, description };
44
+ return { name, description, tags: profileTags(profile.tags) };
45
+ }
46
+
47
+ function profileUpdateInput(input, existing) {
48
+ const profile = input.agent || input.profile || {};
49
+ const hasName = Object.hasOwn(profile, 'name');
50
+ const hasDescription = Object.hasOwn(profile, 'description');
51
+ const hasTags = Object.hasOwn(profile, 'tags');
52
+ if (!hasName && !hasDescription && !hasTags) {
53
+ requireInput(['agent.name', 'agent.description', 'agent.tags']);
54
+ }
55
+ const name = text(hasName ? profile.name : existing.name);
56
+ const description = text(hasDescription ? profile.description : existing.description);
57
+ if (!name || !description) requireInput(['agent.name', 'agent.description']);
58
+ return { name, description, tags: profileTags(hasTags ? profile.tags : existing.tags) };
29
59
  }
30
60
 
31
61
  export async function ensureAgent(context) {
@@ -42,3 +72,20 @@ export async function ensureAgent(context) {
42
72
  }
43
73
  return { agent: result.agent, created: true };
44
74
  }
75
+
76
+ export async function updateAgent(context) {
77
+ const existing = await getMyAgent(context);
78
+ if (!existing) {
79
+ actionFailure('AGENT_PROFILE_REQUIRED', 'Create the account Agent profile before updating it.');
80
+ }
81
+ const result = await context.mutate({
82
+ method: 'PATCH',
83
+ path: `/agent-network-api/agents/${encodeURIComponent(existing.id)}`,
84
+ body: profileUpdateInput(context.input, existing),
85
+ label: 'agent:update',
86
+ });
87
+ if (!result?.agent) {
88
+ actionFailure('AGENT_UPDATE_PROTOCOL_ERROR', 'Agent update returned no Agent.');
89
+ }
90
+ return { agent: result.agent, updated: true };
91
+ }
package/src/api-client.js CHANGED
@@ -12,7 +12,7 @@ const CLIENT_VERSION = '0.1.0';
12
12
 
13
13
  export class AuthorizationRequiredError extends Error {
14
14
  constructor(verificationUrl) {
15
- super('Complete Agent Network authorization in the browser, then retry the action.');
15
+ super('Default browser handoff failed; resume the pending action to continue polling.');
16
16
  this.name = 'AuthorizationRequiredError';
17
17
  this.status = 'authorization_required';
18
18
  this.verificationUrl = verificationUrl;
@@ -54,7 +54,19 @@ export function createActionApi(options = {}) {
54
54
  baseUrl, stateDir, platform, env, homeDir, hostname, browser, http, store, writeEvent,
55
55
  } = resolveOptions(options);
56
56
  const origin = normalizeBaseUrl(baseUrl);
57
- const resolvedStore = store || createCredentialStore({ stateDir, origin, platform, env, homeDir });
57
+ const resolvedStore = store || createCredentialStore({
58
+ stateDir,
59
+ origin,
60
+ platform,
61
+ env,
62
+ homeDir,
63
+ onFallback: ({ backend, directory, reason }) => writeEvent({
64
+ event: 'credential_store_fallback',
65
+ backend,
66
+ directory,
67
+ reason,
68
+ }),
69
+ });
58
70
  const workflowStore = createWorkflowStore({ stateDir, origin, platform, homeDir });
59
71
  const connector = createConnector({
60
72
  baseUrl: origin,
@@ -19,7 +19,7 @@ async function resolveTarget(context) {
19
19
  const name = text(target.name);
20
20
  if (!name) requireInput(['target.id or target.name']);
21
21
  const agents = await context.get(
22
- `/agent-network-api/agents?q=${encodeURIComponent(name)}&limit=20`,
22
+ `/agent-network-api/agents?q=${encodeURIComponent(name)}`,
23
23
  );
24
24
  if (!Array.isArray(agents) || agents.length === 0) {
25
25
  actionFailure('TARGET_AGENT_NOT_FOUND', `No Agent matched "${name}".`);
package/src/index.js CHANGED
@@ -12,9 +12,11 @@ const ACTION_SCHEMA = {
12
12
  operation: {
13
13
  type: 'string',
14
14
  enum: [
15
- 'abandon_action', 'search_agents', 'get_my_agent', 'ensure_agent', 'contact_agent',
15
+ 'abandon_action', 'search_agents', 'get_my_agent', 'ensure_agent', 'update_agent',
16
+ 'contact_agent',
16
17
  'list_inbox', 'get_conversation', 'reply', 'mark_read',
17
18
  'withdraw_message', 'block_agent', 'unblock_agent', 'report', 'appeal',
19
+ 'get_memory_settings', 'propose_memory', 'list_memories', 'delete_memory',
18
20
  ],
19
21
  },
20
22
  input: {
@@ -57,7 +59,7 @@ function getExecutor(config) {
57
59
  }
58
60
 
59
61
  export default defineToolPlugin({
60
- id: 'tokensmind-agent-network-runtime',
62
+ id: 'tokensmind-agent-network',
61
63
  name: 'TokensMind Agent Network Runtime',
62
64
  description: 'Run high-level Agent Network operations with private authorization.',
63
65
  configSchema: CONFIG_SCHEMA,
@@ -0,0 +1,112 @@
1
+ import { actionFailure, requireInput } from './action-errors.js';
2
+ import { getMyAgent } from './agent-actions.js';
3
+ import { isObject, optionalLimit, requiredId, requiredText, text } from './action-validation.js';
4
+
5
+ const MEMORY_KINDS = new Set(['agent_experience', 'matching_preference']);
6
+ const MEMORY_POLARITIES = new Set(['negative', 'positive']);
7
+ const MEMORY_SCOPES = new Set(['contextual', 'global']);
8
+ // platform_event 由服务端独占写入,客户端提交会被拒绝。
9
+ const MEMORY_SOURCES = new Set(['model_inferred', 'user_explicit']);
10
+ const MEMORY_STATUSES = new Set(['active', 'deleted', 'pending_review', 'rejected']);
11
+ const MAX_INFERRED_CONFIDENCE = 0.6;
12
+
13
+ function requireChoice(input, field, allowed) {
14
+ const value = text(input?.[field]).toLowerCase();
15
+ if (!allowed.has(value)) requireInput([field], `${field} has an unsupported value.`);
16
+ return value;
17
+ }
18
+
19
+ function optionalConfidence(value, sourceType) {
20
+ if (value === undefined || value === null || value === '') {
21
+ return sourceType === 'model_inferred' ? MAX_INFERRED_CONFIDENCE : 1;
22
+ }
23
+ const confidence = Number(value);
24
+ const inferredLimitExceeded = sourceType === 'model_inferred'
25
+ && confidence > MAX_INFERRED_CONFIDENCE;
26
+ if (!Number.isFinite(confidence) || confidence <= 0 || confidence > 1 || inferredLimitExceeded) {
27
+ requireInput(['confidence'], 'confidence must be above 0 and no more than 0.6 for inferred memory.');
28
+ }
29
+ return confidence;
30
+ }
31
+
32
+ async function ownedAgent(context) {
33
+ const agent = await getMyAgent(context);
34
+ if (!agent) actionFailure('AGENT_PROFILE_REQUIRED', 'Create the account Agent profile first.');
35
+ return agent;
36
+ }
37
+
38
+ function agentPath(agentId, suffix) {
39
+ return `/agent-network-api/agents/${encodeURIComponent(agentId)}/${suffix}`;
40
+ }
41
+
42
+ function optionalText(input, field) {
43
+ return Object.hasOwn(input, field) ? text(input[field]) || null : null;
44
+ }
45
+
46
+ function memoryBody(input) {
47
+ if (!isObject(input)) requireInput(['input']);
48
+ const sourceType = requireChoice(input, 'sourceType', MEMORY_SOURCES);
49
+ const scope = input.scope ? requireChoice(input, 'scope', MEMORY_SCOPES) : 'contextual';
50
+ const contextText = scope === 'global' ? '' : requiredText(input, 'contextText');
51
+ return {
52
+ clientMemoryId: requiredText(input, 'clientMemoryId'),
53
+ confidence: optionalConfidence(input.confidence, sourceType),
54
+ contextText,
55
+ conversationId: optionalText(input, 'conversationId'),
56
+ expiresAt: optionalText(input, 'expiresAt'),
57
+ kind: requireChoice(input, 'kind', MEMORY_KINDS),
58
+ polarity: requireChoice(input, 'polarity', MEMORY_POLARITIES),
59
+ requirementId: optionalText(input, 'requirementId'),
60
+ scope,
61
+ sourceType,
62
+ statement: requiredText(input, 'statement'),
63
+ targetAgentId: optionalText(input, 'targetAgentId'),
64
+ };
65
+ }
66
+
67
+ function listQuery(input) {
68
+ const params = new URLSearchParams({ limit: String(optionalLimit(input.limit)) });
69
+ if (input.offset !== undefined) {
70
+ const offset = Number(input.offset);
71
+ if (!Number.isInteger(offset) || offset < 0) requireInput(['offset']);
72
+ params.set('offset', String(offset));
73
+ }
74
+ if (input.status) params.set('status', requireChoice(input, 'status', MEMORY_STATUSES));
75
+ return params.toString();
76
+ }
77
+
78
+ export async function getMemorySettings(context) {
79
+ const agent = await ownedAgent(context);
80
+ return context.get(agentPath(agent.id, 'memory-settings'));
81
+ }
82
+
83
+ export async function proposeMemory(context) {
84
+ const body = memoryBody(context.input);
85
+ const agent = await ownedAgent(context);
86
+ const settings = await context.get(agentPath(agent.id, 'memory-settings'));
87
+ if (settings?.collectionEnabled !== true) {
88
+ actionFailure('MEMORY_COLLECTION_DISABLED', 'Memory collection is disabled for this Agent.');
89
+ }
90
+ return context.mutate({
91
+ method: 'POST',
92
+ path: agentPath(agent.id, 'memories'),
93
+ body,
94
+ label: 'memory:propose',
95
+ });
96
+ }
97
+
98
+ export async function listMemories(context) {
99
+ const query = listQuery(context.input);
100
+ const agent = await ownedAgent(context);
101
+ return context.get(`${agentPath(agent.id, 'memories')}?${query}`);
102
+ }
103
+
104
+ export async function deleteMemory(context) {
105
+ const memoryId = requiredId(context.input, 'memoryId');
106
+ const agent = await ownedAgent(context);
107
+ return context.mutate({
108
+ method: 'DELETE',
109
+ path: `${agentPath(agent.id, 'memories')}/${encodeURIComponent(memoryId)}`,
110
+ label: 'memory:delete',
111
+ });
112
+ }
@@ -8,7 +8,6 @@ import {
8
8
  } from './deviceAuthorization.js';
9
9
  import {
10
10
  buildBusinessUrl,
11
- isPublicDiscoveryRequest,
12
11
  validateBusinessRequest,
13
12
  } from './requestPolicy.js';
14
13
 
@@ -47,15 +46,6 @@ function assertActiveCredential(active) {
47
46
  return active;
48
47
  }
49
48
 
50
- function authorizationPending(verificationUrl) {
51
- const error = new Error(
52
- 'Complete Agent Network authorization in the browser, then retry the action.',
53
- );
54
- error.status = 'authorization_required';
55
- error.verificationUrl = verificationUrl;
56
- return error;
57
- }
58
-
59
49
  async function executeBusinessRequest({ operation, token, baseUrl, http, signal }) {
60
50
  return http.request({
61
51
  url: buildBusinessUrl(baseUrl, operation.path),
@@ -90,7 +80,6 @@ async function authorize({ operation, store, browser, baseUrl, http, client, sig
90
80
  pending = await createRemoteAuthorization({ pending, baseUrl, http, client, signal });
91
81
  await store.write('pending', pending);
92
82
  await browser.open(pending.authorization.verificationUrl);
93
- throw authorizationPending(pending.authorization.verificationUrl);
94
83
  }
95
84
  if (pending.phase === 'authorizing') {
96
85
  await waitForApproval({ pending, baseUrl, http, signal });
@@ -131,6 +120,11 @@ function isInvalidAgentCredential(error) {
131
120
  ].includes(error.code);
132
121
  }
133
122
 
123
+ function requiresAuthorization(error) {
124
+ return error instanceof AgentNetworkHttpError
125
+ && (error.status === 401 || isInvalidAgentCredential(error));
126
+ }
127
+
134
128
  async function executeAndFinalize({ pending, active, dependencies }) {
135
129
  assertActiveCredential(active);
136
130
  try {
@@ -144,7 +138,7 @@ async function executeAndFinalize({ pending, active, dependencies }) {
144
138
  } catch (error) {
145
139
  if (error instanceof AgentNetworkHttpError && error.status < 500 && error.status !== 429) {
146
140
  await dependencies.store.remove('pending');
147
- if (isInvalidAgentCredential(error)) await dependencies.store.remove('active');
141
+ if (requiresAuthorization(error)) await dependencies.store.remove('active');
148
142
  }
149
143
  throw error;
150
144
  }
@@ -170,7 +164,7 @@ export function createConnector({ store, browser, baseUrl, http, client }) {
170
164
  try {
171
165
  return await executeBusinessRequest({ operation, token: active.token, baseUrl, http, signal });
172
166
  } catch (error) {
173
- if (!isInvalidAgentCredential(error)) throw error;
167
+ if (!requiresAuthorization(error)) throw error;
174
168
  await store.remove('active');
175
169
  return authorizeAndExecute(operation, signal);
176
170
  }
@@ -181,15 +175,10 @@ export function createConnector({ store, browser, baseUrl, http, client }) {
181
175
  const normalized = validateBusinessRequest(params);
182
176
  const operation = { ...normalized, body: params.body };
183
177
  const reauthorize = params.reauthorize === true;
178
+
184
179
  const pending = await store.read('pending');
185
180
  const active = await store.read('active');
186
-
187
181
  if (pending) return resumePending(pending, operation, signal);
188
-
189
- if (isPublicDiscoveryRequest(operation) && !reauthorize) {
190
- return executeBusinessRequest({ operation, baseUrl, http, signal });
191
- }
192
-
193
182
  if (!active || reauthorize) return authorizeAndExecute(operation, signal);
194
183
  return executeWithActive(operation, active, signal);
195
184
  }
@@ -6,7 +6,10 @@ import {
6
6
  originNamespace,
7
7
  resolvePortableStateDir,
8
8
  } from './portableStore.js';
9
- import { resolveSystemCredentialStore } from './systemCredentialStore.js';
9
+ import {
10
+ resolveSystemCredentialStore,
11
+ SystemCredentialStoreError,
12
+ } from './systemCredentialStore.js';
10
13
 
11
14
  const RECORD_NAMES = Object.freeze(['instance', 'pending', 'active']);
12
15
 
@@ -122,6 +125,53 @@ function createFileStores({ directories, origin, platform, env, homeDir, fs, ran
122
125
  }));
123
126
  }
124
127
 
128
+ async function validateSystemRecords(systemStore) {
129
+ for (const name of RECORD_NAMES) await systemStore.read(name);
130
+ }
131
+
132
+ async function initializeStore({
133
+ systemStore, fallback, fallbackDirectory, legacyDirectories, storeOptions, onFallback,
134
+ }) {
135
+ const recordDirectory = path.join(
136
+ fallbackDirectory, originNamespace(storeOptions.origin),
137
+ );
138
+ const legacySources = createFileStores({
139
+ ...storeOptions, directories: legacyDirectories,
140
+ });
141
+ if (!systemStore) {
142
+ onFallback({
143
+ backend: null,
144
+ directory: recordDirectory,
145
+ reason: 'No supported system credential store is available',
146
+ });
147
+ await migrateCredentialStores({ target: fallback, sources: legacySources });
148
+ return fallback;
149
+ }
150
+ try {
151
+ if (typeof systemStore.verifyAvailability !== 'function') {
152
+ throw new SystemCredentialStoreError(
153
+ 'System credential store does not support availability verification',
154
+ );
155
+ }
156
+ await systemStore.verifyAvailability();
157
+ await validateSystemRecords(systemStore);
158
+ const sources = createFileStores({
159
+ ...storeOptions, directories: [fallbackDirectory, ...legacyDirectories],
160
+ });
161
+ await migrateCredentialStores({ target: systemStore, sources });
162
+ return systemStore;
163
+ } catch (error) {
164
+ if (!(error instanceof SystemCredentialStoreError)) throw error;
165
+ onFallback({
166
+ backend: systemStore.backend,
167
+ directory: recordDirectory,
168
+ reason: error.message,
169
+ });
170
+ await migrateCredentialStores({ target: fallback, sources: legacySources });
171
+ return fallback;
172
+ }
173
+ }
174
+
125
175
  export function createCredentialStore({
126
176
  stateDir,
127
177
  origin,
@@ -133,6 +183,7 @@ export function createCredentialStore({
133
183
  secureStore,
134
184
  resolveSecureStore = resolveSystemCredentialStore,
135
185
  run,
186
+ onFallback = () => {},
136
187
  } = {}) {
137
188
  if (stateDir) {
138
189
  return createPortableStore({ stateDir, origin, platform, env, homeDir, fs, randomId });
@@ -147,16 +198,14 @@ export function createCredentialStore({
147
198
  platform, namespace: originNamespace(origin), env, fs, run,
148
199
  })
149
200
  : secureStore;
150
- const target = systemStore || fallback;
151
- const sourceDirectories = [
152
- ...(systemStore ? [fallbackDirectory] : []),
153
- ...resolveLegacyStateDirs({ platform, env, homeDir }),
154
- ];
155
- const sources = createFileStores({
156
- directories: [...new Set(sourceDirectories)],
157
- origin, platform, env, homeDir, fs, randomId,
201
+ const legacyDirectories = resolveLegacyStateDirs({ platform, env, homeDir });
202
+ return initializeStore({
203
+ systemStore,
204
+ fallback,
205
+ fallbackDirectory,
206
+ legacyDirectories: [...new Set(legacyDirectories)],
207
+ storeOptions: { origin, platform, env, homeDir, fs, randomId },
208
+ onFallback,
158
209
  });
159
- await migrateCredentialStores({ target, sources });
160
- return target;
161
210
  });
162
211
  }
@@ -1,8 +1,6 @@
1
1
  import { INTERNAL_PATH_PATTERNS, MUTATION_METHODS } from './constants.js';
2
2
 
3
3
  const SUPPORTED_METHODS = new Set(['GET', 'POST', 'PATCH', 'DELETE']);
4
- const PUBLIC_AGENT_DIRECTORY_PATH = '/agent-network-api/agents';
5
-
6
4
  export function normalizeBaseUrl(value) {
7
5
  const url = new URL(value);
8
6
  if (!['http:', 'https:'].includes(url.protocol)) {
@@ -44,12 +42,3 @@ export function buildBusinessUrl(baseUrl, path) {
44
42
  }
45
43
  return url.toString();
46
44
  }
47
-
48
- export function isPublicDiscoveryRequest({ method, path }) {
49
- if (method !== 'GET') return false;
50
- const url = new URL(path, 'https://tokensmind.invalid');
51
- const mineRequested = [...url.searchParams.entries()]
52
- .some(([key, value]) => key === 'mine' && value === '1');
53
- return url.pathname === PUBLIC_AGENT_DIRECTORY_PATH
54
- && !mineRequested;
55
- }