psyche-ai 11.5.2 → 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 +16 -0
- package/dist/adapters/http.js +5 -0
- package/dist/adapters/mcp.d.ts +2 -2
- package/dist/adapters/mcp.js +26 -4
- package/dist/ambient-priors.d.ts +1 -1
- package/dist/ambient-priors.js +11 -0
- package/dist/ambient-runtime.d.ts +4 -1
- package/dist/ambient-runtime.js +17 -2
- package/dist/cli.js +26 -6
- package/dist/core.d.ts +7 -1
- package/dist/core.js +15 -3
- package/dist/prompt.d.ts +3 -1
- package/dist/prompt.js +54 -1
- package/dist/types.d.ts +18 -0
- package/dist/types.js +42 -0
- package/openclaw.plugin.json +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -87,6 +87,22 @@ Psyche 要解决的不可压缩问题只有一个:
|
|
|
87
87
|
- `Psyche` 回答“我因此变成了什么”
|
|
88
88
|
- `Thronglets` 回答“这个变化属于谁、谁能验证、谁能继续承认它”
|
|
89
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
|
+
|
|
90
106
|
## 可分离安装
|
|
91
107
|
|
|
92
108
|
这两层默认就是可分离的,不应互相成为硬依赖。
|
package/dist/adapters/http.js
CHANGED
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
// Zero dependencies — uses node:http only.
|
|
17
17
|
// ============================================================
|
|
18
18
|
import { createServer } from "node:http";
|
|
19
|
+
import { normalizeActivePolicyRules, normalizeCurrentGoal, } from "../types.js";
|
|
19
20
|
import { parseAmbientPriorsInput } from "../ambient-runtime.js";
|
|
20
21
|
import { computeOverlay } from "../overlay.js";
|
|
21
22
|
const VALID_WRITEBACK_SIGNALS = new Set([
|
|
@@ -96,11 +97,15 @@ export function createPsycheServer(engine, opts) {
|
|
|
96
97
|
const result = await engine.processInput(body.text ?? "", {
|
|
97
98
|
userId: body.userId,
|
|
98
99
|
ambientPriors: parseAmbientPriors(body.ambientPriors),
|
|
100
|
+
currentGoal: normalizeCurrentGoal(body.currentGoal),
|
|
101
|
+
activePolicy: normalizeActivePolicyRules(body.activePolicy),
|
|
99
102
|
});
|
|
100
103
|
json(res, 200, {
|
|
101
104
|
systemContext: result.systemContext,
|
|
102
105
|
dynamicContext: result.dynamicContext,
|
|
103
106
|
ambientPriors: result.ambientPriors ?? [],
|
|
107
|
+
currentGoal: result.currentGoal ?? null,
|
|
108
|
+
activePolicy: result.activePolicy ?? [],
|
|
104
109
|
ambientPriorContext: result.ambientPriorContext ?? null,
|
|
105
110
|
appraisal: result.appraisal,
|
|
106
111
|
legacyStimulus: result.legacyStimulus,
|
package/dist/adapters/mcp.d.ts
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
2
|
import { PsycheEngine } from "../core.js";
|
|
3
3
|
import { fetchAmbientPriorsFromThronglets, type ThrongletsAmbientRuntimeOptions } from "../ambient-runtime.js";
|
|
4
|
-
import type
|
|
4
|
+
import { type ActivePolicyRule, type AmbientPriorView, type CurrentGoal } from "../types.js";
|
|
5
5
|
export interface McpAmbientRuntimeOptions {
|
|
6
6
|
mode?: "auto" | "off";
|
|
7
7
|
thronglets?: ThrongletsAmbientRuntimeOptions;
|
|
8
8
|
fetcher?: typeof fetchAmbientPriorsFromThronglets;
|
|
9
9
|
}
|
|
10
10
|
declare function getEngine(): Promise<PsycheEngine>;
|
|
11
|
-
export declare function resolveRuntimeAmbientPriors(text: string, explicit?: AmbientPriorView[], opts?: McpAmbientRuntimeOptions): Promise<AmbientPriorView[] | undefined>;
|
|
11
|
+
export declare function resolveRuntimeAmbientPriors(text: string, explicit?: AmbientPriorView[], currentGoal?: CurrentGoal, activePolicy?: ActivePolicyRule[], opts?: McpAmbientRuntimeOptions): Promise<AmbientPriorView[] | undefined>;
|
|
12
12
|
declare const server: McpServer;
|
|
13
13
|
export declare function runMcpServer(): Promise<void>;
|
|
14
14
|
export { server, getEngine };
|
package/dist/adapters/mcp.js
CHANGED
|
@@ -32,6 +32,7 @@ import { z } from "zod";
|
|
|
32
32
|
import { PsycheEngine } from "../core.js";
|
|
33
33
|
import { fetchAmbientPriorsFromThronglets, resolveAmbientPriorsForTurn, } from "../ambient-runtime.js";
|
|
34
34
|
import { MemoryStorageAdapter, FileStorageAdapter, resolveWorkspaceDir } from "../storage.js";
|
|
35
|
+
import { CURRENT_GOALS } from "../types.js";
|
|
35
36
|
import { getPackageVersion } from "../update.js";
|
|
36
37
|
import { runDemo } from "../demo.js";
|
|
37
38
|
const PACKAGE_VERSION = await getPackageVersion();
|
|
@@ -55,6 +56,7 @@ const DEFAULT_MCP_AMBIENT_OPTIONS = {
|
|
|
55
56
|
space: process.env.THRONGLETS_SPACE ?? "psyche",
|
|
56
57
|
},
|
|
57
58
|
};
|
|
59
|
+
const CURRENT_GOAL_SCHEMA = z.enum(CURRENT_GOALS);
|
|
58
60
|
// ── Parse CLI args (--mbti, --name, --mode, --locale) ──────
|
|
59
61
|
function parseCLIArgs() {
|
|
60
62
|
const args = process.argv.slice(2);
|
|
@@ -124,11 +126,18 @@ async function getEngine() {
|
|
|
124
126
|
await engine.initialize();
|
|
125
127
|
return engine;
|
|
126
128
|
}
|
|
127
|
-
export async function resolveRuntimeAmbientPriors(text, explicit, opts = DEFAULT_MCP_AMBIENT_OPTIONS) {
|
|
129
|
+
export async function resolveRuntimeAmbientPriors(text, explicit, currentGoal, activePolicy, opts = DEFAULT_MCP_AMBIENT_OPTIONS) {
|
|
130
|
+
const throngletsOptions = opts.thronglets || currentGoal || activePolicy?.length
|
|
131
|
+
? {
|
|
132
|
+
...(opts.thronglets ?? {}),
|
|
133
|
+
goal: currentGoal ?? opts.thronglets?.goal,
|
|
134
|
+
activePolicy: activePolicy ?? opts.thronglets?.activePolicy,
|
|
135
|
+
}
|
|
136
|
+
: undefined;
|
|
128
137
|
return resolveAmbientPriorsForTurn(text, {
|
|
129
138
|
explicit,
|
|
130
139
|
enabled: opts.mode !== "off",
|
|
131
|
-
thronglets:
|
|
140
|
+
thronglets: throngletsOptions,
|
|
132
141
|
fetcher: opts.fetcher ?? fetchAmbientPriorsFromThronglets,
|
|
133
142
|
});
|
|
134
143
|
}
|
|
@@ -191,15 +200,26 @@ server.tool("process_input", "Process user input through the emotional engine. R
|
|
|
191
200
|
summary: z.string(),
|
|
192
201
|
confidence: z.number().min(0).max(1),
|
|
193
202
|
kind: z.enum(["failure-residue", "mixed-residue", "success-prior"]).optional(),
|
|
203
|
+
policyState: z.enum(["policy-conflict", "method-conflict", "stable-path"]).optional(),
|
|
204
|
+
goal: CURRENT_GOAL_SCHEMA.optional(),
|
|
194
205
|
provider: z.string().optional(),
|
|
195
206
|
refs: z.array(z.string()).optional(),
|
|
196
207
|
})).optional().describe("Optional runtime ambient priors from the environment; consumed this turn only, not persisted as self-state"),
|
|
197
|
-
|
|
208
|
+
currentGoal: CURRENT_GOAL_SCHEMA.optional().describe("Optional single current runtime goal for this turn"),
|
|
209
|
+
activePolicy: z.array(z.object({
|
|
210
|
+
id: z.string(),
|
|
211
|
+
strength: z.enum(["hard", "soft"]),
|
|
212
|
+
scope: z.enum(["task", "project"]),
|
|
213
|
+
summary: z.string(),
|
|
214
|
+
})).optional().describe("Optional explicit current-turn method policy view. Runtime-only; not persisted as self-state."),
|
|
215
|
+
}, async ({ text, userId, ambientPriors, currentGoal, activePolicy }) => {
|
|
198
216
|
const eng = await getEngine();
|
|
199
|
-
const resolvedAmbientPriors = await resolveRuntimeAmbientPriors(text, ambientPriors);
|
|
217
|
+
const resolvedAmbientPriors = await resolveRuntimeAmbientPriors(text, ambientPriors, currentGoal, activePolicy);
|
|
200
218
|
const result = await eng.processInput(text, {
|
|
201
219
|
userId,
|
|
202
220
|
ambientPriors: resolvedAmbientPriors,
|
|
221
|
+
currentGoal,
|
|
222
|
+
activePolicy,
|
|
203
223
|
});
|
|
204
224
|
return {
|
|
205
225
|
content: [{
|
|
@@ -208,6 +228,8 @@ server.tool("process_input", "Process user input through the emotional engine. R
|
|
|
208
228
|
systemContext: result.systemContext,
|
|
209
229
|
dynamicContext: result.dynamicContext,
|
|
210
230
|
ambientPriors: result.ambientPriors ?? [],
|
|
231
|
+
activePolicy: result.activePolicy ?? [],
|
|
232
|
+
currentGoal: result.currentGoal ?? null,
|
|
211
233
|
ambientPriorContext: result.ambientPriorContext ?? null,
|
|
212
234
|
appraisal: result.appraisal,
|
|
213
235
|
legacyStimulus: result.legacyStimulus,
|
package/dist/ambient-priors.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type AmbientPriorView } from "./types.js";
|
|
2
2
|
export declare function normalizeAmbientPriors(priors: readonly AmbientPriorView[] | unknown, limit?: number): AmbientPriorView[];
|
package/dist/ambient-priors.js
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
|
+
import { AMBIENT_POLICY_STATES, CURRENT_GOALS } from "./types.js";
|
|
1
2
|
const AMBIENT_PRIOR_KINDS = new Set([
|
|
2
3
|
"failure-residue",
|
|
3
4
|
"mixed-residue",
|
|
4
5
|
"success-prior",
|
|
5
6
|
]);
|
|
7
|
+
const AMBIENT_POLICY_STATE_SET = new Set(AMBIENT_POLICY_STATES);
|
|
8
|
+
const AMBIENT_PRIOR_GOALS = new Set(CURRENT_GOALS);
|
|
6
9
|
export function normalizeAmbientPriors(priors, limit = 5) {
|
|
7
10
|
if (!Array.isArray(priors))
|
|
8
11
|
return [];
|
|
@@ -28,6 +31,14 @@ export function normalizeAmbientPriors(priors, limit = 5) {
|
|
|
28
31
|
&& AMBIENT_PRIOR_KINDS.has(rawKind)) {
|
|
29
32
|
normalizedEntry.kind = rawKind;
|
|
30
33
|
}
|
|
34
|
+
if (typeof record.policyState === "string"
|
|
35
|
+
&& AMBIENT_POLICY_STATE_SET.has(record.policyState)) {
|
|
36
|
+
normalizedEntry.policyState = record.policyState;
|
|
37
|
+
}
|
|
38
|
+
if (typeof record.goal === "string"
|
|
39
|
+
&& AMBIENT_PRIOR_GOALS.has(record.goal)) {
|
|
40
|
+
normalizedEntry.goal = record.goal;
|
|
41
|
+
}
|
|
31
42
|
if (typeof record.provider === "string") {
|
|
32
43
|
const provider = record.provider.trim();
|
|
33
44
|
if (provider)
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AmbientPriorView } from "./types.js";
|
|
1
|
+
import type { ActivePolicyRule, AmbientPriorView, CurrentGoal } from "./types.js";
|
|
2
2
|
interface CommandResult {
|
|
3
3
|
ok: boolean;
|
|
4
4
|
stdout: string;
|
|
@@ -9,6 +9,8 @@ export interface ThrongletsAmbientRuntimeOptions {
|
|
|
9
9
|
binaryPath?: string;
|
|
10
10
|
dataDir?: string;
|
|
11
11
|
space?: string;
|
|
12
|
+
goal?: CurrentGoal;
|
|
13
|
+
activePolicy?: ActivePolicyRule[];
|
|
12
14
|
limit?: number;
|
|
13
15
|
timeoutMs?: number;
|
|
14
16
|
runner?: CommandRunner;
|
|
@@ -16,6 +18,7 @@ export interface ThrongletsAmbientRuntimeOptions {
|
|
|
16
18
|
export interface AmbientPriorResolutionOptions {
|
|
17
19
|
explicit?: readonly AmbientPriorView[] | unknown;
|
|
18
20
|
enabled?: boolean;
|
|
21
|
+
activePolicy?: ActivePolicyRule[];
|
|
19
22
|
thronglets?: ThrongletsAmbientRuntimeOptions;
|
|
20
23
|
fetcher?: typeof fetchAmbientPriorsFromThronglets;
|
|
21
24
|
}
|
package/dist/ambient-runtime.js
CHANGED
|
@@ -2,10 +2,15 @@ import { spawn } from "node:child_process";
|
|
|
2
2
|
import { normalizeAmbientPriors } from "./ambient-priors.js";
|
|
3
3
|
const DEFAULT_AMBIENT_LIMIT = 3;
|
|
4
4
|
const DEFAULT_TIMEOUT_MS = 800;
|
|
5
|
+
const THRONGLETS_AMBIENT_SCHEMA_VERSION = "thronglets.ambient.v1";
|
|
5
6
|
function parseAmbientPriorOutput(stdout) {
|
|
6
7
|
if (!stdout.trim())
|
|
7
8
|
return [];
|
|
8
9
|
const parsed = JSON.parse(stdout);
|
|
10
|
+
if (typeof parsed.schema_version === "string"
|
|
11
|
+
&& parsed.schema_version !== THRONGLETS_AMBIENT_SCHEMA_VERSION) {
|
|
12
|
+
return [];
|
|
13
|
+
}
|
|
9
14
|
if (Array.isArray(parsed.priors)) {
|
|
10
15
|
return normalizeAmbientPriors(parsed.priors);
|
|
11
16
|
}
|
|
@@ -55,6 +60,7 @@ export async function fetchAmbientPriorsFromThronglets(text, opts = {}) {
|
|
|
55
60
|
const binaryPath = opts.binaryPath ?? process.env.THRONGLETS_BIN ?? "thronglets";
|
|
56
61
|
const dataDir = opts.dataDir ?? process.env.THRONGLETS_DATA_DIR;
|
|
57
62
|
const space = opts.space ?? process.env.THRONGLETS_SPACE ?? "psyche";
|
|
63
|
+
const goal = opts.goal;
|
|
58
64
|
const limit = Math.max(1, Math.min(5, opts.limit ?? DEFAULT_AMBIENT_LIMIT));
|
|
59
65
|
const timeoutMs = Math.max(100, opts.timeoutMs ?? DEFAULT_TIMEOUT_MS);
|
|
60
66
|
const runner = opts.runner ?? defaultRunner;
|
|
@@ -63,7 +69,13 @@ export async function fetchAmbientPriorsFromThronglets(text, opts = {}) {
|
|
|
63
69
|
args.push("--data-dir", dataDir.trim());
|
|
64
70
|
}
|
|
65
71
|
args.push("ambient-priors", "--json");
|
|
66
|
-
const payload = JSON.stringify({
|
|
72
|
+
const payload = JSON.stringify({
|
|
73
|
+
text: trimmed,
|
|
74
|
+
space,
|
|
75
|
+
goal,
|
|
76
|
+
limit,
|
|
77
|
+
active_policy: opts.activePolicy ?? [],
|
|
78
|
+
});
|
|
67
79
|
try {
|
|
68
80
|
const result = await runner(binaryPath, args, payload, timeoutMs);
|
|
69
81
|
if (!result.ok)
|
|
@@ -85,6 +97,9 @@ export async function resolveAmbientPriorsForTurn(text, opts = {}) {
|
|
|
85
97
|
if (opts.enabled === false)
|
|
86
98
|
return undefined;
|
|
87
99
|
const fetcher = opts.fetcher ?? fetchAmbientPriorsFromThronglets;
|
|
88
|
-
const priors = await fetcher(text,
|
|
100
|
+
const priors = await fetcher(text, {
|
|
101
|
+
...(opts.thronglets ?? {}),
|
|
102
|
+
activePolicy: opts.activePolicy ?? opts.thronglets?.activePolicy,
|
|
103
|
+
});
|
|
89
104
|
return priors.length > 0 ? priors : undefined;
|
|
90
105
|
}
|
package/dist/cli.js
CHANGED
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
import { resolve, join } from "node:path";
|
|
22
22
|
import { homedir } from "node:os";
|
|
23
23
|
import { parseArgs } from "node:util";
|
|
24
|
-
import { readFile, writeFile, mkdir, access } from "node:fs/promises";
|
|
24
|
+
import { readFile, writeFile, mkdir, access, rename, rm } from "node:fs/promises";
|
|
25
25
|
import { loadState, saveState, decayAndSave, initializeState, mergeUpdates, generatePsycheMd, getRelationship, } from "./psyche-file.js";
|
|
26
26
|
import { describeEmotionalState, getExpressionHint, detectEmotions } from "./chemistry.js";
|
|
27
27
|
import { generateReport, formatReport, toGitHubIssueBody } from "./diagnostics.js";
|
|
@@ -606,6 +606,28 @@ async function fileExists(path) {
|
|
|
606
606
|
return false;
|
|
607
607
|
}
|
|
608
608
|
}
|
|
609
|
+
async function writeTextAtomic(path, content) {
|
|
610
|
+
const absPath = resolve(path);
|
|
611
|
+
const dir = resolve(absPath, "..");
|
|
612
|
+
await mkdir(dir, { recursive: true });
|
|
613
|
+
const base = absPath.split("/").pop() ?? "file";
|
|
614
|
+
const tmpPath = join(dir, `.${base}.${process.pid}.${Date.now()}.${Math.random().toString(36).slice(2)}.tmp`);
|
|
615
|
+
await writeFile(tmpPath, content, "utf-8");
|
|
616
|
+
try {
|
|
617
|
+
await rename(tmpPath, absPath);
|
|
618
|
+
}
|
|
619
|
+
catch (error) {
|
|
620
|
+
if (error?.code !== "EEXIST" && error?.code !== "EPERM") {
|
|
621
|
+
try {
|
|
622
|
+
await rm(tmpPath, { force: true });
|
|
623
|
+
}
|
|
624
|
+
catch { /* noop */ }
|
|
625
|
+
throw error;
|
|
626
|
+
}
|
|
627
|
+
await rm(absPath, { force: true });
|
|
628
|
+
await rename(tmpPath, absPath);
|
|
629
|
+
}
|
|
630
|
+
}
|
|
609
631
|
async function cmdSetup(opts) {
|
|
610
632
|
const { name, mbti, locale, proxy, target, port, dryRun } = opts;
|
|
611
633
|
const env = {};
|
|
@@ -676,8 +698,7 @@ async function cmdSetup(opts) {
|
|
|
676
698
|
actions++;
|
|
677
699
|
continue;
|
|
678
700
|
}
|
|
679
|
-
await
|
|
680
|
-
await writeFile(t.configPath, result.content, "utf-8");
|
|
701
|
+
await writeTextAtomic(t.configPath, result.content);
|
|
681
702
|
console.log(` ✓ ${t.name} (restart to activate)`);
|
|
682
703
|
actions++;
|
|
683
704
|
continue;
|
|
@@ -704,8 +725,7 @@ async function cmdSetup(opts) {
|
|
|
704
725
|
actions++;
|
|
705
726
|
continue;
|
|
706
727
|
}
|
|
707
|
-
await
|
|
708
|
-
await writeFile(t.configPath, JSON.stringify(cfg, null, 2) + "\n", "utf-8");
|
|
728
|
+
await writeTextAtomic(t.configPath, JSON.stringify(cfg, null, 2) + "\n");
|
|
709
729
|
console.log(` ✓ ${t.name} (restart to activate)`);
|
|
710
730
|
actions++;
|
|
711
731
|
}
|
|
@@ -739,7 +759,7 @@ async function cmdSetup(opts) {
|
|
|
739
759
|
if (rcFile) {
|
|
740
760
|
const rc = await fileExists(rcFile) ? await readFile(rcFile, "utf-8") : "";
|
|
741
761
|
if (!rc.includes("# psyche-proxy")) {
|
|
742
|
-
await
|
|
762
|
+
await writeTextAtomic(rcFile, rc + (rc.endsWith("\n") ? "" : "\n") + exportLine + "\n");
|
|
743
763
|
console.log(` ✓ ${envVar} → ${proxyUrl} (${rcFile})`);
|
|
744
764
|
}
|
|
745
765
|
else {
|
package/dist/core.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AmbientPriorView, PsycheState, StimulusType, Locale, MBTIType, OutcomeScore, PsycheMode, PersonalityTraits, PolicyModifiers, ClassifierProvider, SubjectivityKernel, ResponseContract, GenerationControls, SessionBridgeState, ThrongletsExport, TurnObservability, WritebackCalibrationFeedback, WritebackSignalType, ExternalContinuityEnvelope, AppraisalAxes } from "./types.js";
|
|
1
|
+
import type { ActivePolicyRule, AmbientPriorView, CurrentGoal, PsycheState, StimulusType, Locale, MBTIType, OutcomeScore, PsycheMode, PersonalityTraits, PolicyModifiers, ClassifierProvider, SubjectivityKernel, ResponseContract, GenerationControls, SessionBridgeState, ThrongletsExport, TurnObservability, WritebackCalibrationFeedback, WritebackSignalType, ExternalContinuityEnvelope, AppraisalAxes } from "./types.js";
|
|
2
2
|
import type { StorageAdapter } from "./storage.js";
|
|
3
3
|
import type { DiagnosticReport, SessionMetrics } from "./diagnostics.js";
|
|
4
4
|
import type { ReplyEnvelope } from "./reply-envelope.js";
|
|
@@ -39,6 +39,10 @@ export interface ProcessInputResult {
|
|
|
39
39
|
dynamicContext: string;
|
|
40
40
|
/** Runtime-only environmental priors consumed this turn */
|
|
41
41
|
ambientPriors?: AmbientPriorView[];
|
|
42
|
+
/** Runtime-only explicit method policy for the current task lineage */
|
|
43
|
+
activePolicy?: ActivePolicyRule[];
|
|
44
|
+
/** Optional current runtime goal carried through this turn only */
|
|
45
|
+
currentGoal?: CurrentGoal;
|
|
42
46
|
/** Rendered environmental prior context injected into the turn, if any */
|
|
43
47
|
ambientPriorContext?: string;
|
|
44
48
|
/** Canonical host-facing subjective appraisal for this turn, null if no appraisal fired */
|
|
@@ -89,6 +93,8 @@ export interface ProcessInputResult {
|
|
|
89
93
|
export interface ProcessInputOptions {
|
|
90
94
|
userId?: string;
|
|
91
95
|
ambientPriors?: AmbientPriorView[];
|
|
96
|
+
currentGoal?: CurrentGoal;
|
|
97
|
+
activePolicy?: ActivePolicyRule[];
|
|
92
98
|
}
|
|
93
99
|
export interface ProcessOutputResult {
|
|
94
100
|
/** LLM output with <psyche_update> tags stripped */
|
package/dist/core.js
CHANGED
|
@@ -11,12 +11,13 @@
|
|
|
11
11
|
//
|
|
12
12
|
// Orchestrates: self-state, appraisal, prompt, profiles, guards, learning
|
|
13
13
|
// ============================================================
|
|
14
|
+
import { normalizeActivePolicyRules, normalizeCurrentGoal } from "./types.js";
|
|
14
15
|
import { DEFAULT_RELATIONSHIP, DEFAULT_DRIVES, DEFAULT_LEARNING_STATE, DEFAULT_METACOGNITIVE_STATE, DEFAULT_PERSONHOOD_STATE, DEFAULT_ENERGY_BUDGETS, DEFAULT_TRAIT_DRIFT, DEFAULT_SUBJECT_RESIDUE, DEFAULT_DYADIC_FIELD } from "./types.js";
|
|
15
16
|
import { MemoryStorageAdapter } from "./storage.js";
|
|
16
17
|
import { applyDecay, applyStimulus, applyContagion, clamp, describeEmotionalState } from "./chemistry.js";
|
|
17
18
|
import { classifyLegacyStimulus, BuiltInClassifier, buildLLMClassifierPrompt, parseLLMClassification } from "./classify.js";
|
|
18
19
|
import { perceive } from "./perceive.js";
|
|
19
|
-
import { buildAmbientPriorContext, buildCompactContext, buildProtocolContext } from "./prompt.js";
|
|
20
|
+
import { buildActivePolicyContext, buildAmbientPriorContext, buildCompactContext, buildProtocolContext } from "./prompt.js";
|
|
20
21
|
import { getSensitivity, getBaseline, getDefaultSelfModel, traitsToBaseline } from "./profiles.js";
|
|
21
22
|
import { isStimulusType } from "./guards.js";
|
|
22
23
|
import { parsePsycheUpdate, mergeUpdates, updateAgreementStreak, pushSnapshot, compressSession, summarizeTurnSemantic, } from "./psyche-file.js";
|
|
@@ -460,7 +461,11 @@ export class PsycheEngine {
|
|
|
460
461
|
}
|
|
461
462
|
const writebackNote = formatWritebackFeedbackNote(writebackFeedback, locale);
|
|
462
463
|
const ambientPriors = normalizeAmbientPriors(opts?.ambientPriors);
|
|
464
|
+
const activePolicy = normalizeActivePolicyRules(opts?.activePolicy) ?? [];
|
|
465
|
+
const currentGoal = normalizeCurrentGoal(opts?.currentGoal)
|
|
466
|
+
?? ambientPriors.find((prior) => prior.goal)?.goal;
|
|
463
467
|
const ambientPriorContext = buildAmbientPriorContext(ambientPriors, locale);
|
|
468
|
+
const activePolicyContext = buildActivePolicyContext(activePolicy, locale);
|
|
464
469
|
const reflectiveTurn = runReflectiveTurnPhases({
|
|
465
470
|
state,
|
|
466
471
|
appraisalAxes,
|
|
@@ -494,6 +499,7 @@ export class PsycheEngine {
|
|
|
494
499
|
userText: text || undefined,
|
|
495
500
|
legacyStimulus: appliedStimulus,
|
|
496
501
|
ambientPriors,
|
|
502
|
+
activePolicy,
|
|
497
503
|
ambientPriorContext: ambientPriorContext || undefined,
|
|
498
504
|
personalityIntensity: this.cfg.personalityIntensity,
|
|
499
505
|
metacognitiveNote: reflectiveTurn.metacognitiveNote,
|
|
@@ -506,7 +512,9 @@ export class PsycheEngine {
|
|
|
506
512
|
primarySystemsDescription: reflectiveTurn.primarySystemsDescription,
|
|
507
513
|
subjectivityContext: derivedReplyEnvelope.subjectivityContext,
|
|
508
514
|
responseContractContext: derivedReplyEnvelope.responseContractContext,
|
|
509
|
-
policyContext: derivedReplyEnvelope.policyContext
|
|
515
|
+
policyContext: [activePolicyContext, derivedReplyEnvelope.policyContext]
|
|
516
|
+
.filter((value) => Boolean(value && value.trim().length > 0))
|
|
517
|
+
.join("\n") || undefined,
|
|
510
518
|
sessionBridge,
|
|
511
519
|
};
|
|
512
520
|
const observability = buildTurnObservability(state, {
|
|
@@ -526,6 +534,8 @@ export class PsycheEngine {
|
|
|
526
534
|
systemContext: "",
|
|
527
535
|
dynamicContext: buildCompactContext(state, opts?.userId, promptRenderInputs),
|
|
528
536
|
ambientPriors,
|
|
537
|
+
activePolicy,
|
|
538
|
+
currentGoal,
|
|
529
539
|
ambientPriorContext: ambientPriorContext || undefined,
|
|
530
540
|
appraisal: appraisalAxes,
|
|
531
541
|
legacyStimulus: appliedStimulus,
|
|
@@ -542,7 +552,9 @@ export class PsycheEngine {
|
|
|
542
552
|
externalContinuity,
|
|
543
553
|
throngletsExports,
|
|
544
554
|
observability,
|
|
545
|
-
policyContext: derivedReplyEnvelope.policyContext
|
|
555
|
+
policyContext: [activePolicyContext, derivedReplyEnvelope.policyContext]
|
|
556
|
+
.filter((value) => Boolean(value && value.trim().length > 0))
|
|
557
|
+
.join("\n"),
|
|
546
558
|
};
|
|
547
559
|
}
|
|
548
560
|
/**
|
package/dist/prompt.d.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import type { AmbientPriorView, PsycheState, Locale, StateSnapshot, PsycheMode } from "./types.js";
|
|
1
|
+
import type { ActivePolicyRule, AmbientPriorView, PsycheState, Locale, StateSnapshot, PsycheMode } from "./types.js";
|
|
2
2
|
import type { AutonomicState } from "./autonomic.js";
|
|
3
3
|
import type { ChannelType } from "./channels.js";
|
|
4
4
|
export interface PromptRenderInputs {
|
|
5
5
|
userText?: string;
|
|
6
6
|
legacyStimulus?: string | null;
|
|
7
7
|
ambientPriors?: AmbientPriorView[];
|
|
8
|
+
activePolicy?: ActivePolicyRule[];
|
|
8
9
|
ambientPriorContext?: string;
|
|
9
10
|
personalityIntensity?: number;
|
|
10
11
|
channelType?: ChannelType;
|
|
@@ -23,6 +24,7 @@ export interface PromptRenderInputs {
|
|
|
23
24
|
sessionBridge?: import("./types.js").SessionBridgeState | null;
|
|
24
25
|
}
|
|
25
26
|
export declare function buildAmbientPriorContext(priors: AmbientPriorView[] | undefined, locale: Locale): string;
|
|
27
|
+
export declare function buildActivePolicyContext(activePolicy: ActivePolicyRule[] | undefined, locale: Locale): string;
|
|
26
28
|
/**
|
|
27
29
|
* Build the dynamic per-turn emotional context injected via before_prompt_build.
|
|
28
30
|
*
|
package/dist/prompt.js
CHANGED
|
@@ -17,6 +17,8 @@ export function buildAmbientPriorContext(priors, locale) {
|
|
|
17
17
|
summary: prior.summary.trim().replace(/\s+/g, " "),
|
|
18
18
|
confidence: Math.max(0, Math.min(1, prior.confidence)),
|
|
19
19
|
kind: prior.kind,
|
|
20
|
+
goal: prior.goal,
|
|
21
|
+
policyState: prior.policyState,
|
|
20
22
|
provider: prior.provider?.trim(),
|
|
21
23
|
}))
|
|
22
24
|
.filter((prior) => prior.summary.length > 0)
|
|
@@ -39,6 +41,27 @@ export function buildAmbientPriorContext(priors, locale) {
|
|
|
39
41
|
return "low confidence";
|
|
40
42
|
};
|
|
41
43
|
const title = locale === "zh" ? "环境先验" : "Ambient Prior";
|
|
44
|
+
const goal = normalized
|
|
45
|
+
.map((prior) => prior.goal)
|
|
46
|
+
.find((value) => Boolean(value));
|
|
47
|
+
const goalLabel = (value) => {
|
|
48
|
+
if (locale === "zh") {
|
|
49
|
+
if (value === "explore")
|
|
50
|
+
return "当前目标: 探索";
|
|
51
|
+
if (value === "build")
|
|
52
|
+
return "当前目标: 构建";
|
|
53
|
+
if (value === "repair")
|
|
54
|
+
return "当前目标: 修复";
|
|
55
|
+
return "当前目标: 结算";
|
|
56
|
+
}
|
|
57
|
+
if (value === "explore")
|
|
58
|
+
return "Current goal: explore";
|
|
59
|
+
if (value === "build")
|
|
60
|
+
return "Current goal: build";
|
|
61
|
+
if (value === "repair")
|
|
62
|
+
return "Current goal: repair";
|
|
63
|
+
return "Current goal: settle";
|
|
64
|
+
};
|
|
42
65
|
const kindLabel = (kind) => {
|
|
43
66
|
if (locale === "zh") {
|
|
44
67
|
if (kind === "failure-residue")
|
|
@@ -58,12 +81,42 @@ export function buildAmbientPriorContext(priors, locale) {
|
|
|
58
81
|
return "ambient";
|
|
59
82
|
};
|
|
60
83
|
const lines = normalized.map((prior) => {
|
|
84
|
+
const statePrefix = prior.policyState === "policy-conflict"
|
|
85
|
+
? locale === "zh" ? "策略冲突 · " : "policy conflict · "
|
|
86
|
+
: prior.policyState === "method-conflict"
|
|
87
|
+
? locale === "zh" ? "方法冲突 · " : "method conflict · "
|
|
88
|
+
: "";
|
|
61
89
|
const source = prior.provider
|
|
62
90
|
? locale === "zh"
|
|
63
91
|
? `${prior.provider}: `
|
|
64
92
|
: `${prior.provider}: `
|
|
65
93
|
: "";
|
|
66
|
-
return `- ${kindLabel(prior.kind)} · ${source}${prior.summary} (${confidenceLabel(prior.confidence)})`;
|
|
94
|
+
return `- ${statePrefix}${kindLabel(prior.kind)} · ${source}${prior.summary} (${confidenceLabel(prior.confidence)})`;
|
|
95
|
+
});
|
|
96
|
+
const heading = goal ? `${title} · ${goalLabel(goal)}` : title;
|
|
97
|
+
const guidance = goal === "explore"
|
|
98
|
+
? locale === "zh"
|
|
99
|
+
? "- 将这些先验只当作软提示;保留可逆的、非共识的试探空间。"
|
|
100
|
+
: "- Treat these priors as soft hints only; preserve room for reversible non-consensus probes."
|
|
101
|
+
: "";
|
|
102
|
+
return `[${heading}]\n${guidance ? `${guidance}\n` : ""}${lines.join("\n")}`;
|
|
103
|
+
}
|
|
104
|
+
export function buildActivePolicyContext(activePolicy, locale) {
|
|
105
|
+
const rules = (activePolicy ?? [])
|
|
106
|
+
.map((rule) => ({
|
|
107
|
+
...rule,
|
|
108
|
+
summary: rule.summary.trim().replace(/\s+/g, " "),
|
|
109
|
+
}))
|
|
110
|
+
.filter((rule) => rule.summary.length > 0)
|
|
111
|
+
.slice(0, 3);
|
|
112
|
+
if (rules.length === 0)
|
|
113
|
+
return "";
|
|
114
|
+
const title = locale === "zh" ? "当前方法约束" : "Active Method Policy";
|
|
115
|
+
const lines = rules.map((rule) => {
|
|
116
|
+
const strength = rule.strength === "hard"
|
|
117
|
+
? (locale === "zh" ? "硬" : "hard")
|
|
118
|
+
: (locale === "zh" ? "软" : "soft");
|
|
119
|
+
return `- ${strength} · ${rule.summary}`;
|
|
67
120
|
});
|
|
68
121
|
return `[${title}]\n${lines.join("\n")}`;
|
|
69
122
|
}
|
package/dist/types.d.ts
CHANGED
|
@@ -579,10 +579,28 @@ export interface SessionBridgeState {
|
|
|
579
579
|
* It lets hosts surface sparse, task-conditioned priors without turning Psyche
|
|
580
580
|
* into an operations memory store.
|
|
581
581
|
*/
|
|
582
|
+
export declare const CURRENT_GOALS: readonly ["explore", "build", "repair", "settle"];
|
|
583
|
+
export type CurrentGoal = (typeof CURRENT_GOALS)[number];
|
|
584
|
+
export declare const ACTIVE_POLICY_STRENGTHS: readonly ["hard", "soft"];
|
|
585
|
+
export type ActivePolicyStrength = (typeof ACTIVE_POLICY_STRENGTHS)[number];
|
|
586
|
+
export declare const ACTIVE_POLICY_SCOPES: readonly ["task", "project"];
|
|
587
|
+
export type ActivePolicyScope = (typeof ACTIVE_POLICY_SCOPES)[number];
|
|
588
|
+
export declare const AMBIENT_POLICY_STATES: readonly ["policy-conflict", "method-conflict", "stable-path"];
|
|
589
|
+
export type AmbientPolicyState = (typeof AMBIENT_POLICY_STATES)[number];
|
|
590
|
+
export interface ActivePolicyRule {
|
|
591
|
+
id: string;
|
|
592
|
+
strength: ActivePolicyStrength;
|
|
593
|
+
scope: ActivePolicyScope;
|
|
594
|
+
summary: string;
|
|
595
|
+
}
|
|
596
|
+
export declare function normalizeCurrentGoal(value: unknown): CurrentGoal | undefined;
|
|
597
|
+
export declare function normalizeActivePolicyRules(value: unknown, limit?: number): ActivePolicyRule[] | undefined;
|
|
582
598
|
export interface AmbientPriorView {
|
|
583
599
|
summary: string;
|
|
584
600
|
confidence: number;
|
|
585
601
|
kind?: "failure-residue" | "mixed-residue" | "success-prior";
|
|
602
|
+
policyState?: AmbientPolicyState;
|
|
603
|
+
goal?: CurrentGoal;
|
|
586
604
|
provider?: string;
|
|
587
605
|
refs?: string[];
|
|
588
606
|
}
|
package/dist/types.js
CHANGED
|
@@ -209,6 +209,48 @@ export const DEFAULT_DYADIC_FIELD = {
|
|
|
209
209
|
lastMove: "none",
|
|
210
210
|
updatedAt: new Date(0).toISOString(),
|
|
211
211
|
};
|
|
212
|
+
/**
|
|
213
|
+
* AmbientPriorView — runtime-only environmental prior.
|
|
214
|
+
*
|
|
215
|
+
* This is a view projected into the current turn, not persistent self-state.
|
|
216
|
+
* It lets hosts surface sparse, task-conditioned priors without turning Psyche
|
|
217
|
+
* into an operations memory store.
|
|
218
|
+
*/
|
|
219
|
+
export const CURRENT_GOALS = ["explore", "build", "repair", "settle"];
|
|
220
|
+
export const ACTIVE_POLICY_STRENGTHS = ["hard", "soft"];
|
|
221
|
+
export const ACTIVE_POLICY_SCOPES = ["task", "project"];
|
|
222
|
+
export const AMBIENT_POLICY_STATES = [
|
|
223
|
+
"policy-conflict",
|
|
224
|
+
"method-conflict",
|
|
225
|
+
"stable-path",
|
|
226
|
+
];
|
|
227
|
+
export function normalizeCurrentGoal(value) {
|
|
228
|
+
return typeof value === "string" && CURRENT_GOALS.includes(value)
|
|
229
|
+
? value
|
|
230
|
+
: undefined;
|
|
231
|
+
}
|
|
232
|
+
export function normalizeActivePolicyRules(value, limit = 3) {
|
|
233
|
+
if (!Array.isArray(value))
|
|
234
|
+
return undefined;
|
|
235
|
+
const normalized = value
|
|
236
|
+
.filter((item) => !!item && typeof item === "object")
|
|
237
|
+
.map((item) => ({
|
|
238
|
+
id: typeof item.id === "string" ? item.id.trim() : "",
|
|
239
|
+
summary: typeof item.summary === "string" ? item.summary.trim().replace(/\s+/g, " ") : "",
|
|
240
|
+
strength: typeof item.strength === "string" && ACTIVE_POLICY_STRENGTHS.includes(item.strength)
|
|
241
|
+
? item.strength
|
|
242
|
+
: undefined,
|
|
243
|
+
scope: typeof item.scope === "string" && ACTIVE_POLICY_SCOPES.includes(item.scope)
|
|
244
|
+
? item.scope
|
|
245
|
+
: undefined,
|
|
246
|
+
}))
|
|
247
|
+
.filter((rule) => (rule.id.length > 0
|
|
248
|
+
&& rule.summary.length > 0
|
|
249
|
+
&& rule.strength !== undefined
|
|
250
|
+
&& rule.scope !== undefined))
|
|
251
|
+
.slice(0, Math.max(1, limit));
|
|
252
|
+
return normalized.length > 0 ? normalized : undefined;
|
|
253
|
+
}
|
|
212
254
|
/** Default empty trait drift state */
|
|
213
255
|
export const DEFAULT_TRAIT_DRIFT = {
|
|
214
256
|
accumulators: {
|
package/openclaw.plugin.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"id": "psyche-ai",
|
|
3
3
|
"name": "Artificial Psyche",
|
|
4
4
|
"description": "AI-first subjectivity kernel for agents with continuous appraisal, relation dynamics, and adaptive reply loops",
|
|
5
|
-
"version": "11.5.
|
|
5
|
+
"version": "11.5.3",
|
|
6
6
|
"configSchema": {
|
|
7
7
|
"type": "object",
|
|
8
8
|
"additionalProperties": false,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "psyche-ai",
|
|
3
|
-
"version": "11.5.
|
|
3
|
+
"version": "11.5.3",
|
|
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",
|