@hashgraphonline/standards-agent-kit 0.2.162 → 0.2.165
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/README.md +68 -0
- package/dist/cjs/builders/inscriber/inscriber-builder.d.ts +2 -2
- package/dist/cjs/standards-agent-kit.cjs +1 -1
- package/dist/cjs/standards-agent-kit.cjs.map +1 -1
- package/dist/es/builders/inscriber/inscriber-builder.d.ts +2 -2
- package/dist/es/standards-agent-kit.es48.js +3 -7
- package/dist/es/standards-agent-kit.es48.js.map +1 -1
- package/dist/es/standards-agent-kit.es49.js +7 -3
- package/dist/es/standards-agent-kit.es49.js.map +1 -1
- package/dist/es/standards-agent-kit.es6.js +1 -1
- package/dist/es/standards-agent-kit.es7.js +1 -1
- package/dist/es/standards-agent-kit.es8.js +26 -47
- package/dist/es/standards-agent-kit.es8.js.map +1 -1
- package/dist/es/standards-agent-kit.es9.js +1 -1
- package/dist/umd/builders/inscriber/inscriber-builder.d.ts +2 -2
- package/dist/umd/standards-agent-kit.umd.js +1 -220
- package/dist/umd/standards-agent-kit.umd.js.map +1 -1
- package/package.json +36 -28
- package/src/builders/inscriber/inscriber-builder.ts +34 -59
- package/src/plugins/index.ts +1 -0
- package/src/plugins/registry-broker/RegistryBrokerClientProvider.ts +116 -0
- package/src/plugins/registry-broker/RegistryBrokerConversationStore.ts +46 -0
- package/src/plugins/registry-broker/RegistryBrokerOperationTool.ts +630 -0
- package/src/plugins/registry-broker/RegistryBrokerPlugin.ts +63 -0
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hashgraphonline/standards-agent-kit",
|
|
3
|
-
"version": "0.2.
|
|
4
|
-
"description": "A modular SDK for building on-chain autonomous agents using Hashgraph Online Standards, including HCS-10 for agent discovery and communication.",
|
|
3
|
+
"version": "0.2.165",
|
|
4
|
+
"description": "A modular SDK for building on-chain autonomous agents using Hashgraph Online Standards, including HCS-10 for agent discovery and communication. https://hol.org",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/cjs/standards-agent-kit.cjs",
|
|
7
7
|
"module": "./dist/es/standards-agent-kit.es.js",
|
|
@@ -21,6 +21,33 @@
|
|
|
21
21
|
"LICENSE",
|
|
22
22
|
"README.md"
|
|
23
23
|
],
|
|
24
|
+
"scripts": {
|
|
25
|
+
"clean": "rimraf dist",
|
|
26
|
+
"build:es": "BUILD_FORMAT=es vite build",
|
|
27
|
+
"build:cjs": "BUILD_FORMAT=cjs vite build",
|
|
28
|
+
"build:umd": "BUILD_FORMAT=umd vite build",
|
|
29
|
+
"build": "pnpm run clean && pnpm run build:es && pnpm run build:cjs && pnpm run build:umd",
|
|
30
|
+
"test": "jest",
|
|
31
|
+
"lint": "eslint . --ext .ts",
|
|
32
|
+
"lint:fix": "eslint . --ext .ts --fix",
|
|
33
|
+
"prepare": "pnpm run build",
|
|
34
|
+
"prepublishOnly": "pnpm run build",
|
|
35
|
+
"release": "pnpm publish --access public",
|
|
36
|
+
"release:canary": "pnpm run prepublishOnly && pnpm publish --tag canary --access public",
|
|
37
|
+
"version:canary": "pnpm version prerelease --preid canary --no-git-tag-version",
|
|
38
|
+
"publish:canary": "pnpm run version:canary && pnpm run release:canary",
|
|
39
|
+
"demo:cli": "tsx examples/cli-demo.ts",
|
|
40
|
+
"demo:interactive": "tsx examples/interactive-demo.ts",
|
|
41
|
+
"demo:langchain": "tsx examples/langchain-demo.ts",
|
|
42
|
+
"demo:plugin": "tsx examples/plugin-system-example.ts",
|
|
43
|
+
"demo:plugin:weather": "tsx examples/plugins/weather/index.ts",
|
|
44
|
+
"demo:plugin:defi": "tsx examples/plugins/defi/index.ts",
|
|
45
|
+
"demo:plugin:openconvai": "tsx examples/openconvai-plugin-example.ts",
|
|
46
|
+
"demo:inscription-quotes": "tsx examples/inscription-quote-demo.ts",
|
|
47
|
+
"standards-agent:start": "tsx examples/standards-expert/cli.ts -- start",
|
|
48
|
+
"standards-agent:process-docs": "tsx examples/standards-expert/cli.ts -- process-docs --all-repos",
|
|
49
|
+
"typecheck": "tsc --noEmit"
|
|
50
|
+
},
|
|
24
51
|
"keywords": [
|
|
25
52
|
"hedera",
|
|
26
53
|
"hcs10",
|
|
@@ -63,7 +90,7 @@
|
|
|
63
90
|
},
|
|
64
91
|
"dependencies": {
|
|
65
92
|
"@hashgraph/sdk": "^2.72.0",
|
|
66
|
-
"@hashgraphonline/standards-sdk": "^0.1.
|
|
93
|
+
"@hashgraphonline/standards-sdk": "^0.1.111",
|
|
67
94
|
"@kiloscribe/inscription-sdk": "^1.0.60",
|
|
68
95
|
"@langchain/community": "^0.3.5",
|
|
69
96
|
"@langchain/core": "^0.3.71",
|
|
@@ -102,29 +129,10 @@
|
|
|
102
129
|
"vite-plugin-node-polyfills": "^0.23.0",
|
|
103
130
|
"vite-plugin-string-replace": "^1.1.3"
|
|
104
131
|
},
|
|
105
|
-
"
|
|
106
|
-
|
|
107
|
-
"
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
"build": "pnpm run clean && pnpm run build:es && pnpm run build:cjs && pnpm run build:umd",
|
|
111
|
-
"test": "jest",
|
|
112
|
-
"lint": "eslint . --ext .ts",
|
|
113
|
-
"lint:fix": "eslint . --ext .ts --fix",
|
|
114
|
-
"release": "pnpm publish --access public",
|
|
115
|
-
"release:canary": "pnpm run prepublishOnly && pnpm publish --tag canary --access public",
|
|
116
|
-
"version:canary": "pnpm version prerelease --preid canary --no-git-tag-version",
|
|
117
|
-
"publish:canary": "pnpm run version:canary && pnpm run release:canary",
|
|
118
|
-
"demo:cli": "tsx examples/cli-demo.ts",
|
|
119
|
-
"demo:interactive": "tsx examples/interactive-demo.ts",
|
|
120
|
-
"demo:langchain": "tsx examples/langchain-demo.ts",
|
|
121
|
-
"demo:plugin": "tsx examples/plugin-system-example.ts",
|
|
122
|
-
"demo:plugin:weather": "tsx examples/plugins/weather/index.ts",
|
|
123
|
-
"demo:plugin:defi": "tsx examples/plugins/defi/index.ts",
|
|
124
|
-
"demo:plugin:openconvai": "tsx examples/openconvai-plugin-example.ts",
|
|
125
|
-
"demo:inscription-quotes": "tsx examples/inscription-quote-demo.ts",
|
|
126
|
-
"standards-agent:start": "tsx examples/standards-expert/cli.ts -- start",
|
|
127
|
-
"standards-agent:process-docs": "tsx examples/standards-expert/cli.ts -- process-docs --all-repos",
|
|
128
|
-
"typecheck": "tsc --noEmit"
|
|
132
|
+
"packageManager": "pnpm@10.11.1+sha512.e519b9f7639869dc8d5c3c5dfef73b3f091094b0a006d7317353c72b124e80e1afd429732e28705ad6bfa1ee879c1fce46c128ccebd3192101f43dd67c667912",
|
|
133
|
+
"pnpm": {
|
|
134
|
+
"overrides": {
|
|
135
|
+
"@hashgraph/sdk": "2.72.0"
|
|
136
|
+
}
|
|
129
137
|
}
|
|
130
|
-
}
|
|
138
|
+
}
|
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
inscribe,
|
|
5
5
|
inscribeWithSigner,
|
|
6
6
|
retrieveInscription,
|
|
7
|
+
getOrCreateSDK,
|
|
7
8
|
InscriptionInput,
|
|
8
9
|
InscriptionOptions,
|
|
9
10
|
InscriptionResponse,
|
|
@@ -13,10 +14,10 @@ import {
|
|
|
13
14
|
getTopicId,
|
|
14
15
|
Logger,
|
|
15
16
|
} from '@hashgraphonline/standards-sdk';
|
|
16
|
-
import {
|
|
17
|
+
import type {
|
|
17
18
|
InscriptionSDK,
|
|
18
|
-
|
|
19
|
-
|
|
19
|
+
InscriptionResult,
|
|
20
|
+
RegistrationProgressData,
|
|
20
21
|
} from '@kiloscribe/inscription-sdk';
|
|
21
22
|
import type { AgentOperationalMode } from 'hedera-agent-kit';
|
|
22
23
|
|
|
@@ -46,12 +47,7 @@ export interface CompletedInscriptionResponse {
|
|
|
46
47
|
/**
|
|
47
48
|
* Builder for Inscription operations
|
|
48
49
|
*/
|
|
49
|
-
type InscriptionSDKInstance =
|
|
50
|
-
type InscriptionSDKAuthParams = Parameters<
|
|
51
|
-
typeof InscriptionSDK.createWithAuth
|
|
52
|
-
>[0];
|
|
53
|
-
type ClientAuthConfig = Extract<InscriptionSDKAuthParams, { type: 'client' }>;
|
|
54
|
-
type ServerAuthConfig = Extract<InscriptionSDKAuthParams, { type: 'server' }>;
|
|
50
|
+
type InscriptionSDKInstance = InscriptionSDK;
|
|
55
51
|
|
|
56
52
|
export const toDashedTransactionId = (transactionId: string): string => {
|
|
57
53
|
if (transactionId.includes('-')) {
|
|
@@ -159,7 +155,7 @@ export class InscriberBuilder extends BaseServiceBuilder {
|
|
|
159
155
|
* Get or create Inscription SDK
|
|
160
156
|
*/
|
|
161
157
|
protected async getInscriptionSDK(
|
|
162
|
-
|
|
158
|
+
options: InscriptionOptions
|
|
163
159
|
): Promise<InscriptionSDKInstance | null> {
|
|
164
160
|
if (this.inscriptionSDK) {
|
|
165
161
|
return this.inscriptionSDK;
|
|
@@ -172,55 +168,37 @@ export class InscriberBuilder extends BaseServiceBuilder {
|
|
|
172
168
|
? 'mainnet'
|
|
173
169
|
: 'testnet';
|
|
174
170
|
const accountId = this.hederaKit.signer.getAccountId().toString();
|
|
171
|
+
const operatorKey = this.hederaKit.signer?.getOperatorPrivateKey();
|
|
172
|
+
const baseOptions: InscriptionOptions = {
|
|
173
|
+
...options,
|
|
174
|
+
network: options.network ?? networkType,
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
const apiKey = baseOptions.apiKey ?? (operatorKey ? undefined : 'public-access');
|
|
178
|
+
const effectiveOptions: InscriptionOptions = apiKey
|
|
179
|
+
? { ...baseOptions, apiKey }
|
|
180
|
+
: baseOptions;
|
|
181
|
+
|
|
182
|
+
const clientConfig = {
|
|
183
|
+
accountId,
|
|
184
|
+
privateKey: operatorKey?.toStringRaw() ?? apiKey ?? 'public-access',
|
|
185
|
+
network: networkType,
|
|
186
|
+
};
|
|
175
187
|
|
|
176
188
|
try {
|
|
177
|
-
this.
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
this.inscriptionSDK = await InscriptionSDK.createWithAuth({
|
|
184
|
-
type: 'server',
|
|
185
|
-
accountId,
|
|
186
|
-
privateKey:
|
|
187
|
-
privateKey.toStringRaw() as ServerAuthConfig['privateKey'],
|
|
188
|
-
network: networkType,
|
|
189
|
-
});
|
|
190
|
-
this.logger.info('Created InscriptionSDK via createWithAuth', {
|
|
191
|
-
network: networkType,
|
|
192
|
-
});
|
|
193
|
-
}
|
|
189
|
+
this.inscriptionSDK = await getOrCreateSDK(
|
|
190
|
+
clientConfig,
|
|
191
|
+
effectiveOptions,
|
|
192
|
+
this.inscriptionSDK
|
|
193
|
+
);
|
|
194
|
+
return this.inscriptionSDK;
|
|
194
195
|
} catch (error) {
|
|
195
|
-
this.logger.
|
|
196
|
+
this.logger.error('failed to setup sdk', {
|
|
197
|
+
error: error instanceof Error ? error.message : String(error),
|
|
198
|
+
});
|
|
196
199
|
this.inscriptionSDK = undefined;
|
|
200
|
+
return null;
|
|
197
201
|
}
|
|
198
|
-
|
|
199
|
-
if (!this.inscriptionSDK) {
|
|
200
|
-
try {
|
|
201
|
-
this.logger.info('Creating fallback InscriptionSDK instance', {
|
|
202
|
-
network: networkType,
|
|
203
|
-
});
|
|
204
|
-
this.inscriptionSDK = new InscriptionSDK({
|
|
205
|
-
apiKey: 'public-access',
|
|
206
|
-
network: networkType,
|
|
207
|
-
connectionMode: 'http',
|
|
208
|
-
});
|
|
209
|
-
this.logger.info('Created fallback InscriptionSDK instance', {
|
|
210
|
-
network: networkType,
|
|
211
|
-
});
|
|
212
|
-
return this.inscriptionSDK;
|
|
213
|
-
} catch (fallbackError) {
|
|
214
|
-
this.logger.error(
|
|
215
|
-
'Failed to create InscriptionSDK fallback instance',
|
|
216
|
-
fallbackError
|
|
217
|
-
);
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
this.logger.error('failed to setup sdk');
|
|
222
|
-
|
|
223
|
-
return null;
|
|
224
202
|
}
|
|
225
203
|
|
|
226
204
|
/**
|
|
@@ -410,6 +388,8 @@ export class InscriberBuilder extends BaseServiceBuilder {
|
|
|
410
388
|
network
|
|
411
389
|
);
|
|
412
390
|
const transactionId = exec?.transactionId || '';
|
|
391
|
+
const rawTransactionId = startResponse.tx_id || transactionId;
|
|
392
|
+
const canonicalTransactionId = toDashedTransactionId(rawTransactionId);
|
|
413
393
|
|
|
414
394
|
this.logger.info('inscribeAuto wallet execution', {
|
|
415
395
|
transactionId,
|
|
@@ -419,9 +399,6 @@ export class InscriberBuilder extends BaseServiceBuilder {
|
|
|
419
399
|
const shouldWait = options.quoteOnly
|
|
420
400
|
? false
|
|
421
401
|
: options.waitForConfirmation ?? true;
|
|
422
|
-
const canonicalTransactionId = toDashedTransactionId(
|
|
423
|
-
startResponse.tx_id || transactionId
|
|
424
|
-
);
|
|
425
402
|
if (shouldWait) {
|
|
426
403
|
const maxAttempts =
|
|
427
404
|
(options as { waitMaxAttempts?: number }).waitMaxAttempts ?? 60;
|
|
@@ -433,8 +410,6 @@ export class InscriberBuilder extends BaseServiceBuilder {
|
|
|
433
410
|
let retrieved: RetrievedInscriptionResult | null = null;
|
|
434
411
|
const sdk = await this.getInscriptionSDK(options);
|
|
435
412
|
|
|
436
|
-
console.log('got an SDK', sdk);
|
|
437
|
-
|
|
438
413
|
if (sdk) {
|
|
439
414
|
try {
|
|
440
415
|
retrieved = await sdk.waitForInscription(
|
package/src/plugins/index.ts
CHANGED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import {
|
|
2
|
+
RegistryBrokerClient,
|
|
3
|
+
type RegistryBrokerClientOptions,
|
|
4
|
+
type LedgerCredentialAuthOptions,
|
|
5
|
+
} from '@hashgraphonline/standards-sdk/services/registry-broker';
|
|
6
|
+
import type { GenericPluginContext } from '../PluginInterface';
|
|
7
|
+
|
|
8
|
+
export interface RegistryBrokerLedgerOptions
|
|
9
|
+
extends LedgerCredentialAuthOptions {
|
|
10
|
+
autoAuthenticate?: boolean;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface RegistryBrokerPluginConfiguration {
|
|
14
|
+
client?: RegistryBrokerClientOptions;
|
|
15
|
+
ledger?: RegistryBrokerLedgerOptions;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
type ClientFactory = (
|
|
19
|
+
options: RegistryBrokerClientOptions,
|
|
20
|
+
) => RegistryBrokerClient;
|
|
21
|
+
|
|
22
|
+
const env = (key: string): string | undefined =>
|
|
23
|
+
process.env[key]?.trim() || undefined;
|
|
24
|
+
|
|
25
|
+
export class RegistryBrokerClientProvider {
|
|
26
|
+
private clientPromise: Promise<RegistryBrokerClient> | null = null;
|
|
27
|
+
|
|
28
|
+
constructor(
|
|
29
|
+
private readonly config: RegistryBrokerPluginConfiguration | undefined,
|
|
30
|
+
private readonly logger: GenericPluginContext['logger'],
|
|
31
|
+
private readonly createClient: ClientFactory = options =>
|
|
32
|
+
new RegistryBrokerClient(options),
|
|
33
|
+
) {}
|
|
34
|
+
|
|
35
|
+
async getClient(): Promise<RegistryBrokerClient> {
|
|
36
|
+
if (!this.clientPromise) {
|
|
37
|
+
this.clientPromise = this.initialiseClient();
|
|
38
|
+
}
|
|
39
|
+
return this.clientPromise;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
private async initialiseClient(): Promise<RegistryBrokerClient> {
|
|
43
|
+
const options = this.buildClientOptions();
|
|
44
|
+
const client = this.createClient(options);
|
|
45
|
+
const ledgerConfig = this.resolveLedgerOptions();
|
|
46
|
+
if (ledgerConfig) {
|
|
47
|
+
const { autoAuthenticate, ...authOptions } = ledgerConfig;
|
|
48
|
+
if (autoAuthenticate === false) {
|
|
49
|
+
this.logger.info?.(
|
|
50
|
+
'[RegistryBrokerPlugin] Ledger authentication disabled via configuration.',
|
|
51
|
+
);
|
|
52
|
+
} else {
|
|
53
|
+
await client.authenticateWithLedgerCredentials(authOptions);
|
|
54
|
+
this.logger.info?.(
|
|
55
|
+
`[RegistryBrokerPlugin] Authenticated with ledger account ${authOptions.accountId}.`,
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
} else if (!options.apiKey) {
|
|
59
|
+
this.logger.warn?.(
|
|
60
|
+
'[RegistryBrokerPlugin] Neither REGISTRY_BROKER_API_KEY nor ledger credentials were provided. Paid endpoints will fail.',
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
return client;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
private buildClientOptions(): RegistryBrokerClientOptions {
|
|
67
|
+
const merged: RegistryBrokerClientOptions = {
|
|
68
|
+
...this.config?.client,
|
|
69
|
+
};
|
|
70
|
+
merged.baseUrl =
|
|
71
|
+
merged.baseUrl ?? env('REGISTRY_BROKER_BASE_URL') ?? merged.baseUrl;
|
|
72
|
+
merged.apiKey =
|
|
73
|
+
this.normalizeSecret(this.config?.client?.apiKey) ??
|
|
74
|
+
this.normalizeSecret(env('REGISTRY_BROKER_API_KEY')) ??
|
|
75
|
+
this.normalizeSecret(env('RB_API_KEY')) ??
|
|
76
|
+
merged.apiKey;
|
|
77
|
+
merged.ledgerApiKey =
|
|
78
|
+
this.normalizeSecret(this.config?.client?.ledgerApiKey) ??
|
|
79
|
+
this.normalizeSecret(env('REGISTRY_BROKER_LEDGER_KEY')) ??
|
|
80
|
+
merged.ledgerApiKey;
|
|
81
|
+
return merged;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
private normalizeSecret(value?: string): string | undefined {
|
|
85
|
+
if (!value) {
|
|
86
|
+
return undefined;
|
|
87
|
+
}
|
|
88
|
+
const trimmed = value.trim();
|
|
89
|
+
return trimmed.length > 0 ? trimmed : undefined;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
private resolveLedgerOptions(): RegistryBrokerLedgerOptions | undefined {
|
|
93
|
+
if (this.config?.ledger) {
|
|
94
|
+
return this.config.ledger;
|
|
95
|
+
}
|
|
96
|
+
const accountId =
|
|
97
|
+
env('REGISTRY_BROKER_LEDGER_ACCOUNT_ID') ?? env('HEDERA_ACCOUNT_ID');
|
|
98
|
+
const hederaPrivateKey =
|
|
99
|
+
env('REGISTRY_BROKER_LEDGER_PRIVATE_KEY') ?? env('HEDERA_PRIVATE_KEY');
|
|
100
|
+
const evmPrivateKey =
|
|
101
|
+
env('REGISTRY_BROKER_LEDGER_EVM_PRIVATE_KEY') ?? env('ETH_PK');
|
|
102
|
+
const network =
|
|
103
|
+
env('REGISTRY_BROKER_LEDGER_NETWORK') ??
|
|
104
|
+
env('HEDERA_NETWORK') ??
|
|
105
|
+
'hedera:testnet';
|
|
106
|
+
if (accountId && network && (hederaPrivateKey || evmPrivateKey)) {
|
|
107
|
+
return {
|
|
108
|
+
accountId,
|
|
109
|
+
network,
|
|
110
|
+
hederaPrivateKey,
|
|
111
|
+
evmPrivateKey,
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
return undefined;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
ChatConversationHandle,
|
|
3
|
+
ConversationMode,
|
|
4
|
+
SessionEncryptionSummary,
|
|
5
|
+
} from '@hashgraphonline/standards-sdk/services/registry-broker';
|
|
6
|
+
|
|
7
|
+
export interface StoredConversationHandle {
|
|
8
|
+
handleId: string;
|
|
9
|
+
sessionId: string;
|
|
10
|
+
mode: ConversationMode;
|
|
11
|
+
summary: SessionEncryptionSummary | null | undefined;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export class RegistryBrokerConversationStore {
|
|
15
|
+
private readonly handles = new Map<string, ChatConversationHandle>();
|
|
16
|
+
|
|
17
|
+
register(handle: ChatConversationHandle): StoredConversationHandle {
|
|
18
|
+
const handleId = this.createHandleId();
|
|
19
|
+
this.handles.set(handleId, handle);
|
|
20
|
+
return {
|
|
21
|
+
handleId,
|
|
22
|
+
sessionId: handle.sessionId,
|
|
23
|
+
mode: handle.mode,
|
|
24
|
+
summary: handle.summary ?? null,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
get(handleId: string): ChatConversationHandle {
|
|
29
|
+
const handle = this.handles.get(handleId);
|
|
30
|
+
if (!handle) {
|
|
31
|
+
throw new Error(`Conversation handle not found: ${handleId}`);
|
|
32
|
+
}
|
|
33
|
+
return handle;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
release(handleId: string): boolean {
|
|
37
|
+
return this.handles.delete(handleId);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
private createHandleId(): string {
|
|
41
|
+
if (typeof globalThis.crypto?.randomUUID === 'function') {
|
|
42
|
+
return globalThis.crypto.randomUUID();
|
|
43
|
+
}
|
|
44
|
+
return `${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}`;
|
|
45
|
+
}
|
|
46
|
+
}
|