@honeybee-ai/incubator 1.0.0
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.
Potentially problematic release.
This version of @honeybee-ai/incubator might be problematic. Click here for more details.
- package/README.md +586 -0
- package/dashboard/dist/assets/index-CVqcfjV3.js +9 -0
- package/dashboard/dist/assets/index-CyFMIiFl.css +1 -0
- package/dashboard/dist/index.html +13 -0
- package/dist/agent/prompt.d.ts +70 -0
- package/dist/agent/prompt.js +165 -0
- package/dist/agent/prompt.js.map +1 -0
- package/dist/agent/providers.d.ts +6 -0
- package/dist/agent/providers.js +320 -0
- package/dist/agent/providers.js.map +1 -0
- package/dist/agent/runner.d.ts +22 -0
- package/dist/agent/runner.js +282 -0
- package/dist/agent/runner.js.map +1 -0
- package/dist/agent/test-helpers.d.ts +11 -0
- package/dist/agent/test-helpers.js +63 -0
- package/dist/agent/test-helpers.js.map +1 -0
- package/dist/agent/tools.d.ts +4 -0
- package/dist/agent/tools.js +545 -0
- package/dist/agent/tools.js.map +1 -0
- package/dist/agent/types.d.ts +54 -0
- package/dist/agent/types.js +2 -0
- package/dist/agent/types.js.map +1 -0
- package/dist/bus.d.ts +24 -0
- package/dist/bus.js +79 -0
- package/dist/bus.js.map +1 -0
- package/dist/guard.d.ts +44 -0
- package/dist/guard.js +178 -0
- package/dist/guard.js.map +1 -0
- package/dist/heartbeat.d.ts +41 -0
- package/dist/heartbeat.js +104 -0
- package/dist/heartbeat.js.map +1 -0
- package/dist/honeycomb.d.ts +49 -0
- package/dist/honeycomb.js +176 -0
- package/dist/honeycomb.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +371 -0
- package/dist/index.js.map +1 -0
- package/dist/integrations/config.d.ts +14 -0
- package/dist/integrations/config.js +48 -0
- package/dist/integrations/config.js.map +1 -0
- package/dist/integrations/index.d.ts +4 -0
- package/dist/integrations/index.js +4 -0
- package/dist/integrations/index.js.map +1 -0
- package/dist/integrations/loader.d.ts +8 -0
- package/dist/integrations/loader.js +27 -0
- package/dist/integrations/loader.js.map +1 -0
- package/dist/integrations/manager.d.ts +29 -0
- package/dist/integrations/manager.js +108 -0
- package/dist/integrations/manager.js.map +1 -0
- package/dist/namespaces.d.ts +25 -0
- package/dist/namespaces.js +84 -0
- package/dist/namespaces.js.map +1 -0
- package/dist/persistence.d.ts +7 -0
- package/dist/persistence.js +62 -0
- package/dist/persistence.js.map +1 -0
- package/dist/protocol/index.d.ts +5 -0
- package/dist/protocol/index.js +5 -0
- package/dist/protocol/index.js.map +1 -0
- package/dist/protocol/parser.d.ts +31 -0
- package/dist/protocol/parser.js +193 -0
- package/dist/protocol/parser.js.map +1 -0
- package/dist/protocol/renderer.d.ts +16 -0
- package/dist/protocol/renderer.js +193 -0
- package/dist/protocol/renderer.js.map +1 -0
- package/dist/protocol/schema.d.ts +341 -0
- package/dist/protocol/schema.js +285 -0
- package/dist/protocol/schema.js.map +1 -0
- package/dist/protocol/types.d.ts +144 -0
- package/dist/protocol/types.js +8 -0
- package/dist/protocol/types.js.map +1 -0
- package/dist/protocol/variables.d.ts +22 -0
- package/dist/protocol/variables.js +58 -0
- package/dist/protocol/variables.js.map +1 -0
- package/dist/rest.d.ts +3 -0
- package/dist/rest.js +794 -0
- package/dist/rest.js.map +1 -0
- package/dist/server.d.ts +17 -0
- package/dist/server.js +410 -0
- package/dist/server.js.map +1 -0
- package/dist/stores/backend.d.ts +15 -0
- package/dist/stores/backend.js +28 -0
- package/dist/stores/backend.js.map +1 -0
- package/dist/stores/claims.d.ts +14 -0
- package/dist/stores/claims.js +77 -0
- package/dist/stores/claims.js.map +1 -0
- package/dist/stores/conflicts.d.ts +10 -0
- package/dist/stores/conflicts.js +39 -0
- package/dist/stores/conflicts.js.map +1 -0
- package/dist/stores/control.d.ts +37 -0
- package/dist/stores/control.js +105 -0
- package/dist/stores/control.js.map +1 -0
- package/dist/stores/discoveries.d.ts +11 -0
- package/dist/stores/discoveries.js +45 -0
- package/dist/stores/discoveries.js.map +1 -0
- package/dist/stores/events.d.ts +14 -0
- package/dist/stores/events.js +37 -0
- package/dist/stores/events.js.map +1 -0
- package/dist/stores/help.d.ts +11 -0
- package/dist/stores/help.js +46 -0
- package/dist/stores/help.js.map +1 -0
- package/dist/stores/interfaces.d.ts +87 -0
- package/dist/stores/interfaces.js +2 -0
- package/dist/stores/interfaces.js.map +1 -0
- package/dist/stores/messages.d.ts +8 -0
- package/dist/stores/messages.js +29 -0
- package/dist/stores/messages.js.map +1 -0
- package/dist/stores/progress.d.ts +8 -0
- package/dist/stores/progress.js +21 -0
- package/dist/stores/progress.js.map +1 -0
- package/dist/stores/proposals.d.ts +11 -0
- package/dist/stores/proposals.js +46 -0
- package/dist/stores/proposals.js.map +1 -0
- package/dist/stores/redis/claims.d.ts +15 -0
- package/dist/stores/redis/claims.js +96 -0
- package/dist/stores/redis/claims.js.map +1 -0
- package/dist/stores/redis/db.d.ts +39 -0
- package/dist/stores/redis/db.js +34 -0
- package/dist/stores/redis/db.js.map +1 -0
- package/dist/stores/redis/discoveries.d.ts +13 -0
- package/dist/stores/redis/discoveries.js +54 -0
- package/dist/stores/redis/discoveries.js.map +1 -0
- package/dist/stores/redis/events.d.ts +17 -0
- package/dist/stores/redis/events.js +57 -0
- package/dist/stores/redis/events.js.map +1 -0
- package/dist/stores/redis/index.d.ts +3 -0
- package/dist/stores/redis/index.js +29 -0
- package/dist/stores/redis/index.js.map +1 -0
- package/dist/stores/redis/state.d.ts +14 -0
- package/dist/stores/redis/state.js +83 -0
- package/dist/stores/redis/state.js.map +1 -0
- package/dist/stores/reinforcements.d.ts +11 -0
- package/dist/stores/reinforcements.js +42 -0
- package/dist/stores/reinforcements.js.map +1 -0
- package/dist/stores/roles.d.ts +9 -0
- package/dist/stores/roles.js +22 -0
- package/dist/stores/roles.js.map +1 -0
- package/dist/stores/sqlite/claims.d.ts +17 -0
- package/dist/stores/sqlite/claims.js +121 -0
- package/dist/stores/sqlite/claims.js.map +1 -0
- package/dist/stores/sqlite/db.d.ts +16 -0
- package/dist/stores/sqlite/db.js +77 -0
- package/dist/stores/sqlite/db.js.map +1 -0
- package/dist/stores/sqlite/discoveries.d.ts +14 -0
- package/dist/stores/sqlite/discoveries.js +66 -0
- package/dist/stores/sqlite/discoveries.js.map +1 -0
- package/dist/stores/sqlite/events.d.ts +16 -0
- package/dist/stores/sqlite/events.js +75 -0
- package/dist/stores/sqlite/events.js.map +1 -0
- package/dist/stores/sqlite/index.d.ts +2 -0
- package/dist/stores/sqlite/index.js +31 -0
- package/dist/stores/sqlite/index.js.map +1 -0
- package/dist/stores/sqlite/state.d.ts +15 -0
- package/dist/stores/sqlite/state.js +99 -0
- package/dist/stores/sqlite/state.js.map +1 -0
- package/dist/stores/state.d.ts +11 -0
- package/dist/stores/state.js +67 -0
- package/dist/stores/state.js.map +1 -0
- package/dist/types.d.ts +45 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/utils.d.ts +3 -0
- package/dist/utils.js +20 -0
- package/dist/utils.js.map +1 -0
- package/dist/ws.d.ts +25 -0
- package/dist/ws.js +117 -0
- package/dist/ws.js.map +1 -0
- package/package.json +74 -0
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Proposal } from '../types.js';
|
|
2
|
+
import type { IProposalStore, IEventStore } from './interfaces.js';
|
|
3
|
+
export declare class ProposalStore implements IProposalStore {
|
|
4
|
+
private proposals;
|
|
5
|
+
private eventStore;
|
|
6
|
+
constructor(eventStore: IEventStore);
|
|
7
|
+
propose(agentId: string, action: string, detail?: string, quorum?: number): Promise<Proposal>;
|
|
8
|
+
endorse(proposalId: string, agentId: string): Promise<Proposal | null>;
|
|
9
|
+
list(status?: string): Promise<Proposal[]>;
|
|
10
|
+
get(proposalId: string): Promise<Proposal | null>;
|
|
11
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { randomBytes } from 'node:crypto';
|
|
2
|
+
export class ProposalStore {
|
|
3
|
+
proposals = new Map();
|
|
4
|
+
eventStore;
|
|
5
|
+
constructor(eventStore) {
|
|
6
|
+
this.eventStore = eventStore;
|
|
7
|
+
}
|
|
8
|
+
async propose(agentId, action, detail, quorum) {
|
|
9
|
+
const proposal = {
|
|
10
|
+
id: randomBytes(8).toString('hex'),
|
|
11
|
+
proposedBy: agentId,
|
|
12
|
+
action,
|
|
13
|
+
detail,
|
|
14
|
+
requires_quorum: quorum ?? 2,
|
|
15
|
+
endorsements: [agentId],
|
|
16
|
+
status: 'open',
|
|
17
|
+
createdAt: new Date().toISOString(),
|
|
18
|
+
};
|
|
19
|
+
this.proposals.set(proposal.id, proposal);
|
|
20
|
+
await this.eventStore.publish('governance.proposal.created', { proposal_id: proposal.id, action, proposedBy: agentId, requires_quorum: proposal.requires_quorum }, agentId);
|
|
21
|
+
return proposal;
|
|
22
|
+
}
|
|
23
|
+
async endorse(proposalId, agentId) {
|
|
24
|
+
const proposal = this.proposals.get(proposalId);
|
|
25
|
+
if (!proposal || proposal.status !== 'open')
|
|
26
|
+
return null;
|
|
27
|
+
if (!proposal.endorsements.includes(agentId)) {
|
|
28
|
+
proposal.endorsements.push(agentId);
|
|
29
|
+
}
|
|
30
|
+
if (proposal.endorsements.length >= proposal.requires_quorum) {
|
|
31
|
+
proposal.status = 'approved';
|
|
32
|
+
await this.eventStore.publish('governance.proposal.approved', { proposal_id: proposalId, action: proposal.action, endorsements: proposal.endorsements }, agentId);
|
|
33
|
+
}
|
|
34
|
+
return proposal;
|
|
35
|
+
}
|
|
36
|
+
async list(status) {
|
|
37
|
+
const all = [...this.proposals.values()];
|
|
38
|
+
if (!status)
|
|
39
|
+
return all;
|
|
40
|
+
return all.filter(p => p.status === status);
|
|
41
|
+
}
|
|
42
|
+
async get(proposalId) {
|
|
43
|
+
return this.proposals.get(proposalId) ?? null;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=proposals.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"proposals.js","sourceRoot":"","sources":["../../src/stores/proposals.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C,MAAM,OAAO,aAAa;IAChB,SAAS,GAAG,IAAI,GAAG,EAAoB,CAAC;IACxC,UAAU,CAAc;IAEhC,YAAY,UAAuB;QACjC,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;IAC/B,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,OAAe,EAAE,MAAc,EAAE,MAAe,EAAE,MAAe;QAC7E,MAAM,QAAQ,GAAa;YACzB,EAAE,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC;YAClC,UAAU,EAAE,OAAO;YACnB,MAAM;YACN,MAAM;YACN,eAAe,EAAE,MAAM,IAAI,CAAC;YAC5B,YAAY,EAAE,CAAC,OAAO,CAAC;YACvB,MAAM,EAAE,MAAM;YACd,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;SACpC,CAAC;QACF,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,EAAE,QAAQ,CAAC,CAAC;QAC1C,MAAM,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,6BAA6B,EAAE,EAAE,WAAW,EAAE,QAAQ,CAAC,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,eAAe,EAAE,QAAQ,CAAC,eAAe,EAAE,EAAE,OAAO,CAAC,CAAC;QAC5K,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,UAAkB,EAAE,OAAe;QAC/C,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QAChD,IAAI,CAAC,QAAQ,IAAI,QAAQ,CAAC,MAAM,KAAK,MAAM;YAAE,OAAO,IAAI,CAAC;QACzD,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;YAC7C,QAAQ,CAAC,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACtC,CAAC;QACD,IAAI,QAAQ,CAAC,YAAY,CAAC,MAAM,IAAI,QAAQ,CAAC,eAAe,EAAE,CAAC;YAC7D,QAAQ,CAAC,MAAM,GAAG,UAAU,CAAC;YAC7B,MAAM,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,8BAA8B,EAAE,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,YAAY,EAAE,QAAQ,CAAC,YAAY,EAAE,EAAE,OAAO,CAAC,CAAC;QACpK,CAAC;QACD,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,MAAe;QACxB,MAAM,GAAG,GAAG,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC;QACzC,IAAI,CAAC,MAAM;YAAE,OAAO,GAAG,CAAC;QACxB,OAAO,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC;IAC9C,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,UAAkB;QAC1B,OAAO,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,IAAI,CAAC;IAChD,CAAC;CACF"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { Claim, ClaimResult } from '../../types.js';
|
|
2
|
+
import type { IClaimStore, IEventStore } from '../interfaces.js';
|
|
3
|
+
import type { Redis } from './db.js';
|
|
4
|
+
export declare class RedisClaimStore implements IClaimStore {
|
|
5
|
+
private client;
|
|
6
|
+
private hashKey;
|
|
7
|
+
private eventStore;
|
|
8
|
+
constructor(client: Redis, namespace: string, eventStore: IEventStore);
|
|
9
|
+
claim(resource: string, value: string, agentId: string, ttlMs?: number): Promise<ClaimResult>;
|
|
10
|
+
release(resource: string, agentId: string): Promise<Claim | null>;
|
|
11
|
+
check(resource: string): Promise<Claim | null>;
|
|
12
|
+
list(pattern?: string): Promise<Claim[]>;
|
|
13
|
+
getAll(): Promise<Claim[]>;
|
|
14
|
+
load(claims: Claim[]): Promise<void>;
|
|
15
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { matchGlob, isExpired } from '../../utils.js';
|
|
2
|
+
export class RedisClaimStore {
|
|
3
|
+
client;
|
|
4
|
+
hashKey;
|
|
5
|
+
eventStore;
|
|
6
|
+
constructor(client, namespace, eventStore) {
|
|
7
|
+
this.client = client;
|
|
8
|
+
this.hashKey = `incubator:${namespace}:claims`;
|
|
9
|
+
this.eventStore = eventStore;
|
|
10
|
+
}
|
|
11
|
+
async claim(resource, value, agentId, ttlMs) {
|
|
12
|
+
const raw = await this.client.hget(this.hashKey, resource);
|
|
13
|
+
if (raw) {
|
|
14
|
+
const existing = JSON.parse(raw);
|
|
15
|
+
if (existing.status === 'active' && !isExpired(existing.claimedAt, existing.ttlMs)) {
|
|
16
|
+
if (existing.owner !== agentId) {
|
|
17
|
+
return { status: 'rejected', claim: existing };
|
|
18
|
+
}
|
|
19
|
+
// Same owner re-claiming: update value/ttl
|
|
20
|
+
existing.value = value;
|
|
21
|
+
existing.ttlMs = ttlMs;
|
|
22
|
+
await this.client.hset(this.hashKey, resource, JSON.stringify(existing));
|
|
23
|
+
return { status: 'approved', claim: existing };
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
const claim = {
|
|
27
|
+
resource,
|
|
28
|
+
value,
|
|
29
|
+
owner: agentId,
|
|
30
|
+
status: 'active',
|
|
31
|
+
claimedAt: new Date().toISOString(),
|
|
32
|
+
ttlMs,
|
|
33
|
+
};
|
|
34
|
+
await this.client.hset(this.hashKey, resource, JSON.stringify(claim));
|
|
35
|
+
await this.eventStore.publish('claim.acquired', { resource, value, owner: agentId }, agentId);
|
|
36
|
+
return { status: 'approved', claim };
|
|
37
|
+
}
|
|
38
|
+
async release(resource, agentId) {
|
|
39
|
+
const raw = await this.client.hget(this.hashKey, resource);
|
|
40
|
+
if (!raw)
|
|
41
|
+
return null;
|
|
42
|
+
const claim = JSON.parse(raw);
|
|
43
|
+
if (claim.status !== 'active')
|
|
44
|
+
return null;
|
|
45
|
+
if (claim.owner !== agentId)
|
|
46
|
+
return null;
|
|
47
|
+
claim.status = 'released';
|
|
48
|
+
await this.client.hset(this.hashKey, resource, JSON.stringify(claim));
|
|
49
|
+
await this.eventStore.publish('claim.released', { resource, owner: agentId }, agentId);
|
|
50
|
+
return claim;
|
|
51
|
+
}
|
|
52
|
+
async check(resource) {
|
|
53
|
+
const raw = await this.client.hget(this.hashKey, resource);
|
|
54
|
+
if (!raw)
|
|
55
|
+
return null;
|
|
56
|
+
const claim = JSON.parse(raw);
|
|
57
|
+
if (claim.status === 'active' && isExpired(claim.claimedAt, claim.ttlMs)) {
|
|
58
|
+
claim.status = 'expired';
|
|
59
|
+
await this.client.hset(this.hashKey, resource, JSON.stringify(claim));
|
|
60
|
+
}
|
|
61
|
+
return claim;
|
|
62
|
+
}
|
|
63
|
+
async list(pattern) {
|
|
64
|
+
const all = await this.client.hgetall(this.hashKey);
|
|
65
|
+
const results = [];
|
|
66
|
+
for (const [, raw] of Object.entries(all)) {
|
|
67
|
+
const claim = JSON.parse(raw);
|
|
68
|
+
if (claim.status === 'active' && isExpired(claim.claimedAt, claim.ttlMs)) {
|
|
69
|
+
claim.status = 'expired';
|
|
70
|
+
await this.client.hset(this.hashKey, claim.resource, JSON.stringify(claim));
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
if (claim.status !== 'active')
|
|
74
|
+
continue;
|
|
75
|
+
if (pattern && !matchGlob(pattern, claim.resource))
|
|
76
|
+
continue;
|
|
77
|
+
results.push(claim);
|
|
78
|
+
}
|
|
79
|
+
return results;
|
|
80
|
+
}
|
|
81
|
+
async getAll() {
|
|
82
|
+
const all = await this.client.hgetall(this.hashKey);
|
|
83
|
+
return Object.values(all).map(raw => JSON.parse(raw));
|
|
84
|
+
}
|
|
85
|
+
async load(claims) {
|
|
86
|
+
await this.client.del(this.hashKey);
|
|
87
|
+
if (claims.length === 0)
|
|
88
|
+
return;
|
|
89
|
+
const data = {};
|
|
90
|
+
for (const claim of claims) {
|
|
91
|
+
data[claim.resource] = JSON.stringify(claim);
|
|
92
|
+
}
|
|
93
|
+
await this.client.hset(this.hashKey, data);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=claims.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claims.js","sourceRoot":"","sources":["../../../src/stores/redis/claims.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
export interface Redis {
|
|
2
|
+
get(key: string): Promise<string | null>;
|
|
3
|
+
set(key: string, value: string): Promise<'OK'>;
|
|
4
|
+
del(...keys: string[]): Promise<number>;
|
|
5
|
+
hget(key: string, field: string): Promise<string | null>;
|
|
6
|
+
hset(key: string, field: string, value: string): Promise<number>;
|
|
7
|
+
hset(key: string, data: Record<string, string>): Promise<number>;
|
|
8
|
+
hdel(key: string, ...fields: string[]): Promise<number>;
|
|
9
|
+
hgetall(key: string): Promise<Record<string, string>>;
|
|
10
|
+
incr(key: string): Promise<number>;
|
|
11
|
+
zadd(key: string, ...args: (string | number)[]): Promise<number>;
|
|
12
|
+
zrangebyscore(key: string, min: string | number, max: string | number): Promise<string[]>;
|
|
13
|
+
zrange(key: string, start: number, stop: number): Promise<string[]>;
|
|
14
|
+
rpush(key: string, ...values: string[]): Promise<number>;
|
|
15
|
+
lrange(key: string, start: number, stop: number): Promise<string[]>;
|
|
16
|
+
multi(): RedisPipeline;
|
|
17
|
+
publish(channel: string, message: string): Promise<number>;
|
|
18
|
+
quit(): Promise<'OK'>;
|
|
19
|
+
status: string;
|
|
20
|
+
duplicate(): Redis;
|
|
21
|
+
}
|
|
22
|
+
export interface RedisPipeline {
|
|
23
|
+
incr(key: string): RedisPipeline;
|
|
24
|
+
set(key: string, value: string): RedisPipeline;
|
|
25
|
+
zadd(key: string, ...args: (string | number)[]): RedisPipeline;
|
|
26
|
+
del(...keys: string[]): RedisPipeline;
|
|
27
|
+
rpush(key: string, ...values: string[]): RedisPipeline;
|
|
28
|
+
hset(key: string, data: Record<string, string>): RedisPipeline;
|
|
29
|
+
exec(): Promise<Array<[Error | null, unknown]> | null>;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Get or create a Redis client for the given URL.
|
|
33
|
+
* Cached by URL — same URL returns the same client.
|
|
34
|
+
*/
|
|
35
|
+
export declare function getRedisClient(url: string): Redis;
|
|
36
|
+
/**
|
|
37
|
+
* Wait for a Redis client to be ready.
|
|
38
|
+
*/
|
|
39
|
+
export declare function waitForReady(client: Redis): Promise<void>;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { createRequire } from 'node:module';
|
|
2
|
+
const clientCache = new Map();
|
|
3
|
+
/**
|
|
4
|
+
* Get or create a Redis client for the given URL.
|
|
5
|
+
* Cached by URL — same URL returns the same client.
|
|
6
|
+
*/
|
|
7
|
+
export function getRedisClient(url) {
|
|
8
|
+
const cached = clientCache.get(url);
|
|
9
|
+
if (cached)
|
|
10
|
+
return cached;
|
|
11
|
+
const require = createRequire(import.meta.url);
|
|
12
|
+
const IORedis = require('ioredis');
|
|
13
|
+
const client = new IORedis(url);
|
|
14
|
+
clientCache.set(url, client);
|
|
15
|
+
return client;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Wait for a Redis client to be ready.
|
|
19
|
+
*/
|
|
20
|
+
export async function waitForReady(client) {
|
|
21
|
+
if (client.status === 'ready')
|
|
22
|
+
return;
|
|
23
|
+
return new Promise((resolve, reject) => {
|
|
24
|
+
const onReady = () => { cleanup(); resolve(); };
|
|
25
|
+
const onError = (err) => { cleanup(); reject(err); };
|
|
26
|
+
const cleanup = () => {
|
|
27
|
+
client.removeListener('ready', onReady);
|
|
28
|
+
client.removeListener('error', onError);
|
|
29
|
+
};
|
|
30
|
+
client.once('ready', onReady);
|
|
31
|
+
client.once('error', onError);
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=db.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"db.js","sourceRoot":"","sources":["../../../src/stores/redis/db.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAmC5C,MAAM,WAAW,GAAG,IAAI,GAAG,EAAiB,CAAC;AAE7C;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,GAAW;IACxC,MAAM,MAAM,GAAG,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACpC,IAAI,MAAM;QAAE,OAAO,MAAM,CAAC;IAE1B,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC/C,MAAM,OAAO,GAAG,OAAO,CAAC,SAAS,CAA+B,CAAC;IACjE,MAAM,MAAM,GAAG,IAAI,OAAO,CAAC,GAAG,CAAC,CAAC;IAEhC,WAAW,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;IAC7B,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,MAAa;IAC9C,IAAI,MAAM,CAAC,MAAM,KAAK,OAAO;QAAE,OAAO;IACtC,OAAO,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QAC3C,MAAM,OAAO,GAAG,GAAG,EAAE,GAAG,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC;QAChD,MAAM,OAAO,GAAG,CAAC,GAAU,EAAE,EAAE,GAAG,OAAO,EAAE,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QAC5D,MAAM,OAAO,GAAG,GAAG,EAAE;YAClB,MAAsE,CAAC,cAAc,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YACxG,MAAsE,CAAC,cAAc,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAC3G,CAAC,CAAC;QACD,MAA4D,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QACpF,MAA4D,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IACvF,CAAC,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Discovery } from '../../types.js';
|
|
2
|
+
import type { IDiscoveryStore, IEventStore } from '../interfaces.js';
|
|
3
|
+
import type { Redis } from './db.js';
|
|
4
|
+
export declare class RedisDiscoveryStore implements IDiscoveryStore {
|
|
5
|
+
private client;
|
|
6
|
+
private listKey;
|
|
7
|
+
private eventStore;
|
|
8
|
+
constructor(client: Redis, namespace: string, eventStore: IEventStore);
|
|
9
|
+
publish(topic: string, content: string, agentId: string, category?: string): Promise<Discovery>;
|
|
10
|
+
search(query?: string, category?: string): Promise<Discovery[]>;
|
|
11
|
+
getAll(): Promise<Discovery[]>;
|
|
12
|
+
load(discoveries: Discovery[]): Promise<void>;
|
|
13
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { generateId } from '../../utils.js';
|
|
2
|
+
export class RedisDiscoveryStore {
|
|
3
|
+
client;
|
|
4
|
+
listKey;
|
|
5
|
+
eventStore;
|
|
6
|
+
constructor(client, namespace, eventStore) {
|
|
7
|
+
this.client = client;
|
|
8
|
+
this.listKey = `incubator:${namespace}:discoveries`;
|
|
9
|
+
this.eventStore = eventStore;
|
|
10
|
+
}
|
|
11
|
+
async publish(topic, content, agentId, category) {
|
|
12
|
+
const discovery = {
|
|
13
|
+
id: generateId(),
|
|
14
|
+
topic,
|
|
15
|
+
content,
|
|
16
|
+
category,
|
|
17
|
+
publishedBy: agentId,
|
|
18
|
+
publishedAt: new Date().toISOString(),
|
|
19
|
+
};
|
|
20
|
+
await this.client.rpush(this.listKey, JSON.stringify(discovery));
|
|
21
|
+
await this.eventStore.publish('discovery.published', {
|
|
22
|
+
id: discovery.id,
|
|
23
|
+
topic,
|
|
24
|
+
category,
|
|
25
|
+
}, agentId);
|
|
26
|
+
return discovery;
|
|
27
|
+
}
|
|
28
|
+
async search(query, category) {
|
|
29
|
+
const raws = await this.client.lrange(this.listKey, 0, -1);
|
|
30
|
+
let results = raws.map(raw => JSON.parse(raw));
|
|
31
|
+
if (category) {
|
|
32
|
+
results = results.filter(d => d.category === category);
|
|
33
|
+
}
|
|
34
|
+
if (query) {
|
|
35
|
+
const lower = query.toLowerCase();
|
|
36
|
+
results = results.filter(d => d.topic.toLowerCase().includes(lower) ||
|
|
37
|
+
d.content.toLowerCase().includes(lower));
|
|
38
|
+
}
|
|
39
|
+
return results;
|
|
40
|
+
}
|
|
41
|
+
async getAll() {
|
|
42
|
+
const raws = await this.client.lrange(this.listKey, 0, -1);
|
|
43
|
+
return raws.map(raw => JSON.parse(raw));
|
|
44
|
+
}
|
|
45
|
+
async load(discoveries) {
|
|
46
|
+
const pipeline = this.client.multi();
|
|
47
|
+
pipeline.del(this.listKey);
|
|
48
|
+
for (const d of discoveries) {
|
|
49
|
+
pipeline.rpush(this.listKey, JSON.stringify(d));
|
|
50
|
+
}
|
|
51
|
+
await pipeline.exec();
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=discoveries.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"discoveries.js","sourceRoot":"","sources":["../../../src/stores/redis/discoveries.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAE5C,MAAM,OAAO,mBAAmB;IACtB,MAAM,CAAQ;IACd,OAAO,CAAS;IAChB,UAAU,CAAc;IAEhC,YAAY,MAAa,EAAE,SAAiB,EAAE,UAAuB;QACnE,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,OAAO,GAAG,aAAa,SAAS,cAAc,CAAC;QACpD,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;IAC/B,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,KAAa,EAAE,OAAe,EAAE,OAAe,EAAE,QAAiB;QAC9E,MAAM,SAAS,GAAc;YAC3B,EAAE,EAAE,UAAU,EAAE;YAChB,KAAK;YACL,OAAO;YACP,QAAQ;YACR,WAAW,EAAE,OAAO;YACpB,WAAW,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;SACtC,CAAC;QAEF,MAAM,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,CAAC;QACjE,MAAM,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,qBAAqB,EAAE;YACnD,EAAE,EAAE,SAAS,CAAC,EAAE;YAChB,KAAK;YACL,QAAQ;SACT,EAAE,OAAO,CAAC,CAAC;QAEZ,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,KAAc,EAAE,QAAiB;QAC5C,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QAC3D,IAAI,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAc,CAAC,CAAC;QAE5D,IAAI,QAAQ,EAAE,CAAC;YACb,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC;QACzD,CAAC;QAED,IAAI,KAAK,EAAE,CAAC;YACV,MAAM,KAAK,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC;YAClC,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAC3B,CAAC,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC;gBACrC,CAAC,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,CACxC,CAAC;QACJ,CAAC;QAED,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,KAAK,CAAC,MAAM;QACV,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QAC3D,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAc,CAAC,CAAC;IACvD,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,WAAwB;QACjC,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;QACrC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAE3B,KAAK,MAAM,CAAC,IAAI,WAAW,EAAE,CAAC;YAC5B,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;QAClD,CAAC;QAED,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;IACxB,CAAC;CACF"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { IncubatorEvent } from '../../types.js';
|
|
2
|
+
import type { IEventStore } from '../interfaces.js';
|
|
3
|
+
import type { Redis } from './db.js';
|
|
4
|
+
export declare class RedisEventStore implements IEventStore {
|
|
5
|
+
private client;
|
|
6
|
+
private eventsKey;
|
|
7
|
+
private cursorKey;
|
|
8
|
+
constructor(client: Redis, namespace: string);
|
|
9
|
+
publish(type: string, data: unknown, agentId: string): Promise<IncubatorEvent>;
|
|
10
|
+
getEvents(since?: number, type?: string): Promise<{
|
|
11
|
+
events: IncubatorEvent[];
|
|
12
|
+
cursor: number;
|
|
13
|
+
}>;
|
|
14
|
+
getCursor(): Promise<number>;
|
|
15
|
+
getAll(): Promise<IncubatorEvent[]>;
|
|
16
|
+
load(events: IncubatorEvent[], cursor: number): Promise<void>;
|
|
17
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
export class RedisEventStore {
|
|
2
|
+
client;
|
|
3
|
+
eventsKey;
|
|
4
|
+
cursorKey;
|
|
5
|
+
constructor(client, namespace) {
|
|
6
|
+
this.client = client;
|
|
7
|
+
this.eventsKey = `incubator:${namespace}:events`;
|
|
8
|
+
this.cursorKey = `incubator:${namespace}:cursor`;
|
|
9
|
+
}
|
|
10
|
+
async publish(type, data, agentId) {
|
|
11
|
+
const now = new Date().toISOString();
|
|
12
|
+
// Atomic: increment cursor, then add event with cursor as score
|
|
13
|
+
const pipeline = this.client.multi();
|
|
14
|
+
pipeline.incr(this.cursorKey);
|
|
15
|
+
const results = await pipeline.exec();
|
|
16
|
+
if (!results)
|
|
17
|
+
throw new Error('Redis MULTI/EXEC failed');
|
|
18
|
+
const id = results[0][1];
|
|
19
|
+
const event = {
|
|
20
|
+
id,
|
|
21
|
+
type,
|
|
22
|
+
data,
|
|
23
|
+
publishedBy: agentId,
|
|
24
|
+
publishedAt: now,
|
|
25
|
+
};
|
|
26
|
+
await this.client.zadd(this.eventsKey, id, JSON.stringify(event));
|
|
27
|
+
return event;
|
|
28
|
+
}
|
|
29
|
+
async getEvents(since, type) {
|
|
30
|
+
const min = since !== undefined ? since + 1 : '-inf';
|
|
31
|
+
const raws = await this.client.zrangebyscore(this.eventsKey, min, '+inf');
|
|
32
|
+
let events = raws.map(raw => JSON.parse(raw));
|
|
33
|
+
if (type) {
|
|
34
|
+
events = events.filter(e => e.type === type);
|
|
35
|
+
}
|
|
36
|
+
const cursor = await this.getCursor();
|
|
37
|
+
return { events, cursor };
|
|
38
|
+
}
|
|
39
|
+
async getCursor() {
|
|
40
|
+
const raw = await this.client.get(this.cursorKey);
|
|
41
|
+
return raw ? parseInt(raw, 10) : 0;
|
|
42
|
+
}
|
|
43
|
+
async getAll() {
|
|
44
|
+
const raws = await this.client.zrange(this.eventsKey, 0, -1);
|
|
45
|
+
return raws.map(raw => JSON.parse(raw));
|
|
46
|
+
}
|
|
47
|
+
async load(events, cursor) {
|
|
48
|
+
const pipeline = this.client.multi();
|
|
49
|
+
pipeline.del(this.eventsKey);
|
|
50
|
+
for (const event of events) {
|
|
51
|
+
pipeline.zadd(this.eventsKey, event.id, JSON.stringify(event));
|
|
52
|
+
}
|
|
53
|
+
pipeline.set(this.cursorKey, String(cursor));
|
|
54
|
+
await pipeline.exec();
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=events.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"events.js","sourceRoot":"","sources":["../../../src/stores/redis/events.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { RedisStateStore } from './state.js';
|
|
2
|
+
import { RedisEventStore } from './events.js';
|
|
3
|
+
import { RedisClaimStore } from './claims.js';
|
|
4
|
+
import { RedisDiscoveryStore } from './discoveries.js';
|
|
5
|
+
import { MessageStore } from '../messages.js';
|
|
6
|
+
import { HelpStore } from '../help.js';
|
|
7
|
+
import { ProgressStore } from '../progress.js';
|
|
8
|
+
import { ConflictStore } from '../conflicts.js';
|
|
9
|
+
import { RoleStore } from '../roles.js';
|
|
10
|
+
import { ProposalStore } from '../proposals.js';
|
|
11
|
+
import { ReinforcementStore } from '../reinforcements.js';
|
|
12
|
+
import { ControlStore } from '../control.js';
|
|
13
|
+
export function createRedisStores(client, namespace) {
|
|
14
|
+
const events = new RedisEventStore(client, namespace);
|
|
15
|
+
const state = new RedisStateStore(client, namespace);
|
|
16
|
+
const claims = new RedisClaimStore(client, namespace, events);
|
|
17
|
+
const discoveries = new RedisDiscoveryStore(client, namespace, events);
|
|
18
|
+
// New coordination stores use in-memory backend for now
|
|
19
|
+
const messages = new MessageStore();
|
|
20
|
+
const help = new HelpStore(events);
|
|
21
|
+
const progress = new ProgressStore();
|
|
22
|
+
const conflicts = new ConflictStore(events);
|
|
23
|
+
const roles = new RoleStore();
|
|
24
|
+
const proposals = new ProposalStore(events);
|
|
25
|
+
const reinforcements = new ReinforcementStore(events);
|
|
26
|
+
const control = new ControlStore(events);
|
|
27
|
+
return { state, events, claims, discoveries, messages, help, progress, conflicts, roles, proposals, reinforcements, control };
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/stores/redis/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAE7C,MAAM,UAAU,iBAAiB,CAAC,MAAa,EAAE,SAAiB;IAChE,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IACtD,MAAM,KAAK,GAAG,IAAI,eAAe,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IACrD,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC;IAC9D,MAAM,WAAW,GAAG,IAAI,mBAAmB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC;IACvE,wDAAwD;IACxD,MAAM,QAAQ,GAAG,IAAI,YAAY,EAAE,CAAC;IACpC,MAAM,IAAI,GAAG,IAAI,SAAS,CAAC,MAAM,CAAC,CAAC;IACnC,MAAM,QAAQ,GAAG,IAAI,aAAa,EAAE,CAAC;IACrC,MAAM,SAAS,GAAG,IAAI,aAAa,CAAC,MAAM,CAAC,CAAC;IAC5C,MAAM,KAAK,GAAG,IAAI,SAAS,EAAE,CAAC;IAC9B,MAAM,SAAS,GAAG,IAAI,aAAa,CAAC,MAAM,CAAC,CAAC;IAC5C,MAAM,cAAc,GAAG,IAAI,kBAAkB,CAAC,MAAM,CAAC,CAAC;IACtD,MAAM,OAAO,GAAG,IAAI,YAAY,CAAC,MAAM,CAAC,CAAC;IACzC,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE,cAAc,EAAE,OAAO,EAAE,CAAC;AAChI,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { StateEntry } from '../../types.js';
|
|
2
|
+
import type { IStateStore } from '../interfaces.js';
|
|
3
|
+
import type { Redis } from './db.js';
|
|
4
|
+
export declare class RedisStateStore implements IStateStore {
|
|
5
|
+
private client;
|
|
6
|
+
private hashKey;
|
|
7
|
+
constructor(client: Redis, namespace: string);
|
|
8
|
+
get(key: string): Promise<StateEntry | null>;
|
|
9
|
+
set(key: string, value: unknown, agentId: string, category?: string, ttlMs?: number): Promise<StateEntry>;
|
|
10
|
+
delete(key: string): Promise<boolean>;
|
|
11
|
+
query(pattern?: string, category?: string): Promise<StateEntry[]>;
|
|
12
|
+
getAll(): Promise<StateEntry[]>;
|
|
13
|
+
load(entries: StateEntry[]): Promise<void>;
|
|
14
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { matchGlob, isExpired } from '../../utils.js';
|
|
2
|
+
export class RedisStateStore {
|
|
3
|
+
client;
|
|
4
|
+
hashKey;
|
|
5
|
+
constructor(client, namespace) {
|
|
6
|
+
this.client = client;
|
|
7
|
+
this.hashKey = `incubator:${namespace}:state`;
|
|
8
|
+
}
|
|
9
|
+
async get(key) {
|
|
10
|
+
const raw = await this.client.hget(this.hashKey, key);
|
|
11
|
+
if (!raw)
|
|
12
|
+
return null;
|
|
13
|
+
const entry = JSON.parse(raw);
|
|
14
|
+
if (isExpired(entry.setAt, entry.ttlMs)) {
|
|
15
|
+
await this.client.hdel(this.hashKey, key);
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
return entry;
|
|
19
|
+
}
|
|
20
|
+
async set(key, value, agentId, category, ttlMs) {
|
|
21
|
+
const now = new Date().toISOString();
|
|
22
|
+
const existing = await this.get(key);
|
|
23
|
+
const setAt = existing?.setAt ?? now;
|
|
24
|
+
const entry = {
|
|
25
|
+
key,
|
|
26
|
+
value,
|
|
27
|
+
category,
|
|
28
|
+
setBy: agentId,
|
|
29
|
+
setAt,
|
|
30
|
+
updatedAt: now,
|
|
31
|
+
ttlMs,
|
|
32
|
+
};
|
|
33
|
+
await this.client.hset(this.hashKey, key, JSON.stringify(entry));
|
|
34
|
+
return entry;
|
|
35
|
+
}
|
|
36
|
+
async delete(key) {
|
|
37
|
+
const count = await this.client.hdel(this.hashKey, key);
|
|
38
|
+
return count > 0;
|
|
39
|
+
}
|
|
40
|
+
async query(pattern, category) {
|
|
41
|
+
const all = await this.client.hgetall(this.hashKey);
|
|
42
|
+
const results = [];
|
|
43
|
+
for (const [, raw] of Object.entries(all)) {
|
|
44
|
+
const entry = JSON.parse(raw);
|
|
45
|
+
if (isExpired(entry.setAt, entry.ttlMs)) {
|
|
46
|
+
await this.client.hdel(this.hashKey, entry.key);
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
if (pattern && !matchGlob(pattern, entry.key))
|
|
50
|
+
continue;
|
|
51
|
+
if (category && entry.category !== category)
|
|
52
|
+
continue;
|
|
53
|
+
results.push(entry);
|
|
54
|
+
}
|
|
55
|
+
return results;
|
|
56
|
+
}
|
|
57
|
+
async getAll() {
|
|
58
|
+
const all = await this.client.hgetall(this.hashKey);
|
|
59
|
+
const results = [];
|
|
60
|
+
for (const [, raw] of Object.entries(all)) {
|
|
61
|
+
const entry = JSON.parse(raw);
|
|
62
|
+
if (!isExpired(entry.setAt, entry.ttlMs)) {
|
|
63
|
+
results.push(entry);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return results;
|
|
67
|
+
}
|
|
68
|
+
async load(entries) {
|
|
69
|
+
await this.client.del(this.hashKey);
|
|
70
|
+
if (entries.length === 0)
|
|
71
|
+
return;
|
|
72
|
+
const data = {};
|
|
73
|
+
for (const entry of entries) {
|
|
74
|
+
if (!isExpired(entry.setAt, entry.ttlMs)) {
|
|
75
|
+
data[entry.key] = JSON.stringify(entry);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
if (Object.keys(data).length > 0) {
|
|
79
|
+
await this.client.hset(this.hashKey, data);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=state.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"state.js","sourceRoot":"","sources":["../../../src/stores/redis/state.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAEtD,MAAM,OAAO,eAAe;IAClB,MAAM,CAAQ;IACd,OAAO,CAAS;IAExB,YAAY,MAAa,EAAE,SAAiB;QAC1C,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,OAAO,GAAG,aAAa,SAAS,QAAQ,CAAC;IAChD,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,GAAW;QACnB,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;QACtD,IAAI,CAAC,GAAG;YAAE,OAAO,IAAI,CAAC;QAEtB,MAAM,KAAK,GAAe,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC1C,IAAI,SAAS,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;YACxC,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;YAC1C,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,GAAW,EAAE,KAAc,EAAE,OAAe,EAAE,QAAiB,EAAE,KAAc;QACvF,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QACrC,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACrC,MAAM,KAAK,GAAG,QAAQ,EAAE,KAAK,IAAI,GAAG,CAAC;QAErC,MAAM,KAAK,GAAe;YACxB,GAAG;YACH,KAAK;YACL,QAAQ;YACR,KAAK,EAAE,OAAO;YACd,KAAK;YACL,SAAS,EAAE,GAAG;YACd,KAAK;SACN,CAAC;QAEF,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC;QACjE,OAAO,KAAK,CAAC;IACf,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,GAAW;QACtB,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;QACxD,OAAO,KAAK,GAAG,CAAC,CAAC;IACnB,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,OAAgB,EAAE,QAAiB;QAC7C,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACpD,MAAM,OAAO,GAAiB,EAAE,CAAC;QAEjC,KAAK,MAAM,CAAC,EAAE,GAAG,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;YAC1C,MAAM,KAAK,GAAe,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YAC1C,IAAI,SAAS,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;gBACxC,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC;gBAChD,SAAS;YACX,CAAC;YACD,IAAI,OAAO,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,KAAK,CAAC,GAAG,CAAC;gBAAE,SAAS;YACxD,IAAI,QAAQ,IAAI,KAAK,CAAC,QAAQ,KAAK,QAAQ;gBAAE,SAAS;YACtD,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACtB,CAAC;QACD,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,KAAK,CAAC,MAAM;QACV,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACpD,MAAM,OAAO,GAAiB,EAAE,CAAC;QAEjC,KAAK,MAAM,CAAC,EAAE,GAAG,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;YAC1C,MAAM,KAAK,GAAe,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YAC1C,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;gBACzC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACtB,CAAC;QACH,CAAC;QACD,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,OAAqB;QAC9B,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACpC,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO;QAEjC,MAAM,IAAI,GAA2B,EAAE,CAAC;QACxC,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC5B,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;gBACzC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;YAC1C,CAAC;QACH,CAAC;QACD,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACjC,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;QAC7C,CAAC;IACH,CAAC;CACF"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ReinforcementRequest } from '../types.js';
|
|
2
|
+
import type { IReinforcementStore, IEventStore } from './interfaces.js';
|
|
3
|
+
export declare class ReinforcementStore implements IReinforcementStore {
|
|
4
|
+
private requests;
|
|
5
|
+
private eventStore;
|
|
6
|
+
constructor(eventStore: IEventStore);
|
|
7
|
+
request(agentId: string, role: string, count: number, reason?: string): Promise<ReinforcementRequest>;
|
|
8
|
+
approve(requestId: string): Promise<ReinforcementRequest | null>;
|
|
9
|
+
deny(requestId: string, reason: string): Promise<ReinforcementRequest | null>;
|
|
10
|
+
list(): Promise<ReinforcementRequest[]>;
|
|
11
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { randomBytes } from 'node:crypto';
|
|
2
|
+
export class ReinforcementStore {
|
|
3
|
+
requests = new Map();
|
|
4
|
+
eventStore;
|
|
5
|
+
constructor(eventStore) {
|
|
6
|
+
this.eventStore = eventStore;
|
|
7
|
+
}
|
|
8
|
+
async request(agentId, role, count, reason) {
|
|
9
|
+
const req = {
|
|
10
|
+
id: randomBytes(8).toString('hex'),
|
|
11
|
+
requestedBy: agentId,
|
|
12
|
+
role,
|
|
13
|
+
count: Math.max(1, count),
|
|
14
|
+
reason,
|
|
15
|
+
status: 'pending',
|
|
16
|
+
createdAt: new Date().toISOString(),
|
|
17
|
+
};
|
|
18
|
+
this.requests.set(req.id, req);
|
|
19
|
+
return req;
|
|
20
|
+
}
|
|
21
|
+
async approve(requestId) {
|
|
22
|
+
const req = this.requests.get(requestId);
|
|
23
|
+
if (!req || req.status !== 'pending')
|
|
24
|
+
return null;
|
|
25
|
+
req.status = 'approved';
|
|
26
|
+
await this.eventStore.publish('reinforcement.approved', { request_id: requestId, role: req.role, count: req.count }, 'server');
|
|
27
|
+
return req;
|
|
28
|
+
}
|
|
29
|
+
async deny(requestId, reason) {
|
|
30
|
+
const req = this.requests.get(requestId);
|
|
31
|
+
if (!req || req.status !== 'pending')
|
|
32
|
+
return null;
|
|
33
|
+
req.status = 'denied';
|
|
34
|
+
req.denialReason = reason;
|
|
35
|
+
await this.eventStore.publish('reinforcement.denied', { request_id: requestId, role: req.role, reason }, 'server');
|
|
36
|
+
return req;
|
|
37
|
+
}
|
|
38
|
+
async list() {
|
|
39
|
+
return [...this.requests.values()];
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=reinforcements.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reinforcements.js","sourceRoot":"","sources":["../../src/stores/reinforcements.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C,MAAM,OAAO,kBAAkB;IACrB,QAAQ,GAAG,IAAI,GAAG,EAAgC,CAAC;IACnD,UAAU,CAAc;IAEhC,YAAY,UAAuB;QACjC,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;IAC/B,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,OAAe,EAAE,IAAY,EAAE,KAAa,EAAE,MAAe;QACzE,MAAM,GAAG,GAAyB;YAChC,EAAE,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC;YAClC,WAAW,EAAE,OAAO;YACpB,IAAI;YACJ,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC;YACzB,MAAM;YACN,MAAM,EAAE,SAAS;YACjB,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;SACpC,CAAC;QACF,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;QAC/B,OAAO,GAAG,CAAC;IACb,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,SAAiB;QAC7B,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QACzC,IAAI,CAAC,GAAG,IAAI,GAAG,CAAC,MAAM,KAAK,SAAS;YAAE,OAAO,IAAI,CAAC;QAClD,GAAG,CAAC,MAAM,GAAG,UAAU,CAAC;QACxB,MAAM,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,wBAAwB,EAAE,EAAE,UAAU,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,EAAE,EAAE,QAAQ,CAAC,CAAC;QAC/H,OAAO,GAAG,CAAC;IACb,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,SAAiB,EAAE,MAAc;QAC1C,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QACzC,IAAI,CAAC,GAAG,IAAI,GAAG,CAAC,MAAM,KAAK,SAAS;YAAE,OAAO,IAAI,CAAC;QAClD,GAAG,CAAC,MAAM,GAAG,QAAQ,CAAC;QACtB,GAAG,CAAC,YAAY,GAAG,MAAM,CAAC;QAC1B,MAAM,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,sBAAsB,EAAE,EAAE,UAAU,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,QAAQ,CAAC,CAAC;QACnH,OAAO,GAAG,CAAC;IACb,CAAC;IAED,KAAK,CAAC,IAAI;QACR,OAAO,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;IACrC,CAAC;CACF"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { RoleAssignment } from '../types.js';
|
|
2
|
+
import type { IRoleStore } from './interfaces.js';
|
|
3
|
+
export declare class RoleStore implements IRoleStore {
|
|
4
|
+
private assignments;
|
|
5
|
+
assign(agentId: string, role: string): Promise<RoleAssignment>;
|
|
6
|
+
getAssignments(): Promise<RoleAssignment[]>;
|
|
7
|
+
getByAgent(agentId: string): Promise<RoleAssignment | null>;
|
|
8
|
+
remove(agentId: string): Promise<boolean>;
|
|
9
|
+
}
|