fix: make optional services non-blocking

This commit is contained in:
owo
2026-09-15 21:37:16 +08:00
parent f3f6a3ebaf
commit e748132541
6 changed files with 48 additions and 8 deletions
+19 -1
View File
@@ -1345,7 +1345,25 @@ export class TelegramBridge {
}
// ── ask_user_question: TG answering via dual-path race with the UI ──
userQuestions() {
return this.ctx.userQuestions;
const ctx = this.ctx;
if (typeof ctx.get === 'function') {
try {
const service = ctx.get('userQuestions');
if (service)
return service;
}
catch {
// Continue to the plain-object fallback used by tests and simple hosts.
}
}
try {
return Object.prototype.hasOwnProperty.call(ctx, 'userQuestions')
? ctx.userQuestions
: undefined;
}
catch {
return undefined;
}
}
/**
* Wrap the UI provider's ask() so Telegram gets a parallel answer path.
+1 -1
View File
@@ -1,7 +1,7 @@
import type { Context } from '@deepseek-ai/cordis';
import Schema from '@deepseek-ai/schemastery';
export declare const name = "dsh-telegram-channel";
/** agents: followup; apiProxy: workspace/session catalog + /model; userQuestions: TG answer hook (Cordis requires inject). */
/** agents: followup; apiProxy and userQuestions are optional runtime services. */
export declare const inject: string[];
export interface TelegramChannelConfig {
token?: string;
+2 -2
View File
@@ -1,8 +1,8 @@
import Schema from '@deepseek-ai/schemastery';
import { TelegramBridge } from './bridge.js';
export const name = 'dsh-telegram-channel';
/** agents: followup; apiProxy: workspace/session catalog + /model; userQuestions: TG answer hook (Cordis requires inject). */
export const inject = ['agents', 'apiProxy', 'userQuestions'];
/** agents: followup; apiProxy and userQuestions are optional runtime services. */
export const inject = ['agents'];
export const Config = Schema.object({
token: Schema.string().default(''),
allowedUserIds: Schema.array(Schema.number()).default([]),
+19 -1
View File
@@ -1521,7 +1521,25 @@ export class TelegramBridge {
// ── ask_user_question: TG answering via dual-path race with the UI ──
private userQuestions(): UserQuestionsServiceLike | undefined {
return (this.ctx as unknown as { userQuestions?: UserQuestionsServiceLike }).userQuestions
const ctx = this.ctx as Context & {
get?: (name: string, strict?: boolean) => unknown
userQuestions?: UserQuestionsServiceLike
}
if (typeof ctx.get === 'function') {
try {
const service = ctx.get('userQuestions') as UserQuestionsServiceLike | undefined
if (service) return service
} catch {
// Continue to the plain-object fallback used by tests and simple hosts.
}
}
try {
return Object.prototype.hasOwnProperty.call(ctx, 'userQuestions')
? ctx.userQuestions
: undefined
} catch {
return undefined
}
}
/**
+2 -2
View File
@@ -3,8 +3,8 @@ import Schema from '@deepseek-ai/schemastery'
import { TelegramBridge } from './bridge.js'
export const name = 'dsh-telegram-channel'
/** agents: followup; apiProxy: workspace/session catalog + /model; userQuestions: TG answer hook (Cordis requires inject). */
export const inject = ['agents', 'apiProxy', 'userQuestions']
/** agents: followup; apiProxy and userQuestions are optional runtime services. */
export const inject = ['agents']
export interface TelegramChannelConfig {
token?: string
+5 -1
View File
@@ -1,6 +1,10 @@
import assert from 'node:assert/strict'
import test from 'node:test'
import { apply } from '../src/index.ts'
import { apply, inject } from '../src/index.ts'
test('optional host services are not hard Cordis dependencies', () => {
assert.deepEqual(inject, ['agents'])
})
test('apply without token does not throw and does not start effect', () => {
const effects: string[] = []