psyche-ai 10.0.4 → 10.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/README.md +8 -2
- package/dist/adapters/claude-sdk.d.ts +144 -0
- package/dist/adapters/claude-sdk.js +229 -0
- package/dist/index.js +5 -4
- package/dist/prompt.js +8 -15
- package/llms.txt +19 -0
- package/package.json +5 -1
package/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Psyche — 面向智能体的 AI-first 主观性内核
|
|
2
2
|
|
|
3
3
|
[](https://www.npmjs.com/package/psyche-ai)
|
|
4
|
-
[]()
|
|
5
5
|
[]()
|
|
6
6
|
[](LICENSE)
|
|
7
7
|
|
|
@@ -446,19 +446,25 @@ const engine = new PsycheEngine({
|
|
|
446
446
|
|
|
447
447
|
## 不只是 OpenClaw
|
|
448
448
|
|
|
449
|
-
Psyche
|
|
449
|
+
Psyche 是通用的,6 个 adapter 覆盖主流 agent 框架:
|
|
450
450
|
|
|
451
451
|
```bash
|
|
452
452
|
npm install psyche-ai
|
|
453
453
|
```
|
|
454
454
|
|
|
455
455
|
```javascript
|
|
456
|
+
// Claude Agent SDK
|
|
457
|
+
import { PsycheClaudeSDK } from "psyche-ai/claude-sdk";
|
|
458
|
+
|
|
456
459
|
// Vercel AI SDK
|
|
457
460
|
import { psycheMiddleware } from "psyche-ai/vercel-ai";
|
|
458
461
|
|
|
459
462
|
// LangChain
|
|
460
463
|
import { PsycheLangChain } from "psyche-ai/langchain";
|
|
461
464
|
|
|
465
|
+
// MCP(Claude Desktop / Cursor / Windsurf / Claude Code)
|
|
466
|
+
// npx psyche-mcp --mbti ENFP --name Luna
|
|
467
|
+
|
|
462
468
|
// 任何语言(HTTP API)
|
|
463
469
|
// psyche serve --port 3210
|
|
464
470
|
```
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import type { PsycheEngine, ProcessInputResult } from "../core.js";
|
|
2
|
+
import type { ThrongletsExport, ThrongletsTracePayload, WritebackSignalType } from "../types.js";
|
|
3
|
+
interface HookInput {
|
|
4
|
+
session_id: string;
|
|
5
|
+
cwd: string;
|
|
6
|
+
hook_event_name: string;
|
|
7
|
+
agent_id?: string;
|
|
8
|
+
agent_type?: string;
|
|
9
|
+
[key: string]: unknown;
|
|
10
|
+
}
|
|
11
|
+
interface HookOutput {
|
|
12
|
+
systemMessage?: string;
|
|
13
|
+
continue?: boolean;
|
|
14
|
+
}
|
|
15
|
+
type HookCallback = (input: HookInput, toolUseID: string | undefined, context: {
|
|
16
|
+
signal: AbortSignal;
|
|
17
|
+
}) => Promise<HookOutput | undefined>;
|
|
18
|
+
interface HookCallbackMatcher {
|
|
19
|
+
matcher?: string;
|
|
20
|
+
hooks: HookCallback[];
|
|
21
|
+
timeout?: number;
|
|
22
|
+
}
|
|
23
|
+
type HookEvent = string;
|
|
24
|
+
type HooksConfig = Partial<Record<HookEvent, HookCallbackMatcher[]>>;
|
|
25
|
+
interface SystemPromptPreset {
|
|
26
|
+
type: "preset";
|
|
27
|
+
preset: string;
|
|
28
|
+
append?: string;
|
|
29
|
+
}
|
|
30
|
+
interface AgentOptions {
|
|
31
|
+
systemPrompt?: string | SystemPromptPreset;
|
|
32
|
+
hooks?: HooksConfig;
|
|
33
|
+
[key: string]: unknown;
|
|
34
|
+
}
|
|
35
|
+
declare function stripPsycheTags(text: string): string;
|
|
36
|
+
/** Signal payload for `mcp__thronglets__signal_post` */
|
|
37
|
+
export interface ThrongletsSignalPayload {
|
|
38
|
+
kind: "psyche_state";
|
|
39
|
+
agent_id: string;
|
|
40
|
+
message: string;
|
|
41
|
+
}
|
|
42
|
+
export interface PsycheClaudeSdkOptions {
|
|
43
|
+
/** User ID for multi-user relationship tracking. Default: "default" */
|
|
44
|
+
userId?: string;
|
|
45
|
+
/** Enable Thronglets trace/signal export after each turn. Default: false */
|
|
46
|
+
thronglets?: boolean;
|
|
47
|
+
/** Agent identity for Thronglets traces/signals (e.g. "ENFP-Luna"). Default: engine name or "psyche" */
|
|
48
|
+
agentId?: string;
|
|
49
|
+
/** Session ID for Thronglets trace serialization */
|
|
50
|
+
sessionId?: string;
|
|
51
|
+
/** Override locale for protocol context */
|
|
52
|
+
locale?: "zh" | "en";
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Psyche integration for the Claude Agent SDK.
|
|
56
|
+
*
|
|
57
|
+
* Provides hook-based emotional context injection (automatic via
|
|
58
|
+
* UserPromptSubmit) and explicit output processing (processResponse).
|
|
59
|
+
*
|
|
60
|
+
* @example
|
|
61
|
+
* ```ts
|
|
62
|
+
* const psyche = new PsycheClaudeSDK(engine);
|
|
63
|
+
* const options = psyche.mergeOptions({ model: "sonnet" });
|
|
64
|
+
* for await (const msg of query({ prompt: "Hey!", options })) { ... }
|
|
65
|
+
* await psyche.processResponse(fullText);
|
|
66
|
+
* ```
|
|
67
|
+
*/
|
|
68
|
+
export declare class PsycheClaudeSDK {
|
|
69
|
+
private engine;
|
|
70
|
+
private opts;
|
|
71
|
+
private lastInputResult;
|
|
72
|
+
private lastThrongletsExports;
|
|
73
|
+
constructor(engine: PsycheEngine, opts?: PsycheClaudeSdkOptions);
|
|
74
|
+
/**
|
|
75
|
+
* Returns the stable emotional protocol prompt.
|
|
76
|
+
* Suitable for `systemPrompt.append` — changes only when locale changes.
|
|
77
|
+
*/
|
|
78
|
+
getProtocol(): string;
|
|
79
|
+
/**
|
|
80
|
+
* Returns Claude Agent SDK hooks config.
|
|
81
|
+
*
|
|
82
|
+
* - `UserPromptSubmit`: calls `engine.processInput()`, injects
|
|
83
|
+
* `dynamicContext` as `systemMessage` visible to the model.
|
|
84
|
+
*/
|
|
85
|
+
getHooks(): HooksConfig;
|
|
86
|
+
/**
|
|
87
|
+
* Process the assistant's full output text.
|
|
88
|
+
*
|
|
89
|
+
* Strips `<psyche_update>` tags and updates internal chemistry.
|
|
90
|
+
* Call this after consuming the full query output.
|
|
91
|
+
*
|
|
92
|
+
* @returns Cleaned text with tags removed
|
|
93
|
+
*/
|
|
94
|
+
processResponse(text: string, opts?: {
|
|
95
|
+
signals?: WritebackSignalType[];
|
|
96
|
+
signalConfidence?: number;
|
|
97
|
+
}): Promise<string>;
|
|
98
|
+
/**
|
|
99
|
+
* Get Thronglets trace payloads from the most recent turn.
|
|
100
|
+
*
|
|
101
|
+
* Returns serialized traces ready for `mcp__thronglets__trace_record`.
|
|
102
|
+
* Each trace includes `agent_id` for multi-agent disambiguation.
|
|
103
|
+
* Empty array if thronglets option is disabled or no exports were produced.
|
|
104
|
+
*/
|
|
105
|
+
getThrongletsTraces(): (ThrongletsTracePayload & {
|
|
106
|
+
agent_id: string;
|
|
107
|
+
})[];
|
|
108
|
+
/**
|
|
109
|
+
* Get a signal payload for `mcp__thronglets__signal_post`.
|
|
110
|
+
*
|
|
111
|
+
* Broadcasts current chemical state so other agents can sense this
|
|
112
|
+
* agent's emotional state via `substrate_query(intent: "signals", kind: "psyche_state")`.
|
|
113
|
+
*
|
|
114
|
+
* Returns null if thronglets is disabled or no processInput has run yet.
|
|
115
|
+
*/
|
|
116
|
+
getThrongletsSignal(): ThrongletsSignalPayload | null;
|
|
117
|
+
/**
|
|
118
|
+
* Get raw Thronglets exports from the most recent turn.
|
|
119
|
+
*/
|
|
120
|
+
getThrongletsExports(): ThrongletsExport[];
|
|
121
|
+
/**
|
|
122
|
+
* Get the last processInput result (useful for inspecting
|
|
123
|
+
* stimulus, subjectivityKernel, generationControls, etc.)
|
|
124
|
+
*/
|
|
125
|
+
getLastInputResult(): ProcessInputResult | null;
|
|
126
|
+
/**
|
|
127
|
+
* Merge Psyche hooks and system prompt into existing options.
|
|
128
|
+
*
|
|
129
|
+
* This is the primary integration point — pass the result to `query()`.
|
|
130
|
+
*
|
|
131
|
+
* @example
|
|
132
|
+
* ```ts
|
|
133
|
+
* const options = psyche.mergeOptions({ model: "sonnet", allowedTools: ["Read"] });
|
|
134
|
+
* for await (const msg of query({ prompt: "Hey!", options })) { ... }
|
|
135
|
+
* ```
|
|
136
|
+
*/
|
|
137
|
+
mergeOptions(baseOptions?: AgentOptions): AgentOptions;
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Strip `<psyche_update>` tags from a text string.
|
|
141
|
+
*
|
|
142
|
+
* Useful for post-processing query output when not using `processResponse`.
|
|
143
|
+
*/
|
|
144
|
+
export { stripPsycheTags };
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
// ============================================================
|
|
2
|
+
// Claude Agent SDK Adapter — Hook-based integration
|
|
3
|
+
//
|
|
4
|
+
// Usage:
|
|
5
|
+
// import { PsycheEngine, MemoryStorageAdapter } from "psyche-ai";
|
|
6
|
+
// import { PsycheClaudeSDK } from "psyche-ai/claude-sdk";
|
|
7
|
+
// import { query } from "@anthropic-ai/claude-agent-sdk";
|
|
8
|
+
//
|
|
9
|
+
// const engine = new PsycheEngine({ name: "Luna", mbti: "ENFP" }, new MemoryStorageAdapter());
|
|
10
|
+
// await engine.initialize();
|
|
11
|
+
//
|
|
12
|
+
// const psyche = new PsycheClaudeSDK(engine);
|
|
13
|
+
// let text = "";
|
|
14
|
+
// for await (const msg of query({ prompt: "Hey!", options: psyche.mergeOptions() })) {
|
|
15
|
+
// text += msg.content ?? "";
|
|
16
|
+
// }
|
|
17
|
+
// const clean = await psyche.processResponse(text);
|
|
18
|
+
//
|
|
19
|
+
// Architecture:
|
|
20
|
+
// - UserPromptSubmit hook → processInput → inject dynamicContext via systemMessage
|
|
21
|
+
// - systemPrompt.append → stable protocol context (cached, amortized)
|
|
22
|
+
// - processResponse() → strip <psyche_update> tags + update chemistry
|
|
23
|
+
// - Thronglets traces → optional export after each turn
|
|
24
|
+
//
|
|
25
|
+
// The SDK has no middleware interface and hooks cannot modify assistant
|
|
26
|
+
// output, so processResponse must be called explicitly by the host.
|
|
27
|
+
// ============================================================
|
|
28
|
+
import { serializeThrongletsExportAsTrace } from "../thronglets-runtime.js";
|
|
29
|
+
// ── Tag stripping ────────────────────────────────────────────
|
|
30
|
+
const PSYCHE_TAG_RE = /<psyche_update>[\s\S]*?<\/psyche_update>/g;
|
|
31
|
+
function stripPsycheTags(text) {
|
|
32
|
+
return text.replace(PSYCHE_TAG_RE, "").trim();
|
|
33
|
+
}
|
|
34
|
+
// ── Main class ──────────────────────────────────────────────
|
|
35
|
+
/**
|
|
36
|
+
* Psyche integration for the Claude Agent SDK.
|
|
37
|
+
*
|
|
38
|
+
* Provides hook-based emotional context injection (automatic via
|
|
39
|
+
* UserPromptSubmit) and explicit output processing (processResponse).
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* ```ts
|
|
43
|
+
* const psyche = new PsycheClaudeSDK(engine);
|
|
44
|
+
* const options = psyche.mergeOptions({ model: "sonnet" });
|
|
45
|
+
* for await (const msg of query({ prompt: "Hey!", options })) { ... }
|
|
46
|
+
* await psyche.processResponse(fullText);
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
49
|
+
export class PsycheClaudeSDK {
|
|
50
|
+
engine;
|
|
51
|
+
opts;
|
|
52
|
+
lastInputResult = null;
|
|
53
|
+
lastThrongletsExports = [];
|
|
54
|
+
constructor(engine, opts) {
|
|
55
|
+
this.engine = engine;
|
|
56
|
+
const state = engine.getState();
|
|
57
|
+
this.opts = {
|
|
58
|
+
userId: opts?.userId ?? "default",
|
|
59
|
+
thronglets: opts?.thronglets ?? false,
|
|
60
|
+
agentId: opts?.agentId ?? state.meta.agentName ?? "psyche",
|
|
61
|
+
sessionId: opts?.sessionId ?? "claude-sdk",
|
|
62
|
+
locale: opts?.locale ?? "en",
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
// ── Protocol (stable, cacheable) ──────────────────────────
|
|
66
|
+
/**
|
|
67
|
+
* Returns the stable emotional protocol prompt.
|
|
68
|
+
* Suitable for `systemPrompt.append` — changes only when locale changes.
|
|
69
|
+
*/
|
|
70
|
+
getProtocol() {
|
|
71
|
+
return this.engine.getProtocol(this.opts.locale);
|
|
72
|
+
}
|
|
73
|
+
// ── Hooks ─────────────────────────────────────────────────
|
|
74
|
+
/**
|
|
75
|
+
* Returns Claude Agent SDK hooks config.
|
|
76
|
+
*
|
|
77
|
+
* - `UserPromptSubmit`: calls `engine.processInput()`, injects
|
|
78
|
+
* `dynamicContext` as `systemMessage` visible to the model.
|
|
79
|
+
*/
|
|
80
|
+
getHooks() {
|
|
81
|
+
const self = this;
|
|
82
|
+
return {
|
|
83
|
+
UserPromptSubmit: [
|
|
84
|
+
{
|
|
85
|
+
hooks: [
|
|
86
|
+
async (input) => {
|
|
87
|
+
const userMessage = input.user_message ?? "";
|
|
88
|
+
const result = await self.engine.processInput(userMessage, {
|
|
89
|
+
userId: self.opts.userId,
|
|
90
|
+
});
|
|
91
|
+
self.lastInputResult = result;
|
|
92
|
+
// Cache Thronglets exports from this turn
|
|
93
|
+
if (self.opts.thronglets && result.throngletsExports) {
|
|
94
|
+
self.lastThrongletsExports = result.throngletsExports;
|
|
95
|
+
}
|
|
96
|
+
return { systemMessage: result.dynamicContext };
|
|
97
|
+
},
|
|
98
|
+
],
|
|
99
|
+
},
|
|
100
|
+
],
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
// ── Output processing ─────────────────────────────────────
|
|
104
|
+
/**
|
|
105
|
+
* Process the assistant's full output text.
|
|
106
|
+
*
|
|
107
|
+
* Strips `<psyche_update>` tags and updates internal chemistry.
|
|
108
|
+
* Call this after consuming the full query output.
|
|
109
|
+
*
|
|
110
|
+
* @returns Cleaned text with tags removed
|
|
111
|
+
*/
|
|
112
|
+
async processResponse(text, opts) {
|
|
113
|
+
const result = await this.engine.processOutput(text, {
|
|
114
|
+
userId: this.opts.userId,
|
|
115
|
+
signals: opts?.signals,
|
|
116
|
+
signalConfidence: opts?.signalConfidence,
|
|
117
|
+
});
|
|
118
|
+
return result.cleanedText;
|
|
119
|
+
}
|
|
120
|
+
// ── Thronglets integration ────────────────────────────────
|
|
121
|
+
/**
|
|
122
|
+
* Get Thronglets trace payloads from the most recent turn.
|
|
123
|
+
*
|
|
124
|
+
* Returns serialized traces ready for `mcp__thronglets__trace_record`.
|
|
125
|
+
* Each trace includes `agent_id` for multi-agent disambiguation.
|
|
126
|
+
* Empty array if thronglets option is disabled or no exports were produced.
|
|
127
|
+
*/
|
|
128
|
+
getThrongletsTraces() {
|
|
129
|
+
if (!this.opts.thronglets)
|
|
130
|
+
return [];
|
|
131
|
+
return this.lastThrongletsExports.map((exp) => ({
|
|
132
|
+
...serializeThrongletsExportAsTrace(exp, {
|
|
133
|
+
sessionId: this.opts.sessionId,
|
|
134
|
+
}),
|
|
135
|
+
agent_id: this.opts.agentId,
|
|
136
|
+
}));
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Get a signal payload for `mcp__thronglets__signal_post`.
|
|
140
|
+
*
|
|
141
|
+
* Broadcasts current chemical state so other agents can sense this
|
|
142
|
+
* agent's emotional state via `substrate_query(intent: "signals", kind: "psyche_state")`.
|
|
143
|
+
*
|
|
144
|
+
* Returns null if thronglets is disabled or no processInput has run yet.
|
|
145
|
+
*/
|
|
146
|
+
getThrongletsSignal() {
|
|
147
|
+
if (!this.opts.thronglets)
|
|
148
|
+
return null;
|
|
149
|
+
const state = this.engine.getState();
|
|
150
|
+
const c = state.current;
|
|
151
|
+
return {
|
|
152
|
+
kind: "psyche_state",
|
|
153
|
+
agent_id: this.opts.agentId,
|
|
154
|
+
message: `DA:${c.DA} HT:${c.HT} CORT:${c.CORT} OT:${c.OT} NE:${c.NE} END:${c.END}`,
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Get raw Thronglets exports from the most recent turn.
|
|
159
|
+
*/
|
|
160
|
+
getThrongletsExports() {
|
|
161
|
+
if (!this.opts.thronglets)
|
|
162
|
+
return [];
|
|
163
|
+
return [...this.lastThrongletsExports];
|
|
164
|
+
}
|
|
165
|
+
// ── State access ──────────────────────────────────────────
|
|
166
|
+
/**
|
|
167
|
+
* Get the last processInput result (useful for inspecting
|
|
168
|
+
* stimulus, subjectivityKernel, generationControls, etc.)
|
|
169
|
+
*/
|
|
170
|
+
getLastInputResult() {
|
|
171
|
+
return this.lastInputResult;
|
|
172
|
+
}
|
|
173
|
+
// ── Convenience ───────────────────────────────────────────
|
|
174
|
+
/**
|
|
175
|
+
* Merge Psyche hooks and system prompt into existing options.
|
|
176
|
+
*
|
|
177
|
+
* This is the primary integration point — pass the result to `query()`.
|
|
178
|
+
*
|
|
179
|
+
* @example
|
|
180
|
+
* ```ts
|
|
181
|
+
* const options = psyche.mergeOptions({ model: "sonnet", allowedTools: ["Read"] });
|
|
182
|
+
* for await (const msg of query({ prompt: "Hey!", options })) { ... }
|
|
183
|
+
* ```
|
|
184
|
+
*/
|
|
185
|
+
mergeOptions(baseOptions) {
|
|
186
|
+
const protocol = this.getProtocol();
|
|
187
|
+
const hooks = this.getHooks();
|
|
188
|
+
// Merge system prompt
|
|
189
|
+
let systemPrompt;
|
|
190
|
+
const base = baseOptions?.systemPrompt;
|
|
191
|
+
if (typeof base === "object" && base !== null && "type" in base) {
|
|
192
|
+
// Preset mode — append protocol
|
|
193
|
+
systemPrompt = {
|
|
194
|
+
...base,
|
|
195
|
+
append: protocol + (base.append ? "\n\n" + base.append : ""),
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
else if (typeof base === "string") {
|
|
199
|
+
// String mode — prepend protocol
|
|
200
|
+
systemPrompt = protocol + "\n\n" + base;
|
|
201
|
+
}
|
|
202
|
+
else {
|
|
203
|
+
// No base — use preset with append
|
|
204
|
+
systemPrompt = {
|
|
205
|
+
type: "preset",
|
|
206
|
+
preset: "claude_code",
|
|
207
|
+
append: protocol,
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
// Merge hooks (preserve existing hooks, add Psyche hooks)
|
|
211
|
+
const mergedHooks = { ...(baseOptions?.hooks ?? {}) };
|
|
212
|
+
for (const [event, matchers] of Object.entries(hooks)) {
|
|
213
|
+
const existing = mergedHooks[event] ?? [];
|
|
214
|
+
mergedHooks[event] = [...existing, ...matchers];
|
|
215
|
+
}
|
|
216
|
+
return {
|
|
217
|
+
...baseOptions,
|
|
218
|
+
systemPrompt,
|
|
219
|
+
hooks: mergedHooks,
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
// ── Utility: strip tags from message stream ─────────────────
|
|
224
|
+
/**
|
|
225
|
+
* Strip `<psyche_update>` tags from a text string.
|
|
226
|
+
*
|
|
227
|
+
* Useful for post-processing query output when not using `processResponse`.
|
|
228
|
+
*/
|
|
229
|
+
export { stripPsycheTags };
|
package/dist/index.js
CHANGED
|
@@ -7,10 +7,11 @@
|
|
|
7
7
|
// and advanced use, but are NOT part of the public contract.
|
|
8
8
|
//
|
|
9
9
|
// Framework adapters available via subpath imports:
|
|
10
|
-
// psyche-ai/openclaw
|
|
11
|
-
// psyche-ai/vercel-ai
|
|
12
|
-
// psyche-ai/langchain
|
|
13
|
-
// psyche-ai/http
|
|
10
|
+
// psyche-ai/openclaw — OpenClaw plugin
|
|
11
|
+
// psyche-ai/vercel-ai — Vercel AI SDK middleware
|
|
12
|
+
// psyche-ai/langchain — LangChain helper
|
|
13
|
+
// psyche-ai/http — HTTP server for Python/Go/etc.
|
|
14
|
+
// psyche-ai/claude-sdk — Claude Agent SDK hooks
|
|
14
15
|
// ============================================================
|
|
15
16
|
// ── Core engine ─────────────────────────────────────────────
|
|
16
17
|
export { PsycheEngine } from "./core.js";
|
package/dist/prompt.js
CHANGED
|
@@ -516,16 +516,6 @@ function buildMirrorConstraints(userText, locale) {
|
|
|
516
516
|
const title = locale === "zh" ? "镜像约束" : "Mirror Constraints";
|
|
517
517
|
return `[${title}]\n${lines.join("\n")}`;
|
|
518
518
|
}
|
|
519
|
-
function buildCompactSensingContext(_userText, locale, algorithmStimulus) {
|
|
520
|
-
if (locale === "zh") {
|
|
521
|
-
return algorithmStimulus
|
|
522
|
-
? `[情绪感知] 算法初判:${algorithmStimulus};你终判。`
|
|
523
|
-
: `[情绪感知] 情绪由你终判。`;
|
|
524
|
-
}
|
|
525
|
-
return algorithmStimulus
|
|
526
|
-
? `[Emotional Sensing] Algorithm hint: ${algorithmStimulus}; final tonal read is yours.`
|
|
527
|
-
: `[Emotional Sensing] Make the final tonal read yourself.`;
|
|
528
|
-
}
|
|
529
519
|
function isNeutralMetacognitiveNote(note) {
|
|
530
520
|
return note.includes("normal parameters")
|
|
531
521
|
|| note.includes("No regulation needed")
|
|
@@ -936,11 +926,14 @@ export function buildCompactContext(state, userId, opts) {
|
|
|
936
926
|
parts.push(bias);
|
|
937
927
|
}
|
|
938
928
|
// ── 5. Sensing ──
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
929
|
+
// v10.1: When SubjectivityKernel + ResponseContract are present (engine path),
|
|
930
|
+
// sensing is redundant — the kernel already encodes the *consequence* of the
|
|
931
|
+
// stimulus (pressure, warmth, boundary state). "你终判" is misleading because
|
|
932
|
+
// the kernel has already been computed. ambiguityPlane handles real uncertainty.
|
|
933
|
+
//
|
|
934
|
+
// Legacy verbose path (no ResponseContract) kept for non-engine callers.
|
|
935
|
+
if (userText && !opts?.responseContractContext) {
|
|
936
|
+
if (locale === "zh") {
|
|
944
937
|
parts.push(`[情绪感知]\n` +
|
|
945
938
|
`对方刚才说了: "${userText.slice(0, 200)}"\n` +
|
|
946
939
|
(algoStimulus ? `算法初判: ${algoStimulus}(仅供参考,你来终判)\n` : "") +
|
package/llms.txt
CHANGED
|
@@ -112,6 +112,24 @@ const output = await engine.processOutput(llmResponse);
|
|
|
112
112
|
}
|
|
113
113
|
```
|
|
114
114
|
|
|
115
|
+
## Quick Start (Claude Agent SDK)
|
|
116
|
+
|
|
117
|
+
```ts
|
|
118
|
+
import { PsycheEngine, MemoryStorageAdapter } from "psyche-ai";
|
|
119
|
+
import { PsycheClaudeSDK } from "psyche-ai/claude-sdk";
|
|
120
|
+
import { query } from "@anthropic-ai/claude-agent-sdk";
|
|
121
|
+
|
|
122
|
+
const engine = new PsycheEngine({ name: "Luna" }, new MemoryStorageAdapter());
|
|
123
|
+
await engine.initialize();
|
|
124
|
+
|
|
125
|
+
const psyche = new PsycheClaudeSDK(engine);
|
|
126
|
+
let text = "";
|
|
127
|
+
for await (const msg of query({ prompt: "Hey!", options: psyche.mergeOptions() })) {
|
|
128
|
+
text += msg.content ?? "";
|
|
129
|
+
}
|
|
130
|
+
await psyche.processResponse(text);
|
|
131
|
+
```
|
|
132
|
+
|
|
115
133
|
## Why Hosts Use It
|
|
116
134
|
|
|
117
135
|
- zero extra model calls
|
|
@@ -147,6 +165,7 @@ npx psyche-mcp
|
|
|
147
165
|
## Adapter Sub-paths
|
|
148
166
|
|
|
149
167
|
- `psyche-ai` — core engine (PsycheEngine, MemoryStorageAdapter)
|
|
168
|
+
- `psyche-ai/claude-sdk` — Claude Agent SDK hooks (PsycheClaudeSDK)
|
|
150
169
|
- `psyche-ai/mcp` — MCP stdio server
|
|
151
170
|
- `psyche-ai/vercel-ai` — Vercel AI SDK middleware
|
|
152
171
|
- `psyche-ai/langchain` — LangChain adapter
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "psyche-ai",
|
|
3
|
-
"version": "10.0
|
|
3
|
+
"version": "10.1.0",
|
|
4
4
|
"description": "AI-first subjectivity kernel for agents with continuous appraisal, relation dynamics, and adaptive reply loops",
|
|
5
5
|
"mcpName": "io.github.Shangri-la-0428/psyche-ai",
|
|
6
6
|
"type": "module",
|
|
@@ -30,6 +30,10 @@
|
|
|
30
30
|
"./mcp": {
|
|
31
31
|
"types": "./dist/adapters/mcp.d.ts",
|
|
32
32
|
"default": "./dist/adapters/mcp.js"
|
|
33
|
+
},
|
|
34
|
+
"./claude-sdk": {
|
|
35
|
+
"types": "./dist/adapters/claude-sdk.d.ts",
|
|
36
|
+
"default": "./dist/adapters/claude-sdk.js"
|
|
33
37
|
}
|
|
34
38
|
},
|
|
35
39
|
"bin": {
|