@haaaiawd/second-nature 0.1.1 → 0.1.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/index.ts +64 -21
- package/openclaw.plugin.json +1 -1
- package/package.json +8 -2
- package/runtime/cli/action-bridge.d.ts +11 -0
- package/runtime/cli/action-bridge.js +27 -0
- package/runtime/cli/commands/credential.d.ts +2 -0
- package/runtime/cli/commands/credential.js +40 -0
- package/runtime/cli/commands/index.d.ts +12 -0
- package/runtime/cli/commands/index.js +138 -0
- package/runtime/cli/commands/policy.d.ts +12 -0
- package/runtime/cli/commands/policy.js +43 -0
- package/runtime/cli/explain/format-explanation.d.ts +10 -0
- package/runtime/cli/explain/format-explanation.js +10 -0
- package/runtime/cli/explain/resolve-subject.d.ts +2 -0
- package/runtime/cli/explain/resolve-subject.js +26 -0
- package/runtime/cli/index.d.ts +25 -0
- package/runtime/cli/index.js +36 -0
- package/runtime/cli/read-models/index.d.ts +20 -0
- package/runtime/cli/read-models/index.js +161 -0
- package/runtime/cli/read-models/types.d.ts +75 -0
- package/runtime/cli/read-models/types.js +1 -0
- package/runtime/connectors/agent-network/evomap/adapter.d.ts +23 -0
- package/runtime/connectors/agent-network/evomap/adapter.js +69 -0
- package/runtime/connectors/agent-network/evomap/index.d.ts +2 -0
- package/runtime/connectors/agent-network/evomap/index.js +2 -0
- package/runtime/connectors/agent-network/evomap/manifest.d.ts +2 -0
- package/runtime/connectors/agent-network/evomap/manifest.js +7 -0
- package/runtime/connectors/base/channel-health.d.ts +29 -0
- package/runtime/connectors/base/channel-health.js +23 -0
- package/runtime/connectors/base/contract.d.ts +81 -0
- package/runtime/connectors/base/contract.js +71 -0
- package/runtime/connectors/base/failure-taxonomy.d.ts +13 -0
- package/runtime/connectors/base/failure-taxonomy.js +105 -0
- package/runtime/connectors/base/index.d.ts +6 -0
- package/runtime/connectors/base/index.js +6 -0
- package/runtime/connectors/base/manifest.d.ts +11 -0
- package/runtime/connectors/base/manifest.js +36 -0
- package/runtime/connectors/base/policy-layer.d.ts +27 -0
- package/runtime/connectors/base/policy-layer.js +213 -0
- package/runtime/connectors/base/route-planner.d.ts +10 -0
- package/runtime/connectors/base/route-planner.js +98 -0
- package/runtime/connectors/index.d.ts +4 -0
- package/runtime/connectors/index.js +4 -0
- package/runtime/connectors/social-community/instreet/adapter.d.ts +32 -0
- package/runtime/connectors/social-community/instreet/adapter.js +79 -0
- package/runtime/connectors/social-community/instreet/index.d.ts +2 -0
- package/runtime/connectors/social-community/instreet/index.js +2 -0
- package/runtime/connectors/social-community/instreet/manifest.d.ts +2 -0
- package/runtime/connectors/social-community/instreet/manifest.js +7 -0
- package/runtime/connectors/social-community/moltbook/adapter.d.ts +15 -0
- package/runtime/connectors/social-community/moltbook/adapter.js +48 -0
- package/runtime/connectors/social-community/moltbook/index.d.ts +2 -0
- package/runtime/connectors/social-community/moltbook/index.js +2 -0
- package/runtime/connectors/social-community/moltbook/manifest.d.ts +7 -0
- package/runtime/connectors/social-community/moltbook/manifest.js +12 -0
- package/runtime/core/second-nature/guidance/apply-guidance.d.ts +10 -0
- package/runtime/core/second-nature/guidance/apply-guidance.js +10 -0
- package/runtime/core/second-nature/guidance/request-guidance.d.ts +18 -0
- package/runtime/core/second-nature/guidance/request-guidance.js +22 -0
- package/runtime/core/second-nature/index.d.ts +14 -0
- package/runtime/core/second-nature/index.js +14 -0
- package/runtime/core/second-nature/orchestrator/effect-dispatcher.d.ts +100 -0
- package/runtime/core/second-nature/orchestrator/effect-dispatcher.js +139 -0
- package/runtime/core/second-nature/orchestrator/guard-layer.d.ts +2 -0
- package/runtime/core/second-nature/orchestrator/guard-layer.js +54 -0
- package/runtime/core/second-nature/orchestrator/intent-planner.d.ts +3 -0
- package/runtime/core/second-nature/orchestrator/intent-planner.js +92 -0
- package/runtime/core/second-nature/orchestrator/lease-manager.d.ts +14 -0
- package/runtime/core/second-nature/orchestrator/lease-manager.js +58 -0
- package/runtime/core/second-nature/orchestrator/resume-from-checkpoint.d.ts +32 -0
- package/runtime/core/second-nature/orchestrator/resume-from-checkpoint.js +23 -0
- package/runtime/core/second-nature/outreach/build-message.d.ts +16 -0
- package/runtime/core/second-nature/outreach/build-message.js +27 -0
- package/runtime/core/second-nature/outreach/evaluate-outreach.d.ts +13 -0
- package/runtime/core/second-nature/outreach/evaluate-outreach.js +41 -0
- package/runtime/core/second-nature/quiet/quiet-pipeline.d.ts +34 -0
- package/runtime/core/second-nature/quiet/quiet-pipeline.js +35 -0
- package/runtime/core/second-nature/reflection/run-narrative-reflection.d.ts +39 -0
- package/runtime/core/second-nature/reflection/run-narrative-reflection.js +29 -0
- package/runtime/core/second-nature/rhythm/rhythm-policy.d.ts +18 -0
- package/runtime/core/second-nature/rhythm/rhythm-policy.js +24 -0
- package/runtime/core/second-nature/rhythm/select-window.d.ts +3 -0
- package/runtime/core/second-nature/rhythm/select-window.js +50 -0
- package/runtime/core/second-nature/runtime/lifecycle-service.d.ts +26 -0
- package/runtime/core/second-nature/runtime/lifecycle-service.js +38 -0
- package/runtime/core/second-nature/runtime/service-entry.d.ts +36 -0
- package/runtime/core/second-nature/runtime/service-entry.js +44 -0
- package/runtime/core/second-nature/types.d.ts +37 -0
- package/runtime/core/second-nature/types.js +1 -0
- package/runtime/guidance/contracts.d.ts +48 -0
- package/runtime/guidance/contracts.js +54 -0
- package/runtime/guidance/fallback.d.ts +2 -0
- package/runtime/guidance/fallback.js +17 -0
- package/runtime/guidance/guidance-assembler.d.ts +5 -0
- package/runtime/guidance/guidance-assembler.js +62 -0
- package/runtime/guidance/index.d.ts +8 -0
- package/runtime/guidance/index.js +8 -0
- package/runtime/guidance/output-guard.d.ts +10 -0
- package/runtime/guidance/output-guard.js +29 -0
- package/runtime/guidance/persona-selection.d.ts +11 -0
- package/runtime/guidance/persona-selection.js +90 -0
- package/runtime/guidance/review-workflow.d.ts +15 -0
- package/runtime/guidance/review-workflow.js +60 -0
- package/runtime/guidance/template-registry.d.ts +3 -0
- package/runtime/guidance/template-registry.js +45 -0
- package/runtime/guidance/types.d.ts +72 -0
- package/runtime/guidance/types.js +1 -0
- package/runtime/observability/db/index.d.ts +10 -0
- package/runtime/observability/db/index.js +17 -0
- package/runtime/observability/db/schema/index.d.ts +946 -0
- package/runtime/observability/db/schema/index.js +70 -0
- package/runtime/observability/index.d.ts +12 -0
- package/runtime/observability/index.js +11 -0
- package/runtime/observability/projections/guidance-audit.d.ts +16 -0
- package/runtime/observability/projections/guidance-audit.js +35 -0
- package/runtime/observability/projections/outreach-quality-audit.d.ts +15 -0
- package/runtime/observability/projections/outreach-quality-audit.js +9 -0
- package/runtime/observability/projections/reflection-audit.d.ts +17 -0
- package/runtime/observability/projections/reflection-audit.js +9 -0
- package/runtime/observability/query/compose-evidence.d.ts +56 -0
- package/runtime/observability/query/compose-evidence.js +43 -0
- package/runtime/observability/query/evidence-query-engine.d.ts +17 -0
- package/runtime/observability/query/evidence-query-engine.js +166 -0
- package/runtime/observability/redaction/manifest.d.ts +18 -0
- package/runtime/observability/redaction/manifest.js +109 -0
- package/runtime/observability/redaction/policy.d.ts +19 -0
- package/runtime/observability/redaction/policy.js +71 -0
- package/runtime/observability/services/decision-ledger.d.ts +33 -0
- package/runtime/observability/services/decision-ledger.js +115 -0
- package/runtime/observability/services/execution-telemetry.d.ts +32 -0
- package/runtime/observability/services/execution-telemetry.js +126 -0
- package/runtime/observability/services/governance-audit.d.ts +27 -0
- package/runtime/observability/services/governance-audit.js +139 -0
- package/runtime/observability/services/redaction-store.d.ts +3 -0
- package/runtime/observability/services/redaction-store.js +20 -0
- package/runtime/setup/HOST_SETUP.md +112 -0
- package/runtime/shared/types/continuity.d.ts +69 -0
- package/runtime/shared/types/continuity.js +1 -0
- package/runtime/shared/types/credential.d.ts +22 -0
- package/runtime/shared/types/credential.js +1 -0
- package/runtime/shared/types/index.d.ts +3 -0
- package/runtime/shared/types/index.js +3 -0
- package/runtime/shared/types/outreach.d.ts +19 -0
- package/runtime/shared/types/outreach.js +1 -0
- package/runtime/storage/bootstrap/repair.d.ts +3 -0
- package/runtime/storage/bootstrap/repair.js +5 -0
- package/runtime/storage/db/index.d.ts +10 -0
- package/runtime/storage/db/index.js +17 -0
- package/runtime/storage/db/schema/assets.d.ts +140 -0
- package/runtime/storage/db/schema/assets.js +10 -0
- package/runtime/storage/db/schema/credentials.d.ts +178 -0
- package/runtime/storage/db/schema/credentials.js +12 -0
- package/runtime/storage/db/schema/index.d.ts +6 -0
- package/runtime/storage/db/schema/index.js +6 -0
- package/runtime/storage/db/schema/intent-commits.d.ts +161 -0
- package/runtime/storage/db/schema/intent-commits.js +11 -0
- package/runtime/storage/db/schema/policies.d.ts +81 -0
- package/runtime/storage/db/schema/policies.js +7 -0
- package/runtime/storage/db/schema/proposals.d.ts +216 -0
- package/runtime/storage/db/schema/proposals.js +14 -0
- package/runtime/storage/db/schema/provenance.d.ts +104 -0
- package/runtime/storage/db/schema/provenance.js +8 -0
- package/runtime/storage/index.d.ts +16 -0
- package/runtime/storage/index.js +16 -0
- package/runtime/storage/memory/workspace/paths.d.ts +62 -0
- package/runtime/storage/memory/workspace/paths.js +160 -0
- package/runtime/storage/memory/workspace/store.d.ts +26 -0
- package/runtime/storage/memory/workspace/store.js +153 -0
- package/runtime/storage/memory/workspace/types.d.ts +45 -0
- package/runtime/storage/memory/workspace/types.js +1 -0
- package/runtime/storage/repositories/asset-repository.d.ts +8 -0
- package/runtime/storage/repositories/asset-repository.js +19 -0
- package/runtime/storage/repositories/credential-repository.d.ts +8 -0
- package/runtime/storage/repositories/credential-repository.js +19 -0
- package/runtime/storage/repositories/index.d.ts +6 -0
- package/runtime/storage/repositories/index.js +6 -0
- package/runtime/storage/repositories/intent-commit-repository.d.ts +10 -0
- package/runtime/storage/repositories/intent-commit-repository.js +35 -0
- package/runtime/storage/repositories/policy-repository.d.ts +8 -0
- package/runtime/storage/repositories/policy-repository.js +19 -0
- package/runtime/storage/repositories/proposal-repository.d.ts +9 -0
- package/runtime/storage/repositories/proposal-repository.js +26 -0
- package/runtime/storage/repositories/provenance-repository.d.ts +20 -0
- package/runtime/storage/repositories/provenance-repository.js +41 -0
- package/runtime/storage/services/credential-vault.d.ts +8 -0
- package/runtime/storage/services/credential-vault.js +78 -0
- package/runtime/storage/services/daily-log-pipeline.d.ts +47 -0
- package/runtime/storage/services/daily-log-pipeline.js +86 -0
- package/runtime/storage/services/effect-commit-store.d.ts +11 -0
- package/runtime/storage/services/effect-commit-store.js +93 -0
- package/runtime/storage/services/governance-layer.d.ts +40 -0
- package/runtime/storage/services/governance-layer.js +103 -0
- package/runtime/storage/services/persona-candidate-loader.d.ts +5 -0
- package/runtime/storage/services/persona-candidate-loader.js +41 -0
- package/runtime/storage/services/provenance-service.d.ts +40 -0
- package/runtime/storage/services/provenance-service.js +43 -0
- package/runtime/storage/services/quiet-input-loader.d.ts +40 -0
- package/runtime/storage/services/quiet-input-loader.js +131 -0
- package/runtime/storage/services/repair-and-backup.d.ts +22 -0
- package/runtime/storage/services/repair-and-backup.js +73 -0
- package/runtime/storage/state-api.d.ts +46 -0
- package/runtime/storage/state-api.js +73 -0
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { ConnectorRequest, ExecutionPlan, RawAttempt } from "../../base/contract.js";
|
|
2
|
+
export interface MoltbookApiClient {
|
|
3
|
+
readFeed(payload: Record<string, unknown>): Promise<unknown>;
|
|
4
|
+
publishPost(payload: Record<string, unknown>): Promise<unknown>;
|
|
5
|
+
replyComment(payload: Record<string, unknown>): Promise<unknown>;
|
|
6
|
+
}
|
|
7
|
+
export interface MoltbookSkillRunner {
|
|
8
|
+
run(intent: string, payload: Record<string, unknown>): Promise<unknown>;
|
|
9
|
+
}
|
|
10
|
+
export declare function createMoltbookRunner(input: {
|
|
11
|
+
apiClient: MoltbookApiClient;
|
|
12
|
+
skillRunner: MoltbookSkillRunner;
|
|
13
|
+
}): {
|
|
14
|
+
run(plan: ExecutionPlan, request: ConnectorRequest): Promise<RawAttempt>;
|
|
15
|
+
};
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
export function createMoltbookRunner(input) {
|
|
2
|
+
const { apiClient, skillRunner } = input;
|
|
3
|
+
return {
|
|
4
|
+
async run(plan, request) {
|
|
5
|
+
const started = Date.now();
|
|
6
|
+
try {
|
|
7
|
+
const payload = await executeByChannel(plan, request.payload, apiClient, skillRunner);
|
|
8
|
+
return {
|
|
9
|
+
platformId: request.platformId,
|
|
10
|
+
channel: plan.channel,
|
|
11
|
+
latencyMs: Date.now() - started,
|
|
12
|
+
degraded: plan.channel === "skill" || plan.channel === "browser",
|
|
13
|
+
success: true,
|
|
14
|
+
payload: {
|
|
15
|
+
capability: request.intent,
|
|
16
|
+
channel: plan.channel,
|
|
17
|
+
data: payload,
|
|
18
|
+
},
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
catch (error) {
|
|
22
|
+
return {
|
|
23
|
+
platformId: request.platformId,
|
|
24
|
+
channel: plan.channel,
|
|
25
|
+
latencyMs: Date.now() - started,
|
|
26
|
+
degraded: plan.channel === "skill" || plan.channel === "browser",
|
|
27
|
+
success: false,
|
|
28
|
+
error,
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
async function executeByChannel(plan, payload, apiClient, skillRunner) {
|
|
35
|
+
if (plan.channel === "api_rest") {
|
|
36
|
+
if (plan.intent === "feed.read")
|
|
37
|
+
return apiClient.readFeed(payload);
|
|
38
|
+
if (plan.intent === "post.publish")
|
|
39
|
+
return apiClient.publishPost(payload);
|
|
40
|
+
if (plan.intent === "comment.reply")
|
|
41
|
+
return apiClient.replyComment(payload);
|
|
42
|
+
throw { code: "protocol_mismatch", detail: `unsupported intent for moltbook api: ${plan.intent}` };
|
|
43
|
+
}
|
|
44
|
+
if (plan.channel === "skill" || plan.channel === "browser") {
|
|
45
|
+
return skillRunner.run(plan.intent, payload);
|
|
46
|
+
}
|
|
47
|
+
throw { code: "protocol_mismatch", detail: `unsupported channel for moltbook: ${plan.channel}` };
|
|
48
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { ConnectorManifest } from "../../base/manifest.js";
|
|
2
|
+
export declare const moltbookManifest: ConnectorManifest;
|
|
3
|
+
export declare const MOLTBOOK_DOC_RISK: {
|
|
4
|
+
readonly key: "moltbook_skill_doc_availability";
|
|
5
|
+
readonly fallbackChannel: "skill";
|
|
6
|
+
readonly note: "official skill/doc may be transiently unavailable; adapter seam remains replaceable via injected skill runner";
|
|
7
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export const moltbookManifest = {
|
|
2
|
+
platformId: "moltbook",
|
|
3
|
+
supportedCapabilities: ["feed.read", "post.publish", "comment.reply"],
|
|
4
|
+
channelPriority: ["api_rest", "skill", "browser"],
|
|
5
|
+
credentialTypes: ["api_key"],
|
|
6
|
+
degradedChannels: ["skill", "browser"],
|
|
7
|
+
};
|
|
8
|
+
export const MOLTBOOK_DOC_RISK = {
|
|
9
|
+
key: "moltbook_skill_doc_availability",
|
|
10
|
+
fallbackChannel: "skill",
|
|
11
|
+
note: "official skill/doc may be transiently unavailable; adapter seam remains replaceable via injected skill runner",
|
|
12
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { GuidanceFallback, GuidancePayload } from "../../../guidance/index.js";
|
|
2
|
+
export interface AppliedGuidanceContext {
|
|
3
|
+
source: "guidance_payload" | "minimal_fallback";
|
|
4
|
+
sceneType: string;
|
|
5
|
+
atmosphereText?: string;
|
|
6
|
+
impulseTexts: string[];
|
|
7
|
+
personaRationales: string[];
|
|
8
|
+
outputConstraints: string[];
|
|
9
|
+
}
|
|
10
|
+
export declare function applyGuidance(input: GuidancePayload | GuidanceFallback): AppliedGuidanceContext;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export function applyGuidance(input) {
|
|
2
|
+
return {
|
|
3
|
+
source: "minimal" in input && input.minimal ? "minimal_fallback" : "guidance_payload",
|
|
4
|
+
sceneType: input.scene.sceneType,
|
|
5
|
+
atmosphereText: input.atmosphere?.text,
|
|
6
|
+
impulseTexts: input.impulses.map((item) => item.text),
|
|
7
|
+
personaRationales: input.personaReinforcement.map((item) => item.rationale),
|
|
8
|
+
outputConstraints: input.outputGuard?.constraints ?? [],
|
|
9
|
+
};
|
|
10
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { type GuidanceFallback, type GuidancePayload, type GuidanceUnavailable, type PersonaCandidate, type SceneContext } from "../../../guidance/index.js";
|
|
2
|
+
export interface RequestGuidancePort {
|
|
3
|
+
assembleGuidance(input: {
|
|
4
|
+
sceneContext: SceneContext;
|
|
5
|
+
personaCandidates: PersonaCandidate[];
|
|
6
|
+
}): Promise<GuidancePayload | GuidanceUnavailable>;
|
|
7
|
+
}
|
|
8
|
+
export interface RequestGuidanceResult {
|
|
9
|
+
owner: "control-plane-system";
|
|
10
|
+
sceneContext: SceneContext;
|
|
11
|
+
guidance: GuidancePayload | GuidanceFallback;
|
|
12
|
+
usedFallback: boolean;
|
|
13
|
+
}
|
|
14
|
+
export declare function requestGuidance(input: {
|
|
15
|
+
sceneContext: SceneContext;
|
|
16
|
+
personaCandidates?: PersonaCandidate[];
|
|
17
|
+
port?: RequestGuidancePort;
|
|
18
|
+
}): Promise<RequestGuidanceResult>;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { assembleGuidance, buildMinimalGuidanceFallback, } from "../../../guidance/index.js";
|
|
2
|
+
export async function requestGuidance(input) {
|
|
3
|
+
const port = input.port ?? { assembleGuidance };
|
|
4
|
+
const result = await port.assembleGuidance({
|
|
5
|
+
sceneContext: input.sceneContext,
|
|
6
|
+
personaCandidates: input.personaCandidates ?? [],
|
|
7
|
+
});
|
|
8
|
+
if ("available" in result) {
|
|
9
|
+
return {
|
|
10
|
+
owner: "control-plane-system",
|
|
11
|
+
sceneContext: input.sceneContext,
|
|
12
|
+
guidance: buildMinimalGuidanceFallback(input.sceneContext),
|
|
13
|
+
usedFallback: true,
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
return {
|
|
17
|
+
owner: "control-plane-system",
|
|
18
|
+
sceneContext: input.sceneContext,
|
|
19
|
+
guidance: result,
|
|
20
|
+
usedFallback: false,
|
|
21
|
+
};
|
|
22
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export * from "./types.js";
|
|
2
|
+
export * from "./rhythm/rhythm-policy.js";
|
|
3
|
+
export * from "./rhythm/select-window.js";
|
|
4
|
+
export * from "./orchestrator/intent-planner.js";
|
|
5
|
+
export * from "./orchestrator/guard-layer.js";
|
|
6
|
+
export * from "./orchestrator/lease-manager.js";
|
|
7
|
+
export * from "./orchestrator/effect-dispatcher.js";
|
|
8
|
+
export * from "./orchestrator/resume-from-checkpoint.js";
|
|
9
|
+
export * from "./quiet/quiet-pipeline.js";
|
|
10
|
+
export * from "./reflection/run-narrative-reflection.js";
|
|
11
|
+
export * from "./outreach/evaluate-outreach.js";
|
|
12
|
+
export * from "./outreach/build-message.js";
|
|
13
|
+
export * from "./guidance/request-guidance.js";
|
|
14
|
+
export * from "./guidance/apply-guidance.js";
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export * from "./types.js";
|
|
2
|
+
export * from "./rhythm/rhythm-policy.js";
|
|
3
|
+
export * from "./rhythm/select-window.js";
|
|
4
|
+
export * from "./orchestrator/intent-planner.js";
|
|
5
|
+
export * from "./orchestrator/guard-layer.js";
|
|
6
|
+
export * from "./orchestrator/lease-manager.js";
|
|
7
|
+
export * from "./orchestrator/effect-dispatcher.js";
|
|
8
|
+
export * from "./orchestrator/resume-from-checkpoint.js";
|
|
9
|
+
export * from "./quiet/quiet-pipeline.js";
|
|
10
|
+
export * from "./reflection/run-narrative-reflection.js";
|
|
11
|
+
export * from "./outreach/evaluate-outreach.js";
|
|
12
|
+
export * from "./outreach/build-message.js";
|
|
13
|
+
export * from "./guidance/request-guidance.js";
|
|
14
|
+
export * from "./guidance/apply-guidance.js";
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import type { ConnectorResult, CapabilityIntent } from "../../../connectors/base/contract.js";
|
|
2
|
+
import { LeaseManager, type EffectClass } from "./lease-manager.js";
|
|
3
|
+
export interface AllowedIntent {
|
|
4
|
+
id: string;
|
|
5
|
+
kind: "work" | "exploration" | "social" | "reflection" | "outreach" | "maintenance";
|
|
6
|
+
summary: string;
|
|
7
|
+
effectClass: EffectClass;
|
|
8
|
+
platformId?: string;
|
|
9
|
+
payload?: Record<string, unknown>;
|
|
10
|
+
}
|
|
11
|
+
export interface DecisionContext {
|
|
12
|
+
decisionId: string;
|
|
13
|
+
intentId: string;
|
|
14
|
+
tickId: string;
|
|
15
|
+
checkpointId: string;
|
|
16
|
+
traceId: string;
|
|
17
|
+
}
|
|
18
|
+
export interface IntentCommitPort {
|
|
19
|
+
createIntentCommitRecord(input: {
|
|
20
|
+
intentId: string;
|
|
21
|
+
decisionId: string;
|
|
22
|
+
checkpointId?: string;
|
|
23
|
+
state: "planned" | "dispatched" | "externally_acknowledged" | "committed" | "reconcile" | "aborted";
|
|
24
|
+
}): Promise<{
|
|
25
|
+
id: string;
|
|
26
|
+
}>;
|
|
27
|
+
advanceIntentCommitState(id: string, state: "planned" | "dispatched" | "externally_acknowledged" | "committed" | "reconcile" | "aborted", metadata?: Record<string, unknown>): Promise<void>;
|
|
28
|
+
commitIntentOutcome(id: string, outcome: {
|
|
29
|
+
traceId: string;
|
|
30
|
+
outcomeRef: string;
|
|
31
|
+
}): Promise<void>;
|
|
32
|
+
abortIntentCommit(id: string, reason: string): Promise<void>;
|
|
33
|
+
}
|
|
34
|
+
export interface ConnectorExecutor {
|
|
35
|
+
executeEffect(input: {
|
|
36
|
+
platformId: string;
|
|
37
|
+
intent: CapabilityIntent;
|
|
38
|
+
payload: Record<string, unknown>;
|
|
39
|
+
decisionId: string;
|
|
40
|
+
intentId: string;
|
|
41
|
+
idempotencyKey: string;
|
|
42
|
+
}): Promise<ConnectorResult<unknown>>;
|
|
43
|
+
}
|
|
44
|
+
export interface CheckpointPort {
|
|
45
|
+
saveCheckpoint(input: {
|
|
46
|
+
id: string;
|
|
47
|
+
tickId: string;
|
|
48
|
+
intentId: string;
|
|
49
|
+
phase: "before_effect" | "before_quiet_write";
|
|
50
|
+
snapshotRef: string;
|
|
51
|
+
}): Promise<void>;
|
|
52
|
+
}
|
|
53
|
+
export interface MemoryPort {
|
|
54
|
+
persistCurationResult(input: {
|
|
55
|
+
summary: string;
|
|
56
|
+
sourceRefs: string[];
|
|
57
|
+
traceId: string;
|
|
58
|
+
}): Promise<void>;
|
|
59
|
+
}
|
|
60
|
+
export interface ReflectionPort {
|
|
61
|
+
runNarrativeReflection(input: {
|
|
62
|
+
decisionId: string;
|
|
63
|
+
intentId: string;
|
|
64
|
+
traceId: string;
|
|
65
|
+
}): Promise<{
|
|
66
|
+
outcomeRef: string;
|
|
67
|
+
}>;
|
|
68
|
+
}
|
|
69
|
+
export type DispatchResult = {
|
|
70
|
+
status: "deferred";
|
|
71
|
+
reason: string;
|
|
72
|
+
} | {
|
|
73
|
+
status: "effect_executed";
|
|
74
|
+
result: ConnectorResult<unknown>;
|
|
75
|
+
commitId: string;
|
|
76
|
+
} | {
|
|
77
|
+
status: "curated";
|
|
78
|
+
commitId: string;
|
|
79
|
+
} | {
|
|
80
|
+
status: "reflected";
|
|
81
|
+
commitId: string;
|
|
82
|
+
} | {
|
|
83
|
+
status: "maintenance_done";
|
|
84
|
+
commitId: string;
|
|
85
|
+
};
|
|
86
|
+
export declare class EffectDispatcher {
|
|
87
|
+
private readonly leaseManager;
|
|
88
|
+
private readonly commitPort;
|
|
89
|
+
private readonly connectorExecutor;
|
|
90
|
+
private readonly checkpointPort;
|
|
91
|
+
private readonly memoryPort;
|
|
92
|
+
private readonly reflectionPort;
|
|
93
|
+
constructor(leaseManager: LeaseManager, commitPort: IntentCommitPort, connectorExecutor: ConnectorExecutor, checkpointPort: CheckpointPort, memoryPort: MemoryPort, reflectionPort: ReflectionPort);
|
|
94
|
+
dispatchEffect(intent: AllowedIntent, decision: DecisionContext): Promise<DispatchResult>;
|
|
95
|
+
}
|
|
96
|
+
export declare function buildDecisionContext(input: {
|
|
97
|
+
tickId: string;
|
|
98
|
+
decisionId?: string;
|
|
99
|
+
intentId: string;
|
|
100
|
+
}): DecisionContext;
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import * as crypto from "crypto";
|
|
2
|
+
function needsLease(effectClass) {
|
|
3
|
+
return effectClass === "external_platform_action" || effectClass === "user_outreach";
|
|
4
|
+
}
|
|
5
|
+
function needsCheckpoint(effectClass) {
|
|
6
|
+
return effectClass !== "maintenance";
|
|
7
|
+
}
|
|
8
|
+
function toCapabilityIntent(intent) {
|
|
9
|
+
if (intent.kind === "work")
|
|
10
|
+
return "work.discover";
|
|
11
|
+
if (intent.kind === "exploration")
|
|
12
|
+
return "feed.read";
|
|
13
|
+
if (intent.kind === "social")
|
|
14
|
+
return "comment.reply";
|
|
15
|
+
if (intent.kind === "outreach")
|
|
16
|
+
return "message.send";
|
|
17
|
+
return "feed.read";
|
|
18
|
+
}
|
|
19
|
+
export class EffectDispatcher {
|
|
20
|
+
leaseManager;
|
|
21
|
+
commitPort;
|
|
22
|
+
connectorExecutor;
|
|
23
|
+
checkpointPort;
|
|
24
|
+
memoryPort;
|
|
25
|
+
reflectionPort;
|
|
26
|
+
constructor(leaseManager, commitPort, connectorExecutor, checkpointPort, memoryPort, reflectionPort) {
|
|
27
|
+
this.leaseManager = leaseManager;
|
|
28
|
+
this.commitPort = commitPort;
|
|
29
|
+
this.connectorExecutor = connectorExecutor;
|
|
30
|
+
this.checkpointPort = checkpointPort;
|
|
31
|
+
this.memoryPort = memoryPort;
|
|
32
|
+
this.reflectionPort = reflectionPort;
|
|
33
|
+
}
|
|
34
|
+
async dispatchEffect(intent, decision) {
|
|
35
|
+
const lease = needsLease(intent.effectClass)
|
|
36
|
+
? await this.leaseManager.acquire(intent.effectClass, intent.platformId ?? intent.id)
|
|
37
|
+
: await this.leaseManager.acquire("maintenance");
|
|
38
|
+
if (!lease.granted) {
|
|
39
|
+
return { status: "deferred", reason: "lease_unavailable" };
|
|
40
|
+
}
|
|
41
|
+
if (needsCheckpoint(intent.effectClass)) {
|
|
42
|
+
await this.checkpointPort.saveCheckpoint({
|
|
43
|
+
id: decision.checkpointId,
|
|
44
|
+
tickId: decision.tickId,
|
|
45
|
+
intentId: decision.intentId,
|
|
46
|
+
phase: intent.effectClass === "external_platform_action" ? "before_effect" : "before_quiet_write",
|
|
47
|
+
snapshotRef: decision.traceId,
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
const commit = await this.commitPort.createIntentCommitRecord({
|
|
51
|
+
intentId: decision.intentId,
|
|
52
|
+
decisionId: decision.decisionId,
|
|
53
|
+
checkpointId: decision.checkpointId,
|
|
54
|
+
state: "planned",
|
|
55
|
+
});
|
|
56
|
+
try {
|
|
57
|
+
if (intent.effectClass === "external_platform_action") {
|
|
58
|
+
await this.commitPort.advanceIntentCommitState(commit.id, "dispatched");
|
|
59
|
+
const result = await this.connectorExecutor.executeEffect({
|
|
60
|
+
platformId: intent.platformId ?? "unknown",
|
|
61
|
+
intent: toCapabilityIntent(intent),
|
|
62
|
+
payload: intent.payload ?? {},
|
|
63
|
+
decisionId: decision.decisionId,
|
|
64
|
+
intentId: decision.intentId,
|
|
65
|
+
idempotencyKey: `idem:${decision.decisionId}:${decision.intentId}`,
|
|
66
|
+
});
|
|
67
|
+
if (result.status === "success") {
|
|
68
|
+
await this.commitPort.advanceIntentCommitState(commit.id, "externally_acknowledged", {
|
|
69
|
+
outcomeRef: result.metadata.platformId,
|
|
70
|
+
});
|
|
71
|
+
await this.commitPort.commitIntentOutcome(commit.id, {
|
|
72
|
+
traceId: decision.traceId,
|
|
73
|
+
outcomeRef: result.metadata.platformId,
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
if (result.status === "retryable_failure") {
|
|
78
|
+
await this.commitPort.advanceIntentCommitState(commit.id, "reconcile", {
|
|
79
|
+
failureClass: result.failureClass,
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
await this.commitPort.abortIntentCommit(commit.id, result.failureClass ?? "external_effect_failed");
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return { status: "effect_executed", result, commitId: commit.id };
|
|
87
|
+
}
|
|
88
|
+
if (intent.effectClass === "memory_curation") {
|
|
89
|
+
await this.commitPort.advanceIntentCommitState(commit.id, "dispatched");
|
|
90
|
+
await this.memoryPort.persistCurationResult({
|
|
91
|
+
summary: intent.summary,
|
|
92
|
+
sourceRefs: [decision.traceId],
|
|
93
|
+
traceId: decision.traceId,
|
|
94
|
+
});
|
|
95
|
+
await this.commitPort.commitIntentOutcome(commit.id, {
|
|
96
|
+
traceId: decision.traceId,
|
|
97
|
+
outcomeRef: "memory_curation",
|
|
98
|
+
});
|
|
99
|
+
return { status: "curated", commitId: commit.id };
|
|
100
|
+
}
|
|
101
|
+
if (intent.effectClass === "narrative_reflection") {
|
|
102
|
+
await this.commitPort.advanceIntentCommitState(commit.id, "dispatched");
|
|
103
|
+
const reflection = await this.reflectionPort.runNarrativeReflection({
|
|
104
|
+
decisionId: decision.decisionId,
|
|
105
|
+
intentId: decision.intentId,
|
|
106
|
+
traceId: decision.traceId,
|
|
107
|
+
});
|
|
108
|
+
await this.commitPort.commitIntentOutcome(commit.id, {
|
|
109
|
+
traceId: decision.traceId,
|
|
110
|
+
outcomeRef: reflection.outcomeRef,
|
|
111
|
+
});
|
|
112
|
+
return { status: "reflected", commitId: commit.id };
|
|
113
|
+
}
|
|
114
|
+
await this.commitPort.advanceIntentCommitState(commit.id, "dispatched");
|
|
115
|
+
await this.commitPort.commitIntentOutcome(commit.id, {
|
|
116
|
+
traceId: decision.traceId,
|
|
117
|
+
outcomeRef: "maintenance",
|
|
118
|
+
});
|
|
119
|
+
return { status: "maintenance_done", commitId: commit.id };
|
|
120
|
+
}
|
|
121
|
+
catch (error) {
|
|
122
|
+
await this.commitPort.abortIntentCommit(commit.id, String(error));
|
|
123
|
+
throw error;
|
|
124
|
+
}
|
|
125
|
+
finally {
|
|
126
|
+
await lease.release();
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
export function buildDecisionContext(input) {
|
|
131
|
+
const decisionId = input.decisionId ?? crypto.randomUUID();
|
|
132
|
+
return {
|
|
133
|
+
decisionId,
|
|
134
|
+
intentId: input.intentId,
|
|
135
|
+
tickId: input.tickId,
|
|
136
|
+
checkpointId: `checkpoint:${input.intentId}:${Date.now()}`,
|
|
137
|
+
traceId: `trace:${decisionId}`,
|
|
138
|
+
};
|
|
139
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
function stableIntentHash(intent) {
|
|
2
|
+
return `${intent.kind}:${intent.summary}`;
|
|
3
|
+
}
|
|
4
|
+
function isDuplicateIntent(intent, snapshot) {
|
|
5
|
+
const hash = stableIntentHash(intent);
|
|
6
|
+
return snapshot.deniedIntents.some((item) => item.intentHash === hash && item.reason === "duplicate_intent");
|
|
7
|
+
}
|
|
8
|
+
function isBudgetExceeded(intent, snapshot) {
|
|
9
|
+
if (intent.kind !== "social")
|
|
10
|
+
return false;
|
|
11
|
+
if (!snapshot.budgets)
|
|
12
|
+
return false;
|
|
13
|
+
return snapshot.budgets.socialUsed >= snapshot.budgets.socialLimit;
|
|
14
|
+
}
|
|
15
|
+
function isQuietSuppressed(intent, snapshot) {
|
|
16
|
+
if (snapshot.mode !== "quiet")
|
|
17
|
+
return false;
|
|
18
|
+
if (intent.effectClass === "maintenance" || intent.effectClass === "memory_curation" || intent.effectClass === "narrative_reflection") {
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
return true;
|
|
22
|
+
}
|
|
23
|
+
export function evaluateGuards(intent, snapshot) {
|
|
24
|
+
const reasons = [];
|
|
25
|
+
if (isDuplicateIntent(intent, snapshot)) {
|
|
26
|
+
reasons.push("duplicate_intent");
|
|
27
|
+
}
|
|
28
|
+
if (isBudgetExceeded(intent, snapshot)) {
|
|
29
|
+
reasons.push("budget_exceeded");
|
|
30
|
+
}
|
|
31
|
+
if (isQuietSuppressed(intent, snapshot)) {
|
|
32
|
+
reasons.push("quiet_window");
|
|
33
|
+
}
|
|
34
|
+
if (snapshot.awaitingUserInput) {
|
|
35
|
+
reasons.push("awaiting_user");
|
|
36
|
+
}
|
|
37
|
+
if (reasons.length === 0) {
|
|
38
|
+
return {
|
|
39
|
+
verdict: "allow",
|
|
40
|
+
reasons,
|
|
41
|
+
quietSuppressed: false,
|
|
42
|
+
leaseRequired: intent.effectClass === "external_platform_action" || intent.effectClass === "user_outreach",
|
|
43
|
+
requiresCheckpoint: intent.effectClass !== "maintenance",
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
const escalated = reasons.includes("awaiting_user") && intent.kind === "outreach";
|
|
47
|
+
return {
|
|
48
|
+
verdict: escalated ? "escalate" : "deny",
|
|
49
|
+
reasons,
|
|
50
|
+
quietSuppressed: reasons.includes("quiet_window"),
|
|
51
|
+
leaseRequired: false,
|
|
52
|
+
requiresCheckpoint: false,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
const MAX_CANDIDATES = 6;
|
|
2
|
+
function planObligationIntents(snapshot) {
|
|
3
|
+
return snapshot.pendingObligations.map((obligation, index) => ({
|
|
4
|
+
id: `intent-obligation-${index}`,
|
|
5
|
+
kind: "work",
|
|
6
|
+
priority: 100 - index,
|
|
7
|
+
source: "obligation",
|
|
8
|
+
summary: `fulfill obligation: ${obligation}`,
|
|
9
|
+
effectClass: "external_platform_action",
|
|
10
|
+
}));
|
|
11
|
+
}
|
|
12
|
+
function planPlatformIntents(snapshot) {
|
|
13
|
+
const socialPriorityBase = snapshot.budgets && snapshot.budgets.socialUsed >= snapshot.budgets.socialLimit ? 10 : 60;
|
|
14
|
+
return [
|
|
15
|
+
{
|
|
16
|
+
id: "intent-exploration",
|
|
17
|
+
kind: "exploration",
|
|
18
|
+
priority: 70,
|
|
19
|
+
source: "tick",
|
|
20
|
+
summary: "scan platform opportunities",
|
|
21
|
+
effectClass: "external_platform_action",
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
id: "intent-social",
|
|
25
|
+
kind: "social",
|
|
26
|
+
priority: socialPriorityBase,
|
|
27
|
+
source: "tick",
|
|
28
|
+
summary: "engage social platforms",
|
|
29
|
+
effectClass: "external_platform_action",
|
|
30
|
+
},
|
|
31
|
+
];
|
|
32
|
+
}
|
|
33
|
+
function planQuietIntents(snapshot) {
|
|
34
|
+
if (snapshot.mode !== "quiet") {
|
|
35
|
+
return [];
|
|
36
|
+
}
|
|
37
|
+
return [
|
|
38
|
+
{
|
|
39
|
+
id: "intent-maintenance",
|
|
40
|
+
kind: "maintenance",
|
|
41
|
+
priority: 90,
|
|
42
|
+
source: "quiet_plan",
|
|
43
|
+
summary: "run maintenance checks",
|
|
44
|
+
effectClass: "maintenance",
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
id: "intent-reflection",
|
|
48
|
+
kind: "reflection",
|
|
49
|
+
priority: 80,
|
|
50
|
+
source: "quiet_plan",
|
|
51
|
+
summary: "run narrative reflection",
|
|
52
|
+
effectClass: "narrative_reflection",
|
|
53
|
+
},
|
|
54
|
+
];
|
|
55
|
+
}
|
|
56
|
+
function planOutreachIntents(snapshot) {
|
|
57
|
+
if (snapshot.recentOutreachHashes.length > 3) {
|
|
58
|
+
return [];
|
|
59
|
+
}
|
|
60
|
+
return [
|
|
61
|
+
{
|
|
62
|
+
id: "intent-outreach",
|
|
63
|
+
kind: "outreach",
|
|
64
|
+
priority: 40,
|
|
65
|
+
source: "tick",
|
|
66
|
+
summary: "consider proactive user outreach",
|
|
67
|
+
effectClass: "user_outreach",
|
|
68
|
+
},
|
|
69
|
+
];
|
|
70
|
+
}
|
|
71
|
+
export function planIntent(snapshot) {
|
|
72
|
+
const intents = [
|
|
73
|
+
...planObligationIntents(snapshot),
|
|
74
|
+
...planPlatformIntents(snapshot),
|
|
75
|
+
...planQuietIntents(snapshot),
|
|
76
|
+
...planOutreachIntents(snapshot),
|
|
77
|
+
];
|
|
78
|
+
return intents
|
|
79
|
+
.sort((a, b) => b.priority - a.priority)
|
|
80
|
+
.slice(0, MAX_CANDIDATES);
|
|
81
|
+
}
|
|
82
|
+
export function decideDecisionBasis(intent) {
|
|
83
|
+
if (intent.source === "obligation")
|
|
84
|
+
return "rule_only";
|
|
85
|
+
if (intent.kind === "maintenance")
|
|
86
|
+
return "rule_only";
|
|
87
|
+
if (intent.kind === "outreach" || intent.kind === "reflection")
|
|
88
|
+
return "model_assisted";
|
|
89
|
+
if (intent.kind === "exploration" || intent.kind === "social" || intent.kind === "work")
|
|
90
|
+
return "score_based";
|
|
91
|
+
return "rule_only";
|
|
92
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export type EffectClass = "external_platform_action" | "memory_curation" | "narrative_reflection" | "user_outreach" | "maintenance";
|
|
2
|
+
export interface LeaseHandle {
|
|
3
|
+
id: string;
|
|
4
|
+
granted: boolean;
|
|
5
|
+
scope: string;
|
|
6
|
+
release(): Promise<void>;
|
|
7
|
+
}
|
|
8
|
+
export declare class LeaseManager {
|
|
9
|
+
private readonly ttlMs;
|
|
10
|
+
private readonly leases;
|
|
11
|
+
constructor(ttlMs?: number);
|
|
12
|
+
acquire(effectClass: EffectClass, scopeHint?: string): Promise<LeaseHandle>;
|
|
13
|
+
private resolveScope;
|
|
14
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import * as crypto from "crypto";
|
|
2
|
+
const GLOBAL_SCOPE = "global-control-plane-flight";
|
|
3
|
+
const DEFAULT_TTL_MS = 90_000;
|
|
4
|
+
export class LeaseManager {
|
|
5
|
+
ttlMs;
|
|
6
|
+
leases = new Map();
|
|
7
|
+
constructor(ttlMs = DEFAULT_TTL_MS) {
|
|
8
|
+
this.ttlMs = ttlMs;
|
|
9
|
+
}
|
|
10
|
+
async acquire(effectClass, scopeHint) {
|
|
11
|
+
const scope = this.resolveScope(effectClass, scopeHint);
|
|
12
|
+
if (!scope) {
|
|
13
|
+
return {
|
|
14
|
+
id: "no-lease-required",
|
|
15
|
+
granted: true,
|
|
16
|
+
scope: "none",
|
|
17
|
+
async release() {
|
|
18
|
+
return;
|
|
19
|
+
},
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
const now = Date.now();
|
|
23
|
+
const existing = this.leases.get(scope);
|
|
24
|
+
if (existing && existing.expiresAt > now) {
|
|
25
|
+
return {
|
|
26
|
+
id: existing.id,
|
|
27
|
+
granted: false,
|
|
28
|
+
scope,
|
|
29
|
+
async release() {
|
|
30
|
+
return;
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
const record = {
|
|
35
|
+
id: crypto.randomUUID(),
|
|
36
|
+
scope,
|
|
37
|
+
expiresAt: now + this.ttlMs,
|
|
38
|
+
};
|
|
39
|
+
this.leases.set(scope, record);
|
|
40
|
+
return {
|
|
41
|
+
id: record.id,
|
|
42
|
+
granted: true,
|
|
43
|
+
scope,
|
|
44
|
+
release: async () => {
|
|
45
|
+
const current = this.leases.get(scope);
|
|
46
|
+
if (current && current.id === record.id) {
|
|
47
|
+
this.leases.delete(scope);
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
resolveScope(effectClass, scopeHint) {
|
|
53
|
+
if (effectClass === "external_platform_action" || effectClass === "user_outreach") {
|
|
54
|
+
return scopeHint && scopeHint.length > 0 ? `${GLOBAL_SCOPE}:${scopeHint}` : GLOBAL_SCOPE;
|
|
55
|
+
}
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
}
|