バージョン: v0.0.3-2 (Phase 3-2) 最終更新: 2026-01-19 (JST) 対象: Promps コアライブラリと統合する開発者
このドキュメントは、Promps Phase 0 コアライブラリの完全な API リファレンスを提供します。ライブラリは以下で使用できるパーシングとプロンプト生成機能を公開します:
- CLI アプリケーション
- GUI アプリケーション(Tauri)
- 外部ツール
- テストフレームワーク
インポート:
use promps::{PromptPart, parse_input, generate_prompt};型アノテーション付きの単一の意味的単位(文/節)を表現します。
定義:
#[derive(Debug, Clone)]
pub struct PromptPart {
pub is_noun: bool, // 型アノテーション(名詞 or その他)
pub text: String, // 正規化されたテキスト(プレフィックス除去済み)
}フィールド:
| フィールド | 型 | 説明 |
|---|---|---|
is_noun |
bool |
文が _N: マーカーを含む場合 true、それ以外は false |
text |
String |
全ての _N: プレフィックスが除去された文のテキスト |
トレイト:
Debug:{:?}で出力可能Clone:.clone()でクローン可能
例:
let part = PromptPart {
is_noun: true,
text: "ユーザー が 注文 を 作成".to_string(),
};
println!("{:?}", part);
// 出力: PromptPart { is_noun: true, text: "ユーザー が 注文 を 作成" }生の DSL 入力テキストを構造化された PromptPart ベクターにパースします。
シグネチャ:
pub fn parse_input(input: &str) -> Vec<PromptPart>パラメータ:
| パラメータ | 型 | 説明 |
|---|---|---|
input |
&str |
スペース区切りトークンを持つ生の DSL 入力テキスト |
戻り値:
Vec<PromptPart>: パースされたプロンプトパーツのベクター
パーシングルール:
- 行分割: 改行(
\n)で分割 - 文分割: ダブルスペース(またはそれ以上)で分割
- トークン分割: シングルスペースで分割
- 名詞検出: 任意のトークンで
_N:プレフィックスをスキャン - テキスト再構築: プレフィックスを除去して文を再構築
エッジケース:
| 入力 | 結果 | 備考 |
|---|---|---|
| 空文字列 | vec![] |
空のベクターを返す |
| 空白のみ | vec![] |
空白はトリムされ無視される |
| 空行 | スキップ | 空行は無視される |
| 複数スペース | 文区切り | 2+ スペース = 文の境界 |
例 1: 基本的な使用
let input = "_N:ユーザー が _N:注文 を 作成 説明文です";
let parts = parse_input(input);
assert_eq!(parts.len(), 2);
assert_eq!(parts[0].is_noun, true);
assert_eq!(parts[0].text, "ユーザー が 注文 を 作成");
assert_eq!(parts[1].is_noun, false);
assert_eq!(parts[1].text, "説明文です");例 2: 複数行入力
let input = "_N:機能名
説明文です
_N:対象ユーザー 開発者向け";
let parts = parse_input(input);
assert_eq!(parts.len(), 3);
// パート 1: 機能名 (NOUN)
// パート 2: 説明文です
// パート 3: 対象ユーザー 開発者向け (2 文を持つ NOUN)例 3: 空入力
let input = "";
let parts = parse_input(input);
assert_eq!(parts.len(), 0);例 4: 文中の名詞
let input = "これは _N:変数 を 使います";
let parts = parse_input(input);
assert_eq!(parts.len(), 1);
assert_eq!(parts[0].is_noun, true);
assert_eq!(parts[0].text, "これは 変数 を 使います");時間計算量: O(m × k)、m = トークン数、k = 平均トークン長
メモリ割り当て:
- 各
PromptPartに新しいStringを割り当て - 合計: O(n)、n = 入力の総文字数
PromptPart ベクターからフォーマットされたプロンプト文字列を生成します。
シグネチャ:
pub fn generate_prompt(parts: &[PromptPart]) -> Stringパラメータ:
| パラメータ | 型 | 説明 |
|---|---|---|
parts |
&[PromptPart] |
PromptPart インスタンスのスライス |
戻り値:
String:(NOUN)アノテーション付きのフォーマットされたプロンプト
出力フォーマット:
{text} (NOUN)\n ← is_noun == true の場合
{text}\n ← is_noun == false の場合
エッジケース:
| 入力 | 出力 | 備考 |
|---|---|---|
| 空スライス | "" |
空文字列 |
| 全て名詞 | 全行が (NOUN) で終わる |
全パートが is_noun == true |
| 名詞なし | (NOUN) アノテーションなし |
全パートが is_noun == false |
例 1: 混合型
let parts = vec![
PromptPart {
is_noun: true,
text: "機能名".to_string(),
},
PromptPart {
is_noun: false,
text: "説明文".to_string(),
},
];
let prompt = generate_prompt(&parts);
assert_eq!(prompt, "機能名 (NOUN)\n説明文\n");例 2: 空ベクター
let parts = vec![];
let prompt = generate_prompt(&parts);
assert_eq!(prompt, "");例 3: 全て名詞
let parts = vec![
PromptPart { is_noun: true, text: "A".to_string() },
PromptPart { is_noun: true, text: "B".to_string() },
];
let prompt = generate_prompt(&parts);
assert_eq!(prompt, "A (NOUN)\nB (NOUN)\n");時間計算量: O(p × t)、p = パーツ数、t = 平均テキスト長
メモリ割り当て:
- 単一
String割り当て(段階的に拡張) - 合計: O(n)、n = 総出力文字数
単一のトークンを PromptPart にパースします。
シグネチャ:
impl PromptPart {
pub fn from_token(token: &str) -> Self
}パラメータ:
| パラメータ | 型 | 説明 |
|---|---|---|
token |
&str |
単一トークン文字列(_N: プレフィックスを含む可能性あり) |
戻り値:
PromptPart: パースされたインスタンス
動作:
- トークンが
_N:で始まるかチェック - はいの場合: プレフィックスを除去、
is_noun = trueを設定 - いいえの場合: トークンをそのまま使用、
is_noun = falseを設定
例 1: 名詞トークン
let part = PromptPart::from_token("_N:データベース");
assert_eq!(part.is_noun, true);
assert_eq!(part.text, "データベース");例 2: 非名詞トークン
let part = PromptPart::from_token("を作成");
assert_eq!(part.is_noun, false);
assert_eq!(part.text, "を作成");例 3: エッジケース - 空のプレフィックス
let part = PromptPart::from_token("_N:");
assert_eq!(part.is_noun, true);
assert_eq!(part.text, "");使用上の注意: このメソッドは主に parse_input() によって内部的に使用されます。直接使用はサポートされていますが、典型的なワークフローでは一般的ではありません。
時間計算量: O(n)、n = トークン長
メモリ割り当て: 新しい String を割り当て(O(n))
フロントエンド-バックエンド通信用の Tauri 固有コマンド。
インポート:
use commands::{generate_prompt_from_text, greet};parse_input() + generate_prompt() の Tauri コマンドラッパー。
シグネチャ:
#[tauri::command]
pub fn generate_prompt_from_text(input: String) -> Stringパラメータ:
| パラメータ | 型 | 説明 |
|---|---|---|
input |
String |
生の DSL テキスト(所有) |
戻り値:
String: フォーマットされたプロンプト文字列
フロントエンド使用(JavaScript):
import { invoke } from '@tauri-apps/api/tauri';
const input = "_N:ユーザー が _N:注文 を 作成";
const prompt = await invoke('generate_prompt_from_text', { input });
console.log(prompt);
// 出力:
// ユーザー が 注文 を 作成 (NOUN)バックエンド実装:
pub fn generate_prompt_from_text(input: String) -> String {
let parts = parse_input(&input);
generate_prompt(&parts)
}エラーハンドリング: なし(空でも常に文字列を返す)
Tauri 通信テスト用のヘルスチェックコマンド。
シグネチャ:
#[tauri::command]
pub fn greet(name: String) -> Stringパラメータ:
| パラメータ | 型 | 説明 |
|---|---|---|
name |
String |
挨拶する名前 |
戻り値:
String: 挨拶メッセージ
フロントエンド使用(JavaScript):
const message = await invoke('greet', { name: 'World' });
console.log(message);
// 出力: "Hello, World! Welcome to Promps."目的: Tauri IPC(プロセス間通信)が正しく動作していることを確認する。
use std::io::{self, Read};
use promps::{parse_input, generate_prompt};
fn main() {
// stdin から読み込み
let mut input = String::new();
io::stdin().read_to_string(&mut input).unwrap();
// パースと生成
let parts = parse_input(&input);
let prompt = generate_prompt(&parts);
// stdout に出力
println!("{}", prompt);
}バックエンド (src/commands.rs):
#[tauri::command]
pub fn generate_prompt_from_text(input: String) -> String {
let parts = parse_input(&input);
generate_prompt(&parts)
}フロントエンド (JavaScript):
async function generatePrompt() {
const input = document.getElementById('input').value;
const output = await invoke('generate_prompt_from_text', { input });
document.getElementById('output').textContent = output;
}use promps::{parse_input, generate_prompt};
fn process_batch(inputs: Vec<String>) -> Vec<String> {
inputs
.iter()
.map(|input| {
let parts = parse_input(input);
generate_prompt(&parts)
})
.collect()
}use promps::{parse_input, generate_prompt, PromptPart};
fn process_with_custom_logic(input: &str) -> String {
let mut parts = parse_input(input);
// カスタム処理: メタデータを追加
for part in &mut parts {
if part.is_noun {
part.text = format!("[ENTITY] {}", part.text);
}
}
// 変更されたプロンプトを生成
generate_prompt(&parts)
}明示的なエラーハンドリングなし:
- 無効な入力 → そのままパース(予期しない結果を生成する可能性あり)
- 空の入力 → 空のベクター/文字列を返す
- 不正な形式の入力 → 検証エラーなし
根拠: Phase 0 はコア機能に焦点を当てています。検証は Phase N に延期されます。
計画されたエラー型:
pub enum PrompError {
InvalidSyntax(String),
MissingNoun,
InvalidPattern,
EmptyInput,
}
pub type Result<T> = std::result::Result<T, PrompError>;計画されたシグネチャ:
pub fn parse_input(input: &str) -> Result<Vec<PromptPart>>;
pub fn generate_prompt(parts: &[PromptPart]) -> Result<String>;| 操作 | 入力サイズ | 時間 | メモリ |
|---|---|---|---|
parse_input() |
100 文字 | ~5 μs | ~1 KB |
parse_input() |
1,000 文字 | ~50 μs | ~10 KB |
parse_input() |
10,000 文字 | ~500 μs | ~100 KB |
generate_prompt() |
10 パーツ | ~2 μs | ~500 バイト |
generate_prompt() |
100 パーツ | ~20 μs | ~5 KB |
ハードウェア: x86_64 Linux、Rust 1.70、リリースビルド
注意: これらは概算です。実際のパフォーマンスはハードウェアと入力特性に依存します。
1. アロケーションの再利用:
// ✅ 良い - String を再利用
let mut output = String::with_capacity(1024);
for part in parts {
output.push_str(&generate_prompt(&[part]));
}
// ❌ 悪い - 多数のアロケーション
let mut outputs = Vec::new();
for part in parts {
outputs.push(generate_prompt(&[part]));
}
let output = outputs.join("");2. バッチ処理:
// ✅ 良い - 一度だけパース
let parts = parse_input(&large_input);
for part in &parts {
process(part);
}
// ❌ 悪い - 複数回パース
for line in large_input.lines() {
let parts = parse_input(line);
// ...
}3. 容量の事前割り当て:
// ✅ 良い - サイズが既知の場合事前割り当て
let mut parts = Vec::with_capacity(expected_count);
// ❌ OK - ただし再割り当ての可能性あり
let mut parts = Vec::new();総テスト数: 102(バックエンド 26 + フロントエンド 76)
テスト実行:
# バックエンドテスト(Rust)
cargo test
# フロントエンドテスト(Jest)
cd res/tests && npm test
# 全テスト実行
cargo test && cd res/tests && npm testテストモジュール: src/lib.rs(13 テスト)、src/commands.rs(13 テスト)
テスト例:
#[test]
fn test_parse_input() {
let input = "_N:データベーステーブルブロック機能 データベースのテーブル構造を視覚的に定義する機能です";
let parts = parse_input(input);
assert_eq!(parts.len(), 2);
assert_eq!(parts[0].is_noun, true);
assert_eq!(parts[0].text, "データベーステーブルブロック機能");
assert_eq!(parts[1].is_noun, false);
assert_eq!(parts[1].text, "データベースのテーブル構造を視覚的に定義する機能です");
}テストモジュール: res/tests/blockly-config.test.js(61 テスト)、res/tests/main.test.js(15 テスト)
テストカテゴリ:
- 名詞ブロック: 固定名詞ブロック、カスタム名詞ブロック
- 助詞ブロック: 9種類の助詞(が、を、に、で、と、は、も、から、まで)
- 動詞ブロック: 固定動詞ブロック、カスタム動詞ブロック
- 改行ブロック: 改行ブロック
- ツールボックス: カテゴリ構成
テスト例:
describe('Verb Blocks', () => {
test('verb_analyze block should be defined', () => {
expect(Blockly.Blocks['verb_analyze']).toBeDefined();
});
test('verb_custom block should generate correct DSL', () => {
const block = createMockBlock('verb_custom', { VERB_TEXT: '削除して' });
const code = javascriptGenerator.forBlock['verb_custom'](block);
expect(code).toBe('削除して');
});
});ファイル: tests/integration_test.rs(例)
use promps::{parse_input, generate_prompt};
#[test]
fn test_full_workflow() {
// 準備
let input = "_N:ユーザー が _N:注文 を 作成 説明文";
// 実行
let parts = parse_input(input);
let prompt = generate_prompt(&parts);
// 検証
assert!(prompt.contains("(NOUN)"));
assert!(prompt.contains("説明文\n"));
}API 変更なし:
- コアライブラリ(
src/lib.rs)は変更なし - Tauri コマンドは拡張されたが既存 API は維持
- 100% 後方互換
追加された機能:
- Blockly.js ビジュアルブロックビルダー
- 名詞ブロック(固定 + カスタム)
- リアルタイムプレビュー
API 変更なし: 100% 後方互換
追加された機能:
- 9種類の助詞ブロック(が、を、に、で、と、は、も、から、まで)
- ツールボックスに「助詞」カテゴリ追加
API 変更なし: 100% 後方互換
追加された機能:
- 3種類の固定動詞ブロック(分析して、要約して、翻訳して)
- カスタム動詞ブロック
- ツールボックスに「動詞」カテゴリ追加
破壊的変更が予想されます:
- エラーハンドリング: 関数は
Result<T, PrompError>を返す - 検証: 無効なパターンはエラーを返す
マイグレーション戦略:
// Phase 0(現在)
let parts = parse_input(input);
// Phase N(将来)
let parts = parse_input(input)?; // エラーを伝播
// または
let parts = parse_input(input).unwrap_or_default(); // エラー時デフォルトを使用現在のバージョン: v0.0.3-2 (Phase 3-2)
セマンティックバージョニング:
- Phase 0:
0.0.1(コアライブラリ)✅ 完了 - Phase 1:
0.0.2(GUI 統合)✅ 完了 - Phase 2:
0.0.3(助詞ブロック)✅ 完了 - Phase 3:
0.0.3-2(動詞ブロック)✅ 完了 - Phase N:
1.0.x(ロジックチェック - 最初の安定版リリース)
互換性の約束:
- パッチバージョン(0.1.x): 破壊的変更なし
- マイナーバージョン(0.x.0): 追加機能、後方互換性あり
- メジャーバージョン(x.0.0): 破壊的変更許可
名詞マーカー: _N:
トークン区切り: シングルスペース (0x20)
文区切り: ダブルスペース (0x20 0x20) 以上
改行: \n(文は行内で継続)
例:
_N:User が _N:Order を 作成 説明文です
└─┬──┘ │ └─┬───┘ │ ──┬─ └───┬────┘
名詞 助詞 名詞 助詞 動詞 説明
- コア機能:
CORE_FEATURES.md - アーキテクチャ:
ARCHITECTURE.md - ユーザーガイド:
../../README.md
ドキュメントバージョン: 2.0 最終更新: 2026-01-19 (JST) 次回レビュー: Phase 4 リリース前