۱. مقدمه
Google Workspace Studio به شما امکان میدهد فرایندهای کسبوکار را در برنامههای Google Workspace مانند Gmail، Google Chat، Google Drive، و «کاربرگنگار Google» خودکارسازی کنید. وقتی گردشهای کار شما باید از یک برنامه وب خارجی شروع شود یا منطق سفارشی در محیط ابری خودتان اجرا شود، میتوانید بااستفاده از برافزای Google Workspace در Node.js در Cloud Run، «استودیوِ Google Workspace» را با HTTP گسترش دهید:
- مرحله آغازگر سفارشی (
workflowTrigger): با فراخوانی «میانای برنامهسازی کاربردی»triggers.fireREST در Google Workspace Studio، وقتی رویداد خارجی رخ میدهد (مثلاً مشتری در درگاه وب داخلی درخواست پشتیبانی ارسال میکند) جریان Google Workspace Studio را شروع میکند. - مرحله کنش سفارشی (
workflowAction): متغیرها را از مراحل قبلی در جریان دریافت میکند، منطق سفارشی یا استنباط هوش مصنوعی را در سرویس Node.js شما اجرا میکند، و متغیرهای برونداد را به Google Workspace Studio برمیگرداند.
در این codelab، افزونه کامل Node.js HTTP برای Google Workspace Studio را در Cloud Run میسازید و مستقر میکنید، از Cloud Firestore برای ماندگار کردن اشتراکهای راهانداز جاری و درخواستهای ارسالشده در سراسر تجدیدنظرهای محتوی استفاده میکنید، و بااستفاده از Gemini 3.8 Flash (gemini-3.8-flash) در پلاتفرم عامل Gemini Enterprise با برگشتی مقاوم دربرابر تطبیق کلیدواژه، فوریت درخواست را در مرحله کنش سفارشی خود طبقهبندی میکنید.
آنچه خواهید ساخت
- برنامه وب درگاه سریع پشتیبانی و «برافزای Google Workspace» با HTTP که با Node.js، Express، و Firestore در Cloud Run ساخته شده است.
- یک مرحله آغازگر سفارشی درخواست پشتیبانی جدید (
supportTicketTrigger) که اشتراکهای جاری گردش کار را درstudio_triggersمجموعه Firestore حفظ میکند، درخواستهای ارسالشده را درsupport_ticketsمجموعه Firestore ثبت میکند، و هرگاه درگاه وب درخواستی ارسال شود اجرا میشود—ticketTitleوticketDescriptionرا به گردش کار «استودیوِ Google Workspace» منتقل میکند. - یک مرحله کنش سفارشی تشخیص فوریت (
urgencyDetectorStep) که فوریت درخواست پشتیبانی را بااستفاده از Gemini 3.8 Flash (gemini-3.8-flash) در پلاتفرم Gemini Enterprise Agent (aiplatform.googleapis.com) طبقهبندی میکند، با بازگشت خودکار به تطبیق کلیدواژه (urgent،blocker،critical).
آنچه خواهید آموخت
- نحوه پیکربندی مانیفست استقرار «برافزای Google Workspace» با پروتکل HTTP (
deployment.json) با عناصرworkflowTriggerوworkflowAction. - نحوه ماندگار کردن اشتراکهای راهانداز «استودیوِ Google Workspace» (
triggerId،notifyUri، وuserOAuthToken) درstudio_triggersمجموعه Firestore و راهاندازی جریانها بااستفاده ازtriggers.fireREST API. - نحوه ساختن گام سفارشی
workflowActionدر Node.js بااستفاده از برونداد ساختاری Gemini 3.8 Flash (gemini-3.8-flash) در پلاتفرم Gemini Enterprise Agent با کلیدواژه برگشتی.
پیشنیازها
- حساب Google Workspace با دسترسی به استودیو Google Workspace.
- پروژه Google Cloud با صورتحساب فعال که در همان سازمان Google Workspace حساب کاربری شما ایجاد شده است تا بتوانید استقرار افزونههای منتشرنشده را برای آزمایش نصب کنید.
۲. راهاندازی پروژه Google Cloud و Firestore
در این مرحله، صفحه رضایت OAuth پروژه خود را پیکربندی میکنید، «میاناهای برنامهسازی کاربردی» Google Cloud و Google Workspace موردنیاز را در Cloud Shell فعال میکنید، پایگاه داده (default) Firestore خود را آماده میکنید، و حساب سرویس مجوز برافزای خود را مقداردهی اولیه میکنید.
- کنسول Google Cloud را باز کنید، پروژه Google Cloud خود را انتخاب کنید، و روی نماد فعالسازی Cloud Shell در نوار پیمایش بالا کلیک کنید.
- صفحه کسب رضایت OAuth را پیکربندی کنید تا Google Workspace بتواند کارخواه OAuth را برای برافزای شما آماده کند:
- صفحه «نمانام پلاتفرم اصالتسنجی Google» را باز کنید.
- اگر درخواست شد، روی شروع به کار کلیک کنید. (اگر صفحه موافقت شما ازقبل پیکربندی شده است، به مرحله ۳ بروید.)
- در بخش اطلاعات برنامه،
Support Extensionرا برای نام برنامه وارد کنید، ایمیل پشتیبانی کاربر را انتخاب کنید، و روی بعدی کلیک کنید. - در بخش مخاطب، داخلی را انتخاب کنید و روی بعدی کلیک کنید.
- در بخش اطلاعات تماس، نشانی ایمیلتان را وارد کنید و روی بعدی کلیک کنید.
- در بخش تکمیل، با خطمشی دادههای کاربر «سرویسهای Google API» موافقت کنید، روی ادامه کلیک کنید، و سپس روی ایجاد کلیک کنید.
- در Cloud Shell، پروژه فعال خود را تنظیم کنید (
YOUR_PROJECT_IDرا با شناسه پروژه Google Cloud خود جایگزین کنید) و میاناهای برنامهسازی کاربردی موردنیاز را فعال کنید:gcloud config set project YOUR_PROJECT_ID gcloud services enable \ aiplatform.googleapis.com \ firestore.googleapis.com \ run.googleapis.com \ cloudbuild.googleapis.com \ artifactregistry.googleapis.com \ appsmarket-component.googleapis.com \ gsuiteaddons.googleapis.com \ workspacestudio.googleapis.com - پایگاه داده
(default)Firestore خود را درus-central1تدارک ببینید (اگر ازقبل وجود ندارد) و حساب سرویس «برافزاهای Google Workspace» خود را مقداردهی اولیه کنید:gcloud firestore databases describe --database="(default)" >/dev/null 2>&1 || \ gcloud firestore databases create \ --database="(default)" \ --location=us-central1 \ --type=firestore-native \ --quiet gcloud workspace-add-ons get-authorization
۳. ساختن برنامه Node.js با Firestore و Gemini 3.8 Flash
در این مرحله، برنامه Node.js را در ~/studio-support-addon میسازید. برای اینکه کد را واحدی و خوانا نگه دارید، پروژه را در پنج فایل متمرکز سازماندهی میکنید:
firestore.js: کارخواه Cloud Firestore (مجموعههایstudio_triggersوsupport_tickets) را مقداردهی اولیه میکند و ژتونهای OAuth ذخیرهشده در حافظه نهان را بازآوری میکند.-
starter.js: وبقلابهای مرحله آغازگر سفارشی بلیت پشتیبانی جدید را پیادهسازی میکند (/onConfigTriggerو/onManageTrigger). action.js: وبقلابهای مرحله کنش سفارشی تشخیص فوریت (/onConfigUrgencyو/onExecuteUrgency) را بااستفاده از Gemini 3.8 Flash (gemini-3.8-flash) با برگشتی تطبیق کلیدواژه پیادهسازی میکند.portal.js: رابط کاربری وب درگاه سریع پشتیبانی (GET /) را ارائه میدهد و محرکهای فعال Google Workspace Studio (POST /api/submit-ticket) را راهاندازی میکند.-
index.js: همه مسیرهای Express را بههم متصل میکند و سرور HTTP را شروع میکند.
مقداردهی اولیه پروژه و package.json
- فهرست راهنمای پروژه بسازید و به آن پیمایش کنید:
mkdir -p ~/studio-support-addon && cd ~/studio-support-addon - ساختن
package.jsonباexpress،@google-cloud/firestore، و@google/genai:cat << 'EOF' > package.json { "name": "studio-support-addon", "version": "1.0.0", "type": "module", "main": "index.js", "scripts": { "start": "node index.js" }, "dependencies": { "@google-cloud/firestore": "^7.11.0", "@google/genai": "^1.0.0", "express": "^4.21.2" } } EOF
firestore.js — وضعیت Firestore همرسانیشده و بازآوری کد OAuth
برای مدیریت دو مجموعه Firestore و تازه نگه داشتن ژتونهای OAuth کاربر ذخیرهشده در حافظه نهان، firestore.js را ایجاد کنید:
studio_triggers: اشتراکهای جاری فعال Google Workspace Studio (triggerId،notifyUri، وuserOAuthToken) را ذخیره میکند تا از رویدادهای مقیاسبندی به صفر و راهاندازی مجدد محتوی Cloud Run جان سالم بهدر ببرند.support_tickets: سابقه هر بلیت پشتیبانی ارائهشده ازطریق درگاه را ذخیره میکند.refreshTokenInFirestore(req): هروقت «استودیوِ Google Workspace» با هریک از نقاط پایانی وبقلاب شما تماس میگیرد،authorizationEventObject.userOAuthTokenکوتاهمدتی را اضافه میکند. این دستیار اسناد محرک فعال را با جدیدترین کد بهروزرسانی میکند تا تماسهای پسزمینهtriggers.fireهمچنان مجاز باقی بمانند.
cat << 'EOF' > firestore.js
import { Firestore } from '@google-cloud/firestore';
export const db = new Firestore({
projectId: process.env.GOOGLE_CLOUD_PROJECT || undefined,
databaseId: '(default)',
ignoreUndefinedProperties: true,
});
export const triggersCollection = db.collection(
process.env.FIRESTORE_TRIGGERS_COLLECTION || 'studio_triggers'
);
export const ticketsCollection = db.collection(
process.env.FIRESTORE_TICKETS_COLLECTION || 'support_tickets'
);
// Keep cached userOAuthToken fresh across active trigger documents
export async function refreshTokenInFirestore(req) {
const freshToken = req.body?.authorizationEventObject?.userOAuthToken;
if (!freshToken) return;
try {
const snapshot = await triggersCollection.get();
if (snapshot.empty) return;
const batch = db.batch();
snapshot.docs.forEach((doc) => {
batch.set(
doc.ref,
{ userOAuthToken: freshToken, updatedAt: new Date().toISOString() },
{ merge: true }
);
});
await batch.commit();
} catch (err) {
console.error('Error refreshing OAuth token in Firestore:', err.message);
}
}
EOF
starter.js — مرحله شروع سفارشی (workflowTrigger)
برای پیادهسازی دو نقطه پایانی وبقلاب موردنیاز مرحله آغازگر سفارشی Google Workspace Studio، starter.js را ایجاد کنید:
onConfigTrigger(POST /onConfigTrigger): زمانی فراخوانده میشود که کاربر درخواست پشتیبانی جدید را بهعنوان شروعکننده جاریسازی خود در «استودیو Google Workspace» انتخاب کند. کنش پیمایشpushCardرا برمیگرداند که شروعکننده را توصیف میکند.onManageTrigger(POST /onManageTrigger): وقتی کاربر جریانی را روشن (req.body.workflow.triggerCreation) یا خاموش میکند / آن را حذف میکند (req.body.workflow.triggerDeletion)، فراخوانده میشود. سند اشتراک را در مجموعهstudio_triggersFirestore ذخیره یا حذف میکند.
cat << 'EOF' > starter.js
import { triggersCollection, refreshTokenInFirestore } from './firestore.js';
// Custom Starter Configuration Card
export async function onConfigTrigger(req, res) {
await refreshTokenInFirestore(req);
res.status(200).json({
action: {
navigations: [
{
pushCard: {
sections: [
{
header: 'Support Ticket Listener',
widgets: [
{
textParagraph: {
text: 'This starter listens for new tickets submitted through the Support Quick Portal and stores subscriptions in Firestore.',
},
},
],
},
],
},
},
],
},
});
}
// Custom Starter Subscription Lifecycle (Firestore studio_triggers collection)
export async function onManageTrigger(req, res) {
try {
const triggerCreation = req.body?.workflow?.triggerCreation;
const triggerDeletion = req.body?.workflow?.triggerDeletion;
const userOAuthToken =
req.body?.authorizationEventObject?.userOAuthToken || null;
if (triggerCreation?.triggerId) {
const triggerId = String(triggerCreation.triggerId);
const docId = encodeURIComponent(triggerId);
await triggersCollection.doc(docId).set(
{
triggerId,
notifyUri: triggerCreation.notifyUri || null,
...(userOAuthToken ? { userOAuthToken } : {}),
updatedAt: new Date().toISOString(),
},
{ merge: true }
);
}
if (triggerDeletion?.triggerId) {
const triggerId = String(triggerDeletion.triggerId);
const docId = encodeURIComponent(triggerId);
await triggersCollection.doc(docId).delete();
}
if (!triggerCreation && !triggerDeletion && userOAuthToken) {
await refreshTokenInFirestore(req);
}
} catch (err) {
console.error('Error in /onManageTrigger:', err.message);
}
res.status(200).json({});
}
EOF
action.js — مرحله کنش سفارشی (workflowAction) با Gemini 3.8 Flash
برای پیادهسازی دو نقطه پایانی وبقلاب موردنیاز مرحله کنش سفارشی Google Workspace Studio، action.js را ایجاد کنید:
onConfigUrgency(POST /onConfigUrgency): کارت پیکربندی با ابزارهtextInputبرمیگرداند کهhostAppDataSource.workflowDataSource.includeVariables: trueرا تنظیم میکند و به کاربران امکان میدهد متغیرticketDescriptionرا که توسط مرحله شروع تولید شده است انتخاب کنند.onExecuteUrgency(POST /onExecuteUrgency): ورودیticketDescriptionرا ازreq.body.workflow.actionInvocation.inputsمیخواند، تأثیر کسبوکار و فوریت آن را بااستفاده از Gemini 3.8 Flash (gemini-3.8-flash) در پلاتفرم Gemini Enterprise Agent با برونداد ساختاریافته (responseSchemaenum["High", "Normal"]) طبقهبندی میکند، اگر فراخوانی مدل ناموفق باشد بهdetectKeywordUrgency()(urgent،blocker،critical) برمیگردد، و متغیر بروندادurgencyLevelرا بااستفاده ازhostAppAction.workflowAction.returnOutputVariablesActionبرمیگرداند.
cat << 'EOF' > action.js
import { GoogleGenAI, Type } from '@google/genai';
import { refreshTokenInFirestore } from './firestore.js';
// Initialize Google GenAI SDK for the Gemini Enterprise Agent Platform
const ai = new GoogleGenAI({
vertexai: true,
project: process.env.GOOGLE_CLOUD_PROJECT,
location: 'global',
});
// Fallback keyword classifier if the Gemini API call is unavailable
export function detectKeywordUrgency(description) {
const lower = (description || '').toLowerCase();
return lower.includes('urgent') ||
lower.includes('blocker') ||
lower.includes('critical')
? 'High'
: 'Normal';
}
// Custom Action Step Configuration Card
export async function onConfigUrgency(req, res) {
await refreshTokenInFirestore(req);
res.status(200).json({
action: {
navigations: [
{
pushCard: {
sections: [
{
header: 'Urgency Detector Step',
widgets: [
{
textInput: {
name: 'ticketDescription',
label: 'Source Description',
hintText:
'Select the description variable outputted by the starter',
hostAppDataSource: {
workflowDataSource: {
includeVariables: true,
},
},
},
},
],
},
],
},
},
],
},
});
}
// Custom Action Step Execution: Gemini 3.8 Flash with keyword fallback
export async function onExecuteUrgency(req, res) {
await refreshTokenInFirestore(req);
const inputs = req.body?.workflow?.actionInvocation?.inputs || {};
const description = inputs.ticketDescription?.stringValues?.[0] || '';
let urgencyLevel = detectKeywordUrgency(description);
try {
const response = await ai.models.generateContent({
model: 'gemini-3.8-flash',
contents: `Evaluate the business impact and time sensitivity of this support ticket description and classify its urgency:\n\n${description}`,
config: {
responseMimeType: 'text/x.enum',
responseSchema: {
type: Type.STRING,
enum: ['High', 'Normal'],
},
},
});
const candidate = (response.text || '').trim();
if (candidate === 'High' || candidate === 'Normal') {
urgencyLevel = candidate;
}
} catch (err) {
console.error('Gemini fallback to keyword matching:', err.message);
}
res.status(200).json({
hostAppAction: {
workflowAction: {
returnOutputVariablesAction: {
variables: {
urgencyLevel: {
stringValues: [urgencyLevel],
},
},
},
},
},
});
}
EOF
portal.js — پشتیبانی از رابط کاربری «درگاه سریع» و توزیعکننده triggers.fire
portal.js را برای ارائه درگاه وب و ارسال درخواستهای بلیت به Google Workspace Studio ایجاد کنید:
renderPortal(GET /): مجموعهstudio_triggersFirestore را پُرسمان میکند تا نشان دهد چند راهانداز فعال Google Workspace Studio ثبت شده است و فرم ارسال درخواست پشتیبانی HTML را ارائه میدهد.submitTicket(POST /api/submit-ticket): در همه سندهای محرک فعال درstudio_triggersتکرار میکند، نقطه پایانیtriggers.fire«استودیو Google Workspace» (https://workspacestudio.googleapis.com/v1/triggers/{triggerId}:fire) را با متغیرهای بروندادticketTitleوticketDescriptionوrequestIdمنحصربهفرد فرا میخواند، و درخواست پشتیبانی را در مجموعهsupport_ticketsFirestore ذخیره میکند.
cat << 'EOF' > portal.js
import { triggersCollection, ticketsCollection } from './firestore.js';
// Support Quick Portal UI
export async function renderPortal(req, res) {
let activeCount = 0;
try {
const snapshot = await triggersCollection.get();
activeCount = snapshot.size;
} catch (err) {
console.error('Error reading studio_triggers collection:', err.message);
}
res.status(200).send(`<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Support Quick Portal</title>
<style>
body { font-family: Arial, sans-serif; padding: 24px; max-width: 540px; margin: auto; color: #202124; }
.badge { background: #e8f0fe; color: #1967d2; padding: 8px 12px; border-radius: 6px; font-size: 14px; margin-bottom: 16px; }
label { font-weight: bold; display: block; margin-top: 16px; }
input, textarea { width: 100%; margin-top: 6px; padding: 10px; box-sizing: border-box; border: 1px solid #dadce0; border-radius: 4px; }
button { background-color: #1a73e8; color: white; border: none; padding: 10px 18px; margin-top: 16px; font-weight: bold; cursor: pointer; border-radius: 4px; }
button:hover { background-color: #1557b0; }
#status { margin-top: 16px; font-weight: bold; }
</style>
</head>
<body>
<h2>Support Quick Portal</h2>
<div class="badge">
Active Google Workspace Studio triggers in Firestore (<code>studio_triggers</code>):
<strong id="trigger-count">${activeCount}</strong>
</div>
<p>Submit a support ticket below to fire your Google Workspace Studio flow.</p>
<label for="title">Ticket Title</label>
<input type="text" id="title" placeholder="e.g. Database failure">
<label for="description">Issue Description</label>
<textarea id="description" rows="4" placeholder="Describe the issue..."></textarea>
<button onclick="submitTicket()">Submit Ticket</button>
<div id="status"></div>
<script>
async function submitTicket() {
const title = document.getElementById('title').value.trim();
const description = document.getElementById('description').value.trim();
const statusEl = document.getElementById('status');
if (!title || !description) {
statusEl.style.color = '#d93025';
statusEl.textContent = 'Please fill out both fields.';
return;
}
statusEl.style.color = '#188038';
statusEl.textContent = 'Submitting ticket...';
try {
const res = await fetch('/api/submit-ticket', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ title, description }),
});
const data = await res.json();
if (data.ok) {
statusEl.textContent =
'Ticket saved to Firestore! Fired ' + data.triggersFired + ' Google Workspace Studio trigger(s).';
} else {
statusEl.style.color = '#d93025';
statusEl.textContent = 'Error: ' + (data.error || 'Unknown error');
}
} catch (err) {
statusEl.style.color = '#d93025';
statusEl.textContent = 'Request failed: ' + err.message;
}
}
</script>
</body>
</html>`);
}
// Portal Form Submission -> Fire Active Google Workspace Studio Triggers
export async function submitTicket(req, res) {
const title = req.body?.title || 'Untitled Ticket';
const description = req.body?.description || '';
const results = [];
try {
const snapshot = await triggersCollection.get();
for (const doc of snapshot.docs) {
const trigger = doc.data();
if (!trigger.triggerId || !trigger.userOAuthToken) continue;
const response = await fetch(
`https://workspacestudio.googleapis.com/v1/triggers/${encodeURIComponent(trigger.triggerId)}:fire`,
{
method: 'POST',
headers: {
Authorization: `Bearer ${trigger.userOAuthToken}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
name: 'triggers/' + trigger.triggerId,
outputs: {
ticketTitle: { stringValues: [title] },
ticketDescription: { stringValues: [description] },
},
requestId:
'req_' + Date.now() + '_' + Math.floor(Math.random() * 1000),
}),
}
);
results.push({ triggerId: trigger.triggerId, status: response.status });
}
await ticketsCollection.add({
title,
description,
triggersFired: results.length,
createdAt: new Date().toISOString(),
});
res.status(200).json({ ok: true, triggersFired: results.length, results });
} catch (err) {
console.error('Error in /api/submit-ticket:', err.message);
res.status(500).json({ ok: false, error: err.message });
}
}
EOF
index.js — نقطه ورودی سرور Express
index.js را ایجاد کنید تا مسیرهای درگاه و نقاط پایانی وبقلاب Google Workspace Studio را در سرور Express HTTP که در PORT (پیشفرض 8080 در Cloud Run) گوش میدهد بههم متصل کنید:
cat << 'EOF' > index.js
import express from 'express';
import { onConfigTrigger, onManageTrigger } from './starter.js';
import { onConfigUrgency, onExecuteUrgency } from './action.js';
import { renderPortal, submitTicket } from './portal.js';
const app = express();
app.use(express.json());
// Support Quick Portal routes
app.get('/', renderPortal);
app.post('/api/submit-ticket', submitTicket);
// Google Workspace Studio Custom Starter Step webhooks
app.post('/onConfigTrigger', onConfigTrigger);
app.post('/onManageTrigger', onManageTrigger);
// Google Workspace Studio Custom Action Step webhooks
app.post('/onConfigUrgency', onConfigUrgency);
app.post('/onExecuteUrgency', onExecuteUrgency);
const PORT = process.env.PORT || 8080;
app.listen(PORT, () => {
console.log(`Support Extension listening on port ${PORT}`);
});
EOF
۴. مستقر کردن در Cloud Run و نصب برافزا
در این مرحله، سرویس Node.js را در Cloud Run مستقر میکنید، اجازههای IAM را برای فراخواننده «برافزاهای Google Workspace» و دسترسی زمان اجرای Firestore و «پلاتفرم عامل» اعطا میکنید، deployment.json مانیفست را تولید میکنید، و استقرار برافزا را نصب میکنید.
- سرویس
support-extensionرا با متغیرهای محیطی پروژه و مجموعه Firestore در Cloud Run مستقر کنید:gcloud run deploy support-extension \ --source . \ --region us-central1 \ --allow-unauthenticated \ --set-env-vars="GOOGLE_CLOUD_PROJECT=$(gcloud config get-value project),FIRESTORE_TRIGGERS_COLLECTION=studio_triggers,FIRESTORE_TICKETS_COLLECTION=support_tickets" \ --quiet - به حساب خدمات «برافزاهای Google Workspace» در سرویس Cloud Run
roles/run.invokerاعطا کنید تا «استودیو Google Workspace» بتواند نقطههای پایانی وبقلاب شما را فراخوانی کند:ADDON_SA=$(gcloud workspace-add-ons get-authorization --format="value(serviceAccountEmail)") gcloud run services add-iam-policy-binding support-extension \ --region=us-central1 \ --member="serviceAccount:${ADDON_SA}" \ --role="roles/run.invoker" \ --quiet -
roles/datastore.user(برای خواندن و نوشتن مجموعههایstudio_triggersوsupport_ticketsFirestore) وroles/aiplatform.user(برای فراخوانی Gemini در «پلاتفرم نماینده Gemini Enterprise») را به حساب سرویس زمان اجرای Cloud Run اعطا کنید:PROJECT_ID=$(gcloud config get-value project) PROJECT_NUMBER=$(gcloud projects describe "${PROJECT_ID}" --format="value(projectNumber)") RUNTIME_SA=$(gcloud run services describe support-extension --region=us-central1 --format="value(spec.template.spec.serviceAccountName)") RUNTIME_SA=${RUNTIME_SA:-"${PROJECT_NUMBER}-compute@developer.gserviceaccount.com"} gcloud projects add-iam-policy-binding "${PROJECT_ID}" \ --member="serviceAccount:${RUNTIME_SA}" \ --role="roles/datastore.user" \ --condition=None \ --quiet gcloud projects add-iam-policy-binding "${PROJECT_ID}" \ --member="serviceAccount:${RUNTIME_SA}" \ --role="roles/aiplatform.user" \ --condition=None \ --quiet - نشانی وب Cloud Run مستقرشده خود را بازیابی کنید و مانیفست
deployment.jsonرا که عناصرsupportTicketTrigger(workflowTrigger) وurgencyDetectorStep(workflowAction) را تعریف میکند تولید کنید:SERVICE_URL=$(gcloud run services describe support-extension --region=us-central1 --format="value(status.url)") cat << EOF > deployment.json { "oauthScopes": [ "https://www.googleapis.com/auth/workspace.studio.trigger", "https://www.googleapis.com/auth/userinfo.email" ], "addOns": { "common": { "name": "Support Extension", "logoUrl": "https://www.gstatic.com/images/branding/productlogos/buganizer/v1/192px.svg" }, "studio": { "flows": { "workflowElements": [ { "id": "supportTicketTrigger", "state": "ACTIVE", "name": "New Support Ticket", "description": "Fires when someone submits a ticket in the Support Quick Portal.", "workflowTrigger": { "inputs": [], "outputs": [ { "id": "ticketTitle", "description": "Ticket Title", "cardinality": "SINGLE", "dataType": { "basicType": "STRING" } }, { "id": "ticketDescription", "description": "Ticket Description", "cardinality": "SINGLE", "dataType": { "basicType": "STRING" } } ], "onConfigFunction": "${SERVICE_URL}/onConfigTrigger", "onManageFunction": "${SERVICE_URL}/onManageTrigger" } }, { "id": "urgencyDetectorStep", "state": "ACTIVE", "name": "Detect Urgency", "description": "Evaluates the ticket description to detect High or Normal urgency.", "workflowAction": { "inputs": [ { "id": "ticketDescription", "description": "Description to scan", "cardinality": "SINGLE", "dataType": { "basicType": "STRING" } } ], "outputs": [ { "id": "urgencyLevel", "description": "Detected Urgency (High / Normal)", "cardinality": "SINGLE", "dataType": { "basicType": "STRING" } } ], "onConfigFunction": "${SERVICE_URL}/onConfigUrgency", "onExecuteFunction": "${SERVICE_URL}/onExecuteUrgency" } } ] } }, "httpOptions": { "authorizationHeader": "SYSTEM_ID_TOKEN" } } } EOF - استقرار «برافزای Google Workspace» را برای حسابتان ایجاد (یا جایگزین) و نصب کنید، و نشانی وب «درگاه سریع پشتیبانی» را چاپ کنید:
gcloud workspace-add-ons deployments create support-extension --deployment-file=deployment.json || \ gcloud workspace-add-ons deployments replace support-extension --deployment-file=deployment.json gcloud workspace-add-ons deployments install support-extension echo "Support Quick Portal URL: ${SERVICE_URL}"
۵. آزمایش کردن مراحل سفارشی در Google Workspace Studio
- Google Workspace Studio را باز کنید (اگر قبلاً باز بوده است، برگه مرورگر را بازآوری کنید) و روی جریان جدید کلیک کنید.
- روی انتخاب یک شروعکننده > افزونه پشتیبانی > درخواست پشتیبانی جدید کلیک کنید.
- روی افزودن مرحله (
+) > افزونه پشتیبانی > تشخیص فوریت کلیک کنید. در فیلد شرح منبع، روی + متغیرها کلیک کنید و شرح درخواست پشتیبانی را انتخاب کنید. - روی افزودن مرحله (
+) کلیک کنید و مرحله گپ > در Chat به من اطلاع بده را اضافه کنید که شامل متغیرهای عنوان درخواست پشتیبانی، سطح فوریت، و شرح درخواست پشتیبانی در پیام باشد. - جریان را در گوشه بالا سمت راست روشن کنید. Google Workspace Studio بلافاصله با نقطه پایانی
/onManageTriggerشما در Cloud Run تماس میگیرد، که اشتراک محرک فعال را در مجموعهstudio_triggersدر Firestore مینویسد. - نشانی وب «درگاه سریع پشتیبانی» (
https://support-extension-...run.app) را در برگه جدیدی باز کنید، تأیید کنید که درگاه1محرک فعال را در Firestore نمایش میدهد، و دو درخواست پشتیبانی برای آزمایش طبقهبندی Gemini 3.8 Flash (gemini-3.8-flash) ارسال کنید:- درخواست پشتیبانی با تأثیر بالا (عنوان درخواست پشتیبانی:
London office lockout، شرح مشکل:All 500 employees in the London office are locked out of their workstations 20 minutes before the board presentation.): حتی بدون کلیدواژههای کدبندیشده سخت مثلurgentیاblocker،gemini-3.8-flashاین درخواست پشتیبانی را بهعنوان فوریتHighطبقهبندی میکند. - درخواست روال (عنوان درخواست:
Conference room adapters، شرح مشکل:Could we order two extra HDMI adapters for the third-floor conference room next month?):gemini-3.8-flashاین درخواست را بهعنوان فوریتNormalطبقهبندی میکند.
- درخواست پشتیبانی با تأثیر بالا (عنوان درخواست پشتیبانی:
- در Google Chat و در برگه فعالیت Google Workspace Studio تأیید کنید که جریان شما برای هر دو درخواست با
Urgency Level: HighوUrgency Level: Normalاجرا شده است.
۶. مرتبسازی
برای جلوگیری از کسر هزینههای جاری از حساب Google Cloud خود، منابع مستقرشده را در Cloud Shell بردارید:
gcloud workspace-add-ons deployments uninstall support-extension
gcloud workspace-add-ons deployments delete support-extension --quiet
gcloud run services delete support-extension --region=us-central1 --quiet
gcloud firestore databases delete --database="(default)" --quiet
۷. تبریک!
بااستفاده از Firestore، Cloud Run، و Gemini 3.8 Flash در پلاتفرم کارگزار Gemini Enterprise، افزونه Node.js HTTP برای Google Workspace Studio ساختید، مستقر کردید، و آزمایش کردید!
آنچه پوشش دادهایم
- درحال پیکربندی مانیفست برافزای HTTP «استودیوِ Google Workspace» (
deployment.json) باworkflowTriggerوworkflowActionعنصر. - اشتراکهای Google Workspace Studio
workflowTriggerدر مجموعهstudio_triggersFirestore ماندگار میشوند و ارسالهای درگاه درsupport_ticketsثبت میشوند تا محرکها از مقیاسبندی و استقرار مجدد Cloud Run جان سالم بهدر ببرند. - درحال ساختن مرحله
workflowActionکه پیامهای پشتیبانی را با Gemini 3.8 Flash (gemini-3.8-flash) برونداد ساختاریافته در پلاتفرم Gemini Enterprise Agent طبقهبندی میکند، با یک برگشت به تطبیق کلیدواژه انعطافپذیر.