Repository navigation
docs: README を本質だけに絞り、サイトのヒーロー文をブランド軸の一行に揃える - #1335
Merged
Merged
Conversation
…、column.list がそれを返す (#1242) - column.add: `widgets` ([{ installId, accountKey? }]) / `aiscriptCode` / `flashId` / `pageId` を受け、中身を持つ種別も作れるようにする。宣言に漏れていた `roleId` / `sources` も載せる - column.list / column.active: `widgets` と `aiscriptCode` を返し、column.add に渡せば同じカラムを作り直せる形にそろえる - レジストリの `customAddFlow` は column.add の除外にしか使われていなかったので外す Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
- ヘッダーの `loopback` 宣言を TS でも読む (正規化は Rust と同じ golden) - dispatcher: `http.fetch` × plugin principal のときだけ loopback の判定 (連鎖 → 対象外 → 常に拒否するポート → 宣言 → 本文の鮮度 → 同意)。未同意 × UI 起点だけ同意ダイアログを出し、承認 = Rust への記録でその要求の確認を兼ねる。同じプラグイン × ポートのダイアログは同時に 1 枚 - 実行の起点 `origin` と動かしている本文の hash を plugin の実行文脈 (withPluginAccountContext / sandbox / Nd:http) に通し、`capabilityExecute` / `capabilityPreview` に添える - 拒否はプラグインカラムのバッジ (理由つき、押すと詳細) / UI 起点ならトースト / 運用ログに残す。Rust の LOOPBACK_* の code も同じ理由に写す - プラグイン詳細の設定タブ (宣言があれば出す) に許可 / 取り消し / 再起動、権限ウィンドウの AiScript 行に同意の一覧と取り消し (`useLoopbackConsent`) - 文言・capabilities.json5・SECURITY.md・DEVELOPMENT.md・サイトのプラグイン文書 (ja / en / zh / ko) Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…w-1242 feat(capability): column.add が widget / aiscript / play / page の中身を受ける (#1242)
feat(plugin): 利用者がプラグイン単位で同意した loopback ポートだけ Nd:http を通す (#1293)
公式の連携 3 つ (別リポジトリ、本体の追加なし) を 1 ページにまとめる。共通の仕組み (永続 API トークンと権限の交差 / 書き込みは NoteDeck の画面で確認 / notedeck:// は トークン不要 / 安全境界ではない) を先に置き、連携ごとにできることの表と、同じ API で 自分で書く入口 (API ドキュメントのカラム / SSE / MCP) を添える。3 つともストア未掲載と 実機未確認は明記する。 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
公式の連携が 4 つになったので、ページの表と各連携の節にブラウザ拡張 (Chromium) を追加し、 ランディングの「外部からも動かせる」の文にもブラウザを足す。4 言語の訳と sourceHash を追従。 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
AiScript のハイライトは公式 aiscript-vscode、NoteDeck 固有 (設定フォルダ / 検証 / 本体へ送る / capability 実行) は notedeck-vscode、という役割分担で 4 言語に 1 文ずつ。sourceHash 追従。 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
|
Warning Review limit reachedYou've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. Next included review available in 53 minutes. View limit details
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. |
API surface diff外部アプリ向け API 面 ( Full diffdiff --git a/src/bindings.ts b/src/bindings.ts
index b551dbb..7d2d274 100644
--- a/src/bindings.ts
+++ b/src/bindings.ts
@@ -2664,18 +2664,18 @@ async maidTurnSystem(turnId: string) : Promise<Result<JsonValue | null, { code:
}
},
/** @see crates/notemaid/src/commands/ai_chat.rs */
-async capabilityExecute(id: string, params: JsonValue, principal: string, accountId: string | null, tainted: boolean, pluginId: string | null, tokenId: string | null, tokenName: string | null) : Promise<Result<ExecOutcome, { code: string; message: string; apiCode: string | null; i18n: JsonValue | null; retryAfterMs: number | null }>> {
+async capabilityExecute(id: string, params: JsonValue, principal: string, accountId: string | null, tainted: boolean, pluginId: string | null, tokenId: string | null, tokenName: string | null, bodyHash: string | null) : Promise<Result<ExecOutcome, { code: string; message: string; apiCode: string | null; i18n: JsonValue | null; retryAfterMs: number | null }>> {
try {
- return { status: "ok", data: await TAURI_INVOKE("capability_execute", { id, params, principal, accountId, tainted, pluginId, tokenId, tokenName }) };
+ return { status: "ok", data: await TAURI_INVOKE("capability_execute", { id, params, principal, accountId, tainted, pluginId, tokenId, tokenName, bodyHash }) };
} catch (e) {
if(e instanceof Error) throw e;
else return { status: "error", error: e as any };
}
},
/** @see crates/notemaid/src/commands/ai_chat.rs */
-async capabilityPreview(id: string, params: JsonValue, principal: string, accountId: string | null, tainted: boolean, pluginId: string | null, tokenId: string | null, tokenName: string | null) : Promise<Result<JsonValue | null, { code: string; message: string; apiCode: string | null; i18n: JsonValue | null; retryAfterMs: number | null }>> {
+async capabilityPreview(id: string, params: JsonValue, principal: string, accountId: string | null, tainted: boolean, pluginId: string | null, tokenId: string | null, tokenName: string | null, bodyHash: string | null) : Promise<Result<JsonValue | null, { code: string; message: string; apiCode: string | null; i18n: JsonValue | null; retryAfterMs: number | null }>> {
try {
- return { status: "ok", data: await TAURI_INVOKE("capability_preview", { id, params, principal, accountId, tainted, pluginId, tokenId, tokenName }) };
+ return { status: "ok", data: await TAURI_INVOKE("capability_preview", { id, params, principal, accountId, tainted, pluginId, tokenId, tokenName, bodyHash }) };
} catch (e) {
if(e instanceof Error) throw e;
else return { status: "error", error: e as any };
@@ -2762,6 +2762,60 @@ async httpFetch(request: HttpFetchRequest) : Promise<Result<HttpFetchResponse, {
else return { status: "error", error: e as any };
}
},
+/** @see crates/notecore/src/commands/loopback.rs */
+async loopbackConsentStatus(pluginId: string) : Promise<Result<LoopbackConsentStatus, { code: string; message: string; apiCode: string | null; i18n: JsonValue | null; retryAfterMs: number | null }>> {
+ try {
+ return { status: "ok", data: await TAURI_INVOKE("loopback_consent_status", { pluginId }) };
+} catch (e) {
+ if(e instanceof Error) throw e;
+ else return { status: "error", error: e as any };
+}
+},
+/** @see crates/notecore/src/commands/loopback.rs */
+async loopbackConsentList() : Promise<Result<LoopbackConsentRow[], { code: string; message: string; apiCode: string | null; i18n: JsonValue | null; retryAfterMs: number | null }>> {
+ try {
+ return { status: "ok", data: await TAURI_INVOKE("loopback_consent_list") };
+} catch (e) {
+ if(e instanceof Error) throw e;
+ else return { status: "error", error: e as any };
+}
+},
+/** @see crates/notecore/src/commands/loopback.rs */
+async loopbackConsentGrant(pluginId: string, port: number, expectedHash: string) : Promise<Result<null, { code: string; message: string; apiCode: string | null; i18n: JsonValue | null; retryAfterMs: number | null }>> {
+ try {
+ return { status: "ok", data: await TAURI_INVOKE("loopback_consent_grant", { pluginId, port, expectedHash }) };
+} catch (e) {
+ if(e instanceof Error) throw e;
+ else return { status: "error", error: e as any };
+}
+},
+/** @see crates/notecore/src/commands/loopback.rs */
+async loopbackConsentRevoke(pluginId: string, port: number) : Promise<Result<null, { code: string; message: string; apiCode: string | null; i18n: JsonValue | null; retryAfterMs: number | null }>> {
+ try {
+ return { status: "ok", data: await TAURI_INVOKE("loopback_consent_revoke", { pluginId, port }) };
+} catch (e) {
+ if(e instanceof Error) throw e;
+ else return { status: "error", error: e as any };
+}
+},
+/** @see crates/notecore/src/commands/loopback.rs */
+async httpLoopbackClassify(url: string, pluginId: string, bodyHash: string) : Promise<Result<LoopbackClassification, { code: string; message: string; apiCode: string | null; i18n: JsonValue | null; retryAfterMs: number | null }>> {
+ try {
+ return { status: "ok", data: await TAURI_INVOKE("http_loopback_classify", { url, pluginId, bodyHash }) };
+} catch (e) {
+ if(e instanceof Error) throw e;
+ else return { status: "error", error: e as any };
+}
+},
+/** @see crates/notecore/src/commands/loopback.rs */
+async pluginBodyHash(content: string) : Promise<Result<string, { code: string; message: string; apiCode: string | null; i18n: JsonValue | null; retryAfterMs: number | null }>> {
+ try {
+ return { status: "ok", data: await TAURI_INVOKE("plugin_body_hash", { content }) };
+} catch (e) {
+ if(e instanceof Error) throw e;
+ else return { status: "error", error: e as any };
+}
+},
/** @see crates/notemaid/src/commands/heartbeat.rs */
async heartbeatTriggerNow() : Promise<Result<null, { code: string; message: string; apiCode: string | null; i18n: JsonValue | null; retryAfterMs: number | null }>> {
try {
@@ -3866,6 +3920,70 @@ resident: ResidentStatus }
* の形で、TS は `nativeField(line, 'text')` で表示言語の文にする
*/
export type LocalizedLine = { text: string; i18n: JsonValue }
+/**
+ * `http.fetch` の URL の分類 (WebView の dispatcher が確認の要否を決める材料)
+ */
+export type LoopbackClassification = {
+/**
+ * URL の host が loopback の 3 表記か。false なら他の欄は意味を持たない
+ */
+loopback: boolean; port: number | null;
+/**
+ * 常に拒否するポート (自アプリ / ブラウザが繋がない / 危険なローカルサービス)
+ */
+alwaysDenied: boolean;
+/**
+ * 今のソースの宣言にそのポートがある
+ */
+declared: boolean;
+/**
+ * 同意済み (ディスクの hash と同意の hash が一致し、ポートが同意にある)
+ */
+granted: boolean;
+/**
+ * 動かしている本文がディスクの本文と違う (再起動が要る)
+ */
+stale: boolean }
+/**
+ * 権限ウィンドウの一覧の 1 行 (実在する個体だけ)
+ */
+export type LoopbackConsentRow = ({
+/**
+ * 今のソースの宣言 (正規化済み)。個体が無ければ空
+ */
+declared: number[];
+/**
+ * ディスク上の本文の hash (grant の `expected_hash` に渡す)
+ */
+hash: string;
+/**
+ * 同意済みのポート (宣言にあるものだけ)。stale のときは同意した当時のもの
+ */
+granted: number[];
+/**
+ * 同意はあるが本文が変わっていて、次の使用時に再同意になる
+ */
+stale: boolean }) & { pluginId: string; name: string }
+/**
+ * プラグイン 1 個体の宣言と同意の状態 (プラグイン詳細 / 権限ウィンドウ用)
+ */
+export type LoopbackConsentStatus = {
+/**
+ * 今のソースの宣言 (正規化済み)。個体が無ければ空
+ */
+declared: number[];
+/**
+ * ディスク上の本文の hash (grant の `expected_hash` に渡す)
+ */
+hash: string;
+/**
+ * 同意済みのポート (宣言にあるものだけ)。stale のときは同意した当時のもの
+ */
+granted: number[];
+/**
+ * 同意はあるが本文が変わっていて、次の使用時に再同意になる
+ */
+stale: boolean }
/**
* Misskey の `mutedWords` / `hardMutedWords` の 1 要素。
* 文字列配列なら AND 語群(全語含むとマッチ)、文字列なら `/regex/flags` 形式の正規表現。
|
This was referenced Nov 3, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
変更
なぜ
旧 README は情報が全部同じ重さで並んでいて要点が沈んでいた。旧ヒーロー文は BRANDING.md が「主張しないこと」に挙げる機能説明寄りの文で、README と食い違っていた。
備考
pnpm lint:docs/ biome / typecheck は pre-commit で通過🤖 Generated with Claude Code