style: apply prettier formatting to touched files
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -9,10 +9,7 @@
|
|||||||
*/
|
*/
|
||||||
import { getDb, hasTable } from './db/connection.js';
|
import { getDb, hasTable } from './db/connection.js';
|
||||||
|
|
||||||
export type GateResult =
|
export type GateResult = { action: 'pass' } | { action: 'filter' } | { action: 'deny'; command: string };
|
||||||
| { action: 'pass' }
|
|
||||||
| { action: 'filter' }
|
|
||||||
| { action: 'deny'; command: string };
|
|
||||||
|
|
||||||
const FILTERED_COMMANDS = new Set(['/help', '/login', '/logout', '/doctor', '/config', '/remote-control']);
|
const FILTERED_COMMANDS = new Set(['/help', '/login', '/logout', '/doctor', '/config', '/remote-control']);
|
||||||
const ADMIN_COMMANDS = new Set(['/clear', '/compact', '/context', '/cost', '/files']);
|
const ADMIN_COMMANDS = new Set(['/clear', '/compact', '/context', '/cost', '/files']);
|
||||||
@@ -23,11 +20,7 @@ const ADMIN_COMMANDS = new Set(['/clear', '/compact', '/context', '/cost', '/fil
|
|||||||
* 'filter' for silently-dropped commands, 'deny' for unauthorized
|
* 'filter' for silently-dropped commands, 'deny' for unauthorized
|
||||||
* admin commands.
|
* admin commands.
|
||||||
*/
|
*/
|
||||||
export function gateCommand(
|
export function gateCommand(content: string, userId: string | null, agentGroupId: string): GateResult {
|
||||||
content: string,
|
|
||||||
userId: string | null,
|
|
||||||
agentGroupId: string,
|
|
||||||
): GateResult {
|
|
||||||
let text: string;
|
let text: string;
|
||||||
try {
|
try {
|
||||||
const parsed = JSON.parse(content);
|
const parsed = JSON.parse(content);
|
||||||
|
|||||||
@@ -110,7 +110,15 @@ async function spawnContainer(session: Session): Promise<void> {
|
|||||||
// OneCLI agent identifier is always the agent group id — stable across
|
// OneCLI agent identifier is always the agent group id — stable across
|
||||||
// sessions and reversible via getAgentGroup() for approval routing.
|
// sessions and reversible via getAgentGroup() for approval routing.
|
||||||
const agentIdentifier = agentGroup.id;
|
const agentIdentifier = agentGroup.id;
|
||||||
const args = await buildContainerArgs(mounts, containerName, agentGroup, containerConfig, provider, contribution, agentIdentifier);
|
const args = await buildContainerArgs(
|
||||||
|
mounts,
|
||||||
|
containerName,
|
||||||
|
agentGroup,
|
||||||
|
containerConfig,
|
||||||
|
provider,
|
||||||
|
contribution,
|
||||||
|
agentIdentifier,
|
||||||
|
);
|
||||||
|
|
||||||
log.info('Spawning container', { sessionId: session.id, agentGroup: agentGroup.name, containerName });
|
log.info('Spawning container', { sessionId: session.id, agentGroup: agentGroup.name, containerName });
|
||||||
|
|
||||||
@@ -263,10 +271,7 @@ function buildMounts(
|
|||||||
* selection. Each symlink points to a container path (/app/skills/<name>)
|
* selection. Each symlink points to a container path (/app/skills/<name>)
|
||||||
* so it's dangling on the host but valid inside the container.
|
* so it's dangling on the host but valid inside the container.
|
||||||
*/
|
*/
|
||||||
function syncSkillSymlinks(
|
function syncSkillSymlinks(claudeDir: string, containerConfig: import('./container-config.js').ContainerConfig): void {
|
||||||
claudeDir: string,
|
|
||||||
containerConfig: import('./container-config.js').ContainerConfig,
|
|
||||||
): void {
|
|
||||||
const skillsDir = path.join(claudeDir, 'skills');
|
const skillsDir = path.join(claudeDir, 'skills');
|
||||||
if (!fs.existsSync(skillsDir)) {
|
if (!fs.existsSync(skillsDir)) {
|
||||||
fs.mkdirSync(skillsDir, { recursive: true });
|
fs.mkdirSync(skillsDir, { recursive: true });
|
||||||
|
|||||||
@@ -75,7 +75,9 @@ export const migration010: Migration = {
|
|||||||
`);
|
`);
|
||||||
|
|
||||||
// Backfill existing rows in JS (parsing JSON per-row is painful in pure SQL).
|
// Backfill existing rows in JS (parsing JSON per-row is painful in pure SQL).
|
||||||
const rows = db.prepare('SELECT id, trigger_rules, response_scope FROM messaging_group_agents').all() as LegacyRow[];
|
const rows = db
|
||||||
|
.prepare('SELECT id, trigger_rules, response_scope FROM messaging_group_agents')
|
||||||
|
.all() as LegacyRow[];
|
||||||
const update = db.prepare(
|
const update = db.prepare(
|
||||||
`UPDATE messaging_group_agents
|
`UPDATE messaging_group_agents
|
||||||
SET engage_mode = ?,
|
SET engage_mode = ?,
|
||||||
|
|||||||
@@ -96,7 +96,9 @@ async function handleRegisteredApproval(
|
|||||||
log.info('Approval handled', { approvalId: approval.approval_id, action: approval.action, userId });
|
log.info('Approval handled', { approvalId: approval.approval_id, action: approval.action, userId });
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
log.error('Approval handler threw', { approvalId: approval.approval_id, action: approval.action, err });
|
log.error('Approval handler threw', { approvalId: approval.approval_id, action: approval.action, err });
|
||||||
notify(`Your ${approval.action} was approved, but applying it failed: ${err instanceof Error ? err.message : String(err)}.`);
|
notify(
|
||||||
|
`Your ${approval.action} was approved, but applying it failed: ${err instanceof Error ? err.message : String(err)}.`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
deletePendingApproval(approval.approval_id);
|
deletePendingApproval(approval.approval_id);
|
||||||
|
|||||||
@@ -22,4 +22,3 @@ import './scheduling/index.js';
|
|||||||
import './permissions/index.js';
|
import './permissions/index.js';
|
||||||
import './agent-to-agent/index.js';
|
import './agent-to-agent/index.js';
|
||||||
import './self-mod/index.js';
|
import './self-mod/index.js';
|
||||||
|
|
||||||
|
|||||||
@@ -46,7 +46,11 @@ async function handleInteractiveResponse(payload: ResponsePayload): Promise<bool
|
|||||||
});
|
});
|
||||||
|
|
||||||
deletePendingQuestion(payload.questionId);
|
deletePendingQuestion(payload.questionId);
|
||||||
log.info('Question response routed', { questionId: payload.questionId, selectedOption: payload.value, sessionId: session.id });
|
log.info('Question response routed', {
|
||||||
|
questionId: payload.questionId,
|
||||||
|
selectedOption: payload.value,
|
||||||
|
sessionId: session.id,
|
||||||
|
});
|
||||||
|
|
||||||
await wakeContainer(session);
|
await wakeContainer(session);
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -197,9 +197,9 @@ describe('unknown-channel registration flow', () => {
|
|||||||
await new Promise((r) => setTimeout(r, 10));
|
await new Promise((r) => setTimeout(r, 10));
|
||||||
|
|
||||||
const { getDb } = await import('../../db/connection.js');
|
const { getDb } = await import('../../db/connection.js');
|
||||||
const pending = getDb()
|
const pending = getDb().prepare('SELECT messaging_group_id FROM pending_channel_approvals').get() as {
|
||||||
.prepare('SELECT messaging_group_id FROM pending_channel_approvals')
|
messaging_group_id: string;
|
||||||
.get() as { messaging_group_id: string };
|
};
|
||||||
expect(pending).toBeDefined();
|
expect(pending).toBeDefined();
|
||||||
|
|
||||||
// Owner clicks approve.
|
// Owner clicks approve.
|
||||||
@@ -240,9 +240,8 @@ describe('unknown-channel registration flow', () => {
|
|||||||
expect(member).toBeDefined();
|
expect(member).toBeDefined();
|
||||||
|
|
||||||
// Pending row cleared and container woken via replay.
|
// Pending row cleared and container woken via replay.
|
||||||
const stillPending = (
|
const stillPending = (getDb().prepare('SELECT COUNT(*) AS c FROM pending_channel_approvals').get() as { c: number })
|
||||||
getDb().prepare('SELECT COUNT(*) AS c FROM pending_channel_approvals').get() as { c: number }
|
.c;
|
||||||
).c;
|
|
||||||
expect(stillPending).toBe(0);
|
expect(stillPending).toBe(0);
|
||||||
expect(wakeContainer).toHaveBeenCalled();
|
expect(wakeContainer).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
@@ -255,9 +254,9 @@ describe('unknown-channel registration flow', () => {
|
|||||||
await new Promise((r) => setTimeout(r, 10));
|
await new Promise((r) => setTimeout(r, 10));
|
||||||
|
|
||||||
const { getDb } = await import('../../db/connection.js');
|
const { getDb } = await import('../../db/connection.js');
|
||||||
const pending = getDb()
|
const pending = getDb().prepare('SELECT messaging_group_id FROM pending_channel_approvals').get() as {
|
||||||
.prepare('SELECT messaging_group_id FROM pending_channel_approvals')
|
messaging_group_id: string;
|
||||||
.get() as { messaging_group_id: string };
|
};
|
||||||
|
|
||||||
for (const handler of getResponseHandlers()) {
|
for (const handler of getResponseHandlers()) {
|
||||||
const claimed = await handler({
|
const claimed = await handler({
|
||||||
@@ -285,9 +284,9 @@ describe('unknown-channel registration flow', () => {
|
|||||||
await routeInbound(groupMention('chat-deny'));
|
await routeInbound(groupMention('chat-deny'));
|
||||||
await new Promise((r) => setTimeout(r, 10));
|
await new Promise((r) => setTimeout(r, 10));
|
||||||
const { getDb } = await import('../../db/connection.js');
|
const { getDb } = await import('../../db/connection.js');
|
||||||
const pending = getDb()
|
const pending = getDb().prepare('SELECT messaging_group_id FROM pending_channel_approvals').get() as {
|
||||||
.prepare('SELECT messaging_group_id FROM pending_channel_approvals')
|
messaging_group_id: string;
|
||||||
.get() as { messaging_group_id: string };
|
};
|
||||||
|
|
||||||
for (const handler of getResponseHandlers()) {
|
for (const handler of getResponseHandlers()) {
|
||||||
const claimed = await handler({
|
const claimed = await handler({
|
||||||
@@ -317,9 +316,8 @@ describe('unknown-channel registration flow', () => {
|
|||||||
await routeInbound(groupMention('chat-deny', '@bot please'));
|
await routeInbound(groupMention('chat-deny', '@bot please'));
|
||||||
await new Promise((r) => setTimeout(r, 10));
|
await new Promise((r) => setTimeout(r, 10));
|
||||||
expect(deliverMock).not.toHaveBeenCalled();
|
expect(deliverMock).not.toHaveBeenCalled();
|
||||||
const stillPending = (
|
const stillPending = (getDb().prepare('SELECT COUNT(*) AS c FROM pending_channel_approvals').get() as { c: number })
|
||||||
getDb().prepare('SELECT COUNT(*) AS c FROM pending_channel_approvals').get() as { c: number }
|
.c;
|
||||||
).c;
|
|
||||||
expect(stillPending).toBe(0);
|
expect(stillPending).toBe(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -330,9 +328,9 @@ describe('unknown-channel registration flow', () => {
|
|||||||
await routeInbound(groupMention('chat-unauth'));
|
await routeInbound(groupMention('chat-unauth'));
|
||||||
await new Promise((r) => setTimeout(r, 10));
|
await new Promise((r) => setTimeout(r, 10));
|
||||||
const { getDb } = await import('../../db/connection.js');
|
const { getDb } = await import('../../db/connection.js');
|
||||||
const pending = getDb()
|
const pending = getDb().prepare('SELECT messaging_group_id FROM pending_channel_approvals').get() as {
|
||||||
.prepare('SELECT messaging_group_id FROM pending_channel_approvals')
|
messaging_group_id: string;
|
||||||
.get() as { messaging_group_id: string };
|
};
|
||||||
|
|
||||||
for (const handler of getResponseHandlers()) {
|
for (const handler of getResponseHandlers()) {
|
||||||
const claimed = await handler({
|
const claimed = await handler({
|
||||||
@@ -353,9 +351,8 @@ describe('unknown-channel registration flow', () => {
|
|||||||
.get(pending.messaging_group_id) as { c: number }
|
.get(pending.messaging_group_id) as { c: number }
|
||||||
).c;
|
).c;
|
||||||
expect(mgaCount).toBe(0);
|
expect(mgaCount).toBe(0);
|
||||||
const stillPending = (
|
const stillPending = (getDb().prepare('SELECT COUNT(*) AS c FROM pending_channel_approvals').get() as { c: number })
|
||||||
getDb().prepare('SELECT COUNT(*) AS c FROM pending_channel_approvals').get() as { c: number }
|
.c;
|
||||||
).c;
|
|
||||||
expect(stillPending).toBe(1);
|
expect(stillPending).toBe(1);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -37,19 +37,14 @@ export function createPendingSenderApproval(row: PendingSenderApproval): void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function getPendingSenderApproval(id: string): PendingSenderApproval | undefined {
|
export function getPendingSenderApproval(id: string): PendingSenderApproval | undefined {
|
||||||
return getDb()
|
return getDb().prepare('SELECT * FROM pending_sender_approvals WHERE id = ?').get(id) as
|
||||||
.prepare('SELECT * FROM pending_sender_approvals WHERE id = ?')
|
| PendingSenderApproval
|
||||||
.get(id) as PendingSenderApproval | undefined;
|
| undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function hasInFlightSenderApproval(
|
export function hasInFlightSenderApproval(messagingGroupId: string, senderIdentity: string): boolean {
|
||||||
messagingGroupId: string,
|
|
||||||
senderIdentity: string,
|
|
||||||
): boolean {
|
|
||||||
const row = getDb()
|
const row = getDb()
|
||||||
.prepare(
|
.prepare('SELECT 1 AS x FROM pending_sender_approvals WHERE messaging_group_id = ? AND sender_identity = ?')
|
||||||
'SELECT 1 AS x FROM pending_sender_approvals WHERE messaging_group_id = ? AND sender_identity = ?',
|
|
||||||
)
|
|
||||||
.get(messagingGroupId, senderIdentity) as { x: number } | undefined;
|
.get(messagingGroupId, senderIdentity) as { x: number } | undefined;
|
||||||
return row !== undefined;
|
return row !== undefined;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,9 +59,7 @@ describe('handleRecurrence', () => {
|
|||||||
await handleRecurrence(db, fakeSession());
|
await handleRecurrence(db, fakeSession());
|
||||||
|
|
||||||
const rows = db
|
const rows = db
|
||||||
.prepare(
|
.prepare(`SELECT id, status, process_after, recurrence, series_id FROM messages_in ORDER BY seq`)
|
||||||
`SELECT id, status, process_after, recurrence, series_id FROM messages_in ORDER BY seq`,
|
|
||||||
)
|
|
||||||
.all() as Array<{
|
.all() as Array<{
|
||||||
id: string;
|
id: string;
|
||||||
status: string;
|
status: string;
|
||||||
|
|||||||
@@ -24,7 +24,10 @@ export const applyInstallPackages: ApprovalHandler = async ({ session, payload,
|
|||||||
if (payload.npm) cfg.packages.npm.push(...(payload.npm as string[]));
|
if (payload.npm) cfg.packages.npm.push(...(payload.npm as string[]));
|
||||||
});
|
});
|
||||||
|
|
||||||
const pkgs = [...((payload.apt as string[] | undefined) || []), ...((payload.npm as string[] | undefined) || [])].join(', ');
|
const pkgs = [
|
||||||
|
...((payload.apt as string[] | undefined) || []),
|
||||||
|
...((payload.npm as string[] | undefined) || []),
|
||||||
|
].join(', ');
|
||||||
log.info('Package install approved', { agentGroupId: session.agent_group_id, userId });
|
log.info('Package install approved', { agentGroupId: session.agent_group_id, userId });
|
||||||
try {
|
try {
|
||||||
await buildAgentGroupImage(session.agent_group_id);
|
await buildAgentGroupImage(session.agent_group_id);
|
||||||
|
|||||||
Reference in New Issue
Block a user