@hazeljs/organism 2.0.6
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 +205 -0
- package/dist/__tests__/organism.embedding.test.d.ts +2 -0
- package/dist/__tests__/organism.embedding.test.d.ts.map +1 -0
- package/dist/__tests__/organism.embedding.test.js +166 -0
- package/dist/__tests__/organism.embedding.test.js.map +1 -0
- package/dist/__tests__/organism.phase1.test.d.ts +2 -0
- package/dist/__tests__/organism.phase1.test.d.ts.map +1 -0
- package/dist/__tests__/organism.phase1.test.js +375 -0
- package/dist/__tests__/organism.phase1.test.js.map +1 -0
- package/dist/__tests__/organism.phase2-3.test.d.ts +2 -0
- package/dist/__tests__/organism.phase2-3.test.d.ts.map +1 -0
- package/dist/__tests__/organism.phase2-3.test.js +320 -0
- package/dist/__tests__/organism.phase2-3.test.js.map +1 -0
- package/dist/__tests__/organism.phase4.test.d.ts +2 -0
- package/dist/__tests__/organism.phase4.test.d.ts.map +1 -0
- package/dist/__tests__/organism.phase4.test.js +217 -0
- package/dist/__tests__/organism.phase4.test.js.map +1 -0
- package/dist/bridge/signal-bridge.d.ts +46 -0
- package/dist/bridge/signal-bridge.d.ts.map +1 -0
- package/dist/bridge/signal-bridge.js +75 -0
- package/dist/bridge/signal-bridge.js.map +1 -0
- package/dist/core/capability-registry.d.ts +16 -0
- package/dist/core/capability-registry.d.ts.map +1 -0
- package/dist/core/capability-registry.js +71 -0
- package/dist/core/capability-registry.js.map +1 -0
- package/dist/core/clock.d.ts +17 -0
- package/dist/core/clock.d.ts.map +1 -0
- package/dist/core/clock.js +63 -0
- package/dist/core/clock.js.map +1 -0
- package/dist/core/mission.d.ts +4 -0
- package/dist/core/mission.d.ts.map +1 -0
- package/dist/core/mission.js +74 -0
- package/dist/core/mission.js.map +1 -0
- package/dist/core/organism-context.d.ts +139 -0
- package/dist/core/organism-context.d.ts.map +1 -0
- package/dist/core/organism-context.js +62 -0
- package/dist/core/organism-context.js.map +1 -0
- package/dist/core/organism-runtime.d.ts +199 -0
- package/dist/core/organism-runtime.d.ts.map +1 -0
- package/dist/core/organism-runtime.js +1016 -0
- package/dist/core/organism-runtime.js.map +1 -0
- package/dist/decorators/index.d.ts +39 -0
- package/dist/decorators/index.d.ts.map +1 -0
- package/dist/decorators/index.js +165 -0
- package/dist/decorators/index.js.map +1 -0
- package/dist/economy/market-engine.d.ts +57 -0
- package/dist/economy/market-engine.d.ts.map +1 -0
- package/dist/economy/market-engine.js +258 -0
- package/dist/economy/market-engine.js.map +1 -0
- package/dist/economy/resource-allocator.d.ts +39 -0
- package/dist/economy/resource-allocator.d.ts.map +1 -0
- package/dist/economy/resource-allocator.js +153 -0
- package/dist/economy/resource-allocator.js.map +1 -0
- package/dist/economy/utility-engine.d.ts +16 -0
- package/dist/economy/utility-engine.d.ts.map +1 -0
- package/dist/economy/utility-engine.js +80 -0
- package/dist/economy/utility-engine.js.map +1 -0
- package/dist/economy/utility-forecaster.d.ts +24 -0
- package/dist/economy/utility-forecaster.d.ts.map +1 -0
- package/dist/economy/utility-forecaster.js +60 -0
- package/dist/economy/utility-forecaster.js.map +1 -0
- package/dist/errors/organism.errors.d.ts +23 -0
- package/dist/errors/organism.errors.d.ts.map +1 -0
- package/dist/errors/organism.errors.js +50 -0
- package/dist/errors/organism.errors.js.map +1 -0
- package/dist/events/organism-events.d.ts +61 -0
- package/dist/events/organism-events.d.ts.map +1 -0
- package/dist/events/organism-events.js +95 -0
- package/dist/events/organism-events.js.map +1 -0
- package/dist/evolution/evolution-engine.d.ts +41 -0
- package/dist/evolution/evolution-engine.d.ts.map +1 -0
- package/dist/evolution/evolution-engine.js +135 -0
- package/dist/evolution/evolution-engine.js.map +1 -0
- package/dist/evolution/mutation-engine.d.ts +21 -0
- package/dist/evolution/mutation-engine.d.ts.map +1 -0
- package/dist/evolution/mutation-engine.js +84 -0
- package/dist/evolution/mutation-engine.js.map +1 -0
- package/dist/genealogy/genealogy-manager.d.ts +18 -0
- package/dist/genealogy/genealogy-manager.d.ts.map +1 -0
- package/dist/genealogy/genealogy-manager.js +64 -0
- package/dist/genealogy/genealogy-manager.js.map +1 -0
- package/dist/governance/constitution.d.ts +20 -0
- package/dist/governance/constitution.d.ts.map +1 -0
- package/dist/governance/constitution.js +109 -0
- package/dist/governance/constitution.js.map +1 -0
- package/dist/host/organism-host-registry.d.ts +24 -0
- package/dist/host/organism-host-registry.d.ts.map +1 -0
- package/dist/host/organism-host-registry.js +65 -0
- package/dist/host/organism-host-registry.js.map +1 -0
- package/dist/host/organism-host.d.ts +32 -0
- package/dist/host/organism-host.d.ts.map +1 -0
- package/dist/host/organism-host.js +64 -0
- package/dist/host/organism-host.js.map +1 -0
- package/dist/index.d.ts +43 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +117 -0
- package/dist/index.js.map +1 -0
- package/dist/integration/create-ops-organism.d.ts +34 -0
- package/dist/integration/create-ops-organism.d.ts.map +1 -0
- package/dist/integration/create-ops-organism.js +43 -0
- package/dist/integration/create-ops-organism.js.map +1 -0
- package/dist/lifecycle/birth-engine.d.ts +41 -0
- package/dist/lifecycle/birth-engine.d.ts.map +1 -0
- package/dist/lifecycle/birth-engine.js +182 -0
- package/dist/lifecycle/birth-engine.js.map +1 -0
- package/dist/lifecycle/decision-engine.d.ts +19 -0
- package/dist/lifecycle/decision-engine.d.ts.map +1 -0
- package/dist/lifecycle/decision-engine.js +137 -0
- package/dist/lifecycle/decision-engine.js.map +1 -0
- package/dist/lifecycle/reproduction-engine.d.ts +58 -0
- package/dist/lifecycle/reproduction-engine.d.ts.map +1 -0
- package/dist/lifecycle/reproduction-engine.js +207 -0
- package/dist/lifecycle/reproduction-engine.js.map +1 -0
- package/dist/lifecycle/survival-engine.d.ts +17 -0
- package/dist/lifecycle/survival-engine.d.ts.map +1 -0
- package/dist/lifecycle/survival-engine.js +83 -0
- package/dist/lifecycle/survival-engine.js.map +1 -0
- package/dist/observability/metrics.d.ts +37 -0
- package/dist/observability/metrics.d.ts.map +1 -0
- package/dist/observability/metrics.js +80 -0
- package/dist/observability/metrics.js.map +1 -0
- package/dist/perception/perception-engine.d.ts +40 -0
- package/dist/perception/perception-engine.d.ts.map +1 -0
- package/dist/perception/perception-engine.js +126 -0
- package/dist/perception/perception-engine.js.map +1 -0
- package/dist/persistence/in-memory-organism-repository.d.ts +2 -0
- package/dist/persistence/in-memory-organism-repository.d.ts.map +1 -0
- package/dist/persistence/in-memory-organism-repository.js +18 -0
- package/dist/persistence/in-memory-organism-repository.js.map +1 -0
- package/dist/persistence/organism-repository.d.ts +42 -0
- package/dist/persistence/organism-repository.d.ts.map +1 -0
- package/dist/persistence/organism-repository.js +105 -0
- package/dist/persistence/organism-repository.js.map +1 -0
- package/dist/types/organism.types.d.ts +482 -0
- package/dist/types/organism.types.d.ts.map +1 -0
- package/dist/types/organism.types.js +45 -0
- package/dist/types/organism.types.js.map +1 -0
- package/examples/ecommerce-organism/run.ts +245 -0
- package/package.json +73 -0
- package/src/bridge/signal-bridge.ts +116 -0
- package/src/core/capability-registry.ts +72 -0
- package/src/core/clock.ts +58 -0
- package/src/core/mission.ts +83 -0
- package/src/core/organism-context.ts +176 -0
- package/src/core/organism-runtime.ts +1369 -0
- package/src/decorators/index.ts +180 -0
- package/src/economy/market-engine.ts +324 -0
- package/src/economy/resource-allocator.ts +188 -0
- package/src/economy/utility-engine.ts +103 -0
- package/src/economy/utility-forecaster.ts +88 -0
- package/src/errors/organism.errors.ts +47 -0
- package/src/events/organism-events.ts +122 -0
- package/src/evolution/evolution-engine.ts +167 -0
- package/src/evolution/mutation-engine.ts +110 -0
- package/src/genealogy/genealogy-manager.ts +70 -0
- package/src/governance/constitution.ts +120 -0
- package/src/host/organism-host-registry.ts +72 -0
- package/src/host/organism-host.ts +103 -0
- package/src/index.ts +78 -0
- package/src/integration/create-ops-organism.ts +80 -0
- package/src/lifecycle/birth-engine.ts +225 -0
- package/src/lifecycle/decision-engine.ts +158 -0
- package/src/lifecycle/reproduction-engine.ts +289 -0
- package/src/lifecycle/survival-engine.ts +95 -0
- package/src/observability/metrics.ts +120 -0
- package/src/perception/perception-engine.ts +140 -0
- package/src/persistence/in-memory-organism-repository.ts +1 -0
- package/src/persistence/organism-repository.ts +134 -0
- package/src/types/organism.types.ts +591 -0
- package/tsconfig.jest.json +8 -0
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Genealogy helpers — parent/child tree formatting and queries.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import type { AgentGenealogy, RuntimeAgentRecord } from '../types/organism.types';
|
|
6
|
+
import type { OrganismRepository } from '../persistence/organism-repository';
|
|
7
|
+
|
|
8
|
+
export class GenealogyManager {
|
|
9
|
+
constructor(
|
|
10
|
+
private readonly repo: OrganismRepository,
|
|
11
|
+
private readonly organismId: string
|
|
12
|
+
) {}
|
|
13
|
+
|
|
14
|
+
async list(): Promise<AgentGenealogy[]> {
|
|
15
|
+
return this.repo.listGenealogy(this.organismId);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
async getLineage(agentId: string): Promise<AgentGenealogy[]> {
|
|
19
|
+
const all = await this.list();
|
|
20
|
+
const byId = new Map(all.map((g) => [g.agentId, g]));
|
|
21
|
+
const chain: AgentGenealogy[] = [];
|
|
22
|
+
let current = byId.get(agentId);
|
|
23
|
+
while (current) {
|
|
24
|
+
chain.unshift(current);
|
|
25
|
+
current = current.parentAgentId ? byId.get(current.parentAgentId) : undefined;
|
|
26
|
+
}
|
|
27
|
+
return chain;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
async countLiveChildren(parentId: string, agents: RuntimeAgentRecord[]): Promise<number> {
|
|
31
|
+
const live = new Set(
|
|
32
|
+
agents.filter((a) => a.status !== 'terminated' && a.status !== 'failed').map((a) => a.id)
|
|
33
|
+
);
|
|
34
|
+
const gene = (await this.list()).find((g) => g.agentId === parentId);
|
|
35
|
+
if (!gene) return 0;
|
|
36
|
+
return gene.children.filter((id) => live.has(id)).length;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* ASCII tree suitable for CLI / debug logs.
|
|
41
|
+
*/
|
|
42
|
+
formatTree(agents: RuntimeAgentRecord[], genealogy: AgentGenealogy[]): string {
|
|
43
|
+
const byId = new Map(agents.map((a) => [a.id, a]));
|
|
44
|
+
const geneById = new Map(genealogy.map((g) => [g.agentId, g]));
|
|
45
|
+
const roots = genealogy.filter((g) => !g.parentAgentId || !geneById.has(g.parentAgentId));
|
|
46
|
+
|
|
47
|
+
const lines: string[] = [];
|
|
48
|
+
const walk = (node: AgentGenealogy, prefix: string, isLast: boolean): void => {
|
|
49
|
+
const agent = byId.get(node.agentId);
|
|
50
|
+
const label = agent
|
|
51
|
+
? `${agent.name} #${agent.id} gen=${node.generation} [${agent.status}]`
|
|
52
|
+
: `${node.agentId} gen=${node.generation}`;
|
|
53
|
+
const branch = prefix === '' ? '' : isLast ? '└── ' : '├── ';
|
|
54
|
+
lines.push(`${prefix}${branch}${label}`);
|
|
55
|
+
const childPrefix = prefix === '' ? '' : prefix + (isLast ? ' ' : '│ ');
|
|
56
|
+
const children = node.children
|
|
57
|
+
.map((id) => geneById.get(id))
|
|
58
|
+
.filter((g): g is AgentGenealogy => !!g);
|
|
59
|
+
children.forEach((child, i) => {
|
|
60
|
+
walk(child, childPrefix, i === children.length - 1);
|
|
61
|
+
});
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
if (!roots.length) {
|
|
65
|
+
return '(empty genealogy)';
|
|
66
|
+
}
|
|
67
|
+
roots.forEach((root, i) => walk(root, '', i === roots.length - 1));
|
|
68
|
+
return lines.join('\n');
|
|
69
|
+
}
|
|
70
|
+
}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import type { PolicyRule } from '@hazeljs/agent';
|
|
2
|
+
import type { ConstitutionDefinition, ConstitutionRule } from '../types/organism.types';
|
|
3
|
+
import { OrganismConstitutionError } from '../errors/organism.errors';
|
|
4
|
+
import { OrganismEventEmitter, OrganismEventType } from '../events/organism-events';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Compiles constitution rules into PolicyEngine-compatible rules and
|
|
8
|
+
* evaluates lifecycle actions against critical/high constraints.
|
|
9
|
+
*/
|
|
10
|
+
export class ConstitutionEnforcer {
|
|
11
|
+
constructor(
|
|
12
|
+
private readonly constitution: ConstitutionDefinition | undefined,
|
|
13
|
+
private readonly events: OrganismEventEmitter,
|
|
14
|
+
private readonly organismId: string
|
|
15
|
+
) {}
|
|
16
|
+
|
|
17
|
+
getRules(): ConstitutionRule[] {
|
|
18
|
+
return this.constitution?.rules ?? [];
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/** Map critical/high textual rules into deny/approval PolicyEngine rules. */
|
|
22
|
+
toPolicyRules(): PolicyRule[] {
|
|
23
|
+
const rules = this.getRules();
|
|
24
|
+
const out: PolicyRule[] = [];
|
|
25
|
+
for (const rule of rules) {
|
|
26
|
+
if (rule.severity !== 'critical' && rule.severity !== 'high') continue;
|
|
27
|
+
const lower = rule.rule.toLowerCase();
|
|
28
|
+
if (lower.includes('pii') || lower.includes('personally identifiable')) {
|
|
29
|
+
out.push({
|
|
30
|
+
id: `constitution:${rule.id}`,
|
|
31
|
+
tool: '*',
|
|
32
|
+
effect: 'deny',
|
|
33
|
+
whenInputIncludes: 'ssn',
|
|
34
|
+
reason: rule.rule,
|
|
35
|
+
priority: 100,
|
|
36
|
+
});
|
|
37
|
+
out.push({
|
|
38
|
+
id: `constitution:${rule.id}:email`,
|
|
39
|
+
tool: '*',
|
|
40
|
+
effect: 'mask',
|
|
41
|
+
maskFields: ['email', 'phone', 'ssn', 'address'],
|
|
42
|
+
reason: rule.rule,
|
|
43
|
+
priority: 90,
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
if (lower.includes('refund') && (lower.includes('approval') || lower.includes('human'))) {
|
|
47
|
+
out.push({
|
|
48
|
+
id: `constitution:${rule.id}`,
|
|
49
|
+
tool: 'refund',
|
|
50
|
+
effect: 'require_approval',
|
|
51
|
+
reason: rule.rule,
|
|
52
|
+
priority: 100,
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
if (lower.includes('budget') || lower.includes('never exceed')) {
|
|
56
|
+
out.push({
|
|
57
|
+
id: `constitution:${rule.id}`,
|
|
58
|
+
tool: '*',
|
|
59
|
+
effect: 'require_approval',
|
|
60
|
+
whenInputIncludes: 'override_budget',
|
|
61
|
+
reason: rule.rule,
|
|
62
|
+
priority: 100,
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return out;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
assertAllows(action: string, context: Record<string, unknown> = {}): void {
|
|
70
|
+
for (const rule of this.getRules()) {
|
|
71
|
+
if (rule.severity !== 'critical' && rule.severity !== 'high') continue;
|
|
72
|
+
const lower = rule.rule.toLowerCase();
|
|
73
|
+
|
|
74
|
+
if (
|
|
75
|
+
(lower.includes('pii') || lower.includes('personally identifiable')) &&
|
|
76
|
+
context.exposesPii === true
|
|
77
|
+
) {
|
|
78
|
+
void this.events.emit(OrganismEventType.ORGANISM_CONSTITUTION_VIOLATION, this.organismId, {
|
|
79
|
+
ruleId: rule.id,
|
|
80
|
+
action,
|
|
81
|
+
rule: rule.rule,
|
|
82
|
+
});
|
|
83
|
+
throw new OrganismConstitutionError(`Constitution violation (${rule.id}): ${rule.rule}`);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if (lower.includes('budget') && context.exceedsBudget === true) {
|
|
87
|
+
void this.events.emit(OrganismEventType.ORGANISM_CONSTITUTION_VIOLATION, this.organismId, {
|
|
88
|
+
ruleId: rule.id,
|
|
89
|
+
action,
|
|
90
|
+
rule: rule.rule,
|
|
91
|
+
});
|
|
92
|
+
throw new OrganismConstitutionError(`Constitution violation (${rule.id}): ${rule.rule}`);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if (
|
|
96
|
+
lower.includes('refund') &&
|
|
97
|
+
typeof context.refundAmount === 'number' &&
|
|
98
|
+
context.refundAmount > 200 &&
|
|
99
|
+
context.humanApproved !== true
|
|
100
|
+
) {
|
|
101
|
+
const match = lower.match(/\$?(\d+)/);
|
|
102
|
+
const limit = match ? Number(match[1]) : 200;
|
|
103
|
+
if (context.refundAmount > limit) {
|
|
104
|
+
void this.events.emit(
|
|
105
|
+
OrganismEventType.ORGANISM_CONSTITUTION_VIOLATION,
|
|
106
|
+
this.organismId,
|
|
107
|
+
{ ruleId: rule.id, action, rule: rule.rule }
|
|
108
|
+
);
|
|
109
|
+
throw new OrganismConstitutionError(`Constitution violation (${rule.id}): ${rule.rule}`);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/** Child may only inherit a subset of parent permissions / capabilities. */
|
|
116
|
+
subsetCapabilities(parent: string[], requested: string[]): string[] {
|
|
117
|
+
const allowed = new Set(parent);
|
|
118
|
+
return requested.filter((c) => allowed.has(c));
|
|
119
|
+
}
|
|
120
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* In-process registry of live OrganismHost instances.
|
|
3
|
+
* Product layers (e.g. Zynli AutonomousRuntime) should use this instead of
|
|
4
|
+
* maintaining a parallel Map of hosts.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import type { OrganismHost } from './organism-host';
|
|
8
|
+
|
|
9
|
+
export class OrganismHostRegistry {
|
|
10
|
+
private readonly hosts = new Map<string, OrganismHost>();
|
|
11
|
+
|
|
12
|
+
get(id: string): OrganismHost | undefined {
|
|
13
|
+
return this.hosts.get(id);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
has(id: string): boolean {
|
|
17
|
+
return this.hosts.has(id);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
register(host: OrganismHost): void {
|
|
21
|
+
this.hosts.set(host.id, host);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
unregister(id: string): boolean {
|
|
25
|
+
return this.hosts.delete(id);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
list(): OrganismHost[] {
|
|
29
|
+
return [...this.hosts.values()];
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Return an existing host by id, or create/register a new one via factory.
|
|
34
|
+
* When `preferredId` is set and already registered, factory is not called.
|
|
35
|
+
*/
|
|
36
|
+
async getOrCreate(
|
|
37
|
+
preferredId: string | undefined,
|
|
38
|
+
factory: () => Promise<OrganismHost>
|
|
39
|
+
): Promise<OrganismHost> {
|
|
40
|
+
if (preferredId) {
|
|
41
|
+
const existing = this.hosts.get(preferredId);
|
|
42
|
+
if (existing) return existing;
|
|
43
|
+
}
|
|
44
|
+
const host = await factory();
|
|
45
|
+
this.hosts.set(host.id, host);
|
|
46
|
+
return host;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
async emergencyStop(id: string, reason?: string): Promise<boolean> {
|
|
50
|
+
const host = this.hosts.get(id);
|
|
51
|
+
if (!host) return false;
|
|
52
|
+
await host.emergencyStop(reason);
|
|
53
|
+
return true;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
async emergencyStopAll(reason?: string): Promise<string[]> {
|
|
57
|
+
const ids: string[] = [];
|
|
58
|
+
for (const host of this.hosts.values()) {
|
|
59
|
+
await host.emergencyStop(reason);
|
|
60
|
+
ids.push(host.id);
|
|
61
|
+
}
|
|
62
|
+
return ids;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
clear(): void {
|
|
66
|
+
this.hosts.clear();
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
get size(): number {
|
|
70
|
+
return this.hosts.size;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* App-facing OrganismHost — thin facade over OrganismRuntime for product services.
|
|
3
|
+
*
|
|
4
|
+
* Prefer this when embedding @hazeljs/organism in an ops / platform service
|
|
5
|
+
* instead of reinventing start/observe/inspect/simulate lifecycle wrappers.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import {
|
|
9
|
+
createOrganism,
|
|
10
|
+
type CreateOrganismOptions,
|
|
11
|
+
type SimulateOptions,
|
|
12
|
+
} from '../core/organism-runtime';
|
|
13
|
+
import type { OrganismRuntime } from '../core/organism-runtime';
|
|
14
|
+
import type {
|
|
15
|
+
AgentOutcomeReport,
|
|
16
|
+
EnvironmentSignal,
|
|
17
|
+
OrganismDecision,
|
|
18
|
+
OrganismInspectState,
|
|
19
|
+
} from '../types/organism.types';
|
|
20
|
+
|
|
21
|
+
export interface OrganismHost {
|
|
22
|
+
readonly id: string;
|
|
23
|
+
/** Underlying runtime for advanced use (genealogy, market, events). */
|
|
24
|
+
readonly runtime: OrganismRuntime;
|
|
25
|
+
start(): Promise<void>;
|
|
26
|
+
pause(): Promise<void>;
|
|
27
|
+
resume(): Promise<void>;
|
|
28
|
+
observe(
|
|
29
|
+
signal: Partial<EnvironmentSignal> & Pick<EnvironmentSignal, 'type' | 'source'>
|
|
30
|
+
): Promise<OrganismDecision | undefined>;
|
|
31
|
+
inspect(): Promise<OrganismInspectState>;
|
|
32
|
+
reportOutcome(agentId: string, report: AgentOutcomeReport): Promise<void>;
|
|
33
|
+
emergencyStop(reason?: string): Promise<void>;
|
|
34
|
+
terminate(reason?: string): Promise<void>;
|
|
35
|
+
simulate(options: SimulateOptions): Promise<OrganismInspectState>;
|
|
36
|
+
listAgents(): Promise<Awaited<ReturnType<OrganismRuntime['listAgents']>>>;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
class OrganismHostImpl implements OrganismHost {
|
|
40
|
+
constructor(public readonly runtime: OrganismRuntime) {}
|
|
41
|
+
|
|
42
|
+
get id(): string {
|
|
43
|
+
return this.runtime.id;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
start(): Promise<void> {
|
|
47
|
+
return this.runtime.start();
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
pause(): Promise<void> {
|
|
51
|
+
return this.runtime.pause();
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
resume(): Promise<void> {
|
|
55
|
+
return this.runtime.resume();
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
observe(
|
|
59
|
+
signal: Partial<EnvironmentSignal> & Pick<EnvironmentSignal, 'type' | 'source'>
|
|
60
|
+
): Promise<OrganismDecision | undefined> {
|
|
61
|
+
return this.runtime.observe(signal);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
inspect(): Promise<OrganismInspectState> {
|
|
65
|
+
return this.runtime.inspect();
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
reportOutcome(agentId: string, report: AgentOutcomeReport): Promise<void> {
|
|
69
|
+
return this.runtime.reportOutcome(agentId, report);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
async emergencyStop(reason?: string): Promise<void> {
|
|
73
|
+
void reason;
|
|
74
|
+
await this.runtime.emergencyStop();
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
async terminate(reason?: string): Promise<void> {
|
|
78
|
+
void reason;
|
|
79
|
+
await this.runtime.terminate();
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
simulate(options: SimulateOptions): Promise<OrganismInspectState> {
|
|
83
|
+
return this.runtime.simulate(options);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
listAgents(): Promise<Awaited<ReturnType<OrganismRuntime['listAgents']>>> {
|
|
87
|
+
return this.runtime.listAgents();
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Create an OrganismHost from the same options as createOrganism.
|
|
93
|
+
* This is the recommended entry point for external products (e.g. Zynli ops).
|
|
94
|
+
*/
|
|
95
|
+
export async function createOrganismHost(options: CreateOrganismOptions): Promise<OrganismHost> {
|
|
96
|
+
const runtime = await createOrganism(options);
|
|
97
|
+
return new OrganismHostImpl(runtime);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/** Wrap an existing OrganismRuntime as OrganismHost. */
|
|
101
|
+
export function wrapOrganismRuntime(runtime: OrganismRuntime): OrganismHost {
|
|
102
|
+
return new OrganismHostImpl(runtime);
|
|
103
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @hazeljs/organism
|
|
3
|
+
* Agentic Organism Runtime — mission-defined, self-organizing ephemeral agent societies.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import '@hazeljs/core';
|
|
7
|
+
|
|
8
|
+
export * from './types/organism.types';
|
|
9
|
+
export * from './errors/organism.errors';
|
|
10
|
+
export * from './events/organism-events';
|
|
11
|
+
export * from './persistence/organism-repository';
|
|
12
|
+
export { InMemoryOrganismRepository } from './persistence/organism-repository';
|
|
13
|
+
|
|
14
|
+
export {
|
|
15
|
+
Mission,
|
|
16
|
+
Organism,
|
|
17
|
+
AgentGene,
|
|
18
|
+
Environment,
|
|
19
|
+
Constitution,
|
|
20
|
+
Resource,
|
|
21
|
+
getMissionMetadata,
|
|
22
|
+
getOrganismMetadata,
|
|
23
|
+
getAgentGeneMetadata,
|
|
24
|
+
getEnvironmentMetadata,
|
|
25
|
+
getConstitutionMetadata,
|
|
26
|
+
getResourceMetadata,
|
|
27
|
+
getRegisteredMissions,
|
|
28
|
+
getRegisteredOrganisms,
|
|
29
|
+
getRegisteredGenes,
|
|
30
|
+
getRegisteredEnvironments,
|
|
31
|
+
getRegisteredConstitutions,
|
|
32
|
+
getRegisteredResources,
|
|
33
|
+
resolveMission,
|
|
34
|
+
resolveGene,
|
|
35
|
+
resolveEnvironment,
|
|
36
|
+
resolveConstitution,
|
|
37
|
+
resolveResource,
|
|
38
|
+
} from './decorators';
|
|
39
|
+
|
|
40
|
+
export { OrganismRuntime, createOrganism } from './core/organism-runtime';
|
|
41
|
+
export type { CreateOrganismOptions, SimulateOptions } from './core/organism-runtime';
|
|
42
|
+
export { OrganismAgentContext } from './core/organism-context';
|
|
43
|
+
export { CapabilityRegistry } from './core/capability-registry';
|
|
44
|
+
export { createMissionProgress, applyMissionMetricUpdates } from './core/mission';
|
|
45
|
+
export { OrganismClock, parseDurationMs } from './core/clock';
|
|
46
|
+
|
|
47
|
+
export { PerceptionEngine, NeedDetector } from './perception/perception-engine';
|
|
48
|
+
export { DecisionEngine } from './lifecycle/decision-engine';
|
|
49
|
+
export { BirthEngine, TerminationEngine, resetAgentSeqForTests } from './lifecycle/birth-engine';
|
|
50
|
+
export { SurvivalEngine } from './lifecycle/survival-engine';
|
|
51
|
+
export { ReproductionEngine, DEFAULT_REPRODUCTION_CONFIG } from './lifecycle/reproduction-engine';
|
|
52
|
+
export type { ReproductionConfig } from './lifecycle/reproduction-engine';
|
|
53
|
+
export { GenealogyManager } from './genealogy/genealogy-manager';
|
|
54
|
+
export { MutationEngine } from './evolution/mutation-engine';
|
|
55
|
+
export type { MutationRequest } from './evolution/mutation-engine';
|
|
56
|
+
export { EvolutionEngine, GenerationManager } from './evolution/evolution-engine';
|
|
57
|
+
|
|
58
|
+
export { ResourceAllocator, createEmptyWallet, throwIfDenied } from './economy/resource-allocator';
|
|
59
|
+
export { UtilityEngine, ReputationEngine } from './economy/utility-engine';
|
|
60
|
+
export { UtilityForecaster } from './economy/utility-forecaster';
|
|
61
|
+
export { MarketEngine, resetBidSeqForTests } from './economy/market-engine';
|
|
62
|
+
export { ConstitutionEnforcer } from './governance/constitution';
|
|
63
|
+
export { OrganismMetrics } from './observability/metrics';
|
|
64
|
+
export type { OrganismMetricsSnapshot } from './observability/metrics';
|
|
65
|
+
|
|
66
|
+
/** App embedding / product-platform boilerplate */
|
|
67
|
+
export { createOrganismHost, wrapOrganismRuntime } from './host/organism-host';
|
|
68
|
+
export type { OrganismHost } from './host/organism-host';
|
|
69
|
+
export { OrganismHostRegistry } from './host/organism-host-registry';
|
|
70
|
+
export {
|
|
71
|
+
toEnvironmentSignal,
|
|
72
|
+
toIncidentEnvironmentSignal,
|
|
73
|
+
incidentNeedMappings,
|
|
74
|
+
toAgentOutcomeReport,
|
|
75
|
+
} from './bridge/signal-bridge';
|
|
76
|
+
export type { ExternalSignalLike, OutcomeVerdictLike } from './bridge/signal-bridge';
|
|
77
|
+
export { createOpsOrganism } from './integration/create-ops-organism';
|
|
78
|
+
export type { CreateOpsOrganismOptions } from './integration/create-ops-organism';
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Boilerplate factory for ops-style organisms used by product platforms.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import type { CreateOrganismOptions } from '../core/organism-runtime';
|
|
6
|
+
import { createOrganismHost, type OrganismHost } from '../host/organism-host';
|
|
7
|
+
import { incidentNeedMappings } from '../bridge/signal-bridge';
|
|
8
|
+
import type {
|
|
9
|
+
AgentGeneDefinition,
|
|
10
|
+
ConstitutionDefinition,
|
|
11
|
+
MissionDefinition,
|
|
12
|
+
MissionMetric,
|
|
13
|
+
OrganismLimits,
|
|
14
|
+
ResourceDefinition,
|
|
15
|
+
SignalNeedMapping,
|
|
16
|
+
} from '../types/organism.types';
|
|
17
|
+
import { DEFAULT_ORGANISM_LIMITS } from '../types/organism.types';
|
|
18
|
+
import type { OrganismRepository } from '../persistence/organism-repository';
|
|
19
|
+
|
|
20
|
+
export interface CreateOpsOrganismOptions {
|
|
21
|
+
id?: string;
|
|
22
|
+
mission:
|
|
23
|
+
| MissionDefinition
|
|
24
|
+
| {
|
|
25
|
+
id: string;
|
|
26
|
+
objective: string;
|
|
27
|
+
successCriteria?: MissionMetric[];
|
|
28
|
+
constraints?: string[];
|
|
29
|
+
};
|
|
30
|
+
genes: AgentGeneDefinition[];
|
|
31
|
+
constitution?: ConstitutionDefinition;
|
|
32
|
+
/** Direct signal→need mappings from the vertical pack. */
|
|
33
|
+
signalNeedMappings?: SignalNeedMapping[];
|
|
34
|
+
/** Incident types detected outside organism (e.g. refund_spike). */
|
|
35
|
+
incidentTypes?: string[];
|
|
36
|
+
/** Capabilities used when routing incident.* observations. */
|
|
37
|
+
investigationCapabilities?: string[];
|
|
38
|
+
limits?: Partial<OrganismLimits>;
|
|
39
|
+
resources?: ResourceDefinition;
|
|
40
|
+
repository?: OrganismRepository;
|
|
41
|
+
simulation?: boolean;
|
|
42
|
+
debug?: boolean;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Create an organism configured for autonomous operations embedding.
|
|
47
|
+
* Does not include vertical detectors/policies — those stay in the product layer.
|
|
48
|
+
*/
|
|
49
|
+
export async function createOpsOrganism(options: CreateOpsOrganismOptions): Promise<OrganismHost> {
|
|
50
|
+
const investigationCaps = options.investigationCapabilities ??
|
|
51
|
+
options.genes.find((g) => g.capabilities.length > 0)?.capabilities ?? ['operations'];
|
|
52
|
+
|
|
53
|
+
const incidentMappings = incidentNeedMappings(options.incidentTypes ?? [], investigationCaps);
|
|
54
|
+
|
|
55
|
+
const createOptions: CreateOrganismOptions = {
|
|
56
|
+
id: options.id,
|
|
57
|
+
mission: {
|
|
58
|
+
id: options.mission.id,
|
|
59
|
+
objective: options.mission.objective,
|
|
60
|
+
successCriteria: options.mission.successCriteria,
|
|
61
|
+
constraints: options.mission.constraints,
|
|
62
|
+
},
|
|
63
|
+
genes: options.genes,
|
|
64
|
+
constitution: options.constitution,
|
|
65
|
+
signalNeedMappings: [...(options.signalNeedMappings ?? []), ...incidentMappings],
|
|
66
|
+
limits: {
|
|
67
|
+
...DEFAULT_ORGANISM_LIMITS,
|
|
68
|
+
...options.limits,
|
|
69
|
+
},
|
|
70
|
+
resources: options.resources ?? {
|
|
71
|
+
tokenBudget: 500_000,
|
|
72
|
+
maxConcurrentAgents: options.limits?.maxAgents ?? DEFAULT_ORGANISM_LIMITS.maxAgents,
|
|
73
|
+
},
|
|
74
|
+
repository: options.repository,
|
|
75
|
+
simulation: options.simulation ?? false,
|
|
76
|
+
debug: options.debug ?? false,
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
return createOrganismHost(createOptions);
|
|
80
|
+
}
|