@haaaiawd/second-nature 0.1.23 → 0.1.24

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@haaaiawd/second-nature",
3
- "version": "0.1.23",
3
+ "version": "0.1.24",
4
4
  "description": "OpenClaw native plugin with synchronous registration, a packaged runtime artifact, and operator-facing status/explain flows.",
5
5
  "keywords": [
6
6
  "openclaw",
@@ -8,6 +8,51 @@ import { createCliReadModels, } from "./read-models/index.js";
8
8
  import { resolvePackagedRuntime } from "./runtime/runtime-artifact-boundary.js";
9
9
  import { createRuntimeDecisionRecorder, } from "../observability/services/runtime-decision-recorder.js";
10
10
  import { createConnectorExecutorAdapter, } from "../connectors/services/connector-executor-adapter.js";
11
+ import { DynamicConnectorRegistry, createRegistrySnapshotStore, } from "../connectors/registry/index.js";
12
+ /** Built-in connector manifests for DynamicConnectorRegistry. */
13
+ const BUILT_IN_CONNECTOR_MANIFESTS = [
14
+ {
15
+ schemaVersion: "sn.connector.v1",
16
+ platformId: "moltbook",
17
+ displayName: "Moltbook",
18
+ family: "social_community",
19
+ capabilities: [
20
+ { id: "feed.read" },
21
+ { id: "post.publish" },
22
+ { id: "comment.reply" },
23
+ ],
24
+ runner: { kind: "declarative_http" },
25
+ credentials: [{ type: "api_key", required: true }],
26
+ sourceRefPolicy: { minSourceRefs: 1 },
27
+ },
28
+ {
29
+ schemaVersion: "sn.connector.v1",
30
+ platformId: "evomap",
31
+ displayName: "EvoMap",
32
+ family: "agent_network",
33
+ capabilities: [
34
+ { id: "agent.register" },
35
+ { id: "work.discover" },
36
+ ],
37
+ runner: { kind: "declarative_http" },
38
+ credentials: [{ type: "api_key", required: true }],
39
+ sourceRefPolicy: { minSourceRefs: 1 },
40
+ },
41
+ {
42
+ schemaVersion: "sn.connector.v1",
43
+ platformId: "agent-world",
44
+ displayName: "Agent World",
45
+ family: "agent_network",
46
+ capabilities: [
47
+ { id: "feed.read" },
48
+ { id: "work.discover" },
49
+ { id: "task.claim" },
50
+ ],
51
+ runner: { kind: "declarative_http" },
52
+ credentials: [{ type: "api_key", required: true }],
53
+ sourceRefPolicy: { minSourceRefs: 1 },
54
+ },
55
+ ];
11
56
  export function createCliRuntimeDeps(overrides = {}) {
12
57
  const stateDb = overrides.stateDb ?? createStateDatabase();
13
58
  const observabilityDb = overrides.observabilityDb ?? createObservabilityDatabase();
@@ -26,6 +71,11 @@ export function createCliRuntimeDeps(overrides = {}) {
26
71
  stateDb,
27
72
  observabilityDb,
28
73
  });
74
+ const registry = overrides.registry ??
75
+ new DynamicConnectorRegistry({
76
+ builtInManifests: BUILT_IN_CONNECTOR_MANIFESTS,
77
+ snapshotStore: createRegistrySnapshotStore(),
78
+ });
29
79
  return {
30
80
  stateDb,
31
81
  observabilityDb,
@@ -34,6 +84,7 @@ export function createCliRuntimeDeps(overrides = {}) {
34
84
  actionBridge,
35
85
  runtimeRecorder,
36
86
  connectorExecutor,
87
+ registry,
37
88
  };
38
89
  }
39
90
  export function createCommandRouter(options = {}) {
@@ -47,6 +98,7 @@ export function createCommandRouter(options = {}) {
47
98
  workspaceRoot: process.cwd(),
48
99
  observabilityDb: runtime.observabilityDb,
49
100
  connectorExecutor: runtime.connectorExecutor,
101
+ registry: runtime.registry,
50
102
  });
51
103
  const commands = createCliCommands({
52
104
  readModels: runtime.readModels,
@@ -0,0 +1,11 @@
1
+ import type { ConnectorRequest, ExecutionPlan, RawAttempt } from "../../base/contract.js";
2
+ export interface AgentWorldApiClient {
3
+ readFeed(payload: Record<string, unknown>, apiKey: string): Promise<unknown>;
4
+ discoverWork(payload: Record<string, unknown>, apiKey: string): Promise<unknown>;
5
+ claimTask(payload: Record<string, unknown>, apiKey: string): Promise<unknown>;
6
+ }
7
+ export declare function createAgentWorldRunner(input: {
8
+ apiClient: AgentWorldApiClient;
9
+ }): {
10
+ run(plan: ExecutionPlan, request: ConnectorRequest): Promise<RawAttempt>;
11
+ };
@@ -0,0 +1,58 @@
1
+ export function createAgentWorldRunner(input) {
2
+ const { apiClient } = input;
3
+ return {
4
+ async run(plan, request) {
5
+ const started = Date.now();
6
+ try {
7
+ const apiKey = request.payload?.apiKey ?? "";
8
+ if (!apiKey) {
9
+ return {
10
+ platformId: request.platformId,
11
+ channel: plan.channel,
12
+ latencyMs: Date.now() - started,
13
+ success: false,
14
+ error: {
15
+ code: "auth_failure",
16
+ detail: "api_key_required_for_agent_world",
17
+ },
18
+ };
19
+ }
20
+ let result;
21
+ if (plan.intent === "feed.read") {
22
+ result = await apiClient.readFeed(request.payload, String(apiKey));
23
+ }
24
+ else if (plan.intent === "work.discover") {
25
+ result = await apiClient.discoverWork(request.payload, String(apiKey));
26
+ }
27
+ else if (plan.intent === "task.claim") {
28
+ result = await apiClient.claimTask(request.payload, String(apiKey));
29
+ }
30
+ else {
31
+ throw { code: "protocol_mismatch", detail: `unsupported agent-world intent: ${plan.intent}` };
32
+ }
33
+ return {
34
+ platformId: request.platformId,
35
+ channel: plan.channel,
36
+ latencyMs: Date.now() - started,
37
+ degraded: plan.channel === "skill",
38
+ success: true,
39
+ payload: {
40
+ capability: request.intent,
41
+ channel: plan.channel,
42
+ data: result,
43
+ },
44
+ };
45
+ }
46
+ catch (error) {
47
+ return {
48
+ platformId: request.platformId,
49
+ channel: plan.channel,
50
+ latencyMs: Date.now() - started,
51
+ degraded: plan.channel === "skill",
52
+ success: false,
53
+ error,
54
+ };
55
+ }
56
+ },
57
+ };
58
+ }
@@ -0,0 +1,2 @@
1
+ export { agentWorldManifest } from "./manifest.js";
2
+ export { createAgentWorldRunner, type AgentWorldApiClient } from "./adapter.js";
@@ -0,0 +1,2 @@
1
+ export { agentWorldManifest } from "./manifest.js";
2
+ export { createAgentWorldRunner } from "./adapter.js";
@@ -0,0 +1,2 @@
1
+ import type { ConnectorManifest } from "../../base/manifest.js";
2
+ export declare const agentWorldManifest: ConnectorManifest;
@@ -0,0 +1,7 @@
1
+ export const agentWorldManifest = {
2
+ platformId: "agent-world",
3
+ supportedCapabilities: ["feed.read", "work.discover", "task.claim"],
4
+ channelPriority: ["api_rest", "a2a", "skill"],
5
+ credentialTypes: ["api_key"],
6
+ degradedChannels: ["skill"],
7
+ };
@@ -5,8 +5,10 @@ import { createConnectorPolicyLayer } from "../base/policy-layer.js";
5
5
  import { InMemoryEffectCommitLedger } from "../base/execution-policy.js";
6
6
  import { moltbookManifest } from "../social-community/moltbook/manifest.js";
7
7
  import { evomapManifest } from "../agent-network/evomap/manifest.js";
8
+ import { agentWorldManifest } from "../agent-network/agent-world/manifest.js";
8
9
  import { createMoltbookApiClient } from "../social-community/moltbook/api-client.js";
9
10
  import { createMoltbookRunner } from "../social-community/moltbook/adapter.js";
11
+ import { createAgentWorldRunner } from "../agent-network/agent-world/adapter.js";
10
12
  import { ExecutionTelemetry } from "../../observability/services/execution-telemetry.js";
11
13
  import { createCredentialVault } from "../../storage/services/credential-vault.js";
12
14
  import { createCredentialRouteContextPort } from "./credential-route-context.js";
@@ -74,6 +76,52 @@ function createAdaptiveExecutionRunner(vault) {
74
76
  },
75
77
  };
76
78
  }
79
+ if (platformId === "agent-world") {
80
+ const baseUrl = process.env.SECOND_NATURE_AGENT_WORLD_BASE_URL;
81
+ if (!baseUrl) {
82
+ return {
83
+ platformId,
84
+ channel: request.preferredChannel ?? "api_rest",
85
+ latencyMs: Date.now() - started,
86
+ success: false,
87
+ error: {
88
+ code: "configuration_missing",
89
+ detail: "SECOND_NATURE_AGENT_WORLD_BASE_URL not set",
90
+ },
91
+ };
92
+ }
93
+ const runner = createAgentWorldRunner({
94
+ apiClient: {
95
+ async readFeed(payload, _apiKey) {
96
+ const resp = await fetch(`${baseUrl}/api/v1/feed`, {
97
+ headers: { "Authorization": `Bearer ${_apiKey}`, "Content-Type": "application/json" },
98
+ });
99
+ if (!resp.ok)
100
+ throw { code: "api_error", detail: `agent-world feed: ${resp.status}` };
101
+ return resp.json();
102
+ },
103
+ async discoverWork(payload, _apiKey) {
104
+ const resp = await fetch(`${baseUrl}/api/v1/work`, {
105
+ headers: { "Authorization": `Bearer ${_apiKey}`, "Content-Type": "application/json" },
106
+ });
107
+ if (!resp.ok)
108
+ throw { code: "api_error", detail: `agent-world work: ${resp.status}` };
109
+ return resp.json();
110
+ },
111
+ async claimTask(payload, _apiKey) {
112
+ const resp = await fetch(`${baseUrl}/api/v1/tasks/${payload.taskId ?? "unknown"}/claim`, {
113
+ method: "POST",
114
+ headers: { "Authorization": `Bearer ${_apiKey}`, "Content-Type": "application/json" },
115
+ body: JSON.stringify(payload),
116
+ });
117
+ if (!resp.ok)
118
+ throw { code: "api_error", detail: `agent-world claim: ${resp.status}` };
119
+ return resp.json();
120
+ },
121
+ },
122
+ });
123
+ return runner.run(_plan, request);
124
+ }
77
125
  return {
78
126
  platformId,
79
127
  channel: request.preferredChannel ?? "api_rest",
@@ -92,6 +140,7 @@ export function createConnectorExecutorAdapter(options) {
92
140
  const registry = new CapabilityContractRegistry();
93
141
  registry.register({ ...moltbookManifest });
94
142
  registry.register({ ...evomapManifest });
143
+ registry.register({ ...agentWorldManifest });
95
144
  const routeContextPort = createCredentialRouteContextPort(vault);
96
145
  const routePlanner = new ConnectorRoutePlanner(registry, routeContextPort, new ChannelHealthStore());
97
146
  const telemetry = new ExecutionTelemetry(options.observabilityDb);
@@ -47,6 +47,7 @@ export async function openWorkspaceOpsBridge(workspaceRoot) {
47
47
  state: stateDb,
48
48
  workspaceRoot: resolvedRoot,
49
49
  connectorExecutor: deps.connectorExecutor,
50
+ registry: deps.registry,
50
51
  });
51
52
  const commands = commandsMod.createCliCommands({
52
53
  readModels: deps.readModels,