好きなものだけ書く。ポジティブに。

好きなことを楽しく。プログラミング、写真、音楽、ガジェットとか。

Knock の Slack 拡張で、属人化を一気に飛び越えられそう

おつかれさまです!のぶじゃすです。

今日 Knock のドキュメントを眺めていたら、ものすごく良さそうな機能を見つけたのでシェアします。

https://docs.knock.app/integrations/extensions/slack

Slack で @Knock するだけで Knock の agent が動く

ざっくり言うと、Slack のワークスペースに Knock の拡張を入れると、

  • Slack の DM から Knock agent に話しかけられる
  • 任意のチャンネルで @Knock と mention するだけで agent セッションが始まる

これだけ。本当にこれだけ。Knock のダッシュボードを開かなくても、Slack のいつもの会話の中から「@Knock 新規ユーザー向けのオンボーディング workflow を作って」みたいな投げ方が出来る。

何が嬉しいの?個人的に刺さったのはここ

Knock とコードの分断が地味にめんどくさい問題、これは現場あるあるだと思っていて。

  • coding agent に MCP を繋ぐ案も一瞬考えたんですが、全開発者の手元に繋ぐの面倒
  • うちは社内で 非エンジニアも coding agent を使っている ので、その人たちのところにも MCP を整えるのが現実的に重い
  • 結果として Knock の対応が属人化 していた

Slack 拡張なら、開発者も非エンジニアも、すでに毎日使っている Slack の中から同じ入口で Knock を触れる。これが大きい。MCP の設定も要らないし、ツールの起動先を覚える必要もない。

環境の指定もプロンプトで出来る

デフォルトは development 環境で動くんですが、プロンプト内で環境を指定できるのが地味に便利。

例えばこんな書き方。

@Knock in the production environment, update the subject line of the welcome email to 'Welcome to our platform!'

手数が減るのは正義です。

試してみる

明日から触ってみようと思います。Slack 拡張のインストールは Settings > Extensions から「Connect」を押すだけのようなので、すぐに試せそう。

これで Knock 周りの属人化が一段下がると、運用がだいぶ楽になりそうでワクワクしています。

アクセスありがとうございます🙇‍♂️

ここまで読んでいただき誠にありがとうございました。もしこの記事が役に立ったらはてブや、Twitterのフォローしていただけると大変喜びます😊

Google検索、辞めました

おつかれさまです!のぶじゃすです。

タイトルの通りなのですが、Chromeのタイトルバーに文字列を入力してEnterを押した時に検索される検索サイトを変えちゃいました。

今まではデフォルトのGoogleだったのですが、 https://www.perplexity.ai/ に変更しました。 PerplexityAI はAI検索のツールです。

なぜ変えたのか

  • Google検索する時のような入力で検索出来るので、行動に変化が少ない
  • 初めてPerplexityAI上で検索してみた時の体験で驚きしかなかった
  • 初めてPerplexityAI上で検索してから、Chromeの検索を変更するまでの導線が自然だった
  • 無料でもGoogle検索より欲しい結果に早くたどり着ける感覚を得られた
  • 5日間ぐらい使ってみて困ることがなかった

普通、はじめはうさぎのことを聞くよね

Proに課金するかどうかは迷ってる

  • 無料でも異常に便利
  • 応援のために課金したいくらいの気持ち
  • GPT4oとか、Claude-3、Sonar Largeなど他モデルを利用出来るのは嬉しい・・・のか?
  • 画像生成もあると嬉しい・・・のか?

アクセスありがとうございます🙇‍♂️

ここまで読んでいただき誠にありがとうございました。もしこの記事が役に立ったらはてブや、Twitterのフォローしていただけると大変喜びます😊

Durable Functionsで引数を受け取る方法を解説

おつかれさまです!のぶじゃすです。

Azure 関数アプリ で Timeoutの制限や複雑な処理を整理するために Durable Functions という機能があります。とても便利なのでAzure 関数アプリを使っている人は是非試してみると良いと思います。

learn.microsoft.com

今回は、Durable Functions でHTTPトリガーやService Bugトリガーで処理に引数に受け渡す方法が明記されている記事が見つけられなかったので備忘録的な記事です。さくっと結論のみ書きますー

引数の渡し方

learn.microsoft.com

const client = df.getClient(context);
const instanceId: string = await client.startNew(
  request.params.orchestratorName,
  { input: "input string!" }
);

startNew 関数*1 の第2引数の input プロパティ*2 にJSONシリアライザブルな値を渡せる。

引数の受け取り方

const someHandler: OrchestrationHandler = function* (
  context: OrchestrationContext
) {
  const input = context.df.getInput();

OrchestrationContextdf.getInput() 関数*3 で渡した値が受け取れる。

アクセスありがとうございます🙇‍♂️

ここまで読んでいただき誠にありがとうございました。もしこの記事が役に立ったらはてブや、Twitterのフォローしていただけると大変喜びます😊

BigQuery の js api ライブラリ @google-cloud/bigquery を JWT 認証で実行したい

おつかれさまです!のぶじゃすです。

@google-cloud/bigquery を実行する際にJWT認証で実行出来るようにしたい。サービスアカウントを使って利用していたりするとJWT認証じゃないと厳しい場面が発生する。(credentialファイルを置けないとか)

「@google-cloud/bigquery を JWT 認証で実行したい」という文字が書いてある。鍵をもってこちらを見ている女性が背景。

具体的に今回やりたいのは、googleapis と同様に

const auth = new google.auth.JWT(
  env.GOOGLE_EMAIL,
  undefined,
  env.GOOGLE_PRIVATE_KEY, 
  [
    "https://www.googleapis.com/auth/drive",
  ]
);
export const driveService = google.drive({ version: "v3", auth });

みたいな感じで BigQuery のAPIを実行したい。

結論

まずは結論から。これで動きました。調べた事を後述していますので気になる方はどうぞ。

const auth = new google.auth.JWT(
  env.GOOGLE_EMAIL,
  undefined,
  env.GOOGLE_PRIVATE_KEY, 
  [
    "https://www.googleapis.com/auth/drive",
  ]
);

new BigQuery({
  authClient: auth,
  projectId: `{env.GCP_PROJECT_ID}`
});

BigQuery の API がどうなっているのか調べてみる

BigQuery クラスの constructor は @google-cloud/commonGoogleAuthOptions を継承している
export interface BigQueryOptions extends GoogleAuthOptions

nodejs-bigquery/src/bigquery.ts at main · googleapis/nodejs-bigquery · GitHub

@google-cloud/commonGoogleAuthOptions の実体は google-auth-libraryGoogleAuthOptions
export {GoogleAuthOptions} from 'google-auth-library';

nodejs-common/src/index.ts at main · googleapis/nodejs-common · GitHub

google-auth-libraryGoogleAuthOptions の実体はこれ

google-auth-library-nodejs/src/auth/googleauth.ts at main · googleapis/google-auth-library-nodejs · GitHub

googleapis のAPIがどうなっているのか調べてみる

Drive クラスの constructorgoogleapis-commonGlobalOptions を利用している
 constructor(options: GlobalOptions, google?: GoogleConfigurable) {

google-api-nodejs-client/src/apis/drive/v3.ts at main · googleapis/google-api-nodejs-client · GitHub

googleapis-commonGlobalOptionsauthgoogle-auth-library の OAuth2Client や GoogleAuth を渡せる
export interface GlobalOptions extends MethodOptions {
  auth?: GoogleAuth | OAuth2Client | BaseExternalAccountClient | string;
}

nodejs-googleapis-common/src/api.ts at main · googleapis/nodejs-googleapis-common · GitHub

new google.auth を探ってみる

googleapis-commonAuthPlusgoogle.auth の実体
export class GoogleApis extends GeneratedAPIs {
  private _discovery = new Discovery({debug: false, includePrivate: false});
  auth = new AuthPlus();

google-api-nodejs-client/src/googleapis.ts at main · googleapis/google-api-nodejs-client · GitHub

AuthPlusJWTgoogle-auth-libraryJWT
export class AuthPlus extends GoogleAuth {
  JWT = JWT;

nodejs-googleapis-common/src/authplus.ts at main · googleapis/nodejs-googleapis-common · GitHub

google-auth-libraryJWTOAuth2Client の継承
export class JWT extends OAuth2Client

google-auth-library-nodejs/src/auth/jwtclient.ts at main · googleapis/google-auth-library-nodejs · GitHub

ということで GoogleAuthOptionsJWT を渡せる手段がありそうか探してみる

export interface GoogleAuthOptions<T extends AuthClient = JSONClient> {
  /**
   * An `AuthClient` to use
   */
  authClient?: T;

JSONClient という型がある

export type JSONClient =
  | JWT
  | UserRefreshClient
  | BaseExternalAccountClient
  | ExternalAccountAuthorizedUserClient
  | Impersonated;

JWT が渡せそうだ!

動いた

ということで以下のようにしたら動きました。納得感持って繋げられたのでよかった。

new BigQuery({
  authClient: auth,
  projectId: `{env.GCP_PROJECT_ID}`
});

アクセスありがとうございます🙇‍♂️

ここまで読んでいただき誠にありがとうございました。もしこの記事が役に立ったらはてブや、Twitterのフォローしていただけると大変喜びます😊

Next.JS App Router でURLクエリー文字列を取得するのはクライアントコンポーネントとpage.tsxで出来る

きっとURLクエリー文字列を使ってなにか魅力的なものを検索していたりするはずの女性のイラスト
なにか検索していますね。クエリー文字列をきっと使っているはずです

おつかれさまです!のぶじゃすです。

URLクエリー文字列を取得する方法

https://example.com/anypage?search=abcdefg の様なURLのクエリー文字列をNext.jsのApp Routerを用いて取得する方法について解説します。

Next.JS App Router ではクエリー文字列を取得する2つの主な方法があります。

  1. クライアントコンポーネントで useSearchParams を使う方法
  2. page.tsxsearchParams を参照する方法

Next.jsのApp Router導入後、ClientとServerの両方を考慮してコーディングする必要が出てきました。 書き味が少し違うので何が何に対比していて、どこに制限があるのかを意識しないと素早く書けないです。 この辺りが頭に入っているのといないのでは、設計時に見通せる世界が広がります。

1. クライアントコンポーネントで useSearchParams を使う方法

"use client";
import { useSearchParams } from "next/navigation";

export const PresentationSearchPanel = () => {
  const sParams = useSearchParams();
  const search = sParams.get("search");
  return <div>{search}</div>;
};

詳細についてはNext.js公式ドキュメントを参照してください。 nextjs.org

2. page.tsxで searchParams を参照する方法

export default async function AnyPage({
  searchParams,
}: {
  searchParams: z.infer<typeof formSchema>;
}) {
  return <div>{searchParams.search}</div>
});

詳細についてはNext.js公式ドキュメントを参照してください。 nextjs.org

検証環境

package.json 抜粋

"next": "^13.5.2",

next.config.mjs 抜粋

const config = {
  reactStrictMode: true,
  experimental: {
    serverActions: true,
  },
};

アクセスありがとうございます🙇‍♂️

ここまで読んでいただき誠にありがとうございました。もしこの記事が役に立ったらはてブや、Twitterのフォローしていただけると大変喜びます😊

Phaser 3.60.0 で六角形(Hexagon)を描く方法、あるいは本業以外のプログラミングを書くということ

Phaserを試してみたくてやってみた。 sinとcosが思い出せなくて泣いた。手触り感的には結構悪くない。きっとこういうメソッドあるんだろうなーが当たる確率が高い。

stability.ai で生成したプログラミングで正六角形を書く女性
stability.ai で生成したプログラミングで正六角形を書く女性

全然まったく、決して本業とは関係ない。本業はそれなりに忙しくさせてもらっているが、スキマで違うプログラミングを書いたりすると気分転換になるし楽しい。

完成がいつになるのかは分からない。それでもいい。本業でも発想が柔らかくなったりいい効果も少しだけある。

「今日は夜1時間だけやれるように時間作るぞ」と考えて生きていると少し前のめりに動ける。ほんのちょっとだけ潤う。

See the Pen Phaser Hexagon Example by noblejasper (@noblejasper) on CodePen.