Compare commits
5 Commits
main
...
feat/swift
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
990a778d00 | ||
|
|
56274eb76e | ||
|
|
d9987a65b2 | ||
|
|
b59c9c38c2 | ||
|
|
d32b77b330 |
@ -23,6 +23,7 @@
|
|||||||
- Sessions: add agent‑to‑agent post step with `ANNOUNCE_SKIP` to suppress channel announcements.
|
- Sessions: add agent‑to‑agent post step with `ANNOUNCE_SKIP` to suppress channel announcements.
|
||||||
|
|
||||||
### Fixes
|
### Fixes
|
||||||
|
- macOS: improve Swift 6 strict concurrency compatibility (#166) — thanks @Nachx639.
|
||||||
- CI: fix lint ordering after merge cleanup (#156) — thanks @steipete.
|
- CI: fix lint ordering after merge cleanup (#156) — thanks @steipete.
|
||||||
- CI: consolidate checks to avoid redundant installs (#144) — thanks @thewilloftheshadow.
|
- CI: consolidate checks to avoid redundant installs (#144) — thanks @thewilloftheshadow.
|
||||||
- WhatsApp: support `gifPlayback` for MP4 GIF sends via CLI/gateway.
|
- WhatsApp: support `gifPlayback` for MP4 GIF sends via CLI/gateway.
|
||||||
|
|||||||
2
Peekaboo
2
Peekaboo
@ -1 +1 @@
|
|||||||
Subproject commit 9db365b73c7027485cf17507dff8fd59fbd02584
|
Subproject commit b69e4e8dc0f34fca488e034c6cb1373f1259589d
|
||||||
@ -91,19 +91,26 @@ final class MacNodeLocationService: NSObject, CLLocationManagerDelegate {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
|
// MARK: - CLLocationManagerDelegate (nonisolated for Swift 6 compatibility)
|
||||||
guard let cont = self.locationContinuation else { return }
|
|
||||||
self.locationContinuation = nil
|
nonisolated func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
|
||||||
if let latest = locations.last {
|
Task { @MainActor in
|
||||||
cont.resume(returning: latest)
|
guard let cont = self.locationContinuation else { return }
|
||||||
} else {
|
self.locationContinuation = nil
|
||||||
cont.resume(throwing: Error.unavailable)
|
if let latest = locations.last {
|
||||||
|
cont.resume(returning: latest)
|
||||||
|
} else {
|
||||||
|
cont.resume(throwing: Error.unavailable)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func locationManager(_ manager: CLLocationManager, didFailWithError error: Swift.Error) {
|
nonisolated func locationManager(_ manager: CLLocationManager, didFailWithError error: Swift.Error) {
|
||||||
guard let cont = self.locationContinuation else { return }
|
let errorCopy = error // Capture error for Sendable compliance
|
||||||
self.locationContinuation = nil
|
Task { @MainActor in
|
||||||
cont.resume(throwing: error)
|
guard let cont = self.locationContinuation else { return }
|
||||||
|
self.locationContinuation = nil
|
||||||
|
cont.resume(throwing: errorCopy)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,6 +6,25 @@ import SwiftUI
|
|||||||
|
|
||||||
private let onboardingWizardLogger = Logger(subsystem: "com.clawdis", category: "onboarding.wizard")
|
private let onboardingWizardLogger = Logger(subsystem: "com.clawdis", category: "onboarding.wizard")
|
||||||
|
|
||||||
|
// MARK: - Swift 6 AnyCodable Bridging Helpers
|
||||||
|
// Bridge between ClawdisProtocol.AnyCodable and the local module to avoid
|
||||||
|
// Swift 6 strict concurrency type conflicts.
|
||||||
|
|
||||||
|
private typealias ProtocolAnyCodable = ClawdisProtocol.AnyCodable
|
||||||
|
|
||||||
|
private func bridgeToLocal(_ value: ProtocolAnyCodable) -> AnyCodable {
|
||||||
|
if let data = try? JSONEncoder().encode(value),
|
||||||
|
let decoded = try? JSONDecoder().decode(AnyCodable.self, from: data)
|
||||||
|
{
|
||||||
|
return decoded
|
||||||
|
}
|
||||||
|
return AnyCodable(value.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
private func bridgeToLocal(_ value: ProtocolAnyCodable?) -> AnyCodable? {
|
||||||
|
value.map(bridgeToLocal)
|
||||||
|
}
|
||||||
|
|
||||||
@MainActor
|
@MainActor
|
||||||
@Observable
|
@Observable
|
||||||
final class OnboardingWizardModel {
|
final class OnboardingWizardModel {
|
||||||
@ -285,11 +304,11 @@ struct OnboardingWizardStepView: View {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
let option = optionItems[selectedIndex].option
|
let option = optionItems[selectedIndex].option
|
||||||
onSubmit(option.value ?? AnyCodable(option.label))
|
onSubmit(bridgeToLocal(option.value) ?? AnyCodable(option.label))
|
||||||
case "multiselect":
|
case "multiselect":
|
||||||
let values = optionItems
|
let values = optionItems
|
||||||
.filter { selectedIndices.contains($0.index) }
|
.filter { selectedIndices.contains($0.index) }
|
||||||
.map { $0.option.value ?? AnyCodable($0.option.label) }
|
.map { bridgeToLocal($0.option.value) ?? AnyCodable($0.option.label) }
|
||||||
onSubmit(AnyCodable(values))
|
onSubmit(AnyCodable(values))
|
||||||
case "action":
|
case "action":
|
||||||
onSubmit(AnyCodable(true))
|
onSubmit(AnyCodable(true))
|
||||||
@ -307,12 +326,12 @@ private struct WizardOptionItem: Identifiable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private struct WizardOption {
|
private struct WizardOption {
|
||||||
let value: AnyCodable?
|
let value: ProtocolAnyCodable?
|
||||||
let label: String
|
let label: String
|
||||||
let hint: String?
|
let hint: String?
|
||||||
}
|
}
|
||||||
|
|
||||||
private func decodeWizardStep(_ raw: [String: AnyCodable]?) -> WizardStep? {
|
private func decodeWizardStep(_ raw: [String: ProtocolAnyCodable]?) -> WizardStep? {
|
||||||
guard let raw else { return nil }
|
guard let raw else { return nil }
|
||||||
do {
|
do {
|
||||||
let data = try JSONEncoder().encode(raw)
|
let data = try JSONEncoder().encode(raw)
|
||||||
@ -323,7 +342,7 @@ private func decodeWizardStep(_ raw: [String: AnyCodable]?) -> WizardStep? {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func parseWizardOptions(_ raw: [[String: AnyCodable]]?) -> [WizardOption] {
|
private func parseWizardOptions(_ raw: [[String: ProtocolAnyCodable]]?) -> [WizardOption] {
|
||||||
guard let raw else { return [] }
|
guard let raw else { return [] }
|
||||||
return raw.map { entry in
|
return raw.map { entry in
|
||||||
let value = entry["value"]
|
let value = entry["value"]
|
||||||
@ -337,7 +356,7 @@ private func wizardStepType(_ step: WizardStep) -> String {
|
|||||||
(step.type.value as? String) ?? ""
|
(step.type.value as? String) ?? ""
|
||||||
}
|
}
|
||||||
|
|
||||||
private func anyCodableString(_ value: AnyCodable?) -> String {
|
private func anyCodableString(_ value: ProtocolAnyCodable?) -> String {
|
||||||
switch value?.value {
|
switch value?.value {
|
||||||
case let string as String:
|
case let string as String:
|
||||||
return string
|
return string
|
||||||
@ -352,11 +371,11 @@ private func anyCodableString(_ value: AnyCodable?) -> String {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func anyCodableStringValue(_ value: AnyCodable?) -> String? {
|
private func anyCodableStringValue(_ value: ProtocolAnyCodable?) -> String? {
|
||||||
value?.value as? String
|
value?.value as? String
|
||||||
}
|
}
|
||||||
|
|
||||||
private func anyCodableBool(_ value: AnyCodable?) -> Bool {
|
private func anyCodableBool(_ value: ProtocolAnyCodable?) -> Bool {
|
||||||
switch value?.value {
|
switch value?.value {
|
||||||
case let bool as Bool:
|
case let bool as Bool:
|
||||||
return bool
|
return bool
|
||||||
@ -367,18 +386,18 @@ private func anyCodableBool(_ value: AnyCodable?) -> Bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func anyCodableArray(_ value: AnyCodable?) -> [AnyCodable] {
|
private func anyCodableArray(_ value: ProtocolAnyCodable?) -> [ProtocolAnyCodable] {
|
||||||
switch value?.value {
|
switch value?.value {
|
||||||
case let arr as [AnyCodable]:
|
case let arr as [ProtocolAnyCodable]:
|
||||||
return arr
|
return arr
|
||||||
case let arr as [Any]:
|
case let arr as [Any]:
|
||||||
return arr.map { AnyCodable($0) }
|
return arr.map { ProtocolAnyCodable($0) }
|
||||||
default:
|
default:
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func anyCodableEqual(_ lhs: AnyCodable?, _ rhs: AnyCodable?) -> Bool {
|
private func anyCodableEqual(_ lhs: ProtocolAnyCodable?, _ rhs: ProtocolAnyCodable?) -> Bool {
|
||||||
switch (lhs?.value, rhs?.value) {
|
switch (lhs?.value, rhs?.value) {
|
||||||
case let (l as String, r as String):
|
case let (l as String, r as String):
|
||||||
return l == r
|
return l == r
|
||||||
|
|||||||
@ -289,10 +289,14 @@ final class LocationPermissionRequester: NSObject, CLLocationManagerDelegate {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) {
|
// nonisolated for Swift 6 strict concurrency compatibility
|
||||||
guard let cont = self.continuation else { return }
|
nonisolated func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) {
|
||||||
self.continuation = nil
|
let status = manager.authorizationStatus
|
||||||
cont.resume(returning: manager.authorizationStatus)
|
Task { @MainActor in
|
||||||
|
guard let cont = self.continuation else { return }
|
||||||
|
self.continuation = nil
|
||||||
|
cont.resume(returning: status)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -871,7 +871,7 @@ public struct WizardStep: Codable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct WizardNextResult: Codable {
|
public struct WizardNextResult: Codable, Sendable {
|
||||||
public let done: Bool
|
public let done: Bool
|
||||||
public let step: [String: AnyCodable]?
|
public let step: [String: AnyCodable]?
|
||||||
public let status: AnyCodable?
|
public let status: AnyCodable?
|
||||||
@ -896,7 +896,7 @@ public struct WizardNextResult: Codable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct WizardStartResult: Codable {
|
public struct WizardStartResult: Codable, Sendable {
|
||||||
public let sessionid: String
|
public let sessionid: String
|
||||||
public let done: Bool
|
public let done: Bool
|
||||||
public let step: [String: AnyCodable]?
|
public let step: [String: AnyCodable]?
|
||||||
@ -925,7 +925,7 @@ public struct WizardStartResult: Codable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct WizardStatusResult: Codable {
|
public struct WizardStatusResult: Codable, Sendable {
|
||||||
public let status: AnyCodable
|
public let status: AnyCodable
|
||||||
public let error: String?
|
public let error: String?
|
||||||
|
|
||||||
|
|||||||
@ -125,7 +125,7 @@ describe("sessions tools", () => {
|
|||||||
callGatewayMock.mockReset();
|
callGatewayMock.mockReset();
|
||||||
const calls: Array<{ method?: string; params?: unknown }> = [];
|
const calls: Array<{ method?: string; params?: unknown }> = [];
|
||||||
let agentCallCount = 0;
|
let agentCallCount = 0;
|
||||||
let historyCallCount = 0;
|
let _historyCallCount = 0;
|
||||||
let sendCallCount = 0;
|
let sendCallCount = 0;
|
||||||
let waitRunId: string | undefined;
|
let waitRunId: string | undefined;
|
||||||
let nextHistoryIsWaitReply = false;
|
let nextHistoryIsWaitReply = false;
|
||||||
@ -153,7 +153,7 @@ describe("sessions tools", () => {
|
|||||||
return { runId: params?.runId ?? "run-1", status: "ok" };
|
return { runId: params?.runId ?? "run-1", status: "ok" };
|
||||||
}
|
}
|
||||||
if (request.method === "chat.history") {
|
if (request.method === "chat.history") {
|
||||||
historyCallCount += 1;
|
_historyCallCount += 1;
|
||||||
const text = nextHistoryIsWaitReply ? "done" : "ANNOUNCE_SKIP";
|
const text = nextHistoryIsWaitReply ? "done" : "ANNOUNCE_SKIP";
|
||||||
nextHistoryIsWaitReply = false;
|
nextHistoryIsWaitReply = false;
|
||||||
return {
|
return {
|
||||||
@ -219,8 +219,9 @@ describe("sessions tools", () => {
|
|||||||
(call) =>
|
(call) =>
|
||||||
typeof (call.params as { extraSystemPrompt?: string })
|
typeof (call.params as { extraSystemPrompt?: string })
|
||||||
?.extraSystemPrompt === "string" &&
|
?.extraSystemPrompt === "string" &&
|
||||||
(call.params as { extraSystemPrompt?: string })
|
(
|
||||||
?.extraSystemPrompt?.includes("Agent-to-agent message context"),
|
call.params as { extraSystemPrompt?: string }
|
||||||
|
)?.extraSystemPrompt?.includes("Agent-to-agent message context"),
|
||||||
),
|
),
|
||||||
).toBe(true);
|
).toBe(true);
|
||||||
expect(
|
expect(
|
||||||
@ -228,8 +229,9 @@ describe("sessions tools", () => {
|
|||||||
(call) =>
|
(call) =>
|
||||||
typeof (call.params as { extraSystemPrompt?: string })
|
typeof (call.params as { extraSystemPrompt?: string })
|
||||||
?.extraSystemPrompt === "string" &&
|
?.extraSystemPrompt === "string" &&
|
||||||
(call.params as { extraSystemPrompt?: string })
|
(
|
||||||
?.extraSystemPrompt?.includes("Agent-to-agent post step"),
|
call.params as { extraSystemPrompt?: string }
|
||||||
|
)?.extraSystemPrompt?.includes("Agent-to-agent post step"),
|
||||||
),
|
),
|
||||||
).toBe(true);
|
).toBe(true);
|
||||||
expect(waitCalls).toHaveLength(3);
|
expect(waitCalls).toHaveLength(3);
|
||||||
|
|||||||
@ -2774,7 +2774,9 @@ function buildAgentToAgentPostContext(params: {
|
|||||||
? `Requester surface: ${params.requesterSurface}.`
|
? `Requester surface: ${params.requesterSurface}.`
|
||||||
: undefined,
|
: undefined,
|
||||||
`Target session: ${params.targetSessionKey}.`,
|
`Target session: ${params.targetSessionKey}.`,
|
||||||
params.targetChannel ? `Target surface: ${params.targetChannel}.` : undefined,
|
params.targetChannel
|
||||||
|
? `Target surface: ${params.targetChannel}.`
|
||||||
|
: undefined,
|
||||||
`Original request: ${params.originalMessage}`,
|
`Original request: ${params.originalMessage}`,
|
||||||
params.roundOneReply
|
params.roundOneReply
|
||||||
? `Round 1 reply: ${params.roundOneReply}`
|
? `Round 1 reply: ${params.roundOneReply}`
|
||||||
@ -2840,34 +2842,35 @@ function createSessionsSendTool(opts?: {
|
|||||||
extraSystemPrompt: agentMessageContext,
|
extraSystemPrompt: agentMessageContext,
|
||||||
};
|
};
|
||||||
|
|
||||||
const resolveAnnounceTarget = async (): Promise<AnnounceTarget | null> => {
|
const resolveAnnounceTarget =
|
||||||
const parsed = resolveAnnounceTargetFromKey(resolvedKey);
|
async (): Promise<AnnounceTarget | null> => {
|
||||||
if (parsed) return parsed;
|
const parsed = resolveAnnounceTargetFromKey(resolvedKey);
|
||||||
try {
|
if (parsed) return parsed;
|
||||||
const list = (await callGateway({
|
try {
|
||||||
method: "sessions.list",
|
const list = (await callGateway({
|
||||||
params: {
|
method: "sessions.list",
|
||||||
includeGlobal: true,
|
params: {
|
||||||
includeUnknown: true,
|
includeGlobal: true,
|
||||||
limit: 200,
|
includeUnknown: true,
|
||||||
},
|
limit: 200,
|
||||||
})) as { sessions?: Array<Record<string, unknown>> };
|
},
|
||||||
const sessions = Array.isArray(list?.sessions) ? list.sessions : [];
|
})) as { sessions?: Array<Record<string, unknown>> };
|
||||||
const match =
|
const sessions = Array.isArray(list?.sessions) ? list.sessions : [];
|
||||||
sessions.find((entry) => entry?.key === resolvedKey) ??
|
const match =
|
||||||
sessions.find((entry) => entry?.key === displayKey);
|
sessions.find((entry) => entry?.key === resolvedKey) ??
|
||||||
const channel =
|
sessions.find((entry) => entry?.key === displayKey);
|
||||||
typeof match?.lastChannel === "string"
|
const channel =
|
||||||
? match.lastChannel
|
typeof match?.lastChannel === "string"
|
||||||
: undefined;
|
? match.lastChannel
|
||||||
const to =
|
: undefined;
|
||||||
typeof match?.lastTo === "string" ? match.lastTo : undefined;
|
const to =
|
||||||
if (channel && to) return { channel, to };
|
typeof match?.lastTo === "string" ? match.lastTo : undefined;
|
||||||
} catch {
|
if (channel && to) return { channel, to };
|
||||||
// ignore; fall through to null
|
} catch {
|
||||||
}
|
// ignore; fall through to null
|
||||||
return null;
|
}
|
||||||
};
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
const runAgentToAgentPost = async (roundOneReply?: string) => {
|
const runAgentToAgentPost = async (roundOneReply?: string) => {
|
||||||
const announceTarget = await resolveAnnounceTarget();
|
const announceTarget = await resolveAnnounceTarget();
|
||||||
@ -2917,9 +2920,7 @@ function createSessionsSendTool(opts?: {
|
|||||||
params: { sessionKey: resolvedKey, limit: 50 },
|
params: { sessionKey: resolvedKey, limit: 50 },
|
||||||
})) as { messages?: unknown[] };
|
})) as { messages?: unknown[] };
|
||||||
const postFiltered = stripToolMessages(
|
const postFiltered = stripToolMessages(
|
||||||
Array.isArray(postHistory?.messages)
|
Array.isArray(postHistory?.messages) ? postHistory.messages : [],
|
||||||
? postHistory.messages
|
|
||||||
: [],
|
|
||||||
);
|
);
|
||||||
const postLast =
|
const postLast =
|
||||||
postFiltered.length > 0
|
postFiltered.length > 0
|
||||||
|
|||||||
@ -3,7 +3,7 @@ import { buildWorkspaceSkillStatus } from "../agents/skills-status.js";
|
|||||||
import type { ClawdisConfig } from "../config/config.js";
|
import type { ClawdisConfig } from "../config/config.js";
|
||||||
import type { RuntimeEnv } from "../runtime.js";
|
import type { RuntimeEnv } from "../runtime.js";
|
||||||
import type { WizardPrompter } from "../wizard/prompts.js";
|
import type { WizardPrompter } from "../wizard/prompts.js";
|
||||||
import { resolveNodeManagerOptions } from "./onboard-helpers.js";
|
import { detectBinary, resolveNodeManagerOptions } from "./onboard-helpers.js";
|
||||||
|
|
||||||
function summarizeInstallFailure(message: string): string | undefined {
|
function summarizeInstallFailure(message: string): string | undefined {
|
||||||
const cleaned = message
|
const cleaned = message
|
||||||
@ -59,6 +59,13 @@ export async function setupSkills(
|
|||||||
);
|
);
|
||||||
const blocked = report.skills.filter((s) => s.blockedByAllowlist);
|
const blocked = report.skills.filter((s) => s.blockedByAllowlist);
|
||||||
|
|
||||||
|
const needsBrewPrompt =
|
||||||
|
process.platform !== "win32" &&
|
||||||
|
report.skills.some((skill) =>
|
||||||
|
skill.install.some((option) => option.kind === "brew"),
|
||||||
|
) &&
|
||||||
|
!(await detectBinary("brew"));
|
||||||
|
|
||||||
await prompter.note(
|
await prompter.note(
|
||||||
[
|
[
|
||||||
`Eligible: ${eligible.length}`,
|
`Eligible: ${eligible.length}`,
|
||||||
@ -74,6 +81,29 @@ export async function setupSkills(
|
|||||||
});
|
});
|
||||||
if (!shouldConfigure) return cfg;
|
if (!shouldConfigure) return cfg;
|
||||||
|
|
||||||
|
if (needsBrewPrompt) {
|
||||||
|
await prompter.note(
|
||||||
|
[
|
||||||
|
"Many skill dependencies are shipped via Homebrew.",
|
||||||
|
"Without brew, you'll need to build from source or download releases manually.",
|
||||||
|
].join("\n"),
|
||||||
|
"Homebrew recommended",
|
||||||
|
);
|
||||||
|
const showBrewInstall = await prompter.confirm({
|
||||||
|
message: "Show Homebrew install command?",
|
||||||
|
initialValue: true,
|
||||||
|
});
|
||||||
|
if (showBrewInstall) {
|
||||||
|
await prompter.note(
|
||||||
|
[
|
||||||
|
"Run:",
|
||||||
|
'/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"',
|
||||||
|
].join("\n"),
|
||||||
|
"Homebrew install",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const nodeManager = (await prompter.select({
|
const nodeManager = (await prompter.select({
|
||||||
message: "Preferred node manager for skill installs",
|
message: "Preferred node manager for skill installs",
|
||||||
options: resolveNodeManagerOptions(),
|
options: resolveNodeManagerOptions(),
|
||||||
|
|||||||
@ -57,7 +57,10 @@ import { type DiscordProbe, probeDiscord } from "../discord/probe.js";
|
|||||||
import { shouldLogVerbose } from "../globals.js";
|
import { shouldLogVerbose } from "../globals.js";
|
||||||
import { sendMessageIMessage } from "../imessage/index.js";
|
import { sendMessageIMessage } from "../imessage/index.js";
|
||||||
import { type IMessageProbe, probeIMessage } from "../imessage/probe.js";
|
import { type IMessageProbe, probeIMessage } from "../imessage/probe.js";
|
||||||
import { onAgentEvent, registerAgentRunContext } from "../infra/agent-events.js";
|
import {
|
||||||
|
onAgentEvent,
|
||||||
|
registerAgentRunContext,
|
||||||
|
} from "../infra/agent-events.js";
|
||||||
import type { startNodeBridgeServer } from "../infra/bridge/server.js";
|
import type { startNodeBridgeServer } from "../infra/bridge/server.js";
|
||||||
import { getLastHeartbeatEvent } from "../infra/heartbeat-events.js";
|
import { getLastHeartbeatEvent } from "../infra/heartbeat-events.js";
|
||||||
import { setHeartbeatsEnabled } from "../infra/heartbeat-runner.js";
|
import { setHeartbeatsEnabled } from "../infra/heartbeat-runner.js";
|
||||||
|
|||||||
@ -214,9 +214,7 @@ describe("gateway server cron", () => {
|
|||||||
testState.cronStorePath = undefined;
|
testState.cronStorePath = undefined;
|
||||||
});
|
});
|
||||||
|
|
||||||
test(
|
test("enables cron scheduler by default and runs due jobs automatically", async () => {
|
||||||
"enables cron scheduler by default and runs due jobs automatically",
|
|
||||||
async () => {
|
|
||||||
const dir = await fs.mkdtemp(
|
const dir = await fs.mkdtemp(
|
||||||
path.join(os.tmpdir(), "clawdis-gw-cron-default-on-"),
|
path.join(os.tmpdir(), "clawdis-gw-cron-default-on-"),
|
||||||
);
|
);
|
||||||
@ -307,7 +305,5 @@ describe("gateway server cron", () => {
|
|||||||
testState.cronStorePath = undefined;
|
testState.cronStorePath = undefined;
|
||||||
await fs.rm(dir, { recursive: true, force: true });
|
await fs.rm(dir, { recursive: true, force: true });
|
||||||
}
|
}
|
||||||
},
|
}, 15_000);
|
||||||
15_000,
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user