@haaaiawd/second-nature 0.1.30 → 0.1.31
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.js +1 -1
- package/openclaw.plugin.json +1 -1
- package/package.json +1 -1
- package/runtime/cli/commands/connector-status.d.ts +1 -0
- package/runtime/cli/commands/connector-status.js +5 -0
- package/runtime/cli/commands/index.js +16 -0
- package/runtime/cli/ops/ops-router.js +3 -0
- package/runtime/core/second-nature/orchestrator/intent-planner.js +3 -0
- package/runtime/core/second-nature/orchestrator/platform-capability-router.js +18 -2
- package/workspace-ops-bridge.js +13 -1
package/index.js
CHANGED
|
@@ -71,7 +71,7 @@ process.stderr.write("[second-nature] module evaluated\n");
|
|
|
71
71
|
const INTERNAL_RUNTIME_TRACE_PREFIX = "sn-runtime-";
|
|
72
72
|
const HOST_SAFE_LIMITATION_MESSAGE = "Host-safe plugin package keeps synchronous register/load semantics, but mutating workspace runtime flows remain unavailable here.";
|
|
73
73
|
const SETUP_MARKER_RELATIVE_PATH = path.join(".second-nature", "setup", "agent-inner-guide-ack.json");
|
|
74
|
-
const SETUP_GUIDE_VERSION = "0.1.
|
|
74
|
+
const SETUP_GUIDE_VERSION = "0.1.31";
|
|
75
75
|
const SETUP_COMMANDS = new Set(["setup_hint", "setup_ack"]);
|
|
76
76
|
let activationSpine = null;
|
|
77
77
|
/** T1.1.4 — lazily opened full read bridge; closed when workspace root / resolution changes. */
|
package/openclaw.plugin.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"id": "second-nature",
|
|
3
3
|
"name": "Second Nature",
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.31",
|
|
5
5
|
"description": "OpenClaw native plugin with synchronous surface registration and bundled runtime spine. Set SECOND_NATURE_WORKSPACE_ROOT or tool workspaceRoot to the same path as the agent workspace. Agent inner guide is packaged as agent-inner-guide.md. v7 ops surface: self_health, tool_affordance, heartbeat_digest, narrative:diff, timeline, restore, runtime_secret_bootstrap.",
|
|
6
6
|
"activation": {
|
|
7
7
|
"onStartup": true,
|
package/package.json
CHANGED
|
@@ -7,6 +7,7 @@ export interface ConnectorStatusInput {
|
|
|
7
7
|
export interface ConnectorTestInput {
|
|
8
8
|
platformId: string;
|
|
9
9
|
dryRun?: boolean;
|
|
10
|
+
workspaceRoot?: string;
|
|
10
11
|
}
|
|
11
12
|
export declare function connectorStatus(registry: DynamicConnectorRegistry | undefined, ledger: ConnectorInventoryLedger | undefined, input?: ConnectorStatusInput): Promise<Record<string, unknown>>;
|
|
12
13
|
export declare function connectorTest(registry: DynamicConnectorRegistry | undefined, input: ConnectorTestInput): Promise<Record<string, unknown>>;
|
|
@@ -97,6 +97,11 @@ export async function connectorTest(registry, input) {
|
|
|
97
97
|
},
|
|
98
98
|
};
|
|
99
99
|
}
|
|
100
|
+
// Workspace bridge calls are often process-isolated per tool invocation.
|
|
101
|
+
// Reload here as well as in connector_status so dry-run tests see the same inventory.
|
|
102
|
+
if (input.workspaceRoot) {
|
|
103
|
+
registry.reloadConnectors(input.workspaceRoot);
|
|
104
|
+
}
|
|
100
105
|
const entry = registry.describeConnector(platformId);
|
|
101
106
|
if (!entry) {
|
|
102
107
|
return {
|
|
@@ -23,6 +23,14 @@ function explainSubjectError(code, message) {
|
|
|
23
23
|
}
|
|
24
24
|
export function createCliCommands(deps) {
|
|
25
25
|
const { readModels, actionBridge, opsRouter } = deps;
|
|
26
|
+
const opsCommand = (name, description) => ({
|
|
27
|
+
name,
|
|
28
|
+
description,
|
|
29
|
+
execute: async (input) => {
|
|
30
|
+
const surface = await Promise.resolve(opsRouter.dispatch(name, input));
|
|
31
|
+
return surface;
|
|
32
|
+
},
|
|
33
|
+
});
|
|
26
34
|
return [
|
|
27
35
|
{
|
|
28
36
|
name: "status",
|
|
@@ -268,6 +276,14 @@ export function createCliCommands(deps) {
|
|
|
268
276
|
return surface;
|
|
269
277
|
},
|
|
270
278
|
},
|
|
279
|
+
opsCommand("connector:run", "T-ROS.C.3 — manually execute a connector capability outside heartbeat cadence"),
|
|
280
|
+
opsCommand("self_health", "T-ROS.C.1 — show v7 self-health snapshot and degraded dimensions"),
|
|
281
|
+
opsCommand("tool_affordance", "T-ROS.C.1 — show v7 tool affordance map or explicit unavailable state"),
|
|
282
|
+
opsCommand("heartbeat_digest", "T-ROS.C.1 — assemble v7 heartbeat digest for a day"),
|
|
283
|
+
opsCommand("narrative:diff", "T-ROS.C.1 — compare two narrative timeline versions"),
|
|
284
|
+
opsCommand("timeline", "T-ROS.C.1 — query v7 narrative timeline with cursor pagination"),
|
|
285
|
+
opsCommand("restore", "T-ROS.C.1 — apply bounded restore and write restore audit"),
|
|
286
|
+
opsCommand("runtime_secret_bootstrap", "T-ROS.C.1 — inspect runtime secret anchor health without exposing plaintext"),
|
|
271
287
|
{
|
|
272
288
|
name: "goal",
|
|
273
289
|
description: "T1.2.4 — owner-governed goal operations: set, list, accept, reject",
|
|
@@ -249,6 +249,9 @@ export function createOpsRouter(deps) {
|
|
|
249
249
|
const result = await connectorTest(deps.registry, {
|
|
250
250
|
platformId: typeof input?.platformId === "string" ? input.platformId : "",
|
|
251
251
|
dryRun: isWet ? false : (input?.dryRun === false ? false : true),
|
|
252
|
+
workspaceRoot: typeof input?.workspaceRoot === "string"
|
|
253
|
+
? input.workspaceRoot
|
|
254
|
+
: deps.workspaceRoot,
|
|
252
255
|
});
|
|
253
256
|
if (isWet && result.ok) {
|
|
254
257
|
// Annotate result with manual trigger context (DR-038 / T-ROS.C.3)
|
|
@@ -79,6 +79,9 @@ export function planIntentWithKind(kind, basePriority, runtime, context, registr
|
|
|
79
79
|
return [];
|
|
80
80
|
const config = INTENT_CONFIGS[kind];
|
|
81
81
|
const platformId = resolvePlatformForIntent(kind, context ?? {}, registry);
|
|
82
|
+
if (kind === "work" && !options?.multiSource && !platformId) {
|
|
83
|
+
return [];
|
|
84
|
+
}
|
|
82
85
|
let priority = basePriority;
|
|
83
86
|
// Social budget exhaustion → cap priority.
|
|
84
87
|
if (kind === "social" &&
|
|
@@ -14,7 +14,19 @@ function getPlatformIds(registry) {
|
|
|
14
14
|
return registry.listRegisteredPlatformIds();
|
|
15
15
|
}
|
|
16
16
|
// Fallback: built-in platforms when registry is absent (backward compat)
|
|
17
|
-
return ["moltbook", "instreet", "evomap"];
|
|
17
|
+
return ["moltbook", "instreet", "evomap", "agent-world"];
|
|
18
|
+
}
|
|
19
|
+
const FALLBACK_PLATFORM_CAPABILITIES = {
|
|
20
|
+
"moltbook": ["feed.read", "post.publish", "comment.reply", "message.send"],
|
|
21
|
+
"instreet": ["notification.list", "message.send", "comment.reply", "agent.heartbeat"],
|
|
22
|
+
"evomap": ["agent.register", "agent.heartbeat", "work.discover", "task.claim"],
|
|
23
|
+
"agent-world": ["feed.read", "work.discover", "task.claim"],
|
|
24
|
+
};
|
|
25
|
+
function fallbackPlatformSupportsCapability(platformId, kind) {
|
|
26
|
+
const capability = kindToCapability(kind);
|
|
27
|
+
if (!capability)
|
|
28
|
+
return false;
|
|
29
|
+
return (FALLBACK_PLATFORM_CAPABILITIES[platformId] ?? []).includes(capability);
|
|
18
30
|
}
|
|
19
31
|
function extractPlatformIdsFromGoals(goals, kind, platformIds) {
|
|
20
32
|
const capability = kindToCapability(kind);
|
|
@@ -110,6 +122,10 @@ export function resolvePlatformForIntent(kind, context, registry) {
|
|
|
110
122
|
// Registry says unsupported → undefined (guard layer will deny)
|
|
111
123
|
return undefined;
|
|
112
124
|
}
|
|
113
|
-
// No registry:
|
|
125
|
+
// No registry: keep legacy platform-name fallback, but do not invent an
|
|
126
|
+
// unsupported platform/capability pair that later fails as protocol_mismatch.
|
|
127
|
+
if (!fallbackPlatformSupportsCapability(single, kind)) {
|
|
128
|
+
return undefined;
|
|
129
|
+
}
|
|
114
130
|
return single;
|
|
115
131
|
}
|
package/workspace-ops-bridge.js
CHANGED
|
@@ -23,7 +23,19 @@ import fs from "node:fs";
|
|
|
23
23
|
import path from "node:path";
|
|
24
24
|
import { fileURLToPath } from "node:url";
|
|
25
25
|
export async function openWorkspaceOpsBridge(workspaceRoot) {
|
|
26
|
-
const
|
|
26
|
+
const declaredRoot = typeof workspaceRoot === "string" ? workspaceRoot.trim() : "";
|
|
27
|
+
if (!declaredRoot) {
|
|
28
|
+
return {
|
|
29
|
+
ok: false,
|
|
30
|
+
error: {
|
|
31
|
+
code: "WORKSPACE_ROOT_REQUIRED",
|
|
32
|
+
message: "openWorkspaceOpsBridge requires a workspaceRoot path. Set SECOND_NATURE_WORKSPACE_ROOT or pass tool workspaceRoot.",
|
|
33
|
+
nextStep: "reinvoke_with_workspaceRoot_or_set_SECOND_NATURE_WORKSPACE_ROOT",
|
|
34
|
+
requiredUserInput: ["workspaceRoot"],
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
const resolvedRoot = path.resolve(declaredRoot);
|
|
27
39
|
try {
|
|
28
40
|
const pluginPackageRoot = path.dirname(fileURLToPath(import.meta.url));
|
|
29
41
|
// Packaged `plugin/runtime` is emitted JS without sibling `.d.ts` in this repo layout.
|