go to post Timothy Leavitt · 7 hr ago Sure! I have this class (extending %JSON.Adaptor rather than using https://github.com/intersystems/isc-json would be almost as good): Class pkg.isc.mcp.message.BaseRequest Extends (Ens.Request, %pkg.isc.json.adaptor) { /// This method is called by the Management Portal to determine /// the content type that will be returned by the <method>%ShowContents</method> /// Override to application/json for pkg.isc.mcp.types.BaseModel.cls extends both /// %XML.Adaptor and %pkg.isc.json.adaptor but returns JSON Method %GetContentType() As %String { Quit "application/json" } Storage Default { <Type>%Storage.Persistent</Type> } } With a subclass, pkg.isc.mcp.message.ToolCallRequest, that has a few more properties. This shows up in the visual trace OOTB as:
go to post Timothy Leavitt · Dec 4 Thanks! There's actually a reasonable level of built-in support for JSON display of messages at the platform level now (not *quite* as pretty as that package), you just need to have a JSONENABLED message class and override: Method %GetContentType() As %String { Quit "application/json" }
go to post Timothy Leavitt · Dec 1 A relevant note / tool I (re-?)discovered today: for critical sequences where an interrupt could leave the system in an inconsistent state, you can use the BREAK command to disable/enable Ctrl+C.See: https://docs.intersystems.com/iris20191/csp/docbook/DocBook.UI.Page.cls?...Here's some sample code covering both the "tracking variable" and "destructor" patterns: Class TSL.Breakfest Extends %RegisteredObject { ClassMethod Run() { Set initialInterruptState = $ZJob\4#2 Try { // Should be able to break during this Hang 5 Set e = 1/0 } Catch e { // Should not be able to break starting here. Break 0 Write !,"bad stuff happened" Hang 2 } Break 0 // Should not be able to break during this Hang 2 Write !,"Got to the end of the critical cleanup step." Break initialInterruptState } ClassMethod RunObject() { Set inst = ..%New() Hang 2 Write !,"Killing inst..." Kill inst } /// This callback method is invoked by the <METHOD>%Close</METHOD> method to /// provide notification that the current object is being closed. /// /// <P>The return value of this method is ignored. Method %OnClose() As %Status [ Private, ServerOnly = 1 ] { Set initialInterruptState = $ZJob\4#2 // Concern: what if the <INTERRUPT> hits exactly here between Set and Break? Extremely hard to test. Not sure if this could happen. Break 0 Hang 2 Write !,"Finished %OnClose" Break initialInterruptState Quit $$$OK } }
go to post Timothy Leavitt · Aug 27 Ended up writing my own based on https://github.com/intersystems/isc-json/blob/main/cls/_pkg/isc/json/path.cls which implements https://goessner.net/articles/JsonPath/ - syntax looks like this, where inputObject and result are both %DynamicAbstractObjects: Set result = ##class(%pkg.isc.json.transformer).For(inputObject ).Remove("$..url" // Remove URL ).Remove("$..requested_fields" // Remove requested_fields ).Remove("$..[?($IsObject(@) && (@.%Size() = 0))]" // Remove empty arrays/objects ).Remove("$..[?($IsObject(@) && (@.%Size() = 1) && (@.%GetTypeOf(1) = ""null""))]" // Remove one-element arrays containing only a null ).TransformElement("$..issue_type","$.name" // Replace issue type object with just the name ).TransformElement("$..priority","$.name" // Replace priority object with just the name ).TransformElement("$..status","$.name" // Replace status object with just the name ).TransformElement("$..[?($IsObject(@) && @.%IsA(""%DynamicObject"") && (@.""avatar_url"" '= """"))]","$.display_name" // Replace any user (indicated by avatar_url) with just the user's display name ).GetResult() I'll probably get this into https://github.com/intersystems/isc-json at some point (subject to some process hurdles); if you're interested nag me here / via DM.
go to post Timothy Leavitt · Aug 20 Thanks! I couldn't actually find that in the docs (just wasn't searching correctly, I guess).
go to post Timothy Leavitt · Aug 20 Came here to say this. From the top-level readme @ https://github.com/intersystems/ipm:IPM 0.9.0+ can be installed with different versions and registry settings per namespace, and does not have the community package registry enabled by default. If you want the legacy (<=0.7.x) behavior of a system-wide installation and access to community packages in all namespaces, run zpm "enable -community" after installing IPM. See zpm "help enable" for details.
go to post Timothy Leavitt · Aug 18 Found the answer:class Foo.Baz extends Foo.Bar{Parameter SETTINGS = "-Whatever";} Thought I'd seen that syntax once, but was looking at a class further down the hierarchy and also needed to recompile it to have the change in the intermediate class take effect. This query was helpful to identify settings behavior in built-in interop classes: select parent,_default from %Dictionary.ParameterDefinition where name = 'SETTINGS'
go to post Timothy Leavitt · Aug 11 Oops - I was out on leave, just seeing this now. Filed a GitHub issue to support/document such a use case: https://github.com/intersystems/isc-codetidy/issues/66Currently, the expectation is that isc.codetidy is configured as a server-side extension so it automatically applies on e.g. isfs-mode editing from VSCode, or any use of Studio (if you still must). I *think* the edits will also work for client-side editing and be reflected automatically, similar to storage definition changes, but that isn't part of the workflow it's intended for.
go to post Timothy Leavitt · Aug 8 FWIW, this is my favorite set of guidelines of the sort I've read so far. I particularly appreciate that you don't throw out postconditionals entirely (and agree on the appropriate uses you've described).
go to post Timothy Leavitt · Jun 11 @Ashok Kumar T thank you for raising these issues - we'll make the error message cleaner and explicitly point to flexible python runtime configuration as the likely culprit.
go to post Timothy Leavitt · Apr 24 Ah, the classic w "</"_script>"... ("The classic" is how it seems ChatGPT responds to every error/oddity I give it these days, but in this case it's actually a classic.)Maybe look into using %CSP.REST to serve up the data.
go to post Timothy Leavitt · Apr 24 Fair enough! I've set a calendar reminder to come back here in 6 months and a year and see whether the article as a whole has aged like wine or milk.
go to post Timothy Leavitt · Apr 19 What is the output of: zpm "list" Can you do $System.OBJ.CompilePackage("Source control","ck") in the namespace where you installed and copy the output? Cc @Pravin Barton @Elijah Tamarchenko @Nick Petrocelli
go to post Timothy Leavitt · Apr 18 In your CSP page, when writing out the JS, you could do something like: write "var myObject = ",! do stream.OutputToDevice()
go to post Timothy Leavitt · Apr 16 I originally posted this article on an internal blog, and have reposted here on others' recommendation. Shortly after the initial post, Anthropic released a "Learning Mode" in Claude for Education - but I'll concede that they probably came up with the idea before me.
go to post Timothy Leavitt · Apr 9 This question isn't really best for me, but I'd like to see something like what you suggested in https://github.com/intersystems/isc-json .
go to post Timothy Leavitt · Apr 9 Note - the "proxy" approach would also serve the role of "API gateway" in e.g. https://blog.christianposta.com/the-updated-mcp-oauth-spec-is-a-mess/
go to post Timothy Leavitt · Apr 8 Hi @Alex Efa I'd recommend checking out Embedded Git: https://github.com/intersystems/git-source-control The approach with Embedded Git is very similar to what you're doing. You want each developer to be able to work in their own feature branch and switch between feature branches easily, but this is a namespace-scoped operation, so it's still good practice for each dev to have their own namespace. Embedded Git manages synchronization of a git repo (on the remote server, alongside IRIS) with the contents of the database. This works both ways: do a git pull through Embedded Git, and it'll import and compile the updated code; change something in the database (e.g., in an isfs folder in VSCode or through a management portal interoperability editor), and it'll get exported to the filesystem in the right place. Embedded Git includes tools for coordination/merging (although the actual workflow should be driven through merge requests in your git remote). Your staging/production namespace would also have Embedded Git configured; just do a git pull there to load the incremental diff from a branch corresponding to the environment. We have a weekly stakeholder meeting / office hours for Embedded Git and would be happy to connect with you there; drop me a direct message with your email address and I'll add you to the invite.