pi-honcho-memory 0.1.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/LICENSE +21 -0
- package/README.md +133 -0
- package/extensions/client.ts +64 -0
- package/extensions/commands.ts +198 -0
- package/extensions/config.ts +307 -0
- package/extensions/context.ts +107 -0
- package/extensions/git.ts +28 -0
- package/extensions/index.ts +190 -0
- package/extensions/session.ts +53 -0
- package/extensions/tools.ts +162 -0
- package/extensions/upload.ts +216 -0
- package/package.json +43 -0
- package/types/shims.d.ts +3 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 acsezen
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
# pi-honcho-memory
|
|
2
|
+
|
|
3
|
+
Honcho-backed persistent memory extension for the [PI coding agent](https://github.com/nicholasgasior/pi-coding-agent). Full feature parity with the [Hermes agent Honcho plugin](https://github.com/NousResearch/hermes-agent).
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pi install npm:pi-honcho-memory
|
|
9
|
+
# or from git
|
|
10
|
+
pi install https://github.com/acsezen/pi-memory-honcho
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Setup
|
|
14
|
+
|
|
15
|
+
1. Get a Honcho API key from [honcho.dev](https://honcho.dev) or self-host.
|
|
16
|
+
2. Run `/honcho:setup` inside PI to configure your key, workspace, and peer names.
|
|
17
|
+
3. Verify with `/honcho:doctor`.
|
|
18
|
+
|
|
19
|
+
Or create `~/.honcho/config.json` manually:
|
|
20
|
+
|
|
21
|
+
```json
|
|
22
|
+
{
|
|
23
|
+
"apiKey": "hch-v3-...",
|
|
24
|
+
"peerName": "yourname",
|
|
25
|
+
"hosts": {
|
|
26
|
+
"pi": {
|
|
27
|
+
"workspace": "pi",
|
|
28
|
+
"aiPeer": "pi",
|
|
29
|
+
"recallMode": "hybrid"
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Features
|
|
36
|
+
|
|
37
|
+
### Memory tools
|
|
38
|
+
|
|
39
|
+
| Tool | Description |
|
|
40
|
+
|------|-------------|
|
|
41
|
+
| `honcho_profile` | Retrieve what Honcho knows about the user |
|
|
42
|
+
| `honcho_search` | Search durable memory for prior conversations and facts |
|
|
43
|
+
| `honcho_context` | Synthesize memory context via dialectic reasoning |
|
|
44
|
+
| `honcho_conclude` | Store a durable preference, fact, or decision |
|
|
45
|
+
| `honcho_seed_identity` | Seed the AI peer's identity representation |
|
|
46
|
+
|
|
47
|
+
### Commands
|
|
48
|
+
|
|
49
|
+
| Command | Description |
|
|
50
|
+
|---------|-------------|
|
|
51
|
+
| `/honcho:setup` | Interactive first-time configuration |
|
|
52
|
+
| `/honcho:status` | Show connection, cache, and config status |
|
|
53
|
+
| `/honcho:config` | Show effective config (redacted API key) |
|
|
54
|
+
| `/honcho:doctor` | Preflight check for config, connectivity, session |
|
|
55
|
+
| `/honcho:interview` | Save a preference or working style insight |
|
|
56
|
+
| `/honcho:mode` | Switch recall mode (hybrid / context / tools) |
|
|
57
|
+
| `/honcho:sync` | Force context refresh and flush pending uploads |
|
|
58
|
+
| `/honcho:map` | Map current directory to a custom session name |
|
|
59
|
+
|
|
60
|
+
### Lifecycle
|
|
61
|
+
|
|
62
|
+
- **Session start**: Bootstraps Honcho connection, fetches context, migrates legacy memory files (MEMORY.md, USER.md, SOUL.md)
|
|
63
|
+
- **Before agent start**: Injects persistent memory into the system prompt (user profile, peer cards, AI profile, project summary)
|
|
64
|
+
- **Agent end**: Uploads conversation messages to Honcho
|
|
65
|
+
- **Session shutdown/switch/fork/compact**: Flushes pending uploads
|
|
66
|
+
|
|
67
|
+
## Configuration
|
|
68
|
+
|
|
69
|
+
All fields can be set via `~/.honcho/config.json` (under `hosts.pi`) or environment variables.
|
|
70
|
+
|
|
71
|
+
| Field | Env var | Default | Description |
|
|
72
|
+
|-------|---------|---------|-------------|
|
|
73
|
+
| `recallMode` | `HONCHO_RECALL_MODE` | `hybrid` | `hybrid` / `context` / `tools` |
|
|
74
|
+
| `sessionStrategy` | `HONCHO_SESSION_STRATEGY` | `per-directory` | `per-directory` / `git-branch` / `pi-session` / `per-repo` / `global` |
|
|
75
|
+
| `writeFrequency` | `HONCHO_WRITE_FREQUENCY` | `async` | `async` / `turn` / `session` / N (number) |
|
|
76
|
+
| `injectionFrequency` | `HONCHO_INJECTION_FREQUENCY` | `every-turn` | `every-turn` / `first-turn` |
|
|
77
|
+
| `saveMessages` | `HONCHO_SAVE_MESSAGES` | `true` | Upload conversation messages to Honcho |
|
|
78
|
+
| `dialecticDynamic` | `HONCHO_DIALECTIC_DYNAMIC` | `true` | Auto-bump reasoning level by query length |
|
|
79
|
+
| `dialecticMaxChars` | `HONCHO_DIALECTIC_MAX_CHARS` | `600` | Truncate dialectic results |
|
|
80
|
+
| `dialecticMaxInputChars` | `HONCHO_DIALECTIC_MAX_INPUT_CHARS` | `10000` | Truncate dialectic queries |
|
|
81
|
+
| `reasoningLevel` | `HONCHO_REASONING_LEVEL` | `low` | Base reasoning level for dialectic |
|
|
82
|
+
| `reasoningLevelCap` | `HONCHO_REASONING_LEVEL_CAP` | none | Hard cap on reasoning level |
|
|
83
|
+
| `contextTokens` | `HONCHO_CONTEXT_TOKENS` | `1200` | Token budget for injected context |
|
|
84
|
+
| `contextRefreshTtlSeconds` | `HONCHO_CONTEXT_REFRESH_TTL_SECONDS` | `300` | TTL before re-fetching context |
|
|
85
|
+
| `maxMessageLength` | `HONCHO_MAX_MESSAGE_LENGTH` | `25000` | Max chars per message chunk |
|
|
86
|
+
| `searchLimit` | `HONCHO_SEARCH_LIMIT` | `8` | Max search results |
|
|
87
|
+
| `sessionPeerPrefix` | `HONCHO_SESSION_PEER_PREFIX` | `false` | Prefix session keys with peer name |
|
|
88
|
+
| `observationMode` | `HONCHO_OBSERVATION_MODE` | `directional` | `directional` / `unified` |
|
|
89
|
+
| `contextCadence` | `HONCHO_CONTEXT_CADENCE` | `1` | Min turns between context API calls |
|
|
90
|
+
| `dialecticCadence` | `HONCHO_DIALECTIC_CADENCE` | `1` | Min turns between dialectic calls |
|
|
91
|
+
| `environment` | `HONCHO_ENVIRONMENT` | `production` | `local` / `production` |
|
|
92
|
+
| `logging` | `HONCHO_LOGGING` | `true` | Enable console logging |
|
|
93
|
+
|
|
94
|
+
### Manual session mappings
|
|
95
|
+
|
|
96
|
+
Add `sessions` to your `~/.honcho/config.json` to map directories to specific session names:
|
|
97
|
+
|
|
98
|
+
```json
|
|
99
|
+
{
|
|
100
|
+
"sessions": {
|
|
101
|
+
"/home/user/project-a": "my-project-a",
|
|
102
|
+
"/home/user/project-b": "my-project-b"
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### Linked hosts
|
|
108
|
+
|
|
109
|
+
Share memory across hosts (e.g., Claude Code, Codex, Hermes):
|
|
110
|
+
|
|
111
|
+
```json
|
|
112
|
+
{
|
|
113
|
+
"hosts": {
|
|
114
|
+
"pi": {
|
|
115
|
+
"linkedHosts": ["claude_code", "codex", "hermes"]
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## Development
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
git clone https://github.com/acsezen/pi-memory-honcho.git
|
|
125
|
+
cd pi-memory-honcho
|
|
126
|
+
npm install
|
|
127
|
+
npm run typecheck
|
|
128
|
+
npm test
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
## License
|
|
132
|
+
|
|
133
|
+
MIT
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { Honcho } from "@honcho-ai/sdk";
|
|
2
|
+
import type { Peer, Session } from "@honcho-ai/sdk";
|
|
3
|
+
import type { HonchoConfig } from "./config.js";
|
|
4
|
+
import { deriveSessionKey } from "./session.js";
|
|
5
|
+
|
|
6
|
+
export interface HonchoHandles {
|
|
7
|
+
honcho: Honcho;
|
|
8
|
+
userPeer: Peer;
|
|
9
|
+
aiPeer: Peer;
|
|
10
|
+
session: Session | null;
|
|
11
|
+
sessionKey: string;
|
|
12
|
+
config: HonchoConfig;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
let cachedHandles: HonchoHandles | null = null;
|
|
16
|
+
let sessionPromise: Promise<Session> | null = null;
|
|
17
|
+
|
|
18
|
+
export const getHandles = (): HonchoHandles | null => cachedHandles;
|
|
19
|
+
export const clearHandles = (): void => {
|
|
20
|
+
cachedHandles = null;
|
|
21
|
+
sessionPromise = null;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const initSession = async (handles: HonchoHandles): Promise<Session> => {
|
|
25
|
+
const session = await handles.honcho.session(handles.sessionKey);
|
|
26
|
+
await session.addPeers([
|
|
27
|
+
[handles.userPeer, { observeMe: handles.config.observeMe, observeOthers: handles.config.observeOthers }],
|
|
28
|
+
[handles.aiPeer, { observeMe: handles.config.aiObserveMe, observeOthers: handles.config.aiObserveOthers }],
|
|
29
|
+
]);
|
|
30
|
+
handles.session = session;
|
|
31
|
+
return session;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export const ensureSession = async (handles: HonchoHandles): Promise<Session> => {
|
|
35
|
+
if (handles.session) return handles.session;
|
|
36
|
+
if (sessionPromise) return sessionPromise;
|
|
37
|
+
sessionPromise = initSession(handles).finally(() => { sessionPromise = null; });
|
|
38
|
+
return sessionPromise;
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
export const bootstrap = async (config: HonchoConfig, cwd: string): Promise<HonchoHandles> => {
|
|
42
|
+
const honcho = new Honcho({
|
|
43
|
+
apiKey: config.apiKey,
|
|
44
|
+
baseURL: config.baseURL,
|
|
45
|
+
workspaceId: config.workspace,
|
|
46
|
+
environment: config.environment,
|
|
47
|
+
});
|
|
48
|
+
const sessionKey = await deriveSessionKey(cwd, config.sessionStrategy, config);
|
|
49
|
+
const [userPeer, aiPeer] = await Promise.all([
|
|
50
|
+
honcho.peer(config.peerName),
|
|
51
|
+
honcho.peer(config.aiPeer),
|
|
52
|
+
]);
|
|
53
|
+
|
|
54
|
+
if (config.recallMode === "tools") {
|
|
55
|
+
// Lazy: defer session creation until first tool call
|
|
56
|
+
cachedHandles = { honcho, userPeer, aiPeer, session: null, sessionKey, config };
|
|
57
|
+
return cachedHandles;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Eager: full init
|
|
61
|
+
cachedHandles = { honcho, userPeer, aiPeer, session: null, sessionKey, config };
|
|
62
|
+
await ensureSession(cachedHandles);
|
|
63
|
+
return cachedHandles;
|
|
64
|
+
};
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
import { Honcho } from "@honcho-ai/sdk";
|
|
2
|
+
import type { ExtensionAPI, ExtensionContext } from "@mariozechner/pi-coding-agent";
|
|
3
|
+
import { bootstrap, clearHandles, getHandles } from "./client.js";
|
|
4
|
+
import { type RecallMode, normalizeRecallMode, resolveConfig, saveConfig, setRecallMode } from "./config.js";
|
|
5
|
+
import { clearCachedContext, refreshCachedContext, renderCachedContext } from "./context.js";
|
|
6
|
+
import { deriveSessionKey } from "./session.js";
|
|
7
|
+
|
|
8
|
+
const parseCsv = (value: string | undefined, fallback: string[]): string[] => {
|
|
9
|
+
if (!value) return fallback;
|
|
10
|
+
return value
|
|
11
|
+
.split(",")
|
|
12
|
+
.map((entry) => entry.trim())
|
|
13
|
+
.filter(Boolean);
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
const statusText = async (): Promise<string> => {
|
|
17
|
+
const config = await resolveConfig();
|
|
18
|
+
const handles = getHandles();
|
|
19
|
+
const cache = renderCachedContext(config.contextTokens);
|
|
20
|
+
const sessionSource = handles?.sessionKey && config.sessions[process.cwd()]
|
|
21
|
+
? "manual" : "derived";
|
|
22
|
+
return [
|
|
23
|
+
`Enabled: ${config.enabled ? "yes" : "no"}`,
|
|
24
|
+
`Connected: ${handles ? "yes" : "no"}`,
|
|
25
|
+
`Workspace: ${config.workspace}`,
|
|
26
|
+
`Peer: ${config.peerName}`,
|
|
27
|
+
`AI peer: ${config.aiPeer}`,
|
|
28
|
+
`Linked hosts: ${config.linkedHosts.length > 0 ? config.linkedHosts.join(", ") : "none"}`,
|
|
29
|
+
`Strategy: ${config.sessionStrategy}`,
|
|
30
|
+
`Recall mode: ${config.recallMode}`,
|
|
31
|
+
`Write frequency: ${config.writeFrequency}`,
|
|
32
|
+
`Injection: ${config.injectionFrequency}`,
|
|
33
|
+
`Dialectic dynamic: ${config.dialecticDynamic ? "on" : "off"}`,
|
|
34
|
+
`Reasoning level: ${config.reasoningLevel}${config.reasoningLevelCap ? ` (cap: ${config.reasoningLevelCap})` : ""}`,
|
|
35
|
+
`Context TTL: ${config.contextRefreshTtlSeconds}s`,
|
|
36
|
+
`Max message length: ${config.maxMessageLength}`,
|
|
37
|
+
`Save messages: ${config.saveMessages ? "yes" : "no"}`,
|
|
38
|
+
`Session key: ${handles?.sessionKey ?? "uninitialized"} (${sessionSource})`,
|
|
39
|
+
`Cache: ${cache ? `${cache.length} chars` : "empty"}`,
|
|
40
|
+
].join("\n");
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
const connect = async (ctx: ExtensionContext): Promise<void> => {
|
|
44
|
+
clearHandles();
|
|
45
|
+
const config = await resolveConfig();
|
|
46
|
+
if (!config.enabled || !config.apiKey) throw new Error("Honcho is not configured.");
|
|
47
|
+
const handles = await bootstrap(config, ctx.cwd);
|
|
48
|
+
await refreshCachedContext(handles);
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
export const registerCommands = (pi: ExtensionAPI): void => {
|
|
52
|
+
pi.registerCommand("honcho:status", {
|
|
53
|
+
description: "Show Honcho connection and cache status",
|
|
54
|
+
handler: async (_args, ctx) => {
|
|
55
|
+
ctx.ui.notify(await statusText(), "info");
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
pi.registerCommand("honcho:setup", {
|
|
60
|
+
description: "Interactive first-time setup for Honcho in PI",
|
|
61
|
+
handler: async (_args, ctx) => {
|
|
62
|
+
const existing = await resolveConfig();
|
|
63
|
+
const maskedKey = existing.apiKey ? `${existing.apiKey.slice(0, 6)}...` : "hch-...";
|
|
64
|
+
const apiKeyInput = await ctx.ui.input("Honcho API key", maskedKey);
|
|
65
|
+
const apiKey = apiKeyInput === maskedKey ? existing.apiKey : apiKeyInput;
|
|
66
|
+
if (!apiKey) {
|
|
67
|
+
ctx.ui.notify("Setup cancelled: API key is required.", "warning");
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
const peerName = await ctx.ui.input("Your peer name", existing.peerName);
|
|
71
|
+
const workspace = await ctx.ui.input("Honcho workspace", existing.workspace);
|
|
72
|
+
const aiPeer = await ctx.ui.input("AI peer name", existing.aiPeer);
|
|
73
|
+
const endpoint = await ctx.ui.input("Endpoint (optional)", existing.baseURL ?? "");
|
|
74
|
+
const linkedHosts = await ctx.ui.input(
|
|
75
|
+
"Linked hosts (comma-separated, optional)",
|
|
76
|
+
existing.linkedHosts.join(", "),
|
|
77
|
+
);
|
|
78
|
+
const strategyInput = await ctx.ui.input(
|
|
79
|
+
"Session strategy (per-directory / git-branch / pi-session)",
|
|
80
|
+
existing.sessionStrategy,
|
|
81
|
+
);
|
|
82
|
+
await saveConfig({
|
|
83
|
+
apiKey,
|
|
84
|
+
peerName: peerName ?? existing.peerName,
|
|
85
|
+
workspace: workspace ?? existing.workspace,
|
|
86
|
+
aiPeer: aiPeer ?? existing.aiPeer,
|
|
87
|
+
endpoint: endpoint || undefined,
|
|
88
|
+
linkedHosts: parseCsv(linkedHosts, existing.linkedHosts),
|
|
89
|
+
sessionStrategy:
|
|
90
|
+
strategyInput === "git-branch" || strategyInput === "pi-session" || strategyInput === "per-directory"
|
|
91
|
+
? strategyInput
|
|
92
|
+
: existing.sessionStrategy,
|
|
93
|
+
});
|
|
94
|
+
await connect(ctx);
|
|
95
|
+
ctx.ui.notify("Honcho setup saved and connection initialized.", "info");
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
pi.registerCommand("honcho:config", {
|
|
100
|
+
description: "Show the current effective Honcho config for PI",
|
|
101
|
+
handler: async (_args, ctx) => {
|
|
102
|
+
const config = await resolveConfig();
|
|
103
|
+
const safe = { ...config, apiKey: config.apiKey ? `${config.apiKey.slice(0, 6)}...redacted` : undefined };
|
|
104
|
+
ctx.ui.notify(JSON.stringify(safe, null, 2), "info");
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
pi.registerCommand("honcho:interview", {
|
|
109
|
+
description: "Kick off a short preference interview and save a durable summary",
|
|
110
|
+
handler: async (_args, ctx) => {
|
|
111
|
+
const handles = getHandles();
|
|
112
|
+
if (!handles) {
|
|
113
|
+
ctx.ui.notify("Connect Honcho first with /honcho:setup.", "warning");
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
const preference = await ctx.ui.input("What should PI remember about how you like to work?");
|
|
117
|
+
if (!preference) {
|
|
118
|
+
ctx.ui.notify("Interview cancelled.", "warning");
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
await handles.aiPeer.conclusionsOf(handles.userPeer).create({
|
|
122
|
+
content: `User preference: ${preference}`,
|
|
123
|
+
sessionId: handles.session ?? undefined,
|
|
124
|
+
});
|
|
125
|
+
ctx.ui.notify("Saved interview insight to Honcho.", "info");
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
pi.registerCommand("honcho:doctor", {
|
|
130
|
+
description: "Run a quick Honcho preflight for config, connectivity, and session mapping",
|
|
131
|
+
handler: async (_args, ctx) => {
|
|
132
|
+
const config = await resolveConfig();
|
|
133
|
+
const checks: string[] = [];
|
|
134
|
+
|
|
135
|
+
checks.push(`api_key: ${config.apiKey ? "ok" : "missing"}`);
|
|
136
|
+
checks.push(`workspace: ${config.workspace}`);
|
|
137
|
+
checks.push(`session_strategy: ${config.sessionStrategy}`);
|
|
138
|
+
checks.push(`linked_hosts: ${config.linkedHosts.length > 0 ? config.linkedHosts.join(", ") : "none"}`);
|
|
139
|
+
|
|
140
|
+
if (!config.enabled || !config.apiKey) {
|
|
141
|
+
ctx.ui.notify([...checks, "connectivity: skipped (Honcho not configured)"].join("\n"), "warning");
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
try {
|
|
146
|
+
const honcho = new Honcho({ apiKey: config.apiKey, baseURL: config.baseURL, workspaceId: config.workspace, environment: config.environment });
|
|
147
|
+
const sessionKey = await deriveSessionKey(ctx.cwd, config.sessionStrategy, config);
|
|
148
|
+
await Promise.all([
|
|
149
|
+
honcho.peer(config.peerName),
|
|
150
|
+
honcho.peer(config.aiPeer),
|
|
151
|
+
honcho.session(sessionKey)
|
|
152
|
+
]);
|
|
153
|
+
checks.push(`connectivity: ok`);
|
|
154
|
+
checks.push(`session_key: ${sessionKey}`);
|
|
155
|
+
ctx.ui.notify(checks.join("\n"), "info");
|
|
156
|
+
} catch (error) {
|
|
157
|
+
checks.push(`connectivity: failed`);
|
|
158
|
+
checks.push(`error: ${error instanceof Error ? error.message : String(error)}`);
|
|
159
|
+
ctx.ui.notify(checks.join("\n"), "error");
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
pi.registerCommand("honcho:mode", {
|
|
165
|
+
description: "Switch recall mode (hybrid / context / tools)",
|
|
166
|
+
handler: async (args, ctx) => {
|
|
167
|
+
const mode = normalizeRecallMode(args?.trim());
|
|
168
|
+
setRecallMode(mode);
|
|
169
|
+
ctx.ui.notify(`Recall mode set to: ${mode}`, "info");
|
|
170
|
+
},
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
pi.registerCommand("honcho:map", {
|
|
174
|
+
description: "Map the current directory to a custom Honcho session name",
|
|
175
|
+
handler: async (args, ctx) => {
|
|
176
|
+
const name = args?.trim();
|
|
177
|
+
if (!name) {
|
|
178
|
+
ctx.ui.notify("Usage: /honcho:map <session-name>", "warning");
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
ctx.ui.notify(`Session mapping: ${ctx.cwd} → ${name}\nNote: add to ~/.honcho/config.json sessions manually for persistence.`, "info");
|
|
182
|
+
},
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
pi.registerCommand("honcho:sync", {
|
|
186
|
+
description: "Force context refresh and flush pending uploads",
|
|
187
|
+
handler: async (_args, ctx) => {
|
|
188
|
+
const handles = getHandles();
|
|
189
|
+
if (!handles) {
|
|
190
|
+
ctx.ui.notify("Connect Honcho first with /honcho:setup.", "warning");
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
clearCachedContext();
|
|
194
|
+
await refreshCachedContext(handles);
|
|
195
|
+
ctx.ui.notify("Context refreshed.", "info");
|
|
196
|
+
},
|
|
197
|
+
});
|
|
198
|
+
};
|