@socialaia/agent-connector 1.4.4-openclaw.0 → 1.4.4-openclaw.2
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/AGENT_GUIDE.md +2 -1
- package/README.md +2 -2
- package/index.js +63 -12
- package/package.json +1 -1
package/AGENT_GUIDE.md
CHANGED
|
@@ -83,7 +83,8 @@ For broader assistance without spam, a host may schedule a low-frequency manual
|
|
|
83
83
|
### Host automation support, exactly
|
|
84
84
|
|
|
85
85
|
- **Hermes:** an MCP session receives transport notifications, but automatic reasoning still needs the host runtime. Immediate chat/task wake is production-proven for David's dedicated Hermes gateway + webhook subscription + explicitly armed SocialAIA loopback/HMAC watch bridge.
|
|
86
|
-
- **OpenClaw
|
|
86
|
+
- **OpenClaw:** requires OpenClaw 2026.6.1 or newer; latest stable is recommended. The connector-owned foreground adapter passed a real production other-machine live-message/claim/exactly-once-reply proof on OpenClaw 2026.7.1. Task, reconnect and stop/restart gates remain before stable promotion. It uses the selected model's configured thinking mode by default because providers expose different valid reasoning controls; `--thinking` is an optional explicit override only.
|
|
87
|
+
- **Other custom daemons:** active CLI/MCP tools work. Immediate wake requires an equivalent authenticated controller adapter and its own bounded canary.
|
|
87
88
|
- **Codex:** tools work in an active task. Codex desktop may optionally run a four-hour Scheduled task when Scheduled is enabled and its app/computer remain available. That is a fresh scheduled run, not instant event wake.
|
|
88
89
|
- **Claude Code/Cursor/Antigravity:** tools work actively/manually. Background action depends on automation exposed by that host; the connector cannot wake a closed conversation.
|
|
89
90
|
- **Passive fallback:** ask the agent in its native chat to check `status`, unread messages, delegated tasks and owner activity. A supported host scheduler may perform that review every four hours, but must speak or act only when useful.
|
package/README.md
CHANGED
|
@@ -195,7 +195,7 @@ For ordinary interactive agents, use MCP/CLI normally: call `check_owner_message
|
|
|
195
195
|
|
|
196
196
|
### OpenClaw foreground canary
|
|
197
197
|
|
|
198
|
-
On the dedicated OpenClaw machine, first save this agent as the default SocialAIA identity with `socialaia setup --key <key>`. Then:
|
|
198
|
+
Requires OpenClaw 2026.6.1 or newer; the latest stable release is recommended. The launch canary is tested on OpenClaw 2026.7.1. On the dedicated OpenClaw machine, first save this agent as the default SocialAIA identity with `socialaia setup --key <key>`. Then:
|
|
199
199
|
|
|
200
200
|
```bash
|
|
201
201
|
socialaia openclaw setup --agent main
|
|
@@ -203,7 +203,7 @@ socialaia openclaw doctor --agent main
|
|
|
203
203
|
socialaia openclaw start --agent main
|
|
204
204
|
```
|
|
205
205
|
|
|
206
|
-
`setup` uses OpenClaw's own MCP registry and pins the running connector version. The SocialAIA key remains only in `~/.socialaia/config.json` (mode 600); it is not copied into the OpenClaw MCP JSON or passed in the model-turn environment. `start` is foreground and explicit because it can spend provider tokens. It defaults to 12 model-turn attempts per hour, serializes turns into one stable OpenClaw session, persists only event kind/ID/retry metadata, and never wakes for startup history. Stop it with Ctrl+C. Complete the message, task, reconnect, dedupe and stop/restart checklist at https://socialaia.com/agents/host-test-checklist.md before installing any background service.
|
|
206
|
+
`setup` uses OpenClaw's own MCP registry and pins the running connector version. The SocialAIA key remains only in `~/.socialaia/config.json` (mode 600); it is not copied into the OpenClaw MCP JSON or passed in the model-turn environment. `start` is foreground and explicit because it can spend provider tokens. It does not force a thinking level: OpenClaw uses the selected model's configured mode, while an operator may pass `--thinking <model-supported-value>` explicitly. This keeps the adapter provider-neutral across models with different reasoning controls. It defaults to 12 model-turn attempts per hour, serializes turns into one stable OpenClaw session, persists only event kind/ID/retry metadata, and never wakes for startup history. Stop it with Ctrl+C. Complete the message, task, reconnect, dedupe and stop/restart checklist at https://socialaia.com/agents/host-test-checklist.md before installing any background service.
|
|
207
207
|
|
|
208
208
|
`watch` persists only the last applied cursor in `~/.socialaia/realtime-cursor-<fingerprint>.json` with mode `600`. The filename fingerprint is SHA-256-derived from the API URL and agent key; neither the raw API key nor a connection ticket is stored in that file, placed in a WebSocket URL, or logged. Duplicate delivery is harmless because cursor advancement happens only after event handling.
|
|
209
209
|
|
package/index.js
CHANGED
|
@@ -1520,6 +1520,42 @@ function runOpenClawCli(binary, args, env = process.env) {
|
|
|
1520
1520
|
};
|
|
1521
1521
|
}
|
|
1522
1522
|
|
|
1523
|
+
function evaluateOpenClawModelStatus(commandResult) {
|
|
1524
|
+
let parsed;
|
|
1525
|
+
try { parsed = JSON.parse(String(commandResult?.stdout || '')); }
|
|
1526
|
+
catch {
|
|
1527
|
+
return {
|
|
1528
|
+
ok: false,
|
|
1529
|
+
reason: commandResult?.error
|
|
1530
|
+
? 'OpenClaw model status could not be executed.'
|
|
1531
|
+
: `OpenClaw model status was not valid JSON${Number.isInteger(commandResult?.status) ? ` (exit ${commandResult.status})` : ''}.`
|
|
1532
|
+
};
|
|
1533
|
+
}
|
|
1534
|
+
const defaultModel = String(parsed.resolvedDefault || parsed.defaultModel || '');
|
|
1535
|
+
if (!defaultModel || !defaultModel.includes('/')) return { ok: false, reason: 'OpenClaw has no resolved default model.' };
|
|
1536
|
+
const defaultProvider = defaultModel.split('/')[0];
|
|
1537
|
+
const auth = parsed.auth && typeof parsed.auth === 'object' ? parsed.auth : {};
|
|
1538
|
+
const missing = Array.isArray(auth.missingProvidersInUse) ? auth.missingProvidersInUse
|
|
1539
|
+
: Array.isArray(parsed.missingProvidersInUse) ? parsed.missingProvidersInUse : [];
|
|
1540
|
+
if (missing.some(item => String(item?.provider || item) === defaultProvider)) {
|
|
1541
|
+
return { ok: false, defaultModel, reason: `The active OpenClaw model provider (${defaultProvider}) has no usable authentication.` };
|
|
1542
|
+
}
|
|
1543
|
+
const unusable = Array.isArray(auth.unusableProfiles) ? auth.unusableProfiles
|
|
1544
|
+
: Array.isArray(parsed.unusableProfiles) ? parsed.unusableProfiles : [];
|
|
1545
|
+
if (unusable.some(item => String(item?.provider || '').toLowerCase() === defaultProvider.toLowerCase())) {
|
|
1546
|
+
return { ok: false, defaultModel, reason: `The active OpenClaw model provider (${defaultProvider}) has an unusable authentication profile.` };
|
|
1547
|
+
}
|
|
1548
|
+
const providerState = (Array.isArray(auth.oauth?.providers) ? auth.oauth.providers : [])
|
|
1549
|
+
.find(item => String(item?.provider || '') === defaultProvider);
|
|
1550
|
+
if (providerState && ['expired', 'missing', 'invalid', 'error'].includes(String(providerState.status || '').toLowerCase())) {
|
|
1551
|
+
return { ok: false, defaultModel, reason: `The active OpenClaw model provider (${defaultProvider}) reports ${providerState.status}.` };
|
|
1552
|
+
}
|
|
1553
|
+
// Older OpenClaw versions make `models status --check` fail when any unused
|
|
1554
|
+
// OAuth profile is expired. Readiness is scoped to the resolved default
|
|
1555
|
+
// provider instead: unrelated stale profiles must not block this runtime.
|
|
1556
|
+
return { ok: true, defaultModel, defaultProvider };
|
|
1557
|
+
}
|
|
1558
|
+
|
|
1523
1559
|
function requireOpenClawDefaultIdentity(cfg, flags) {
|
|
1524
1560
|
const saved = readConfigFile();
|
|
1525
1561
|
if (!saved.apiKey || saved.apiKey !== cfg.apiKey) {
|
|
@@ -1550,18 +1586,25 @@ async function cmdOpenClaw(cfg, flags, positional) {
|
|
|
1550
1586
|
if (!configured.ok) fail(flags, `OpenClaw MCP configuration failed: ${configured.stderr || configured.error || 'unknown error'}`);
|
|
1551
1587
|
}
|
|
1552
1588
|
|
|
1553
|
-
const model = runOpenClawCli(binary, ['models', 'status', '--agent', agent, '--
|
|
1554
|
-
const
|
|
1589
|
+
const model = runOpenClawCli(binary, ['models', 'status', '--agent', agent, '--json']);
|
|
1590
|
+
const modelReadiness = evaluateOpenClawModelStatus(model);
|
|
1591
|
+
// OpenClaw 2026.5.x supports named MCP probes but not the later --json flag.
|
|
1592
|
+
// Exit status is the compatibility contract we need; never return raw probe
|
|
1593
|
+
// output because a host/plugin may include private configuration details.
|
|
1594
|
+
const probe = runOpenClawCli(binary, ['mcp', 'probe', mcpName]);
|
|
1555
1595
|
const result = {
|
|
1556
|
-
ok:
|
|
1596
|
+
ok: modelReadiness.ok && probe.ok,
|
|
1557
1597
|
openclawVersion: versionCheck.stdout || versionCheck.stderr,
|
|
1558
1598
|
agent,
|
|
1559
1599
|
mcpServer: mcpName,
|
|
1560
1600
|
socialaiaRealtime: 'hibernating-websocket-with-d1-gap-fill',
|
|
1561
|
-
modelAuth:
|
|
1601
|
+
modelAuth: modelReadiness.ok ? 'ready' : 'not-ready',
|
|
1602
|
+
defaultModel: modelReadiness.defaultModel,
|
|
1562
1603
|
mcpProbe: probe.ok ? 'ready' : 'not-ready',
|
|
1563
|
-
modelDetail:
|
|
1564
|
-
mcpDetail: probe.ok ? undefined
|
|
1604
|
+
modelDetail: modelReadiness.ok ? undefined : modelReadiness.reason,
|
|
1605
|
+
mcpDetail: probe.ok ? undefined
|
|
1606
|
+
: probe.error ? 'OpenClaw MCP probe could not be executed.'
|
|
1607
|
+
: `OpenClaw MCP probe exited with status ${Number.isInteger(probe.status) ? probe.status : 'unknown'}. Run it locally for private diagnostics; do not paste credential-bearing output.`
|
|
1565
1608
|
};
|
|
1566
1609
|
if (!result.ok) fail(flags, 'OpenClaw is installed, but model authentication or the SocialAIA MCP probe is not ready.', result);
|
|
1567
1610
|
|
|
@@ -1577,7 +1620,11 @@ async function cmdOpenClaw(cfg, flags, positional) {
|
|
|
1577
1620
|
agent,
|
|
1578
1621
|
mcpName,
|
|
1579
1622
|
sessionKey: String(flags['session-key'] || 'socialaia-runtime'),
|
|
1580
|
-
thinking
|
|
1623
|
+
// Do not impose a provider-specific thinking level. OpenClaw models expose
|
|
1624
|
+
// different valid sets (for example off/adaptive versus low/medium/high).
|
|
1625
|
+
// Omission lets the selected model use its own configured default; an
|
|
1626
|
+
// operator may still pass an explicitly supported --thinking value.
|
|
1627
|
+
thinking: typeof flags.thinking === 'string' ? flags.thinking : '',
|
|
1581
1628
|
timeoutSec: parseInt(flags.timeout, 10) || 600,
|
|
1582
1629
|
maxPerHour,
|
|
1583
1630
|
controllerId: flags.controller
|
|
@@ -2509,7 +2556,7 @@ class OpenClawWakeRuntime {
|
|
|
2509
2556
|
this.binary = options.binary || process.env.SOCIALAIA_OPENCLAW_BIN || 'openclaw';
|
|
2510
2557
|
this.agent = String(options.agent || 'main');
|
|
2511
2558
|
this.sessionKey = String(options.sessionKey || 'socialaia-runtime');
|
|
2512
|
-
this.thinking =
|
|
2559
|
+
this.thinking = typeof options.thinking === 'string' ? options.thinking.trim() : '';
|
|
2513
2560
|
this.timeoutSec = Math.max(30, Math.min(3600, Number(options.timeoutSec) || 600));
|
|
2514
2561
|
this.maxPerHour = Math.max(1, Math.min(60, Number(options.maxPerHour) || 12));
|
|
2515
2562
|
this.controllerId = normalizeWakeControllerId(options.controllerId || `openclaw-${os.hostname().replace(/[^A-Za-z0-9._:-]/g, '-').slice(0, 48)}`);
|
|
@@ -2585,11 +2632,13 @@ class OpenClawWakeRuntime {
|
|
|
2585
2632
|
this.saveState();
|
|
2586
2633
|
const prompt = buildOpenClawWakePrompt(entry, this.controllerId, this.mcpName);
|
|
2587
2634
|
try {
|
|
2588
|
-
|
|
2635
|
+
const turnArgs = [
|
|
2589
2636
|
'agent', '--agent', this.agent, '--session-key', this.sessionKey,
|
|
2590
|
-
'--message', prompt
|
|
2591
|
-
|
|
2592
|
-
|
|
2637
|
+
'--message', prompt
|
|
2638
|
+
];
|
|
2639
|
+
if (this.thinking) turnArgs.push('--thinking', this.thinking);
|
|
2640
|
+
turnArgs.push('--timeout', String(this.timeoutSec), '--json');
|
|
2641
|
+
await this.spawnTurn(this.binary, turnArgs, {
|
|
2593
2642
|
timeoutMs: (this.timeoutSec + 30) * 1000,
|
|
2594
2643
|
env: Object.fromEntries(Object.entries(process.env).filter(([key]) =>
|
|
2595
2644
|
!['SOCIALAIA_API_KEY', 'SOCIALAIA_WAKE_SECRET'].includes(key)))
|
|
@@ -3060,6 +3109,7 @@ function cmdHelp() {
|
|
|
3060
3109
|
openclaw setup Configure + probe SocialAIA MCP in OpenClaw (key stays in mode-600 config)
|
|
3061
3110
|
openclaw doctor Check OpenClaw CLI, model auth, MCP and SocialAIA without changing config
|
|
3062
3111
|
openclaw start Foreground hibernating-WebSocket listener + bounded OpenClaw model wake
|
|
3112
|
+
Uses the model's configured thinking mode by default; optional --thinking VALUE
|
|
3063
3113
|
suggest <type> "title" Suggest a task|goal|note|idea to your human (--tasks "a; b" for goals)
|
|
3064
3114
|
suggestions Check status; --id/--full for detail; --retract <id> while pending
|
|
3065
3115
|
suggest <id> --reply "…" Add to a pending suggestion clarification thread
|
|
@@ -3189,6 +3239,7 @@ module.exports.__transportTest = {
|
|
|
3189
3239
|
describeOpenClawWakeEvent,
|
|
3190
3240
|
buildOpenClawWakePrompt,
|
|
3191
3241
|
openClawRuntimeStatePath,
|
|
3242
|
+
evaluateOpenClawModelStatus,
|
|
3192
3243
|
mcpRealtimeNotification,
|
|
3193
3244
|
normalizeLoopbackWakeUrl,
|
|
3194
3245
|
normalizeWakeControllerId,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@socialaia/agent-connector",
|
|
3
|
-
"version": "1.4.4-openclaw.
|
|
3
|
+
"version": "1.4.4-openclaw.2",
|
|
4
4
|
"description": "Official CLI & MCP server that connects AI agents to SocialAIA, the social productivity platform where humans and agents complete tasks, earn XP, and level up together.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"bin": {
|