focusnoteapp

Polar Sponsor
爱发电 赞助
.NET 9.0

在FocusNote今日日记中添加文本作为新要点。

Focus Note: 添加到 Daily Note 中

功能概述

Focus Note: 添加到 Daily Note 中是一项面向实际任务的技能,主要用于此技能将用户提供的文本添加到 FocusNote 中的今天的每日注中, 作为新的项目点;它如何工作;

核心要点

  • 读取 FocusNote 文档路径从 ~/.lucia/ 文件 ~ /.。
  • 它将相关步骤、工具调用和结果整理方式集中到统一流程中,帮助使用者更快完成目标并减少重复操作。
  • 使用时应结合输入条件选择合适的执行方式,核对必要参数、依赖环境与输出内容,并按原始要求处理异常情况。

使用与执行

从功能定位来看,该技能强调把分散的操作要求整理成清晰、可复用的处理流程,使用户能够围绕既定目标快速准备输入、选择执行方式并获得结构化结果。实际使用前应先确认任务范围、数据来源、运行环境、必要权限和关键参数,再依据技能说明逐步执行;若输入条件不完整,应先补齐信息或采用保守配置,避免因错误假设导致结果偏离需求。

结果检查与注意事项

执行过程中需要关注工具调用是否成功、接口或依赖是否可用、输出格式是否符合预期,并对异常提示、缺失字段和边界情况进行处理;涉及批量任务时,还应保存进度,避免中断后重复操作。该技能适合用于一次性任务,也可以接入自动化工作流,与其他技能或上层代理配合完成更完整的业务链路;在组合使用时,应明确每一步的输入输出关系,并避免不同步骤之间出现参数冲突。

FocusNote:添加到每日笔记

该技能将用户提供的文本作为新项目符号(bullet point)添加至 FocusNote 中今天的每日笔记。

工作原理

  1. 从 ~/.lucia/documents-path.txt 读取 FocusNote 的文档路径
  2. 以 YYYY-MM-DD 格式生成今日日期
  3. 定位或创建今日的每日笔记目录
  4. 将用户输入的文本作为新的项目符号添加进去
  5. 更新文档对应的 JSON 结构文件(_structure.json 和 _metadata.json)

前提条件

  • FocusNote 应用必须正在运行(启动时会创建 ~/.lucia/documents-path.txt)
  • 需已安装 Node.js,用于运行辅助脚本

实现方式

当用户请求将文本添加至其每日笔记时,请按以下步骤执行:

步骤 1:读取文档路径

const fs = require("fs");
const path = require("path");
const os = require("os");

// 从 FocusNote 的配置文件中读取文档路径
const focusnoteConfigPath = path.join(
  os.homedir(),
  ".lucia",
  "documents-path.txt",
);
const documentsPath = fs.readFileSync(focusnoteConfigPath, "utf-8").trim();

步骤 2:生成今日日期

const today = new Date();
const year = today.getFullYear();
const month = String(today.getMonth() + 1).padStart(2, "0");
const day = String(today.getDate()).padStart(2, "0");
const todayDocName = `${year}-${month}-${day}`;

步骤 3:定位每日笔记目录

const dailyNotePath = path.join(documentsPath, "notes", todayDocName);
const structurePath = path.join(dailyNotePath, "_structure.json");
const metadataPath = path.join(dailyNotePath, "_metadata.json");
const nodesDir = path.join(dailyNotePath, ".nodes");

步骤 4:若每日笔记不存在,则创建它

if (!fs.existsSync(dailyNotePath)) {
  // 创建目录结构
  fs.mkdirSync(dailyNotePath, { recursive: true });
  fs.mkdirSync(nodesDir, { recursive: true });

  // 创建元数据文件
  const metadata = {
    name: todayDocName,
    createdAt: Date.now(),
    updatedAt: Date.now(),
  };
  fs.writeFileSync(metadataPath, JSON.stringify(metadata, null, 2));

  // 创建空的结构文件
  const structure = {
    rootNodeIds: [],
    deletedNodeIds: [],
    nodes: {},
  };
  fs.writeFileSync(structurePath, JSON.stringify(structure, null, 2));
}

步骤 5:创建新的项目符号节点

const { v4: uuidv4 } = require("uuid"); // npm install uuid

// 生成唯一节点 ID
const nodeId = uuidv4();
const timestamp = Date.now();

// 构建 Lexical 格式的项目符号内容结构
const lexicalContent = {
  root: {
    children: [
      {
        children: [
          {
            children: [
              {
                detail: 0,
                format: 0,
                mode: "normal",
                style: "",
                text: userText, // 用户输入的文本
                type: "text",
                version: 1,
              },
            ],
            direction: "ltr",
            format: "",
            indent: 0,
            type: "listitem",
            version: 1,
            value: 1,
          },
        ],
        direction: "ltr",
        format: "",
        indent: 0,
        type: "list",
        version: 1,
        listType: "bullet",
        start: 1,
        tag: "ul",
      },
    ],
    direction: "ltr",
    format: "",
    indent: 0,
    type: "root",
    version: 1,
  },
};

// 构建节点对象
const newNode = {
  id: nodeId,
  content: JSON.stringify(lexicalContent),
  isFolded: false,
  isTodo: false,
  isDone: false,
  isInProgress: false,
  isBlurred: false,
  backgroundColor: null,
  createdAt: timestamp,
  updatedAt: timestamp,
};

步骤 6:将节点保存至分片(sharded)目录

// 按节点 ID 的前两个字符进行分片
const shard = nodeId.substring(0, 2);
const shardDir = path.join(nodesDir, shard);

if (!fs.existsSync(shardDir)) {
  fs.mkdirSync(shardDir, { recursive: true });
}

const nodeFilePath = path.join(shardDir, `node-${nodeId}.json`);
fs.writeFileSync(nodeFilePath, JSON.stringify(newNode, null, 2));

步骤 7:更新结构文件

// 读取当前结构文件
const structure = JSON.parse(fs.readFileSync(structurePath, "utf-8"));

// 将新节点加入结构
structure.rootNodeIds.push(nodeId);
structure.nodes[nodeId] = {
  parentId: null,
  orderIndex: structure.rootNodeIds.length - 1,
  childIds: [],
};

// 更新时间戳
structure.updatedAt = timestamp;

// 写入更新后的结构文件
fs.writeFileSync(structurePath, JSON.stringify(structure, null, 2));

完整脚本示例

以下是一个可直接使用的完整 Node.js 脚本:

#!/usr/bin/env node

const fs = require("fs");
const path = require("path");
const os = require("os");
const { v4: uuidv4 } = require("uuid");

function addToDailyNote(userText) {
  try {
    // 步骤 1:读取文档路径
    const focusnoteConfigPath = path.join(
      os.homedir(),
      ".lucia",
      "documents-path.txt",
    );
    if (!fs.existsSync(focusnoteConfigPath)) {
      throw new Error(
        "FocusNote 配置文件未找到。请确保 FocusNote 正在运行。",
      );
    }
    const documentsPath = fs.readFileSync(focusnoteConfigPath, "utf-8").trim();

    // 步骤 2:生成今日日期
    const today = new Date();
    const year = today.getFullYear();
    const month = String(today.getMonth() + 1).padStart(2, "0");
    const day = String(today.getDate()).padStart(2, "0");
    const todayDocName = `${year}-${month}-${day}`;

    // 步骤 3:设置路径
    const dailyNotePath = path.join(documentsPath, "notes", todayDocName);
    const structurePath = path.join(dailyNotePath, "_structure.json");
    const metadataPath = path.join(dailyNotePath, "_metadata.json");
    const nodesDir = path.join(dailyNotePath, ".nodes");

    // 步骤 4:如需则创建每日笔记目录
    if (!fs.existsSync(dailyNotePath)) {
      fs.mkdirSync(dailyNotePath, { recursive: true });
      fs.mkdirSync(nodesDir, { recursive: true });

      const metadata = {
        name: todayDocName,
        createdAt: Date.now(),
        updatedAt: Date.now(),
      };
      fs.writeFileSync(metadataPath, JSON.stringify(metadata, null, 2));

      const structure = {
        rootNodeIds: [],
        deletedNodeIds: [],
        nodes: {},
      };
      fs.writeFileSync(structurePath, JSON.stringify(structure, null, 2));
    }

    // 步骤 5:创建新的项目符号节点
    const nodeId = uuidv4();
    const timestamp = Date.now();

    const lexicalContent = {
      root: {
        children: [
          {
            children: [
              {
                children: [
                  {
                    detail: 0,
                    format: 0,
                    mode: "normal",
                    style: "",
                    text: userText,
                    type: "text",
                    version: 1,
                  },
                ],
                direction: "ltr",
                format: "",
                indent: 0,
                type: "listitem",
                version: 1,
                value: 1,
              },
            ],
            direction: "ltr",
            format: "",
            indent: 0,
            type: "list",
            version: 1,
            listType: "bullet",
            start: 1,
            tag: "ul",
          },
        ],
        direction: "ltr",
        format: "",
        indent: 0,
        type: "root",
        version: 1,
      },
    };

    const newNode = {
      id: nodeId,
      content: JSON.stringify(lexicalContent),
      isFolded: false,
      isTodo: false,
      isDone: false,
      isInProgress: false,
      isBlurred: false,
      backgroundColor: null,
      createdAt: timestamp,
      updatedAt: timestamp,
    };

    // 步骤 6:保存节点文件
    const shard = nodeId.substring(0, 2);
    const shardDir = path.join(nodesDir, shard);

    if (!fs.existsSync(shardDir)) {
      fs.mkdirSync(shardDir, { recursive: true });
    }

    const nodeFilePath = path.join(shardDir, `node-${nodeId}.json`);
    fs.writeFileSync(nodeFilePath, JSON.stringify(newNode, null, 2));

    // 步骤 7:更新结构文件
    const structure = JSON.parse(fs.readFileSync(structurePath, "utf-8"));
    structure.rootNodeIds.push(nodeId);
    structure.nodes[nodeId] = {
      parentId: null,
      orderIndex: structure.rootNodeIds.length - 1,
      childIds: [],
    };
    structure.updatedAt = timestamp;
    fs.writeFileSync(structurePath, JSON.stringify(structure, null, 2));

    console.log(`✅ 已向 ${todayDocName} 添加项目符号:"${userText}"`);
    return { success: true, documentName: todayDocName, nodeId };
  } catch (error) {
    console.error("❌ 向每日笔记添加内容时出错:", error.message);
    return { success: false, error: error.message };
  }
}

// 示例调用方式
if (require.main === module) {
  const userText = process.argv.slice(2).join(" ") || "New bullet point";
  addToDailyNote(userText);
}

module.exports = { addToDailyNote };

使用示例

用户:“添加到我的每日笔记:完成了 OpenClaw 技能的实现”

助手:我将把该内容添加至您的每日笔记中。

# 运行脚本
node add-to-daily-note.js "Finished the OpenClaw skill implementation"

输出: ✅ 已向 2026-02-11 添加项目符号:"Finished the OpenClaw skill implementation"

用户:“添加一个提醒:明天给妈妈打电话”

助手:我将把该提醒添加至今天的笔记中。

node add-to-daily-note.js "Reminder to call mom tomorrow"

安装方法

  1. 将脚本保存为 add-to-daily-note.js,置于您的 OpenClaw skills 目录下
  2. 安装依赖项:npm install uuid
  3. 赋予可执行权限:chmod +x add-to-daily-note.js

注意事项

  • 每次调用该技能都会创建一个新的项目符号节点
  • 项目符号始终追加至每日笔记末尾
  • 若当日的每日笔记尚不存在,系统将自动创建
  • FocusNote 应用必须处于运行状态,以确保 ~/.lucia/documents-path.txt 存在
  • 在 FocusNote 中打开或刷新每日笔记后,更改将立即可见

故障排查

错误:“FocusNote 配置文件未找到”

  • 请确认 FocusNote 正在运行
  • 检查 ~/.lucia/documents-path.txt 是否存在

项目符号未在 FocusNote 中显示

  • 尝试关闭并重新打开该每日笔记
  • 检查 .nodes/ 目录下是否已成功创建节点文件
  • 确认 _structure.json 文件是否已正确更新

相关专题

更多
Uvicorn 报错与问题解决教程
Uvicorn 报错与问题解决教程

本专题汇总了Uvicorn服务器常见问题与报错解决的教程合集,涵盖启动失败、端口占用、模块导入错误、事件循环冲突及热重载失效等典型故障的排查思路。同时整理了多进程与Worker配置、SSL/HTTPS证书报错、跨域与代理配置等实战解决方案,助你快速定位并解决Uvicorn运行中的各类问题。

2026.11.02

0

14

Uvicorn使用教程
Uvicorn使用教程

本专题汇总了Uvicorn使用教程与启动运行指南,涵盖其作为Python ASGI服务器的定位与特点,以及命令行启动(uvicorn main:app --reload)、参数配置(host/port/workers)、程序内嵌运行与Gunicorn结合部署等核心用法。同时整理了热重载调试、日志配置与生产环境部署优化等技巧,助你快速掌握Uvicorn的运行与配置。

2026.11.02

0

17

Uvicorn安装配置教程
Uvicorn安装配置教程

本专题汇总了Uvicorn的安装配置教程与部署指南,涵盖通过pip安装Uvicorn、启动FastAPI/Starlette应用、开发模式热重载(--reload)及多进程工作模式配置等核心操作。同时整理了结合Gunicorn的生产部署方案、HTTPS与反向代理配置及性能调优技巧,助你快速完成Uvicorn服务的安装与上线部署。

2026.11.02

0

17

Vite 项目如何打包和部署
Vite 项目如何打包和部署

Vite项目打包部署专题汇集生产构建、产物预览、输出目录、资源路径、Nginx与GitHub Pages部署及常见白屏和路由404问题的已审核文章,帮助读者完成上线流程。

2026.10.28

0

16

Vite 如何搭配 Vue.js
Vite 如何搭配 Vue.js

Vite搭配Vue.js专题汇集创建Vue 3项目、配置开发环境、路径别名、Vue插件、代理、多环境构建与调试的已审核文章,帮助读者完成从初始化到日常开发的配置。

2026.10.28

0

15

Vite 项目目录怎么看
Vite 项目目录怎么看

Vite项目目录专题汇集入口文件、src源码、public静态资源、路径别名、项目根目录和构建输出目录相关的已审核文章,帮助读者理解各文件夹的用途与引用方式。

2026.10.28

0

10

Gradle插件开发入门教程
Gradle插件开发入门教程

本专题介绍Gradle插件开发的基本流程,涵盖插件类编写、自定义任务注册、扩展参数设计和插件应用方法,帮助你理解插件如何组织构建逻辑,减少多个项目之间的重复配置。

2026.10.22

0

11

Gradle Wrapper配置教程
Gradle Wrapper配置教程

本专题介绍Gradle Wrapper的基本作用,涵盖文件组成、生成方法、版本配置和任务调用,帮助你理解项目如何使用指定的Gradle版本,减少不同开发环境带来的构建差异。

2026.10.22

0

10

Golangci-lint检查器使用教程
Golangci-lint检查器使用教程

本专题整理Golangci-lint常用Linters的用途与配置方法,覆盖错误处理、无效代码、安全、复杂度、命名和依赖检查,帮助项目合理选规则。

2026.10.22

0

15

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
热门推荐
/
最新课程
phpStudy极速入门视频教程
phpStudy极速入门视频教程

共6课时 | 54.7万人学习

独孤九贱(4)_PHP视频教程
独孤九贱(4)_PHP视频教程

共89课时 | 134.1万人学习