Skill script-include-patterns
✓ VerifiedTulis dan kelola ServiceNow Script Includes menggunakan Class.create, AbstractAjaxProcessor, dan pola inheritance.
- Bintang GitHub
- 77
- File
- 1
- Commit terakhir
- 20 Okt 2026
- Lisensi
- Apache-2.0
- Tool yang diizinkan
- —
Apa fungsi skill script-include-patterns?
script-include-patterns adalah agent skill. Tulis dan kelola ServiceNow Script Includes menggunakan Class.create, AbstractAjaxProcessor, dan pola inheritance.
Ringkasan dibuat dari SKILL.md skill ini.
Tentang skill script-include-patterns
Fungsi utama dari SKILL ini adalah membantu pengembangan library JavaScript server-side yang reusable untuk ServiceNow. SKILL ini membantu developer dalam menulis dan mengelola berbagai tipe Script Includes, termasuk utilitas standar, API client-callable untuk GlideAjax, dan class on-demand lazy loading. SKILL ini mendukung pola arsitektur kompleks seperti inheritance melalui Object.extendsObject serta implementasi spesifik untuk scoped applications.
Agent harus memuat skill ini saat developer perlu membangun atau memodifikasi logika ServiceNow. SKILL ini menyediakan tool spesifik untuk mengotomatisasi siklus pengembangan, seperti snow_create_script_include untuk membuat class baru, snow_artifact_manage untuk mencari atau memperbarui kode yang sudah ada, dan snow_execute_script untuk menguji logika. Dengan mengikuti standar ES5, SKILL ini memastikan kompatibilitas dengan lingkungan ServiceNow sekaligus membantu menjaga kebersihan kode melalui pola terstruktur seperti AbstractAjaxProcessor untuk komunikasi client-server.
Apa yang bisa dilakukan agent dengannya
- 1Build client-callable APIsKembangkan class yang meng-extend AbstractAjaxProcessor agar client script dapat berkomunikasi dengan server melalui GlideAjax.
- 2Implement class inheritanceBuat derived class yang mewarisi fungsionalitas dari base task utility class.
Ditulis dari SKILL.md milik skill tersebut. Setiap use case diverifikasi dengan kutipan darinya.
Cara install skill script-include-patterns
Setiap perintah menyalin folder skill ke direktori skills client. Restart client atau mulai sesi baru untuk memuatnya.Install skill script-include-patterns di Claude Code
~/.claude/skills/script-include-patterns/SKILL.md
$ npx degit serac-labs/serac/packages/skills/script-include-patterns ~/.claude/skills/script-include-patternsInstall skill script-include-patterns di Claude Code (project)
.claude/skills/script-include-patterns/SKILL.md
$ npx degit serac-labs/serac/packages/skills/script-include-patterns .claude/skills/script-include-patternsInstall skill script-include-patterns di Codex
~/.agents/skills/script-include-patterns/SKILL.md
$ npx degit serac-labs/serac/packages/skills/script-include-patterns ~/.agents/skills/script-include-patternsInstall skill script-include-patterns di Gemini CLI
~/.gemini/skills/script-include-patterns/SKILL.md
$ npx degit serac-labs/serac/packages/skills/script-include-patterns ~/.gemini/skills/script-include-patternsInstall skill script-include-patterns di Claude.ai
npx degit serac-labs/serac/packages/skills/script-include-patterns script-include-patterns && zip -r script-include-patterns.zip script-include-patterns # claude.ai → Customize → Skills → + → Create skill → Upload a skill → script-include-patterns.zip
Pengecekan otomatis
Berjalan 14 Nov 2026Laporan lengkap →Lolos cek otomatis kami. Ini bukan audit keamanan: baca skripnya sebelum membiarkan agent menjalankannya. Cara kerja checks · Yang perlu diperbaiki untuk menambah poin
- Source repository terhubung dan dapat dijangkauserac-labs/serac/packages/skills/script-include-patterns is public and reachablegithub.com/serac-labs/serac/tree/HEAD/packages/skills/script ↗Lolos
- Lisensi open source (OSI)Apache-2.0spdx.org/licenses/Apache-2.0.html ↗Lolos
- Ada commit atau release dalam satu tahun terakhirLast commit 2026-10-20github.com/serac-labs/serac/commits ↗Lolos
- Skrip tanpa unduh-lalu-jalankan atau pencurian kredensialNo scripts in the skill folderLolos
- Tidak ada instruksi tersembunyi di SKILL.mdNo override phrases, safeguard switches, credential requests or hidden charactersgithub.com/serac-labs/serac/blob/HEAD/packages/skills/script ↗Lolos
- Tool yang diizinkan otomatis dibatasiNo pre-approved tools; the agent asks before using onegithub.com/serac-labs/serac/blob/HEAD/packages/skills/script ↗Lolos
- SKILL.md mengikuti format Agent Skillsthe description does not say when to use the skillgithub.com/serac-labs/serac/blob/HEAD/packages/skills/script ↗Temuan
SKILL.md
Lihat di GitHubScript Include Patterns for ServiceNow
Script Includes are reusable server-side JavaScript libraries that can be called from any server-side script.
Script Include Types
| Type | Use Case | Client Callable |
|---|---|---|
| Standard | Server-side utilities | No |
| Client Callable | GlideAjax from client | Yes |
| On-Demand | Lazy loading | No |
| AbstractAjaxProcessor | Client-server communication | Yes |
Standard Script Include (ES5)
// Basic utility class
var IncidentUtils = Class.create()
IncidentUtils.prototype = {
initialize: function () {
this.LOG_PREFIX = "[IncidentUtils] "
},
/**
* Get incident by number
* @param {string} number - Incident number (INC0010001)
* @returns {GlideRecord|null} - Incident record or null
*/
getByNumber: function (number) {
var gr = new GlideRecord("incident")
gr.addQuery("number", number)
gr.query()
if (gr.next()) {
return gr
}
return null
},
/**
* Calculate priority based on impact and urgency
* @param {number} impact - Impact value (1-3)
* @param {number} urgency - Urgency value (1-3)
* @returns {number} - Calculated priority (1-5)
*/
calculatePriority: function (impact, urgency) {
var matrix = {
"1-1": 1,
"1-2": 2,
"1-3": 3,
"2-1": 2,
"2-2": 3,
"2-3": 4,
"3-1": 3,
"3-2": 4,
"3-3": 5,
}
var key = impact + "-" + urgency
return matrix[key] || 4
},
/**
* Get open incidents for user
* @param {string} userSysId - User sys_id
* @returns {Array} - Array of incident objects
*/
getOpenIncidentsForUser: function (userSysId) {
var incidents = []
var gr = new GlideRecord("incident")
gr.addQuery("caller_id", userSysId)
gr.addQuery("active", true)
gr.orderByDesc("opened_at")
gr.query()
while (gr.next()) {
incidents.push({
sys_id: gr.getUniqueValue(),
number: gr.getValue("number"),
short_description: gr.getValue("short_description"),
state: gr.state.getDisplayValue(),
priority: gr.priority.getDisplayValue(),
})
}
return incidents
},
type: "IncidentUtils",
}
Client Callable Script Include (ES5)
// Extends AbstractAjaxProcessor for GlideAjax calls
var IncidentAjax = Class.create()
IncidentAjax.prototype = Object.extendsObject(AbstractAjaxProcessor, {
/**
* Get incident details - callable from client
* Client calls: new GlideAjax('IncidentAjax').addParam('sysparm_name', 'getIncidentDetails')
*/
getIncidentDetails: function () {
var incidentId = this.getParameter("sysparm_incident_id")
var result = {}
var gr = new GlideRecord("incident")
if (gr.get(incidentId)) {
result.success = true
result.number = gr.getValue("number")
result.short_description = gr.getValue("short_description")
result.state = gr.state.getDisplayValue()
result.priority = gr.priority.getDisplayValue()
result.assigned_to = gr.assigned_to.getDisplayValue()
result.assignment_group = gr.assignment_group.getDisplayValue()
} else {
result.success = false
result.message = "Incident not found"
}
return JSON.stringify(result)
},
/**
* Search incidents by keyword
*/
searchIncidents: function () {
var keyword = this.getParameter("sysparm_keyword")
var limit = parseInt(this.getParameter("sysparm_limit"), 10) || 10
var incidents = []
var gr = new GlideRecord("incident")
gr.addQuery("short_description", "CONTAINS", keyword)
gr.addOrCondition("description", "CONTAINS", keyword)
gr.addQuery("active", true)
gr.setLimit(limit)
gr.orderByDesc("opened_at")
gr.query()
while (gr.next()) {
incidents.push({
sys_id: gr.getUniqueValue(),
number: gr.getValue("number"),
short_description: gr.getValue("short_description"),
})
}
return JSON.stringify(incidents)
},
/**
* Check if user can update incident
*/
canUserUpdate: function () {
var incidentId = this.getParameter("sysparm_incident_id")
var userId = gs.getUserID()
var gr = new GlideRecord("incident")
if (gr.get(incidentId)) {
// Check if user is assigned or in assignment group
var canUpdate =
gr.getValue("assigned_to") === userId || this._isUserInGroup(userId, gr.getValue("assignment_group"))
return JSON.stringify({ canUpdate: canUpdate })
}
return JSON.stringify({ canUpdate: false })
},
_isUserInGroup: function (userId, groupId) {
var member = new GlideRecord("sys_user_grmember")
member.addQuery("user", userId)
member.addQuery("group", groupId)
member.query()
return member.hasNext()
},
type: "IncidentAjax",
})
Client-Side GlideAjax Call (ES5)
// Client script calling Script Include
function getIncidentDetails(incidentSysId, callback) {
var ga = new GlideAjax("IncidentAjax")
ga.addParam("sysparm_name", "getIncidentDetails")
ga.addParam("sysparm_incident_id", incidentSysId)
ga.getXMLAnswer(function (answer) {
var result = JSON.parse(answer)
callback(result)
})
}
// Usage in client script
getIncidentDetails(g_form.getUniqueValue(), function (incident) {
if (incident.success) {
g_form.addInfoMessage("Incident: " + incident.number)
} else {
g_form.addErrorMessage(incident.message)
}
})
Inheritance Pattern (ES5)
// Base class
var TaskUtils = Class.create()
TaskUtils.prototype = {
initialize: function (tableName) {
this.tableName = tableName || "task"
},
getByState: function (state) {
var records = []
var gr = new GlideRecord(this.tableName)
gr.addQuery("state", state)
gr.query()
while (gr.next()) {
records.push(this._toObject(gr))
}
return records
},
_toObject: function (gr) {
return {
sys_id: gr.getUniqueValue(),
number: gr.getValue("number"),
short_description: gr.getValue("short_description"),
state: gr.getValue("state"),
}
},
type: "TaskUtils",
}
// Derived class
var IncidentUtilsExtended = Class.create()
IncidentUtilsExtended.prototype = Object.extendsObject(TaskUtils, {
initialize: function () {
TaskUtils.prototype.initialize.call(this, "incident")
},
getP1Incidents: function () {
var incidents = []
var gr = new GlideRecord("incident")
gr.addQuery("priority", 1)
gr.addQuery("active", true)
gr.query()
while (gr.next()) {
var obj = this._toObject(gr)
obj.caller = gr.caller_id.getDisplayValue()
incidents.push(obj)
}
return incidents
},
type: "IncidentUtilsExtended",
})
Scoped Script Include (ES5)
// In scoped application: x_myapp
var MyAppUtils = Class.create()
MyAppUtils.prototype = {
initialize: function () {
this.APP_SCOPE = "x_myapp"
},
/**
* Get application property
* @param {string} name - Property name (without scope prefix)
*/
getAppProperty: function (name) {
return gs.getProperty(this.APP_SCOPE + "." + name)
},
/**
* Log with application prefix
*/
log: function (message, source) {
gs.info("[" + this.APP_SCOPE + "][" + (source || "MyAppUtils") + "] " + message)
},
/**
* Access cross-scope table safely
*/
getGlobalUser: function (userId) {
var gr = new GlideRecord("sys_user")
if (gr.get(userId)) {
return {
name: gr.getValue("name"),
email: gr.getValue("email"),
}
}
return null
},
type: "MyAppUtils",
}
MCP Tool Integration
Available Script Include Tools
| Tool | Purpose |
|---|---|
snow_create_script_include |
Create new Script Include |
snow_artifact_manage (action='find') |
Find existing Script Includes |
snow_artifact_manage (action='update') |
Modify Script Include code |
snow_execute_script |
Test Script Include |
Example Workflow
// 1. Create Script Include
await snow_create_script_include({
name: "IncidentUtils",
script: "/* Script Include code */",
client_callable: false,
description: "Incident utility functions",
})
// 2. Test the Script Include
await snow_execute_script({
script: `
var utils = new IncidentUtils();
var incident = utils.getByNumber('INC0010001');
gs.info('Found: ' + (incident ? incident.number : 'null'));
`,
})
Best Practices
- Single Responsibility - One class, one purpose
- Meaningful Names - IncidentUtils not Utils
- Document Methods - JSDoc comments
- Error Handling - Try-catch with logging
- Private Methods - Prefix with underscore
- No Side Effects - Initialization should not modify data
- Testable - Write methods that can be unit tested
- ES5 Only - No const, let, arrow functions, template literals
Berkas dalam skill ini
1Pertanyaan seputar skill script-include-patterns
Bagaimana cara install skill script-include-patterns di Claude Code?
Jalankan npx degit serac-labs/serac/packages/skills/script-include-patterns ~/.claude/skills/script-include-patterns. Claude Code memuat skill dari ~/.claude/skills (semua proyek) atau .claude/skills (satu proyek) dan menggunakan skill saat deskripsinya cocok dengan tugas.
Client mana saja yang bisa menggunakan skill script-include-patterns?
Client apa pun yang membaca format Agent Skills: Claude Code, Codex, Gemini CLI, dan claude.ai (unggah sebagai ZIP). Script dalam skill hanya berjalan di client yang mengizinkan eksekusi kode.
Apa saja tipe Script Includes yang berbeda di ServiceNow?
Script Includes dapat berupa Standard (utilitas server-side), Client Callable (untuk GlideAjax), On-Demand (lazy loading), atau AbstractAjaxProcessor (untuk komunikasi client-server).
Bagaimana cara mengimplementasikan inheritance dalam ServiceNow Script Include?
Anda dapat menggunakan metode Object.extendsObject untuk memungkinkan class turunan mewarisi properti dari base class.
Standar coding apa yang harus diikuti saat menulis Script Includes?
Developer sebaiknya menggunakan sintaks ES5 (hindari const, let, atau arrow functions), mengikuti single responsibility principle, menggunakan penamaan yang bermakna, dan memberikan prefix underscore pada private methods.