hebbian 0.3.3 → 0.3.4
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/dist/bin/hebbian.js +289 -0
- package/dist/bin/hebbian.js.map +1 -1
- package/dist/evolve.d.ts +22 -0
- package/dist/evolve.d.ts.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +234 -0
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/evolve.d.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { Episode } from './episode';
|
|
2
|
+
import type { Brain } from './types';
|
|
3
|
+
export interface EvolveAction {
|
|
4
|
+
type: 'grow' | 'fire' | 'signal' | 'prune' | 'decay';
|
|
5
|
+
path: string;
|
|
6
|
+
reason: string;
|
|
7
|
+
signal?: string;
|
|
8
|
+
}
|
|
9
|
+
export interface EvolveResult {
|
|
10
|
+
actions: EvolveAction[];
|
|
11
|
+
executed: number;
|
|
12
|
+
skipped: number;
|
|
13
|
+
dryRun: boolean;
|
|
14
|
+
}
|
|
15
|
+
export declare function runEvolve(brainRoot: string, dryRun: boolean): Promise<EvolveResult>;
|
|
16
|
+
export declare function buildBrainSummary(brain: Brain): string;
|
|
17
|
+
export declare function buildPrompt(summary: string, episodes: Episode[]): string;
|
|
18
|
+
export declare function callGemini(prompt: string, apiKey: string): Promise<EvolveAction[]>;
|
|
19
|
+
export declare function parseActions(text: string): EvolveAction[];
|
|
20
|
+
export declare function validateActions(actions: EvolveAction[], _brain: Brain): EvolveAction[];
|
|
21
|
+
export declare function executeActions(brainRoot: string, actions: EvolveAction[]): number;
|
|
22
|
+
//# sourceMappingURL=evolve.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"evolve.d.ts","sourceRoot":"","sources":["../src/evolve.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEzC,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAWrC,MAAM,WAAW,YAAY;IAC5B,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,QAAQ,GAAG,OAAO,GAAG,OAAO,CAAC;IACrD,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,YAAY;IAC5B,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,OAAO,CAAC;CAChB;AAUD,wBAAsB,SAAS,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG,OAAO,CAAC,YAAY,CAAC,CA+CzF;AAID,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,CAuBtD;AAID,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,MAAM,CAsCxE;AAID,wBAAsB,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CAyDxF;AAID,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,EAAE,CA8BzD;AAID,wBAAgB,eAAe,CAAC,OAAO,EAAE,YAAY,EAAE,EAAE,MAAM,EAAE,KAAK,GAAG,YAAY,EAAE,CAmBtF;AAID,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,EAAE,GAAG,MAAM,CA8BjF"}
|
package/dist/index.d.ts
CHANGED
|
@@ -27,4 +27,6 @@ export type { HookStatus } from './hooks';
|
|
|
27
27
|
export { digestTranscript, extractCorrections, readHookInput } from './digest';
|
|
28
28
|
export type { DigestResult, ExtractedCorrection } from './digest';
|
|
29
29
|
export { resolveBrainRoot } from './constants';
|
|
30
|
+
export { runEvolve } from './evolve';
|
|
31
|
+
export type { EvolveAction, EvolveResult } from './evolve';
|
|
30
32
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,cAAc,SAAS,CAAC;AACxB,cAAc,aAAa,CAAC;AAC5B,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACjE,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,QAAQ,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AACxC,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AACpC,YAAY,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AACzC,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACnC,YAAY,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAC3C,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACnC,YAAY,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAC3C,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AACnC,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,eAAe,EAAE,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AAG3G,OAAO,EAAE,QAAQ,EAAE,eAAe,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AACnF,YAAY,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACrD,YAAY,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AACtE,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAGvD,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACnE,YAAY,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAC1C,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAC/E,YAAY,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AAClE,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,cAAc,SAAS,CAAC;AACxB,cAAc,aAAa,CAAC;AAC5B,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACjE,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,QAAQ,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AACxC,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AACpC,YAAY,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AACzC,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACnC,YAAY,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAC3C,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACnC,YAAY,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAC3C,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AACnC,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,eAAe,EAAE,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AAG3G,OAAO,EAAE,QAAQ,EAAE,eAAe,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AACnF,YAAY,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACrD,YAAY,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AACtE,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAGvD,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACnE,YAAY,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAC1C,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAC/E,YAAY,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AAClE,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAG/C,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AACrC,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1823,6 +1823,239 @@ function writeAuditLog(brainRoot, sessionId, entries) {
|
|
|
1823
1823
|
);
|
|
1824
1824
|
writeFileSync11(logPath, lines.join("\n") + (lines.length > 0 ? "\n" : ""), "utf8");
|
|
1825
1825
|
}
|
|
1826
|
+
|
|
1827
|
+
// src/evolve.ts
|
|
1828
|
+
var MAX_ACTIONS = 10;
|
|
1829
|
+
var PROTECTED_REGIONS = ["brainstem", "limbic", "sensors"];
|
|
1830
|
+
var DEFAULT_MODEL = "gemini-2.0-flash-lite";
|
|
1831
|
+
var API_TIMEOUT = 3e4;
|
|
1832
|
+
var RETRY_DELAY = 5e3;
|
|
1833
|
+
async function runEvolve(brainRoot, dryRun) {
|
|
1834
|
+
const apiKey = process.env.GEMINI_API_KEY;
|
|
1835
|
+
if (!apiKey) {
|
|
1836
|
+
console.error("\u274C GEMINI_API_KEY not set. Get one at https://aistudio.google.com/apikey");
|
|
1837
|
+
return { actions: [], executed: 0, skipped: 0, dryRun };
|
|
1838
|
+
}
|
|
1839
|
+
const episodes = readEpisodes(brainRoot);
|
|
1840
|
+
const brain = scanBrain(brainRoot);
|
|
1841
|
+
const summary = buildBrainSummary(brain);
|
|
1842
|
+
const prompt = buildPrompt(summary, episodes);
|
|
1843
|
+
let rawActions;
|
|
1844
|
+
try {
|
|
1845
|
+
rawActions = await callGemini(prompt, apiKey);
|
|
1846
|
+
} catch (err) {
|
|
1847
|
+
const msg = err.message;
|
|
1848
|
+
console.log(`\u23ED\uFE0F evolve skipped: ${msg}`);
|
|
1849
|
+
logEpisode(brainRoot, "evolve-error", "", msg);
|
|
1850
|
+
return { actions: [], executed: 0, skipped: 0, dryRun };
|
|
1851
|
+
}
|
|
1852
|
+
const actions = validateActions(rawActions, brain);
|
|
1853
|
+
const skipped = rawActions.length - actions.length;
|
|
1854
|
+
if (actions.length === 0) {
|
|
1855
|
+
console.log("\u{1F9E0} evolve: no valid actions proposed");
|
|
1856
|
+
return { actions: [], executed: 0, skipped, dryRun };
|
|
1857
|
+
}
|
|
1858
|
+
if (dryRun) {
|
|
1859
|
+
console.log(`\u{1F9E0} evolve (dry-run): ${actions.length} action(s) proposed`);
|
|
1860
|
+
for (const action of actions) {
|
|
1861
|
+
console.log(` ${actionIcon(action.type)} ${action.type} ${action.path} \u2014 ${action.reason}`);
|
|
1862
|
+
}
|
|
1863
|
+
return { actions, executed: 0, skipped, dryRun: true };
|
|
1864
|
+
}
|
|
1865
|
+
const executed = executeActions(brainRoot, actions);
|
|
1866
|
+
logEpisode(brainRoot, "evolve", "", `${executed} action(s) executed, ${skipped} skipped`);
|
|
1867
|
+
console.log(`\u{1F9E0} evolve: ${executed} action(s) executed, ${skipped} skipped`);
|
|
1868
|
+
return { actions, executed, skipped, dryRun: false };
|
|
1869
|
+
}
|
|
1870
|
+
function buildBrainSummary(brain) {
|
|
1871
|
+
const lines = ["# Brain State\n"];
|
|
1872
|
+
for (const region of brain.regions) {
|
|
1873
|
+
const neurons = region.neurons;
|
|
1874
|
+
if (neurons.length === 0 && !region.hasBomb) continue;
|
|
1875
|
+
lines.push(`## ${region.name} (P${REGION_PRIORITY[region.name]})`);
|
|
1876
|
+
if (region.hasBomb) lines.push("\u26A0\uFE0F BOMB active \u2014 region blocked");
|
|
1877
|
+
for (const neuron of neurons) {
|
|
1878
|
+
const flags = [];
|
|
1879
|
+
if (neuron.isDormant) flags.push("dormant");
|
|
1880
|
+
if (neuron.hasBomb) flags.push("bomb");
|
|
1881
|
+
if (neuron.hasMemory) flags.push("memory");
|
|
1882
|
+
if (neuron.dopamine > 0) flags.push(`dopamine:${neuron.dopamine}`);
|
|
1883
|
+
const flagStr = flags.length > 0 ? ` [${flags.join(", ")}]` : "";
|
|
1884
|
+
lines.push(`- ${neuron.path} (counter:${neuron.counter}, intensity:${neuron.intensity})${flagStr}`);
|
|
1885
|
+
}
|
|
1886
|
+
lines.push("");
|
|
1887
|
+
}
|
|
1888
|
+
return lines.join("\n");
|
|
1889
|
+
}
|
|
1890
|
+
function buildPrompt(summary, episodes) {
|
|
1891
|
+
const episodeLines = episodes.length > 0 ? episodes.map((e) => `- [${e.ts}] ${e.type}: ${e.path} \u2014 ${e.detail}`).join("\n") : "(no recent episodes)";
|
|
1892
|
+
return `You are the evolve engine for a hebbian brain \u2014 a filesystem-based memory system for AI agents.
|
|
1893
|
+
|
|
1894
|
+
## Axioms
|
|
1895
|
+
- Folder = Neuron, File = Firing Trace, Counter = Activation strength
|
|
1896
|
+
- 7 regions in subsumption cascade: brainstem(P0) > limbic(P1) > hippocampus(P2) > sensors(P3) > cortex(P4) > ego(P5) > prefrontal(P6)
|
|
1897
|
+
- Lower priority ALWAYS overrides higher priority
|
|
1898
|
+
- PROTECTED regions (brainstem, limbic, sensors): NEVER propose mutations for these
|
|
1899
|
+
|
|
1900
|
+
## Current Brain
|
|
1901
|
+
${summary}
|
|
1902
|
+
|
|
1903
|
+
## Recent Episodes (last ${episodes.length})
|
|
1904
|
+
${episodeLines}
|
|
1905
|
+
|
|
1906
|
+
## Available Actions
|
|
1907
|
+
- grow: Create a new neuron at the given path (region/name). Use for recurring patterns that deserve permanent memory.
|
|
1908
|
+
- fire: Increment an existing neuron's counter. Use for strengthening well-confirmed rules.
|
|
1909
|
+
- signal: Add dopamine (reward), bomb (block), or memory signal. Use sparingly.
|
|
1910
|
+
- prune: Decrement a neuron's counter. Use for rules that aren't working or cause issues.
|
|
1911
|
+
- decay: Mark inactive neurons as dormant. Use for stale rules with no recent activity.
|
|
1912
|
+
|
|
1913
|
+
## Constraints
|
|
1914
|
+
- Max ${MAX_ACTIONS} actions per cycle
|
|
1915
|
+
- PREFER fire over grow \u2014 strengthen existing neurons before creating new ones
|
|
1916
|
+
- NEVER target brainstem, limbic, or sensors regions
|
|
1917
|
+
- Each action needs a "reason" explaining why
|
|
1918
|
+
|
|
1919
|
+
## Task
|
|
1920
|
+
Analyze the brain state and recent episodes. Propose actions to improve the brain.
|
|
1921
|
+
Focus on: strengthening repeatedly-used rules, pruning ineffective ones, growing new neurons from repeated patterns.
|
|
1922
|
+
|
|
1923
|
+
Respond with a JSON array of actions:
|
|
1924
|
+
[{"type":"fire","path":"cortex/NO_console_log","reason":"fired 3 times in recent sessions"}]`;
|
|
1925
|
+
}
|
|
1926
|
+
async function callGemini(prompt, apiKey) {
|
|
1927
|
+
const model = process.env.EVOLVE_MODEL || DEFAULT_MODEL;
|
|
1928
|
+
const url = `https://generativelanguage.googleapis.com/v1beta/models/${model}:generateContent?key=${apiKey}`;
|
|
1929
|
+
const body = {
|
|
1930
|
+
contents: [{ parts: [{ text: prompt }] }],
|
|
1931
|
+
generationConfig: {
|
|
1932
|
+
responseMimeType: "application/json",
|
|
1933
|
+
temperature: 0.2
|
|
1934
|
+
}
|
|
1935
|
+
};
|
|
1936
|
+
let lastError = null;
|
|
1937
|
+
for (let attempt = 0; attempt < 2; attempt++) {
|
|
1938
|
+
if (attempt > 0) {
|
|
1939
|
+
await new Promise((r) => setTimeout(r, RETRY_DELAY));
|
|
1940
|
+
}
|
|
1941
|
+
try {
|
|
1942
|
+
const res = await fetch(url, {
|
|
1943
|
+
method: "POST",
|
|
1944
|
+
headers: { "Content-Type": "application/json" },
|
|
1945
|
+
body: JSON.stringify(body),
|
|
1946
|
+
signal: AbortSignal.timeout(API_TIMEOUT)
|
|
1947
|
+
});
|
|
1948
|
+
if (!res.ok) {
|
|
1949
|
+
lastError = new Error(`Gemini API ${res.status}: ${res.statusText}`);
|
|
1950
|
+
continue;
|
|
1951
|
+
}
|
|
1952
|
+
const data = await res.json();
|
|
1953
|
+
if (data.error) {
|
|
1954
|
+
lastError = new Error(`Gemini error: ${data.error.message || "unknown"}`);
|
|
1955
|
+
continue;
|
|
1956
|
+
}
|
|
1957
|
+
const text = data.candidates?.[0]?.content?.parts?.[0]?.text;
|
|
1958
|
+
if (!text) {
|
|
1959
|
+
lastError = new Error("Gemini returned empty response");
|
|
1960
|
+
continue;
|
|
1961
|
+
}
|
|
1962
|
+
return parseActions(text);
|
|
1963
|
+
} catch (err) {
|
|
1964
|
+
lastError = err;
|
|
1965
|
+
continue;
|
|
1966
|
+
}
|
|
1967
|
+
}
|
|
1968
|
+
throw lastError || new Error("Gemini call failed");
|
|
1969
|
+
}
|
|
1970
|
+
function parseActions(text) {
|
|
1971
|
+
let parsed;
|
|
1972
|
+
try {
|
|
1973
|
+
parsed = JSON.parse(text);
|
|
1974
|
+
} catch {
|
|
1975
|
+
throw new Error(`Failed to parse LLM response as JSON: ${text.slice(0, 100)}`);
|
|
1976
|
+
}
|
|
1977
|
+
if (!Array.isArray(parsed)) {
|
|
1978
|
+
throw new Error("LLM response is not an array");
|
|
1979
|
+
}
|
|
1980
|
+
const validTypes = /* @__PURE__ */ new Set(["grow", "fire", "signal", "prune", "decay"]);
|
|
1981
|
+
const actions = [];
|
|
1982
|
+
for (const item of parsed) {
|
|
1983
|
+
if (!item || typeof item !== "object") continue;
|
|
1984
|
+
const { type, path, reason, signal } = item;
|
|
1985
|
+
if (typeof type !== "string" || !validTypes.has(type)) continue;
|
|
1986
|
+
if (typeof path !== "string" || path.length === 0) continue;
|
|
1987
|
+
if (typeof reason !== "string") continue;
|
|
1988
|
+
const action = { type, path, reason };
|
|
1989
|
+
if (type === "signal" && typeof signal === "string") {
|
|
1990
|
+
action.signal = signal;
|
|
1991
|
+
}
|
|
1992
|
+
actions.push(action);
|
|
1993
|
+
}
|
|
1994
|
+
return actions;
|
|
1995
|
+
}
|
|
1996
|
+
function validateActions(actions, _brain) {
|
|
1997
|
+
return actions.filter((action) => {
|
|
1998
|
+
const region = action.path.split("/")[0];
|
|
1999
|
+
if (!region || PROTECTED_REGIONS.includes(region)) {
|
|
2000
|
+
console.log(` \u{1F6E1}\uFE0F blocked: ${action.type} ${action.path} (protected region)`);
|
|
2001
|
+
return false;
|
|
2002
|
+
}
|
|
2003
|
+
if (!REGIONS.includes(region)) {
|
|
2004
|
+
console.log(` \u26A0\uFE0F skipped: ${action.type} ${action.path} (invalid region)`);
|
|
2005
|
+
return false;
|
|
2006
|
+
}
|
|
2007
|
+
if (action.type === "signal" && action.signal && !["dopamine", "bomb", "memory"].includes(action.signal)) {
|
|
2008
|
+
console.log(` \u26A0\uFE0F skipped: signal ${action.path} (invalid signal type: ${action.signal})`);
|
|
2009
|
+
return false;
|
|
2010
|
+
}
|
|
2011
|
+
return true;
|
|
2012
|
+
}).slice(0, MAX_ACTIONS);
|
|
2013
|
+
}
|
|
2014
|
+
function executeActions(brainRoot, actions) {
|
|
2015
|
+
let executed = 0;
|
|
2016
|
+
for (const action of actions) {
|
|
2017
|
+
try {
|
|
2018
|
+
switch (action.type) {
|
|
2019
|
+
case "fire":
|
|
2020
|
+
fireNeuron(brainRoot, action.path);
|
|
2021
|
+
break;
|
|
2022
|
+
case "grow":
|
|
2023
|
+
growNeuron(brainRoot, action.path);
|
|
2024
|
+
break;
|
|
2025
|
+
case "signal":
|
|
2026
|
+
signalNeuron(brainRoot, action.path, action.signal || "dopamine");
|
|
2027
|
+
break;
|
|
2028
|
+
case "prune":
|
|
2029
|
+
rollbackNeuron(brainRoot, action.path);
|
|
2030
|
+
break;
|
|
2031
|
+
case "decay":
|
|
2032
|
+
runDecay(brainRoot, 0);
|
|
2033
|
+
break;
|
|
2034
|
+
}
|
|
2035
|
+
console.log(` ${actionIcon(action.type)} ${action.type} ${action.path}`);
|
|
2036
|
+
executed++;
|
|
2037
|
+
} catch (err) {
|
|
2038
|
+
console.log(` \u26A0\uFE0F failed: ${action.type} ${action.path} \u2014 ${err.message}`);
|
|
2039
|
+
}
|
|
2040
|
+
}
|
|
2041
|
+
return executed;
|
|
2042
|
+
}
|
|
2043
|
+
function actionIcon(type) {
|
|
2044
|
+
switch (type) {
|
|
2045
|
+
case "fire":
|
|
2046
|
+
return "\u{1F525}";
|
|
2047
|
+
case "grow":
|
|
2048
|
+
return "\u{1F331}";
|
|
2049
|
+
case "signal":
|
|
2050
|
+
return "\u26A1";
|
|
2051
|
+
case "prune":
|
|
2052
|
+
return "\u2702\uFE0F";
|
|
2053
|
+
case "decay":
|
|
2054
|
+
return "\u{1F4A4}";
|
|
2055
|
+
default:
|
|
2056
|
+
return "\u2753";
|
|
2057
|
+
}
|
|
2058
|
+
}
|
|
1826
2059
|
export {
|
|
1827
2060
|
DECAY_DAYS,
|
|
1828
2061
|
DIGEST_LOG_DIR,
|
|
@@ -1869,6 +2102,7 @@ export {
|
|
|
1869
2102
|
rollbackNeuron,
|
|
1870
2103
|
runDecay,
|
|
1871
2104
|
runDedup,
|
|
2105
|
+
runEvolve,
|
|
1872
2106
|
runSubsumption,
|
|
1873
2107
|
scanBrain,
|
|
1874
2108
|
signalNeuron,
|