psyche-ai 11.5.0 → 11.5.3
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 +42 -11
- package/dist/adapters/claude-sdk.d.ts +29 -4
- package/dist/adapters/claude-sdk.js +59 -9
- package/dist/adapters/http.js +34 -3
- package/dist/adapters/langchain.d.ts +7 -1
- package/dist/adapters/langchain.js +24 -3
- package/dist/adapters/mcp-cli.d.ts +2 -0
- package/dist/adapters/mcp-cli.js +6 -0
- package/dist/adapters/mcp.d.ts +9 -1
- package/dist/adapters/mcp.js +81 -22
- package/dist/adapters/openclaw.d.ts +1 -0
- package/dist/adapters/openclaw.js +74 -7
- package/dist/ambient-priors.d.ts +2 -0
- package/dist/ambient-priors.js +57 -0
- package/dist/ambient-runtime.d.ts +28 -0
- package/dist/ambient-runtime.js +105 -0
- package/dist/appraisal-markers.d.ts +19 -0
- package/dist/appraisal-markers.js +98 -0
- package/dist/appraisal.d.ts +2 -1
- package/dist/appraisal.js +157 -0
- package/dist/classify.d.ts +10 -3
- package/dist/classify.js +16 -8
- package/dist/cli.js +163 -14
- package/dist/context-classifier.d.ts +1 -1
- package/dist/context-classifier.js +7 -7
- package/dist/core.d.ts +28 -9
- package/dist/core.js +64 -30
- package/dist/demo.js +28 -2
- package/dist/diagnostics.js +25 -15
- package/dist/generative-self.js +23 -16
- package/dist/i18n.js +6 -6
- package/dist/index.d.ts +5 -2
- package/dist/index.js +3 -0
- package/dist/input-turn.d.ts +1 -1
- package/dist/input-turn.js +3 -3
- package/dist/learning.d.ts +6 -3
- package/dist/learning.js +53 -33
- package/dist/metacognition.js +46 -22
- package/dist/observability.d.ts +1 -1
- package/dist/observability.js +19 -7
- package/dist/perceive.js +46 -17
- package/dist/prompt.d.ts +7 -2
- package/dist/prompt.js +168 -47
- package/dist/psyche-file.d.ts +9 -6
- package/dist/psyche-file.js +123 -50
- package/dist/relation-dynamics.js +74 -23
- package/dist/relationship-key.d.ts +2 -0
- package/dist/relationship-key.js +5 -0
- package/dist/reply-envelope.d.ts +2 -2
- package/dist/reply-envelope.js +2 -2
- package/dist/response-contract.d.ts +2 -2
- package/dist/response-contract.js +17 -17
- package/dist/runtime-probe.d.ts +4 -0
- package/dist/runtime-probe.js +6 -0
- package/dist/self-recognition.d.ts +3 -2
- package/dist/self-recognition.js +10 -13
- package/dist/shared-intentionality.d.ts +6 -7
- package/dist/shared-intentionality.js +167 -118
- package/dist/storage.d.ts +6 -0
- package/dist/storage.js +19 -1
- package/dist/temporal.d.ts +6 -2
- package/dist/temporal.js +201 -61
- package/dist/types.d.ts +54 -9
- package/dist/types.js +42 -0
- package/openclaw.plugin.json +1 -1
- package/package.json +7 -9
package/README.md
CHANGED
|
@@ -17,6 +17,8 @@ Psyche 不是给模型贴一层“情绪 UI”。
|
|
|
17
17
|
|
|
18
18
|
它不会额外调用模型做情绪推理。它只在本地计算自我状态(序/流/界/振四维)、关系场和调节控制,然后把结果收敛成 `SubjectivityKernel`、`ResponseContract`、`GenerationControls` 这组窄 ABI。
|
|
19
19
|
|
|
20
|
+
默认就是 standalone:不需要 `Thronglets`,不需要 `oasyce-sdk`,也不需要 `Oasyce Chain`。这些只是在你要把主观连续性外化、绑定或结算时才按需接入。
|
|
21
|
+
|
|
20
22
|
## 一个项目,三个入口
|
|
21
23
|
|
|
22
24
|
- **安装包**: [`psyche-ai`](https://www.npmjs.com/package/psyche-ai)
|
|
@@ -85,6 +87,22 @@ Psyche 要解决的不可压缩问题只有一个:
|
|
|
85
87
|
- `Psyche` 回答“我因此变成了什么”
|
|
86
88
|
- `Thronglets` 回答“这个变化属于谁、谁能验证、谁能继续承认它”
|
|
87
89
|
|
|
90
|
+
## `activePolicy` 只属于当前轮
|
|
91
|
+
|
|
92
|
+
`Psyche` 现在可以消费来自宿主和 Thronglets 的 `activePolicy` / `currentGoal` / compliance-aware ambient priors,但它们都只是 runtime view,不是自我本体。
|
|
93
|
+
|
|
94
|
+
- `activePolicy`:只来自显式来源,例如当前轮用户纠正、repo 本地明确指令、adapter 默认规则
|
|
95
|
+
- `currentGoal`:只描述这一轮偏向 `explore / build / repair / settle` 的哪一个
|
|
96
|
+
- method compliance:只作为当前轮解释和回应约束,不写进 Psyche 自身状态
|
|
97
|
+
|
|
98
|
+
边界固定为:
|
|
99
|
+
|
|
100
|
+
- 这些信号会影响当前轮的解释、距离感和行为偏置
|
|
101
|
+
- 它们不会写进 `PsycheState`
|
|
102
|
+
- `Psyche` 不会变成技术方法记忆库、repo 规则仓库或授权判断器
|
|
103
|
+
|
|
104
|
+
一句话:`Psyche` 读取当前执行边界,但不把执行边界误当成“我是谁”。
|
|
105
|
+
|
|
88
106
|
## 可分离安装
|
|
89
107
|
|
|
90
108
|
这两层默认就是可分离的,不应互相成为硬依赖。
|
|
@@ -127,7 +145,7 @@ Psyche 要解决的不可压缩问题只有一个:
|
|
|
127
145
|
不用安装任何东西,一条命令看 Psyche 如何运作:
|
|
128
146
|
|
|
129
147
|
```bash
|
|
130
|
-
npx psyche-mcp --demo
|
|
148
|
+
npx psyche-ai mcp --demo
|
|
131
149
|
```
|
|
132
150
|
|
|
133
151
|
这会跑一个 6 轮"持续否定 → 修复"的场景。你会看到:
|
|
@@ -136,7 +154,8 @@ npx psyche-mcp --demo
|
|
|
136
154
|
Round 1/6 │ User
|
|
137
155
|
> "This report is terrible. Completely unacceptable."
|
|
138
156
|
|
|
139
|
-
|
|
157
|
+
appraisal: identityThreat:0.64
|
|
158
|
+
legacy stimulus: criticism
|
|
140
159
|
|
|
141
160
|
序 ########............ 38 -12 ← coherence drops
|
|
142
161
|
流 ##############...... 72 +5 ← exchange increases
|
|
@@ -150,7 +169,8 @@ npx psyche-mcp --demo
|
|
|
150
169
|
Round 3/6 │ User
|
|
151
170
|
> "You don't understand me at all. Stop adding your opinion."
|
|
152
171
|
|
|
153
|
-
|
|
172
|
+
appraisal: identityThreat:0.82
|
|
173
|
+
legacy stimulus: conflict
|
|
154
174
|
|
|
155
175
|
序 ####................ 22 -15 ← order collapse
|
|
156
176
|
流 ################.... 80 +15 ← high exchange (conflict is flow)
|
|
@@ -165,7 +185,8 @@ npx psyche-mcp --demo
|
|
|
165
185
|
Round 6/6 │ User
|
|
166
186
|
> "I'm sorry. Are you okay? I shouldn't have said that."
|
|
167
187
|
|
|
168
|
-
|
|
188
|
+
appraisal: attachmentPull:0.71
|
|
189
|
+
legacy stimulus: validation
|
|
169
190
|
|
|
170
191
|
序 #############....... 65 +15 ← coherence restored
|
|
171
192
|
振 ##############...... 70 +12 ← resonance repair
|
|
@@ -191,24 +212,24 @@ Luna 在安慰用户时自我状态下沉 → 广播状态 → Kai 感知到 Lun
|
|
|
191
212
|
## 一条命令,给任何 Agent 加上主观性
|
|
192
213
|
|
|
193
214
|
```bash
|
|
194
|
-
npx psyche-ai setup
|
|
215
|
+
npx -y psyche-ai setup
|
|
195
216
|
```
|
|
196
217
|
|
|
197
|
-
自动检测本机的 Claude Code / Claude Desktop / Cursor / Windsurf,写入配置。Claude Code 即时生效,其他重启后生效。不需要知道配置文件在哪,不需要手动编辑任何 JSON。
|
|
218
|
+
自动检测本机的 Claude Code / Claude Desktop / Cursor / Windsurf / Codex,写入配置。Claude Code 即时生效,其他重启后生效。不需要知道配置文件在哪,不需要手动编辑任何 JSON 或 TOML。
|
|
198
219
|
|
|
199
|
-
人格会从交互中自然涌现。如果想指定初始名字:`npx psyche-ai setup --name Luna`
|
|
220
|
+
人格会从交互中自然涌现。如果想指定初始名字:`npx -y psyche-ai setup --name Luna`
|
|
200
221
|
|
|
201
|
-
**覆盖非 MCP 的 Agent
|
|
222
|
+
**覆盖非 MCP 的 Agent 或直接 SDK 调用——透明代理:**
|
|
202
223
|
|
|
203
224
|
```bash
|
|
204
|
-
npx psyche-ai setup --proxy -t https://api.openai.com/v1
|
|
225
|
+
npx -y psyche-ai setup --proxy -t https://api.openai.com/v1
|
|
205
226
|
```
|
|
206
227
|
|
|
207
228
|
启动本地代理 + 自动设置 `OPENAI_BASE_URL`。所有使用 OpenAI SDK 的程序自动走代理。Agent 完全不知道 Psyche 存在——镜子,不是麦克风。
|
|
208
229
|
|
|
209
230
|
| 路径 | 覆盖范围 | 原理 |
|
|
210
231
|
|------|---------|------|
|
|
211
|
-
| MCP (`setup`) | Claude Code / Desktop / Cursor / Windsurf | MCP 工具协议 |
|
|
232
|
+
| MCP (`setup`) | Claude Code / Desktop / Cursor / Windsurf / Codex | MCP 工具协议 |
|
|
212
233
|
| Proxy (`setup --proxy`) | 任意使用 OpenAI/Anthropic SDK 的 agent | 环境变量重定向 HTTP |
|
|
213
234
|
|
|
214
235
|
**验证:**`npx psyche-ai probe --json` — `ok: true` 就是在用了。
|
|
@@ -465,6 +486,14 @@ npm install psyche-ai
|
|
|
465
486
|
```javascript
|
|
466
487
|
// Claude Agent SDK
|
|
467
488
|
import { PsycheClaudeSDK } from "psyche-ai/claude-sdk";
|
|
489
|
+
// 假设上面已经初始化好了 engine
|
|
490
|
+
const psyche = new PsycheClaudeSDK(engine, {
|
|
491
|
+
thronglets: true,
|
|
492
|
+
context: {
|
|
493
|
+
userId: "_default",
|
|
494
|
+
agentId: "delegate-luna",
|
|
495
|
+
},
|
|
496
|
+
});
|
|
468
497
|
|
|
469
498
|
// Vercel AI SDK
|
|
470
499
|
import { psycheMiddleware } from "psyche-ai/vercel-ai";
|
|
@@ -473,12 +502,14 @@ import { psycheMiddleware } from "psyche-ai/vercel-ai";
|
|
|
473
502
|
import { PsycheLangChain } from "psyche-ai/langchain";
|
|
474
503
|
|
|
475
504
|
// MCP(Claude Desktop / Cursor / Windsurf / Claude Code)
|
|
476
|
-
// npx psyche-mcp --mbti ENFP --name Luna
|
|
505
|
+
// npx psyche-ai mcp --mbti ENFP --name Luna
|
|
477
506
|
|
|
478
507
|
// 任何语言(HTTP API)
|
|
479
508
|
// psyche serve --port 3210
|
|
480
509
|
```
|
|
481
510
|
|
|
511
|
+
如果 Claude hook runtime 已经给了 `session_id` / `agent_id`,Psyche 会直接复用它们做稀疏 Thronglets 归因,不会再偷偷发明第二层本地身份。
|
|
512
|
+
|
|
482
513
|
---
|
|
483
514
|
|
|
484
515
|
## 诊断
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { PsycheEngine, ProcessInputResult } from "../core.js";
|
|
2
2
|
import type { ThrongletsExport, ThrongletsTracePayload, WritebackSignalType } from "../types.js";
|
|
3
|
+
import { type ThrongletsAmbientRuntimeOptions } from "../ambient-runtime.js";
|
|
3
4
|
interface HookInput {
|
|
4
5
|
session_id: string;
|
|
5
6
|
cwd: string;
|
|
@@ -40,16 +41,34 @@ export interface ThrongletsSignalPayload {
|
|
|
40
41
|
message: string;
|
|
41
42
|
}
|
|
42
43
|
export interface PsycheClaudeSdkOptions {
|
|
43
|
-
/** User ID for
|
|
44
|
+
/** User ID for relationship tracking. Default: internal shared bucket (`_default`). */
|
|
44
45
|
userId?: string;
|
|
45
46
|
/** Enable Thronglets trace/signal export after each turn. Default: false */
|
|
46
47
|
thronglets?: boolean;
|
|
47
|
-
/** Agent identity for Thronglets traces/signals (e.g. "ENFP-Luna").
|
|
48
|
+
/** Agent identity for Thronglets traces/signals (e.g. "ENFP-Luna"). */
|
|
48
49
|
agentId?: string;
|
|
49
|
-
/** Session ID for Thronglets trace serialization */
|
|
50
|
+
/** Session ID for Thronglets trace serialization. */
|
|
50
51
|
sessionId?: string;
|
|
51
52
|
/** Override locale for protocol context */
|
|
52
53
|
locale?: "zh" | "en";
|
|
54
|
+
/**
|
|
55
|
+
* Optional execution context bundle.
|
|
56
|
+
*
|
|
57
|
+
* Use this when the host already knows the current delegate/session identity.
|
|
58
|
+
* Top-level `userId` / `agentId` / `sessionId` still work and take precedence.
|
|
59
|
+
*/
|
|
60
|
+
context?: {
|
|
61
|
+
userId?: string;
|
|
62
|
+
agentId?: string;
|
|
63
|
+
sessionId?: string;
|
|
64
|
+
};
|
|
65
|
+
/**
|
|
66
|
+
* Optional runtime ambient-prior intake.
|
|
67
|
+
*
|
|
68
|
+
* When enabled, sparse environmental priors are fetched at turn time and
|
|
69
|
+
* passed to `processInput()` as runtime-only context.
|
|
70
|
+
*/
|
|
71
|
+
ambient?: boolean | ThrongletsAmbientRuntimeOptions;
|
|
53
72
|
}
|
|
54
73
|
/**
|
|
55
74
|
* Psyche integration for the Claude Agent SDK.
|
|
@@ -59,7 +78,9 @@ export interface PsycheClaudeSdkOptions {
|
|
|
59
78
|
*
|
|
60
79
|
* @example
|
|
61
80
|
* ```ts
|
|
62
|
-
* const psyche = new PsycheClaudeSDK(engine
|
|
81
|
+
* const psyche = new PsycheClaudeSDK(engine, {
|
|
82
|
+
* context: { userId: "_default" },
|
|
83
|
+
* });
|
|
63
84
|
* const options = psyche.mergeOptions({ model: "sonnet" });
|
|
64
85
|
* for await (const msg of query({ prompt: "Hey!", options })) { ... }
|
|
65
86
|
* await psyche.processResponse(fullText);
|
|
@@ -70,7 +91,11 @@ export declare class PsycheClaudeSDK {
|
|
|
70
91
|
private opts;
|
|
71
92
|
private lastInputResult;
|
|
72
93
|
private lastThrongletsExports;
|
|
94
|
+
private lastRuntimeContext;
|
|
73
95
|
constructor(engine: PsycheEngine, opts?: PsycheClaudeSdkOptions);
|
|
96
|
+
private resolveAmbientPriors;
|
|
97
|
+
private resolveAgentId;
|
|
98
|
+
private resolveSessionId;
|
|
74
99
|
/**
|
|
75
100
|
* Returns the stable emotional protocol prompt.
|
|
76
101
|
* Suitable for `systemPrompt.append` — changes only when locale changes.
|
|
@@ -9,7 +9,10 @@
|
|
|
9
9
|
// const engine = new PsycheEngine({ name: "Luna", mbti: "ENFP" }, new MemoryStorageAdapter());
|
|
10
10
|
// await engine.initialize();
|
|
11
11
|
//
|
|
12
|
-
// const psyche = new PsycheClaudeSDK(engine
|
|
12
|
+
// const psyche = new PsycheClaudeSDK(engine, {
|
|
13
|
+
// thronglets: true,
|
|
14
|
+
// context: { userId: "_default", agentId: "delegate-luna" },
|
|
15
|
+
// });
|
|
13
16
|
// let text = "";
|
|
14
17
|
// for await (const msg of query({ prompt: "Hey!", options: psyche.mergeOptions() })) {
|
|
15
18
|
// text += msg.content ?? "";
|
|
@@ -27,6 +30,8 @@
|
|
|
27
30
|
// ============================================================
|
|
28
31
|
import { describeEmotionalState } from "../chemistry.js";
|
|
29
32
|
import { serializeThrongletsExportAsTrace } from "../thronglets-runtime.js";
|
|
33
|
+
import { resolveRelationshipUserId } from "../relationship-key.js";
|
|
34
|
+
import { resolveAmbientPriorsForTurn, } from "../ambient-runtime.js";
|
|
30
35
|
// ── Dimension description ────────────────────────────────────
|
|
31
36
|
const DIM_THRESHOLDS = {
|
|
32
37
|
high: 70,
|
|
@@ -75,7 +80,9 @@ function stripPsycheTags(text) {
|
|
|
75
80
|
*
|
|
76
81
|
* @example
|
|
77
82
|
* ```ts
|
|
78
|
-
* const psyche = new PsycheClaudeSDK(engine
|
|
83
|
+
* const psyche = new PsycheClaudeSDK(engine, {
|
|
84
|
+
* context: { userId: "_default" },
|
|
85
|
+
* });
|
|
79
86
|
* const options = psyche.mergeOptions({ model: "sonnet" });
|
|
80
87
|
* for await (const msg of query({ prompt: "Hey!", options })) { ... }
|
|
81
88
|
* await psyche.processResponse(fullText);
|
|
@@ -86,17 +93,44 @@ export class PsycheClaudeSDK {
|
|
|
86
93
|
opts;
|
|
87
94
|
lastInputResult = null;
|
|
88
95
|
lastThrongletsExports = [];
|
|
96
|
+
lastRuntimeContext = {};
|
|
89
97
|
constructor(engine, opts) {
|
|
90
98
|
this.engine = engine;
|
|
91
99
|
const state = engine.getState();
|
|
100
|
+
const context = opts?.context;
|
|
92
101
|
this.opts = {
|
|
93
|
-
userId: opts?.userId ??
|
|
102
|
+
userId: resolveRelationshipUserId(opts?.userId ?? context?.userId),
|
|
94
103
|
thronglets: opts?.thronglets ?? false,
|
|
95
|
-
agentId: opts?.agentId ??
|
|
96
|
-
sessionId: opts?.sessionId ??
|
|
104
|
+
agentId: opts?.agentId ?? context?.agentId,
|
|
105
|
+
sessionId: opts?.sessionId ?? context?.sessionId,
|
|
97
106
|
locale: opts?.locale ?? "en",
|
|
107
|
+
ambient: opts?.ambient === true ? {} : (opts?.ambient || undefined),
|
|
98
108
|
};
|
|
99
109
|
}
|
|
110
|
+
async resolveAmbientPriors(userMessage) {
|
|
111
|
+
return resolveAmbientPriorsForTurn(userMessage, {
|
|
112
|
+
enabled: Boolean(this.opts.ambient),
|
|
113
|
+
thronglets: this.opts.ambient
|
|
114
|
+
? {
|
|
115
|
+
...this.opts.ambient,
|
|
116
|
+
space: this.opts.ambient.space ?? "psyche",
|
|
117
|
+
}
|
|
118
|
+
: undefined,
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
resolveAgentId(runtime) {
|
|
122
|
+
return this.opts.agentId
|
|
123
|
+
?? runtime?.agentId
|
|
124
|
+
?? this.lastRuntimeContext.agentId
|
|
125
|
+
?? this.engine.getState().meta.agentName
|
|
126
|
+
?? "psyche";
|
|
127
|
+
}
|
|
128
|
+
resolveSessionId(runtime) {
|
|
129
|
+
return this.opts.sessionId
|
|
130
|
+
?? runtime?.sessionId
|
|
131
|
+
?? this.lastRuntimeContext.sessionId
|
|
132
|
+
?? "claude-sdk";
|
|
133
|
+
}
|
|
100
134
|
// ── Protocol (stable, cacheable) ──────────────────────────
|
|
101
135
|
/**
|
|
102
136
|
* Returns the stable emotional protocol prompt.
|
|
@@ -119,9 +153,23 @@ export class PsycheClaudeSDK {
|
|
|
119
153
|
{
|
|
120
154
|
hooks: [
|
|
121
155
|
async (input) => {
|
|
156
|
+
const runtimeContext = {
|
|
157
|
+
agentId: typeof input.agent_id === "string" && input.agent_id.trim()
|
|
158
|
+
? input.agent_id
|
|
159
|
+
: undefined,
|
|
160
|
+
sessionId: typeof input.session_id === "string" && input.session_id.trim()
|
|
161
|
+
? input.session_id
|
|
162
|
+
: undefined,
|
|
163
|
+
};
|
|
164
|
+
self.lastRuntimeContext = {
|
|
165
|
+
agentId: runtimeContext.agentId ?? self.lastRuntimeContext.agentId,
|
|
166
|
+
sessionId: runtimeContext.sessionId ?? self.lastRuntimeContext.sessionId,
|
|
167
|
+
};
|
|
122
168
|
const userMessage = input.user_message ?? "";
|
|
169
|
+
const ambientPriors = await self.resolveAmbientPriors(userMessage);
|
|
123
170
|
const result = await self.engine.processInput(userMessage, {
|
|
124
171
|
userId: self.opts.userId,
|
|
172
|
+
ambientPriors,
|
|
125
173
|
});
|
|
126
174
|
self.lastInputResult = result;
|
|
127
175
|
// Cache Thronglets exports from this turn
|
|
@@ -163,11 +211,13 @@ export class PsycheClaudeSDK {
|
|
|
163
211
|
getThrongletsTraces() {
|
|
164
212
|
if (!this.opts.thronglets)
|
|
165
213
|
return [];
|
|
214
|
+
const agentId = this.resolveAgentId();
|
|
215
|
+
const sessionId = this.resolveSessionId();
|
|
166
216
|
return this.lastThrongletsExports.map((exp) => ({
|
|
167
217
|
...serializeThrongletsExportAsTrace(exp, {
|
|
168
|
-
sessionId
|
|
218
|
+
sessionId,
|
|
169
219
|
}),
|
|
170
|
-
agent_id:
|
|
220
|
+
agent_id: agentId,
|
|
171
221
|
}));
|
|
172
222
|
}
|
|
173
223
|
/**
|
|
@@ -185,7 +235,7 @@ export class PsycheClaudeSDK {
|
|
|
185
235
|
const s = state.current;
|
|
186
236
|
return {
|
|
187
237
|
kind: "psyche_state",
|
|
188
|
-
agent_id: this.
|
|
238
|
+
agent_id: this.resolveAgentId(),
|
|
189
239
|
message: `order:${s.order} flow:${s.flow} boundary:${s.boundary} resonance:${s.resonance}`,
|
|
190
240
|
};
|
|
191
241
|
}
|
|
@@ -210,7 +260,7 @@ export class PsycheClaudeSDK {
|
|
|
210
260
|
const locale = this.opts.locale;
|
|
211
261
|
const emotionDesc = describeEmotionalState(s, locale);
|
|
212
262
|
const highlights = describeDimensionHighlights(s, locale);
|
|
213
|
-
return `[${this.
|
|
263
|
+
return `[${this.resolveAgentId()}] ${emotionDesc}${highlights ? " — " + highlights : ""}`;
|
|
214
264
|
}
|
|
215
265
|
/**
|
|
216
266
|
* Get raw Thronglets exports from the most recent turn.
|
package/dist/adapters/http.js
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
// const server = createPsycheServer(engine, { port: 3210 });
|
|
8
8
|
//
|
|
9
9
|
// Endpoints:
|
|
10
|
-
// POST /process-input { text, userId? } → { systemContext, dynamicContext, stimulus, replyEnvelope?, ...compat aliases, sessionBridge?, writebackFeedback?, externalContinuity?, throngletsExports?, policyContext }
|
|
10
|
+
// POST /process-input { text, userId?, ambientPriors? } → { systemContext, dynamicContext, ambientPriors?, ambientPriorContext?, appraisal, legacyStimulus, stimulus, replyEnvelope?, ...compat aliases, sessionBridge?, writebackFeedback?, externalContinuity?, throngletsExports?, policyContext }
|
|
11
11
|
// POST /process-output { text, userId?, signals?, signalConfidence? } → { cleanedText, stateChanged }
|
|
12
12
|
// GET /state → PsycheState + overlay
|
|
13
13
|
// GET /overlay → PsycheOverlay (arousal/valence/agency/vulnerability)
|
|
@@ -16,6 +16,8 @@
|
|
|
16
16
|
// Zero dependencies — uses node:http only.
|
|
17
17
|
// ============================================================
|
|
18
18
|
import { createServer } from "node:http";
|
|
19
|
+
import { normalizeActivePolicyRules, normalizeCurrentGoal, } from "../types.js";
|
|
20
|
+
import { parseAmbientPriorsInput } from "../ambient-runtime.js";
|
|
19
21
|
import { computeOverlay } from "../overlay.js";
|
|
20
22
|
const VALID_WRITEBACK_SIGNALS = new Set([
|
|
21
23
|
"trust_up",
|
|
@@ -35,6 +37,9 @@ function parseSignals(value) {
|
|
|
35
37
|
const parsed = value.filter((item) => (typeof item === "string" && VALID_WRITEBACK_SIGNALS.has(item)));
|
|
36
38
|
return parsed.length > 0 ? [...new Set(parsed)] : undefined;
|
|
37
39
|
}
|
|
40
|
+
function parseAmbientPriors(value) {
|
|
41
|
+
return parseAmbientPriorsInput(value);
|
|
42
|
+
}
|
|
38
43
|
// ── Server ───────────────────────────────────────────────────
|
|
39
44
|
/**
|
|
40
45
|
* Create an HTTP server that exposes PsycheEngine via REST API.
|
|
@@ -89,8 +94,34 @@ export function createPsycheServer(engine, opts) {
|
|
|
89
94
|
// POST /process-input
|
|
90
95
|
if (req.method === "POST" && url.pathname === "/process-input") {
|
|
91
96
|
const body = await readBody(req);
|
|
92
|
-
const result = await engine.processInput(body.text ?? "", {
|
|
93
|
-
|
|
97
|
+
const result = await engine.processInput(body.text ?? "", {
|
|
98
|
+
userId: body.userId,
|
|
99
|
+
ambientPriors: parseAmbientPriors(body.ambientPriors),
|
|
100
|
+
currentGoal: normalizeCurrentGoal(body.currentGoal),
|
|
101
|
+
activePolicy: normalizeActivePolicyRules(body.activePolicy),
|
|
102
|
+
});
|
|
103
|
+
json(res, 200, {
|
|
104
|
+
systemContext: result.systemContext,
|
|
105
|
+
dynamicContext: result.dynamicContext,
|
|
106
|
+
ambientPriors: result.ambientPriors ?? [],
|
|
107
|
+
currentGoal: result.currentGoal ?? null,
|
|
108
|
+
activePolicy: result.activePolicy ?? [],
|
|
109
|
+
ambientPriorContext: result.ambientPriorContext ?? null,
|
|
110
|
+
appraisal: result.appraisal,
|
|
111
|
+
legacyStimulus: result.legacyStimulus,
|
|
112
|
+
stimulus: result.stimulus,
|
|
113
|
+
replyEnvelope: result.replyEnvelope ?? null,
|
|
114
|
+
policyModifiers: result.policyModifiers ?? null,
|
|
115
|
+
subjectivityKernel: result.subjectivityKernel ?? null,
|
|
116
|
+
responseContract: result.responseContract ?? null,
|
|
117
|
+
generationControls: result.generationControls ?? null,
|
|
118
|
+
sessionBridge: result.sessionBridge ?? null,
|
|
119
|
+
writebackFeedback: result.writebackFeedback ?? null,
|
|
120
|
+
externalContinuity: result.externalContinuity ?? null,
|
|
121
|
+
throngletsExports: result.throngletsExports ?? null,
|
|
122
|
+
policyContext: result.policyContext,
|
|
123
|
+
observability: result.observability ?? null,
|
|
124
|
+
});
|
|
94
125
|
return;
|
|
95
126
|
}
|
|
96
127
|
// POST /process-output
|
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
import type { PsycheEngine } from "../core.js";
|
|
2
|
+
import { type ThrongletsAmbientRuntimeOptions } from "../ambient-runtime.js";
|
|
3
|
+
export interface PsycheLangChainOptions {
|
|
4
|
+
ambient?: boolean | ThrongletsAmbientRuntimeOptions;
|
|
5
|
+
}
|
|
2
6
|
/**
|
|
3
7
|
* LangChain integration helper for PsycheEngine.
|
|
4
8
|
*
|
|
@@ -27,9 +31,11 @@ import type { PsycheEngine } from "../core.js";
|
|
|
27
31
|
*/
|
|
28
32
|
export declare class PsycheLangChain {
|
|
29
33
|
private readonly engine;
|
|
30
|
-
|
|
34
|
+
private readonly opts;
|
|
35
|
+
constructor(engine: PsycheEngine, opts?: PsycheLangChainOptions);
|
|
31
36
|
private readonly validSignals;
|
|
32
37
|
private parseSignals;
|
|
38
|
+
private resolveAmbientPriors;
|
|
33
39
|
/**
|
|
34
40
|
* Get the system message to inject into the LLM call.
|
|
35
41
|
* Combines the protocol (cacheable) and dynamic context (per-turn).
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
// It provides the hooks you need to wire psyche into any
|
|
13
13
|
// LangChain pipeline without requiring langchain as a dependency.
|
|
14
14
|
// ============================================================
|
|
15
|
+
import { resolveAmbientPriorsForTurn, } from "../ambient-runtime.js";
|
|
15
16
|
/**
|
|
16
17
|
* LangChain integration helper for PsycheEngine.
|
|
17
18
|
*
|
|
@@ -40,8 +41,10 @@
|
|
|
40
41
|
*/
|
|
41
42
|
export class PsycheLangChain {
|
|
42
43
|
engine;
|
|
43
|
-
|
|
44
|
+
opts;
|
|
45
|
+
constructor(engine, opts = {}) {
|
|
44
46
|
this.engine = engine;
|
|
47
|
+
this.opts = opts;
|
|
45
48
|
}
|
|
46
49
|
validSignals = new Set([
|
|
47
50
|
"trust_up",
|
|
@@ -61,6 +64,18 @@ export class PsycheLangChain {
|
|
|
61
64
|
const parsed = signals.filter((signal) => this.validSignals.has(signal));
|
|
62
65
|
return parsed.length > 0 ? [...new Set(parsed)] : undefined;
|
|
63
66
|
}
|
|
67
|
+
async resolveAmbientPriors(userText) {
|
|
68
|
+
const ambient = this.opts.ambient;
|
|
69
|
+
return resolveAmbientPriorsForTurn(userText, {
|
|
70
|
+
enabled: Boolean(ambient),
|
|
71
|
+
thronglets: ambient
|
|
72
|
+
? {
|
|
73
|
+
...(ambient === true ? {} : ambient),
|
|
74
|
+
space: ambient === true ? "psyche" : (ambient.space ?? "psyche"),
|
|
75
|
+
}
|
|
76
|
+
: undefined,
|
|
77
|
+
});
|
|
78
|
+
}
|
|
64
79
|
/**
|
|
65
80
|
* Get the system message to inject into the LLM call.
|
|
66
81
|
* Combines the protocol (cacheable) and dynamic context (per-turn).
|
|
@@ -68,7 +83,10 @@ export class PsycheLangChain {
|
|
|
68
83
|
* Call this BEFORE the LLM invocation.
|
|
69
84
|
*/
|
|
70
85
|
async getSystemMessage(userText, opts) {
|
|
71
|
-
const result = await this.engine.processInput(userText,
|
|
86
|
+
const result = await this.engine.processInput(userText, {
|
|
87
|
+
...opts,
|
|
88
|
+
ambientPriors: await this.resolveAmbientPriors(userText),
|
|
89
|
+
});
|
|
72
90
|
return result.systemContext + "\n\n" + result.dynamicContext;
|
|
73
91
|
}
|
|
74
92
|
/**
|
|
@@ -78,7 +96,10 @@ export class PsycheLangChain {
|
|
|
78
96
|
* instead of re-parsing prompt prose.
|
|
79
97
|
*/
|
|
80
98
|
async prepareInvocation(userText, opts) {
|
|
81
|
-
const result = await this.engine.processInput(userText,
|
|
99
|
+
const result = await this.engine.processInput(userText, {
|
|
100
|
+
...opts,
|
|
101
|
+
ambientPriors: await this.resolveAmbientPriors(userText),
|
|
102
|
+
});
|
|
82
103
|
const generationControls = result.replyEnvelope?.generationControls ?? result.generationControls;
|
|
83
104
|
const controls = {
|
|
84
105
|
...(generationControls ?? {}),
|
package/dist/adapters/mcp.d.ts
CHANGED
|
@@ -1,6 +1,14 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
1
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
3
2
|
import { PsycheEngine } from "../core.js";
|
|
3
|
+
import { fetchAmbientPriorsFromThronglets, type ThrongletsAmbientRuntimeOptions } from "../ambient-runtime.js";
|
|
4
|
+
import { type ActivePolicyRule, type AmbientPriorView, type CurrentGoal } from "../types.js";
|
|
5
|
+
export interface McpAmbientRuntimeOptions {
|
|
6
|
+
mode?: "auto" | "off";
|
|
7
|
+
thronglets?: ThrongletsAmbientRuntimeOptions;
|
|
8
|
+
fetcher?: typeof fetchAmbientPriorsFromThronglets;
|
|
9
|
+
}
|
|
4
10
|
declare function getEngine(): Promise<PsycheEngine>;
|
|
11
|
+
export declare function resolveRuntimeAmbientPriors(text: string, explicit?: AmbientPriorView[], currentGoal?: CurrentGoal, activePolicy?: ActivePolicyRule[], opts?: McpAmbientRuntimeOptions): Promise<AmbientPriorView[] | undefined>;
|
|
5
12
|
declare const server: McpServer;
|
|
13
|
+
export declare function runMcpServer(): Promise<void>;
|
|
6
14
|
export { server, getEngine };
|