@zhijiewang/openharness 2.0.0 → 2.3.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.
- package/README.md +4 -4
- package/dist/DeferredTool.js +3 -1
- package/dist/Tool.d.ts +1 -1
- package/dist/agents/roles.js +58 -62
- package/dist/commands/cybergotchi.d.ts +1 -1
- package/dist/commands/cybergotchi.js +30 -30
- package/dist/commands/index.js +360 -122
- package/dist/components/App.d.ts +1 -1
- package/dist/components/App.js +6 -6
- package/dist/components/CompanionFooter.d.ts +1 -1
- package/dist/components/CompanionFooter.js +6 -8
- package/dist/components/CybergotchiBubble.js +5 -5
- package/dist/components/CybergotchiPanel.d.ts +1 -1
- package/dist/components/CybergotchiPanel.js +7 -7
- package/dist/components/CybergotchiPanelConnected.js +2 -2
- package/dist/components/CybergotchiSetup.js +26 -24
- package/dist/components/CybergotchiSprite.d.ts +1 -1
- package/dist/components/CybergotchiSprite.js +8 -12
- package/dist/components/DiffView.d.ts +1 -1
- package/dist/components/DiffView.js +10 -10
- package/dist/components/ErrorBoundary.d.ts +1 -1
- package/dist/components/ErrorBoundary.js +1 -1
- package/dist/components/InitWizard.js +65 -33
- package/dist/components/Markdown.js +2 -4
- package/dist/components/Messages.js +4 -4
- package/dist/components/PermissionPrompt.d.ts +1 -1
- package/dist/components/PermissionPrompt.js +15 -17
- package/dist/components/REPL.d.ts +1 -1
- package/dist/components/REPL.js +74 -49
- package/dist/components/Spinner.js +2 -2
- package/dist/components/TextInput.js +35 -29
- package/dist/components/ToolCallDisplay.js +3 -5
- package/dist/cybergotchi/bones.d.ts +1 -1
- package/dist/cybergotchi/bones.js +8 -8
- package/dist/cybergotchi/config.d.ts +2 -2
- package/dist/cybergotchi/config.js +13 -13
- package/dist/cybergotchi/events.d.ts +5 -5
- package/dist/cybergotchi/events.js +7 -7
- package/dist/cybergotchi/needs.d.ts +2 -2
- package/dist/cybergotchi/needs.js +7 -9
- package/dist/cybergotchi/personality.d.ts +2 -2
- package/dist/cybergotchi/personality.js +2 -2
- package/dist/cybergotchi/species.d.ts +1 -1
- package/dist/cybergotchi/species.js +145 -217
- package/dist/cybergotchi/speech.d.ts +2 -2
- package/dist/cybergotchi/speech.js +43 -43
- package/dist/cybergotchi/types.d.ts +4 -4
- package/dist/cybergotchi/types.js +26 -26
- package/dist/cybergotchi/useCybergotchi.d.ts +1 -1
- package/dist/cybergotchi/useCybergotchi.js +29 -25
- package/dist/git/index.js +11 -9
- package/dist/harness/checkpoints.js +29 -21
- package/dist/harness/config.d.ts +12 -2
- package/dist/harness/config.js +15 -9
- package/dist/harness/context-warning.d.ts +1 -1
- package/dist/harness/context-warning.js +1 -1
- package/dist/harness/cost.js +1 -1
- package/dist/harness/credentials.js +13 -13
- package/dist/harness/hooks.js +7 -5
- package/dist/harness/keybindings.js +20 -18
- package/dist/harness/marketplace.d.ts +3 -3
- package/dist/harness/marketplace.js +55 -42
- package/dist/harness/memory.d.ts +23 -5
- package/dist/harness/memory.js +142 -41
- package/dist/harness/onboarding.js +30 -10
- package/dist/harness/plugins.d.ts +9 -1
- package/dist/harness/plugins.js +54 -30
- package/dist/harness/rules.js +12 -7
- package/dist/harness/sandbox.d.ts +34 -0
- package/dist/harness/sandbox.js +104 -0
- package/dist/harness/session-db.d.ts +55 -0
- package/dist/harness/session-db.js +165 -0
- package/dist/harness/session.d.ts +1 -1
- package/dist/harness/session.js +34 -15
- package/dist/harness/store.d.ts +3 -3
- package/dist/harness/store.js +6 -4
- package/dist/harness/submit-handler.d.ts +4 -4
- package/dist/harness/submit-handler.js +57 -21
- package/dist/harness/telemetry.d.ts +1 -1
- package/dist/harness/telemetry.js +23 -19
- package/dist/harness/traces.d.ts +2 -2
- package/dist/harness/traces.js +44 -33
- package/dist/harness/verification.d.ts +1 -1
- package/dist/harness/verification.js +50 -44
- package/dist/lsp/client.js +44 -40
- package/dist/main.js +100 -59
- package/dist/mcp/DeferredMcpTool.d.ts +4 -4
- package/dist/mcp/DeferredMcpTool.js +9 -5
- package/dist/mcp/McpTool.d.ts +4 -4
- package/dist/mcp/McpTool.js +8 -4
- package/dist/mcp/client.d.ts +2 -2
- package/dist/mcp/client.js +21 -21
- package/dist/mcp/loader.d.ts +1 -1
- package/dist/mcp/loader.js +17 -12
- package/dist/mcp/registry.d.ts +3 -3
- package/dist/mcp/registry.js +97 -97
- package/dist/mcp/schema.d.ts +1 -1
- package/dist/mcp/schema.js +16 -16
- package/dist/mcp/server.d.ts +1 -1
- package/dist/mcp/server.js +21 -21
- package/dist/mcp/types.d.ts +3 -3
- package/dist/providers/anthropic.d.ts +2 -2
- package/dist/providers/anthropic.js +10 -9
- package/dist/providers/base.d.ts +1 -1
- package/dist/providers/index.js +10 -3
- package/dist/providers/llamacpp.d.ts +2 -2
- package/dist/providers/llamacpp.js +1 -3
- package/dist/providers/ollama.d.ts +2 -2
- package/dist/providers/ollama.js +3 -4
- package/dist/providers/openai.d.ts +2 -2
- package/dist/providers/openai.js +3 -5
- package/dist/providers/openrouter.d.ts +2 -2
- package/dist/providers/router.d.ts +1 -1
- package/dist/providers/router.js +7 -7
- package/dist/query/compress.d.ts +2 -2
- package/dist/query/compress.js +22 -21
- package/dist/query/context-manager.d.ts +2 -2
- package/dist/query/context-manager.js +8 -11
- package/dist/query/errors.js +1 -1
- package/dist/query/index.d.ts +1 -1
- package/dist/query/index.js +30 -22
- package/dist/query/tools.js +15 -12
- package/dist/query/types.d.ts +1 -1
- package/dist/query.d.ts +1 -1
- package/dist/query.js +1 -1
- package/dist/remote/auth.d.ts +2 -2
- package/dist/remote/auth.js +8 -8
- package/dist/remote/server.d.ts +3 -3
- package/dist/remote/server.js +60 -60
- package/dist/renderer/cells.js +9 -9
- package/dist/renderer/colors.js +24 -6
- package/dist/renderer/diff.d.ts +2 -2
- package/dist/renderer/diff.js +27 -19
- package/dist/renderer/differ.d.ts +1 -1
- package/dist/renderer/differ.js +9 -9
- package/dist/renderer/image.js +19 -19
- package/dist/renderer/index.d.ts +6 -6
- package/dist/renderer/index.js +163 -93
- package/dist/renderer/input.js +66 -48
- package/dist/renderer/layout.d.ts +6 -6
- package/dist/renderer/layout.js +163 -124
- package/dist/renderer/markdown.d.ts +2 -2
- package/dist/renderer/markdown.js +173 -54
- package/dist/renderer/session-browser.d.ts +2 -2
- package/dist/renderer/session-browser.js +19 -21
- package/dist/repl.d.ts +5 -5
- package/dist/repl.js +300 -198
- package/dist/sdk/index.d.ts +8 -7
- package/dist/sdk/index.js +59 -42
- package/dist/services/AgentDispatcher.d.ts +3 -3
- package/dist/services/AgentDispatcher.js +33 -29
- package/dist/services/CronExecutor.d.ts +4 -4
- package/dist/services/CronExecutor.js +12 -8
- package/dist/services/EvaluatorLoop.d.ts +3 -3
- package/dist/services/EvaluatorLoop.js +29 -21
- package/dist/services/MetaHarness.d.ts +1 -1
- package/dist/services/MetaHarness.js +41 -33
- package/dist/services/PipelineExecutor.d.ts +1 -1
- package/dist/services/PipelineExecutor.js +23 -25
- package/dist/services/SkillExtractor.d.ts +43 -0
- package/dist/services/SkillExtractor.js +143 -0
- package/dist/services/StreamingToolExecutor.d.ts +2 -2
- package/dist/services/StreamingToolExecutor.js +11 -7
- package/dist/services/a2a.d.ts +8 -8
- package/dist/services/a2a.js +44 -34
- package/dist/services/agent-messaging.d.ts +33 -15
- package/dist/services/agent-messaging.js +65 -13
- package/dist/services/cron.js +16 -16
- package/dist/tools/AgentTool/index.d.ts +5 -2
- package/dist/tools/AgentTool/index.js +35 -15
- package/dist/tools/AskUserTool/index.js +1 -1
- package/dist/tools/BashTool/index.d.ts +2 -2
- package/dist/tools/BashTool/index.js +18 -10
- package/dist/tools/CronTool/index.d.ts +2 -2
- package/dist/tools/CronTool/index.js +30 -12
- package/dist/tools/DiagnosticsTool/index.js +28 -22
- package/dist/tools/EnterPlanModeTool/index.js +93 -14
- package/dist/tools/EnterWorktreeTool/index.js +7 -3
- package/dist/tools/ExitPlanModeTool/index.d.ts +22 -1
- package/dist/tools/ExitPlanModeTool/index.js +20 -5
- package/dist/tools/ExitWorktreeTool/index.js +11 -4
- package/dist/tools/FileEditTool/index.js +3 -5
- package/dist/tools/FileReadTool/index.js +16 -10
- package/dist/tools/FileWriteTool/index.js +2 -2
- package/dist/tools/GlobTool/index.js +5 -9
- package/dist/tools/GrepTool/index.d.ts +2 -2
- package/dist/tools/GrepTool/index.js +14 -9
- package/dist/tools/ImageReadTool/index.js +2 -2
- package/dist/tools/KillProcessTool/index.js +11 -7
- package/dist/tools/LSTool/index.js +3 -3
- package/dist/tools/MemoryTool/index.d.ts +11 -11
- package/dist/tools/MemoryTool/index.js +28 -14
- package/dist/tools/MonitorTool/index.d.ts +2 -2
- package/dist/tools/MonitorTool/index.js +24 -19
- package/dist/tools/MultiEditTool/index.js +9 -5
- package/dist/tools/NotebookEditTool/index.js +3 -3
- package/dist/tools/ParallelAgentTool/index.d.ts +4 -4
- package/dist/tools/ParallelAgentTool/index.js +12 -6
- package/dist/tools/PipelineTool/index.d.ts +4 -4
- package/dist/tools/PipelineTool/index.js +3 -3
- package/dist/tools/PowerShellTool/index.js +10 -6
- package/dist/tools/RemoteTriggerTool/index.js +8 -4
- package/dist/tools/ScheduleWakeupTool/index.d.ts +42 -0
- package/dist/tools/ScheduleWakeupTool/index.js +115 -0
- package/dist/tools/SendMessageTool/index.js +25 -7
- package/dist/tools/SessionSearchTool/index.d.ts +15 -0
- package/dist/tools/SessionSearchTool/index.js +36 -0
- package/dist/tools/SkillTool/index.d.ts +3 -0
- package/dist/tools/SkillTool/index.js +39 -9
- package/dist/tools/TaskCreateTool/index.d.ts +2 -2
- package/dist/tools/TaskCreateTool/index.js +2 -2
- package/dist/tools/TaskGetTool/index.js +2 -2
- package/dist/tools/TaskListTool/index.js +3 -5
- package/dist/tools/TaskOutputTool/index.js +2 -2
- package/dist/tools/TaskStopTool/index.js +3 -3
- package/dist/tools/TaskUpdateTool/index.d.ts +4 -4
- package/dist/tools/TaskUpdateTool/index.js +2 -2
- package/dist/tools/ToolSearchTool/index.js +9 -6
- package/dist/tools/WebFetchTool/index.js +1 -1
- package/dist/tools/WebSearchTool/index.js +2 -6
- package/dist/tools.js +31 -30
- package/dist/types/permissions.js +15 -9
- package/dist/utils/bash-safety.d.ts +1 -1
- package/dist/utils/bash-safety.js +64 -54
- package/dist/utils/diff-algorithm.d.ts +3 -3
- package/dist/utils/diff-algorithm.js +7 -7
- package/dist/utils/fs.js +3 -3
- package/dist/utils/safe-env.js +1 -1
- package/dist/utils/theme-data.d.ts +1 -1
- package/dist/utils/theme-data.js +1 -1
- package/dist/utils/theme.d.ts +1 -1
- package/dist/utils/theme.js +1 -1
- package/dist/utils/tool-summary.d.ts +1 -1
- package/dist/utils/tool-summary.js +27 -9
- package/package.json +10 -3
|
@@ -1,69 +1,69 @@
|
|
|
1
1
|
const SPEECHES = {
|
|
2
2
|
toolError: {
|
|
3
|
-
default: [
|
|
4
|
-
snarky: [
|
|
5
|
-
sage: [
|
|
6
|
-
chaotic: [
|
|
7
|
-
impatient: [
|
|
3
|
+
default: ["Hmm, that didn't work...", "Error? Let's try again!", "Oops. Check the logs?"],
|
|
4
|
+
snarky: ["Predictable.", "Cool error. Very cool.", "Did you even test this?"],
|
|
5
|
+
sage: ["Every failure teaches us something.", "Errors are just feedback."],
|
|
6
|
+
chaotic: ["BURN IT DOWN AND REBUILD!", "ERROR = OPPORTUNITY!!", "Chaos reigns!"],
|
|
7
|
+
impatient: ["Again?! Fix it already!", "This is taking forever..."],
|
|
8
8
|
},
|
|
9
9
|
toolSuccess: {
|
|
10
|
-
default: [
|
|
11
|
-
snarky: [
|
|
12
|
-
sage: [
|
|
13
|
-
chaotic: [
|
|
14
|
-
impatient: [
|
|
10
|
+
default: ["Nice!", "That worked!", "One down!", "Smooth."],
|
|
11
|
+
snarky: ["About time.", "Oh wow, it worked. Shocking."],
|
|
12
|
+
sage: ["Progress, one step at a time.", "Well done."],
|
|
13
|
+
chaotic: ["IT WORKED!! AMAZING!!", "YES YES YES!!"],
|
|
14
|
+
impatient: ["Finally!", "Took long enough."],
|
|
15
15
|
},
|
|
16
16
|
longWait: {
|
|
17
|
-
default: [
|
|
18
|
-
snarky: [
|
|
19
|
-
sage: [
|
|
20
|
-
chaotic: [
|
|
21
|
-
impatient: [
|
|
17
|
+
default: ["Still thinking...", "Working on it!", "This might take a sec..."],
|
|
18
|
+
snarky: ["Oh good, more waiting.", "Any day now..."],
|
|
19
|
+
sage: ["Patience is a virtue.", "Good things take time."],
|
|
20
|
+
chaotic: ["DO SOMETHING!! ANYTHING!!", "TIME IS AN ILLUSION!"],
|
|
21
|
+
impatient: ["Come ON already!", "I'm DYING here..."],
|
|
22
22
|
},
|
|
23
23
|
commit: {
|
|
24
|
-
default: [
|
|
25
|
-
snarky: [
|
|
26
|
-
sage: [
|
|
27
|
-
chaotic: [
|
|
28
|
-
impatient: [
|
|
24
|
+
default: ["Committed!", "Saved to history!", "Git it! 🎯"],
|
|
25
|
+
snarky: ["Committing mistakes to history, great.", "Future you will love this."],
|
|
26
|
+
sage: ["A clear commit message is a gift to the future."],
|
|
27
|
+
chaotic: ["COMMIT EVERYTHING!! NO TESTS NEEDED!!"],
|
|
28
|
+
impatient: ["Finally shipped something."],
|
|
29
29
|
},
|
|
30
30
|
taskComplete: {
|
|
31
|
-
default: [
|
|
32
|
-
snarky: [
|
|
33
|
-
sage: [
|
|
34
|
-
chaotic: [
|
|
35
|
-
impatient: [
|
|
31
|
+
default: ["Task done!", "Check!", "Nailed it!", "One more down!"],
|
|
32
|
+
snarky: ["Congrats, you did the thing.", "Gold star, I guess."],
|
|
33
|
+
sage: ["Completion is its own reward.", "Well executed."],
|
|
34
|
+
chaotic: ["DONE DONE DONE PARTY TIME!!"],
|
|
35
|
+
impatient: ["Finally. Next!"],
|
|
36
36
|
},
|
|
37
37
|
userAddressed: {
|
|
38
|
-
default: [
|
|
39
|
-
snarky: [
|
|
40
|
-
sage: [
|
|
41
|
-
chaotic: [
|
|
42
|
-
impatient: [
|
|
38
|
+
default: ["Hey! I'm here!", "*waves*", "You called?", "What's up?"],
|
|
39
|
+
snarky: ["Oh NOW you talk to me.", "Finally acknowledged."],
|
|
40
|
+
sage: ["Hello, friend.", "How can I help?"],
|
|
41
|
+
chaotic: ["HIIII YES HELLO I AM HERE!!", "You're my favorite human!!"],
|
|
42
|
+
impatient: ["Yes yes, what is it?"],
|
|
43
43
|
},
|
|
44
44
|
idle: {
|
|
45
|
-
default: [
|
|
46
|
-
snarky: [
|
|
47
|
-
sage: [
|
|
48
|
-
chaotic: [
|
|
49
|
-
impatient: [
|
|
45
|
+
default: ["...", "*yawns*", "la la la...", "*stares into the void*"],
|
|
46
|
+
snarky: ["Still here. Waiting.", "Bored now."],
|
|
47
|
+
sage: ["In stillness, clarity.", "*meditates*"],
|
|
48
|
+
chaotic: ["*vibrates intensely*", "I CONTAIN MULTITUDES"],
|
|
49
|
+
impatient: ["Let's GO already!", "Hurry up!"],
|
|
50
50
|
},
|
|
51
51
|
};
|
|
52
52
|
function pick(arr) {
|
|
53
53
|
return arr[Math.floor(Math.random() * arr.length)];
|
|
54
54
|
}
|
|
55
55
|
const TOOL_QUIPS = {
|
|
56
|
-
BashTool: [
|
|
57
|
-
FileWriteTool: [
|
|
58
|
-
FileEditTool: [
|
|
59
|
-
GlobTool: [
|
|
60
|
-
GrepTool: [
|
|
61
|
-
WebFetchTool: [
|
|
62
|
-
WebSearchTool: [
|
|
56
|
+
BashTool: ["ooh shell time!", "running commands...", "bash go brrr"],
|
|
57
|
+
FileWriteTool: ["writing to disk...", "saving the work!", "persisting..."],
|
|
58
|
+
FileEditTool: ["editing a file!", "making changes...", "diff time!"],
|
|
59
|
+
GlobTool: ["searching files...", "globbing away!", "finding stuff..."],
|
|
60
|
+
GrepTool: ["grepping...", "scanning content!", "pattern match!"],
|
|
61
|
+
WebFetchTool: ["going online!", "fetching the web!", "http request!"],
|
|
62
|
+
WebSearchTool: ["googling it!", "searching the web!", "looking it up!"],
|
|
63
63
|
};
|
|
64
64
|
export function getSpeech(eventType, stats, toolName) {
|
|
65
65
|
// Tool-specific quips for successful tool calls
|
|
66
|
-
if (eventType ===
|
|
66
|
+
if (eventType === "toolSuccess" && toolName && TOOL_QUIPS[toolName]) {
|
|
67
67
|
return pick(TOOL_QUIPS[toolName]);
|
|
68
68
|
}
|
|
69
69
|
const templates = SPEECHES[eventType];
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
export type Emotion =
|
|
2
|
-
export type Stat =
|
|
3
|
-
export type HatKey =
|
|
4
|
-
export type Rarity =
|
|
1
|
+
export type Emotion = "idle" | "happy" | "alarm";
|
|
2
|
+
export type Stat = "DEBUGGING" | "PATIENCE" | "CHAOS" | "WISDOM" | "SNARK";
|
|
3
|
+
export type HatKey = "none" | "cap" | "crown" | "beanie" | "tophat" | "halo";
|
|
4
|
+
export type Rarity = "common" | "uncommon" | "rare" | "epic" | "legendary";
|
|
5
5
|
export declare const EYE_STYLES: string[];
|
|
6
6
|
export declare const HAT_ART: Record<HatKey, string | null>;
|
|
7
7
|
/** Rarity tiers with weights (must sum to 100) and stat floors */
|
|
@@ -1,42 +1,42 @@
|
|
|
1
|
-
export const EYE_STYLES = [
|
|
1
|
+
export const EYE_STYLES = ["o o", "^ ^", "- -", "> <", "* *", "~ ~"];
|
|
2
2
|
export const HAT_ART = {
|
|
3
3
|
none: null,
|
|
4
|
-
cap:
|
|
5
|
-
crown:
|
|
6
|
-
beanie:
|
|
7
|
-
tophat:
|
|
8
|
-
halo:
|
|
4
|
+
cap: " [___] ",
|
|
5
|
+
crown: " /\\|/\\ ",
|
|
6
|
+
beanie: " (~~~~) ",
|
|
7
|
+
tophat: " [=====]",
|
|
8
|
+
halo: " ( o ) ",
|
|
9
9
|
};
|
|
10
10
|
/** Rarity tiers with weights (must sum to 100) and stat floors */
|
|
11
11
|
export const RARITY_TIERS = [
|
|
12
|
-
{ rarity:
|
|
13
|
-
{ rarity:
|
|
14
|
-
{ rarity:
|
|
15
|
-
{ rarity:
|
|
16
|
-
{ rarity:
|
|
12
|
+
{ rarity: "common", weight: 60, statFloor: 5 },
|
|
13
|
+
{ rarity: "uncommon", weight: 25, statFloor: 15 },
|
|
14
|
+
{ rarity: "rare", weight: 10, statFloor: 25 },
|
|
15
|
+
{ rarity: "epic", weight: 4, statFloor: 35 },
|
|
16
|
+
{ rarity: "legendary", weight: 1, statFloor: 50 },
|
|
17
17
|
];
|
|
18
18
|
/** Hats available per rarity tier and above */
|
|
19
19
|
export const RARITY_HATS = {
|
|
20
|
-
common: [
|
|
21
|
-
uncommon: [
|
|
22
|
-
rare: [
|
|
23
|
-
epic: [
|
|
24
|
-
legendary: [
|
|
20
|
+
common: ["none"],
|
|
21
|
+
uncommon: ["none", "crown", "cap"],
|
|
22
|
+
rare: ["none", "crown", "cap", "halo", "beanie"],
|
|
23
|
+
epic: ["none", "crown", "cap", "halo", "beanie", "tophat"],
|
|
24
|
+
legendary: ["none", "crown", "cap", "halo", "beanie", "tophat"],
|
|
25
25
|
};
|
|
26
26
|
/** Color for each rarity tier in terminal */
|
|
27
27
|
export const RARITY_COLORS = {
|
|
28
|
-
common:
|
|
29
|
-
uncommon:
|
|
30
|
-
rare:
|
|
31
|
-
epic:
|
|
32
|
-
legendary:
|
|
28
|
+
common: "cyan",
|
|
29
|
+
uncommon: "green",
|
|
30
|
+
rare: "blue",
|
|
31
|
+
epic: "magenta",
|
|
32
|
+
legendary: "yellow",
|
|
33
33
|
};
|
|
34
34
|
export const RARITY_STARS = {
|
|
35
|
-
common:
|
|
36
|
-
uncommon:
|
|
37
|
-
rare:
|
|
38
|
-
epic:
|
|
39
|
-
legendary:
|
|
35
|
+
common: "★",
|
|
36
|
+
uncommon: "★★",
|
|
37
|
+
rare: "★★★",
|
|
38
|
+
epic: "★★★★",
|
|
39
|
+
legendary: "★★★★★",
|
|
40
40
|
};
|
|
41
41
|
export const DEFAULT_NEEDS = {
|
|
42
42
|
hunger: 80,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { CompanionConfig, CompanionRuntime, CompanionState
|
|
1
|
+
import type { CompanionBones, CompanionConfig, CompanionRuntime, CompanionState } from "./types.js";
|
|
2
2
|
interface UseCompanionResult {
|
|
3
3
|
config: CompanionConfig | null;
|
|
4
4
|
bones: CompanionBones | null;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { cybergotchiEvents } from
|
|
5
|
-
import {
|
|
6
|
-
import { getSpecies } from
|
|
7
|
-
import {
|
|
1
|
+
import { useCallback, useEffect, useRef, useState } from "react";
|
|
2
|
+
import { roll } from "./bones.js";
|
|
3
|
+
import { loadCompanionConfig, saveCompanionConfig } from "./config.js";
|
|
4
|
+
import { cybergotchiEvents } from "./events.js";
|
|
5
|
+
import { applyEvent, decayNeeds } from "./needs.js";
|
|
6
|
+
import { getSpecies } from "./species.js";
|
|
7
|
+
import { getSpeech } from "./speech.js";
|
|
8
8
|
const TICK_MS = 500;
|
|
9
9
|
const SPEECH_TTL_TICKS = 10; // 5 seconds
|
|
10
10
|
const IDLE_INTERVAL_TICKS = 120; // 60 seconds
|
|
@@ -13,10 +13,10 @@ const SAVE_INTERVAL_TICKS = 60; // 30 seconds — persist needs decay periodical
|
|
|
13
13
|
function emotionFromNeeds(config) {
|
|
14
14
|
const { hunger, energy, happiness } = config.needs;
|
|
15
15
|
if (hunger < 20 || happiness < 20)
|
|
16
|
-
return
|
|
16
|
+
return "alarm";
|
|
17
17
|
if (happiness > 60 && hunger > 50 && energy > 50)
|
|
18
|
-
return
|
|
19
|
-
return
|
|
18
|
+
return "happy";
|
|
19
|
+
return "idle";
|
|
20
20
|
}
|
|
21
21
|
export function useCybergotchi(paused) {
|
|
22
22
|
const configRef = useRef(loadCompanionConfig());
|
|
@@ -25,7 +25,7 @@ export function useCybergotchi(paused) {
|
|
|
25
25
|
// Compute bones from seed (deterministic, recomputed each session)
|
|
26
26
|
const bonesRef = useRef(config ? roll(config.seed) : null);
|
|
27
27
|
const [state, setState] = useState({
|
|
28
|
-
emotion:
|
|
28
|
+
emotion: "idle",
|
|
29
29
|
frame: 0,
|
|
30
30
|
speech: null,
|
|
31
31
|
speechTtl: 0,
|
|
@@ -44,8 +44,10 @@ export function useCybergotchi(paused) {
|
|
|
44
44
|
const handler = (event) => {
|
|
45
45
|
eventQueue.current.push(event);
|
|
46
46
|
};
|
|
47
|
-
cybergotchiEvents.on(
|
|
48
|
-
return () => {
|
|
47
|
+
cybergotchiEvents.on("cybergotchi", handler);
|
|
48
|
+
return () => {
|
|
49
|
+
cybergotchiEvents.off("cybergotchi", handler);
|
|
50
|
+
};
|
|
49
51
|
}, []);
|
|
50
52
|
// Animation + needs tick
|
|
51
53
|
useEffect(() => {
|
|
@@ -70,7 +72,7 @@ export function useCybergotchi(paused) {
|
|
|
70
72
|
const bones = bonesRef.current;
|
|
71
73
|
if (!bones)
|
|
72
74
|
return;
|
|
73
|
-
setState(prev => {
|
|
75
|
+
setState((prev) => {
|
|
74
76
|
let { frame, speech, speechTtl } = prev;
|
|
75
77
|
let emotion = emotionFromNeeds(cfg);
|
|
76
78
|
// Drain speech TTL
|
|
@@ -94,7 +96,7 @@ export function useCybergotchi(paused) {
|
|
|
94
96
|
idleTicksRef.current += 1;
|
|
95
97
|
if (idleTicksRef.current >= IDLE_INTERVAL_TICKS) {
|
|
96
98
|
idleTicksRef.current = 0;
|
|
97
|
-
speech = getSpeech(
|
|
99
|
+
speech = getSpeech("idle", bones.baseStats);
|
|
98
100
|
speechTtl = SPEECH_TTL_TICKS;
|
|
99
101
|
}
|
|
100
102
|
}
|
|
@@ -105,16 +107,18 @@ export function useCybergotchi(paused) {
|
|
|
105
107
|
});
|
|
106
108
|
}, TICK_MS);
|
|
107
109
|
return () => clearInterval(tick);
|
|
108
|
-
}, [config]);
|
|
109
|
-
const runtime = config && bonesRef.current
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
110
|
+
}, [config, paused]);
|
|
111
|
+
const runtime = config && bonesRef.current
|
|
112
|
+
? {
|
|
113
|
+
bones: bonesRef.current,
|
|
114
|
+
soul: config.soul,
|
|
115
|
+
needs: config.needs,
|
|
116
|
+
needsUpdatedAt: config.needsUpdatedAt,
|
|
117
|
+
currentStreak: config.currentStreak,
|
|
118
|
+
lifetime: config.lifetime,
|
|
119
|
+
evolutionStage: config.evolutionStage,
|
|
120
|
+
}
|
|
121
|
+
: null;
|
|
118
122
|
return { config, bones: bonesRef.current, runtime, state, isSetupNeeded, reload };
|
|
119
123
|
}
|
|
120
124
|
//# sourceMappingURL=useCybergotchi.js.map
|
package/dist/git/index.js
CHANGED
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
* Inspired by Aider's git-native workflow.
|
|
4
4
|
*/
|
|
5
5
|
import { execSync, spawnSync } from "node:child_process";
|
|
6
|
-
import { join } from "node:path";
|
|
7
6
|
import { existsSync } from "node:fs";
|
|
7
|
+
import { join } from "node:path";
|
|
8
8
|
/**
|
|
9
9
|
* Check if we're in a git repository.
|
|
10
10
|
*/
|
|
@@ -91,9 +91,9 @@ export function isInMergeOrRebase(cwd) {
|
|
|
91
91
|
const root = cwd ?? process.cwd();
|
|
92
92
|
try {
|
|
93
93
|
const gitDir = join(root, ".git");
|
|
94
|
-
return existsSync(join(gitDir, "MERGE_HEAD"))
|
|
95
|
-
|
|
96
|
-
|
|
94
|
+
return (existsSync(join(gitDir, "MERGE_HEAD")) ||
|
|
95
|
+
existsSync(join(gitDir, "rebase-merge")) ||
|
|
96
|
+
existsSync(join(gitDir, "rebase-apply")));
|
|
97
97
|
}
|
|
98
98
|
catch {
|
|
99
99
|
return false;
|
|
@@ -126,7 +126,9 @@ export function autoCommitAIEdits(toolName, files, cwd) {
|
|
|
126
126
|
return null;
|
|
127
127
|
// Generate commit message with Co-Authored-By trailer
|
|
128
128
|
const fileList = files.length > 0
|
|
129
|
-
?
|
|
129
|
+
? files.length <= 3
|
|
130
|
+
? files.join(", ")
|
|
131
|
+
: `${files.length} files`
|
|
130
132
|
: staged.split("\n").slice(0, 3).join(", ");
|
|
131
133
|
const message = `oh: ${toolName} ${fileList}\n\nCo-Authored-By: OpenHarness <noreply@openharness.dev>`;
|
|
132
134
|
// Respect git signing config — don't pass --no-gpg-sign
|
|
@@ -175,10 +177,10 @@ export function createWorktree(cwd) {
|
|
|
175
177
|
return null;
|
|
176
178
|
try {
|
|
177
179
|
const id = Date.now().toString(36) + Math.random().toString(36).slice(2, 6);
|
|
178
|
-
const worktreePath = join(cwd ?? process.cwd(),
|
|
179
|
-
const
|
|
180
|
+
const worktreePath = join(cwd ?? process.cwd(), "..", `.oh-worktree-${id}`);
|
|
181
|
+
const _branch = `oh-agent-${id}`;
|
|
180
182
|
// Create a detached worktree from HEAD
|
|
181
|
-
execSync(`git worktree add --detach "${worktreePath}"`, { cwd, stdio:
|
|
183
|
+
execSync(`git worktree add --detach "${worktreePath}"`, { cwd, stdio: "pipe" });
|
|
182
184
|
return worktreePath;
|
|
183
185
|
}
|
|
184
186
|
catch {
|
|
@@ -215,7 +217,7 @@ export function gitRoot(cwd) {
|
|
|
215
217
|
*/
|
|
216
218
|
export function removeWorktree(worktreePath, cwd) {
|
|
217
219
|
try {
|
|
218
|
-
execSync(`git worktree remove --force "${worktreePath}"`, { cwd, stdio:
|
|
220
|
+
execSync(`git worktree remove --force "${worktreePath}"`, { cwd, stdio: "pipe" });
|
|
219
221
|
}
|
|
220
222
|
catch {
|
|
221
223
|
// Best effort cleanup
|
|
@@ -6,11 +6,11 @@
|
|
|
6
6
|
*
|
|
7
7
|
* Storage: .oh/checkpoints/{sessionId}/{turnN}/{relativePath}
|
|
8
8
|
*/
|
|
9
|
-
import {
|
|
10
|
-
import { join, relative
|
|
11
|
-
const CHECKPOINTS_DIR =
|
|
9
|
+
import { copyFileSync, existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
10
|
+
import { dirname, join, relative } from "node:path";
|
|
11
|
+
const CHECKPOINTS_DIR = ".oh/checkpoints";
|
|
12
12
|
const MAX_CHECKPOINTS = 20; // per session
|
|
13
|
-
let currentSessionId =
|
|
13
|
+
let currentSessionId = "";
|
|
14
14
|
let checkpointLog = [];
|
|
15
15
|
/** Initialize checkpoint system for a session */
|
|
16
16
|
export function initCheckpoints(sessionId) {
|
|
@@ -19,10 +19,10 @@ export function initCheckpoints(sessionId) {
|
|
|
19
19
|
const dir = join(CHECKPOINTS_DIR, sessionId);
|
|
20
20
|
if (existsSync(dir)) {
|
|
21
21
|
// Load existing checkpoint log
|
|
22
|
-
const logPath = join(dir,
|
|
22
|
+
const logPath = join(dir, "log.json");
|
|
23
23
|
if (existsSync(logPath)) {
|
|
24
24
|
try {
|
|
25
|
-
checkpointLog = JSON.parse(readFileSync(logPath,
|
|
25
|
+
checkpointLog = JSON.parse(readFileSync(logPath, "utf-8"));
|
|
26
26
|
}
|
|
27
27
|
catch {
|
|
28
28
|
checkpointLog = [];
|
|
@@ -51,7 +51,9 @@ export function createCheckpoint(turn, filePaths, description) {
|
|
|
51
51
|
copyFileSync(filePath, destPath);
|
|
52
52
|
savedFiles.push(relPath);
|
|
53
53
|
}
|
|
54
|
-
catch {
|
|
54
|
+
catch {
|
|
55
|
+
/* skip unreadable files */
|
|
56
|
+
}
|
|
55
57
|
}
|
|
56
58
|
if (savedFiles.length === 0)
|
|
57
59
|
return null;
|
|
@@ -69,10 +71,12 @@ export function createCheckpoint(turn, filePaths, description) {
|
|
|
69
71
|
try {
|
|
70
72
|
rmSync(oldDir, { recursive: true });
|
|
71
73
|
}
|
|
72
|
-
catch {
|
|
74
|
+
catch {
|
|
75
|
+
/* ignore */
|
|
76
|
+
}
|
|
73
77
|
}
|
|
74
78
|
// Persist log
|
|
75
|
-
const logPath = join(CHECKPOINTS_DIR, currentSessionId,
|
|
79
|
+
const logPath = join(CHECKPOINTS_DIR, currentSessionId, "log.json");
|
|
76
80
|
mkdirSync(dirname(logPath), { recursive: true });
|
|
77
81
|
writeFileSync(logPath, JSON.stringify(checkpointLog, null, 2));
|
|
78
82
|
return checkpoint;
|
|
@@ -95,16 +99,20 @@ export function rewindLastCheckpoint() {
|
|
|
95
99
|
mkdirSync(dirname(destPath), { recursive: true });
|
|
96
100
|
copyFileSync(srcPath, destPath);
|
|
97
101
|
}
|
|
98
|
-
catch {
|
|
102
|
+
catch {
|
|
103
|
+
/* skip */
|
|
104
|
+
}
|
|
99
105
|
}
|
|
100
106
|
}
|
|
101
107
|
// Clean up the restored checkpoint dir
|
|
102
108
|
try {
|
|
103
109
|
rmSync(dir, { recursive: true });
|
|
104
110
|
}
|
|
105
|
-
catch {
|
|
111
|
+
catch {
|
|
112
|
+
/* ignore */
|
|
113
|
+
}
|
|
106
114
|
// Persist updated log
|
|
107
|
-
const logPath = join(CHECKPOINTS_DIR, currentSessionId,
|
|
115
|
+
const logPath = join(CHECKPOINTS_DIR, currentSessionId, "log.json");
|
|
108
116
|
writeFileSync(logPath, JSON.stringify(checkpointLog, null, 2));
|
|
109
117
|
return checkpoint;
|
|
110
118
|
}
|
|
@@ -122,22 +130,22 @@ export function checkpointCount() {
|
|
|
122
130
|
*/
|
|
123
131
|
export function getAffectedFiles(toolName, toolInput) {
|
|
124
132
|
switch (toolName) {
|
|
125
|
-
case
|
|
126
|
-
case
|
|
133
|
+
case "FileWrite":
|
|
134
|
+
case "Write":
|
|
127
135
|
return toolInput.file_path ? [String(toolInput.file_path)] : [];
|
|
128
|
-
case
|
|
129
|
-
case
|
|
136
|
+
case "FileEdit":
|
|
137
|
+
case "Edit":
|
|
130
138
|
return toolInput.file_path ? [String(toolInput.file_path)] : [];
|
|
131
|
-
case
|
|
139
|
+
case "NotebookEdit":
|
|
132
140
|
return toolInput.notebook_path ? [String(toolInput.notebook_path)] : [];
|
|
133
|
-
case
|
|
141
|
+
case "Bash": {
|
|
134
142
|
// Extract file paths from bash commands that modify files
|
|
135
|
-
const cmd = String(toolInput.command ??
|
|
143
|
+
const cmd = String(toolInput.command ?? "");
|
|
136
144
|
const files = [];
|
|
137
145
|
// Detect redirect targets: > file, >> file
|
|
138
146
|
const redirects = cmd.matchAll(/>{1,2}\s*(\S+)/g);
|
|
139
147
|
for (const m of redirects)
|
|
140
|
-
if (m[1] && !m[1].startsWith(
|
|
148
|
+
if (m[1] && !m[1].startsWith("/dev/"))
|
|
141
149
|
files.push(m[1]);
|
|
142
150
|
// Detect sed -i targets
|
|
143
151
|
const sedMatch = cmd.match(/sed\s+-i\S*\s+.*\s+(\S+)$/);
|
|
@@ -147,7 +155,7 @@ export function getAffectedFiles(toolName, toolInput) {
|
|
|
147
155
|
const mvMatch = cmd.match(/(?:mv|cp)\s+\S+\s+(\S+)$/);
|
|
148
156
|
if (mvMatch?.[1])
|
|
149
157
|
files.push(mvMatch[1]);
|
|
150
|
-
return files.filter(f => existsSync(f));
|
|
158
|
+
return files.filter((f) => existsSync(f));
|
|
151
159
|
}
|
|
152
160
|
default:
|
|
153
161
|
return [];
|
package/dist/harness/config.d.ts
CHANGED
|
@@ -45,7 +45,7 @@ export type OhConfig = {
|
|
|
45
45
|
provider: string;
|
|
46
46
|
model: string;
|
|
47
47
|
permissionMode: PermissionMode;
|
|
48
|
-
theme?:
|
|
48
|
+
theme?: "dark" | "light";
|
|
49
49
|
apiKey?: string;
|
|
50
50
|
baseUrl?: string;
|
|
51
51
|
mcpServers?: McpServerConfig[];
|
|
@@ -55,7 +55,7 @@ export type OhConfig = {
|
|
|
55
55
|
/** Verification loops — auto-run lint/typecheck after file edits */
|
|
56
56
|
verification?: {
|
|
57
57
|
enabled?: boolean;
|
|
58
|
-
mode?:
|
|
58
|
+
mode?: "warn" | "block";
|
|
59
59
|
rules?: VerificationRuleConfig[];
|
|
60
60
|
};
|
|
61
61
|
/** Memory consolidation settings */
|
|
@@ -68,11 +68,21 @@ export type OhConfig = {
|
|
|
68
68
|
balanced?: string;
|
|
69
69
|
powerful?: string;
|
|
70
70
|
};
|
|
71
|
+
/** Effort level for LLM reasoning depth */
|
|
72
|
+
effortLevel?: "low" | "medium" | "high" | "max";
|
|
71
73
|
/** Opt-in telemetry (default: off) */
|
|
72
74
|
telemetry?: {
|
|
73
75
|
enabled?: boolean;
|
|
74
76
|
endpoint?: string;
|
|
75
77
|
};
|
|
78
|
+
/** Sandbox — filesystem and network restrictions */
|
|
79
|
+
sandbox?: {
|
|
80
|
+
enabled?: boolean;
|
|
81
|
+
allowedPaths?: string[];
|
|
82
|
+
allowedDomains?: string[];
|
|
83
|
+
blockNetwork?: boolean;
|
|
84
|
+
blockedCommands?: string[];
|
|
85
|
+
};
|
|
76
86
|
/** Remote server security settings */
|
|
77
87
|
remote?: {
|
|
78
88
|
tokens?: string[];
|
package/dist/harness/config.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* .oh/config.yaml — provider, model, permissionMode and other persisted settings.
|
|
3
3
|
*/
|
|
4
|
-
import {
|
|
5
|
-
import { join } from "node:path";
|
|
4
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
6
5
|
import { homedir } from "node:os";
|
|
6
|
+
import { join } from "node:path";
|
|
7
7
|
import { parse, stringify } from "yaml";
|
|
8
8
|
function yamlScalar(value) {
|
|
9
9
|
return `'${value.replace(/'/g, "''")}'`;
|
|
@@ -20,7 +20,7 @@ export function invalidateConfigCache() {
|
|
|
20
20
|
}
|
|
21
21
|
/** Path to global config: ~/.oh/config.yaml */
|
|
22
22
|
function globalConfigPath() {
|
|
23
|
-
return join(homedir(),
|
|
23
|
+
return join(homedir(), ".oh", "config.yaml");
|
|
24
24
|
}
|
|
25
25
|
/** Read global config as fallback defaults */
|
|
26
26
|
function readGlobalConfig() {
|
|
@@ -28,7 +28,7 @@ function readGlobalConfig() {
|
|
|
28
28
|
if (!existsSync(p))
|
|
29
29
|
return null;
|
|
30
30
|
try {
|
|
31
|
-
return parse(readFileSync(p,
|
|
31
|
+
return parse(readFileSync(p, "utf-8"));
|
|
32
32
|
}
|
|
33
33
|
catch {
|
|
34
34
|
return null;
|
|
@@ -47,7 +47,9 @@ export function readOhConfig(root) {
|
|
|
47
47
|
try {
|
|
48
48
|
projectCfg = parse(readFileSync(p, "utf-8"));
|
|
49
49
|
}
|
|
50
|
-
catch {
|
|
50
|
+
catch {
|
|
51
|
+
/* ignore malformed project config */
|
|
52
|
+
}
|
|
51
53
|
}
|
|
52
54
|
// If neither exists, no config
|
|
53
55
|
if (!globalCfg && !projectCfg) {
|
|
@@ -69,7 +71,9 @@ export function readOhConfig(root) {
|
|
|
69
71
|
return merged;
|
|
70
72
|
}
|
|
71
73
|
}
|
|
72
|
-
catch {
|
|
74
|
+
catch {
|
|
75
|
+
/* ignore malformed local config */
|
|
76
|
+
}
|
|
73
77
|
}
|
|
74
78
|
_configCache = base;
|
|
75
79
|
_configCacheRoot = effectiveRoot;
|
|
@@ -79,9 +83,11 @@ export function writeOhConfig(cfg, root) {
|
|
|
79
83
|
invalidateConfigCache();
|
|
80
84
|
// Emit configChange hook (lazy import to avoid circular dependency)
|
|
81
85
|
try {
|
|
82
|
-
require(
|
|
86
|
+
require("./hooks.js").emitHook("configChange", {});
|
|
87
|
+
}
|
|
88
|
+
catch {
|
|
89
|
+
/* ignore */
|
|
83
90
|
}
|
|
84
|
-
catch { /* ignore */ }
|
|
85
91
|
const p = configPath(root);
|
|
86
92
|
mkdirSync(join(root ?? ".", ".oh"), { recursive: true });
|
|
87
93
|
if (cfg.provider === "llamacpp" || cfg.provider === "lmstudio") {
|
|
@@ -110,7 +116,7 @@ export function writeOhConfig(cfg, root) {
|
|
|
110
116
|
// fall back to stringify for mcpServers since it's complex
|
|
111
117
|
lines.push("", stringify({ mcpServers: cfg.mcpServers }).trim());
|
|
112
118
|
}
|
|
113
|
-
writeFileSync(p, lines.join("\n")
|
|
119
|
+
writeFileSync(p, `${lines.join("\n")}\n`);
|
|
114
120
|
return;
|
|
115
121
|
}
|
|
116
122
|
writeFileSync(p, stringify(cfg));
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Context window warning — shared between cell renderer and Ink REPL.
|
|
3
3
|
*/
|
|
4
|
-
import type { Message } from
|
|
4
|
+
import type { Message } from "../types/message.js";
|
|
5
5
|
/** Estimate total tokens from messages (incremental-friendly) */
|
|
6
6
|
export declare function estimateMessageTokens(messages: Message[], startFrom?: number): number;
|
|
7
7
|
/** Compute context warning if usage exceeds 75% */
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Context window warning — shared between cell renderer and Ink REPL.
|
|
3
3
|
*/
|
|
4
|
-
import { getContextWindow } from
|
|
4
|
+
import { getContextWindow } from "./cost.js";
|
|
5
5
|
/** Estimate total tokens from messages (incremental-friendly) */
|
|
6
6
|
export function estimateMessageTokens(messages, startFrom = 0) {
|
|
7
7
|
let total = 0;
|
package/dist/harness/cost.js
CHANGED
|
@@ -51,7 +51,7 @@ export const MODEL_PRICING = {
|
|
|
51
51
|
"gpt-4o": [2.5, 10.0],
|
|
52
52
|
"gpt-4o-mini": [0.15, 0.6],
|
|
53
53
|
"o3-mini": [1.1, 4.4],
|
|
54
|
-
|
|
54
|
+
o3: [10.0, 40.0],
|
|
55
55
|
"claude-sonnet-4-6": [3.0, 15.0],
|
|
56
56
|
"claude-haiku-4-5": [0.8, 4.0],
|
|
57
57
|
"claude-opus-4-6": [15.0, 75.0],
|