@karmaniverous/jeeves-scripts-core
    Preparing search index...

    Function deriveIntegrations

    • Derive resolved integration settings from a loaded config.

      Parameters

      • config: {
            $schema?: string;
            instance: { baseDir: string; name: string };
            integrations: {
                gh: {
                    account?: string;
                    bin?: string;
                    botUser?: string;
                    configDir?: string;
                };
                gog: { bin?: string };
                jira: {
                    apiTokenPath?: string;
                    boardId?: number;
                    email?: string;
                    fieldsFilename?: string;
                    maxHistory?: number;
                    siteUrl?: string;
                };
                linear: { configPath?: string; maxHistory?: number };
                notion: { version?: string };
                qdrant: { apiUrl?: string; serviceName?: string };
                x: { accounts: Record<string, { relativePath?: string; silo?: string }> };
            };
            jobs: Record<
                string,
                {
                    account?: string;
                    args?: string[];
                    contextThreshold?: number;
                    enabled?: boolean;
                    env?: Record<string, string>;
                    excludedKeys?: string[];
                    extraDirs?: string[];
                    files?: { source: string; target: string }[];
                    idleMinutes?: number;
                    on_failure?: string | null;
                    owners?: {
                        exclude?: string[];
                        include?: string[];
                        owner: string;
                        ruleset?: boolean;
                        type: "user" | "org";
                    }[];
                    ruleset?: {
                        enforcement: string;
                        name: string;
                        rules: { type: string; [key: string]: unknown }[];
                        target: string;
                        [key: string]: unknown;
                    };
                    schedule?: string
                    | Record<string, unknown>;
                    silo?: string;
                    taskFile?: string;
                    timeout_seconds?: number;
                },
            >;
            library: {
                mirrors: {
                    adopt: boolean;
                    dest: string;
                    exclude: string[];
                    id: string;
                    minRatio: number;
                    ref: string;
                    repo: string;
                    siteLinks?: { pattern: string; target: string };
                    subdir: string;
                }[];
            };
            local?: unknown;
            paths: {
                configDir?: string;
                contentDir?: string;
                credentialsDir?: string;
                gogHome?: string;
                scriptsDir?: string;
                stateDir?: string;
                tokenMetricsDir?: string;
            };
            people: Record<
                string,
                {
                    accounts?: { account: string; channel: string; id: string }[];
                    emails?: string[];
                    name: string;
                },
            >;
            pipeline?: {
                accounts: {
                    calendar?: { tokenFile: string }
                    | { serviceAccount: "auto" };
                    email: string;
                    emailPolling: boolean;
                    folders?: string[];
                    imap?: {
                        host: string;
                        password: { secretRef: string };
                        port: number;
                        tls: boolean;
                        user: string;
                    };
                    reportOnly?: boolean;
                    type: "gmail"
                    | "imap";
                }[];
                buckets: {
                    domains: { bucket: string; pattern: string }[];
                    priority: string[];
                };
                emailConfig: {
                    backfill?: {
                        accounts: string[];
                        lookbackDays: number;
                        windowDays: number;
                    };
                    digest: { slackChannelId: string };
                    meetings?: { archive: boolean };
                    reportOnly: boolean;
                    respond?: {
                        allowedSenders: string[];
                        dryRun?: boolean;
                        label: string;
                        mailbox: string;
                        maxPerRun: number;
                        maxRepliesPerThreadPerHour: number;
                        slackMirror: boolean;
                    };
                };
                googleDrive?: unknown;
                refs: Record<string, string>;
            };
            punchList?: {
                cursorFile?: string;
                dir: string;
                inboxDir?: string;
                inputRoots?: string[];
                installMap: Record<string, { component: string; packageJson: string }[]>;
                lockFile?: string;
                pendingFile?: string;
                retentionDays: number;
                scriptsRepo: { clone: string; repo: string };
                slack: { account: string; channel: string; pinnedTs?: string };
                specPath?: string;
                timeZone: string;
            };
            siloRouting: {
                defaultBasePath?: string;
                silos: Record<
                    string,
                    {
                        basePath: string;
                        emailDomains?: string[];
                        githubOrgs?: (string | { githubOrg: string; relativePath: string })[];
                        jira?: boolean;
                        linear?: boolean;
                        slackWorkspaces?: string[];
                    },
                >;
            };
            skillReview?: {
                budgetAlertPercent: number;
                outputDir?: string;
                reportAccount: string;
                reportChannel: string;
                serverKey: string;
                timezone: string;
            };
            slack: {
                backfillBudgetSeconds: number;
                channelMeta?: {
                    activityDays: number;
                    descriptionMaxChars: number;
                    excludeChannels: string[];
                    maxChannels: number;
                    outputDir?: string;
                    pathRoots: Record<string, string>;
                    relativeRoot?: string;
                    reportAccount?: string;
                    reportChannel?: string;
                    reportTextAccounts?: string[];
                    serverKey: string;
                    sweepPatterns: string[];
                    timezone: string;
                    topicMaxChars: number;
                    updateDescriptions: boolean;
                    updateTopics: boolean;
                };
                channels: Record<string, { homeDir?: string; project?: string }>;
                newChannelLookbackDays?: number;
            };
            transcripts?: {
                libraryDir?: string;
                scratchDir?: string;
                userAgent?: string;
            };
        }
        • Optional$schema?: string

          JSON Schema reference for editor completion.

        • instance: { baseDir: string; name: string }

          Instance identity and base directory.

          • baseDir: string

            Base directory every default path derives from.

          • name: string

            Instance name (e.g. acme).

        • integrations: {
              gh: {
                  account?: string;
                  bin?: string;
                  botUser?: string;
                  configDir?: string;
              };
              gog: { bin?: string };
              jira: {
                  apiTokenPath?: string;
                  boardId?: number;
                  email?: string;
                  fieldsFilename?: string;
                  maxHistory?: number;
                  siteUrl?: string;
              };
              linear: { configPath?: string; maxHistory?: number };
              notion: { version?: string };
              qdrant: { apiUrl?: string; serviceName?: string };
              x: { accounts: Record<string, { relativePath?: string; silo?: string }> };
          }

          External tools and services.

          • gh: { account?: string; bin?: string; botUser?: string; configDir?: string }

            GitHub CLI.

            • Optionalaccount?: string

              GitHub user or org whose repos the github domain syncs.

            • Optionalbin?: string

              Path to the gh executable. Default: gh on PATH.

            • OptionalbotUser?: string

              GitHub bot user that acts for the instance.

            • OptionalconfigDir?: string

              GH_CONFIG_DIR for gh (auth, hosts). Default: {configDir}/gh-cli.

          • gog: { bin?: string }

            gog.

            • Optionalbin?: string

              Path to the gog executable. Default: gog on PATH.

          • jira: {
                apiTokenPath?: string;
                boardId?: number;
                email?: string;
                fieldsFilename?: string;
                maxHistory?: number;
                siteUrl?: string;
            }

            Jira.

            • OptionalapiTokenPath?: string

              Path to the file holding the API token. Default: under credentialsDir.

            • OptionalboardId?: number

              Agile board id the backlog jobs work on.

            • Optionalemail?: string

              Account email the API token belongs to.

            • OptionalfieldsFilename?: string

              File name of the cached field map at the Jira domain root.

            • OptionalmaxHistory?: number

              Maximum history entries kept per Jira entity file.

            • OptionalsiteUrl?: string

              Jira site base URL.

          • linear: { configPath?: string; maxHistory?: number }

            Linear.

            • OptionalconfigPath?: string

              Path to the Linear credential file. Default: under credentialsDir.

            • OptionalmaxHistory?: number

              Maximum history entries kept per Linear entity file.

          • notion: { version?: string }

            Notion.

            • Optionalversion?: string

              Notion-Version API header value.

          • qdrant: { apiUrl?: string; serviceName?: string }

            Qdrant.

            • OptionalapiUrl?: string

              Qdrant HTTP API base URL. Default: the watcher's vectorStore.url ({configDir}/jeeves-watcher/config.json), else http://localhost:6333. Set it only when no watcher config names the Qdrant this instance uses.

            • OptionalserviceName?: string

              OS service name the health check restarts (case-sensitive on Windows).

          • x: { accounts: Record<string, { relativePath?: string; silo?: string }> }

            X / Twitter.

            • accounts: Record<string, { relativePath?: string; silo?: string }>

              Accounts by handle.

        • jobs: Record<
              string,
              {
                  account?: string;
                  args?: string[];
                  contextThreshold?: number;
                  enabled?: boolean;
                  env?: Record<string, string>;
                  excludedKeys?: string[];
                  extraDirs?: string[];
                  files?: { source: string; target: string }[];
                  idleMinutes?: number;
                  on_failure?: string | null;
                  owners?: {
                      exclude?: string[];
                      include?: string[];
                      owner: string;
                      ruleset?: boolean;
                      type: "user" | "org";
                  }[];
                  ruleset?: {
                      enforcement: string;
                      name: string;
                      rules: { type: string; [key: string]: unknown }[];
                      target: string;
                      [key: string]: unknown;
                  };
                  schedule?: string
                  | Record<string, unknown>;
                  silo?: string;
                  taskFile?: string;
                  timeout_seconds?: number;
              },
          >

          Per-job deltas.

        • library: {
              mirrors: {
                  adopt: boolean;
                  dest: string;
                  exclude: string[];
                  id: string;
                  minRatio: number;
                  ref: string;
                  repo: string;
                  siteLinks?: { pattern: string; target: string };
                  subdir: string;
              }[];
          }

          Public repo subdirectories mirrored into the content tree (library-sync-mirrors).

          • mirrors: {
                adopt: boolean;
                dest: string;
                exclude: string[];
                id: string;
                minRatio: number;
                ref: string;
                repo: string;
                siteLinks?: { pattern: string; target: string };
                subdir: string;
            }[]

            The mirrors, run in order (default none: library-sync-mirrors skips).

        • Optionallocal?: unknown

          The instance's own block: core never reads it; the instance plugin's configSchema validates it and localConfig() returns it.

        • paths: {
              configDir?: string;
              contentDir?: string;
              credentialsDir?: string;
              gogHome?: string;
              scriptsDir?: string;
              stateDir?: string;
              tokenMetricsDir?: string;
          }

          Path overrides.

          • OptionalconfigDir?: string

            Config directory. Default: {baseDir}/config.

          • OptionalcontentDir?: string

            Content directory, the default silo's base path. Default: {baseDir}/content.

          • OptionalcredentialsDir?: string

            Credential files. Default: {configDir}/credentials.

          • OptionalgogHome?: string

            gog home (service-account keys, OAuth client credentials, file keyring). Its own key because it does not sit under configDir on every instance (some keep it under their credentials dir). Default: {configDir}/gogcli; GOG_HOME wins.

          • OptionalscriptsDir?: string

            The instance repo. Default: {baseDir}/jeeves-scripts.

          • OptionalstateDir?: string

            Service state. Default: {baseDir}/state.

          • OptionaltokenMetricsDir?: string

            Token metrics output. Default: under stateDir; TOKEN_METRICS_DIR wins.

        • people: Record<
              string,
              {
                  accounts?: { account: string; channel: string; id: string }[];
                  emails?: string[];
                  name: string;
              },
          >

          Which accounts and emails belong to one person (Decision 34).

        • Optionalpipeline?: {
              accounts: {
                  calendar?: { tokenFile: string } | { serviceAccount: "auto" };
                  email: string;
                  emailPolling: boolean;
                  folders?: string[];
                  imap?: {
                      host: string;
                      password: { secretRef: string };
                      port: number;
                      tls: boolean;
                      user: string;
                  };
                  reportOnly?: boolean;
                  type: "gmail"
                  | "imap";
              }[];
              buckets: {
                  domains: { bucket: string; pattern: string }[];
                  priority: string[];
              };
              emailConfig: {
                  backfill?: {
                      accounts: string[];
                      lookbackDays: number;
                      windowDays: number;
                  };
                  digest: { slackChannelId: string };
                  meetings?: { archive: boolean };
                  reportOnly: boolean;
                  respond?: {
                      allowedSenders: string[];
                      dryRun?: boolean;
                      label: string;
                      mailbox: string;
                      maxPerRun: number;
                      maxRepliesPerThreadPerHour: number;
                      slackMirror: boolean;
                  };
              };
              googleDrive?: unknown;
              refs: Record<string, string>;
          }

          Mail, calendar and refs (the template's pipeline-config.json).

          • accounts: {
                calendar?: { tokenFile: string } | { serviceAccount: "auto" };
                email: string;
                emailPolling: boolean;
                folders?: string[];
                imap?: {
                    host: string;
                    password: { secretRef: string };
                    port: number;
                    tls: boolean;
                    user: string;
                };
                reportOnly?: boolean;
                type: "gmail"
                | "imap";
            }[]

            Mail and calendar accounts.

          • buckets: { domains: { bucket: string; pattern: string }[]; priority: string[] }

            Mail bucket routing.

            • domains: { bucket: string; pattern: string }[]

              Domain rules, first match wins.

            • priority: string[]

              Bucket names, highest priority first.

          • emailConfig: {
                backfill?: {
                    accounts: string[];
                    lookbackDays: number;
                    windowDays: number;
                };
                digest: { slackChannelId: string };
                meetings?: { archive: boolean };
                reportOnly: boolean;
                respond?: {
                    allowedSenders: string[];
                    dryRun?: boolean;
                    label: string;
                    mailbox: string;
                    maxPerRun: number;
                    maxRepliesPerThreadPerHour: number;
                    slackMirror: boolean;
                };
            }

            Email pipeline settings.

            • Optionalbackfill?: { accounts: string[]; lookbackDays: number; windowDays: number }

              Paced historical backfill.

              • accounts: string[]

                Gmail accounts to backfill.

              • lookbackDays: number

                How far back from now to walk, in days.

              • windowDays: number

                Days searched per run, per account.

            • digest: { slackChannelId: string }

              Email digest.

              • slackChannelId: string

                Slack channel the email digest posts to.

            • Optionalmeetings?: { archive: boolean }

              Actions on meeting source emails.

              • archive: boolean

                Archive the source email out of INBOX after packaging.

            • reportOnly: boolean

              Report Gmail changes (labels, archive) without making them, for every account. accounts[].reportOnly opts a single account in.

            • Optionalrespond?: {
                  allowedSenders: string[];
                  dryRun?: boolean;
                  label: string;
                  mailbox: string;
                  maxPerRun: number;
                  maxRepliesPerThreadPerHour: number;
                  slackMirror: boolean;
              }

              Assistant-mailbox auto-reply (email-respond).

              • allowedSenders: string[]

                Senders allowed to trigger a reply: exact addresses or *@example.com (that domain; not a consumer provider). Must not list mailbox exactly; a pattern covering it never lets it qualify.

              • OptionaldryRun?: boolean

                Discovery + qualification only: no dispatch, no send, no state writes.

              • label: string

                Gmail label applied to a thread after a successful reply.

              • mailbox: string

                The mailbox that receives and replies to mail.

              • maxPerRun: number

                Messages processed per run, oldest first (default 3).

              • maxRepliesPerThreadPerHour: number

                Per-thread reply rate limit (default 3/hour).

              • slackMirror: boolean

                Mirror each sent reply to Slack (the sender's DM, or a channel the email asked for). Needs the users:read.email bot scope. Default off.

          • OptionalgoogleDrive?: unknown

            Google Drive sync block, kept raw here: the google-drive domain validates it, so a mistake in it fails only the Drive job, never every job that loads this config.

          • refs: Record<string, string>

            Named references (Slack channels, Notion ids, paths) by dotted key.

        • OptionalpunchList?: {
              cursorFile?: string;
              dir: string;
              inboxDir?: string;
              inputRoots?: string[];
              installMap: Record<string, { component: string; packageJson: string }[]>;
              lockFile?: string;
              pendingFile?: string;
              retentionDays: number;
              scriptsRepo: { clone: string; repo: string };
              slack: { account: string; channel: string; pinnedTs?: string };
              specPath?: string;
              timeZone: string;
          }

          The instance's daily punch list (punch-list-*); absent: both runnables skip.

          • OptionalcursorFile?: string

            Harvest window cursor (default {stateDir}/punch-list/harvest-cursor.json).

          • dir: string

            Directory of the daily files, harvest/ records and an optional TASK.md.

          • OptionalinboxDir?: string

            Where the harvest worker writes its report (default {stateDir}/punch-list/inbox).

          • OptionalinputRoots?: string[]

            What the harvester's pre-check watches for new input (default: the default silo's email, slack, meetings and google-drive, plus {stateDir}/jeeves-watcher/issues.json). {home} and {npmGlobal} are expanded.

          • installMap: Record<string, { component: string; packageJson: string }[]>

            Versioned repos (owner/name) scanned for milestones, with where each component installs (default none).

          • OptionallockFile?: string

            Lock held by every runnable write (default {stateDir}/punch-list/punch-list.lock).

          • OptionalpendingFile?: string

            Notifications not yet posted (default {stateDir}/punch-list/status-pending.json).

          • retentionDays: number

            Days a finished entry stays before it is left off the next day's file (default 30).

          • scriptsRepo: { clone: string; repo: string }

            This instance's scripts repo: unversioned, so Done means a merged PR.

            • clone: string

              The deployed clone; a PR is installed once its merge commit is in its HEAD.

            • repo: string

              owner/name.

          • slack: { account: string; channel: string; pinnedTs?: string }

            Where both runnables post.

            • account: string

              Gateway Slack account whose bot token posts (default default).

            • channel: string

              Conversation id the runnables post to.

            • OptionalpinnedTs?: string

              ts of the pinned quick-links message; unset: the harvester leaves it alone.

          • OptionalspecPath?: string

            Absolute path of the punch-list spec, linked from the pinned message and the harvest task.

          • timeZone: string

            The day rolls over in this IANA zone (day boundaries only, not when the runner fires).

        • siloRouting: {
              defaultBasePath?: string;
              silos: Record<
                  string,
                  {
                      basePath: string;
                      emailDomains?: string[];
                      githubOrgs?: (string | { githubOrg: string; relativePath: string })[];
                      jira?: boolean;
                      linear?: boolean;
                      slackWorkspaces?: string[];
                  },
              >;
          }

          Data silos (Decision 28).

          • OptionaldefaultBasePath?: string

            Default silo base path. Default: paths().contentDir (Decision 28).

          • silos: Record<
                string,
                {
                    basePath: string;
                    emailDomains?: string[];
                    githubOrgs?: (string | { githubOrg: string; relativePath: string })[];
                    jira?: boolean;
                    linear?: boolean;
                    slackWorkspaces?: string[];
                },
            >

            Named silos.

        • OptionalskillReview?: {
              budgetAlertPercent: number;
              outputDir?: string;
              reportAccount: string;
              reportChannel: string;
              serverKey: string;
              timezone: string;
          }

          The daily Skill Workshop review (admin-review-skill-proposals); absent: it skips.

          • budgetAlertPercent: number

            Quiet-day alert threshold, percent of the catalog's character budget.

          • OptionaloutputDir?: string

            Report directory; default slack.channels.<reportChannel>.homeDir, required for a DM or a channel without one.

          • reportAccount: string

            Gateway Slack account whose bot posts (default default).

          • reportChannel: string

            Slack conversation the summary and the quiet-day alert go to.

          • serverKey: string

            jeeves-server machine key (in the server's own keys) that resolves the report's insider link.

          • timezone: string

            IANA zone of the report date (no default).

        • slack: {
              backfillBudgetSeconds: number;
              channelMeta?: {
                  activityDays: number;
                  descriptionMaxChars: number;
                  excludeChannels: string[];
                  maxChannels: number;
                  outputDir?: string;
                  pathRoots: Record<string, string>;
                  relativeRoot?: string;
                  reportAccount?: string;
                  reportChannel?: string;
                  reportTextAccounts?: string[];
                  serverKey: string;
                  sweepPatterns: string[];
                  timezone: string;
                  topicMaxChars: number;
                  updateDescriptions: boolean;
                  updateTopics: boolean;
              };
              channels: Record<string, { homeDir?: string; project?: string }>;
              newChannelLookbackDays?: number;
          }

          What this instance decides about Slack channels (Decision 9).

          • backfillBudgetSeconds: number

            slack-poll: the most time one channel may take in a run. A channel with a larger backlog saves its read position and resumes next run, so it can't starve the channels after it. Keep it well under the job's timeout.

          • OptionalchannelMeta?: {
                activityDays: number;
                descriptionMaxChars: number;
                excludeChannels: string[];
                maxChannels: number;
                outputDir?: string;
                pathRoots: Record<string, string>;
                relativeRoot?: string;
                reportAccount?: string;
                reportChannel?: string;
                reportTextAccounts?: string[];
                serverKey: string;
                sweepPatterns: string[];
                timezone: string;
                topicMaxChars: number;
                updateDescriptions: boolean;
                updateTopics: boolean;
            }

            slack-refresh-channel-meta (spec 2.6); absent: it skips.

            • activityDays: number

              Recent-message window for topics, in days.

            • descriptionMaxChars: number

              Longest description (Slack purpose) the runnable sets.

            • excludeChannels: string[]

              Channel ids left out.

            • maxChannels: number

              Channels sent to the worker per run; the rest wait.

            • OptionaloutputDir?: string

              Report directory; default slack.channels.<reportChannel>.homeDir, required when the report goes to a DM.

            • pathRoots: Record<string, string>

              A written path's first segment to the absolute directory it stands for.

            • OptionalrelativeRoot?: string

              Directory a back-ticked relative path is resolved against.

            • OptionalreportAccount?: string

              Gateway Slack account whose bot posts the summary; default found.

            • OptionalreportChannel?: string

              Summary target: a channel (C/G/D) or a user (U/W, their DM); default the OpenClaw command owner's DM.

            • OptionalreportTextAccounts?: string[]

              Gateway Slack accounts whose channels the report may name and quote; default the report target's own.

            • serverKey: string

              jeeves-server machine key (in the server's own keys) that resolves the report's insider link.

            • sweepPatterns: string[]

              Regular expressions (case-insensitive) a message must all match to assign a home directory.

            • timezone: string

              IANA zone of the report date (no default).

            • topicMaxChars: number

              Longest topic the runnable sets.

            • updateDescriptions: boolean

              false: report only, never set a description.

            • updateTopics: boolean

              false: report only, never set a topic.

          • channels: Record<string, { homeDir?: string; project?: string }>

            Per-channel decisions, keyed by channel id.

          • OptionalnewChannelLookbackDays?: number

            slack-poll: how far back to read a channel with no read position yet (newly joined or discovered). 0 starts from now; unset reads its full history.

        • Optionaltranscripts?: { libraryDir?: string; scratchDir?: string; userAgent?: string }

          Where transcripts-fetch-video files and caches transcripts.

          • OptionallibraryDir?: string

            Where transcripts are filed (default <default silo>/library/video-transcripts).

          • OptionalscratchDir?: string

            Raw API response cache (default {stateDir}/transcripts).

          • OptionaluserAgent?: string

            User-Agent sent to the transcript API (default jeeves-scripts/<instance.name>).

      Returns ResolvedIntegrations