mirror of
https://github.com/qwibitai/nanoclaw.git
synced 2026-07-09 18:57:08 +08:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| af0d7c6153 |
+3
-3
@@ -20,7 +20,7 @@ import {
|
||||
markDeliveryFailed,
|
||||
migrateDeliveredTable,
|
||||
} from './db/session-db.js';
|
||||
import { guard, type GuardedAction, type Unguarded } from './guard/index.js';
|
||||
import { guard, isUnguarded, type GuardedAction, type Unguarded } from './guard/index.js';
|
||||
import { log } from './log.js';
|
||||
import { normalizeOptions } from './channels/ask-question.js';
|
||||
import { clearOutbox, openInboundDb, openOutboundDb, readOutboxFiles } from './session-manager.js';
|
||||
@@ -438,7 +438,7 @@ type DeliveryEntry =
|
||||
const deliveryActions = new Map<string, DeliveryEntry>();
|
||||
|
||||
function isUnguardedEntry(entry: DeliveryEntry): entry is Extract<DeliveryEntry, { guard: Unguarded }> {
|
||||
return 'reason' in entry.guard;
|
||||
return isUnguarded(entry.guard);
|
||||
}
|
||||
|
||||
export function registerDeliveryAction(action: string, handler: DeliveryActionHandler, unguardedDecl: Unguarded): void;
|
||||
@@ -455,7 +455,7 @@ export function registerDeliveryAction(
|
||||
// skill that wants to extend a guarded action must compose at the
|
||||
// module's exported functions instead, or re-register with a guard spec
|
||||
// of its own.
|
||||
if ('reason' in guardDecl && !isUnguardedEntry(existing)) {
|
||||
if (isUnguarded(guardDecl) && !isUnguardedEntry(existing)) {
|
||||
throw new Error(
|
||||
`delivery action "${action}" is guard-wrapped; re-registering it without a guard spec would disarm the guard`,
|
||||
);
|
||||
|
||||
@@ -20,6 +20,7 @@ export {
|
||||
ALLOW,
|
||||
DENY,
|
||||
HOLD,
|
||||
isUnguarded,
|
||||
unguarded,
|
||||
type GuardActor,
|
||||
type GuardDecision,
|
||||
|
||||
+12
-2
@@ -31,7 +31,7 @@ export interface GuardInput {
|
||||
grant?: PendingApproval | null;
|
||||
}
|
||||
|
||||
declare const unguardedBrand: unique symbol;
|
||||
const unguardedBrand = Symbol('unguarded');
|
||||
/**
|
||||
* A registration that deliberately carries no guard. Omission is not
|
||||
* representable — every registry requires either a guard spec or this
|
||||
@@ -42,7 +42,17 @@ declare const unguardedBrand: unique symbol;
|
||||
export type Unguarded = { readonly reason: string; readonly [unguardedBrand]: true };
|
||||
|
||||
export function unguarded(reason: string): Unguarded {
|
||||
return Object.freeze({ reason }) as Unguarded;
|
||||
return Object.freeze({ reason, [unguardedBrand]: true as const });
|
||||
}
|
||||
|
||||
/**
|
||||
* The one runtime discriminator for guard declarations. The brand symbol is
|
||||
* module-private, so `unguarded()` is the only mint — a look-alike
|
||||
* `{ reason }` object (or a guard spec that someday grows a `reason` field)
|
||||
* doesn't pass.
|
||||
*/
|
||||
export function isUnguarded(decl: object): decl is Unguarded {
|
||||
return unguardedBrand in decl;
|
||||
}
|
||||
|
||||
export type GuardDecision =
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
* unguarded must declare so with `unguarded(<reason>)`, at the registration
|
||||
* site, in the diff that adds it.
|
||||
*/
|
||||
import { guard, type GuardActor, type GuardedAction, type Unguarded } from './guard/index.js';
|
||||
import { guard, isUnguarded, type GuardActor, type GuardedAction, type Unguarded } from './guard/index.js';
|
||||
import { log } from './log.js';
|
||||
|
||||
export interface ResponsePayload {
|
||||
@@ -50,7 +50,7 @@ function responseActor(payload: ResponsePayload): GuardActor {
|
||||
}
|
||||
|
||||
export function registerResponseHandler(handler: ResponseHandler, guardDecl: ResponseGuardSpec | Unguarded): void {
|
||||
if ('reason' in guardDecl) {
|
||||
if (isUnguarded(guardDecl)) {
|
||||
// Explicitly declared unguarded — the carried reason is the reviewable record.
|
||||
responseHandlers.push(handler);
|
||||
return;
|
||||
|
||||
+2
-2
@@ -20,7 +20,7 @@
|
||||
import { getChannelAdapter } from './channels/channel-registry.js';
|
||||
import { gateCommand } from './command-gate.js';
|
||||
import { getAgentGroup } from './db/agent-groups.js';
|
||||
import { guard, type GuardActor, type GuardedAction, type Unguarded } from './guard/index.js';
|
||||
import { guard, isUnguarded, type GuardActor, type GuardedAction, type Unguarded } from './guard/index.js';
|
||||
import { recordDroppedMessage } from './db/dropped-messages.js';
|
||||
import {
|
||||
createMessagingGroup,
|
||||
@@ -145,7 +145,7 @@ export function registerMessageInterceptor(
|
||||
fn: MessageInterceptorFn,
|
||||
guardDecl: InterceptorGuardSpec | Unguarded,
|
||||
): void {
|
||||
if ('reason' in guardDecl) {
|
||||
if (isUnguarded(guardDecl)) {
|
||||
// Explicitly declared unguarded — the carried reason is the reviewable record.
|
||||
messageInterceptors.push(fn);
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user