@twsxtd/hapi-openclaw 0.1.6 → 0.1.8

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.
Files changed (2) hide show
  1. package/dist/index.js +55 -3
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -251,6 +251,8 @@ function stripReplyToCurrentPrefix(text) {
251
251
  // src/openclawAdapter.ts
252
252
  var CONVERSATION_TITLE = "OpenClaw";
253
253
  var RUN_COMPLETION_SETTLE_MS = 50;
254
+ var DEFAULT_PROVIDER = "openai";
255
+ var DEFAULT_MODEL = "gpt-5.4";
254
256
 
255
257
  class ConversationBusyError extends Error {
256
258
  constructor() {
@@ -275,6 +277,42 @@ function getStateNamespace(sessionKey, fallbackNamespace) {
275
277
  function delay(ms) {
276
278
  return new Promise((resolve) => setTimeout(resolve, ms));
277
279
  }
280
+ function readPrimaryModelRef(value) {
281
+ if (typeof value === "string" && value.trim().length > 0) {
282
+ return value.trim();
283
+ }
284
+ if (typeof value === "object" && value !== null && !Array.isArray(value)) {
285
+ const primary = value.primary;
286
+ return typeof primary === "string" && primary.trim().length > 0 ? primary.trim() : null;
287
+ }
288
+ return null;
289
+ }
290
+ function resolvePreferredModelRef(config, agentId) {
291
+ const agents = typeof config.agents === "object" && config.agents !== null ? config.agents : null;
292
+ const list = Array.isArray(agents?.list) ? agents.list : [];
293
+ const matchedAgent = list.find((entry) => {
294
+ return typeof entry === "object" && entry !== null && entry.id === agentId;
295
+ });
296
+ const defaults = typeof agents?.defaults === "object" && agents.defaults !== null ? agents.defaults : null;
297
+ const rawRef = readPrimaryModelRef(matchedAgent?.model) ?? readPrimaryModelRef(defaults?.model);
298
+ if (!rawRef) {
299
+ return {
300
+ provider: DEFAULT_PROVIDER,
301
+ model: DEFAULT_MODEL
302
+ };
303
+ }
304
+ const separatorIndex = rawRef.indexOf("/");
305
+ if (separatorIndex <= 0 || separatorIndex === rawRef.length - 1) {
306
+ return {
307
+ provider: DEFAULT_PROVIDER,
308
+ model: rawRef
309
+ };
310
+ }
311
+ return {
312
+ provider: rawRef.slice(0, separatorIndex).trim() || DEFAULT_PROVIDER,
313
+ model: rawRef.slice(separatorIndex + 1).trim() || DEFAULT_MODEL
314
+ };
315
+ }
278
316
  async function ensureSessionBinding(runtime, sessionKey, agentId) {
279
317
  const storePath = runtime.agent.session.resolveStorePath(undefined, { agentId });
280
318
  const store = runtime.agent.session.loadSessionStore(storePath);
@@ -302,11 +340,13 @@ class RealOpenClawAdapter {
302
340
  namespace;
303
341
  runtime;
304
342
  callbackClient;
343
+ logger;
305
344
  supportsApprovals = false;
306
- constructor(namespace, runtime, callbackClient) {
345
+ constructor(namespace, runtime, callbackClient, logger) {
307
346
  this.namespace = namespace;
308
347
  this.runtime = runtime;
309
348
  this.callbackClient = callbackClient;
349
+ this.logger = logger;
310
350
  }
311
351
  async ensureDefaultConversation(externalUserKey) {
312
352
  return {
@@ -322,6 +362,7 @@ class RealOpenClawAdapter {
322
362
  throw new ConversationBusyError;
323
363
  }
324
364
  const namespace = getStateNamespace(action.conversationId, this.namespace);
365
+ this.logger.info(`[${namespace}] hapi-openclaw send-message start conversation=${action.conversationId}`);
325
366
  await this.callbackClient.postEvent(createStateEvent({
326
367
  namespace,
327
368
  conversationId: action.conversationId,
@@ -335,7 +376,9 @@ class RealOpenClawAdapter {
335
376
  dir: this.runtime.agent.resolveAgentWorkspaceDir(config, agentId)
336
377
  })).dir;
337
378
  const agentDir = this.runtime.agent.resolveAgentDir(config, agentId);
379
+ const modelRef = resolvePreferredModelRef(config, agentId);
338
380
  const { sessionId, sessionFile } = await ensureSessionBinding(this.runtime, action.conversationId, agentId);
381
+ this.logger.info(`[${namespace}] hapi-openclaw runEmbeddedPiAgent sessionId=${sessionId} agentId=${agentId} ` + `provider=${modelRef.provider} model=${modelRef.model}`);
339
382
  const result = await this.runtime.agent.runEmbeddedPiAgent({
340
383
  sessionId,
341
384
  sessionKey: action.conversationId,
@@ -345,12 +388,15 @@ class RealOpenClawAdapter {
345
388
  config,
346
389
  agentId,
347
390
  prompt: action.text,
391
+ provider: modelRef.provider,
392
+ model: modelRef.model,
348
393
  timeoutMs: this.runtime.agent.resolveAgentTimeoutMs({ cfg: config }),
349
394
  runId: randomUUID(),
350
395
  trigger: "user"
351
396
  });
352
397
  const runError = result.meta.error?.message?.trim() || null;
353
398
  if (runError) {
399
+ this.logger.warn(`[${namespace}] hapi-openclaw run failed conversation=${action.conversationId}: ${runError}`);
354
400
  if (adapterState.finishRun(action.conversationId)) {
355
401
  await this.callbackClient.postEvent(createStateEvent({
356
402
  namespace,
@@ -361,6 +407,7 @@ class RealOpenClawAdapter {
361
407
  }
362
408
  return;
363
409
  }
410
+ this.logger.info(`[${namespace}] hapi-openclaw run completed conversation=${action.conversationId}` + (result.meta.finalAssistantVisibleText ? ` finalText=${JSON.stringify(result.meta.finalAssistantVisibleText)}` : ""));
364
411
  if (result.meta.finalAssistantVisibleText) {
365
412
  await delay(RUN_COMPLETION_SETTLE_MS);
366
413
  }
@@ -374,6 +421,7 @@ class RealOpenClawAdapter {
374
421
  }
375
422
  } catch (error2) {
376
423
  const message = error2 instanceof Error ? error2.message : "OpenClaw embedded run failed";
424
+ this.logger.error(`[${namespace}] hapi-openclaw send-message error conversation=${action.conversationId}: ${message}`);
377
425
  if (adapterState.finishRun(action.conversationId)) {
378
426
  await this.callbackClient.postEvent(createStateEvent({
379
427
  namespace,
@@ -2205,6 +2253,7 @@ function createPluginApp(deps) {
2205
2253
  retryAfterMs: null
2206
2254
  };
2207
2255
  deps.idempotencyCache.set(idempotencyKey, ack);
2256
+ deps.logger.info(`[${deps.namespace}] hapi-openclaw accepted send-message conversation=${body.conversationId} localMessageId=${body.localMessageId}`);
2208
2257
  queueMicrotask(() => {
2209
2258
  deps.runtime.sendMessage({
2210
2259
  kind: "send-message",
@@ -2215,8 +2264,10 @@ function createPluginApp(deps) {
2215
2264
  await dispatchMaybeEvents(deps.callbackClient, events);
2216
2265
  }).catch((error2) => {
2217
2266
  if (error2 instanceof ConversationBusyError) {
2267
+ deps.logger.warn(`[${deps.namespace}] hapi-openclaw conversation busy conversation=${body.conversationId}`);
2218
2268
  return;
2219
2269
  }
2270
+ deps.logger.error(`[${deps.namespace}] hapi-openclaw send-message task failed conversation=${body.conversationId}: ` + (error2 instanceof Error ? error2.message : String(error2)));
2220
2271
  });
2221
2272
  });
2222
2273
  return c.json(ack);
@@ -2311,7 +2362,7 @@ function resolveRegisteredPluginConfig(api) {
2311
2362
  function registerPluginRoutes(api) {
2312
2363
  const config = resolveRegisteredPluginConfig(api);
2313
2364
  const callbackClient = new HapiCallbackClient(config.hapiBaseUrl, config.sharedSecret);
2314
- const runtime = new RealOpenClawAdapter(config.namespace, api.runtime, callbackClient);
2365
+ const runtime = new RealOpenClawAdapter(config.namespace, api.runtime, callbackClient, api.logger);
2315
2366
  const app = createPluginApp({
2316
2367
  sharedSecret: config.sharedSecret,
2317
2368
  namespace: config.namespace,
@@ -2319,7 +2370,8 @@ function registerPluginRoutes(api) {
2319
2370
  runtime,
2320
2371
  idempotencyCache: new Map,
2321
2372
  prototypeCaptureSessionKey: config.prototypeCaptureSessionKey,
2322
- prototypeCaptureFileName: config.prototypeCaptureFileName
2373
+ prototypeCaptureFileName: config.prototypeCaptureFileName,
2374
+ logger: api.logger
2323
2375
  });
2324
2376
  api.registerHttpRoute({
2325
2377
  path: "/hapi",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@twsxtd/hapi-openclaw",
3
- "version": "0.1.6",
3
+ "version": "0.1.8",
4
4
  "description": "Native OpenClaw plugin that bridges HAPI to the OpenClaw Gateway route surface.",
5
5
  "license": "AGPL-3.0-only",
6
6
  "type": "module",